1#include <config.h>
2#include <stdio.h>
3#include <pwd.h>
4#ifdef HAVE_SHADOW_H
5#include <shadow.h>
6#endif
7#include <sys/stat.h>
8#include <sys/types.h>
9#include <fcntl.h>
10#include <unistd.h>
11#include <string.h>
12#ifdef HAVE_CRYPT_H
13#include <crypt.h>
14#endif
15#ifdef WANT_PAM
16#include <security/pam_appl.h>
17#endif
18#ifdef HAVE_UTMP_H
19# include <utmp.h>
20# ifdef HAVE_PATHS_H
21#  include <paths.h>
22#  ifndef _PATH_WTMP
23#   define _PATH_WTMP "/dev/null"
24#   warning "<paths.h> doesn't set _PATH_WTMP. You can not use wtmp logging"
25#   warning "with bftpd."
26#  endif
27# else
28#  define _PATH_WTMP "/dev/null"
29#  warning "<paths.h> was not found. You can not use wtmp logging with bftpd."
30# endif
31#endif
32#include <errno.h>
33#include <grp.h>
34#include <stdlib.h>
35#ifdef HAVE_SYS_TIME_H
36#include <sys/time.h>
37#endif
38#ifdef HAVE_TIME_H
39#include <time.h>
40#endif
41
42#include "cwd.h"
43#include "dirlist.h"
44#include "mystring.h"
45#include "options.h"
46#include "login.h"
47#include "logging.h"
48#include "bftpdutmp.h"
49#include "main.h"
50
51#include <openssl/sha.h>
52
53#ifdef WANT_PAM
54char usepam = 0;
55pam_handle_t *pamh = NULL;
56#endif
57
58#ifdef HAVE_UTMP_H
59FILE *wtmp;
60#endif
61
62struct passwd userinfo;
63char userinfo_set = 0;
64
65/*zzz add for geting first partition, 12/11/2007 */
66#define NDEBUG //turn off to set assert and P1MSG
67#ifdef NDEBUG
68  #define P1MSG(args...)
69#else
70  #define P1MSG(args...) fprintf(stderr, "%s-%04d: ", __FILE__, __LINE__) ; fprintf(stderr, ## args)
71#endif // NDEBUG
72
73/* Foxconn added start by Jenny Zhao, 06/10/2011 @USB log */
74#include <acosNvramConfig.h>
75#include <errno.h>
76extern int g_isLanIp;
77extern char client_ip[32];
78
79/*
80 ** check whether an IP address is in the LAN subnet
81 **/
82int isLanSubnet(char *ipAddr)
83{
84    long netAddr, netMask, netIp;
85    netAddr = inet_addr(acosNvramConfig_get("lan_ipaddr"));
86    netMask = inet_addr(acosNvramConfig_get("lan_netmask"));
87    netIp   = inet_addr(ipAddr);
88    if ((netAddr & netMask) != (netIp & netMask))
89    {
90        return FALSE;
91    }
92    return TRUE;
93}
94
95void write_usb_access_log(void)
96{
97    if (!g_isLanIp)
98    {
99        FILE *fp;
100        char logBuffer[96];
101        if ((fp = fopen("/dev/aglog", "r+")) != NULL)
102        {
103            sprintf(logBuffer, "[USB remote access] from %s through FTP,", client_ip);
104            fwrite(logBuffer, sizeof(char), strlen(logBuffer)+1, fp);
105            fclose(fp);
106        }
107    }
108}
109
110void write_usb_fail_log(void)
111{
112    if (!g_isLanIp)
113    {
114        FILE *fp;
115        char logBuffer[96];
116        if ((fp = fopen("/dev/aglog", "r+")) != NULL)
117        {
118            sprintf(logBuffer, "[USB remote access rejected] from %s through FTP,", client_ip);
119            fwrite(logBuffer, sizeof(char), strlen(logBuffer)+1, fp);
120            fclose(fp);
121        }
122    }
123}
124/* Foxconn added end by Jenny Zhao, 06/10/2011 */
125
126
127static char mount_path[128];
128int readOnlyOnPart1 = 0; //@ftpRW
129
130static void scanPartitons()
131{
132    FILE *fp = 0;
133    char line[256];
134
135//===================================
136// parse /proc/mounts
137// format:
138// /dev/sdb1 /mnt/share/usb1/part1 vfat rw,sync 0 0
139//===================================
140
141
142    fp = fopen("/proc/mounts", "r");
143    mount_path[0] = 0;
144    readOnlyOnPart1 = 0;
145    if (fp)
146    {
147        while (1)
148        {
149            memset(line, 0x00, 256);
150            if (feof(fp))
151            {
152                break;
153            }
154
155            fgets(line, 256, fp);
156            if (strncmp(line, "/dev/sd", 7) == 0)
157            {
158                char *saveptr1;
159                char *token = strtok_r(line, " \t\n", &saveptr1);
160
161                if (token)
162                {
163                    token = strtok_r(NULL, " \t,\n", &saveptr1);
164
165                    P1MSG("save path %s \n", token);
166                    strcpy(mount_path, token);
167
168                    /*
169                    ** @ftpRW
170                    **  update the r/w mode from mount message
171                    */
172                    token = strtok_r(NULL, " \t,\n", &saveptr1);//fs type
173                    token = strtok_r(NULL, " \t,\n", &saveptr1);//rw
174                    if(!strstr(token,"w"))
175                        readOnlyOnPart1 = 1;
176
177
178                    break;
179                } //if token
180
181            }
182        } //while 1 -> read lines in files
183        fclose(fp);
184    }
185    else
186    {
187        fprintf(stderr, "open /porc/mount failed\n");
188    }
189}
190/* szzz added end */
191
192
193
194
195
196char *mygetpwuid (int uid, FILE * file, char *name)
197{
198    int _uid;
199    char foo[256];
200    int i;
201
202    if (file)
203    {
204        rewind (file);
205        while (fscanf (file, "%255s%*[^\n]\n", foo) != EOF)
206        {
207            if ((foo[0] == '#') || (!strchr (foo, ':'))
208                || (strchr (foo, ':') > foo + USERLEN - 1))
209                continue;
210            i = strchr (foo, ':') - foo;
211            strncpy (name, foo, i);
212            name[i] = 0;
213            sscanf (strchr (foo + i + 1, ':') + 1, "%i", &_uid);
214            if (_uid == uid)
215            {
216                if (name[0] == '\n')
217                    cutto (name, 1);
218                return name;
219            }
220        }
221    }
222    sprintf (name, "%i", uid);
223    return name;
224}
225
226int mygetpwnam (char *name, FILE * file)
227{
228    char _name[USERLEN + 1];
229    char foo[256];
230    int uid, i;
231
232    if (file)
233    {
234        rewind (file);
235        while (fscanf (file, "%255s%*[^\n]\n", foo) != EOF)
236        {
237            if ((foo[0] == '#') || (!strchr (foo, ':'))
238                || (strchr (foo, ':') > foo + USERLEN - 1))
239                continue;
240            i = strchr (foo, ':') - foo;
241            strncpy (_name, foo, i);
242            _name[i] = 0;
243            sscanf (strchr (foo + i + 1, ':') + 1, "%i", &uid);
244            if (_name[0] == '\n')
245                cutto (_name, 1);
246            if (!strcmp (name, _name))
247                return uid;
248        }
249    }
250    return -1;
251}
252
253#ifdef HAVE_UTMP_H
254void wtmp_init ()
255{
256    if (strcasecmp (config_getoption ("LOG_WTMP"), "no"))
257    {
258        if (!((wtmp = fopen (_PATH_WTMP, "a"))))
259            bftpd_log ("Warning: Unable to open %s.\n", _PATH_WTMP);
260    }
261}
262
263void bftpd_logwtmp (char type)
264{
265    struct utmp ut;
266
267    if (!wtmp)
268        return;
269    memset ((void *) &ut, 0, sizeof (ut));
270#ifdef _HAVE_UT_PID
271    ut.ut_pid = getpid ();
272#endif
273    sprintf (ut.ut_line, "ftp%i", (int) getpid ());
274    if (type)
275    {
276#ifdef _HAVE_UT_TYPE
277        ut.ut_type = USER_PROCESS;
278#endif
279        strncpy (ut.ut_name, user, sizeof (ut.ut_name));
280#ifdef _HAVE_UT_HOST
281        strncpy (ut.ut_host, remotehostname, sizeof (ut.ut_host));
282#endif
283    }
284    else
285    {
286#ifdef _HAVE_UT_TYPE
287        ut.ut_type = DEAD_PROCESS;
288#endif
289    }
290    time (&(ut.ut_time));
291    fseek (wtmp, 0, SEEK_END);
292    fwrite ((void *) &ut, sizeof (ut), 1, wtmp);
293    fflush (wtmp);
294}
295
296void wtmp_end ()
297{
298    if (wtmp)
299    {
300        if (state >= STATE_AUTHENTICATED)
301            bftpd_logwtmp (0);
302        fclose (wtmp);
303    }
304}
305#endif
306
307void login_init ()
308{
309    char *foo = config_getoption ("INITIAL_CHROOT");
310
311#ifdef HAVE_UTMP_H
312    wtmp_init ();
313#endif
314    if (foo[0])
315    {                           /* Initial chroot */
316        if (chroot (foo) == -1)
317        {
318            control_printf (SL_FAILURE, "421 Initial chroot failed.\r\n.");
319            exit (1);
320        }
321    }
322}
323
324int bftpd_setuid (uid_t uid)
325{
326    /* If we must open the data connections from port 20,
327     * we have to keep the possibility to regain root privileges */
328    if (!strcasecmp (config_getoption ("DATAPORT20"), "yes"))
329        return seteuid (uid);
330    else
331        return setuid (uid);
332}
333
334int bftpd_login (char *password)
335{
336    char str[256];
337    char *foo;
338    int maxusers;
339    char *file_auth;            /* if used, points to file used to auth users */
340    char *home_directory = NULL;        /* retrieved from auth_file */
341    char *anonymous = NULL;
342    char chfolder [256]=""; /* Foxconn add, Jasmine Yang, 09/12/2007 */
343    char tmpBuf[256] = "";/*foxconn, water, 11/07/2008*/
344
345    P1MSG("%s(%d)\r\n", __FUNCTION__, __LINE__);
346    str[0] = '\0';              /* avoid garbage in str */
347    file_auth = config_getoption ("FILE_AUTH");
348
349    if (!file_auth[0])          /* not using auth file */
350    {
351        // check to see if regular authentication is avail
352#ifndef NO_GETPWNAM
353        if (!getpwnam (user))
354        {
355            /* foxconn added start, zacker, 09/13/2010, @chrome_login */
356            if (strcasecmp (config_getoption ("ANONYMOUS_USER"), "yes")
357                && !strcasecmp (user, "anonymous"))
358            {
359                control_printf (SL_FAILURE, "530 Sorry, no ANONYMOUS access allowed.");
360                return 0; /* STATE_USER, for later command 'QUIT' handling */
361            }
362            /* foxconn added end, zacker, 09/13/2010, @chrome_login */
363            else
364            {
365                control_printf (SL_FAILURE, "421 Login incorrect.");
366                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
367                exit (0);
368            }
369        }
370#endif
371    }
372    /* we are using auth_file */
373    else
374    {
375        home_directory = check_file_password (file_auth, user, password);
376        anonymous = config_getoption ("ANONYMOUS_USER");
377        if (!home_directory)
378        {
379            if (!strcasecmp (anonymous, "yes"))
380                home_directory = "/";
381            else
382            {
383                control_printf (SL_FAILURE, "421 Authentication incorrect.");
384                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
385                exit (0);
386            }
387        }
388    }
389
390    if (strncasecmp (foo = config_getoption ("DENY_LOGIN"), "no", 2))
391    {
392        if (foo[0] != '\0')
393        {
394            if (strncasecmp (foo, "yes", 3))
395            {
396                control_printf (SL_FAILURE,
397                                "421-Server disabled.\r\n421 Reason: %s",
398                                foo);
399                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
400            }
401            else
402            {
403                control_printf (SL_FAILURE, "421 Login incorrect.");
404                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
405            }
406            bftpd_log ("Login as user '%s' failed: Server disabled.\n", user);
407            exit (0);
408        }
409    }
410    maxusers = strtoul (config_getoption ("USERLIMIT_GLOBAL"), NULL, 10);
411    if ((maxusers) && (maxusers == bftpdutmp_usercount ("*")))
412    {
413        control_printf (SL_FAILURE,
414                        "421 There are already %i users logged in.",
415                        maxusers);
416        bftpd_log ("Login as user '%s' failed. Too many users on server.\n",
417                   user);
418        //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
419        exit (0);
420    }
421    maxusers = strtoul (config_getoption ("USERLIMIT_SINGLEUSER"), NULL, 10);
422    if ((maxusers) && (maxusers == bftpdutmp_usercount (user)))
423    {
424        control_printf (SL_FAILURE,
425                        "421 User %s is already logged in %i times.", user,
426                        maxusers);
427        bftpd_log ("Login as user '%s' failed. Already logged in %d times.",
428                   maxusers);
429        //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
430        exit (0);
431    }
432
433    /* Check to see if we should block mulitple logins from the same machine.
434       -- Jesse <slicer69@hotmail.com>
435     */
436    maxusers = strtoul (config_getoption ("USERLIMIT_HOST"), NULL, 10);
437    if ((maxusers) && (maxusers == bftpdutmp_dup_ip_count (remotehostname)))
438    {
439        control_printf (SL_FAILURE,
440                        "421 Too many connections from your IP address.");
441        bftpd_log
442            ("Login as user '%s' failed. Already %d connections from %s.\n",
443             user, maxusers, remotehostname);
444        //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
445        exit (0);
446    }
447
448    /* disable these checks when logging in via auth file */
449    if (!file_auth[0])
450    {
451#ifndef NO_GETPWNAM
452/* Foxconn add start, Jasmine Yang, 09/12/2007 */
453        //if (checkuser () || checkshell ())
454        if (checkuser ())
455/* Foxconn add end, Jasmine Yang, 09/12/2007 */
456        {
457            control_printf (SL_FAILURE, "421 Login incorrect.");
458            //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
459            exit (0);
460        }
461#endif
462    }
463
464    /* do not do this check when we are using auth_file */
465    if (!file_auth[0])
466    {
467#ifndef NO_GETPWNAM
468        if (checkpass (password))
469            return 1;
470#endif
471    }
472
473    if (strcasecmp ((char *) config_getoption ("RATIO"), "none"))
474    {
475        sscanf ((char *) config_getoption ("RATIO"), "%i/%i", &ratio_send,
476                &ratio_recv);
477    }
478
479    /* do these checks if logging in via normal methods */
480    if (!file_auth[0])
481    {
482        strcpy (str, config_getoption ("ROOTDIR"));
483        if (!str[0])
484            strcpy (str, "%h");
485        P1MSG("userinfo.pw_name=%s,userinfo.pw_dir=%s\r\n",  userinfo.pw_name, userinfo.pw_dir);
486        replace (str, "%u", userinfo.pw_name);
487        strcpy(tmpBuf, userinfo.pw_dir);/*foxconn, water, 11/07/2008*/
488        replace (str, "%h", userinfo.pw_dir);
489        if (!strcasecmp (config_getoption ("RESOLVE_UIDS"), "yes"))
490        {
491            passwdfile = fopen ("/etc/passwd", "r");
492            groupfile = fopen ("/etc/group", "r");
493        }
494
495        setgid (userinfo.pw_gid);
496        initgroups (userinfo.pw_name, userinfo.pw_gid);
497        /* Foxconn add start, Jasmine Yang, 09/12/2007 */
498        scanPartitons(); //zzz, get first partition, 12/11/2007
499        /* Make sure the login folder is user's account name */
500
501        /* Foxconn Add Start : Steve Hsieh : 01/22/2008, @ftpRW {*/
502        /* -- should use shared dir in usb_setting page as root dir --*/
503
504        /*foxconn modified start, water, 11/07/2008,
505          I think it isn't a good solution, need further implement later*/
506        //sprintf (chfolder, "%s/%s", mount_path, userinfo.pw_name);
507        sprintf (chfolder, "%s%s", mount_path, tmpBuf);
508        /*foxconn modified end, water, 11/07/2008, it isn't a good solution, need further implement*/
509
510        /* Foxconn Add End : Steve Hsieh : 01/22/2008, @ftpRW }*/
511
512        //water add temporarily, no usb now, it will be removed soon, @debug 05/30/2008
513        //sprintf (chfolder, "/tmp");
514
515
516        /*
517        **  @ftpRW
518        **  if readonly fs, just use the "/" as root dir
519        */
520        //if (access (chfolder, 7) != 0)
521        if(readOnlyOnPart1)
522        {
523            /* zzz add. 12/11/2007 */
524            //set ftp root to "/" if the mounted partition is read only
525            bftpd_log("partition 1 is readonly\n");
526            sprintf (chfolder, "%s", mount_path);
527
528            printf("checking %s\n", mount_path);
529
530            if (access(chfolder, R_OK|X_OK) == 0 )
531            {
532                sprintf (chfolder, "%s", mount_path);
533            }
534            else
535            {
536                //zzz: Is this correct? Think twice??
537            sprintf(chfolder, "/tmp/samba/share/%s", userinfo.pw_name);
538            }
539            /* zzz added. 12/11/2007 */
540        }
541        else    //RW file system
542        {
543            /*
544            **  mkdir to the target shared forder if the dir is not exist
545            */
546            if (access (chfolder, R_OK) != 0)
547            {
548                char cmdx[512]="";
549                sprintf(cmdx,"mkdir -p %s",chfolder) ;
550                bftpd_log("create dir [%s]\n",chfolder);
551                system(cmdx);
552            }
553        }
554
555        /* Foxconn modified start pling 05/14/2009 */
556        /* Change rootdir to "/tmp" */
557        //strcpy(str,chfolder );
558        strcpy(str, "/tmp" );
559        /* Foxconn modified end pling 05/14/2009 */
560	/* Foxconn added start by Jenny Zhao, 06/10/2011 @USB log */
561        /* In fact, we want to write USB remote access log after "230
562	 * User logged in.". But the log file /dev/aglog can't be opened
563	 * after chroot to "/tmp",we write log at here before do chroot
564	 * function */
565        write_usb_access_log();
566        /* Foxconn added end by Jenny Zhao, 06/10/2011 */
567
568        /* Foxconn add end, Jasmine Yang, 09/12/2007 */
569        if (strcasecmp (config_getoption ("DO_CHROOT"), "no"))
570        {
571            bftpd_log("change for ROOTDIR [%s]\n",chfolder);
572            if (chroot (str))
573            {
574                control_printf (SL_FAILURE,
575                                "421 Unable to change root directory.\r\n%s.",
576                                strerror (errno));
577                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
578                exit (0);
579            }
580            if (bftpd_setuid (userinfo.pw_uid))
581            {
582                control_printf (SL_FAILURE, "421 Unable to change uid.");
583                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
584                exit (0);
585            }
586            if (chdir ("/"))
587            {
588                control_printf (SL_FAILURE,
589                                "421 Unable to change working directory.\r\n%s.",
590                                strerror (errno));
591                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
592                exit (0);
593            }
594        }
595        else
596        {
597            if (bftpd_setuid (userinfo.pw_uid))
598            {
599                control_printf (SL_FAILURE, "421 Unable to change uid.");
600                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
601                exit (0);
602            }
603            if (chdir (str))
604            {
605                control_printf (SL_FAILURE,
606                                "230 Couldn't change cwd to '%s': %s.", str,
607                                strerror (errno));
608                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
609                chdir ("/");
610            }
611        }
612
613    }                           /* end of if we are using regular authentication methods */
614
615    else                        /* we are using file authentication */
616    {
617        /* get home directory */
618        strcpy (str, config_getoption ("ROOTDIR"));
619        if (!str[0])
620            strcpy (str, "%h");
621        replace (str, "%h", home_directory);
622        replace (str, "%u", user);
623
624        /* see if we should change root */
625        if (!strcasecmp (config_getoption ("DO_CHROOT"), "yes"))
626        {
627            if (chroot (home_directory))
628            {
629                control_printf (SL_FAILURE,
630                                "421 Unable to change root directory.\r\n");
631                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
632                exit (0);
633            }
634            if (chdir ("/"))
635            {
636                control_printf (SL_FAILURE,
637                                "421 Unable to change working directory.\r\n");
638                //printf ("%s(%d)\r\n", __FUNCTION__, __LINE__);
639                exit (0);
640            }
641        }
642
643    }                           /* end of using file auth */
644
645    new_umask ();
646    print_file (230, config_getoption ("MOTD_USER"));
647    control_printf (SL_SUCCESS, "230 User logged in.");
648#ifdef HAVE_UTMP_H
649    bftpd_logwtmp (1);
650#endif
651    bftpdutmp_log (1);
652    bftpd_log ("Successfully logged in as user '%s'.\n", user);
653    if (config_getoption ("AUTO_CHDIR")[0])
654        chdir (config_getoption ("AUTO_CHDIR"));
655
656    state = STATE_AUTHENTICATED;
657    bftpd_cwd_init ();
658
659    /* a little clean up before we go */
660    if ((home_directory) && (strcmp (home_directory, "/")))
661        free (home_directory);
662    return 0;
663}
664
665
666/* Return 1 on failure and 0 on success. */
667int checkpass (char *password)
668{
669#ifndef NO_GETPWNAM
670    if (!getpwnam (user))
671        return 1;
672#endif
673
674    if (!strcasecmp (config_getoption ("ANONYMOUS_USER"), "yes"))
675        return 0;
676
677#ifdef WANT_PAM
678    if (!strcasecmp (config_getoption ("AUTH"), "pam"))
679        return checkpass_pam (password);
680    else
681#endif
682        return checkpass_pwd (password);
683}
684
685
686
687void login_end ()
688{
689#ifdef WANT_PAM
690    if (usepam)
691        return end_pam ();
692#endif
693#ifdef HAVE_UTMP_H
694    wtmp_end ();
695#endif
696}
697
698int checkpass_pwd (char *password)
699{
700#ifdef HAVE_SHADOW_H
701    struct spwd *shd;
702#endif
703/* Foxconn add start, Jasmine Yang, 09/12/2007 */
704    //if (strcmp(userinfo.pw_passwd, (char *) crypt(password, userinfo.pw_passwd))) {
705
706    P1MSG("%s(%d)userinfo.pw_passwd=%s , password=%s \r\n", __FUNCTION__,
707            __LINE__, userinfo.pw_passwd, password);
708
709    int i;
710    char * pData = NULL;
711#ifdef SHA256_DIGEST_LENGTH
712    //using SHA256
713    char password_hash[SHA256_DIGEST_LENGTH] = "";
714    char password_hash_str[2*SHA256_DIGEST_LENGTH+1] = "";
715    pData = password_hash_str;
716    SHA256(password, strlen(password), password_hash);
717    for (i=0; i<SHA256_DIGEST_LENGTH; i++) {
718        sprintf(pData,"%02x",(unsigned char)password_hash[i]);
719        pData += 2;
720    }
721#else
722    //using SHA1
723    char password_hash[SHA_DIGEST_LENGTH] = "";
724    char password_hash_str[2*SHA_DIGEST_LENGTH+1] = "";
725    pData = password_hash_str;
726    SHA1(password, strlen(password), password_hash);
727    for (i=0; i<SHA_DIGEST_LENGTH; i++) {
728        sprintf(pData,"%02x",(unsigned char)password_hash[i]);
729        pData += 2;
730    }
731#endif
732    //if (strcmp (userinfo.pw_passwd, password))
733    if (strcmp (userinfo.pw_passwd, password_hash_str))
734    {
735/* Foxconn add end, Jasmine Yang, 09/12/2007 */
736#ifdef HAVE_SHADOW_H
737        if (!(shd = getspnam (user)))
738            return 1;
739        if (strcmp (shd->sp_pwdp, (char *) crypt (password, shd->sp_pwdp)))
740#endif
741            return 1;
742    }
743    return 0;
744}
745
746#ifdef WANT_PAM
747int conv_func (int num_msg, const struct pam_message **msgm,
748               struct pam_response **resp, void *appdata_ptr)
749{
750    struct pam_response *response;
751    int i;
752    response =
753        (struct pam_response *) malloc (sizeof (struct pam_response) *
754                                        num_msg);
755    for (i = 0; i < num_msg; i++)
756    {
757        response[i].resp = (char *) strdup (appdata_ptr);
758        response[i].resp_retcode = 0;
759    }
760    *resp = response;
761    return 0;
762}
763
764int checkpass_pam (char *password)
765{
766    struct pam_conv conv = { conv_func, password };
767    int retval = pam_start ("bftpd", user, (struct pam_conv *) &conv,
768                            (pam_handle_t **) & pamh);
769
770    if (retval != PAM_SUCCESS)
771    {
772        printf ("Error while initializing PAM: %s\n",
773                pam_strerror (pamh, retval));
774        return 1;
775    }
776    pam_fail_delay (pamh, 0);
777    retval = pam_authenticate (pamh, 0);
778    if (retval == PAM_SUCCESS)
779        retval = pam_acct_mgmt (pamh, 0);
780    if (retval == PAM_SUCCESS)
781        pam_open_session (pamh, 0);
782    if (retval != PAM_SUCCESS)
783        return 1;
784    else
785        return 0;
786}
787
788void end_pam ()
789{
790    if (pamh)
791    {
792        pam_close_session (pamh, 0);
793        pam_end (pamh, 0);
794    }
795}
796#endif
797
798int checkuser ()
799{
800
801    FILE *fd;
802    char *p;
803    char line[256];
804
805    if ((fd = fopen (config_getoption ("PATH_FTPUSERS"), "r")))
806    {
807        while (fgets (line, sizeof (line), fd))
808            if ((p = strchr (line, '\n')))
809            {
810                *p = '\0';
811                if (line[0] == '#')
812                    continue;
813                if (!strcasecmp (line, user))
814                {
815                    fclose (fd);
816                    return 1;
817                }
818            }
819        fclose (fd);
820    }
821    return 0;
822}
823
824int checkshell ()
825{
826#ifdef HAVE_GETUSERSHELL
827    char *cp;
828    struct passwd *pwd;
829
830    if (!strcasecmp (config_getoption ("AUTH_ETCSHELLS"), "no"))
831        return 0;
832
833    pwd = getpwnam (user);
834    while ((cp = getusershell ()))
835        if (!strcmp (cp, pwd->pw_shell))
836            break;
837    endusershell ();
838
839    if (!cp)
840        return 1;
841    else
842        return 0;
843#else
844    return 0;
845#   warning "Your system doesn't have getusershell(). You can not"
846#   warning "use /etc/shells authentication with bftpd."
847#endif
848}
849
850
851
852
853/*
854This function searches through a text file for a matching
855username. If a match is found, the password in the
856text file is compared to the password passed in to
857the function. If the password matches, the function
858returns the fourth field (home directory). On failure,
859it returns NULL.
860-- Jesse
861*/
862char *check_file_password (char *my_filename, char *my_username,
863                           char *my_password)
864{
865    FILE *my_file;
866    int found_user = 0;
867    char user[32], password[32], group[32], home_dir[32];
868    char *my_home_dir = NULL;
869    int return_value;
870
871    my_file = fopen (my_filename, "r");
872    if (!my_file)
873        return NULL;
874
875    return_value =
876        fscanf (my_file, "%s %s %s %s", user, password, group, home_dir);
877    if (!strcmp (user, my_username))
878        found_user = 1;
879
880    while ((!found_user) && (return_value != EOF))
881    {
882        return_value =
883            fscanf (my_file, "%s %s %s %s", user, password, group, home_dir);
884        if (!strcmp (user, my_username))
885            found_user = 1;
886    }
887
888    fclose (my_file);
889    if (found_user)
890    {
891        /* check password */
892        if (!strcmp (password, "*"))
893        {
894        }
895        else if (strcmp (password, my_password))
896            return NULL;
897
898        my_home_dir = calloc (strlen (home_dir), sizeof (char));
899        if (!my_home_dir)
900            return NULL;
901        strcpy (my_home_dir, home_dir);
902    }
903
904    return my_home_dir;
905}
906