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

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

Initial import of bbftp source

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