]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - libexec/ftpd/ftpd.c
Add UPDATING entries and bump version.
[FreeBSD/FreeBSD.git] / libexec / ftpd / ftpd.c
1 /*-
2  * SPDX-License-Identifier: BSD-3-Clause
3  *
4  * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
5  *      The Regents of the University of California.  All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. Neither the name of the University nor the names of its contributors
16  *    may be used to endorse or promote products derived from this software
17  *    without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29  * SUCH DAMAGE.
30  */
31
32 #if 0
33 #ifndef lint
34 static char copyright[] =
35 "@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\
36         The Regents of the University of California.  All rights reserved.\n";
37 #endif /* not lint */
38 #endif
39
40 #ifndef lint
41 #if 0
42 static char sccsid[] = "@(#)ftpd.c      8.4 (Berkeley) 4/16/94";
43 #endif
44 #endif /* not lint */
45
46 #include <sys/cdefs.h>
47 __FBSDID("$FreeBSD$");
48
49 /*
50  * FTP server.
51  */
52 #include <sys/param.h>
53 #include <sys/ioctl.h>
54 #include <sys/mman.h>
55 #include <sys/socket.h>
56 #include <sys/stat.h>
57 #include <sys/time.h>
58 #include <sys/wait.h>
59
60 #include <netinet/in.h>
61 #include <netinet/in_systm.h>
62 #include <netinet/ip.h>
63 #include <netinet/tcp.h>
64
65 #define FTP_NAMES
66 #include <arpa/ftp.h>
67 #include <arpa/inet.h>
68 #include <arpa/telnet.h>
69
70 #include <ctype.h>
71 #include <dirent.h>
72 #include <err.h>
73 #include <errno.h>
74 #include <fcntl.h>
75 #include <glob.h>
76 #include <limits.h>
77 #include <netdb.h>
78 #include <pwd.h>
79 #include <grp.h>
80 #include <opie.h>
81 #include <signal.h>
82 #include <stdint.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 "blacklist_client.h"
99 #include "pathnames.h"
100 #include "extern.h"
101
102 #include <stdarg.h>
103
104 static char version[] = "Version 6.00LS";
105 #undef main
106
107 union sockunion ctrl_addr;
108 union sockunion data_source;
109 union sockunion data_dest;
110 union sockunion his_addr;
111 union sockunion pasv_addr;
112
113 int     daemon_mode;
114 int     data;
115 int     dataport;
116 int     hostinfo = 1;   /* print host-specific info in messages */
117 int     logged_in;
118 struct  passwd *pw;
119 char    *homedir;
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     assumeutf8 = 0;   /* Assume that server file names are in UTF-8 */
128 int     guest;
129 int     dochroot;
130 char    *chrootdir;
131 int     dowtmp = 1;
132 int     stats;
133 int     statfd = -1;
134 int     type;
135 int     form;
136 int     stru;                   /* avoid C keyword */
137 int     mode;
138 int     usedefault = 1;         /* for data transfers */
139 int     pdata = -1;             /* for passive mode */
140 int     readonly = 0;           /* Server is in readonly mode.  */
141 int     noepsv = 0;             /* EPSV command is disabled.    */
142 int     noretr = 0;             /* RETR command is disabled.    */
143 int     noguestretr = 0;        /* RETR command is disabled for anon users. */
144 int     noguestmkd = 0;         /* MKD command is disabled for anon users. */
145 int     noguestmod = 1;         /* anon users may not modify existing files. */
146 int     use_blacklist = 0;
147
148 off_t   file_size;
149 off_t   byte_count;
150 #if !defined(CMASK) || CMASK == 0
151 #undef CMASK
152 #define CMASK 027
153 #endif
154 int     defumask = CMASK;               /* default umask value */
155 char    tmpline[7];
156 char    *hostname;
157 int     epsvall = 0;
158
159 #ifdef VIRTUAL_HOSTING
160 char    *ftpuser;
161
162 static struct ftphost {
163         struct ftphost  *next;
164         struct addrinfo *hostinfo;
165         char            *hostname;
166         char            *anonuser;
167         char            *statfile;
168         char            *welcome;
169         char            *loginmsg;
170 } *thishost, *firsthost;
171
172 #endif
173 char    remotehost[NI_MAXHOST];
174 char    *ident = NULL;
175
176 static char     wtmpid[20];
177
178 #ifdef USE_PAM
179 static int      auth_pam(struct passwd**, const char*);
180 pam_handle_t    *pamh = NULL;
181 #endif
182
183 static struct opie      opiedata;
184 static char             opieprompt[OPIE_CHALLENGE_MAX+1];
185 static int              pwok;
186
187 char    *pid_file = NULL; /* means default location to pidfile(3) */
188
189 /*
190  * Limit number of pathnames that glob can return.
191  * A limit of 0 indicates the number of pathnames is unlimited.
192  */
193 #define MAXGLOBARGS     16384
194 #
195
196 /*
197  * Timeout intervals for retrying connections
198  * to hosts that don't accept PORT cmds.  This
199  * is a kludge, but given the problems with TCP...
200  */
201 #define SWAITMAX        90      /* wait at most 90 seconds */
202 #define SWAITINT        5       /* interval between retries */
203
204 int     swaitmax = SWAITMAX;
205 int     swaitint = SWAITINT;
206
207 #ifdef SETPROCTITLE
208 char    proctitle[LINE_MAX];    /* initial part of title */
209 #endif /* SETPROCTITLE */
210
211 #define LOGCMD(cmd, file)               logcmd((cmd), (file), NULL, -1)
212 #define LOGCMD2(cmd, file1, file2)      logcmd((cmd), (file1), (file2), -1)
213 #define LOGBYTES(cmd, file, cnt)        logcmd((cmd), (file), NULL, (cnt))
214
215 static  volatile sig_atomic_t recvurg;
216 static  int transflag;          /* NB: for debugging only */
217
218 #define STARTXFER       flagxfer(1)
219 #define ENDXFER         flagxfer(0)
220
221 #define START_UNSAFE    maskurg(1)
222 #define END_UNSAFE      maskurg(0)
223
224 /* It's OK to put an `else' clause after this macro. */
225 #define CHECKOOB(action)                                                \
226         if (recvurg) {                                                  \
227                 recvurg = 0;                                            \
228                 if (myoob()) {                                          \
229                         ENDXFER;                                        \
230                         action;                                         \
231                 }                                                       \
232         }
233
234 #ifdef VIRTUAL_HOSTING
235 static void      inithosts(int);
236 static void      selecthost(union sockunion *);
237 #endif
238 static void      ack(char *);
239 static void      sigurg(int);
240 static void      maskurg(int);
241 static void      flagxfer(int);
242 static int       myoob(void);
243 static int       checkuser(char *, char *, int, char **, int *);
244 static FILE     *dataconn(char *, off_t, char *);
245 static void      dolog(struct sockaddr *);
246 static void      end_login(void);
247 static FILE     *getdatasock(char *);
248 static int       guniquefd(char *, char **);
249 static void      lostconn(int);
250 static void      sigquit(int);
251 static int       receive_data(FILE *, FILE *);
252 static int       send_data(FILE *, FILE *, size_t, off_t, int);
253 static struct passwd *
254                  sgetpwnam(char *);
255 static char     *sgetsave(char *);
256 static void      reapchild(int);
257 static void      appendf(char **, char *, ...) __printflike(2, 3);
258 static void      logcmd(char *, char *, char *, off_t);
259 static void      logxfer(char *, off_t, time_t);
260 static char     *doublequote(char *);
261 static int      *socksetup(int, char *, const char *);
262
263 int
264 main(int argc, char *argv[], char **envp)
265 {
266         socklen_t addrlen;
267         int ch, on = 1, tos, s = STDIN_FILENO;
268         char *cp, line[LINE_MAX];
269         FILE *fd;
270         char    *bindname = NULL;
271         const char *bindport = "ftp";
272         int     family = AF_UNSPEC;
273         struct sigaction sa;
274
275         tzset();                /* in case no timezone database in ~ftp */
276         sigemptyset(&sa.sa_mask);
277         sa.sa_flags = SA_RESTART;
278
279         /*
280          * Prevent diagnostic messages from appearing on stderr.
281          * We run as a daemon or from inetd; in both cases, there's
282          * more reason in logging to syslog.
283          */
284         (void) freopen(_PATH_DEVNULL, "w", stderr);
285         opterr = 0;
286
287         /*
288          * LOG_NDELAY sets up the logging connection immediately,
289          * necessary for anonymous ftp's that chroot and can't do it later.
290          */
291         openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
292
293         while ((ch = getopt(argc, argv,
294                             "468a:ABdDEhlmMoOp:P:rRSt:T:u:UvW")) != -1) {
295                 switch (ch) {
296                 case '4':
297                         family = (family == AF_INET6) ? AF_UNSPEC : AF_INET;
298                         break;
299
300                 case '6':
301                         family = (family == AF_INET) ? AF_UNSPEC : AF_INET6;
302                         break;
303
304                 case '8':
305                         assumeutf8 = 1;
306                         break;
307
308                 case 'a':
309                         bindname = optarg;
310                         break;
311
312                 case 'A':
313                         anon_only = 1;
314                         break;
315
316                 case 'B':
317 #ifdef USE_BLACKLIST
318                         use_blacklist = 1;
319 #else
320                         syslog(LOG_WARNING, "not compiled with USE_BLACKLIST support");
321 #endif
322                         break;
323
324                 case 'd':
325                         ftpdebug++;
326                         break;
327
328                 case 'D':
329                         daemon_mode++;
330                         break;
331
332                 case 'E':
333                         noepsv = 1;
334                         break;
335
336                 case 'h':
337                         hostinfo = 0;
338                         break;
339
340                 case 'l':
341                         logging++;      /* > 1 == extra logging */
342                         break;
343
344                 case 'm':
345                         noguestmod = 0;
346                         break;
347
348                 case 'M':
349                         noguestmkd = 1;
350                         break;
351
352                 case 'o':
353                         noretr = 1;
354                         break;
355
356                 case 'O':
357                         noguestretr = 1;
358                         break;
359
360                 case 'p':
361                         pid_file = optarg;
362                         break;
363
364                 case 'P':
365                         bindport = optarg;
366                         break;
367
368                 case 'r':
369                         readonly = 1;
370                         break;
371
372                 case 'R':
373                         paranoid = 0;
374                         break;
375
376                 case 'S':
377                         stats++;
378                         break;
379
380                 case 't':
381                         timeout = atoi(optarg);
382                         if (maxtimeout < timeout)
383                                 maxtimeout = timeout;
384                         break;
385
386                 case 'T':
387                         maxtimeout = atoi(optarg);
388                         if (timeout > maxtimeout)
389                                 timeout = maxtimeout;
390                         break;
391
392                 case 'u':
393                     {
394                         long val = 0;
395
396                         val = strtol(optarg, &optarg, 8);
397                         if (*optarg != '\0' || val < 0)
398                                 syslog(LOG_WARNING, "bad value for -u");
399                         else
400                                 defumask = val;
401                         break;
402                     }
403                 case 'U':
404                         restricted_data_ports = 0;
405                         break;
406
407                 case 'v':
408                         ftpdebug++;
409                         break;
410
411                 case 'W':
412                         dowtmp = 0;
413                         break;
414
415                 default:
416                         syslog(LOG_WARNING, "unknown flag -%c ignored", optopt);
417                         break;
418                 }
419         }
420
421         /* handle filesize limit gracefully */
422         sa.sa_handler = SIG_IGN;
423         (void)sigaction(SIGXFSZ, &sa, NULL);
424
425         if (daemon_mode) {
426                 int *ctl_sock, fd, maxfd = -1, nfds, i;
427                 fd_set defreadfds, readfds;
428                 pid_t pid;
429                 struct pidfh *pfh;
430
431                 if ((pfh = pidfile_open(pid_file, 0600, &pid)) == NULL) {
432                         if (errno == EEXIST) {
433                                 syslog(LOG_ERR, "%s already running, pid %d",
434                                        getprogname(), (int)pid);
435                                 exit(1);
436                         }
437                         syslog(LOG_WARNING, "pidfile_open: %m");
438                 }
439
440                 /*
441                  * Detach from parent.
442                  */
443                 if (daemon(1, 1) < 0) {
444                         syslog(LOG_ERR, "failed to become a daemon");
445                         exit(1);
446                 }
447
448                 if (pfh != NULL && pidfile_write(pfh) == -1)
449                         syslog(LOG_WARNING, "pidfile_write: %m");
450
451                 sa.sa_handler = reapchild;
452                 (void)sigaction(SIGCHLD, &sa, NULL);
453
454 #ifdef VIRTUAL_HOSTING
455                 inithosts(family);
456 #endif
457
458                 /*
459                  * Open a socket, bind it to the FTP port, and start
460                  * listening.
461                  */
462                 ctl_sock = socksetup(family, bindname, bindport);
463                 if (ctl_sock == NULL)
464                         exit(1);
465
466                 FD_ZERO(&defreadfds);
467                 for (i = 1; i <= *ctl_sock; i++) {
468                         FD_SET(ctl_sock[i], &defreadfds);
469                         if (listen(ctl_sock[i], 32) < 0) {
470                                 syslog(LOG_ERR, "control listen: %m");
471                                 exit(1);
472                         }
473                         if (maxfd < ctl_sock[i])
474                                 maxfd = ctl_sock[i];
475                 }
476
477                 /*
478                  * Loop forever accepting connection requests and forking off
479                  * children to handle them.
480                  */
481                 while (1) {
482                         FD_COPY(&defreadfds, &readfds);
483                         nfds = select(maxfd + 1, &readfds, NULL, NULL, 0);
484                         if (nfds <= 0) {
485                                 if (nfds < 0 && errno != EINTR)
486                                         syslog(LOG_WARNING, "select: %m");
487                                 continue;
488                         }
489
490                         pid = -1;
491                         for (i = 1; i <= *ctl_sock; i++)
492                                 if (FD_ISSET(ctl_sock[i], &readfds)) {
493                                         addrlen = sizeof(his_addr);
494                                         fd = accept(ctl_sock[i],
495                                             (struct sockaddr *)&his_addr,
496                                             &addrlen);
497                                         if (fd == -1) {
498                                                 syslog(LOG_WARNING,
499                                                        "accept: %m");
500                                                 continue;
501                                         }
502                                         switch (pid = fork()) {
503                                         case 0:
504                                                 /* child */
505                                                 (void) dup2(fd, s);
506                                                 (void) dup2(fd, STDOUT_FILENO);
507                                                 (void) close(fd);
508                                                 for (i = 1; i <= *ctl_sock; i++)
509                                                         close(ctl_sock[i]);
510                                                 if (pfh != NULL)
511                                                         pidfile_close(pfh);
512                                                 goto gotchild;
513                                         case -1:
514                                                 syslog(LOG_WARNING, "fork: %m");
515                                                 /* FALLTHROUGH */
516                                         default:
517                                                 close(fd);
518                                         }
519                                 }
520                 }
521         } else {
522                 addrlen = sizeof(his_addr);
523                 if (getpeername(s, (struct sockaddr *)&his_addr, &addrlen) < 0) {
524                         syslog(LOG_ERR, "getpeername (%s): %m",argv[0]);
525                         exit(1);
526                 }
527
528 #ifdef VIRTUAL_HOSTING
529                 if (his_addr.su_family == AF_INET6 &&
530                     IN6_IS_ADDR_V4MAPPED(&his_addr.su_sin6.sin6_addr))
531                         family = AF_INET;
532                 else
533                         family = his_addr.su_family;
534                 inithosts(family);
535 #endif
536         }
537
538 gotchild:
539         sa.sa_handler = SIG_DFL;
540         (void)sigaction(SIGCHLD, &sa, NULL);
541
542         sa.sa_handler = sigurg;
543         sa.sa_flags = 0;                /* don't restart syscalls for SIGURG */
544         (void)sigaction(SIGURG, &sa, NULL);
545
546         sigfillset(&sa.sa_mask);        /* block all signals in handler */
547         sa.sa_flags = SA_RESTART;
548         sa.sa_handler = sigquit;
549         (void)sigaction(SIGHUP, &sa, NULL);
550         (void)sigaction(SIGINT, &sa, NULL);
551         (void)sigaction(SIGQUIT, &sa, NULL);
552         (void)sigaction(SIGTERM, &sa, NULL);
553
554         sa.sa_handler = lostconn;
555         (void)sigaction(SIGPIPE, &sa, NULL);
556
557         addrlen = sizeof(ctrl_addr);
558         if (getsockname(s, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) {
559                 syslog(LOG_ERR, "getsockname (%s): %m",argv[0]);
560                 exit(1);
561         }
562         dataport = ntohs(ctrl_addr.su_port) - 1; /* as per RFC 959 */
563 #ifdef VIRTUAL_HOSTING
564         /* select our identity from virtual host table */
565         selecthost(&ctrl_addr);
566 #endif
567 #ifdef IP_TOS
568         if (ctrl_addr.su_family == AF_INET)
569       {
570         tos = IPTOS_LOWDELAY;
571         if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0)
572                 syslog(LOG_WARNING, "control setsockopt (IP_TOS): %m");
573       }
574 #endif
575         /*
576          * Disable Nagle on the control channel so that we don't have to wait
577          * for peer's ACK before issuing our next reply.
578          */
579         if (setsockopt(s, IPPROTO_TCP, TCP_NODELAY, &on, sizeof(on)) < 0)
580                 syslog(LOG_WARNING, "control setsockopt (TCP_NODELAY): %m");
581
582         data_source.su_port = htons(ntohs(ctrl_addr.su_port) - 1);
583
584         (void)snprintf(wtmpid, sizeof(wtmpid), "%xftpd", getpid());
585
586         /* Try to handle urgent data inline */
587 #ifdef SO_OOBINLINE
588         if (setsockopt(s, SOL_SOCKET, SO_OOBINLINE, &on, sizeof(on)) < 0)
589                 syslog(LOG_WARNING, "control setsockopt (SO_OOBINLINE): %m");
590 #endif
591
592 #ifdef  F_SETOWN
593         if (fcntl(s, F_SETOWN, getpid()) == -1)
594                 syslog(LOG_ERR, "fcntl F_SETOWN: %m");
595 #endif
596         dolog((struct sockaddr *)&his_addr);
597         /*
598          * Set up default state
599          */
600         data = -1;
601         type = TYPE_A;
602         form = FORM_N;
603         stru = STRU_F;
604         mode = MODE_S;
605         tmpline[0] = '\0';
606
607         /* If logins are disabled, print out the message. */
608         if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) {
609                 while (fgets(line, sizeof(line), fd) != NULL) {
610                         if ((cp = strchr(line, '\n')) != NULL)
611                                 *cp = '\0';
612                         lreply(530, "%s", line);
613                 }
614                 (void) fflush(stdout);
615                 (void) fclose(fd);
616                 reply(530, "System not available.");
617                 exit(0);
618         }
619 #ifdef VIRTUAL_HOSTING
620         fd = fopen(thishost->welcome, "r");
621 #else
622         fd = fopen(_PATH_FTPWELCOME, "r");
623 #endif
624         if (fd != NULL) {
625                 while (fgets(line, sizeof(line), fd) != NULL) {
626                         if ((cp = strchr(line, '\n')) != NULL)
627                                 *cp = '\0';
628                         lreply(220, "%s", line);
629                 }
630                 (void) fflush(stdout);
631                 (void) fclose(fd);
632                 /* reply(220,) must follow */
633         }
634 #ifndef VIRTUAL_HOSTING
635         if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL)
636                 fatalerror("Ran out of memory.");
637         if (gethostname(hostname, MAXHOSTNAMELEN - 1) < 0)
638                 hostname[0] = '\0';
639         hostname[MAXHOSTNAMELEN - 1] = '\0';
640 #endif
641         if (hostinfo)
642                 reply(220, "%s FTP server (%s) ready.", hostname, version);
643         else
644                 reply(220, "FTP server ready.");
645         BLACKLIST_INIT();
646         for (;;)
647                 (void) yyparse();
648         /* NOTREACHED */
649 }
650
651 static void
652 lostconn(int signo)
653 {
654
655         if (ftpdebug)
656                 syslog(LOG_DEBUG, "lost connection");
657         dologout(1);
658 }
659
660 static void
661 sigquit(int signo)
662 {
663
664         syslog(LOG_ERR, "got signal %d", signo);
665         dologout(1);
666 }
667
668 #ifdef VIRTUAL_HOSTING
669 /*
670  * read in virtual host tables (if they exist)
671  */
672
673 static void
674 inithosts(int family)
675 {
676         int insert;
677         size_t len;
678         FILE *fp;
679         char *cp, *mp, *line;
680         char *hostname;
681         char *vhost, *anonuser, *statfile, *welcome, *loginmsg;
682         struct ftphost *hrp, *lhrp;
683         struct addrinfo hints, *res, *ai;
684
685         /*
686          * Fill in the default host information
687          */
688         if ((hostname = malloc(MAXHOSTNAMELEN)) == NULL)
689                 fatalerror("Ran out of memory.");
690         if (gethostname(hostname, MAXHOSTNAMELEN - 1) < 0)
691                 hostname[0] = '\0';
692         hostname[MAXHOSTNAMELEN - 1] = '\0';
693         if ((hrp = malloc(sizeof(struct ftphost))) == NULL)
694                 fatalerror("Ran out of memory.");
695         hrp->hostname = hostname;
696         hrp->hostinfo = NULL;
697
698         memset(&hints, 0, sizeof(hints));
699         hints.ai_flags = AI_PASSIVE;
700         hints.ai_family = family;
701         hints.ai_socktype = SOCK_STREAM;
702         if (getaddrinfo(hrp->hostname, NULL, &hints, &res) == 0)
703                 hrp->hostinfo = res;
704         hrp->statfile = _PATH_FTPDSTATFILE;
705         hrp->welcome  = _PATH_FTPWELCOME;
706         hrp->loginmsg = _PATH_FTPLOGINMESG;
707         hrp->anonuser = "ftp";
708         hrp->next = NULL;
709         thishost = firsthost = lhrp = hrp;
710         if ((fp = fopen(_PATH_FTPHOSTS, "r")) != NULL) {
711                 int addrsize, gothost;
712                 void *addr;
713                 struct hostent *hp;
714
715                 while ((line = fgetln(fp, &len)) != NULL) {
716                         int     i, hp_error;
717
718                         /* skip comments */
719                         if (line[0] == '#')
720                                 continue;
721                         if (line[len - 1] == '\n') {
722                                 line[len - 1] = '\0';
723                                 mp = NULL;
724                         } else {
725                                 if ((mp = malloc(len + 1)) == NULL)
726                                         fatalerror("Ran out of memory.");
727                                 memcpy(mp, line, len);
728                                 mp[len] = '\0';
729                                 line = mp;
730                         }
731                         cp = strtok(line, " \t");
732                         /* skip empty lines */
733                         if (cp == NULL)
734                                 goto nextline;
735                         vhost = cp;
736
737                         /* set defaults */
738                         anonuser = "ftp";
739                         statfile = _PATH_FTPDSTATFILE;
740                         welcome  = _PATH_FTPWELCOME;
741                         loginmsg = _PATH_FTPLOGINMESG;
742
743                         /*
744                          * Preparse the line so we can use its info
745                          * for all the addresses associated with
746                          * the virtual host name.
747                          * Field 0, the virtual host name, is special:
748                          * it's already parsed off and will be strdup'ed
749                          * later, after we know its canonical form.
750                          */
751                         for (i = 1; i < 5 && (cp = strtok(NULL, " \t")); i++)
752                                 if (*cp != '-' && (cp = strdup(cp)))
753                                         switch (i) {
754                                         case 1: /* anon user permissions */
755                                                 anonuser = cp;
756                                                 break;
757                                         case 2: /* statistics file */
758                                                 statfile = cp;
759                                                 break;
760                                         case 3: /* welcome message */
761                                                 welcome  = cp;
762                                                 break;
763                                         case 4: /* login message */
764                                                 loginmsg = cp;
765                                                 break;
766                                         default: /* programming error */
767                                                 abort();
768                                                 /* NOTREACHED */
769                                         }
770
771                         hints.ai_flags = AI_PASSIVE;
772                         hints.ai_family = family;
773                         hints.ai_socktype = SOCK_STREAM;
774                         if (getaddrinfo(vhost, NULL, &hints, &res) != 0)
775                                 goto nextline;
776                         for (ai = res; ai != NULL && ai->ai_addr != NULL;
777                              ai = ai->ai_next) {
778
779                         gothost = 0;
780                         for (hrp = firsthost; hrp != NULL; hrp = hrp->next) {
781                                 struct addrinfo *hi;
782
783                                 for (hi = hrp->hostinfo; hi != NULL;
784                                      hi = hi->ai_next)
785                                         if (hi->ai_addrlen == ai->ai_addrlen &&
786                                             memcmp(hi->ai_addr,
787                                                    ai->ai_addr,
788                                                    ai->ai_addr->sa_len) == 0) {
789                                                 gothost++;
790                                                 break;
791                                         }
792                                 if (gothost)
793                                         break;
794                         }
795                         if (hrp == NULL) {
796                                 if ((hrp = malloc(sizeof(struct ftphost))) == NULL)
797                                         goto nextline;
798                                 hrp->hostname = NULL;
799                                 insert = 1;
800                         } else {
801                                 if (hrp->hostinfo && hrp->hostinfo != res)
802                                         freeaddrinfo(hrp->hostinfo);
803                                 insert = 0; /* host already in the chain */
804                         }
805                         hrp->hostinfo = res;
806
807                         /*
808                          * determine hostname to use.
809                          * force defined name if there is a valid alias
810                          * otherwise fallback to primary hostname
811                          */
812                         /* XXX: getaddrinfo() can't do alias check */
813                         switch(hrp->hostinfo->ai_family) {
814                         case AF_INET:
815                                 addr = &((struct sockaddr_in *)hrp->hostinfo->ai_addr)->sin_addr;
816                                 addrsize = sizeof(struct in_addr);
817                                 break;
818                         case AF_INET6:
819                                 addr = &((struct sockaddr_in6 *)hrp->hostinfo->ai_addr)->sin6_addr;
820                                 addrsize = sizeof(struct in6_addr);
821                                 break;
822                         default:
823                                 /* should not reach here */
824                                 freeaddrinfo(hrp->hostinfo);
825                                 if (insert)
826                                         free(hrp); /*not in chain, can free*/
827                                 else
828                                         hrp->hostinfo = NULL; /*mark as blank*/
829                                 goto nextline;
830                                 /* NOTREACHED */
831                         }
832                         if ((hp = getipnodebyaddr(addr, addrsize,
833                                                   hrp->hostinfo->ai_family,
834                                                   &hp_error)) != NULL) {
835                                 if (strcmp(vhost, hp->h_name) != 0) {
836                                         if (hp->h_aliases == NULL)
837                                                 vhost = hp->h_name;
838                                         else {
839                                                 i = 0;
840                                                 while (hp->h_aliases[i] &&
841                                                        strcmp(vhost, hp->h_aliases[i]) != 0)
842                                                         ++i;
843                                                 if (hp->h_aliases[i] == NULL)
844                                                         vhost = hp->h_name;
845                                         }
846                                 }
847                         }
848                         if (hrp->hostname &&
849                             strcmp(hrp->hostname, vhost) != 0) {
850                                 free(hrp->hostname);
851                                 hrp->hostname = NULL;
852                         }
853                         if (hrp->hostname == NULL &&
854                             (hrp->hostname = strdup(vhost)) == NULL) {
855                                 freeaddrinfo(hrp->hostinfo);
856                                 hrp->hostinfo = NULL; /* mark as blank */
857                                 if (hp)
858                                         freehostent(hp);
859                                 goto nextline;
860                         }
861                         hrp->anonuser = anonuser;
862                         hrp->statfile = statfile;
863                         hrp->welcome  = welcome;
864                         hrp->loginmsg = loginmsg;
865                         if (insert) {
866                                 hrp->next  = NULL;
867                                 lhrp->next = hrp;
868                                 lhrp = hrp;
869                         }
870                         if (hp)
871                                 freehostent(hp);
872                       }
873 nextline:
874                         if (mp)
875                                 free(mp);
876                 }
877                 (void) fclose(fp);
878         }
879 }
880
881 static void
882 selecthost(union sockunion *su)
883 {
884         struct ftphost  *hrp;
885         u_int16_t port;
886 #ifdef INET6
887         struct in6_addr *mapped_in6 = NULL;
888 #endif
889         struct addrinfo *hi;
890
891 #ifdef INET6
892         /*
893          * XXX IPv4 mapped IPv6 addr consideraton,
894          * specified in rfc2373.
895          */
896         if (su->su_family == AF_INET6 &&
897             IN6_IS_ADDR_V4MAPPED(&su->su_sin6.sin6_addr))
898                 mapped_in6 = &su->su_sin6.sin6_addr;
899 #endif
900
901         hrp = thishost = firsthost;     /* default */
902         port = su->su_port;
903         su->su_port = 0;
904         while (hrp != NULL) {
905             for (hi = hrp->hostinfo; hi != NULL; hi = hi->ai_next) {
906                 if (memcmp(su, hi->ai_addr, hi->ai_addrlen) == 0) {
907                         thishost = hrp;
908                         goto found;
909                 }
910 #ifdef INET6
911                 /* XXX IPv4 mapped IPv6 addr consideraton */
912                 if (hi->ai_addr->sa_family == AF_INET && mapped_in6 != NULL &&
913                     (memcmp(&mapped_in6->s6_addr[12],
914                             &((struct sockaddr_in *)hi->ai_addr)->sin_addr,
915                             sizeof(struct in_addr)) == 0)) {
916                         thishost = hrp;
917                         goto found;
918                 }
919 #endif
920             }
921             hrp = hrp->next;
922         }
923 found:
924         su->su_port = port;
925         /* setup static variables as appropriate */
926         hostname = thishost->hostname;
927         ftpuser = thishost->anonuser;
928 }
929 #endif
930
931 /*
932  * Helper function for sgetpwnam().
933  */
934 static char *
935 sgetsave(char *s)
936 {
937         char *new = malloc(strlen(s) + 1);
938
939         if (new == NULL) {
940                 reply(421, "Ran out of memory.");
941                 dologout(1);
942                 /* NOTREACHED */
943         }
944         (void) strcpy(new, s);
945         return (new);
946 }
947
948 /*
949  * Save the result of a getpwnam.  Used for USER command, since
950  * the data returned must not be clobbered by any other command
951  * (e.g., globbing).
952  * NB: The data returned by sgetpwnam() will remain valid until
953  * the next call to this function.  Its difference from getpwnam()
954  * is that sgetpwnam() is known to be called from ftpd code only.
955  */
956 static struct passwd *
957 sgetpwnam(char *name)
958 {
959         static struct passwd save;
960         struct passwd *p;
961
962         if ((p = getpwnam(name)) == NULL)
963                 return (p);
964         if (save.pw_name) {
965                 free(save.pw_name);
966                 free(save.pw_passwd);
967                 free(save.pw_class);
968                 free(save.pw_gecos);
969                 free(save.pw_dir);
970                 free(save.pw_shell);
971         }
972         save = *p;
973         save.pw_name = sgetsave(p->pw_name);
974         save.pw_passwd = sgetsave(p->pw_passwd);
975         save.pw_class = sgetsave(p->pw_class);
976         save.pw_gecos = sgetsave(p->pw_gecos);
977         save.pw_dir = sgetsave(p->pw_dir);
978         save.pw_shell = sgetsave(p->pw_shell);
979         return (&save);
980 }
981
982 static int login_attempts;      /* number of failed login attempts */
983 static int askpasswd;           /* had user command, ask for passwd */
984 static char curname[MAXLOGNAME];        /* current USER name */
985
986 /*
987  * USER command.
988  * Sets global passwd pointer pw if named account exists and is acceptable;
989  * sets askpasswd if a PASS command is expected.  If logged in previously,
990  * need to reset state.  If name is "ftp" or "anonymous", the name is not in
991  * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
992  * If account doesn't exist, ask for passwd anyway.  Otherwise, check user
993  * requesting login privileges.  Disallow anyone who does not have a standard
994  * shell as returned by getusershell().  Disallow anyone mentioned in the file
995  * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
996  */
997 void
998 user(char *name)
999 {
1000         int ecode;
1001         char *cp, *shell;
1002
1003         if (logged_in) {
1004                 if (guest) {
1005                         reply(530, "Can't change user from guest login.");
1006                         return;
1007                 } else if (dochroot) {
1008                         reply(530, "Can't change user from chroot user.");
1009                         return;
1010                 }
1011                 end_login();
1012         }
1013
1014         guest = 0;
1015 #ifdef VIRTUAL_HOSTING
1016         pw = sgetpwnam(thishost->anonuser);
1017 #else
1018         pw = sgetpwnam("ftp");
1019 #endif
1020         if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
1021                 if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL, &ecode) ||
1022                     (ecode != 0 && ecode != ENOENT))
1023                         reply(530, "User %s access denied.", name);
1024                 else if (checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL, &ecode) ||
1025                     (ecode != 0 && ecode != ENOENT))
1026                         reply(530, "User %s access denied.", name);
1027                 else if (pw != NULL) {
1028                         guest = 1;
1029                         askpasswd = 1;
1030                         reply(331,
1031                         "Guest login ok, send your email address as password.");
1032                 } else
1033                         reply(530, "User %s unknown.", name);
1034                 if (!askpasswd && logging)
1035                         syslog(LOG_NOTICE,
1036                             "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
1037                 return;
1038         }
1039         if (anon_only != 0) {
1040                 reply(530, "Sorry, only anonymous ftp allowed.");
1041                 return;
1042         }
1043                 
1044         if ((pw = sgetpwnam(name))) {
1045                 if ((shell = pw->pw_shell) == NULL || *shell == 0)
1046                         shell = _PATH_BSHELL;
1047                 setusershell();
1048                 while ((cp = getusershell()) != NULL)
1049                         if (strcmp(cp, shell) == 0)
1050                                 break;
1051                 endusershell();
1052
1053                 if (cp == NULL || 
1054                     (checkuser(_PATH_FTPUSERS, name, 1, NULL, &ecode) ||
1055                     (ecode != 0 && ecode != ENOENT))) {
1056                         reply(530, "User %s access denied.", name);
1057                         if (logging)
1058                                 syslog(LOG_NOTICE,
1059                                     "FTP LOGIN REFUSED FROM %s, %s",
1060                                     remotehost, name);
1061                         pw = NULL;
1062                         return;
1063                 }
1064         }
1065         if (logging)
1066                 strlcpy(curname, name, sizeof(curname));
1067
1068         pwok = 0;
1069 #ifdef USE_PAM
1070         /* XXX Kluge! The conversation mechanism needs to be fixed. */
1071 #endif
1072         if (opiechallenge(&opiedata, name, opieprompt) == 0) {
1073                 pwok = (pw != NULL) &&
1074                        opieaccessfile(remotehost) &&
1075                        opiealways(pw->pw_dir);
1076                 reply(331, "Response to %s %s for %s.",
1077                       opieprompt, pwok ? "requested" : "required", name);
1078         } else {
1079                 pwok = 1;
1080                 reply(331, "Password required for %s.", name);
1081         }
1082         askpasswd = 1;
1083         /*
1084          * Delay before reading passwd after first failed
1085          * attempt to slow down passwd-guessing programs.
1086          */
1087         if (login_attempts)
1088                 sleep(login_attempts);
1089 }
1090
1091 /*
1092  * Check if a user is in the file "fname",
1093  * return a pointer to a malloc'd string with the rest
1094  * of the matching line in "residue" if not NULL.
1095  */
1096 static int
1097 checkuser(char *fname, char *name, int pwset, char **residue, int *ecode)
1098 {
1099         FILE *fd;
1100         int found = 0;
1101         size_t len;
1102         char *line, *mp, *p;
1103
1104         if (ecode != NULL)
1105                 *ecode = 0;
1106         if ((fd = fopen(fname, "r")) != NULL) {
1107                 while (!found && (line = fgetln(fd, &len)) != NULL) {
1108                         /* skip comments */
1109                         if (line[0] == '#')
1110                                 continue;
1111                         if (line[len - 1] == '\n') {
1112                                 line[len - 1] = '\0';
1113                                 mp = NULL;
1114                         } else {
1115                                 if ((mp = malloc(len + 1)) == NULL)
1116                                         fatalerror("Ran out of memory.");
1117                                 memcpy(mp, line, len);
1118                                 mp[len] = '\0';
1119                                 line = mp;
1120                         }
1121                         /* avoid possible leading and trailing whitespace */
1122                         p = strtok(line, " \t");
1123                         /* skip empty lines */
1124                         if (p == NULL)
1125                                 goto nextline;
1126                         /*
1127                          * if first chr is '@', check group membership
1128                          */
1129                         if (p[0] == '@') {
1130                                 int i = 0;
1131                                 struct group *grp;
1132
1133                                 if (p[1] == '\0') /* single @ matches anyone */
1134                                         found = 1;
1135                                 else {
1136                                         if ((grp = getgrnam(p+1)) == NULL)
1137                                                 goto nextline;
1138                                         /*
1139                                          * Check user's default group
1140                                          */
1141                                         if (pwset && grp->gr_gid == pw->pw_gid)
1142                                                 found = 1;
1143                                         /*
1144                                          * Check supplementary groups
1145                                          */
1146                                         while (!found && grp->gr_mem[i])
1147                                                 found = strcmp(name,
1148                                                         grp->gr_mem[i++])
1149                                                         == 0;
1150                                 }
1151                         }
1152                         /*
1153                          * Otherwise, just check for username match
1154                          */
1155                         else
1156                                 found = strcmp(p, name) == 0;
1157                         /*
1158                          * Save the rest of line to "residue" if matched
1159                          */
1160                         if (found && residue) {
1161                                 if ((p = strtok(NULL, "")) != NULL)
1162                                         p += strspn(p, " \t");
1163                                 if (p && *p) {
1164                                         if ((*residue = strdup(p)) == NULL)
1165                                                 fatalerror("Ran out of memory.");
1166                                 } else
1167                                         *residue = NULL;
1168                         }
1169 nextline:
1170                         if (mp)
1171                                 free(mp);
1172                 }
1173                 (void) fclose(fd);
1174         } else if (ecode != NULL)
1175                 *ecode = errno;
1176         return (found);
1177 }
1178
1179 /*
1180  * Terminate login as previous user, if any, resetting state;
1181  * used when USER command is given or login fails.
1182  */
1183 static void
1184 end_login(void)
1185 {
1186 #ifdef USE_PAM
1187         int e;
1188 #endif
1189
1190         (void) seteuid(0);
1191 #ifdef  LOGIN_CAP
1192         setusercontext(NULL, getpwuid(0), 0, LOGIN_SETALL & ~(LOGIN_SETLOGIN |
1193                        LOGIN_SETUSER | LOGIN_SETGROUP | LOGIN_SETPATH |
1194                        LOGIN_SETENV));
1195 #endif
1196         if (logged_in && dowtmp)
1197                 ftpd_logwtmp(wtmpid, NULL, NULL);
1198         pw = NULL;
1199 #ifdef USE_PAM
1200         if (pamh) {
1201                 if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS)
1202                         syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e));
1203                 if ((e = pam_close_session(pamh,0)) != PAM_SUCCESS)
1204                         syslog(LOG_ERR, "pam_close_session: %s", pam_strerror(pamh, e));
1205                 if ((e = pam_end(pamh, e)) != PAM_SUCCESS)
1206                         syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1207                 pamh = NULL;
1208         }
1209 #endif
1210         logged_in = 0;
1211         guest = 0;
1212         dochroot = 0;
1213 }
1214
1215 #ifdef USE_PAM
1216
1217 /*
1218  * the following code is stolen from imap-uw PAM authentication module and
1219  * login.c
1220  */
1221 #define COPY_STRING(s) (s ? strdup(s) : NULL)
1222
1223 struct cred_t {
1224         const char *uname;              /* user name */
1225         const char *pass;               /* password */
1226 };
1227 typedef struct cred_t cred_t;
1228
1229 static int
1230 auth_conv(int num_msg, const struct pam_message **msg,
1231           struct pam_response **resp, void *appdata)
1232 {
1233         int i;
1234         cred_t *cred = (cred_t *) appdata;
1235         struct pam_response *reply;
1236
1237         reply = calloc(num_msg, sizeof *reply);
1238         if (reply == NULL)
1239                 return PAM_BUF_ERR;
1240
1241         for (i = 0; i < num_msg; i++) {
1242                 switch (msg[i]->msg_style) {
1243                 case PAM_PROMPT_ECHO_ON:        /* assume want user name */
1244                         reply[i].resp_retcode = PAM_SUCCESS;
1245                         reply[i].resp = COPY_STRING(cred->uname);
1246                         /* PAM frees resp. */
1247                         break;
1248                 case PAM_PROMPT_ECHO_OFF:       /* assume want password */
1249                         reply[i].resp_retcode = PAM_SUCCESS;
1250                         reply[i].resp = COPY_STRING(cred->pass);
1251                         /* PAM frees resp. */
1252                         break;
1253                 case PAM_TEXT_INFO:
1254                 case PAM_ERROR_MSG:
1255                         reply[i].resp_retcode = PAM_SUCCESS;
1256                         reply[i].resp = NULL;
1257                         break;
1258                 default:                        /* unknown message style */
1259                         free(reply);
1260                         return PAM_CONV_ERR;
1261                 }
1262         }
1263
1264         *resp = reply;
1265         return PAM_SUCCESS;
1266 }
1267
1268 /*
1269  * Attempt to authenticate the user using PAM.  Returns 0 if the user is
1270  * authenticated, or 1 if not authenticated.  If some sort of PAM system
1271  * error occurs (e.g., the "/etc/pam.conf" file is missing) then this
1272  * function returns -1.  This can be used as an indication that we should
1273  * fall back to a different authentication mechanism.
1274  */
1275 static int
1276 auth_pam(struct passwd **ppw, const char *pass)
1277 {
1278         const char *tmpl_user;
1279         const void *item;
1280         int rval;
1281         int e;
1282         cred_t auth_cred = { (*ppw)->pw_name, pass };
1283         struct pam_conv conv = { &auth_conv, &auth_cred };
1284
1285         e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh);
1286         if (e != PAM_SUCCESS) {
1287                 /*
1288                  * In OpenPAM, it's OK to pass NULL to pam_strerror()
1289                  * if context creation has failed in the first place.
1290                  */
1291                 syslog(LOG_ERR, "pam_start: %s", pam_strerror(NULL, e));
1292                 return -1;
1293         }
1294
1295         e = pam_set_item(pamh, PAM_RHOST, remotehost);
1296         if (e != PAM_SUCCESS) {
1297                 syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
1298                         pam_strerror(pamh, e));
1299                 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
1300                         syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1301                 }
1302                 pamh = NULL;
1303                 return -1;
1304         }
1305
1306         e = pam_authenticate(pamh, 0);
1307         switch (e) {
1308         case PAM_SUCCESS:
1309                 /*
1310                  * With PAM we support the concept of a "template"
1311                  * user.  The user enters a login name which is
1312                  * authenticated by PAM, usually via a remote service
1313                  * such as RADIUS or TACACS+.  If authentication
1314                  * succeeds, a different but related "template" name
1315                  * is used for setting the credentials, shell, and
1316                  * home directory.  The name the user enters need only
1317                  * exist on the remote authentication server, but the
1318                  * template name must be present in the local password
1319                  * database.
1320                  *
1321                  * This is supported by two various mechanisms in the
1322                  * individual modules.  However, from the application's
1323                  * point of view, the template user is always passed
1324                  * back as a changed value of the PAM_USER item.
1325                  */
1326                 if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
1327                     PAM_SUCCESS) {
1328                         tmpl_user = (const char *) item;
1329                         if (strcmp((*ppw)->pw_name, tmpl_user) != 0)
1330                                 *ppw = getpwnam(tmpl_user);
1331                 } else
1332                         syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
1333                             pam_strerror(pamh, e));
1334                 rval = 0;
1335                 break;
1336
1337         case PAM_AUTH_ERR:
1338         case PAM_USER_UNKNOWN:
1339         case PAM_MAXTRIES:
1340                 rval = 1;
1341                 break;
1342
1343         default:
1344                 syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, e));
1345                 rval = -1;
1346                 break;
1347         }
1348
1349         if (rval == 0) {
1350                 e = pam_acct_mgmt(pamh, 0);
1351                 if (e != PAM_SUCCESS) {
1352                         syslog(LOG_ERR, "pam_acct_mgmt: %s",
1353                                                 pam_strerror(pamh, e));
1354                         rval = 1;
1355                 }
1356         }
1357
1358         if (rval != 0) {
1359                 if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
1360                         syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
1361                 }
1362                 pamh = NULL;
1363         }
1364         return rval;
1365 }
1366
1367 #endif /* USE_PAM */
1368
1369 void
1370 pass(char *passwd)
1371 {
1372         int rval, ecode;
1373         FILE *fd;
1374 #ifdef  LOGIN_CAP
1375         login_cap_t *lc = NULL;
1376 #endif
1377 #ifdef USE_PAM
1378         int e;
1379 #endif
1380         char *residue = NULL;
1381         char *xpasswd;
1382
1383         if (logged_in || askpasswd == 0) {
1384                 reply(503, "Login with USER first.");
1385                 return;
1386         }
1387         askpasswd = 0;
1388         if (!guest) {           /* "ftp" is only account allowed no password */
1389                 if (pw == NULL) {
1390                         rval = 1;       /* failure below */
1391                         goto skip;
1392                 }
1393 #ifdef USE_PAM
1394                 rval = auth_pam(&pw, passwd);
1395                 if (rval >= 0) {
1396                         opieunlock();
1397                         goto skip;
1398                 }
1399 #endif
1400                 if (opieverify(&opiedata, passwd) == 0)
1401                         xpasswd = pw->pw_passwd;
1402                 else if (pwok) {
1403                         xpasswd = crypt(passwd, pw->pw_passwd);
1404                         if (passwd[0] == '\0' && pw->pw_passwd[0] != '\0')
1405                                 xpasswd = ":";
1406                 } else {
1407                         rval = 1;
1408                         goto skip;
1409                 }
1410                 rval = strcmp(pw->pw_passwd, xpasswd);
1411                 if (pw->pw_expire && time(NULL) >= pw->pw_expire)
1412                         rval = 1;       /* failure */
1413 skip:
1414                 /*
1415                  * If rval == 1, the user failed the authentication check
1416                  * above.  If rval == 0, either PAM or local authentication
1417                  * succeeded.
1418                  */
1419                 if (rval) {
1420                         reply(530, "Login incorrect.");
1421                         BLACKLIST_NOTIFY(BLACKLIST_AUTH_FAIL, STDIN_FILENO, "Login incorrect");
1422                         if (logging) {
1423                                 syslog(LOG_NOTICE,
1424                                     "FTP LOGIN FAILED FROM %s",
1425                                     remotehost);
1426                                 syslog(LOG_AUTHPRIV | LOG_NOTICE,
1427                                     "FTP LOGIN FAILED FROM %s, %s",
1428                                     remotehost, curname);
1429                         }
1430                         pw = NULL;
1431                         if (login_attempts++ >= 5) {
1432                                 syslog(LOG_NOTICE,
1433                                     "repeated login failures from %s",
1434                                     remotehost);
1435                                 exit(0);
1436                         }
1437                         return;
1438                 } else {
1439                         BLACKLIST_NOTIFY(BLACKLIST_AUTH_OK, STDIN_FILENO, "Login successful");
1440                 }
1441         }
1442         login_attempts = 0;             /* this time successful */
1443         if (setegid(pw->pw_gid) < 0) {
1444                 reply(550, "Can't set gid.");
1445                 return;
1446         }
1447         /* May be overridden by login.conf */
1448         (void) umask(defumask);
1449 #ifdef  LOGIN_CAP
1450         if ((lc = login_getpwclass(pw)) != NULL) {
1451                 char    remote_ip[NI_MAXHOST];
1452
1453                 if (getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
1454                         remote_ip, sizeof(remote_ip) - 1, NULL, 0,
1455                         NI_NUMERICHOST))
1456                                 *remote_ip = 0;
1457                 remote_ip[sizeof(remote_ip) - 1] = 0;
1458                 if (!auth_hostok(lc, remotehost, remote_ip)) {
1459                         syslog(LOG_INFO|LOG_AUTH,
1460                             "FTP LOGIN FAILED (HOST) as %s: permission denied.",
1461                             pw->pw_name);
1462                         reply(530, "Permission denied.");
1463                         pw = NULL;
1464                         return;
1465                 }
1466                 if (!auth_timeok(lc, time(NULL))) {
1467                         reply(530, "Login not available right now.");
1468                         pw = NULL;
1469                         return;
1470                 }
1471         }
1472         setusercontext(lc, pw, 0, LOGIN_SETALL &
1473                        ~(LOGIN_SETRESOURCES | LOGIN_SETUSER | LOGIN_SETPATH | LOGIN_SETENV));
1474 #else
1475         setlogin(pw->pw_name);
1476         (void) initgroups(pw->pw_name, pw->pw_gid);
1477 #endif
1478
1479 #ifdef USE_PAM
1480         if (pamh) {
1481                 if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
1482                         syslog(LOG_ERR, "pam_open_session: %s", pam_strerror(pamh, e));
1483                 } else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED)) != PAM_SUCCESS) {
1484                         syslog(LOG_ERR, "pam_setcred: %s", pam_strerror(pamh, e));
1485                 }
1486         }
1487 #endif
1488
1489         dochroot =
1490                 checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &residue, &ecode)
1491 #ifdef  LOGIN_CAP       /* Allow login.conf configuration as well */
1492                 || login_getcapbool(lc, "ftp-chroot", 0)
1493 #endif
1494         ;
1495         /*
1496          * It is possible that checkuser() failed to open the chroot file.
1497          * If this is the case, report that logins are un-available, since we
1498          * have no way of checking whether or not the user should be chrooted.
1499          * We ignore ENOENT since it is not required that this file be present.
1500          */
1501         if (ecode != 0 && ecode != ENOENT) {
1502                 reply(530, "Login not available right now.");
1503                 return;
1504         }
1505         chrootdir = NULL;
1506
1507         /* Disable wtmp logging when chrooting. */
1508         if (dochroot || guest)
1509                 dowtmp = 0;
1510         if (dowtmp)
1511                 ftpd_logwtmp(wtmpid, pw->pw_name,
1512                     (struct sockaddr *)&his_addr);
1513         logged_in = 1;
1514
1515 #ifdef  LOGIN_CAP
1516         setusercontext(lc, pw, 0, LOGIN_SETRESOURCES);
1517 #endif
1518
1519         if (guest && stats && statfd < 0) {
1520 #ifdef VIRTUAL_HOSTING
1521                 statfd = open(thishost->statfile, O_WRONLY|O_APPEND);
1522 #else
1523                 statfd = open(_PATH_FTPDSTATFILE, O_WRONLY|O_APPEND);
1524 #endif
1525                 if (statfd < 0)
1526                         stats = 0;
1527         }
1528
1529         /*
1530          * For a chrooted local user,
1531          * a) see whether ftpchroot(5) specifies a chroot directory,
1532          * b) extract the directory pathname from the line,
1533          * c) expand it to the absolute pathname if necessary.
1534          */
1535         if (dochroot && residue &&
1536             (chrootdir = strtok(residue, " \t")) != NULL) {
1537                 if (chrootdir[0] != '/')
1538                         asprintf(&chrootdir, "%s/%s", pw->pw_dir, chrootdir);
1539                 else
1540                         chrootdir = strdup(chrootdir); /* make it permanent */
1541                 if (chrootdir == NULL)
1542                         fatalerror("Ran out of memory.");
1543         }
1544         if (guest || dochroot) {
1545                 /*
1546                  * If no chroot directory set yet, use the login directory.
1547                  * Copy it so it can be modified while pw->pw_dir stays intact.
1548                  */
1549                 if (chrootdir == NULL &&
1550                     (chrootdir = strdup(pw->pw_dir)) == NULL)
1551                         fatalerror("Ran out of memory.");
1552                 /*
1553                  * Check for the "/chroot/./home" syntax,
1554                  * separate the chroot and home directory pathnames.
1555                  */
1556                 if ((homedir = strstr(chrootdir, "/./")) != NULL) {
1557                         *(homedir++) = '\0';    /* wipe '/' */
1558                         homedir++;              /* skip '.' */
1559                 } else {
1560                         /*
1561                          * We MUST do a chdir() after the chroot. Otherwise
1562                          * the old current directory will be accessible as "."
1563                          * outside the new root!
1564                          */
1565                         homedir = "/";
1566                 }
1567                 /*
1568                  * Finally, do chroot()
1569                  */
1570                 if (chroot(chrootdir) < 0) {
1571                         reply(550, "Can't change root.");
1572                         goto bad;
1573                 }
1574                 __FreeBSD_libc_enter_restricted_mode();
1575         } else  /* real user w/o chroot */
1576                 homedir = pw->pw_dir;
1577         /*
1578          * Set euid *before* doing chdir() so
1579          * a) the user won't be carried to a directory that he couldn't reach
1580          *    on his own due to no permission to upper path components,
1581          * b) NFS mounted homedirs w/restrictive permissions will be accessible
1582          *    (uid 0 has no root power over NFS if not mapped explicitly.)
1583          */
1584         if (seteuid(pw->pw_uid) < 0) {
1585                 if (guest || dochroot) {
1586                         fatalerror("Can't set uid.");
1587                 } else {
1588                         reply(550, "Can't set uid.");
1589                         goto bad;
1590                 }
1591         }
1592         /*
1593          * Do not allow the session to live if we're chroot()'ed and chdir()
1594          * fails. Otherwise the chroot jail can be escaped.
1595          */
1596         if (chdir(homedir) < 0) {
1597                 if (guest || dochroot) {
1598                         fatalerror("Can't change to base directory.");
1599                 } else {
1600                         if (chdir("/") < 0) {
1601                                 reply(550, "Root is inaccessible.");
1602                                 goto bad;
1603                         }
1604                         lreply(230, "No directory! Logging in with home=/.");
1605                 }
1606         }
1607
1608         /*
1609          * Display a login message, if it exists.
1610          * N.B. reply(230,) must follow the message.
1611          */
1612 #ifdef VIRTUAL_HOSTING
1613         fd = fopen(thishost->loginmsg, "r");
1614 #else
1615         fd = fopen(_PATH_FTPLOGINMESG, "r");
1616 #endif
1617         if (fd != NULL) {
1618                 char *cp, line[LINE_MAX];
1619
1620                 while (fgets(line, sizeof(line), fd) != NULL) {
1621                         if ((cp = strchr(line, '\n')) != NULL)
1622                                 *cp = '\0';
1623                         lreply(230, "%s", line);
1624                 }
1625                 (void) fflush(stdout);
1626                 (void) fclose(fd);
1627         }
1628         if (guest) {
1629                 if (ident != NULL)
1630                         free(ident);
1631                 ident = strdup(passwd);
1632                 if (ident == NULL)
1633                         fatalerror("Ran out of memory.");
1634
1635                 reply(230, "Guest login ok, access restrictions apply.");
1636 #ifdef SETPROCTITLE
1637 #ifdef VIRTUAL_HOSTING
1638                 if (thishost != firsthost)
1639                         snprintf(proctitle, sizeof(proctitle),
1640                                  "%s: anonymous(%s)/%s", remotehost, hostname,
1641                                  passwd);
1642                 else
1643 #endif
1644                         snprintf(proctitle, sizeof(proctitle),
1645                                  "%s: anonymous/%s", remotehost, passwd);
1646                 setproctitle("%s", proctitle);
1647 #endif /* SETPROCTITLE */
1648                 if (logging)
1649                         syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s",
1650                             remotehost, passwd);
1651         } else {
1652                 if (dochroot)
1653                         reply(230, "User %s logged in, "
1654                                    "access restrictions apply.", pw->pw_name);
1655                 else
1656                         reply(230, "User %s logged in.", pw->pw_name);
1657
1658 #ifdef SETPROCTITLE
1659                 snprintf(proctitle, sizeof(proctitle),
1660                          "%s: user/%s", remotehost, pw->pw_name);
1661                 setproctitle("%s", proctitle);
1662 #endif /* SETPROCTITLE */
1663                 if (logging)
1664                         syslog(LOG_INFO, "FTP LOGIN FROM %s as %s",
1665                             remotehost, pw->pw_name);
1666         }
1667         if (logging && (guest || dochroot))
1668                 syslog(LOG_INFO, "session root changed to %s", chrootdir);
1669 #ifdef  LOGIN_CAP
1670         login_close(lc);
1671 #endif
1672         if (residue)
1673                 free(residue);
1674         return;
1675 bad:
1676         /* Forget all about it... */
1677 #ifdef  LOGIN_CAP
1678         login_close(lc);
1679 #endif
1680         if (residue)
1681                 free(residue);
1682         end_login();
1683 }
1684
1685 void
1686 retrieve(char *cmd, char *name)
1687 {
1688         FILE *fin, *dout;
1689         struct stat st;
1690         int (*closefunc)(FILE *);
1691         time_t start;
1692         char line[BUFSIZ];
1693
1694         if (cmd == 0) {
1695                 fin = fopen(name, "r"), closefunc = fclose;
1696                 st.st_size = 0;
1697         } else {
1698                 (void) snprintf(line, sizeof(line), cmd, name);
1699                 name = line;
1700                 fin = ftpd_popen(line, "r"), closefunc = ftpd_pclose;
1701                 st.st_size = -1;
1702                 st.st_blksize = BUFSIZ;
1703         }
1704         if (fin == NULL) {
1705                 if (errno != 0) {
1706                         perror_reply(550, name);
1707                         if (cmd == 0) {
1708                                 LOGCMD("get", name);
1709                         }
1710                 }
1711                 return;
1712         }
1713         byte_count = -1;
1714         if (cmd == 0) {
1715                 if (fstat(fileno(fin), &st) < 0) {
1716                         perror_reply(550, name);
1717                         goto done;
1718                 }
1719                 if (!S_ISREG(st.st_mode)) {
1720                         /*
1721                          * Never sending a raw directory is a workaround
1722                          * for buggy clients that will attempt to RETR
1723                          * a directory before listing it, e.g., Mozilla.
1724                          * Preventing a guest from getting irregular files
1725                          * is a simple security measure.
1726                          */
1727                         if (S_ISDIR(st.st_mode) || guest) {
1728                                 reply(550, "%s: not a plain file.", name);
1729                                 goto done;
1730                         }
1731                         st.st_size = -1;
1732                         /* st.st_blksize is set for all descriptor types */
1733                 }
1734         }
1735         if (restart_point) {
1736                 if (type == TYPE_A) {
1737                         off_t i, n;
1738                         int c;
1739
1740                         n = restart_point;
1741                         i = 0;
1742                         while (i++ < n) {
1743                                 if ((c=getc(fin)) == EOF) {
1744                                         perror_reply(550, name);
1745                                         goto done;
1746                                 }
1747                                 if (c == '\n')
1748                                         i++;
1749                         }
1750                 } else if (lseek(fileno(fin), restart_point, L_SET) < 0) {
1751                         perror_reply(550, name);
1752                         goto done;
1753                 }
1754         }
1755         dout = dataconn(name, st.st_size, "w");
1756         if (dout == NULL)
1757                 goto done;
1758         time(&start);
1759         send_data(fin, dout, st.st_blksize, st.st_size,
1760                   restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode));
1761         if (cmd == 0 && guest && stats && byte_count > 0)
1762                 logxfer(name, byte_count, start);
1763         (void) fclose(dout);
1764         data = -1;
1765         pdata = -1;
1766 done:
1767         if (cmd == 0)
1768                 LOGBYTES("get", name, byte_count);
1769         (*closefunc)(fin);
1770 }
1771
1772 void
1773 store(char *name, char *mode, int unique)
1774 {
1775         int fd;
1776         FILE *fout, *din;
1777         int (*closefunc)(FILE *);
1778
1779         if (*mode == 'a') {             /* APPE */
1780                 if (unique) {
1781                         /* Programming error */
1782                         syslog(LOG_ERR, "Internal: unique flag to APPE");
1783                         unique = 0;
1784                 }
1785                 if (guest && noguestmod) {
1786                         reply(550, "Appending to existing file denied.");
1787                         goto err;
1788                 }
1789                 restart_point = 0;      /* not affected by preceding REST */
1790         }
1791         if (unique)                     /* STOU overrides REST */
1792                 restart_point = 0;
1793         if (guest && noguestmod) {
1794                 if (restart_point) {    /* guest STOR w/REST */
1795                         reply(550, "Modifying existing file denied.");
1796                         goto err;
1797                 } else                  /* treat guest STOR as STOU */
1798                         unique = 1;
1799         }
1800
1801         if (restart_point)
1802                 mode = "r+";    /* so ASCII manual seek can work */
1803         if (unique) {
1804                 if ((fd = guniquefd(name, &name)) < 0)
1805                         goto err;
1806                 fout = fdopen(fd, mode);
1807         } else
1808                 fout = fopen(name, mode);
1809         closefunc = fclose;
1810         if (fout == NULL) {
1811                 perror_reply(553, name);
1812                 goto err;
1813         }
1814         byte_count = -1;
1815         if (restart_point) {
1816                 if (type == TYPE_A) {
1817                         off_t i, n;
1818                         int c;
1819
1820                         n = restart_point;
1821                         i = 0;
1822                         while (i++ < n) {
1823                                 if ((c=getc(fout)) == EOF) {
1824                                         perror_reply(550, name);
1825                                         goto done;
1826                                 }
1827                                 if (c == '\n')
1828                                         i++;
1829                         }
1830                         /*
1831                          * We must do this seek to "current" position
1832                          * because we are changing from reading to
1833                          * writing.
1834                          */
1835                         if (fseeko(fout, 0, SEEK_CUR) < 0) {
1836                                 perror_reply(550, name);
1837                                 goto done;
1838                         }
1839                 } else if (lseek(fileno(fout), restart_point, L_SET) < 0) {
1840                         perror_reply(550, name);
1841                         goto done;
1842                 }
1843         }
1844         din = dataconn(name, -1, "r");
1845         if (din == NULL)
1846                 goto done;
1847         if (receive_data(din, fout) == 0) {
1848                 if (unique)
1849                         reply(226, "Transfer complete (unique file name:%s).",
1850                             name);
1851                 else
1852                         reply(226, "Transfer complete.");
1853         }
1854         (void) fclose(din);
1855         data = -1;
1856         pdata = -1;
1857 done:
1858         LOGBYTES(*mode == 'a' ? "append" : "put", name, byte_count);
1859         (*closefunc)(fout);
1860         return;
1861 err:
1862         LOGCMD(*mode == 'a' ? "append" : "put" , name);
1863         return;
1864 }
1865
1866 static FILE *
1867 getdatasock(char *mode)
1868 {
1869         int on = 1, s, t, tries;
1870
1871         if (data >= 0)
1872                 return (fdopen(data, mode));
1873
1874         s = socket(data_dest.su_family, SOCK_STREAM, 0);
1875         if (s < 0)
1876                 goto bad;
1877         if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
1878                 syslog(LOG_WARNING, "data setsockopt (SO_REUSEADDR): %m");
1879         /* anchor socket to avoid multi-homing problems */
1880         data_source = ctrl_addr;
1881         data_source.su_port = htons(dataport);
1882         (void) seteuid(0);
1883         for (tries = 1; ; tries++) {
1884                 /*
1885                  * We should loop here since it's possible that
1886                  * another ftpd instance has passed this point and is
1887                  * trying to open a data connection in active mode now.
1888                  * Until the other connection is opened, we'll be getting
1889                  * EADDRINUSE because no SOCK_STREAM sockets in the system
1890                  * can share both local and remote addresses, localIP:20
1891                  * and *:* in this case.
1892                  */
1893                 if (bind(s, (struct sockaddr *)&data_source,
1894                     data_source.su_len) >= 0)
1895                         break;
1896                 if (errno != EADDRINUSE || tries > 10)
1897                         goto bad;
1898                 sleep(tries);
1899         }
1900         (void) seteuid(pw->pw_uid);
1901 #ifdef IP_TOS
1902         if (data_source.su_family == AF_INET)
1903       {
1904         on = IPTOS_THROUGHPUT;
1905         if (setsockopt(s, IPPROTO_IP, IP_TOS, &on, sizeof(int)) < 0)
1906                 syslog(LOG_WARNING, "data setsockopt (IP_TOS): %m");
1907       }
1908 #endif
1909 #ifdef TCP_NOPUSH
1910         /*
1911          * Turn off push flag to keep sender TCP from sending short packets
1912          * at the boundaries of each write().
1913          */
1914         on = 1;
1915         if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, &on, sizeof on) < 0)
1916                 syslog(LOG_WARNING, "data setsockopt (TCP_NOPUSH): %m");
1917 #endif
1918         return (fdopen(s, mode));
1919 bad:
1920         /* Return the real value of errno (close may change it) */
1921         t = errno;
1922         (void) seteuid(pw->pw_uid);
1923         (void) close(s);
1924         errno = t;
1925         return (NULL);
1926 }
1927
1928 static FILE *
1929 dataconn(char *name, off_t size, char *mode)
1930 {
1931         char sizebuf[32];
1932         FILE *file;
1933         int retry = 0, tos, conerrno;
1934
1935         file_size = size;
1936         byte_count = 0;
1937         if (size != -1)
1938                 (void) snprintf(sizebuf, sizeof(sizebuf),
1939                                 " (%jd bytes)", (intmax_t)size);
1940         else
1941                 *sizebuf = '\0';
1942         if (pdata >= 0) {
1943                 union sockunion from;
1944                 socklen_t fromlen = ctrl_addr.su_len;
1945                 int flags, s;
1946                 struct timeval timeout;
1947                 fd_set set;
1948
1949                 FD_ZERO(&set);
1950                 FD_SET(pdata, &set);
1951
1952                 timeout.tv_usec = 0;
1953                 timeout.tv_sec = 120;
1954
1955                 /*
1956                  * Granted a socket is in the blocking I/O mode,
1957                  * accept() will block after a successful select()
1958                  * if the selected connection dies in between.
1959                  * Therefore set the non-blocking I/O flag here.
1960                  */
1961                 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1962                     fcntl(pdata, F_SETFL, flags | O_NONBLOCK) == -1)
1963                         goto pdata_err;
1964                 if (select(pdata+1, &set, NULL, NULL, &timeout) <= 0 ||
1965                     (s = accept(pdata, (struct sockaddr *) &from, &fromlen)) < 0)
1966                         goto pdata_err;
1967                 (void) close(pdata);
1968                 pdata = s;
1969                 /*
1970                  * Unset the inherited non-blocking I/O flag
1971                  * on the child socket so stdio can work on it.
1972                  */
1973                 if ((flags = fcntl(pdata, F_GETFL, 0)) == -1 ||
1974                     fcntl(pdata, F_SETFL, flags & ~O_NONBLOCK) == -1)
1975                         goto pdata_err;
1976 #ifdef IP_TOS
1977                 if (from.su_family == AF_INET)
1978               {
1979                 tos = IPTOS_THROUGHPUT;
1980                 if (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0)
1981                         syslog(LOG_WARNING, "pdata setsockopt (IP_TOS): %m");
1982               }
1983 #endif
1984                 reply(150, "Opening %s mode data connection for '%s'%s.",
1985                      type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
1986                 return (fdopen(pdata, mode));
1987 pdata_err:
1988                 reply(425, "Can't open data connection.");
1989                 (void) close(pdata);
1990                 pdata = -1;
1991                 return (NULL);
1992         }
1993         if (data >= 0) {
1994                 reply(125, "Using existing data connection for '%s'%s.",
1995                     name, sizebuf);
1996                 usedefault = 1;
1997                 return (fdopen(data, mode));
1998         }
1999         if (usedefault)
2000                 data_dest = his_addr;
2001         usedefault = 1;
2002         do {
2003                 file = getdatasock(mode);
2004                 if (file == NULL) {
2005                         char hostbuf[NI_MAXHOST], portbuf[NI_MAXSERV];
2006
2007                         if (getnameinfo((struct sockaddr *)&data_source,
2008                                 data_source.su_len,
2009                                 hostbuf, sizeof(hostbuf) - 1,
2010                                 portbuf, sizeof(portbuf) - 1,
2011                                 NI_NUMERICHOST|NI_NUMERICSERV))
2012                                         *hostbuf = *portbuf = 0;
2013                         hostbuf[sizeof(hostbuf) - 1] = 0;
2014                         portbuf[sizeof(portbuf) - 1] = 0;
2015                         reply(425, "Can't create data socket (%s,%s): %s.",
2016                                 hostbuf, portbuf, strerror(errno));
2017                         return (NULL);
2018                 }
2019                 data = fileno(file);
2020                 conerrno = 0;
2021                 if (connect(data, (struct sockaddr *)&data_dest,
2022                     data_dest.su_len) == 0)
2023                         break;
2024                 conerrno = errno;
2025                 (void) fclose(file);
2026                 data = -1;
2027                 if (conerrno == EADDRINUSE) {
2028                         sleep(swaitint);
2029                         retry += swaitint;
2030                 } else {
2031                         break;
2032                 }
2033         } while (retry <= swaitmax);
2034         if (conerrno != 0) {
2035                 reply(425, "Can't build data connection: %s.",
2036                            strerror(conerrno));
2037                 return (NULL);
2038         }
2039         reply(150, "Opening %s mode data connection for '%s'%s.",
2040              type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf);
2041         return (file);
2042 }
2043
2044 /*
2045  * A helper macro to avoid code duplication
2046  * in send_data() and receive_data().
2047  *
2048  * XXX We have to block SIGURG during putc() because BSD stdio
2049  * is unable to restart interrupted write operations and hence
2050  * the entire buffer contents will be lost as soon as a write()
2051  * call indicates EINTR to stdio.
2052  */
2053 #define FTPD_PUTC(ch, file, label)                                      \
2054         do {                                                            \
2055                 int ret;                                                \
2056                                                                         \
2057                 do {                                                    \
2058                         START_UNSAFE;                                   \
2059                         ret = putc((ch), (file));                       \
2060                         END_UNSAFE;                                     \
2061                         CHECKOOB(return (-1))                           \
2062                         else if (ferror(file))                          \
2063                                 goto label;                             \
2064                         clearerr(file);                                 \
2065                 } while (ret == EOF);                                   \
2066         } while (0)
2067
2068 /*
2069  * Transfer the contents of "instr" to "outstr" peer using the appropriate
2070  * encapsulation of the data subject to Mode, Structure, and Type.
2071  *
2072  * NB: Form isn't handled.
2073  */
2074 static int
2075 send_data(FILE *instr, FILE *outstr, size_t blksize, off_t filesize, int isreg)
2076 {
2077         int c, cp, filefd, netfd;
2078         char *buf;
2079
2080         STARTXFER;
2081
2082         switch (type) {
2083
2084         case TYPE_A:
2085                 cp = EOF;
2086                 for (;;) {
2087                         c = getc(instr);
2088                         CHECKOOB(return (-1))
2089                         else if (c == EOF && ferror(instr))
2090                                 goto file_err;
2091                         if (c == EOF) {
2092                                 if (ferror(instr)) {    /* resume after OOB */
2093                                         clearerr(instr);
2094                                         continue;
2095                                 }
2096                                 if (feof(instr))        /* EOF */
2097                                         break;
2098                                 syslog(LOG_ERR, "Internal: impossible condition"
2099                                                 " on file after getc()");
2100                                 goto file_err;
2101                         }
2102                         if (c == '\n' && cp != '\r') {
2103                                 FTPD_PUTC('\r', outstr, data_err);
2104                                 byte_count++;
2105                         }
2106                         FTPD_PUTC(c, outstr, data_err);
2107                         byte_count++;
2108                         cp = c;
2109                 }
2110 #ifdef notyet   /* BSD stdio isn't ready for that */
2111                 while (fflush(outstr) == EOF) {
2112                         CHECKOOB(return (-1))
2113                         else
2114                                 goto data_err;
2115                         clearerr(outstr);
2116                 }
2117                 ENDXFER;
2118 #else
2119                 ENDXFER;
2120                 if (fflush(outstr) == EOF)
2121                         goto data_err;
2122 #endif
2123                 reply(226, "Transfer complete.");
2124                 return (0);
2125
2126         case TYPE_I:
2127         case TYPE_L:
2128                 /*
2129                  * isreg is only set if we are not doing restart and we
2130                  * are sending a regular file
2131                  */
2132                 netfd = fileno(outstr);
2133                 filefd = fileno(instr);
2134
2135                 if (isreg) {
2136                         char *msg = "Transfer complete.";
2137                         off_t cnt, offset;
2138                         int err;
2139
2140                         cnt = offset = 0;
2141
2142                         while (filesize > 0) {
2143                                 err = sendfile(filefd, netfd, offset, 0,
2144                                                NULL, &cnt, 0);
2145                                 /*
2146                                  * Calculate byte_count before OOB processing.
2147                                  * It can be used in myoob() later.
2148                                  */
2149                                 byte_count += cnt;
2150                                 offset += cnt;
2151                                 filesize -= cnt;
2152                                 CHECKOOB(return (-1))
2153                                 else if (err == -1) {
2154                                         if (errno != EINTR &&
2155                                             cnt == 0 && offset == 0)
2156                                                 goto oldway;
2157                                         goto data_err;
2158                                 }
2159                                 if (err == -1)  /* resume after OOB */
2160                                         continue;
2161                                 /*
2162                                  * We hit the EOF prematurely.
2163                                  * Perhaps the file was externally truncated.
2164                                  */
2165                                 if (cnt == 0) {
2166                                         msg = "Transfer finished due to "
2167                                               "premature end of file.";
2168                                         break;
2169                                 }
2170                         }
2171                         ENDXFER;
2172                         reply(226, "%s", msg);
2173                         return (0);
2174                 }
2175
2176 oldway:
2177                 if ((buf = malloc(blksize)) == NULL) {
2178                         ENDXFER;
2179                         reply(451, "Ran out of memory.");
2180                         return (-1);
2181                 }
2182
2183                 for (;;) {
2184                         int cnt, len;
2185                         char *bp;
2186
2187                         cnt = read(filefd, buf, blksize);
2188                         CHECKOOB(free(buf); return (-1))
2189                         else if (cnt < 0) {
2190                                 free(buf);
2191                                 goto file_err;
2192                         }
2193                         if (cnt < 0)    /* resume after OOB */
2194                                 continue;
2195                         if (cnt == 0)   /* EOF */
2196                                 break;
2197                         for (len = cnt, bp = buf; len > 0;) {
2198                                 cnt = write(netfd, bp, len);
2199                                 CHECKOOB(free(buf); return (-1))
2200                                 else if (cnt < 0) {
2201                                         free(buf);
2202                                         goto data_err;
2203                                 }
2204                                 if (cnt <= 0)
2205                                         continue;
2206                                 len -= cnt;
2207                                 bp += cnt;
2208                                 byte_count += cnt;
2209                         }
2210                 }
2211                 ENDXFER;
2212                 free(buf);
2213                 reply(226, "Transfer complete.");
2214                 return (0);
2215         default:
2216                 ENDXFER;
2217                 reply(550, "Unimplemented TYPE %d in send_data.", type);
2218                 return (-1);
2219         }
2220
2221 data_err:
2222         ENDXFER;
2223         perror_reply(426, "Data connection");
2224         return (-1);
2225
2226 file_err:
2227         ENDXFER;
2228         perror_reply(551, "Error on input file");
2229         return (-1);
2230 }
2231
2232 /*
2233  * Transfer data from peer to "outstr" using the appropriate encapulation of
2234  * the data subject to Mode, Structure, and Type.
2235  *
2236  * N.B.: Form isn't handled.
2237  */
2238 static int
2239 receive_data(FILE *instr, FILE *outstr)
2240 {
2241         int c, cp;
2242         int bare_lfs = 0;
2243
2244         STARTXFER;
2245
2246         switch (type) {
2247
2248         case TYPE_I:
2249         case TYPE_L:
2250                 for (;;) {
2251                         int cnt, len;
2252                         char *bp;
2253                         char buf[BUFSIZ];
2254
2255                         cnt = read(fileno(instr), buf, sizeof(buf));
2256                         CHECKOOB(return (-1))
2257                         else if (cnt < 0)
2258                                 goto data_err;
2259                         if (cnt < 0)    /* resume after OOB */
2260                                 continue;
2261                         if (cnt == 0)   /* EOF */
2262                                 break;
2263                         for (len = cnt, bp = buf; len > 0;) {
2264                                 cnt = write(fileno(outstr), bp, len);
2265                                 CHECKOOB(return (-1))
2266                                 else if (cnt < 0)
2267                                         goto file_err;
2268                                 if (cnt <= 0)
2269                                         continue;
2270                                 len -= cnt;
2271                                 bp += cnt;
2272                                 byte_count += cnt;
2273                         }
2274                 }
2275                 ENDXFER;
2276                 return (0);
2277
2278         case TYPE_E:
2279                 ENDXFER;
2280                 reply(553, "TYPE E not implemented.");
2281                 return (-1);
2282
2283         case TYPE_A:
2284                 cp = EOF;
2285                 for (;;) {
2286                         c = getc(instr);
2287                         CHECKOOB(return (-1))
2288                         else if (c == EOF && ferror(instr))
2289                                 goto data_err;
2290                         if (c == EOF && ferror(instr)) { /* resume after OOB */
2291                                 clearerr(instr);
2292                                 continue;
2293                         }
2294
2295                         if (cp == '\r') {
2296                                 if (c != '\n')
2297                                         FTPD_PUTC('\r', outstr, file_err);
2298                         } else
2299                                 if (c == '\n')
2300                                         bare_lfs++;
2301                         if (c == '\r') {
2302                                 byte_count++;
2303                                 cp = c;
2304                                 continue;
2305                         }
2306
2307                         /* Check for EOF here in order not to lose last \r. */
2308                         if (c == EOF) {
2309                                 if (feof(instr))        /* EOF */
2310                                         break;
2311                                 syslog(LOG_ERR, "Internal: impossible condition"
2312                                                 " on data stream after getc()");
2313                                 goto data_err;
2314                         }
2315
2316                         byte_count++;
2317                         FTPD_PUTC(c, outstr, file_err);
2318                         cp = c;
2319                 }
2320 #ifdef notyet   /* BSD stdio isn't ready for that */
2321                 while (fflush(outstr) == EOF) {
2322                         CHECKOOB(return (-1))
2323                         else
2324                                 goto file_err;
2325                         clearerr(outstr);
2326                 }
2327                 ENDXFER;
2328 #else
2329                 ENDXFER;
2330                 if (fflush(outstr) == EOF)
2331                         goto file_err;
2332 #endif
2333                 if (bare_lfs) {
2334                         lreply(226,
2335                 "WARNING! %d bare linefeeds received in ASCII mode.",
2336                             bare_lfs);
2337                 (void)printf("   File may not have transferred correctly.\r\n");
2338                 }
2339                 return (0);
2340         default:
2341                 ENDXFER;
2342                 reply(550, "Unimplemented TYPE %d in receive_data.", type);
2343                 return (-1);
2344         }
2345
2346 data_err:
2347         ENDXFER;
2348         perror_reply(426, "Data connection");
2349         return (-1);
2350
2351 file_err:
2352         ENDXFER;
2353         perror_reply(452, "Error writing to file");
2354         return (-1);
2355 }
2356
2357 void
2358 statfilecmd(char *filename)
2359 {
2360         FILE *fin;
2361         int atstart;
2362         int c, code;
2363         char line[LINE_MAX];
2364         struct stat st;
2365
2366         code = lstat(filename, &st) == 0 && S_ISDIR(st.st_mode) ? 212 : 213;
2367         (void)snprintf(line, sizeof(line), _PATH_LS " -lgA %s", filename);
2368         fin = ftpd_popen(line, "r");
2369         if (fin == NULL) {
2370                 perror_reply(551, filename);
2371                 return;
2372         }
2373         lreply(code, "Status of %s:", filename);
2374         atstart = 1;
2375         while ((c = getc(fin)) != EOF) {
2376                 if (c == '\n') {
2377                         if (ferror(stdout)){
2378                                 perror_reply(421, "Control connection");
2379                                 (void) ftpd_pclose(fin);
2380                                 dologout(1);
2381                                 /* NOTREACHED */
2382                         }
2383                         if (ferror(fin)) {
2384                                 perror_reply(551, filename);
2385                                 (void) ftpd_pclose(fin);
2386                                 return;
2387                         }
2388                         (void) putc('\r', stdout);
2389                 }
2390                 /*
2391                  * RFC 959 says neutral text should be prepended before
2392                  * a leading 3-digit number followed by whitespace, but
2393                  * many ftp clients can be confused by any leading digits,
2394                  * as a matter of fact.
2395                  */
2396                 if (atstart && isdigit(c))
2397                         (void) putc(' ', stdout);
2398                 (void) putc(c, stdout);
2399                 atstart = (c == '\n');
2400         }
2401         (void) ftpd_pclose(fin);
2402         reply(code, "End of status.");
2403 }
2404
2405 void
2406 statcmd(void)
2407 {
2408         union sockunion *su;
2409         u_char *a, *p;
2410         char hname[NI_MAXHOST];
2411         int ispassive;
2412
2413         if (hostinfo) {
2414                 lreply(211, "%s FTP server status:", hostname);
2415                 printf("     %s\r\n", version);
2416         } else
2417                 lreply(211, "FTP server status:");
2418         printf("     Connected to %s", remotehost);
2419         if (!getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
2420                          hname, sizeof(hname) - 1, NULL, 0, NI_NUMERICHOST)) {
2421                 hname[sizeof(hname) - 1] = 0;
2422                 if (strcmp(hname, remotehost) != 0)
2423                         printf(" (%s)", hname);
2424         }
2425         printf("\r\n");
2426         if (logged_in) {
2427                 if (guest)
2428                         printf("     Logged in anonymously\r\n");
2429                 else
2430                         printf("     Logged in as %s\r\n", pw->pw_name);
2431         } else if (askpasswd)
2432                 printf("     Waiting for password\r\n");
2433         else
2434                 printf("     Waiting for user name\r\n");
2435         printf("     TYPE: %s", typenames[type]);
2436         if (type == TYPE_A || type == TYPE_E)
2437                 printf(", FORM: %s", formnames[form]);
2438         if (type == TYPE_L)
2439 #if CHAR_BIT == 8
2440                 printf(" %d", CHAR_BIT);
2441 #else
2442                 printf(" %d", bytesize);        /* need definition! */
2443 #endif
2444         printf("; STRUcture: %s; transfer MODE: %s\r\n",
2445             strunames[stru], modenames[mode]);
2446         if (data != -1)
2447                 printf("     Data connection open\r\n");
2448         else if (pdata != -1) {
2449                 ispassive = 1;
2450                 su = &pasv_addr;
2451                 goto printaddr;
2452         } else if (usedefault == 0) {
2453                 ispassive = 0;
2454                 su = &data_dest;
2455 printaddr:
2456 #define UC(b) (((int) b) & 0xff)
2457                 if (epsvall) {
2458                         printf("     EPSV only mode (EPSV ALL)\r\n");
2459                         goto epsvonly;
2460                 }
2461
2462                 /* PORT/PASV */
2463                 if (su->su_family == AF_INET) {
2464                         a = (u_char *) &su->su_sin.sin_addr;
2465                         p = (u_char *) &su->su_sin.sin_port;
2466                         printf("     %s (%d,%d,%d,%d,%d,%d)\r\n",
2467                                 ispassive ? "PASV" : "PORT",
2468                                 UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
2469                                 UC(p[0]), UC(p[1]));
2470                 }
2471
2472                 /* LPRT/LPSV */
2473             {
2474                 int alen, af, i;
2475
2476                 switch (su->su_family) {
2477                 case AF_INET:
2478                         a = (u_char *) &su->su_sin.sin_addr;
2479                         p = (u_char *) &su->su_sin.sin_port;
2480                         alen = sizeof(su->su_sin.sin_addr);
2481                         af = 4;
2482                         break;
2483                 case AF_INET6:
2484                         a = (u_char *) &su->su_sin6.sin6_addr;
2485                         p = (u_char *) &su->su_sin6.sin6_port;
2486                         alen = sizeof(su->su_sin6.sin6_addr);
2487                         af = 6;
2488                         break;
2489                 default:
2490                         af = 0;
2491                         break;
2492                 }
2493                 if (af) {
2494                         printf("     %s (%d,%d,", ispassive ? "LPSV" : "LPRT",
2495                                 af, alen);
2496                         for (i = 0; i < alen; i++)
2497                                 printf("%d,", UC(a[i]));
2498                         printf("%d,%d,%d)\r\n", 2, UC(p[0]), UC(p[1]));
2499                 }
2500             }
2501
2502 epsvonly:;
2503                 /* EPRT/EPSV */
2504             {
2505                 int af;
2506
2507                 switch (su->su_family) {
2508                 case AF_INET:
2509                         af = 1;
2510                         break;
2511                 case AF_INET6:
2512                         af = 2;
2513                         break;
2514                 default:
2515                         af = 0;
2516                         break;
2517                 }
2518                 if (af) {
2519                         union sockunion tmp;
2520
2521                         tmp = *su;
2522                         if (tmp.su_family == AF_INET6)
2523                                 tmp.su_sin6.sin6_scope_id = 0;
2524                         if (!getnameinfo((struct sockaddr *)&tmp, tmp.su_len,
2525                                         hname, sizeof(hname) - 1, NULL, 0,
2526                                         NI_NUMERICHOST)) {
2527                                 hname[sizeof(hname) - 1] = 0;
2528                                 printf("     %s |%d|%s|%d|\r\n",
2529                                         ispassive ? "EPSV" : "EPRT",
2530                                         af, hname, htons(tmp.su_port));
2531                         }
2532                 }
2533             }
2534 #undef UC
2535         } else
2536                 printf("     No data connection\r\n");
2537         reply(211, "End of status.");
2538 }
2539
2540 void
2541 fatalerror(char *s)
2542 {
2543
2544         reply(451, "Error in server: %s", s);
2545         reply(221, "Closing connection due to server error.");
2546         dologout(0);
2547         /* NOTREACHED */
2548 }
2549
2550 void
2551 reply(int n, const char *fmt, ...)
2552 {
2553         va_list ap;
2554
2555         (void)printf("%d ", n);
2556         va_start(ap, fmt);
2557         (void)vprintf(fmt, ap);
2558         va_end(ap);
2559         (void)printf("\r\n");
2560         (void)fflush(stdout);
2561         if (ftpdebug) {
2562                 syslog(LOG_DEBUG, "<--- %d ", n);
2563                 va_start(ap, fmt);
2564                 vsyslog(LOG_DEBUG, fmt, ap);
2565                 va_end(ap);
2566         }
2567 }
2568
2569 void
2570 lreply(int n, const char *fmt, ...)
2571 {
2572         va_list ap;
2573
2574         (void)printf("%d- ", n);
2575         va_start(ap, fmt);
2576         (void)vprintf(fmt, ap);
2577         va_end(ap);
2578         (void)printf("\r\n");
2579         (void)fflush(stdout);
2580         if (ftpdebug) {
2581                 syslog(LOG_DEBUG, "<--- %d- ", n);
2582                 va_start(ap, fmt);
2583                 vsyslog(LOG_DEBUG, fmt, ap);
2584                 va_end(ap);
2585         }
2586 }
2587
2588 static void
2589 ack(char *s)
2590 {
2591
2592         reply(250, "%s command successful.", s);
2593 }
2594
2595 void
2596 nack(char *s)
2597 {
2598
2599         reply(502, "%s command not implemented.", s);
2600 }
2601
2602 /* ARGSUSED */
2603 void
2604 yyerror(char *s)
2605 {
2606         char *cp;
2607
2608         if ((cp = strchr(cbuf,'\n')))
2609                 *cp = '\0';
2610         reply(500, "%s: command not understood.", cbuf);
2611 }
2612
2613 void
2614 delete(char *name)
2615 {
2616         struct stat st;
2617
2618         LOGCMD("delete", name);
2619         if (lstat(name, &st) < 0) {
2620                 perror_reply(550, name);
2621                 return;
2622         }
2623         if (S_ISDIR(st.st_mode)) {
2624                 if (rmdir(name) < 0) {
2625                         perror_reply(550, name);
2626                         return;
2627                 }
2628                 goto done;
2629         }
2630         if (guest && noguestmod) {
2631                 reply(550, "Operation not permitted.");
2632                 return;
2633         }
2634         if (unlink(name) < 0) {
2635                 perror_reply(550, name);
2636                 return;
2637         }
2638 done:
2639         ack("DELE");
2640 }
2641
2642 void
2643 cwd(char *path)
2644 {
2645
2646         if (chdir(path) < 0)
2647                 perror_reply(550, path);
2648         else
2649                 ack("CWD");
2650 }
2651
2652 void
2653 makedir(char *name)
2654 {
2655         char *s;
2656
2657         LOGCMD("mkdir", name);
2658         if (guest && noguestmkd)
2659                 reply(550, "Operation not permitted.");
2660         else if (mkdir(name, 0777) < 0)
2661                 perror_reply(550, name);
2662         else {
2663                 if ((s = doublequote(name)) == NULL)
2664                         fatalerror("Ran out of memory.");
2665                 reply(257, "\"%s\" directory created.", s);
2666                 free(s);
2667         }
2668 }
2669
2670 void
2671 removedir(char *name)
2672 {
2673
2674         LOGCMD("rmdir", name);
2675         if (rmdir(name) < 0)
2676                 perror_reply(550, name);
2677         else
2678                 ack("RMD");
2679 }
2680
2681 void
2682 pwd(void)
2683 {
2684         char *s, path[MAXPATHLEN + 1];
2685
2686         if (getcwd(path, sizeof(path)) == NULL)
2687                 perror_reply(550, "Get current directory");
2688         else {
2689                 if ((s = doublequote(path)) == NULL)
2690                         fatalerror("Ran out of memory.");
2691                 reply(257, "\"%s\" is current directory.", s);
2692                 free(s);
2693         }
2694 }
2695
2696 char *
2697 renamefrom(char *name)
2698 {
2699         struct stat st;
2700
2701         if (guest && noguestmod) {
2702                 reply(550, "Operation not permitted.");
2703                 return (NULL);
2704         }
2705         if (lstat(name, &st) < 0) {
2706                 perror_reply(550, name);
2707                 return (NULL);
2708         }
2709         reply(350, "File exists, ready for destination name.");
2710         return (name);
2711 }
2712
2713 void
2714 renamecmd(char *from, char *to)
2715 {
2716         struct stat st;
2717
2718         LOGCMD2("rename", from, to);
2719
2720         if (guest && (stat(to, &st) == 0)) {
2721                 reply(550, "%s: permission denied.", to);
2722                 return;
2723         }
2724
2725         if (rename(from, to) < 0)
2726                 perror_reply(550, "rename");
2727         else
2728                 ack("RNTO");
2729 }
2730
2731 static void
2732 dolog(struct sockaddr *who)
2733 {
2734         char who_name[NI_MAXHOST];
2735
2736         realhostname_sa(remotehost, sizeof(remotehost) - 1, who, who->sa_len);
2737         remotehost[sizeof(remotehost) - 1] = 0;
2738         if (getnameinfo(who, who->sa_len,
2739                 who_name, sizeof(who_name) - 1, NULL, 0, NI_NUMERICHOST))
2740                         *who_name = 0;
2741         who_name[sizeof(who_name) - 1] = 0;
2742
2743 #ifdef SETPROCTITLE
2744 #ifdef VIRTUAL_HOSTING
2745         if (thishost != firsthost)
2746                 snprintf(proctitle, sizeof(proctitle), "%s: connected (to %s)",
2747                          remotehost, hostname);
2748         else
2749 #endif
2750                 snprintf(proctitle, sizeof(proctitle), "%s: connected",
2751                          remotehost);
2752         setproctitle("%s", proctitle);
2753 #endif /* SETPROCTITLE */
2754
2755         if (logging) {
2756 #ifdef VIRTUAL_HOSTING
2757                 if (thishost != firsthost)
2758                         syslog(LOG_INFO, "connection from %s (%s) to %s",
2759                                remotehost, who_name, hostname);
2760                 else
2761 #endif
2762                         syslog(LOG_INFO, "connection from %s (%s)",
2763                                remotehost, who_name);
2764         }
2765 }
2766
2767 /*
2768  * Record logout in wtmp file
2769  * and exit with supplied status.
2770  */
2771 void
2772 dologout(int status)
2773 {
2774
2775         if (logged_in && dowtmp) {
2776                 (void) seteuid(0);
2777 #ifdef          LOGIN_CAP
2778                 setusercontext(NULL, getpwuid(0), 0, LOGIN_SETALL & ~(LOGIN_SETLOGIN |
2779                        LOGIN_SETUSER | LOGIN_SETGROUP | LOGIN_SETPATH |
2780                        LOGIN_SETENV));
2781 #endif
2782                 ftpd_logwtmp(wtmpid, NULL, NULL);
2783         }
2784         /* beware of flushing buffers after a SIGPIPE */
2785         _exit(status);
2786 }
2787
2788 static void
2789 sigurg(int signo)
2790 {
2791
2792         recvurg = 1;
2793 }
2794
2795 static void
2796 maskurg(int flag)
2797 {
2798         int oerrno;
2799         sigset_t sset;
2800
2801         if (!transflag) {
2802                 syslog(LOG_ERR, "Internal: maskurg() while no transfer");
2803                 return;
2804         }
2805         oerrno = errno;
2806         sigemptyset(&sset);
2807         sigaddset(&sset, SIGURG);
2808         sigprocmask(flag ? SIG_BLOCK : SIG_UNBLOCK, &sset, NULL);
2809         errno = oerrno;
2810 }
2811
2812 static void
2813 flagxfer(int flag)
2814 {
2815
2816         if (flag) {
2817                 if (transflag)
2818                         syslog(LOG_ERR, "Internal: flagxfer(1): "
2819                                         "transfer already under way");
2820                 transflag = 1;
2821                 maskurg(0);
2822                 recvurg = 0;
2823         } else {
2824                 if (!transflag)
2825                         syslog(LOG_ERR, "Internal: flagxfer(0): "
2826                                         "no active transfer");
2827                 maskurg(1);
2828                 transflag = 0;
2829         }
2830 }
2831
2832 /*
2833  * Returns 0 if OK to resume or -1 if abort requested.
2834  */
2835 static int
2836 myoob(void)
2837 {
2838         char *cp;
2839         int ret;
2840
2841         if (!transflag) {
2842                 syslog(LOG_ERR, "Internal: myoob() while no transfer");
2843                 return (0);
2844         }
2845         cp = tmpline;
2846         ret = get_line(cp, 7, stdin);
2847         if (ret == -1) {
2848                 reply(221, "You could at least say goodbye.");
2849                 dologout(0);
2850         } else if (ret == -2) {
2851                 /* Ignore truncated command. */
2852                 return (0);
2853         }
2854         upper(cp);
2855         if (strcmp(cp, "ABOR\r\n") == 0) {
2856                 tmpline[0] = '\0';
2857                 reply(426, "Transfer aborted. Data connection closed.");
2858                 reply(226, "Abort successful.");
2859                 return (-1);
2860         }
2861         if (strcmp(cp, "STAT\r\n") == 0) {
2862                 tmpline[0] = '\0';
2863                 if (file_size != -1)
2864                         reply(213, "Status: %jd of %jd bytes transferred.",
2865                                    (intmax_t)byte_count, (intmax_t)file_size);
2866                 else
2867                         reply(213, "Status: %jd bytes transferred.",
2868                                    (intmax_t)byte_count);
2869         }
2870         return (0);
2871 }
2872
2873 /*
2874  * Note: a response of 425 is not mentioned as a possible response to
2875  *      the PASV command in RFC959. However, it has been blessed as
2876  *      a legitimate response by Jon Postel in a telephone conversation
2877  *      with Rick Adams on 25 Jan 89.
2878  */
2879 void
2880 passive(void)
2881 {
2882         socklen_t len;
2883         int on;
2884         char *p, *a;
2885
2886         if (pdata >= 0)         /* close old port if one set */
2887                 close(pdata);
2888
2889         pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
2890         if (pdata < 0) {
2891                 perror_reply(425, "Can't open passive connection");
2892                 return;
2893         }
2894         on = 1;
2895         if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
2896                 syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m");
2897
2898         (void) seteuid(0);
2899
2900 #ifdef IP_PORTRANGE
2901         if (ctrl_addr.su_family == AF_INET) {
2902             on = restricted_data_ports ? IP_PORTRANGE_HIGH
2903                                        : IP_PORTRANGE_DEFAULT;
2904
2905             if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
2906                             &on, sizeof(on)) < 0)
2907                     goto pasv_error;
2908         }
2909 #endif
2910 #ifdef IPV6_PORTRANGE
2911         if (ctrl_addr.su_family == AF_INET6) {
2912             on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
2913                                        : IPV6_PORTRANGE_DEFAULT;
2914
2915             if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
2916                             &on, sizeof(on)) < 0)
2917                     goto pasv_error;
2918         }
2919 #endif
2920
2921         pasv_addr = ctrl_addr;
2922         pasv_addr.su_port = 0;
2923         if (bind(pdata, (struct sockaddr *)&pasv_addr, pasv_addr.su_len) < 0)
2924                 goto pasv_error;
2925
2926         (void) seteuid(pw->pw_uid);
2927
2928         len = sizeof(pasv_addr);
2929         if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
2930                 goto pasv_error;
2931         if (listen(pdata, 1) < 0)
2932                 goto pasv_error;
2933         if (pasv_addr.su_family == AF_INET)
2934                 a = (char *) &pasv_addr.su_sin.sin_addr;
2935         else if (pasv_addr.su_family == AF_INET6 &&
2936                  IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr))
2937                 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
2938         else
2939                 goto pasv_error;
2940                 
2941         p = (char *) &pasv_addr.su_port;
2942
2943 #define UC(b) (((int) b) & 0xff)
2944
2945         reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]),
2946                 UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1]));
2947         return;
2948
2949 pasv_error:
2950         (void) seteuid(pw->pw_uid);
2951         (void) close(pdata);
2952         pdata = -1;
2953         perror_reply(425, "Can't open passive connection");
2954         return;
2955 }
2956
2957 /*
2958  * Long Passive defined in RFC 1639.
2959  *     228 Entering Long Passive Mode
2960  *         (af, hal, h1, h2, h3,..., pal, p1, p2...)
2961  */
2962
2963 void
2964 long_passive(char *cmd, int pf)
2965 {
2966         socklen_t len;
2967         int on;
2968         char *p, *a;
2969
2970         if (pdata >= 0)         /* close old port if one set */
2971                 close(pdata);
2972
2973         if (pf != PF_UNSPEC) {
2974                 if (ctrl_addr.su_family != pf) {
2975                         switch (ctrl_addr.su_family) {
2976                         case AF_INET:
2977                                 pf = 1;
2978                                 break;
2979                         case AF_INET6:
2980                                 pf = 2;
2981                                 break;
2982                         default:
2983                                 pf = 0;
2984                                 break;
2985                         }
2986                         /*
2987                          * XXX
2988                          * only EPRT/EPSV ready clients will understand this
2989                          */
2990                         if (strcmp(cmd, "EPSV") == 0 && pf) {
2991                                 reply(522, "Network protocol mismatch, "
2992                                         "use (%d)", pf);
2993                         } else
2994                                 reply(501, "Network protocol mismatch."); /*XXX*/
2995
2996                         return;
2997                 }
2998         }
2999                 
3000         pdata = socket(ctrl_addr.su_family, SOCK_STREAM, 0);
3001         if (pdata < 0) {
3002                 perror_reply(425, "Can't open passive connection");
3003                 return;
3004         }
3005         on = 1;
3006         if (setsockopt(pdata, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
3007                 syslog(LOG_WARNING, "pdata setsockopt (SO_REUSEADDR): %m");
3008
3009         (void) seteuid(0);
3010
3011         pasv_addr = ctrl_addr;
3012         pasv_addr.su_port = 0;
3013         len = pasv_addr.su_len;
3014
3015 #ifdef IP_PORTRANGE
3016         if (ctrl_addr.su_family == AF_INET) {
3017             on = restricted_data_ports ? IP_PORTRANGE_HIGH
3018                                        : IP_PORTRANGE_DEFAULT;
3019
3020             if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE,
3021                             &on, sizeof(on)) < 0)
3022                     goto pasv_error;
3023         }
3024 #endif
3025 #ifdef IPV6_PORTRANGE
3026         if (ctrl_addr.su_family == AF_INET6) {
3027             on = restricted_data_ports ? IPV6_PORTRANGE_HIGH
3028                                        : IPV6_PORTRANGE_DEFAULT;
3029
3030             if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE,
3031                             &on, sizeof(on)) < 0)
3032                     goto pasv_error;
3033         }
3034 #endif
3035
3036         if (bind(pdata, (struct sockaddr *)&pasv_addr, len) < 0)
3037                 goto pasv_error;
3038
3039         (void) seteuid(pw->pw_uid);
3040
3041         if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0)
3042                 goto pasv_error;
3043         if (listen(pdata, 1) < 0)
3044                 goto pasv_error;
3045
3046 #define UC(b) (((int) b) & 0xff)
3047
3048         if (strcmp(cmd, "LPSV") == 0) {
3049                 p = (char *)&pasv_addr.su_port;
3050                 switch (pasv_addr.su_family) {
3051                 case AF_INET:
3052                         a = (char *) &pasv_addr.su_sin.sin_addr;
3053                 v4_reply:
3054                         reply(228,
3055 "Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)",
3056                               4, 4, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
3057                               2, UC(p[0]), UC(p[1]));
3058                         return;
3059                 case AF_INET6:
3060                         if (IN6_IS_ADDR_V4MAPPED(&pasv_addr.su_sin6.sin6_addr)) {
3061                                 a = (char *) &pasv_addr.su_sin6.sin6_addr.s6_addr[12];
3062                                 goto v4_reply;
3063                         }
3064                         a = (char *) &pasv_addr.su_sin6.sin6_addr;
3065                         reply(228,
3066 "Entering Long Passive Mode "
3067 "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
3068                               6, 16, UC(a[0]), UC(a[1]), UC(a[2]), UC(a[3]),
3069                               UC(a[4]), UC(a[5]), UC(a[6]), UC(a[7]),
3070                               UC(a[8]), UC(a[9]), UC(a[10]), UC(a[11]),
3071                               UC(a[12]), UC(a[13]), UC(a[14]), UC(a[15]),
3072                               2, UC(p[0]), UC(p[1]));
3073                         return;
3074                 }
3075         } else if (strcmp(cmd, "EPSV") == 0) {
3076                 switch (pasv_addr.su_family) {
3077                 case AF_INET:
3078                 case AF_INET6:
3079                         reply(229, "Entering Extended Passive Mode (|||%d|)",
3080                                 ntohs(pasv_addr.su_port));
3081                         return;
3082                 }
3083         } else {
3084                 /* more proper error code? */
3085         }
3086
3087 pasv_error:
3088         (void) seteuid(pw->pw_uid);
3089         (void) close(pdata);
3090         pdata = -1;
3091         perror_reply(425, "Can't open passive connection");
3092         return;
3093 }
3094
3095 /*
3096  * Generate unique name for file with basename "local"
3097  * and open the file in order to avoid possible races.
3098  * Try "local" first, then "local.1", "local.2" etc, up to "local.99".
3099  * Return descriptor to the file, set "name" to its name.
3100  *
3101  * Generates failure reply on error.
3102  */
3103 static int
3104 guniquefd(char *local, char **name)
3105 {
3106         static char new[MAXPATHLEN];
3107         struct stat st;
3108         char *cp;
3109         int count;
3110         int fd;
3111
3112         cp = strrchr(local, '/');
3113         if (cp)
3114                 *cp = '\0';
3115         if (stat(cp ? local : ".", &st) < 0) {
3116                 perror_reply(553, cp ? local : ".");
3117                 return (-1);
3118         }
3119         if (cp) {
3120                 /*
3121                  * Let not overwrite dirname with counter suffix.
3122                  * -4 is for /nn\0
3123                  * In this extreme case dot won't be put in front of suffix.
3124                  */
3125                 if (strlen(local) > sizeof(new) - 4) {
3126                         reply(553, "Pathname too long.");
3127                         return (-1);
3128                 }
3129                 *cp = '/';
3130         }
3131         /* -4 is for the .nn<null> we put on the end below */
3132         (void) snprintf(new, sizeof(new) - 4, "%s", local);
3133         cp = new + strlen(new);
3134         /* 
3135          * Don't generate dotfile unless requested explicitly.
3136          * This covers the case when basename gets truncated off
3137          * by buffer size.
3138          */
3139         if (cp > new && cp[-1] != '/')
3140                 *cp++ = '.';
3141         for (count = 0; count < 100; count++) {
3142                 /* At count 0 try unmodified name */
3143                 if (count)
3144                         (void)sprintf(cp, "%d", count);
3145                 if ((fd = open(count ? new : local,
3146                     O_RDWR | O_CREAT | O_EXCL, 0666)) >= 0) {
3147                         *name = count ? new : local;
3148                         return (fd);
3149                 }
3150                 if (errno != EEXIST) {
3151                         perror_reply(553, count ? new : local);
3152                         return (-1);
3153                 }
3154         }
3155         reply(452, "Unique file name cannot be created.");
3156         return (-1);
3157 }
3158
3159 /*
3160  * Format and send reply containing system error number.
3161  */
3162 void
3163 perror_reply(int code, char *string)
3164 {
3165
3166         reply(code, "%s: %s.", string, strerror(errno));
3167 }
3168
3169 static char *onefile[] = {
3170         "",
3171         0
3172 };
3173
3174 void
3175 send_file_list(char *whichf)
3176 {
3177         struct stat st;
3178         DIR *dirp = NULL;
3179         struct dirent *dir;
3180         FILE *dout = NULL;
3181         char **dirlist, *dirname;
3182         int simple = 0;
3183         int freeglob = 0;
3184         glob_t gl;
3185
3186         if (strpbrk(whichf, "~{[*?") != NULL) {
3187                 int flags = GLOB_BRACE|GLOB_NOCHECK|GLOB_TILDE;
3188
3189                 memset(&gl, 0, sizeof(gl));
3190                 gl.gl_matchc = MAXGLOBARGS;
3191                 flags |= GLOB_LIMIT;
3192                 freeglob = 1;
3193                 if (glob(whichf, flags, 0, &gl)) {
3194                         reply(550, "No matching files found.");
3195                         goto out;
3196                 } else if (gl.gl_pathc == 0) {
3197                         errno = ENOENT;
3198                         perror_reply(550, whichf);
3199                         goto out;
3200                 }
3201                 dirlist = gl.gl_pathv;
3202         } else {
3203                 onefile[0] = whichf;
3204                 dirlist = onefile;
3205                 simple = 1;
3206         }
3207
3208         while ((dirname = *dirlist++)) {
3209                 if (stat(dirname, &st) < 0) {
3210                         /*
3211                          * If user typed "ls -l", etc, and the client
3212                          * used NLST, do what the user meant.
3213                          */
3214                         if (dirname[0] == '-' && *dirlist == NULL &&
3215                             dout == NULL)
3216                                 retrieve(_PATH_LS " %s", dirname);
3217                         else
3218                                 perror_reply(550, whichf);
3219                         goto out;
3220                 }
3221
3222                 if (S_ISREG(st.st_mode)) {
3223                         if (dout == NULL) {
3224                                 dout = dataconn("file list", -1, "w");
3225                                 if (dout == NULL)
3226                                         goto out;
3227                                 STARTXFER;
3228                         }
3229                         START_UNSAFE;
3230                         fprintf(dout, "%s%s\n", dirname,
3231                                 type == TYPE_A ? "\r" : "");
3232                         END_UNSAFE;
3233                         if (ferror(dout))
3234                                 goto data_err;
3235                         byte_count += strlen(dirname) +
3236                                       (type == TYPE_A ? 2 : 1);
3237                         CHECKOOB(goto abrt);
3238                         continue;
3239                 } else if (!S_ISDIR(st.st_mode))
3240                         continue;
3241
3242                 if ((dirp = opendir(dirname)) == NULL)
3243                         continue;
3244
3245                 while ((dir = readdir(dirp)) != NULL) {
3246                         char nbuf[MAXPATHLEN];
3247
3248                         CHECKOOB(goto abrt);
3249
3250                         if (dir->d_name[0] == '.' && dir->d_namlen == 1)
3251                                 continue;
3252                         if (dir->d_name[0] == '.' && dir->d_name[1] == '.' &&
3253                             dir->d_namlen == 2)
3254                                 continue;
3255
3256                         snprintf(nbuf, sizeof(nbuf),
3257                                 "%s/%s", dirname, dir->d_name);
3258
3259                         /*
3260                          * We have to do a stat to insure it's
3261                          * not a directory or special file.
3262                          */
3263                         if (simple || (stat(nbuf, &st) == 0 &&
3264                             S_ISREG(st.st_mode))) {
3265                                 if (dout == NULL) {
3266                                         dout = dataconn("file list", -1, "w");
3267                                         if (dout == NULL)
3268                                                 goto out;
3269                                         STARTXFER;
3270                                 }
3271                                 START_UNSAFE;
3272                                 if (nbuf[0] == '.' && nbuf[1] == '/')
3273                                         fprintf(dout, "%s%s\n", &nbuf[2],
3274                                                 type == TYPE_A ? "\r" : "");
3275                                 else
3276                                         fprintf(dout, "%s%s\n", nbuf,
3277                                                 type == TYPE_A ? "\r" : "");
3278                                 END_UNSAFE;
3279                                 if (ferror(dout))
3280                                         goto data_err;
3281                                 byte_count += strlen(nbuf) +
3282                                               (type == TYPE_A ? 2 : 1);
3283                                 CHECKOOB(goto abrt);
3284                         }
3285                 }
3286                 (void) closedir(dirp);
3287                 dirp = NULL;
3288         }
3289
3290         if (dout == NULL)
3291                 reply(550, "No files found.");
3292         else if (ferror(dout))
3293 data_err:       perror_reply(550, "Data connection");
3294         else
3295                 reply(226, "Transfer complete.");
3296 out:
3297         if (dout) {
3298                 ENDXFER;
3299 abrt:
3300                 (void) fclose(dout);
3301                 data = -1;
3302                 pdata = -1;
3303         }
3304         if (dirp)
3305                 (void) closedir(dirp);
3306         if (freeglob) {
3307                 freeglob = 0;
3308                 globfree(&gl);
3309         }
3310 }
3311
3312 void
3313 reapchild(int signo)
3314 {
3315         while (waitpid(-1, NULL, WNOHANG) > 0);
3316 }
3317
3318 static void
3319 appendf(char **strp, char *fmt, ...)
3320 {
3321         va_list ap;
3322         char *ostr, *p;
3323
3324         va_start(ap, fmt);
3325         vasprintf(&p, fmt, ap);
3326         va_end(ap);
3327         if (p == NULL)
3328                 fatalerror("Ran out of memory.");
3329         if (*strp == NULL)
3330                 *strp = p;
3331         else {
3332                 ostr = *strp;
3333                 asprintf(strp, "%s%s", ostr, p);
3334                 if (*strp == NULL)
3335                         fatalerror("Ran out of memory.");
3336                 free(ostr);
3337         }
3338 }
3339
3340 static void
3341 logcmd(char *cmd, char *file1, char *file2, off_t cnt)
3342 {
3343         char *msg = NULL;
3344         char wd[MAXPATHLEN + 1];
3345
3346         if (logging <= 1)
3347                 return;
3348
3349         if (getcwd(wd, sizeof(wd) - 1) == NULL)
3350                 strcpy(wd, strerror(errno));
3351
3352         appendf(&msg, "%s", cmd);
3353         if (file1)
3354                 appendf(&msg, " %s", file1);
3355         if (file2)
3356                 appendf(&msg, " %s", file2);
3357         if (cnt >= 0)
3358                 appendf(&msg, " = %jd bytes", (intmax_t)cnt);
3359         appendf(&msg, " (wd: %s", wd);
3360         if (guest || dochroot)
3361                 appendf(&msg, "; chrooted");
3362         appendf(&msg, ")");
3363         syslog(LOG_INFO, "%s", msg);
3364         free(msg);
3365 }
3366
3367 static void
3368 logxfer(char *name, off_t size, time_t start)
3369 {
3370         char buf[MAXPATHLEN + 1024];
3371         char path[MAXPATHLEN + 1];
3372         time_t now;
3373
3374         if (statfd >= 0) {
3375                 time(&now);
3376                 if (realpath(name, path) == NULL) {
3377                         syslog(LOG_NOTICE, "realpath failed on %s: %m", path);
3378                         return;
3379                 }
3380                 snprintf(buf, sizeof(buf), "%.20s!%s!%s!%s!%jd!%ld\n",
3381                         ctime(&now)+4, ident, remotehost,
3382                         path, (intmax_t)size,
3383                         (long)(now - start + (now == start)));
3384                 write(statfd, buf, strlen(buf));
3385         }
3386 }
3387
3388 static char *
3389 doublequote(char *s)
3390 {
3391         int n;
3392         char *p, *s2;
3393
3394         for (p = s, n = 0; *p; p++)
3395                 if (*p == '"')
3396                         n++;
3397
3398         if ((s2 = malloc(p - s + n + 1)) == NULL)
3399                 return (NULL);
3400
3401         for (p = s2; *s; s++, p++) {
3402                 if ((*p = *s) == '"')
3403                         *(++p) = '"';
3404         }
3405         *p = '\0';
3406
3407         return (s2);
3408 }
3409
3410 /* setup server socket for specified address family */
3411 /* if af is PF_UNSPEC more than one socket may be returned */
3412 /* the returned list is dynamically allocated, so caller needs to free it */
3413 static int *
3414 socksetup(int af, char *bindname, const char *bindport)
3415 {
3416         struct addrinfo hints, *res, *r;
3417         int error, maxs, *s, *socks;
3418         const int on = 1;
3419
3420         memset(&hints, 0, sizeof(hints));
3421         hints.ai_flags = AI_PASSIVE;
3422         hints.ai_family = af;
3423         hints.ai_socktype = SOCK_STREAM;
3424         error = getaddrinfo(bindname, bindport, &hints, &res);
3425         if (error) {
3426                 syslog(LOG_ERR, "%s", gai_strerror(error));
3427                 if (error == EAI_SYSTEM)
3428                         syslog(LOG_ERR, "%s", strerror(errno));
3429                 return NULL;
3430         }
3431
3432         /* Count max number of sockets we may open */
3433         for (maxs = 0, r = res; r; r = r->ai_next, maxs++)
3434                 ;
3435         socks = malloc((maxs + 1) * sizeof(int));
3436         if (!socks) {
3437                 freeaddrinfo(res);
3438                 syslog(LOG_ERR, "couldn't allocate memory for sockets");
3439                 return NULL;
3440         }
3441
3442         *socks = 0;   /* num of sockets counter at start of array */
3443         s = socks + 1;
3444         for (r = res; r; r = r->ai_next) {
3445                 *s = socket(r->ai_family, r->ai_socktype, r->ai_protocol);
3446                 if (*s < 0) {
3447                         syslog(LOG_DEBUG, "control socket: %m");
3448                         continue;
3449                 }
3450                 if (setsockopt(*s, SOL_SOCKET, SO_REUSEADDR,
3451                     &on, sizeof(on)) < 0)
3452                         syslog(LOG_WARNING,
3453                             "control setsockopt (SO_REUSEADDR): %m");
3454                 if (r->ai_family == AF_INET6) {
3455                         if (setsockopt(*s, IPPROTO_IPV6, IPV6_V6ONLY,
3456                             &on, sizeof(on)) < 0)
3457                                 syslog(LOG_WARNING,
3458                                     "control setsockopt (IPV6_V6ONLY): %m");
3459                 }
3460                 if (bind(*s, r->ai_addr, r->ai_addrlen) < 0) {
3461                         syslog(LOG_DEBUG, "control bind: %m");
3462                         close(*s);
3463                         continue;
3464                 }
3465                 (*socks)++;
3466                 s++;
3467         }
3468
3469         if (res)
3470                 freeaddrinfo(res);
3471
3472         if (*socks == 0) {
3473                 syslog(LOG_ERR, "control socket: Couldn't bind to any socket");
3474                 free(socks);
3475                 return NULL;
3476         }
3477         return(socks);
3478 }