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