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