1 /* 2 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 3 * Use is subject to license terms. 4 */ 5 6 #pragma ident "%Z%%M% %I% %E% SMI" 7 8 /**************************************************************************** 9 10 Copyright (c) 1999,2000,2001 WU-FTPD Development Group. 11 All rights reserved. 12 13 Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994 14 The Regents of the University of California. 15 Portions Copyright (c) 1993, 1994 Washington University in Saint Louis. 16 Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc. 17 Portions Copyright (c) 1989 Massachusetts Institute of Technology. 18 Portions Copyright (c) 1998 Sendmail, Inc. 19 Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P. Allman. 20 Portions Copyright (c) 1997 by Stan Barber. 21 Portions Copyright (c) 1997 by Kent Landfield. 22 Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997 23 Free Software Foundation, Inc. 24 25 Use and distribution of this software and its source code are governed 26 by the terms and conditions of the WU-FTPD Software License ("LICENSE"). 27 28 If you did not receive a copy of the license, it may be obtained online 29 at http://www.wu-ftpd.org/license.html. 30 31 $Id: ftpd.c,v 1.111 2000/07/01 18:17:39 wuftpd Exp $ 32 33 ****************************************************************************/ 34 /* FTP server. */ 35 #include "config.h" 36 37 #include <sys/types.h> 38 #include <sys/param.h> 39 #include <sys/stat.h> 40 #include <sys/ioctl.h> 41 #include <sys/socket.h> 42 #include <sys/file.h> 43 #include <sys/wait.h> 44 45 #ifdef AIX 46 #include <sys/id.h> 47 #include <sys/priv.h> 48 #include <netinet/if_ether.h> 49 #include <net/if_dl.h> 50 #endif 51 52 #ifdef AUX 53 #include <compat.h> 54 #endif 55 56 #include <netinet/in.h> 57 #include <netinet/in_systm.h> 58 #include <netinet/ip.h> 59 60 #define FTP_NAMES 61 #include <arpa/ftp.h> 62 #include <arpa/inet.h> 63 64 #include <ctype.h> 65 #include <stdio.h> 66 #include <stdlib.h> 67 #include <signal.h> 68 #include <pwd.h> 69 #include <grp.h> 70 #include <setjmp.h> 71 #include <errno.h> 72 #include <string.h> 73 #ifdef INTERNAL_LS 74 #ifdef HAVE_GLOB_H 75 #include <glob.h> 76 #else 77 #include <wuftpd_glob.h> 78 #endif 79 #endif 80 #ifdef HAVE_GRP_H 81 #include <grp.h> 82 #endif 83 #include <sys/stat.h> 84 85 #define VA_LOCAL_DECL va_list ap; 86 #define VA_START(f) va_start(ap, f) 87 #define VA_END va_end(ap) 88 89 #include "proto.h" 90 91 #ifdef HAVE_UFS_QUOTA_H 92 #include <ufs/quota.h> 93 #endif 94 #ifdef HAVE_SYS_FS_UFS_QUOTA_H 95 #include <sys/fs/ufs_quota.h> 96 #endif 97 98 #ifdef HAVE_SYS_SYSLOG_H 99 #include <sys/syslog.h> 100 #endif 101 #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H)) 102 #include <syslog.h> 103 #endif 104 #ifdef TIME_WITH_SYS_TIME 105 #include <time.h> 106 #include <sys/time.h> 107 #else 108 #ifdef HAVE_SYS_TIME_H 109 #include <sys/time.h> 110 #else 111 #include <time.h> 112 #endif 113 #endif 114 115 #ifdef HAVE_SYS_SENDFILE_H 116 #include <sys/sendfile.h> 117 #endif 118 119 #include "conversions.h" 120 #include "extensions.h" 121 122 #ifdef SHADOW_PASSWORD 123 #include <shadow.h> 124 #endif 125 126 #include "pathnames.h" 127 128 #ifdef M_UNIX 129 #include <arpa/nameser.h> 130 #include <resolv.h> 131 #endif 132 133 #if defined(HAVE_FCNTL_H) 134 #include <fcntl.h> 135 #endif 136 137 #ifdef HAVE_SYSINFO 138 #include <sys/systeminfo.h> 139 #endif 140 141 #ifdef KERBEROS 142 #include <sys/types.h> 143 #include <auth.h> 144 #include <krb.h> 145 #endif 146 147 #ifdef ULTRIX_AUTH 148 #include <auth.h> 149 #include <sys/svcinfo.h> 150 #endif 151 152 #ifndef HAVE_LSTAT 153 #define lstat stat 154 #endif 155 156 #ifdef AFS_AUTH 157 #include <afs/stds.h> 158 #include <afs/kautils.h> 159 #endif 160 161 #ifdef DCE_AUTH 162 #include <dce/rpc.h> 163 #include <dce/sec_login.h> 164 #include <dce/dce_error.h> 165 #endif 166 167 168 #ifdef HAVE_DIRENT_H 169 #include <dirent.h> 170 #else 171 #include <sys/dir.h> 172 #endif 173 174 #if defined(USE_LONGJMP) 175 #define wu_longjmp(x, y) longjmp((x), (y)) 176 #define wu_setjmp(x) setjmp(x) 177 #ifndef JMP_BUF 178 #define JMP_BUF jmp_buf 179 #endif 180 #else 181 #define wu_longjmp(x, y) siglongjmp((x), (y)) 182 #define wu_setjmp(x) sigsetjmp((x), 1) 183 #ifndef JMP_BUF 184 #define JMP_BUF sigjmp_buf 185 #endif 186 #endif 187 188 #ifndef MAXHOSTNAMELEN 189 #define MAXHOSTNAMELEN 64 /* may be too big */ 190 #endif 191 192 #ifndef TRUE 193 #define TRUE 1 194 #endif 195 196 #ifndef FALSE 197 #define FALSE !TRUE 198 #endif 199 200 #ifdef MAIL_ADMIN 201 #define MAILSERVERS 10 202 #define INCMAILS 10 203 int mailservers = 0; 204 char *mailserver[MAILSERVERS]; 205 int incmails = 0; 206 char *incmail[INCMAILS]; 207 char *mailfrom; 208 char *email(char *full_address); 209 FILE *SockOpen(char *host, int clientPort); 210 char *SockGets(FILE *sockfp, char *buf, int len); 211 int SockWrite(char *buf, int size, int nels, FILE *sockfp); 212 int SockPrintf(FILE *sockfp, char *format,...); 213 int SockPuts(FILE *sockfp, char *buf); 214 int Reply(FILE *sockfp); 215 int Send(FILE *sockfp, char *format,...); 216 #endif /* MAIL_ADMIN */ 217 218 #if defined(_SCO_DS) && !defined(SIGURG) 219 #define SIGURG SIGUSR1 220 #endif 221 222 /* File containing login names NOT to be used on this machine. Commonly used 223 * to disallow uucp. */ 224 extern int errno; 225 226 extern char *ctime(const time_t *); 227 #ifndef NO_CRYPT_PROTO 228 extern char *crypt(const char *, const char *); 229 #endif 230 231 extern char version[]; 232 extern char *home; /* pointer to home directory for glob */ 233 extern char cbuf[]; 234 extern off_t restart_point; 235 extern int yyerrorcalled; 236 237 struct SOCKSTORAGE ctrl_addr; 238 struct SOCKSTORAGE data_source; 239 struct SOCKSTORAGE data_dest; 240 struct SOCKSTORAGE his_addr; 241 struct SOCKSTORAGE pasv_addr; 242 struct SOCKSTORAGE vect_addr; 243 int route_vectored = 0; 244 int passive_port_min = 1024; 245 int passive_port_max = 65535; 246 int restricted_user = 0; 247 unsigned short data_port = 0; 248 249 #ifdef INET6 250 int ctrl_v4mapped = 0; 251 int epsv_all = 0; 252 int listen_v4 = 0; /* when set, listen on IPv4 socket in standalone mode */ 253 #endif 254 255 #ifdef VIRTUAL 256 char virtual_root[MAXPATHLEN]; 257 char virtual_banner[MAXPATHLEN]; 258 char virtual_email[MAXPATHLEN]; 259 260 char virtual_hostname[MAXHOSTNAMELEN]; 261 char virtual_address[MAXHOSTNAMELEN]; 262 263 extern int virtual_mode; 264 extern int virtual_ftpaccess; 265 #endif 266 267 #ifdef QUOTA 268 extern struct dqblk quota; 269 #endif 270 271 #if defined(USE_GSS) 272 #include "gssutil.h" 273 274 extern gss_info_t gss_info; 275 276 int allow_ccc = 0; 277 int ccc_ok = 0; 278 extern char *cur_auth_type; 279 #endif /* USE_GSS */ 280 281 int data; 282 jmp_buf errcatch; 283 JMP_BUF urgcatch; 284 int logged_in = 0; 285 struct passwd *pw; 286 char chroot_path[MAXPATHLEN]; 287 int debug = 0; 288 int disable_rfc931 = 0; 289 extern unsigned int timeout_idle; 290 extern unsigned int timeout_maxidle; 291 extern unsigned int timeout_data; 292 extern unsigned int timeout_accept; 293 extern unsigned int timeout_connect; 294 295 /* previously defaulted to 1, and -l or -L set them to 1, so that there was 296 no way to turn them *off*! Changed so that the manpage reflects common 297 sense. -L is way noisy; -l we'll change to be "just right". _H */ 298 int logging = 0; 299 int log_commands = 0; 300 int log_security = 0; 301 int syslogmsg = 0; 302 static int wtmp_logging = 1; 303 304 #ifdef SECUREOSF 305 #define SecureWare /* Does this mean it works for all SecureWare? */ 306 #endif 307 308 #ifdef HPUX_10_TRUSTED 309 #include <hpsecurity.h> 310 #endif 311 312 #if defined(SecureWare) || defined(HPUX_10_TRUSTED) 313 #include <prot.h> 314 #endif 315 316 int anonymous = 1; 317 int guest; 318 int type; 319 int form; 320 int stru; /* avoid C keyword */ 321 int mode; 322 int usedefault = 1; /* for data transfers */ 323 int pdata = -1; /* for passive mode */ 324 int transflag; 325 int ftwflag; 326 off_t file_size; 327 off_t byte_count; 328 int TCPwindowsize = 0; /* 0 = use system default */ 329 size_t sendbufsz; /* buffer size to use when sending data */ 330 size_t recvbufsz; /* buffer size to use when receiving data */ 331 332 #ifdef TRANSFER_COUNT 333 off_t data_count_total = 0; /* total number of data bytes */ 334 off_t data_count_in = 0; 335 off_t data_count_out = 0; 336 off_t byte_count_total = 0; /* total number of general traffic */ 337 off_t byte_count_in = 0; 338 off_t byte_count_out = 0; 339 int file_count_total = 0; /* total number of data files */ 340 int file_count_in = 0; 341 int file_count_out = 0; 342 int xfer_count_total = 0; /* total number of transfers */ 343 int xfer_count_in = 0; 344 int xfer_count_out = 0; 345 #ifdef TRANSFER_LIMIT 346 int file_limit_raw_in = 0; 347 int file_limit_raw_out = 0; 348 int file_limit_raw_total = 0; 349 int file_limit_data_in = 0; 350 int file_limit_data_out = 0; 351 int file_limit_data_total = 0; 352 off_t data_limit_raw_in = 0; 353 off_t data_limit_raw_out = 0; 354 off_t data_limit_raw_total = 0; 355 off_t data_limit_data_in = 0; 356 off_t data_limit_data_out = 0; 357 off_t data_limit_data_total = 0; 358 #ifdef RATIO /* 1998/08/04 K.Wakui */ 359 #define TRUNC_KB(n) ((n)/1024+(((n)%1024)?1:0)) 360 off_t total_free_dl = 0; 361 int upload_download_rate = 0; 362 int freefile; 363 int is_downloadfree( char * ); 364 #endif /* RATIO */ 365 #endif 366 #endif 367 368 int retrieve_is_data = 1; /* !0=data, 0=general traffic -- for 'ls' */ 369 char LastFileTransferred[MAXPATHLEN] = ""; 370 371 static char *RootDirectory = NULL; 372 373 #if !defined(CMASK) || CMASK == 0 374 #undef CMASK 375 #define CMASK 022 376 #endif 377 mode_t defumask = CMASK; /* default umask value */ 378 #ifdef ALTERNATE_CD 379 char defhome[] = "/"; 380 #endif 381 char tmpline[7]; 382 char hostname[MAXHOSTNAMELEN]; 383 char remotehost[MAXHOSTNAMELEN]; 384 char remoteaddr[MAXHOSTNAMELEN]; 385 char *remoteident = "[nowhere yet]"; 386 int rhlookup = TRUE; /* when TRUE lookup the remote hosts name */ 387 388 #if defined(SOLARIS_2) && !defined(NAME_SERVICE_DOOR) 389 #define NAME_SERVICE_DOOR "/var/run/name_service_door" 390 #endif 391 392 #if defined(SOLARIS_2) 393 int close_nsdoor(void *cb_data, int fd); 394 void cleanup_nscd(); 395 #endif 396 397 /* log failures 27-apr-93 ehk/bm */ 398 #define MAXUSERNAMELEN 256 399 char the_user[MAXUSERNAMELEN]; 400 401 /* Access control and logging passwords */ 402 /* OFF by default. _H */ 403 int use_accessfile = 0; 404 char guestpw[MAXHOSTNAMELEN]; 405 char privatepw[MAXHOSTNAMELEN]; 406 int nameserved = 0; 407 extern char authuser[]; 408 extern int authenticated; 409 extern int keepalive; 410 411 /* File transfer logging (xferlog) */ 412 int xferlog = 0; 413 int log_outbound_xfers = 0; 414 int log_incoming_xfers = 0; 415 char logfile[MAXPATHLEN]; 416 417 /* Allow use of lreply(); this is here since some older FTP clients don't 418 * support continuation messages. In violation of the RFCs... */ 419 int dolreplies = 1; 420 421 /* Spontaneous reply text. To be sent along with next reply to user */ 422 char *autospout = NULL; 423 int autospout_free = 0; 424 425 /* allowed on-the-fly file manipulations (compress, tar) */ 426 int mangleopts = 0; 427 428 /* number of login failures before attempts are logged and FTP *EXITS* */ 429 int lgi_failure_threshold = 5; 430 431 /* Timeout intervals for retrying connections to hosts that don't accept PORT 432 * cmds. This is a kludge, but given the problems with TCP... */ 433 #define SWAITMAX 90 /* wait at most 90 seconds */ 434 #define SWAITINT 5 /* interval between retries */ 435 436 int swaitmax = SWAITMAX; 437 int swaitint = SWAITINT; 438 439 SIGNAL_TYPE lostconn(int sig); 440 SIGNAL_TYPE randomsig(int sig); 441 SIGNAL_TYPE myoob(int sig); 442 FILE *getdatasock(char *mode); 443 FILE *dataconn(char *name, off_t size, char *mode); 444 void setproctitle(const char *fmt,...); 445 void initsetproctitle(int, char **, char **); 446 void reply(int, char *fmt,...); 447 void lreply(int, char *fmt,...); 448 449 #ifndef HAVE_VSNPRINTF 450 extern int vsnprintf(char *, size_t, const char *, va_list); 451 #endif 452 453 #ifndef HAVE_SNPRINTF 454 extern int snprintf(char *, size_t, const char *,...); 455 #endif 456 457 #ifdef NEED_SIGFIX 458 extern sigset_t block_sigmask; /* defined in sigfix.c */ 459 #endif 460 461 char proctitle[BUFSIZ]; /* initial part of title */ 462 463 #if defined(SKEY) && defined(OPIE) 464 #error YOU SHOULD NOT HAVE BOTH SKEY AND OPIE DEFINED!!!!! 465 #endif 466 467 #ifdef SKEY 468 #include <skey.h> 469 int pwok = 0; 470 #endif 471 472 #ifdef OPIE 473 #include <opie.h> 474 int pwok = 0; 475 int af_pwok = 0; 476 struct opie opiestate; 477 #endif 478 479 #ifdef KERBEROS 480 void init_krb(); 481 void end_krb(); 482 char krb_ticket_name[100]; 483 #endif /* KERBEROS */ 484 485 #ifdef ULTRIX_AUTH 486 int ultrix_check_pass(char *passwd, char *xpasswd); 487 #endif 488 489 #ifdef USE_PAM 490 #if defined(ULTRIX_AUTH) || defined(SECUREOSF) || defined(KERBEROS) || defined(SKEY) || defined (OPIE) || defined (BSD_AUTH) 491 #error No other auth methods are allowed with PAM. 492 #endif 493 #include <security/pam_appl.h> 494 static int pam_check_pass(char *user, char *passwd); 495 pam_handle_t *pamh; 496 #endif 497 498 #ifndef INTERNAL_LS 499 /* ls program commands and options for lreplies on and off */ 500 char ls_long[BUFSIZ * 2]; 501 char ls_short[BUFSIZ * 2]; 502 char ls_plain[BUFSIZ * 2]; 503 #endif 504 505 #define FTPD_OPTS ":4aAdiIlLoP:qQr:t:T:u:vVwWxX" 506 #if defined(DAEMON) 507 # define DAEMON_OPTS "p:sS" 508 #else /* !(defined(DAEMON)) */ 509 # define DAEMON_OPTS 510 #endif /* !(defined(DAEMON)) */ 511 #if defined(USE_GSS) 512 # define GSS_OPTS "CK" 513 #else /* !(defined(USE_GSS)) */ 514 # define GSS_OPTS 515 #endif /* !(defined(USE_GSS)) */ 516 517 /* Some systems use one format, some another. This takes care of the garbage */ 518 #ifndef L_FORMAT /* Autoconf detects this... */ 519 #if (defined(BSD) && (BSD >= 199103)) && !defined(LONGOFF_T) 520 #define L_FORMAT "qd" 521 #else 522 #ifdef _AIX42 523 #define L_FORMAT "lld" 524 #else 525 #ifdef SOLARIS_2 526 #define L_FORMAT "ld" 527 #else 528 #define L_FORMAT "d" 529 #endif 530 #endif 531 #endif 532 #endif 533 534 #ifdef DAEMON 535 int be_daemon = 0; /* Run standalone? */ 536 int daemon_port = 0; 537 static void do_daemon(void); 538 #endif 539 int Bypass_PID_Files = 0; 540 541 #ifdef OTHER_PASSWD 542 #include "getpwnam.h" 543 char _path_passwd[MAXPATHLEN]; 544 #ifdef SHADOW_PASSWORD 545 char _path_shadow[MAXPATHLEN]; 546 #endif 547 #endif 548 #if defined(USE_PAM) && defined(OTHER_PASSWD) 549 int use_pam = 1; 550 #else 551 int use_pam = 0; 552 #endif 553 554 void print_copyright(void); 555 char *mapping_getcwd(char *path, size_t size); 556 557 void dolog(struct SOCKSTORAGE *); 558 559 #ifdef THROUGHPUT 560 extern void throughput_calc(char *, int *, double *); 561 extern void throughput_adjust(char *); 562 #endif 563 564 time_t login_time; 565 time_t limit_time = 0; 566 567 int regexmatch(char *name, char *rgexp); 568 569 int pasv_allowed(char *remoteaddr); 570 int port_allowed(char *remoteaddr); 571 572 #if sparc && !__svr4__ 573 int fclose(FILE *); 574 #endif 575 576 static SIGNAL_TYPE alarm_signal(int sig) 577 { 578 } 579 580 static FILE *draconian_FILE = NULL; 581 582 static SIGNAL_TYPE draconian_alarm_signal(int sig) 583 { 584 if (draconian_FILE != NULL) { 585 fclose(draconian_FILE); 586 draconian_FILE = NULL; 587 } 588 (void) signal(SIGALRM, draconian_alarm_signal); 589 } 590 591 static void socket_flush_wait(FILE *file) 592 { 593 static int flushwait = TRUE; 594 static int first_time = TRUE; 595 char c; 596 int set; 597 int fd = fileno(file); 598 int serrno = errno; 599 struct aclmember *entry; 600 601 if (first_time) { 602 entry = NULL; 603 /* flush-wait yes|no [typelist] */ 604 while (getaclentry("flush-wait", &entry)) { 605 if (!ARG0) 606 continue; 607 if (strcasecmp(ARG0, "yes") == 0) 608 set = TRUE; 609 else if (strcasecmp(ARG0, "no") == 0) 610 set = FALSE; 611 else 612 continue; 613 614 if (!ARG1) 615 flushwait = set; 616 else if (type_match(ARG1)) { 617 flushwait = set; 618 break; 619 } 620 } 621 first_time = FALSE; 622 } 623 if (flushwait) { 624 if (draconian_FILE != NULL) 625 shutdown(fd, 1); 626 if (draconian_FILE != NULL) 627 read(fd, &c, 1); 628 } 629 errno = serrno; 630 /* 631 * GAL - the read() here should be checked to ensure it returned 0 (indicating 632 * EOF) or -1 (an error occurred). Anything else (real data) is a protocol 633 * error. 634 */ 635 } 636 637 static int IPClassOfService(const char *type) 638 { 639 int ipcos = -1, value; 640 char *endp; 641 struct aclmember *entry = NULL; 642 643 /* ipcos control|data <value> [<typelist>] */ 644 while (getaclentry("ipcos", &entry)) { 645 if (ARG0 && ARG1) { 646 if (strcasecmp(type, ARG0) == 0) { 647 if (!ARG2) { 648 errno = 0; 649 value = (int) strtol(ARG1, &endp, 0); 650 if ((errno == 0) && (value >= 0) && (*endp == '\0')) 651 ipcos = value; 652 } 653 else if (type_match(ARG2)) { 654 errno = 0; 655 value = (int) strtol(ARG1, &endp, 0); 656 if ((errno == 0) && (value >= 0) && (*endp == '\0')) { 657 ipcos = value; 658 break; 659 } 660 } 661 } 662 } 663 } 664 return ipcos; 665 } 666 667 int main(int argc, char **argv, char **envp) 668 { 669 #if defined(UNIXWARE) || defined(AIX) 670 size_t addrlen; 671 #else 672 int addrlen; 673 #endif 674 int on = 1; 675 int cos; 676 int c; 677 #ifndef INTERNAL_LS 678 int which; 679 #endif 680 extern int optopt; 681 extern char *optarg; 682 char *hp; 683 struct aclmember *entry; 684 #ifdef VIRTUAL 685 #if defined(UNIXWARE) || defined(AIX) 686 size_t virtual_len; 687 #else 688 int virtual_len; 689 #endif 690 struct SOCKSTORAGE virtual_addr; 691 #endif 692 struct servent *serv; 693 694 #ifdef AUX 695 setcompat(COMPAT_POSIX | COMPAT_BSDSETUGID); 696 #endif 697 698 closelog(); 699 #ifdef FACILITY 700 openlog("ftpd", LOG_PID | LOG_NDELAY, FACILITY); 701 #else 702 openlog("ftpd", LOG_PID); 703 #endif 704 705 #ifdef SecureWare 706 setluid(1); /* make sure there is a valid luid */ 707 set_auth_parameters(argc, argv); 708 setreuid(0, 0); 709 #endif 710 #if defined(M_UNIX) && !defined(_M_UNIX) 711 res_init(); /* bug in old (1.1.1) resolver */ 712 _res.retrans = 20; /* because of fake syslog in 3.2.2 */ 713 setlogmask(LOG_UPTO(LOG_INFO)); 714 #endif 715 716 while ((c = getopt(argc, argv, FTPD_OPTS DAEMON_OPTS GSS_OPTS)) != -1) { 717 switch (c) { 718 719 case '4': 720 #ifdef INET6 721 listen_v4 = 1; 722 #endif 723 break; 724 725 case 'a': 726 use_accessfile = 1; 727 break; 728 729 case 'A': 730 use_accessfile = 0; 731 break; 732 733 case 'v': 734 debug = 1; 735 break; 736 737 case 'd': 738 debug = 1; 739 break; 740 741 #if defined(USE_GSS) 742 case 'C': 743 gss_info.want_creds = 1; 744 break; 745 746 case 'K': 747 gss_info.must_gss_auth = 1; 748 break; 749 #endif /* USE_GSS */ 750 751 case 'l': 752 logging = 1; 753 break; 754 755 case 'L': 756 log_commands = 3; 757 break; 758 759 case 'i': 760 log_incoming_xfers = 3; 761 break; 762 763 case 'I': 764 disable_rfc931 = 1; 765 break; 766 767 case 'o': 768 log_outbound_xfers = 3; 769 break; 770 771 case 'q': 772 Bypass_PID_Files = 0; 773 break; 774 775 case 'Q': 776 Bypass_PID_Files = 1; 777 break; 778 779 case 'r': 780 if ((optarg != NULL) && (optarg[0] != '\0')) { 781 RootDirectory = malloc(strlen(optarg) + 1); 782 if (RootDirectory != NULL) 783 strcpy(RootDirectory, optarg); 784 } 785 break; 786 787 case 'P': 788 data_port = htons(atoi(optarg)); 789 break; 790 791 #ifdef DAEMON 792 case 'p': 793 daemon_port = atoi(optarg); 794 break; 795 796 case 's': 797 be_daemon = 1; 798 break; 799 800 case 'S': 801 be_daemon = 2; 802 break; 803 #endif /* DAEMON */ 804 805 case 't': 806 timeout_idle = atoi(optarg); 807 if (timeout_maxidle < timeout_idle) 808 timeout_maxidle = timeout_idle; 809 break; 810 811 case 'T': 812 timeout_maxidle = atoi(optarg); 813 if (timeout_idle > timeout_maxidle) 814 timeout_idle = timeout_maxidle; 815 break; 816 817 case 'u': 818 { 819 unsigned int val = 0; 820 821 while (*optarg && *optarg >= '0' && *optarg <= '7') 822 val = val * 8 + *optarg++ - '0'; 823 if (*optarg || val > 0777) 824 syslog(LOG_ERR, "bad value for -u"); 825 else 826 defumask = val; 827 break; 828 } 829 830 case 'V': 831 print_copyright(); 832 exit(0); 833 /* NOTREACHED */ 834 case 'w': 835 wtmp_logging = 1; 836 break; 837 838 case 'W': 839 wtmp_logging = 0; 840 break; 841 842 case 'x': 843 syslogmsg = 2; 844 break; 845 846 case 'X': 847 syslogmsg = 1; 848 break; 849 850 case ':': 851 syslog(LOG_ERR, "option -%c requires an argument", optopt); 852 break; 853 854 default: 855 syslog(LOG_ERR, "unknown option -%c ignored", optopt); 856 break; 857 } 858 } 859 initsetproctitle(argc, argv, envp); 860 (void) freopen(_PATH_DEVNULL, "w", stderr); 861 862 /* Checking for random signals ... */ 863 #ifdef NEED_SIGFIX 864 sigemptyset(&block_sigmask); 865 #endif 866 #ifndef SIG_DEBUG 867 #ifdef SIGHUP 868 (void) signal(SIGHUP, randomsig); 869 #ifdef NEED_SIGFIX 870 sigaddset(&block_sigmask, SIGHUP); 871 #endif 872 #endif 873 #ifdef SIGINT 874 (void) signal(SIGINT, randomsig); 875 #ifdef NEED_SIGFIX 876 sigaddset(&block_sigmask, SIGINT); 877 #endif 878 #endif 879 #ifdef SIGQUIT 880 (void) signal(SIGQUIT, randomsig); 881 #ifdef NEED_SIGFIX 882 sigaddset(&block_sigmask, SIGQUIT); 883 #endif 884 #endif 885 #ifdef SIGILL 886 (void) signal(SIGILL, randomsig); 887 #ifdef NEED_SIGFIX 888 sigaddset(&block_sigmask, SIGILL); 889 #endif 890 #endif 891 #ifdef SIGTRAP 892 (void) signal(SIGTRAP, randomsig); 893 #ifdef NEED_SIGFIX 894 sigaddset(&block_sigmask, SIGTRAP); 895 #endif 896 #endif 897 #ifdef SIGIOT 898 (void) signal(SIGIOT, randomsig); 899 #ifdef NEED_SIGFIX 900 sigaddset(&block_sigmask, SIGIOT); 901 #endif 902 #endif 903 #ifdef SIGEMT 904 (void) signal(SIGEMT, randomsig); 905 #ifdef NEED_SIGFIX 906 sigaddset(&block_sigmask, SIGEMT); 907 #endif 908 #endif 909 #ifdef SIGFPE 910 (void) signal(SIGFPE, randomsig); 911 #ifdef NEED_SIGFIX 912 sigaddset(&block_sigmask, SIGFPE); 913 #endif 914 #endif 915 #ifdef SIGKILL 916 (void) signal(SIGKILL, randomsig); 917 #ifdef NEED_SIGFIX 918 sigaddset(&block_sigmask, SIGKILL); 919 #endif 920 #endif 921 #ifdef SIGBUS 922 (void) signal(SIGBUS, randomsig); 923 #ifdef NEED_SIGFIX 924 sigaddset(&block_sigmask, SIGBUS); 925 #endif 926 #endif 927 #ifdef SIGSEGV 928 (void) signal(SIGSEGV, randomsig); 929 #ifdef NEED_SIGFIX 930 sigaddset(&block_sigmask, SIGSEGV); 931 #endif 932 #endif 933 #ifdef SIGSYS 934 (void) signal(SIGSYS, randomsig); 935 #ifdef NEED_SIGFIX 936 sigaddset(&block_sigmask, SIGSYS); 937 #endif 938 #endif 939 #ifdef SIGALRM 940 (void) signal(SIGALRM, randomsig); 941 #ifdef NEED_SIGFIX 942 sigaddset(&block_sigmask, SIGALRM); 943 #endif 944 #endif 945 #ifdef SIGSTOP 946 (void) signal(SIGSTOP, randomsig); 947 #ifdef NEED_SIGFIX 948 sigaddset(&block_sigmask, SIGSTOP); 949 #endif 950 #endif 951 #ifdef SIGTSTP 952 (void) signal(SIGTSTP, randomsig); 953 #ifdef NEED_SIGFIX 954 sigaddset(&block_sigmask, SIGTSTP); 955 #endif 956 #endif 957 #ifdef SIGTTIN 958 (void) signal(SIGTTIN, randomsig); 959 #ifdef NEED_SIGFIX 960 sigaddset(&block_sigmask, SIGTTIN); 961 #endif 962 #endif 963 #ifdef SIGTTOU 964 (void) signal(SIGTTOU, randomsig); 965 #ifdef NEED_SIGFIX 966 sigaddset(&block_sigmask, SIGTTOU); 967 #endif 968 #endif 969 #ifdef SIGIO 970 (void) signal(SIGIO, randomsig); 971 #ifdef NEED_SIGFIX 972 sigaddset(&block_sigmask, SIGIO); 973 #endif 974 #endif 975 #ifdef SIGXCPU 976 (void) signal(SIGXCPU, randomsig); 977 #ifdef NEED_SIGFIX 978 sigaddset(&block_sigmask, SIGXCPU); 979 #endif 980 #endif 981 #ifdef SIGXFSZ 982 (void) signal(SIGXFSZ, randomsig); 983 #ifdef NEED_SIGFIX 984 sigaddset(&block_sigmask, SIGXFSZ); 985 #endif 986 #endif 987 #ifdef SIGWINCH 988 (void) signal(SIGWINCH, randomsig); 989 #ifdef NEED_SIGFIX 990 sigaddset(&block_sigmask, SIGWINCH); 991 #endif 992 #endif 993 #ifdef SIGVTALRM 994 (void) signal(SIGVTALRM, randomsig); 995 #ifdef NEED_SIGFIX 996 sigaddset(&block_sigmask, SIGVTALRM); 997 #endif 998 #endif 999 #ifdef SIGPROF 1000 (void) signal(SIGPROF, randomsig); 1001 #ifdef NEED_SIGFIX 1002 sigaddset(&block_sigmask, SIGPROF); 1003 #endif 1004 #endif 1005 #ifdef SIGUSR1 1006 (void) signal(SIGUSR1, randomsig); 1007 #ifdef NEED_SIGFIX 1008 sigaddset(&block_sigmask, SIGUSR1); 1009 #endif 1010 #endif 1011 #ifdef SIGUSR2 1012 (void) signal(SIGUSR2, randomsig); 1013 #ifdef NEED_SIGFIX 1014 sigaddset(&block_sigmask, SIGUSR2); 1015 #endif 1016 #endif 1017 1018 #ifdef SIGPIPE 1019 (void) signal(SIGPIPE, lostconn); 1020 #ifdef NEED_SIGFIX 1021 sigaddset(&block_sigmask, SIGPIPE); 1022 #endif 1023 #endif 1024 #ifdef SIGCHLD 1025 (void) signal(SIGCHLD, SIG_IGN); 1026 #ifdef NEED_SIGFIX 1027 sigaddset(&block_sigmask, SIGCHLD); 1028 #endif 1029 #endif 1030 1031 #ifdef SIGURG 1032 if (signal(SIGURG, myoob) == SIG_ERR) 1033 syslog(LOG_ERR, "signal: %m"); 1034 #ifdef NEED_SIGFIX 1035 sigaddset(&block_sigmask, SIGURG); 1036 #endif 1037 #endif 1038 #endif /* SIG_DEBUG */ 1039 1040 #ifdef VIRTUAL 1041 virtual_root[0] = '\0'; 1042 virtual_banner[0] = '\0'; 1043 #endif 1044 1045 setup_paths(); 1046 1047 #ifdef OTHER_PASSWD 1048 strcpy(_path_passwd, "/etc/passwd"); 1049 #ifdef SHADOW_PASSWORD 1050 strcpy(_path_shadow, "/etc/shadow"); 1051 #endif 1052 #endif 1053 1054 access_init(); 1055 1056 #ifdef DAEMON 1057 if (be_daemon != 0) 1058 do_daemon(); 1059 else { 1060 #endif 1061 addrlen = sizeof(his_addr); 1062 if (getpeername(0, (struct sockaddr *) &his_addr, &addrlen) < 0) { 1063 syslog(LOG_ERR, "getpeername: %m"); 1064 #ifndef DEBUG 1065 exit(1); 1066 #endif 1067 } 1068 #ifdef DAEMON 1069 } 1070 #endif 1071 addrlen = sizeof(ctrl_addr); 1072 if (getsockname(0, (struct sockaddr *) &ctrl_addr, &addrlen) < 0) { 1073 syslog(LOG_ERR, "getsockname: %m"); 1074 #ifndef DEBUG 1075 exit(1); 1076 #endif 1077 } 1078 /* Sanity check */ 1079 if ((SOCK_FAMILY(ctrl_addr) != AF_INET) 1080 #ifdef INET6 1081 && (SOCK_FAMILY(ctrl_addr) != AF_INET6) 1082 #endif 1083 ) { 1084 syslog(LOG_ERR, "control connection address family (%d) not supported.", 1085 SOCK_FAMILY(ctrl_addr)); 1086 #ifndef DEBUG 1087 exit(1); 1088 #endif 1089 } 1090 #ifdef SOLARIS_BSM_AUDIT 1091 /* Set audit characteristics */ 1092 if (audit_settid(0)) { 1093 syslog(LOG_ERR, "audit failure"); 1094 exit(1); 1095 } 1096 #endif 1097 #ifdef INET6 1098 /* IP_TOS is an IPv4 socket option */ 1099 if (SOCK_FAMILY(ctrl_addr) == AF_INET) 1100 #endif 1101 if ((cos = IPClassOfService("control")) >= 0) { 1102 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *) &cos, sizeof(int)) < 0) 1103 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 1104 } 1105 1106 #ifdef TCP_NODELAY 1107 /* 1108 * Disable Nagle on the control channel so that we don't have to wait 1109 * for peer's ACK before issuing our next reply. 1110 */ 1111 if (setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof (on)) < 0) 1112 syslog(LOG_WARNING, "control setsockopt TCP_NODELAY: %m"); 1113 #endif 1114 1115 if (keepalive) 1116 if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0) 1117 syslog(LOG_ERR, "setsockopt SO_KEEPALIVE %m"); 1118 1119 /* Try to handle urgent data inline */ 1120 #ifdef SO_OOBINLINE 1121 if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof(int)) < 0) 1122 syslog(LOG_ERR, "setsockopt (SO_OOBINLINE): %m"); 1123 #endif 1124 1125 #ifdef F_SETOWN 1126 if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) 1127 syslog(LOG_ERR, "fcntl F_SETOWN: %m"); 1128 #elif defined(SIOCSPGRP) 1129 { 1130 int pid; 1131 pid = getpid(); 1132 if (ioctl(fileno(stdin), SIOCSPGRP, &pid) == -1) 1133 syslog(LOG_ERR, "ioctl SIOCSPGRP: %m"); 1134 } 1135 #endif 1136 1137 #ifdef INET6 1138 if ((SOCK_FAMILY(ctrl_addr) == AF_INET6) && 1139 IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)&(ctrl_addr))->sin6_addr)) 1140 ctrl_v4mapped = 1; 1141 #endif 1142 1143 if (data_port == 0) { 1144 serv = getservbyname("ftp-data", "tcp"); 1145 if (serv != NULL) 1146 data_port = serv->s_port; 1147 else 1148 data_port = htons(ntohs(SOCK_PORT(ctrl_addr)) - 1); 1149 } 1150 1151 if (RootDirectory != NULL) { 1152 if ((chroot(RootDirectory) < 0) 1153 || (chdir("/") < 0)) { 1154 syslog(LOG_ERR, "Cannot chroot to initial directory, aborting."); 1155 exit(1); 1156 } 1157 } 1158 1159 load_timeouts(); 1160 1161 /* set resolver options */ 1162 set_res_options(); 1163 1164 dolog(&his_addr); 1165 /* Set up default state */ 1166 data = -1; 1167 type = TYPE_A; 1168 form = FORM_N; 1169 stru = STRU_F; 1170 mode = MODE_S; 1171 tmpline[0] = '\0'; 1172 yyerrorcalled = 0; 1173 1174 entry = (struct aclmember *) NULL; 1175 if ((getaclentry("hostname", &entry)) && ARG0) { 1176 (void) strncpy(hostname, ARG0, sizeof(hostname)); 1177 hostname[sizeof(hostname) - 1] = '\0'; 1178 } 1179 else { 1180 #ifdef HAVE_SYSINFO 1181 sysinfo(SI_HOSTNAME, hostname, sizeof(hostname)); 1182 #else 1183 (void) gethostname(hostname, sizeof(hostname)); 1184 #endif 1185 /* set the FQDN here */ 1186 hp = wu_gethostbyname(hostname); 1187 if (hp) { 1188 (void) strncpy(hostname, hp, sizeof(hostname)); 1189 hostname[sizeof(hostname) - 1] = '\0'; 1190 } 1191 } 1192 route_vectored = routevector(); 1193 conv_init(); 1194 1195 #ifdef MAIL_ADMIN 1196 incmails = 0; 1197 mailfrom = NULL; 1198 #endif /* MAIL_ADMIN */ 1199 #ifdef VIRTUAL 1200 /* 1201 ** If virtual_mode is set at this point then an alternate ftpaccess 1202 ** is in use. Otherwise we need to check the Master ftpaccess file 1203 ** to see if the site is only using the "virtual" directives to 1204 ** specify virtual site directives. 1205 ** 1206 ** In this manner an admin can put a virtual site in the ftpservers 1207 ** file if they need expanded configuration support or can use the 1208 ** minimal root/banner/logfile if they do not need any more than that. 1209 */ 1210 1211 if (virtual_mode) { 1212 /* Get the root of the virtual server directory */ 1213 entry = (struct aclmember *) NULL; 1214 if (getaclentry("root", &entry)) { 1215 if (ARG0) 1216 strcpy(virtual_root, ARG0); 1217 } 1218 1219 /* Get the logfile to use */ 1220 entry = (struct aclmember *) NULL; 1221 if (getaclentry("logfile", &entry)) { 1222 if (ARG0) 1223 strcpy(logfile, ARG0); 1224 } 1225 } 1226 else { 1227 virtual_hostname[0] = '\0'; 1228 virtual_address[0] = '\0'; 1229 virtual_len = sizeof(virtual_addr); 1230 if (getsockname(0, (struct sockaddr *) &virtual_addr, &virtual_len) == 0) { 1231 strcpy(virtual_address, inet_stop(&virtual_addr)); 1232 wu_gethostbyaddr(&virtual_addr, virtual_hostname, sizeof(virtual_hostname)); 1233 entry = (struct aclmember *) NULL; 1234 while (getaclentry("virtual", &entry)) { 1235 if (!ARG0 || !ARG1 || !ARG2) 1236 continue; 1237 if (hostmatch(ARG0, virtual_address, virtual_hostname)) { 1238 if (!strcasecmp(ARG1, "root")) { 1239 if (debug) 1240 syslog(LOG_DEBUG, "VirtualFTP Connect to: %s [%s]", 1241 virtual_hostname, virtual_address); 1242 virtual_mode = 1; 1243 strncpy(virtual_root, ARG2, sizeof(virtual_root)); 1244 virtual_root[sizeof(virtual_root) - 1] = '\0'; 1245 /* reset hostname to this virtual name */ 1246 (void) strcpy(hostname, virtual_hostname); 1247 virtual_email[0] = '\0'; 1248 } 1249 if (!strcasecmp(ARG1, "banner")) { 1250 strncpy(virtual_banner, ARG2, sizeof(virtual_banner)); 1251 virtual_banner[sizeof(virtual_banner) - 1] = '\0'; 1252 } 1253 if (!strcasecmp(ARG1, "logfile")) { 1254 strncpy(logfile, ARG2, sizeof(logfile)); 1255 logfile[sizeof(logfile) - 1] = '\0'; 1256 } 1257 if (!strcasecmp(ARG1, "hostname")) { 1258 strncpy(hostname, ARG2, sizeof(hostname)); 1259 hostname[sizeof(hostname) - 1] = '\0'; 1260 } 1261 if (!strcasecmp(ARG1, "email")) { 1262 strncpy(virtual_email, ARG2, sizeof(virtual_email)); 1263 virtual_email[sizeof(virtual_email) - 1] = '\0'; 1264 } 1265 #ifdef OTHER_PASSWD 1266 if (!strcasecmp(ARG1, "passwd")) { 1267 strncpy(_path_passwd, ARG2, sizeof(_path_passwd)); 1268 _path_passwd[sizeof(_path_passwd) - 1] = '\0'; 1269 #ifdef USE_PAM 1270 use_pam = 0; 1271 #endif 1272 } 1273 #ifdef SHADOW_PASSWORD 1274 if (!strcasecmp(ARG1, "shadow")) { 1275 strncpy(_path_shadow, ARG2, sizeof(_path_shadow)); 1276 _path_shadow[sizeof(_path_shadow) - 1] = '\0'; 1277 #ifdef USE_PAM 1278 use_pam = 0; 1279 #endif 1280 } 1281 #endif 1282 #endif 1283 #ifdef MAIL_ADMIN 1284 if (mailfrom == NULL) 1285 if (!strcasecmp(ARG1, "mailfrom")) { 1286 mailfrom = strdup(ARG2); 1287 } 1288 if (!strcasecmp(ARG1, "incmail")) { 1289 if (incmails < INCMAILS) 1290 incmail[incmails++] = strdup(ARG2); 1291 } 1292 #endif 1293 } 1294 } 1295 if (!virtual_mode) { 1296 entry = (struct aclmember *) NULL; 1297 while (getaclentry("defaultserver", &entry)) { 1298 if (!ARG0 || !ARG1) 1299 continue; 1300 #ifdef MAIL_ADMIN 1301 if (mailfrom == NULL) 1302 if (!strcasecmp(ARG0, "mailfrom")) { 1303 mailfrom = strdup(ARG1); 1304 } 1305 if (!strcasecmp(ARG0, "incmail")) { 1306 if (incmails < INCMAILS) 1307 incmail[incmails++] = strdup(ARG1); 1308 } 1309 #endif 1310 } 1311 } 1312 } 1313 } 1314 1315 #ifdef VIRTUAL_DEBUG 1316 lreply(220, "_path_ftpaccess == %s", _path_ftpaccess); 1317 lreply(220, "_path_ftpusers == %s", _path_ftpusers); 1318 lreply(220, "_path_ftphosts == %s", _path_ftphosts); 1319 lreply(220, "_path_private == %s", _path_private); 1320 lreply(220, "_path_cvt == %s", _path_cvt); 1321 if (virtual_mode) { 1322 if (virtual_ftpaccess) 1323 lreply(220, "VIRTUAL Mode: Using %s specific %s access file", 1324 hostname, _path_ftpaccess); 1325 else 1326 lreply(220, "VIRTUAL Mode: Using Master access file %s", 1327 _path_ftpaccess); 1328 1329 lreply(220, "virtual_root == %s", virtual_root); 1330 if (!virtual_ftpaccess) 1331 lreply(220, "virtual_banner == %s", virtual_banner); 1332 } 1333 lreply(220, "logfile == %s", logfile); 1334 #endif 1335 #endif 1336 1337 if (is_shutdown(1, 1) != 0) { 1338 syslog(LOG_INFO, "connection refused (server shut down) from %s", 1339 remoteident); 1340 reply(500, "%s FTP server shut down -- please try again later.", 1341 hostname); 1342 exit(0); 1343 } 1344 1345 #ifdef OPIE 1346 af_pwok = opieaccessfile(remotehost); 1347 #endif 1348 1349 /* check permitted access based on name and address lookup of remote host */ 1350 if (!check_rhost_reverse()) { 1351 exit(0); 1352 } 1353 if (!check_rhost_matches()) { 1354 exit(0); 1355 } 1356 1357 show_banner(220); 1358 1359 #ifndef INTERNAL_LS 1360 entry = (struct aclmember *) NULL; 1361 if (getaclentry("lslong", &entry) && ARG0 && (int) strlen(ARG0) > 0) { 1362 strcpy(ls_long, ARG0); 1363 for (which = 1; (which < MAXARGS) && ARG[which]; which++) { 1364 strcat(ls_long, " "); 1365 strcat(ls_long, ARG[which]); 1366 } 1367 } 1368 else { 1369 #if defined(SVR4) || defined(ISC) 1370 #if defined(AIX) || defined(SOLARIS_2) 1371 strcpy(ls_long, "/bin/ls -lA"); 1372 #else 1373 strcpy(ls_long, "/bin/ls -la"); 1374 #endif 1375 #else 1376 strcpy(ls_long, "/bin/ls -lgA"); 1377 #endif 1378 } 1379 strcat(ls_long, " %s"); 1380 1381 entry = (struct aclmember *) NULL; 1382 if (getaclentry("lsshort", &entry) && ARG0 && (int) strlen(ARG0) > 0) { 1383 strcpy(ls_short, ARG0); 1384 for (which = 1; (which < MAXARGS) && ARG[which]; which++) { 1385 strcat(ls_short, " "); 1386 strcat(ls_short, ARG[which]); 1387 } 1388 } 1389 else { 1390 #if defined(SVR4) || defined(ISC) 1391 #if defined(AIX) || defined(SOLARIS_2) 1392 strcpy(ls_short, "/bin/ls -lA"); 1393 #else 1394 strcpy(ls_short, "/bin/ls -la"); 1395 1396 #endif 1397 #else 1398 strcpy(ls_short, "/bin/ls -lgA"); 1399 #endif 1400 } 1401 strcat(ls_short, " %s"); 1402 1403 entry = (struct aclmember *) NULL; 1404 if (getaclentry("lsplain", &entry) && ARG0 && (int) strlen(ARG0) > 0) { 1405 strcpy(ls_plain, ARG0); 1406 for (which = 1; (which < MAXARGS) && ARG[which]; which++) { 1407 strcat(ls_plain, " "); 1408 strcat(ls_plain, ARG[which]); 1409 } 1410 } 1411 else 1412 strcpy(ls_plain, "/bin/ls"); 1413 strcat(ls_plain, " %s"); 1414 #endif /* ! INTERNAL_LS */ 1415 #ifdef MAIL_ADMIN 1416 mailservers = 0; 1417 entry = (struct aclmember *) NULL; 1418 while (getaclentry("mailserver", &entry) && ARG0 && mailservers < MAILSERVERS) 1419 mailserver[mailservers++] = strdup(ARG0); 1420 if (mailservers == 0) 1421 mailserver[mailservers++] = strdup("localhost"); 1422 if (incmails == 0) { 1423 entry = (struct aclmember *) NULL; 1424 while (getaclentry("incmail", &entry) && ARG0 && incmails < INCMAILS) 1425 incmail[incmails++] = strdup(ARG0); 1426 } 1427 if (mailfrom == NULL) { 1428 entry = (struct aclmember *) NULL; 1429 if (getaclentry("mailfrom", &entry) && ARG0) 1430 mailfrom = strdup(ARG0); 1431 else 1432 mailfrom = strdup("wu-ftpd"); 1433 } 1434 #endif /* MAIL_ADMIN */ 1435 { 1436 #define OUTPUT_LEN (BUFSIZ * 2) 1437 int version_option = 0; 1438 char output_text[OUTPUT_LEN + 1]; 1439 int which; 1440 1441 entry = NULL; 1442 if (getaclentry("greeting", &entry) && ARG0) { 1443 if (!strcasecmp(ARG0, "full")) 1444 version_option = 0; 1445 else if (!strcasecmp(ARG0, "text") && ARG1) 1446 version_option = 3; 1447 else if (!strcasecmp(ARG0, "terse")) 1448 version_option = 2; 1449 else if (!strcasecmp(ARG0, "brief")) 1450 version_option = 1; 1451 } 1452 switch (version_option) { 1453 default: 1454 reply(220, "%s FTP server (%s) ready.", hostname, version); 1455 break; 1456 case 1: 1457 reply(220, "%s FTP server ready.", hostname); 1458 break; 1459 case 2: 1460 reply(220, "FTP server ready."); 1461 break; 1462 case 3: 1463 output_text[0] = '\0'; 1464 for (which = 1; (which < MAXARGS) && ARG[which]; which++) { 1465 if (which > 1) 1466 (void) strlcat(output_text, " ", sizeof(output_text)); 1467 (void) strlcat(output_text, ARG[which], sizeof(output_text)); 1468 } 1469 reply(220, "%s", output_text); 1470 break; 1471 } 1472 } 1473 (void) setjmp(errcatch); 1474 1475 for (;;) 1476 (void) yyparse(); 1477 /* NOTREACHED */ 1478 } 1479 1480 1481 SIGNAL_TYPE randomsig(int sig) 1482 { 1483 #ifdef HAVE_SIGLIST 1484 syslog(LOG_ERR, "exiting on signal %d: %s", sig, sys_siglist[sig]); 1485 #else 1486 syslog(LOG_ERR, "exiting on signal %d", sig); 1487 #endif 1488 chdir("/"); 1489 signal(SIGIOT, SIG_DFL); 1490 signal(SIGILL, SIG_DFL); 1491 exit(1); 1492 /* dologout(-1); *//* NOTREACHED */ 1493 } 1494 1495 SIGNAL_TYPE lostconn(int sig) 1496 { 1497 #ifdef VERBOSE_ERROR_LOGING 1498 syslog(LOG_INFO, "lost connection to %s", remoteident); 1499 #else 1500 if (debug) 1501 syslog(LOG_DEBUG, "lost connection to %s", remoteident); 1502 #endif 1503 dologout(-1); 1504 } 1505 1506 static char ttyline[20]; 1507 1508 #ifdef MAPPING_CHDIR 1509 /* Keep track of the path the user has chdir'd into and respond with 1510 * that to pwd commands. This is to avoid having the absolue disk 1511 * path returned, which I want to avoid. 1512 */ 1513 char mapped_path[MAXPATHLEN] = "/"; 1514 1515 #if !defined(HAVE_GETCWD) 1516 char *mapping_getwd(char *path) 1517 { 1518 strcpy(path, mapped_path); 1519 return path; 1520 } 1521 #endif /* !defined(HAVE_GETCWD) */ 1522 1523 char *mapping_getcwd(char *path, size_t size) 1524 { 1525 (void) strlcpy(path, mapped_path, size); 1526 return path; 1527 } 1528 1529 /* Make these globals rather than local to mapping_chdir to avoid stack overflow */ 1530 char pathspace[MAXPATHLEN]; 1531 char old_mapped_path[MAXPATHLEN]; 1532 1533 void do_elem(char *dir) 1534 { 1535 /* . */ 1536 if (dir[0] == '.' && dir[1] == '\0') { 1537 /* ignore it */ 1538 return; 1539 } 1540 1541 /* .. */ 1542 if (dir[0] == '.' && dir[1] == '.' && dir[2] == '\0') { 1543 char *last; 1544 /* lop the last directory off the path */ 1545 if ((last = strrchr(mapped_path, '/'))) { 1546 /* If start of pathname leave the / */ 1547 if (last == mapped_path) 1548 last++; 1549 *last = '\0'; 1550 } 1551 return; 1552 } 1553 1554 /* append the dir part with a leading / unless at root */ 1555 if (!(mapped_path[0] == '/' && mapped_path[1] == '\0')) 1556 (void) strlcat(mapped_path, "/", sizeof(mapped_path)); 1557 (void) strlcat(mapped_path, dir, sizeof(mapped_path)); 1558 } 1559 1560 int mapping_chdir(char *orig_path) 1561 { 1562 int ret; 1563 char *sl, *path; 1564 1565 (void) strlcpy(old_mapped_path, mapped_path, sizeof(old_mapped_path)); 1566 (void) strlcpy(pathspace, orig_path, sizeof(pathspace)); 1567 path = pathspace; 1568 1569 /* / at start of path, set the start of the mapped_path to / */ 1570 if (path[0] == '/') { 1571 mapped_path[0] = '/'; 1572 mapped_path[1] = '\0'; 1573 path++; 1574 } 1575 1576 while ((sl = strchr(path, '/'))) { 1577 char *dir; 1578 dir = path; 1579 *sl = '\0'; 1580 path = sl + 1; 1581 if (*dir) 1582 do_elem(dir); 1583 if (*path == '\0') 1584 break; 1585 } 1586 if (*path) 1587 do_elem(path); 1588 1589 if ((ret = chdir(mapped_path)) < 0) { 1590 (void) strlcpy(mapped_path, old_mapped_path, sizeof(mapped_path)); 1591 } 1592 1593 return ret; 1594 } 1595 /* From now on use the mapping version */ 1596 1597 #define chdir(d) mapping_chdir(d) 1598 #define getwd(d) mapping_getwd(d) 1599 #define getcwd(d,u) mapping_getcwd((d),(u)) 1600 1601 #endif /* MAPPING_CHDIR */ 1602 1603 /* Helper function for sgetpwnam(). */ 1604 char *sgetsave(char *s) 1605 { 1606 char *new; 1607 1608 new = (char *) malloc(strlen(s) + 1); 1609 1610 if (new == NULL) { 1611 perror_reply(421, "Local resource failure: malloc"); 1612 dologout(1); 1613 /* NOTREACHED */ 1614 } 1615 (void) strcpy(new, s); 1616 return (new); 1617 } 1618 1619 /* Save the result of a getpwnam. Used for USER command, since the data 1620 * returned must not be clobbered by any other command (e.g., globbing). */ 1621 struct passwd *sgetpwnam(char *name) 1622 { 1623 static struct passwd save; 1624 register struct passwd *p; 1625 #ifdef M_UNIX 1626 struct passwd *ret = (struct passwd *) NULL; 1627 #endif 1628 char *sgetsave(char *s); 1629 #ifdef KERBEROS 1630 register struct authorization *q; 1631 #endif /* KERBEROS */ 1632 1633 #if defined(SecureWare) || defined(HPUX_10_TRUSTED) 1634 struct pr_passwd *pr; 1635 #endif 1636 1637 #ifdef KERBEROS 1638 init_krb(); 1639 q = getauthuid(p->pw_uid); 1640 end_krb(); 1641 #endif /* KERBEROS */ 1642 1643 #ifdef M_UNIX 1644 #if defined(SecureWare) || defined(HPUX_10_TRUSTED) 1645 if ((pr = getprpwnam(name)) == NULL) 1646 goto DONE; 1647 #endif /* SecureWare || HPUX_10_TRUSTED */ 1648 #ifdef OTHER_PASSWD 1649 if ((p = bero_getpwnam(name, _path_passwd)) == NULL) 1650 #else 1651 if ((p = getpwnam(name)) == NULL) 1652 #endif 1653 goto DONE; 1654 #else /* M_UNIX */ 1655 #if defined(SecureWare) || defined(HPUX_10_TRUSTED) 1656 if ((pr = getprpwnam(name)) == NULL) 1657 return ((struct passwd *) pr); 1658 #endif /* SecureWare || HPUX_10_TRUSTED */ 1659 #ifdef OTHER_PASSWD 1660 if ((p = bero_getpwnam(name, _path_passwd)) == NULL) 1661 #else 1662 if ((p = getpwnam(name)) == NULL) 1663 #endif 1664 return (p); 1665 #endif /* M_UNIX */ 1666 1667 if (save.pw_name) 1668 free(save.pw_name); 1669 if (save.pw_gecos) 1670 free(save.pw_gecos); 1671 if (save.pw_dir) 1672 free(save.pw_dir); 1673 if (save.pw_shell) 1674 free(save.pw_shell); 1675 if (save.pw_passwd) 1676 free(save.pw_passwd); 1677 1678 save = *p; 1679 1680 save.pw_name = sgetsave(p->pw_name); 1681 1682 #ifdef KERBEROS 1683 save.pw_passwd = sgetsave(q->a_password); 1684 #elif defined(SecureWare) || defined(HPUX_10_TRUSTED) 1685 if (pr->uflg.fg_encrypt && pr->ufld.fd_encrypt && *pr->ufld.fd_encrypt) 1686 save.pw_passwd = sgetsave(pr->ufld.fd_encrypt); 1687 else 1688 save.pw_passwd = sgetsave(""); 1689 #else 1690 save.pw_passwd = sgetsave(p->pw_passwd); 1691 #endif 1692 #ifdef SHADOW_PASSWORD 1693 if (p && (p->pw_passwd==NULL || strlen(p->pw_passwd)<8)) { 1694 struct spwd *spw; 1695 #ifdef OTHER_PASSWD 1696 if ((spw = bero_getspnam(p->pw_name, _path_shadow)) != NULL) { 1697 #else 1698 setspent(); 1699 if ((spw = getspnam(p->pw_name)) != NULL) { 1700 #endif 1701 int expired = 0; 1702 /*XXX Does this work on all Shadow Password Implementations? */ 1703 /* it is supposed to work on Solaris 2.x */ 1704 time_t now; 1705 long today; 1706 1707 now = time((time_t *) 0); 1708 today = now / (60 * 60 * 24); 1709 1710 if ((spw->sp_expire > 0) && (spw->sp_expire < today)) 1711 expired++; 1712 if ((spw->sp_max > 0) && (spw->sp_lstchg > 0) && 1713 (spw->sp_lstchg + spw->sp_max < today)) 1714 expired++; 1715 free(save.pw_passwd); 1716 save.pw_passwd = sgetsave(expired ? "" : spw->sp_pwdp); 1717 } 1718 /* Don't overwrite the password if the shadow read fails, getpwnam() is NIS 1719 aware but getspnam() is not. */ 1720 /* Shadow passwords are optional on Linux. --marekm */ 1721 #if !defined(LINUX) && !defined(UNIXWARE) 1722 else { 1723 free(save.pw_passwd); 1724 save.pw_passwd = sgetsave(""); 1725 } 1726 #endif 1727 /* marekm's fix for linux proc file system shadow passwd exposure problem */ 1728 #ifndef OTHER_PASSWD 1729 endspent(); 1730 #endif 1731 } 1732 #endif 1733 save.pw_gecos = sgetsave(p->pw_gecos); 1734 save.pw_dir = sgetsave(p->pw_dir); 1735 save.pw_shell = sgetsave(p->pw_shell); 1736 #ifdef M_UNIX 1737 ret = &save; 1738 DONE: 1739 endpwent(); 1740 #endif 1741 #if defined(SecureWare) || defined(HPUX_10_TRUSTED) 1742 endprpwent(); 1743 #endif 1744 #ifdef M_UNIX 1745 return (ret); 1746 #else 1747 return (&save); 1748 #endif 1749 } 1750 #if defined(SKEY) && !defined(__NetBSD__) 1751 /* 1752 * From Wietse Venema, Eindhoven University of Technology. 1753 */ 1754 /* skey_challenge - additional password prompt stuff */ 1755 1756 char *skey_challenge(char *name, struct passwd *pwd, int pwok) 1757 { 1758 static char buf[128]; 1759 char sbuf[40]; 1760 struct skey skey; 1761 1762 /* Display s/key challenge where appropriate. */ 1763 1764 if (pwd == NULL || skeychallenge(&skey, pwd->pw_name, sbuf)) 1765 sprintf(buf, "Password required for %s.", name); 1766 else 1767 sprintf(buf, "%s %s for %s.", sbuf, 1768 pwok ? "allowed" : "required", name); 1769 return (buf); 1770 } 1771 #endif 1772 1773 int login_attempts; /* number of failed login attempts */ 1774 int askpasswd; /* had user command, ask for passwd */ 1775 #ifndef HELP_CRACKERS 1776 int DenyLoginAfterPassword; 1777 char DelayedMessageFile[MAXPATHLEN]; 1778 extern void pr_mesg(int msgcode, char *msgfile); 1779 #endif 1780 1781 #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER) 1782 static int defaultserver_allow(const char *username) 1783 { 1784 struct aclmember *entry = NULL; 1785 int which; 1786 1787 while (getaclentry("defaultserver", &entry)) 1788 if (ARG0 && !strcasecmp(ARG0, "allow")) 1789 for (which = 1; (which < MAXARGS) && ARG[which]; which++) 1790 if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which])) 1791 return (1); 1792 return (0); 1793 } 1794 1795 static int defaultserver_deny(const char *username) 1796 { 1797 struct aclmember *entry = NULL; 1798 int which; 1799 1800 while (getaclentry("defaultserver", &entry)) 1801 if (ARG0 && !strcasecmp(ARG0, "deny")) 1802 for (which = 1; (which < MAXARGS) && ARG[which]; which++) 1803 if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which])) 1804 return (1); 1805 return (0); 1806 } 1807 1808 static int defaultserver_private(void) 1809 { 1810 struct aclmember *entry = NULL; 1811 1812 while (getaclentry("defaultserver", &entry)) 1813 if (ARG0 && !strcasecmp(ARG0, "private")) 1814 return (1); 1815 return (0); 1816 } 1817 #endif 1818 1819 /* USER command. Sets global passwd pointer pw if named account exists and is 1820 * acceptable; sets askpasswd if a PASS command is expected. If logged in 1821 * previously, need to reset state. If name is "ftp" or "anonymous", the 1822 * name is not in the ftpusers file, and ftp account exists, set anonymous and 1823 * pw, then just return. If account doesn't exist, ask for passwd anyway. 1824 * Otherwise, check user requesting login privileges. Disallow anyone who 1825 * does not have a standard shell as returned by getusershell(). Disallow 1826 * anyone mentioned in the ftpusers file to allow people such as root and 1827 * uucp to be avoided. */ 1828 1829 /* 1830 char *getusershell(); 1831 */ 1832 void user(char *name) 1833 { 1834 char *cp; 1835 char *shell; 1836 #ifdef BSD_AUTH 1837 char *auth; 1838 #endif 1839 #if defined(USE_GSS) 1840 int gss_need_passwd = 1; 1841 #endif 1842 1843 /* H* fix: if we're logged in at all, we can't log in again. */ 1844 if (logged_in) { 1845 #ifdef VERBOSE_ERROR_LOGING 1846 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (already logged in as %s) FROM %s, %s", 1847 pw->pw_name, remoteident, name); 1848 #endif 1849 reply(530, "Already logged in."); 1850 return; 1851 } 1852 #ifndef HELP_CRACKERS 1853 askpasswd = 1; 1854 DenyLoginAfterPassword = 0; 1855 DelayedMessageFile[0] = '\0'; 1856 #endif 1857 #ifdef BSD_AUTH 1858 if ((auth = strchr(name, ':'))) 1859 *auth++ = 0; 1860 #endif 1861 1862 #ifdef HOST_ACCESS /* 19-Mar-93 BM */ 1863 if (!rhost_ok(name, remotehost, remoteaddr)) { 1864 #ifndef HELP_CRACKERS 1865 DenyLoginAfterPassword = 1; 1866 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (name in %s) FROM %s, %s", 1867 _path_ftphosts, remoteident, name); 1868 #else 1869 reply(530, "User %s access denied.", name); 1870 syslog(LOG_NOTICE, 1871 "FTP LOGIN REFUSED (name in %s) FROM %s, %s", 1872 _path_ftphosts, remoteident, name); 1873 return; 1874 #endif 1875 } 1876 #endif 1877 1878 strncpy(the_user, name, MAXUSERNAMELEN - 1); 1879 1880 anonymous = 0; 1881 guest = 0; 1882 1883 if (!strcasecmp(name, "ftp") || !strcasecmp(name, "anonymous")) { 1884 struct aclmember *entry = NULL; 1885 int machineok = 1; 1886 char guestservername[MAXHOSTNAMELEN]; 1887 guestservername[0] = '\0'; 1888 1889 #ifdef NO_ANONYMOUS_ACCESS 1890 reply(530, "Anonymous FTP access denied."); 1891 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (anonymous ftp not supported) FROM %s, %s", 1892 remoteident, name); 1893 return; 1894 #else 1895 #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER) 1896 if (!virtual_mode && defaultserver_private()) { 1897 #ifndef HELP_CRACKERS 1898 DenyLoginAfterPassword = 1; 1899 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (anonymous ftp denied on default server) FROM %s, %s", 1900 remoteident, name); 1901 #else 1902 reply(530, "User %s access denied.", name); 1903 syslog(LOG_NOTICE, 1904 "FTP LOGIN REFUSED (anonymous ftp denied on default server) FROM %s, %s", 1905 remoteident, name); 1906 return; 1907 #endif 1908 } 1909 #endif 1910 if (checkuser("ftp") || checkuser("anonymous")) { 1911 #ifndef HELP_CRACKERS 1912 DenyLoginAfterPassword = 1; 1913 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (ftp in %s) FROM %s, %s", 1914 _path_ftpusers, remoteident, name); 1915 #else 1916 reply(530, "User %s access denied.", name); 1917 syslog(LOG_NOTICE, 1918 "FTP LOGIN REFUSED (ftp in %s) FROM %s, %s", 1919 _path_ftpusers, remoteident, name); 1920 return; 1921 #endif 1922 1923 /* 1924 ** Algorithm used: 1925 ** - if no "guestserver" directive is present, 1926 ** anonymous access is allowed, for backward compatibility. 1927 ** - if a "guestserver" directive is present, 1928 ** anonymous access is restricted to the machines listed, 1929 ** usually the machine whose CNAME on the current domain 1930 ** is "ftp"... 1931 ** 1932 ** the format of the "guestserver" line is 1933 ** guestserver [<machine1> [<machineN>]] 1934 ** that is, "guestserver" will forbid anonymous access on all machines 1935 ** while "guestserver ftp inf" will allow anonymous access on 1936 ** the two machines whose CNAMES are "ftp.enst.fr" and "inf.enst.fr". 1937 ** 1938 ** if anonymous access is denied on the current machine, 1939 ** the user will be asked to use the first machine listed (if any) 1940 ** on the "guestserver" line instead: 1941 ** 530- Guest login not allowed on this machine, 1942 ** connect to ftp.enst.fr instead. 1943 ** 1944 ** -- <Nicolas.Pioch (at) enst.fr> 1945 */ 1946 } 1947 else if (getaclentry("guestserver", &entry)) { 1948 char *tmphost; 1949 1950 /* 1951 ** if a "guestserver" line is present, 1952 ** default is not to allow guest logins 1953 */ 1954 machineok = 0; 1955 1956 if (hostname[0] 1957 && ((tmphost = wu_gethostbyname(hostname)))) { 1958 1959 /* 1960 ** hostname is the only first part of the FQDN 1961 ** this may or may not correspond to the h_name value 1962 ** (machines with more than one IP#, CNAMEs...) 1963 ** -> need to fix that, calling gethostbyname on hostname 1964 ** 1965 ** WARNING! 1966 ** for SunOS 4.x, you need to have a working resolver in the libc 1967 ** for CNAMES to work properly. 1968 ** If you don't, add "-lresolv" to the libraries before compiling! 1969 */ 1970 char dns_localhost[MAXHOSTNAMELEN]; 1971 int machinecount; 1972 1973 strncpy(dns_localhost, tmphost, sizeof(dns_localhost)); 1974 dns_localhost[sizeof(dns_localhost) - 1] = '\0'; 1975 1976 for (machinecount = 0; 1977 (machinecount < MAXARGS) && entry->arg[machinecount]; 1978 machinecount++) { 1979 1980 if ((tmphost = wu_gethostbyname(entry->arg[machinecount]))) { 1981 /* 1982 ** remember the name of the first machine for redirection 1983 */ 1984 1985 if (!machinecount) { 1986 strncpy(guestservername, entry->arg[machinecount], 1987 sizeof(guestservername)); 1988 guestservername[sizeof(guestservername) - 1] = '\0'; 1989 } 1990 1991 if (!strcasecmp(tmphost, dns_localhost)) { 1992 machineok++; 1993 break; 1994 } 1995 } 1996 } 1997 } 1998 } 1999 if (!machineok) { 2000 if (guestservername[0]) 2001 reply(530, 2002 "Guest login not allowed on this machine, connect to %s instead.", 2003 guestservername); 2004 else 2005 reply(530, 2006 "Guest login not allowed on this machine."); 2007 syslog(LOG_NOTICE, 2008 "FTP LOGIN REFUSED (localhost not in guestservers) FROM %s, %s", 2009 remoteident, name); 2010 /* End of the big patch -- Nap */ 2011 2012 dologout(0); 2013 } 2014 else if ((pw = sgetpwnam("ftp")) != NULL) { 2015 anonymous = 1; /* for the access_ok call */ 2016 if (access_ok(530) < 1) { 2017 #ifndef HELP_CRACKERS 2018 DenyLoginAfterPassword = 1; 2019 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s, %s", 2020 remoteident, name); 2021 reply(331, "Guest login ok, send your complete e-mail address as password."); 2022 #else 2023 reply(530, "User %s access denied.", name); 2024 syslog(LOG_NOTICE, 2025 "FTP LOGIN REFUSED (access denied) FROM %s, %s", 2026 remoteident, name); 2027 dologout(0); 2028 #endif 2029 } 2030 else { 2031 askpasswd = 1; 2032 /* H* fix: obey use_accessfile a little better. This way, things set on the 2033 command line [like xferlog stuff] don't get stupidly overridden. 2034 XXX: all these checks maybe should be in acl.c and access.c */ 2035 if (use_accessfile) 2036 acl_setfunctions(); 2037 reply(331, "Guest login ok, send your complete e-mail address as password."); 2038 } 2039 } 2040 else { 2041 #ifndef HELP_CRACKERS 2042 DenyLoginAfterPassword = 1; 2043 reply(331, "Guest login ok, send your complete e-mail address as password."); 2044 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (ftp not in /etc/passwd) FROM %s, %s", 2045 remoteident, name); 2046 #else 2047 reply(530, "User %s unknown.", name); 2048 syslog(LOG_NOTICE, 2049 "FTP LOGIN REFUSED (ftp not in /etc/passwd) FROM %s, %s", 2050 remoteident, name); 2051 #endif 2052 #ifdef SOLARIS_BSM_AUDIT 2053 audit_ftpd_no_anon(); 2054 #endif 2055 } 2056 return; 2057 #endif 2058 } 2059 #ifdef ANON_ONLY 2060 /* H* fix: define the above to completely DISABLE logins by real users, 2061 despite ftpusers, shells, or any of that rot. You can always hang your 2062 "real" server off some other port, and access-control it. */ 2063 2064 else { /* "ftp" or "anon" -- MARK your conditionals, okay?! */ 2065 #ifndef HELP_CRACKERS 2066 DenyLoginAfterPassword = 1; 2067 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (not anonymous) FROM %s, %s", 2068 remoteident, name); 2069 reply(331, "Password required for %s.", name); 2070 #else 2071 reply(530, "User %s unknown.", name); 2072 syslog(LOG_NOTICE, 2073 "FTP LOGIN REFUSED (not anonymous) FROM %s, %s", 2074 remoteident, name); 2075 #endif 2076 return; 2077 } 2078 /* fall here if username okay in any case */ 2079 #endif /* ANON_ONLY */ 2080 2081 #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER) 2082 if (!virtual_mode && defaultserver_deny(name) && !defaultserver_allow(name)) { 2083 #ifndef HELP_CRACKERS 2084 DenyLoginAfterPassword = 1; 2085 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (ftp denied on default server) FROM %s, %s", 2086 remoteident, name); 2087 #else 2088 reply(530, "User %s access denied.", name); 2089 syslog(LOG_NOTICE, 2090 "FTP LOGIN REFUSED (ftp denied on default server) FROM %s, %s", 2091 remoteident, name); 2092 return; 2093 #endif 2094 } 2095 #endif 2096 2097 #if defined(USE_GSS) 2098 if (gss_info.must_gss_auth && 2099 (!IS_GSSAUTH(cur_auth_type) || 2100 !(gss_info.authstate & GSS_ADAT_DONE))) { 2101 reply(530, "Must perform authentication before identifying USER."); 2102 return; 2103 } 2104 #endif /* USE_GSS */ 2105 2106 if ((pw = sgetpwnam(name)) != NULL) { 2107 if ((denieduid(pw->pw_uid) && !alloweduid(pw->pw_uid)) 2108 || (deniedgid(pw->pw_gid) && !allowedgid(pw->pw_gid))) { 2109 #ifndef HELP_CRACKERS 2110 DenyLoginAfterPassword = 1; 2111 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (username in denied-uid) FROM %s, %s", 2112 remoteident, name); 2113 reply(331, "Password required for %s.", name); 2114 #else 2115 reply(530, "User %s access denied.", name); 2116 syslog(LOG_NOTICE, 2117 "FTP LOGIN REFUSED (username in denied-uid) FROM %s, %s", 2118 remoteident, name); 2119 #endif 2120 return; 2121 } 2122 #if defined(USE_GSS) 2123 if (IS_GSSAUTH(cur_auth_type) && 2124 (gss_info.authstate & GSS_ADAT_DONE)) { 2125 char buf[BUFSIZ]; 2126 2127 if (gss_user(pw)) 2128 gss_info.authstate |= GSS_USER_DONE; 2129 2130 if (gss_info.must_gss_auth && 2131 !GSSUSERAUTH_OK(gss_info)) { 2132 reply(530, "User %s access denied", name); 2133 if (logging) 2134 syslog(LOG_NOTICE, "FTP GSSAPI LOGIN REFUSED FROM %s, %s", 2135 remoteident, name); 2136 pw = NULL; 2137 return; 2138 } 2139 /* 2140 * If GSSAPI user auth failed, or it succeeded but creds were 2141 * not forwarded as required, prompt for password. 2142 */ 2143 gss_need_passwd = !GSSUSERAUTH_OK(gss_info) || 2144 (GSSUSERAUTH_OK(gss_info) && 2145 (gss_info.want_creds && !gss_info.have_creds)); 2146 if (gss_need_passwd) { 2147 snprintf(buf, sizeof(buf), 2148 "GSSAPI user %s is authorized as %s password required", 2149 gss_info.display_name, name); 2150 reply(331, "%s", buf); 2151 askpasswd = 1; 2152 syslog(LOG_DEBUG, "%s", buf); 2153 return; 2154 } 2155 } 2156 #endif /* defined(USE_GSS) */ 2157 2158 #if !defined(USE_PAM) || (defined(USE_PAM) && defined(OTHER_PASSWD)) || defined(SOLARIS_2) /* PAM should be doing these checks, not ftpd */ 2159 #if defined(USE_PAM) && !defined(SOLARIS_2) 2160 if(!use_pam) { 2161 #endif 2162 if ((shell = pw->pw_shell) == NULL || *shell == 0) 2163 shell = _PATH_BSHELL; 2164 while ((cp = getusershell()) != NULL) 2165 if (strcmp(cp, shell) == 0) 2166 break; 2167 endusershell(); 2168 if (cp == NULL || checkuser(name)) { 2169 #ifndef HELP_CRACKERS 2170 DenyLoginAfterPassword = 1; 2171 if (cp == NULL) 2172 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (shell not in /etc/shells) FROM %s, %s", remoteident, name); 2173 else 2174 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (username in %s) FROM %s, %s", _path_ftpusers, remoteident, name); 2175 reply(331, "Password required for %s.", name); 2176 #else 2177 reply(530, "User %s access denied.", name); 2178 if (cp == NULL) 2179 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (shell not in /etc/shells) FROM %s, %s", remoteident, name); 2180 else 2181 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (username in %s) FROM %s, %s", _path_ftpusers, remoteident, name); 2182 #endif /* HELP_CRACKERS */ 2183 pw = (struct passwd *) NULL; 2184 return; 2185 } 2186 #if defined(USE_PAM) && !defined(SOLARIS_2) 2187 } /* if(!use_pam) */ 2188 #endif 2189 #endif /* !USE_PAM || (USE_PAM && OTHER_PASSWD) || SOLARIS_2 */ 2190 /* if user is a member of any of the guestgroups, cause a chroot() */ 2191 /* after they log in successfully */ 2192 if (use_accessfile) { /* see above. _H */ 2193 guest = acl_guestgroup(pw); 2194 if (guest && acl_realgroup(pw)) 2195 guest = 0; 2196 } 2197 } 2198 if (access_ok(530) < 1) { 2199 #ifndef HELP_CRACKERS 2200 DenyLoginAfterPassword = 1; 2201 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s, %s", 2202 remoteident, name); 2203 reply(331, "Password required for %s.", name); 2204 #else 2205 reply(530, "User %s access denied.", name); 2206 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s, %s", 2207 remoteident, name); 2208 #endif 2209 return; 2210 } 2211 else if (use_accessfile) /* see above. _H */ 2212 acl_setfunctions(); 2213 2214 #ifdef BSD_AUTH 2215 if ((cp = start_auth(auth, name, pw)) != NULL) { 2216 char *s; 2217 2218 for (;;) { 2219 s = strsep(&cp, "\n"); 2220 if (cp == NULL || *cp == '\0') 2221 break; 2222 lreply(331, "%s", s); 2223 } 2224 reply(331, "%s", s); 2225 } 2226 else { 2227 #endif /* BSD_AUTH */ 2228 #ifdef SKEY 2229 #ifndef __NetBSD__ 2230 #ifdef SKEY_NAME 2231 /* this is the old way, but freebsd uses it */ 2232 pwok = skeyaccess(name, NULL, remotehost, remoteaddr); 2233 #else 2234 /* this is the new way */ 2235 pwok = skeyaccess(pw, NULL, remotehost, remoteaddr); 2236 #endif /* SKEY_NAME */ 2237 reply(331, "%s", skey_challenge(name, pw, pwok)); 2238 #else 2239 if (skey_haskey(name) == 0) { 2240 char *myskey; 2241 2242 myskey = skey_keyinfo(name); 2243 reply(331, "Password [%s] required for %s.", 2244 myskey ? myskey : "error getting challenge", name); 2245 } 2246 else 2247 reply(331, "Password required for %s.", name); 2248 #endif /* __NetBSD__ */ 2249 #else 2250 #ifdef OPIE 2251 { 2252 char prompt[OPIE_CHALLENGE_MAX + 1]; 2253 opiechallenge(&opiestate, name, prompt); 2254 2255 if (askpasswd == -1) { 2256 syslog(LOG_WARNING, "Invalid FTP user name %s attempted from %s", name, remotehost); 2257 pwok = 0; 2258 } 2259 else 2260 pwok = af_pwok && opiealways(pw->pw_dir); 2261 reply(331, "Response to %s %s for %s.", 2262 prompt, pwok ? "requested" : "required", name); 2263 } 2264 #else /* !SKEY */ 2265 2266 #if defined(USE_GSS) 2267 if (GSSUSERAUTH_OK(gss_info) && !gss_need_passwd) { 2268 /* 2269 * We got this far, we are allowing the GSSAPI authentication 2270 * to succeed without further passwd prompting. Jump 2271 * to "pass" processing. 2272 */ 2273 askpasswd = 0; 2274 logged_in = 1; 2275 pass(""); 2276 return; 2277 } 2278 #endif /* defined(USE_GSS) */ 2279 reply(331, "Password required for %s.", name); 2280 #endif /* OPIE */ 2281 #endif /* SKEY */ 2282 #ifdef BSD_AUTH 2283 } 2284 #endif /* BSD_AUTH */ 2285 2286 askpasswd = 1; 2287 /* Delay before reading passwd after first failed attempt to slow down 2288 * passwd-guessing programs. */ 2289 if (login_attempts) { 2290 enable_signaling(); /* we can allow signals once again: kinch */ 2291 sleep((unsigned) login_attempts); 2292 } 2293 return; 2294 } 2295 2296 /* Check if a user is in the ftpusers file */ 2297 int checkuser(char *name) 2298 { 2299 register FILE *fd; 2300 register char *p; 2301 char line[BUFSIZ]; 2302 2303 #ifdef SOLARIS_ETC_FTPUSERS 2304 static int etc_ftpusers = 0; 2305 2306 if (etc_ftpusers) { 2307 strcpy(_path_ftpusers, _PATH_FTPUSERS); 2308 etc_ftpusers = 0; 2309 } 2310 retry: 2311 #endif 2312 if ((fd = fopen(_path_ftpusers, "r")) != NULL) { 2313 while (fgets(line, sizeof(line), fd) != NULL) 2314 if ((p = strchr(line, '\n')) != NULL) { 2315 *p = '\0'; 2316 if (line[0] == '#') 2317 continue; 2318 if (strcasecmp(line, name) == 0) { 2319 (void) fclose(fd); 2320 #ifdef SOLARIS_BSM_AUDIT 2321 audit_ftpd_excluded(name); 2322 #endif 2323 #ifdef SOLARIS_ETC_FTPUSERS 2324 if (etc_ftpusers) 2325 syslog(LOG_NOTICE, "%s is deprecated, use %s instead", _path_ftpusers, _PATH_FTPUSERS); 2326 #endif 2327 return (1); 2328 } 2329 } 2330 (void) fclose(fd); 2331 } 2332 #ifdef SOLARIS_ETC_FTPUSERS 2333 if (!etc_ftpusers && (strcmp(_path_ftpusers, _PATH_FTPUSERS) == 0)) { 2334 strcpy(_path_ftpusers, "/etc/ftpusers"); 2335 etc_ftpusers = 1; 2336 goto retry; 2337 } 2338 #endif 2339 return (0); 2340 } 2341 2342 int uid_match(char *keyword, uid_t uid) 2343 { 2344 struct aclmember *entry = NULL; 2345 int which; 2346 char *ptr; 2347 struct passwd *pw; 2348 2349 /* 2350 * keyword <uid-range> [<uid-range> ...] 2351 * 2352 * uid-range may be a username or begin with '%' and be treated as numeric: 2353 * %<uid> A single numeric UID 2354 * %<uid>+ All UIDs greater or equal to UID 2355 * %<uid>- All UIDs greater or equal to UID 2356 * %-<uid> All UIDs less or equal to UID 2357 * %<uid>-<uid> All UIDs between the two (inclusive) 2358 * * All UIDs 2359 */ 2360 while (getaclentry(keyword, &entry)) { 2361 for (which = 0; (which < MAXARGS) && ARG[which]; which++) { 2362 if (!strcmp(ARG[which], "*")) 2363 return (1); 2364 if (ARG[which][0] == '%') { 2365 if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) { 2366 if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) { 2367 if (uid == strtoul(ARG[which] + 1, NULL, 0)) 2368 return (1); 2369 } 2370 else { 2371 *ptr++ = '\0'; 2372 if ((ARG[which][1] == '\0') 2373 || (uid >= strtoul(ARG[which] + 1, NULL, 0))) { 2374 *--ptr = '+'; 2375 return (1); 2376 } 2377 *--ptr = '+'; 2378 } 2379 } 2380 else { 2381 *ptr++ = '\0'; 2382 if (((ARG[which][1] == '\0') 2383 || (uid >= strtoul(ARG[which] + 1, NULL, 0))) 2384 && ((*ptr == '\0') 2385 || (uid <= strtoul(ptr, NULL, 0)))) { 2386 *--ptr = '-'; 2387 return (1); 2388 } 2389 *--ptr = '-'; 2390 } 2391 } 2392 else { 2393 #ifdef OTHER_PASSWD 2394 pw = bero_getpwnam(ARG[which], _path_passwd); 2395 #else 2396 pw = getpwnam(ARG[which]); 2397 #endif 2398 if (pw && (uid == pw->pw_uid)) 2399 return (1); 2400 } 2401 } 2402 } 2403 return (0); 2404 } 2405 2406 int gid_match(char *keyword, gid_t gid, char *username) 2407 { 2408 struct aclmember *entry = NULL; 2409 int which; 2410 char *ptr; 2411 struct group *grp; 2412 char **member; 2413 2414 /* 2415 * keyword <gid-range> [<gid-range> ...] 2416 * 2417 * gid-range may be a groupname or begin with '%' and be treated as numeric: 2418 * %<gid> A single GID 2419 * %<gid>+ All GIDs greater or equal to GID 2420 * %<gid>- All GIDs greater or equal to GID 2421 * %-<gid> All GIDs less or equal to GID 2422 * %<gid>-<gid> All GIDs between the two (inclusive) 2423 * * All GIDs 2424 */ 2425 while (getaclentry(keyword, &entry)) { 2426 for (which = 0; (which < MAXARGS) && ARG[which]; which++) { 2427 if (!strcmp(ARG[which], "*")) 2428 return (1); 2429 if (ARG[which][0] == '%') { 2430 if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) { 2431 if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) { 2432 if (gid == strtoul(ARG[which] + 1, NULL, 0)) 2433 return (1); 2434 } 2435 else { 2436 *ptr++ = '\0'; 2437 if ((ARG[which][1] == '\0') 2438 || (gid >= strtoul(ARG[which] + 1, NULL, 0))) { 2439 *--ptr = '+'; 2440 return (1); 2441 } 2442 *--ptr = '+'; 2443 } 2444 } 2445 else { 2446 *ptr++ = '\0'; 2447 if (((ARG[which][1] == '\0') 2448 || (gid >= strtoul(ARG[which] + 1, NULL, 0))) 2449 && ((*ptr == '\0') 2450 || (gid <= strtoul(ptr, NULL, 0)))) { 2451 *--ptr = '-'; 2452 return (1); 2453 } 2454 *--ptr = '-'; 2455 } 2456 } 2457 else { 2458 if ((grp = getgrnam(ARG[which]))) { 2459 if (gid == grp->gr_gid) 2460 return (1); 2461 if (username) { 2462 for (member = grp->gr_mem; *member; member++) 2463 if (!strcasecmp(*member, username)) 2464 return (1); 2465 } 2466 } 2467 } 2468 } 2469 } 2470 return (0); 2471 } 2472 2473 int denieduid(uid_t uid) 2474 { 2475 return uid_match("deny-uid", uid); 2476 } 2477 2478 int alloweduid(uid_t uid) 2479 { 2480 return uid_match("allow-uid", uid); 2481 } 2482 2483 int deniedgid(gid_t gid) 2484 { 2485 return gid_match("deny-gid", gid, NULL); 2486 } 2487 2488 int allowedgid(gid_t gid) 2489 { 2490 return gid_match("allow-gid", gid, NULL); 2491 } 2492 2493 /* Terminate login as previous user, if any, resetting state; used when USER 2494 * command is given or login fails. */ 2495 2496 void end_login(void) 2497 { 2498 delay_signaling(); /* we can't allow any signals while euid==0: kinch */ 2499 (void) seteuid((uid_t) 0); 2500 if (logged_in) { 2501 if (wtmp_logging) 2502 wu_logwtmp(ttyline, pw->pw_name, remotehost, 0); 2503 #ifdef USE_PAM 2504 if (!anonymous && pamh) { 2505 (void) pam_close_session(pamh, 0); 2506 (void) pam_end(pamh, PAM_SUCCESS); 2507 pamh = (pam_handle_t *)0; 2508 } 2509 #endif 2510 } 2511 pw = NULL; 2512 #ifdef AFS_AUTH 2513 ktc_ForgetAllTokens(); 2514 #endif 2515 logged_in = 0; 2516 anonymous = 0; 2517 guest = 0; 2518 } 2519 2520 int validate_eaddr(char *eaddr) 2521 { 2522 int i, host, state; 2523 2524 for (i = host = state = 0; eaddr[i] != '\0'; i++) { 2525 switch (eaddr[i]) { 2526 case '.': 2527 if (!host) 2528 return 0; 2529 if (state == 2) 2530 state = 3; 2531 host = 0; 2532 break; 2533 case '@': 2534 if (!host || state > 1 || !strncasecmp("ftp", eaddr + i - host, host)) 2535 return 0; 2536 state = 2; 2537 host = 0; 2538 break; 2539 case '!': 2540 case '%': 2541 if (!host || state > 1) 2542 return 0; 2543 state = 1; 2544 host = 0; 2545 break; 2546 case '-': 2547 break; 2548 default: 2549 host++; 2550 } 2551 } 2552 if (((state == 3) && host > 1) || ((state == 1) && host > 1)) 2553 return 1; 2554 else 2555 return 0; 2556 } 2557 2558 2559 #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER) 2560 static int AllowVirtualUser(const char *username) 2561 { 2562 struct aclmember *entry = NULL; 2563 int which; 2564 2565 while (getaclentry("virtual", &entry)) 2566 if (ARG0 && hostmatch(ARG0, virtual_address, virtual_hostname) 2567 && ARG1 && !strcasecmp(ARG1, "allow")) 2568 for (which = 2; (which < MAXARGS) && ARG[which]; which++) 2569 if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which])) 2570 return (1); 2571 return (0); 2572 } 2573 2574 static int DenyVirtualUser(const char *username) 2575 { 2576 struct aclmember *entry = NULL; 2577 int which; 2578 2579 while (getaclentry("virtual", &entry)) 2580 if (ARG0 && hostmatch(ARG0, virtual_address, virtual_hostname) 2581 && ARG1 && !strcasecmp(ARG1, "deny")) 2582 for (which = 2; (which < MAXARGS) && ARG[which]; which++) 2583 if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which])) 2584 return (1); 2585 return (0); 2586 } 2587 2588 static int DenyVirtualAnonymous(void) 2589 { 2590 struct aclmember *entry = NULL; 2591 2592 while (getaclentry("virtual", &entry)) 2593 if (ARG0 && hostmatch(ARG0, virtual_address, virtual_hostname) 2594 && ARG1 && !strcasecmp(ARG1, "private")) 2595 return (1); 2596 return (0); 2597 } 2598 #endif 2599 2600 void pass(char *passwd) 2601 { 2602 2603 #if !defined(USE_PAM) || (defined(USE_PAM) && defined(OTHER_PASSWD)) 2604 char *xpasswd, *salt; 2605 #endif 2606 2607 int passwarn = 0; 2608 int rval = 1; 2609 int success_code = 230; 2610 int cos; 2611 2612 #ifdef SECUREOSF 2613 struct pr_passwd *pr; 2614 int crypt_alg = 0; 2615 #endif 2616 2617 #ifdef BSD_AUTH 2618 extern int ext_auth; 2619 extern char *check_auth(); 2620 #endif 2621 2622 #ifdef ULTRIX_AUTH 2623 int numfails; 2624 #endif /* ULTRIX_AUTH */ 2625 2626 #ifdef HAS_PW_EXPIRE 2627 int set_expired = FALSE; 2628 #endif 2629 2630 #ifdef AFS_AUTH 2631 char *reason; 2632 #endif /* AFS_AUTH */ 2633 2634 #ifdef DCE_AUTH 2635 sec_passwd_rec_t pwr; 2636 sec_login_handle_t lhdl; 2637 boolean32 rstpwd; 2638 sec_login_auth_src_t asrc; 2639 error_status_t status; 2640 #endif /* DCE_AUTH */ 2641 2642 #if defined(USE_GSS) 2643 /* 2644 * LOGIC: 2645 * If [ the user presented GSSAPI creds and was authorized ] 2646 * jump down past the password validation code. 2647 */ 2648 if (GSSUSERAUTH_OK(gss_info) && logged_in) { 2649 /* 2650 * We could reply(202, "PASS command superfluous.") here, but 2651 * allow this for compat with some clients. 2652 */ 2653 success_code = 232; 2654 goto pwd_validation_done; 2655 } 2656 #endif /* defined(USE_GSS) */ 2657 2658 if (logged_in || askpasswd == 0) { 2659 #ifdef VERBOSE_ERROR_LOGING 2660 syslog(LOG_NOTICE, "FTP LOGIN REFUSED (PASS before USER) FROM %s", 2661 remoteident); 2662 #endif 2663 reply(503, "Login with USER first."); 2664 return; 2665 } 2666 askpasswd = 0; 2667 2668 /* Disable lreply() if the first character of the password is '-' since 2669 * some hosts don't understand continuation messages and hang... */ 2670 2671 if (*passwd == '-') 2672 dolreplies = 0; 2673 else 2674 dolreplies = 1; 2675 /* ******** REGULAR/GUEST USER PASSWORD PROCESSING ********** */ 2676 if (!anonymous) { /* "ftp" is only account allowed no password */ 2677 #ifndef HELP_CRACKERS 2678 if (DenyLoginAfterPassword) { 2679 pr_mesg(530, DelayedMessageFile); 2680 reply(530, "Login incorrect."); 2681 #ifdef SOLARIS_BSM_AUDIT 2682 audit_ftpd_failure(the_user); 2683 #endif 2684 acl_remove(); 2685 pw = NULL; 2686 if (++login_attempts >= lgi_failure_threshold) { 2687 syslog(LOG_NOTICE, "repeated login failures from %s", 2688 remoteident); 2689 exit(0); 2690 } 2691 return; 2692 } 2693 #endif 2694 if (*passwd == '-') 2695 passwd++; 2696 #ifdef USE_PAM 2697 #ifdef OTHER_PASSWD 2698 if (use_pam 2699 #if defined(USE_GSS) 2700 && !GSSUSERAUTH_OK(gss_info) 2701 #endif 2702 ) { 2703 #endif 2704 /* PAM authentication 2705 * If PAM authenticates a user we know nothing about on the local 2706 * system, use the generic guest account credentials. We should make 2707 * this somehow a configurable item somewhere; later more on that. 2708 * 2709 * For now assume the guest (not anonymous) identity, so the site 2710 * admins can still differentiate between the truw anonymous user and 2711 * a little bit more special ones. Otherwise he wouldn't go the extra 2712 * mile to have a different user database, right? 2713 * --gaftonc */ 2714 if (pam_check_pass(the_user, passwd)) { 2715 rval = 0; 2716 if (pw == NULL) { 2717 /* assume guest account identity */ 2718 pw = sgetpwnam("ftp"); 2719 anonymous = 0; 2720 guest = 1; 2721 /* even go as far as... */ 2722 if (pw != NULL && pw->pw_name != NULL) { 2723 free(pw->pw_name); 2724 pw->pw_name = sgetsave(the_user); 2725 } 2726 } 2727 } 2728 #ifdef OTHER_PASSWD 2729 } else { 2730 #endif 2731 #endif /* USE_PAM */ 2732 #if !defined(USE_PAM) || (defined(USE_PAM) && defined(OTHER_PASSWD)) 2733 #ifdef BSD_AUTH 2734 if (ext_auth) { 2735 if ((salt = check_auth(the_user, passwd))) { 2736 reply(530, "%s", salt); 2737 #ifdef LOG_FAILED /* 27-Apr-93 EHK/BM */ 2738 /* 2739 * To avoid logging passwords mistakenly entered as 2740 * usernames, only log the names of users which exist. 2741 */ 2742 syslog(LOG_INFO, "failed login from %s, %s", remoteident, 2743 (pw == NULL) ? "[unknown]" : the_user); 2744 #endif /* LOG_FAILED */ 2745 acl_remove(); 2746 pw = NULL; 2747 if (++login_attempts >= lgi_failure_threshold) { 2748 syslog(LOG_NOTICE, "repeated login failures from %s", 2749 remoteident); 2750 exit(0); 2751 } 2752 return; 2753 } 2754 } 2755 else { 2756 #endif /* BSD_AUTH */ 2757 *guestpw = '\0'; 2758 if (pw == NULL) 2759 salt = "xx"; 2760 else 2761 #ifndef OPIE 2762 salt = pw->pw_passwd; 2763 #ifdef SECUREOSF 2764 if ((pr = getprpwnam(pw->pw_name)) != NULL) { 2765 if (pr->uflg.fg_newcrypt) 2766 crypt_alg = pr->ufld.fd_newcrypt; 2767 else if (pr->sflg.fg_newcrypt) 2768 crypt_alg = pr->sfld.fd_newcrypt; 2769 else 2770 crypt_alg = 0; 2771 } 2772 else 2773 crypt_alg = 0; 2774 2775 xpasswd = dispcrypt(passwd, salt, crypt_alg); 2776 #elif defined(SecureWare) || defined(HPUX_10_TRUSTED) 2777 xpasswd = bigcrypt(passwd, salt); 2778 #elif defined(KERBEROS) 2779 xpasswd = crypt16(passwd, salt); 2780 #elif defined(SKEY) 2781 #ifndef __NetBSD__ 2782 xpasswd = skey_crypt(passwd, salt, pw, pwok); 2783 pwok = 0; 2784 #else 2785 if ((pw != NULL) && (pw->pw_name != NULL) && skey_haskey(pw->pw_name) == 0 && 2786 skey_passcheck(pw->pw_name, passwd) != -1) 2787 xpasswd = pw->pw_passwd; 2788 else 2789 xpasswd = crypt(passwd, salt); 2790 #endif 2791 #else /* !SKEY */ 2792 xpasswd = crypt(passwd, salt); 2793 #endif /* SKEY */ 2794 #else /* OPIE */ 2795 if (!opieverify(&opiestate, passwd)) 2796 rval = 0; 2797 xpasswd = crypt(passwd, pw->pw_passwd); 2798 #endif /* OPIE */ 2799 #ifdef ULTRIX_AUTH 2800 if ((numfails = ultrix_check_pass(passwd, xpasswd)) >= 0) { 2801 #else 2802 if (pw != NULL) { 2803 #ifdef AFS_AUTH 2804 if (strcmp(pw->pw_passwd, "X") == 0) 2805 if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION | KA_USERAUTH_DOSETPAG, pw->pw_name, "", 0, passwd, 0, 0, 0, &reason) == 0) 2806 rval = 0; 2807 else 2808 printf("230-AFS: %s", reason); 2809 else 2810 #endif /* AFS_AUTH */ 2811 /* The strcmp does not catch null passwords! */ 2812 #ifdef HAS_PW_EXPIRE 2813 if(pw->pw_expire != NULL) { 2814 if(pw->pw_expire && time(NULL) >= pw->pw_expire) { 2815 set_expired = TRUE; 2816 } 2817 } 2818 #endif 2819 2820 if (*pw->pw_passwd != '\0' && 2821 #ifdef HAS_PW_EXPIRE 2822 !set_expired && 2823 #endif 2824 strcmp(xpasswd, pw->pw_passwd) == 0) { 2825 #endif 2826 rval = 0; 2827 } 2828 #ifdef DCE_AUTH 2829 #ifndef ALWAYS_TRY_DCE 2830 else 2831 #endif /* ALWAYS_TRY_DCE */ 2832 { 2833 sec_login_setup_identity((unsigned_char_p_t) pw->pw_name, sec_login_no_flags, &lhdl, &status); 2834 if (status == error_status_ok) { 2835 printf("230-sec_login_setup_identity OK\n"); 2836 pwr.key.tagged_union.plain = (idl_char *) passwd; 2837 pwr.key.key_type = sec_passwd_plain; 2838 pwr.pepper = 0; 2839 pwr.version_number = sec_passwd_c_version_none; 2840 /* validate password with login context */ 2841 sec_login_valid_and_cert_ident(lhdl, &pwr, &rstpwd, &asrc, &status); 2842 if (!rstpwd && (asrc == sec_login_auth_src_network) && (status == error_status_ok)) { 2843 printf("230-sec_login_valid_and_cert_ident OK\n"); 2844 sec_login_set_context(lhdl, &status); 2845 printf("230-sec_login_set_context finished\n"); 2846 if (status != error_status_ok) { 2847 int pstatus; 2848 dce_error_string_t s; 2849 printf("230-Error status: %d:\n", status); 2850 dce_error_inq_text(status, s, &pstatus); 2851 printf("230-%s\n", s); 2852 fflush(stderr); 2853 sec_login_purge_context(lhdl, &status); 2854 } 2855 else { 2856 /*sec_login_get_pwent(lhdl, &pw, &status); */ 2857 rval = 0; 2858 } 2859 } 2860 } 2861 } 2862 #endif /* DCE_AUTH */ 2863 } 2864 #ifdef USE_PAM 2865 } 2866 #endif 2867 #endif /* !USE_PAM || (USE_PAM && OTHER_PASSWD) */ 2868 if (rval) { 2869 reply(530, "Login incorrect."); 2870 2871 #ifdef LOG_FAILED /* 27-Apr-93 EHK/BM */ 2872 /* H* add-on: yell about attempts to use the trojan. This may alarm you 2873 if you're "stringsing" the binary and you see "NULL" pop out in just 2874 about the same place as it would have in 2.2c! */ 2875 if (!strcasecmp(passwd, "NULL")) 2876 syslog(LOG_NOTICE, "REFUSED \"NULL\" from %s, %s", 2877 remoteident, the_user); 2878 else { 2879 /* 2880 * To avoid logging passwords mistakenly entered as 2881 * usernames, only log the names of users which exist. 2882 */ 2883 syslog(LOG_INFO, "failed login from %s, %s", remoteident, 2884 (pw == NULL) ? "[unknown]" : the_user); 2885 } 2886 #endif 2887 #ifdef SOLARIS_BSM_AUDIT 2888 audit_ftpd_failure(the_user); 2889 #endif 2890 acl_remove(); 2891 2892 pw = NULL; 2893 if (++login_attempts >= lgi_failure_threshold) { 2894 syslog(LOG_NOTICE, "repeated login failures from %s", 2895 remoteident); 2896 exit(0); 2897 } 2898 return; 2899 } 2900 #ifdef BSD_AUTH 2901 } 2902 #endif 2903 /* ANONYMOUS USER PROCESSING STARTS HERE */ 2904 } 2905 else { 2906 char *pwin, *pwout = guestpw; 2907 struct aclmember *entry = NULL; 2908 int valid; 2909 int enforce = 0; 2910 2911 if (getaclentry("passwd-check", &entry) && 2912 ARG0 && strcasecmp(ARG0, "none")) { 2913 2914 if (!strcasecmp(ARG0, "rfc822")) 2915 valid = validate_eaddr(passwd); 2916 else if (!strcasecmp(ARG0, "trivial")) 2917 valid = (strchr(passwd, '@') == NULL) ? 0 : 1; 2918 else 2919 valid = 1; 2920 if (ARG1 && !strcasecmp(ARG1, "enforce")) 2921 enforce = 1; 2922 /* Block off "default" responses like mozilla@ and IE30User@ 2923 * (at the administrator's discretion). --AC 2924 */ 2925 entry = NULL; 2926 while (getaclentry("deny-email", &entry)) { 2927 if (ARG0 2928 && ((strcasecmp(passwd, ARG0) == 0) 2929 || regexmatch(passwd, ARG0) 2930 || ((*passwd == '-') 2931 && ((strcasecmp(passwd + 1, ARG0) == 0) 2932 || regexmatch(passwd + 1, ARG0))))) { 2933 valid = 0; 2934 break; 2935 } 2936 } 2937 if (!valid && enforce) { 2938 lreply(530, "The response '%s' is not valid", passwd); 2939 lreply(530, "Please use your e-mail address as your password"); 2940 lreply(530, " for example: %s@%s%s", 2941 authenticated ? authuser : "joe", remotehost, 2942 strchr(remotehost, '.') ? "" : ".network"); 2943 reply(530, "Login incorrect."); 2944 #ifdef VERBOSE_ERROR_LOGING 2945 syslog(LOG_NOTICE, "FTP ACCESS REFUSED (anonymous password not rfc822) from %s", 2946 remoteident); 2947 #endif 2948 #ifdef SOLARIS_BSM_AUDIT 2949 audit_ftpd_bad_pw(the_user); 2950 #endif 2951 acl_remove(); 2952 if (++login_attempts >= lgi_failure_threshold) { 2953 syslog(LOG_NOTICE, "repeated login failures from %s", 2954 remoteident); 2955 exit(0); 2956 } 2957 return; 2958 } 2959 else if (!valid) 2960 passwarn = 1; 2961 } 2962 if (!*passwd) { 2963 strcpy(guestpw, "[none_given]"); 2964 } 2965 else { 2966 int cnt = sizeof(guestpw) - 2; 2967 2968 for (pwin = passwd; *pwin && cnt--; pwin++) 2969 if (!isgraph(*pwin)) 2970 *pwout++ = '_'; 2971 else 2972 *pwout++ = *pwin; 2973 } 2974 #ifndef HELP_CRACKERS 2975 if (DenyLoginAfterPassword) { 2976 pr_mesg(530, DelayedMessageFile); 2977 reply(530, "Login incorrect."); 2978 #ifdef SOLARIS_BSM_AUDIT 2979 audit_ftpd_failure(the_user); 2980 #endif 2981 acl_remove(); 2982 pw = NULL; 2983 if (++login_attempts >= lgi_failure_threshold) { 2984 syslog(LOG_NOTICE, "repeated login failures from %s", 2985 remoteident); 2986 exit(0); 2987 } 2988 return; 2989 } 2990 #endif 2991 } 2992 2993 #if defined(USE_GSS) 2994 pwd_validation_done: 2995 #endif /* USE_GSS */ 2996 /* if logging is enabled, open logfile before chroot or set group ID */ 2997 if ((log_outbound_xfers || log_incoming_xfers) && (syslogmsg != 1)) { 2998 mode_t oldmask; 2999 oldmask = umask(0); 3000 xferlog = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0640); 3001 (void) umask(oldmask); 3002 if (xferlog < 0) { 3003 syslog(LOG_ERR, "cannot open logfile %s: %s", logfile, 3004 strerror(errno)); 3005 xferlog = 0; 3006 } 3007 } 3008 3009 #ifdef DEBUG 3010 /* I had a lot of trouble getting xferlog working, because of two factors: 3011 acl_setfunctions making stupid assumptions, and sprintf LOSING. _H */ 3012 /* 3013 * Actually, sprintf was not losing, but the rules changed... next release 3014 * this will be fixed the correct way, but right now, it works well enough 3015 * -- sob 3016 */ 3017 syslog(LOG_INFO, "-i %d,-o %d,xferlog %s: %d", 3018 log_incoming_xfers, log_outbound_xfers, logfile, xferlog); 3019 #endif 3020 enable_signaling(); /* we can allow signals once again: kinch */ 3021 /* if autogroup command applies to user's class change pw->pw_gid */ 3022 if (anonymous && use_accessfile) { /* see above. _H */ 3023 (void) acl_autogroup(pw); 3024 guest = acl_guestgroup(pw); /* the new group may be a guest */ 3025 if (guest && acl_realgroup(pw)) 3026 guest = 0; 3027 anonymous = !guest; 3028 } 3029 /* END AUTHENTICATION */ 3030 3031 /* SET GROUP ID STARTS HERE */ 3032 #ifndef AIX 3033 (void) setegid((gid_t) pw->pw_gid); 3034 #else 3035 (void) setgid((gid_t) pw->pw_gid); 3036 #endif 3037 (void) initgroups(pw->pw_name, pw->pw_gid); 3038 #ifdef DEBUG 3039 syslog(LOG_DEBUG, "initgroups has been called"); 3040 #endif 3041 /* WTMP PROCESSING STARTS HERE */ 3042 if (wtmp_logging) { 3043 /* open wtmp before chroot */ 3044 #if ((defined(BSD) && (BSD >= 199103)) || defined(sun)) 3045 (void) sprintf(ttyline, "ftp%ld", (long) getpid()); 3046 #else 3047 (void) sprintf(ttyline, "ftpd%d", getpid()); 3048 #endif 3049 #ifdef DEBUG 3050 syslog(LOG_DEBUG, "about to call wtmp"); 3051 #endif 3052 wu_logwtmp(ttyline, pw->pw_name, remotehost, 1); 3053 } 3054 logged_in = 1; 3055 3056 expand_id(); 3057 3058 #ifdef QUOTA 3059 memset("a, 0, sizeof(quota)); 3060 get_quota(pw->pw_dir, pw->pw_uid); 3061 #endif 3062 3063 restricted_user = 0; 3064 if (!anonymous) 3065 if ((restricteduid(pw->pw_uid) && !unrestricteduid(pw->pw_uid)) 3066 || (restrictedgid(pw->pw_gid) && !unrestrictedgid(pw->pw_gid))) 3067 restricted_user = 1; 3068 if (anonymous || guest) { 3069 char *sp; 3070 /* We MUST do a chdir() after the chroot. Otherwise the old current 3071 * directory will be accessible as "." outside the new root! */ 3072 #ifdef ALTERNATE_CD 3073 home = defhome; 3074 #endif 3075 #ifdef VIRTUAL 3076 if (virtual_mode && !guest) { 3077 #ifdef CLOSED_VIRTUAL_SERVER 3078 if (DenyVirtualAnonymous()) { 3079 #ifdef VERBOSE_ERROR_LOGING 3080 syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host anonymous access denied) for %s", 3081 remoteident); 3082 #endif 3083 reply(530, "Login incorrect."); 3084 if (++login_attempts >= lgi_failure_threshold) { 3085 syslog(LOG_NOTICE, "repeated login failures from %s", remoteident); 3086 dologout(0); 3087 } 3088 goto bad; 3089 } 3090 #endif 3091 /* Anonymous user in virtual_mode */ 3092 if (pw->pw_dir) 3093 free(pw->pw_dir); 3094 pw->pw_dir = sgetsave(virtual_root); 3095 } 3096 else 3097 #endif 3098 3099 /* 3100 * New chroot logic. 3101 * 3102 * If VIRTUAL is supported, the chroot for anonymous users on the 3103 * virtual host has already been determined. Otherwise the logic 3104 * below applies: 3105 * 3106 * If this is an anonymous user, the chroot directory is determined 3107 * by the "anonymous-root" clause and the home directory is taken 3108 * from the etc/passwd file found after chroot'ing. 3109 * 3110 * If this a guest user, the chroot directory is determined by the 3111 * "guest-root" clause and the home directory is taken from the 3112 * etc/passwd file found after chroot'ing. 3113 * 3114 * The effect of this logic is that the entire chroot environment 3115 * is under the control of the ftpaccess file and the supporting 3116 * files in the ftp environment. The system-wide passwd file is 3117 * used only to authenticate the user. 3118 */ 3119 3120 { 3121 struct aclmember *entry = NULL; 3122 char *root_path = NULL; 3123 3124 if (anonymous) { 3125 char class[BUFSIZ]; 3126 3127 (void) acl_getclass(class); 3128 while (getaclentry("anonymous-root", &entry) && ARG0) { 3129 if (!ARG1) { 3130 if (!root_path) 3131 root_path = ARG0; 3132 } 3133 else { 3134 int which; 3135 3136 for (which = 1; (which < MAXARGS) && ARG[which]; which++) { 3137 if (!strcmp(ARG[which], "*")) { 3138 if (!root_path) 3139 root_path = ARG0; 3140 } 3141 else { 3142 if (!strcasecmp(ARG[which], class)) 3143 root_path = ARG0; 3144 } 3145 } 3146 } 3147 } 3148 } 3149 else { /* (guest) */ 3150 while (getaclentry("guest-root", &entry) && ARG0) { 3151 if (!ARG1) { 3152 if (!root_path) 3153 root_path = ARG0; 3154 } 3155 else { 3156 int which; 3157 char *ptr; 3158 3159 for (which = 1; (which < MAXARGS) && ARG[which]; which++) { 3160 if (!strcmp(ARG[which], "*")) { 3161 if (!root_path) 3162 root_path = ARG0; 3163 } 3164 else { 3165 if (ARG[which][0] == '%') { 3166 if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) { 3167 if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) { 3168 if (pw->pw_uid == strtoul(ARG[which] + 1, NULL, 0)) 3169 root_path = ARG0; 3170 } 3171 else { 3172 *ptr++ = '\0'; 3173 if ((ARG[which][1] == '\0') 3174 || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0))) 3175 root_path = ARG0; 3176 *--ptr = '+'; 3177 } 3178 } 3179 else { 3180 *ptr++ = '\0'; 3181 if (((ARG[which][1] == '\0') 3182 || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0))) 3183 && ((*ptr == '\0') 3184 || (pw->pw_uid <= strtoul(ptr, NULL, 0)))) 3185 root_path = ARG0; 3186 *--ptr = '-'; 3187 } 3188 } 3189 else { 3190 #ifdef OTHER_PASSWD 3191 struct passwd *guest_pw = bero_getpwnam(ARG[which], _path_passwd); 3192 #else 3193 struct passwd *guest_pw = getpwnam(ARG[which]); 3194 #endif 3195 if (guest_pw && (pw->pw_uid == guest_pw->pw_uid)) 3196 root_path = ARG0; 3197 } 3198 } 3199 } 3200 } 3201 } 3202 } 3203 3204 if (root_path) { 3205 struct passwd *chroot_pw = NULL; 3206 3207 #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER) 3208 if (virtual_mode && strcmp(root_path, virtual_root) && !(AllowVirtualUser(pw->pw_name) && !DenyVirtualUser(pw->pw_name))) { 3209 #ifdef VERBOSE_ERROR_LOGING 3210 syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host access denied) for %s, %s", 3211 remoteident, pw->pw_name); 3212 #endif 3213 reply(530, "Login incorrect."); 3214 if (++login_attempts >= lgi_failure_threshold) { 3215 syslog(LOG_NOTICE, "repeated login failures from %s", remoteident); 3216 dologout(0); 3217 } 3218 goto bad; 3219 } 3220 #endif 3221 (void) strncpy(chroot_path, root_path, sizeof(chroot_path)); 3222 chroot_path[sizeof(chroot_path) - 1] = '\0'; 3223 if (pw->pw_dir) 3224 free(pw->pw_dir); 3225 pw->pw_dir = sgetsave(chroot_path); 3226 #if defined(SOLARIS_2) 3227 cleanup_nscd(); 3228 #endif 3229 if (chroot(root_path) < 0 || chdir("/") < 0) { 3230 #ifdef VERBOSE_ERROR_LOGING 3231 syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set guest privileges) for %s, %s", 3232 remoteident, pw->pw_name); 3233 #endif 3234 reply(530, "Can't set guest privileges."); 3235 goto bad; 3236 } 3237 #ifdef OTHER_PASSWD 3238 if ((chroot_pw = bero_getpwuid(pw->pw_uid, _path_passwd)) != NULL) 3239 #else 3240 if ((chroot_pw = getpwuid(pw->pw_uid)) != NULL) 3241 #endif 3242 if (chdir(chroot_pw->pw_dir) >= 0) 3243 home = sgetsave(chroot_pw->pw_dir); 3244 goto slimy_hack; /* onea these days I'll make this structured code, honest ... */ 3245 } 3246 } 3247 3248 /* determine root and home directory */ 3249 3250 if ((sp = strstr(pw->pw_dir, "/./")) == NULL) { 3251 (void) strncpy(chroot_path, pw->pw_dir, sizeof(chroot_path)); 3252 chroot_path[sizeof(chroot_path) - 1] = '\0'; 3253 #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER) 3254 if (virtual_mode && strcmp(chroot_path, virtual_root) && !(AllowVirtualUser(pw->pw_name) && !DenyVirtualUser(pw->pw_name))) { 3255 #ifdef VERBOSE_ERROR_LOGING 3256 syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host access denied) for %s, %s", 3257 remoteident, pw->pw_name); 3258 #endif 3259 reply(530, "Login incorrect."); 3260 if (++login_attempts >= lgi_failure_threshold) { 3261 syslog(LOG_NOTICE, "repeated login failures from %s", remoteident); 3262 dologout(0); 3263 } 3264 goto bad; 3265 } 3266 #endif 3267 #if defined(SOLARIS_2) 3268 cleanup_nscd(); 3269 #endif 3270 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { 3271 #ifdef VERBOSE_ERROR_LOGING 3272 syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set guest privileges) for %s, %s", 3273 remoteident, pw->pw_name); 3274 #endif 3275 reply(530, "Can't set guest privileges."); 3276 goto bad; 3277 } 3278 } 3279 else { 3280 *sp++ = '\0'; 3281 (void) strncpy(chroot_path, pw->pw_dir, sizeof(chroot_path)); 3282 chroot_path[sizeof(chroot_path) - 1] = '\0'; 3283 #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER) 3284 if (virtual_mode && strcmp(chroot_path, virtual_root) && !(AllowVirtualUser(pw->pw_name) && !DenyVirtualUser(pw->pw_name))) { 3285 #ifdef VERBOSE_ERROR_LOGING 3286 syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host access denied) for %s, %s", 3287 remoteident, pw->pw_name); 3288 #endif 3289 reply(530, "Login incorrect."); 3290 if (++login_attempts >= lgi_failure_threshold) { 3291 syslog(LOG_NOTICE, "repeated login failures from %s", remoteident); 3292 dologout(0); 3293 } 3294 goto bad; 3295 } 3296 #endif 3297 #if defined(SOLARIS_2) 3298 cleanup_nscd(); 3299 #endif 3300 if (chroot(pw->pw_dir) < 0 || chdir(++sp) < 0) { 3301 #ifdef VERBOSE_ERROR_LOGING 3302 syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set guest privileges) for %s, %s", 3303 remoteident, pw->pw_name); 3304 #endif 3305 reply(550, "Can't set guest privileges."); 3306 goto bad; 3307 } 3308 #ifdef ALTERNATE_CD 3309 home = sp; 3310 #endif 3311 } 3312 slimy_hack: 3313 /* shut up you stupid compiler! */ { 3314 int i = 0; 3315 i++; 3316 } 3317 } 3318 #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER) 3319 else if (virtual_mode && !(AllowVirtualUser(pw->pw_name) && !DenyVirtualUser(pw->pw_name))) { 3320 #ifdef VERBOSE_ERROR_LOGING 3321 syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host access denied) for %s, %s", 3322 remoteident, pw->pw_name); 3323 #endif 3324 reply(530, "Login incorrect."); 3325 if (++login_attempts >= lgi_failure_threshold) { 3326 syslog(LOG_NOTICE, "repeated login failures from %s", remoteident); 3327 dologout(0); 3328 } 3329 goto bad; 3330 } 3331 #endif 3332 #ifdef AIX 3333 { 3334 /* AIX 3 lossage. Don't ask. It's undocumented. */ 3335 priv_t priv; 3336 3337 priv.pv_priv[0] = 0; 3338 priv.pv_priv[1] = 0; 3339 /* setgroups(NULL, NULL); */ 3340 if (setpriv(PRIV_SET | PRIV_INHERITED | PRIV_EFFECTIVE | PRIV_BEQUEATH, 3341 &priv, sizeof(priv_t)) < 0 || 3342 setuidx(ID_REAL | ID_EFFECTIVE, (uid_t) pw->pw_uid) < 0 || 3343 seteuid((uid_t) pw->pw_uid) < 0) { 3344 #ifdef VERBOSE_ERROR_LOGING 3345 syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set uid) for %s, %s", 3346 remoteident, pw->pw_name); 3347 #endif 3348 reply(530, "Can't set uid (AIX3)."); 3349 goto bad; 3350 } 3351 } 3352 #ifdef UID_DEBUG 3353 lreply(success_code, "ruid=%d, euid=%d, suid=%d, luid=%d", getuidx(ID_REAL), 3354 getuidx(ID_EFFECTIVE), getuidx(ID_SAVED), getuidx(ID_LOGIN)); 3355 lreply(success_code, "rgid=%d, egid=%d, sgid=%d, lgid=%d", getgidx(ID_REAL), 3356 getgidx(ID_EFFECTIVE), getgidx(ID_SAVED), getgidx(ID_LOGIN)); 3357 #endif 3358 #else /* AIX */ 3359 #ifdef HAVE_SETREUID 3360 if (setreuid(-1, (uid_t) pw->pw_uid) < 0) { 3361 #else 3362 if (seteuid((uid_t) pw->pw_uid) < 0) { 3363 #endif 3364 #ifdef VERBOSE_ERROR_LOGING 3365 syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set uid) for %s, %s", 3366 remoteident, pw->pw_name); 3367 #endif 3368 reply(530, "Can't set uid."); 3369 goto bad; 3370 } 3371 #endif /* AIX */ 3372 if (!anonymous && !guest) { 3373 if (chdir(pw->pw_dir) < 0) { 3374 #ifdef PARANOID 3375 #ifdef VERBOSE_ERROR_LOGING 3376 syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot chdir) for %s, %s", 3377 remoteident, pw->pw_name); 3378 #endif 3379 reply(530, "User %s: can't change directory to %s.", 3380 pw->pw_name, pw->pw_dir); 3381 goto bad; 3382 #else /* PARANOID */ 3383 if (restricted_user || chdir("/") < 0) { 3384 #ifdef VERBOSE_ERROR_LOGING 3385 syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot chdir) for %s, %s", 3386 remoteident, pw->pw_name); 3387 #endif 3388 reply(530, "User %s: can't change directory to %s.", 3389 pw->pw_name, pw->pw_dir); 3390 goto bad; 3391 } 3392 else { 3393 lreply(success_code, "No directory! Logging in with home=/"); 3394 #ifdef ALTERNATE_CD 3395 home = defhome; 3396 #endif 3397 } 3398 #endif /* PARANOID */ 3399 } 3400 } 3401 3402 if (passwarn) { 3403 lreply(success_code, "The response '%s' is not valid", passwd); 3404 lreply(success_code, 3405 "Next time please use your e-mail address as your password"); 3406 lreply(success_code, " for example: %s@%s%s", 3407 authenticated ? authuser : "joe", remotehost, 3408 strchr(remotehost, '.') ? "" : ".network"); 3409 } 3410 3411 login_attempts = 0; /* this time successful */ 3412 3413 /* following two lines were inside the next scope... */ 3414 3415 show_message(success_code, LOG_IN); 3416 show_message(success_code, C_WD); 3417 show_readme(success_code, LOG_IN); 3418 show_readme(success_code, C_WD); 3419 3420 #ifdef ULTRIX_AUTH 3421 if (!anonymous && numfails > 0) { 3422 lreply(success_code, 3423 "There have been %d unsuccessful login attempts on your account", 3424 numfails); 3425 } 3426 #endif /* ULTRIX_AUTH */ 3427 3428 (void) is_shutdown(0, 0); /* display any shutdown messages now */ 3429 3430 if (anonymous) { 3431 3432 reply(success_code, "Guest login ok, access restrictions apply."); 3433 sprintf(proctitle, "%s: anonymous/%.*s", remotehost, 3434 (int) (sizeof(proctitle) - sizeof(remotehost) - 3435 sizeof(": anonymous/")), passwd); 3436 setproctitle("%s", proctitle); 3437 if (logging) 3438 syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", 3439 remoteident, passwd); 3440 } 3441 else { 3442 reply(success_code, "User %s logged in.%s", pw->pw_name, guest ? 3443 " Access restrictions apply." : ""); 3444 sprintf(proctitle, "%s: %s", remotehost, pw->pw_name); 3445 setproctitle("%s", proctitle); 3446 if (logging) 3447 syslog(LOG_INFO, "FTP LOGIN FROM %s, %s", remoteident, pw->pw_name); 3448 /* H* mod: if non-anonymous user, copy it to "authuser" so everyone can 3449 see it, since whoever he was @foreign-host is now largely irrelevant. 3450 NMM mod: no, it isn't! Think about accounting for the transfers from or 3451 to a shared account. */ 3452 /* strcpy (authuser, pw->pw_name); */ 3453 } /* anonymous */ 3454 #ifdef ALTERNATE_CD 3455 if (!home) 3456 #endif 3457 home = pw->pw_dir; /* home dir for globbing */ 3458 (void) umask(defumask); 3459 time(&login_time); 3460 { 3461 struct aclmember *entry; 3462 entry = NULL; 3463 while (getaclentry("limit-time", &entry) && ARG0 && ARG1) 3464 if ((anonymous && strcasecmp(ARG0, "anonymous") == 0) 3465 || (guest && strcasecmp(ARG0, "guest") == 0) 3466 || ((guest | anonymous) && strcmp(ARG0, "*") == 0)) 3467 limit_time = strtoul(ARG1, NULL, 0); 3468 } 3469 3470 /* Need to reset here as user type/class now known */ 3471 #ifdef INET6 3472 /* IP_TOS is an IPv4 socket option */ 3473 if (SOCK_FAMILY(ctrl_addr) == AF_INET) 3474 #endif 3475 if ((cos = IPClassOfService("control")) >= 0) { 3476 if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *) &cos, sizeof(int)) < 0) 3477 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 3478 } 3479 3480 #ifdef SOLARIS_BSM_AUDIT 3481 audit_ftpd_success(the_user); 3482 #endif 3483 init_privs(pw->pw_name); 3484 return; 3485 bad: 3486 /* Forget all about it... */ 3487 if (xferlog) 3488 close(xferlog); 3489 xferlog = 0; 3490 acl_remove(); 3491 #ifdef SOLARIS_BSM_AUDIT 3492 audit_ftpd_failure(the_user); 3493 #endif 3494 end_login(); 3495 return; 3496 } 3497 3498 int restricteduid(uid_t uid) 3499 { 3500 return uid_match("restricted-uid", uid); 3501 } 3502 3503 int unrestricteduid(uid_t uid) 3504 { 3505 return uid_match("unrestricted-uid", uid); 3506 } 3507 3508 int restrictedgid(gid_t gid) 3509 { 3510 return gid_match("restricted-gid", gid, NULL); 3511 } 3512 3513 int unrestrictedgid(gid_t gid) 3514 { 3515 return gid_match("unrestricted-gid", gid, NULL); 3516 } 3517 3518 char *opt_string(int options) 3519 { 3520 static char buf[100]; 3521 char *ptr = buf; 3522 3523 if ((options & O_COMPRESS) != 0) /* debian fixes: NULL -> 0 */ 3524 *ptr++ = 'C'; 3525 if ((options & O_TAR) != 0) 3526 *ptr++ = 'T'; 3527 if ((options & O_UNCOMPRESS) != 0) 3528 *ptr++ = 'U'; 3529 if (options == 0) 3530 *ptr++ = '_'; 3531 *ptr++ = '\0'; 3532 return (buf); 3533 } 3534 3535 #ifdef INTERNAL_LS 3536 char *rpad(char *s, unsigned int len) 3537 { 3538 char *a; 3539 a = (char *) malloc(len + 1); 3540 memset(a, ' ', len); 3541 a[len] = 0; 3542 if (strlen(s) <= len) 3543 memcpy(a, s, strlen(s)); 3544 else 3545 strncpy(a, s, len); 3546 return a; 3547 } 3548 3549 char *ls_file(const char *file, int nameonly, char remove_path, char classify) 3550 { 3551 static const char month[12][4] = 3552 {"Jan", "Feb", "Mar", "Apr", "May", "Jun", 3553 "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; 3554 3555 char *permissions; 3556 struct stat s; 3557 struct tm *t; 3558 char *ls_entry; 3559 char *owner, *ownerg; 3560 char *rpowner, *rpownerg; 3561 char *link; 3562 #ifndef LS_NUMERIC_UIDS 3563 struct passwd *pw; 3564 struct group *gr; 3565 #endif 3566 link = NULL; 3567 owner = NULL; 3568 ownerg = NULL; 3569 if (lstat(file, &s) != 0) /* File doesn't exist, or is not readable by user */ 3570 return NULL; 3571 ls_entry = (char *) malloc(312); 3572 memset(ls_entry, 0, 312); 3573 permissions = strdup("----------"); 3574 if (S_ISLNK(s.st_mode)) { 3575 permissions[0] = 'l'; 3576 if (classify) 3577 classify = '@'; 3578 } 3579 else if (S_ISDIR(s.st_mode)) { 3580 permissions[0] = 'd'; 3581 if (classify) 3582 classify = '/'; 3583 } 3584 else if (S_ISBLK(s.st_mode)) 3585 permissions[0] = 'b'; 3586 else if (S_ISCHR(s.st_mode)) 3587 permissions[0] = 'c'; 3588 else if (S_ISFIFO(s.st_mode)) { 3589 permissions[0] = 'p'; 3590 if (classify == 1) 3591 classify = '='; 3592 } 3593 #ifdef S_ISSOCK 3594 else if (S_ISSOCK(s.st_mode)) 3595 permissions[0] = 's'; 3596 #endif 3597 if ((s.st_mode & S_IRUSR) == S_IRUSR) 3598 permissions[1] = 'r'; 3599 if ((s.st_mode & S_IWUSR) == S_IWUSR) 3600 permissions[2] = 'w'; 3601 if ((s.st_mode & S_IXUSR) == S_IXUSR) { 3602 permissions[3] = 'x'; 3603 if (classify == 1) 3604 classify = '*'; 3605 #ifndef HIDE_SETUID 3606 if ((s.st_mode & S_ISUID) == S_ISUID) 3607 permissions[3] = 's'; 3608 #endif 3609 } 3610 #ifndef HIDE_SETUID 3611 else if ((s.st_mode & S_ISUID) == S_ISUID) 3612 permissions[3] = 'S'; 3613 #endif 3614 if ((s.st_mode & S_IRGRP) == S_IRGRP) 3615 permissions[4] = 'r'; 3616 if ((s.st_mode & S_IWGRP) == S_IWGRP) 3617 permissions[5] = 'w'; 3618 if ((s.st_mode & S_IXGRP) == S_IXGRP) { 3619 permissions[6] = 'x'; 3620 if (classify == 1) 3621 classify = '*'; 3622 #ifndef HIDE_SETUID 3623 if ((s.st_mode & S_ISGID) == S_ISGID) 3624 permissions[6] = 's'; 3625 #endif 3626 } 3627 #ifndef HIDE_SETUID 3628 else if ((s.st_mode & S_ISGID) == S_ISGID) 3629 permissions[6] = 'S'; 3630 #endif 3631 if ((s.st_mode & S_IROTH) == S_IROTH) 3632 permissions[7] = 'r'; 3633 if ((s.st_mode & S_IWOTH) == S_IWOTH) 3634 permissions[8] = 'w'; 3635 if ((s.st_mode & S_IXOTH) == S_IXOTH) { 3636 permissions[9] = 'x'; 3637 if (classify == 1) 3638 classify = '*'; 3639 #ifndef HIDE_SETUID 3640 if ((s.st_mode & S_ISVTX) == S_ISVTX) 3641 permissions[9] = 't'; 3642 #endif 3643 } 3644 #ifndef HIDE_SETUID 3645 else if ((s.st_mode & S_ISVTX) == S_ISVTX) 3646 permissions[9] = 'T'; 3647 #endif 3648 t = localtime(&s.st_mtime); 3649 #ifndef LS_NUMERIC_UIDS 3650 #ifdef OTHER_PASSWD 3651 pw = bero_getpwuid(s.st_uid, _path_passwd); 3652 #else 3653 pw = getpwuid(s.st_uid); 3654 #endif 3655 if (pw != NULL) 3656 owner = strdup(pw->pw_name); 3657 gr = getgrgid(s.st_gid); 3658 if (gr != NULL) 3659 ownerg = strdup(gr->gr_name); 3660 #endif 3661 if (owner == NULL) { /* Can't figure out username (or don't want to) */ 3662 if (s.st_uid == 0) 3663 owner = strdup("root"); 3664 else { 3665 owner = (char *) malloc(9); 3666 memset(owner, 0, 9); 3667 #ifdef SOLARIS_2 3668 snprintf(owner, 8, "%lu", s.st_uid); 3669 #else 3670 snprintf(owner, 8, "%u", s.st_uid); 3671 #endif 3672 } 3673 } 3674 if (ownerg == NULL) { /* Can't figure out groupname (or don't want to) */ 3675 if (s.st_gid == 0) 3676 ownerg = strdup("root"); 3677 else { 3678 ownerg = (char *) malloc(9); 3679 memset(ownerg, 0, 9); 3680 #ifdef SOLARIS_2 3681 snprintf(ownerg, 8, "%lu", s.st_gid); 3682 #else 3683 snprintf(ownerg, 8, "%u", s.st_gid); 3684 #endif 3685 } 3686 } 3687 3688 #ifdef HAVE_LSTAT 3689 if (S_ISLNK(s.st_mode)) { 3690 link = (char *) malloc(MAXPATHLEN); 3691 memset(link, 0, MAXPATHLEN); 3692 if (readlink(file, link, MAXPATHLEN) == -1) { 3693 free(link); 3694 link = NULL; 3695 } 3696 } 3697 #endif 3698 3699 if (remove_path != 0 && strchr(file, '/')) 3700 file = strrchr(file, '/') + 1; 3701 3702 rpowner = rpad(owner, 8); 3703 rpownerg = rpad(ownerg, 8); 3704 3705 #ifdef SOLARIS_2 3706 #define N_FORMAT "lu" 3707 #else 3708 #if defined(__FreeBSD__) || defined(__bsdi__) 3709 #define N_FORMAT "u" 3710 #else 3711 #define N_FORMAT "u" 3712 #endif 3713 #endif 3714 3715 if (nameonly) { 3716 sprintf(ls_entry, "%s", file); 3717 if (link != NULL) 3718 free(link); 3719 } 3720 else { 3721 if ((time(NULL) - s.st_mtime) > 6307200) { /* File is older than 6 months */ 3722 if (link == NULL) 3723 snprintf(ls_entry, 311, "%s %3" N_FORMAT " %s %s %8" L_FORMAT " %s %2u %5u %s", permissions, s.st_nlink, rpowner, rpownerg, s.st_size, month[t->tm_mon], t->tm_mday, 1900 + t->tm_year, file); 3724 else { 3725 snprintf(ls_entry, 311, "%s %3" N_FORMAT " %s %s %8" L_FORMAT " %s %2u %5u %s -> %s", permissions, s.st_nlink, rpowner, rpownerg, s.st_size, month[t->tm_mon], t->tm_mday, 1900 + t->tm_year, file, link); 3726 free(link); 3727 } 3728 } 3729 else if (link == NULL) 3730 snprintf(ls_entry, 311, "%s %3" N_FORMAT " %s %s %8" L_FORMAT " %s %2u %02u:%02u %s", permissions, s.st_nlink, rpowner, rpownerg, s.st_size, month[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, file); 3731 else { 3732 snprintf(ls_entry, 311, "%s %3" N_FORMAT " %s %s %8" L_FORMAT " %s %2u %02u:%02u %s -> %s", permissions, s.st_nlink, rpowner, rpownerg, s.st_size, month[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, file, link); 3733 free(link); 3734 } 3735 } 3736 free(rpowner); 3737 free(rpownerg); 3738 free(owner); 3739 free(ownerg); 3740 if (classify > 1) 3741 sprintf(ls_entry + strlen(ls_entry), "%c", classify); 3742 strcat(ls_entry, "\r\n"); 3743 free(permissions); 3744 return ls_entry; 3745 } 3746 3747 void ls_dir(char *d, char ls_a, char ls_F, char ls_l, char ls_R, char omit_total, FILE *out) 3748 { 3749 int total; 3750 char *realdir; /* fixed up value to pass to glob() */ 3751 char **subdirs; /* Subdirs to be scanned for ls -R */ 3752 int numSubdirs = 0; 3753 glob_t g; 3754 char isDir; /* 0: d is a file; 1: d is some files; 2: d is dir */ 3755 struct stat s; 3756 char *dirlist; 3757 unsigned long dl_size, dl_used; 3758 char *c; 3759 char *lsentry; 3760 int i; 3761 #ifndef GLOB_PERIOD 3762 char *dperiod; 3763 #endif 3764 3765 isDir = 0; 3766 realdir = (char *) malloc(strlen(d) + 3); 3767 memset(realdir, 0, strlen(d) + 3); 3768 strcpy(realdir, d); 3769 if (strcmp(realdir, ".") == 0) 3770 realdir[0] = '*'; 3771 if (strcmp(realdir + strlen(realdir) - 2, "/.") == 0) 3772 realdir[strlen(realdir) - 1] = '*'; 3773 if (realdir[strlen(realdir) - 1] == '/') 3774 strcat(realdir, "*"); 3775 if (strchr(realdir, '*') || strchr(realdir, '?')) 3776 isDir = 1; 3777 if (strcmp(realdir, "*") == 0 || strcmp(realdir + strlen(realdir) - 2, "/*") == 0) 3778 isDir = 2; 3779 else { 3780 if (lstat(realdir, &s) == 0) { 3781 if (S_ISDIR(s.st_mode)) { 3782 strcat(realdir, "/*"); 3783 isDir = 2; 3784 } 3785 } 3786 } 3787 3788 if (isDir == 0) { 3789 if (ls_l) { 3790 lsentry = ls_file(realdir, 0, 0, ls_F); 3791 if (lsentry != NULL) { 3792 if (draconian_FILE != NULL) { 3793 (void) signal(SIGALRM, draconian_alarm_signal); 3794 alarm(timeout_data); 3795 #if defined(USE_GSS) 3796 sec_fprintf(out, "%s", lsentry); 3797 #else 3798 fputs(lsentry, out); 3799 #endif /* defined(USE_GSS) */ 3800 (void) signal(SIGALRM, SIG_DFL); 3801 } 3802 free(lsentry); 3803 } 3804 } 3805 else { 3806 if (draconian_FILE != NULL) { 3807 (void) signal(SIGALRM, draconian_alarm_signal); 3808 alarm(timeout_data); 3809 #if defined(USE_GSS) 3810 sec_fprintf(out, "%s", realdir); 3811 #else 3812 fputs(realdir, out); 3813 #endif /* defined(USE_GSS) */ 3814 (void) signal(SIGALRM, SIG_DFL); 3815 } 3816 } 3817 free(realdir); 3818 } 3819 else { 3820 if (ls_R) { 3821 numSubdirs = 0; 3822 subdirs = (char **) malloc(200 * sizeof(char *)); 3823 memset(subdirs, 0, 200 * sizeof(char *)); 3824 } 3825 3826 dl_size = 65536; 3827 dirlist = (char *) malloc(65536); 3828 memset(dirlist, 0, 65536); 3829 dl_used = 0; 3830 3831 total = 0; 3832 memset(&g, 0, sizeof(g)); 3833 if (ls_a) { 3834 #ifdef GLOB_PERIOD 3835 if (glob(realdir, GLOB_ERR | GLOB_PERIOD, NULL, &g) != 0) 3836 g.gl_pathc = 0; 3837 #else 3838 dperiod = (char *) malloc(strlen(realdir) + 2); 3839 memset(dperiod, 0, strlen(realdir) + 2); 3840 strcpy(dperiod, "."); 3841 strcat(dperiod, realdir); 3842 if (glob(dperiod, GLOB_ERR, NULL, &g) != 0) 3843 g.gl_pathc = 0; 3844 glob(realdir, GLOB_ERR | GLOB_APPEND, NULL, &g); 3845 free(dperiod); 3846 #endif 3847 } 3848 else if (glob(realdir, GLOB_ERR, NULL, &g) != 0) 3849 g.gl_pathc = 0; 3850 free(realdir); 3851 for (i = 0; i < g.gl_pathc; i++) { 3852 c = g.gl_pathv[i]; 3853 if (lstat(c, &s) != -1) { 3854 if (ls_l) { 3855 total += s.st_blocks; 3856 lsentry = ls_file(c, 0, 1, ls_F); 3857 if (lsentry != NULL) { 3858 /* This can actually happen even though the lstat() worked - 3859 if someone deletes the file between the lstat() and ls_file() 3860 calls. Unlikely, but better safe than sorry... */ 3861 int flag = snprintf(dirlist + dl_used, dl_size - dl_used, "%s", lsentry); 3862 dl_used += (flag == -1 ? dl_size - dl_used : flag); 3863 free(lsentry); 3864 } 3865 } 3866 else { 3867 int flag; 3868 lsentry = ls_file(c, 1, 1, ls_F); 3869 if (lsentry != NULL) { 3870 flag = snprintf(dirlist + dl_used, dl_size - dl_used, "%s", lsentry); 3871 dl_used += (flag == -1 ? dl_size - dl_used : flag); 3872 free(lsentry); 3873 } 3874 } 3875 if ((ls_R != 0) && (S_ISDIR(s.st_mode)) 3876 && (strcmp(c, "..") != 0) && (strcmp(c, ".") != 0) 3877 && !(strlen(c) > 3 && strcmp(c + strlen(c) - 3, "/..") == 0) 3878 && !(strlen(c) > 2 && strcmp(c + strlen(c) - 2, "/.") == 0)) { 3879 subdirs[numSubdirs++] = strdup(c); 3880 if ((numSubdirs % 200) == 0) 3881 subdirs = (char **) realloc(subdirs, (numSubdirs + 200) * sizeof(char *)); 3882 } 3883 } 3884 if (dl_used + 512 >= dl_size) { 3885 dl_size += 65536; 3886 dirlist = (char *) realloc(dirlist, dl_size); 3887 } 3888 } 3889 globfree(&g); 3890 if (ls_l && isDir == 2 && omit_total == 0) { 3891 if (draconian_FILE != NULL) { 3892 (void) signal(SIGALRM, draconian_alarm_signal); 3893 alarm(timeout_data); 3894 #if defined(USE_GSS) 3895 sec_fprintf(out, "total %u\r\n", total); 3896 #else 3897 fprintf(out, "total %u\r\n", total); 3898 #endif /* defined(USE_GSS) */ 3899 } 3900 } 3901 if (draconian_FILE != NULL) { 3902 (void) signal(SIGALRM, draconian_alarm_signal); 3903 alarm(timeout_data); 3904 #if defined(USE_GSS) 3905 sec_fprintf(out, "%s", dirlist); 3906 #else 3907 fputs(dirlist, out); 3908 #endif /* defined(USE_GSS) */ 3909 } 3910 free(dirlist); 3911 if (ls_R) { 3912 for (i = 0; i < numSubdirs; i++) { 3913 if (draconian_FILE != NULL) { 3914 (void) signal(SIGALRM, draconian_alarm_signal); 3915 alarm(timeout_data); 3916 #if defined(USE_GSS) 3917 sec_fprintf(out, "\r\n%s:\r\n", subdirs[i]); 3918 #else 3919 fprintf(out, "\r\n%s:\r\n", subdirs[i]); 3920 #endif /* defined(USE_GSS) */ 3921 ls_dir(subdirs[i], ls_a, ls_F, ls_l, ls_R, 0, out); 3922 } 3923 free(subdirs[i]); 3924 } 3925 free(subdirs); 3926 } 3927 } 3928 } 3929 3930 void ls(char *file, char nlst) 3931 { 3932 FILE *out; 3933 char free_file = 0; 3934 char ls_l = 0, ls_a = 0, ls_R = 0, ls_F = 0; 3935 3936 if (nlst == 0) 3937 ls_l = 1; /* LIST defaults to ls -l */ 3938 if (file == NULL) { 3939 file = strdup("."); 3940 free_file = 1; 3941 } 3942 if (strcmp(file, "*") == 0) 3943 file[0] = '.'; 3944 3945 if (file[0] == '-') { /* options... */ 3946 if (strchr(file, ' ') == 0) { 3947 if (strchr(file, 'l')) 3948 ls_l = 1; 3949 if (strchr(file, 'a')) 3950 ls_a = 1; 3951 if (strchr(file, 'R')) 3952 ls_R = 1; 3953 if (strchr(file, 'F')) 3954 ls_F = 1; 3955 file = strdup("."); 3956 free_file = 1; 3957 } 3958 else { 3959 if (strchr(file, 'l') != NULL && strchr(file, 'l') < strchr(file, ' ')) 3960 ls_l = 1; 3961 if (strchr(file, 'a') != NULL && strchr(file, 'a') < strchr(file, ' ')) 3962 ls_a = 1; 3963 if (strchr(file, 'R') != NULL && strchr(file, 'R') < strchr(file, ' ')) 3964 ls_R = 1; 3965 if (strchr(file, 'F') != NULL && strchr(file, 'F') < strchr(file, ' ')) 3966 ls_F = 1; 3967 file = strchr(file, ' '); 3968 } 3969 } 3970 while (file[0] == ' ') /* ignore additional whitespaces between parameters */ 3971 file++; 3972 if (strlen(file) == 0) { 3973 file = strdup("."); 3974 free_file = 1; 3975 } 3976 3977 out = dataconn("directory listing", -1, "w"); 3978 draconian_FILE = out; 3979 3980 transflag++; 3981 3982 fixpath(file); 3983 if (file[0] == '\0') { 3984 if (free_file != 0) 3985 free(file); 3986 file = strdup("."); 3987 free_file = 1; 3988 } 3989 3990 ls_dir(file, ls_a, ls_F, ls_l, ls_R, 0, out); 3991 data = -1; 3992 pdata = -1; 3993 if (draconian_FILE != NULL) { 3994 (void) signal(SIGALRM, draconian_alarm_signal); 3995 alarm(timeout_data); 3996 #if defined(USE_GSS) 3997 if (sec_fflush(out) < 0) { 3998 draconian_FILE = NULL; 3999 alarm(0); 4000 transflag = 0; 4001 perror_reply(550, "Data connection"); 4002 fclose(out); 4003 goto ls_done; 4004 } 4005 #else 4006 fflush(out); 4007 #endif /* defined(USE_GSS) */ 4008 } 4009 if (draconian_FILE != NULL) { 4010 (void) signal(SIGALRM, draconian_alarm_signal); 4011 alarm(timeout_data); 4012 socket_flush_wait(out); 4013 } 4014 if (draconian_FILE != NULL) { 4015 (void) signal(SIGALRM, draconian_alarm_signal); 4016 alarm(timeout_data); 4017 fclose(out); 4018 draconian_FILE = NULL; 4019 } 4020 alarm(0); 4021 transflag = 0; 4022 reply(226, "Transfer complete."); 4023 ls_done: 4024 if (free_file != 0) 4025 free(file); 4026 } 4027 #endif /* INTERNAL_LS */ 4028 4029 void retrieve(char *cmd, char *name) 4030 { 4031 FILE *fin = NULL, *dout; 4032 struct stat st, junk; 4033 int (*closefunc) () = NULL; 4034 int options = 0; 4035 int ThisRetrieveIsData = retrieve_is_data; 4036 time_t start_time = time(NULL); 4037 char *logname; 4038 char namebuf[MAXPATHLEN]; 4039 char fnbuf[MAXPATHLEN]; 4040 static int TransferComplete; /* static as retrieve can call itself */ 4041 struct convert *cptr; 4042 char realname[MAXPATHLEN]; 4043 int stat_ret = -1; 4044 size_t buffersize; 4045 4046 TransferComplete = 0; 4047 wu_realpath(name, realname, chroot_path); 4048 4049 if (cmd == NULL && (stat_ret = stat(name, &st)) == 0) 4050 /* there isn't a command and the file exists */ 4051 if (use_accessfile && checknoretrieve(name)) { /* see above. _H */ 4052 if (log_security) 4053 if (anonymous) 4054 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to download %s (noretrieve)", 4055 guestpw, remoteident, realname); 4056 else 4057 syslog(LOG_NOTICE, "%s of %s tried to download %s (noretrieve)", 4058 pw->pw_name, remoteident, realname); 4059 return; 4060 } 4061 4062 #ifdef TRANSFER_COUNT 4063 #ifdef TRANSFER_LIMIT 4064 if (retrieve_is_data) 4065 if (((file_limit_data_out > 0) && (file_count_out >= file_limit_data_out)) 4066 || ((file_limit_data_total > 0) && (file_count_total >= file_limit_data_total)) 4067 || ((data_limit_data_out > 0) && (data_count_out >= data_limit_data_out)) 4068 || ((data_limit_data_total > 0) && (data_count_total >= data_limit_data_total))) { 4069 if (log_security) 4070 if (anonymous) 4071 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to retrieve %s (Transfer limits exceeded)", 4072 guestpw, remoteident, realname); 4073 else 4074 syslog(LOG_NOTICE, "%s of %s tried to retrieve %s (Transfer limits exceeded)", 4075 pw->pw_name, remoteident, realname); 4076 reply(553, "Permission denied on server. (Transfer limits exceeded)"); 4077 return; 4078 } 4079 if (((file_limit_raw_out > 0) && (xfer_count_out >= file_limit_raw_out)) 4080 || ((file_limit_raw_total > 0) && (xfer_count_total >= file_limit_raw_total)) 4081 || ((data_limit_raw_out > 0) && (byte_count_out >= data_limit_raw_out)) 4082 || ((data_limit_raw_total > 0) && (byte_count_total >= data_limit_raw_total))) { 4083 if (log_security) 4084 if (anonymous) 4085 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to retrieve %s (Transfer limits exceeded)", 4086 guestpw, remoteident, realname); 4087 else 4088 syslog(LOG_NOTICE, "%s of %s tried to retrieve %s (Transfer limits exceeded)", 4089 pw->pw_name, remoteident, realname); 4090 reply(553, "Permission denied on server. (Transfer limits exceeded)"); 4091 return; 4092 } 4093 #ifdef RATIO 4094 if (retrieve_is_data && (upload_download_rate > 0) ) 4095 if( freefile = is_downloadfree(name) ) { 4096 syslog(LOG_INFO, "%s is download free.", name ); 4097 } 4098 else { 4099 if ((cmd == NULL) && ((data_count_in * upload_download_rate) < (data_count_out - total_free_dl))) { 4100 reply(550, "%s: Upload/Download ratio exceeded", name); 4101 goto done; 4102 } 4103 } 4104 #endif /* RATIO */ 4105 #endif 4106 #endif 4107 4108 logname = (char *) NULL; 4109 if (cmd == NULL && stat_ret != 0) { /* file does not exist */ 4110 char *ptr; 4111 4112 for (cptr = cvtptr; cptr != NULL; cptr = cptr->next) { 4113 if (!(mangleopts & O_COMPRESS) && (cptr->options & O_COMPRESS)) 4114 continue; 4115 if (!(mangleopts & O_UNCOMPRESS) && (cptr->options & O_UNCOMPRESS)) 4116 continue; 4117 if (!(mangleopts & O_TAR) && (cptr->options & O_TAR)) 4118 continue; 4119 4120 if ((cptr->stripfix) && (cptr->postfix)) { 4121 int pfxlen = strlen(cptr->postfix); 4122 int sfxlen = strlen(cptr->stripfix); 4123 int namelen = strlen(name); 4124 4125 if (namelen <= pfxlen) 4126 continue; 4127 if (((namelen - pfxlen + sfxlen) >= sizeof(fnbuf)) || 4128 (namelen >= sizeof(fnbuf))) 4129 continue; 4130 4131 (void) strcpy(fnbuf, name); 4132 if (strcmp(fnbuf + namelen - pfxlen, cptr->postfix)) 4133 continue; 4134 *(fnbuf + namelen - pfxlen) = '\0'; 4135 (void) strcat(fnbuf, cptr->stripfix); 4136 if (stat(fnbuf, &st) != 0) 4137 continue; 4138 } 4139 else if (cptr->postfix) { 4140 int pfxlen = strlen(cptr->postfix); 4141 int namelen = strlen(name); 4142 4143 if ((namelen <= pfxlen) || (namelen >= sizeof(fnbuf))) 4144 continue; 4145 (void) strcpy(fnbuf, name); 4146 if (strcmp(fnbuf + namelen - pfxlen, cptr->postfix)) 4147 continue; 4148 *(fnbuf + namelen - pfxlen) = (char) NULL; 4149 if (stat(fnbuf, &st) != 0) 4150 continue; 4151 } 4152 else if (cptr->stripfix) { 4153 if (strlen(name) + strlen(cptr->stripfix) >= sizeof(fnbuf)) 4154 continue; 4155 (void) strcpy(fnbuf, name); 4156 (void) strcat(fnbuf, cptr->stripfix); 4157 if (stat(fnbuf, &st) != 0) 4158 continue; 4159 } 4160 else { 4161 continue; 4162 } 4163 4164 if (S_ISDIR(st.st_mode)) { 4165 if (!cptr->types || !(cptr->types & T_DIR)) { 4166 reply(550, "Cannot %s directories.", cptr->name); 4167 return; 4168 } 4169 if ((cptr->options & O_TAR)) { 4170 strcpy(namebuf, fnbuf); 4171 if (strlcat(namebuf, "/.notar", sizeof(namebuf)) >= 4172 sizeof(namebuf)) 4173 continue; 4174 if (stat(namebuf, &junk) == 0) { 4175 if (log_security) 4176 if (anonymous) 4177 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to tar %s (.notar)", 4178 guestpw, remoteident, realname); 4179 else 4180 syslog(LOG_NOTICE, "%s of %s tried to tar %s (.notar)", 4181 pw->pw_name, remoteident, realname); 4182 reply(550, "Sorry, you may not TAR that directory."); 4183 return; 4184 } 4185 } 4186 } 4187 /* XXX: checknoretrieve() test is weak in that if I can't get /etc/passwd 4188 but I can tar /etc or /, I still win. Be careful out there... _H* 4189 but you could put .notar in / and /etc and stop that ! */ 4190 if (use_accessfile && checknoretrieve(fnbuf)) { 4191 if (log_security) 4192 if (anonymous) 4193 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to download %s (noretrieve)", 4194 guestpw, remoteident, realname); 4195 else 4196 syslog(LOG_NOTICE, "%s of %s tried to download %s (noretrieve)", 4197 pw->pw_name, remoteident, realname); 4198 return; 4199 } 4200 4201 if (S_ISREG(st.st_mode) && (!cptr->types || (cptr->types & T_REG) == 0)) { 4202 reply(550, "Cannot %s plain files.", cptr->name); 4203 return; 4204 } 4205 if (S_ISREG(st.st_mode) != 0 && S_ISDIR(st.st_mode) != 0) { 4206 reply(550, "Cannot %s special files.", cptr->name); 4207 return; 4208 } 4209 if ((!cptr->types || !(cptr->types & T_ASCII)) && deny_badasciixfer(550, "")) 4210 return; 4211 4212 logname = &fnbuf[0]; 4213 options |= cptr->options; 4214 4215 strcpy(namebuf, cptr->external_cmd); 4216 if ((ptr = strchr(namebuf, ' ')) != NULL) 4217 *ptr = '\0'; 4218 if (stat(namebuf, &junk) != 0) { 4219 syslog(LOG_ERR, "external command %s not found", namebuf); 4220 reply(550, 4221 "Local error: conversion program not found. Cannot %s file.", 4222 cptr->name); 4223 return; 4224 } 4225 (void) retrieve(cptr->external_cmd, logname); 4226 4227 goto logresults; /* transfer of converted file completed */ 4228 } 4229 } 4230 4231 if (cmd == NULL) { /* no command */ 4232 fin = fopen(name, "r"), closefunc = fclose; 4233 st.st_size = 0; 4234 } 4235 else { /* run command */ 4236 static char line[BUFSIZ]; 4237 4238 (void) snprintf(line, sizeof(line), cmd, name), name = line; 4239 fin = ftpd_popen(line, "r", 1), closefunc = ftpd_pclose; 4240 st.st_size = -1; 4241 #ifdef HAVE_ST_BLKSIZE 4242 st.st_blksize = BUFSIZ; 4243 #endif 4244 } 4245 if (fin == NULL) { 4246 if (errno != 0) 4247 perror_reply(550, name); 4248 if ((errno == EACCES) || (errno == EPERM)) 4249 if (log_security) 4250 if (anonymous) 4251 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to download %s (file permissions)", 4252 guestpw, remoteident, realname); 4253 else 4254 syslog(LOG_NOTICE, "%s of %s tried to download %s (file permissions)", 4255 pw->pw_name, remoteident, realname); 4256 return; 4257 } 4258 if (cmd == NULL && 4259 (fstat(fileno(fin), &st) < 0 || (st.st_mode & S_IFMT) != S_IFREG)) { 4260 reply(550, "%s: not a plain file.", name); 4261 goto done; 4262 } 4263 if (restart_point) { 4264 if (type == TYPE_A) { 4265 register int c; 4266 off_t i; 4267 4268 i = 0; 4269 while (i++ < restart_point) { 4270 if ((c = getc(fin)) == EOF) { 4271 perror_reply(550, name); 4272 goto done; 4273 } 4274 if (c == '\n') 4275 i++; 4276 } 4277 } 4278 else if (lseek(fileno(fin), restart_point, SEEK_SET) < 0) { 4279 perror_reply(550, name); 4280 goto done; 4281 } 4282 } 4283 4284 dout = dataconn(name, st.st_size, "w"); 4285 if (dout == NULL) 4286 goto done; 4287 4288 if (sendbufsz > 0) { 4289 buffersize = sendbufsz; 4290 } 4291 else { 4292 #ifdef BUFFER_SIZE 4293 buffersize = BUFFER_SIZE; 4294 #elif HAVE_ST_BLKSIZE 4295 buffersize = st.st_blksize * 2; 4296 #else 4297 buffersize = BUFSIZ * 16; 4298 #endif 4299 } 4300 4301 #ifdef THROUGHPUT 4302 TransferComplete = send_data(name, fin, dout, buffersize); 4303 #else 4304 TransferComplete = send_data(fin, dout, buffersize); 4305 #endif 4306 #ifdef SIGPIPE 4307 (void) signal(SIGPIPE, SIG_IGN); 4308 #endif 4309 (void) fclose(dout); 4310 #ifdef SIGPIPE 4311 (void) signal(SIGPIPE, lostconn); 4312 #endif 4313 4314 logresults: 4315 if (ThisRetrieveIsData) 4316 fb_realpath((logname != NULL) ? logname : name, LastFileTransferred); 4317 4318 if (log_outbound_xfers && (xferlog || syslogmsg) && (cmd == NULL)) { 4319 char msg[MAXXFERSTRLEN]; /* see extensions.h */ 4320 int xfertime = time(NULL) - start_time; 4321 size_t msglen; 4322 4323 if (!xfertime) 4324 xfertime++; 4325 4326 /* Gather transfer statistics */ 4327 xfervalues.filename = (logname != NULL) ? logname : name; 4328 xfervalues.filesize = st.st_size; 4329 xfervalues.transfer_bytes = byte_count; 4330 xfervalues.transfer_direction = 'o'; 4331 xfervalues.transfer_type = (type == TYPE_A) ? 'a' : 'b'; 4332 xfervalues.transfer_time = xfertime; 4333 xfervalues.restart_offset = restart_point; 4334 strlcpy(xfervalues.special_action, opt_string(options), MAXSPACTCHARS); 4335 xfervalues.access_mode = anonymous ? 'a' : (guest ? 'g' : 'r'); 4336 xfervalues.auth = authenticated; 4337 xfervalues.completion = TransferComplete ? 'c' : 'i'; 4338 4339 xferdone = 1; 4340 msg_massage(xferlog_format, msg, sizeof(msg)); 4341 xferdone = 0; 4342 4343 /* Ensure msg always ends with '\n' */ 4344 msglen = strlen(msg); 4345 if (msglen == sizeof(msg) - 1) { 4346 msg[sizeof(msg) - 2] = '\n'; 4347 msg[sizeof(msg) - 1] = '\0'; 4348 } 4349 else { 4350 msg[msglen] = '\n'; 4351 msg[msglen + 1] = '\0'; 4352 } 4353 4354 if (syslogmsg != 1) 4355 write(xferlog, msg, strlen(msg)); 4356 if (syslogmsg != 0) { 4357 char *msgp = msg; 4358 /* 4359 * To preserve the behavior when the xferlog format was fixed, skip 4360 * over the time string if the message starts with the local time. 4361 */ 4362 if (strncmp(xferlog_format, "%T ", 3) == 0) 4363 msgp += 25; 4364 syslog(LOG_INFO, "xferlog (send): %s", msgp); 4365 } 4366 } 4367 data = -1; 4368 pdata = -1; 4369 done: 4370 if (closefunc) 4371 (*closefunc) (fin); 4372 } 4373 4374 void store(char *name, char *mode, int unique) 4375 { 4376 FILE *fout, *din; 4377 struct stat st; 4378 int TransferIncomplete = 1; 4379 char *gunique(char *local); 4380 time_t start_time = time(NULL); 4381 4382 struct aclmember *entry = NULL; 4383 4384 int fdout; 4385 char realname[MAXPATHLEN]; 4386 4387 #ifdef OVERWRITE 4388 int overwrite = 1; 4389 int exists = 0; 4390 4391 #endif /* OVERWRITE */ 4392 4393 int open_flags = 0; 4394 4395 #ifdef UPLOAD 4396 mode_t oldmask; 4397 uid_t uid; 4398 gid_t gid; 4399 uid_t oldid; 4400 int f_mode = -1, match_value = -1; 4401 int valid = 0; 4402 int ret, serrno; 4403 open_flags = (O_RDWR | O_CREAT | 4404 ((mode != NULL && *mode == 'a') ? O_APPEND : O_TRUNC)); 4405 #endif /* UPLOAD */ 4406 4407 wu_realpath(name, realname, chroot_path); 4408 4409 #ifdef TRANSFER_COUNT 4410 #ifdef TRANSFER_LIMIT 4411 if (((file_limit_data_in > 0) && (file_count_in >= file_limit_data_in)) 4412 || ((file_limit_data_total > 0) && (file_count_total >= file_limit_data_total)) 4413 || ((data_limit_data_in > 0) && (data_count_in >= data_limit_data_in)) 4414 || ((data_limit_data_total > 0) && (data_count_total >= data_limit_data_total))) { 4415 if (log_security) 4416 if (anonymous) 4417 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (Transfer limits exceeded)", 4418 guestpw, remoteident, realname); 4419 else 4420 syslog(LOG_NOTICE, "%s of %s tried to upload %s (Transfer limits exceeded)", 4421 pw->pw_name, remoteident, realname); 4422 reply(553, "Permission denied on server. (Transfer limits exceeded)"); 4423 return; 4424 } 4425 if (((file_limit_raw_in > 0) && (xfer_count_in >= file_limit_raw_in)) 4426 || ((file_limit_raw_total > 0) && (xfer_count_total >= file_limit_raw_total)) 4427 || ((data_limit_raw_in > 0) && (byte_count_in >= data_limit_raw_in)) 4428 || ((data_limit_raw_total > 0) && (byte_count_total >= data_limit_raw_total))) { 4429 if (log_security) 4430 if (anonymous) 4431 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (Transfer limits exceeded)", 4432 guestpw, remoteident, realname); 4433 else 4434 syslog(LOG_NOTICE, "%s of %s tried to upload %s (Transfer limits exceeded)", 4435 pw->pw_name, remoteident, realname); 4436 reply(553, "Permission denied on server. (Transfer limits exceeded)"); 4437 return; 4438 } 4439 #endif 4440 #endif 4441 4442 if (unique && stat(name, &st) == 0 && 4443 (name = gunique(name)) == NULL) 4444 return; 4445 4446 /* 4447 * check the filename, is it legal? 4448 */ 4449 if ((fn_check(name)) <= 0) { 4450 if (log_security) 4451 if (anonymous) 4452 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload \"%s\" (path-filter)", 4453 guestpw, remoteident, realname); 4454 else 4455 syslog(LOG_NOTICE, "%s of %s tried to upload \"%s\" (path-filter)", 4456 pw->pw_name, remoteident, realname); 4457 return; 4458 } 4459 4460 #ifdef OVERWRITE 4461 /* if overwrite permission denied and file exists... then deny the user 4462 * permission to write the file. */ 4463 while (getaclentry("overwrite", &entry) && ARG0 && ARG1 != NULL) { 4464 if (type_match(ARG1)) 4465 if (strcasecmp(ARG0, "yes") != 0) { 4466 overwrite = 0; 4467 open_flags |= O_EXCL; 4468 } 4469 } 4470 4471 #ifdef PARANOID 4472 overwrite = 0; 4473 #endif 4474 if (!stat(name, &st)) 4475 exists = 1; 4476 4477 if (!overwrite && exists) { 4478 if (log_security) 4479 if (anonymous) 4480 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to overwrite %s", 4481 guestpw, remoteident, realname); 4482 else 4483 syslog(LOG_NOTICE, "%s of %s tried to overwrite %s", 4484 pw->pw_name, remoteident, realname); 4485 reply(553, "%s: Permission denied on server. (Overwrite)", name); 4486 return; 4487 } 4488 #endif /* OVERWRITE */ 4489 4490 #ifdef UPLOAD 4491 if ((match_value = upl_check(name, &uid, &gid, &f_mode, &valid)) < 0) { 4492 if (log_security) 4493 if (anonymous) 4494 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (upload denied)", 4495 guestpw, remoteident, realname); 4496 else 4497 syslog(LOG_NOTICE, "%s of %s tried to upload %s (upload denied)", 4498 pw->pw_name, remoteident, realname); 4499 return; 4500 } 4501 4502 /* do not truncate the file if we are restarting */ 4503 if (restart_point) 4504 open_flags &= ~O_TRUNC; 4505 4506 /* if the user has an explicit new file mode, than open the file using 4507 * that mode. We must take care to not let the umask affect the file 4508 * mode. 4509 * 4510 * else open the file and let the default umask determine the file mode. */ 4511 if (f_mode >= 0) { 4512 oldmask = umask(0000); 4513 fdout = open(name, open_flags, f_mode); 4514 umask(oldmask); 4515 } 4516 else 4517 fdout = open(name, open_flags, 0666); 4518 4519 if (fdout < 0) { 4520 if (log_security) 4521 if (anonymous) 4522 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (permissions)", 4523 guestpw, remoteident, realname); 4524 else 4525 syslog(LOG_NOTICE, "%s of %s tried to upload %s (permissions)", 4526 pw->pw_name, remoteident, realname); 4527 perror_reply(553, name); 4528 return; 4529 } 4530 /* if we have a uid and gid, then use them. */ 4531 4532 #ifdef OVERWRITE 4533 if (!exists) 4534 #endif 4535 if (valid > 0) { 4536 oldid = geteuid(); 4537 if (uid != 0) 4538 (void) seteuid((uid_t) uid); 4539 if ((uid == 0) || ((fchown(fdout, uid, gid)) < 0)) { 4540 chown_priv_on(0); 4541 ret = fchown(fdout, uid, gid); 4542 serrno = errno; 4543 chown_priv_off(oldid); 4544 if (ret < 0) { 4545 errno = serrno; 4546 perror_reply(550, "fchown"); 4547 return; 4548 } 4549 } 4550 else 4551 (void) seteuid(oldid); 4552 } 4553 #endif /* UPLOAD */ 4554 4555 if (restart_point && (open_flags & O_APPEND) == 0) 4556 mode = "r+"; 4557 4558 #ifdef UPLOAD 4559 fout = fdopen(fdout, mode); 4560 #else 4561 fout = fopen(name, mode); 4562 #endif /* UPLOAD */ 4563 4564 if (fout == NULL) { 4565 if (log_security) 4566 if (anonymous) 4567 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to upload %s (permissions)", 4568 guestpw, remoteident, realname); 4569 else 4570 syslog(LOG_NOTICE, "%s of %s tried to upload %s (permissions)", 4571 pw->pw_name, remoteident, realname); 4572 perror_reply(553, name); 4573 return; 4574 } 4575 if (restart_point && (open_flags & O_APPEND) == 0) { 4576 if (type == TYPE_A) { 4577 register int c; 4578 off_t i; 4579 4580 i = 0; 4581 while (i++ < restart_point) { 4582 if ((c = getc(fout)) == EOF) { 4583 perror_reply(550, name); 4584 goto done; 4585 } 4586 if (c == '\n') 4587 i++; 4588 } 4589 /* We must do this seek to "current" position because we are 4590 * changing from reading to writing. */ 4591 #if _FILE_OFFSET_BITS == 64 4592 if (fseeko(fout, 0L, SEEK_CUR) < 0) { 4593 #else 4594 if (fseek(fout, 0L, SEEK_CUR) < 0) { 4595 #endif 4596 perror_reply(550, name); 4597 goto done; 4598 } 4599 } 4600 else if (lseek(fileno(fout), restart_point, SEEK_SET) < 0) { 4601 perror_reply(550, name); 4602 goto done; 4603 } 4604 } 4605 din = dataconn(name, (off_t) - 1, "r"); 4606 if (din == NULL) 4607 goto done; 4608 TransferIncomplete = receive_data(din, fout); 4609 4610 if (fstat(fileno(fout), &st) != 0) { 4611 /* shouldn't fail, but just in case */ 4612 st.st_size = -1; 4613 } 4614 (void) fclose(din); 4615 if (TransferIncomplete == 0) { 4616 if (unique) 4617 reply(226, "Transfer complete (unique file name:%s).", name); 4618 else 4619 reply(226, "Transfer complete."); 4620 } 4621 4622 fb_realpath(name, LastFileTransferred); 4623 4624 #ifdef MAIL_ADMIN 4625 if (anonymous && incmails > 0) { 4626 FILE *sck = NULL; 4627 4628 unsigned char temp = 0, temp2 = 0; 4629 char pathname[MAXPATHLEN]; 4630 while ((temp < mailservers) && (sck == NULL)) 4631 sck = SockOpen(mailserver[temp++], 25); 4632 if (sck == NULL) { 4633 syslog(LOG_ERR, "Can't connect to a mailserver."); 4634 goto mailfail; 4635 } 4636 if (Reply(sck) != 220) { 4637 syslog(LOG_ERR, "Mailserver failed to initiate contact."); 4638 goto mailfail; 4639 } 4640 if (Send(sck, "HELO localhost\r\n") != 250) { 4641 syslog(LOG_ERR, "Mailserver doesn't understand HELO."); 4642 goto mailfail; 4643 } 4644 if (Send(sck, "MAIL FROM: <%s>\r\n", email(mailfrom)) != 250) { 4645 syslog(LOG_ERR, "Mailserver didn't accept MAIL FROM."); 4646 goto mailfail; 4647 } 4648 for (temp = 0; temp < incmails; temp++) { 4649 if (Send(sck, "RCPT TO: <%s>\r\n", email(incmail[temp])) == 250) 4650 temp2++; 4651 } 4652 if (temp2 == 0) { 4653 syslog(LOG_ERR, "Mailserver didn't accept any RCPT TO."); 4654 goto mailfail; 4655 } 4656 if (Send(sck, "DATA\r\n") != 354) { 4657 syslog(LOG_ERR, "Mailserver didn't accept DATA."); 4658 goto mailfail; 4659 } 4660 SockPrintf(sck, "From: wu-ftpd <%s>\r\n", mailfrom); 4661 SockPrintf(sck, "Subject: New file uploaded: %s\r\n\r\n", name); 4662 fb_realpath(name, pathname); 4663 SockPrintf(sck, "%s uploaded %s from %s.\r\nFile size is %" L_FORMAT ".\r\nPlease move the file where it belongs.\r\n", guestpw, pathname, remotehost, st.st_size); 4664 if (Send(sck, ".\r\n") != 250) 4665 syslog(LOG_ERR, "Message rejected by mailserver."); 4666 if (Send(sck, "QUIT\r\n") != 221) 4667 syslog(LOG_ERR, "Mailserver didn't accept QUIT."); 4668 mailfail: 4669 if (sck != NULL) 4670 fclose(sck); 4671 } 4672 #endif /* MAIL_ADMIN */ 4673 4674 if (log_incoming_xfers && (xferlog || syslogmsg)) { 4675 char msg[MAXXFERSTRLEN]; /* see extensions.h */ 4676 int xfertime = time(NULL) - start_time; 4677 size_t msglen; 4678 4679 if (!xfertime) 4680 xfertime++; 4681 4682 /* Gather transfer statistics */ 4683 xfervalues.filename = name; 4684 xfervalues.filesize = st.st_size; 4685 xfervalues.transfer_bytes = byte_count; 4686 xfervalues.transfer_direction = 'i'; 4687 xfervalues.transfer_type = (type == TYPE_A) ? 'a' : 'b'; 4688 xfervalues.transfer_time = xfertime; 4689 xfervalues.restart_offset = restart_point; 4690 strlcpy(xfervalues.special_action, opt_string(0), MAXSPACTCHARS); 4691 xfervalues.access_mode = anonymous ? 'a' : (guest ? 'g' : 'r'); 4692 xfervalues.auth = authenticated; 4693 xfervalues.completion = TransferIncomplete ? 'i' : 'c'; 4694 4695 xferdone = 1; 4696 msg_massage(xferlog_format, msg, sizeof(msg)); 4697 xferdone = 0; 4698 4699 /* Ensure msg always ends with '\n' */ 4700 msglen = strlen(msg); 4701 if (msglen == sizeof(msg) - 1) { 4702 msg[sizeof(msg) - 2] = '\n'; 4703 msg[sizeof(msg) - 1] = '\0'; 4704 } 4705 else { 4706 msg[msglen] = '\n'; 4707 msg[msglen + 1] = '\0'; 4708 } 4709 4710 if (syslogmsg != 1) 4711 write(xferlog, msg, strlen(msg)); 4712 if (syslogmsg != 0) { 4713 char *msgp = msg; 4714 /* 4715 * To preserve the behavior when the xferlog format was fixed, skip 4716 * over the time string if the message starts with the local time. 4717 */ 4718 if (strncmp(xferlog_format, "%T ", 3) == 0) 4719 msgp += 25; 4720 syslog(LOG_INFO, "xferlog (recv): %s", msgp); 4721 } 4722 } 4723 data = -1; 4724 pdata = -1; 4725 done: 4726 (void) fclose(fout); 4727 } 4728 4729 FILE *getdatasock(char *mode) 4730 { 4731 int s, on = 1, tries; 4732 4733 if (data >= 0) 4734 return (fdopen(data, mode)); 4735 port_priv_on(0); 4736 s = socket(SOCK_FAMILY(data_dest), SOCK_STREAM, 0); 4737 if (s < 0) 4738 goto bad; 4739 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, 4740 (char *) &on, sizeof(on)) < 0) 4741 goto bad; 4742 if (keepalive) 4743 (void) setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)); 4744 if (TCPwindowsize) 4745 (void) setsockopt(s, SOL_SOCKET, (*mode == 'w' ? SO_SNDBUF : SO_RCVBUF), 4746 (char *) &TCPwindowsize, sizeof(TCPwindowsize)); 4747 /* anchor socket to avoid multi-homing problems */ 4748 #ifdef INET6 4749 if (SOCK_FAMILY(data_dest) == SOCK_FAMILY(ctrl_addr)) 4750 data_source = ctrl_addr; 4751 else if ((SOCK_FAMILY(data_dest) == AF_INET) && ctrl_v4mapped) { 4752 struct sockaddr_in6 *ctrl_sin6 = (struct sockaddr_in6 *)&ctrl_addr; 4753 struct sockaddr_in *data_sin = (struct sockaddr_in *)&data_source; 4754 4755 SET_SOCK_FAMILY(data_source, AF_INET); 4756 memcpy(&data_sin->sin_addr, &ctrl_sin6->sin6_addr.s6_addr[12], 4757 sizeof(struct in_addr)); 4758 } 4759 else { 4760 memset(&data_source, 0, sizeof(struct sockaddr_in6)); 4761 SET_SOCK_FAMILY(data_source, SOCK_FAMILY(data_dest)); 4762 SET_SOCK_ADDR_ANY(data_source); 4763 } 4764 #else 4765 data_source = ctrl_addr; 4766 #endif 4767 SET_SOCK_PORT(data_source, data_port); 4768 4769 #if defined(VIRTUAL) && defined(CANT_BIND) /* can't bind to virtual address */ 4770 SET_SOCK_ADDR_ANY(data_source); 4771 #endif 4772 for (tries = 1;; tries++) { 4773 if (bind(s, (struct sockaddr *) &data_source, SOCK_LEN(data_source)) >= 0) 4774 break; 4775 if (errno != EADDRINUSE || tries > 10) 4776 goto bad; 4777 sleep(tries); 4778 } 4779 #if defined(M_UNIX) && !defined(_M_UNIX) /* bug in old TCP/IP release */ 4780 { 4781 struct linger li; 4782 li.l_onoff = 1; 4783 li.l_linger = 900; 4784 if (setsockopt(s, SOL_SOCKET, SO_LINGER, 4785 (char *) &li, sizeof(struct linger)) < 0) { 4786 syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m"); 4787 goto bad; 4788 } 4789 } 4790 #endif 4791 port_priv_off((uid_t) pw->pw_uid); 4792 4793 #ifdef INET6 4794 /* IP_TOS is an IPv4 socket option */ 4795 if (SOCK_FAMILY(data_source) == AF_INET) 4796 #endif 4797 if ((on = IPClassOfService("data")) >= 0) { 4798 if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *) &on, sizeof(int)) < 0) 4799 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); 4800 } 4801 #ifdef TCP_NOPUSH 4802 /* 4803 * Turn off push flag to keep sender TCP from sending short packets 4804 * at the boundaries of each write(). Should probably do a SO_SNDBUF 4805 * to set the send buffer size as well, but that may not be desirable 4806 * in heavy-load situations. 4807 */ 4808 on = 1; 4809 if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *) &on, sizeof on) < 0) 4810 syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); 4811 #endif 4812 4813 return (fdopen(s, mode)); 4814 bad: 4815 on = errno; /* hold errno for return */ 4816 port_priv_off((uid_t) pw->pw_uid); 4817 if (s != -1) 4818 (void) close(s); 4819 errno = on; 4820 return (NULL); 4821 } 4822 4823 FILE *dataconn(char *name, off_t size, char *mode) 4824 { 4825 char sizebuf[32]; 4826 FILE *file; 4827 int retry = 0; 4828 int on = 1; 4829 int cval, serrno; 4830 int cos; 4831 #ifdef THROUGHPUT 4832 int bps; 4833 double bpsmult; 4834 #endif 4835 4836 file_size = size; 4837 byte_count = 0; 4838 if (size != (off_t) - 1) 4839 (void) sprintf(sizebuf, " (%" L_FORMAT " bytes)", size); 4840 else 4841 (void) strcpy(sizebuf, ""); 4842 if (pdata >= 0) { 4843 struct SOCKSTORAGE from; 4844 char dataaddr[MAXHOSTNAMELEN]; 4845 #if defined(UNIXWARE) || defined(AIX) 4846 size_t fromlen = sizeof(from); 4847 #else 4848 int fromlen = sizeof(from); 4849 #endif 4850 int s; 4851 #ifdef FD_ZERO 4852 int rv; 4853 #endif 4854 4855 if (keepalive) 4856 (void) setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)); 4857 if (TCPwindowsize) 4858 (void) setsockopt(pdata, SOL_SOCKET, (*mode == 'w' ? SO_SNDBUF : SO_RCVBUF), 4859 (char *) &TCPwindowsize, sizeof(TCPwindowsize)); 4860 #ifdef FD_ZERO 4861 do { 4862 struct timeval timeout; 4863 fd_set set; 4864 4865 FD_ZERO(&set); 4866 FD_SET(pdata, &set); 4867 4868 timeout.tv_usec = 0; 4869 timeout.tv_sec = timeout_accept; 4870 #ifdef HPUX_SELECT 4871 rv = select(pdata + 1, (int *) &set, NULL, NULL, &timeout); 4872 #else 4873 rv = select(pdata + 1, &set, (fd_set *) 0, (fd_set *) 0, 4874 (struct timeval *) &timeout); 4875 #endif 4876 } while ((rv == -1) && (errno == EINTR)); 4877 if ((rv != -1) && (rv != 0)) 4878 s = accept(pdata, (struct sockaddr *) &from, &fromlen); 4879 else 4880 s = -1; 4881 #else /* FD_ZERO */ 4882 (void) signal(SIGALRM, alarm_signal); 4883 alarm(timeout_accept); 4884 s = accept(pdata, (struct sockaddr *) &from, &fromlen); 4885 alarm(0); 4886 #endif 4887 if (s == -1) { 4888 reply(425, "Can't open data connection."); 4889 (void) close(pdata); 4890 pdata = -1; 4891 return (NULL); 4892 } 4893 (void) close(pdata); 4894 pdata = s; 4895 #ifdef INET6 4896 /* IP_TOS is an IPv4 socket option */ 4897 if (SOCK_FAMILY(from) == AF_INET) 4898 #endif 4899 if ((cos = IPClassOfService("data")) >= 0) 4900 (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&cos, sizeof(int)); 4901 (void) strncpy(dataaddr, inet_stop(&from), sizeof(dataaddr)); 4902 if (!pasv_allowed(dataaddr)) 4903 if (strcasecmp(dataaddr, remoteaddr) != 0) { 4904 /* 4905 * This will log when data connection comes from an address different 4906 * than the control connection. 4907 */ 4908 #ifdef FIGHT_PASV_PORT_RACE 4909 syslog(LOG_ERR, "%s of %s: data connect from %s for %s%s", 4910 anonymous ? guestpw : pw->pw_name, remoteident, 4911 dataaddr, name, sizebuf); 4912 reply(425, "Possible PASV port theft, cannot open data connection."); 4913 (void) close(pdata); 4914 pdata = -1; 4915 return (NULL); 4916 #else 4917 syslog(LOG_NOTICE, "%s of %s: data connect from %s for %s%s", 4918 anonymous ? guestpw : pw->pw_name, remoteident, 4919 dataaddr, name, sizebuf); 4920 #endif 4921 } 4922 #ifdef THROUGHPUT 4923 throughput_calc(name, &bps, &bpsmult); 4924 if (bps != -1) { 4925 lreply(150, "Opening %s mode data connection for %s%s.", 4926 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 4927 reply(150, "Restricting network throughput to %d bytes/s.", bps); 4928 } 4929 else 4930 #endif 4931 reply(150, "Opening %s mode data connection for %s%s.", 4932 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 4933 return (fdopen(pdata, mode)); 4934 } 4935 if (data >= 0) { 4936 reply(125, "Using existing data connection for %s%s.", 4937 name, sizebuf); 4938 usedefault = 1; 4939 return (fdopen(data, mode)); 4940 } 4941 if (usedefault) 4942 data_dest = his_addr; 4943 if (SOCK_PORT(data_dest) == 0) { 4944 reply(500, "Can't build data connection: no PORT specified"); 4945 return (NULL); 4946 } 4947 usedefault = 1; 4948 do { 4949 file = getdatasock(mode); 4950 if (file == NULL) { 4951 reply(425, "Can't create data socket (%s,%d): %s.", 4952 inet_stop(&data_source), ntohs(SOCK_PORT(data_source)), 4953 strerror(errno)); 4954 return (NULL); 4955 } 4956 data = fileno(file); 4957 (void) signal(SIGALRM, alarm_signal); 4958 alarm(timeout_connect); 4959 cval = connect(data, (struct sockaddr *) &data_dest, 4960 SOCK_LEN(data_dest)); 4961 serrno = errno; 4962 alarm(0); 4963 if (cval == -1) { 4964 /* 4965 * When connect fails, the state of the socket is unspecified so 4966 * it should be closed and a new socket created for each connection 4967 * attempt. This also prevents denial of service problems when 4968 * running on operating systems that only allow one non-connected 4969 * socket bound to the same local address. 4970 */ 4971 (void) fclose(file); 4972 data = -1; 4973 errno = serrno; 4974 if ((errno == EADDRINUSE || errno == EINTR) && retry < swaitmax) { 4975 sleep((unsigned) swaitint); 4976 retry += swaitint; 4977 } 4978 else { 4979 perror_reply(425, "Can't build data connection"); 4980 return (NULL); 4981 } 4982 } 4983 } while (cval == -1); 4984 if (keepalive) 4985 (void) setsockopt(data, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)); 4986 if (TCPwindowsize) 4987 (void) setsockopt(data, SOL_SOCKET, (*mode == 'w' ? SO_SNDBUF : SO_RCVBUF), 4988 (char *) &TCPwindowsize, sizeof(TCPwindowsize)); 4989 #ifdef THROUGHPUT 4990 throughput_calc(name, &bps, &bpsmult); 4991 if (bps != -1) { 4992 lreply(150, "Opening %s mode data connection for %s%s.", 4993 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 4994 reply(150, "Restricting network throughput to %d bytes/s.", bps); 4995 } 4996 else 4997 #endif 4998 reply(150, "Opening %s mode data connection for %s%s.", 4999 type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); 5000 return (file); 5001 } 5002 5003 /* Tranfer the contents of "instr" to "outstr" peer using the appropriate 5004 * encapsulation of the data subject to Mode, Structure, and Type. 5005 * 5006 * NB: Form isn't handled. */ 5007 5008 int 5009 #ifdef THROUGHPUT 5010 send_data(char *name, FILE *instr, FILE *outstr, size_t blksize) 5011 #else 5012 send_data(FILE *instr, FILE *outstr, size_t blksize) 5013 #endif 5014 { 5015 register int c, cnt = 0; 5016 static char *buf; 5017 int netfd, filefd; 5018 #ifdef THROUGHPUT 5019 int bps; 5020 double bpsmult; 5021 time_t t1, t2; 5022 #endif 5023 #ifdef SENDFILE 5024 int use_sf = 0; 5025 size_t xferred; 5026 struct stat st; 5027 struct sendfilevec sfv; 5028 #endif 5029 5030 buf = NULL; 5031 if (wu_setjmp(urgcatch)) { 5032 draconian_FILE = NULL; 5033 alarm(0); 5034 transflag = 0; 5035 #ifdef SIGPIPE 5036 (void) signal(SIGPIPE, lostconn); 5037 #endif 5038 if (buf) 5039 (void) free(buf); 5040 retrieve_is_data = 1; 5041 return (0); 5042 } 5043 transflag++; 5044 5045 #ifdef THROUGHPUT 5046 throughput_calc(name, &bps, &bpsmult); 5047 #endif 5048 5049 switch (type) { 5050 5051 case TYPE_A: 5052 #ifdef SIGPIPE 5053 /* 5054 * Ignore SIGPIPE while sending data, necessary so lostconn() isn't 5055 * called if we write to the data connection after the client has 5056 * closed it. 5057 */ 5058 (void) signal(SIGPIPE, SIG_IGN); 5059 #endif 5060 draconian_FILE = outstr; 5061 (void) signal(SIGALRM, draconian_alarm_signal); 5062 alarm(timeout_data); 5063 #ifdef THROUGHPUT 5064 if (bps != -1) 5065 t1 = time(NULL); 5066 #endif 5067 while ((draconian_FILE != NULL) && ((c = getc(instr)) != EOF)) { 5068 if (++byte_count % 4096 == 0) 5069 alarm(timeout_data); 5070 if (c == '\n') { 5071 if (ferror(outstr)) 5072 goto data_err; 5073 if (++byte_count % 4096 == 0) 5074 alarm(timeout_data); 5075 #if defined(USE_GSS) 5076 if (sec_putc('\r', outstr) != '\r') 5077 goto data_err; 5078 #else 5079 (void) putc('\r', outstr); 5080 #endif 5081 #ifdef TRANSFER_COUNT 5082 if (retrieve_is_data) { 5083 data_count_total++; 5084 data_count_out++; 5085 } 5086 byte_count_total++; 5087 byte_count_out++; 5088 #endif 5089 } 5090 #if defined(USE_GSS) 5091 if (sec_putc(c, outstr) != c) 5092 goto data_err; 5093 #else 5094 (void) putc(c, outstr); 5095 #endif 5096 5097 #ifdef TRANSFER_COUNT 5098 if (retrieve_is_data) { 5099 data_count_total++; 5100 data_count_out++; 5101 } 5102 byte_count_total++; 5103 byte_count_out++; 5104 #endif 5105 #ifdef THROUGHPUT 5106 if (bps > 0 && (byte_count % bps) == 0) { 5107 t2 = time(NULL); 5108 if (t2 == t1) 5109 sleep(1); 5110 t1 = time(NULL); 5111 } 5112 #endif 5113 } 5114 #ifdef THROUGHPUT 5115 if (bps != -1) 5116 throughput_adjust(name); 5117 #endif 5118 if (draconian_FILE != NULL) { 5119 alarm(timeout_data); 5120 #if defined(USE_GSS) 5121 if (sec_fflush(outstr) < 0) 5122 goto data_err; 5123 #else 5124 fflush(outstr); 5125 #endif /* defined(USE_GSS) */ 5126 } 5127 if (draconian_FILE != NULL) { 5128 alarm(timeout_data); 5129 socket_flush_wait(outstr); 5130 } 5131 transflag = 0; 5132 if (ferror(instr)) 5133 goto file_err; 5134 if ((draconian_FILE == NULL) || ferror(outstr)) 5135 goto data_err; 5136 draconian_FILE = NULL; 5137 alarm(0); 5138 #ifdef SIGPIPE 5139 (void) signal(SIGPIPE, lostconn); 5140 #endif 5141 reply(226, "Transfer complete."); 5142 #ifdef TRANSFER_COUNT 5143 if (retrieve_is_data) { 5144 file_count_total++; 5145 file_count_out++; 5146 } 5147 xfer_count_total++; 5148 xfer_count_out++; 5149 #endif 5150 retrieve_is_data = 1; 5151 return (1); 5152 5153 case TYPE_I: 5154 case TYPE_L: 5155 #ifdef THROUGHPUT 5156 if (bps != -1) 5157 blksize = bps; 5158 #endif 5159 netfd = fileno(outstr); 5160 filefd = fileno(instr); 5161 #ifdef SENDFILE 5162 /* check the input file is a regular file */ 5163 if ((fstat(filefd, &st) == 0) && ((st.st_mode & S_IFMT) == S_IFREG)) { 5164 #if defined(USE_GSS) 5165 if (gss_info.data_prot == PROT_C || !IS_GSSAUTH(cur_auth_type) || 5166 !(gss_info.authstate & GSS_ADAT_DONE)) 5167 #endif /* defined(USE_GSS) */ 5168 { 5169 use_sf = 1; 5170 /* 5171 * Use a private sfv_flag SFV_NOWAIT to tell sendfilev(), 5172 * when zero-copy is enabled, not to wait for all data to be 5173 * ACKed before returning. This is important for throughput 5174 * performance when sendfilev() is called to send small piece 5175 * at a time. 5176 */ 5177 sfv.sfv_flag = SFV_NOWAIT; 5178 sfv.sfv_fd = filefd; 5179 sfv.sfv_off = restart_point; 5180 sfv.sfv_len = blksize; 5181 } 5182 } 5183 if (use_sf == 0) 5184 #endif 5185 if ((buf = (char *) malloc(blksize)) == NULL) { 5186 transflag = 0; 5187 perror_reply(451, "Local resource failure: malloc"); 5188 retrieve_is_data = 1; 5189 return (0); 5190 } 5191 #ifdef SIGPIPE 5192 /* 5193 * Ignore SIGPIPE while sending data, necessary so lostconn() isn't 5194 * called if we write to the data connection after the client has 5195 * closed it. 5196 */ 5197 (void) signal(SIGPIPE, SIG_IGN); 5198 #endif 5199 draconian_FILE = outstr; 5200 (void) signal(SIGALRM, draconian_alarm_signal); 5201 alarm(timeout_data); 5202 #ifdef THROUGHPUT 5203 if (bps != -1) 5204 t1 = time(NULL); 5205 #endif 5206 while ((draconian_FILE != NULL) && ( 5207 #ifdef SENDFILE 5208 (use_sf && (cnt = sendfilev(netfd, &sfv, 1, &xferred)) > 0) 5209 || (!use_sf && 5210 #endif 5211 ((cnt = read(filefd, buf, blksize)) > 0 && 5212 #if defined(USE_GSS) 5213 sec_write(netfd, buf, cnt) == cnt) 5214 #else 5215 write(netfd, buf, cnt) == cnt) 5216 #endif /* defined(USE_GSS) */ 5217 #ifdef SENDFILE 5218 ) 5219 #endif 5220 )) { 5221 alarm(timeout_data); 5222 #ifdef SENDFILE 5223 sfv.sfv_off += cnt; 5224 #endif 5225 byte_count += cnt; 5226 #ifdef TRANSFER_COUNT 5227 if (retrieve_is_data) { 5228 #ifdef RATIO 5229 if( freefile ) { 5230 total_free_dl += cnt; 5231 } 5232 #endif /* RATIO */ 5233 data_count_total += cnt; 5234 data_count_out += cnt; 5235 } 5236 byte_count_total += cnt; 5237 byte_count_out += cnt; 5238 #endif 5239 #ifdef THROUGHPUT 5240 if (bps != -1) { 5241 t2 = time(NULL); 5242 if (t2 == t1) 5243 sleep(1); 5244 t1 = time(NULL); 5245 } 5246 #endif /* THROUGHPUT */ 5247 } 5248 #ifdef THROUGHPUT 5249 if (bps != -1) 5250 throughput_adjust(name); 5251 #endif 5252 #if defined(USE_GSS) 5253 if (sec_fflush(outstr) < 0) 5254 goto data_err; 5255 #endif 5256 transflag = 0; 5257 if (buf) 5258 (void) free(buf); 5259 if (draconian_FILE != NULL) { 5260 alarm(timeout_data); 5261 socket_flush_wait(outstr); 5262 } 5263 if (cnt != 0) { 5264 #ifdef SENDFILE 5265 if (use_sf && cnt < 0 && errno == EPIPE) 5266 goto data_err; 5267 #endif 5268 if (cnt < 0) 5269 goto file_err; 5270 goto data_err; 5271 } 5272 if (draconian_FILE == NULL) 5273 goto data_err; 5274 draconian_FILE = NULL; 5275 alarm(0); 5276 #ifdef SIGPIPE 5277 (void) signal(SIGPIPE, lostconn); 5278 #endif 5279 reply(226, "Transfer complete."); 5280 #ifdef TRANSFER_COUNT 5281 if (retrieve_is_data) { 5282 file_count_total++; 5283 file_count_out++; 5284 } 5285 xfer_count_total++; 5286 xfer_count_out++; 5287 #endif 5288 retrieve_is_data = 1; 5289 return (1); 5290 default: 5291 transflag = 0; 5292 reply(550, "Unimplemented TYPE %d in send_data", type); 5293 retrieve_is_data = 1; 5294 return (0); 5295 } 5296 5297 data_err: 5298 draconian_FILE = NULL; 5299 alarm(0); 5300 transflag = 0; 5301 #ifdef SIGPIPE 5302 (void) signal(SIGPIPE, lostconn); 5303 #endif 5304 perror_reply(426, "Data connection"); 5305 retrieve_is_data = 1; 5306 return (0); 5307 5308 file_err: 5309 draconian_FILE = NULL; 5310 alarm(0); 5311 transflag = 0; 5312 #ifdef SIGPIPE 5313 (void) signal(SIGPIPE, lostconn); 5314 #endif 5315 perror_reply(551, "Error on input file"); 5316 retrieve_is_data = 1; 5317 return (0); 5318 } 5319 5320 /* Transfer data from peer to "outstr" using the appropriate encapulation of 5321 * the data subject to Mode, Structure, and Type. 5322 * 5323 * N.B.: Form isn't handled. */ 5324 5325 int receive_data(FILE *instr, FILE *outstr) 5326 { 5327 register int c; 5328 int rcnt = 0, n = 0, bare_lfs = 0; 5329 static char *buf; 5330 int netfd, filefd, wcnt; 5331 #ifdef BUFFER_SIZE 5332 size_t buffer_size = BUFFER_SIZE; 5333 #else 5334 size_t buffer_size = BUFSIZ * 16; 5335 #endif 5336 5337 buf = NULL; 5338 if (wu_setjmp(urgcatch)) { 5339 alarm(0); 5340 transflag = 0; 5341 if (buf) 5342 (void) free(buf); 5343 return (-1); 5344 } 5345 transflag++; 5346 switch (type) { 5347 5348 case TYPE_I: 5349 case TYPE_L: 5350 #if defined(USE_GSS) 5351 if (GSSUSERAUTH_OK(gss_info)) 5352 buffer_size = gss_getinbufsz(); 5353 else 5354 #endif 5355 if (recvbufsz > 0) 5356 buffer_size = recvbufsz; 5357 if ((buf = (char *) malloc(buffer_size)) == NULL) { 5358 transflag = 0; 5359 perror_reply(451, "Local resource failure: malloc"); 5360 return (-1); 5361 } 5362 netfd = fileno(instr); 5363 filefd = fileno(outstr); 5364 draconian_FILE = instr; 5365 (void) signal(SIGALRM, draconian_alarm_signal); 5366 alarm(timeout_data); 5367 5368 while ((draconian_FILE != NULL) && 5369 #if defined(USE_GSS) 5370 (rcnt = sec_read(netfd, buf, buffer_size)) > 0) { 5371 #else 5372 (rcnt = read(netfd, buf, buffer_size)) > 0) { 5373 #endif 5374 for (wcnt = 0; wcnt < rcnt; wcnt += n) { 5375 if ((n = write(filefd, &buf[wcnt], rcnt - wcnt)) == -1) 5376 break; 5377 } 5378 byte_count += wcnt; 5379 #ifdef TRANSFER_COUNT 5380 data_count_total += wcnt; 5381 data_count_in += wcnt; 5382 byte_count_total += wcnt; 5383 byte_count_in += wcnt; 5384 #endif 5385 if (n == -1) 5386 break; 5387 alarm(timeout_data); 5388 } 5389 transflag = 0; 5390 (void) free(buf); 5391 if ((rcnt == -1) || (draconian_FILE == NULL)) 5392 goto data_err; 5393 if (n == -1) 5394 goto file_err; 5395 draconian_FILE = NULL; 5396 alarm(0); 5397 #ifdef TRANSFER_COUNT 5398 file_count_total++; 5399 file_count_in++; 5400 xfer_count_total++; 5401 xfer_count_in++; 5402 #endif 5403 return (0); 5404 5405 case TYPE_E: 5406 reply(553, "TYPE E not implemented."); 5407 transflag = 0; 5408 return (-1); 5409 5410 case TYPE_A: 5411 draconian_FILE = instr; 5412 (void) signal(SIGALRM, draconian_alarm_signal); 5413 alarm(timeout_data); 5414 while ((draconian_FILE != NULL) && 5415 #if defined(USE_GSS) 5416 ((c = sec_getc(instr)) != EOF) 5417 #else 5418 ((c = getc(instr)) != EOF) 5419 #endif 5420 ) { 5421 if (++byte_count % 4096 == 0) 5422 alarm(timeout_data); 5423 if (c == '\n') 5424 bare_lfs++; 5425 while (c == '\r') { 5426 if (ferror(outstr)) 5427 goto file_err; 5428 alarm(timeout_data); 5429 if (draconian_FILE != NULL) { 5430 #if defined(USE_GSS) 5431 if ((c = sec_getc(instr)) != '\n') 5432 #else 5433 if ((c = getc(instr)) != '\n') 5434 #endif 5435 (void) putc('\r', outstr); 5436 #ifdef TRANSFER_COUNT 5437 data_count_total++; 5438 data_count_in++; 5439 byte_count_total++; 5440 byte_count_in++; 5441 #endif 5442 if (c == EOF) /* null byte fix, noid (at) cyborg.larc.nasa.gov */ 5443 goto contin2; 5444 if (++byte_count % 4096 == 0) 5445 alarm(timeout_data); 5446 } 5447 } 5448 (void) putc(c, outstr); 5449 #ifdef TRANSFER_COUNT 5450 data_count_total++; 5451 data_count_in++; 5452 byte_count_total++; 5453 byte_count_in++; 5454 #endif 5455 contin2:; 5456 } 5457 fflush(outstr); 5458 if ((draconian_FILE == NULL) || ferror(instr)) 5459 goto data_err; 5460 if (ferror(outstr)) 5461 goto file_err; 5462 transflag = 0; 5463 draconian_FILE = NULL; 5464 alarm(0); 5465 if (bare_lfs) { 5466 lreply(226, "WARNING! %d bare linefeeds received in ASCII mode", bare_lfs); 5467 lreply(0, " File may not have transferred correctly."); 5468 } 5469 #ifdef TRANSFER_COUNT 5470 file_count_total++; 5471 file_count_in++; 5472 xfer_count_total++; 5473 xfer_count_in++; 5474 #endif 5475 return (0); 5476 default: 5477 reply(550, "Unimplemented TYPE %d in receive_data", type); 5478 transflag = 0; 5479 return (-1); 5480 } 5481 5482 data_err: 5483 draconian_FILE = NULL; 5484 alarm(0); 5485 transflag = 0; 5486 perror_reply(426, "Data Connection"); 5487 return (-1); 5488 5489 file_err: 5490 draconian_FILE = NULL; 5491 alarm(0); 5492 transflag = 0; 5493 perror_reply(452, "Error writing file"); 5494 return (-1); 5495 } 5496 5497 void statfilecmd(char *filename) 5498 { 5499 #ifndef INTERNAL_LS 5500 char line[BUFSIZ * 2], *ptr; 5501 FILE *fin; 5502 int c; 5503 #endif /* ! INTERNAL_LS */ 5504 5505 fixpath(filename); 5506 if (filename[0] == '\0') 5507 filename = "."; 5508 #ifndef INTERNAL_LS 5509 if (anonymous && dolreplies) 5510 (void) snprintf(line, sizeof(line), ls_long, filename); 5511 else 5512 (void) snprintf(line, sizeof(line), ls_short, filename); 5513 fin = ftpd_popen(line, "r", 0); 5514 #endif /* ! INTERNAL_LS */ 5515 lreply(213, "status of %s:", filename); 5516 #ifndef INTERNAL_LS 5517 /* 5518 while ((c = getc(fin)) != EOF) { 5519 if (c == '\n') { 5520 if (ferror(stdout)) { 5521 perror_reply(421, "control connection"); 5522 (void) ftpd_pclose(fin); 5523 dologout(1); 5524 / * NOTREACHED * / 5525 } 5526 if (ferror(fin)) { 5527 perror_reply(551, filename); 5528 (void) ftpd_pclose(fin); 5529 return; 5530 } 5531 (void) putc('\r', stdout); 5532 } 5533 (void) putc(c, stdout); 5534 } 5535 */ 5536 while (fgets(line, sizeof(line), fin) != NULL) { 5537 if ((ptr = strchr(line, '\n'))) /* clip out unnecessary newline */ 5538 *ptr = '\0'; 5539 lreply(0, "%s", line); 5540 } 5541 (void) ftpd_pclose(fin); 5542 #else /* INTERNAL_LS */ 5543 ls_dir(filename, 1, 0, 1, 0, 1, stdout); 5544 #endif /* INTERNAL_LS */ 5545 reply(213, "End of Status"); 5546 } 5547 5548 void statcmd(void) 5549 { 5550 struct SOCKSTORAGE *sin; 5551 u_char *a, *p; 5552 unsigned short port; 5553 #ifdef INET6 5554 int isv4 = 0; 5555 #endif 5556 5557 lreply(211, "%s FTP server status:", hostname); 5558 lreply(0, " %s", version); 5559 if (nameserved) 5560 lreply(0, " Connected to %s (%s)", remotehost, remoteaddr); 5561 else 5562 lreply(0, " Connected to %s", remotehost); 5563 5564 if (logged_in) { 5565 if (anonymous) 5566 lreply(0, " Logged in anonymously"); 5567 else 5568 lreply(0, " Logged in as %s", pw->pw_name); 5569 } 5570 else if (askpasswd) 5571 lreply(0, " Waiting for password"); 5572 else 5573 lreply(0, " Waiting for user name"); 5574 5575 if (type == TYPE_L) 5576 #ifdef NBBY 5577 lreply(0, " TYPE: %s %d; STRUcture: %s; transfer MODE: %s", 5578 typenames[type], NBBY, strunames[stru], modenames[mode]); 5579 #else 5580 lreply(0, " TYPE: %s %d; STRUcture: %s; transfer MODE: %s", 5581 typenames[type], bytesize, strunames[stru], modenames[mode]); 5582 #endif /* NBBY */ 5583 else 5584 lreply(0, " TYPE: %s%s%s; STRUcture: %s; transfer MODE: %s", 5585 typenames[type], (type == TYPE_A || type == TYPE_E) ? 5586 ", FORM: " : "", (type == TYPE_A || type == TYPE_E) ? 5587 formnames[form] : "", strunames[stru], modenames[mode]); 5588 if (data != -1) 5589 lreply(0, " Data connection open"); 5590 else if (pdata != -1 || usedefault == 0) { 5591 if (usedefault == 0) { 5592 sin = &data_dest; 5593 port = SOCK_PORT(data_dest); 5594 } 5595 else { 5596 port = SOCK_PORT(pasv_addr); 5597 if (route_vectored) 5598 sin = &vect_addr; 5599 else 5600 sin = &pasv_addr; 5601 } 5602 a = (u_char *) SOCK_ADDR(*sin); 5603 p = (u_char *) &port; 5604 #define UC(b) (((int) b) & 0xff) 5605 #ifdef INET6 5606 if (SOCK_FAMILY(*sin) == AF_INET) 5607 isv4 = 1; 5608 else if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)sin)->sin6_addr)) 5609 { 5610 isv4 = 1; 5611 a += 12; /* move to the IPv4 part of an IPv4-mapped IPv6 address */ 5612 } 5613 if (epsv_all) 5614 lreply(0, " EPSV only mode (EPSV ALL)"); 5615 if (isv4 && !epsv_all) 5616 #endif 5617 lreply(0, " %s (%d,%d,%d,%d,%d,%d)", 5618 usedefault == 0 ? "PORT" : "PASV", 5619 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 5620 #ifdef INET6 5621 lreply(0, " %s (|%d|%s|%d|)", usedefault == 0 ? "EPRT" : "EPSV", 5622 isv4 ? 1 : 2, inet_stop(sin), ntohs(port)); 5623 if (!epsv_all) 5624 if (isv4) 5625 lreply(0, " %s (4,4,%d,%d,%d,%d,2,%d,%d)", 5626 usedefault == 0 ? "LPRT" : "LPSV", 5627 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 5628 UC(p[0]), UC(p[1])); 5629 else 5630 lreply(0, " %s (6,16,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d," 5631 "%d,%d,%d,%d,2,%d,%d)", 5632 usedefault == 0 ? "LPRT" : "LPSV", 5633 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 5634 UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), 5635 UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]), 5636 UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), 5637 UC(p[0]), UC(p[1])); 5638 #endif 5639 #undef UC 5640 } 5641 else 5642 lreply(0, " No data connection"); 5643 #ifdef TRANSFER_COUNT 5644 lreply(0, " %" L_FORMAT " data bytes received in %d files", data_count_in, file_count_in); 5645 lreply(0, " %" L_FORMAT " data bytes transmitted in %d files", data_count_out, file_count_out); 5646 lreply(0, " %" L_FORMAT " data bytes total in %d files", data_count_total, file_count_total); 5647 lreply(0, " %" L_FORMAT " traffic bytes received in %d transfers", byte_count_in, xfer_count_in); 5648 lreply(0, " %" L_FORMAT " traffic bytes transmitted in %d transfers", byte_count_out, xfer_count_out); 5649 lreply(0, " %" L_FORMAT " traffic bytes total in %d transfers", byte_count_total, xfer_count_total); 5650 #endif 5651 reply(211, "End of status"); 5652 } 5653 5654 void fatal(char *s) 5655 { 5656 reply(451, "Error in server: %s\n", s); 5657 reply(221, "Closing connection due to server error."); 5658 dologout(0); 5659 /* NOTREACHED */ 5660 } 5661 5662 #define USE_REPLY_NOTFMT (1<<1) /* fmt is not a printf fmt (KLUDGE) */ 5663 #define USE_REPLY_LONG (1<<2) /* this is a long reply; use a - */ 5664 5665 void vreply(long flags, int n, char *fmt, va_list ap) 5666 { 5667 char buf[BUFSIZ * 16]; 5668 5669 flags &= USE_REPLY_NOTFMT | USE_REPLY_LONG; 5670 5671 if (n) /* if numeric is 0, don't output one; use n==0 in place of printf's */ 5672 sprintf(buf, "%03d%c", n, flags & USE_REPLY_LONG ? '-' : ' '); 5673 5674 /* This is somewhat of a kludge for autospout. I personally think that 5675 * autospout should be done differently, but that's not my department. -Kev 5676 */ 5677 if (flags & USE_REPLY_NOTFMT) 5678 snprintf(buf + (n ? 4 : 0), n ? sizeof(buf) - 4 : sizeof(buf), "%s", fmt); 5679 else 5680 vsnprintf(buf + (n ? 4 : 0), n ? sizeof(buf) - 4 : sizeof(buf), fmt, ap); 5681 5682 #if defined(USE_GSS) 5683 if (IS_GSSAUTH(cur_auth_type) && 5684 (gss_info.authstate & GSS_ADAT_DONE) && 5685 gss_info.ctrl_prot != PROT_C) { 5686 if (buf[strlen(buf)-1] != '\n') 5687 strlcat(buf, "\r\n", sizeof(buf)); 5688 (void) sec_reply(buf, sizeof(buf), n); 5689 } 5690 #endif 5691 5692 if (debug) /* debugging output :) */ 5693 syslog(LOG_DEBUG, "<--- %s", buf); 5694 5695 /* Yes, you want the debugging output before the client output; wrapping 5696 * stuff goes here, you see, and you want to log the cleartext and send 5697 * the wrapped text to the client. 5698 */ 5699 5700 printf("%s\r\n", buf); /* and send it to the client */ 5701 #ifdef TRANSFER_COUNT 5702 byte_count_total += strlen(buf); 5703 byte_count_out += strlen(buf); 5704 #endif 5705 /* 5706 * We dont need to worry about "sec_fflush" here since "sec_reply" 5707 * already wrapped the reply if necessary. 5708 */ 5709 fflush(stdout); 5710 } 5711 5712 void reply(int n, char *fmt,...) 5713 { 5714 VA_LOCAL_DECL 5715 5716 if (autospout != NULL) { /* deal with the autospout stuff... */ 5717 char *p, *ptr = autospout; 5718 5719 while (*ptr) { 5720 if ((p = strchr(ptr, '\n')) != NULL) /* step through line by line */ 5721 *p = '\0'; 5722 5723 /* send a line...(note that this overrides dolreplies!) */ 5724 vreply(USE_REPLY_LONG | USE_REPLY_NOTFMT, n, ptr, ap); 5725 5726 if (p) 5727 ptr = p + 1; /* set to the next line... (\0 is handled in the while) */ 5728 else 5729 break; /* oh, we're done; drop out of the loop */ 5730 } 5731 5732 if (autospout_free) { /* free autospout if necessary */ 5733 (void) free(autospout); 5734 autospout_free = 0; 5735 } 5736 autospout = 0; /* clear the autospout */ 5737 } 5738 5739 VA_START(fmt); 5740 5741 /* send the reply */ 5742 vreply(0L, n, fmt, ap); 5743 5744 VA_END; 5745 } 5746 5747 void lreply(int n, char *fmt,...) 5748 { 5749 VA_LOCAL_DECL 5750 5751 if (!dolreplies) /* prohibited from doing long replies? */ 5752 return; 5753 5754 VA_START(fmt); 5755 5756 /* send the reply */ 5757 vreply(USE_REPLY_LONG, n, fmt, ap); 5758 5759 VA_END; 5760 } 5761 5762 void ack(char *s) 5763 { 5764 reply(250, "%s command successful.", s); 5765 } 5766 5767 void nack(char *s) 5768 { 5769 reply(502, "%s command not implemented.", s); 5770 } 5771 5772 void yyerror(char *s) 5773 { 5774 char *cp; 5775 if (s == NULL || yyerrorcalled != 0) 5776 return; 5777 if ((cp = strchr(cbuf, '\n')) != NULL) 5778 *cp = '\0'; 5779 reply(500, "'%s': command not understood.", cbuf); 5780 yyerrorcalled = 1; 5781 return; 5782 } 5783 5784 void delete(char *name) 5785 { 5786 struct stat st; 5787 char realname[MAXPATHLEN]; 5788 5789 /* 5790 * delete permission? 5791 */ 5792 5793 wu_realpath(name, realname, chroot_path); 5794 5795 if ((del_check(name)) == 0) { 5796 if (log_security) 5797 if (anonymous) 5798 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to delete %s", 5799 guestpw, remoteident, realname); 5800 else 5801 syslog(LOG_NOTICE, "%s of %s tried to delete %s", 5802 pw->pw_name, remoteident, realname); 5803 return; 5804 } 5805 5806 if (lstat(name, &st) < 0) { 5807 perror_reply(550, name); 5808 return; 5809 } 5810 if ((st.st_mode & S_IFMT) == S_IFDIR) { 5811 uid_t uid; 5812 gid_t gid; 5813 int d_mode; 5814 int valid; 5815 5816 /* 5817 * check the directory, can we rmdir here? 5818 */ 5819 if ((dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0) { 5820 if (log_security) 5821 if (anonymous) 5822 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to delete directory %s", 5823 guestpw, remoteident, realname); 5824 else 5825 syslog(LOG_NOTICE, "%s of %s tried to delete directory %s", 5826 pw->pw_name, remoteident, realname); 5827 return; 5828 } 5829 5830 if (rmdir(name) < 0) { 5831 if (log_security) 5832 if (anonymous) 5833 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to delete directory %s (permissions)", 5834 guestpw, remoteident, realname); 5835 else 5836 syslog(LOG_NOTICE, "%s of %s tried to delete directory %s (permissions)", 5837 pw->pw_name, remoteident, realname); 5838 perror_reply(550, name); 5839 return; 5840 } 5841 goto done; 5842 } 5843 if (unlink(name) < 0) { 5844 if (log_security) 5845 if (anonymous) 5846 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to delete %s (permissions)", 5847 guestpw, remoteident, realname); 5848 else 5849 syslog(LOG_NOTICE, "%s of %s tried to delete %s (permissions)", 5850 pw->pw_name, remoteident, realname); 5851 perror_reply(550, name); 5852 return; 5853 } 5854 done: 5855 { 5856 char path[MAXPATHLEN]; 5857 5858 wu_realpath(name, path, chroot_path); 5859 5860 if (log_security) 5861 if ((st.st_mode & S_IFMT) == S_IFDIR) 5862 if (anonymous) { 5863 syslog(LOG_NOTICE, "%s of %s deleted directory %s", guestpw, remoteident, path); 5864 } 5865 else { 5866 syslog(LOG_NOTICE, "%s of %s deleted directory %s", pw->pw_name, 5867 remoteident, path); 5868 } 5869 else if (anonymous) { 5870 syslog(LOG_NOTICE, "%s of %s deleted %s", guestpw, 5871 remoteident, path); 5872 } 5873 else { 5874 syslog(LOG_NOTICE, "%s of %s deleted %s", pw->pw_name, 5875 remoteident, path); 5876 } 5877 } 5878 5879 ack("DELE"); 5880 } 5881 5882 void cwd(char *path) 5883 { 5884 struct aclmember *entry = NULL; 5885 char cdpath[MAXPATHLEN]; 5886 5887 if (chdir(path) < 0) { 5888 /* alias checking */ 5889 while (getaclentry("alias", &entry) && ARG0 && ARG1 != NULL) { 5890 if (!strcasecmp(ARG0, path)) { 5891 if (chdir(ARG1) < 0) 5892 perror_reply(550, path); 5893 else { 5894 show_message(250, C_WD); 5895 show_readme(250, C_WD); 5896 ack("CWD"); 5897 } 5898 return; 5899 } 5900 } 5901 /* check for "cdpath" directories. */ 5902 entry = (struct aclmember *) NULL; 5903 while (getaclentry("cdpath", &entry) && ARG0 != NULL) { 5904 snprintf(cdpath, sizeof cdpath, "%s/%s", ARG0, path); 5905 if (chdir(cdpath) >= 0) { 5906 show_message(250, C_WD); 5907 show_readme(250, C_WD); 5908 ack("CWD"); 5909 return; 5910 } 5911 } 5912 perror_reply(550, path); 5913 } 5914 else { 5915 show_message(250, C_WD); 5916 show_readme(250, C_WD); 5917 ack("CWD"); 5918 } 5919 } 5920 5921 void makedir(char *name) 5922 { 5923 uid_t uid; 5924 gid_t gid; 5925 int d_mode; 5926 mode_t oldumask; 5927 int valid; 5928 int ret, serrno; 5929 uid_t oldid; 5930 char path[MAXPATHLEN + 1]; /* for realpath() later - cky */ 5931 char realname[MAXPATHLEN]; 5932 5933 wu_realpath(name, realname, chroot_path); 5934 /* 5935 * check the directory, can we mkdir here? 5936 */ 5937 if ((dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0) { 5938 if (log_security) 5939 if (anonymous) 5940 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to create directory %s", 5941 guestpw, remoteident, realname); 5942 else 5943 syslog(LOG_NOTICE, "%s of %s tried to create directory %s", 5944 pw->pw_name, remoteident, realname); 5945 return; 5946 } 5947 5948 /* 5949 * check the filename, is it legal? 5950 */ 5951 if ((fn_check(name)) <= 0) { 5952 if (log_security) 5953 if (anonymous) 5954 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to create directory %s (path-filter)", 5955 guestpw, remoteident, realname); 5956 else 5957 syslog(LOG_NOTICE, "%s of %s tried to create directory %s (path-filter)", 5958 pw->pw_name, remoteident, realname); 5959 return; 5960 } 5961 5962 oldumask = umask(0000); 5963 if (valid <= 0) { 5964 d_mode = 0777; 5965 umask(oldumask); 5966 } 5967 5968 if (mkdir(name, d_mode) < 0) { 5969 if (errno == EEXIST) { 5970 if (log_security) 5971 if (anonymous) 5972 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to create directory %s (exists)", 5973 guestpw, remoteident, realname); 5974 else 5975 syslog(LOG_NOTICE, "%s of %s tried to create directory %s (exists)", 5976 pw->pw_name, remoteident, realname); 5977 fb_realpath(name, path); 5978 reply(521, "\"%s\" directory exists", path); 5979 } 5980 else { 5981 if (log_security) 5982 if (anonymous) 5983 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to create directory %s (permissions)", 5984 guestpw, remoteident, realname); 5985 else 5986 syslog(LOG_NOTICE, "%s of %s tried to create directory %s (permissions)", 5987 pw->pw_name, remoteident, realname); 5988 perror_reply(550, name); 5989 } 5990 umask(oldumask); 5991 return; 5992 } 5993 umask(oldumask); 5994 if (valid > 0) { 5995 oldid = geteuid(); 5996 if (uid != 0) 5997 (void) seteuid((uid_t) uid); 5998 if ((uid == 0) || ((chown(name, uid, gid)) < 0)) { 5999 chown_priv_on(0); 6000 ret = chown(name, uid, gid); 6001 serrno = errno; 6002 chown_priv_off(oldid); 6003 if (ret < 0) { 6004 errno = serrno; 6005 perror_reply(550, "chown"); 6006 return; 6007 } 6008 } 6009 else 6010 (void) seteuid(oldid); 6011 } 6012 wu_realpath(name, path, chroot_path); 6013 if (log_security) 6014 if (anonymous) { 6015 syslog(LOG_NOTICE, "%s of %s created directory %s", guestpw, remoteident, path); 6016 } 6017 else { 6018 syslog(LOG_NOTICE, "%s of %s created directory %s", pw->pw_name, 6019 remoteident, path); 6020 } 6021 fb_realpath(name, path); 6022 /* According to RFC 959: 6023 * The 257 reply to the MKD command must always contain the 6024 * absolute pathname of the created directory. 6025 * This is implemented here using similar code to the PWD command. 6026 * XXX - still need to do `quote-doubling'. 6027 */ 6028 reply(257, "\"%s\" new directory created.", path); 6029 } 6030 6031 void removedir(char *name) 6032 { 6033 uid_t uid; 6034 gid_t gid; 6035 int d_mode; 6036 int valid; 6037 char realname[MAXPATHLEN]; 6038 6039 wu_realpath(name, realname, chroot_path); 6040 6041 /* 6042 * delete permission? 6043 */ 6044 6045 if ((del_check(name)) == 0) 6046 return; 6047 /* 6048 * check the directory, can we rmdir here? 6049 */ 6050 if ((dir_check(name, &uid, &gid, &d_mode, &valid)) <= 0) { 6051 if (log_security) 6052 if (anonymous) 6053 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to remove directory %s", 6054 guestpw, remoteident, realname); 6055 else 6056 syslog(LOG_NOTICE, "%s of %s tried to remove directory %s", 6057 pw->pw_name, remoteident, realname); 6058 return; 6059 } 6060 6061 if (rmdir(name) < 0) { 6062 if (errno == EBUSY) 6063 perror_reply(450, name); 6064 else { 6065 if (log_security) 6066 if (anonymous) 6067 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to remove directory %s (permissions)", 6068 guestpw, remoteident, realname); 6069 else 6070 syslog(LOG_NOTICE, "%s of %s tried to remove directory %s (permissions)", 6071 pw->pw_name, remoteident, realname); 6072 perror_reply(550, name); 6073 } 6074 } 6075 else { 6076 char path[MAXPATHLEN]; 6077 6078 wu_realpath(name, path, chroot_path); 6079 6080 if (log_security) 6081 if (anonymous) { 6082 syslog(LOG_NOTICE, "%s of %s deleted directory %s", guestpw, remoteident, path); 6083 } 6084 else { 6085 syslog(LOG_NOTICE, "%s of %s deleted directory %s", pw->pw_name, 6086 remoteident, path); 6087 } 6088 ack("RMD"); 6089 } 6090 } 6091 6092 void pwd(void) 6093 { 6094 char path[MAXPATHLEN + 1]; 6095 char rhome[MAXPATHLEN + 1]; 6096 char *rpath = path; /* Path to return to client */ 6097 int pathlen; 6098 #ifndef MAPPING_CHDIR 6099 #ifdef HAVE_GETCWD 6100 extern char *getcwd(); 6101 #else 6102 extern char *getwd(char *); 6103 #endif 6104 #endif /* MAPPING_CHDIR */ 6105 6106 #ifdef HAVE_GETCWD 6107 if (getcwd(path, MAXPATHLEN) == (char *) NULL) 6108 #else 6109 if (getwd(path) == (char *) NULL) 6110 #endif 6111 /* Dink! If you couldn't get the path and the buffer is now likely to 6112 be undefined, why are you trying to PRINT it?! _H* 6113 reply(550, "%s.", path); */ 6114 { 6115 fb_realpath(".", path); /* realpath_on_steroids can deal */ 6116 } 6117 /* relative to home directory if restricted_user */ 6118 if (restricted_user) { 6119 /* 6120 * Re-adjust real path because previous call to getXwd() did 6121 * not resolve symlink. 6122 */ 6123 fb_realpath(".", path); 6124 fb_realpath(home, rhome); 6125 pathlen = strlen(rhome); 6126 if (pathlen && rhome[pathlen - 1] == '/') 6127 pathlen--; 6128 rpath = rpath + pathlen; 6129 if (!*rpath) 6130 strcpy(rpath, "/"); 6131 } 6132 reply(257, "\"%s\" is current directory.", rpath); 6133 } 6134 6135 char *renamefrom(char *name) 6136 { 6137 struct stat st; 6138 6139 if (lstat(name, &st) < 0) { 6140 perror_reply(550, name); 6141 return ((char *) 0); 6142 } 6143 reply(350, "File exists, ready for destination name"); 6144 return (name); 6145 } 6146 6147 void renamecmd(char *from, char *to) 6148 { 6149 int allowed = (anonymous ? 0 : 1); 6150 char realfrom[MAXPATHLEN]; 6151 char realto[MAXPATHLEN]; 6152 struct aclmember *entry = NULL; 6153 #ifdef PARANOID 6154 struct stat st; 6155 #endif 6156 wu_realpath(from, realfrom, chroot_path); 6157 wu_realpath(to, realto, chroot_path); 6158 /* 6159 * check the filename, is it legal? 6160 */ 6161 if ((fn_check(to)) == 0) { 6162 if (log_security) 6163 if (anonymous) 6164 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to rename %s to \"%s\" (path-filter)", 6165 guestpw, remoteident, realfrom, realto); 6166 else 6167 syslog(LOG_NOTICE, "%s of %s tried to rename %s to \"%s\" (path-filter)", 6168 pw->pw_name, remoteident, realfrom, realto); 6169 return; 6170 } 6171 6172 /* 6173 * if rename permission denied and file exists... then deny the user 6174 * permission to rename the file. 6175 */ 6176 while (getaclentry("rename", &entry) && ARG0 && ARG1 != NULL) { 6177 if (type_match(ARG1)) 6178 if (anonymous) { 6179 if (*ARG0 == 'y') 6180 allowed = 1; 6181 } 6182 else if (*ARG0 == 'n') 6183 allowed = 0; 6184 } 6185 if (!allowed) { 6186 if (log_security) 6187 if (anonymous) 6188 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to rename %s to %s", 6189 guestpw, remoteident, realfrom, realto); 6190 else 6191 syslog(LOG_NOTICE, "%s of %s tried to rename %s to %s", 6192 pw->pw_name, remoteident, realfrom, realto); 6193 reply(553, "%s: Permission denied on server. (rename)", from); 6194 return; 6195 } 6196 6197 6198 #ifdef PARANOID 6199 /* Almost forgot about this. Don't allow renaming TO existing files -- 6200 otherwise someone can rename "trivial" to "warez", and "warez" is gone! 6201 XXX: This part really should do the same "overwrite" check as store(). */ 6202 if (!stat(to, &st)) { 6203 if (log_security) 6204 if (anonymous) 6205 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to rename %s to %s", 6206 guestpw, remoteident, realfrom, realto); 6207 else 6208 syslog(LOG_NOTICE, "%s of %s tried to rename %s to %s", 6209 pw->pw_name, remoteident, realfrom, realto); 6210 reply(550, "%s: Permission denied on server. (rename)", to); 6211 return; 6212 } 6213 #endif 6214 if (rename(from, to) < 0) { 6215 if (log_security) 6216 if (anonymous) 6217 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to rename %s to %s", 6218 guestpw, remoteident, realfrom, realto); 6219 else 6220 syslog(LOG_NOTICE, "%s of %s tried to rename %s to %s", 6221 pw->pw_name, remoteident, realfrom, realto); 6222 perror_reply(550, "rename"); 6223 } 6224 else { 6225 char frompath[MAXPATHLEN]; 6226 char topath[MAXPATHLEN]; 6227 6228 wu_realpath(from, frompath, chroot_path); 6229 wu_realpath(to, topath, chroot_path); 6230 6231 if (log_security) 6232 if (anonymous) { 6233 syslog(LOG_NOTICE, "%s of %s renamed %s to %s", guestpw, remoteident, frompath, topath); 6234 } 6235 else { 6236 syslog(LOG_NOTICE, "%s of %s renamed %s to %s", pw->pw_name, 6237 remoteident, frompath, topath); 6238 } 6239 ack("RNTO"); 6240 } 6241 } 6242 6243 void dolog(struct SOCKSTORAGE *sin) 6244 { 6245 char *blah; 6246 int rval; 6247 6248 blah = inet_stop(sin); 6249 (void) strncpy(remoteaddr, blah, sizeof(remoteaddr)); 6250 nameserved = 0; 6251 (void) strncpy(remotehost, remoteaddr, sizeof(remotehost)); 6252 6253 rhlookup = rhostlookup(remoteaddr); 6254 if (rhlookup) { 6255 if (!strcasecmp(remoteaddr, "0.0.0.0")) { 6256 nameserved = 1; 6257 strncpy(remotehost, "localhost", sizeof(remotehost)); 6258 } 6259 else { 6260 #ifdef DNS_TRYAGAIN 6261 int num_dns_tries = 0; 6262 /* 6263 * 27-Apr-93 EHK/BM 6264 * far away connections might take some time to get their IP address 6265 * resolved. That's why we try again -- maybe our DNS cache has the 6266 * PTR-RR now. This code is sloppy. Far better is to check what the 6267 * resolver returned so that in case of error, there's no need to 6268 * try again. 6269 */ 6270 dns_again: 6271 #endif /* DNS_TRYAGAIN */ 6272 6273 rval = wu_gethostbyaddr(sin, remotehost, sizeof(remotehost)); 6274 6275 #ifdef DNS_TRYAGAIN 6276 if (!rval && ++num_dns_tries <= 1) { 6277 sleep(3); 6278 goto dns_again; /* try DNS lookup once more */ 6279 } 6280 #endif /* DNS_TRYAGAIN */ 6281 6282 if (rval) 6283 nameserved = 1; 6284 } 6285 } 6286 6287 remotehost[sizeof(remotehost) - 1] = '\0'; 6288 sprintf(proctitle, "%s: connected", remotehost); 6289 setproctitle("%s", proctitle); 6290 6291 wu_authenticate(); 6292 /* Create a composite source identification string, to improve the logging 6293 * when RFC 931 is being used. */ 6294 { 6295 int n = 20 + strlen(remotehost) + strlen(remoteaddr) + 6296 (authenticated ? strlen(authuser + 5) : 0); 6297 if ((remoteident = malloc(n)) == NULL) { 6298 syslog(LOG_ERR, "malloc: %m"); 6299 #ifndef DEBUG 6300 exit(1); 6301 #endif 6302 } 6303 else if (authenticated) 6304 sprintf(remoteident, "%s @ %s [%s]", 6305 authuser, remotehost, remoteaddr); 6306 else 6307 sprintf(remoteident, "%s [%s]", remotehost, remoteaddr); 6308 } 6309 #ifdef DAEMON 6310 if (be_daemon && logging) 6311 syslog(LOG_INFO, "connection from %s", remoteident); 6312 #else 6313 #if 0 /* this is redundant unless the caller doesn't do *anything*, and 6314 tcpd will pick it up and deal with it better anyways. _H */ 6315 if (logging) 6316 syslog(LOG_INFO, "connection from %s", remoteident); 6317 #endif 6318 #endif 6319 } 6320 6321 /* Record logout in wtmp file and exit with supplied status. */ 6322 6323 void dologout(int status) 6324 { 6325 /* 6326 * Prevent reception of SIGURG from resulting in a resumption 6327 * back to the main program loop. 6328 */ 6329 transflag = 0; 6330 6331 /* 6332 * Cancel any pending alarm request, reception of SIGALRM would cause 6333 * dologout() to be called again from the SIGALRM handler toolong(). 6334 */ 6335 (void) alarm(0); 6336 6337 if (logged_in) { 6338 delay_signaling(); /* we can't allow any signals while euid==0: kinch */ 6339 #if defined(SOLARIS_BSM_AUDIT) && !defined(SOLARIS_NO_AUDIT_FTPD_LOGOUT) 6340 audit_ftpd_logout(); 6341 #endif 6342 (void) seteuid((uid_t) 0); 6343 if (wtmp_logging) 6344 wu_logwtmp(ttyline, pw->pw_name, remotehost, 0); 6345 #ifdef USE_PAM 6346 if (!anonymous && pamh) { 6347 (void) pam_close_session(pamh, 0); 6348 (void) pam_end(pamh, PAM_SUCCESS); 6349 pamh = (pam_handle_t *)0; 6350 } 6351 #endif 6352 } 6353 if (logging) 6354 syslog(LOG_INFO, "FTP session closed"); 6355 if (xferlog) 6356 close(xferlog); 6357 acl_remove(); 6358 if (data >= 0) 6359 close(data); 6360 if (pdata >= 0) 6361 close(pdata); 6362 #ifdef AFS_AUTH 6363 ktc_ForgetAllTokens(); 6364 #endif 6365 /* beware of flushing buffers after a SIGPIPE */ 6366 _exit(status); 6367 } 6368 6369 SIGNAL_TYPE myoob(int sig) 6370 { 6371 char *cp; 6372 #ifdef SIGPIPE 6373 void (*pipe_handler)(); 6374 #endif 6375 6376 /* only process if transfer occurring */ 6377 if (!transflag) { 6378 #ifdef SIGURG 6379 (void) signal(SIGURG, myoob); 6380 #endif 6381 return; 6382 } 6383 #ifdef SIGPIPE 6384 pipe_handler = signal(SIGPIPE, lostconn); 6385 #endif 6386 cp = tmpline; 6387 if (wu_getline(cp, sizeof(tmpline) - 1, stdin) == NULL) { 6388 reply(221, "You could at least say goodbye."); 6389 dologout(0); 6390 } 6391 upper(cp); 6392 if (strcasecmp(cp, "ABOR\r\n") == 0) { 6393 tmpline[0] = '\0'; 6394 reply(426, "Transfer aborted. Data connection closed."); 6395 reply(226, "Abort successful"); 6396 #ifdef SIGPIPE 6397 (void) signal(SIGPIPE, pipe_handler); 6398 #endif 6399 #ifdef SIGURG 6400 (void) signal(SIGURG, myoob); 6401 #endif 6402 if (ftwflag > 0) { 6403 ftwflag++; 6404 return; 6405 } 6406 wu_longjmp(urgcatch, 1); 6407 } 6408 if (strcasecmp(cp, "STAT\r\n") == 0) { 6409 tmpline[0] = '\0'; 6410 if (file_size != (off_t) - 1) 6411 reply(213, "Status: %" L_FORMAT " of %" L_FORMAT " bytes transferred", 6412 byte_count, file_size); 6413 else 6414 reply(213, "Status: %" L_FORMAT " bytes transferred", byte_count); 6415 } 6416 #ifdef SIGPIPE 6417 (void) signal(SIGPIPE, pipe_handler); 6418 #endif 6419 #ifdef SIGURG 6420 (void) signal(SIGURG, myoob); 6421 #endif 6422 } 6423 6424 /* Note: a response of 425 is not mentioned as a possible response to the 6425 * PASV command in RFC959. However, it has been blessed as a legitimate 6426 * response by Jon Postel in a telephone conversation with Rick Adams on 25 6427 * Jan 89. */ 6428 6429 void passive(int passive_mode, int proto) 6430 { 6431 /* First prime number after 2^n where 4 <= n <= 16 */ 6432 static int primes[] = {17,37,67,131,257,521,1031,2053,4099,8209,16411,32771,65537,0}; 6433 static int prime = 0; 6434 static int range; 6435 #if defined(UNIXWARE) || defined(AIX) 6436 size_t len; 6437 #else 6438 int len; 6439 #endif 6440 int bind_error, serrno; 6441 int on = 1; 6442 int i, j, inc, val; 6443 unsigned short port; 6444 register char *p, *a; 6445 struct SOCKSTORAGE *reply_addr; 6446 struct timeval tv; 6447 #ifdef INET6 6448 int isv4 = 0; 6449 #endif 6450 6451 /* H* fix: if we already *have* a passive socket, close it first. Prevents 6452 a whole variety of entertaining clogging attacks. */ 6453 if (pdata >= 0) { 6454 close(pdata); 6455 pdata = -1; 6456 } 6457 if (!logged_in) { 6458 reply(530, "Login with USER first."); 6459 return; 6460 } 6461 #ifdef INET6 6462 switch (proto) { 6463 case 0: 6464 if ((passive_mode == TYPE_PASV) && (SOCK_FAMILY(ctrl_addr) == AF_INET6) 6465 && !ctrl_v4mapped) { 6466 reply(501, "Network protocol mismatch"); 6467 return; 6468 } 6469 else 6470 pasv_addr = ctrl_addr; 6471 break; 6472 case 1: 6473 if (SOCK_FAMILY(ctrl_addr) == AF_INET) 6474 pasv_addr = ctrl_addr; 6475 else if (ctrl_v4mapped) { 6476 struct sockaddr_in6 *ctrl_sin6 = (struct sockaddr_in6 *)&ctrl_addr; 6477 struct sockaddr_in *pasv_sin = (struct sockaddr_in *)&pasv_addr; 6478 6479 SET_SOCK_FAMILY(pasv_addr, AF_INET); 6480 memcpy(&pasv_sin->sin_addr, &ctrl_sin6->sin6_addr.s6_addr[12], 6481 sizeof(struct in_addr)); 6482 } 6483 else { 6484 reply(522, "Network protocol mismatch, use (2)"); 6485 return; 6486 } 6487 break; 6488 case 2: 6489 if ((SOCK_FAMILY(ctrl_addr) == AF_INET6) && !ctrl_v4mapped) 6490 pasv_addr = ctrl_addr; 6491 else { 6492 reply(522, "Network protocol mismatch, use (1)"); 6493 return; 6494 } 6495 break; 6496 default: 6497 reply(522, "Network protocol not supported, use (1,2)"); 6498 return; 6499 } 6500 #else 6501 pasv_addr = ctrl_addr; 6502 #endif 6503 6504 if (passive_port_min == 0 && passive_port_max == 0) { 6505 /* let the kernel allocate the port */ 6506 SET_SOCK_PORT(pasv_addr, 0); 6507 } 6508 else if (prime == 0) { 6509 range = passive_port_max - passive_port_min + 1; 6510 6511 /* find the first prime greater than the range in the primes list */ 6512 for (i = 0; primes[i] != 0 && range >= primes[i]; i++) 6513 ; 6514 /* shouldn't happen, but check just in case */ 6515 if (primes[i] == 0) { 6516 syslog(LOG_ERR, "passive ports range too large %d-%d", passive_port_min, passive_port_max); 6517 /* let the kernel allocate the port */ 6518 SET_SOCK_PORT(pasv_addr, 0); 6519 } 6520 else 6521 prime = primes[i]; 6522 } 6523 len = SOCK_LEN(pasv_addr); 6524 6525 port_priv_on(0); /* necessary as port can be < 1024 */ 6526 pdata = socket(SOCK_FAMILY(pasv_addr), SOCK_STREAM, 0); 6527 if (pdata < 0) { 6528 serrno = errno; 6529 port_priv_off((uid_t) pw->pw_uid); 6530 errno = serrno; 6531 perror_reply(425, "Can't open passive connection"); 6532 return; 6533 } 6534 if (keepalive) 6535 (void) setsockopt(pdata, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)); 6536 if (TCPwindowsize) { 6537 (void) setsockopt(pdata, SOL_SOCKET, SO_SNDBUF, (char *) &TCPwindowsize, sizeof(TCPwindowsize)); 6538 (void) setsockopt(pdata, SOL_SOCKET, SO_RCVBUF, (char *) &TCPwindowsize, sizeof(TCPwindowsize)); 6539 } 6540 6541 bind_error = -1; 6542 errno = EADDRINUSE; 6543 6544 /* try each port in the specified range a maximum of 3 times */ 6545 for (i = 0; i < 3 && bind_error != 0 && \ 6546 ((errno == EADDRINUSE) || (errno == EACCES)); i++) { 6547 if (i > 0) 6548 sleep(i); 6549 if (SOCK_PORT(pasv_addr) == 0) 6550 bind_error = bind(pdata, (struct sockaddr *) &pasv_addr, len); 6551 else { 6552 gettimeofday(&tv, NULL); 6553 srand(tv.tv_usec + tv.tv_sec); 6554 inc = 1 + (int) ((1.0 * (prime - 1) * rand()) / (RAND_MAX + 1.0)); 6555 val = (int) ((1.0 * range * rand()) / (RAND_MAX + 1.0)); 6556 /* 6557 * Using the modulus operator with a prime number allows us to 6558 * try each port in the range once. 6559 */ 6560 for (j = 0; j < range && bind_error != 0 && \ 6561 ((errno == EADDRINUSE) || (errno == EACCES)); j++) { 6562 while ((val = ((val + inc) % prime)) >= range) 6563 ; 6564 SET_SOCK_PORT(pasv_addr, htons(val + passive_port_min)); 6565 bind_error = bind(pdata, (struct sockaddr *) &pasv_addr, len); 6566 } 6567 } 6568 } 6569 serrno = errno; 6570 port_priv_off((uid_t) pw->pw_uid); 6571 if (bind_error != 0) { 6572 errno = serrno; 6573 goto pasv_error; 6574 } 6575 6576 /* if the kernel allocated the port, find out which one */ 6577 if ((SOCK_PORT(pasv_addr) == 0) && 6578 (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)) 6579 goto pasv_error; 6580 6581 if (listen(pdata, 1) < 0) 6582 goto pasv_error; 6583 usedefault = 1; 6584 if (route_vectored) 6585 reply_addr = &vect_addr; 6586 else 6587 reply_addr = &pasv_addr; 6588 a = (char *) SOCK_ADDR(*reply_addr); 6589 port = SOCK_PORT(pasv_addr); 6590 p = (char *) &port; 6591 6592 #define UC(b) (((int) b) & 0xff) 6593 6594 if (debug) { 6595 char *s = calloc(128 + strlen(remoteident), sizeof(char)); 6596 if (s) { 6597 int i = ntohs(port); 6598 sprintf(s, "PASV port %i assigned to %s", i, remoteident); 6599 syslog(LOG_DEBUG, "%s", s); 6600 free(s); 6601 } 6602 } 6603 #ifdef INET6 6604 if (SOCK_FAMILY(*reply_addr) == AF_INET) 6605 isv4 = 1; 6606 else if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)reply_addr)->sin6_addr)) { 6607 isv4 = 1; 6608 a += 12; /* move to the IPv4 part of an IPv4-mapped IPv6 address */ 6609 } 6610 switch (passive_mode) { 6611 case TYPE_PASV: 6612 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", 6613 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 6614 return; 6615 case TYPE_EPSV: 6616 reply(229, "Entering Extended Passive Mode (|||%d|)", ntohs(port)); 6617 return; 6618 case TYPE_LPSV: 6619 if (isv4) { 6620 reply(228, "Entering Long Passive Mode " 6621 "(%d,%d,%d,%d,%d,%d,%d,%d,%d)", 6622 4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 6623 2, UC(p[0]), UC(p[1])); 6624 } 6625 else { 6626 reply(228, "Entering Long Passive Mode " 6627 "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d," 6628 "%d,%d,%d,%d,%d)", 6, 16, 6629 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]), 6630 UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]), 6631 UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]), 6632 UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]), 6633 2, UC(p[0]), UC(p[1])); 6634 } 6635 return; 6636 } 6637 #else 6638 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), 6639 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); 6640 return; 6641 #endif /* INET6 */ 6642 6643 pasv_error: 6644 perror_reply(425, "Can't open passive connection"); 6645 (void) close(pdata); 6646 pdata = -1; 6647 if (debug) { 6648 char *s = calloc(128 + strlen(remoteident), sizeof(char)); 6649 if (s) { 6650 sprintf(s, "PASV port assignment assigned for %s", remoteident); 6651 syslog(LOG_DEBUG, "%s", s); 6652 free(s); 6653 } 6654 } 6655 return; 6656 } 6657 6658 /* 6659 * Generate unique name for file with basename "local". The file named 6660 * "local" is already known to exist. Generates failure reply on error. 6661 */ 6662 char *gunique(char *local) 6663 { 6664 static char new[MAXPATHLEN]; 6665 struct stat st; 6666 char *cp = strrchr(local, '/'); 6667 int count = 0; 6668 6669 if (cp) 6670 *cp = '\0'; 6671 if (stat(cp ? local : ".", &st) < 0) { 6672 perror_reply(553, cp ? local : "."); 6673 return ((char *) 0); 6674 } 6675 if (cp) 6676 *cp = '/'; 6677 (void) strncpy(new, local, (sizeof new) - 3); 6678 new[sizeof(new) - 3] = '\0'; 6679 cp = new + strlen(new); 6680 *cp++ = '.'; 6681 for (count = 1; count < 100; count++) { 6682 if (count == 10) { 6683 cp -= 2; 6684 *cp++ = '.'; 6685 } 6686 (void) sprintf(cp, "%d", count); 6687 if (stat(new, &st) < 0) 6688 return (new); 6689 } 6690 reply(452, "Unique file name cannot be created."); 6691 return ((char *) 0); 6692 } 6693 6694 /* Format and send reply containing system error number. */ 6695 6696 void perror_reply(int code, char *string) 6697 { 6698 /* 6699 * If restricted user and string starts with home dir path, strip it off 6700 * and return only the relative path. 6701 */ 6702 if (restricted_user && (home != NULL) && (home[0] != '\0')) { 6703 size_t len = strlen (home); 6704 if (strncmp (home, string, len) == 0) { 6705 if (string[len - 1] == '/') 6706 string += len - 1; 6707 else if (string[len] == '/') 6708 string += len; 6709 else if (string[len] == '\0') 6710 string = "/"; 6711 } 6712 } 6713 reply(code, "%s: %s.", string, strerror(errno)); 6714 } 6715 6716 static char *onefile[] = 6717 {"", 0}; 6718 6719 extern char **ftpglob(register char *v); 6720 extern char *globerr; 6721 6722 void send_file_list(char *whichfiles) 6723 { 6724 /* static so not clobbered by longjmp(), volatile would also work */ 6725 static FILE *dout; 6726 static DIR *dirp; 6727 static char **sdirlist; 6728 static char *wildcard = NULL; 6729 6730 struct stat st; 6731 6732 register char **dirlist, *dirname; 6733 int simple = 0; 6734 int statret; 6735 /* This is ANSI/ISO C .. strpbrk should be in <string.h> which we've 6736 ** already included so we don't need the following line. 'sides, it 6737 ** breaks the GNU EGCS C compiler 6738 ** extern char *strpbrk(const char *, const char *); 6739 */ 6740 6741 #ifdef TRANSFER_COUNT 6742 #ifdef TRANSFER_LIMIT 6743 if (((file_limit_raw_out > 0) && (xfer_count_out >= file_limit_raw_out)) 6744 || ((file_limit_raw_total > 0) && (xfer_count_total >= file_limit_raw_total)) 6745 || ((data_limit_raw_out > 0) && (byte_count_out >= data_limit_raw_out)) 6746 || ((data_limit_raw_total > 0) && (byte_count_total >= data_limit_raw_total))) { 6747 if (log_security) 6748 if (anonymous) 6749 syslog(LOG_NOTICE, "anonymous(%s) of %s tried to list files (Transfer limits exceeded)", 6750 guestpw, remoteident); 6751 else 6752 syslog(LOG_NOTICE, "%s of %s tried to list files (Transfer limits exceeded)", 6753 pw->pw_name, remoteident); 6754 reply(553, "Permission denied on server. (Transfer limits exceeded)"); 6755 return; 6756 } 6757 #endif 6758 #endif 6759 6760 draconian_FILE = NULL; 6761 dout = NULL; 6762 dirp = NULL; 6763 sdirlist = NULL; 6764 wildcard = NULL; 6765 if (strpbrk(whichfiles, "~{[*?") == NULL) { 6766 if (whichfiles[0] == '\0') { 6767 wildcard = strdup("*"); 6768 if (wildcard == NULL) { 6769 reply(550, "Memory allocation error"); 6770 goto globfree; 6771 } 6772 whichfiles = wildcard; 6773 } 6774 else { 6775 if (statret=stat(whichfiles, &st) < 0) 6776 statret=lstat(whichfiles, &st); /* Check if it's a dangling symlink */ 6777 if (statret >= 0) { 6778 if ((st.st_mode & S_IFMT) == S_IFDIR) { 6779 wildcard = malloc(strlen(whichfiles) + 3); 6780 if (wildcard == NULL) { 6781 reply(550, "Memory allocation error"); 6782 goto globfree; 6783 } 6784 strcpy(wildcard, whichfiles); 6785 strcat(wildcard, "/*"); 6786 whichfiles = wildcard; 6787 } 6788 } 6789 } 6790 } 6791 if (strpbrk(whichfiles, "~{[*?") != NULL) { 6792 globerr = NULL; 6793 dirlist = ftpglob(whichfiles); 6794 sdirlist = dirlist; /* save to free later */ 6795 if (globerr != NULL) { 6796 reply(550, "%s", globerr); 6797 goto globfree; 6798 } 6799 else if (dirlist == NULL) { 6800 errno = ENOENT; 6801 perror_reply(550, whichfiles); 6802 goto globfree; 6803 } 6804 } 6805 else { 6806 onefile[0] = whichfiles; 6807 dirlist = onefile; 6808 simple = 1; 6809 } 6810 6811 if (wu_setjmp(urgcatch)) { 6812 transflag = 0; 6813 if (dout != NULL) 6814 (void) fclose(dout); 6815 if (dirp != NULL) 6816 (void) closedir(dirp); 6817 data = -1; 6818 pdata = -1; 6819 goto globfree; 6820 } 6821 while ((dirname = *dirlist++) != NULL) { 6822 statret=stat(dirname, &st); 6823 if (statret < 0) 6824 statret=lstat(dirname, &st); /* Could be a dangling symlink */ 6825 if (statret < 0) { 6826 /* If user typed "ls -l", etc, and the client used NLST, do what 6827 * the user meant. */ 6828 if (dirname[0] == '-' && *dirlist == NULL && transflag == 0) { 6829 retrieve_is_data = 0; 6830 #ifndef INTERNAL_LS 6831 retrieve(ls_plain, dirname); 6832 #else 6833 ls(dirname, 1); 6834 #endif 6835 retrieve_is_data = 1; 6836 goto globfree; 6837 } 6838 perror_reply(550, dirname); 6839 if (dout != NULL) { 6840 (void) fclose(dout); 6841 transflag = 0; 6842 data = -1; 6843 pdata = -1; 6844 } 6845 goto globfree; 6846 } 6847 #ifndef NLST_SHOWS_DIRS 6848 if ((st.st_mode & S_IFMT) != S_IFDIR) 6849 #endif 6850 { 6851 if (dout == NULL) { 6852 dout = dataconn("file list", (off_t) - 1, "w"); 6853 if (dout == NULL) 6854 goto globfree; 6855 transflag++; 6856 draconian_FILE = dout; 6857 } 6858 if (draconian_FILE != NULL) { 6859 (void) signal(SIGALRM, draconian_alarm_signal); 6860 alarm(timeout_data); 6861 #if defined(USE_GSS) 6862 (void) sec_fprintf(dout, "%s%s\n", dirname, 6863 type == TYPE_A ? "\r" : ""); 6864 #else 6865 fprintf(dout, "%s%s\n", dirname, 6866 type == TYPE_A ? "\r" : ""); 6867 #endif /* USE_GSS */ 6868 } 6869 byte_count += strlen(dirname) + 1; 6870 #ifdef TRANSFER_COUNT 6871 byte_count_total += strlen(dirname) + 1; 6872 byte_count_out += strlen(dirname) + 1; 6873 if (type == TYPE_A) { 6874 byte_count_total++; 6875 byte_count_out++; 6876 } 6877 #endif 6878 } 6879 } 6880 6881 if (dout != NULL) { 6882 if (draconian_FILE != NULL) { 6883 (void) signal(SIGALRM, draconian_alarm_signal); 6884 alarm(timeout_data); 6885 #if defined(USE_GSS) 6886 if (sec_fflush(dout) < 0) { 6887 alarm(0); 6888 perror_reply(550, "Data connection"); 6889 goto sfl_cleanup; /* send file list cleanup */ 6890 } 6891 #else 6892 fflush(dout); 6893 #endif /* USE_GSS */ 6894 } 6895 if (draconian_FILE != NULL) { 6896 (void) signal(SIGALRM, draconian_alarm_signal); 6897 alarm(timeout_data); 6898 socket_flush_wait(dout); 6899 } 6900 } 6901 if (dout == NULL) 6902 reply(550, "No files found."); 6903 else if ((draconian_FILE == NULL) || ferror(dout) != 0) { 6904 alarm(0); 6905 perror_reply(550, "Data connection"); 6906 } 6907 else { 6908 #ifdef TRANSFER_COUNT 6909 xfer_count_total++; 6910 xfer_count_out++; 6911 #endif 6912 alarm(0); 6913 reply(226, "Transfer complete."); 6914 } 6915 sfl_cleanup: 6916 transflag = 0; 6917 if ((dout != NULL) && (draconian_FILE != NULL)) 6918 (void) fclose(dout); 6919 data = -1; 6920 pdata = -1; 6921 globfree: 6922 if (wildcard != NULL) { 6923 free(wildcard); 6924 wildcard = NULL; 6925 } 6926 if (sdirlist) { 6927 blkfree(sdirlist); 6928 free((char *) sdirlist); 6929 } 6930 } 6931 6932 /* 6934 ** SETPROCTITLE -- set process title for ps 6935 ** 6936 ** Parameters: 6937 ** fmt -- a printf style format string. 6938 ** a, b, c -- possible parameters to fmt. 6939 ** 6940 ** Returns: 6941 ** none. 6942 ** 6943 ** Side Effects: 6944 ** Clobbers argv of our main procedure so ps(1) will 6945 ** display the title. 6946 */ 6947 6948 #define SPT_NONE 0 /* don't use it at all */ 6949 #define SPT_REUSEARGV 1 /* cover argv with title information */ 6950 #define SPT_BUILTIN 2 /* use libc builtin */ 6951 #define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */ 6952 #define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */ 6953 #define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */ 6954 #define SPT_SCO 6 /* write kernel u. area */ 6955 #define SPT_CHANGEARGV 7 /* write our own strings into argv[] */ 6956 #define MAXLINE 2048 /* max line length for setproctitle */ 6957 #define SPACELEFT(buf, ptr) (sizeof buf - ((ptr) - buf)) 6958 6959 #ifndef SPT_TYPE 6960 #define SPT_TYPE SPT_REUSEARGV 6961 #endif 6962 6963 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN 6964 6965 #if SPT_TYPE == SPT_PSTAT 6966 #include <sys/pstat.h> 6967 #endif 6968 #if SPT_TYPE == SPT_PSSTRINGS 6969 #include <machine/vmparam.h> 6970 #include <sys/exec.h> 6971 #ifndef PS_STRINGS /* hmmmm.... apparently not available after all */ 6972 #undef SPT_TYPE 6973 #define SPT_TYPE SPT_REUSEARGV 6974 #else 6975 #ifndef NKPDE /* FreeBSD 2.0 */ 6976 #define NKPDE 63 6977 typedef unsigned int *pt_entry_t; 6978 #endif 6979 #endif 6980 #endif 6981 6982 #if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV 6983 #define SETPROC_STATIC static 6984 #else 6985 #define SETPROC_STATIC 6986 #endif 6987 6988 #if SPT_TYPE == SPT_SYSMIPS 6989 #include <sys/sysmips.h> 6990 #include <sys/sysnews.h> 6991 #endif 6992 6993 #if SPT_TYPE == SPT_SCO 6994 #ifdef UNIXWARE 6995 #include <sys/exec.h> 6996 #include <sys/ksym.h> 6997 #include <sys/proc.h> 6998 #include <sys/user.h> 6999 #else /* UNIXWARE */ 7000 #include <sys/immu.h> 7001 #include <sys/dir.h> 7002 #include <sys/user.h> 7003 #include <sys/fs/s5param.h> 7004 #endif /* UNIXWARE */ 7005 #if PSARGSZ > MAXLINE 7006 #define SPT_BUFSIZE PSARGSZ 7007 #endif 7008 #ifndef _PATH_KMEM 7009 #define _PATH_KMEM "/dev/kmem" 7010 #endif /* _PATH_KMEM */ 7011 #endif /* SPT_SCO */ 7012 7013 #ifndef SPT_PADCHAR 7014 #define SPT_PADCHAR ' ' 7015 #endif 7016 7017 #ifndef SPT_BUFSIZE 7018 #define SPT_BUFSIZE MAXLINE 7019 #endif 7020 7021 #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ 7022 7023 #if SPT_TYPE == SPT_REUSEARGV || SPT_TYPE == SPT_CHANGEARGV 7024 char **Argv = NULL; /* pointer to argument vector */ 7025 #endif 7026 7027 #if SPT_TYPE == SPT_REUSEARGV 7028 char *LastArgv = NULL; /* end of argv */ 7029 #endif 7030 7031 /* 7032 ** Pointers for setproctitle. 7033 ** This allows "ps" listings to give more useful information. 7034 */ 7035 void initsetproctitle(argc, argv, envp) 7036 int argc; 7037 char **argv; 7038 char **envp; 7039 { 7040 #if SPT_TYPE == SPT_REUSEARGV 7041 register int i, envpsize = 0; 7042 char **newenviron; 7043 extern char **environ; 7044 7045 /* 7046 ** Save start and extent of argv for setproctitle. 7047 */ 7048 7049 LastArgv = argv[argc - 1] + strlen(argv[argc - 1]); 7050 if (envp != NULL) { 7051 /* 7052 ** Move the environment so setproctitle can use the space at 7053 ** the top of memory. 7054 */ 7055 for (i = 0; envp[i] != NULL; i++) 7056 envpsize += strlen(envp[i]) + 1; 7057 newenviron = (char **) malloc(sizeof(char *) * (i + 1)); 7058 if (newenviron) { 7059 int err = 0; 7060 for (i = 0; envp[i] != NULL; i++) { 7061 if ((newenviron[i] = strdup(envp[i])) == NULL) { 7062 err = 1; 7063 break; 7064 } 7065 } 7066 if (err) { 7067 for (i = 0; newenviron[i] != NULL; i++) 7068 free(newenviron[i]); 7069 free(newenviron); 7070 i = 0; 7071 } 7072 else { 7073 newenviron[i] = NULL; 7074 environ = newenviron; 7075 } 7076 } 7077 else { 7078 i = 0; 7079 } 7080 7081 /* 7082 ** Find the last environment variable within wu-ftpd's 7083 ** process memory area. 7084 */ 7085 while (i > 0 && (envp[i - 1] < argv[0] || 7086 envp[i - 1] > (argv[argc - 1] + strlen(argv[argc - 1]) + 7087 1 + envpsize))) 7088 i--; 7089 7090 if (i > 0) 7091 LastArgv = envp[i - 1] + strlen(envp[i - 1]); 7092 } 7093 #endif /* SPT_TYPE == SPT_REUSEARGV */ 7094 7095 #if SPT_TYPE == SPT_REUSEARGV || SPT_TYPE == SPT_CHANGEARGV 7096 Argv = argv; 7097 #endif 7098 } 7099 7100 7101 #if SPT_TYPE != SPT_BUILTIN 7102 7103 /*VARARGS1 */ 7104 void setproctitle(const char *fmt,...) 7105 { 7106 #if SPT_TYPE != SPT_NONE 7107 register char *p; 7108 register int i; 7109 SETPROC_STATIC char buf[SPT_BUFSIZE]; 7110 VA_LOCAL_DECL 7111 #if SPT_TYPE == SPT_PSTAT 7112 union pstun pst; 7113 #endif 7114 #if SPT_TYPE == SPT_SCO 7115 static off_t seek_off; 7116 static int kmemfd = -1; 7117 static int kmempid = -1; 7118 #ifdef UNIXWARE 7119 off_t offset; 7120 void *ptr; 7121 struct mioc_rksym rks; 7122 #endif /* UNIXWARE */ 7123 #endif /* SPT_SCO */ 7124 7125 p = buf; 7126 7127 /* print ftpd: heading for grep */ 7128 (void) strcpy(p, "ftpd: "); 7129 p += strlen(p); 7130 7131 /* print the argument string */ 7132 VA_START(fmt); 7133 (void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap); 7134 VA_END; 7135 7136 i = strlen(buf); 7137 7138 #if SPT_TYPE == SPT_PSTAT 7139 pst.pst_command = buf; 7140 pstat(PSTAT_SETCMD, pst, i, 0, 0); 7141 #endif 7142 #if SPT_TYPE == SPT_PSSTRINGS 7143 PS_STRINGS->ps_nargvstr = 1; 7144 PS_STRINGS->ps_argvstr = buf; 7145 #endif 7146 #if SPT_TYPE == SPT_SYSMIPS 7147 sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf); 7148 #endif 7149 #if SPT_TYPE == SPT_SCO 7150 if (kmemfd < 0 || kmempid != getpid()) { 7151 if (kmemfd >= 0) 7152 close(kmemfd); 7153 if ((kmemfd = open(_PATH_KMEM, O_RDWR, 0)) < 0) 7154 return; 7155 (void) fcntl(kmemfd, F_SETFD, 1); 7156 kmempid = getpid(); 7157 #ifdef UNIXWARE 7158 seek_off = 0; 7159 rks.mirk_symname = "upointer"; 7160 rks.mirk_buf = &ptr; 7161 rks.mirk_buflen = sizeof(ptr); 7162 if (ioctl(kmemfd, MIOC_READKSYM, &rks) < 0) 7163 return; 7164 offset = (off_t) ptr + (off_t) & ((struct user *) 0)->u_procp; 7165 if (lseek(kmemfd, offset, SEEK_SET) != offset) 7166 return; 7167 if (read(kmemfd, &ptr, sizeof(ptr)) != sizeof(ptr)) 7168 return; 7169 offset = (off_t) ptr + (off_t) & ((struct proc *) 0)->p_execinfo; 7170 if (lseek(kmemfd, offset, SEEK_SET) != offset) 7171 return; 7172 if (read(kmemfd, &ptr, sizeof(ptr)) != sizeof(ptr)) 7173 return; 7174 seek_off = (off_t) ptr + (off_t) ((struct execinfo *) 0)->ei_psargs; 7175 #else /* UNIXWARE */ 7176 seek_off = UVUBLK + (off_t) & ((struct user *) 0)->u_psargs; 7177 #endif /* UNIXWARE */ 7178 } 7179 #ifdef UNIXWARE 7180 if (seek_off == 0) 7181 return; 7182 #endif /* UNIXWARE */ 7183 buf[PSARGSZ - 1] = '\0'; 7184 if (lseek(kmemfd, (off_t) seek_off, SEEK_SET) == seek_off) 7185 (void) write(kmemfd, buf, PSARGSZ); 7186 #endif /* SPT_SCO */ 7187 #if SPT_TYPE == SPT_REUSEARGV 7188 if (i > LastArgv - Argv[0] - 2) { 7189 i = LastArgv - Argv[0] - 2; 7190 buf[i] = '\0'; 7191 } 7192 (void) strcpy(Argv[0], buf); 7193 p = &Argv[0][i]; 7194 while (p < LastArgv) 7195 *p++ = SPT_PADCHAR; 7196 Argv[1] = NULL; 7197 #endif 7198 #if SPT_TYPE == SPT_CHANGEARGV 7199 Argv[0] = buf; 7200 Argv[1] = 0; 7201 #endif 7202 #endif /* SPT_TYPE != SPT_NONE */ 7203 } 7204 7205 #endif /* SPT_TYPE != SPT_BUILTIN */ 7206 7207 #ifdef KERBEROS 7208 /* thanks to gshapiro (at) wpi.wpi.edu for the following kerberosities */ 7209 7210 void init_krb() 7211 { 7212 char hostname[100]; 7213 7214 #ifdef HAVE_SYSINFO 7215 if (sysinfo(SI_HOSTNAME, hostname, sizeof(hostname)) < 0) { 7216 perror("sysinfo"); 7217 #else 7218 if (gethostname(hostname, sizeof(hostname)) < 0) { 7219 perror("gethostname"); 7220 #endif 7221 exit(1); 7222 } 7223 if (strchr(hostname, '.')) 7224 *(strchr(hostname, '.')) = 0; 7225 7226 sprintf(krb_ticket_name, "/var/dss/kerberos/tkt/tkt.%d", getpid()); 7227 krb_set_tkt_string(krb_ticket_name); 7228 7229 config_auth(); 7230 7231 if (krb_svc_init("hesiod", hostname, (char *) NULL, 0, (char *) NULL, 7232 (char *) NULL) != KSUCCESS) { 7233 fprintf(stderr, "Couldn't initialize Kerberos\n"); 7234 exit(1); 7235 } 7236 } 7237 7238 void end_krb() 7239 { 7240 unlink(krb_ticket_name); 7241 } 7242 7243 #endif /* KERBEROS */ 7244 7245 #ifdef ULTRIX_AUTH 7246 static int ultrix_check_pass(char *passwd, char *xpasswd) 7247 { 7248 struct svcinfo *svp; 7249 int auth_status; 7250 7251 if ((svp = getsvc()) == (struct svcinfo *) NULL) { 7252 syslog(LOG_WARNING, "getsvc() failed in ultrix_check_pass"); 7253 return -1; 7254 } 7255 if (pw == (struct passwd *) NULL) { 7256 return -1; 7257 } 7258 if (((svp->svcauth.seclevel == SEC_UPGRADE) && 7259 (!strcmp(pw->pw_passwd, "*"))) 7260 || (svp->svcauth.seclevel == SEC_ENHANCED)) { 7261 if ((auth_status = authenticate_user(pw, passwd, "/dev/ttypXX")) >= 0) { 7262 /* Indicate successful validation */ 7263 return auth_status; 7264 } 7265 if (auth_status < 0 && errno == EPERM) { 7266 /* Log some information about the failed login attempt. */ 7267 switch (abs(auth_status)) { 7268 case A_EBADPASS: 7269 break; 7270 case A_ESOFTEXP: 7271 syslog(LOG_NOTICE, "password will expire soon for user %s", 7272 pw->pw_name); 7273 break; 7274 case A_EHARDEXP: 7275 syslog(LOG_NOTICE, "password has expired for user %s", 7276 pw->pw_name); 7277 break; 7278 case A_ENOLOGIN: 7279 syslog(LOG_NOTICE, "user %s attempted login to disabled acct", 7280 pw->pw_name); 7281 break; 7282 } 7283 } 7284 } 7285 else { 7286 if ((*pw->pw_passwd != '\0') && (!strcmp(xpasswd, pw->pw_passwd))) { 7287 /* passwd in /etc/passwd isn't empty && encrypted passwd matches */ 7288 return 0; 7289 } 7290 } 7291 return -1; 7292 } 7293 #endif /* ULTRIX_AUTH */ 7294 7295 #ifdef USE_PAM 7296 /* This is rather an abuse of PAM, but the FTP protocol doesn't allow much 7297 * flexibility here. :-( 7298 */ 7299 7300 /* Static variables used to communicate between the conversation function 7301 * and the server_login function 7302 */ 7303 static char *PAM_password; 7304 7305 /* PAM conversation function 7306 * Here we assume (for now, at least) that echo on means login name, and 7307 * echo off means password. 7308 */ 7309 #ifdef SOLARIS_2 7310 /* Workaround bug 4430970/4413889 which causes a compiler warning, necessary 7311 * as usr/src/Makefile.master now includes "-errwarn=%all". 7312 */ 7313 static int PAM_conv(int num_msg, struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) 7314 #else 7315 static int PAM_conv(int num_msg, const struct pam_message **msg, struct pam_response **resp, void *appdata_ptr) 7316 #endif 7317 { 7318 int replies = 0; 7319 struct pam_response *reply = NULL; 7320 7321 #define COPY_STRING(s) (s) ? strdup(s) : NULL 7322 7323 reply = malloc(sizeof(struct pam_response) * num_msg); 7324 if (!reply) 7325 return PAM_CONV_ERR; 7326 7327 for (replies = 0; replies < num_msg; replies++) { 7328 switch (msg[replies]->msg_style) { 7329 case PAM_PROMPT_ECHO_ON: 7330 return PAM_CONV_ERR; 7331 break; 7332 case PAM_PROMPT_ECHO_OFF: 7333 reply[replies].resp_retcode = PAM_SUCCESS; 7334 reply[replies].resp = COPY_STRING(PAM_password); 7335 /* PAM frees resp */ 7336 break; 7337 case PAM_TEXT_INFO: 7338 /* ignore it... */ 7339 reply[replies].resp_retcode = PAM_SUCCESS; 7340 reply[replies].resp = NULL; 7341 break; 7342 case PAM_ERROR_MSG: 7343 /* ignore it... */ 7344 reply[replies].resp_retcode = PAM_SUCCESS; 7345 reply[replies].resp = NULL; 7346 break; 7347 default: 7348 /* Must be an error of some sort... */ 7349 return PAM_CONV_ERR; 7350 } 7351 } 7352 *resp = reply; 7353 return PAM_SUCCESS; 7354 } 7355 static struct pam_conv PAM_conversation = 7356 { 7357 &PAM_conv, 7358 NULL 7359 }; 7360 7361 static int pam_check_pass(char *user, char *passwd) 7362 { 7363 char tty[20]; 7364 int pam_session = 0; 7365 7366 /* Now use PAM to do authentication and session logging. Bail out if 7367 * there are any errors. Since this is a limited protocol, and an even 7368 * more limited function within a server speaking this protocol, we 7369 * can't be as verbose as would otherwise make sense. 7370 */ 7371 PAM_password = passwd; 7372 pamh = (pam_handle_t *)0; 7373 if (pam_start("ftp", user, &PAM_conversation, &pamh) != PAM_SUCCESS) 7374 return 0; 7375 7376 #if ((defined(BSD) && (BSD >= 199103)) || defined(sun)) 7377 (void) sprintf(tty, "/dev/ftp%ld", (long) getpid()); 7378 #else 7379 (void) sprintf(tty, "/dev/ftpd%d", getpid()); 7380 #endif 7381 7382 if (pam_set_item(pamh, PAM_TTY, tty) !=