ftpd.c
上传用户:zibowangxu
上传日期:2007-01-04
资源大小:331k
文件大小:183k
源码类别:

Ftp客户端

开发平台:

Unix_Linux

  1. /****************************************************************************  
  2.  
  3.   Copyright (c) 1999 WU-FTPD Development Group.  
  4.   All rights reserved.
  5.   
  6.   Portions Copyright (c) 1980, 1985, 1988, 1989, 1990, 1991, 1993, 1994
  7.     The Regents of the University of California.
  8.   Portions Copyright (c) 1993, 1994 Washington University in Saint Louis.
  9.   Portions Copyright (c) 1996, 1998 Berkeley Software Design, Inc.
  10.   Portions Copyright (c) 1989 Massachusetts Institute of Technology.
  11.   Portions Copyright (c) 1998 Sendmail, Inc.
  12.   Portions Copyright (c) 1983, 1995, 1996, 1997 Eric P.  Allman.
  13.   Portions Copyright (c) 1997 by Stan Barber.
  14.   Portions Copyright (c) 1997 by Kent Landfield.
  15.   Portions Copyright (c) 1991, 1992, 1993, 1994, 1995, 1996, 1997
  16.     Free Software Foundation, Inc.  
  17.  
  18.   Use and distribution of this software and its source code are governed 
  19.   by the terms and conditions of the WU-FTPD Software License ("LICENSE").
  20.  
  21.   If you did not receive a copy of the license, it may be obtained online
  22.   at http://www.wu-ftpd.org/license.html.
  23.  
  24.   $Id: ftpd.c,v 1.106 1999/10/14 14:41:47 wuftpd Exp $
  25.  
  26. ****************************************************************************/
  27. /* FTP server. */
  28. #include "config.h"
  29. #include <sys/types.h>
  30. #include <sys/param.h>
  31. #include <sys/stat.h>
  32. #include <sys/ioctl.h>
  33. #include <sys/socket.h>
  34. #include <sys/file.h>
  35. #include <sys/wait.h>
  36. #ifdef AIX
  37. #include <sys/id.h>
  38. #include <sys/priv.h>
  39. #include <netinet/if_ether.h>
  40. #include <net/if_dl.h>
  41. #endif
  42. #ifdef AUX
  43. #include <compat.h>
  44. #endif
  45. #include <netinet/in.h>
  46. #include <netinet/in_systm.h>
  47. #include <netinet/ip.h>
  48. #define FTP_NAMES
  49. #include "../support/ftp.h"
  50. #include <arpa/inet.h>
  51. #include <arpa/telnet.h>
  52. #include <ctype.h>
  53. #include <stdio.h>
  54. #include <stdlib.h>
  55. #include <signal.h>
  56. #include <pwd.h>
  57. #include <grp.h>
  58. #include <setjmp.h>
  59. #include <errno.h>
  60. #include <string.h>
  61. #ifdef INTERNAL_LS
  62. #ifdef HAVE_GLOB_H
  63. #include <glob.h>
  64. #else
  65. #include <wuftpd_glob.h>
  66. #endif
  67. #endif
  68. #ifdef HAVE_GRP_H
  69. #include <grp.h>
  70. #endif
  71. #include <sys/stat.h>
  72. #define VA_LOCAL_DECL va_list ap;
  73. #define VA_START(f) va_start(ap, f)
  74. #define VA_END va_end(ap)
  75. #include "proto.h"
  76. #ifdef HAVE_UFS_QUOTA_H
  77. #include <ufs/quota.h>
  78. #endif
  79. #ifdef HAVE_SYS_FS_UFS_QUOTA_H
  80. #include <sys/fs/ufs_quota.h>
  81. #endif
  82. #ifdef HAVE_SYS_SYSLOG_H
  83. #include <sys/syslog.h>
  84. #endif
  85. #if defined(HAVE_SYSLOG_H) || (!defined(AUTOCONF) && !defined(HAVE_SYS_SYSLOG_H))
  86. #include <syslog.h>
  87. #endif
  88. #ifdef TIME_WITH_SYS_TIME
  89. #include <time.h>
  90. #include <sys/time.h>
  91. #else
  92. #ifdef HAVE_SYS_TIME_H
  93. #include <sys/time.h>
  94. #else
  95. #include <time.h>
  96. #endif
  97. #endif
  98. #include "conversions.h"
  99. #include "extensions.h"
  100. #ifdef SHADOW_PASSWORD
  101. #include <shadow.h>
  102. #endif
  103. #include "pathnames.h"
  104. #ifdef M_UNIX
  105. #include <arpa/nameser.h>
  106. #include <resolv.h>
  107. #endif
  108. #if defined(HAVE_FCNTL_H)
  109. #include <fcntl.h>
  110. #endif
  111. #ifdef HAVE_SYSINFO
  112. #include <sys/systeminfo.h>
  113. #endif
  114. #ifdef KERBEROS
  115. #include <sys/types.h>
  116. #include <auth.h>
  117. #include <krb.h>
  118. #endif
  119. #ifdef ULTRIX_AUTH
  120. #include <auth.h>
  121. #include <sys/svcinfo.h>
  122. #endif
  123. #ifndef HAVE_LSTAT
  124. #define lstat stat
  125. #endif
  126. #ifdef AFS_AUTH
  127. #include <afs/stds.h>
  128. #include <afs/kautils.h>
  129. #endif
  130. #ifdef DCE_AUTH
  131. #include <dce/rpc.h>
  132. #include <dce/sec_login.h>
  133. #include <dce/dce_error.h>
  134. #endif
  135. #ifdef HAVE_DIRENT_H
  136. #include <dirent.h>
  137. #else
  138. #include <sys/dir.h>
  139. #endif
  140. #ifdef HAVE_GETRLIMIT
  141. #include <sys/resource.h>
  142. #endif
  143. #if defined(USE_LONGJMP)
  144. #define wu_longjmp(x, y) longjmp((x), (y))
  145. #define wu_setjmp(x) setjmp(x)
  146. #ifndef JMP_BUF
  147. #define JMP_BUF jmp_buf
  148. #endif
  149. #else
  150. #define wu_longjmp(x, y) siglongjmp((x), (y))
  151. #define wu_setjmp(x) sigsetjmp((x), 1)
  152. #ifndef JMP_BUF
  153. #define JMP_BUF sigjmp_buf
  154. #endif
  155. #endif
  156. #ifndef MAXHOSTNAMELEN
  157. #define MAXHOSTNAMELEN 64 /* may be too big */
  158. #endif
  159. #ifndef TRUE
  160. #define  TRUE   1
  161. #endif
  162. #ifndef FALSE
  163. #define  FALSE  !TRUE
  164. #endif
  165. #ifdef MAIL_ADMIN
  166. #define MAILSERVERS 10
  167. #define INCMAILS 10
  168. int mailservers = 0;
  169. char *mailserver[MAILSERVERS];
  170. int incmails = 0;
  171. char *incmail[INCMAILS];
  172. char *mailfrom;
  173. char *email(char *full_address);
  174. FILE *SockOpen(char *host, int clientPort);
  175. char *SockGets(FILE *sockfp, char *buf, int len);
  176. int SockWrite(char *buf, int size, int nels, FILE *sockfp);
  177. int SockPrintf(FILE *sockfp, char *format,...);
  178. int SockPuts(FILE *sockfp, char *buf);
  179. int Reply(FILE *sockfp);
  180. int Send(FILE *sockfp, char *format,...);
  181. #endif /* MAIL_ADMIN */
  182. #if defined(_SCO_DS) && !defined(SIGURG)
  183. #define SIGURG SIGUSR1
  184. #endif
  185. /* File containing login names NOT to be used on this machine. Commonly used
  186.  * to disallow uucp. */
  187. extern int errno;
  188. extern int pidfd;
  189. extern char *ctime(const time_t *);
  190. #ifndef NO_CRYPT_PROTO
  191. extern char *crypt(const char *, const char *);
  192. #endif
  193. extern char version[];
  194. extern char *home; /* pointer to home directory for glob */
  195. extern char cbuf[];
  196. extern off_t restart_point;
  197. extern int yyerrorcalled;
  198. struct sockaddr_in ctrl_addr;
  199. struct sockaddr_in data_source;
  200. struct sockaddr_in data_dest;
  201. struct sockaddr_in his_addr;
  202. struct sockaddr_in pasv_addr;
  203. struct sockaddr_in vect_addr;
  204. int route_vectored = 0;
  205. int passive_port_min = -1;
  206. int passive_port_max = -1;
  207. int restricted_user = 0;
  208. #ifdef VIRTUAL
  209. char virtual_root[MAXPATHLEN];
  210. char virtual_banner[MAXPATHLEN];
  211. char virtual_email[MAXPATHLEN];
  212. char virtual_hostname[MAXHOSTNAMELEN];
  213. char virtual_address[MAXHOSTNAMELEN];
  214. char hostaddress[32];
  215. extern int virtual_mode;
  216. extern int virtual_ftpaccess;
  217. #endif
  218. #ifdef QUOTA
  219. extern struct dqblk quota;
  220. #endif
  221. int data;
  222. jmp_buf errcatch;
  223. JMP_BUF urgcatch;
  224. int logged_in = 0;
  225. struct passwd *pw;
  226. char chroot_path[MAXPATHLEN];
  227. int debug = 0;
  228. int disable_rfc931 = 0;
  229. extern unsigned int timeout_idle;
  230. extern unsigned int timeout_maxidle;
  231. extern unsigned int timeout_data;
  232. extern unsigned int timeout_accept;
  233. extern unsigned int timeout_connect;
  234. /* previously defaulted to 1, and -l or -L set them to 1, so that there was
  235.    no way to turn them *off*!  Changed so that the manpage reflects common
  236.    sense.  -L is way noisy; -l we'll change to be "just right".  _H */
  237. int logging = 0;
  238. int log_commands = 0;
  239. int log_security = 0;
  240. int syslogmsg = 0;
  241. static int wtmp_logging = 1;
  242. #ifdef SECUREOSF
  243. #define SecureWare /* Does this mean it works for all SecureWare? */
  244. #endif
  245. #ifdef HPUX_10_TRUSTED
  246. #include <hpsecurity.h>
  247. #endif
  248. #if defined(SecureWare) || defined(HPUX_10_TRUSTED)
  249. #include <prot.h>
  250. #endif
  251. int anonymous = 1;
  252. int guest;
  253. int type;
  254. int form;
  255. int stru; /* avoid C keyword */
  256. int mode;
  257. int usedefault = 1; /* for data transfers */
  258. int pdata = -1; /* for passive mode */
  259. int transflag;
  260. int ftwflag;
  261. off_t file_size;
  262. off_t byte_count;
  263. int TCPwindowsize = 0; /* 0 = use system default */
  264. #ifdef TRANSFER_COUNT
  265. int data_count_total = 0; /* total number of data bytes */
  266. int data_count_in = 0;
  267. int data_count_out = 0;
  268. int byte_count_total = 0; /* total number of general traffic */
  269. int byte_count_in = 0;
  270. int byte_count_out = 0;
  271. int file_count_total = 0; /* total number of data files */
  272. int file_count_in = 0;
  273. int file_count_out = 0;
  274. int xfer_count_total = 0; /* total number of transfers */
  275. int xfer_count_in = 0;
  276. int xfer_count_out = 0;
  277. #ifdef TRANSFER_LIMIT
  278. int file_limit_raw_in = 0;
  279. int file_limit_raw_out = 0;
  280. int file_limit_raw_total = 0;
  281. int file_limit_data_in = 0;
  282. int file_limit_data_out = 0;
  283. int file_limit_data_total = 0;
  284. int data_limit_raw_in = 0;
  285. int data_limit_raw_out = 0;
  286. int data_limit_raw_total = 0;
  287. int data_limit_data_in = 0;
  288. int data_limit_data_out = 0;
  289. int data_limit_data_total = 0;
  290. #endif
  291. #endif
  292. int retrieve_is_data = 1; /* !0=data, 0=general traffic -- for 'ls' */
  293. char LastFileTransferred[MAXPATHLEN] = "";
  294. static char *RootDirectory = NULL;
  295. #if !defined(CMASK) || CMASK == 0
  296. #undef CMASK
  297. #define CMASK 022
  298. #endif
  299. mode_t defumask = CMASK; /* default umask value */
  300. #ifdef ALTERNATE_CD
  301. char defhome[] = "/";
  302. #endif
  303. char tmpline[7];
  304. char hostname[MAXHOSTNAMELEN];
  305. char remotehost[MAXHOSTNAMELEN];
  306. char remoteaddr[MAXHOSTNAMELEN];
  307. char *remoteident = "[nowhere yet]";
  308. /* log failures         27-apr-93 ehk/bm */
  309. #ifdef LOG_FAILED
  310. #define MAXUSERNAMELEN 256
  311. char the_user[MAXUSERNAMELEN];
  312. #endif
  313. /* Access control and logging passwords */
  314. /* OFF by default.  _H */
  315. int use_accessfile = 0;
  316. char guestpw[MAXHOSTNAMELEN];
  317. char privatepw[MAXHOSTNAMELEN];
  318. int nameserved = 0;
  319. extern char authuser[];
  320. extern int authenticated;
  321. extern int keepalive;
  322. /* File transfer logging */
  323. int xferlog = 0;
  324. int log_outbound_xfers = 0;
  325. int log_incoming_xfers = 0;
  326. char logfile[MAXPATHLEN];
  327. /* Allow use of lreply(); this is here since some older FTP clients don't
  328.  * support continuation messages.  In violation of the RFCs... */
  329. int dolreplies = 1;
  330. /* Spontaneous reply text.  To be sent along with next reply to user */
  331. char *autospout = NULL;
  332. int autospout_free = 0;
  333. /* allowed on-the-fly file manipulations (compress, tar) */
  334. int mangleopts = 0;
  335. /* number of login failures before attempts are logged and FTP *EXITS* */
  336. int lgi_failure_threshold = 5;
  337. /* Timeout intervals for retrying connections to hosts that don't accept PORT
  338.  * cmds.  This is a kludge, but given the problems with TCP... */
  339. #define SWAITMAX    90 /* wait at most 90 seconds */
  340. #define SWAITINT    5 /* interval between retries */
  341. int swaitmax = SWAITMAX;
  342. int swaitint = SWAITINT;
  343. SIGNAL_TYPE lostconn(int sig);
  344. SIGNAL_TYPE randomsig(int sig);
  345. SIGNAL_TYPE myoob(int sig);
  346. FILE *getdatasock(char *mode);
  347. FILE *dataconn(char *name, off_t size, char *mode);
  348. void setproctitle(const char *fmt,...);
  349. void initsetproctitle(int, char **, char **);
  350. void reply(int, char *fmt,...);
  351. void lreply(int, char *fmt,...);
  352. #ifndef HAVE_VSNPRINTF
  353. extern int vsnprintf(char *, size_t, const char *, va_list);
  354. #endif
  355. #ifndef HAVE_SNPRINTF
  356. extern int snprintf(char *, size_t, const char *,...);
  357. #endif
  358. #ifdef HAVE_LIBRESOLV
  359. int initialize_dns(struct sockaddr_in *remote_socket);
  360. int check_reverse_dns(void);
  361. int check_matching_dns(void);
  362. #endif
  363. #ifdef NEED_SIGFIX
  364. extern sigset_t block_sigmask; /* defined in sigfix.c */
  365. #endif
  366. char proctitle[BUFSIZ]; /* initial part of title */
  367. #if defined(SKEY) && defined(OPIE)
  368. #error YOU SHOULD NOT HAVE BOTH SKEY AND OPIE DEFINED!!!!!
  369. #endif
  370. #ifdef SKEY
  371. #include <skey.h>
  372. int pwok = 0;
  373. #endif
  374. #ifdef OPIE
  375. #include <opie.h>
  376. int pwok = 0;
  377. int af_pwok = 0;
  378. struct opie opiestate;
  379. #endif
  380. #ifdef KERBEROS
  381. void init_krb();
  382. void end_krb();
  383. char krb_ticket_name[100];
  384. #endif /* KERBEROS */
  385. #ifdef ULTRIX_AUTH
  386. int ultrix_check_pass(char *passwd, char *xpasswd);
  387. #endif
  388. #ifdef USE_PAM
  389. #if defined(ULTRIX_AUTH) || defined(SHADOW_PASSWORD) || defined(SECUREOSF) || defined(KERBEROS) || defined(SKEY) || defined (OPIE) || defined (BSD_AUTH)
  390. #error No other auth methods are allowed with PAM.
  391. #endif
  392. static int pam_check_pass(char *user, char *passwd);
  393. #endif
  394. #ifndef INTERNAL_LS
  395. /* ls program commands and options for lreplies on and off */
  396. char ls_long[1024];
  397. char ls_short[1024];
  398. char ls_plain[1024];
  399. #endif
  400. #ifdef DAEMON
  401. int be_daemon = 0; /* Run standalone? */
  402. int daemon_port = 0;
  403. void do_daemon(int argc, char **argv, char **envp);
  404. #endif
  405. int Bypass_PID_Files = 0;
  406. void end_login(void);
  407. void print_copyright(void);
  408. char *mapping_getcwd(char *path, size_t size);
  409. #ifdef THROUGHPUT
  410. int send_data(char *name, FILE *, FILE *, off_t);
  411. #else
  412. int send_data(FILE *, FILE *, off_t);
  413. #endif
  414. void dolog(struct sockaddr_in *);
  415. void dologout(int);
  416. void perror_reply(int, char *);
  417. int denieduid(uid_t);
  418. int alloweduid(uid_t);
  419. int deniedgid(gid_t);
  420. int allowedgid(gid_t);
  421. int restricteduid(uid_t);
  422. int unrestricteduid(uid_t);
  423. int restrictedgid(gid_t);
  424. int unrestrictedgid(gid_t);
  425. #ifdef THROUGHPUT
  426. extern void throughput_calc(char *, int *, double *);
  427. extern void throughput_adjust(char *);
  428. #endif
  429. time_t login_time;
  430. time_t limit_time = 0;
  431. int regexmatch(char *name, char *rgexp);
  432. int pasv_allowed(char *remoteaddr);
  433. int port_allowed(char *remoteaddr);
  434. #if sparc && !__svr4__
  435. int fclose(FILE *);
  436. #endif
  437. static SIGNAL_TYPE alarm_signal(int sig)
  438. {
  439. }
  440. static FILE *draconian_FILE = NULL;
  441. static SIGNAL_TYPE draconian_alarm_signal(int sig)
  442. {
  443.     if (draconian_FILE != NULL) {
  444. fclose(draconian_FILE);
  445. draconian_FILE = NULL;
  446.     }
  447. }
  448. static void socket_flush_wait(FILE *file)
  449. {
  450. #ifndef SUPPORT_BROKEN_CLIENTS
  451.     char c;
  452.     int fd = fileno(file);
  453.     if (draconian_FILE != NULL)
  454. shutdown(fd, 1);
  455.     if (draconian_FILE != NULL)
  456. read(fd, &c, 1);
  457. /*
  458.  * GAL - the read() here should be checked to ensure it returned 0 (indicating
  459.  * EOF) or -1 (an error occurred).  Anything else (real data) is a protocol
  460.  * error.
  461.  */
  462. #endif
  463. }
  464. int main(int argc, char **argv, char **envp)
  465. {
  466. #if defined(UNIXWARE) || defined(AIX)
  467.     size_t addrlen;
  468. #else
  469.     int addrlen;
  470. #endif
  471.     int on = 1;
  472. #ifdef IPTOS_LOWDELAY
  473.     int tos;
  474. #endif
  475.     int c;
  476. #ifndef INTERNAL_LS
  477.     int which;
  478. #endif
  479.     extern int optopt;
  480.     extern char *optarg;
  481.     struct hostent *shp;
  482.     struct aclmember *entry;
  483. #ifdef VIRTUAL
  484. #if defined(UNIXWARE) || defined(AIX)
  485.     size_t virtual_len;
  486. #else
  487.     int virtual_len;
  488. #endif
  489.     struct sockaddr_in *virtual_ptr;
  490.     struct sockaddr_in virtual_addr;
  491. #endif
  492. #ifndef DAEMON
  493.     struct servent *serv;
  494. #endif
  495. #ifdef AUX
  496.     setcompat(COMPAT_POSIX | COMPAT_BSDSETUGID);
  497. #endif
  498.     closelog();
  499. #ifdef FACILITY
  500.     openlog("ftpd", LOG_PID | LOG_NDELAY, FACILITY);
  501. #else
  502.     openlog("ftpd", LOG_PID);
  503. #endif
  504. #ifdef SecureWare
  505.     setluid(1); /* make sure there is a valid luid */
  506.     set_auth_parameters(argc, argv);
  507.     setreuid(0, 0);
  508. #endif
  509. #if defined(M_UNIX) && !defined(_M_UNIX)
  510.     res_init(); /* bug in old (1.1.1) resolver     */
  511.     _res.retrans = 20; /* because of fake syslog in 3.2.2 */
  512.     setlogmask(LOG_UPTO(LOG_INFO));
  513. #endif
  514. #ifndef DAEMON
  515.     addrlen = sizeof(his_addr);
  516.     if (getpeername(0, (struct sockaddr *) &his_addr, &addrlen) < 0) {
  517. syslog(LOG_ERR, "getpeername (%s): %m", argv[0]);
  518. #ifndef DEBUG
  519. exit(1);
  520. #endif
  521.     }
  522.     addrlen = sizeof(ctrl_addr);
  523.     if (getsockname(0, (struct sockaddr *) &ctrl_addr, &addrlen) < 0) {
  524. syslog(LOG_ERR, "getsockname (%s): %m", argv[0]);
  525. #ifndef DEBUG
  526. exit(1);
  527. #endif
  528.     }
  529. #ifdef IPTOS_LOWDELAY
  530.     tos = IPTOS_LOWDELAY;
  531.     if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0)
  532.     syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
  533. #endif
  534.     serv = getservbyname("ftp-data", "tcp");
  535.     if (serv != NULL)
  536. data_source.sin_port = serv->s_port;
  537.     else
  538. data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
  539. #endif /* DAEMON */
  540. #ifndef DAEMON
  541.     while ((c = getopt(argc, argv, ":aAvdlLiIoP:qQr:t:T:u:wVWX")) != -1) {
  542. #else /* DAEMON */
  543.     while ((c = getopt(argc, argv, ":aAvdlLiIop:P:qQr:sSt:T:u:VwWX")) != -1) {
  544. #endif /* DAEMON */
  545. switch (c) {
  546. case 'a':
  547.     use_accessfile = 1;
  548.     break;
  549. case 'A':
  550.     use_accessfile = 0;
  551.     break;
  552. case 'v':
  553.     debug = 1;
  554.     break;
  555. case 'd':
  556.     debug = 1;
  557.     break;
  558. case 'l':
  559.     logging = 1;
  560.     break;
  561. case 'L':
  562.     log_commands = 1;
  563.     break;
  564. case 'i':
  565.     log_incoming_xfers = 1;
  566.     break;
  567. case 'I':
  568.     disable_rfc931 = 1;
  569.     break;
  570. case 'o':
  571.     log_outbound_xfers = 1;
  572.     break;
  573. case 'q':
  574.     Bypass_PID_Files = 0;
  575.     break;
  576. case 'Q':
  577.     Bypass_PID_Files = 1;
  578.     break;
  579. case 'r':
  580.     if ((optarg != NULL) && (optarg[0] != '')) {
  581. RootDirectory = malloc(strlen(optarg) + 1);
  582. if (RootDirectory != NULL)
  583.     strcpy(RootDirectory, optarg);
  584.     }
  585.     break;
  586. case 'P':
  587.     data_source.sin_port = htons(atoi(optarg));
  588.     break;
  589. #ifdef DAEMON
  590. case 'p':
  591.     daemon_port = atoi(optarg);
  592.     break;
  593. case 's':
  594.     be_daemon = 1;
  595.     break;
  596. case 'S':
  597.     be_daemon = 2;
  598.     break;
  599. #endif /* DAEMON */
  600. case 't':
  601.     timeout_idle = atoi(optarg);
  602.     if (timeout_maxidle < timeout_idle)
  603. timeout_maxidle = timeout_idle;
  604.     break;
  605. case 'T':
  606.     timeout_maxidle = atoi(optarg);
  607.     if (timeout_idle > timeout_maxidle)
  608. timeout_idle = timeout_maxidle;
  609.     break;
  610. case 'u':
  611.     {
  612. unsigned int val = 0;
  613. while (*optarg && *optarg >= '0' && *optarg <= '9')
  614.     val = val * 8 + *optarg++ - '0';
  615. if (*optarg || val > 0777)
  616.     syslog(LOG_ERR, "bad value for -u");
  617. else
  618.     defumask = val;
  619. break;
  620.     }
  621. case 'V':
  622.     print_copyright();
  623.     exit(0);
  624.     /* NOTREACHED */
  625. case 'w':
  626.     wtmp_logging = 1;
  627.     break;
  628. case 'W':
  629.     wtmp_logging = 0;
  630.     break;
  631. case 'x':
  632.     syslogmsg = 2;
  633.     break;
  634. case 'X':
  635.     syslogmsg = 1;
  636.     break;
  637. case ':':
  638.     syslog(LOG_ERR, "option -%c requires an argument", optopt);
  639.     break;
  640. default:
  641.     syslog(LOG_ERR, "unknown option -%c ignored", optopt);
  642.     break;
  643. }
  644.     }
  645.     initsetproctitle(argc, argv, envp);
  646.     (void) freopen(_PATH_DEVNULL, "w", stderr);
  647.     /* Checking for random signals ... */
  648. #ifdef NEED_SIGFIX
  649.     sigemptyset(&block_sigmask);
  650. #endif
  651. #ifndef SIG_DEBUG
  652. #ifdef SIGHUP
  653.     (void) signal(SIGHUP, randomsig);
  654. #ifdef NEED_SIGFIX
  655.     sigaddset(&block_sigmask, SIGHUP);
  656. #endif
  657. #endif
  658. #ifdef SIGINT
  659.     (void) signal(SIGINT, randomsig);
  660. #ifdef NEED_SIGFIX
  661.     sigaddset(&block_sigmask, SIGINT);
  662. #endif
  663. #endif
  664. #ifdef SIGQUIT
  665.     (void) signal(SIGQUIT, randomsig);
  666. #ifdef NEED_SIGFIX
  667.     sigaddset(&block_sigmask, SIGQUIT);
  668. #endif
  669. #endif
  670. #ifdef SIGILL
  671.     (void) signal(SIGILL, randomsig);
  672. #ifdef NEED_SIGFIX
  673.     sigaddset(&block_sigmask, SIGILL);
  674. #endif
  675. #endif
  676. #ifdef SIGTRAP
  677.     (void) signal(SIGTRAP, randomsig);
  678. #ifdef NEED_SIGFIX
  679.     sigaddset(&block_sigmask, SIGTRAP);
  680. #endif
  681. #endif
  682. #ifdef SIGIOT
  683.     (void) signal(SIGIOT, randomsig);
  684. #ifdef NEED_SIGFIX
  685.     sigaddset(&block_sigmask, SIGIOT);
  686. #endif
  687. #endif
  688. #ifdef SIGEMT
  689.     (void) signal(SIGEMT, randomsig);
  690. #ifdef NEED_SIGFIX
  691.     sigaddset(&block_sigmask, SIGEMT);
  692. #endif
  693. #endif
  694. #ifdef SIGFPE
  695.     (void) signal(SIGFPE, randomsig);
  696. #ifdef NEED_SIGFIX
  697.     sigaddset(&block_sigmask, SIGFPE);
  698. #endif
  699. #endif
  700. #ifdef SIGKILL
  701.     (void) signal(SIGKILL, randomsig);
  702. #ifdef NEED_SIGFIX
  703.     sigaddset(&block_sigmask, SIGKILL);
  704. #endif
  705. #endif
  706. #ifdef SIGBUS
  707.     (void) signal(SIGBUS, randomsig);
  708. #ifdef NEED_SIGFIX
  709.     sigaddset(&block_sigmask, SIGBUS);
  710. #endif
  711. #endif
  712. #ifdef SIGSEGV
  713.     (void) signal(SIGSEGV, randomsig);
  714. #ifdef NEED_SIGFIX
  715.     sigaddset(&block_sigmask, SIGSEGV);
  716. #endif
  717. #endif
  718. #ifdef SIGSYS
  719.     (void) signal(SIGSYS, randomsig);
  720. #ifdef NEED_SIGFIX
  721.     sigaddset(&block_sigmask, SIGSYS);
  722. #endif
  723. #endif
  724. #ifdef SIGALRM
  725.     (void) signal(SIGALRM, randomsig);
  726. #ifdef NEED_SIGFIX
  727.     sigaddset(&block_sigmask, SIGALRM);
  728. #endif
  729. #endif
  730. #ifdef SIGSTOP
  731.     (void) signal(SIGSTOP, randomsig);
  732. #ifdef NEED_SIGFIX
  733.     sigaddset(&block_sigmask, SIGSTOP);
  734. #endif
  735. #endif
  736. #ifdef SIGTSTP
  737.     (void) signal(SIGTSTP, randomsig);
  738. #ifdef NEED_SIGFIX
  739.     sigaddset(&block_sigmask, SIGTSTP);
  740. #endif
  741. #endif
  742. #ifdef SIGTTIN
  743.     (void) signal(SIGTTIN, randomsig);
  744. #ifdef NEED_SIGFIX
  745.     sigaddset(&block_sigmask, SIGTTIN);
  746. #endif
  747. #endif
  748. #ifdef SIGTTOU
  749.     (void) signal(SIGTTOU, randomsig);
  750. #ifdef NEED_SIGFIX
  751.     sigaddset(&block_sigmask, SIGTTOU);
  752. #endif
  753. #endif
  754. #ifdef SIGIO
  755.     (void) signal(SIGIO, randomsig);
  756. #ifdef NEED_SIGFIX
  757.     sigaddset(&block_sigmask, SIGIO);
  758. #endif
  759. #endif
  760. #ifdef SIGXCPU
  761.     (void) signal(SIGXCPU, randomsig);
  762. #ifdef NEED_SIGFIX
  763.     sigaddset(&block_sigmask, SIGXCPU);
  764. #endif
  765. #endif
  766. #ifdef SIGXFSZ
  767.     (void) signal(SIGXFSZ, randomsig);
  768. #ifdef NEED_SIGFIX
  769.     sigaddset(&block_sigmask, SIGXFSZ);
  770. #endif
  771. #endif
  772. #ifdef SIGWINCH
  773.     (void) signal(SIGWINCH, randomsig);
  774. #ifdef NEED_SIGFIX
  775.     sigaddset(&block_sigmask, SIGWINCH);
  776. #endif
  777. #endif
  778. #ifdef SIGVTALRM
  779.     (void) signal(SIGVTALRM, randomsig);
  780. #ifdef NEED_SIGFIX
  781.     sigaddset(&block_sigmask, SIGVTALRM);
  782. #endif
  783. #endif
  784. #ifdef SIGPROF
  785.     (void) signal(SIGPROF, randomsig);
  786. #ifdef NEED_SIGFIX
  787.     sigaddset(&block_sigmask, SIGPROF);
  788. #endif
  789. #endif
  790. #ifdef SIGUSR1
  791.     (void) signal(SIGUSR1, randomsig);
  792. #ifdef NEED_SIGFIX
  793.     sigaddset(&block_sigmask, SIGUSR1);
  794. #endif
  795. #endif
  796. #ifdef SIGUSR2
  797.     (void) signal(SIGUSR2, randomsig);
  798. #ifdef NEED_SIGFIX
  799.     sigaddset(&block_sigmask, SIGUSR2);
  800. #endif
  801. #endif
  802. #ifdef SIGPIPE
  803.     (void) signal(SIGPIPE, lostconn);
  804. #ifdef NEED_SIGFIX
  805.     sigaddset(&block_sigmask, SIGPIPE);
  806. #endif
  807. #endif
  808. #ifdef SIGCHLD
  809.     (void) signal(SIGCHLD, SIG_IGN);
  810. #ifdef NEED_SIGFIX
  811.     sigaddset(&block_sigmask, SIGCHLD);
  812. #endif
  813. #endif
  814. #ifdef SIGURG
  815.     if (signal(SIGURG, myoob) == SIG_ERR)
  816. syslog(LOG_ERR, "signal: %m");
  817. #ifdef NEED_SIGFIX
  818.     sigaddset(&block_sigmask, SIGURG);
  819. #endif
  820. #endif
  821. #endif /* SIG_DEBUG */
  822. #ifdef VIRTUAL
  823.     virtual_root[0] = '';
  824.     virtual_banner[0] = '';
  825. #endif
  826.     setup_paths();
  827.     access_init();
  828. #ifdef DAEMON
  829.     if (be_daemon != 0)
  830. do_daemon(argc, argv, envp);
  831.     addrlen = sizeof(his_addr);
  832.     if (getpeername(0, (struct sockaddr *) &his_addr, &addrlen) < 0) {
  833. syslog(LOG_ERR, "getpeername (%s): %m", argv[0]);
  834. #ifndef DEBUG
  835. exit(1);
  836. #endif
  837.     }
  838.     addrlen = sizeof(ctrl_addr);
  839.     if (getsockname(0, (struct sockaddr *) &ctrl_addr, &addrlen) < 0) {
  840. syslog(LOG_ERR, "getsockname (%s): %m", argv[0]);
  841. #ifndef DEBUG
  842. exit(1);
  843. #endif
  844.     }
  845. #ifdef IPTOS_LOWDELAY
  846.     tos = IPTOS_LOWDELAY;
  847.     if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0)
  848.     syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
  849. #endif
  850.     if (keepalive)
  851. if (setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, (char *) &on, sizeof(on)) < 0)
  852.     syslog(LOG_ERR, "setsockopt SO_KEEPALIVE %m");
  853.     data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
  854. #endif /* DAEMON */
  855.     /* Try to handle urgent data inline */
  856. #ifdef SO_OOBINLINE
  857.     if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *) &on, sizeof(int)) < 0)
  858.     syslog(LOG_ERR, "setsockopt (SO_OOBINLINE): %m");
  859. #endif
  860. #ifdef  F_SETOWN
  861.     if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
  862. syslog(LOG_ERR, "fcntl F_SETOWN: %m");
  863. #elif defined(SIOCSPGRP)
  864.     {
  865. int pid;
  866. pid = getpid();
  867. if (ioctl(fileno(stdin), SIOCSPGRP, &pid) == -1)
  868.     syslog(LOG_ERR, "ioctl SIOCSPGRP: %m");
  869.     }
  870. #endif
  871.     if (RootDirectory != NULL) {
  872. if ((chroot(RootDirectory) < 0)
  873.     || (chdir("/") < 0)) {
  874.     syslog(LOG_ERR, "Cannot chroot to initial directory, aborting.");
  875.     exit(1);
  876. }
  877.     }
  878. #ifdef HAVE_LIBRESOLV
  879.     /* initialize the resolver, and set global DNS variables */
  880.     initialize_dns(&his_addr);
  881. #endif
  882.     dolog(&his_addr);
  883.     /* Set up default state */
  884.     data = -1;
  885.     type = TYPE_A;
  886.     form = FORM_N;
  887.     stru = STRU_F;
  888.     mode = MODE_S;
  889.     tmpline[0] = '';
  890.     yyerrorcalled = 0;
  891.     entry = (struct aclmember *) NULL;
  892.     if ((getaclentry("hostname", &entry)) && ARG0) {
  893. (void) strncpy(hostname, ARG0, sizeof(hostname));
  894. hostname[sizeof(hostname) - 1] = '';
  895.     }
  896.     else {
  897. #ifdef HAVE_SYSINFO
  898. sysinfo(SI_HOSTNAME, hostname, sizeof(hostname));
  899. #else
  900. (void) gethostname(hostname, sizeof(hostname));
  901. #endif
  902. /* set the FQDN here */
  903. shp = gethostbyname(hostname);
  904. if (shp != NULL) {
  905.     (void) strncpy(hostname, shp->h_name, sizeof(hostname));
  906.     hostname[sizeof(hostname) - 1] = '';
  907. }
  908.     }
  909.     route_vectored = routevector();
  910.     conv_init();
  911. #ifdef MAIL_ADMIN
  912.     incmails = 0;
  913.     mailfrom = NULL;
  914. #endif /* MAIL_ADMIN */
  915. #ifdef VIRTUAL
  916.     /*
  917.        ** If virtual_mode is set at this point then an alternate ftpaccess
  918.        ** is in use.  Otherwise we need to check the Master ftpaccess file
  919.        ** to see if the site is only using the "virtual" directives to
  920.        ** specify virtual site directives.
  921.        **
  922.        ** In this manner an admin can put a virtual site in the ftpservers
  923.        ** file if they need expanded configuration support or can use the
  924.        ** minimal root/banner/logfile if they do not need any more than that.
  925.      */
  926.     if (virtual_mode) {
  927. /* Get the root of the virtual server directory */
  928. entry = (struct aclmember *) NULL;
  929. if (getaclentry("root", &entry)) {
  930.     if (ARG0)
  931. strcpy(virtual_root, ARG0);
  932. }
  933. /* Get the logfile to use */
  934. entry = (struct aclmember *) NULL;
  935. if (getaclentry("logfile", &entry)) {
  936.     if (ARG0)
  937. strcpy(logfile, ARG0);
  938. }
  939.     }
  940.     else {
  941. virtual_hostname[0] = '';
  942. virtual_address[0] = '';
  943. virtual_len = sizeof(virtual_addr);
  944. if (getsockname(0, (struct sockaddr *) &virtual_addr, &virtual_len) == 0) {
  945.     virtual_ptr = (struct sockaddr_in *) &virtual_addr;
  946.     strcpy(virtual_address, inet_ntoa(virtual_ptr->sin_addr));
  947.     shp = gethostbyaddr((char *) &virtual_ptr->sin_addr, sizeof(struct in_addr), AF_INET);
  948.     if (shp != NULL) {
  949. (void) strncpy(virtual_hostname, shp->h_name, sizeof(virtual_hostname));
  950. virtual_hostname[sizeof(virtual_hostname) - 1] = '';
  951.     }
  952.     entry = (struct aclmember *) NULL;
  953.     while (getaclentry("virtual", &entry)) {
  954. if (!ARG0 || !ARG1 || !ARG2)
  955.     continue;
  956. if (hostmatch(ARG0, virtual_address, virtual_hostname)) {
  957.     if (!strcasecmp(ARG1, "root")) {
  958. syslog(LOG_NOTICE, "VirtualFTP Connect to: %s [%s]",
  959.        virtual_hostname, virtual_address);
  960. virtual_mode = 1;
  961. strncpy(virtual_root, ARG2, sizeof(virtual_root));
  962. virtual_root[sizeof(virtual_root) - 1] = '';
  963. /* reset hostname to this virtual name */
  964. (void) strcpy(hostname, virtual_hostname);
  965. virtual_email[0] = '';
  966.     }
  967.     if (!strcasecmp(ARG1, "banner")) {
  968. strncpy(virtual_banner, ARG2, sizeof(virtual_banner));
  969. virtual_banner[sizeof(virtual_banner) - 1] = '';
  970.     }
  971.     if (!strcasecmp(ARG1, "logfile")) {
  972. strncpy(logfile, ARG2, sizeof(logfile));
  973. logfile[sizeof(logfile) - 1] = '';
  974.     }
  975.     if (!strcasecmp(ARG1, "hostname")) {
  976. strncpy(hostname, ARG2, sizeof(hostname));
  977. hostname[sizeof(hostname) - 1] = '';
  978.     }
  979.     if (!strcasecmp(ARG1, "email")) {
  980. strncpy(virtual_email, ARG2, sizeof(virtual_email));
  981. virtual_email[sizeof(virtual_email) - 1] = '';
  982.     }
  983. #ifdef MAIL_ADMIN
  984.     if (mailfrom == NULL)
  985. if (!strcasecmp(ARG1, "mailfrom")) {
  986.     mailfrom = strdup(ARG2);
  987. }
  988.     if (!strcasecmp(ARG1, "incmail")) {
  989. if (incmails < INCMAILS)
  990.     incmail[incmails++] = strdup(ARG2);
  991.     }
  992. #endif
  993. }
  994.     }
  995.     if (!virtual_mode) {
  996. entry = (struct aclmember *) NULL;
  997. while (getaclentry("defaultserver", &entry)) {
  998.     if (!ARG0 || !ARG1)
  999. continue;
  1000. #ifdef MAIL_ADMIN
  1001.     if (mailfrom == NULL)
  1002. if (!strcasecmp(ARG0, "mailfrom")) {
  1003.     mailfrom = strdup(ARG1);
  1004. }
  1005.     if (!strcasecmp(ARG0, "incmail")) {
  1006. if (incmails < INCMAILS)
  1007.     incmail[incmails++] = strdup(ARG1);
  1008.     }
  1009. #endif
  1010. }
  1011.     }
  1012. }
  1013.     }
  1014. #ifdef VIRTUAL_DEBUG
  1015.     lreply(220, "_path_ftpaccess == %s", _path_ftpaccess);
  1016.     lreply(220, "_path_ftpusers == %s", _path_ftpusers);
  1017.     lreply(220, "_path_ftphosts == %s", _path_ftphosts);
  1018.     lreply(220, "_path_private == %s", _path_private);
  1019.     lreply(220, "_path_cvt == %s", _path_cvt);
  1020.     if (virtual_mode) {
  1021. if (virtual_ftpaccess)
  1022.     lreply(220, "VIRTUAL Mode: Using %s specific %s access file",
  1023.    hostname, _path_ftpaccess);
  1024. else
  1025.     lreply(220, "VIRTUAL Mode: Using Master access file %s",
  1026.    _path_ftpaccess);
  1027. lreply(220, "virtual_root == %s", virtual_root);
  1028. if (!virtual_ftpaccess)
  1029.     lreply(220, "virtual_banner == %s", virtual_banner);
  1030.     }
  1031.     lreply(220, "logfile == %s", logfile);
  1032. #endif
  1033. #endif
  1034.     if (is_shutdown(1, 1) != 0) {
  1035. syslog(LOG_INFO, "connection refused (server shut down) from %s",
  1036.        remoteident);
  1037. reply(500, "%s FTP server shut down -- please try again later.",
  1038.       hostname);
  1039. exit(0);
  1040.     }
  1041. #ifdef OPIE
  1042.     af_pwok = opieaccessfile(remotehost);
  1043. #endif
  1044. #ifdef HAVE_LIBRESOLV
  1045.     /* check permitted access based on remote host DNS information */
  1046.     if (!check_reverse_dns()) {
  1047. exit(0);
  1048.     }
  1049.     if (!check_matching_dns()) {
  1050. exit(0);
  1051.     }
  1052. #endif /* HAVE_LIBRESOLV */
  1053.     show_banner(220);
  1054. #ifndef INTERNAL_LS
  1055.     entry = (struct aclmember *) NULL;
  1056.     if (getaclentry("lslong", &entry) && ARG0 && (int) strlen(ARG0) > 0) {
  1057. strcpy(ls_long, ARG0);
  1058. for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
  1059.     strcat(ls_long, " ");
  1060.     strcat(ls_long, ARG[which]);
  1061. }
  1062.     }
  1063.     else {
  1064. #if defined(SVR4) || defined(ISC)
  1065. #if defined(AIX) || defined(SOLARIS2)
  1066. strcpy(ls_long, "/bin/ls -lA");
  1067. #else
  1068. strcpy(ls_long, "/bin/ls -la");
  1069. #endif
  1070. #else
  1071. strcpy(ls_long, "/bin/ls -lgA");
  1072. #endif
  1073.     }
  1074.     strcat(ls_long, " %s");
  1075.     entry = (struct aclmember *) NULL;
  1076.     if (getaclentry("lsshort", &entry) && ARG0 && (int) strlen(ARG0) > 0) {
  1077. strcpy(ls_short, ARG0);
  1078. for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
  1079.     strcat(ls_short, " ");
  1080.     strcat(ls_short, ARG[which]);
  1081. }
  1082.     }
  1083.     else {
  1084. #if defined(SVR4) || defined(ISC)
  1085. #if defined(AIX) || defined(SOLARIS2)
  1086. strcpy(ls_short, "/bin/ls -lA");
  1087. #else
  1088. strcpy(ls_short, "/bin/ls -la");
  1089. #endif
  1090. #else
  1091. strcpy(ls_short, "/bin/ls -lgA");
  1092. #endif
  1093.     }
  1094.     strcat(ls_short, " %s");
  1095.     entry = (struct aclmember *) NULL;
  1096.     if (getaclentry("lsplain", &entry) && ARG0 && (int) strlen(ARG0) > 0) {
  1097. strcpy(ls_plain, ARG0);
  1098. for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
  1099.     strcat(ls_plain, " ");
  1100.     strcat(ls_plain, ARG[which]);
  1101. }
  1102.     }
  1103.     else
  1104. strcpy(ls_plain, "/bin/ls");
  1105.     strcat(ls_plain, " %s");
  1106. #endif /* ! INTERNAL_LS */
  1107. #ifdef MAIL_ADMIN
  1108.     mailservers = 0;
  1109.     entry = (struct aclmember *) NULL;
  1110.     while (getaclentry("mailserver", &entry) && ARG0 && mailservers < MAILSERVERS)
  1111. mailserver[mailservers++] = strdup(ARG0);
  1112.     if (mailservers == 0)
  1113. mailserver[mailservers++] = strdup("localhost");
  1114.     if (incmails == 0) {
  1115. entry = (struct aclmember *) NULL;
  1116. while (getaclentry("incmail", &entry) && ARG0 && incmails < INCMAILS)
  1117.     incmail[incmails++] = strdup(ARG0);
  1118.     }
  1119.     if (mailfrom == NULL) {
  1120. entry = (struct aclmember *) NULL;
  1121. if (getaclentry("mailfrom", &entry) && ARG0)
  1122.     mailfrom = strdup(ARG0);
  1123. else
  1124.     mailfrom = strdup("wu-ftpd");
  1125.     }
  1126. #endif /* MAIL_ADMIN */
  1127.     {
  1128. #define OUTPUT_LEN 1024
  1129. int version_option = 0;
  1130. char output_text[OUTPUT_LEN + 1];
  1131. int arg_count, output_len;
  1132. entry = NULL;
  1133. if (getaclentry("greeting", &entry) && ARG0) {
  1134.     if (!strcasecmp(ARG0, "full"))
  1135. version_option = 0;
  1136.     else if (!strcasecmp(ARG0, "text") && ARG1)
  1137. version_option = 3;
  1138.     else if (!strcasecmp(ARG0, "terse"))
  1139. version_option = 2;
  1140.     else if (!strcasecmp(ARG0, "brief"))
  1141. version_option = 1;
  1142. }
  1143. switch (version_option) {
  1144. default:
  1145.     reply(220, "%s FTP server (%s) ready.", hostname, version);
  1146.     break;
  1147. case 1:
  1148.     reply(220, "%s FTP server ready.", hostname);
  1149.     break;
  1150. case 2:
  1151.     reply(220, "FTP server ready.");
  1152.     break;
  1153. case 3:
  1154.     output_text[0] = '';
  1155.     output_len = 0;
  1156.     for (arg_count = 1; ARG[arg_count] != NULL; arg_count++) {
  1157. int arg_len;
  1158. arg_len = strlen(ARG[arg_count]);
  1159. if ((output_len + arg_len) > OUTPUT_LEN) {
  1160.     /* avoid possible buffer overflow */
  1161.     break;
  1162. }
  1163. /* append the text to the greeting */
  1164. strcat(output_text, ARG[arg_count]);
  1165. output_len += arg_len;
  1166. if (ARG[arg_count + 1] != NULL) {
  1167.     if ((output_len + 2) > OUTPUT_LEN) {
  1168. /* avoid possible buffer overflow and adding a trailing space */
  1169. break;
  1170.     }
  1171.     /* if the next entry exists, add a white space */
  1172.     strcat(output_text, " ");
  1173.     output_len += 1;
  1174. }
  1175.     }
  1176.     reply(220, "%s", output_text);
  1177.     break;
  1178. }
  1179.     }
  1180.     (void) setjmp(errcatch);
  1181.     for (;;)
  1182. (void) yyparse();
  1183.     /* NOTREACHED */
  1184. }
  1185. SIGNAL_TYPE randomsig(int sig)
  1186. {
  1187. #ifdef HAVE_SIGLIST
  1188.     syslog(LOG_ERR, "exiting on signal %d: %s", sig, sys_siglist[sig]);
  1189. #else
  1190.     syslog(LOG_ERR, "exiting on signal %d", sig);
  1191. #endif
  1192.     chdir("/");
  1193.     signal(SIGIOT, SIG_DFL);
  1194.     signal(SIGILL, SIG_DFL);
  1195.     exit(1);
  1196.     /* dologout(-1); *//* NOTREACHED */
  1197. }
  1198. SIGNAL_TYPE lostconn(int sig)
  1199. {
  1200. #ifdef VERBOSE_ERROR_LOGING
  1201.     syslog(LOG_INFO, "lost connection to %s", remoteident);
  1202. #else
  1203.     if (debug)
  1204. syslog(LOG_DEBUG, "lost connection to %s", remoteident);
  1205. #endif
  1206.     dologout(-1);
  1207. }
  1208. static char ttyline[20];
  1209. #ifdef MAPPING_CHDIR
  1210. /* Keep track of the path the user has chdir'd into and respond with
  1211.  * that to pwd commands.  This is to avoid having the absolue disk
  1212.  * path returned, which I want to avoid.
  1213.  */
  1214. char mapped_path[MAXPATHLEN] = "/";
  1215. char *mapping_getwd(char *path)
  1216. {
  1217.     strcpy(path, mapped_path);
  1218.     return path;
  1219. }
  1220. char *mapping_getcwd(char *path, size_t size)
  1221. {
  1222.     strncpy(path, mapped_path, size);
  1223.     path[size - 1] = '';
  1224.     return path;
  1225. }
  1226. /* Make these globals rather than local to mapping_chdir to avoid stack overflow */
  1227. char pathspace[MAXPATHLEN];
  1228. char old_mapped_path[MAXPATHLEN];
  1229. void do_elem(char *dir)
  1230. {
  1231.     /* . */
  1232.     if (dir[0] == '.' && dir[1] == '') {
  1233. /* ignore it */
  1234. return;
  1235.     }
  1236.     /* .. */
  1237.     if (dir[0] == '.' && dir[1] == '.' && dir[2] == '') {
  1238. char *last;
  1239. /* lop the last directory off the path */
  1240. if ((last = strrchr(mapped_path, '/'))) {
  1241.     /* If start of pathname leave the / */
  1242.     if (last == mapped_path)
  1243. last++;
  1244.     *last = '';
  1245. }
  1246. return;
  1247.     }
  1248.     /* append the dir part with a leading / unless at root */
  1249.     if (!(mapped_path[0] == '/' && mapped_path[1] == ''))
  1250. if (strlen(mapped_path) < sizeof(mapped_path) - 1)
  1251.     strcat(mapped_path, "/");
  1252.     if (sizeof(mapped_path) - strlen(mapped_path) > 1)
  1253. strncat(mapped_path, dir, sizeof(mapped_path) - strlen(mapped_path) - 1);
  1254. }
  1255. int mapping_chdir(char *orig_path)
  1256. {
  1257.     int ret;
  1258.     char *sl, *path;
  1259.     strcpy(old_mapped_path, mapped_path);
  1260.     path = &pathspace[0];
  1261.     strcpy(path, orig_path);
  1262.     /* / at start of path, set the start of the mapped_path to / */
  1263.     if (path[0] == '/') {
  1264. mapped_path[0] = '/';
  1265. mapped_path[1] = '';
  1266. path++;
  1267.     }
  1268.     while ((sl = strchr(path, '/'))) {
  1269. char *dir;
  1270. dir = path;
  1271. *sl = '';
  1272. path = sl + 1;
  1273. if (*dir)
  1274.     do_elem(dir);
  1275. if (*path == '')
  1276.     break;
  1277.     }
  1278.     if (*path)
  1279. do_elem(path);
  1280.     if ((ret = chdir(mapped_path)) < 0) {
  1281. strcpy(mapped_path, old_mapped_path);
  1282.     }
  1283.     return ret;
  1284. }
  1285. /* From now on use the mapping version */
  1286. #define chdir(d) mapping_chdir(d)
  1287. #define getwd(d) mapping_getwd(d)
  1288. #define getcwd(d,u) mapping_getcwd((d),(u))
  1289. #endif /* MAPPING_CHDIR */
  1290. /* Helper function for sgetpwnam(). */
  1291. char *sgetsave(char *s)
  1292. {
  1293.     char *new;
  1294.     new = (char *) malloc(strlen(s) + 1);
  1295.     if (new == NULL) {
  1296. perror_reply(421, "Local resource failure: malloc");
  1297. dologout(1);
  1298. /* NOTREACHED */
  1299.     }
  1300.     (void) strcpy(new, s);
  1301.     return (new);
  1302. }
  1303. /* Save the result of a getpwnam.  Used for USER command, since the data
  1304.  * returned must not be clobbered by any other command (e.g., globbing). */
  1305. struct passwd *sgetpwnam(char *name)
  1306. {
  1307.     static struct passwd save;
  1308.     register struct passwd *p;
  1309. #ifdef M_UNIX
  1310.     struct passwd *ret = (struct passwd *) NULL;
  1311. #endif
  1312.     char *sgetsave(char *s);
  1313. #ifdef KERBEROS
  1314.     register struct authorization *q;
  1315. #endif /* KERBEROS */
  1316. #if defined(SecureWare) || defined(HPUX_10_TRUSTED)
  1317.     struct pr_passwd *pr;
  1318. #endif
  1319. #ifdef KERBEROS
  1320.     init_krb();
  1321.     q = getauthuid(p->pw_uid);
  1322.     end_krb();
  1323. #endif /* KERBEROS */
  1324. #ifdef M_UNIX
  1325. #if defined(SecureWare) || defined(HPUX_10_TRUSTED)
  1326.     if ((pr = getprpwnam(name)) == NULL)
  1327. goto DONE;
  1328. #endif /* SecureWare || HPUX_10_TRUSTED */
  1329.     if ((p = getpwnam(name)) == NULL)
  1330. goto DONE;
  1331. #else /* M_UNIX */
  1332. #if defined(SecureWare) || defined(HPUX_10_TRUSTED)
  1333.     if ((pr = getprpwnam(name)) == NULL)
  1334. return ((struct passwd *) pr);
  1335. #endif /* SecureWare || HPUX_10_TRUSTED */
  1336.     if ((p = getpwnam(name)) == NULL)
  1337. return (p);
  1338. #endif /* M_UNIX */
  1339.     if (save.pw_name)
  1340. free(save.pw_name);
  1341.     if (save.pw_gecos)
  1342. free(save.pw_gecos);
  1343.     if (save.pw_dir)
  1344. free(save.pw_dir);
  1345.     if (save.pw_shell)
  1346. free(save.pw_shell);
  1347.     if (save.pw_passwd)
  1348. free(save.pw_passwd);
  1349.     save = *p;
  1350.     save.pw_name = sgetsave(p->pw_name);
  1351. #ifdef KERBEROS
  1352.     save.pw_passwd = sgetsave(q->a_password);
  1353. #elif defined(SecureWare) || defined(HPUX_10_TRUSTED)
  1354.     if (pr->uflg.fg_encrypt && pr->ufld.fd_encrypt && *pr->ufld.fd_encrypt)
  1355. save.pw_passwd = sgetsave(pr->ufld.fd_encrypt);
  1356.     else
  1357. save.pw_passwd = sgetsave("");
  1358. #else
  1359.     save.pw_passwd = sgetsave(p->pw_passwd);
  1360. #endif
  1361. #ifdef SHADOW_PASSWORD
  1362.     if (p) {
  1363. struct spwd *spw;
  1364. setspent();
  1365. if ((spw = getspnam(p->pw_name)) != NULL) {
  1366.     int expired = 0;
  1367.     /*XXX Does this work on all Shadow Password Implementations? */
  1368.     /* it is supposed to work on Solaris 2.x */
  1369.     time_t now;
  1370.     long today;
  1371.     now = time((time_t *) 0);
  1372.     today = now / (60 * 60 * 24);
  1373.     if ((spw->sp_expire > 0) && (spw->sp_expire < today))
  1374. expired++;
  1375.     if ((spw->sp_max > 0) && (spw->sp_lstchg > 0) &&
  1376. (spw->sp_lstchg + spw->sp_max < today))
  1377. expired++;
  1378.     free(save.pw_passwd);
  1379.     save.pw_passwd = sgetsave(expired ? "" : spw->sp_pwdp);
  1380. }
  1381. /* Don't overwrite the password if the shadow read fails, getpwnam() is NIS
  1382.    aware but getspnam() is not. */
  1383. /* Shadow passwords are optional on Linux.  --marekm */
  1384. #if !defined(LINUX) && !defined(UNIXWARE)
  1385. else {
  1386.     free(save.pw_passwd);
  1387.     save.pw_passwd = sgetsave("");
  1388. }
  1389. #endif
  1390. /* marekm's fix for linux proc file system shadow passwd exposure problem */
  1391. endspent();
  1392.     }
  1393. #endif
  1394.     save.pw_gecos = sgetsave(p->pw_gecos);
  1395.     save.pw_dir = sgetsave(p->pw_dir);
  1396.     save.pw_shell = sgetsave(p->pw_shell);
  1397. #ifdef M_UNIX
  1398.     ret = &save;
  1399.   DONE:
  1400.     endpwent();
  1401. #endif
  1402. #if defined(SecureWare) || defined(HPUX_10_TRUSTED)
  1403.     endprpwent();
  1404. #endif
  1405. #ifdef M_UNIX
  1406.     return (ret);
  1407. #else
  1408.     return (&save);
  1409. #endif
  1410. }
  1411. #if defined(SKEY) && !defined(__NetBSD__)
  1412. /*
  1413.  * From Wietse Venema, Eindhoven University of Technology. 
  1414.  */
  1415. /* skey_challenge - additional password prompt stuff */
  1416. char *skey_challenge(char *name, struct passwd *pwd, int pwok)
  1417. {
  1418.     static char buf[128];
  1419.     char sbuf[40];
  1420.     struct skey skey;
  1421.     /* Display s/key challenge where appropriate. */
  1422.     if (pwd == NULL || skeychallenge(&skey, pwd->pw_name, sbuf))
  1423. sprintf(buf, "Password required for %s.", name);
  1424.     else
  1425. sprintf(buf, "%s %s for %s.", sbuf,
  1426. pwok ? "allowed" : "required", name);
  1427.     return (buf);
  1428. }
  1429. #endif
  1430. int login_attempts; /* number of failed login attempts */
  1431. int askpasswd; /* had user command, ask for passwd */
  1432. #ifndef HELP_CRACKERS
  1433. int DenyLoginAfterPassword;
  1434. char DelayedMessageFile[MAXPATHLEN];
  1435. extern void pr_mesg(int msgcode, char *msgfile);
  1436. #endif
  1437. #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)
  1438. static int defaultserver_allow(const char *username)
  1439. {
  1440.     struct aclmember *entry = NULL;
  1441.     int which;
  1442.     while (getaclentry("defaultserver", &entry))
  1443. if (ARG0 && !strcasecmp(ARG0, "allow"))
  1444.     for (which = 1; (which < MAXARGS) && ARG[which]; which++)
  1445. if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which]))
  1446.     return (1);
  1447.     return (0);
  1448. }
  1449. static int defaultserver_deny(const char *username)
  1450. {
  1451.     struct aclmember *entry = NULL;
  1452.     int which;
  1453.     while (getaclentry("defaultserver", &entry))
  1454. if (ARG0 && !strcasecmp(ARG0, "deny"))
  1455.     for (which = 1; (which < MAXARGS) && ARG[which]; which++)
  1456. if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which]))
  1457.     return (1);
  1458.     return (0);
  1459. }
  1460. static int defaultserver_private(void)
  1461. {
  1462.     struct aclmember *entry = NULL;
  1463.     while (getaclentry("defaultserver", &entry))
  1464. if (ARG0 && !strcasecmp(ARG0, "private"))
  1465.     return (1);
  1466.     return (0);
  1467. }
  1468. #endif
  1469. /* USER command. Sets global passwd pointer pw if named account exists and is
  1470.  * acceptable; sets askpasswd if a PASS command is expected.  If logged in
  1471.  * previously, need to reset state.  If name is "ftp" or "anonymous", the
  1472.  * name is not in _PATH_FTPUSERS, and ftp account exists, set anonymous and
  1473.  * pw, then just return.  If account doesn't exist, ask for passwd anyway.
  1474.  * Otherwise, check user requesting login privileges.  Disallow anyone who
  1475.  * does not have a standard shell as returned by getusershell().  Disallow
  1476.  * anyone mentioned in the file _PATH_FTPUSERS to allow people such as root
  1477.  * and uucp to be avoided. */
  1478. /*
  1479.    char *getusershell();
  1480.  */
  1481. void user(char *name)
  1482. {
  1483.     char *cp;
  1484.     char *shell;
  1485. #ifdef BSD_AUTH
  1486.     char *auth;
  1487. #endif
  1488. /* H* fix: if we're logged in at all, we can't log in again. */
  1489.     if (logged_in) {
  1490. #ifdef VERBOSE_ERROR_LOGING
  1491. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (already logged in as %s) FROM %s, %s",
  1492.        pw->pw_name, remoteident, name);
  1493. #endif
  1494. reply(530, "Already logged in.");
  1495. return;
  1496.     }
  1497. #ifndef HELP_CRACKERS
  1498.     askpasswd = 1;
  1499.     DenyLoginAfterPassword = 0;
  1500.     DelayedMessageFile[0] = '';
  1501. #endif
  1502. #ifdef BSD_AUTH
  1503.     if ((auth = strchr(name, ':')))
  1504. *auth++ = 0;
  1505. #endif
  1506. #ifdef HOST_ACCESS /* 19-Mar-93    BM              */
  1507.     if (!rhost_ok(name, remotehost, remoteaddr)) {
  1508. #ifndef HELP_CRACKERS
  1509. DenyLoginAfterPassword = 1;
  1510. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (name in %s) FROM %s, %s",
  1511.        _PATH_FTPHOSTS, remoteident, name);
  1512. #else
  1513. reply(530, "User %s access denied.", name);
  1514. syslog(LOG_NOTICE,
  1515.        "FTP LOGIN REFUSED (name in %s) FROM %s, %s",
  1516.        _PATH_FTPHOSTS, remoteident, name);
  1517. return;
  1518. #endif
  1519.     }
  1520. #endif
  1521. #ifdef LOG_FAILED /* 06-Nov-92    EHK             */
  1522.     strncpy(the_user, name, MAXUSERNAMELEN - 1);
  1523. #endif
  1524.     anonymous = 0;
  1525.     acl_remove();
  1526.     if (!strcasecmp(name, "ftp") || !strcasecmp(name, "anonymous")) {
  1527. struct aclmember *entry = NULL;
  1528. int machineok = 1;
  1529. char guestservername[MAXHOSTNAMELEN];
  1530. guestservername[0] = '';
  1531. #ifdef NO_ANONYMOUS_ACCESS
  1532. reply(530, "Anonymous FTP access denied.");
  1533. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (anonymous ftp not supported) FROM %s, %s",
  1534.        remoteident, name);
  1535. return;
  1536. #else
  1537. #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)
  1538. if (!virtual_mode && defaultserver_private()) {
  1539. #ifndef HELP_CRACKERS
  1540.     DenyLoginAfterPassword = 1;
  1541.     syslog(LOG_NOTICE, "FTP LOGIN REFUSED (anonymous ftp denied on default server) FROM %s, %s",
  1542.    remoteident, name);
  1543. #else
  1544.     reply(530, "User %s access denied.", name);
  1545.     syslog(LOG_NOTICE,
  1546.    "FTP LOGIN REFUSED (anonymous ftp denied on default server) FROM %s, %s",
  1547.    remoteident, name);
  1548.     return;
  1549. #endif
  1550. }
  1551. #endif
  1552. if (checkuser("ftp") || checkuser("anonymous")) {
  1553. #ifndef HELP_CRACKERS
  1554.     DenyLoginAfterPassword = 1;
  1555.     syslog(LOG_NOTICE, "FTP LOGIN REFUSED (ftp in %s) FROM %s, %s",
  1556.    _PATH_FTPUSERS, remoteident, name);
  1557. #else
  1558.     reply(530, "User %s access denied.", name);
  1559.     syslog(LOG_NOTICE,
  1560.    "FTP LOGIN REFUSED (ftp in %s) FROM %s, %s",
  1561.    _PATH_FTPUSERS, remoteident, name);
  1562.     return;
  1563. #endif
  1564.     /*
  1565.        ** Algorithm used:
  1566.        ** - if no "guestserver" directive is present,
  1567.        **     anonymous access is allowed, for backward compatibility.
  1568.        ** - if a "guestserver" directive is present,
  1569.        **     anonymous access is restricted to the machines listed,
  1570.        **     usually the machine whose CNAME on the current domain
  1571.        **     is "ftp"...
  1572.        **
  1573.        ** the format of the "guestserver" line is
  1574.        ** guestserver [<machine1> [<machineN>]]
  1575.        ** that is, "guestserver" will forbid anonymous access on all machines
  1576.        ** while "guestserver ftp inf" will allow anonymous access on
  1577.        ** the two machines whose CNAMES are "ftp.enst.fr" and "inf.enst.fr".
  1578.        **
  1579.        ** if anonymous access is denied on the current machine,
  1580.        ** the user will be asked to use the first machine listed (if any)
  1581.        ** on the "guestserver" line instead:
  1582.        ** 530- Guest login not allowed on this machine,
  1583.        **      connect to ftp.enst.fr instead.
  1584.        **
  1585.        ** -- <Nicolas.Pioch@enst.fr>
  1586.      */
  1587. }
  1588. else if (getaclentry("guestserver", &entry)
  1589.  && ARG0 && (int) strlen(ARG0) > 0) {
  1590.     struct hostent *tmphostent;
  1591.     /*
  1592.        ** if a "guestserver" line is present,
  1593.        ** default is not to allow guest logins
  1594.      */
  1595.     machineok = 0;
  1596.     if (hostname[0]
  1597. && ((tmphostent = gethostbyname(hostname)))) {
  1598. /*
  1599.    ** hostname is the only first part of the FQDN
  1600.    ** this may or may not correspond to the h_name value
  1601.    ** (machines with more than one IP#, CNAMEs...)
  1602.    ** -> need to fix that, calling gethostbyname on hostname
  1603.    **
  1604.    ** WARNING!
  1605.    ** for SunOS 4.x, you need to have a working resolver in the libc
  1606.    ** for CNAMES to work properly.
  1607.    ** If you don't, add "-lresolv" to the libraries before compiling!
  1608.  */
  1609. char dns_localhost[MAXHOSTNAMELEN];
  1610. int machinecount;
  1611. strncpy(dns_localhost,
  1612. tmphostent->h_name,
  1613. sizeof(dns_localhost));
  1614. dns_localhost[sizeof(dns_localhost) - 1] = '';
  1615. for (machinecount = 0;
  1616.   entry->arg[machinecount] && (entry->arg[machinecount])[0];
  1617.      machinecount++) {
  1618.     if ((tmphostent = gethostbyname(entry->arg[machinecount]))) {
  1619. /*
  1620.    ** remember the name of the first machine for redirection
  1621.  */
  1622. if ((!machinecount) && tmphostent->h_name) {
  1623.     strncpy(guestservername, entry->arg[machinecount],
  1624.     sizeof(guestservername));
  1625.     guestservername[sizeof(guestservername) - 1] = '';
  1626. }
  1627. if (!strcasecmp(tmphostent->h_name, dns_localhost)) {
  1628.     machineok++;
  1629.     break;
  1630. }
  1631.     }
  1632. }
  1633.     }
  1634. }
  1635. if (!machineok) {
  1636.     if (guestservername[0])
  1637. reply(530,
  1638.       "Guest login not allowed on this machine, connect to %s instead.",
  1639.       guestservername);
  1640.     else
  1641. reply(530,
  1642.       "Guest login not allowed on this machine.");
  1643.     syslog(LOG_NOTICE,
  1644.     "FTP LOGIN REFUSED (localhost not in guestservers) FROM %s, %s",
  1645.    remoteident, name);
  1646.     /* End of the big patch -- Nap */
  1647. }
  1648. else if ((pw = sgetpwnam("ftp")) != NULL) {
  1649.     anonymous = 1; /* for the access_ok call */
  1650.     if (access_ok(530) < 1) {
  1651. #ifndef HELP_CRACKERS
  1652. DenyLoginAfterPassword = 1;
  1653. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s, %s",
  1654.        remoteident, name);
  1655. reply(331, "Guest login ok, send your complete e-mail address as password.");
  1656. #else
  1657. reply(530, "User %s access denied.", name);
  1658. syslog(LOG_NOTICE,
  1659.        "FTP LOGIN REFUSED (access denied) FROM %s, %s",
  1660.        remoteident, name);
  1661. dologout(0);
  1662. #endif
  1663.     }
  1664.     else {
  1665. askpasswd = 1;
  1666. /* H* fix: obey use_accessfile a little better.  This way, things set on the
  1667.    command line [like xferlog stuff] don't get stupidly overridden.
  1668.    XXX: all these checks maybe should be in acl.c and access.c */
  1669. if (use_accessfile)
  1670.     acl_setfunctions();
  1671. reply(331, "Guest login ok, send your complete e-mail address as password.");
  1672.     }
  1673. }
  1674. else {
  1675. #ifndef HELP_CRACKERS
  1676.     DenyLoginAfterPassword = 1;
  1677.     reply(331, "Guest login ok, send your complete e-mail address as password.");
  1678.     syslog(LOG_NOTICE, "FTP LOGIN REFUSED (ftp not in /etc/passwd) FROM %s, %s",
  1679.    remoteident, name);
  1680. #else
  1681.     reply(530, "User %s unknown.", name);
  1682.     syslog(LOG_NOTICE,
  1683.    "FTP LOGIN REFUSED (ftp not in /etc/passwd) FROM %s, %s",
  1684.    remoteident, name);
  1685. #endif
  1686. }
  1687. return;
  1688. #endif
  1689.     }
  1690. #ifdef ANON_ONLY
  1691. /* H* fix: define the above to completely DISABLE logins by real users,
  1692.    despite ftpusers, shells, or any of that rot.  You can always hang your
  1693.    "real" server off some other port, and access-control it. */
  1694.     else { /* "ftp" or "anon" -- MARK your conditionals, okay?! */
  1695. #ifndef HELP_CRACKERS
  1696. DenyLoginAfterPassword = 1;
  1697. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (not anonymous) FROM %s, %s",
  1698.        remoteident, name);
  1699. reply(331, "Password required for %s.", name);
  1700. #else
  1701. reply(530, "User %s unknown.", name);
  1702. syslog(LOG_NOTICE,
  1703.        "FTP LOGIN REFUSED (not anonymous) FROM %s, %s",
  1704.        remoteident, name);
  1705. #endif
  1706. return;
  1707.     }
  1708. /* fall here if username okay in any case */
  1709. #endif /* ANON_ONLY */
  1710. #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)
  1711.     if (!virtual_mode && defaultserver_deny(name) && !defaultserver_allow(name)) {
  1712. #ifndef HELP_CRACKERS
  1713. DenyLoginAfterPassword = 1;
  1714. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (ftp denied on default server) FROM %s, %s",
  1715.        remoteident, name);
  1716. #else
  1717. reply(530, "User %s access denied.", name);
  1718. syslog(LOG_NOTICE,
  1719.      "FTP LOGIN REFUSED (ftp denied on default server) FROM %s, %s",
  1720.        remoteident, name);
  1721. return;
  1722. #endif
  1723.     }
  1724. #endif
  1725.     if ((pw = sgetpwnam(name)) != NULL) {
  1726. if ((denieduid(pw->pw_uid) && !alloweduid(pw->pw_uid))
  1727.     || (deniedgid(pw->pw_gid) && !allowedgid(pw->pw_gid))) {
  1728. #ifndef HELP_CRACKERS
  1729.     DenyLoginAfterPassword = 1;
  1730.     syslog(LOG_NOTICE, "FTP LOGIN REFUSED (username in denied-uid) FROM %s, %s",
  1731.    remoteident, name);
  1732.     reply(331, "Password required for %s.", name);
  1733. #else
  1734.     reply(530, "User %s access denied.", name);
  1735.     syslog(LOG_NOTICE,
  1736.    "FTP LOGIN REFUSED (username in denied-uid) FROM %s, %s",
  1737.    remoteident, name);
  1738. #endif
  1739.     return;
  1740. }
  1741. #ifndef USE_PAM /* PAM should be doing these checks, not ftpd */
  1742. if ((shell = pw->pw_shell) == NULL || *shell == 0)
  1743.     shell = _PATH_BSHELL;
  1744. while ((cp = getusershell()) != NULL)
  1745.     if (strcmp(cp, shell) == 0)
  1746. break;
  1747. endusershell();
  1748. if (cp == NULL || checkuser(name)) {
  1749. #ifndef HELP_CRACKERS
  1750.     DenyLoginAfterPassword = 1;
  1751.     if (cp == NULL)
  1752. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (shell not in /etc/shells) FROM %s, %s", remoteident, name);
  1753.     else
  1754. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (username in %s) FROM %s, %s", _PATH_FTPUSERS, remoteident, name);
  1755.     reply(331, "Password required for %s.", name);
  1756. #else
  1757.     reply(530, "User %s access denied.", name);
  1758.     if (cp == NULL)
  1759. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (shell not in /etc/shells) FROM %s, %s", remoteident, name);
  1760.     else
  1761. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (username in %s) FROM %s, %s", _PATH_FTPUSERS, remoteident, name);
  1762. #endif
  1763.     pw = (struct passwd *) NULL;
  1764.     return;
  1765. }
  1766. #endif /* USE_PAM */
  1767. /* if user is a member of any of the guestgroups, cause a chroot() */
  1768. /* after they log in successfully                                  */
  1769. if (use_accessfile) { /* see above.  _H */
  1770.     guest = acl_guestgroup(pw);
  1771.     if (guest && acl_realgroup(pw))
  1772. guest = 0;
  1773. }
  1774.     }
  1775.     if (access_ok(530) < 1) {
  1776. #ifndef HELP_CRACKERS
  1777. DenyLoginAfterPassword = 1;
  1778. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s, %s",
  1779.        remoteident, name);
  1780. reply(331, "Password required for %s.", name);
  1781. #else
  1782. reply(530, "User %s access denied.", name);
  1783. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s, %s",
  1784.        remoteident, name);
  1785. #endif
  1786. return;
  1787.     }
  1788.     else if (use_accessfile) /* see above.  _H */
  1789. acl_setfunctions();
  1790. #ifdef BSD_AUTH
  1791.     if ((cp = start_auth(auth, name, pw)) != NULL) {
  1792. char *s;
  1793. for (;;) {
  1794.     s = strsep(&cp, "n");
  1795.     if (cp == NULL || *cp == '')
  1796. break;
  1797.     lreply(331, s);
  1798. }
  1799. reply(331, s);
  1800.     }
  1801.     else {
  1802. #endif
  1803. #ifdef SKEY
  1804. #ifndef __NetBSD__
  1805. #ifdef SKEY_NAME
  1806. /* this is the old way, but freebsd uses it */
  1807. pwok = skeyaccess(name, NULL, remotehost, remoteaddr);
  1808. #else
  1809. /* this is the new way */
  1810. pwok = skeyaccess(pw, NULL, remotehost, remoteaddr);
  1811. #endif
  1812. reply(331, "%s", skey_challenge(name, pw, pwok));
  1813. #else
  1814. if (skey_haskey(name) == 0) {
  1815.     char *myskey;
  1816.     myskey = skey_keyinfo(name);
  1817.     reply(331, "Password [%s] required for %s.",
  1818.   myskey ? myskey : "error getting challenge", name);
  1819. }
  1820. else
  1821.     reply(331, "Password required for %s.", name);
  1822. #endif
  1823. #else
  1824. #ifdef OPIE
  1825. {
  1826.     char prompt[OPIE_CHALLENGE_MAX + 1];
  1827.     opiechallenge(&opiestate, name, prompt);
  1828.     if (askpasswd == -1) {
  1829. syslog(LOG_WARNING, "Invalid FTP user name %s attempted from %s", name, remotehost);
  1830. pwok = 0;
  1831.     }
  1832.     else
  1833. pwok = af_pwok && opiealways(pw->pw_dir);
  1834.     reply(331, "Response to %s %s for %s.",
  1835.   prompt, pwok ? "requested" : "required", name);
  1836. }
  1837. #else
  1838. reply(331, "Password required for %s.", name);
  1839. #endif
  1840. #endif
  1841. #ifdef BSD_AUTH
  1842.     }
  1843. #endif
  1844.     askpasswd = 1;
  1845.     /* Delay before reading passwd after first failed attempt to slow down
  1846.      * passwd-guessing programs. */
  1847.     if (login_attempts) {
  1848. enable_signaling(); /* we can allow signals once again: kinch */
  1849. sleep((unsigned) login_attempts);
  1850.     }
  1851.     return;
  1852. }
  1853. /* Check if a user is in the file _PATH_FTPUSERS */
  1854. int checkuser(char *name)
  1855. {
  1856.     register FILE *fd;
  1857.     register char *p;
  1858.     char line[BUFSIZ];
  1859.     if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) {
  1860. while (fgets(line, sizeof(line), fd) != NULL)
  1861.     if ((p = strchr(line, 'n')) != NULL) {
  1862. *p = '';
  1863. if (line[0] == '#')
  1864.     continue;
  1865. if (strcasecmp(line, name) == 0) {
  1866.     (void) fclose(fd);
  1867.     return (1);
  1868. }
  1869.     }
  1870. (void) fclose(fd);
  1871.     }
  1872.     return (0);
  1873. }
  1874. int denieduid(uid_t uid)
  1875. {
  1876.     struct aclmember *entry = NULL;
  1877.     int which;
  1878.     char *ptr;
  1879.     struct passwd *pw;
  1880.     while (getaclentry("deny-uid", &entry)) {
  1881. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  1882.     if (!strcmp(ARG[which], "*"))
  1883. return (1);
  1884.     if (ARG[which][0] == '%') {
  1885. if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) {
  1886.     if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) {
  1887. if (uid == strtoul(ARG[which] + 1, NULL, 0))
  1888.     return (1);
  1889.     }
  1890.     else {
  1891. *ptr++ = '';
  1892. if ((ARG[which][1] == '')
  1893.     || (uid >= strtoul(ARG[which] + 1, NULL, 0))) {
  1894.     *--ptr = '+';
  1895.     return (1);
  1896. }
  1897. *--ptr = '+';
  1898.     }
  1899. }
  1900. else {
  1901.     *ptr++ = '';
  1902.     if (((ARG[which][1] == '')
  1903.  || (uid >= strtoul(ARG[which] + 1, NULL, 0)))
  1904. && ((*ptr == '')
  1905.     || (uid <= strtoul(ptr, NULL, 0)))) {
  1906. *--ptr = '-';
  1907. return (1);
  1908.     }
  1909.     *--ptr = '-';
  1910. }
  1911.     }
  1912.     else {
  1913. pw = getpwnam(ARG[which]);
  1914. if (pw && (uid == pw->pw_uid))
  1915.     return (1);
  1916.     }
  1917. }
  1918.     }
  1919.     return (0);
  1920. }
  1921. int alloweduid(uid_t uid)
  1922. {
  1923.     struct aclmember *entry = NULL;
  1924.     int which;
  1925.     char *ptr;
  1926.     struct passwd *pw;
  1927.     while (getaclentry("allow-uid", &entry)) {
  1928. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  1929.     if (!strcmp(ARG[which], "*"))
  1930. return (1);
  1931.     if (ARG[which][0] == '%') {
  1932. if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) {
  1933.     if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) {
  1934. if (uid == strtoul(ARG[which] + 1, NULL, 0))
  1935.     return (1);
  1936.     }
  1937.     else {
  1938. *ptr++ = '';
  1939. if ((ARG[which][1] == '')
  1940.     || (uid >= strtoul(ARG[which] + 1, NULL, 0))) {
  1941.     *--ptr = '+';
  1942.     return (1);
  1943. }
  1944. *--ptr = '+';
  1945.     }
  1946. }
  1947. else {
  1948.     *ptr++ = '';
  1949.     if (((ARG[which][1] == '')
  1950.  || (uid >= strtoul(ARG[which] + 1, NULL, 0)))
  1951. && ((*ptr == '')
  1952.     || (uid <= strtoul(ptr, NULL, 0)))) {
  1953. *--ptr = '-';
  1954. return (1);
  1955.     }
  1956.     *--ptr = '-';
  1957. }
  1958.     }
  1959.     else {
  1960. pw = getpwnam(ARG[which]);
  1961. if (pw && (uid == pw->pw_uid))
  1962.     return (1);
  1963.     }
  1964. }
  1965.     }
  1966.     return (0);
  1967. }
  1968. int deniedgid(gid_t gid)
  1969. {
  1970.     struct aclmember *entry = NULL;
  1971.     int which;
  1972.     char *ptr;
  1973.     struct group *grp;
  1974.     while (getaclentry("deny-gid", &entry)) {
  1975. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  1976.     if (!strcmp(ARG[which], "*"))
  1977. return (1);
  1978.     if (ARG[which][0] == '%') {
  1979. if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) {
  1980.     if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) {
  1981. if (gid == strtoul(ARG[which] + 1, NULL, 0))
  1982.     return (1);
  1983.     }
  1984.     else {
  1985. *ptr++ = '';
  1986. if ((ARG[which][1] == '')
  1987.     || (gid >= strtoul(ARG[which] + 1, NULL, 0))) {
  1988.     *--ptr = '+';
  1989.     return (1);
  1990. }
  1991. *--ptr = '+';
  1992.     }
  1993. }
  1994. else {
  1995.     *ptr++ = '';
  1996.     if (((ARG[which][1] == '')
  1997.  || (gid >= strtoul(ARG[which] + 1, NULL, 0)))
  1998. && ((*ptr == '')
  1999.     || (gid <= strtoul(ptr, NULL, 0)))) {
  2000. *--ptr = '-';
  2001. return (1);
  2002.     }
  2003.     *--ptr = '-';
  2004. }
  2005.     }
  2006.     else {
  2007. grp = getgrnam(ARG[which]);
  2008. if (grp && (gid == grp->gr_gid))
  2009.     return (1);
  2010.     }
  2011. }
  2012.     }
  2013.     return (0);
  2014. }
  2015. int allowedgid(gid_t gid)
  2016. {
  2017.     struct aclmember *entry = NULL;
  2018.     int which;
  2019.     char *ptr;
  2020.     struct group *grp;
  2021.     while (getaclentry("allow-gid", &entry)) {
  2022. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  2023.     if (!strcmp(ARG[which], "*"))
  2024. return (1);
  2025.     if (ARG[which][0] == '%') {
  2026. if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) {
  2027.     if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) {
  2028. if (gid == strtoul(ARG[which] + 1, NULL, 0))
  2029.     return (1);
  2030.     }
  2031.     else {
  2032. *ptr++ = '';
  2033. if ((ARG[which][1] == '')
  2034.     || (gid >= strtoul(ARG[which] + 1, NULL, 0))) {
  2035.     *--ptr = '+';
  2036.     return (1);
  2037. }
  2038. *--ptr = '+';
  2039.     }
  2040. }
  2041. else {
  2042.     *ptr++ = '';
  2043.     if (((ARG[which][1] == '')
  2044.  || (gid >= strtoul(ARG[which] + 1, NULL, 0)))
  2045. && ((*ptr == '')
  2046.     || (gid <= strtoul(ptr, NULL, 0)))) {
  2047. *--ptr = '-';
  2048. return (1);
  2049.     }
  2050.     *--ptr = '-';
  2051. }
  2052.     }
  2053.     else {
  2054. grp = getgrnam(ARG[which]);
  2055. if (grp && (gid == grp->gr_gid))
  2056.     return (1);
  2057.     }
  2058. }
  2059.     }
  2060.     return (0);
  2061. }
  2062. /* Terminate login as previous user, if any, resetting state; used when USER
  2063.  * command is given or login fails. */
  2064. void end_login(void)
  2065. {
  2066.     delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  2067.     (void) seteuid((uid_t) 0);
  2068.     if (logged_in)
  2069. if (wtmp_logging)
  2070.     wu_logwtmp(ttyline, pw->pw_name, remotehost, 0);
  2071.     pw = NULL;
  2072. #ifdef AFS_AUTH
  2073.     ktc_ForgetAllTokens();
  2074. #endif
  2075.     logged_in = 0;
  2076.     anonymous = 0;
  2077.     guest = 0;
  2078. }
  2079. int validate_eaddr(char *eaddr)
  2080. {
  2081.     int i, host, state;
  2082.     for (i = host = state = 0; eaddr[i] != ''; i++) {
  2083. switch (eaddr[i]) {
  2084. case '.':
  2085.     if (!host)
  2086. return 0;
  2087.     if (state == 2)
  2088. state = 3;
  2089.     host = 0;
  2090.     break;
  2091. case '@':
  2092.     if (!host || state > 1 || !strncasecmp("ftp", eaddr + i - host, host))
  2093. return 0;
  2094.     state = 2;
  2095.     host = 0;
  2096.     break;
  2097. case '!':
  2098. case '%':
  2099.     if (!host || state > 1)
  2100. return 0;
  2101.     state = 1;
  2102.     host = 0;
  2103.     break;
  2104. case '-':
  2105.     break;
  2106. default:
  2107.     host++;
  2108. }
  2109.     }
  2110.     if (((state == 3) && host > 1) || ((state == 2) && !host) ||
  2111. ((state == 1) && host > 1))
  2112. return 1;
  2113.     else
  2114. return 0;
  2115. }
  2116. #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)
  2117. static int AllowVirtualUser(const char *username)
  2118. {
  2119.     struct aclmember *entry = NULL;
  2120.     int which;
  2121.     while (getaclentry("virtual", &entry))
  2122. if (ARG0 && hostmatch(ARG0, virtual_address, virtual_hostname)
  2123.     && ARG1 && !strcasecmp(ARG1, "allow"))
  2124.     for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  2125. if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which]))
  2126.     return (1);
  2127.     return (0);
  2128. }
  2129. static int DenyVirtualUser(const char *username)
  2130. {
  2131.     struct aclmember *entry = NULL;
  2132.     int which;
  2133.     while (getaclentry("virtual", &entry))
  2134. if (ARG0 && hostmatch(ARG0, virtual_address, virtual_hostname)
  2135.     && ARG1 && !strcasecmp(ARG1, "deny"))
  2136.     for (which = 2; (which < MAXARGS) && ARG[which]; which++)
  2137. if (!strcasecmp(username, ARG[which]) || !strcmp("*", ARG[which]))
  2138.     return (1);
  2139.     return (0);
  2140. }
  2141. static int DenyVirtualAnonymous(void)
  2142. {
  2143.     struct aclmember *entry = NULL;
  2144.     while (getaclentry("virtual", &entry))
  2145. if (ARG0 && hostmatch(ARG0, virtual_address, virtual_hostname)
  2146.     && ARG1 && !strcasecmp(ARG1, "private"))
  2147.     return (1);
  2148.     return (0);
  2149. }
  2150. #endif
  2151. void pass(char *passwd)
  2152. {
  2153. #ifndef USE_PAM
  2154.     char *xpasswd, *salt;
  2155. #endif
  2156.     int passwarn = 0;
  2157.     int rval = 1;
  2158. #ifdef SECUREOSF
  2159.     struct pr_passwd *pr;
  2160.     int crypt_alg = 0;
  2161. #endif
  2162. #ifdef BSD_AUTH
  2163.     extern int ext_auth;
  2164.     extern char *check_auth();
  2165. #endif
  2166. #ifdef ULTRIX_AUTH
  2167.     int numfails;
  2168. #endif /* ULTRIX_AUTH */
  2169. #ifdef HAS_PW_EXPIRE
  2170.     int set_expired = FALSE;
  2171. #endif 
  2172. #ifdef AFS_AUTH
  2173.     char *reason;
  2174. #endif /* AFS_AUTH */
  2175. #ifdef DCE_AUTH
  2176.     sec_passwd_rec_t pwr;
  2177.     sec_login_handle_t lhdl;
  2178.     boolean32 rstpwd;
  2179.     sec_login_auth_src_t asrc;
  2180.     error_status_t status;
  2181. #endif /* DCE_AUTH */
  2182.     if (logged_in || askpasswd == 0) {
  2183. #ifdef VERBOSE_ERROR_LOGING
  2184. syslog(LOG_NOTICE, "FTP LOGIN REFUSED (PASS before USER) FROM %s",
  2185.        remoteident);
  2186. #endif
  2187. reply(503, "Login with USER first.");
  2188. return;
  2189.     }
  2190.     askpasswd = 0;
  2191.     /* Disable lreply() if the first character of the password is '-' since
  2192.      * some hosts don't understand continuation messages and hang... */
  2193.     if (*passwd == '-')
  2194. dolreplies = 0;
  2195.     else
  2196. dolreplies = 1;
  2197. /* ******** REGULAR/GUEST USER PASSWORD PROCESSING ********** */
  2198.     if (!anonymous) { /* "ftp" is only account allowed no password */
  2199. #ifndef HELP_CRACKERS
  2200. if (DenyLoginAfterPassword) {
  2201.     pr_mesg(530, DelayedMessageFile);
  2202.     reply(530, "Login incorrect.");
  2203.     acl_remove();
  2204.     pw = NULL;
  2205.     if (++login_attempts >= lgi_failure_threshold) {
  2206. syslog(LOG_NOTICE, "repeated login failures from %s",
  2207.        remoteident);
  2208. exit(0);
  2209.     }
  2210.     return;
  2211. }
  2212. #endif
  2213. if (*passwd == '-')
  2214.     passwd++;
  2215. #ifdef USE_PAM
  2216. /* PAM authentication
  2217.  * If PAM authenticates a user we know nothing about on the local
  2218.  * system, use the generic guest account credentials. We should make
  2219.  * this somehow a configurable item somewhere; later more on that.
  2220.  *
  2221.  * For now assume the guest (not anonymous) identity, so the site
  2222.  * admins can still differentiate between the truw anonymous user and
  2223.  * a little bit more special ones. Otherwise he wouldn't go the extra
  2224.  * mile to have a different user database, right?
  2225.  *              --gaftonc */
  2226. if (pam_check_pass(the_user, passwd)) {
  2227.     rval = 0;
  2228.     if (pw == NULL) {
  2229. /* assume guest account identity */
  2230. pw = sgetpwnam("ftp");
  2231. anonymous = 0;
  2232. guest = 1;
  2233. /* even go as far as... */
  2234. if (pw != NULL && pw->pw_name != NULL) {
  2235.     free(pw->pw_name);
  2236.     pw->pw_name = sgetsave(the_user);
  2237. }
  2238.     }
  2239. }
  2240. #else /* !USE_PAM */
  2241. #ifdef BSD_AUTH
  2242. if (ext_auth) {
  2243.     if ((salt = check_auth(the_user, passwd))) {
  2244. reply(530, salt);
  2245. #ifdef LOG_FAILED /* 27-Apr-93      EHK/BM          */
  2246. syslog(LOG_INFO, "failed login from %s",
  2247.        remoteident);
  2248. #endif
  2249. acl_remove();
  2250. pw = NULL;
  2251. if (++login_attempts >= lgi_failure_threshold) {
  2252.     syslog(LOG_NOTICE, "repeated login failures from %s",
  2253.    remoteident);
  2254.     exit(0);
  2255. }
  2256. return;
  2257.     }
  2258. }
  2259. else {
  2260. #endif
  2261.     *guestpw = '';
  2262.     if (pw == NULL)
  2263. salt = "xx";
  2264.     else
  2265. #ifndef OPIE
  2266. salt = pw->pw_passwd;
  2267. #ifdef SECUREOSF
  2268.     if ((pr = getprpwnam(pw->pw_name)) != NULL) {
  2269. if (pr->uflg.fg_newcrypt)
  2270.     crypt_alg = pr->ufld.fd_newcrypt;
  2271. else if (pr->sflg.fg_newcrypt)
  2272.     crypt_alg = pr->sfld.fd_newcrypt;
  2273. else
  2274.     crypt_alg = 0;
  2275.     }
  2276.     else
  2277. crypt_alg = 0;
  2278.     xpasswd = dispcrypt(passwd, salt, crypt_alg);
  2279. #elif defined(SecureWare) || defined(HPUX_10_TRUSTED)
  2280.     xpasswd = bigcrypt(passwd, salt);
  2281. #elif defined(KERBEROS)
  2282.     xpasswd = crypt16(passwd, salt);
  2283. #elif defined(SKEY)
  2284. #ifndef __NetBSD__
  2285.     xpasswd = skey_crypt(passwd, salt, pw, pwok);
  2286.     pwok = 0;
  2287. #else
  2288.     if ((pw != NULL) && (pw->pw_name != NULL) && skey_haskey(pw->pw_name) == 0 &&
  2289. skey_passcheck(pw->pw_name, passwd) != -1)
  2290. xpasswd = pw->pw_passwd;
  2291.     else
  2292. xpasswd = crypt(passwd, salt);
  2293. #endif
  2294. #else
  2295.     xpasswd = crypt(passwd, salt);
  2296. #endif /* SKEY */
  2297. #else /* OPIE */
  2298.     if (!opieverify(&opiestate, passwd))
  2299. rval = 0;
  2300.     xpasswd = crypt(passwd, pw->pw_passwd);
  2301. #endif /* OPIE */
  2302. #ifdef ULTRIX_AUTH
  2303.     if ((numfails = ultrix_check_pass(passwd, xpasswd)) >= 0) {
  2304. #else
  2305.     if (pw != NULL) {
  2306. #ifdef AFS_AUTH
  2307. if (strcmp(pw->pw_passwd, "X") == 0)
  2308.     if (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION | KA_USERAUTH_DOSETPAG, pw->pw_name, "", 0, passwd, 0, 0, 0, &reason) == 0)
  2309. rval = 0;
  2310.     else
  2311. printf("230-AFS: %s", reason);
  2312. else
  2313. #endif /* AFS_AUTH */
  2314.     /* The strcmp does not catch null passwords! */
  2315. #ifdef HAS_PW_EXPIRE
  2316.     if(pw->pw_expire != NULL) {
  2317. if(pw->pw_expire && time(NULL) >= pw->pw_expire) {
  2318.     set_expired = TRUE;
  2319.     }
  2320. #endif
  2321.     
  2322.     if (*pw->pw_passwd != '' &&
  2323. #ifdef HAS_PW_EXPIRE
  2324. !set_expired &&
  2325. #endif
  2326. strcmp(xpasswd, pw->pw_passwd) == 0) {
  2327. #endif
  2328.     rval = 0;
  2329. }
  2330. #ifdef DCE_AUTH
  2331. #ifndef ALWAYS_TRY_DCE
  2332. else
  2333. #endif /* ALWAYS_TRY_DCE */
  2334. {
  2335.     sec_login_setup_identity((unsigned_char_p_t) pw->pw_name, sec_login_no_flags, &lhdl, &status);
  2336.     if (status == error_status_ok) {
  2337. printf("230-sec_login_setup_identity OKn");
  2338. pwr.key.tagged_union.plain = (idl_char *) passwd;
  2339. pwr.key.key_type = sec_passwd_plain;
  2340. pwr.pepper = 0;
  2341. pwr.version_number = sec_passwd_c_version_none;
  2342. /* validate password with login context */
  2343. sec_login_valid_and_cert_ident(lhdl, &pwr, &rstpwd, &asrc, &status);
  2344. if (!rstpwd && (asrc == sec_login_auth_src_network) && (status == error_status_ok)) {
  2345.     printf("230-sec_login_valid_and_cert_ident OKn");
  2346.     sec_login_set_context(lhdl, &status);
  2347.     printf("230-sec_login_set_context finishedn");
  2348.     if (status != error_status_ok) {
  2349. int pstatus;
  2350. dce_error_string_t s;
  2351. printf("230-Error status: %d:n", status);
  2352. dce_error_inq_text(status, s, &pstatus);
  2353. printf("230-%sn", s);
  2354. fflush(stderr);
  2355. sec_login_purge_context(lhdl, &status);
  2356.     }
  2357.     else {
  2358. /*sec_login_get_pwent(lhdl, &pw, &status); */
  2359. rval = 0;
  2360.     }
  2361. }
  2362.     }
  2363. }
  2364. #endif /* DCE_AUTH */
  2365.     }
  2366. #endif /* !USE_PAM */
  2367.     if (rval) {
  2368. reply(530, "Login incorrect.");
  2369. #ifdef LOG_FAILED /* 27-Apr-93    EHK/BM             */
  2370. /* H* add-on: yell about attempts to use the trojan.  This may alarm you
  2371.    if you're "stringsing" the binary and you see "NULL" pop out in just
  2372.    about the same place as it would have in 2.2c! */
  2373. if (!strcasecmp(passwd, "NULL"))
  2374.     syslog(LOG_NOTICE, "REFUSED "NULL" from %s, %s",
  2375.    remoteident, the_user);
  2376. else
  2377.     syslog(LOG_INFO, "failed login from %s",
  2378.    remoteident);
  2379. #endif
  2380. acl_remove();
  2381. pw = NULL;
  2382. if (++login_attempts >= lgi_failure_threshold) {
  2383.     syslog(LOG_NOTICE, "repeated login failures from %s",
  2384.    remoteident);
  2385.     exit(0);
  2386. }
  2387. return;
  2388.     }
  2389. #ifdef BSD_AUTH
  2390. }
  2391. #endif
  2392. /* ANONYMOUS USER PROCESSING STARTS HERE */
  2393.     }
  2394.     else {
  2395. char *pwin, *pwout = guestpw;
  2396. struct aclmember *entry = NULL;
  2397. int valid;
  2398. int enforce = 0;
  2399. if (getaclentry("passwd-check", &entry) &&
  2400.     ARG0 && strcasecmp(ARG0, "none")) {
  2401.     if (!strcasecmp(ARG0, "rfc822"))
  2402. valid = validate_eaddr(passwd);
  2403.     else if (!strcasecmp(ARG0, "trivial"))
  2404. valid = (strchr(passwd, '@') == NULL) ? 0 : 1;
  2405.     else
  2406. valid = 1;
  2407.     if (ARG1 && !strcasecmp(ARG1, "enforce"))
  2408. enforce = 1;
  2409.     /* Block off "default" responses like mozilla@ and IE30User@
  2410.      * (at the administrator's discretion).  --AC
  2411.      */
  2412.     entry = NULL;
  2413.     while (getaclentry("deny-email", &entry)) {
  2414. if (ARG0
  2415.     && ((strcasecmp(passwd, ARG0) == 0)
  2416. || regexmatch(passwd, ARG0)
  2417. || ((*passwd == '-')
  2418.     && ((strcasecmp(passwd + 1, ARG0) == 0)
  2419. || regexmatch(passwd + 1, ARG0))))) {
  2420.     valid = 0;
  2421.     break;
  2422. }
  2423.     }
  2424.     if (!valid && enforce) {
  2425. lreply(530, "The response '%s' is not valid", passwd);
  2426. lreply(530, "Please use your e-mail address as your password");
  2427. lreply(530, "   for example: %s@%s or %s@",
  2428.        authenticated ? authuser : "joe", remotehost,
  2429.        authenticated ? authuser : "joe");
  2430. lreply(530, "[%s will be added if password ends with @]",
  2431.        remotehost);
  2432. reply(530, "Login incorrect.");
  2433. #ifdef VERBOSE_ERROR_LOGING
  2434. syslog(LOG_NOTICE, "FTP ACCESS REFUSED (anonymous password not rfc822) from %s",
  2435.        remoteident);
  2436. #endif
  2437. acl_remove();
  2438. if (++login_attempts >= lgi_failure_threshold) {
  2439.     syslog(LOG_NOTICE, "repeated login failures from %s",
  2440.    remoteident);
  2441.     exit(0);
  2442. }
  2443. return;
  2444.     }
  2445.     else if (!valid)
  2446. passwarn = 1;
  2447. }
  2448. if (!*passwd) {
  2449.     strcpy(guestpw, "[none_given]");
  2450. }
  2451. else {
  2452.     int cnt = sizeof(guestpw) - 2;
  2453.     for (pwin = passwd; *pwin && cnt--; pwin++)
  2454. if (!isgraph(*pwin))
  2455.     *pwout++ = '_';
  2456. else
  2457.     *pwout++ = *pwin;
  2458. }
  2459. #ifndef HELP_CRACKERS
  2460. if (DenyLoginAfterPassword) {
  2461.     pr_mesg(530, DelayedMessageFile);
  2462.     reply(530, "Login incorrect.");
  2463.     acl_remove();
  2464.     pw = NULL;
  2465.     if (++login_attempts >= lgi_failure_threshold) {
  2466. syslog(LOG_NOTICE, "repeated login failures from %s",
  2467.        remoteident);
  2468. exit(0);
  2469.     }
  2470.     return;
  2471. }
  2472. #endif
  2473.     }
  2474.     /* if logging is enabled, open logfile before chroot or set group ID */
  2475.     if ((log_outbound_xfers || log_incoming_xfers) && (syslogmsg != 1)) {
  2476. mode_t oldmask;
  2477. oldmask = umask(0);
  2478. xferlog = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0640);
  2479. (void) umask(oldmask);
  2480. if (xferlog < 0) {
  2481.     syslog(LOG_ERR, "cannot open logfile %s: %s", logfile,
  2482.    strerror(errno));
  2483.     xferlog = 0;
  2484. }
  2485.     }
  2486. #ifdef DEBUG
  2487. /* I had a lot of trouble getting xferlog working, because of two factors:
  2488.    acl_setfunctions making stupid assumptions, and sprintf LOSING.  _H */
  2489. /* 
  2490.  * Actually, sprintf was not losing, but the rules changed... next release
  2491.  * this will be fixed the correct way, but right now, it works well enough
  2492.  * -- sob 
  2493.  */
  2494.     syslog(LOG_INFO, "-i %d,-o %d,xferlog %s: %d",
  2495.    log_incoming_xfers, log_outbound_xfers, logfile, xferlog);
  2496. #endif
  2497.     enable_signaling(); /* we can allow signals once again: kinch */
  2498.     /* if autogroup command applies to user's class change pw->pw_gid */
  2499.     if (anonymous && use_accessfile) { /* see above.  _H */
  2500. (void) acl_autogroup(pw);
  2501. guest = acl_guestgroup(pw); /* the new group may be a guest */
  2502. if (guest && acl_realgroup(pw))
  2503.     guest = 0;
  2504. anonymous = !guest;
  2505.     }
  2506. /* END AUTHENTICATION */
  2507.     login_attempts = 0; /* this time successful */
  2508. /* SET GROUP ID STARTS HERE */
  2509. #ifndef AIX
  2510.     (void) setegid((gid_t) pw->pw_gid);
  2511. #else
  2512.     (void) setgid((gid_t) pw->pw_gid);
  2513. #endif
  2514.     (void) initgroups(pw->pw_name, pw->pw_gid);
  2515. #ifdef DEBUG
  2516.     syslog(LOG_DEBUG, "initgroups has been called");
  2517. #endif
  2518. /* WTMP PROCESSING STARTS HERE */
  2519.     if (wtmp_logging) {
  2520. /* open wtmp before chroot */
  2521. #if ((defined(BSD) && (BSD >= 199103)) || defined(sun))
  2522. (void) sprintf(ttyline, "ftp%ld", (long) getpid());
  2523. #else
  2524. (void) sprintf(ttyline, "ftpd%d", getpid());
  2525. #endif
  2526. #ifdef DEBUG
  2527. syslog(LOG_DEBUG, "about to call wtmp");
  2528. #endif
  2529. wu_logwtmp(ttyline, pw->pw_name, remotehost, 1);
  2530.     }
  2531.     logged_in = 1;
  2532.     expand_id();
  2533. #ifdef QUOTA
  2534.     memset(&quota, 0, sizeof(quota));
  2535.     get_quota(pw->pw_dir, pw->pw_uid);
  2536. #endif
  2537.     restricted_user = 0;
  2538.     if (!anonymous)
  2539. if ((restricteduid(pw->pw_uid) && !unrestricteduid(pw->pw_uid))
  2540.     || (restrictedgid(pw->pw_gid) && !unrestrictedgid(pw->pw_gid)))
  2541.     restricted_user = 1;
  2542.     if (anonymous || guest) {
  2543. char *sp;
  2544. /* We MUST do a chdir() after the chroot. Otherwise the old current
  2545.  * directory will be accessible as "." outside the new root! */
  2546. #ifdef ALTERNATE_CD
  2547. home = defhome;
  2548. #endif
  2549. #ifdef VIRTUAL
  2550. if (virtual_mode && !guest) {
  2551. #ifdef CLOSED_VIRTUAL_SERVER
  2552.     if (DenyVirtualAnonymous()) {
  2553. #ifdef VERBOSE_ERROR_LOGING
  2554. syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host anonymous access denied) for %s",
  2555.        remoteident);
  2556. #endif
  2557. reply(530, "Login incorrect.");
  2558. if (++login_attempts >= lgi_failure_threshold) {
  2559.     syslog(LOG_NOTICE, "repeated login failures from %s", remoteident);
  2560.     exit(0);
  2561. }
  2562. goto bad;
  2563.     }
  2564. #endif
  2565.     /* Anonymous user in virtual_mode */
  2566.     if (pw->pw_dir)
  2567. free(pw->pw_dir);
  2568.     pw->pw_dir = sgetsave(virtual_root);
  2569. }
  2570. else
  2571. #endif
  2572.     /*
  2573.        *  New chroot logic.
  2574.        *
  2575.        *  If VIRTUAL is supported, the chroot for anonymous users on the
  2576.        *  virtual host has already been determined.  Otherwise the logic
  2577.        *  below applies:
  2578.        *
  2579.        *  If this is an anonymous user, the chroot directory is determined
  2580.        *  by the "anonymous-root" clause and the home directory is taken
  2581.        *  from the etc/passwd file found after chroot'ing.
  2582.        *
  2583.        *  If this a guest user, the chroot directory is determined by the
  2584.        *  "guest-root" clause and the home directory is taken from the
  2585.        *  etc/passwd file found after chroot'ing.
  2586.        *
  2587.        *  The effect of this logic is that the entire chroot environment
  2588.        *  is under the control of the ftpaccess file and the supporting
  2589.        *  files in the ftp environment.  The system-wide passwd file is
  2590.        *  used only to authenticate the user.
  2591.      */
  2592. {
  2593.     struct aclmember *entry = NULL;
  2594.     char *root_path = NULL;
  2595.     if (anonymous) {
  2596. char class[1024];
  2597. (void) acl_getclass(class);
  2598. while (getaclentry("anonymous-root", &entry) && ARG0) {
  2599.     if (!ARG1) {
  2600. if (!root_path)
  2601.     root_path = ARG0;
  2602.     }
  2603.     else {
  2604. int which;
  2605. for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
  2606.     if (!strcmp(ARG[which], "*")) {
  2607. if (!root_path)
  2608.     root_path = ARG0;
  2609.     }
  2610.     else {
  2611. if (!strcasecmp(ARG[which], class))
  2612.     root_path = ARG0;
  2613.     }
  2614. }
  2615.     }
  2616. }
  2617.     }
  2618.     else { /* (guest) */
  2619. while (getaclentry("guest-root", &entry) && ARG0) {
  2620.     if (!ARG1) {
  2621. if (!root_path)
  2622.     root_path = ARG0;
  2623.     }
  2624.     else {
  2625. int which;
  2626. char *ptr;
  2627. for (which = 1; (which < MAXARGS) && ARG[which]; which++) {
  2628.     if (!strcmp(ARG[which], "*")) {
  2629. if (!root_path)
  2630.     root_path = ARG0;
  2631.     }
  2632.     else {
  2633. if (ARG[which][0] == '%') {
  2634.     if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) {
  2635. if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) {
  2636.     if (pw->pw_uid == strtoul(ARG[which] + 1, NULL, 0))
  2637. root_path = ARG0;
  2638. }
  2639. else {
  2640.     *ptr++ = '';
  2641.     if ((ARG[which][1] == '')
  2642. || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0)))
  2643. root_path = ARG0;
  2644.     *--ptr = '+';
  2645. }
  2646.     }
  2647.     else {
  2648. *ptr++ = '';
  2649. if (((ARG[which][1] == '')
  2650.      || (pw->pw_uid >= strtoul(ARG[which] + 1, NULL, 0)))
  2651.     && ((*ptr == '')
  2652. || (pw->pw_uid <= strtoul(ptr, NULL, 0))))
  2653.     root_path = ARG0;
  2654. *--ptr = '-';
  2655.     }
  2656. }
  2657. else {
  2658.     struct passwd *guest_pw = getpwnam(ARG[which]);
  2659.     if (guest_pw && (pw->pw_uid == guest_pw->pw_uid))
  2660. root_path = ARG0;
  2661. }
  2662.     }
  2663. }
  2664.     }
  2665. }
  2666.     }
  2667.     if (root_path) {
  2668. struct passwd *chroot_pw = NULL;
  2669. #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)
  2670. if (virtual_mode && strcmp(root_path, virtual_root) && !(AllowVirtualUser(pw->pw_name) && !DenyVirtualUser(pw->pw_name))) {
  2671. #ifdef VERBOSE_ERROR_LOGING
  2672.     syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host access denied) for %s, %s",
  2673.    remoteident, pw->pw_name);
  2674. #endif
  2675.     reply(530, "Login incorrect.");
  2676.     if (++login_attempts >= lgi_failure_threshold) {
  2677. syslog(LOG_NOTICE, "repeated login failures from %s", remoteident);
  2678. exit(0);
  2679.     }
  2680.     goto bad;
  2681. }
  2682. #endif
  2683. (void) strncpy(chroot_path, root_path, sizeof(chroot_path));
  2684. chroot_path[sizeof(chroot_path) - 1] = '';
  2685. pw->pw_dir = sgetsave(chroot_path);
  2686. if (chroot(root_path) < 0 || chdir("/") < 0) {
  2687. #ifdef VERBOSE_ERROR_LOGING
  2688.     syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set guest privileges) for %s, %s",
  2689.    remoteident, pw->pw_name);
  2690. #endif
  2691.     reply(530, "Can't set guest privileges.");
  2692.     goto bad;
  2693. }
  2694. if ((chroot_pw = getpwuid(pw->pw_uid)) != NULL)
  2695.     if (chdir(chroot_pw->pw_dir) >= 0)
  2696. home = sgetsave(chroot_pw->pw_dir);
  2697. goto slimy_hack; /* onea these days I'll make this structured code, honest ... */
  2698.     }
  2699. }
  2700. /* determine root and home directory */
  2701. if ((sp = strstr(pw->pw_dir, "/./")) == NULL) {
  2702.     (void) strncpy(chroot_path, pw->pw_dir, sizeof(chroot_path));
  2703.     chroot_path[sizeof(chroot_path) - 1] = '';
  2704. #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)
  2705.     if (virtual_mode && strcmp(chroot_path, virtual_root) && !(AllowVirtualUser(pw->pw_name) && !DenyVirtualUser(pw->pw_name))) {
  2706. #ifdef VERBOSE_ERROR_LOGING
  2707. syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host access denied) for %s, %s",
  2708.        remoteident, pw->pw_name);
  2709. #endif
  2710. reply(530, "Login incorrect.");
  2711. if (++login_attempts >= lgi_failure_threshold) {
  2712.     syslog(LOG_NOTICE, "repeated login failures from %s", remoteident);
  2713.     exit(0);
  2714. }
  2715. goto bad;
  2716.     }
  2717. #endif
  2718.     if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
  2719. #ifdef VERBOSE_ERROR_LOGING
  2720. syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set guest privileges) for %s, %s",
  2721.        remoteident, pw->pw_name);
  2722. #endif
  2723. reply(530, "Can't set guest privileges.");
  2724. goto bad;
  2725.     }
  2726. }
  2727. else {
  2728.     *sp++ = '';
  2729.     (void) strncpy(chroot_path, pw->pw_dir, sizeof(chroot_path));
  2730.     chroot_path[sizeof(chroot_path) - 1] = '';
  2731. #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)
  2732.     if (virtual_mode && strcmp(chroot_path, virtual_root) && !(AllowVirtualUser(pw->pw_name) && !DenyVirtualUser(pw->pw_name))) {
  2733. #ifdef VERBOSE_ERROR_LOGING
  2734. syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host access denied) for %s, %s",
  2735.        remoteident, pw->pw_name);
  2736. #endif
  2737. reply(530, "Login incorrect.");
  2738. if (++login_attempts >= lgi_failure_threshold) {
  2739.     syslog(LOG_NOTICE, "repeated login failures from %s", remoteident);
  2740.     exit(0);
  2741. }
  2742. goto bad;
  2743.     }
  2744. #endif
  2745.     if (chroot(pw->pw_dir) < 0 || chdir(++sp) < 0) {
  2746. #ifdef VERBOSE_ERROR_LOGING
  2747. syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set guest privileges) for %s, %s",
  2748.        remoteident, pw->pw_name);
  2749. #endif
  2750. reply(550, "Can't set guest privileges.");
  2751. goto bad;
  2752.     }
  2753. #ifdef ALTERNATE_CD
  2754.     home = sp;
  2755. #endif
  2756. }
  2757.       slimy_hack:
  2758. /* shut up you stupid compiler! */  {
  2759.     int i = 0;
  2760.     i++;
  2761. }
  2762.     }
  2763. #if defined(VIRTUAL) && defined(CLOSED_VIRTUAL_SERVER)
  2764.     else if (virtual_mode && !(AllowVirtualUser(pw->pw_name) && !DenyVirtualUser(pw->pw_name))) {
  2765. #ifdef VERBOSE_ERROR_LOGING
  2766. syslog(LOG_NOTICE, "FTP LOGIN FAILED (virtual host access denied) for %s, %s",
  2767.        remoteident, pw->pw_name);
  2768. #endif
  2769. reply(530, "Login incorrect.");
  2770. if (++login_attempts >= lgi_failure_threshold) {
  2771.     syslog(LOG_NOTICE, "repeated login failures from %s", remoteident);
  2772.     exit(0);
  2773. }
  2774. goto bad;
  2775.     }
  2776. #endif
  2777. #ifdef AIX
  2778.     {
  2779. /* AIX 3 lossage.  Don't ask.  It's undocumented.  */
  2780. priv_t priv;
  2781. priv.pv_priv[0] = 0;
  2782. priv.pv_priv[1] = 0;
  2783. /*       setgroups(NULL, NULL); */
  2784. if (setpriv(PRIV_SET | PRIV_INHERITED | PRIV_EFFECTIVE | PRIV_BEQUEATH,
  2785.     &priv, sizeof(priv_t)) < 0 ||
  2786.     setuidx(ID_REAL | ID_EFFECTIVE, (uid_t) pw->pw_uid) < 0 ||
  2787.     seteuid((uid_t) pw->pw_uid) < 0) {
  2788. #ifdef VERBOSE_ERROR_LOGING
  2789.     syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set uid) for %s, %s",
  2790.    remoteident, pw->pw_name);
  2791. #endif
  2792.     reply(530, "Can't set uid (AIX3).");
  2793.     goto bad;
  2794. }
  2795.     }
  2796. #ifdef UID_DEBUG
  2797.     lreply(230, "ruid=%d, euid=%d, suid=%d, luid=%d", getuidx(ID_REAL),
  2798.    getuidx(ID_EFFECTIVE), getuidx(ID_SAVED), getuidx(ID_LOGIN));
  2799.     lreply(230, "rgid=%d, egid=%d, sgid=%d, lgid=%d", getgidx(ID_REAL),
  2800.    getgidx(ID_EFFECTIVE), getgidx(ID_SAVED), getgidx(ID_LOGIN));
  2801. #endif
  2802. #else
  2803. #ifdef HAVE_SETREUID
  2804.     if (setreuid(-1, (uid_t) pw->pw_uid) < 0) {
  2805. #else
  2806.     if (seteuid((uid_t) pw->pw_uid) < 0) {
  2807. #endif
  2808. #ifdef VERBOSE_ERROR_LOGING
  2809. syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot set uid) for %s, %s",
  2810.        remoteident, pw->pw_name);
  2811. #endif
  2812. reply(530, "Can't set uid.");
  2813. goto bad;
  2814.     }
  2815. #endif
  2816.     if (!anonymous && !guest) {
  2817. if (chdir(pw->pw_dir) < 0) {
  2818. #ifdef PARANOID
  2819. #ifdef VERBOSE_ERROR_LOGING
  2820.     syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot chdir) for %s, %s",
  2821.    remoteident, pw->pw_name);
  2822. #endif
  2823.     reply(530, "User %s: can't change directory to %s.",
  2824.   pw->pw_name, pw->pw_dir);
  2825.     goto bad;
  2826. #else
  2827.     if (chdir("/") < 0) {
  2828. #ifdef VERBOSE_ERROR_LOGING
  2829. syslog(LOG_NOTICE, "FTP LOGIN FAILED (cannot chdir) for %s, %s",
  2830.        remoteident, pw->pw_name);
  2831. #endif
  2832. reply(530, "User %s: can't change directory to %s.",
  2833.       pw->pw_name, pw->pw_dir);
  2834. goto bad;
  2835.     }
  2836.     else {
  2837. lreply(230, "No directory! Logging in with home=/");
  2838. #ifdef ALTERNATE_CD
  2839. home = defhome;
  2840. #endif
  2841.     }
  2842. #endif
  2843. }
  2844.     }
  2845.     if (passwarn) {
  2846. lreply(230, "The response '%s' is not valid", passwd);
  2847. lreply(230,
  2848.        "Next time please use your e-mail address as your password");
  2849. lreply(230, "        for example: %s@%s",
  2850.        authenticated ? authuser : "joe", remotehost);
  2851.     }
  2852.     /* following two lines were inside the next scope... */
  2853.     show_message(230, LOG_IN);
  2854.     show_message(230, C_WD);
  2855.     show_readme(230, LOG_IN);
  2856.     show_readme(230, C_WD);
  2857. #ifdef ULTRIX_AUTH
  2858.     if (!anonymous && numfails > 0) {
  2859. lreply(230,
  2860.    "There have been %d unsuccessful login attempts on your account",
  2861.        numfails);
  2862.     }
  2863. #endif /* ULTRIX_AUTH */
  2864.     (void) is_shutdown(0, 0); /* display any shutdown messages now */
  2865.     if (anonymous) {
  2866. reply(230, "Guest login ok, access restrictions apply.");
  2867. sprintf(proctitle, "%s: anonymous/%.*s", remotehost,
  2868. (int) (sizeof(proctitle) - sizeof(remotehost) -
  2869.        sizeof(": anonymous/")), passwd);
  2870. setproctitle("%s", proctitle);
  2871. if (logging)
  2872.     syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
  2873.    remoteident, passwd);
  2874.     }
  2875.     else {
  2876. reply(230, "User %s logged in.%s", pw->pw_name, guest ?
  2877.       "  Access restrictions apply." : "");
  2878. sprintf(proctitle, "%s: %s", remotehost, pw->pw_name);
  2879. setproctitle(proctitle);
  2880. if (logging)
  2881.     syslog(LOG_INFO, "FTP LOGIN FROM %s, %s", remoteident, pw->pw_name);
  2882. /* H* mod: if non-anonymous user, copy it to "authuser" so everyone can
  2883.    see it, since whoever he was @foreign-host is now largely irrelevant.
  2884.    NMM mod: no, it isn't!  Think about accounting for the transfers from or
  2885.    to a shared account. */
  2886. /* strcpy (authuser, pw->pw_name); */
  2887.     } /* anonymous */
  2888. #ifdef ALTERNATE_CD
  2889.     if (!home)
  2890. #endif
  2891. home = pw->pw_dir; /* home dir for globbing */
  2892.     (void) umask(defumask);
  2893.     time(&login_time);
  2894.     {
  2895. struct aclmember *entry;
  2896. entry = NULL;
  2897. while (getaclentry("limit-time", &entry) && ARG0 && ARG1)
  2898.     if ((anonymous && strcasecmp(ARG0, "anonymous") == 0)
  2899. || (guest && strcasecmp(ARG0, "guest") == 0)
  2900. || ((guest | anonymous) && strcmp(ARG0, "*") == 0))
  2901. limit_time = strtoul(ARG1, NULL, 0);
  2902.     }
  2903.     return;
  2904.   bad:
  2905.     /* Forget all about it... */
  2906.     if (xferlog)
  2907. close(xferlog);
  2908.     xferlog = 0;
  2909.     end_login();
  2910.     return;
  2911. }
  2912. int restricteduid(uid_t uid)
  2913. {
  2914.     struct aclmember *entry = NULL;
  2915.     int which;
  2916.     char *ptr;
  2917.     struct passwd *pw;
  2918.     while (getaclentry("restricted-uid", &entry)) {
  2919. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  2920.     if (!strcmp(ARG[which], "*"))
  2921. return (1);
  2922.     if (ARG[which][0] == '%') {
  2923. if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) {
  2924.     if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) {
  2925. if (uid == strtoul(ARG[which] + 1, NULL, 0))
  2926.     return (1);
  2927.     }
  2928.     else {
  2929. *ptr++ = '';
  2930. if ((ARG[which][1] == '')
  2931.     || (uid >= strtoul(ARG[which] + 1, NULL, 0))) {
  2932.     *--ptr = '+';
  2933.     return (1);
  2934. }
  2935. *--ptr = '+';
  2936.     }
  2937. }
  2938. else {
  2939.     *ptr++ = '';
  2940.     if (((ARG[which][1] == '')
  2941.  || (uid >= strtoul(ARG[which] + 1, NULL, 0)))
  2942. && ((*ptr == '')
  2943.     || (uid <= strtoul(ptr, NULL, 0)))) {
  2944. *--ptr = '-';
  2945. return (1);
  2946.     }
  2947.     *--ptr = '-';
  2948. }
  2949.     }
  2950.     else {
  2951. pw = getpwnam(ARG[which]);
  2952. if (pw && (uid == pw->pw_uid))
  2953.     return (1);
  2954.     }
  2955. }
  2956.     }
  2957.     return (0);
  2958. }
  2959. int unrestricteduid(uid_t uid)
  2960. {
  2961.     struct aclmember *entry = NULL;
  2962.     int which;
  2963.     char *ptr;
  2964.     struct passwd *pw;
  2965.     while (getaclentry("unrestricted-uid", &entry)) {
  2966. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  2967.     if (!strcmp(ARG[which], "*"))
  2968. return (1);
  2969.     if (ARG[which][0] == '%') {
  2970. if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) {
  2971.     if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) {
  2972. if (uid == strtoul(ARG[which] + 1, NULL, 0))
  2973.     return (1);
  2974.     }
  2975.     else {
  2976. *ptr++ = '';
  2977. if ((ARG[which][1] == '')
  2978.     || (uid >= strtoul(ARG[which] + 1, NULL, 0))) {
  2979.     *--ptr = '+';
  2980.     return (1);
  2981. }
  2982. *--ptr = '+';
  2983.     }
  2984. }
  2985. else {
  2986.     *ptr++ = '';
  2987.     if (((ARG[which][1] == '')
  2988.  || (uid >= strtoul(ARG[which] + 1, NULL, 0)))
  2989. && ((*ptr == '')
  2990.     || (uid <= strtoul(ptr, NULL, 0)))) {
  2991. *--ptr = '-';
  2992. return (1);
  2993.     }
  2994.     *--ptr = '-';
  2995. }
  2996.     }
  2997.     else {
  2998. pw = getpwnam(ARG[which]);
  2999. if (pw && (uid == pw->pw_uid))
  3000.     return (1);
  3001.     }
  3002. }
  3003.     }
  3004.     return (0);
  3005. }
  3006. int restrictedgid(gid_t gid)
  3007. {
  3008.     struct aclmember *entry = NULL;
  3009.     int which;
  3010.     char *ptr;
  3011.     struct group *grp;
  3012.     while (getaclentry("restricted-gid", &entry)) {
  3013. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  3014.     if (!strcmp(ARG[which], "*"))
  3015. return (1);
  3016.     if (ARG[which][0] == '%') {
  3017. if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) {
  3018.     if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) {
  3019. if (gid == strtoul(ARG[which] + 1, NULL, 0))
  3020.     return (1);
  3021.     }
  3022.     else {
  3023. *ptr++ = '';
  3024. if ((ARG[which][1] == '')
  3025.     || (gid >= strtoul(ARG[which] + 1, NULL, 0))) {
  3026.     *--ptr = '+';
  3027.     return (1);
  3028. }
  3029. *--ptr = '+';
  3030.     }
  3031. }
  3032. else {
  3033.     *ptr++ = '';
  3034.     if (((ARG[which][1] == '')
  3035.  || (gid >= strtoul(ARG[which] + 1, NULL, 0)))
  3036. && ((*ptr == '')
  3037.     || (gid <= strtoul(ptr, NULL, 0)))) {
  3038. *--ptr = '-';
  3039. return (1);
  3040.     }
  3041.     *--ptr = '-';
  3042. }
  3043.     }
  3044.     else {
  3045. grp = getgrnam(ARG[which]);
  3046. if (grp && (gid == grp->gr_gid))
  3047.     return (1);
  3048.     }
  3049. }
  3050.     }
  3051.     return (0);
  3052. }
  3053. int unrestrictedgid(gid_t gid)
  3054. {
  3055.     struct aclmember *entry = NULL;
  3056.     int which;
  3057.     char *ptr;
  3058.     struct group *grp;
  3059.     while (getaclentry("unrestricted-gid", &entry)) {
  3060. for (which = 0; (which < MAXARGS) && ARG[which]; which++) {
  3061.     if (!strcmp(ARG[which], "*"))
  3062. return (1);
  3063.     if (ARG[which][0] == '%') {
  3064. if ((ptr = strchr(ARG[which] + 1, '-')) == NULL) {
  3065.     if ((ptr = strchr(ARG[which] + 1, '+')) == NULL) {
  3066. if (gid == strtoul(ARG[which] + 1, NULL, 0))
  3067.     return (1);
  3068.     }
  3069.     else {
  3070. *ptr++ = '';
  3071. if ((ARG[which][1] == '')
  3072.     || (gid >= strtoul(ARG[which] + 1, NULL, 0))) {
  3073.     *--ptr = '+';
  3074.     return (1);
  3075. }
  3076. *--ptr = '+';
  3077.     }
  3078. }
  3079. else {
  3080.     *ptr++ = '';
  3081.     if (((ARG[which][1] == '')
  3082.  || (gid >= strtoul(ARG[which] + 1, NULL, 0)))
  3083. && ((*ptr == '')
  3084.     || (gid <= strtoul(ptr, NULL, 0)))) {
  3085. *--ptr = '-';
  3086. return (1);
  3087.     }
  3088.     *--ptr = '-';
  3089. }
  3090.     }
  3091.     else {
  3092. grp = getgrnam(ARG[which]);
  3093. if (grp && (gid == grp->gr_gid))
  3094.     return (1);
  3095.     }
  3096. }
  3097.     }
  3098.     return (0);
  3099. }
  3100. char *opt_string(int options)
  3101. {
  3102.     static char buf[100];
  3103.     char *ptr = buf;
  3104.     if ((options & O_COMPRESS) != 0) /* debian fixes: NULL -> 0 */
  3105. *ptr++ = 'C';
  3106.     if ((options & O_TAR) != 0)
  3107. *ptr++ = 'T';
  3108.     if ((options & O_UNCOMPRESS) != 0)
  3109. *ptr++ = 'U';
  3110.     if (options == 0)
  3111. *ptr++ = '_';
  3112.     *ptr++ = '';
  3113.     return (buf);
  3114. }
  3115. #ifdef INTERNAL_LS
  3116. char *rpad(char *s, unsigned int len)
  3117. {
  3118.     char *a;
  3119.     a = (char *) malloc(len + 1);
  3120.     memset(a, ' ', len);
  3121.     a[len] = 0;
  3122.     if (strlen(s) <= len)
  3123. memcpy(a, s, strlen(s));
  3124.     else
  3125. strncpy(a, s, len);
  3126.     return a;
  3127. }
  3128. char *ls_file(const char *file, int nameonly, char remove_path, char classify)
  3129. {
  3130.     static const char month[12][4] =
  3131.     {"Jan", "Feb", "Mar", "Apr", "May", "Jun",
  3132.      "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
  3133.     char *permissions;
  3134.     struct stat s;
  3135.     struct tm *t;
  3136.     char *ls_entry;
  3137.     char *owner, *ownerg;
  3138.     char *rpowner, *rpownerg;
  3139.     char *link;
  3140. #ifndef LS_NUMERIC_UIDS
  3141.     struct passwd *pw;
  3142.     struct group *gr;
  3143. #endif
  3144.     link = NULL;
  3145.     owner = NULL;
  3146.     ownerg = NULL;
  3147.     if (lstat(file, &s) != 0) { /* File doesn't exist, or is not readable by user */
  3148. return NULL;
  3149.     }
  3150.     ls_entry = (char *) malloc(312);
  3151.     memset(ls_entry, 0, 312);
  3152.     permissions = strdup("----------");
  3153.     if (S_ISLNK(s.st_mode)) {
  3154. permissions[0] = 'l';
  3155. if (classify)
  3156.     classify = '@';
  3157.     }
  3158.     else if (S_ISDIR(s.st_mode)) {
  3159. permissions[0] = 'd';
  3160. if (classify)
  3161.     classify = '/';
  3162.     }
  3163.     else if (S_ISBLK(s.st_mode))
  3164. permissions[0] = 'b';
  3165.     else if (S_ISCHR(s.st_mode))
  3166. permissions[0] = 'c';
  3167.     else if (S_ISFIFO(s.st_mode)) {
  3168. permissions[0] = 'p';
  3169. if (classify == 1)
  3170.     classify = '=';
  3171.     }
  3172. #ifdef S_ISSOCK
  3173.     else if (S_ISSOCK(s.st_mode))
  3174. permissions[0] = 's';
  3175. #endif
  3176.     if ((s.st_mode & S_IRUSR) == S_IRUSR)
  3177. permissions[1] = 'r';
  3178.     if ((s.st_mode & S_IWUSR) == S_IWUSR)
  3179. permissions[2] = 'w';
  3180.     if ((s.st_mode & S_IXUSR) == S_IXUSR) {
  3181. permissions[3] = 'x';
  3182. if (classify == 1)
  3183.     classify = '*';
  3184. #ifndef HIDE_SETUID
  3185. if ((s.st_mode & S_ISUID) == S_ISUID)
  3186.     permissions[3] = 's';
  3187. #endif
  3188.     }
  3189. #ifndef HIDE_SETUID
  3190.     else if ((s.st_mode & S_ISUID) == S_ISUID)
  3191. permissions[3] = 'S';
  3192. #endif
  3193.     if ((s.st_mode & S_IRGRP) == S_IRGRP)
  3194. permissions[4] = 'r';
  3195.     if ((s.st_mode & S_IWGRP) == S_IWGRP)
  3196. permissions[5] = 'w';
  3197.     if ((s.st_mode & S_IXGRP) == S_IXGRP) {
  3198. permissions[6] = 'x';
  3199. if (classify == 1)
  3200.     classify = '*';
  3201. #ifndef HIDE_SETUID
  3202. if ((s.st_mode & S_ISGID) == S_ISGID)
  3203.     permissions[6] = 's';
  3204. #endif
  3205.     }
  3206. #ifndef HIDE_SETUID
  3207.     else if ((s.st_mode & S_ISGID) == S_ISGID)
  3208. permissions[6] = 'S';
  3209. #endif
  3210.     if ((s.st_mode & S_IROTH) == S_IROTH)
  3211. permissions[7] = 'r';
  3212.     if ((s.st_mode & S_IWOTH) == S_IWOTH)
  3213. permissions[8] = 'w';
  3214.     if ((s.st_mode & S_IXOTH) == S_IXOTH) {
  3215. permissions[9] = 'x';
  3216. if (classify == 1)
  3217.     classify = '*';
  3218. #ifndef HIDE_SETUID
  3219. if ((s.st_mode & S_ISVTX) == S_ISVTX)
  3220.     permissions[9] = 't';
  3221. #endif
  3222.     }
  3223. #ifndef HIDE_SETUID
  3224.     else if ((s.st_mode & S_ISVTX) == S_ISVTX)
  3225. permissions[9] = 'T';
  3226. #endif
  3227.     t = localtime(&s.st_mtime);
  3228. #ifndef LS_NUMERIC_UIDS
  3229.     pw = getpwuid(s.st_uid);
  3230.     if (pw != NULL)
  3231. owner = strdup(pw->pw_name);
  3232.     gr = getgrgid(s.st_gid);
  3233.     if (gr != NULL)
  3234. ownerg = strdup(gr->gr_name);
  3235. #endif
  3236.     if (owner == NULL) { /* Can't figure out username (or don't want to) */
  3237. if (s.st_uid == 0)
  3238.     owner = strdup("root");
  3239. else {
  3240.     owner = (char *) malloc(9);
  3241.     memset(owner, 0, 9);
  3242. #ifdef SOLARIS_2
  3243.     sprintf(owner, "%lu", s.st_uid);
  3244. #else
  3245.     sprintf(owner, "%u", s.st_uid);
  3246. #endif
  3247. }
  3248.     }
  3249.     if (ownerg == NULL) { /* Can't figure out groupname (or don't want to) */
  3250. if (s.st_gid == 0)
  3251.     ownerg = strdup("root");
  3252. else {
  3253.     ownerg = (char *) malloc(9);
  3254.     memset(ownerg, 0, 9);
  3255. #ifdef SOLARIS_2
  3256.     sprintf(ownerg, "%lu", s.st_gid);
  3257. #else
  3258.     sprintf(ownerg, "%u", s.st_gid);
  3259. #endif
  3260. }
  3261.     }
  3262. #ifdef HAVE_LSTAT
  3263.     if ((s.st_mode & S_IFLNK) == S_IFLNK) {
  3264. link = (char *) malloc(MAXPATHLEN);
  3265. memset(link, 0, MAXPATHLEN);
  3266. if (readlink(file, link, MAXPATHLEN) == -1) {
  3267.     free(link);
  3268.     link = NULL;
  3269. }
  3270.     }
  3271. #endif
  3272.     if (remove_path != 0 && strchr(file, '/'))
  3273. file = strrchr(file, '/') + 1;
  3274.     rpowner = rpad(owner, 8);
  3275.     rpownerg = rpad(ownerg, 8);
  3276. #ifdef SOLARIS_2
  3277. #define N_FORMAT "lu"
  3278. #define S_FORMAT "lu"
  3279. #else
  3280. #if defined(__FreeBSD__) || defined(__bsdi__)
  3281. #define N_FORMAT "u"
  3282. #define S_FORMAT "ld"
  3283. #else
  3284. #define N_FORMAT "u"
  3285. #define S_FORMAT "u"
  3286. #endif
  3287. #endif
  3288.     if (nameonly) {
  3289. sprintf(ls_entry, "%s", file);
  3290. if (link != NULL)
  3291.     free(link);
  3292.     }
  3293.     else {
  3294. if ((time(NULL) - s.st_mtime) > 6307200) { /* File is older than 6 months */
  3295.     if (link == NULL)
  3296. sprintf(ls_entry, "%s %3" N_FORMAT " %s %s %8" S_FORMAT " %s %2u %5u %s", permissions, s.st_nlink, rpowner, rpownerg, (long) s.st_size, month[t->tm_mon], t->tm_mday, 1900 + t->tm_year, file);
  3297.     else {
  3298. sprintf(ls_entry, "%s %3" N_FORMAT " %s %s %8" S_FORMAT " %s %2u %5u %s -> %s", permissions, s.st_nlink, rpowner, rpownerg, (long) s.st_size, month[t->tm_mon], t->tm_mday, 1900 + t->tm_year, file, link);
  3299. free(link);
  3300.     }
  3301. }
  3302. else if (link == NULL)
  3303.     sprintf(ls_entry, "%s %3" N_FORMAT " %s %s %8" S_FORMAT " %s %2u %02u:%02u %s", permissions, s.st_nlink, rpowner, rpownerg, (long) s.st_size, month[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, file);
  3304. else {
  3305.     sprintf(ls_entry, "%s %3" N_FORMAT " %s %s %8" S_FORMAT " %s %2u %02u:%02u %s -> %s", permissions, s.st_nlink, rpowner, rpownerg, (long) s.st_size, month[t->tm_mon], t->tm_mday, t->tm_hour, t->tm_min, file, link);
  3306.     free(link);
  3307. }
  3308.     }
  3309.     free(rpowner);
  3310.     free(rpownerg);
  3311.     free(owner);
  3312.     free(ownerg);
  3313.     if (classify > 1)
  3314. sprintf(ls_entry + strlen(ls_entry), "%c", classify);
  3315.     strcat(ls_entry, "rn");
  3316.     free(permissions);
  3317.     return ls_entry;
  3318. }
  3319. void ls_dir(char *d, char ls_a, char ls_F, char ls_l, char ls_R, char omit_total, FILE *out)
  3320. {
  3321.     int total;
  3322.     char *realdir; /* fixed up value to pass to glob() */
  3323.     char **subdirs; /* Subdirs to be scanned for ls -R  */
  3324.     int numSubdirs = 0;
  3325.     glob_t g;
  3326.     char isDir; /* 0: d is a file; 1: d is some files; 2: d is dir */
  3327.     struct stat s;
  3328.     char *dirlist;
  3329.     unsigned long dl_size, dl_used;
  3330.     char *c;
  3331.     char *lsentry;
  3332.     int i;
  3333. #ifndef GLOB_PERIOD
  3334.     char *dperiod;
  3335. #endif
  3336.     isDir = 0;
  3337.     realdir = (char *) malloc(strlen(d) + 3);
  3338.     memset(realdir, 0, strlen(d) + 3);
  3339.     strcpy(realdir, d);
  3340.     if (strcmp(realdir, ".") == 0)
  3341. realdir[0] = '*';
  3342.     if (strcmp(realdir + strlen(realdir) - 2, "/.") == 0)
  3343. realdir[strlen(realdir) - 1] = '*';
  3344.     if (realdir[strlen(realdir) - 1] == '/')
  3345. strcat(realdir, "*");
  3346.     if (strchr(realdir, '*') || strchr(realdir, '?'))
  3347. isDir = 1;