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

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

Eliminated all "implicit declaration" warnings from "python setup.py
build"

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#include <stdio.h>
52
53/*#ifndef SX*/
54#ifdef HAVE_CRYPT_H
55#include <crypt.h>
56#endif
57#include <errno.h>
58
59#include <pwd.h>
60#include <sys/types.h>
61#include <grp.h>
62#include <unistd.h>
63#include <utime.h>
64#if HAVE_STRING_H
65# include <string.h>
66#endif
67
68#include <netinet/in.h>
69#include <config.h>
70#include <common.h>
71#include <daemon.h>
72#include <daemon_proto.h>
73#include <structures.h>
74#include <version.h>
75
76#ifdef SHADOW_PASSWORD
77#include <shadow.h>
78#endif
79#ifdef USE_PAM
80#include <security/pam_appl.h>
81#endif
82#ifdef HAVE_SECURITY_PASS
83#include <userpw.h>
84#endif
85
86#include <bbftpd_private_log.h>
87
88
89extern int incontrolsock ;
90extern  int     recvcontrolto ;
91extern char currentusername[MAXLEN] ;
92
93#ifdef USE_PAM
94extern char daemonchar[50] ;
95
96static char *PAM_password;
97/* PAM conversation function
98 * We assume that echo on means login name, and echo off means password.
99 */
100static int PAM_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr)
101{
102    int replies = 0;
103    struct pam_response *reply = NULL;
104
105#define COPY_STRING(s) (s) ? strdup(s) : NULL
106
107    reply = (struct pam_response *) malloc(sizeof(struct pam_response) * num_msg);
108    if (!reply) return PAM_CONV_ERR;
109
110    for (replies = 0; replies < num_msg; replies++) {
111        switch (msg[replies]->msg_style) {
112        case PAM_PROMPT_ECHO_ON:
113            return PAM_CONV_ERR;
114            break;
115        case PAM_PROMPT_ECHO_OFF:
116            reply[replies].resp_retcode = PAM_SUCCESS;
117            reply[replies].resp = COPY_STRING(PAM_password);
118            /* PAM frees resp */
119            break;
120        case PAM_TEXT_INFO:
121            /* ignore it... */
122            reply[replies].resp_retcode = PAM_SUCCESS;
123            reply[replies].resp = NULL;
124            break;
125        case PAM_ERROR_MSG:
126            /* ignore it... */
127            reply[replies].resp_retcode = PAM_SUCCESS;
128            reply[replies].resp = NULL;
129            break;
130        default:
131           /* Must be an error of some sort... */
132            return PAM_CONV_ERR;
133        }
134    }
135    *resp = reply;
136    return PAM_SUCCESS;
137}
138
139static struct pam_conv PAM_conversation =
140{
141    &PAM_conv,
142    NULL
143};
144#endif
145
146int loginsequence() {
147   
148    int        retcode ;
149    char    receive_buffer[MAXMESSLEN] ;
150    struct mess_sec *msg_sec ;
151    struct mess_rsa *msg_rsa ;
152   
153    char    username[MAXLEN] ;
154    char    password[MAXLEN] ;
155    struct    passwd    *uspass ;
156    char    logmessage[1024] ;
157#ifdef SHADOW_PASSWORD
158    struct    spwd    *sunpass ;
159#endif
160#ifdef HAVE_SECURITY_PASS
161    struct    userpw    *secpass ;
162#endif
163    char    *calcpass ;
164#ifdef AFS
165    char    *inst = "";
166#endif
167#ifdef USE_PAM
168    pam_handle_t *pamh=NULL;
169#endif
170    sprintf(logmessage,"bbftpd version %s",VERSION) ;
171    /*
172    ** Read the crypt type
173    */
174    if ( (retcode = readmessage(incontrolsock,receive_buffer,CRYPTMESSLEN,recvcontrolto)) < 0 ) {
175        /*
176        ** Error ...
177        */
178        return(retcode) ;
179    }
180    msg_sec = (struct mess_sec *)receive_buffer ;
181    switch (msg_sec->crtype) {
182        case CRYPT_RSA_PKCS1_OAEP_PADDING :
183            /*
184            ** RSA
185            */
186            if ( (retcode = readmessage(incontrolsock,receive_buffer,RSAMESSLEN,recvcontrolto)) < 0) {
187                return(retcode) ;
188            }
189            if ( decodersapass(receive_buffer,username,password) < 0 ) {
190                bbftpd_log(BBFTPD_ERR,"Decode user/password error") ;
191                strcat(logmessage," : Decode user/password error") ;
192                reply(MSG_BAD,logmessage) ;
193                return -1 ;
194            }
195            break ;
196        case NO_CRYPT :
197            if ( (retcode = readmessage(incontrolsock,receive_buffer,RSAMESSLEN,recvcontrolto)) < 0) {
198                return(retcode) ;
199            }
200            msg_rsa = (struct mess_rsa *)receive_buffer ;
201            strncpy(username, msg_rsa->cryptuser, strlen(msg_rsa->cryptuser));
202            username[strlen(msg_rsa->cryptuser)]='\0';
203            strncpy(password, msg_rsa->cryptpass, strlen(msg_rsa->cryptpass));
204            password[strlen(msg_rsa->cryptpass)]='\0';
205            break ;
206        default :
207            bbftpd_log(BBFTPD_ERR,"Unkwown encryption %d",msg_sec->crtype) ;
208            strcat(logmessage," : Unknwon encryption") ;
209            reply(MSG_BAD,logmessage) ;
210            return -1 ;
211    }
212    /*
213    ** Here we check the username and pass and set the default dir
214    */
215    if ( (uspass = getpwnam(username)) == NULL ) {
216        bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
217        strcat(logmessage," : Unknown user (") ;
218        strcat(logmessage, username);
219        strcat(logmessage, ")");
220        reply(MSG_BAD_NO_RETRY,logmessage) ;
221        return -1 ;
222    }
223/*
224** If the AFS flag is set it take precedence on all other mechanism
225*/
226#ifdef AFS
227    setpag() ;
228    retcode = ka_UserAuthenticate(username,inst,0,password,0,&calcpass) ;
229    if ( retcode != 0 ) {
230        bbftpd_log(BBFTPD_ERR,"ka_UserAuthenticate message : %s ",calcpass) ;
231        /*
232        ** Check local user
233        */
234        if ( (strcmp(uspass->pw_passwd,"x") == 0) || 
235             (strcmp(uspass->pw_passwd,"X") == 0) ) {
236#ifdef SHADOW_PASSWORD
237            if ( (sunpass = getspnam(username)) == NULL ) {
238                bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
239                /*
240                ** We send ka_UserAuthenticate error msg
241                */
242                strcat(logmessage, " : ") ;
243                strcat(logmessage, calcpass) ;
244                reply(MSG_BAD_NO_RETRY,logmessage) ;
245                return -1 ;
246            }
247            calcpass = (char *) crypt(password,sunpass->sp_pwdp) ;
248            if ( strcmp(calcpass,sunpass->sp_pwdp) != 0 ) {
249                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
250                strcat(logmessage," : Incorrect password") ;
251                reply(MSG_BAD_NO_RETRY,logmessage) ;
252                return -1 ;
253            }
254#elif defined(HAVE_SECURITY_PASS)
255            if ( (secpass = getuserpw(username)) == NULL ) {
256                bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
257                /*
258                ** We send ka_UserAuthenticate error msg
259                */
260                strcat(logmessage, " : ") ;
261                strcat(logmessage, calcpass) ;
262                reply(MSG_BAD_NO_RETRY,logmessage) ;
263                return -1 ;
264            }
265            calcpass = (char *) crypt(password,secpass->upw_passwd) ;
266            if ( strcmp(calcpass,secpass->upw_passwd) != 0 ) {
267                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
268                strcat(logmessage," : Incorrect password") ;
269                reply(MSG_BAD_NO_RETRY,logmessage) ;
270                return -1 ;
271            }
272#else
273
274            bbftpd_log(BBFTPD_ERR,"No Password user %s",username) ;
275            strcat(logmessage," : No password user") ;
276            reply(MSG_BAD_NO_RETRY,logmessage) ;
277            return -1 ;
278#endif
279        } else {
280            calcpass = (char *) crypt(password,uspass->pw_passwd) ;
281            if ( strcmp(calcpass,uspass->pw_passwd) != 0 ) {
282                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
283                strcat(logmessage," : Incorrect password") ;
284                reply(MSG_BAD_NO_RETRY,logmessage) ;
285                return -1 ;
286            }
287        }
288    }
289#elif defined(USE_PAM)
290    /*
291    ** For PAM
292    */
293    strcat(logmessage," : PAM Error") ;
294    PAM_password = password ;
295    retcode = pam_start("bbftp", username, &PAM_conversation, &pamh);
296#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; }
297    PAM_BAIL;
298    retcode = pam_authenticate(pamh, PAM_SILENT);
299    PAM_BAIL;
300    retcode = pam_acct_mgmt(pamh, 0);
301    PAM_BAIL;
302#ifdef PAM_ESTABLISH_CRED
303    retcode = pam_setcred(pamh, PAM_ESTABLISH_CRED);
304#else
305    retcode = pam_setcred(pamh, PAM_CRED_ESTABLISH);
306#endif
307    PAM_BAIL;
308    pam_end(pamh, PAM_SUCCESS);
309    /*
310    ** Reopen the lag as the pam functions close it
311    */
312    bbftpd_openlog(daemonchar, LOG_PID | LOG_NDELAY, BBFTPD_FACILITY);
313#else
314    /*
315    ** For the others
316    */
317    if ( (strcmp(uspass->pw_passwd,"x") == 0) || 
318         (strcmp(uspass->pw_passwd,"X") == 0)) {
319#ifdef SHADOW_PASSWORD
320            if ( (sunpass = getspnam(username)) == NULL ) {
321                bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
322                strcat(logmessage," : Unknown user") ;
323                reply(MSG_BAD_NO_RETRY,logmessage) ;
324                return -1 ;
325            }
326            calcpass = (char *) crypt(password,sunpass->sp_pwdp) ;
327            if ( strcmp(calcpass,sunpass->sp_pwdp) != 0 ) {
328                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
329                strcat(logmessage," : Incorrect password") ;
330                reply(MSG_BAD_NO_RETRY,logmessage) ;
331                return -1 ;
332            }
333#elif defined(HAVE_SECURITY_PASS)
334            if ( (secpass = getuserpw(username)) == NULL ) {
335                bbftpd_log(BBFTPD_ERR,"Unknown user %s",username) ;
336                strcat(logmessage," : Unknown user") ;
337                reply(MSG_BAD_NO_RETRY,logmessage) ;
338                return -1 ;
339            }
340            calcpass = (char *) crypt(password,secpass->upw_passwd) ;
341            if ( strcmp(calcpass,secpass->upw_passwd) != 0 ) {
342                bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
343                strcat(logmessage," : Incorrect password") ;
344                reply(MSG_BAD_NO_RETRY,logmessage) ;
345                return -1 ;
346            }
347#else
348            bbftpd_log(BBFTPD_ERR,"No Password user %s",username) ;
349            strcat(logmessage," : No password") ;
350            reply(MSG_BAD_NO_RETRY,logmessage) ;
351            return -1 ;
352#endif
353    } else {
354        calcpass = (char *) crypt(password,uspass->pw_passwd) ;
355        if ( strcmp(calcpass,uspass->pw_passwd) != 0 ) {
356            bbftpd_log(BBFTPD_ERR,"Incorrect password user %s",username) ;
357            strcat(logmessage," : Incorrect password") ;
358            reply(MSG_BAD_NO_RETRY,logmessage) ;
359            return -1 ;
360        }
361    }
362#endif
363    /*
364    ** Set the uid and gid of the process
365    */
366    if ( setgid(uspass->pw_gid) < 0 ) {
367        bbftpd_log(BBFTPD_ERR,"Error setgid user %s : %s",username,strerror(errno)) ;
368        strcat(logmessage," : Unable to set gid: ") ;
369        strcat(logmessage,strerror(errno));
370        reply(MSG_BAD,logmessage) ;
371        return -1 ;
372    }
373    /* Initialize the group list. */
374    if (getuid() == 0) {
375      if (initgroups(uspass->pw_name, uspass->pw_gid) < 0) {
376        bbftpd_log(BBFTPD_WARNING,"Error Initialize the group list %s : %s",username,strerror(errno)) ;
377        return -1 ;
378      }
379      endgrent();
380    }
381
382    if ( setuid(uspass->pw_uid) < 0 ) {
383        bbftpd_log(BBFTPD_ERR,"Error setuid user %s : %s",username,strerror(errno)) ;
384        strcat(logmessage," : Unable to set uid: ") ;
385        strcat(logmessage,strerror(errno));
386        reply(MSG_BAD,logmessage) ;
387        return -1 ;
388    }
389    if ( uspass->pw_dir == NULL ) {
390        bbftpd_log(BBFTPD_ERR,"No home directory user %s : %s",username,strerror(errno)) ;
391        strcat(logmessage," : No home directory: ") ;
392        strcat(logmessage,strerror(errno));
393        reply(MSG_BAD,logmessage) ;
394        return -1 ;
395    }
396    if ( chdir(uspass->pw_dir) < 0) {
397        bbftpd_log(BBFTPD_ERR,"Error chdir user %s : %s",username,strerror(errno)) ;
398        strcat(logmessage," : Unable to change directory: ") ;
399        strcat(logmessage,strerror(errno));
400        reply(MSG_BAD,logmessage) ;
401        return -1 ;
402    }
403               
404    bbftpd_log(BBFTPD_DEBUG,"User %s connected",username) ;
405    strcpy(currentusername,username) ;
406    return 0 ;
407}
Note: See TracBrowser for help on using the repository browser.