source: TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd_login.c @ 1358

Subversion URL: http://proj.badc.rl.ac.uk/svn/ndg/TI05-delivery/trunk/src/bbftp-server-3.2.0/bbftpd/bbftpd_login.c@1358
Revision 1358, 13.8 KB checked in by spascoe, 13 years ago (diff)

Overhalled the logging facility, packaging it so that it is
simmilar to bbftpd_private_auth. When compiling non-embedded bbftp
you can activate what is called "private-logging" with the
--enable-private-logging switch. As a result both the test_embedded.py
and test_bbftpd.py test scripts can be run without access to syslog.

Line 
1/*
2 * bbftpd/bbftpd_login.c
3 * Copyright (C) 1999, 2000, 2001, 2002 IN2P3, CNRS
4 * bbftp@in2p3.fr
5 * http://doc.in2p3.fr/bbftp
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20 */ 
21
22/****************************************************************************
23
24 
25 RETURN:
26         0  login OK
27        -1 login failed
28 
29 bbftpd_login.c  v 1.6.0  2000/03/24    - Creation of the routine. This part of
30                                          code was contained in readcontrol.c
31                 v 1.8.0  2000/04/14    - Introduce RSA Cryptage
32                 v 1.8.3  2000/04/18    - Change the reply message in order
33                                          to stop retry in case of unkown user
34                                          or incorrect password
35                 v 1.8.7  2000/05/24    - Modify headers
36                 v 1.8.11 2000/05/24    - Add Pam for Linux (and only pam...)
37                 v 1.9.0  2000/08/18    - Use configure to help portage
38                                        - Change the reply message (for future
39                                          use)
40                 v 1.9.0  2000/09/19    - Correct bug for pam
41                 v 1.9.4  2000/10/16    - Supress %m
42                 v 2.0.0  2000/12/18    - Use incontrolsock instead of msgsock
43                 v 2.0.1  2001/04/23    - Correct indentation
44                 v 2.0.2  2001/05/04    - Correct return code treatment
45                                        - Change use of tmpchar
46                 v 2.1.0  2001/06/11    - Change file name
47                                     
48 *****************************************************************************/
49#include <bbftpd.h>
50
51/*#ifndef SX*/
52#ifdef HAVE_CRYPT_H
53#include <crypt.h>
54#endif
55#include <errno.h>
56
57#include <pwd.h>
58#include <sys/types.h>
59#include <unistd.h>
60#include <utime.h>
61#if HAVE_STRING_H
62# include <string.h>
63#endif
64
65#include <netinet/in.h>
66#include <config.h>
67#include <common.h>
68#include <daemon.h>
69#include <daemon_proto.h>
70#include <structures.h>
71#include <version.h>
72
73#ifdef SHADOW_PASSWORD
74#include <shadow.h>
75#endif
76#ifdef USE_PAM
77#include <security/pam_appl.h>
78#endif
79#ifdef HAVE_SECURITY_PASS
80#include <userpw.h>
81#endif
82
83#include <bbftpd_private_log.h>
84
85
86extern int incontrolsock ;
87extern  int     recvcontrolto ;
88extern char currentusername[MAXLEN] ;
89
90#ifdef USE_PAM
91extern char daemonchar[50] ;
92
93static char *PAM_password;
94/* PAM conversation function
95 * We assume that echo on means login name, and echo off means password.
96 */
97static int PAM_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
98{
99    int replies = 0;
100    struct pam_response *reply = NULL;
101
102#define COPY_STRING(s) (s) ? strdup(s) : NULL
103
104    reply = (struct pam_response *) malloc(sizeof(struct pam_response) * num_msg);
105    if (!reply) return PAM_CONV_ERR;
106
107    for (replies = 0; replies < num_msg; replies++) {
108        switch (msg[replies]->msg_style) {
109        case PAM_PROMPT_ECHO_ON:
110            return PAM_CONV_ERR;
111            break;
112        case PAM_PROMPT_ECHO_OFF:
113            reply[replies].resp_retcode = PAM_SUCCESS;
114            reply[replies].resp = COPY_STRING(PAM_password);
115            /* PAM frees resp */
116            break;
117        case PAM_TEXT_INFO:
118            /* ignore it... */
119            reply[replies].resp_retcode = PAM_SUCCESS;
120            reply[replies].resp = NULL;
121            break;
122        case PAM_ERROR_MSG:
123            /* ignore it... */
124            reply[replies].resp_retcode = PAM_SUCCESS;
125            reply[replies].resp = NULL;
126            break;
127        default:
128           /* Must be an error of some sort... */
129            return PAM_CONV_ERR;
130        }
131    }
132    *resp = reply;
133    return PAM_SUCCESS;
134}
135
136static struct pam_conv PAM_conversation =
137{
138    &PAM_conv,
139    NULL
140};
141#endif
142
143int loginsequence() {
144   
145    int        retcode ;
146    char    receive_buffer[MAXMESSLEN] ;
147    struct mess_sec *msg_sec ;
148    struct mess_rsa *msg_rsa ;
149   
150    char    username[MAXLEN] ;
151    char    password[MAXLEN] ;
152    struct    passwd    *uspass ;
153    char    logmessage[1024] ;
154#ifdef SHADOW_PASSWORD
155    struct    spwd    *sunpass ;
156#endif
157#ifdef HAVE_SECURITY_PASS
158    struct    userpw    *secpass ;
159#endif
160    char    *calcpass ;
161#ifdef AFS
162    char    *inst = "";
163#endif
164#ifdef USE_PAM
165    pam_handle_t *pamh=NULL;
166#endif
167    sprintf(logmessage,"bbftpd version %s",VERSION) ;
168    /*
169    ** Read the crypt type
170    */
171    if ( (retcode = readmessage(incontrolsock,receive_buffer,CRYPTMESSLEN,recvcontrolto)) < 0 ) {
172        /*
173        ** Error ...
174        */
175        return(retcode) ;
176    }
177    msg_sec = (struct mess_sec *)receive_buffer ;
178    switch (msg_sec->crtype) {
179        case CRYPT_RSA_PKCS1_OAEP_PADDING :
180            /*
181            ** RSA
182            */
183            if ( (retcode = readmessage(incontrolsock,receive_buffer,RSAMESSLEN,recvcontrolto)) < 0) {
184                return(retcode) ;
185            }
186            if ( decodersapass(receive_buffer,username,password) < 0 ) {
187                bbftpd_log(BBFTPD_ERR,"Decode user/password error") ;
188                strcat(logmessage," : Decode user/password error") ;
189                reply(MSG_BAD,logmessage) ;
190                return -1 ;
191            }
192            break ;
193        case NO_CRYPT :
194            if ( (retcode = readmessage(incontrolsock,receive_buffer,RSAMESSLEN,recvcontrolto)) < 0) {
195                return(retcode) ;
196            }
197            msg_rsa = (struct mess_rsa *)receive_buffer ;
198            strncpy(username, msg_rsa->cryptuser, strlen(msg_rsa->cryptuser));
199            username[strlen(msg_rsa->cryptuser)]='\0';
200            strncpy(password, msg_rsa->cryptpass, strlen(msg_rsa->cryptpass));
201            password[strlen(msg_rsa->cryptpass)]='\0';
202            break ;
203        default :
204            bbftpd_log(BBFTPD_ERR,"Unkwown encryption %d",msg_sec->crtype) ;
205            strcat(logmessage," : Unknwon encryption") ;
206            reply(MSG_BAD,logmessage) ;
207            return -1 ;
208    }
209    /*
210    ** Here we check the username and pass and set the default dir
211    */
212    if ( (uspass = getpwnam(username)) == NULL ) {
213        bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
214        strcat(logmessage," : Unknown user (") ;
215        strcat(logmessage, username);
216        strcat(logmessage, ")");
217        reply(MSG_BAD_NO_RETRY,logmessage) ;
218        return -1 ;
219    }
220/*
221** If the AFS flag is set it take precedence on all other mechanism
222*/
223#ifdef AFS
224    setpag() ;
225    retcode = ka_UserAuthenticate(username,inst,0,password,0,&calcpass) ;
226    if ( retcode != 0 ) {
227        bbftpd_log(BBFTPD_ERR,"ka_UserAuthenticate message : %s ",calcpass) ;
228        /*
229        ** Check local user
230        */
231        if ( (strcmp(uspass->pw_passwd,"x") == 0) || 
232             (strcmp(uspass->pw_passwd,"X") == 0) ) {
233#ifdef SHADOW_PASSWORD
234            if ( (sunpass = getspnam(username)) == NULL ) {
235                bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
236                /*
237                ** We send ka_UserAuthenticate error msg
238                */
239                strcat(logmessage, " : ") ;
240                strcat(logmessage, calcpass) ;
241                reply(MSG_BAD_NO_RETRY,logmessage) ;
242                return -1 ;
243            }
244            calcpass = (char *) crypt(password,sunpass->sp_pwdp) ;
245            if ( strcmp(calcpass,sunpass->sp_pwdp) != 0 ) {
246                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
247                strcat(logmessage," : Incorrect password") ;
248                reply(MSG_BAD_NO_RETRY,logmessage) ;
249                return -1 ;
250            }
251#elif defined(HAVE_SECURITY_PASS)
252            if ( (secpass = getuserpw(username)) == NULL ) {
253                bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
254                /*
255                ** We send ka_UserAuthenticate error msg
256                */
257                strcat(logmessage, " : ") ;
258                strcat(logmessage, calcpass) ;
259                reply(MSG_BAD_NO_RETRY,logmessage) ;
260                return -1 ;
261            }
262            calcpass = (char *) crypt(password,secpass->upw_passwd) ;
263            if ( strcmp(calcpass,secpass->upw_passwd) != 0 ) {
264                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
265                strcat(logmessage," : Incorrect password") ;
266                reply(MSG_BAD_NO_RETRY,logmessage) ;
267                return -1 ;
268            }
269#else
270
271            bbftpd_log(BBFTPD_ERR,"No Password user %s",username) ;
272            strcat(logmessage," : No password user") ;
273            reply(MSG_BAD_NO_RETRY,logmessage) ;
274            return -1 ;
275#endif
276        } else {
277            calcpass = (char *) crypt(password,uspass->pw_passwd) ;
278            if ( strcmp(calcpass,uspass->pw_passwd) != 0 ) {
279                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
280                strcat(logmessage," : Incorrect password") ;
281                reply(MSG_BAD_NO_RETRY,logmessage) ;
282                return -1 ;
283            }
284        }
285    }
286#elif defined(USE_PAM)
287    /*
288    ** For PAM
289    */
290    strcat(logmessage," : PAM Error") ;
291    PAM_password = password ;
292    retcode = pam_start("bbftp", username, &PAM_conversation, &pamh);
293#define PAM_BAIL if (retcode != PAM_SUCCESS) { pam_end(pamh, 0); bbftpd_log(BBFTPD_ERR,"PAM error (%d) user %s",retcode,username) ;reply(MSG_BAD_NO_RETRY,logmessage) ;return -1; }
294    PAM_BAIL;
295    retcode = pam_authenticate(pamh, PAM_SILENT);
296    PAM_BAIL;
297    retcode = pam_acct_mgmt(pamh, 0);
298    PAM_BAIL;
299#ifdef PAM_ESTABLISH_CRED
300    retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
301#else
302    retcode = pam_setcred(pamh, PAM_CRED_ESTABLISH);
303#endif
304    PAM_BAIL;
305    pam_end(pamh, PAM_SUCCESS);
306    /*
307    ** Reopen the lag as the pam functions close it
308    */
309    bbftpd_openlog(daemonchar, LOG_PID | LOG_NDELAY, BBFTPD_FACILITY);
310#else
311    /*
312    ** For the others
313    */
314    if ( (strcmp(uspass->pw_passwd,"x") == 0) || 
315         (strcmp(uspass->pw_passwd,"X") == 0)) {
316#ifdef SHADOW_PASSWORD
317            if ( (sunpass = getspnam(username)) == NULL ) {
318                bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
319                strcat(logmessage," : Unknown user") ;
320                reply(MSG_BAD_NO_RETRY,logmessage) ;
321                return -1 ;
322            }
323            calcpass = (char *) crypt(password,sunpass->sp_pwdp) ;
324            if ( strcmp(calcpass,sunpass->sp_pwdp) != 0 ) {
325                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
326                strcat(logmessage," : Incorrect password") ;
327                reply(MSG_BAD_NO_RETRY,logmessage) ;
328                return -1 ;
329            }
330#elif defined(HAVE_SECURITY_PASS)
331            if ( (secpass = getuserpw(username)) == NULL ) {
332                bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
333                strcat(logmessage," : Unknown user") ;
334                reply(MSG_BAD_NO_RETRY,logmessage) ;
335                return -1 ;
336            }
337            calcpass = (char *) crypt(password,secpass->upw_passwd) ;
338            if ( strcmp(calcpass,secpass->upw_passwd) != 0 ) {
339                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
340                strcat(logmessage," : Incorrect password") ;
341                reply(MSG_BAD_NO_RETRY,logmessage) ;
342                return -1 ;
343            }
344#else
345            bbftpd_log(BBFTPD_ERR,"No Password user %s",username) ;
346            strcat(logmessage," : No password") ;
347            reply(MSG_BAD_NO_RETRY,logmessage) ;
348            return -1 ;
349#endif
350    } else {
351        calcpass = (char *) crypt(password,uspass->pw_passwd) ;
352        if ( strcmp(calcpass,uspass->pw_passwd) != 0 ) {
353            bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
354            strcat(logmessage," : Incorrect password") ;
355            reply(MSG_BAD_NO_RETRY,logmessage) ;
356            return -1 ;
357        }
358    }
359#endif
360    /*
361    ** Set the uid and gid of the process
362    */
363    if ( setgid(uspass->pw_gid) < 0 ) {
364        bbftpd_log(BBFTPD_ERR,"Error setgid user %s : %s",username,strerror(errno)) ;
365        strcat(logmessage," : Unable to set gid: ") ;
366        strcat(logmessage,strerror(errno));
367        reply(MSG_BAD,logmessage) ;
368        return -1 ;
369    }
370    /* Initialize the group list. */
371    if (getuid() == 0) {
372      if (initgroups(uspass->pw_name, uspass->pw_gid) < 0) {
373        bbftpd_log(BBFTPD_WARNING,"Error Initialize the group list %s : %s",username,strerror(errno)) ;
374        return -1 ;
375      }
376      endgrent();
377    }
378
379    if ( setuid(uspass->pw_uid) < 0 ) {
380        bbftpd_log(BBFTPD_ERR,"Error setuid user %s : %s",username,strerror(errno)) ;
381        strcat(logmessage," : Unable to set uid: ") ;
382        strcat(logmessage,strerror(errno));
383        reply(MSG_BAD,logmessage) ;
384        return -1 ;
385    }
386    if ( uspass->pw_dir == NULL ) {
387        bbftpd_log(BBFTPD_ERR,"No home directory user %s : %s",username,strerror(errno)) ;
388        strcat(logmessage," : No home directory: ") ;
389        strcat(logmessage,strerror(errno));
390        reply(MSG_BAD,logmessage) ;
391        return -1 ;
392    }
393    if ( chdir(uspass->pw_dir) < 0) {
394        bbftpd_log(BBFTPD_ERR,"Error chdir user %s : %s",username,strerror(errno)) ;
395        strcat(logmessage," : Unable to change directory: ") ;
396        strcat(logmessage,strerror(errno));
397        reply(MSG_BAD,logmessage) ;
398        return -1 ;
399    }
400               
401    bbftpd_log(BBFTPD_DEBUG,"User %s connected",username) ;
402    strcpy(currentusername,username) ;
403    return 0 ;
404}
Note: See TracBrowser for help on using the repository browser.