]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - libexec/ftpd/ftpd.c
Cope with 2292bis-01 getaddrinfo (no NI_WITHSCOPEID, always attach
[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                         reply(226, "Transfer complete.");
1849                         return (0);
1850                 }
1851
1852 oldway:
1853                 if ((buf = malloc((u_int)blksize)) == NULL) {
1854                         transflag = 0;
1855                         perror_reply(451, "Local resource failure: malloc");
1856                         return (-1);
1857                 }
1858
1859                 while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 &&
1860                     write(netfd, buf, cnt) == cnt)
1861                         byte_count += cnt;
1862                 transflag = 0;
1863                 (void)free(buf);
1864                 if (cnt != 0) {
1865                         if (cnt < 0)
1866                                 goto file_err;
1867                         goto data_err;
1868                 }
1869                 reply(226, "Transfer complete.");
1870                 return (0);
1871         default:
1872                 transflag = 0;
1873                 reply(550, "Unimplemented TYPE %d in send_data", type);
1874                 return (-1);
1875         }
1876
1877 data_err:
1878         transflag = 0;
1879         perror_reply(426, "Data connection");
1880         return (-1);
1881
1882 file_err:
1883         transflag = 0;
1884         perror_reply(551, "Error on input file");
1885         return (-1);
1886
1887 got_oob:
1888         myoob();
1889         recvurg = 0;
1890         transflag = 0;
1891         return (-1);
1892 }
1893
1894 /*
1895  * Transfer data from peer to "outstr" using the appropriate encapulation of
1896  * the data subject to Mode, Structure, and Type.
1897  *
1898  * N.B.: Form isn't handled.
1899  */
1900 static int
1901 receive_data(FILE *instr, FILE *outstr)
1902 {
1903         int c;
1904         int cnt, bare_lfs;
1905         char buf[BUFSIZ];
1906
1907         transflag++;
1908         bare_lfs = 0;
1909
1910         switch (type) {
1911
1912         case TYPE_I:
1913         case TYPE_L:
1914                 while ((cnt = read(fileno(instr), buf, sizeof(buf))) > 0) {
1915                         if (recvurg)
1916                                 goto got_oob;
1917                         if (write(fileno(outstr), buf, cnt) != cnt)
1918                                 goto file_err;
1919                         byte_count += cnt;
1920                 }
1921                 if (recvurg)
1922                         goto got_oob;
1923                 if (cnt < 0)
1924                         goto data_err;
1925                 transflag = 0;
1926                 return (0);
1927
1928         case TYPE_E:
1929                 reply(553, "TYPE E not implemented.");
1930                 transflag = 0;
1931                 return (-1);
1932
1933         case TYPE_A:
1934                 while ((c = getc(instr)) != EOF) {
1935                         if (recvurg)
1936                                 goto got_oob;
1937                         byte_count++;
1938                         if (c == '\n')
1939                                 bare_lfs++;
1940                         while (c == '\r') {
1941                                 if (ferror(outstr))
1942                                         goto data_err;
1943                                 if ((c = getc(instr)) != '\n') {
1944                                         (void) putc ('\r', outstr);
1945                                         if (c == '\0' || c == EOF)
1946                                                 goto contin2;
1947                                 }
1948                         }
1949                         (void) putc(c, outstr);
1950         contin2:        ;
1951                 }
1952                 if (recvurg)
1953                         goto got_oob;
1954                 fflush(outstr);
1955                 if (ferror(instr))
1956                         goto data_err;
1957                 if (ferror(outstr))
1958                         goto file_err;
1959                 transflag = 0;
1960                 if (bare_lfs) {
1961                         lreply(226,
1962                 "WARNING! %d bare linefeeds received in ASCII mode",
1963                             bare_lfs);
1964                 (void)printf("   File may not have transferred correctly.\r\n");
1965                 }
1966                 return (0);
1967         default:
1968                 reply(550, "Unimplemented TYPE %d in receive_data", type);
1969                 transflag = 0;
1970                 return (-1);
1971         }
1972
1973 data_err:
1974         transflag = 0;
1975         perror_reply(426, "Data Connection");
1976         return (-1);
1977
1978 file_err:
1979         transflag = 0;
1980         perror_reply(452, "Error writing file");
1981         return (-1);
1982
1983 got_oob:
1984         myoob();
1985         recvurg = 0;
1986         transflag = 0;
1987         return (-1);
1988 }
1989
1990 void
1991 statfilecmd(char *filename)
1992 {
1993         FILE *fin;
1994         int c;
1995         char line[LINE_MAX];
1996
1997         (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
1998         fin = ftpd_popen(line, "r");
1999         lreply(211, "status of %s:", filename);
2000         while ((c = getc(fin)) != EOF) {
2001                 if (c == '\n') {
2002                         if (ferror(stdout)){
2003                                 perror_reply(421, "control connection");
2004                                 (void) ftpd_pclose(fin);
2005                                 dologout(1);
2006                                 /* NOTREACHED */
2007                         }
2008                         if (ferror(fin)) {
2009                                 perror_reply(551, filename);
2010                                 (void) ftpd_pclose(fin);
2011                                 return;
2012                         }
2013                         (void) putc('\r', stdout);
2014                 }
2015                 (void) putc(c, stdout);
2016         }
2017         (void) ftpd_pclose(fin);
2018         reply(211, "End of Status");
2019 }
2020
2021 void
2022 statcmd(void)
2023 {
2024         union sockunion *su;
2025         u_char *a, *p;
2026         char hname[NI_MAXHOST];
2027         int ispassive;
2028
2029         lreply(211, "%s FTP server status:", hostname, version);
2030         printf("     %s\r\n", version);
2031         printf("     Connected to %s", remotehost);
2032         if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
2033                          hname, sizeof(hname) - 1, NULL, 0, NI_NUMERICHOST)) {
2034                 if (strcmp(hname, remotehost) != 0)
2035                         printf(" (%s)", hname);
2036         }
2037         printf("\r\n");
2038         if (logged_in) {
2039                 if (guest)
2040                         printf("     Logged in anonymously\r\n");
2041                 else
2042                         printf("     Logged in as %s\r\n", pw->pw_name);
2043         } else if (askpasswd)
2044                 printf("     Waiting for password\r\n");
2045         else
2046                 printf("     Waiting for user name\r\n");
2047         printf("     TYPE: %s", typenames[type]);
2048         if (type == TYPE_A || type == TYPE_E)
2049                 printf(", FORM: %s", formnames[form]);
2050         if (type == TYPE_L)
2051 #if NBBY == 8
2052                 printf(" %d", NBBY);
2053 #else
2054                 printf(" %d", bytesize);        /* need definition! */
2055 #endif
2056         printf("; STRUcture: %s; transfer MODE: %s\r\n",
2057             strunames[stru], modenames[mode]);
2058         if (data != -1)
2059                 printf("     Data connection open\r\n");
2060         else if (pdata != -1) {
2061                 ispassive = 1;
2062                 su = &pasv_addr;
2063                 goto printaddr;
2064         } else if (usedefault == 0) {
2065                 ispassive = 0;
2066                 su = &data_dest;
2067 printaddr:
2068 #define UC(b) (((int) b) & 0xff)
2069                 if (epsvall) {
2070                         printf("     EPSV only mode (EPSV ALL)\r\n");
2071                         goto epsvonly;
2072                 }
2073
2074                 /* PORT/PASV */
2075                 if (su->su_family == AF_INET) {
2076                         a = (u_char *) &su->su_sin.sin_addr;
2077                         p = (u_char *) &su->su_sin.sin_port;
2078                         printf("     %s (%d,%d,%d,%d,%d,%d)\r\n",
2079                                 ispassive ? "PASV" : "PORT",
2080                                 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2081                                 UC(p[0]), UC(p[1]));
2082                 }
2083
2084                 /* LPRT/LPSV */
2085             {
2086                 int alen, af, i;
2087
2088                 switch (su->su_family) {
2089                 case AF_INET:
2090                         a = (u_char *) &su->su_sin.sin_addr;
2091                         p = (u_char *) &su->su_sin.sin_port;
2092                         alen = sizeof(su->su_sin.sin_addr);
2093                         af = 4;
2094                         break;
2095                 case AF_INET6:
2096                         a = (u_char *) &su->su_sin6.sin6_addr;
2097                         p = (u_char *) &su->su_sin6.sin6_port;
2098                         alen = sizeof(su->su_sin6.sin6_addr);
2099                         af = 6;
2100                         break;
2101                 default:
2102                         af = 0;
2103                         break;
2104                 }
2105                 if (af) {
2106                         printf("     %s (%d,%d,", ispassive ? "LPSV" : "LPRT",
2107                                 af, alen);
2108                         for (i = 0; i < alen; i++)
2109                                 printf("%d,", UC(a[i]));
2110                         printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1]));
2111                 }
2112             }
2113
2114 epsvonly:;
2115                 /* EPRT/EPSV */
2116             {
2117                 int af;
2118
2119                 switch (su->su_family) {
2120                 case AF_INET:
2121                         af = 1;
2122                         break;
2123                 case AF_INET6:
2124                         af = 2;
2125                         break;
2126                 default:
2127                         af = 0;
2128                         break;
2129                 }
2130                 if (af) {
2131                         union sockunion tmp;
2132
2133                         tmp = *su;
2134                         if (tmp.su_family == AF_INET6)
2135                                 tmp.su_sin6.sin6_scope_id = 0;
2136                         if (!getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
2137                                         hname, sizeof(hname) - 1, NULL, 0,
2138                                         NI_NUMERICHOST)) {
2139                                 printf("     %s |%d|%s|%d|\r\n",
2140                                         ispassive ? "EPSV" : "EPRT",
2141                                         af, hname, htons(tmp.su_port));
2142                         }
2143                 }
2144             }
2145 #undef UC
2146         } else
2147                 printf("     No data connection\r\n");
2148         reply(211, "End of status");
2149 }
2150
2151 void
2152 fatalerror(char *s)
2153 {
2154
2155         reply(451, "Error in server: %s\n", s);
2156         reply(221, "Closing connection due to server error.");
2157         dologout(0);
2158         /* NOTREACHED */
2159 }
2160
2161 void
2162 reply(int n, const char *fmt, ...)
2163 {
2164         va_list ap;
2165
2166         va_start(ap, fmt);
2167         (void)printf("%d ", n);
2168         (void)vprintf(fmt, ap);
2169         (void)printf("\r\n");
2170         (void)fflush(stdout);
2171         if (ftpdebug) {
2172                 syslog(LOG_DEBUG, "<--- %d ", n);
2173                 vsyslog(LOG_DEBUG, fmt, ap);
2174         }
2175 }
2176
2177 void
2178 lreply(int n, const char *fmt, ...)
2179 {
2180         va_list ap;
2181
2182         va_start(ap, fmt);
2183         (void)printf("%d- ", n);
2184         (void)vprintf(fmt, ap);
2185         (void)printf("\r\n");
2186         (void)fflush(stdout);
2187         if (ftpdebug) {
2188                 syslog(LOG_DEBUG, "<--- %d- ", n);
2189                 vsyslog(LOG_DEBUG, fmt, ap);
2190         }
2191 }
2192
2193 static void
2194 ack(char *s)
2195 {
2196
2197         reply(250, "%s command successful.", s);
2198 }
2199
2200 void
2201 nack(char *s)
2202 {
2203
2204         reply(502, "%s command not implemented.", s);
2205 }
2206
2207 /* ARGSUSED */
2208 void
2209 yyerror(char *s)
2210 {
2211         char *cp;
2212
2213         if ((cp = strchr(cbuf,'\n')))
2214                 *cp = '\0';
2215         reply(500, "'%s': command not understood.", cbuf);
2216 }
2217
2218 void
2219 delete(char *name)
2220 {
2221         struct stat st;
2222
2223         LOGCMD("delete", name);
2224         if (stat(name, &st) < 0) {
2225                 perror_reply(550, name);
2226                 return;
2227         }
2228         if ((st.st_mode&S_IFMT) == S_IFDIR) {
2229                 if (rmdir(name) < 0) {
2230                         perror_reply(550, name);
2231                         return;
2232                 }
2233                 goto done;
2234         }
2235         if (unlink(name) < 0) {
2236                 perror_reply(550, name);
2237                 return;
2238         }
2239 done:
2240         ack("DELE");
2241 }
2242
2243 void
2244 cwd(char *path)
2245 {
2246
2247         if (chdir(path) < 0)
2248                 perror_reply(550, path);
2249         else
2250                 ack("CWD");
2251 }
2252
2253 void
2254 makedir(char *name)
2255 {
2256
2257         LOGCMD("mkdir", name);
2258         if (guest && noguestmkd)
2259                 reply(550, "%s: permission denied", name);
2260         else if (mkdir(name, 0777) < 0)
2261                 perror_reply(550, name);
2262         else
2263                 reply(257, "MKD command successful.");
2264 }
2265
2266 void
2267 removedir(char *name)
2268 {
2269
2270         LOGCMD("rmdir", name);
2271         if (rmdir(name) < 0)
2272                 perror_reply(550, name);
2273         else
2274                 ack("RMD");
2275 }
2276
2277 void
2278 pwd(void)
2279 {
2280         char path[MAXPATHLEN + 1];
2281
2282         if (getwd(path) == (char *)NULL)
2283                 reply(550, "%s.", path);
2284         else
2285                 reply(257, "\"%s\" is current directory.", path);
2286 }
2287
2288 char *
2289 renamefrom(char *name)
2290 {
2291         struct stat st;
2292
2293         if (stat(name, &st) < 0) {
2294                 perror_reply(550, name);
2295                 return ((char *)0);
2296         }
2297         reply(350, "File exists, ready for destination name");
2298         return (name);
2299 }
2300
2301 void
2302 renamecmd(char *from, char *to)
2303 {
2304         struct stat st;
2305
2306         LOGCMD2("rename", from, to);
2307
2308         if (guest && (stat(to, &st) == 0)) {
2309                 reply(550, "%s: permission denied", to);
2310                 return;
2311         }
2312
2313         if (rename(from, to) < 0)
2314                 perror_reply(550, "rename");
2315         else
2316                 ack("RNTO");
2317 }
2318
2319 static void
2320 dolog(struct sockaddr *who)
2321 {
2322         int error;
2323
2324         realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len);
2325
2326 #ifdef SETPROCTITLE
2327 #ifdef VIRTUAL_HOSTING
2328         if (thishost != firsthost)
2329                 snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
2330                          remotehost, hostname);
2331         else
2332 #endif
2333                 snprintf(proctitle, sizeof(proctitle), "%s: connected",
2334                          remotehost);
2335         setproctitle("%s", proctitle);
2336 #endif /* SETPROCTITLE */
2337
2338         if (logging) {
2339 #ifdef VIRTUAL_HOSTING
2340                 if (thishost != firsthost)
2341                         syslog(LOG_INFO, "connection from %s (to %s)",
2342                                remotehost, hostname);
2343                 else
2344 #endif
2345                 {
2346                         char    who_name[MAXHOSTNAMELEN];
2347
2348                         error = getnameinfo(who, who->sa_len,
2349                                             who_name, sizeof(who_name) - 1,
2350                                             NULL, 0, NI_NUMERICHOST);
2351                         syslog(LOG_INFO, "connection from %s (%s)", remotehost,
2352                                error == 0 ? who_name : "");
2353                 }
2354         }
2355 }
2356
2357 /*
2358  * Record logout in wtmp file
2359  * and exit with supplied status.
2360  */
2361 void
2362 dologout(int status)
2363 {
2364         /*
2365          * Prevent reception of SIGURG from resulting in a resumption
2366          * back to the main program loop.
2367          */
2368         transflag = 0;
2369
2370         if (logged_in) {
2371                 (void) seteuid((uid_t)0);
2372                 ftpd_logwtmp(ttyline, "", NULL);
2373         }
2374         /* beware of flushing buffers after a SIGPIPE */
2375         _exit(status);
2376 }
2377
2378 static void
2379 sigurg(int signo)
2380 {
2381
2382         recvurg = 1;
2383 }
2384
2385 static void
2386 myoob(void)
2387 {
2388         char *cp;
2389
2390         /* only process if transfer occurring */
2391         if (!transflag)
2392                 return;
2393         cp = tmpline;
2394         if (getline(cp, 7, stdin) == NULL) {
2395                 reply(221, "You could at least say goodbye.");
2396                 dologout(0);
2397         }
2398         upper(cp);
2399         if (strcmp(cp, "ABOR\r\n") == 0) {
2400                 tmpline[0] = '\0';
2401                 reply(426, "Transfer aborted. Data connection closed.");
2402                 reply(226, "Abort successful");
2403         }
2404         if (strcmp(cp, "STAT\r\n") == 0) {
2405                 tmpline[0] = '\0';
2406                 if (file_size != (off_t) -1)
2407                         reply(213, "Status: %qd of %qd bytes transferred",
2408                             byte_count, file_size);
2409                 else
2410                         reply(213, "Status: %qd bytes transferred", byte_count);
2411         }
2412 }
2413
2414 /*
2415  * Note: a response of 425 is not mentioned as a possible response to
2416  *      the PASV command in RFC959. However, it has been blessed as
2417  *      a legitimate response by Jon Postel in a telephone conversation
2418  *      with Rick Adams on 25 Jan 89.
2419  */
2420 void
2421 passive(void)
2422 {
2423         int len;
2424         char *p, *a;
2425
2426         if (pdata >= 0)         /* close old port if one set */
2427                 close(pdata);
2428
2429         pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2430         if (pdata < 0) {
2431                 perror_reply(425, "Can't open passive connection");
2432                 return;
2433         }
2434
2435         (void) seteuid((uid_t)0);
2436
2437 #ifdef IP_PORTRANGE
2438         if (ctrl_addr.su_family == AF_INET) {
2439             int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2440                                            : IP_PORTRANGE_DEFAULT;
2441
2442             if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2443                             (char *)&on, sizeof(on)) < 0)
2444                     goto pasv_error;
2445         }
2446 #endif
2447 #ifdef IPV6_PORTRANGE
2448         if (ctrl_addr.su_family == AF_INET6) {
2449             int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2450                                            : IPV6_PORTRANGE_DEFAULT;
2451
2452             if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2453                             (char *)&on, sizeof(on)) < 0)
2454                     goto pasv_error;
2455         }
2456 #endif
2457
2458         pasv_addr = ctrl_addr;
2459         pasv_addr.su_port = 0;
2460         if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2461                 goto pasv_error;
2462
2463         (void) seteuid((uid_t)pw->pw_uid);
2464
2465         len = sizeof(pasv_addr);
2466         if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2467                 goto pasv_error;
2468         if (listen(pdata, 1) < 0)
2469                 goto pasv_error;
2470         if (pasv_addr.su_family == AF_INET)
2471                 a = (char *) &pasv_addr.su_sin.sin_addr;
2472         else if (pasv_addr.su_family == AF_INET6 &&
2473                  IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr))
2474                 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2475         else
2476                 goto pasv_error;
2477                 
2478         p = (char *) &pasv_addr.su_port;
2479
2480 #define UC(b) (((int) b) & 0xff)
2481
2482         reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2483                 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2484         return;
2485
2486 pasv_error:
2487         (void) seteuid((uid_t)pw->pw_uid);
2488         (void) close(pdata);
2489         pdata = -1;
2490         perror_reply(425, "Can't open passive connection");
2491         return;
2492 }
2493
2494 /*
2495  * Long Passive defined in RFC 1639.
2496  *     228 Entering Long Passive Mode
2497  *         (af, hal, h1, h2, h3,..., pal, p1, p2...)
2498  */
2499
2500 void
2501 long_passive(char *cmd, int pf)
2502 {
2503         int len;
2504         char *p, *a;
2505
2506         if (pdata >= 0)         /* close old port if one set */
2507                 close(pdata);
2508
2509         if (pf != PF_UNSPEC) {
2510                 if (ctrl_addr.su_family != pf) {
2511                         switch (ctrl_addr.su_family) {
2512                         case AF_INET:
2513                                 pf = 1;
2514                                 break;
2515                         case AF_INET6:
2516                                 pf = 2;
2517                                 break;
2518                         default:
2519                                 pf = 0;
2520                                 break;
2521                         }
2522                         /*
2523                          * XXX
2524                          * only EPRT/EPSV ready clients will understand this
2525                          */
2526                         if (strcmp(cmd, "EPSV") == 0 && pf) {
2527                                 reply(522, "Network protocol mismatch, "
2528                                         "use (%d)", pf);
2529                         } else
2530                                 reply(501, "Network protocol mismatch"); /*XXX*/
2531
2532                         return;
2533                 }
2534         }
2535                 
2536         pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2537         if (pdata < 0) {
2538                 perror_reply(425, "Can't open passive connection");
2539                 return;
2540         }
2541
2542         (void) seteuid((uid_t)0);
2543
2544         pasv_addr = ctrl_addr;
2545         pasv_addr.su_port = 0;
2546         len = pasv_addr.su_len;
2547
2548 #ifdef IP_PORTRANGE
2549         if (ctrl_addr.su_family == AF_INET) {
2550             int on = restricted_data_ports ? IP_PORTRANGE_HIGH
2551                                            : IP_PORTRANGE_DEFAULT;
2552
2553             if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2554                             (char *)&on, sizeof(on)) < 0)
2555                     goto pasv_error;
2556         }
2557 #endif
2558 #ifdef IPV6_PORTRANGE
2559         if (ctrl_addr.su_family == AF_INET6) {
2560             int on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2561                                            : IPV6_PORTRANGE_DEFAULT;
2562
2563             if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2564                             (char *)&on, sizeof(on)) < 0)
2565                     goto pasv_error;
2566         }
2567 #endif
2568
2569         if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0)
2570                 goto pasv_error;
2571
2572         (void) seteuid((uid_t)pw->pw_uid);
2573
2574         if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2575                 goto pasv_error;
2576         if (listen(pdata, 1) < 0)
2577                 goto pasv_error;
2578
2579 #define UC(b) (((int) b) & 0xff)
2580
2581         if (strcmp(cmd, "LPSV") == 0) {
2582                 p = (char *)&pasv_addr.su_port;
2583                 switch (pasv_addr.su_family) {
2584                 case AF_INET:
2585                         a = (char *) &pasv_addr.su_sin.sin_addr;
2586                 v4_reply:
2587                         reply(228,
2588 "Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2589                               4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2590                               2, UC(p[0]), UC(p[1]));
2591                         return;
2592                 case AF_INET6:
2593                         if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) {
2594                                 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2595                                 goto v4_reply;
2596                         }
2597                         a = (char *) &pasv_addr.su_sin6.sin6_addr;
2598                         reply(228,
2599 "Entering Long Passive Mode "
2600 "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2601                               6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2602                               UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]),
2603                               UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
2604                               UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
2605                               2, UC(p[0]), UC(p[1]));
2606                         return;
2607                 }
2608         } else if (strcmp(cmd, "EPSV") == 0) {
2609                 switch (pasv_addr.su_family) {
2610                 case AF_INET:
2611                 case AF_INET6:
2612                         reply(229, "Entering Extended Passive Mode (|||%d|)",
2613                                 ntohs(pasv_addr.su_port));
2614                         return;
2615                 }
2616         } else {
2617                 /* more proper error code? */
2618         }
2619
2620 pasv_error:
2621         (void) seteuid((uid_t)pw->pw_uid);
2622         (void) close(pdata);
2623         pdata = -1;
2624         perror_reply(425, "Can't open passive connection");
2625         return;
2626 }
2627
2628 /*
2629  * Generate unique name for file with basename "local".
2630  * The file named "local" is already known to exist.
2631  * Generates failure reply on error.
2632  */
2633 static char *
2634 gunique(char *local)
2635 {
2636         static char new[MAXPATHLEN];
2637         struct stat st;
2638         int count;
2639         char *cp;
2640
2641         cp = strrchr(local, '/');
2642         if (cp)
2643                 *cp = '\0';
2644         if (stat(cp ? local : ".", &st) < 0) {
2645                 perror_reply(553, cp ? local : ".");
2646                 return ((char *) 0);
2647         }
2648         if (cp)
2649                 *cp = '/';
2650         /* -4 is for the .nn<null> we put on the end below */
2651         (void) snprintf(new, sizeof(new) - 4, "%s", local);
2652         cp = new + strlen(new);
2653         *cp++ = '.';
2654         for (count = 1; count < 100; count++) {
2655                 (void)sprintf(cp, "%d", count);
2656                 if (stat(new, &st) < 0)
2657                         return (new);
2658         }
2659         reply(452, "Unique file name cannot be created.");
2660         return (NULL);
2661 }
2662
2663 /*
2664  * Format and send reply containing system error number.
2665  */
2666 void
2667 perror_reply(int code, char *string)
2668 {
2669
2670         reply(code, "%s: %s.", string, strerror(errno));
2671 }
2672
2673 static char *onefile[] = {
2674         "",
2675         0
2676 };
2677
2678 void
2679 send_file_list(char *whichf)
2680 {
2681         struct stat st;
2682         DIR *dirp = NULL;
2683         struct dirent *dir;
2684         FILE *dout = NULL;
2685         char **dirlist, *dirname;
2686         int simple = 0;
2687         int freeglob = 0;
2688         glob_t gl;
2689
2690         if (strpbrk(whichf, "~{[*?") != NULL) {
2691                 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_QUOTE|GLOB_TILDE;
2692
2693                 memset(&gl, 0, sizeof(gl));
2694                 gl.gl_matchc = MAXGLOBARGS;
2695                 flags |= GLOB_LIMIT;
2696                 freeglob = 1;
2697                 if (glob(whichf, flags, 0, &gl)) {
2698                         reply(550, "not found");
2699                         goto out;
2700                 } else if (gl.gl_pathc == 0) {
2701                         errno = ENOENT;
2702                         perror_reply(550, whichf);
2703                         goto out;
2704                 }
2705                 dirlist = gl.gl_pathv;
2706         } else {
2707                 onefile[0] = whichf;
2708                 dirlist = onefile;
2709                 simple = 1;
2710         }
2711
2712         while ((dirname = *dirlist++)) {
2713                 if (stat(dirname, &st) < 0) {
2714                         /*
2715                          * If user typed "ls -l", etc, and the client
2716                          * used NLST, do what the user meant.
2717                          */
2718                         if (dirname[0] == '-' && *dirlist == NULL &&
2719                             transflag == 0) {
2720                                 retrieve(_PATH_LS " %s", dirname);
2721                                 goto out;
2722                         }
2723                         perror_reply(550, whichf);
2724                         if (dout != NULL) {
2725                                 (void) fclose(dout);
2726                                 transflag = 0;
2727                                 data = -1;
2728                                 pdata = -1;
2729                         }
2730                         goto out;
2731                 }
2732
2733                 if (S_ISREG(st.st_mode)) {
2734                         if (dout == NULL) {
2735                                 dout = dataconn("file list", (off_t)-1, "w");
2736                                 if (dout == NULL)
2737                                         goto out;
2738                                 transflag++;
2739                         }
2740                         fprintf(dout, "%s%s\n", dirname,
2741                                 type == TYPE_A ? "\r" : "");
2742                         byte_count += strlen(dirname) + 1;
2743                         continue;
2744                 } else if (!S_ISDIR(st.st_mode))
2745                         continue;
2746
2747                 if ((dirp = opendir(dirname)) == NULL)
2748                         continue;
2749
2750                 while ((dir = readdir(dirp)) != NULL) {
2751                         char nbuf[MAXPATHLEN];
2752
2753                         if (recvurg) {
2754                                 myoob();
2755                                 recvurg = 0;
2756                                 transflag = 0;
2757                                 goto out;
2758                         }
2759
2760                         if (dir->d_name[0] == '.' && dir->d_namlen == 1)
2761                                 continue;
2762                         if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
2763                             dir->d_namlen == 2)
2764                                 continue;
2765
2766                         snprintf(nbuf, sizeof(nbuf),
2767                                 "%s/%s", dirname, dir->d_name);
2768
2769                         /*
2770                          * We have to do a stat to insure it's
2771                          * not a directory or special file.
2772                          */
2773                         if (simple || (stat(nbuf, &st) == 0 &&
2774                             S_ISREG(st.st_mode))) {
2775                                 if (dout == NULL) {
2776                                         dout = dataconn("file list", (off_t)-1,
2777                                                 "w");
2778                                         if (dout == NULL)
2779                                                 goto out;
2780                                         transflag++;
2781                                 }
2782                                 if (nbuf[0] == '.' && nbuf[1] == '/')
2783                                         fprintf(dout, "%s%s\n", &nbuf[2],
2784                                                 type == TYPE_A ? "\r" : "");
2785                                 else
2786                                         fprintf(dout, "%s%s\n", nbuf,
2787                                                 type == TYPE_A ? "\r" : "");
2788                                 byte_count += strlen(nbuf) + 1;
2789                         }
2790                 }
2791                 (void) closedir(dirp);
2792         }
2793
2794         if (dout == NULL)
2795                 reply(550, "No files found.");
2796         else if (ferror(dout) != 0)
2797                 perror_reply(550, "Data connection");
2798         else
2799                 reply(226, "Transfer complete.");
2800
2801         transflag = 0;
2802         if (dout != NULL)
2803                 (void) fclose(dout);
2804         data = -1;
2805         pdata = -1;
2806 out:
2807         if (freeglob) {
2808                 freeglob = 0;
2809                 globfree(&gl);
2810         }
2811 }
2812
2813 void
2814 reapchild(int signo)
2815 {
2816         while (wait3(NULL, WNOHANG, NULL) > 0);
2817 }
2818
2819 #ifdef OLD_SETPROCTITLE
2820 /*
2821  * Clobber argv so ps will show what we're doing.  (Stolen from sendmail.)
2822  * Warning, since this is usually started from inetd.conf, it often doesn't
2823  * have much of an environment or arglist to overwrite.
2824  */
2825 void
2826 setproctitle(const char *fmt, ...)
2827 {
2828         int i;
2829         va_list ap;
2830         char *p, *bp, ch;
2831         char buf[LINE_MAX];
2832
2833         va_start(ap, fmt);
2834         (void)vsnprintf(buf, sizeof(buf), fmt, ap);
2835
2836         /* make ps print our process name */
2837         p = Argv[0];
2838         *p++ = '-';
2839
2840         i = strlen(buf);
2841         if (i > LastArgv - p - 2) {
2842                 i = LastArgv - p - 2;
2843                 buf[i] = '\0';
2844         }
2845         bp = buf;
2846         while (ch = *bp++)
2847                 if (ch != '\n' && ch != '\r')
2848                         *p++ = ch;
2849         while (p < LastArgv)
2850                 *p++ = ' ';
2851 }
2852 #endif /* OLD_SETPROCTITLE */
2853
2854 static void
2855 logxfer(char *name, off_t size, time_t start)
2856 {
2857         char buf[1024];
2858         char path[MAXPATHLEN + 1];
2859         time_t now;
2860
2861         if (statfd >= 0 && getwd(path) != NULL) {
2862                 time(&now);
2863                 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s/%s!%qd!%ld\n",
2864                         ctime(&now)+4, ident, remotehost,
2865                         path, name, (long long)size,
2866                         (long)(now - start + (now == start)));
2867                 write(statfd, buf, strlen(buf));
2868         }
2869 }