2 * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by the University of
16 * California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 * may be used to endorse or promote products derived from this software
19 * without specific prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 static char copyright
[] =
37 "@(#) Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994\n\
38 The Regents of the University of California. All rights reserved.\n";
44 static char sccsid
[] = "@(#)ftpd.c 8.4 (Berkeley) 4/16/94";
46 static const char rcsid
[] =
47 "$FreeBSD: src/libexec/ftpd/ftpd.c,v 1.75 2001/03/27 19:40:50 markm Exp $";
53 #include <sys/param.h>
54 #include <sys/ioctl.h>
56 #include <sys/socket.h>
61 #include <netinet/in.h>
62 #include <netinet/in_systm.h>
63 #include <netinet/ip.h>
64 #include <netinet/tcp.h>
68 #include <arpa/inet.h>
69 #include <arpa/telnet.h>
89 // #include <libutil.h>
91 #include <login_cap.h>
99 #include <security/pam_appl.h>
102 #include "pathnames.h"
111 static char version
[] = "Version 6.00LS";
114 /* wrapper for KAME-special getnameinfo() */
115 #ifndef NI_WITHSCOPEID
116 #define NI_WITHSCOPEID 0
119 extern off_t restart_point
;
122 union sockunion server_addr
;
123 union sockunion ctrl_addr
;
124 union sockunion data_source
;
125 union sockunion data_dest
;
126 union sockunion his_addr
;
127 union sockunion pasv_addr
;
131 jmp_buf errcatch
, urgcatch
;
135 int timeout
= 900; /* timeout after 15 minutes of inactivity */
136 int maxtimeout
= 7200;/* don't allow idle time to be set beyond 2 hours */
138 int restricted_data_ports
= 1;
139 int paranoid
= 1; /* be extra careful about security */
140 int anon_only
= 0; /* Only anonymous ftp allowed */
147 int stru
; /* avoid C keyword */
149 int usedefault
= 1; /* for data transfers */
150 int pdata
= -1; /* for passive mode */
151 int readonly
=0; /* Server is in readonly mode. */
152 int noepsv
=0; /* EPSV command is disabled. */
153 sig_atomic_t transflag
;
156 #if !defined(CMASK) || CMASK == 0
160 int defumask
= CMASK
; /* default umask value */
163 #ifdef VIRTUAL_HOSTING
168 static struct ftphost
{
169 struct ftphost
*next
;
170 struct addrinfo
*hostinfo
;
176 } *thishost
, *firsthost
;
179 char remotehost
[MAXHOSTNAMELEN
];
182 static char ttyline
[20];
183 char *tty
= ttyline
; /* for klogin */
186 static int auth_pam
__P((struct passwd
**, const char*));
187 pam_handle_t
*pamh
= NULL
;
190 char *pid_file
= NULL
;
193 * Limit number of pathnames that glob can return.
194 * A limit of 0 indicates the number of pathnames is unlimited.
196 #define MAXGLOBARGS 16384
200 * Timeout intervals for retrying connections
201 * to hosts that don't accept PORT cmds. This
202 * is a kludge, but given the problems with TCP...
204 #define SWAITMAX 90 /* wait at most 90 seconds */
205 #define SWAITINT 5 /* interval between retries */
207 int swaitmax
= SWAITMAX
;
208 int swaitint
= SWAITINT
;
211 #ifdef OLD_SETPROCTITLE
212 char **Argv
= NULL
; /* pointer to argument vector */
213 char *LastArgv
= NULL
; /* end of argv */
214 #endif /* OLD_SETPROCTITLE */
215 char proctitle
[LINE_MAX
]; /* initial part of title */
216 #endif /* SETPROCTITLE */
222 #define LOGCMD(cmd, file) \
224 syslog(LOG_INFO,"%s %s%s", cmd, \
225 *(file) == '/' ? "" : curdir(), file);
226 #define LOGCMD2(cmd, file1, file2) \
228 syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
229 *(file1) == '/' ? "" : curdir(), file1, \
230 *(file2) == '/' ? "" : curdir(), file2);
231 #define LOGBYTES(cmd, file, cnt) \
233 if (cnt == (off_t)-1) \
234 syslog(LOG_INFO,"%s %s%s", cmd, \
235 *(file) == '/' ? "" : curdir(), file); \
237 syslog(LOG_INFO, "%s %s%s = %qd bytes", \
238 cmd, (*(file) == '/') ? "" : curdir(), file, cnt); \
241 #ifdef VIRTUAL_HOSTING
242 static void inithosts
__P((void));
243 static void selecthost
__P((union sockunion
*));
245 static void ack
__P((char *));
246 static void myoob
__P((int));
247 static int checkuser
__P((char *, char *, int));
248 static FILE *dataconn
__P((char *, off_t
, char *));
249 static void dolog
__P((struct sockaddr
*));
250 static char *curdir
__P((void));
251 static void end_login
__P((void));
252 static FILE *getdatasock
__P((char *));
253 static char *gunique
__P((char *));
254 static void lostconn
__P((int));
255 static int receive_data
__P((FILE *, FILE *));
256 static void send_data
__P((FILE *, FILE *, off_t
, off_t
, int));
257 static struct passwd
*
258 sgetpwnam
__P((char *));
259 static char *sgetsave
__P((char *));
260 static void reapchild
__P((int));
261 static void logxfer
__P((char *, long, long));
266 static char path
[MAXPATHLEN
+1+1]; /* path + '/' + '\0' */
268 if (getcwd(path
, sizeof(path
)-2) == NULL
)
270 if (path
[1] != '\0') /* special case for root dir. */
272 /* For guest account, skip / since it's chrooted */
273 return (guest
? path
+1 : path
);
277 main(argc
, argv
, envp
)
282 int addrlen
, ch
, on
= 1, tos
;
283 char *cp
, line
[LINE_MAX
];
286 char *bindname
= NULL
;
287 int family
= AF_UNSPEC
;
290 tzset(); /* in case no timezone database in ~ftp */
292 #ifdef OLD_SETPROCTITLE
294 * Save start and extent of argv for setproctitle.
299 LastArgv
= envp
[-1] + strlen(envp
[-1]);
300 #endif /* OLD_SETPROCTITLE */
303 while ((ch
= getopt(argc
, argv
, "AdlDESURrt:T:u:va:p:46")) != -1) {
318 logging
++; /* > 1 == extra logging */
334 maxtimeout
= atoi(optarg
);
335 if (timeout
> maxtimeout
)
336 timeout
= maxtimeout
;
340 timeout
= atoi(optarg
);
341 if (maxtimeout
< timeout
)
342 maxtimeout
= timeout
;
346 restricted_data_ports
= 0;
361 val
= strtol(optarg
, &optarg
, 8);
362 if (*optarg
!= '\0' || val
< 0)
363 warnx("bad value for -u");
378 if (family
== AF_UNSPEC
)
387 warnx("unknown flag -%c ignored", optopt
);
392 #ifdef VIRTUAL_HOSTING
395 (void) freopen(_PATH_DEVNULL
, "w", stderr
);
398 * LOG_NDELAY sets up the logging connection immediately,
399 * necessary for anonymous ftp's that chroot and can't do it later.
401 openlog("ftpd", LOG_PID
| LOG_NDELAY
, LOG_FTP
);
405 struct addrinfo hints
, *res
;
408 * Detach from parent.
410 if (daemon(1, 1) < 0) {
411 syslog(LOG_ERR
, "failed to become a daemon");
414 (void) signal(SIGCHLD
, reapchild
);
416 memset(&hints
, 0, sizeof(hints
));
418 hints
.ai_family
= family
== AF_UNSPEC
? AF_INET
: family
;
419 hints
.ai_socktype
= SOCK_STREAM
;
420 hints
.ai_protocol
= 0;
421 hints
.ai_flags
= AI_PASSIVE
;
422 error
= getaddrinfo(bindname
, "ftp", &hints
, &res
);
424 if (family
== AF_UNSPEC
) {
425 hints
.ai_family
= AF_UNSPEC
;
426 error
= getaddrinfo(bindname
, "ftp", &hints
,
431 syslog(LOG_ERR
, "%s", gai_strerror(error
));
432 if (error
== EAI_SYSTEM
)
433 syslog(LOG_ERR
, "%s", strerror(errno
));
436 if (res
->ai_addr
== NULL
) {
437 syslog(LOG_ERR
, "-a %s: getaddrinfo failed", hostname
);
440 family
= res
->ai_addr
->sa_family
;
442 * Open a socket, bind it to the FTP port, and start
445 ctl_sock
= socket(family
, SOCK_STREAM
, 0);
447 syslog(LOG_ERR
, "control socket: %m");
450 if (setsockopt(ctl_sock
, SOL_SOCKET
, SO_REUSEADDR
,
451 (char *)&on
, sizeof(on
)) < 0)
452 syslog(LOG_ERR
, "control setsockopt: %m");
453 #ifdef IPV6_BINDV6ONLY
454 if (family
== AF_INET6
&& enable_v4
== 0) {
455 if (setsockopt(ctl_sock
, IPPROTO_IPV6
, IPV6_BINDV6ONLY
,
456 (char *)&on
, sizeof (on
)) < 0)
458 "control setsockopt(IPV6_BINDV6ONLY): %m");
460 #endif /* IPV6_BINDV6ONLY */
461 memcpy(&server_addr
, res
->ai_addr
, res
->ai_addr
->sa_len
);
462 if (bind(ctl_sock
, (struct sockaddr
*)&server_addr
,
463 server_addr
.su_len
) < 0) {
464 syslog(LOG_ERR
, "control bind: %m");
467 if (listen(ctl_sock
, 32) < 0) {
468 syslog(LOG_ERR
, "control listen: %m");
472 * Atomically write process ID
479 fd
= open(pid_file
, O_CREAT
| O_WRONLY
| O_TRUNC
480 | O_NONBLOCK
| O_EXLOCK
, 0644);
483 errx(1, "%s: file locked", pid_file
);
485 err(1, "%s", pid_file
);
487 snprintf(buf
, sizeof(buf
),
488 "%lu\n", (unsigned long) getpid());
489 if (write(fd
, buf
, strlen(buf
)) < 0)
490 err(1, "%s: write", pid_file
);
491 /* Leave the pid file open and locked */
494 * Loop forever accepting connection requests and forking off
495 * children to handle them.
498 addrlen
= server_addr
.su_len
;
499 fd
= accept(ctl_sock
, (struct sockaddr
*)&his_addr
, &addrlen
);
510 addrlen
= sizeof(his_addr
);
511 if (getpeername(0, (struct sockaddr
*)&his_addr
, &addrlen
) < 0) {
512 syslog(LOG_ERR
, "getpeername (%s): %m",argv
[0]);
517 (void) signal(SIGCHLD
, SIG_IGN
);
518 (void) signal(SIGPIPE
, lostconn
);
519 if (signal(SIGURG
, myoob
) == SIG_ERR
)
520 syslog(LOG_ERR
, "signal: %m");
522 addrlen
= sizeof(ctrl_addr
);
523 if (getsockname(0, (struct sockaddr
*)&ctrl_addr
, &addrlen
) < 0) {
524 syslog(LOG_ERR
, "getsockname (%s): %m",argv
[0]);
527 #ifdef VIRTUAL_HOSTING
528 /* select our identity from virtual host table */
529 selecthost(&ctrl_addr
);
532 if (ctrl_addr
.su_family
== AF_INET
)
534 tos
= IPTOS_LOWDELAY
;
535 if (setsockopt(0, IPPROTO_IP
, IP_TOS
, (char *)&tos
, sizeof(int)) < 0)
536 syslog(LOG_WARNING
, "setsockopt (IP_TOS): %m");
540 * Disable Nagle on the control channel so that we don't have to wait
541 * for peer's ACK before issuing our next reply.
543 if (setsockopt(0, IPPROTO_TCP
, TCP_NODELAY
, &on
, sizeof(on
)) < 0)
544 syslog(LOG_WARNING
, "control setsockopt TCP_NODELAY: %m");
546 data_source
.su_port
= htons(ntohs(ctrl_addr
.su_port
) - 1);
548 /* set this here so klogin can use it... */
549 (void)snprintf(ttyline
, sizeof(ttyline
), "ftp%d", getpid());
551 /* Try to handle urgent data inline */
553 if (setsockopt(0, SOL_SOCKET
, SO_OOBINLINE
, (char *)&on
, sizeof(on
)) < 0)
554 syslog(LOG_ERR
, "setsockopt: %m");
558 if (fcntl(fileno(stdin
), F_SETOWN
, getpid()) == -1)
559 syslog(LOG_ERR
, "fcntl F_SETOWN: %m");
561 dolog((struct sockaddr
*)&his_addr
);
563 * Set up default state
572 /* If logins are disabled, print out the message. */
573 if ((fd
= fopen(_PATH_NOLOGIN
,"r")) != NULL
) {
574 while (fgets(line
, sizeof(line
), fd
) != NULL
) {
575 if ((cp
= strchr(line
, '\n')) != NULL
)
577 lreply(530, "%s", line
);
579 (void) fflush(stdout
);
581 reply(530, "System not available.");
584 #ifdef VIRTUAL_HOSTING
585 if ((fd
= fopen(thishost
->welcome
, "r")) != NULL
) {
587 if ((fd
= fopen(_PATH_FTPWELCOME
, "r")) != NULL
) {
589 while (fgets(line
, sizeof(line
), fd
) != NULL
) {
590 if ((cp
= strchr(line
, '\n')) != NULL
)
592 lreply(220, "%s", line
);
594 (void) fflush(stdout
);
596 /* reply(220,) must follow */
598 #ifndef VIRTUAL_HOSTING
599 if ((hostname
= malloc(MAXHOSTNAMELEN
)) == NULL
)
600 fatal("Ran out of memory.");
601 (void) gethostname(hostname
, MAXHOSTNAMELEN
- 1);
602 hostname
[MAXHOSTNAMELEN
- 1] = '\0';
604 reply(220, "%s FTP server (%s) ready.", hostname
, version
);
605 (void) setjmp(errcatch
);
617 syslog(LOG_DEBUG
, "lost connection");
621 #ifdef VIRTUAL_HOSTING
623 * read in virtual host tables (if they exist)
631 struct ftphost
*hrp
, *lhrp
;
633 struct addrinfo hints
, *res
, *ai
;
636 * Fill in the default host information
638 if (gethostname(line
, sizeof(line
)) < 0)
640 if ((hrp
= malloc(sizeof(struct ftphost
))) == NULL
||
641 (hrp
->hostname
= strdup(line
)) == NULL
)
642 fatal("Ran out of memory.");
643 hrp
->hostinfo
= NULL
;
645 memset(&hints
, 0, sizeof(hints
));
646 hints
.ai_flags
= AI_CANONNAME
;
647 hints
.ai_family
= AF_UNSPEC
;
648 getaddrinfo(hrp
->hostname
, NULL
, &hints
, &res
);
651 hrp
->statfile
= _PATH_FTPDSTATFILE
;
652 hrp
->welcome
= _PATH_FTPWELCOME
;
653 hrp
->loginmsg
= _PATH_FTPLOGINMESG
;
654 hrp
->anonuser
= "ftp";
656 thishost
= firsthost
= lhrp
= hrp
;
657 if ((fp
= fopen(_PATH_FTPHOSTS
, "r")) != NULL
) {
658 int addrsize
, error
, gothost
;
662 while (fgets(line
, sizeof(line
), fp
) != NULL
) {
665 if ((cp
= strchr(line
, '\n')) == NULL
) {
666 /* ignore long lines */
667 while (fgets(line
, sizeof(line
), fp
) != NULL
&&
668 strchr(line
, '\n') == NULL
)
673 cp
= strtok(line
, " \t");
674 /* skip comments and empty lines */
675 if (cp
== NULL
|| line
[0] == '#')
679 hints
.ai_family
= AF_UNSPEC
;
680 hints
.ai_flags
= AI_PASSIVE
;
681 error
= getaddrinfo(cp
, NULL
, &hints
, &res
);
684 for (ai
= res
; ai
!= NULL
&& ai
->ai_addr
!= NULL
;
688 for (hrp
= firsthost
; hrp
!= NULL
; hrp
= hrp
->next
) {
691 for (hi
= hrp
->hostinfo
; hi
!= NULL
;
693 if (hi
->ai_addrlen
== ai
->ai_addrlen
&&
696 ai
->ai_addr
->sa_len
) == 0) {
704 if ((hrp
= malloc(sizeof(struct ftphost
))) == NULL
)
707 hrp
->statfile
= _PATH_FTPDSTATFILE
;
708 hrp
->welcome
= _PATH_FTPWELCOME
;
709 hrp
->loginmsg
= _PATH_FTPLOGINMESG
;
710 hrp
->anonuser
= "ftp";
718 * determine hostname to use.
719 * force defined name if there is a valid alias
720 * otherwise fallback to primary hostname
722 /* XXX: getaddrinfo() can't do alias check */
723 switch(hrp
->hostinfo
->ai_family
) {
725 addr
= &((struct sockaddr_in
*)&hrp
->hostinfo
->ai_addr
)->sin_addr
;
726 addrsize
= sizeof(struct sockaddr_in
);
729 addr
= &((struct sockaddr_in6
*)&hrp
->hostinfo
->ai_addr
)->sin6_addr
;
730 addrsize
= sizeof(struct sockaddr_in6
);
733 /* should not reach here */
734 if (hrp
->hostinfo
!= NULL
)
735 freeaddrinfo(hrp
->hostinfo
);
740 if ((hp
= getipnodebyaddr((char*)addr
, addrsize
,
741 hrp
->hostinfo
->ai_family
,
742 &hp_error
)) != NULL
) {
743 if (strcmp(cp
, hp
->h_name
) != 0) {
744 if (hp
->h_aliases
== NULL
)
748 while (hp
->h_aliases
[i
] &&
749 strcmp(cp
, hp
->h_aliases
[i
]) != 0)
751 if (hp
->h_aliases
[i
] == NULL
)
756 hrp
->hostname
= strdup(cp
);
758 /* ok, now we now peel off the rest */
760 while (i
< 4 && (cp
= strtok(NULL
, " \t")) != NULL
) {
761 if (*cp
!= '-' && (cp
= strdup(cp
)) != NULL
) {
763 case 0: /* anon user permissions */
766 case 1: /* statistics file */
769 case 2: /* welcome message */
772 case 3: /* login message */
779 /* XXX: re-initialization for getaddrinfo() loop */
780 cp
= strtok(line
, " \t");
794 struct in6_addr
*mapped_in6
= NULL
;
800 * XXX IPv4 mapped IPv6 addr consideraton,
801 * specified in rfc2373.
803 if (su
->su_family
== AF_INET6
&&
804 IN6_IS_ADDR_V4MAPPED(&su
->su_sin6
.sin6_addr
))
805 mapped_in6
= &su
->su_sin6
.sin6_addr
;
808 hrp
= thishost
= firsthost
; /* default */
811 while (hrp
!= NULL
) {
812 for (hi
= hrp
->hostinfo
; hi
!= NULL
; hi
= hi
->ai_next
) {
813 if (memcmp(su
, hi
->ai_addr
, hi
->ai_addrlen
) == 0) {
818 /* XXX IPv4 mapped IPv6 addr consideraton */
819 if (hi
->ai_addr
->sa_family
== AF_INET
&& mapped_in6
!= NULL
&&
820 (memcmp(&mapped_in6
->s6_addr
[12],
821 &((struct sockaddr_in
*)hi
->ai_addr
)->sin_addr
,
822 sizeof(struct in_addr
)) == 0)) {
831 /* setup static variables as appropriate */
832 hostname
= thishost
->hostname
;
833 ftpuser
= thishost
->anonuser
;
838 * Helper function for sgetpwnam().
844 char *new = malloc((unsigned) strlen(s
) + 1);
847 perror_reply(421, "Local resource failure: malloc");
851 (void) strcpy(new, s
);
856 * Save the result of a getpwnam. Used for USER command, since
857 * the data returned must not be clobbered by any other command
860 static struct passwd
*
864 static struct passwd save
;
867 if ((p
= getpwnam(name
)) == NULL
)
871 free(save
.pw_passwd
);
877 save
.pw_name
= sgetsave(p
->pw_name
);
878 save
.pw_passwd
= sgetsave(p
->pw_passwd
);
879 save
.pw_gecos
= sgetsave(p
->pw_gecos
);
880 save
.pw_dir
= sgetsave(p
->pw_dir
);
881 save
.pw_shell
= sgetsave(p
->pw_shell
);
885 static int login_attempts
; /* number of failed login attempts */
886 static int askpasswd
; /* had user command, ask for passwd */
887 static char curname
[MAXLOGNAME
]; /* current USER name */
891 * Sets global passwd pointer pw if named account exists and is acceptable;
892 * sets askpasswd if a PASS command is expected. If logged in previously,
893 * need to reset state. If name is "ftp" or "anonymous", the name is not in
894 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
895 * If account doesn't exist, ask for passwd anyway. Otherwise, check user
896 * requesting login privileges. Disallow anyone who does not have a standard
897 * shell as returned by getusershell(). Disallow anyone mentioned in the file
898 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
908 reply(530, "Can't change user from guest login.");
910 } else if (dochroot
) {
911 reply(530, "Can't change user from chroot user.");
918 if (strcmp(name
, "ftp") == 0 || strcmp(name
, "anonymous") == 0) {
919 #if !defined(_PATH_FTPUSERS)
920 #define _PATH_FTPUSERS "/etc/ftpusers"
922 if (checkuser(_PATH_FTPUSERS
, "ftp", 0) ||
923 checkuser(_PATH_FTPUSERS
, "anonymous", 0))
924 reply(530, "User %s access denied.", name
);
925 #ifdef VIRTUAL_HOSTING
926 else if ((pw
= sgetpwnam(thishost
->anonuser
)) != NULL
) {
928 else if ((pw
= sgetpwnam("ftp")) != NULL
) {
933 "Guest login ok, send your email address as password.");
935 reply(530, "User %s unknown.", name
);
936 if (!askpasswd
&& logging
)
938 "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost
);
941 if (anon_only
!= 0) {
942 reply(530, "Sorry, only anonymous ftp allowed.");
946 if ((pw
= sgetpwnam(name
))) {
947 if ((shell
= pw
->pw_shell
) == NULL
|| *shell
== 0)
948 shell
= _PATH_BSHELL
;
949 while ((cp
= getusershell()) != NULL
)
950 if (strcmp(cp
, shell
) == 0)
954 if (cp
== NULL
|| checkuser(_PATH_FTPUSERS
, name
, 1)) {
955 reply(530, "User %s access denied.", name
);
958 "FTP LOGIN REFUSED FROM %s, %s",
960 pw
= (struct passwd
*) NULL
;
965 strncpy(curname
, name
, sizeof(curname
)-1);
967 pwok
= skeyaccess(name
, NULL
, remotehost
, remotehost
);
968 reply(331, "%s", skey_challenge(name
, pw
, pwok
));
970 reply(331, "Password required for %s.", name
);
974 * Delay before reading passwd after first failed
975 * attempt to slow down passwd-guessing programs.
978 sleep((unsigned) login_attempts
);
982 * Check if a user is in the file "fname"
985 checkuser(fname
, name
, pwset
)
992 char *p
, line
[BUFSIZ
];
994 if ((fd
= fopen(fname
, "r")) != NULL
) {
995 while (!found
&& fgets(line
, sizeof(line
), fd
) != NULL
)
996 if ((p
= strchr(line
, '\n')) != NULL
) {
1001 * if first chr is '@', check group membership
1003 if (line
[0] == '@') {
1007 if ((grp
= getgrnam(line
+1)) == NULL
)
1010 * Check user's default group
1012 if (pwset
&& grp
->gr_gid
== pw
->pw_gid
)
1015 * Check supplementary groups
1017 while (!found
&& grp
->gr_mem
[i
])
1018 found
= strcmp(name
,
1023 * Otherwise, just check for username match
1026 found
= strcmp(line
, name
) == 0;
1034 * Terminate login as previous user, if any, resetting state;
1035 * used when USER command is given or login fails.
1044 (void) seteuid((uid_t
)0);
1046 ftpd_logwtmp(ttyline
, "", "");
1049 setusercontext(NULL
, getpwuid(0), (uid_t
)0,
1050 LOGIN_SETPRIORITY
|LOGIN_SETRESOURCES
|LOGIN_SETUMASK
);
1053 if ((e
= pam_setcred(pamh
, PAM_DELETE_CRED
)) != PAM_SUCCESS
)
1054 syslog(LOG_ERR
, "pam_setcred: %s", pam_strerror(pamh
, e
));
1055 if ((e
= pam_close_session(pamh
,0)) != PAM_SUCCESS
)
1056 syslog(LOG_ERR
, "pam_close_session: %s", pam_strerror(pamh
, e
));
1057 if ((e
= pam_end(pamh
, e
)) != PAM_SUCCESS
)
1058 syslog(LOG_ERR
, "pam_end: %s", pam_strerror(pamh
, e
));
1069 * the following code is stolen from imap-uw PAM authentication module and
1072 #define COPY_STRING(s) (s ? strdup(s) : NULL)
1075 const char *uname
; /* user name */
1076 const char *pass
; /* password */
1078 typedef struct cred_t cred_t
;
1081 auth_conv(int num_msg
, const struct pam_message
**msg
,
1082 struct pam_response
**resp
, void *appdata
)
1085 cred_t
*cred
= (cred_t
*) appdata
;
1086 struct pam_response
*reply
=
1087 malloc(sizeof(struct pam_response
) * num_msg
);
1089 for (i
= 0; i
< num_msg
; i
++) {
1090 switch (msg
[i
]->msg_style
) {
1091 case PAM_PROMPT_ECHO_ON
: /* assume want user name */
1092 reply
[i
].resp_retcode
= PAM_SUCCESS
;
1093 reply
[i
].resp
= COPY_STRING(cred
->uname
);
1094 /* PAM frees resp. */
1096 case PAM_PROMPT_ECHO_OFF
: /* assume want password */
1097 reply
[i
].resp_retcode
= PAM_SUCCESS
;
1098 reply
[i
].resp
= COPY_STRING(cred
->pass
);
1099 /* PAM frees resp. */
1103 reply
[i
].resp_retcode
= PAM_SUCCESS
;
1104 reply
[i
].resp
= NULL
;
1106 default: /* unknown message style */
1108 return PAM_CONV_ERR
;
1117 * Attempt to authenticate the user using PAM. Returns 0 if the user is
1118 * authenticated, or 1 if not authenticated. If some sort of PAM system
1119 * error occurs (e.g., the "/etc/pam.conf" file is missing) then this
1120 * function returns -1. This can be used as an indication that we should
1121 * fall back to a different authentication mechanism.
1124 auth_pam(struct passwd
**ppw
, const char *pass
)
1126 pam_handle_t
*pamh
= NULL
;
1127 const char *tmpl_user
;
1131 cred_t auth_cred
= { (*ppw
)->pw_name
, pass
};
1132 struct pam_conv conv
= { &auth_conv
, &auth_cred
};
1134 e
= pam_start("ftpd", (*ppw
)->pw_name
, &conv
, &pamh
);
1135 if (e
!= PAM_SUCCESS
) {
1136 syslog(LOG_ERR
, "pam_start: %s", pam_strerror(pamh
, e
));
1140 e
= pam_set_item(pamh
, PAM_RHOST
, remotehost
);
1141 if (e
!= PAM_SUCCESS
) {
1142 syslog(LOG_ERR
, "pam_set_item(PAM_RHOST): %s",
1143 pam_strerror(pamh
, e
));
1147 e
= pam_authenticate(pamh
, 0);
1151 * With PAM we support the concept of a "template"
1152 * user. The user enters a login name which is
1153 * authenticated by PAM, usually via a remote service
1154 * such as RADIUS or TACACS+. If authentication
1155 * succeeds, a different but related "template" name
1156 * is used for setting the credentials, shell, and
1157 * home directory. The name the user enters need only
1158 * exist on the remote authentication server, but the
1159 * template name must be present in the local password
1162 * This is supported by two various mechanisms in the
1163 * individual modules. However, from the application's
1164 * point of view, the template user is always passed
1165 * back as a changed value of the PAM_USER item.
1167 if ((e
= pam_get_item(pamh
, PAM_USER
, &item
)) ==
1169 tmpl_user
= (const char *) item
;
1170 if (strcmp((*ppw
)->pw_name
, tmpl_user
) != 0)
1171 *ppw
= getpwnam(tmpl_user
);
1173 syslog(LOG_ERR
, "Couldn't get PAM_USER: %s",
1174 pam_strerror(pamh
, e
));
1179 case PAM_USER_UNKNOWN
:
1185 syslog(LOG_ERR
, "pam_authenticate: %s", pam_strerror(pamh
, e
));
1191 e
= pam_acct_mgmt(pamh
, 0);
1192 if (e
== PAM_NEW_AUTHTOK_REQD
) {
1193 e
= pam_chauthtok(pamh
, PAM_CHANGE_EXPIRED_AUTHTOK
);
1194 if (e
!= PAM_SUCCESS
) {
1195 syslog(LOG_ERR
, "pam_chauthtok: %s", pam_strerror(pamh
, e
));
1198 } else if (e
!= PAM_SUCCESS
) {
1204 if ((e
= pam_end(pamh
, e
)) != PAM_SUCCESS
) {
1205 syslog(LOG_ERR
, "pam_end: %s", pam_strerror(pamh
, e
));
1212 #endif /* USE_PAM */
1221 login_cap_t
*lc
= NULL
;
1227 if (logged_in
|| askpasswd
== 0) {
1228 reply(503, "Login with USER first.");
1232 if (!guest
) { /* "ftp" is only account allowed no password */
1234 rval
= 1; /* failure below */
1238 rval
= auth_pam(&pw
, passwd
);
1244 rval
= strcmp(pw
->pw_passwd
,
1245 crypt(passwd
, pw
->pw_passwd
));
1247 rval
= strcmp(pw
->pw_passwd
,
1248 skey_crypt(passwd
, pw
->pw_passwd
, pw
, pwok
));
1250 rval
= strcmp(pw
->pw_passwd
, crypt(passwd
, pw
->pw_passwd
));
1252 /* The strcmp does not catch null passwords! */
1253 if (*pw
->pw_passwd
== '\0' ||
1254 (pw
->pw_expire
&& time(NULL
) >= pw
->pw_expire
))
1255 rval
= 1; /* failure */
1258 * If rval == 1, the user failed the authentication check
1259 * above. If rval == 0, either PAM or local authentication
1263 reply(530, "Login incorrect.");
1266 "FTP LOGIN FAILED FROM %s, %s",
1267 remotehost
, curname
);
1269 if (login_attempts
++ >= 5) {
1271 "repeated login failures from %s",
1281 login_attempts
= 0; /* this time successful */
1282 if (setegid((gid_t
)pw
->pw_gid
) < 0) {
1283 reply(550, "Can't set gid.");
1286 /* May be overridden by login.conf */
1287 (void) umask(defumask
);
1289 if ((lc
= login_getpwclass(pw
)) != NULL
) {
1290 char remote_ip
[MAXHOSTNAMELEN
];
1292 getnameinfo((struct sockaddr
*)&his_addr
, his_addr
.su_len
,
1293 remote_ip
, sizeof(remote_ip
) - 1, NULL
, 0,
1294 NI_NUMERICHOST
|NI_WITHSCOPEID
);
1295 remote_ip
[sizeof(remote_ip
) - 1] = 0;
1296 if (!auth_hostok(lc
, remotehost
, remote_ip
)) {
1297 syslog(LOG_INFO
|LOG_AUTH
,
1298 "FTP LOGIN FAILED (HOST) as %s: permission denied.",
1300 reply(530, "Permission denied.\n");
1304 if (!auth_timeok(lc
, time(NULL
))) {
1305 reply(530, "Login not available right now.\n");
1310 setusercontext(lc
, pw
, (uid_t
)0,
1311 LOGIN_SETLOGIN
|LOGIN_SETGROUP
|LOGIN_SETPRIORITY
|
1312 LOGIN_SETRESOURCES
|LOGIN_SETUMASK
);
1314 setlogin(pw
->pw_name
);
1315 (void) initgroups(pw
->pw_name
, pw
->pw_gid
);
1320 if ((e
= pam_open_session(pamh
, 0)) != PAM_SUCCESS
) {
1321 syslog(LOG_ERR
, "pam_open_session: %s", pam_strerror(pamh
, e
));
1322 } else if ((e
= pam_setcred(pamh
, PAM_ESTABLISH_CRED
)) != PAM_SUCCESS
) {
1323 syslog(LOG_ERR
, "pam_setcred: %s", pam_strerror(pamh
, e
));
1328 /* open wtmp before chroot */
1329 ftpd_logwtmp(ttyline
, pw
->pw_name
, remotehost
);
1332 if (guest
&& stats
&& statfd
< 0)
1333 #ifdef VIRTUAL_HOSTING
1334 if ((statfd
= open(thishost
->statfile
, O_WRONLY
|O_APPEND
)) < 0)
1336 if ((statfd
= open(_PATH_FTPDSTATFILE
, O_WRONLY
|O_APPEND
)) < 0)
1341 #ifdef LOGIN_CAP /* Allow login.conf configuration as well */
1342 login_getcapbool(lc
, "ftp-chroot", 0) ||
1344 checkuser(_PATH_FTPCHROOT
, pw
->pw_name
, 1);
1347 * We MUST do a chdir() after the chroot. Otherwise
1348 * the old current directory will be accessible as "."
1349 * outside the new root!
1351 if (chroot(pw
->pw_dir
) < 0 || chdir("/") < 0) {
1352 reply(550, "Can't set guest privileges.");
1355 } else if (dochroot
) {
1356 if (chroot(pw
->pw_dir
) < 0 || chdir("/") < 0) {
1357 reply(550, "Can't change root.");
1360 } else if (chdir(pw
->pw_dir
) < 0) {
1361 if (chdir("/") < 0) {
1362 reply(530, "User %s: can't change directory to %s.",
1363 pw
->pw_name
, pw
->pw_dir
);
1366 lreply(230, "No directory! Logging in with home=/");
1368 if (seteuid((uid_t
)pw
->pw_uid
) < 0) {
1369 reply(550, "Can't set uid.");
1374 * Display a login message, if it exists.
1375 * N.B. reply(230,) must follow the message.
1377 #ifdef VIRTUAL_HOSTING
1378 if ((fd
= fopen(thishost
->loginmsg
, "r")) != NULL
) {
1380 if ((fd
= fopen(_PATH_FTPLOGINMESG
, "r")) != NULL
) {
1382 char *cp
, line
[LINE_MAX
];
1384 while (fgets(line
, sizeof(line
), fd
) != NULL
) {
1385 if ((cp
= strchr(line
, '\n')) != NULL
)
1387 lreply(230, "%s", line
);
1389 (void) fflush(stdout
);
1395 ident
= strdup(passwd
);
1397 fatal("Ran out of memory.");
1399 reply(230, "Guest login ok, access restrictions apply.");
1401 #ifdef VIRTUAL_HOSTING
1402 if (thishost
!= firsthost
)
1403 snprintf(proctitle
, sizeof(proctitle
),
1404 "%s: anonymous(%s)/%.*s", remotehost
, hostname
,
1405 (int)(sizeof(proctitle
) - sizeof(remotehost
) -
1406 sizeof(": anonymous/")), passwd
);
1409 snprintf(proctitle
, sizeof(proctitle
),
1410 "%s: anonymous/%.*s", remotehost
,
1411 (int)(sizeof(proctitle
) - sizeof(remotehost
) -
1412 sizeof(": anonymous/")), passwd
);
1413 setproctitle("%s", proctitle
);
1414 #endif /* SETPROCTITLE */
1416 syslog(LOG_INFO
, "ANONYMOUS FTP LOGIN FROM %s, %s",
1417 remotehost
, passwd
);
1420 reply(230, "User %s logged in, access restrictions apply.",
1423 reply(230, "User %s logged in.", pw
->pw_name
);
1426 snprintf(proctitle
, sizeof(proctitle
),
1427 "%s: %s", remotehost
, pw
->pw_name
);
1428 setproctitle("%s", proctitle
);
1429 #endif /* SETPROCTITLE */
1431 syslog(LOG_INFO
, "FTP LOGIN FROM %s as %s",
1432 remotehost
, pw
->pw_name
);
1439 /* Forget all about it... */
1452 int (*closefunc
) __P((FILE *));
1456 fin
= fopen(name
, "r"), closefunc
= fclose
;
1461 (void) snprintf(line
, sizeof(line
), cmd
, name
), name
= line
;
1462 fin
= ftpd_popen(line
, "r"), closefunc
= ftpd_pclose
;
1464 st
.st_blksize
= BUFSIZ
;
1468 perror_reply(550, name
);
1470 LOGCMD("get", name
);
1476 if (cmd
== 0 && (fstat(fileno(fin
), &st
) < 0 || !S_ISREG(st
.st_mode
))) {
1477 reply(550, "%s: not a plain file.", name
);
1480 if (restart_point
) {
1481 if (type
== TYPE_A
) {
1488 if ((c
=getc(fin
)) == EOF
) {
1489 perror_reply(550, name
);
1495 } else if (lseek(fileno(fin
), restart_point
, L_SET
) < 0) {
1496 perror_reply(550, name
);
1500 dout
= dataconn(name
, st
.st_size
, "w");
1504 send_data(fin
, dout
, st
.st_blksize
, st
.st_size
,
1505 restart_point
== 0 && cmd
== 0 && S_ISREG(st
.st_mode
));
1506 if (cmd
== 0 && guest
&& stats
)
1507 logxfer(name
, st
.st_size
, start
);
1508 (void) fclose(dout
);
1513 LOGBYTES("get", name
, byte_count
);
1518 store(name
, mode
, unique
)
1524 int (*closefunc
) __P((FILE *));
1526 if ((unique
|| guest
) && stat(name
, &st
) == 0 &&
1527 (name
= gunique(name
)) == NULL
) {
1528 LOGCMD(*mode
== 'w' ? "put" : "append", name
);
1534 fout
= fopen(name
, mode
);
1537 perror_reply(553, name
);
1538 LOGCMD(*mode
== 'w' ? "put" : "append", name
);
1542 if (restart_point
) {
1543 if (type
== TYPE_A
) {
1550 if ((c
=getc(fout
)) == EOF
) {
1551 perror_reply(550, name
);
1558 * We must do this seek to "current" position
1559 * because we are changing from reading to
1562 if (fseek(fout
, 0L, L_INCR
) < 0) {
1563 perror_reply(550, name
);
1566 } else if (lseek(fileno(fout
), restart_point
, L_SET
) < 0) {
1567 perror_reply(550, name
);
1571 din
= dataconn(name
, (off_t
)-1, "r");
1574 if (receive_data(din
, fout
) == 0) {
1576 reply(226, "Transfer complete (unique file name:%s).",
1579 reply(226, "Transfer complete.");
1585 LOGBYTES(*mode
== 'w' ? "put" : "append", name
, byte_count
);
1593 int on
= 1, s
, t
, tries
;
1596 return (fdopen(data
, mode
));
1597 (void) seteuid((uid_t
)0);
1599 s
= socket(data_dest
.su_family
, SOCK_STREAM
, 0);
1602 if (setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
,
1603 (char *) &on
, sizeof(on
)) < 0)
1605 /* anchor socket to avoid multi-homing problems */
1606 data_source
= ctrl_addr
;
1607 data_source
.su_port
= htons(20); /* ftp-data port */
1608 for (tries
= 1; ; tries
++) {
1609 if (bind(s
, (struct sockaddr
*)&data_source
,
1610 data_source
.su_len
) >= 0)
1612 if (errno
!= EADDRINUSE
|| tries
> 10)
1616 (void) seteuid((uid_t
)pw
->pw_uid
);
1618 if (data_source
.su_family
== AF_INET
)
1620 on
= IPTOS_THROUGHPUT
;
1621 if (setsockopt(s
, IPPROTO_IP
, IP_TOS
, (char *)&on
, sizeof(int)) < 0)
1622 syslog(LOG_WARNING
, "setsockopt (IP_TOS): %m");
1627 * Turn off push flag to keep sender TCP from sending short packets
1628 * at the boundaries of each write(). Should probably do a SO_SNDBUF
1629 * to set the send buffer size as well, but that may not be desirable
1630 * in heavy-load situations.
1633 if (setsockopt(s
, IPPROTO_TCP
, TCP_NOPUSH
, (char *)&on
, sizeof on
) < 0)
1634 syslog(LOG_WARNING
, "setsockopt (TCP_NOPUSH): %m");
1638 if (setsockopt(s
, SOL_SOCKET
, SO_SNDBUF
, (char *)&on
, sizeof on
) < 0)
1639 syslog(LOG_WARNING
, "setsockopt (SO_SNDBUF): %m");
1642 return (fdopen(s
, mode
));
1644 /* Return the real value of errno (close may change it) */
1646 (void) seteuid((uid_t
)pw
->pw_uid
);
1653 dataconn(name
, size
, mode
)
1664 if (size
!= (off_t
) -1)
1665 (void) snprintf(sizebuf
, sizeof(sizebuf
), " (%qd bytes)", size
);
1669 union sockunion from
;
1670 int s
, fromlen
= ctrl_addr
.su_len
;
1671 struct timeval timeout
;
1675 FD_SET(pdata
, &set
);
1677 timeout
.tv_usec
= 0;
1678 timeout
.tv_sec
= 120;
1680 if (select(pdata
+1, &set
, (fd_set
*) 0, (fd_set
*) 0, &timeout
) == 0 ||
1681 (s
= accept(pdata
, (struct sockaddr
*) &from
, &fromlen
)) < 0) {
1682 reply(425, "Can't open data connection.");
1683 (void) close(pdata
);
1687 (void) close(pdata
);
1690 if (from
.su_family
== AF_INET
)
1692 tos
= IPTOS_THROUGHPUT
;
1693 (void) setsockopt(s
, IPPROTO_IP
, IP_TOS
, (char *)&tos
,
1697 reply(150, "Opening %s mode data connection for '%s'%s.",
1698 type
== TYPE_A
? "ASCII" : "BINARY", name
, sizebuf
);
1699 return (fdopen(pdata
, mode
));
1702 reply(125, "Using existing data connection for '%s'%s.",
1705 return (fdopen(data
, mode
));
1708 data_dest
= his_addr
;
1710 file
= getdatasock(mode
);
1712 #if defined(HAVE_GETNAMEINFO)
1713 char hostbuf
[BUFSIZ
], portbuf
[BUFSIZ
];
1714 getnameinfo((struct sockaddr
*)&data_source
,
1715 data_source
.su_len
, hostbuf
, sizeof(hostbuf
) - 1,
1716 portbuf
, sizeof(portbuf
),
1717 NI_NUMERICHOST
|NI_NUMERICSERV
|NI_WITHSCOPEID
);
1718 reply(425, "Can't create data socket (%s,%s): %s.",
1719 hostbuf
, portbuf
, strerror(errno
));
1721 reply(425, "Can't create data socket (%s,%d): %s.",
1722 inet_ntoa(data_source
.su_sin
.sin_addr
),
1723 ntohs(data_source
.su_sin
.sin_port
), strerror(errno
));
1727 data
= fileno(file
);
1728 while (connect(data
, (struct sockaddr
*)&data_dest
,
1729 data_dest
.su_len
) < 0) {
1730 if (errno
== EADDRINUSE
&& retry
< swaitmax
) {
1731 sleep((unsigned) swaitint
);
1735 perror_reply(425, "Can't build data connection");
1736 (void) fclose(file
);
1740 reply(150, "Opening %s mode data connection for '%s'%s.",
1741 type
== TYPE_A
? "ASCII" : "BINARY", name
, sizebuf
);
1746 * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1747 * encapsulation of the data subject to Mode, Structure, and Type.
1749 * NB: Form isn't handled.
1752 send_data(instr
, outstr
, blksize
, filesize
, isreg
)
1753 FILE *instr
, *outstr
;
1758 int c
, filefd
, netfd
;
1764 if (setjmp(urgcatch
)) {
1771 while ((c
= getc(instr
)) != EOF
) {
1776 (void) putc('\r', outstr
);
1778 (void) putc(c
, outstr
);
1786 reply(226, "Transfer complete.");
1792 * isreg is only set if we are not doing restart and we
1793 * are sending a regular file
1795 netfd
= fileno(outstr
);
1796 filefd
= fileno(instr
);
1798 #if defined(HAVE_SENDFILE)
1805 err
= cnt
= offset
= 0;
1807 while (err
!= -1 && cnt
< filesize
) {
1808 err
= sendfile(filefd
, netfd
, offset
, len
,
1809 (struct sf_hdtr
*) NULL
, &cnt
, 0);
1822 reply(226, "Transfer complete.");
1826 if (isreg
&& filesize
< (off_t
)16 * 1024 * 1024) {
1827 buf
= mmap(0, filesize
, PROT_READ
, MAP_SHARED
, filefd
,
1829 if (buf
== MAP_FAILED
) {
1830 syslog(LOG_WARNING
, "mmap(%lu): %m",
1831 (unsigned long)filesize
);
1837 cnt
= write(netfd
, bp
, len
);
1840 if (cnt
> 0) byte_count
+= cnt
;
1841 } while(cnt
> 0 && len
> 0);
1844 munmap(buf
, (size_t)filesize
);
1847 reply(226, "Transfer complete.");
1852 if ((buf
= malloc((u_int
)blksize
)) == NULL
) {
1854 perror_reply(451, "Local resource failure: malloc");
1858 while ((cnt
= read(filefd
, buf
, (u_int
)blksize
)) > 0 &&
1859 write(netfd
, buf
, cnt
) == cnt
)
1868 reply(226, "Transfer complete.");
1872 reply(550, "Unimplemented TYPE %d in send_data", type
);
1878 perror_reply(426, "Data connection");
1883 perror_reply(551, "Error on input file");
1887 * Transfer data from peer to "outstr" using the appropriate encapulation of
1888 * the data subject to Mode, Structure, and Type.
1890 * N.B.: Form isn't handled.
1893 receive_data(instr
, outstr
)
1894 FILE *instr
, *outstr
;
1901 if (setjmp(urgcatch
)) {
1912 while ((cnt
= read(fileno(instr
), buf
, sizeof(buf
))) > 0) {
1913 if (write(fileno(outstr
), buf
, cnt
) != cnt
)
1923 reply(553, "TYPE E not implemented.");
1928 while ((c
= getc(instr
)) != EOF
) {
1935 if ((c
= getc(instr
)) != '\n') {
1936 (void) putc ('\r', outstr
);
1937 if (c
== '\0' || c
== EOF
)
1941 (void) putc(c
, outstr
);
1952 "WARNING! %d bare linefeeds received in ASCII mode",
1954 (void)printf(" File may not have transferred correctly.\r\n");
1958 reply(550, "Unimplemented TYPE %d in receive_data", type
);
1965 perror_reply(426, "Data Connection");
1970 perror_reply(452, "Error writing file");
1975 statfilecmd(filename
)
1980 char line
[LINE_MAX
];
1982 (void)snprintf(line
, sizeof(line
), _PATH_LS
" -lgA %s", filename
);
1983 fin
= ftpd_popen(line
, "r");
1984 lreply(211, "status of %s:", filename
);
1985 while ((c
= getc(fin
)) != EOF
) {
1987 if (ferror(stdout
)){
1988 perror_reply(421, "control connection");
1989 (void) ftpd_pclose(fin
);
1994 perror_reply(551, filename
);
1995 (void) ftpd_pclose(fin
);
1998 (void) putc('\r', stdout
);
2000 (void) putc(c
, stdout
);
2002 (void) ftpd_pclose(fin
);
2003 reply(211, "End of Status");
2009 union sockunion
*su
;
2011 char hname
[INET6_ADDRSTRLEN
];
2014 lreply(211, "%s FTP server status:", hostname
, version
);
2015 printf(" %s\r\n", version
);
2016 printf(" Connected to %s", remotehost
);
2017 #if defined(HAVE_GETNAMEINFO)
2018 if (!getnameinfo((struct sockaddr
*)&his_addr
, his_addr
.su_len
,
2019 hname
, sizeof(hname
) - 1, NULL
, 0,
2020 NI_NUMERICHOST
|NI_WITHSCOPEID
)) {
2021 if (strcmp(hname
, remotehost
) != 0)
2022 printf(" (%s)", hname
);
2025 if (!isdigit(remotehost
[0]))
2026 printf(" (%s)", inet_ntoa(his_addr
.su_sin
.sin_addr
));
2032 printf(" Logged in anonymously\r\n");
2034 printf(" Logged in as %s\r\n", pw
->pw_name
);
2035 } else if (askpasswd
)
2036 printf(" Waiting for password\r\n");
2038 printf(" Waiting for user name\r\n");
2039 printf(" TYPE: %s", typenames
[type
]);
2040 if (type
== TYPE_A
|| type
== TYPE_E
)
2041 printf(", FORM: %s", formnames
[form
]);
2044 printf(" %d", NBBY
);
2046 printf(" %d", bytesize
); /* need definition! */
2048 printf("; STRUcture: %s; transfer MODE: %s\r\n",
2049 strunames
[stru
], modenames
[mode
]);
2051 printf(" Data connection open\r\n");
2052 else if (pdata
!= -1) {
2056 } else if (usedefault
== 0) {
2060 #define UC(b) (((int) b) & 0xff)
2061 #if defined(VIRTUAL_HOSTING)
2063 printf(" EPSV only mode (EPSV ALL)\r\n");
2069 if (su
->su_family
== AF_INET
) {
2070 a
= (u_char
*) &su
->su_sin
.sin_addr
;
2071 p
= (u_char
*) &su
->su_sin
.sin_port
;
2072 printf(" %s (%d,%d,%d,%d,%d,%d)\r\n",
2073 ispassive
? "PASV" : "PORT",
2074 UC(a
[0]), UC(a
[1]), UC(a
[2]), UC(a
[3]),
2075 UC(p
[0]), UC(p
[1]));
2082 switch (su
->su_family
) {
2084 a
= (u_char
*) &su
->su_sin
.sin_addr
;
2085 p
= (u_char
*) &su
->su_sin
.sin_port
;
2086 alen
= sizeof(su
->su_sin
.sin_addr
);
2090 a
= (u_char
*) &su
->su_sin6
.sin6_addr
;
2091 p
= (u_char
*) &su
->su_sin6
.sin6_port
;
2092 alen
= sizeof(su
->su_sin6
.sin6_addr
);
2100 printf(" %s (%d,%d,", ispassive
? "LPSV" : "LPRT",
2102 for (i
= 0; i
< alen
; i
++)
2103 printf("%d,", UC(a
[i
]));
2104 printf("%d,%d,%d)\r\n", 2, UC(p
[0]), UC(p
[1]));
2108 #if defined(HAVE_GETNAMEINFO)
2114 switch (su
->su_family
) {
2126 if (!getnameinfo((struct sockaddr
*)su
, su
->su_len
,
2127 hname
, sizeof(hname
) - 1, NULL
, 0,
2129 printf(" %s |%d|%s|%d|\r\n",
2130 ispassive
? "EPSV" : "EPRT",
2131 af
, hname
, htons(su
->su_port
));
2138 printf(" No data connection\r\n");
2139 reply(211, "End of status");
2147 reply(451, "Error in server: %s\n", s
);
2148 reply(221, "Closing connection due to server error.");
2155 reply(int n
, const char *fmt
, ...)
2157 reply(n
, fmt
, va_alist
)
2169 (void)printf("%d ", n
);
2170 (void)vprintf(fmt
, ap
);
2171 (void)printf("\r\n");
2172 (void)fflush(stdout
);
2174 syslog(LOG_DEBUG
, "<--- %d ", n
);
2175 vsyslog(LOG_DEBUG
, fmt
, ap
);
2181 lreply(int n
, const char *fmt
, ...)
2183 lreply(n
, fmt
, va_alist
)
2195 (void)printf("%d- ", n
);
2196 (void)vprintf(fmt
, ap
);
2197 (void)printf("\r\n");
2198 (void)fflush(stdout
);
2200 syslog(LOG_DEBUG
, "<--- %d- ", n
);
2201 vsyslog(LOG_DEBUG
, fmt
, ap
);
2210 reply(250, "%s command successful.", s
);
2218 reply(502, "%s command not implemented.", s
);
2228 if ((cp
= strchr(cbuf
,'\n')))
2230 reply(500, "'%s': command not understood.", cbuf
);
2239 LOGCMD("delete", name
);
2240 if (stat(name
, &st
) < 0) {
2241 perror_reply(550, name
);
2244 if ((st
.st_mode
&S_IFMT
) == S_IFDIR
) {
2245 if (rmdir(name
) < 0) {
2246 perror_reply(550, name
);
2251 if (unlink(name
) < 0) {
2252 perror_reply(550, name
);
2264 if (chdir(path
) < 0)
2265 perror_reply(550, path
);
2275 LOGCMD("mkdir", name
);
2276 if (mkdir(name
, 0777) < 0)
2277 perror_reply(550, name
);
2279 reply(257, "MKD command successful.");
2287 LOGCMD("rmdir", name
);
2288 if (rmdir(name
) < 0)
2289 perror_reply(550, name
);
2297 char path
[MAXPATHLEN
+ 1];
2299 if (getwd(path
) == (char *)NULL
)
2300 reply(550, "%s.", path
);
2302 reply(257, "\"%s\" is current directory.", path
);
2311 if (stat(name
, &st
) < 0) {
2312 perror_reply(550, name
);
2315 reply(350, "File exists, ready for destination name");
2325 LOGCMD2("rename", from
, to
);
2327 if (guest
&& (stat(to
, &st
) == 0)) {
2328 reply(550, "%s: permission denied", to
);
2332 if (rename(from
, to
) < 0)
2333 perror_reply(550, "rename");
2340 struct sockaddr
*who
;
2342 #if defined(HAVE_GETNAMEINFO)
2346 #if defined(HAVE_REALHOSTNAME_SA)
2347 realhostname_sa(remotehost
, sizeof(remotehost
) - 1, who
, who
->sa_len
);
2349 struct sockaddr_in
*sin
= (struct sockaddr_in
*)who
;
2350 struct hostent
*hp
= gethostbyaddr((char *)&sin
->sin_addr
,
2351 sizeof(struct in_addr
), AF_INET
);
2354 (void) strncpy(remotehost
, hp
->h_name
, sizeof(remotehost
));
2356 (void) strncpy(remotehost
, inet_ntoa(sin
->sin_addr
),
2357 sizeof(remotehost
));
2361 #ifdef VIRTUAL_HOSTING
2362 if (thishost
!= firsthost
)
2363 snprintf(proctitle
, sizeof(proctitle
), "%s: connected (to %s)",
2364 remotehost
, hostname
);
2367 snprintf(proctitle
, sizeof(proctitle
), "%s: connected",
2369 setproctitle("%s", proctitle
);
2370 #endif /* SETPROCTITLE */
2373 #ifdef VIRTUAL_HOSTING
2374 if (thishost
!= firsthost
)
2375 syslog(LOG_INFO
, "connection from %s (to %s)",
2376 remotehost
, hostname
);
2380 #if defined(HAVE_GETNAMEINFO)
2381 char who_name
[MAXHOSTNAMELEN
];
2383 error
= getnameinfo(who
, who
->sa_len
,
2384 who_name
, sizeof(who_name
) - 1,
2386 NI_NUMERICHOST
|NI_WITHSCOPEID
);
2387 syslog(LOG_INFO
, "connection from %s (%s)", remotehost
,
2388 error
== 0 ? who_name
: "");
2390 syslog(LOG_INFO
, "connection from %s", remotehost
);
2397 * Record logout in wtmp file
2398 * and exit with supplied status.
2405 * Prevent reception of SIGURG from resulting in a resumption
2406 * back to the main program loop.
2411 (void) seteuid((uid_t
)0);
2412 ftpd_logwtmp(ttyline
, "", "");
2414 /* beware of flushing buffers after a SIGPIPE */
2424 /* only process if transfer occurring */
2428 if (getline(cp
, 7, stdin
) == NULL
) {
2429 reply(221, "You could at least say goodbye.");
2433 if (strcmp(cp
, "ABOR\r\n") == 0) {
2435 reply(426, "Transfer aborted. Data connection closed.");
2436 reply(226, "Abort successful");
2437 longjmp(urgcatch
, 1);
2439 if (strcmp(cp
, "STAT\r\n") == 0) {
2441 if (file_size
!= (off_t
) -1)
2442 reply(213, "Status: %qd of %qd bytes transferred",
2443 byte_count
, file_size
);
2445 reply(213, "Status: %qd bytes transferred", byte_count
);
2450 * Note: a response of 425 is not mentioned as a possible response to
2451 * the PASV command in RFC959. However, it has been blessed as
2452 * a legitimate response by Jon Postel in a telephone conversation
2453 * with Rick Adams on 25 Jan 89.
2461 if (pdata
>= 0) /* close old port if one set */
2464 pdata
= socket(ctrl_addr
.su_family
, SOCK_STREAM
, 0);
2466 perror_reply(425, "Can't open passive connection");
2470 (void) seteuid((uid_t
)0);
2473 if (ctrl_addr
.su_family
== AF_INET
) {
2474 int on
= restricted_data_ports
? IP_PORTRANGE_HIGH
2475 : IP_PORTRANGE_DEFAULT
;
2477 if (setsockopt(pdata
, IPPROTO_IP
, IP_PORTRANGE
,
2478 (char *)&on
, sizeof(on
)) < 0)
2482 #ifdef IPV6_PORTRANGE
2483 if (ctrl_addr
.su_family
== AF_INET6
) {
2484 int on
= restricted_data_ports
? IPV6_PORTRANGE_HIGH
2485 : IPV6_PORTRANGE_DEFAULT
;
2487 if (setsockopt(pdata
, IPPROTO_IPV6
, IPV6_PORTRANGE
,
2488 (char *)&on
, sizeof(on
)) < 0)
2493 pasv_addr
= ctrl_addr
;
2494 pasv_addr
.su_port
= 0;
2495 if (bind(pdata
, (struct sockaddr
*)&pasv_addr
, pasv_addr
.su_len
) < 0)
2498 (void) seteuid((uid_t
)pw
->pw_uid
);
2500 len
= sizeof(pasv_addr
);
2501 if (getsockname(pdata
, (struct sockaddr
*) &pasv_addr
, &len
) < 0)
2503 if (listen(pdata
, 1) < 0)
2505 if (pasv_addr
.su_family
== AF_INET
)
2506 a
= (char *) &pasv_addr
.su_sin
.sin_addr
;
2507 else if (pasv_addr
.su_family
== AF_INET6
&&
2508 IN6_IS_ADDR_V4MAPPED(&pasv_addr
.su_sin6
.sin6_addr
))
2509 a
= (char *) &pasv_addr
.su_sin6
.sin6_addr
.s6_addr
[12];
2513 p
= (char *) &pasv_addr
.su_port
;
2515 #define UC(b) (((int) b) & 0xff)
2517 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a
[0]),
2518 UC(a
[1]), UC(a
[2]), UC(a
[3]), UC(p
[0]), UC(p
[1]));
2522 (void) seteuid((uid_t
)pw
->pw_uid
);
2523 (void) close(pdata
);
2525 perror_reply(425, "Can't open passive connection");
2530 * Long Passive defined in RFC 1639.
2531 * 228 Entering Long Passive Mode
2532 * (af, hal, h1, h2, h3,..., pal, p1, p2...)
2536 long_passive(cmd
, pf
)
2543 if (pdata
>= 0) /* close old port if one set */
2546 if (pf
!= PF_UNSPEC
) {
2547 if (ctrl_addr
.su_family
!= pf
) {
2548 switch (ctrl_addr
.su_family
) {
2561 * only EPRT/EPSV ready clients will understand this
2563 if (strcmp(cmd
, "EPSV") == 0 && pf
) {
2564 reply(522, "Network protocol mismatch, "
2567 reply(501, "Network protocol mismatch"); /*XXX*/
2573 pdata
= socket(ctrl_addr
.su_family
, SOCK_STREAM
, 0);
2575 perror_reply(425, "Can't open passive connection");
2579 (void) seteuid((uid_t
)0);
2581 pasv_addr
= ctrl_addr
;
2582 pasv_addr
.su_port
= 0;
2583 len
= pasv_addr
.su_len
;
2586 if (ctrl_addr
.su_family
== AF_INET
) {
2587 int on
= restricted_data_ports
? IP_PORTRANGE_HIGH
2588 : IP_PORTRANGE_DEFAULT
;
2590 if (setsockopt(pdata
, IPPROTO_IP
, IP_PORTRANGE
,
2591 (char *)&on
, sizeof(on
)) < 0)
2595 #ifdef IPV6_PORTRANGE
2596 if (ctrl_addr
.su_family
== AF_INET6
) {
2597 int on
= restricted_data_ports
? IPV6_PORTRANGE_HIGH
2598 : IPV6_PORTRANGE_DEFAULT
;
2600 if (setsockopt(pdata
, IPPROTO_IPV6
, IPV6_PORTRANGE
,
2601 (char *)&on
, sizeof(on
)) < 0)
2606 if (bind(pdata
, (struct sockaddr
*)&pasv_addr
, len
) < 0)
2609 (void) seteuid((uid_t
)pw
->pw_uid
);
2611 if (getsockname(pdata
, (struct sockaddr
*) &pasv_addr
, &len
) < 0)
2613 if (listen(pdata
, 1) < 0)
2616 #define UC(b) (((int) b) & 0xff)
2618 if (strcmp(cmd
, "LPSV") == 0) {
2619 p
= (char *)&pasv_addr
.su_port
;
2620 switch (pasv_addr
.su_family
) {
2622 a
= (char *) &pasv_addr
.su_sin
.sin_addr
;
2625 "Entering Long Passive Mode (%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2626 4, 4, UC(a
[0]), UC(a
[1]), UC(a
[2]), UC(a
[3]),
2627 2, UC(p
[0]), UC(p
[1]));
2630 if (IN6_IS_ADDR_V4MAPPED(&pasv_addr
.su_sin6
.sin6_addr
)) {
2631 a
= (char *) &pasv_addr
.su_sin6
.sin6_addr
.s6_addr
[12];
2634 a
= (char *) &pasv_addr
.su_sin6
.sin6_addr
;
2636 "Entering Long Passive Mode "
2637 "(%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d)",
2638 6, 16, UC(a
[0]), UC(a
[1]), UC(a
[2]), UC(a
[3]),
2639 UC(a
[4]), UC(a
[5]), UC(a
[6]), UC(a
[7]),
2640 UC(a
[8]), UC(a
[9]), UC(a
[10]), UC(a
[11]),
2641 UC(a
[12]), UC(a
[13]), UC(a
[14]), UC(a
[15]),
2642 2, UC(p
[0]), UC(p
[1]));
2645 } else if (strcmp(cmd
, "EPSV") == 0) {
2646 switch (pasv_addr
.su_family
) {
2649 reply(229, "Entering Extended Passive Mode (|||%d|)",
2650 ntohs(pasv_addr
.su_port
));
2654 /* more proper error code? */
2658 (void) seteuid((uid_t
)pw
->pw_uid
);
2659 (void) close(pdata
);
2661 perror_reply(425, "Can't open passive connection");
2666 * Generate unique name for file with basename "local".
2667 * The file named "local" is already known to exist.
2668 * Generates failure reply on error.
2674 static char new[MAXPATHLEN
];
2679 cp
= strrchr(local
, '/');
2682 if (stat(cp
? local
: ".", &st
) < 0) {
2683 perror_reply(553, cp
? local
: ".");
2684 return ((char *) 0);
2688 /* -4 is for the .nn<null> we put on the end below */
2689 (void) snprintf(new, sizeof(new) - 4, "%s", local
);
2690 cp
= new + strlen(new);
2692 for (count
= 1; count
< 100; count
++) {
2693 (void)sprintf(cp
, "%d", count
);
2694 if (stat(new, &st
) < 0)
2697 reply(452, "Unique file name cannot be created.");
2702 * Format and send reply containing system error number.
2705 perror_reply(code
, string
)
2710 reply(code
, "%s: %s.", string
, strerror(errno
));
2713 static char *onefile
[] = {
2719 send_file_list(whichf
)
2726 char **dirlist
, *dirname
;
2731 if (strpbrk(whichf
, "~{[*?") != NULL
) {
2732 int flags
= GLOB_BRACE
|GLOB_NOCHECK
|GLOB_QUOTE
|GLOB_TILDE
;
2734 memset(&gl
, 0, sizeof(gl
));
2735 gl
.gl_matchc
= MAXGLOBARGS
;
2736 #if !defined(GLOB_MAXPATH)
2737 #define GLOB_MAXPATH 0x1000
2739 flags
|= GLOB_MAXPATH
;
2741 if (glob(whichf
, flags
, 0, &gl
)) {
2742 reply(550, "not found");
2744 } else if (gl
.gl_pathc
== 0) {
2746 perror_reply(550, whichf
);
2749 dirlist
= gl
.gl_pathv
;
2751 onefile
[0] = whichf
;
2756 if (setjmp(urgcatch
)) {
2760 while ((dirname
= *dirlist
++)) {
2761 if (stat(dirname
, &st
) < 0) {
2763 * If user typed "ls -l", etc, and the client
2764 * used NLST, do what the user meant.
2766 if (dirname
[0] == '-' && *dirlist
== NULL
&&
2768 retrieve(_PATH_LS
" %s", dirname
);
2771 perror_reply(550, whichf
);
2773 (void) fclose(dout
);
2781 if (S_ISREG(st
.st_mode
)) {
2783 dout
= dataconn("file list", (off_t
)-1, "w");
2788 fprintf(dout
, "%s%s\n", dirname
,
2789 type
== TYPE_A
? "\r" : "");
2790 byte_count
+= strlen(dirname
) + 1;
2792 } else if (!S_ISDIR(st
.st_mode
))
2795 if ((dirp
= opendir(dirname
)) == NULL
)
2798 while ((dir
= readdir(dirp
)) != NULL
) {
2799 char nbuf
[MAXPATHLEN
];
2801 if (dir
->d_name
[0] == '.' && dir
->d_namlen
== 1)
2803 if (dir
->d_name
[0] == '.' && dir
->d_name
[1] == '.' &&
2807 snprintf(nbuf
, sizeof(nbuf
),
2808 "%s/%s", dirname
, dir
->d_name
);
2811 * We have to do a stat to insure it's
2812 * not a directory or special file.
2814 if (simple
|| (stat(nbuf
, &st
) == 0 &&
2815 S_ISREG(st
.st_mode
))) {
2817 dout
= dataconn("file list", (off_t
)-1,
2823 if (nbuf
[0] == '.' && nbuf
[1] == '/')
2824 fprintf(dout
, "%s%s\n", &nbuf
[2],
2825 type
== TYPE_A
? "\r" : "");
2827 fprintf(dout
, "%s%s\n", nbuf
,
2828 type
== TYPE_A
? "\r" : "");
2829 byte_count
+= strlen(nbuf
) + 1;
2832 (void) closedir(dirp
);
2836 reply(550, "No files found.");
2837 else if (ferror(dout
) != 0)
2838 perror_reply(550, "Data connection");
2840 reply(226, "Transfer complete.");
2844 (void) fclose(dout
);
2858 while (wait3(NULL
, WNOHANG
, NULL
) > 0);
2861 #ifdef OLD_SETPROCTITLE
2863 * Clobber argv so ps will show what we're doing. (Stolen from sendmail.)
2864 * Warning, since this is usually started from inetd.conf, it often doesn't
2865 * have much of an environment or arglist to overwrite.
2869 setproctitle(const char *fmt
, ...)
2871 setproctitle(fmt
, va_alist
)
2886 (void)vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
2888 /* make ps print our process name */
2893 if (i
> LastArgv
- p
- 2) {
2894 i
= LastArgv
- p
- 2;
2899 if (ch
!= '\n' && ch
!= '\r')
2901 while (p
< LastArgv
)
2904 #endif /* OLD_SETPROCTITLE */
2907 logxfer(name
, size
, start
)
2913 char path
[MAXPATHLEN
+ 1];
2916 if (statfd
>= 0 && getwd(path
) != NULL
) {
2918 snprintf(buf
, sizeof(buf
), "%.20s!%s!%s!%s/%s!%ld!%ld\n",
2919 ctime(&now
)+4, ident
, remotehost
,
2920 path
, name
, size
, now
- start
+ (now
== start
));
2921 write(statfd
, buf
, strlen(buf
));