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

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

More missing #includes exposed when compiling on easterly.

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