home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Networking / wu-ftpd-2.4.2b13-MIHS / src / ftpd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-03  |  96.4 KB  |  3,766 lines

  1. /* Copyright (c) 1985, 1988, 1990 Regents of the University of California.
  2.  * All rights reserved.
  3.  *
  4.  * Redistribution and use in source and binary forms, with or without
  5.  * modification, are permitted provided that the following conditions are
  6.  * met: 1. Redistributions of source code must retain the above copyright
  7.  * notice, this list of conditions and the following disclaimer. 2.
  8.  * Redistributions in binary form must reproduce the above copyright notice,
  9.  * this list of conditions and the following disclaimer in the documentation
  10.  * and/or other materials provided with the distribution. 3. All advertising
  11.  * materials mentioning features or use of this software must display the
  12.  * following acknowledgement: This product includes software developed by the
  13.  * University of California, Berkeley and its contributors. 4. Neither the
  14.  * name of the University nor the names of its contributors may be used to
  15.  * endorse or promote products derived from this software without specific
  16.  * prior written permission.
  17.  *
  18.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
  19.  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
  20.  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  21.  * DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
  22.  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  23.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
  24.  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
  25.  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  26.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  27.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  28.  * SUCH DAMAGE. 
  29.  */
  30.  
  31. #ifndef lint
  32. char copyright[] =
  33. "@(#) Copyright (c) 1985, 1988, 1990 Regents of the University of California.\n\
  34.  All rights reserved.\n";
  35. #endif /* not lint */
  36.  
  37. #ifndef lint
  38. static char sccsid[] = "@(#)$Id: ftpd.c,v 1.29 1997/03/03 09:39:42 sob Exp sob $ based on ftpd.c  5.40 (Berkeley) 7/2/91";
  39. #endif /* not lint */
  40.  
  41. #define SPT_NONE    0    /* don't use it at all */
  42. #define SPT_REUSEARGV    1    /* cover argv with title information */
  43. #define SPT_BUILTIN    2    /* use libc builtin */
  44. #define SPT_PSTAT    3    /* use pstat(PSTAT_SETCMD, ...) */
  45. #define SPT_PSSTRINGS    4    /* use PS_STRINGS->... */
  46. #define SPT_SYSMIPS    5    /* use sysmips() supported by NEWS-OS 6 */
  47. #define SPT_SCO        6    /* write kernel u. area */
  48.  
  49. /* FTP server. */
  50. #include "config.h"
  51.  
  52. #include <sys/types.h>
  53. #include <sys/param.h>
  54. #include <sys/stat.h>
  55. #include <sys/ioctl.h>
  56. #include <sys/socket.h>
  57. #include <sys/file.h>
  58. #include <sys/wait.h>
  59.  
  60. #ifdef AIX
  61. #include <sys/id.h>
  62. #include <sys/priv.h>
  63. #endif
  64.  
  65. #ifdef AUX
  66. #include <compat.h>
  67. #endif
  68.  
  69. #include <netinet/in.h>
  70. #include <netinet/in_systm.h>
  71. #include <netinet/ip.h>
  72.  
  73. #define FTP_NAMES
  74. #include <arpa/ftp.h>
  75. #include <arpa/inet.h>
  76. #include <arpa/telnet.h>
  77.  
  78. #include <ctype.h>
  79. #include <stdio.h>
  80. #include <signal.h>
  81. #include <pwd.h>
  82. #include <setjmp.h>
  83. #include <netdb.h>
  84. #include <errno.h>
  85. #include <string.h>
  86.  
  87. /*
  88.  *  Arrange to use either varargs or stdargs
  89.  *
  90.  */
  91.  
  92. #ifdef __STDC__
  93.  
  94. #include <stdarg.h>
  95.  
  96. #define VA_LOCAL_DECL    va_list ap;
  97. #define VA_START(f)    va_start(ap, f)
  98. #define VA_END        va_end(ap)
  99.  
  100. #else
  101.  
  102. #include <varargs.h>
  103.  
  104. #define VA_LOCAL_DECL    va_list ap;
  105. #define VA_START(f)    va_start(ap)
  106. #define VA_END        va_end(ap)
  107.  
  108. #endif
  109.  
  110.  
  111. #ifdef SYSSYSLOG
  112. #include <sys/syslog.h>
  113. #else
  114. #include <syslog.h>
  115. #endif
  116. #include <time.h>
  117. #include "conversions.h"
  118. #include "extensions.h"
  119. #include "pathnames.h"
  120.  
  121. #ifdef M_UNIX
  122. #include <arpa/nameser.h>
  123. #include <resolv.h>
  124. #endif
  125.  
  126. #if defined(SVR4) || defined(ISC)
  127. #include <fcntl.h>
  128. #endif
  129.  
  130. #ifdef HAVE_SYSINFO
  131. #include <sys/systeminfo.h>
  132. #endif
  133.  
  134. #ifdef SHADOW_PASSWORD
  135. #include <shadow.h>
  136. #endif
  137.  
  138. #ifdef KERBEROS
  139. #include <sys/types.h>
  140. #include <auth.h>
  141. #include <krb.h>
  142. #endif
  143.  
  144. #ifdef ULTRIX_AUTH
  145. #include <auth.h>
  146. #include <sys/svcinfo.h>
  147. #endif
  148.  
  149. #ifndef HAVE_SYMLINK
  150. #define lstat stat
  151. #endif
  152.  
  153. #ifdef HAVE_DIRENT
  154. #include <dirent.h>
  155. #else
  156. #include <sys/dir.h>
  157. #endif
  158.  
  159. #if (defined(_BSDI_VERSION) && (_BSDI_VERSION < 199501)) /* before version 2 */
  160. #define LONGOFF_T  /* sizeof(off_t) == sizeof(long) */
  161. #endif
  162.  
  163. #ifndef MAXHOSTNAMELEN
  164. #define MAXHOSTNAMELEN 64  /* may be too big */
  165. #endif
  166.  
  167. #ifndef TRUE
  168. #define  TRUE   1
  169. #endif
  170.  
  171. #ifndef FALSE
  172. #define  FALSE  !TRUE
  173. #endif
  174.  
  175. #if defined(_SCO_DS) && !defined(SIGURG)
  176. #define SIGURG    SIGUSR1
  177. #endif
  178.  
  179. /* File containing login names NOT to be used on this machine. Commonly used
  180.  * to disallow uucp. */
  181. extern int errno;
  182. extern int pidfd;
  183. #ifdef __STDC__
  184. extern char *ctime(const time_t *);
  185. #ifndef NO_CRYPT_PROTO
  186. extern char *crypt(const char *, const char *);
  187. #endif
  188. extern FILE *ftpd_popen(char *program, char *type, int closestderr),
  189.  *fopen(const char *, const char *),
  190.  *freopen(const char *, const char *, FILE *);
  191. extern int ftpd_pclose(FILE *iop),
  192.   fclose(FILE *);
  193. extern char *getline(),
  194.  *realpath(const char *pathname, char *result);
  195. #else
  196. extern char *ctime();
  197. #ifndef NO_CRYPT_PROTO
  198. #ifdef _M_UNIX
  199.     extern char *crypt(const char *, const char *);
  200. #else
  201.     extern char *crypt();
  202. #endif
  203. #endif
  204. extern FILE *ftpd_popen(), *fopen(),*freopen();
  205. extern int ftpd_pclose(), fclose();
  206. extern char *getline(), *realpath();
  207. #endif
  208. extern char version[];
  209. extern char *home;              /* pointer to home directory for glob */
  210. extern char cbuf[];
  211. extern off_t restart_point;
  212. extern yyerrorcalled;
  213.  
  214. struct sockaddr_in ctrl_addr;
  215. struct sockaddr_in data_source;
  216. struct sockaddr_in data_dest;
  217. struct sockaddr_in his_addr;
  218. struct sockaddr_in pasv_addr;
  219.  
  220. #ifdef VIRTUAL
  221. int virtual_mode=0;
  222. char virtual_root[MAXPATHLEN];
  223. char virtual_banner[MAXPATHLEN];
  224. #endif
  225.  
  226. int data;
  227. jmp_buf errcatch,
  228.   urgcatch;
  229. int logged_in = 0;
  230. struct passwd *pw;
  231. int debug;
  232. int timeout = 900;              /* timeout after 15 minutes of inactivity */
  233. int maxtimeout = 7200;          /* don't allow idle time to be set beyond 2
  234.                                  * hours */
  235.  
  236. /* previously defaulted to 1, and -l or -L set them to 1, so that there was
  237.    no way to turn them *off*!  Changed so that the manpage reflects common
  238.    sense.  -L is way noisy; -l we'll change to be "just right".  _H*/
  239. int logging = 0;
  240. int log_commands = 0;
  241.  
  242. #ifdef SECUREOSF
  243. #define SecureWare
  244. #include <prot.h>
  245. #endif
  246.  
  247. int anonymous = 1;
  248. int guest;
  249. int type;
  250. int form;
  251. int stru;                       /* avoid C keyword */
  252. int mode;
  253. int usedefault = 1;             /* for data transfers */
  254. int pdata = -1;                 /* for passive mode */
  255. int transflag;
  256. off_t file_size;
  257. off_t byte_count;
  258.  
  259. #if !defined(CMASK) || CMASK == 0
  260. #undef CMASK
  261. #define CMASK 002
  262. #endif
  263. mode_t defumask = CMASK;           /* default umask value */
  264. char tmpline[7];
  265. char hostname[MAXHOSTNAMELEN];
  266. char remotehost[MAXHOSTNAMELEN];
  267. char remoteaddr[MAXHOSTNAMELEN];
  268.  
  269. /* log failures     27-apr-93 ehk/bm */
  270. #ifdef LOG_FAILED
  271. #define MAXUSERNAMELEN    32
  272. char the_user[MAXUSERNAMELEN];
  273. #endif
  274.  
  275. /* Access control and logging passwords */
  276. /* OFF by default.  _H*/
  277. int use_accessfile = 0;
  278. char guestpw[MAXHOSTNAMELEN];
  279. char privatepw[MAXHOSTNAMELEN];
  280. int nameserved = 0;
  281. extern char authuser[];
  282. extern int authenticated;
  283.  
  284. /* File transfer logging */
  285. int xferlog = 0;
  286. int log_outbound_xfers = 0;
  287. int log_incoming_xfers = 0;
  288. char logfile[MAXPATHLEN];
  289.  
  290. /* Allow use of lreply(); this is here since some older FTP clients don't
  291.  * support continuation messages.  In violation of the RFCs... */
  292. int dolreplies = 1;
  293.  
  294. /* Spontaneous reply text.  To be sent along with next reply to user */
  295. char *autospout = NULL;
  296. int autospout_free = 0;
  297.  
  298. /* allowed on-the-fly file manipulations (compress, tar) */
  299. int mangleopts = 0;
  300.  
  301. /* number of login failures before attempts are logged and FTP *EXITS* */
  302. int lgi_failure_threshold = 5;
  303.  
  304. /* Timeout intervals for retrying connections to hosts that don't accept PORT
  305.  * cmds.  This is a kludge, but given the problems with TCP... */
  306. #define SWAITMAX    90          /* wait at most 90 seconds */
  307. #define SWAITINT    5           /* interval between retries */
  308.  
  309. int swaitmax = SWAITMAX;
  310. int swaitint = SWAITINT;
  311.  
  312. #ifdef __STDC__
  313. SIGNAL_TYPE lostconn(int sig);
  314. SIGNAL_TYPE randomsig(int sig);
  315. SIGNAL_TYPE myoob(int sig);
  316. FILE *getdatasock(char *mode),
  317.  *dataconn(char *name, off_t size, char *mode);
  318. void setproctitle(const char *fmt, ...);
  319. void reply(int, char *fmt, ...);
  320. void lreply(int, char *fmt, ...);
  321. #else
  322. SIGNAL_TYPE lostconn();
  323. SIGNAL_TYPE randomsig();
  324. SIGNAL_TYPE myoob();
  325. FILE *getdatasock(), *dataconn();
  326. void setproctitle();
  327. void reply();
  328. void lreply();
  329. #endif
  330.  
  331. #ifdef NEED_SIGFIX
  332. extern sigset_t block_sigmask;  /* defined in sigfix.c */
  333. #endif
  334.  
  335. char **Argv = NULL;             /* pointer to argument vector */
  336. char *LastArgv = NULL;          /* end of argv */
  337. char proctitle[BUFSIZ];         /* initial part of title */
  338.  
  339. #ifdef SKEY
  340. #include <skey.h>
  341. int    pwok = 0;
  342. #endif
  343.  
  344. #ifdef KERBEROS
  345. void init_krb();
  346. void end_krb();
  347. char krb_ticket_name[100];
  348. #endif /* KERBEROS */
  349.  
  350. #ifdef ULTRIX_AUTH
  351. int ultrix_check_pass(char *passwd, char *xpasswd);
  352. #endif
  353.  
  354. /* ls program commands and options for lreplies on and off */
  355. char  ls_long[50];
  356. char  ls_short[50];
  357. struct aclmember *entry = NULL;
  358.  
  359. #ifdef __STDC__
  360. void end_login(void);
  361. void send_data(FILE *, FILE *, off_t);
  362. void dolog(struct sockaddr_in *);
  363. void dologout(int);
  364. void perror_reply(int, char *);
  365. #else
  366. void end_login();
  367. void send_data();
  368. void dolog();
  369. void dologout();
  370. void perror_reply();
  371. #endif
  372.  
  373.  
  374. void
  375. #ifdef __STDC__
  376. main(int argc, char **argv, char **envp)
  377. #else
  378. main(argc,argv,envp)
  379. int argc; char **argv; char **envp;
  380. #endif
  381. {
  382.     int addrlen,
  383.       on = 1;
  384. #ifdef IPTOS_LOWDELAY
  385.     int tos;
  386. #endif
  387.     int c;
  388.     extern int optopt;
  389.     extern char *optarg;
  390.     struct hostent *shp;
  391. #ifdef VIRTUAL
  392.     int virtual_len;
  393.     struct sockaddr_in virtual_addr;
  394.     struct sockaddr_in *virtual_ptr;
  395. #endif
  396.  
  397. #ifdef AUX
  398.     setcompat(COMPAT_POSIX | COMPAT_BSDSETUGID);
  399. #endif
  400.  
  401. #ifdef FACILITY
  402.     openlog("ftpd", LOG_PID | LOG_NDELAY, FACILITY);
  403. #else
  404.     openlog("ftpd", LOG_PID);
  405. #endif
  406.  
  407. #ifdef SecureWare
  408.     setluid(1);                         /* make sure there is a valid luid */
  409.     set_auth_parameters(argc,argv);
  410.     setreuid(0, 0);
  411. #endif
  412. #if defined(M_UNIX) && !defined(_M_UNIX)
  413.     res_init();                         /* bug in old (1.1.1) resolver     */
  414.     _res.retrans = 20;                  /* because of fake syslog in 3.2.2 */
  415.     setlogmask(LOG_UPTO(LOG_INFO));
  416. #endif
  417.  
  418.     addrlen = sizeof(his_addr);
  419.     if (getpeername(0, (struct sockaddr *) &his_addr, &addrlen) < 0) {
  420.         syslog(LOG_ERR, "getpeername (%s): %m", argv[0]);
  421. #ifndef DEBUG
  422.         exit(1);
  423. #endif
  424.     }
  425.     addrlen = sizeof(ctrl_addr);
  426.     if (getsockname(0, (struct sockaddr *) &ctrl_addr, &addrlen) < 0) {
  427.         syslog(LOG_ERR, "getsockname (%s): %m", argv[0]);
  428. #ifndef DEBUG
  429.         exit(1);
  430. #endif
  431.     }
  432. #ifdef IPTOS_LOWDELAY
  433.     tos = IPTOS_LOWDELAY;
  434.     if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *) &tos, sizeof(int)) < 0)
  435.           syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
  436. #endif
  437.  
  438.     data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1);
  439.     debug = 0;
  440.  
  441.     /* Save start and extent of argv for setproctitle. */
  442.     Argv = argv;
  443.     while (*envp)
  444.         envp++;
  445.     LastArgv = envp[-1] + strlen(envp[-1]);
  446.  
  447.     while ((c = getopt(argc, argv, ":aAvdlLiot:T:u:")) != -1) {
  448.         switch (c) {
  449.  
  450.         case 'a':
  451.             use_accessfile = 1;
  452.             break;
  453.  
  454.         case 'A':
  455.             use_accessfile = 0;
  456.             break;
  457.  
  458.         case 'v':
  459.             debug = 1;
  460.             break;
  461.  
  462.         case 'd':
  463.             debug = 1;
  464.             break;
  465.  
  466.         case 'l':
  467.             logging = 1;
  468.             break;
  469.  
  470.         case 'L':
  471.             log_commands = 1;
  472.             break;
  473.  
  474.         case 'i':
  475.             log_incoming_xfers = 1;
  476.             break;
  477.  
  478.         case 'o':
  479.             log_outbound_xfers = 1;
  480.             break;
  481.  
  482.         case 't':
  483.             timeout = atoi(optarg);
  484.             if (maxtimeout < timeout)
  485.                 maxtimeout = timeout;
  486.             break;
  487.  
  488.         case 'T':
  489.             maxtimeout = atoi(optarg);
  490.             if (timeout > maxtimeout)
  491.                 timeout = maxtimeout;
  492.             break;
  493.  
  494.         case 'u':
  495.             {
  496.                 unsigned int val = 0;
  497.  
  498.                 while (*optarg && *optarg >= '0' && *optarg <= '9')
  499.                     val = val * 8 + *optarg++ - '0';
  500.                 if (*optarg || val > 0777)
  501.                     syslog(LOG_ERR, "bad value for -u");
  502.                 else
  503.                     defumask = val;
  504.                 break;
  505.             }
  506.  
  507.         case ':':
  508.             syslog(LOG_ERR, "option -%c requires an argument", optopt);
  509.             break;
  510.  
  511.         default:
  512.             syslog(LOG_ERR, "unknown option -%c ignored", optopt);
  513.             break;
  514.         }
  515.     }
  516.     (void) freopen(_PATH_DEVNULL, "w", stderr);
  517.  
  518.     /* Checking for random signals ... */
  519. #ifdef NEED_SIGFIX
  520. sigemptyset(&block_sigmask);
  521. #endif
  522. #ifndef SIG_DEBUG
  523. #ifdef SIGHUP
  524.     (void) signal(SIGHUP, randomsig);
  525. #ifdef NEED_SIGFIX
  526.     sigaddset(&block_sigmask, SIGHUP);
  527. #endif
  528. #endif
  529. #ifdef SIGINT
  530.     (void) signal(SIGINT, randomsig);
  531. #ifdef NEED_SIGFIX
  532.     sigaddset(&block_sigmask, SIGINT);
  533. #endif
  534. #endif
  535. #ifdef SIGQUIT
  536.     (void) signal(SIGQUIT, randomsig);
  537. #ifdef NEED_SIGFIX
  538.     sigaddset(&block_sigmask, SIGQUIT);
  539. #endif
  540. #endif
  541. #ifdef SIGILL
  542.     (void) signal(SIGILL, randomsig);
  543. #ifdef NEED_SIGFIX
  544.     sigaddset(&block_sigmask, SIGILL);
  545. #endif
  546. #endif
  547. #ifdef SIGTRAP
  548.     (void) signal(SIGTRAP, randomsig);
  549. #ifdef NEED_SIGFIX
  550.     sigaddset(&block_sigmask, SIGTRAP);
  551. #endif
  552. #endif
  553. #ifdef SIGIOT
  554.     (void) signal(SIGIOT, randomsig);
  555. #ifdef NEED_SIGFIX
  556.     sigaddset(&block_sigmask, SIGIOT);
  557. #endif
  558. #endif
  559. #ifdef SIGEMT
  560.     (void) signal(SIGEMT, randomsig);
  561. #ifdef NEED_SIGFIX
  562.     sigaddset(&block_sigmask, SIGEMT);
  563. #endif
  564. #endif
  565. #ifdef SIGFPE
  566.     (void) signal(SIGFPE, randomsig);
  567. #ifdef NEED_SIGFIX
  568.     sigaddset(&block_sigmask, SIGFPE);
  569. #endif
  570. #endif
  571. #ifdef SIGKILL
  572.     (void) signal(SIGKILL, randomsig);
  573. #ifdef NEED_SIGFIX
  574.     sigaddset(&block_sigmask, SIGKILL);
  575. #endif
  576. #endif
  577. #ifdef SIGBUS
  578.     (void) signal(SIGBUS, randomsig);
  579. #ifdef NEED_SIGFIX
  580.     sigaddset(&block_sigmask, SIGBUS);
  581. #endif
  582. #endif
  583. #ifdef SIGSEGV
  584.     (void) signal(SIGSEGV, randomsig);
  585. #ifdef NEED_SIGFIX
  586.     sigaddset(&block_sigmask, SIGSEGV);
  587. #endif
  588. #endif
  589. #ifdef SIGSYS
  590.     (void) signal(SIGSYS, randomsig);
  591. #ifdef NEED_SIGFIX
  592.     sigaddset(&block_sigmask, SIGSYS);
  593. #endif
  594. #endif
  595. #ifdef SIGALRM
  596.     (void) signal(SIGALRM, randomsig);
  597. #ifdef NEED_SIGFIX
  598.     sigaddset(&block_sigmask, SIGALRM);
  599. #endif
  600. #endif
  601. #ifdef SIGSTOP
  602.     (void) signal(SIGSTOP, randomsig);
  603. #ifdef NEED_SIGFIX
  604.     sigaddset(&block_sigmask, SIGSTOP);
  605. #endif
  606. #endif
  607. #ifdef SIGTSTP
  608.     (void) signal(SIGTSTP, randomsig);
  609. #ifdef NEED_SIGFIX
  610.     sigaddset(&block_sigmask, SIGTSTP);
  611. #endif
  612. #endif
  613. #ifdef SIGTTIN
  614.     (void) signal(SIGTTIN, randomsig);
  615. #ifdef NEED_SIGFIX
  616.     sigaddset(&block_sigmask, SIGTTIN);
  617. #endif
  618. #endif
  619. #ifdef SIGTTOU
  620.     (void) signal(SIGTTOU, randomsig);
  621. #ifdef NEED_SIGFIX
  622.     sigaddset(&block_sigmask, SIGTTOU);
  623. #endif
  624. #endif
  625. #ifdef SIGIO
  626.     (void) signal(SIGIO, randomsig);
  627. #ifdef NEED_SIGFIX
  628.     sigaddset(&block_sigmask, SIGIO);
  629. #endif
  630. #endif
  631. #ifdef SIGXCPU
  632.     (void) signal(SIGXCPU, randomsig);
  633. #ifdef NEED_SIGFIX
  634.     sigaddset(&block_sigmask, SIGXCPU);
  635. #endif
  636. #endif
  637. #ifdef SIGXFSZ
  638.     (void) signal(SIGXFSZ, randomsig);
  639. #ifdef NEED_SIGFIX
  640.     sigaddset(&block_sigmask, SIGXFSZ);
  641. #endif
  642. #endif
  643. #ifdef SIGWINCH
  644.     (void) signal(SIGWINCH, randomsig);
  645. #ifdef NEED_SIGFIX
  646.     sigaddset(&block_sigmask, SIGWINCH);
  647. #endif
  648. #endif
  649. #ifdef SIGVTALRM
  650.     (void) signal(SIGVTALRM, randomsig);
  651. #ifdef NEED_SIGFIX
  652.     sigaddset(&block_sigmask, SIGVTALRM);
  653. #endif
  654. #endif
  655. #ifdef SIGPROF
  656.     (void) signal(SIGPROF, randomsig);
  657. #ifdef NEED_SIGFIX
  658.     sigaddset(&block_sigmask, SIGPROF);
  659. #endif
  660. #endif
  661. #ifdef SIGUSR1
  662.     (void) signal(SIGUSR1, randomsig);
  663. #ifdef NEED_SIGFIX
  664.     sigaddset(&block_sigmask, SIGUSR1);
  665. #endif
  666. #endif
  667. #ifdef SIGUSR2
  668.     (void) signal(SIGUSR2, randomsig);
  669. #ifdef NEED_SIGFIX
  670.     sigaddset(&block_sigmask, SIGUSR2);
  671. #endif
  672. #endif
  673.  
  674. #ifdef SIGPIPE
  675.     (void) signal(SIGPIPE, lostconn);
  676. #ifdef NEED_SIGFIX
  677.     sigaddset(&block_sigmask, SIGPIPE);
  678. #endif
  679. #endif
  680. #ifdef SIGCHLD
  681.     (void) signal(SIGCHLD, SIG_IGN);
  682. #ifdef NEED_SIGFIX
  683.     sigaddset(&block_sigmask, SIGCHLD);
  684. #endif
  685. #endif
  686.  
  687. #ifdef SIGURG
  688.     if ((int) signal(SIGURG, myoob) < 0)
  689.         syslog(LOG_ERR, "signal: %m");
  690. #ifdef NEED_SIGFIX
  691.     sigaddset(&block_sigmask, SIGURG);
  692. #endif
  693. #endif
  694. #endif /* SIG_DEBUG */
  695.     /* Try to handle urgent data inline */
  696. #ifdef SO_OOBINLINE
  697.     if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(int)) < 0)
  698.         syslog(LOG_ERR, "setsockopt (SO_OOBINLINE): %m");
  699. #endif
  700.  
  701. #ifdef  F_SETOWN
  702.     if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
  703.         syslog(LOG_ERR, "fcntl F_SETOWN: %m");
  704. #elif defined(SIOCSPGRP)
  705.     {
  706.         int pid;
  707.         pid = getpid();
  708.         if (ioctl(fileno(stdin), SIOCSPGRP, &pid) == -1)
  709.             syslog(LOG_ERR, "ioctl SIOCSPGRP: %m");
  710.     }
  711. #endif
  712.     dolog(&his_addr);
  713.     /* Set up default state */
  714.     data = -1;
  715.     type = TYPE_A;
  716.     form = FORM_N;
  717.     stru = STRU_F;
  718.     mode = MODE_S;
  719.     tmpline[0] = '\0';
  720.     yyerrorcalled = 0;
  721.  
  722. #ifdef HAVE_SYSINFO
  723.     sysinfo(SI_HOSTNAME, hostname, sizeof (hostname));
  724. #else
  725.     (void) gethostname(hostname, sizeof (hostname));
  726. #endif
  727. /* set the FQDN here */
  728.     shp = gethostbyname(hostname);
  729.     if (shp != NULL)
  730.       (void) strncpy(hostname, shp->h_name, sizeof(hostname));
  731.  
  732.     access_init();
  733.     authenticate();
  734.     conv_init();
  735.  
  736. #ifdef VIRTUAL
  737.     virtual_len = sizeof(virtual_addr);
  738.     if (getsockname(0, (struct sockaddr *) &virtual_addr, &virtual_len) == 0) {
  739.         virtual_ptr = (struct sockaddr_in *) &virtual_addr;
  740.         entry = (struct aclmember *) NULL;
  741.         while (getaclentry("virtual", &entry)) {
  742.             if (!ARG0 || !ARG1 || !ARG2)
  743.                 continue;
  744.             if (!strcmp(ARG0, inet_ntoa(virtual_ptr->sin_addr))) {
  745.                 if(!strcmp(ARG1, "root")) {
  746.             syslog(LOG_NOTICE, "VirtualFTP Connect to: %s",
  747.                            inet_ntoa(virtual_ptr->sin_addr));
  748.                     virtual_mode = 1;
  749.                     strncpy(virtual_root, ARG2, MAXPATHLEN);
  750.             /* reset hostname to this virtual name */
  751.             shp = gethostbyaddr((char *) &virtual_ptr->sin_addr,
  752.                                 sizeof (struct in_addr), AF_INET);
  753.             if (shp != NULL)
  754.               (void) strncpy(hostname, shp->h_name, sizeof(hostname));
  755.                 }
  756.                 if(!strcmp(ARG1, "banner")) 
  757.                     strncpy(virtual_banner, ARG2, MAXPATHLEN);
  758.                 if(!strcmp(ARG1, "logfile")) 
  759.                     strncpy(logfile, ARG2, MAXPATHLEN);
  760.             }
  761.         }
  762.     }
  763.     if (!virtual_mode || logfile[0] == '\0')
  764. #endif
  765.     strcpy(logfile, _PATH_XFERLOG);
  766.  
  767.     if (is_shutdown(1, 1) != 0) {
  768.         syslog(LOG_INFO, "connection refused (server shut down) from %s [%s]",
  769.                remotehost, remoteaddr);
  770.         reply(500, "%s FTP server shut down -- please try again later.",
  771.               hostname);
  772.         exit(0);
  773.     }
  774.  
  775.     show_banner(220);
  776.  
  777.     entry = (struct aclmember *) NULL;
  778.     if (getaclentry("lslong", &entry) && ARG0 && (int)strlen(ARG0) > 0) {
  779.           strcpy(ls_long,ARG0);
  780.       if (ARG1 && strlen(ARG1)) {
  781.              strcat(ls_long," ");
  782.          strcat(ls_long,ARG1);
  783.           }
  784.     } else {
  785. #if defined(SVR4) || defined(ISC)
  786. #ifndef AIX
  787.           strcpy(ls_long,"/bin/ls -la");
  788. #else
  789.           strcpy(ls_long,"/bin/ls -lA");
  790. #endif
  791. #else
  792.           strcpy(ls_long,"/bin/ls -lgA");
  793. #endif
  794.     }
  795.     strcat(ls_long," %s");
  796.  
  797.     entry = (struct aclmember *) NULL;
  798.     if (getaclentry("lsshort", &entry) && ARG0 && (int)strlen(ARG0) > 0) {
  799.           strcpy(ls_short,ARG0);
  800.       if (ARG1 && strlen(ARG1)) {
  801.              strcat(ls_short," ");
  802.              strcat(ls_short,ARG1);
  803.       }
  804.     } else {
  805. #if defined(SVR4) || defined(ISC)
  806. #ifndef AIX
  807.           strcpy(ls_short,"/bin/ls -la");
  808. #else
  809.           strcpy(ls_short,"/bin/ls -lA");
  810. #endif
  811. #else
  812.           strcpy(ls_short,"/bin/ls -lgA");
  813. #endif
  814.     }
  815.     strcat(ls_short," %s");
  816.  
  817.     reply(220, "%s FTP server (%s) ready.", hostname, version);
  818.     (void) setjmp(errcatch);
  819.  
  820.     for (;;)
  821.         (void) yyparse();
  822.     /* NOTREACHED */
  823. }
  824.  
  825. SIGNAL_TYPE
  826. #ifdef __STDC__
  827. randomsig(int sig)
  828. #else
  829. randomsig(sig)
  830. int sig;
  831. #endif
  832. {
  833. #ifdef HAVE_SIGLIST
  834.     syslog(LOG_ERR, "exiting on signal %d: %s", sig, sys_siglist[sig] );
  835. #else
  836.     syslog(LOG_ERR, "exiting on signal %d", sig);
  837. #endif
  838.     chdir("/");
  839.     signal(SIGIOT, SIG_DFL);
  840.     signal(SIGILL, SIG_DFL);
  841.     exit (1);
  842.     /* dologout(-1); *//* NOTREACHED */
  843. }
  844.  
  845. SIGNAL_TYPE
  846. #ifdef __STDC__
  847. lostconn(int sig)
  848. #else
  849. lostconn(sig)
  850. int sig;
  851. #endif
  852. {
  853.     if (debug)
  854.         syslog(LOG_DEBUG, "lost connection to %s [%s]", remotehost, remoteaddr);
  855.     dologout(-1);
  856. }
  857.  
  858. static char ttyline[20];
  859.  
  860. /* Helper function for sgetpwnam(). */
  861. char *
  862. #ifdef __STDC__
  863. sgetsave(char *s)
  864. #else
  865. sgetsave(s)
  866. char *s;
  867. #endif
  868. {
  869.     char *new;
  870.     
  871.     new = (char *) malloc(strlen(s) + 1);
  872.  
  873.     if (new == NULL) {
  874.         perror_reply(421, "Local resource failure: malloc");
  875.         dologout(1);
  876.         /* NOTREACHED */
  877.     }
  878.     (void) strcpy(new, s);
  879.     return (new);
  880. }
  881.  
  882. /* Save the result of a getpwnam.  Used for USER command, since the data
  883.  * returned must not be clobbered by any other command (e.g., globbing). */
  884. struct passwd *
  885. #ifdef __STDC__
  886. sgetpwnam(char *name)
  887. #else
  888. sgetpwnam(name)
  889. char *name;
  890. #endif
  891. {
  892.     static struct passwd save;
  893.     register struct passwd *p;
  894. #ifdef M_UNIX
  895.     struct passwd *ret = (struct passwd *) NULL;
  896. #endif
  897. #ifdef __STDC__
  898.     char *sgetsave(char *s);
  899. #else
  900.     char *sgetsave();
  901. #endif
  902. #ifdef KERBEROS
  903.     register struct authorization *q;
  904. #endif /* KERBEROS */
  905.  
  906. #ifdef SecureWare
  907.     struct pr_passwd *pr;
  908. #endif
  909.  
  910. #ifdef KERBEROS
  911.     init_krb();
  912.     q = getauthuid(p->pw_uid);
  913.     end_krb();
  914. #endif /* KERBEROS */
  915.  
  916. #ifdef M_UNIX
  917. # ifdef SecureWare
  918.     if ((pr = getprpwnam(name)) == NULL)
  919.         goto DONE;
  920. # endif /* SecureWare */
  921.     if ((p = getpwnam(name)) == NULL)
  922.         goto DONE;
  923. #else   /* M_UNIX */
  924. # ifdef SecureWare
  925.     if ((pr = getprpwnam(name)) == NULL)
  926.         return((struct passwd *) pr);
  927. # endif /* SecureWare */
  928.     if ((p = getpwnam(name)) == NULL)
  929.         return (p);
  930. #endif  /* M_UNIX */
  931.  
  932.     if (save.pw_name)   free(save.pw_name);
  933.     if (save.pw_gecos)  free(save.pw_gecos);
  934.     if (save.pw_dir)    free(save.pw_dir);
  935.     if (save.pw_shell)  free(save.pw_shell);
  936.  
  937.     save = *p;
  938.  
  939.     save.pw_name = sgetsave(p->pw_name);
  940.  
  941. #ifdef KERBEROS
  942.     save.pw_passwd = sgetsave(q->a_password);
  943. #elif defined(SecureWare)
  944.     if (pr->uflg.fg_encrypt && pr->ufld.fd_encrypt && *pr->ufld.fd_encrypt)
  945.        save.pw_passwd = sgetsave(pr->ufld.fd_encrypt);
  946.     else
  947.        save.pw_passwd = sgetsave("");
  948. #else
  949.     save.pw_passwd = sgetsave(p->pw_passwd);
  950. #endif
  951. #ifdef SHADOW_PASSWORD
  952.         if (p) {
  953.            struct spwd *spw;
  954.        setspent();
  955.            if ((spw = getspnam(p->pw_name)) != NULL) {
  956.                /* TODO: check if password has expired etc.  */
  957.            free(save.pw_passwd);
  958.                save.pw_passwd = sgetsave(spw->sp_pwdp);
  959.            }
  960. /* Shadow passwords are optional on Linux.  --marekm */
  961. #ifndef LINUX 
  962.            else{
  963.          free(save.pw_passwd);
  964.          save.pw_passwd = sgetsave("");
  965.        }
  966. #endif
  967. /* marekm's fix for linux proc file system shadow passwd exposure problem */
  968.        endspent();        
  969.         }
  970. #endif
  971.     save.pw_gecos = sgetsave(p->pw_gecos);
  972.     save.pw_dir = sgetsave(p->pw_dir);
  973.     save.pw_shell = sgetsave(p->pw_shell);
  974. #ifdef M_UNIX
  975.     ret = &save;
  976. DONE:
  977.     endpwent();
  978. #endif
  979. #ifdef SecureWare
  980.     endprpwent();
  981. #endif
  982. #ifdef M_UNIX
  983.     return(ret);
  984. #else
  985.     return(&save);
  986. #endif
  987. }
  988. #ifdef SKEY
  989. /*
  990.  * From Wietse Venema, Eindhoven University of Technology. 
  991.  */
  992. /* skey_challenge - additional password prompt stuff */
  993. #ifdef __STDC__
  994. char   *skey_challenge(char *name, struct passwd *pwd, int pwok)
  995. #else
  996. char   *skey_challenge(name, pwd, pwok)
  997. char   *name;
  998. struct passwd *pwd;
  999. int    pwok;
  1000. #endif
  1001. {
  1002.     static char buf[128];
  1003.     char sbuf[40];
  1004.     struct skey skey;
  1005.  
  1006.     /* Display s/key challenge where appropriate. */
  1007.  
  1008.     if (pwd == NULL || skeychallenge(&skey, pwd->pw_name, sbuf))
  1009.     sprintf(buf, "Password required for %s.", name);
  1010.     else
  1011.     sprintf(buf, "[%s] %s for %s.", sbuf,
  1012.         pwok ? "allowed" : "required", name);
  1013.     return (buf);
  1014. }
  1015. #endif
  1016. int login_attempts;             /* number of failed login attempts */
  1017. int askpasswd;                  /* had user command, ask for passwd */
  1018.  
  1019. /* USER command. Sets global passwd pointer pw if named account exists and is
  1020.  * acceptable; sets askpasswd if a PASS command is expected.  If logged in
  1021.  * previously, need to reset state.  If name is "ftp" or "anonymous", the
  1022.  * name is not in _PATH_FTPUSERS, and ftp account exists, set anonymous and
  1023.  * pw, then just return.  If account doesn't exist, ask for passwd anyway.
  1024.  * Otherwise, check user requesting login privileges.  Disallow anyone who
  1025.  * does not have a standard shell as returned by getusershell().  Disallow
  1026.  * anyone mentioned in the file _PATH_FTPUSERS to allow people such as root
  1027.  * and uucp to be avoided. */
  1028.  
  1029. void
  1030. #ifdef __STDC__
  1031. user(char *name)
  1032. #else
  1033. user(name)
  1034. char *name;
  1035. #endif
  1036. {
  1037.     register char *cp;
  1038.     char *shell;
  1039.     char *getusershell();
  1040.     int   why = 0;
  1041.  
  1042. /* H* fix: if we're logged in at all, we can't log in again. */
  1043.     if (logged_in) {
  1044.     reply(530, "Already logged in.");
  1045.     return;
  1046.     }
  1047.  
  1048. #ifdef HOST_ACCESS                     /* 19-Mar-93    BM              */
  1049.     if (!rhost_ok(name, remotehost, remoteaddr))
  1050.     {
  1051.             reply(530, "User %s access denied.", name);
  1052.             syslog(LOG_NOTICE,
  1053.                     "FTP LOGIN REFUSED (name in %s) FROM %s [%s], %s",
  1054.                      _PATH_FTPHOSTS, remotehost, remoteaddr, name);
  1055.             return;
  1056.     }
  1057. #endif
  1058.  
  1059. #ifdef LOG_FAILED                       /* 06-Nov-92    EHK             */
  1060.     strncpy(the_user, name, MAXUSERNAMELEN - 1);
  1061. #endif
  1062.  
  1063.     if (logged_in) {            /* Now a no-op.  _H*/
  1064.         if (anonymous || guest) {
  1065.             reply(530, "Can't change user from guest login.");
  1066.             return;
  1067.         }
  1068.         end_login();
  1069.     }
  1070.  
  1071.     anonymous = 0;
  1072.     acl_remove();
  1073.  
  1074.     if (!strcasecmp(name, "ftp") || !strcasecmp(name, "anonymous")) {
  1075.       struct aclmember *entry = NULL;
  1076.       int machineok=1;
  1077.       char guestservername[MAXHOSTNAMELEN];
  1078.       guestservername[0]='\0';
  1079.  
  1080.       if (checkuser("ftp") || checkuser("anonymous")) {
  1081.           reply(530, "User %s access denied.", name);
  1082.           syslog(LOG_NOTICE,
  1083.            "FTP LOGIN REFUSED (ftp in /etc/ftpusers) FROM %s [%s], %s",
  1084.            remotehost, remoteaddr, name);
  1085.           return;
  1086.           
  1087.         /*
  1088.         ** Algorithm used:
  1089.         ** - if no "guestserver" directive is present,
  1090.         **     anonymous access is allowed, for backward compatibility.
  1091.         ** - if a "guestserver" directive is present,
  1092.         **     anonymous access is restricted to the machines listed,
  1093.         **     usually the machine whose CNAME on the current domain
  1094.         **     is "ftp"...
  1095.         **
  1096.         ** the format of the "guestserver" line is
  1097.         ** guestserver [<machine1> [<machineN>]]
  1098.         ** that is, "guestserver" will forbid anonymous access on all machines
  1099.         ** while "guestserver ftp inf" will allow anonymous access on
  1100.         ** the two machines whose CNAMES are "ftp.enst.fr" and "inf.enst.fr".
  1101.         **
  1102.         ** if anonymous access is denied on the current machine,
  1103.         ** the user will be asked to use the first machine listed (if any)
  1104.         ** on the "guestserver" line instead:
  1105.         ** 530- Guest login not allowed on this machine,
  1106.         **      connect to ftp.enst.fr instead.
  1107.         **
  1108.         ** -- <Nicolas.Pioch@enst.fr>
  1109.         */
  1110.       } else if (getaclentry("guestserver", &entry)
  1111.                  && ARG0 && (int)strlen(ARG0) > 0) {
  1112.         struct hostent *tmphostent;
  1113.  
  1114.         /*
  1115.         ** if a "guestserver" line is present,
  1116.         ** default is not to allow guest logins
  1117.         */
  1118.         machineok=0;
  1119.  
  1120.         if (hostname[0]
  1121.             && ((tmphostent=gethostbyname(hostname)))) {
  1122.  
  1123.           /*
  1124.           ** hostname is the only first part of the FQDN
  1125.           ** this may or may not correspond to the h_name value
  1126.           ** (machines with more than one IP#, CNAMEs...)
  1127.           ** -> need to fix that, calling gethostbyname on hostname
  1128.           **
  1129.           ** WARNING!
  1130.           ** for SunOS 4.x, you need to have a working resolver in the libc
  1131.           ** for CNAMES to work properly.
  1132.           ** If you don't, add "-lresolv" to the libraries before compiling!
  1133.           */
  1134.           char dns_localhost[MAXHOSTNAMELEN];
  1135.           int machinecount;
  1136.  
  1137.           strncpy(dns_localhost,
  1138.                   tmphostent->h_name,
  1139.                   sizeof(dns_localhost));
  1140.           dns_localhost[sizeof(dns_localhost)-1]='\0';
  1141.  
  1142.           for (machinecount=0;
  1143.                entry->arg[machinecount] && (entry->arg[machinecount])[0];
  1144.                machinecount++) {
  1145.  
  1146.             if ((tmphostent=gethostbyname(entry->arg[machinecount]))) {
  1147.               /*
  1148.               ** remember the name of the first machine for redirection
  1149.               */
  1150.  
  1151.               if ((!machinecount) && tmphostent->h_name) {
  1152.                 strncpy(guestservername, entry->arg[machinecount],
  1153.                         sizeof(guestservername));
  1154.                 guestservername[sizeof(guestservername)-1]='\0';
  1155.               }
  1156.  
  1157.               if (!strcasecmp(tmphostent->h_name, dns_localhost)) {
  1158.                 machineok++;
  1159.                 break;
  1160.               }
  1161.             }
  1162.           }
  1163.         }
  1164.       }
  1165.       if (!machineok) {
  1166.         if (guestservername[0])
  1167.           reply(530,
  1168.              "Guest login not allowed on this machine, connect to %s instead.",
  1169.                 guestservername);
  1170.         else
  1171.           reply(530,
  1172.                 "Guest login not allowed on this machine.");
  1173.         syslog(LOG_NOTICE,
  1174.                "FTP LOGIN REFUSED (localhost not in guestservers) FROM %s [%s], %s",
  1175.                remotehost, remoteaddr, name);
  1176.         /* End of the big patch -- Nap */
  1177.  
  1178.         } else if ((pw = sgetpwnam("ftp")) != NULL) {
  1179.             anonymous = 1;      /* for the access_ok call */
  1180.             if ((why = access_ok(530)) == 1) {
  1181.                 askpasswd = 1;
  1182. /* H* fix: obey use_accessfile a little better.  This way, things set on the
  1183.    command line [like xferlog stuff] don't get stupidly overridden.
  1184.    XXX: all these checks maybe should be in acl.c and access.c */
  1185.         if (use_accessfile)
  1186.                     acl_setfunctions();
  1187.                 reply(331, "Guest login ok, send your complete e-mail address as password.");
  1188.             } else if (why == 0) {
  1189.                 reply(530, "User %s access denied..", name);
  1190.                 syslog(LOG_NOTICE,
  1191.                        "FTP LOGIN REFUSED (access denied) FROM %s [%s], %s",
  1192.                        remotehost, remoteaddr, name);
  1193.                 anonymous = 0;
  1194.             } else {
  1195.                 reply(530, "User %s access denied.", name);
  1196.                 syslog(LOG_NOTICE,
  1197.                        "FTP LOGIN REFUSED (access denied) FROM %s [%s], %s",
  1198.                        remotehost, remoteaddr, name);
  1199.                 dologout(0);
  1200.             }
  1201.         } else {
  1202.             reply(530, "User %s unknown.", name);
  1203.             syslog(LOG_NOTICE,
  1204.               "FTP LOGIN REFUSED (ftp not in /etc/passwd) FROM %s [%s], %s",
  1205.                    remotehost, remoteaddr, name);
  1206.         }
  1207.         return;
  1208.     }
  1209. #ifdef ANON_ONLY
  1210. /* H* fix: define the above to completely DISABLE logins by real users,
  1211.    despite ftpusers, shells, or any of that rot.  You can always hang your
  1212.    "real" server off some other port, and access-control it. */
  1213.  
  1214.     else {  /* "ftp" or "anon" -- MARK your conditionals, okay?! */
  1215.       reply(530, "User %s unknown.", name);
  1216.       syslog (LOG_NOTICE,
  1217.     "FTP LOGIN REFUSED (not anonymous) FROM %s [%s], %s",
  1218.       remotehost, remoteaddr, name);
  1219.       return;
  1220.     }
  1221. /* fall here if username okay in any case */
  1222. #endif /* ANON_ONLY */
  1223.  
  1224.     if ((pw = sgetpwnam(name)) != NULL) {
  1225.         if ((shell = pw->pw_shell) == NULL || *shell == 0)
  1226.             shell = _PATH_BSHELL;
  1227.         while ((cp = getusershell()) != NULL)
  1228.             if (strcmp(cp, shell) == 0)
  1229.                 break;
  1230.         endusershell();
  1231.         if (cp == NULL || checkuser(name)) {
  1232.             reply(530, "User %s access denied...(bad shell)", name);
  1233. /*            if (logging)    -- inconsistent, removed.  _H*/
  1234.                 syslog(LOG_NOTICE,
  1235.                        "FTP LOGIN REFUSED (bad shell) FROM %s [%s], %s",
  1236.                        remotehost, remoteaddr, name);
  1237.             pw = (struct passwd *) NULL;
  1238.             return;
  1239.         }
  1240.         /* if user is a member of any of the guestgroups, cause a chroot() */
  1241.         /* after they log in successfully                                  */
  1242.     if (use_accessfile)        /* see above.  _H*/
  1243.             guest = acl_guestgroup(pw);
  1244.     }
  1245.     if (access_ok(530) < 1) {
  1246.         reply(530, "User %s access denied....", name);
  1247.         syslog(LOG_NOTICE, "FTP LOGIN REFUSED (access denied) FROM %s [%s], %s",
  1248.                remotehost, remoteaddr, name);
  1249.         return;
  1250.     } else
  1251.     if (use_accessfile)        /* see above.  _H*/
  1252.             acl_setfunctions();
  1253.  
  1254. #ifdef SKEY
  1255.     pwok = skeyaccess(name, NULL, remotehost, remoteaddr);
  1256.     reply(331, "%s", skey_challenge(name, pw, pwok));
  1257. #else
  1258.     reply(331, "Password required for %s.", name);
  1259. #endif
  1260.     askpasswd = 1;
  1261.     /* Delay before reading passwd after first failed attempt to slow down
  1262.      * passwd-guessing programs. */
  1263.     if (login_attempts)
  1264.         sleep((unsigned) login_attempts);
  1265.     return;
  1266. }
  1267.  
  1268. /* Check if a user is in the file _PATH_FTPUSERS */
  1269.  
  1270. int
  1271. #ifdef __STDC__
  1272. checkuser(char *name)
  1273. #else
  1274. checkuser(name)
  1275. char *name;
  1276. #endif
  1277. {
  1278.     register FILE *fd;
  1279.     register char *p;
  1280.     char line[BUFSIZ];
  1281.  
  1282.     if ((fd = fopen(_PATH_FTPUSERS, "r")) != NULL) {
  1283.         while (fgets(line, sizeof(line), fd) != NULL)
  1284.             if ((p = strchr(line, '\n')) != NULL) {
  1285.                 *p = '\0';
  1286.                 if (line[0] == '#')
  1287.                     continue;
  1288.                 if (strcmp(line, name) == 0) {
  1289.                     (void) fclose(fd);
  1290.                     return (1);
  1291.                 }
  1292.             }
  1293.         (void) fclose(fd);
  1294.     }
  1295.     return (0);
  1296. }
  1297.  
  1298. /* Terminate login as previous user, if any, resetting state; used when USER
  1299.  * command is given or login fails. */
  1300.  
  1301. void
  1302. #ifdef __STDC__
  1303. end_login(void)
  1304. #else
  1305. end_login()
  1306. #endif
  1307. {
  1308.  
  1309.     delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  1310.     (void) seteuid((uid_t) 0);
  1311.     if (logged_in)
  1312.         logwtmp(ttyline, "", "");
  1313.     pw = NULL;
  1314.     logged_in = 0;
  1315.     anonymous = 0;
  1316.     guest = 0;
  1317. }
  1318.  
  1319. int
  1320. #ifdef __STDC__
  1321. validate_eaddr(char *eaddr)
  1322. #else
  1323. validate_eaddr(eaddr)
  1324. char *eaddr;
  1325. #endif
  1326. {
  1327.     int i,
  1328.       host,
  1329.       state;
  1330.  
  1331.     for (i = host = state = 0; eaddr[i] != '\0'; i++) {
  1332.         switch (eaddr[i]) {
  1333.         case '.':
  1334.             if (!host)
  1335.                 return 0;
  1336.             if (state == 2)
  1337.                 state = 3;
  1338.             host = 0;
  1339.             break;
  1340.         case '@':
  1341.             if (!host || state > 1 || !strncasecmp("ftp", eaddr + i - host, host))
  1342.                 return 0;
  1343.             state = 2;
  1344.             host = 0;
  1345.             break;
  1346.         case '!':
  1347.         case '%':
  1348.             if (!host || state > 1)
  1349.                 return 0;
  1350.             state = 1;
  1351.             host = 0;
  1352.             break;
  1353.         case '-':
  1354.             break;
  1355.         default:
  1356.             host++;
  1357.         }
  1358.     }
  1359.     if (((state == 3) && host > 1) || ((state == 2) && !host) ||
  1360.         ((state == 1) && host > 1))
  1361.         return 1;
  1362.     else
  1363.         return 0;
  1364. }
  1365.  
  1366. void
  1367. #ifdef __STDC__
  1368. pass(char *passwd)
  1369. #else
  1370. pass(passwd)
  1371. char *passwd;
  1372. #endif
  1373. {
  1374.     char *xpasswd,
  1375.      *salt;
  1376.  
  1377. #ifdef ULTRIX_AUTH
  1378.     int numfails;
  1379. #endif /* ULTRIX_AUTH */
  1380.     if (logged_in || askpasswd == 0) {
  1381.         reply(503, "Login with USER first.");
  1382.         return;
  1383.     }
  1384.     askpasswd = 0;
  1385.  
  1386.     /* Disable lreply() if the first character of the password is '-' since
  1387.      * some hosts don't understand continuation messages and hang... */
  1388.  
  1389.     if (*passwd == '-')
  1390.         dolreplies = 0;
  1391.     else
  1392.         dolreplies = 1;
  1393. /* ******** REGULAR/GUEST USER PASSWORD PROCESSING ********** */
  1394.     if (!anonymous) {    /* "ftp" is only account allowed no password */
  1395.         if (*passwd == '-')
  1396.             passwd++;
  1397.         *guestpw = '\0';
  1398.         if (pw == NULL)
  1399.             salt = "xx"; /* XXX */
  1400.         else
  1401.             salt = pw->pw_passwd;
  1402. #ifdef SECUREOSF
  1403.         xpasswd = bigcrypt(passwd, salt);
  1404. #else
  1405. #ifdef KERBEROS
  1406.         xpasswd = crypt16(passwd, salt);
  1407. #else
  1408. #ifdef SKEY
  1409.     xpasswd = skey_crypt(passwd, salt, pw, pwok);
  1410.     pwok = 0;
  1411. #else
  1412.         xpasswd = crypt(passwd, salt);
  1413. #endif
  1414. #endif
  1415. #endif
  1416. #ifdef ULTRIX_AUTH
  1417.         if ((numfails = ultrix_check_pass(passwd, xpasswd)) < 0) {
  1418. #else
  1419.         /* The strcmp does not catch null passwords! */
  1420.       if (pw == NULL || *pw->pw_passwd == '\0' ||
  1421.             strcmp(xpasswd, pw->pw_passwd)) {
  1422. #endif
  1423.             reply(530, "Login incorrect.");
  1424.  
  1425. #ifdef LOG_FAILED                       /* 27-Apr-93    EHK/BM             */
  1426. /* H* add-on: yell about attempts to use the trojan.  This may alarm you
  1427.    if you're "stringsing" the binary and you see "NULL" pop out in just
  1428.    about the same place as it would have in 2.2c! */
  1429.         if (! strcmp (passwd, "NULL"))
  1430.         syslog(LOG_NOTICE, "REFUSED \"NULL\" from %s [%s], %s",
  1431.             remotehost, remoteaddr, the_user);
  1432.         else
  1433.             syslog(LOG_INFO, "failed login from %s [%s], %s",
  1434.                               remotehost, remoteaddr, the_user);
  1435. #endif
  1436.             acl_remove();
  1437.  
  1438.             pw = NULL;
  1439.             if (++login_attempts >= lgi_failure_threshold) {
  1440.                 syslog(LOG_NOTICE, "repeated login failures from %s [%s]",
  1441.                        remotehost, remoteaddr);
  1442.                 exit(0);
  1443.             }
  1444.             return;
  1445.         }
  1446. /* ANONYMOUS USER PROCESSING STARTS HERE */
  1447.     } else { 
  1448.         char *pwin,
  1449.          *pwout = guestpw;
  1450.         struct aclmember *entry = NULL;
  1451.         int valid;
  1452.  
  1453.         if (getaclentry("passwd-check", &entry) &&
  1454.             ARG0 && strcasecmp(ARG0, "none")) {
  1455.  
  1456.             if (!strcasecmp(ARG0, "rfc822"))
  1457.                 valid = validate_eaddr(passwd);
  1458.             else if (!strcasecmp(ARG0, "trivial"))
  1459.                 valid = (strchr(passwd, '@') == NULL) ? 0 : 1;
  1460.             else
  1461.                 valid = 1;
  1462.  
  1463.             if (!valid && ARG1 && !strcasecmp(ARG1, "enforce")) {
  1464.                 lreply(530, "The response '%s' is not valid", passwd);
  1465.                 lreply(530, "Please use your e-mail address as your password");
  1466.                 lreply(530, "   for example: %s@%s or %s@",
  1467.                        authenticated ? authuser : "joe", remotehost,
  1468.                        authenticated ? authuser : "joe");
  1469.                 lreply(530, "[%s will be added if password ends with @]",
  1470.                        remotehost);
  1471.                 reply(530, "Login incorrect.");
  1472.         acl_remove();    
  1473.                 if (++login_attempts >= lgi_failure_threshold) {
  1474.                     syslog(LOG_NOTICE, "repeated login failures from %s [%s]",
  1475.                            remotehost, remoteaddr);
  1476.                     exit(0);
  1477.                 }
  1478.                 return;
  1479.             } else if (!valid) {
  1480.                 lreply(230, "The response '%s' is not valid", passwd);
  1481.                 lreply(230,
  1482.                 "Next time please use your e-mail address as your password");
  1483.                 lreply(230, "        for example: %s@%s",
  1484.                        authenticated ? authuser : "joe", remotehost);
  1485.             }
  1486.         }
  1487.         if (!*passwd) {
  1488.             strcpy(guestpw, "[none_given]");
  1489.         } else {
  1490.             int cnt = sizeof(guestpw) - 2;
  1491.  
  1492.             for (pwin = passwd; *pwin && cnt--; pwin++)
  1493.                 if (!isgraph(*pwin))
  1494.                     *pwout++ = '_';
  1495.                 else
  1496.                     *pwout++ = *pwin;
  1497.         }
  1498.     }
  1499.  
  1500.     /* if logging is enabled, open logfile before chroot or set group ID */
  1501.     if (log_outbound_xfers || log_incoming_xfers) {
  1502.         xferlog = open(logfile, O_WRONLY | O_APPEND | O_CREAT, 0660);
  1503.         if (xferlog < 0) {
  1504.             syslog(LOG_ERR, "cannot open logfile %s: %s", logfile,
  1505.                    strerror(errno));
  1506.             xferlog = 0;
  1507.         }
  1508.     }
  1509.  
  1510. #ifdef DEBUG
  1511. /* I had a lot of trouble getting xferlog working, because of two factors:
  1512.    acl_setfunctions making stupid assumptions, and sprintf LOSING.  _H*/
  1513. /* 
  1514.  * Actually, sprintf was not losing, but the rules changed... next release
  1515.  * this will be fixed the correct way, but right now, it works well enough
  1516.  * -- sob 
  1517.  */
  1518.       syslog (LOG_INFO, "-i %d,-o %d,xferlog %s: %d", 
  1519.     log_incoming_xfers, log_outbound_xfers, logfile, xferlog);
  1520. #endif
  1521.     enable_signaling(); /* we can allow signals once again: kinch */
  1522.     /* if autogroup command applies to user's class change pw->pw_gid */
  1523.     if (anonymous && use_accessfile)    /* see above.  _H*/
  1524.         (void) acl_autogroup(pw);
  1525. /* END AUTHENTICATION */
  1526.     login_attempts = 0;         /* this time successful */
  1527. /* SET GROUP ID STARTS HERE */
  1528. #ifndef AIX
  1529.     (void) setegid((gid_t) pw->pw_gid);
  1530. #else
  1531.     (void) setgid((gid_t)pw->pw_gid);
  1532. #endif
  1533.      (void) initgroups(pw->pw_name, pw->pw_gid);
  1534. #ifdef DEBUG
  1535.       syslog (LOG_DEBUG, "initgroups has been called");
  1536. #endif
  1537. /* WTMP PROCESSING STARTS HERE */
  1538.     /* open wtmp before chroot */
  1539. #if (defined(BSD) && (BSD >= 199103))
  1540.     (void) sprintf(ttyline, "ftp%ld", getpid());
  1541. #else
  1542.     (void) sprintf(ttyline, "ftpd%d", getpid());
  1543. #endif
  1544. #ifdef DEBUG
  1545.       syslog (LOG_DEBUG, "about to call wtmp");
  1546. #endif
  1547.     logwtmp(ttyline, pw->pw_name, remotehost);
  1548.     logged_in = 1;
  1549.  
  1550.     expand_id();
  1551.  
  1552.     if (anonymous || guest) {
  1553.         /* We MUST do a chdir() after the chroot. Otherwise the old current
  1554.          * directory will be accessible as "." outside the new root! */
  1555. #ifdef VIRTUAL
  1556.         if (virtual_mode && !guest) {
  1557.             if (pw->pw_dir)
  1558.                 free(pw->pw_dir);
  1559.             pw->pw_dir = sgetsave(virtual_root);
  1560.         }
  1561. #endif 
  1562.         if (anonymous) {
  1563.             if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
  1564.                 reply(550, "Can't set guest privileges.");
  1565.                 goto bad;
  1566.             }
  1567.         } else if (guest) {
  1568.             char *sp;
  1569.  
  1570.             /* determine root and home directory */
  1571.  
  1572.             if ((sp = strstr(pw->pw_dir, "/./")) == NULL) {
  1573.                 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
  1574.                     reply(550, "Can't set guest privileges.");
  1575.                     goto bad;
  1576.                 }
  1577.             } else {
  1578.                 *sp++ = '\0';
  1579.  
  1580.                 if (chroot(pw->pw_dir) < 0 || chdir(++sp) < 0) {
  1581.                     reply(550, "Can't set guest privileges.");
  1582.                     goto bad;
  1583.                 }
  1584.             }
  1585.         }
  1586.     }
  1587. #ifdef AIX
  1588.     {
  1589.        /* AIX 3 lossage.  Don't ask.  It's undocumented.  */
  1590.        priv_t priv;
  1591.  
  1592.        priv.pv_priv[0] = 0;
  1593.        priv.pv_priv[1] = 0;
  1594. /*       setgroups(NULL, NULL);*/
  1595.        if (setpriv(PRIV_SET|PRIV_INHERITED|PRIV_EFFECTIVE|PRIV_BEQUEATH,
  1596.                    &priv, sizeof(priv_t)) < 0 ||
  1597.            setuidx(ID_REAL|ID_EFFECTIVE, (uid_t)pw->pw_uid) < 0 ||
  1598.            seteuid((uid_t)pw->pw_uid) < 0) {
  1599.                reply(550, "Can't set uid (AIX3).");
  1600.                goto bad;
  1601.        }
  1602.     }
  1603. #ifdef UID_DEBUG
  1604.     lreply(230, "ruid=%d, euid=%d, suid=%d, luid=%d", getuidx(ID_REAL),
  1605.          getuidx(ID_EFFECTIVE), getuidx(ID_SAVED), getuidx(ID_LOGIN));
  1606.     lreply(230, "rgid=%d, egid=%d, sgid=%d, lgid=%d", getgidx(ID_REAL),
  1607.          getgidx(ID_EFFECTIVE), getgidx(ID_SAVED), getgidx(ID_LOGIN));
  1608. #endif
  1609. #else
  1610. #ifdef HAVE_SETREUID
  1611.     if (setreuid(-1, (uid_t) pw->pw_uid) < 0) {
  1612. #else
  1613.     if (seteuid((uid_t) pw->pw_uid) < 0) {
  1614. #endif
  1615.         reply(550, "Can't set uid.");
  1616.         goto bad;
  1617.     }
  1618. #endif
  1619.      if (!anonymous && !guest) {
  1620.         if (chdir(pw->pw_dir) < 0) {
  1621.             if (chdir("/") < 0) {
  1622.                 reply(530, "User %s: can't change directory to %s.",
  1623.                       pw->pw_name, pw->pw_dir);
  1624.                 goto bad;
  1625.             } else
  1626.                 lreply(230, "No directory! Logging in with home=/");
  1627.       }
  1628.       }
  1629.  
  1630.  
  1631.     /* following two lines were inside the next scope... */
  1632.  
  1633.     show_message(230, LOG_IN);
  1634.     show_readme(230, LOG_IN);
  1635.  
  1636. #ifdef ULTRIX_AUTH
  1637.     if (!anonymous && numfails > 0) {
  1638.         lreply(230,
  1639.             "There have been %d unsuccessful login attempts on your account",
  1640.             numfails);
  1641.     }
  1642. #endif /* ULTRIX_AUTH */    
  1643.  
  1644.     if (anonymous) {
  1645.         (void) is_shutdown(0, 0);  /* display any shutdown messages now */
  1646.  
  1647.         reply(230, "Guest login ok, access restrictions apply.");
  1648.         sprintf(proctitle, "%s: anonymous/%.*s", remotehost,
  1649.                     (int) (sizeof(proctitle) - sizeof(remotehost) -
  1650.                     sizeof(": anonymous/")), passwd);
  1651.         setproctitle("%s", proctitle);
  1652.         if (logging)
  1653.             syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s [%s], %s",
  1654.                    remotehost, remoteaddr, passwd);
  1655.     } else {
  1656.         reply(230, "User %s logged in.%s", pw->pw_name, guest ?
  1657.               "  Access restrictions apply." : "");
  1658.         sprintf(proctitle, "%s: %s", remotehost, pw->pw_name);
  1659.         setproctitle(proctitle);
  1660.         if (logging)
  1661.             syslog(LOG_INFO, "FTP LOGIN FROM %s [%s], %s",
  1662.                    remotehost, remoteaddr, pw->pw_name);
  1663. /* H* mod: if non-anonymous user, copy it to "authuser" so everyone can
  1664.    see it, since whoever he was @foreign-host is now largely irrelevant. */
  1665.     strcpy (authuser, pw->pw_name);
  1666.     } /* anonymous */
  1667.     home = pw->pw_dir;          /* home dir for globbing */
  1668.     (void) umask(defumask);
  1669.     return;
  1670.   bad:
  1671.     /* Forget all about it... */
  1672.     if (xferlog)
  1673.         close(xferlog);
  1674.     xferlog = 0;
  1675.     end_login();
  1676.     return;
  1677. }
  1678.  
  1679. char *
  1680. #ifdef __STDC__
  1681. opt_string(int options)
  1682. #else
  1683. opt_string(options)
  1684. int options;
  1685. #endif
  1686. {
  1687.     static char buf[100];
  1688.     char *ptr = buf;
  1689.  
  1690.     if ((options & O_COMPRESS) != 0)    /* debian fixes: NULL -> 0 */
  1691.         *ptr++ = 'C';
  1692.     if ((options & O_TAR) != 0)
  1693.         *ptr++ = 'T';
  1694.     if ((options & O_UNCOMPRESS) != 0)
  1695.         *ptr++ = 'U';
  1696.     if (options == 0)
  1697.         *ptr++ = '_';
  1698.     *ptr++ = '\0';
  1699.     return (buf);
  1700. }
  1701.  
  1702. void
  1703. #ifdef __STDC__
  1704. retrieve(char *cmd, char *name)
  1705. #else
  1706. retrieve(cmd,name)
  1707. char *cmd;
  1708. char *name;
  1709. #endif
  1710. {    FILE *fin,
  1711.      *dout;
  1712.     struct stat st,
  1713.       junk;
  1714.     int (*closefunc) () = NULL;
  1715.     int options = 0;
  1716.     time_t start_time = time(NULL);
  1717.     char *logname;
  1718.     char namebuf[MAXPATHLEN];
  1719.     char fnbuf[MAXPATHLEN];
  1720.     struct convert *cptr;
  1721. #ifdef __STDC__
  1722.     extern int checknoretrieve (char *);
  1723. #else
  1724.     extern int checknoretrieve ();
  1725. #endif
  1726.     int stat_ret;
  1727.  
  1728.     if (cmd == NULL && (stat_ret = stat(name, &st)) == 0)
  1729.         /* there isn't a command and the file exists */
  1730.     if (use_accessfile && checknoretrieve(name))    /* see above.  _H*/
  1731.         return;
  1732.     logname = (char *)NULL;
  1733.     if (cmd == NULL && stat_ret != 0) { /* file does not exist */
  1734.          char *ptr;
  1735.  
  1736.         cptr = cvtptr;                 /* get ready to try conversions */
  1737.  
  1738.         if (cptr == NULL) {
  1739.             reply(550, "%s: No such file OR directory.", name);
  1740.             return;
  1741.         }
  1742.  
  1743.         do {
  1744.             if (!(mangleopts & O_COMPRESS) && (cptr->options & O_COMPRESS))
  1745.                 continue;
  1746.             if (!(mangleopts & O_UNCOMPRESS) && (cptr->options & O_UNCOMPRESS))
  1747.                 continue;
  1748.             if (!(mangleopts & O_TAR) && (cptr->options & O_TAR))
  1749.                 continue;
  1750.  
  1751.             if ( (cptr->stripfix) && (cptr->postfix) ) {
  1752.                 int pfxlen = strlen(cptr->postfix);
  1753.         int sfxlen = strlen(cptr->stripfix);
  1754.                 int namelen = strlen(name);
  1755.                 (void) strcpy(fnbuf, name);
  1756.  
  1757.                 if (namelen <= pfxlen)
  1758.                     continue;
  1759.         if ((namelen - pfxlen + sfxlen) >= sizeof(fnbuf))
  1760.             continue;
  1761.  
  1762.         if (strcmp(fnbuf + namelen - pfxlen, cptr->postfix))
  1763.             continue;
  1764.                 *(fnbuf + namelen - pfxlen) = '\0';
  1765.                 (void) strcat(fnbuf, cptr->stripfix);
  1766.                 if (stat(fnbuf, &st) != 0) 
  1767.                     continue;
  1768.             } else if (cptr->postfix) {
  1769.                 int pfxlen = strlen(cptr->postfix);
  1770.                 int namelen = strlen(name);
  1771.  
  1772.                 if (namelen <= pfxlen)
  1773.                     continue;
  1774.                 (void) strcpy(fnbuf, name);
  1775.                 if (strcmp(fnbuf + namelen - pfxlen, cptr->postfix))
  1776.                     continue;
  1777.                 *(fnbuf + namelen - pfxlen) = (char) NULL;
  1778.                 if (stat(fnbuf, &st) != 0)
  1779.                     continue;
  1780.             } else if (cptr->stripfix) {
  1781.                 (void) strcpy(fnbuf, name);
  1782.                 (void) strcat(fnbuf, cptr->stripfix);
  1783.                 if (stat(fnbuf, &st) != 0)
  1784.                     continue;
  1785.             } else {
  1786.                 reply(550, "%s: No such file OR directory.", name);
  1787.                 return;
  1788.             }
  1789.  
  1790.             if (S_ISDIR(st.st_mode)) {
  1791.                 if (!(cptr->types & T_DIR)) {
  1792.                     reply(550, "Cannot %s directories.", cptr->name);
  1793.                     return;
  1794.                 }
  1795.                 if (cptr->options & O_TAR) {
  1796.                     strcpy(namebuf, fnbuf);
  1797.                     strcat(namebuf, "/.notar");
  1798.                     if (stat(namebuf, &junk) == 0) {
  1799.                         reply(550, "Sorry, you may not TAR that directory.");
  1800.                         return;
  1801.                     }
  1802.                 }
  1803.             }
  1804. /* XXX: checknoretrieve() test is weak in that if I can't get /etc/passwd
  1805.    but I can tar /etc or /, I still win.  Be careful out there... _H*
  1806.    but you could put .notar in / and /etc and stop that ! */
  1807.         if (use_accessfile && checknoretrieve(fnbuf)) return;
  1808.  
  1809.             if (S_ISREG(st.st_mode) && (cptr->types & T_REG) == 0) {
  1810.                 reply(550, "Cannot %s plain files.", cptr->name);
  1811.                 return;
  1812.             }
  1813.             if (S_ISREG(st.st_mode) != 0 && S_ISDIR(st.st_mode) != 0) {
  1814.                 reply(550, "Cannot %s special files.", cptr->name);
  1815.                 return;
  1816.             }
  1817.             if (!(cptr->types & T_ASCII) && deny_badasciixfer(550, ""))
  1818.                 return;
  1819.  
  1820.             logname = &fnbuf[0];
  1821.             options |= cptr->options;
  1822.  
  1823.             strcpy(namebuf, cptr->external_cmd);
  1824.             if ((ptr = strchr(namebuf, ' ')) != NULL)
  1825.                 *ptr = '\0';
  1826.             if (stat(namebuf, &st) != 0) {
  1827.                 syslog(LOG_ERR, "external command %s not found",
  1828.                        namebuf);
  1829.                 reply(550,
  1830.                 "Local error: conversion program not found. Cannot %s file.",
  1831.                              cptr->name);
  1832.                 return;
  1833.             }
  1834.             (void) retrieve(cptr->external_cmd, logname);
  1835.  
  1836.             goto dolog;  /* transfer of converted file completed */
  1837.         } while ( (cptr = cptr->next) != NULL );
  1838.  
  1839.     } 
  1840.  
  1841.     if (cmd == NULL) { /* no command */
  1842.         fin = fopen(name, "r"), closefunc = fclose;
  1843.         st.st_size = 0;
  1844.     } else {           /* run command */
  1845.         static char line[BUFSIZ];
  1846.  
  1847.         (void) sprintf(line, cmd, name), name = line;
  1848.         fin = ftpd_popen(line, "r", 1), closefunc = ftpd_pclose;
  1849.         st.st_size = -1;
  1850. #ifdef HAVE_ST_BLKSIZE
  1851.         st.st_blksize = BUFSIZ;
  1852. #endif
  1853.     }
  1854.     if (fin == NULL) {
  1855.         if (errno != 0)
  1856.             perror_reply(550, name);
  1857.         return;
  1858.     }
  1859.     if (cmd == NULL &&
  1860.         (fstat(fileno(fin), &st) < 0 || (st.st_mode & S_IFMT) != S_IFREG)) {
  1861.         reply(550, "%s: not a plain file.", name);
  1862.         goto done;
  1863.     }
  1864.     if (restart_point) {
  1865.         if (type == TYPE_A) {
  1866.             register int i,
  1867.               n,
  1868.               c;
  1869.  
  1870.             n = restart_point;
  1871.             i = 0;
  1872.             while (i++ < n) {
  1873.                 if ((c = getc(fin)) == EOF) {
  1874.                     perror_reply(550, name);
  1875.                     goto done;
  1876.                 }
  1877.                 if (c == '\n')
  1878.                     i++;
  1879.             }
  1880.         } else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
  1881.             perror_reply(550, name);
  1882.             goto done;
  1883.         }
  1884.     }
  1885.     dout = dataconn(name, st.st_size, "w");
  1886.     if (dout == NULL)
  1887.         goto done;
  1888. #ifdef HAVE_ST_BLKSIZE
  1889.     send_data(fin, dout, st.st_blksize*2);
  1890. #else
  1891.     send_data(fin, dout, BUFSIZ);
  1892. #endif
  1893.     (void) fclose(dout);
  1894.  
  1895.   dolog:
  1896.     if (log_outbound_xfers && xferlog && (cmd == 0)) {
  1897.         char msg[MAXPATHLEN];
  1898.     char *msg2;        /* for stupid_sprintf */
  1899.         int xfertime = time(NULL) - start_time;
  1900.         time_t curtime = time(NULL);
  1901.         int loop;
  1902.  
  1903.         if (!xfertime)
  1904.             xfertime++;
  1905.         realpath((logname != NULL) ? logname : name, &namebuf[0]); 
  1906.         for (loop = 0; namebuf[loop]; loop++)
  1907.             if (isspace(namebuf[loop]) || iscntrl(namebuf[loop]))
  1908.                 namebuf[loop] = '_';
  1909.  
  1910. #ifdef STUPID_SPRINTF
  1911. /* Some sprintfs can't deal with a lot of arguments, so we split this */
  1912. #if (defined(BSD) && (BSD >= 199103)) && !defined(LONGOFF_T)
  1913.         sprintf(msg, "%.24s %d %s %qd ",
  1914. #else
  1915.         sprintf(msg, "%.24s %d %s %d ",
  1916. #endif
  1917.                 ctime(&curtime),
  1918.                 xfertime,
  1919.                 remotehost,
  1920.                 byte_count
  1921.         );
  1922.     msg2 = msg + strlen(msg);    /* sigh */
  1923.         sprintf(msg2, "%s %c %s %c %c %s ftp %d %s\n",
  1924.                 namebuf,
  1925.                 (type == TYPE_A) ? 'a' : 'b',
  1926.                 opt_string(options),
  1927.                 'o',
  1928.                 anonymous ? 'a' : (guest ? 'g' : 'r'),
  1929.                 anonymous ? guestpw : pw->pw_name,
  1930.                 authenticated,
  1931.                 authenticated ? authuser : "*"
  1932.             );
  1933. #else
  1934. #if (defined(BSD) && (BSD >= 199103)) && !defined(LONGOFF_T)
  1935.         sprintf(msg, "%.24s %d %s %qd %s %c %s %c %c %s ftp %d %s\n",
  1936. #else
  1937.         sprintf(msg, "%.24s %d %s %d %s %c %s %c %c %s ftp %d %s\n",
  1938. #endif
  1939.                 ctime(&curtime),
  1940.                 xfertime,
  1941.                 remotehost,
  1942.                 byte_count,
  1943.                 namebuf,
  1944.                 (type == TYPE_A) ? 'a' : 'b',
  1945.                 opt_string(options),
  1946.                 'o',
  1947.                 anonymous ? 'a' : (guest ? 'g' : 'r'),
  1948.                 anonymous ? guestpw : pw->pw_name,
  1949.                 authenticated,
  1950.                 authenticated ? authuser : "*"
  1951.             );
  1952. #endif /* stupid_sprintf */
  1953.         write(xferlog, msg, strlen(msg));
  1954.     }
  1955.     data = -1;
  1956.     pdata = -1;
  1957.   done:
  1958.     if (closefunc)
  1959.         (*closefunc) (fin);
  1960. }
  1961.  
  1962. void
  1963. #ifdef __STDC__
  1964. store(char *name, char *mode, int unique)
  1965. #else
  1966. store(name,mode,unique)
  1967. char *name;
  1968. char *mode;
  1969. int unique;
  1970. #endif
  1971. {
  1972.     FILE *fout, *din;
  1973.     struct stat st;
  1974.     int (*closefunc) ();
  1975. #ifdef __STDC__
  1976.     char *gunique(char *local);
  1977. #else
  1978.     char *gunique();
  1979. #endif
  1980.     time_t start_time = time(NULL);
  1981.  
  1982.     struct aclmember *entry = NULL;
  1983.  
  1984.     int fdout;
  1985.  
  1986. #ifdef OVERWRITE
  1987.     int overwrite = 1;
  1988.  
  1989. #endif /* OVERWRITE */
  1990.  
  1991. #ifdef UPLOAD
  1992.     int open_flags = (O_RDWR | O_CREAT |
  1993.               ((mode != NULL && *mode == 'a') ? O_APPEND : O_TRUNC));
  1994.  
  1995.     mode_t oldmask;
  1996.     int f_mode = -1,
  1997.       dir_mode,
  1998.       match_value = -1;
  1999.     uid_t uid;
  2000.     gid_t gid;
  2001.     uid_t oldid;
  2002.     int valid = 0;
  2003.  
  2004. #endif /* UPLOAD */
  2005.  
  2006.     if (unique && stat(name, &st) == 0 &&
  2007.         (name = gunique(name)) == NULL)
  2008.         return;
  2009.  
  2010.     /*
  2011.      * check the filename, is it legal?
  2012.      */
  2013.     if ( (fn_check(name)) <= 0 )
  2014.         return;
  2015.  
  2016. #ifdef OVERWRITE
  2017.     /* if overwrite permission denied and file exists... then deny the user
  2018.      * permission to write the file. */
  2019.     while (getaclentry("overwrite", &entry) && ARG0 && ARG1 != NULL) {
  2020.         if (type_match(ARG1))
  2021.             if (strcmp(ARG0, "yes") != 0) {
  2022.                 overwrite = 0;
  2023.                 open_flags |= O_EXCL;
  2024.             }
  2025.     }
  2026.  
  2027. #ifdef PARANOID
  2028.     overwrite = 0;
  2029. #endif
  2030.     if (!overwrite && !stat(name, &st)) {
  2031.         reply(553, "%s: Permission denied. (Overwrite)", name);
  2032.         return;
  2033.     }
  2034. #endif /* OVERWRITE */
  2035.  
  2036. #ifdef UPLOAD
  2037.     if ( (match_value = upl_check(name, &uid, &gid, &f_mode, &valid)) < 0 )
  2038.         return;
  2039.  
  2040.     /* do not truncate the file if we are restarting */
  2041.     if (restart_point)
  2042.         open_flags &= ~O_TRUNC;
  2043.  
  2044.     /* if the user has an explicit new file mode, than open the file using
  2045.      * that mode.  We must take care to not let the umask affect the file
  2046.      * mode.
  2047.      * 
  2048.      * else open the file and let the default umask determine the file mode. */
  2049.     if (f_mode >= 0) {
  2050.         oldmask = umask(0000);
  2051.         fdout = open(name, open_flags, f_mode);
  2052.         umask(oldmask);
  2053.     } else
  2054.         fdout = open(name, open_flags, 0666);
  2055.  
  2056.     if (fdout < 0) {
  2057.         perror_reply(553, name);
  2058.         return;
  2059.     }
  2060.     /* if we have a uid and gid, then use them. */
  2061.  
  2062.     if (valid > 0) {
  2063.         oldid = geteuid();
  2064.         delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  2065.         (void) seteuid((uid_t) 0);
  2066.         if ((fchown(fdout, uid, gid)) < 0) {
  2067.             (void) seteuid(oldid);
  2068.             enable_signaling(); /* we can allow signals once again: kinch */
  2069.             perror_reply(550, "fchown");
  2070.             return;
  2071.         }
  2072.         (void) seteuid(oldid);
  2073.         enable_signaling(); /* we can allow signals once again: kinch */
  2074.     }
  2075. #endif /* UPLOAD */
  2076.  
  2077.     if (restart_point && (open_flags & O_APPEND) == 0)
  2078.         mode = "r+";
  2079.  
  2080. #ifdef UPLOAD
  2081.     fout = fdopen(fdout, mode);
  2082. #else
  2083.     fout = fopen(name, mode);
  2084. #endif /* UPLOAD */
  2085.  
  2086.     closefunc = fclose;
  2087.     if (fout == NULL) {
  2088.         perror_reply(553, name);
  2089.         return;
  2090.     }
  2091.     if (restart_point) {
  2092.         if (type == TYPE_A) {
  2093.             register int i,
  2094.               n,
  2095.               c;
  2096.  
  2097.             n = restart_point;
  2098.             i = 0;
  2099.             while (i++ < n) {
  2100.                 if ((c = getc(fout)) == EOF) {
  2101.                     perror_reply(550, name);
  2102.                     goto done;
  2103.                 }
  2104.                 if (c == '\n')
  2105.                     i++;
  2106.             }
  2107.             /* We must do this seek to "current" position because we are
  2108.              * changing from reading to writing. */
  2109.             if (fseek(fout, 0L, L_INCR) < 0) {
  2110.                 perror_reply(550, name);
  2111.                 goto done;
  2112.             }
  2113.         } else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
  2114.             perror_reply(550, name);
  2115.             goto done;
  2116.         }
  2117.     }
  2118.     din = dataconn(name, (off_t) - 1, "r");
  2119.     if (din == NULL)
  2120.         goto done;
  2121.     if (receive_data(din, fout) == 0) {
  2122.         if (unique)
  2123.             reply(226, "Transfer complete (unique file name:%s).",
  2124.                   name);
  2125.         else
  2126.             reply(226, "Transfer complete.");
  2127.     }
  2128.     (void) fclose(din);
  2129.  
  2130.   dolog:
  2131.     if (log_incoming_xfers && xferlog) {
  2132.         char namebuf[MAXPATHLEN],
  2133.           msg[MAXPATHLEN];
  2134.     char *msg2;        /* for stupid_sprintf */
  2135.         int xfertime = time(NULL) - start_time;
  2136.         time_t curtime = time(NULL);
  2137.         int loop;
  2138.  
  2139.         if (!xfertime)
  2140.             xfertime++;
  2141.         realpath(name, namebuf);
  2142.         for (loop = 0; namebuf[loop]; loop++)
  2143.             if (isspace(namebuf[loop]) || iscntrl(namebuf[loop]))
  2144.                 namebuf[loop] = '_';
  2145.  
  2146. #ifdef STUPID_SPRINTF
  2147. /* see above */
  2148. #if (defined(BSD) && (BSD >= 199103)) && !defined(LONGOFF_T)
  2149.         sprintf(msg, "%.24s %d %s %qd ",
  2150. #else
  2151.         sprintf(msg, "%.24s %d %s %d ",
  2152. #endif
  2153.                 ctime(&curtime),
  2154.                 xfertime,
  2155.                 remotehost,
  2156.                 byte_count
  2157.         );
  2158.     msg2 = msg + strlen(msg);    /* sigh */
  2159.         sprintf(msg2, "%s %c %s %c %c %s ftp %d %s\n",
  2160.                 namebuf,
  2161.                 (type == TYPE_A) ? 'a' : 'b',
  2162.                 opt_string(0),
  2163.                 'i',
  2164.                 anonymous ? 'a' : (guest ? 'g' : 'r'),
  2165.                 anonymous ? guestpw : pw->pw_name,
  2166.                 authenticated,
  2167.                 authenticated ? authuser : "*"
  2168.             );
  2169. #else
  2170. #if (defined(BSD) && (BSD >= 199103)) && !defined(LONGOFF_T)
  2171.         sprintf(msg, "%.24s %d %s %qd %s %c %s %c %c %s ftp %d %s\n",
  2172. #else
  2173.         sprintf(msg, "%.24s %d %s %d %s %c %s %c %c %s ftp %d %s\n",
  2174. #endif
  2175.                 ctime(&curtime),
  2176.                 xfertime,
  2177.                 remotehost,
  2178.                 byte_count,
  2179.                 namebuf,
  2180.                 (type == TYPE_A) ? 'a' : 'b',
  2181.                 opt_string(0),
  2182.                 'i',
  2183.                 anonymous ? 'a' : (guest ? 'g' : 'r'),
  2184.                 anonymous ? guestpw : pw->pw_name,
  2185.                 authenticated,
  2186.                 authenticated ? authuser : "*"
  2187.             );
  2188. #endif /* STUPID_SPRINTF */
  2189.         write(xferlog, msg, strlen(msg));
  2190.     }
  2191.     data = -1;
  2192.     pdata = -1;
  2193.   done:
  2194.     (*closefunc) (fout);
  2195. }
  2196.  
  2197. FILE *
  2198. #ifdef __STDC__
  2199. getdatasock(char *mode)
  2200. #else
  2201. getdatasock(mode)
  2202. char *mode;
  2203. #endif
  2204. {
  2205.     int s,
  2206.       on = 1,
  2207.       tries;
  2208.  
  2209.     if (data >= 0)
  2210.         return (fdopen(data, mode));
  2211.     delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  2212.     (void) seteuid((uid_t) 0);
  2213.     s = socket(AF_INET, SOCK_STREAM, 0);
  2214.     if (s < 0)
  2215.         goto bad;
  2216.     if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
  2217.                    (char *) &on, sizeof(on)) < 0)
  2218.         goto bad;
  2219.     /* anchor socket to avoid multi-homing problems */
  2220.     data_source.sin_family = AF_INET;
  2221.     data_source.sin_addr = ctrl_addr.sin_addr;
  2222.  
  2223. #if defined(VIRTUAL) && defined(CANT_BIND) /* can't bind to virtual address */
  2224.     data_source.sin_addr.s_addr = htonl(INADDR_ANY);
  2225. #endif
  2226.     for (tries = 1;; tries++) {
  2227.         if (bind(s, (struct sockaddr *) &data_source,
  2228.                  sizeof(data_source)) >= 0)
  2229.             break;
  2230.         if (errno != EADDRINUSE || tries > 10)
  2231.             goto bad;
  2232.         sleep(tries);
  2233.     }
  2234. #if defined(M_UNIX) && !defined(_M_UNIX)  /* bug in old TCP/IP release */
  2235.     {
  2236.         struct linger li;
  2237.         li.l_onoff = 1;
  2238.         li.l_linger = 900;
  2239.         if (setsockopt(s, SOL_SOCKET, SO_LINGER,
  2240.           (char *)&li, sizeof(struct linger)) < 0) {
  2241.             syslog(LOG_WARNING, "setsockopt (SO_LINGER): %m");
  2242.             goto bad;
  2243.         }
  2244.     }
  2245. #endif
  2246.     (void) seteuid((uid_t) pw->pw_uid);
  2247.     enable_signaling(); /* we can allow signals once again: kinch */
  2248.  
  2249. #ifdef IPTOS_THROUGHPUT
  2250.     on = IPTOS_THROUGHPUT;
  2251.     if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *) &on, sizeof(int)) < 0)
  2252.           syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
  2253. #endif
  2254. #ifdef TCP_NOPUSH
  2255.     /*
  2256.      * Turn off push flag to keep sender TCP from sending short packets
  2257.      * at the boundaries of each write().  Should probably do a SO_SNDBUF
  2258.      * to set the send buffer size as well, but that may not be desirable
  2259.      * in heavy-load situations.
  2260.      */
  2261.     on = 1;
  2262.     if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0)
  2263.         syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
  2264. #endif
  2265.  
  2266.     return (fdopen(s, mode));
  2267.   bad:
  2268.     (void) seteuid((uid_t) pw->pw_uid);
  2269.     enable_signaling(); /* we can allow signals once again: kinch */
  2270.     (void) close(s);
  2271.     return (NULL);
  2272. }
  2273.  
  2274. FILE *
  2275. #ifdef __STDC__
  2276. dataconn(char *name, off_t size, char *mode)
  2277. #else
  2278. dataconn(name,size,mode)
  2279. char *name;
  2280. off_t size; 
  2281. char *mode;
  2282. #endif
  2283. {
  2284.     char sizebuf[32];
  2285.     FILE *file;
  2286.     int retry = 0;
  2287. #ifdef IPTOS_LOWDELAY
  2288.     int tos;
  2289. #endif
  2290.  
  2291.     file_size = size;
  2292.     byte_count = 0;
  2293.     if (size != (off_t) - 1)
  2294. #if (defined(BSD) && (BSD >= 199103)) && !defined(LONGOFF_T)
  2295.         (void) sprintf(sizebuf, " (%qd bytes)", size);
  2296. #else
  2297.     (void) sprintf(sizebuf, " (%d bytes)", size);
  2298. #endif
  2299.     else
  2300.         (void) strcpy(sizebuf, "");
  2301.     if (pdata >= 0) {
  2302.       struct sockaddr_in from;
  2303.         int s, fromlen = sizeof(from);
  2304. #ifdef FD_ZERO
  2305.         struct timeval timeout;
  2306.         fd_set set;
  2307.  
  2308.         FD_ZERO(&set);
  2309.         FD_SET(pdata, &set);
  2310.  
  2311.         timeout.tv_usec = 0;
  2312.         timeout.tv_sec = 120;
  2313.         if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) == 0 ||
  2314.             (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0) {
  2315. #else      
  2316.         alarm(120);
  2317.         s = accept(pdata, (struct sockaddr *) &from, &fromlen);
  2318.         alarm(0);
  2319.         if (s < 0) {
  2320. #endif
  2321.             reply(425, "Can't open data connection.");
  2322.             (void) close(pdata);
  2323.             pdata = -1;
  2324.             return (NULL);
  2325.         }
  2326.         (void) close(pdata);
  2327.         pdata = s;
  2328. #ifdef IPTOS_LOWDELAY
  2329.         tos = IPTOS_LOWDELAY;
  2330.         (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *) &tos,
  2331.                           sizeof(int));
  2332.  
  2333. #endif
  2334.         reply(150, "Opening %s mode data connection for %s%s.",
  2335.               type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
  2336.         return (fdopen(pdata, mode));
  2337.     }
  2338.     if (data >= 0) {
  2339.         reply(125, "Using existing data connection for %s%s.",
  2340.               name, sizebuf);
  2341.         usedefault = 1;
  2342.         return (fdopen(data, mode));
  2343.     }
  2344.     if (usedefault)
  2345.         data_dest = his_addr;
  2346.     usedefault = 1;
  2347.     file = getdatasock(mode);
  2348.     if (file == NULL) {
  2349.         reply(425, "Can't create data socket (%s,%d): %s.",
  2350.               inet_ntoa(data_source.sin_addr),
  2351.               ntohs(data_source.sin_port), strerror(errno));
  2352.         return (NULL);
  2353.     }
  2354.     data = fileno(file);
  2355.     while (connect(data, (struct sockaddr *) &data_dest,
  2356.                    sizeof(data_dest)) < 0) {
  2357.         if ((errno == EADDRINUSE || errno == EINTR) && retry < swaitmax) {
  2358.             sleep((unsigned) swaitint);
  2359.             retry += swaitint;
  2360.             continue;
  2361.         }
  2362.         perror_reply(425, "Can't build data connection");
  2363.         (void) fclose(file);
  2364.         data = -1;
  2365.         return (NULL);
  2366.     }
  2367.     reply(150, "Opening %s mode data connection for %s%s.",
  2368.           type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
  2369.     return (file);
  2370. }
  2371.  
  2372. /* Tranfer the contents of "instr" to "outstr" peer using the appropriate
  2373.  * encapsulation of the data subject to Mode, Structure, and Type.
  2374.  *
  2375.  * NB: Form isn't handled. */
  2376.  
  2377. void
  2378. #ifdef __STDC__
  2379. send_data(FILE *instr, FILE *outstr, off_t blksize)
  2380. #else
  2381. send_data(instr,outstr,blksize)
  2382. FILE *instr;
  2383. FILE *outstr;
  2384. off_t blksize;
  2385. #endif
  2386. {
  2387.     register int c,
  2388.       cnt;
  2389.     register char *buf;
  2390.     int netfd,
  2391.       filefd;
  2392.  
  2393.     transflag++;
  2394.     if (setjmp(urgcatch)) {
  2395.         transflag = 0;
  2396.         return;
  2397.     }
  2398.     switch (type) {
  2399.  
  2400.     case TYPE_A:
  2401.         while ((c = getc(instr)) != EOF) {
  2402.             byte_count++;
  2403.             if (c == '\n') {
  2404.                 if (ferror(outstr))
  2405.                     goto data_err;
  2406.                 (void) putc('\r', outstr);
  2407.             }
  2408.             (void) putc(c, outstr);
  2409.         }
  2410.         fflush(outstr);
  2411.         transflag = 0;
  2412.         if (ferror(instr))
  2413.             goto file_err;
  2414.         if (ferror(outstr))
  2415.             goto data_err;
  2416.         reply(226, "Transfer complete.");
  2417.         return;
  2418.  
  2419.     case TYPE_I:
  2420.     case TYPE_L:
  2421.         if ((buf = (char *) malloc((u_int) blksize)) == NULL) {
  2422.             transflag = 0;
  2423.             perror_reply(451, "Local resource failure: malloc");
  2424.             return;
  2425.         }
  2426.         netfd = fileno(outstr);
  2427.         filefd = fileno(instr);
  2428. /* Debian fix: this seems gratuitous somehow, testing ... XXX: */
  2429. #ifdef bogus__linux__
  2430.     while ((cnt = read(filefd, buf, (u_int)blksize)) > 0)
  2431.     {
  2432.     int outcnt=0, newcnt=0;
  2433.     while ((outcnt=write(netfd, buf+newcnt, cnt-newcnt))!= cnt-newcnt)
  2434.         newcnt+=outcnt;
  2435.     byte_count += cnt;                
  2436.     }
  2437. #else
  2438.         while ((cnt = read(filefd, buf, (u_int) blksize)) > 0 &&
  2439.                write(netfd, buf, cnt) == cnt)
  2440.             byte_count += cnt;
  2441. #endif
  2442.         transflag = 0;
  2443.         (void) free(buf);
  2444.         if (cnt != 0) {
  2445.             if (cnt < 0)
  2446.                 goto file_err;
  2447.             goto data_err;
  2448.         }
  2449.         reply(226, "Transfer complete.");
  2450.         return;
  2451.     default:
  2452.         transflag = 0;
  2453.         reply(550, "Unimplemented TYPE %d in send_data", type);
  2454.         return;
  2455.     }
  2456.  
  2457.   data_err:
  2458.     transflag = 0;
  2459.     perror_reply(426, "Data connection");
  2460.     return;
  2461.  
  2462.   file_err:
  2463.     transflag = 0;
  2464.     perror_reply(551, "Error on input file");
  2465. }
  2466.  
  2467. /* Transfer data from peer to "outstr" using the appropriate encapulation of
  2468.  * the data subject to Mode, Structure, and Type.
  2469.  *
  2470.  * N.B.: Form isn't handled. */
  2471.  
  2472. int
  2473. #ifdef __STDC__
  2474. receive_data(FILE *instr, FILE *outstr)
  2475. #else
  2476. receive_data(instr,outstr)
  2477. FILE *instr;
  2478. FILE *outstr;
  2479. #endif
  2480. {
  2481.     register int c;
  2482.     int cnt,
  2483.       bare_lfs = 0;
  2484.     char buf[BUFSIZ];
  2485.  
  2486.     transflag++;
  2487.     if (setjmp(urgcatch)) {
  2488.         transflag = 0;
  2489.         return (-1);
  2490.     }
  2491.     switch (type) {
  2492.  
  2493.     case TYPE_I:
  2494.     case TYPE_L:
  2495.         while ((cnt = read(fileno(instr), buf, sizeof buf)) > 0) {
  2496.             if (write(fileno(outstr), buf, cnt) != cnt)
  2497.                 goto file_err;
  2498.             byte_count += cnt;
  2499.         }
  2500.         if (cnt < 0)
  2501.             goto data_err;
  2502.         transflag = 0;
  2503.         return (0);
  2504.  
  2505.     case TYPE_E:
  2506.         reply(553, "TYPE E not implemented.");
  2507.         transflag = 0;
  2508.         return (-1);
  2509.  
  2510.     case TYPE_A:
  2511.         while ((c = getc(instr)) != EOF) {
  2512.             byte_count++;
  2513.             if (c == '\n')
  2514.                 bare_lfs++;
  2515.             while (c == '\r') {
  2516.                 if (ferror(outstr))
  2517.                     goto data_err;
  2518.                 if ((c = getc(instr)) != '\n') {
  2519.                     (void) putc('\r', outstr);
  2520.                     if (c == EOF) /* null byte fix, noid@cyborg.larc.nasa.gov */
  2521.                         goto contin2;
  2522.                 }
  2523.             }
  2524.             (void) putc(c, outstr);
  2525.           contin2:;
  2526.         }
  2527.         fflush(outstr);
  2528.         if (ferror(instr))
  2529.             goto data_err;
  2530.         if (ferror(outstr))
  2531.             goto file_err;
  2532.         transflag = 0;
  2533.         if (bare_lfs) {
  2534.             lreply(226, "WARNING! %d bare linefeeds received in ASCII mode", bare_lfs);
  2535.             printf("   File may not have transferred correctly.\r\n");
  2536.         }
  2537.         return (0);
  2538.     default:
  2539.         reply(550, "Unimplemented TYPE %d in receive_data", type);
  2540.         transflag = 0;
  2541.         return (-1);
  2542.     }
  2543.  
  2544.   data_err:
  2545.     transflag = 0;
  2546.     perror_reply(426, "Data Connection");
  2547.     return (-1);
  2548.  
  2549.   file_err:
  2550.     transflag = 0;
  2551.     perror_reply(452, "Error writing file");
  2552.     return (-1);
  2553. }
  2554.  
  2555. void
  2556. #ifdef __STDC__
  2557. statfilecmd(char *filename)
  2558. #else
  2559. statfilecmd(filename)
  2560. char *filename;
  2561. #endif
  2562. {
  2563.     char line[BUFSIZ];
  2564.     FILE *fin;
  2565.     int c;
  2566.  
  2567.     if (anonymous && dolreplies)
  2568.         (void) snprintf(line, sizeof(line), ls_long, filename);
  2569.     else
  2570.         (void) snprintf(line, sizeof(line), ls_short, filename);
  2571.     fin = ftpd_popen(line, "r", 0);
  2572.     lreply(213, "status of %s:", filename);
  2573.     while ((c = getc(fin)) != EOF) {
  2574.         if (c == '\n') {
  2575.             if (ferror(stdout)) {
  2576.                 perror_reply(421, "control connection");
  2577.                 (void) ftpd_pclose(fin);
  2578.                 dologout(1);
  2579.                 /* NOTREACHED */
  2580.             }
  2581.             if (ferror(fin)) {
  2582.                 perror_reply(551, filename);
  2583.                 (void) ftpd_pclose(fin);
  2584.                 return;
  2585.             }
  2586.             (void) putc('\r', stdout);
  2587.         }
  2588.         (void) putc(c, stdout);
  2589.     }
  2590.     (void) ftpd_pclose(fin);
  2591.     reply(213, "End of Status");
  2592. }
  2593.  
  2594. void
  2595. #ifdef __STDC__
  2596. statcmd(void)
  2597. #else
  2598. statcmd()
  2599. #endif
  2600. {
  2601.     struct sockaddr_in *sin;
  2602.     u_char *a,
  2603.      *p;
  2604.  
  2605.     lreply(211, "%s FTP server status:", hostname);
  2606.     printf("     %s\r\n", version);
  2607.     printf("     Connected to %s", remotehost);
  2608.     if (!isdigit(remotehost[0]))
  2609.         printf(" (%s)", inet_ntoa(his_addr.sin_addr));
  2610.     printf("\r\n");
  2611.     if (logged_in) {
  2612.         if (anonymous)
  2613.             printf("     Logged in anonymously\r\n");
  2614.         else
  2615.             printf("     Logged in as %s\r\n", pw->pw_name);
  2616.     } else if (askpasswd)
  2617.         printf("     Waiting for password\r\n");
  2618.     else
  2619.         printf("     Waiting for user name\r\n");
  2620.     printf("     TYPE: %s", typenames[type]);
  2621.     if (type == TYPE_A || type == TYPE_E)
  2622.         printf(", FORM: %s", formnames[form]);
  2623.     if (type == TYPE_L)
  2624. #ifdef NBBY 
  2625.         printf(" %d", NBBY);
  2626. #else
  2627.         printf(" %d", bytesize);/* need definition! */
  2628. #endif
  2629.     printf("; STRUcture: %s; transfer MODE: %s\r\n",
  2630.            strunames[stru], modenames[mode]);
  2631.     if (data != -1)
  2632.         printf("     Data connection open\r\n");
  2633.     else if (pdata != -1) {
  2634.         printf("     in Passive mode");
  2635.         sin = &pasv_addr;
  2636.         goto printaddr;
  2637.     } else if (usedefault == 0) {
  2638.         printf("     PORT");
  2639.         sin = &data_dest;
  2640.       printaddr:
  2641.         a = (u_char *) & sin->sin_addr;
  2642.         p = (u_char *) & sin->sin_port;
  2643. #define UC(b) (((int) b) & 0xff)
  2644.         printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]),
  2645.                UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
  2646. #undef UC
  2647.     } else
  2648.         printf("     No data connection\r\n");
  2649.     reply(211, "End of status");
  2650. }
  2651.  
  2652. void
  2653. #ifdef __STDC__
  2654. fatal(char *s)
  2655. #else
  2656. fatal(s)
  2657. char *s;
  2658. #endif
  2659. {
  2660.     reply(451, "Error in server: %s\n", s);
  2661.     reply(221, "Closing connection due to server error.");
  2662.     dologout(0);
  2663.     /* NOTREACHED */
  2664. }
  2665.  
  2666. void
  2667. #if defined (HAVE_VPRINTF)
  2668. /* VARARGS2 */
  2669. #ifdef __STDC__
  2670. reply(int n, char *fmt, ...)
  2671. #else
  2672. reply(n, fmt, va_alist)
  2673.      int n;
  2674.      char * fmt;
  2675.      va_dcl
  2676. #endif
  2677. {
  2678.     VA_LOCAL_DECL
  2679.     
  2680.     VA_START(fmt); 
  2681.  
  2682.     if (autospout != NULL) {
  2683.         char *ptr = autospout;
  2684.  
  2685.         printf("%d-", n);
  2686.         while (*ptr) {
  2687.             if (*ptr == '\n') {
  2688.                 fputs("\r\n", stdout);
  2689.                 if (*(++ptr))
  2690.                     printf("%03d-", n);
  2691.             } else {
  2692.                 putc(*ptr++,stdout);
  2693.             }
  2694.         }
  2695.         if (*(--ptr) != '\n')
  2696.             printf("\r\n");
  2697.         if (autospout_free) {
  2698.             (void) free(autospout);
  2699.             autospout_free = 0;
  2700.         }
  2701.         autospout = 0;
  2702.     }
  2703.     printf("%d ", n);
  2704.     vprintf(fmt, ap);
  2705.     printf("\r\n");
  2706.     (void) fflush(stdout);
  2707.  
  2708.     if (debug) {
  2709.         char buf[BUFSIZ];
  2710.         (void) vsprintf(buf, fmt, ap);
  2711.  
  2712.         syslog(LOG_DEBUG, "<--- %d ", n);
  2713.         syslog(LOG_DEBUG, buf);
  2714.     }
  2715.  
  2716.     VA_END;
  2717. }
  2718.  
  2719. void
  2720. /* VARARGS2 */
  2721. #ifdef __STDC__
  2722. lreply(int n, char *fmt,...)
  2723. #else
  2724. lreply(n, fmt, va_alist)
  2725.      int n;
  2726.      char * fmt;
  2727.      va_dcl
  2728. #endif
  2729. {
  2730.     VA_LOCAL_DECL
  2731.  
  2732.     VA_START(fmt);
  2733.  
  2734.     if (!dolreplies)
  2735.         return;
  2736.     printf("%d-", n);
  2737.     vprintf(fmt, ap);
  2738.     printf("\r\n");
  2739.     (void) fflush(stdout);
  2740.  
  2741.     if (debug) {
  2742.         char buf[BUFSIZ];
  2743.         (void) vsprintf(buf, fmt, ap);
  2744.  
  2745.         syslog(LOG_DEBUG, "<--- %d- ", n);
  2746.         syslog(LOG_DEBUG, buf);
  2747.     }
  2748.  
  2749.     VA_END;
  2750. }
  2751.  
  2752. #else
  2753. /* VARARGS2 */
  2754. void
  2755. reply(int n, char *fmt, int p0, int p1, int p2, int p3, int p4, int p5)
  2756. {
  2757.     if (autospout != NULL) {
  2758.         char *ptr = autospout;
  2759.  
  2760.         printf("%d-", n);
  2761.         while (*ptr) {
  2762.             if (*ptr == '\n') {
  2763.                 printf("\r\n");
  2764.                 if (*(++ptr))
  2765.                     printf("%d-", n);
  2766.             } else {
  2767.                 putc(*ptr++,stdout);
  2768.             }
  2769.         }
  2770.         if (*(--ptr) != '\n')
  2771.             printf("\r\n");
  2772.         if (autospout_free) {
  2773.             (void) free(autospout);
  2774.             autospout_free = 0;
  2775.         }
  2776.         autospout = 0;
  2777.     }
  2778.     printf("%d ", n);
  2779.     printf(fmt, p0, p1, p2, p3, p4, p5);
  2780.     printf("\r\n");
  2781.     (void) fflush(stdout);
  2782.     if (debug) {
  2783.         syslog(LOG_DEBUG, "<--- %d ", n);
  2784.         syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5);
  2785.     }
  2786. }
  2787.  
  2788. void
  2789. /* VARARGS2 */
  2790. void
  2791. lreply(int n, char *fmt, int p0, int p1, int p2, int p3, int p4, int p5)
  2792. {
  2793.     if (!dolreplies)
  2794.         return;
  2795.     printf("%d-", n);
  2796.     printf(fmt, p0, p1, p2, p3, p4, p5);
  2797.     printf("\r\n");
  2798.     (void) fflush(stdout);
  2799.     if (debug) {
  2800.         syslog(LOG_DEBUG, "<--- %d- ", n);
  2801.         syslog(LOG_DEBUG, fmt, p0, p1, p2, p3, p4, p5);
  2802.     }
  2803. }
  2804. #endif
  2805.  
  2806. void
  2807. #ifdef __STDC__
  2808. ack(char *s)
  2809. #else
  2810. ack(s)
  2811. char *s;
  2812. #endif
  2813. {
  2814.     reply(250, "%s command successful.", s);
  2815. }
  2816.  
  2817. void
  2818. #ifdef __STDC__
  2819. nack(char *s)
  2820. #else
  2821. nack(s)
  2822. char *s;
  2823. #endif
  2824. {
  2825.     reply(502, "%s command not implemented.", s);
  2826. }
  2827.  
  2828. void
  2829. #ifdef __STDC__
  2830. yyerror(char *s)
  2831. #else
  2832. yyerror(s)
  2833. char *s;
  2834. #endif
  2835. {
  2836.     char *cp;
  2837.     if (s == NULL || yyerrorcalled != 0) return;
  2838.     if ((cp = strchr(cbuf, '\n')) != NULL)
  2839.         *cp = '\0';
  2840.     reply(500, "'%s': command not understood.", cbuf);
  2841.     yyerrorcalled = 1;
  2842.     return;
  2843. }
  2844.  
  2845. void
  2846. #ifdef __STDC__
  2847. delete(char *name)
  2848. #else
  2849. delete(name)
  2850. char *name;
  2851. #endif
  2852. {
  2853.     struct stat st;
  2854.  
  2855.     /*
  2856.      * delete permission?
  2857.      */
  2858.  
  2859.     if ( (del_check(name)) == 0 )
  2860.         return;
  2861.  
  2862.     if (lstat(name, &st) < 0) {
  2863.         perror_reply(550, name);
  2864.         return;
  2865.     }
  2866.     if ((st.st_mode & S_IFMT) == S_IFDIR) {
  2867.         uid_t uid;
  2868.         gid_t gid;
  2869.         int valid;
  2870.  
  2871.         /*
  2872.          * check the directory, can we rmdir here?
  2873.          */
  2874.         if ( (dir_check(name, &uid, &gid, &valid)) <= 0 )
  2875.             return;
  2876.  
  2877.         if (rmdir(name) < 0) {
  2878.             perror_reply(550, name);
  2879.             return;
  2880.         }
  2881.         goto done;
  2882.     }
  2883.     if (unlink(name) < 0) {
  2884.         perror_reply(550, name);
  2885.         return;
  2886.     }
  2887.   done:
  2888.     {
  2889.         char path[MAXPATHLEN];
  2890.  
  2891.         realpath(name, path);
  2892.  
  2893.         if (anonymous) {
  2894.             syslog(LOG_NOTICE, "%s of %s [%s] deleted %s", guestpw, remotehost,
  2895.                    remoteaddr, path);
  2896.         } else {
  2897.             syslog(LOG_NOTICE, "%s of %s [%s] deleted %s", pw->pw_name,
  2898.                    remotehost, remoteaddr, path);
  2899.         }
  2900.     }
  2901.  
  2902.     ack("DELE");
  2903. }
  2904.  
  2905. void
  2906. #ifdef __STDC__
  2907. cwd(char *path)
  2908. #else
  2909. cwd(path)
  2910. char *path;
  2911. #endif
  2912. {
  2913.     struct aclmember *entry = NULL;
  2914.     char cdpath[MAXPATHLEN + 1];
  2915.  
  2916.     if (chdir(path) < 0) {
  2917.         /* alias checking */
  2918.         while (getaclentry("alias", &entry) && ARG0 && ARG1 != NULL) {
  2919.             if (!strcasecmp(ARG0, path)) {
  2920.                 if (chdir(ARG1) < 0)
  2921.                     perror_reply(550, path);
  2922.                 else {
  2923.                     show_message(250, C_WD);
  2924.                     show_readme(250, C_WD);
  2925.                     ack("CWD");
  2926.                 }
  2927.                 return;
  2928.             }
  2929.         }
  2930.     /* check for "cdpath" directories. */
  2931.     entry = (struct aclmember *) NULL;
  2932.         while (getaclentry("cdpath", &entry) && ARG0 != NULL) {
  2933.         strcpy(cdpath,ARG0);
  2934.         strcat(cdpath,"/");
  2935.         strcat(cdpath,path);
  2936.             if (chdir(cdpath) >= 0) {
  2937.                 show_message(250, C_WD);
  2938.                 show_readme(250, C_WD);
  2939.                 ack("CWD");
  2940.                 return;
  2941.             }
  2942.         }
  2943.         perror_reply(550,path);
  2944.     } else {
  2945.         show_message(250, C_WD);
  2946.         show_readme(250, C_WD);
  2947.         ack("CWD");
  2948.     }
  2949. }
  2950.  
  2951. void
  2952. #ifdef __STDC__
  2953. makedir(char *name)
  2954. #else
  2955. makedir(name)
  2956. char *name;
  2957. #endif
  2958. {
  2959.     uid_t uid;
  2960.     gid_t gid;
  2961.     int   valid;
  2962.  
  2963.     /*
  2964.      * check the directory, can we mkdir here?
  2965.      */
  2966.     if ( (dir_check(name, &uid, &gid, &valid)) <= 0 )
  2967.         return;
  2968.  
  2969.     /*
  2970.      * check the filename, is it legal?
  2971.      */
  2972.     if ( (fn_check(name)) <= 0 )
  2973.         return;
  2974.  
  2975.     if (mkdir(name, 0777) < 0) {
  2976.         if (errno == EEXIST)
  2977.             perror_reply(553, name);
  2978.         else
  2979.             perror_reply(550, name);
  2980.     return;
  2981.     }
  2982.     reply(257, "MKD command successful.");
  2983. }
  2984.  
  2985. void
  2986. #ifdef __STDC__
  2987. removedir(char *name)
  2988. #else
  2989. removedir(name)
  2990. char *name;
  2991. #endif
  2992. {
  2993.     uid_t uid;
  2994.     gid_t gid;
  2995.     int valid;
  2996.  
  2997.     /*
  2998.      * check the directory, can we rmdir here?
  2999.      */
  3000.     if ( (dir_check(name, &uid, &gid, &valid)) <= 0 )
  3001.         return;
  3002.  
  3003.     /*
  3004.      * delete permission?
  3005.      */
  3006.  
  3007.     if ( (del_check(name)) == 0 )
  3008.         return;
  3009.  
  3010.     if (rmdir(name) < 0) {
  3011.         if (errno == EBUSY)
  3012.             perror_reply(450, name);
  3013.         else
  3014.             perror_reply(550, name);
  3015.     }
  3016.     else
  3017.         ack("RMD");
  3018. }
  3019.  
  3020. void
  3021. #ifdef __STDC__
  3022. pwd(void)
  3023. #else
  3024. pwd()
  3025. #endif
  3026. {
  3027.     char path[MAXPATHLEN + 1];
  3028. #ifdef HAVE_GETCWD
  3029.     extern char *getcwd();
  3030. #else
  3031. #ifdef __STDC__
  3032.     extern char *getwd(char *);
  3033. #else
  3034.     extern char *getwd();
  3035. #endif
  3036. #endif
  3037.  
  3038. #ifdef HAVE_GETCWD
  3039.     if (getcwd(path,MAXPATHLEN) == (char *) NULL)
  3040. #else
  3041.     if (getwd(path) == (char *) NULL)
  3042. #endif
  3043. /* Dink!  If you couldn't get the path and the buffer is now likely to
  3044.    be undefined, why are you trying to PRINT it?!  _H*
  3045.         reply(550, "%s.", path); */
  3046.     {
  3047.     realpath (".", path);    /* realpath_on_steroids can deal */
  3048.     }
  3049.     reply(257, "\"%s\" is current directory.", path);
  3050. }
  3051.  
  3052. char *
  3053. #ifdef __STDC__
  3054. renamefrom(char *name)
  3055. #else
  3056. renamefrom(name)
  3057. char *name;
  3058. #endif
  3059. {
  3060.     struct stat st;
  3061.     struct aclmember *entry = NULL;    /* Added: fixes a bug.  _H*/
  3062.  
  3063.     if (lstat(name, &st) < 0) {
  3064.         perror_reply(550, name);
  3065.         return ((char *) 0);
  3066.     }
  3067.  
  3068.     /* if rename permission denied and file exists... then deny the user
  3069.      * permission to rename the file. 
  3070.      */
  3071.     while (getaclentry("rename", &entry) && ARG0 && ARG1 != NULL) {
  3072.         if (type_match(ARG1))
  3073.             if (strcmp(ARG0, "yes")) {
  3074.                 reply(553, "%s: Permission denied. (rename)", name);
  3075.                 return ((char *) 0);
  3076.             }
  3077.     }
  3078.  
  3079.     reply(350, "File exists, ready for destination name");
  3080.     return (name);
  3081. }
  3082.  
  3083. void
  3084. #ifdef __STDC__
  3085. renamecmd(char *from, char *to)
  3086. #else
  3087. renamecmd(from,to)
  3088. char *from;
  3089. char *to;
  3090. #endif
  3091. {
  3092.     struct stat st;
  3093.  
  3094.     /*
  3095.      * check the filename, is it legal?
  3096.      */
  3097.     if ( (fn_check(to)) == 0 )
  3098.         return;
  3099.  
  3100. #ifdef PARANOID
  3101. /* Almost forgot about this.  Don't allow renaming TO existing files --
  3102.    otherwise someone can rename "trivial" to "warez", and "warez" is gone!
  3103.    XXX: This part really should do the same "overwrite" check as store(). */
  3104.     if (!stat(to, &st)) {
  3105.       reply (550, "%s: Permission denied. (rename)", to);
  3106.       return;
  3107.     }
  3108. #endif
  3109.  
  3110.     if (rename(from, to) < 0)
  3111.         perror_reply(550, "rename");
  3112.     else
  3113.         ack("RNTO");
  3114. }
  3115.  
  3116. void
  3117. #ifdef __STDC__
  3118. dolog(struct sockaddr_in *sin)
  3119. #else
  3120. dolog(sin)
  3121. struct sockaddr_in *sin;
  3122. #endif
  3123. {
  3124.     struct hostent *hp;
  3125.     char *blah;
  3126.  
  3127. #ifdef    DNS_TRYAGAIN
  3128.     int num_dns_tries = 0;
  3129.     /*
  3130.      * 27-Apr-93    EHK/BM
  3131.      * far away connections might take some time to get their IP address
  3132.      * resolved. That's why we try again -- maybe our DNS cache has the
  3133.      * PTR-RR now. This code is sloppy. Far better is to check what the
  3134.      * resolver returned so that in case of error, there's no need to
  3135.      * try again.
  3136.      */
  3137. dns_again:
  3138.      hp = gethostbyaddr((char *) &sin->sin_addr,
  3139.                                 sizeof (struct in_addr), AF_INET);
  3140.  
  3141.      if ( !hp && ++num_dns_tries <= 1 ) {
  3142.         sleep(3);
  3143.         goto dns_again;         /* try DNS lookup once more     */
  3144.      }
  3145. #else
  3146.     hp = gethostbyaddr((char *)&sin->sin_addr, sizeof(struct in_addr), AF_INET);
  3147. #endif
  3148.  
  3149.     blah = inet_ntoa(sin->sin_addr);
  3150.  
  3151.     (void) strncpy(remoteaddr, blah, sizeof(remoteaddr));
  3152.  
  3153.     if (!strcmp(remoteaddr, "0.0.0.0")) {
  3154.         nameserved = 1;
  3155.         strncpy(remotehost, "localhost", sizeof(remotehost));
  3156.     } else {
  3157.         if (hp) {
  3158.             nameserved = 1;
  3159.             (void) strncpy(remotehost, hp->h_name, sizeof(remotehost));
  3160.         } else {
  3161.             nameserved = 0;
  3162.             (void) strncpy(remotehost, remoteaddr, sizeof(remotehost));
  3163.         }
  3164.     }
  3165.  
  3166.     sprintf(proctitle, "%s: connected", remotehost);
  3167.     setproctitle(proctitle);
  3168.  
  3169. #if 0    /* this is redundant unless the caller doesn't do *anything*, and
  3170.        tcpd will pick it up and deal with it better anyways. _H*/
  3171.     if (logging)
  3172.         syslog(LOG_INFO, "connection from %s [%s]", remotehost,
  3173.                remoteaddr);
  3174. #endif
  3175. }
  3176.  
  3177. /* Record logout in wtmp file and exit with supplied status. */
  3178.  
  3179. void
  3180. #ifdef __STDC__
  3181. dologout(int status)
  3182. #else
  3183. dologout(status)
  3184. int status;
  3185. #endif
  3186. {
  3187.      /*
  3188.       * Prevent reception of SIGURG from resulting in a resumption
  3189.       * back to the main program loop.
  3190.       */
  3191.      transflag = 0;
  3192.  
  3193.     if (logged_in) {
  3194.         delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  3195.         (void) seteuid((uid_t) 0);
  3196.         logwtmp(ttyline, "", "");
  3197.     }
  3198.     if (logging)
  3199.     syslog(LOG_INFO, "FTP session closed");
  3200.     if (xferlog)
  3201.         close(xferlog);
  3202.     acl_remove();
  3203.     close (data);        /* H* fix: clean up a little better */
  3204.     close (pdata);
  3205.     /* beware of flushing buffers after a SIGPIPE */
  3206.     _exit(status);
  3207. }
  3208.  
  3209. SIGNAL_TYPE
  3210. #ifdef __STDC__
  3211. myoob(int sig)
  3212. #else
  3213. myoob(sig)
  3214. int sig;
  3215. #endif
  3216. {
  3217.     char *cp;
  3218.  
  3219.     /* only process if transfer occurring */
  3220.     if (!transflag)
  3221.         return;
  3222.     cp = tmpline;
  3223.     if (getline(cp, 7, stdin) == NULL) {
  3224.         reply(221, "You could at least say goodbye.");
  3225.         dologout(0);
  3226.     }
  3227.     upper(cp);
  3228.     if (strcmp(cp, "ABOR\r\n") == 0) {
  3229.         tmpline[0] = '\0';
  3230.         reply(426, "Transfer aborted. Data connection closed.");
  3231.         reply(226, "Abort successful");
  3232.         (void) signal(SIGURG, myoob);
  3233.         longjmp(urgcatch, 1);
  3234.     }
  3235.     if (strcmp(cp, "STAT\r\n") == 0) {
  3236.         if (file_size != (off_t) - 1)
  3237.             reply(213, "Status: %lu of %lu bytes transferred",
  3238.                   byte_count, file_size);
  3239.         else
  3240.             reply(213, "Status: %lu bytes transferred", byte_count);
  3241.     }
  3242. }
  3243.  
  3244. /* Note: a response of 425 is not mentioned as a possible response to the
  3245.  * PASV command in RFC959. However, it has been blessed as a legitimate
  3246.  * response by Jon Postel in a telephone conversation with Rick Adams on 25
  3247.  * Jan 89. */
  3248.  
  3249. void
  3250. #ifdef __STDC__
  3251. passive(void)
  3252. #else
  3253. passive()
  3254. #endif
  3255. {
  3256.     int len;
  3257.     register char *p,
  3258.      *a;
  3259.  
  3260. /* H* fix: if we already *have* a passive socket, close it first.  Prevents
  3261.    a whole variety of entertaining clogging attacks. */
  3262.     if (pdata > 0)
  3263.     close (pdata);
  3264.  
  3265.     pdata = socket(AF_INET, SOCK_STREAM, 0);
  3266.     if (pdata < 0) {
  3267.         perror_reply(425, "Can't open passive connection");
  3268.         return;
  3269.     }
  3270.     pasv_addr = ctrl_addr;
  3271.     pasv_addr.sin_port = 0;
  3272.     delay_signaling(); /* we can't allow any signals while euid==0: kinch */
  3273.     (void) seteuid((uid_t) 0);        /* XXX: not needed if > 1024 */
  3274.     if (bind(pdata, (struct sockaddr *) &pasv_addr, sizeof(pasv_addr)) < 0) {
  3275.         (void) seteuid((uid_t) pw->pw_uid);
  3276.         enable_signaling(); /* we can allow signals once again: kinch */
  3277.         goto pasv_error;
  3278.     }
  3279.     (void) seteuid((uid_t) pw->pw_uid);
  3280.     enable_signaling(); /* we can allow signals once again: kinch */
  3281.     len = sizeof(pasv_addr);
  3282.     if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
  3283.         goto pasv_error;
  3284.     if (listen(pdata, 1) < 0)
  3285.         goto pasv_error;
  3286.     a = (char *) &pasv_addr.sin_addr;
  3287.     p = (char *) &pasv_addr.sin_port;
  3288.  
  3289. #define UC(b) (((int) b) & 0xff)
  3290.  
  3291.     reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
  3292.           UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
  3293.     return;
  3294.  
  3295.   pasv_error:
  3296.     (void) close(pdata);
  3297.     pdata = -1;
  3298.     perror_reply(425, "Can't open passive connection");
  3299.     return;
  3300. }
  3301.  
  3302. /* Generate unique name for file with basename "local". The file named
  3303.  * "local" is already known to exist. Generates failure reply on error. */
  3304. char *
  3305. #ifdef __STDC__
  3306. gunique(char *local)
  3307. #else
  3308. gunique(local)
  3309. char *local;
  3310. #endif
  3311. {
  3312.     static char new[MAXPATHLEN];
  3313.     struct stat st;
  3314.     char *cp = strrchr(local, '/');
  3315.     int count = 0;
  3316.  
  3317.     if (cp)
  3318.         *cp = '\0';
  3319.     if (stat(cp ? local : ".", &st) < 0) {
  3320.         perror_reply(553, cp ? local : ".");
  3321.         return ((char *) 0);
  3322.     }
  3323.     if (cp)
  3324.         *cp = '/';
  3325.     (void) strcpy(new, local);
  3326.     cp = new + strlen(new);
  3327.     *cp++ = '.';
  3328.     for (count = 1; count < 100; count++) {
  3329.         (void) sprintf(cp, "%d", count);
  3330.         if (stat(new, &st) < 0)
  3331.             return (new);
  3332.     }
  3333.     reply(452, "Unique file name cannot be created.");
  3334.     return ((char *) 0);
  3335. }
  3336.  
  3337. /* Format and send reply containing system error number. */
  3338.  
  3339. void
  3340. #ifdef __STDC__
  3341. perror_reply(int code, char *string)
  3342. #else
  3343. perror_reply(code,string)
  3344. int code;
  3345. char *string;
  3346. #endif
  3347. {
  3348.     reply(code, "%s: %s.", string, strerror(errno));
  3349. }
  3350.  
  3351. static char *onefile[] =
  3352. {"", 0};
  3353.  
  3354. void
  3355. #ifdef __STDC__
  3356. send_file_list(char *whichfiles)
  3357. #else
  3358. send_file_list(whichfiles)
  3359. char *whichfiles;
  3360. #endif
  3361. {
  3362.     struct stat st;
  3363.     DIR *dirp = NULL;
  3364.  
  3365. #ifdef HAVE_DIRENT
  3366.     struct dirent *dir;
  3367. #else
  3368.     struct direct *dir;
  3369. #endif
  3370.  
  3371.     FILE *dout = NULL;
  3372.     register char **dirlist,
  3373.      *dirname;
  3374.     int simple = 0;
  3375. #ifdef __STDC__
  3376.     char *strpbrk(const char *, const char *);
  3377. #else
  3378.     char *strpbrk();
  3379. #endif
  3380.     if (strpbrk(whichfiles, "~{[*?") != NULL) {
  3381. #ifdef __STDC__
  3382.         extern char **ftpglob(register char *v),
  3383. #else
  3384.         extern char **ftpglob(),
  3385. #endif
  3386.          *globerr;
  3387.  
  3388.         globerr = NULL;
  3389.         dirlist = ftpglob(whichfiles);
  3390.         if (globerr != NULL) {
  3391.             reply(550, globerr);
  3392.             return;
  3393.         } else if (dirlist == NULL) {
  3394.             errno = ENOENT;
  3395.             perror_reply(550, whichfiles);
  3396.             return;
  3397.         }
  3398.     } else {
  3399.         onefile[0] = whichfiles;
  3400.         dirlist = onefile;
  3401.         simple = 1;
  3402.     }
  3403.  
  3404.     if (setjmp(urgcatch)) {
  3405.         transflag = 0;
  3406.         return;
  3407.     }
  3408.     while ((dirname = *dirlist++) != NULL) {
  3409.         if (stat(dirname, &st) < 0) {
  3410.             /* If user typed "ls -l", etc, and the client used NLST, do what
  3411.              * the user meant. */
  3412.             if (dirname[0] == '-' && *dirlist == NULL && transflag == 0) {
  3413.                 retrieve("/bin/ls %s", dirname);
  3414.                 return;
  3415.             }
  3416.             perror_reply(550, whichfiles);
  3417.             if (dout != NULL) {
  3418.                 (void) fclose(dout);
  3419.                 transflag = 0;
  3420.                 data = -1;
  3421.                 pdata = -1;
  3422.             }
  3423.             return;
  3424.         }
  3425.         if ((st.st_mode & S_IFMT) == S_IFREG) {
  3426.             if (dout == NULL) {
  3427.                 dout = dataconn("file list", (off_t) - 1, "w");
  3428.                 if (dout == NULL)
  3429.                     return;
  3430.                 transflag++;
  3431.             }
  3432.             fprintf(dout, "%s%s\n", dirname,
  3433.                     type == TYPE_A ? "\r" : "");
  3434.             byte_count += strlen(dirname) + 1;
  3435.             continue;
  3436.         } else if ((st.st_mode & S_IFMT) != S_IFDIR)
  3437.             continue;
  3438.  
  3439.         if ((dirp = opendir(dirname)) == NULL)
  3440.             continue;
  3441.  
  3442.         while ((dir = readdir(dirp)) != NULL) {
  3443.             char nbuf[MAXPATHLEN];
  3444.  
  3445. #ifndef HAVE_DIRENT    /* does not have d_namlen */
  3446.             if (dir->d_name[0] == '.' && dir->d_namlen == 1)
  3447. #else
  3448.             if (dir->d_name[0] == '.' && (strlen(dir->d_name) == 1))
  3449. #endif
  3450.                 continue;
  3451. #ifndef HAVE_DIRENT    /* does not have d_namlen */
  3452.             if (dir->d_namlen == 2 && dir->d_name[0] == '.' &&
  3453.                 dir->d_name[1] == '.')
  3454. #else
  3455.             if ((strlen(dir->d_name) == 2) && dir->d_name[0] == '.' &&
  3456.                 dir->d_name[1] == '.')
  3457. #endif
  3458.                 continue;
  3459.  
  3460.             sprintf(nbuf, "%s/%s", dirname, dir->d_name);
  3461.  
  3462.             /* We have to do a stat to insure it's not a directory or special
  3463.              * file. */
  3464.             if (simple || (stat(nbuf, &st) == 0 &&
  3465.                            (st.st_mode & S_IFMT) == S_IFREG)) {
  3466.                 if (dout == NULL) {
  3467.                     dout = dataconn("file list", (off_t) - 1,
  3468.                                     "w");
  3469.                     if (dout == NULL) {
  3470.                         (void) closedir(dirp);
  3471.                         return;
  3472.                     }
  3473.                     transflag++;
  3474.                 }
  3475.                 if (nbuf[0] == '.' && nbuf[1] == '/')
  3476.                     fprintf(dout, "%s%s\n", &nbuf[2],
  3477.                             type == TYPE_A ? "\r" : "");
  3478.                 else
  3479.                     fprintf(dout, "%s%s\n", nbuf,
  3480.                             type == TYPE_A ? "\r" : "");
  3481.                 byte_count += strlen(nbuf) + 1;
  3482.             }
  3483.         }
  3484.         (void) closedir(dirp);
  3485.     }
  3486.  
  3487.     if (dout == NULL)
  3488.         reply(550, "No files found.");
  3489.     else if (ferror(dout) != 0)
  3490.         perror_reply(550, "Data connection");
  3491.     else
  3492.         reply(226, "Transfer complete.");
  3493.  
  3494.     transflag = 0;
  3495.     if (dout != NULL)
  3496.         (void) fclose(dout);
  3497.     data = -1;
  3498.     pdata = -1;
  3499. }
  3500.  
  3501. /*
  3502. **  SETPROCTITLE -- set process title for ps (from sendmail 8)
  3503. **
  3504. **    Parameters:
  3505. **        fmt -- a printf style format string.
  3506. **        a, b, c -- possible parameters to fmt.
  3507. **
  3508. **    Returns:
  3509. **        none.
  3510. **
  3511. **    Side Effects:
  3512. **        Clobbers argv of our main procedure so ps(1) will
  3513. **        display the title.
  3514. */
  3515.  
  3516. #ifndef SPT_TYPE
  3517. # define SPT_TYPE    SPT_REUSEARGV  /* default type */
  3518. #endif
  3519.  
  3520. #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
  3521.  
  3522. #if SPT_TYPE == SPT_PSTAT
  3523. #include <sys/pstat.h>
  3524. #endif
  3525. #if SPT_TYPE == SPT_PSSTRINGS
  3526. #include <machine/vmparam.h>
  3527. #include <sys/exec.h>
  3528. #ifndef PS_STRINGS    /* hmmmm....  apparently not available after all */
  3529. #undef SPT_TYPE
  3530. #define SPT_TYPE    SPT_REUSEARGV
  3531. #else
  3532. #ifndef NKPDE            /* FreeBSD 2.0 */
  3533. #define NKPDE 63
  3534. typedef unsigned int    *pt_entry_t;
  3535. #endif
  3536. #endif
  3537. #endif
  3538.  
  3539. #if SPT_TYPE == SPT_PSSTRINGS
  3540. #define SETPROC_STATIC    static
  3541. #else
  3542. #define SETPROC_STATIC
  3543. #endif
  3544.  
  3545. #if SPT_TYPE == SPT_SYSMIPS
  3546. #include <sys/sysmips.h>
  3547. #include <sys/sysnews.h>
  3548. #endif
  3549.  
  3550. #if SPT_TYPE == SPT_SCO
  3551. #include <sys/immu.h>
  3552. #include <sys/dir.h>
  3553. #include <sys/user.h>
  3554. #include <sys/fs/s5param.h>
  3555. #if PSARGSZ > 2048
  3556. #define SPT_BUFSIZE    PSARGSZ
  3557. #endif
  3558. #endif
  3559.  
  3560. #ifndef SPT_PADCHAR
  3561. #define SPT_PADCHAR    ' '
  3562. #endif
  3563.  
  3564. #ifndef SPT_BUFSIZE
  3565. #define SPT_BUFSIZE    2048
  3566. #endif
  3567.  
  3568. #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
  3569.  
  3570. #if SPT_TYPE != SPT_BUILTIN
  3571.  
  3572. /*VARARGS1*/
  3573. void
  3574. #ifdef __STDC__
  3575. setproctitle(const char *fmt, ...)
  3576. #else
  3577. setproctitle(fmt, va_alist)
  3578.     const char *fmt;
  3579.     va_dcl
  3580. #endif
  3581. {
  3582. #if SPT_TYPE != SPT_NONE
  3583.     register char *p;
  3584.     register int i;
  3585.     SETPROC_STATIC char buf[SPT_BUFSIZE];
  3586.     VA_LOCAL_DECL
  3587. #if SPT_TYPE == SPT_PSTAT
  3588.     union pstun pst;
  3589. #endif
  3590. #if SPT_TYPE == SPT_SCO
  3591.     off_t seek_off;
  3592.     static int kmem = -1;
  3593.     static int kmempid = -1;
  3594. #endif
  3595. #if SPT_TYPE == SPT_REUSEARGV
  3596.     extern char **Argv;
  3597.     extern char *LastArgv;
  3598. #endif
  3599.  
  3600.     p = buf;
  3601.  
  3602.     /* print ftpd: heading for grep */
  3603.     (void) strcpy(p, "ftpd: ");
  3604.     p += strlen(p);
  3605.  
  3606.     /* print the argument string */
  3607.     VA_START(fmt);
  3608.     (void) vsnprintf(p, sizeof buf - (p - buf), fmt, ap);
  3609.     VA_END;
  3610.  
  3611.     i = strlen(buf);
  3612.  
  3613. #if SPT_TYPE == SPT_PSTAT
  3614.     pst.pst_command = buf;
  3615.     pstat(PSTAT_SETCMD, pst, i, 0, 0);
  3616. #endif
  3617. #if SPT_TYPE == SPT_PSSTRINGS
  3618.     if (PS_STRINGS->ps_argvstr) {
  3619.                 static char *ps_argv[2];
  3620.                 ps_argv[0] = buf;
  3621.                 ps_argv[1] = NULL;
  3622.                 PS_STRINGS->ps_nargvstr = 1;
  3623.                 PS_STRINGS->ps_argvstr = ps_argv;
  3624.         } else {
  3625.                 PS_STRINGS->ps_nargvstr = 1;
  3626.                 PS_STRINGS->ps_argvstr = buf;
  3627.         }
  3628. #endif
  3629. #if SPT_TYPE == SPT_SYSMIPS
  3630.     sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
  3631. #endif
  3632. #if SPT_TYPE == SPT_SCO
  3633.     if (kmem < 0 || kmempid != getpid())
  3634.     {
  3635.         if (kmem >= 0)
  3636.             close(kmem);
  3637.         kmem = open(_PATH_KMEM, O_RDWR, 0);
  3638.         if (kmem < 0)
  3639.             return;
  3640.         (void) fcntl(kmem, F_SETFD, 1);
  3641.         kmempid = getpid();
  3642.     }
  3643.     buf[PSARGSZ - 1] = '\0';
  3644.  
  3645.     /* Remove trailing carriage returns and new lines */
  3646.     while (buf[i - 1] == '\r' || buf[i - 1] == '\n')
  3647.         buf[--i] = '\0';
  3648.  
  3649.     seek_off = UVUBLK + (off_t) &((struct user *)0)->u_psargs;
  3650.     if (lseek(kmem, seek_off, SEEK_SET) == seek_off)
  3651.         (void) write(kmem, buf, PSARGSZ);
  3652. #endif
  3653. #if SPT_TYPE == SPT_REUSEARGV
  3654. /* This may fix problems in AIX, I don't really know since I don't have AIX */
  3655. /* Maybe someone will check it out and mail me, or someone will get me      */
  3656. /* ready access to AIX */
  3657. #ifndef AIX
  3658.     if (i > LastArgv - Argv[0] - 2)
  3659.     {
  3660.         i = LastArgv - Argv[0] - 2;
  3661.         buf[i] = '\0';
  3662.     }
  3663. #endif
  3664.     (void) strcpy(Argv[0], buf);
  3665. #ifndef AIX
  3666.     p = &Argv[0][i];
  3667.     while (p < LastArgv)
  3668.         *p++ = SPT_PADCHAR;
  3669.     Argv[1] = NULL;
  3670. #endif
  3671. #endif
  3672. #endif /* SPT_TYPE != SPT_NONE */
  3673. }
  3674.  
  3675. #endif /* SPT_TYPE != SPT_BUILTIN */
  3676.  
  3677. #ifdef KERBEROS
  3678. /* thanks to gshapiro@wpi.wpi.edu for the following kerberosities */
  3679.  
  3680. void
  3681. init_krb()
  3682. {
  3683.     char hostname[100];
  3684.  
  3685. #ifdef HAVE_SYSINFO
  3686.     if (sysinfo(SI_HOSTNAME, hostname, sizeof (hostname)) < 0) {
  3687.         perror("sysinfo");
  3688. #else
  3689.     if (gethostname(hostname, sizeof(hostname)) < 0) {
  3690.         perror("gethostname");
  3691. #endif
  3692.         exit(1);
  3693.     }
  3694.     if (strchr(hostname, '.'))
  3695.         *(strchr(hostname, '.')) = 0;
  3696.  
  3697.     sprintf(krb_ticket_name, "/var/dss/kerberos/tkt/tkt.%d", getpid());
  3698.     krb_set_tkt_string(krb_ticket_name);
  3699.  
  3700.     config_auth();
  3701.  
  3702.     if (krb_svc_init("hesiod", hostname, (char *) NULL, 0, (char *) NULL,
  3703.                      (char *) NULL) != KSUCCESS) {
  3704.         fprintf(stderr, "Couldn't initialize Kerberos\n");
  3705.         exit(1);
  3706.     }
  3707. }
  3708.  
  3709. void
  3710. end_krb()
  3711. {
  3712.     unlink(krb_ticket_name);
  3713. }
  3714. #endif /* KERBEROS */
  3715.  
  3716. #ifdef ULTRIX_AUTH
  3717. static int
  3718. ultrix_check_pass(char *passwd, char *xpasswd)
  3719. {
  3720.     struct svcinfo *svp;
  3721.     int auth_status;
  3722.  
  3723.     if ((svp = getsvc()) == (struct svcinfo *) NULL) {
  3724.         syslog(LOG_WARNING, "getsvc() failed in ultrix_check_pass");
  3725.         return -1;
  3726.     }
  3727.     if (pw == (struct passwd *) NULL) {
  3728.         return -1;
  3729.     }
  3730.     if (((svp->svcauth.seclevel == SEC_UPGRADE) &&
  3731.         (!strcmp(pw->pw_passwd, "*")))
  3732.         || (svp->svcauth.seclevel == SEC_ENHANCED)) {
  3733.         if ((auth_status=authenticate_user(pw, passwd, "/dev/ttypXX")) >= 0) {
  3734.             /* Indicate successful validation */
  3735.             return auth_status;
  3736.         }
  3737.         if (auth_status < 0 && errno == EPERM) {
  3738.             /* Log some information about the failed login attempt. */
  3739.             switch(abs(auth_status)) {
  3740.             case A_EBADPASS:
  3741.                 break;
  3742.             case A_ESOFTEXP:
  3743.                 syslog(LOG_NOTICE, "password will expire soon for user %s",
  3744.                     pw->pw_name);
  3745.                 break;
  3746.             case A_EHARDEXP:
  3747.                 syslog(LOG_NOTICE, "password has expired for user %s",
  3748.                     pw->pw_name);
  3749.                 break;
  3750.             case A_ENOLOGIN:
  3751.                 syslog(LOG_NOTICE, "user %s attempted login to disabled acct",
  3752.                     pw->pw_name);
  3753.                 break;
  3754.             }
  3755.         }
  3756.     }
  3757.     else {
  3758.         if ((*pw->pw_passwd != '\0') && (!strcmp(xpasswd, pw->pw_passwd))) {
  3759.             /* passwd in /etc/passwd isn't empty && encrypted passwd matches */
  3760.             return 0;
  3761.         }
  3762.     }
  3763.     return -1;
  3764. }
  3765. #endif /* ULTRIX_AUTH */
  3766.