]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - libexec/ftpd/ftpd.c
This commit was generated by cvs2svn to compensate for changes in r99679,
[FreeBSD/FreeBSD.git] / libexec / ftpd / ftpd.c
1 /*
2  * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
3  *      The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #if 0
35 #ifndef lint
36 static char copyright[] =
37 "@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\
38         The Regents of the University of California.  All rights reserved.\n";
39 #endif /* not lint */
40 #endif
41
42 #ifndef lint
43 #if 0
44 static char sccsid[] = "@(#)ftpd.c      8.4 (Berkeley) 4/16/94";
45 #endif
46 static const char rcsid[] =
47   "$FreeBSD$";
48 #endif /* not lint */
49
50 /*
51  * FTP server.
52  */
53 #include <sys/param.h>
54 #include <sys/ioctl.h>
55 #include <sys/mman.h>
56 #include <sys/socket.h>
57 #include <sys/stat.h>
58 #include <sys/time.h>
59 #include <sys/wait.h>
60
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
64 #include <netinet/tcp.h>
65
66 #define FTP_NAMES
67 #include <arpa/ftp.h>
68 #include <arpa/inet.h>
69 #include <arpa/telnet.h>
70
71 #include <ctype.h>
72 #include <dirent.h>
73 #include <err.h>
74 #include <errno.h>
75 #include <fcntl.h>
76 #include <glob.h>
77 #include <limits.h>
78 #include <netdb.h>
79 #include <pwd.h>
80 #include <grp.h>
81 #include <opie.h>
82 #include <signal.h>
83 #include <stdio.h>
84 #include <stdlib.h>
85 #include <string.h>
86 #include <syslog.h>
87 #include <time.h>
88 #include <unistd.h>
89 #include <libutil.h>
90 #ifdef  LOGIN_CAP
91 #include <login_cap.h>
92 #endif
93
94 #ifdef USE_PAM
95 #include <security/pam_appl.h>
96 #endif
97
98 #include "pathnames.h"
99 #include "extern.h"
100
101 #include <stdarg.h>
102
103 static char version[] = "Version 6.00LS";
104 #undef main
105
106 extern  off_t restart_point;
107 extern  char cbuf[];
108
109 union sockunion server_addr;
110 union sockunion ctrl_addr;
111 union sockunion data_source;
112 union sockunion data_dest;
113 union sockunion his_addr;
114 union sockunion pasv_addr;
115
116 int     daemon_mode;
117 int     data;
118 int     logged_in;
119 struct  passwd *pw;
120 int     ftpdebug;
121 int     timeout = 900;    /* timeout after 15 minutes of inactivity */
122 int     maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */
123 int     logging;
124 int     restricted_data_ports = 1;
125 int     paranoid = 1;     /* be extra careful about security */
126 int     anon_only = 0;    /* Only anonymous ftp allowed */
127 int     guest;
128 int     dochroot;
129 int     stats;
130 int     statfd = -1;
131 int     type;
132 int     form;
133 int     stru;                   /* avoid C keyword */
134 int     mode;
135 int     usedefault = 1;         /* for data transfers */
136 int     pdata = -1;             /* for passive mode */
137 int     readonly=0;             /* Server is in readonly mode.  */
138 int     noepsv=0;               /* EPSV command is disabled.    */
139 int     noretr=0;               /* RETR command is disabled.    */
140 int     noguestretr=0;          /* RETR command is disabled for anon users. */
141 int     noguestmkd=0;           /* MKD command is disabled for anon users. */
142
143 static volatile sig_atomic_t recvurg;
144 sig_atomic_t transflag;
145 off_t   file_size;
146 off_t   byte_count;
147 #if !defined(CMASK) || CMASK == 0
148 #undef CMASK
149 #define CMASK 027
150 #endif
151 int     defumask = CMASK;               /* default umask value */
152 char    tmpline[7];
153 char    *hostname;
154 int     epsvall = 0;
155
156 #ifdef VIRTUAL_HOSTING
157 char    *ftpuser;
158
159 static struct ftphost {
160         struct ftphost  *next;
161         struct addrinfo *hostinfo;
162         char            *hostname;
163         char            *anonuser;
164         char            *statfile;
165         char            *welcome;
166         char            *loginmsg;
167 } *thishost, *firsthost;
168
169 #endif
170 char    remotehost[MAXHOSTNAMELEN];
171 char    *ident = NULL;
172
173 static char ttyline[20];
174 char    *tty = ttyline;         /* for klogin */
175
176 #ifdef USE_PAM
177 static int      auth_pam(struct passwd**, const char*);
178 pam_handle_t *pamh = NULL;
179 #endif
180
181 static struct opie opiedata;
182 static char opieprompt[OPIE_CHALLENGE_MAX+1];
183 static int pwok;
184
185 char    *pid_file = NULL;
186
187 /*
188  * Limit number of pathnames that glob can return.
189  * A limit of 0 indicates the number of pathnames is unlimited.
190  */
191 #define MAXGLOBARGS     16384
192 #
193
194 /*
195  * Timeout intervals for retrying connections
196  * to hosts that don't accept PORT cmds.  This
197  * is a kludge, but given the problems with TCP...
198  */
199 #define SWAITMAX        90      /* wait at most 90 seconds */
200 #define SWAITINT        5       /* interval between retries */
201
202 int     swaitmax = SWAITMAX;
203 int     swaitint = SWAITINT;
204
205 #ifdef SETPROCTITLE
206 #ifdef OLD_SETPROCTITLE
207 char    **Argv = NULL;          /* pointer to argument vector */
208 char    *LastArgv = NULL;       /* end of argv */
209 #endif /* OLD_SETPROCTITLE */
210 char    proctitle[LINE_MAX];    /* initial part of title */
211 #endif /* SETPROCTITLE */
212
213 #define LOGCMD(cmd, file) \
214         if (logging > 1) \
215             syslog(LOG_INFO,"%s %s%s", cmd, \
216                 *(file) == '/' ? "" : curdir(), file);
217 #define LOGCMD2(cmd, file1, file2) \
218          if (logging > 1) \
219             syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
220                 *(file1) == '/' ? "" : curdir(), file1, \
221                 *(file2) == '/' ? "" : curdir(), file2);
222 #define LOGBYTES(cmd, file, cnt) \
223         if (logging > 1) { \
224                 if (cnt == (off_t)-1) \
225                     syslog(LOG_INFO,"%s %s%s", cmd, \
226                         *(file) == '/' ? "" : curdir(), file); \
227                 else \
228                     syslog(LOG_INFO, "%s %s%s = %qd bytes", \
229                         cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
230         }
231
232 #ifdef VIRTUAL_HOSTING
233 static void      inithosts(void);
234 static void     selecthost(union sockunion *);
235 #endif
236 static void      ack(char *);
237 static void      sigurg(int);
238 static void      myoob(void);
239 static int       checkuser(char *, char *, int);
240 static FILE     *dataconn(char *, off_t, char *);
241 static void      dolog(struct sockaddr *);
242 static char     *curdir(void);
243 static void      end_login(void);
244 static FILE     *getdatasock(char *);
245 static char     *gunique(char *);
246 static void      lostconn(int);
247 static void      sigquit(int);
248 static int       receive_data(FILE *, FILE *);
249 static int       send_data(FILE *, FILE *, off_t, off_t, int);
250 static struct passwd *
251                  sgetpwnam(char *);
252 static char     *sgetsave(char *);
253 static void      reapchild(int);
254 static void      logxfer(char *, off_t, time_t);
255
256 static char *
257 curdir(void)
258 {
259         static char path[MAXPATHLEN+1+1];       /* path + '/' + '\0' */
260
261         if (getcwd(path, sizeof(path)-2) == NULL)
262                 return ("");
263         if (path[1] != '\0')            /* special case for root dir. */
264                 strcat(path, "/");
265         /* For guest account, skip / since it's chrooted */
266         return (guest ? path+1 : path);
267 }
268
269 int
270 main(int argc, char *argv[], char **envp)
271 {
272         int addrlen, ch, on = 1, tos;
273         char *cp, line[LINE_MAX];
274         FILE *fd;
275         int error;
276         char    *bindname = NULL;
277         int     family = AF_UNSPEC;
278         int     enable_v4 = 0;
279         struct sigaction sa;
280
281         tzset();                /* in case no timezone database in ~ftp */
282         sigemptyset(&sa.sa_mask);
283         sa.sa_flags = SA_RESTART;
284
285 #ifdef OLD_SETPROCTITLE
286         /*
287          *  Save start and extent of argv for setproctitle.
288          */
289         Argv = argv;
290         while (*envp)
291                 envp++;
292         LastArgv = envp[-1] + strlen(envp[-1]);
293 #endif /* OLD_SETPROCTITLE */
294
295
296         while ((ch = getopt(argc, argv, "AdlDESURrt:T:u:vMOoa:p:46")) != -1) {
297                 switch (ch) {
298                 case 'D':
299                         daemon_mode++;
300                         break;
301
302                 case 'd':
303                         ftpdebug++;
304                         break;
305
306                 case 'E':
307                         noepsv = 1;
308                         break;
309
310                 case 'l':
311                         logging++;      /* > 1 == extra logging */
312                         break;
313
314                 case 'r':
315                         readonly = 1;
316                         break;
317
318                 case 'R':
319                         paranoid = 0;
320                         break;
321
322                 case 'S':
323                         stats++;
324                         break;
325
326                 case 'T':
327                         maxtimeout = atoi(optarg);
328                         if (timeout > maxtimeout)
329                                 timeout = maxtimeout;
330                         break;
331
332                 case 't':
333                         timeout = atoi(optarg);
334                         if (maxtimeout < timeout)
335                                 maxtimeout = timeout;
336                         break;
337
338                 case 'U':
339                         restricted_data_ports = 0;
340                         break;
341
342                 case 'a':
343                         bindname = optarg;
344                         break;
345
346                 case 'p':
347                         pid_file = optarg;
348                         break;
349
350                 case 'u':
351                     {
352                         long val = 0;
353
354                         val = strtol(optarg, &optarg, 8);
355                         if (*optarg != '\0' || val < 0)
356                                 warnx("bad value for -u");
357                         else
358                                 defumask = val;
359                         break;
360                     }
361                 case 'A':
362                         anon_only = 1;
363                         break;
364
365                 case 'v':
366                         ftpdebug = 1;
367                         break;
368
369                 case '4':
370                         enable_v4 = 1;
371                         if (family == AF_UNSPEC)
372                                 family = AF_INET;
373                         break;
374
375                 case '6':
376                         family = AF_INET6;
377                         break;
378
379                 case 'M':
380                         noguestmkd = 1;
381                         break;
382
383                 case 'O':
384                         noguestretr = 1;
385                         break;
386
387                 case 'o':
388                         noretr = 1;
389                         break;
390
391                 default:
392                         warnx("unknown flag -%c ignored", optopt);
393                         break;
394                 }
395         }
396
397 #ifdef VIRTUAL_HOSTING
398         inithosts();
399 #endif
400         (void) freopen(_PATH_DEVNULL, "w", stderr);
401
402         /*
403          * LOG_NDELAY sets up the logging connection immediately,
404          * necessary for anonymous ftp's that chroot and can't do it later.
405          */
406         openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
407
408         if (daemon_mode) {
409                 int ctl_sock, fd;
410                 struct addrinfo hints, *res;
411
412                 /*
413                  * Detach from parent.
414                  */
415                 if (daemon(1, 1) < 0) {
416                         syslog(LOG_ERR, "failed to become a daemon");
417                         exit(1);
418                 }
419                 sa.sa_handler = reapchild;
420                 (void)sigaction(SIGCHLD, &sa, NULL);
421                 /* init bind_sa */
422                 memset(&hints, 0, sizeof(hints));
423
424                 hints.ai_family = family == AF_UNSPEC ? AF_INET : family;
425                 hints.ai_socktype = SOCK_STREAM;
426                 hints.ai_protocol = 0;
427                 hints.ai_flags = AI_PASSIVE;
428                 error = getaddrinfo(bindname, "ftp", &hints, &res);
429                 if (error) {
430                         if (family == AF_UNSPEC) {
431                                 hints.ai_family = AF_UNSPEC;
432                                 error = getaddrinfo(bindname, "ftp", &hints,
433                                                     &res);
434                         }
435                 }
436                 if (error) {
437                         syslog(LOG_ERR, "%s", gai_strerror(error));
438                         if (error == EAI_SYSTEM)
439                                 syslog(LOG_ERR, "%s", strerror(errno));
440                         exit(1);
441                 }
442                 if (res->ai_addr == NULL) {
443                         syslog(LOG_ERR, "-a %s: getaddrinfo failed", hostname);
444                         exit(1);
445                 } else
446                         family = res->ai_addr->sa_family;
447                 /*
448                  * Open a socket, bind it to the FTP port, and start
449                  * listening.
450                  */
451                 ctl_sock = socket(family, SOCK_STREAM, 0);
452                 if (ctl_sock < 0) {
453                         syslog(LOG_ERR, "control socket: %m");
454                         exit(1);
455                 }
456                 if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR,
457                     (char *)&on, sizeof(on)) < 0)
458                         syslog(LOG_ERR, "control setsockopt: %m");
459 #ifdef IPV6_BINDV6ONLY
460                 if (family == AF_INET6 && enable_v4 == 0) {
461                         if (setsockopt(ctl_sock, IPPROTO_IPV6, IPV6_BINDV6ONLY,
462                                        (char *)&on, sizeof (on)) < 0)
463                                 syslog(LOG_ERR,
464                                        "control setsockopt(IPV6_BINDV6ONLY): %m");
465                 }
466 #endif /* IPV6_BINDV6ONLY */
467                 memcpy(&server_addr, res->ai_addr, res->ai_addr->sa_len);
468                 if (bind(ctl_sock, (struct sockaddr *)&server_addr,
469                          server_addr.su_len) < 0) {
470                         syslog(LOG_ERR, "control bind: %m");
471                         exit(1);
472                 }
473                 if (listen(ctl_sock, 32) < 0) {
474                         syslog(LOG_ERR, "control listen: %m");
475                         exit(1);
476                 }
477                 /*
478                  * Atomically write process ID
479                  */
480                 if (pid_file)
481                 {
482                         int fd;
483                         char buf[20];
484
485                         fd = open(pid_file, O_CREAT | O_WRONLY | O_TRUNC
486                                 | O_NONBLOCK | O_EXLOCK, 0644);
487                         if (fd < 0) {
488                                 if (errno == EAGAIN)
489                                         errx(1, "%s: file locked", pid_file);
490                                 else
491                                         err(1, "%s", pid_file);
492                         }
493                         snprintf(buf, sizeof(buf),
494                                 "%lu\n", (unsigned long) getpid());
495                         if (write(fd, buf, strlen(buf)) < 0)
496                                 err(1, "%s: write", pid_file);
497                         /* Leave the pid file open and locked */
498                 }
499                 /*
500                  * Loop forever accepting connection requests and forking off
501                  * children to handle them.
502                  */
503                 while (1) {
504                         addrlen = server_addr.su_len;
505                         fd = accept(ctl_sock, (struct sockaddr *)&his_addr, &addrlen);
506                         if (fork() == 0) {
507                                 /* child */
508                                 (void) dup2(fd, 0);
509                                 (void) dup2(fd, 1);
510                                 close(ctl_sock);
511                                 break;
512                         }
513                         close(fd);
514                 }
515         } else {
516                 addrlen = sizeof(his_addr);
517                 if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) {
518                         syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
519                         exit(1);
520                 }
521         }
522
523         sa.sa_handler = SIG_DFL;
524         (void)sigaction(SIGCHLD, &sa, NULL);
525
526         sa.sa_handler = sigurg;
527         sa.sa_flags = 0;                /* don't restart syscalls for SIGURG */
528         (void)sigaction(SIGURG, &sa, NULL);
529
530         sigfillset(&sa.sa_mask);        /* block all signals in handler */
531         sa.sa_flags = SA_RESTART;
532         sa.sa_handler = sigquit;
533         (void)sigaction(SIGHUP, &sa, NULL);
534         (void)sigaction(SIGINT, &sa, NULL);
535         (void)sigaction(SIGQUIT, &sa, NULL);
536         (void)sigaction(SIGTERM, &sa, NULL);
537
538         sa.sa_handler = lostconn;
539         (void)sigaction(SIGPIPE, &sa, NULL);
540
541         addrlen = sizeof(ctrl_addr);
542         if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
543                 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
544                 exit(1);
545         }
546 #ifdef VIRTUAL_HOSTING
547         /* select our identity from virtual host table */
548         selecthost(&ctrl_addr);
549 #endif
550 #ifdef IP_TOS
551         if (ctrl_addr.su_family == AF_INET)
552       {
553         tos = IPTOS_LOWDELAY;
554         if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0)
555                 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
556       }
557 #endif
558         /*
559          * Disable Nagle on the control channel so that we don't have to wait
560          * for peer's ACK before issuing our next reply.
561          */
562         if (setsockopt(0, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
563                 syslog(LOG_WARNING, "control setsockopt TCP_NODELAY: %m");
564
565         data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1);
566
567         /* set this here so klogin can use it... */
568         (void)snprintf(ttyline, sizeof(ttyline), "ftp%d", getpid());
569
570         /* Try to handle urgent data inline */
571 #ifdef SO_OOBINLINE
572         if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0)
573                 syslog(LOG_ERR, "setsockopt: %m");
574 #endif
575
576 #ifdef  F_SETOWN
577         if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1)
578                 syslog(LOG_ERR, "fcntl F_SETOWN: %m");
579 #endif
580         dolog((struct sockaddr *)&his_addr);
581         /*
582          * Set up default state
583          */
584         data = -1;
585         type = TYPE_A;
586         form = FORM_N;
587         stru = STRU_F;
588         mode = MODE_S;
589         tmpline[0] = '\0';
590
591         /* If logins are disabled, print out the message. */
592         if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) {
593                 while (fgets(line, sizeof(line), fd) != NULL) {
594                         if ((cp = strchr(line, '\n')) != NULL)
595                                 *cp = '\0';
596                         lreply(530, "%s", line);
597                 }
598                 (void) fflush(stdout);
599                 (void) fclose(fd);
600                 reply(530, "System not available.");
601                 exit(0);
602         }
603 #ifdef VIRTUAL_HOSTING
604         if ((fd = fopen(thishost->welcome, "r")) != NULL) {
605 #else
606         if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) {
607 #endif
608                 while (fgets(line, sizeof(line), fd) != NULL) {
609                         if ((cp = strchr(line, '\n')) != NULL)
610                                 *cp = '\0';
611                         lreply(220, "%s", line);
612                 }
613                 (void) fflush(stdout);
614                 (void) fclose(fd);
615                 /* reply(220,) must follow */
616         }
617 #ifndef VIRTUAL_HOSTING
618         if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL)
619                 fatalerror("Ran out of memory.");
620         (void) gethostname(hostname, MAXHOSTNAMELEN - 1);
621         hostname[MAXHOSTNAMELEN - 1] = '\0';
622 #endif
623         reply(220, "%s FTP server (%s) ready.", hostname, version);
624         for (;;)
625                 (void) yyparse();
626         /* NOTREACHED */
627 }
628
629 static void
630 lostconn(int signo)
631 {
632
633         if (ftpdebug)
634                 syslog(LOG_DEBUG, "lost connection");
635         dologout(1);
636 }
637
638 static void
639 sigquit(int signo)
640 {
641
642         syslog(LOG_ERR, "got signal %d", signo);
643         dologout(1);
644 }
645
646 #ifdef VIRTUAL_HOSTING
647 /*
648  * read in virtual host tables (if they exist)
649  */
650
651 static void
652 inithosts(void)
653 {
654         FILE *fp;
655         char *cp;
656         struct ftphost *hrp, *lhrp;
657         char line[1024];
658         struct addrinfo hints, *res, *ai;
659
660         /*
661          * Fill in the default host information
662          */
663         if (gethostname(line, sizeof(line)) < 0)
664                 line[0] = '\0';
665         if ((hrp = malloc(sizeof(struct ftphost))) == NULL ||
666             (hrp->hostname = strdup(line)) == NULL)
667                 fatalerror("Ran out of memory.");
668         hrp->hostinfo = NULL;
669
670         memset(&hints, 0, sizeof(hints));
671         hints.ai_flags = AI_CANONNAME;
672         hints.ai_family = AF_UNSPEC;
673         getaddrinfo(hrp->hostname, NULL, &hints, &res);
674         if (res)
675                 hrp->hostinfo = res;
676         hrp->statfile = _PATH_FTPDSTATFILE;
677         hrp->welcome  = _PATH_FTPWELCOME;
678         hrp->loginmsg = _PATH_FTPLOGINMESG;
679         hrp->anonuser = "ftp";
680         hrp->next = NULL;
681         thishost = firsthost = lhrp = hrp;
682         if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) {
683                 int addrsize, error, gothost;
684                 void *addr;
685                 struct hostent *hp;
686
687                 while (fgets(line, sizeof(line), fp) != NULL) {
688                         int     i, hp_error;
689
690                         if ((cp = strchr(line, '\n')) == NULL) {
691                                 /* ignore long lines */
692                                 while (fgets(line, sizeof(line), fp) != NULL &&
693                                         strchr(line, '\n') == NULL)
694                                         ;
695                                 continue;
696                         }
697                         *cp = '\0';
698                         cp = strtok(line, " \t");
699                         /* skip comments and empty lines */
700                         if (cp == NULL || line[0] == '#')
701                                 continue;
702
703                         hints.ai_flags = 0;
704                         hints.ai_family = AF_UNSPEC;
705                         hints.ai_flags = AI_PASSIVE;
706                         error = getaddrinfo(cp, NULL, &hints, &res);
707                         if (error != NULL)
708                                 continue;
709                         for (ai = res; ai != NULL && ai->ai_addr != NULL;
710                              ai = ai->ai_next) {
711
712                         gothost = 0;
713                         for (hrp = firsthost; hrp != NULL; hrp = hrp->next) {
714                                 struct addrinfo *hi;
715
716                                 for (hi = hrp->hostinfo; hi != NULL;
717                                      hi = hi->ai_next)
718                                         if (hi->ai_addrlen == ai->ai_addrlen &&
719                                             memcmp(hi->ai_addr,
720                                                    ai->ai_addr,
721                                                    ai->ai_addr->sa_len) == 0) {
722                                                 gothost++;
723                                                 break;
724                                 }
725                                 if (gothost)
726                                         break;
727                         }
728                         if (hrp == NULL) {
729                                 if ((hrp = malloc(sizeof(struct ftphost))) == NULL)
730                                         continue;
731                                 /* defaults */
732                                 hrp->statfile = _PATH_FTPDSTATFILE;
733                                 hrp->welcome  = _PATH_FTPWELCOME;
734                                 hrp->loginmsg = _PATH_FTPLOGINMESG;
735                                 hrp->anonuser = "ftp";
736                                 hrp->next     = NULL;
737                                 lhrp->next = hrp;
738                                 lhrp = hrp;
739                         }
740                         hrp->hostinfo = res;
741
742                         /*
743                          * determine hostname to use.
744                          * force defined name if there is a valid alias
745                          * otherwise fallback to primary hostname
746                          */
747                         /* XXX: getaddrinfo() can't do alias check */
748                         switch(hrp->hostinfo->ai_family) {
749                         case AF_INET:
750                                 addr = &((struct sockaddr_in *)&hrp->hostinfo->ai_addr)->sin_addr;
751                                 addrsize = sizeof(struct sockaddr_in);
752                                 break;
753                         case AF_INET6:
754                                 addr = &((struct sockaddr_in6 *)&hrp->hostinfo->ai_addr)->sin6_addr;
755                                 addrsize = sizeof(struct sockaddr_in6);
756                                 break;
757                         default:
758                                 /* should not reach here */
759                                 if (hrp->hostinfo != NULL)
760                                         freeaddrinfo(hrp->hostinfo);
761                                 free(hrp);
762                                 continue;
763                                 /* NOTREACHED */
764                         }
765                         if ((hp = getipnodebyaddr((char*)addr, addrsize,
766                                                   hrp->hostinfo->ai_family,
767                                                   &hp_error)) != NULL) {
768                                 if (strcmp(cp, hp->h_name) != 0) {
769                                         if (hp->h_aliases == NULL)
770                                                 cp = hp->h_name;
771                                         else {
772                                                 i = 0;
773                                                 while (hp->h_aliases[i] &&
774                                                        strcmp(cp, hp->h_aliases[i]) != 0)
775                                                         ++i;
776                                                 if (hp->h_aliases[i] == NULL)
777                                                         cp = hp->h_name;
778                                         }
779                                 }
780                         }
781                         hrp->hostname = strdup(cp);
782                         freehostent(hp);
783                         /* ok, now we now peel off the rest */
784                         i = 0;
785                         while (i < 4 && (cp = strtok(NULL, " \t")) != NULL) {
786                                 if (*cp != '-' && (cp = strdup(cp)) != NULL) {
787                                         switch (i) {
788                                         case 0: /* anon user permissions */
789                                                 hrp->anonuser = cp;
790                                                 break;
791                                         case 1: /* statistics file */
792                                                 hrp->statfile = cp;
793                                                 break;
794                                         case 2: /* welcome message */
795                                                 hrp->welcome  = cp;
796                                                 break;
797                                         case 3: /* login message */
798                                                 hrp->loginmsg = cp;
799                                                 break;
800                                         }
801                                 }
802                                 ++i;
803                         }
804                         /* XXX: re-initialization for getaddrinfo() loop */
805                         cp = strtok(line, " \t");
806                       }
807                 }
808                 (void) fclose(fp);
809         }
810 }
811
812 static void
813 selecthost(union sockunion *su)
814 {
815         struct ftphost  *hrp;
816         u_int16_t port;
817 #ifdef INET6
818         struct in6_addr *mapped_in6 = NULL;
819 #endif
820         struct addrinfo *hi;
821
822 #ifdef INET6
823         /*
824          * XXX IPv4 mapped IPv6 addr consideraton,
825          * specified in rfc2373.
826          */
827         if (su->su_family == AF_INET6 &&
828             IN6_IS_ADDR_V4MAPPED(&su->su_sin6.sin6_addr))
829                 mapped_in6 = &su->su_sin6.sin6_addr;
830 #endif
831
832         hrp = thishost = firsthost;     /* default */
833         port = su->su_port;
834         su->su_port = 0;
835         while (hrp != NULL) {
836             for (hi = hrp->hostinfo; hi != NULL; hi = hi->ai_next) {
837                 if (memcmp(su, hi->ai_addr, hi->ai_addrlen) == 0) {
838                         thishost = hrp;
839                         break;
840                 }
841 #ifdef INET6
842                 /* XXX IPv4 mapped IPv6 addr consideraton */
843                 if (hi->ai_addr->sa_family == AF_INET && mapped_in6 != NULL &&
844                     (memcmp(&mapped_in6->s6_addr[12],
845                             &((struct sockaddr_in *)hi->ai_addr)->sin_addr,
846                             sizeof(struct in_addr)) == 0)) {
847                         thishost = hrp;
848                         break;
849                 }
850 #endif
851             }
852             hrp = hrp->next;
853         }
854         su->su_port = port;
855         /* setup static variables as appropriate */
856         hostname = thishost->hostname;
857         ftpuser = thishost->anonuser;
858 }
859 #endif
860
861 /*
862  * Helper function for sgetpwnam().
863  */
864 static char *
865 sgetsave(char *s)
866 {
867         char *new = malloc((unsigned) strlen(s) + 1);
868
869         if (new == NULL) {
870                 perror_reply(421, "Local resource failure: malloc");
871                 dologout(1);
872                 /* NOTREACHED */
873         }
874         (void) strcpy(new, s);
875         return (new);
876 }
877
878 /*
879  * Save the result of a getpwnam.  Used for USER command, since
880  * the data returned must not be clobbered by any other command
881  * (e.g., globbing).
882  */
883 static struct passwd *
884 sgetpwnam(char *name)
885 {
886         static struct passwd save;
887         struct passwd *p;
888
889         if ((p = getpwnam(name)) == NULL)
890                 return (p);
891         if (save.pw_name) {
892                 free(save.pw_name);
893                 free(save.pw_passwd);
894                 free(save.pw_gecos);
895                 free(save.pw_dir);
896                 free(save.pw_shell);
897         }
898         save = *p;
899         save.pw_name = sgetsave(p->pw_name);
900         save.pw_passwd = sgetsave(p->pw_passwd);
901         save.pw_gecos = sgetsave(p->pw_gecos);
902         save.pw_dir = sgetsave(p->pw_dir);
903         save.pw_shell = sgetsave(p->pw_shell);
904         return (&save);
905 }
906
907 static int login_attempts;      /* number of failed login attempts */
908 static int askpasswd;           /* had user command, ask for passwd */
909 static char curname[MAXLOGNAME];        /* current USER name */
910
911 /*
912  * USER command.
913  * Sets global passwd pointer pw if named account exists and is acceptable;
914  * sets askpasswd if a PASS command is expected.  If logged in previously,
915  * need to reset state.  If name is "ftp" or "anonymous", the name is not in
916  * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
917  * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
918  * requesting login privileges.  Disallow anyone who does not have a standard
919  * shell as returned by getusershell().  Disallow anyone mentioned in the file
920  * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
921  */
922 void
923 user(char *name)
924 {
925         char *cp, *shell;
926
927         if (logged_in) {
928                 if (guest) {
929                         reply(530, "Can't change user from guest login.");
930                         return;
931                 } else if (dochroot) {
932                         reply(530, "Can't change user from chroot user.");
933                         return;
934                 }
935                 end_login();
936         }
937
938         guest = 0;
939         if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
940                 if (checkuser(_PATH_FTPUSERS, "ftp", 0) ||
941                     checkuser(_PATH_FTPUSERS, "anonymous", 0))
942                         reply(530, "User %s access denied.", name);
943 #ifdef VIRTUAL_HOSTING
944                 else if ((pw = sgetpwnam(thishost->anonuser)) != NULL) {
945 #else
946                 else if ((pw = sgetpwnam("ftp")) != NULL) {
947 #endif
948                         guest = 1;
949                         askpasswd = 1;
950                         reply(331,
951                         "Guest login ok, send your email address as password.");
952                 } else
953                         reply(530, "User %s unknown.", name);
954                 if (!askpasswd && logging)
955                         syslog(LOG_NOTICE,
956                             "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
957                 return;
958         }
959         if (anon_only != 0) {
960                 reply(530, "Sorry, only anonymous ftp allowed.");
961                 return;
962         }
963                 
964         if ((pw = sgetpwnam(name))) {
965                 if ((shell = pw->pw_shell) == NULL || *shell == 0)
966                         shell = _PATH_BSHELL;
967                 while ((cp = getusershell()) != NULL)
968                         if (strcmp(cp, shell) == 0)
969                                 break;
970                 endusershell();
971
972                 if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1)) {
973                         reply(530, "User %s access denied.", name);
974                         if (logging)
975                                 syslog(LOG_NOTICE,
976                                     "FTP LOGIN REFUSED FROM %s, %s",
977                                     remotehost, name);
978                         pw = (struct passwd *) NULL;
979                         return;
980                 }
981         }
982         if (logging)
983                 strncpy(curname, name, sizeof(curname)-1);
984
985         pwok = 0;
986 #ifdef USE_PAM
987         /* XXX Kluge! The conversation mechanism needs to be fixed. */
988 #endif
989         if (opiechallenge(&opiedata, name, opieprompt) == 0) {
990                 pwok = (pw != NULL) &&
991                        opieaccessfile(remotehost) &&
992                        opiealways(pw->pw_dir);
993                 reply(331, "Response to %s %s for %s.",
994                       opieprompt, pwok ? "requested" : "required", name);
995         } else {
996                 pwok = 1;
997                 reply(331, "Password required for %s.", name);
998         }
999         askpasswd = 1;
1000         /*
1001          * Delay before reading passwd after first failed
1002          * attempt to slow down passwd-guessing programs.
1003          */
1004         if (login_attempts)
1005                 sleep((unsigned) login_attempts);
1006 }
1007
1008 /*
1009  * Check if a user is in the file "fname"
1010  */
1011 static int
1012 checkuser(char *fname, char *name, int pwset)
1013 {
1014         FILE *fd;
1015         int found = 0;
1016         char *p, line[BUFSIZ];
1017
1018         if ((fd = fopen(fname, "r")) != NULL) {
1019                 while (!found && fgets(line, sizeof(line), fd) != NULL)
1020                         if ((p = strchr(line, '\n')) != NULL) {
1021                                 *p = '\0';
1022                                 if (line[0] == '#')
1023                                         continue;
1024                                 /*
1025                                  * if first chr is '@', check group membership
1026                                  */
1027                                 if (line[0] == '@') {
1028                                         int i = 0;
1029                                         struct group *grp;
1030
1031                                         if ((grp = getgrnam(line+1)) == NULL)
1032                                                 continue;
1033                                         /*
1034                                          * Check user's default group
1035                                          */
1036                                         if (pwset && grp->gr_gid == pw->pw_gid)
1037                                                 found = 1;
1038                                         /*
1039                                          * Check supplementary groups
1040                                          */
1041                                         while (!found && grp->gr_mem[i])
1042                                                 found = strcmp(name,
1043                                                         grp->gr_mem[i++])
1044                                                         == 0;
1045                                 }
1046                                 /*
1047                                  * Otherwise, just check for username match
1048                                  */
1049                                 else
1050                                         found = strcmp(line, name) == 0;
1051                         }
1052                 (void) fclose(fd);
1053         }
1054         return (found);
1055 }
1056
1057 /*
1058  * Terminate login as previous user, if any, resetting state;
1059  * used when USER command is given or login fails.
1060  */
1061 static void
1062 end_login(void)
1063 {
1064 #ifdef USE_PAM
1065         int e;
1066 #endif
1067
1068         (void) seteuid((uid_t)0);
1069         if (logged_in)
1070                 ftpd_logwtmp(ttyline, "", NULL);
1071         pw = NULL;
1072 #ifdef  LOGIN_CAP
1073         setusercontext(NULL, getpwuid(0), (uid_t)0,
1074                        LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK);
1075 #endif
1076 #ifdef USE_PAM
1077         if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS)
1078                 syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e));
1079         if ((e = pam_close_session(pamh,0)) != PAM_SUCCESS)
1080                 syslog(LOG_ERR, "pam_close_session: %s", pam_strerror(pamh, e));
1081         if ((e = pam_end(pamh, e)) != PAM_SUCCESS)
1082                 syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1083         pamh = NULL;
1084 #endif
1085         logged_in = 0;
1086         guest = 0;
1087         dochroot = 0;
1088 }
1089
1090 #ifdef USE_PAM
1091
1092 /*
1093  * the following code is stolen from imap-uw PAM authentication module and
1094  * login.c
1095  */
1096 #define COPY_STRING(s) (s ? strdup(s) : NULL)
1097
1098 struct cred_t {
1099         const char *uname;              /* user name */
1100         const char *pass;               /* password */
1101 };
1102 typedef struct cred_t cred_t;
1103
1104 static int
1105 auth_conv(int num_msg, const struct pam_message **msg,
1106           struct pam_response **resp, void *appdata)
1107 {
1108         int i;
1109         cred_t *cred = (cred_t *) appdata;
1110         struct pam_response *reply;
1111
1112         reply = calloc(num_msg, sizeof *reply);
1113         if (reply == NULL)
1114                 return PAM_BUF_ERR;
1115
1116         for (i = 0; i < num_msg; i++) {
1117                 switch (msg[i]->msg_style) {
1118                 case PAM_PROMPT_ECHO_ON:        /* assume want user name */
1119                         reply[i].resp_retcode = PAM_SUCCESS;
1120                         reply[i].resp = COPY_STRING(cred->uname);
1121                         /* PAM frees resp. */
1122                         break;
1123                 case PAM_PROMPT_ECHO_OFF:       /* assume want password */
1124                         reply[i].resp_retcode = PAM_SUCCESS;
1125                         reply[i].resp = COPY_STRING(cred->pass);
1126                         /* PAM frees resp. */
1127                         break;
1128                 case PAM_TEXT_INFO:
1129                 case PAM_ERROR_MSG:
1130                         reply[i].resp_retcode = PAM_SUCCESS;
1131                         reply[i].resp = NULL;
1132                         break;
1133                 default:                        /* unknown message style */
1134                         free(reply);
1135                         return PAM_CONV_ERR;
1136                 }
1137         }
1138
1139         *resp = reply;
1140         return PAM_SUCCESS;
1141 }
1142
1143 /*
1144  * Attempt to authenticate the user using PAM.  Returns 0 if the user is
1145  * authenticated, or 1 if not authenticated.  If some sort of PAM system
1146  * error occurs (e.g., the "/etc/pam.conf" file is missing) then this
1147  * function returns -1.  This can be used as an indication that we should
1148  * fall back to a different authentication mechanism.
1149  */
1150 static int
1151 auth_pam(struct passwd **ppw, const char *pass)
1152 {
1153         pam_handle_t *pamh = NULL;
1154         const char *tmpl_user;
1155         const void *item;
1156         int rval;
1157         int e;
1158         cred_t auth_cred = { (*ppw)->pw_name, pass };
1159         struct pam_conv conv = { &auth_conv, &auth_cred };
1160
1161         e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh);
1162         if (e != PAM_SUCCESS) {
1163                 syslog(LOG_ERR, "pam_start: %s", pam_strerror(pamh, e));
1164                 return -1;
1165         }
1166
1167         e = pam_set_item(pamh, PAM_RHOST, remotehost);
1168         if (e != PAM_SUCCESS) {
1169                 syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
1170                         pam_strerror(pamh, e));
1171                 return -1;
1172         }
1173
1174         e = pam_authenticate(pamh, 0);
1175         switch (e) {
1176         case PAM_SUCCESS:
1177                 /*
1178                  * With PAM we support the concept of a "template"
1179                  * user.  The user enters a login name which is
1180                  * authenticated by PAM, usually via a remote service
1181                  * such as RADIUS or TACACS+.  If authentication
1182                  * succeeds, a different but related "template" name
1183                  * is used for setting the credentials, shell, and
1184                  * home directory.  The name the user enters need only
1185                  * exist on the remote authentication server, but the
1186                  * template name must be present in the local password
1187                  * database.
1188                  *
1189                  * This is supported by two various mechanisms in the
1190                  * individual modules.  However, from the application's
1191                  * point of view, the template user is always passed
1192                  * back as a changed value of the PAM_USER item.
1193                  */
1194                 if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
1195                     PAM_SUCCESS) {
1196                         tmpl_user = (const char *) item;
1197                         if (strcmp((*ppw)->pw_name, tmpl_user) != 0)
1198                                 *ppw = getpwnam(tmpl_user);
1199                 } else
1200                         syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
1201                             pam_strerror(pamh, e));
1202                 rval = 0;
1203                 break;
1204
1205         case PAM_AUTH_ERR:
1206         case PAM_USER_UNKNOWN:
1207         case PAM_MAXTRIES:
1208                 rval = 1;
1209                 break;
1210
1211         default:
1212                 syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, e));
1213                 rval = -1;
1214                 break;
1215         }
1216
1217         if (rval == 0) {
1218                 e = pam_acct_mgmt(pamh, 0);
1219                 if (e == PAM_NEW_AUTHTOK_REQD) {
1220                         e = pam_chauthtok(pamh, PAM_CHANGE_EXPIRED_AUTHTOK);
1221                         if (e != PAM_SUCCESS) {
1222                                 syslog(LOG_ERR, "pam_chauthtok: %s", pam_strerror(pamh, e));
1223                                 rval = 1;
1224                         }
1225                 } else if (e != PAM_SUCCESS) {
1226                         rval = 1;
1227                 }
1228         }
1229
1230         if (rval != 0) {
1231                 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
1232                         syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1233                 }
1234                 pamh = NULL;
1235         }
1236         return rval;
1237 }
1238
1239 #endif /* USE_PAM */
1240
1241 void
1242 pass(char *passwd)
1243 {
1244         int rval;
1245         FILE *fd;
1246 #ifdef  LOGIN_CAP
1247         login_cap_t *lc = NULL;
1248 #endif
1249 #ifdef USE_PAM
1250         int e;
1251 #endif
1252         char *xpasswd;
1253
1254         if (logged_in || askpasswd == 0) {
1255                 reply(503, "Login with USER first.");
1256                 return;
1257         }
1258         askpasswd = 0;
1259         if (!guest) {           /* "ftp" is only account allowed no password */
1260                 if (pw == NULL) {
1261                         rval = 1;       /* failure below */
1262                         goto skip;
1263                 }
1264 #ifdef USE_PAM
1265                 rval = auth_pam(&pw, passwd);
1266                 if (rval >= 0) {
1267                         opieunlock();
1268                         goto skip;
1269                 }
1270 #endif
1271                 if (opieverify(&opiedata, passwd) == 0)
1272                         xpasswd = pw->pw_passwd;
1273                 else if (pwok) {
1274                         xpasswd = crypt(passwd, pw->pw_passwd);
1275                         if (passwd[0] == '\0' && pw->pw_passwd[0] != '\0')
1276                                 xpasswd = ":";
1277                 } else {
1278                         rval = 1;
1279                         goto skip;
1280                 }
1281                 rval = strcmp(pw->pw_passwd, xpasswd);
1282                 if (pw->pw_expire && time(NULL) >= pw->pw_expire)
1283                         rval = 1;       /* failure */
1284 skip:
1285                 /*
1286                  * If rval == 1, the user failed the authentication check
1287                  * above.  If rval == 0, either PAM or local authentication
1288                  * succeeded.
1289                  */
1290                 if (rval) {
1291                         reply(530, "Login incorrect.");
1292                         if (logging)
1293                                 syslog(LOG_NOTICE,
1294                                     "FTP LOGIN FAILED FROM %s, %s",
1295                                     remotehost, curname);
1296                         pw = NULL;
1297                         if (login_attempts++ >= 5) {
1298                                 syslog(LOG_NOTICE,
1299                                     "repeated login failures from %s",
1300                                     remotehost);
1301                                 exit(0);
1302                         }
1303                         return;
1304                 }
1305         }
1306         login_attempts = 0;             /* this time successful */
1307         if (setegid((gid_t)pw->pw_gid) < 0) {
1308                 reply(550, "Can't set gid.");
1309                 return;
1310         }
1311         /* May be overridden by login.conf */
1312         (void) umask(defumask);
1313 #ifdef  LOGIN_CAP
1314         if ((lc = login_getpwclass(pw)) != NULL) {
1315                 char    remote_ip[MAXHOSTNAMELEN];
1316
1317                 getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1318                         remote_ip, sizeof(remote_ip) - 1, NULL, 0,
1319                         NI_NUMERICHOST);
1320                 remote_ip[sizeof(remote_ip) - 1] = 0;
1321                 if (!auth_hostok(lc, remotehost, remote_ip)) {
1322                         syslog(LOG_INFO|LOG_AUTH,
1323                             "FTP LOGIN FAILED (HOST) as %s: permission denied.",
1324                             pw->pw_name);
1325                         reply(530, "Permission denied.\n");
1326                         pw = NULL;
1327                         return;
1328                 }
1329                 if (!auth_timeok(lc, time(NULL))) {
1330                         reply(530, "Login not available right now.\n");
1331                         pw = NULL;
1332                         return;
1333                 }
1334         }
1335         setusercontext(lc, pw, (uid_t)0,
1336                 LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY|
1337                 LOGIN_SETRESOURCES|LOGIN_SETUMASK);
1338 #else
1339         setlogin(pw->pw_name);
1340         (void) initgroups(pw->pw_name, pw->pw_gid);
1341 #endif
1342
1343 #ifdef USE_PAM
1344         if (pamh) {
1345                 if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
1346                         syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, e));
1347                 } else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
1348                         syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e));
1349                 }
1350         }
1351 #endif
1352
1353         /* open wtmp before chroot */
1354         ftpd_logwtmp(ttyline, pw->pw_name, (struct sockaddr *)&his_addr);
1355         logged_in = 1;
1356
1357         if (guest && stats && statfd < 0)
1358 #ifdef VIRTUAL_HOSTING
1359                 if ((statfd = open(thishost->statfile, O_WRONLY|O_APPEND)) < 0)
1360 #else
1361                 if ((statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND)) < 0)
1362 #endif
1363                         stats = 0;
1364
1365         dochroot =
1366 #ifdef  LOGIN_CAP       /* Allow login.conf configuration as well */
1367                 login_getcapbool(lc, "ftp-chroot", 0) ||
1368 #endif
1369                 checkuser(_PATH_FTPCHROOT, pw->pw_name, 1);
1370         if (guest) {
1371                 /*
1372                  * We MUST do a chdir() after the chroot. Otherwise
1373                  * the old current directory will be accessible as "."
1374                  * outside the new root!
1375                  */
1376                 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
1377                         reply(550, "Can't set guest privileges.");
1378                         goto bad;
1379                 }
1380         } else if (dochroot) {
1381                 if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
1382                         reply(550, "Can't change root.");
1383                         goto bad;
1384                 }
1385         } else if (chdir(pw->pw_dir) < 0) {
1386                 if (chdir("/") < 0) {
1387                         reply(530, "User %s: can't change directory to %s.",
1388                             pw->pw_name, pw->pw_dir);
1389                         goto bad;
1390                 } else
1391                         lreply(230, "No directory! Logging in with home=/");
1392         }
1393         if (seteuid((uid_t)pw->pw_uid) < 0) {
1394                 reply(550, "Can't set uid.");
1395                 goto bad;
1396         }
1397
1398         /*
1399          * Display a login message, if it exists.
1400          * N.B. reply(230,) must follow the message.
1401          */
1402 #ifdef VIRTUAL_HOSTING
1403         if ((fd = fopen(thishost->loginmsg, "r")) != NULL) {
1404 #else
1405         if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) {
1406 #endif
1407                 char *cp, line[LINE_MAX];
1408
1409                 while (fgets(line, sizeof(line), fd) != NULL) {
1410                         if ((cp = strchr(line, '\n')) != NULL)
1411                                 *cp = '\0';
1412                         lreply(230, "%s", line);
1413                 }
1414                 (void) fflush(stdout);
1415                 (void) fclose(fd);
1416         }
1417         if (guest) {
1418                 if (ident != NULL)
1419                         free(ident);
1420                 ident = strdup(passwd);
1421                 if (ident == NULL)
1422                         fatalerror("Ran out of memory.");
1423
1424                 reply(230, "Guest login ok, access restrictions apply.");
1425 #ifdef SETPROCTITLE
1426 #ifdef VIRTUAL_HOSTING
1427                 if (thishost != firsthost)
1428                         snprintf(proctitle, sizeof(proctitle),
1429                                  "%s: anonymous(%s)/%s", remotehost, hostname,
1430                                  passwd);
1431                 else
1432 #endif
1433                         snprintf(proctitle, sizeof(proctitle),
1434                                  "%s: anonymous/%s", remotehost, passwd);
1435                 setproctitle("%s", proctitle);
1436 #endif /* SETPROCTITLE */
1437                 if (logging)
1438                         syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
1439                             remotehost, passwd);
1440         } else {
1441                 if (dochroot)
1442                         reply(230, "User %s logged in, "
1443                                    "access restrictions apply.", pw->pw_name);
1444                 else
1445                         reply(230, "User %s logged in.", pw->pw_name);
1446
1447 #ifdef SETPROCTITLE
1448                 snprintf(proctitle, sizeof(proctitle),
1449                          "%s: user/%s", remotehost, pw->pw_name);
1450                 setproctitle("%s", proctitle);
1451 #endif /* SETPROCTITLE */
1452                 if (logging)
1453                         syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
1454                             remotehost, pw->pw_name);
1455         }
1456 #ifdef  LOGIN_CAP
1457         login_close(lc);
1458 #endif
1459         return;
1460 bad:
1461         /* Forget all about it... */
1462 #ifdef  LOGIN_CAP
1463         login_close(lc);
1464 #endif
1465         end_login();
1466 }
1467
1468 void
1469 retrieve(char *cmd, char *name)
1470 {
1471         FILE *fin, *dout;
1472         struct stat st;
1473         int (*closefunc)(FILE *);
1474         time_t start;
1475
1476         if (cmd == 0) {
1477                 fin = fopen(name, "r"), closefunc = fclose;
1478                 st.st_size = 0;
1479         } else {
1480                 char line[BUFSIZ];
1481
1482                 (void) snprintf(line, sizeof(line), cmd, name), name = line;
1483                 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1484                 st.st_size = -1;
1485                 st.st_blksize = BUFSIZ;
1486         }
1487         if (fin == NULL) {
1488                 if (errno != 0) {
1489                         perror_reply(550, name);
1490                         if (cmd == 0) {
1491                                 LOGCMD("get", name);
1492                         }
1493                 }
1494                 return;
1495         }
1496         byte_count = -1;
1497         if (cmd == 0 && (fstat(fileno(fin), &st) < 0 || !S_ISREG(st.st_mode))) {
1498                 reply(550, "%s: not a plain file.", name);
1499                 goto done;
1500         }
1501         if (restart_point) {
1502                 if (type == TYPE_A) {
1503                         off_t i, n;
1504                         int c;
1505
1506                         n = restart_point;
1507                         i = 0;
1508                         while (i++ < n) {
1509                                 if ((c=getc(fin)) == EOF) {
1510                                         perror_reply(550, name);
1511                                         goto done;
1512                                 }
1513                                 if (c == '\n')
1514                                         i++;
1515                         }
1516                 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
1517                         perror_reply(550, name);
1518                         goto done;
1519                 }
1520         }
1521         dout = dataconn(name, st.st_size, "w");
1522         if (dout == NULL)
1523                 goto done;
1524         time(&start);
1525         send_data(fin, dout, st.st_blksize, st.st_size,
1526                   restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode));
1527         if (cmd == 0 && guest && stats)
1528                 logxfer(name, st.st_size, start);
1529         (void) fclose(dout);
1530         data = -1;
1531         pdata = -1;
1532 done:
1533         if (cmd == 0)
1534                 LOGBYTES("get", name, byte_count);
1535         (*closefunc)(fin);
1536 }
1537
1538 void
1539 store(char *name, char *mode, int unique)
1540 {
1541         FILE *fout, *din;
1542         struct stat st;
1543         int (*closefunc)(FILE *);
1544
1545         if ((unique || guest) && stat(name, &st) == 0 &&
1546             (name = gunique(name)) == NULL) {
1547                 LOGCMD(*mode == 'w' ? "put" : "append", name);
1548                 return;
1549         }
1550
1551         if (restart_point)
1552                 mode = "r+";
1553         fout = fopen(name, mode);
1554         closefunc = fclose;
1555         if (fout == NULL) {
1556                 perror_reply(553, name);
1557                 LOGCMD(*mode == 'w' ? "put" : "append", name);
1558                 return;
1559         }
1560         byte_count = -1;
1561         if (restart_point) {
1562                 if (type == TYPE_A) {
1563                         off_t i, n;
1564                         int c;
1565
1566                         n = restart_point;
1567                         i = 0;
1568                         while (i++ < n) {
1569                                 if ((c=getc(fout)) == EOF) {
1570                                         perror_reply(550, name);
1571                                         goto done;
1572                                 }
1573                                 if (c == '\n')
1574                                         i++;
1575                         }
1576                         /*
1577                          * We must do this seek to "current" position
1578                          * because we are changing from reading to
1579                          * writing.
1580                          */
1581                         if (fseeko(fout, (off_t)0, SEEK_CUR) < 0) {
1582                                 perror_reply(550, name);
1583                                 goto done;
1584                         }
1585                 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
1586                         perror_reply(550, name);
1587                         goto done;
1588                 }
1589         }
1590         din = dataconn(name, (off_t)-1, "r");
1591         if (din == NULL)
1592                 goto done;
1593         if (receive_data(din, fout) == 0) {
1594                 if (unique)
1595                         reply(226, "Transfer complete (unique file name:%s).",
1596                             name);
1597                 else
1598                         reply(226, "Transfer complete.");
1599         }
1600         (void) fclose(din);
1601         data = -1;
1602         pdata = -1;
1603 done:
1604         LOGBYTES(*mode == 'w' ? "put" : "append", name, byte_count);
1605         (*closefunc)(fout);
1606 }
1607
1608 static FILE *
1609 getdatasock(char *mode)
1610 {
1611         int on = 1, s, t, tries;
1612
1613         if (data >= 0)
1614                 return (fdopen(data, mode));
1615         (void) seteuid((uid_t)0);
1616
1617         s = socket(data_dest.su_family, SOCK_STREAM, 0);
1618         if (s < 0)
1619                 goto bad;
1620         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
1621             (char *) &on, sizeof(on)) < 0)
1622                 goto bad;
1623         /* anchor socket to avoid multi-homing problems */
1624         data_source = ctrl_addr;
1625         data_source.su_port = htons(20); /* ftp-data port */
1626         for (tries = 1; ; tries++) {
1627                 if (bind(s, (struct sockaddr *)&data_source,
1628                     data_source.su_len) >= 0)
1629                         break;
1630                 if (errno != EADDRINUSE || tries > 10)
1631                         goto bad;
1632                 sleep(tries);
1633         }
1634         (void) seteuid((uid_t)pw->pw_uid);
1635 #ifdef IP_TOS
1636         if (data_source.su_family == AF_INET)
1637       {
1638         on = IPTOS_THROUGHPUT;
1639         if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0)
1640                 syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");
1641       }
1642 #endif
1643 #ifdef TCP_NOPUSH
1644         /*
1645          * Turn off push flag to keep sender TCP from sending short packets
1646          * at the boundaries of each write().  Should probably do a SO_SNDBUF
1647          * to set the send buffer size as well, but that may not be desirable
1648          * in heavy-load situations.
1649          */
1650         on = 1;
1651         if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0)
1652                 syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m");
1653 #endif
1654 #ifdef SO_SNDBUF
1655         on = 65536;
1656         if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0)
1657                 syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m");
1658 #endif
1659
1660         return (fdopen(s, mode));
1661 bad:
1662         /* Return the real value of errno (close may change it) */
1663         t = errno;
1664         (void) seteuid((uid_t)pw->pw_uid);
1665         (void) close(s);
1666         errno = t;
1667         return (NULL);
1668 }
1669
1670 static FILE *
1671 dataconn(char *name, off_t size, char *mode)
1672 {
1673         char sizebuf[32];
1674         FILE *file;
1675         int retry = 0, tos;
1676
1677         file_size = size;
1678         byte_count = 0;
1679         if (size != (off_t) -1)
1680                 (void) snprintf(sizebuf, sizeof(sizebuf), " (%qd bytes)", size);
1681         else
1682                 *sizebuf = '\0';
1683         if (pdata >= 0) {
1684                 union sockunion from;
1685                 int flags;
1686                 int s, fromlen = ctrl_addr.su_len;
1687                 struct timeval timeout;
1688                 fd_set set;
1689
1690                 FD_ZERO(&set);
1691                 FD_SET(pdata, &set);
1692
1693                 timeout.tv_usec = 0;
1694                 timeout.tv_sec = 120;
1695
1696                 /*
1697                  * Granted a socket is in the blocking I/O mode,
1698                  * accept() will block after a successful select()
1699                  * if the selected connection dies in between.
1700                  * Therefore set the non-blocking I/O flag here.
1701                  */
1702                 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1703                     fcntl(pdata, F_SETFL, flags | O_NONBLOCK) == -1)
1704                         goto pdata_err;
1705                 if (select(pdata+1, &set, (fd_set *) 0, (fd_set *) 0, &timeout) <= 0 ||
1706                     (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0)
1707                         goto pdata_err;
1708                 (void) close(pdata);
1709                 pdata = s;
1710                 /*
1711                  * Unset the blocking I/O flag on the child socket
1712                  * again so stdio can work on it.
1713                  */
1714                 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1715                     fcntl(pdata, F_SETFL, flags & ~O_NONBLOCK) == -1)
1716                         goto pdata_err;
1717 #ifdef IP_TOS
1718                 if (from.su_family == AF_INET)
1719               {
1720                 tos = IPTOS_THROUGHPUT;
1721                 (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos,
1722                     sizeof(int));
1723               }
1724 #endif
1725                 reply(150, "Opening %s mode data connection for '%s'%s.",
1726                      type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1727                 return (fdopen(pdata, mode));
1728 pdata_err:
1729                 reply(425, "Can't open data connection.");
1730                 (void) close(pdata);
1731                 pdata = -1;
1732                 return (NULL);
1733         }
1734         if (data >= 0) {
1735                 reply(125, "Using existing data connection for '%s'%s.",
1736                     name, sizebuf);
1737                 usedefault = 1;
1738                 return (fdopen(data, mode));
1739         }
1740         if (usedefault)
1741                 data_dest = his_addr;
1742         usedefault = 1;
1743         file = getdatasock(mode);
1744         if (file == NULL) {
1745                 char hostbuf[BUFSIZ], portbuf[BUFSIZ];
1746                 getnameinfo((struct sockaddr *)&data_source,
1747                         data_source.su_len, hostbuf, sizeof(hostbuf) - 1,
1748                         portbuf, sizeof(portbuf),
1749                         NI_NUMERICHOST|NI_NUMERICSERV);
1750                 reply(425, "Can't create data socket (%s,%s): %s.",
1751                         hostbuf, portbuf, strerror(errno));
1752                 return (NULL);
1753         }
1754         data = fileno(file);
1755         while (connect(data, (struct sockaddr *)&data_dest,
1756             data_dest.su_len) < 0) {
1757                 if (errno == EADDRINUSE && retry < swaitmax) {
1758                         sleep((unsigned) swaitint);
1759                         retry += swaitint;
1760                         continue;
1761                 }
1762                 perror_reply(425, "Can't build data connection");
1763                 (void) fclose(file);
1764                 data = -1;
1765                 return (NULL);
1766         }
1767         reply(150, "Opening %s mode data connection for '%s'%s.",
1768              type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1769         return (file);
1770 }
1771
1772 /*
1773  * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1774  * encapsulation of the data subject to Mode, Structure, and Type.
1775  *
1776  * NB: Form isn't handled.
1777  */
1778 static int
1779 send_data(FILE *instr, FILE *outstr, off_t blksize, off_t filesize, int isreg)
1780 {
1781         int c, filefd, netfd;
1782         char *buf;
1783         off_t cnt;
1784
1785         transflag++;
1786         switch (type) {
1787
1788         case TYPE_A:
1789                 while ((c = getc(instr)) != EOF) {
1790                         if (recvurg)
1791                                 goto got_oob;
1792                         byte_count++;
1793                         if (c == '\n') {
1794                                 if (ferror(outstr))
1795                                         goto data_err;
1796                                 (void) putc('\r', outstr);
1797                         }
1798                         (void) putc(c, outstr);
1799                 }
1800                 if (recvurg)
1801                         goto got_oob;
1802                 fflush(outstr);
1803                 transflag = 0;
1804                 if (ferror(instr))
1805                         goto file_err;
1806                 if (ferror(outstr))
1807                         goto data_err;
1808                 reply(226, "Transfer complete.");
1809                 return (0);
1810
1811         case TYPE_I:
1812         case TYPE_L:
1813                 /*
1814                  * isreg is only set if we are not doing restart and we
1815                  * are sending a regular file
1816                  */
1817                 netfd = fileno(outstr);
1818                 filefd = fileno(instr);
1819
1820                 if (isreg) {
1821
1822                         off_t offset;
1823                         int err;
1824
1825                         err = cnt = offset = 0;
1826
1827                         while (err != -1 && filesize > 0) {
1828                                 err = sendfile(filefd, netfd, offset, 0,
1829                                         (struct sf_hdtr *) NULL, &cnt, 0);
1830                                 /*
1831                                  * Calculate byte_count before OOB processing.
1832                                  * It can be used in myoob() later.
1833                                  */
1834                                 byte_count += cnt;
1835                                 if (recvurg)
1836                                         goto got_oob;
1837                                 offset += cnt;
1838                                 filesize -= cnt;
1839
1840                                 if (err == -1) {
1841                                         if (!cnt)
1842                                                 goto oldway;
1843
1844                                         goto data_err;
1845                                 }
1846                         }
1847
1848                         transflag = 0;
1849                         reply(226, "Transfer complete.");
1850                         return (0);
1851                 }
1852
1853 oldway:
1854                 if ((buf = malloc((u_int)blksize)) == NULL) {
1855                         transflag = 0;
1856                         perror_reply(451, "Local resource failure: malloc");
1857                         return (-1);
1858                 }
1859
1860                 while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
1861                     write(netfd, buf, cnt) == cnt)
1862                         byte_count += cnt;
1863                 transflag = 0;
1864                 (void)free(buf);
1865                 if (cnt != 0) {
1866                         if (cnt < 0)
1867                                 goto file_err;
1868                         goto data_err;
1869                 }
1870                 reply(226, "Transfer complete.");
1871                 return (0);
1872         default:
1873                 transflag = 0;
1874                 reply(550, "Unimplemented TYPE %d in send_data", type);
1875                 return (-1);
1876         }
1877
1878 data_err:
1879         transflag = 0;
1880         perror_reply(426, "Data connection");
1881         return (-1);
1882
1883 file_err:
1884         transflag = 0;
1885         perror_reply(551, "Error on input file");
1886         return (-1);
1887
1888 got_oob:
1889         myoob();
1890         recvurg = 0;
1891         transflag = 0;
1892         return (-1);
1893 }
1894
1895 /*
1896  * Transfer data from peer to "outstr" using the appropriate encapulation of
1897  * the data subject to Mode, Structure, and Type.
1898  *
1899  * N.B.: Form isn't handled.
1900  */
1901 static int
1902 receive_data(FILE *instr, FILE *outstr)
1903 {
1904         int c;
1905         int cnt, bare_lfs;
1906         char buf[BUFSIZ];
1907
1908         transflag++;
1909         bare_lfs = 0;
1910
1911         switch (type) {
1912
1913         case TYPE_I:
1914         case TYPE_L:
1915                 while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
1916                         if (recvurg)
1917                                 goto got_oob;
1918                         if (write(fileno(outstr), buf, cnt) != cnt)
1919                                 goto file_err;
1920                         byte_count += cnt;
1921                 }
1922                 if (recvurg)
1923                         goto got_oob;
1924                 if (cnt < 0)
1925                         goto data_err;
1926                 transflag = 0;
1927                 return (0);
1928
1929         case TYPE_E:
1930                 reply(553, "TYPE E not implemented.");
1931                 transflag = 0;
1932                 return (-1);
1933
1934         case TYPE_A:
1935                 while ((c = getc(instr)) != EOF) {
1936                         if (recvurg)
1937                                 goto got_oob;
1938                         byte_count++;
1939                         if (c == '\n')
1940                                 bare_lfs++;
1941                         while (c == '\r') {
1942                                 if (ferror(outstr))
1943                                         goto data_err;
1944                                 if ((c = getc(instr)) != '\n') {
1945                                         (void) putc ('\r', outstr);
1946                                         if (c == '\0' || c == EOF)
1947                                                 goto contin2;
1948                                 }
1949                         }
1950                         (void) putc(c, outstr);
1951         contin2:        ;
1952                 }
1953                 if (recvurg)
1954                         goto got_oob;
1955                 fflush(outstr);
1956                 if (ferror(instr))
1957                         goto data_err;
1958                 if (ferror(outstr))
1959                         goto file_err;
1960                 transflag = 0;
1961                 if (bare_lfs) {
1962                         lreply(226,
1963                 "WARNING! %d bare linefeeds received in ASCII mode",
1964                             bare_lfs);
1965                 (void)printf("   File may not have transferred correctly.\r\n");
1966                 }
1967                 return (0);
1968         default:
1969                 reply(550, "Unimplemented TYPE %d in receive_data", type);
1970                 transflag = 0;
1971                 return (-1);
1972         }
1973
1974 data_err:
1975         transflag = 0;
1976         perror_reply(426, "Data Connection");
1977         return (-1);
1978
1979 file_err:
1980         transflag = 0;
1981         perror_reply(452, "Error writing file");
1982         return (-1);
1983
1984 got_oob:
1985         myoob();
1986         recvurg = 0;
1987         transflag = 0;
1988         return (-1);
1989 }
1990
1991 void
1992 statfilecmd(char *filename)
1993 {
1994         FILE *fin;
1995         int c;
1996         char line[LINE_MAX];
1997
1998         (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
1999         fin = ftpd_popen(line, "r");
2000         lreply(211, "status of %s:", filename);
2001         while ((c = getc(fin)) != EOF) {
2002                 if (c == '\n') {
2003                         if (ferror(stdout)){
2004                                 perror_reply(421, "control connection");
2005                                 (void) ftpd_pclose(fin);
2006                                 dologout(1);
2007                                 /* NOTREACHED */
2008                         }
2009                         if (ferror(fin)) {
2010                                 perror_reply(551, filename);
2011                                 (void) ftpd_pclose(fin);
2012                                 return;
2013                         }
2014                         (void) putc('\r', stdout);
2015                 }
2016                 (void) putc(c, stdout);
2017         }
2018         (void) ftpd_pclose(fin);
2019         reply(211, "End of Status");
2020 }
2021
2022 void
2023 statcmd(void)
2024 {
2025         union sockunion *su;
2026         u_char *a, *p;
2027         char hname[NI_MAXHOST];
2028         int ispassive;
2029
2030         lreply(211, "%s FTP server status:", hostname, version);
2031         printf("     %s\r\n", version);
2032         printf("     Connected to %s", remotehost);
2033         if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
2034                          hname, sizeof(hname) - 1, NULL, 0, NI_NUMERICHOST)) {
2035                 if (strcmp(hname, remotehost) != 0)
2036                         printf(" (%s)", hname);
2037         }
2038         printf("\r\n");
2039         if (logged_in) {
2040                 if (guest)
2041                         printf("     Logged in anonymously\r\n");
2042                 else
2043                         printf("     Logged in as %s\r\n", pw->pw_name);
2044         } else if (askpasswd)
2045                 printf("     Waiting for password\r\n");
2046         else
2047                 printf("     Waiting for user name\r\n");
2048         printf("     TYPE: %s", typenames[type]);
2049         if (type == TYPE_A || type == TYPE_E)
2050                 printf(", FORM: %s", formnames[form]);
2051         if (type == TYPE_L)
2052 #if NBBY == 8
2053                 printf(" %d", NBBY);
2054 #else
2055                 printf(" %d", bytesize);        /* need definition! */
2056 #endif
2057         printf("; STRUcture: %s; transfer MODE: %s\r\n",
2058             strunames[stru], modenames[mode]);
2059         if (data != -1)
2060                 printf("     Data connection open\r\n");
2061         else if (pdata != -1) {
2062                 ispassive = 1;
2063                 su = &pasv_addr;
2064                 goto printaddr;
2065         } else if (usedefault == 0) {
2066                 ispassive = 0;
2067                 su = &data_dest;
2068 printaddr:
2069 #define UC(b) (((int) b) & 0xff)
2070                 if (epsvall) {
2071                         printf("     EPSV only mode (EPSV ALL)\r\n");
2072                         goto epsvonly;
2073                 }
2074
2075                 /* PORT/PASV */
2076                 if (su->su_family == AF_INET) {
2077                         a = (u_char *) &su->su_sin.sin_addr;
2078                         p = (u_char *) &su->su_sin.sin_port;
2079                         printf("     %s (%d,%d,%d,%d,%d,%d)\r\n",
2080                                 ispassive ? "PASV" : "PORT",
2081                                 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2082                                 UC(p[0]), UC(p[1]));
2083                 }
2084
2085                 /* LPRT/LPSV */
2086             {
2087                 int alen, af, i;
2088
2089                 switch (su->su_family) {
2090                 case AF_INET:
2091                         a = (u_char *) &su->su_sin.sin_addr;
2092                         p = (u_char *) &su->su_sin.sin_port;
2093                         alen = sizeof(su->su_sin.sin_addr);
2094                         af = 4;
2095                         break;
2096                 case AF_INET6:
2097                         a = (u_char *) &su->su_sin6.sin6_addr;
2098                         p = (u_char *) &su->su_sin6.sin6_port;
2099                         alen = sizeof(su->su_sin6.sin6_addr);
2100                         af = 6;
2101                         break;
2102                 default:
2103                         af = 0;
2104                         break;
2105                 }
2106                 if (af) {
2107                         printf("     %s (%d,%d,", ispassive ? "LPSV" : "LPRT",
2108                                 af, alen);
2109                         for (i = 0; i < alen; i++)
2110                                 printf("%d,", UC(a[i]));
2111                         printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1]));
2112                 }
2113             }
2114
2115 epsvonly:;
2116                 /* EPRT/EPSV */
2117             {
2118                 int af;
2119
2120                 switch (su->su_family) {
2121                 case AF_INET:
2122                         af = 1;
2123                         break;
2124                 case AF_INET6:
2125                         af = 2;
2126                         break;
2127                 default:
2128                         af = 0;
2129                         break;
2130                 }
2131                 if (af) {
2132                         union sockunion tmp;
2133
2134                         tmp = *su;
2135                         if (tmp.su_family == AF_INET6)
2136                                 tmp.su_sin6.sin6_scope_id = 0;
2137                         if (!getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
2138                                         hname, sizeof(hname) - 1, NULL, 0,
2139                                         NI_NUMERICHOST)) {
2140                                 printf("     %s |%d|%s|%d|\r\n",
2141                                         ispassive ? "EPSV" : "EPRT",
2142                                         af, hname, htons(tmp.su_port));
2143                         }
2144                 }
2145             }
2146 #undef UC
2147         } else
2148                 printf("     No data connection\r\n");
2149         reply(211, "End of status");
2150 }
2151
2152 void
2153 fatalerror(char *s)
2154 {
2155
2156         reply(451, "Error in server: %s\n", s);
2157         reply(221, "Closing connection due to server error.");
2158         dologout(0);
2159         /* NOTREACHED */
2160 }
2161
2162 void
2163 reply(int n, const char *fmt, ...)
2164 {
2165         va_list ap;
2166
2167         va_start(ap, fmt);
2168         (void)printf("%d ", n);
2169         (void)vprintf(fmt, ap);
2170         (void)printf("\r\n");
2171         (void)fflush(stdout);
2172         if (ftpdebug) {
2173                 syslog(LOG_DEBUG, "<--- %d ", n);
2174                 vsyslog(LOG_DEBUG, fmt, ap);
2175         }
2176 }
2177
2178 void
2179 lreply(int n, const char *fmt, ...)
2180 {
2181         va_list ap;
2182
2183         va_start(ap, fmt);
2184         (void)printf("%d- ", n);
2185         (void)vprintf(fmt, ap);
2186         (void)printf("\r\n");
2187         (void)fflush(stdout);
2188         if (ftpdebug) {
2189                 syslog(LOG_DEBUG, "<--- %d- ", n);
2190                 vsyslog(LOG_DEBUG, fmt, ap);
2191         }
2192 }
2193
2194 static void
2195 ack(char *s)
2196 {
2197
2198         reply(250, "%s command successful.", s);
2199 }
2200
2201 void
2202 nack(char *s)
2203 {
2204
2205         reply(502, "%s command not implemented.", s);
2206 }
2207
2208 /* ARGSUSED */
2209 void
2210 yyerror(char *s)
2211 {
2212         char *cp;
2213
2214         if ((cp = strchr(cbuf,'\n')))
2215                 *cp = '\0';
2216         reply(500, "'%s': command not understood.", cbuf);
2217 }
2218
2219 void
2220 delete(char *name)
2221 {
2222         struct stat st;
2223
2224         LOGCMD("delete", name);
2225         if (stat(name, &st) < 0) {
2226                 perror_reply(550, name);
2227                 return;
2228         }
2229         if ((st.st_mode&S_IFMT) == S_IFDIR) {
2230                 if (rmdir(name) < 0) {
2231                         perror_reply(550, name);
2232                         return;
2233                 }
2234                 goto done;
2235         }
2236         if (unlink(name) < 0) {
2237                 perror_reply(550, name);
2238                 return;
2239         }
2240 done:
2241         ack("DELE");
2242 }
2243
2244 void
2245 cwd(char *path)
2246 {
2247
2248         if (chdir(path) < 0)
2249                 perror_reply(550, path);
2250         else
2251                 ack("CWD");
2252 }
2253
2254 void
2255 makedir(char *name)
2256 {
2257
2258         LOGCMD("mkdir", name);
2259         if (guest && noguestmkd)
2260                 reply(550, "%s: permission denied", name);
2261         else if (mkdir(name, 0777) < 0)
2262                 perror_reply(550, name);
2263         else
2264                 reply(257, "MKD command successful.");
2265 }
2266
2267 void
2268 removedir(char *name)
2269 {
2270
2271         LOGCMD("rmdir", name);
2272         if (rmdir(name) < 0)
2273                 perror_reply(550, name);
2274         else
2275                 ack("RMD");
2276 }
2277
2278 void
2279 pwd(void)
2280 {
2281         char path[MAXPATHLEN + 1];
2282
2283         if (getwd(path) == (char *)NULL)
2284                 reply(550, "%s.", path);
2285         else
2286                 reply(257, "\"%s\" is current directory.", path);
2287 }
2288
2289 char *
2290 renamefrom(char *name)
2291 {
2292         struct stat st;
2293
2294         if (stat(name, &st) < 0) {
2295                 perror_reply(550, name);
2296                 return ((char *)0);
2297         }
2298         reply(350, "File exists, ready for destination name");
2299         return (name);
2300 }
2301
2302 void
2303 renamecmd(char *from, char *to)
2304 {
2305         struct stat st;
2306
2307         LOGCMD2("rename", from, to);
2308
2309         if (guest && (stat(to, &st) == 0)) {
2310                 reply(550, "%s: permission denied", to);
2311                 return;
2312         }
2313
2314         if (rename(from, to) < 0)
2315                 perror_reply(550, "rename");
2316         else
2317                 ack("RNTO");
2318 }
2319
2320 static void
2321 dolog(struct sockaddr *who)
2322 {
2323         int error;
2324
2325         realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len);
2326
2327 #ifdef SETPROCTITLE
2328 #ifdef VIRTUAL_HOSTING
2329         if (thishost != firsthost)
2330                 snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
2331                          remotehost, hostname);
2332         else
2333 #endif
2334                 snprintf(proctitle, sizeof(proctitle), "%s: connected",
2335                          remotehost);
2336         setproctitle("%s", proctitle);
2337 #endif /* SETPROCTITLE */
2338
2339         if (logging) {
2340 #ifdef VIRTUAL_HOSTING
2341                 if (thishost != firsthost)
2342                         syslog(LOG_INFO, "connection from %s (to %s)",
2343                                remotehost, hostname);
2344                 else
2345 #endif
2346                 {
2347                         char    who_name[MAXHOSTNAMELEN];
2348
2349                         error = getnameinfo(who, who->sa_len,
2350                                             who_name, sizeof(who_name) - 1,
2351                                             NULL, 0, NI_NUMERICHOST);
2352                         syslog(LOG_INFO, "connection from %s (%s)", remotehost,
2353                                error == 0 ? who_name : "");
2354                 }
2355         }
2356 }
2357
2358 /*
2359  * Record logout in wtmp file
2360  * and exit with supplied status.
2361  */
2362 void
2363 dologout(int status)
2364 {
2365         /*
2366          * Prevent reception of SIGURG from resulting in a resumption
2367          * back to the main program loop.
2368          */
2369         transflag = 0;
2370
2371         if (logged_in) {
2372                 (void) seteuid((uid_t)0);
2373                 ftpd_logwtmp(ttyline, "", NULL);
2374         }
2375         /* beware of flushing buffers after a SIGPIPE */
2376         _exit(status);
2377 }
2378
2379 static void
2380 sigurg(int signo)
2381 {
2382
2383         recvurg = 1;
2384 }
2385
2386 static void
2387 myoob(void)
2388 {
2389         char *cp;
2390
2391         /* only process if transfer occurring */
2392         if (!transflag)
2393                 return;
2394         cp = tmpline;
2395         if (getline(cp, 7, stdin) == NULL) {
2396                 reply(221, "You could at least say goodbye.");
2397                 dologout(0);
2398         }
2399         upper(cp);
2400         if (strcmp(cp, "ABOR\r\n") == 0) {
2401                 tmpline[0] = '\0';
2402                 reply(426, "Transfer aborted. Data connection closed.");
2403                 reply(226, "Abort successful");
2404         }
2405         if (strcmp(cp, "STAT\r\n") == 0) {
2406                 tmpline[0] = '\0';
2407                 if (file_size != (off_t) -1)
2408                         reply(213, "Status: %qd of %qd bytes transferred",
2409                             byte_count, file_size);
2410                 else
2411                         reply(213, "Status: %qd bytes transferred", byte_count);
2412         }
2413 }
2414
2415 /*
2416  * Note: a response of 425 is not mentioned as a possible response to
2417  *      the PASV command in RFC959. However, it has been blessed as
2418  *      a legitimate response by Jon Postel in a telephone conversation
2419  *      with Rick Adams on 25 Jan 89.
2420  */
2421 void
2422 passive(void)
2423 {
2424         int len;
2425         char *p, *a;
2426
2427         if (pdata >= 0)         /* close old port if one set */
2428                 close(pdata);
2429
2430         pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2431         if (pdata < 0) {
2432                 perror_reply(425, "Can't open passive connection");
2433                 return;
2434         }
2435
2436         (void) seteuid((uid_t)0);
2437
2438 #ifdef IP_PORTRANGE
2439         if (ctrl_addr.su_family == AF_INET) {
2440             int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2441                                            : IP_PORTRANGE_DEFAULT;
2442
2443             if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2444                             (char *)&on, sizeof(on)) < 0)
2445                     goto pasv_error;
2446         }
2447 #endif
2448 #ifdef IPV6_PORTRANGE
2449         if (ctrl_addr.su_family == AF_INET6) {
2450             int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2451                                            : IPV6_PORTRANGE_DEFAULT;
2452
2453             if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2454                             (char *)&on, sizeof(on)) < 0)
2455                     goto pasv_error;
2456         }
2457 #endif
2458
2459         pasv_addr = ctrl_addr;
2460         pasv_addr.su_port = 0;
2461         if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2462                 goto pasv_error;
2463
2464         (void) seteuid((uid_t)pw->pw_uid);
2465
2466         len = sizeof(pasv_addr);
2467         if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2468                 goto pasv_error;
2469         if (listen(pdata, 1) < 0)
2470                 goto pasv_error;
2471         if (pasv_addr.su_family == AF_INET)
2472                 a = (char *) &pasv_addr.su_sin.sin_addr;
2473         else if (pasv_addr.su_family == AF_INET6 &&
2474                  IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr))
2475                 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2476         else
2477                 goto pasv_error;
2478                 
2479         p = (char *) &pasv_addr.su_port;
2480
2481 #define UC(b) (((int) b) & 0xff)
2482
2483         reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2484                 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2485         return;
2486
2487 pasv_error:
2488         (void) seteuid((uid_t)pw->pw_uid);
2489         (void) close(pdata);
2490         pdata = -1;
2491         perror_reply(425, "Can't open passive connection");
2492         return;
2493 }
2494
2495 /*
2496  * Long Passive defined in RFC 1639.
2497  *     228 Entering Long Passive Mode
2498  *         (af, hal, h1, h2, h3,..., pal, p1, p2...)
2499  */
2500
2501 void
2502 long_passive(char *cmd, int pf)
2503 {
2504         int len;
2505         char *p, *a;
2506
2507         if (pdata >= 0)         /* close old port if one set */
2508                 close(pdata);
2509
2510         if (pf != PF_UNSPEC) {
2511                 if (ctrl_addr.su_family != pf) {
2512                         switch (ctrl_addr.su_family) {
2513                         case AF_INET:
2514                                 pf = 1;
2515                                 break;
2516                         case AF_INET6:
2517                                 pf = 2;
2518                                 break;
2519                         default:
2520                                 pf = 0;
2521                                 break;
2522                         }
2523                         /*
2524                          * XXX
2525                          * only EPRT/EPSV ready clients will understand this
2526                          */
2527                         if (strcmp(cmd, "EPSV") == 0 && pf) {
2528                                 reply(522, "Network protocol mismatch, "
2529                                         "use (%d)", pf);
2530                         } else
2531                                 reply(501, "Network protocol mismatch"); /*XXX*/
2532
2533                         return;
2534                 }
2535         }
2536                 
2537         pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2538         if (pdata < 0) {
2539                 perror_reply(425, "Can't open passive connection");
2540                 return;
2541         }
2542
2543         (void) seteuid((uid_t)0);
2544
2545         pasv_addr = ctrl_addr;
2546         pasv_addr.su_port = 0;
2547         len = pasv_addr.su_len;
2548
2549 #ifdef IP_PORTRANGE
2550         if (ctrl_addr.su_family == AF_INET) {
2551             int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2552                                            : IP_PORTRANGE_DEFAULT;
2553
2554             if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2555                             (char *)&on, sizeof(on)) < 0)
2556                     goto pasv_error;
2557         }
2558 #endif
2559 #ifdef IPV6_PORTRANGE
2560         if (ctrl_addr.su_family == AF_INET6) {
2561             int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2562                                            : IPV6_PORTRANGE_DEFAULT;
2563
2564             if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2565                             (char *)&on, sizeof(on)) < 0)
2566                     goto pasv_error;
2567         }
2568 #endif
2569
2570         if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0)
2571                 goto pasv_error;
2572
2573         (void) seteuid((uid_t)pw->pw_uid);
2574
2575         if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2576                 goto pasv_error;
2577         if (listen(pdata, 1) < 0)
2578                 goto pasv_error;
2579
2580 #define UC(b) (((int) b) & 0xff)
2581
2582         if (strcmp(cmd, "LPSV") == 0) {
2583                 p = (char *)&pasv_addr.su_port;
2584                 switch (pasv_addr.su_family) {
2585                 case AF_INET:
2586                         a = (char *) &pasv_addr.su_sin.sin_addr;
2587                 v4_reply:
2588                         reply(228,
2589 "Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2590                               4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2591                               2, UC(p[0]), UC(p[1]));
2592                         return;
2593                 case AF_INET6:
2594                         if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) {
2595                                 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2596                                 goto v4_reply;
2597                         }
2598                         a = (char *) &pasv_addr.su_sin6.sin6_addr;
2599                         reply(228,
2600 "Entering Long Passive Mode "
2601 "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2602                               6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2603                               UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]),
2604                               UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
2605                               UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
2606                               2, UC(p[0]), UC(p[1]));
2607                         return;
2608                 }
2609         } else if (strcmp(cmd, "EPSV") == 0) {
2610                 switch (pasv_addr.su_family) {
2611                 case AF_INET:
2612                 case AF_INET6:
2613                         reply(229, "Entering Extended Passive Mode (|||%d|)",
2614                                 ntohs(pasv_addr.su_port));
2615                         return;
2616                 }
2617         } else {
2618                 /* more proper error code? */
2619         }
2620
2621 pasv_error:
2622         (void) seteuid((uid_t)pw->pw_uid);
2623         (void) close(pdata);
2624         pdata = -1;
2625         perror_reply(425, "Can't open passive connection");
2626         return;
2627 }
2628
2629 /*
2630  * Generate unique name for file with basename "local".
2631  * The file named "local" is already known to exist.
2632  * Generates failure reply on error.
2633  */
2634 static char *
2635 gunique(char *local)
2636 {
2637         static char new[MAXPATHLEN];
2638         struct stat st;
2639         int count;
2640         char *cp;
2641
2642         cp = strrchr(local, '/');
2643         if (cp)
2644                 *cp = '\0';
2645         if (stat(cp ? local : ".", &st) < 0) {
2646                 perror_reply(553, cp ? local : ".");
2647                 return ((char *) 0);
2648         }
2649         if (cp)
2650                 *cp = '/';
2651         /* -4 is for the .nn<null> we put on the end below */
2652         (void) snprintf(new, sizeof(new) - 4, "%s", local);
2653         cp = new + strlen(new);
2654         *cp++ = '.';
2655         for (count = 1; count < 100; count++) {
2656                 (void)sprintf(cp, "%d", count);
2657                 if (stat(new, &st) < 0)
2658                         return (new);
2659         }
2660         reply(452, "Unique file name cannot be created.");
2661         return (NULL);
2662 }
2663
2664 /*
2665  * Format and send reply containing system error number.
2666  */
2667 void
2668 perror_reply(int code, char *string)
2669 {
2670
2671         reply(code, "%s: %s.", string, strerror(errno));
2672 }
2673
2674 static char *onefile[] = {
2675         "",
2676         0
2677 };
2678
2679 void
2680 send_file_list(char *whichf)
2681 {
2682         struct stat st;
2683         DIR *dirp = NULL;
2684         struct dirent *dir;
2685         FILE *dout = NULL;
2686         char **dirlist, *dirname;
2687         int simple = 0;
2688         int freeglob = 0;
2689         glob_t gl;
2690
2691         if (strpbrk(whichf, "~{[*?") != NULL) {
2692                 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
2693
2694                 memset(&gl, 0, sizeof(gl));
2695                 gl.gl_matchc = MAXGLOBARGS;
2696                 flags |= GLOB_LIMIT;
2697                 freeglob = 1;
2698                 if (glob(whichf, flags, 0, &gl)) {
2699                         reply(550, "not found");
2700                         goto out;
2701                 } else if (gl.gl_pathc == 0) {
2702                         errno = ENOENT;
2703                         perror_reply(550, whichf);
2704                         goto out;
2705                 }
2706                 dirlist = gl.gl_pathv;
2707         } else {
2708                 onefile[0] = whichf;
2709                 dirlist = onefile;
2710                 simple = 1;
2711         }
2712
2713         while ((dirname = *dirlist++)) {
2714                 if (stat(dirname, &st) < 0) {
2715                         /*
2716                          * If user typed "ls -l", etc, and the client
2717                          * used NLST, do what the user meant.
2718                          */
2719                         if (dirname[0] == '-' && *dirlist == NULL &&
2720                             transflag == 0) {
2721                                 retrieve(_PATH_LS " %s", dirname);
2722                                 goto out;
2723                         }
2724                         perror_reply(550, whichf);
2725                         if (dout != NULL) {
2726                                 (void) fclose(dout);
2727                                 transflag = 0;
2728                                 data = -1;
2729                                 pdata = -1;
2730                         }
2731                         goto out;
2732                 }
2733
2734                 if (S_ISREG(st.st_mode)) {
2735                         if (dout == NULL) {
2736                                 dout = dataconn("file list", (off_t)-1, "w");
2737                                 if (dout == NULL)
2738                                         goto out;
2739                                 transflag++;
2740                         }
2741                         fprintf(dout, "%s%s\n", dirname,
2742                                 type == TYPE_A ? "\r" : "");
2743                         byte_count += strlen(dirname) + 1;
2744                         continue;
2745                 } else if (!S_ISDIR(st.st_mode))
2746                         continue;
2747
2748                 if ((dirp = opendir(dirname)) == NULL)
2749                         continue;
2750
2751                 while ((dir = readdir(dirp)) != NULL) {
2752                         char nbuf[MAXPATHLEN];
2753
2754                         if (recvurg) {
2755                                 myoob();
2756                                 recvurg = 0;
2757                                 transflag = 0;
2758                                 goto out;
2759                         }
2760
2761                         if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2762                                 continue;
2763                         if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2764                             dir->d_namlen == 2)
2765                                 continue;
2766
2767                         snprintf(nbuf, sizeof(nbuf),
2768                                 "%s/%s", dirname, dir->d_name);
2769
2770                         /*
2771                          * We have to do a stat to insure it's
2772                          * not a directory or special file.
2773                          */
2774                         if (simple || (stat(nbuf, &st) == 0 &&
2775                             S_ISREG(st.st_mode))) {
2776                                 if (dout == NULL) {
2777                                         dout = dataconn("file list", (off_t)-1,
2778                                                 "w");
2779                                         if (dout == NULL)
2780                                                 goto out;
2781                                         transflag++;
2782                                 }
2783                                 if (nbuf[0] == '.' && nbuf[1] == '/')
2784                                         fprintf(dout, "%s%s\n", &nbuf[2],
2785                                                 type == TYPE_A ? "\r" : "");
2786                                 else
2787                                         fprintf(dout, "%s%s\n", nbuf,
2788                                                 type == TYPE_A ? "\r" : "");
2789                                 byte_count += strlen(nbuf) + 1;
2790                         }
2791                 }
2792                 (void) closedir(dirp);
2793         }
2794
2795         if (dout == NULL)
2796                 reply(550, "No files found.");
2797         else if (ferror(dout) != 0)
2798                 perror_reply(550, "Data connection");
2799         else
2800                 reply(226, "Transfer complete.");
2801
2802         transflag = 0;
2803         if (dout != NULL)
2804                 (void) fclose(dout);
2805         data = -1;
2806         pdata = -1;
2807 out:
2808         if (freeglob) {
2809                 freeglob = 0;
2810                 globfree(&gl);
2811         }
2812 }
2813
2814 void
2815 reapchild(int signo)
2816 {
2817         while (wait3(NULL, WNOHANG, NULL) > 0);
2818 }
2819
2820 #ifdef OLD_SETPROCTITLE
2821 /*
2822  * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
2823  * Warning, since this is usually started from inetd.conf, it often doesn't
2824  * have much of an environment or arglist to overwrite.
2825  */
2826 void
2827 setproctitle(const char *fmt, ...)
2828 {
2829         int i;
2830         va_list ap;
2831         char *p, *bp, ch;
2832         char buf[LINE_MAX];
2833
2834         va_start(ap, fmt);
2835         (void)vsnprintf(buf, sizeof(buf), fmt, ap);
2836
2837         /* make ps print our process name */
2838         p = Argv[0];
2839         *p++ = '-';
2840
2841         i = strlen(buf);
2842         if (i > LastArgv - p - 2) {
2843                 i = LastArgv - p - 2;
2844                 buf[i] = '\0';
2845         }
2846         bp = buf;
2847         while (ch = *bp++)
2848                 if (ch != '\n' && ch != '\r')
2849                         *p++ = ch;
2850         while (p < LastArgv)
2851                 *p++ = ' ';
2852 }
2853 #endif /* OLD_SETPROCTITLE */
2854
2855 static void
2856 logxfer(char *name, off_t size, time_t start)
2857 {
2858         char buf[1024];
2859         char path[MAXPATHLEN + 1];
2860         time_t now;
2861
2862         if (statfd >= 0 && getwd(path) != NULL) {
2863                 time(&now);
2864                 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%qd!%ld\n",
2865                         ctime(&now)+4, ident, remotehost,
2866                         path, name, (long long)size,
2867                         (long)(now - start + (now == start)));
2868                 write(statfd, buf, strlen(buf));
2869         }
2870 }