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