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