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