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
42 #ifdef HAVE_SYS_TYPES_H
43 #include <sys/types.h>
45 #ifdef HAVE_SYS_PARAM_H
46 #include <sys/param.h>
48 #ifdef HAVE_SYS_STAT_H
51 #ifdef HAVE_SYS_SOCKET_H
52 #include <sys/socket.h>
54 #if defined(HAVE_SYS_IOCTL_H) && SunOS != 4
55 #include <sys/ioctl.h>
57 #ifdef TIME_WITH_SYS_TIME
60 #elif defined(HAVE_SYS_TIME_H)
65 #ifdef HAVE_SYS_RESOURCE_H
66 #include <sys/resource.h>
68 #ifdef HAVE_SYS_WAIT_H
72 #ifdef HAVE_NETINET_IN_H
73 #include <netinet/in.h>
75 #ifdef HAVE_NETINET_IN_SYSTM_H
76 #include <netinet/in_systm.h>
78 #ifdef HAVE_NETINET_IP_H
79 #include <netinet/ip.h>
82 #ifdef HAVE_SYS_MMAN_H
88 #ifdef HAVE_ARPA_INET_H
89 #include <arpa/inet.h>
91 #ifdef HAVE_ARPA_TELNET_H
92 #include <arpa/telnet.h>
127 #include "pathnames.h"
144 extern int LIBPREFIX(fclose
) __P((FILE *));
150 #define LOG_FTP LOG_DAEMON
153 static char version
[] = "Version 6.00";
155 extern off_t restart_point
;
158 struct sockaddr_in ctrl_addr
;
159 struct sockaddr_in data_source
;
160 struct sockaddr_in data_dest
;
161 struct sockaddr_in his_addr
;
162 struct sockaddr_in pasv_addr
;
165 jmp_buf errcatch
, urgcatch
;
170 int ftpd_timeout
= 900; /* timeout after 15 minutes of inactivity */
171 int maxtimeout
= 7200;/* don't allow idle time to be set beyond 2 hours */
177 int stru
; /* avoid C keyword */
179 int usedefault
= 1; /* for data transfers */
180 int pdata
= -1; /* for passive mode */
184 #if !defined(CMASK) || CMASK == 0
188 int defumask
= CMASK
; /* default umask value */
189 int guest_umask
= 0777; /* Paranoia for anonymous users */
191 char hostname
[MaxHostNameLen
];
192 char remotehost
[MaxHostNameLen
];
193 static char ttyline
[20];
195 #define AUTH_PLAIN (1 << 0) /* allow sending passwords */
196 #define AUTH_OTP (1 << 1) /* passwords are one-time */
197 #define AUTH_FTP (1 << 2) /* allow anonymous login */
199 static int auth_level
= 0; /* Only allow kerberos login by default */
202 * Timeout intervals for retrying connections
203 * to hosts that don't accept PORT cmds. This
204 * is a kludge, but given the problems with TCP...
206 #define SWAITMAX 90 /* wait at most 90 seconds */
207 #define SWAITINT 5 /* interval between retries */
209 int swaitmax
= SWAITMAX
;
210 int swaitint
= SWAITINT
;
212 #ifdef HAVE_SETPROCTITLE
213 char proctitle
[BUFSIZ
]; /* initial part of title */
214 #endif /* HAVE_SETPROCTITLE */
216 #define LOGCMD(cmd, file) \
218 syslog(LOG_INFO,"%s %s%s", cmd, \
219 *(file) == '/' ? "" : curdir(), file);
220 #define LOGCMD2(cmd, file1, file2) \
222 syslog(LOG_INFO,"%s %s%s %s%s", cmd, \
223 *(file1) == '/' ? "" : curdir(), file1, \
224 *(file2) == '/' ? "" : curdir(), file2);
225 #define LOGBYTES(cmd, file, cnt) \
227 if (cnt == (off_t)-1) \
228 syslog(LOG_INFO,"%s %s%s", cmd, \
229 *(file) == '/' ? "" : curdir(), file); \
231 syslog(LOG_INFO, "%s %s%s = %ld bytes", \
232 cmd, (*(file) == '/') ? "" : curdir(), file, (long)cnt); \
235 static void ack (char *);
236 static void myoob (int);
237 static int checkuser (char *, char *);
238 static int checkaccess (char *);
239 static FILE *dataconn (char *, off_t
, char *);
240 static void dolog (struct sockaddr_in
*);
241 static void end_login (void);
242 static FILE *getdatasock (char *);
243 static char *gunique (char *);
244 static RETSIGTYPE
lostconn (int);
245 static int receive_data (FILE *, FILE *);
246 static void send_data (FILE *, FILE *);
247 static struct passwd
* sgetpwnam (char *);
248 static void usage(void);
253 static char path
[MaxPathLen
+1+1]; /* path + '/' + '\0' */
255 if (getcwd(path
, sizeof(path
)-2) == NULL
)
257 if (path
[1] != '\0') /* special case for root dir. */
259 /* For guest account, skip / since it's chrooted */
260 return (guest
? path
+1 : path
);
264 #define LINE_MAX 1024
268 parse_auth_level(char *str
)
274 for(p
= strtok_r(str
, ",", &foo
);
276 p
= strtok_r(NULL
, ",", &foo
)) {
277 if(strcmp(p
, "user") == 0)
280 else if(strcmp(p
, "otp") == 0)
281 ret
|= AUTH_PLAIN
|AUTH_OTP
;
283 else if(strcmp(p
, "ftp") == 0 ||
284 strcmp(p
, "safe") == 0)
286 else if(strcmp(p
, "plain") == 0)
288 else if(strcmp(p
, "none") == 0)
289 ret
|= AUTH_PLAIN
|AUTH_FTP
;
291 warnx("bad value for -a: `%s'", p
);
297 * Print usage and die.
304 "Usage: %s [-d] [-i] [-g guest_umask] [-l] [-p port]"
305 " [-t timeout] [-T max_timeout] [-u umask] [-v]"
306 " [-a auth_level] \n",
312 main(int argc
, char **argv
)
314 int addrlen
, ch
, on
= 1, tos
;
315 char *cp
, line
[LINE_MAX
];
322 set_progname (argv
[0]);
324 /* detach from any tickets and tokens */
326 snprintf(tkfile
, sizeof(tkfile
),
327 "/tmp/ftp_%u", (unsigned)getpid());
328 krb_set_tkt_string(tkfile
);
332 sp
= getservbyname("ftp", "tcp");
338 while ((ch
= getopt(argc
, argv
, "a:dg:ilp:t:T:u:v")) != EOF
) {
341 auth_level
= parse_auth_level(optarg
);
354 val
= strtol(optarg
, &optarg
, 8);
355 if (*optarg
!= '\0' || val
< 0)
356 warnx("bad value for -g");
362 logging
++; /* > 1 == extra logging */
366 sp
= getservbyname(optarg
, "tcp");
370 if(isdigit(optarg
[0]))
371 port
= htons(atoi(optarg
));
373 warnx("bad value for -p");
377 ftpd_timeout
= atoi(optarg
);
378 if (maxtimeout
< ftpd_timeout
)
379 maxtimeout
= ftpd_timeout
;
383 maxtimeout
= atoi(optarg
);
384 if (ftpd_timeout
> maxtimeout
)
385 ftpd_timeout
= maxtimeout
;
392 val
= strtol(optarg
, &optarg
, 8);
393 if (*optarg
!= '\0' || val
< 0)
394 warnx("bad value for -u");
413 * LOG_NDELAY sets up the logging connection immediately,
414 * necessary for anonymous ftp's that chroot and can't do it later.
416 openlog("ftpd", LOG_PID
| LOG_NDELAY
, LOG_FTP
);
417 addrlen
= sizeof(his_addr
);
418 if (getpeername(0, (struct sockaddr
*)&his_addr
, &addrlen
) < 0) {
419 syslog(LOG_ERR
, "getpeername (%s): %m",argv
[0]);
422 addrlen
= sizeof(ctrl_addr
);
423 if (getsockname(0, (struct sockaddr
*)&ctrl_addr
, &addrlen
) < 0) {
424 syslog(LOG_ERR
, "getsockname (%s): %m",argv
[0]);
427 #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
428 tos
= IPTOS_LOWDELAY
;
429 if (setsockopt(0, IPPROTO_IP
, IP_TOS
, (void *)&tos
, sizeof(int)) < 0)
430 syslog(LOG_WARNING
, "setsockopt (IP_TOS): %m");
432 data_source
.sin_port
= htons(ntohs(ctrl_addr
.sin_port
) - 1);
434 /* set this here so it can be put in wtmp */
435 snprintf(ttyline
, sizeof(ttyline
), "ftp%u", (unsigned)getpid());
438 /* freopen(_PATH_DEVNULL, "w", stderr); */
439 signal(SIGPIPE
, lostconn
);
440 signal(SIGCHLD
, SIG_IGN
);
442 if (signal(SIGURG
, myoob
) == SIG_ERR
)
443 syslog(LOG_ERR
, "signal: %m");
448 /* Try to handle urgent data inline */
449 #if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT)
450 if (setsockopt(0, SOL_SOCKET
, SO_OOBINLINE
, (void *)&on
,
452 syslog(LOG_ERR
, "setsockopt: %m");
456 if (fcntl(fileno(stdin
), F_SETOWN
, getpid()) == -1)
457 syslog(LOG_ERR
, "fcntl F_SETOWN: %m");
461 * Set up default state
470 /* If logins are disabled, print out the message. */
471 if ((fd
= fopen(_PATH_NOLOGIN
,"r")) != NULL
) {
472 while (fgets(line
, sizeof(line
), fd
) != NULL
) {
473 if ((cp
= strchr(line
, '\n')) != NULL
)
475 lreply(530, "%s", line
);
479 reply(530, "System not available.");
482 if ((fd
= fopen(_PATH_FTPWELCOME
, "r")) != NULL
) {
483 while (fgets(line
, sizeof(line
), fd
) != NULL
) {
484 if ((cp
= strchr(line
, '\n')) != NULL
)
486 lreply(220, "%s", line
);
490 /* reply(220,) must follow */
492 gethostname(hostname
, sizeof(hostname
));
493 reply(220, "%s FTP server (%s+%s) ready.", hostname
,
494 version
, krb4_version
);
506 syslog(LOG_DEBUG
, "lost connection");
511 * Helper function for sgetpwnam().
516 char *new = strdup(s
);
519 perror_reply(421, "Local resource failure: malloc");
527 * Save the result of a getpwnam. Used for USER command, since
528 * the data returned must not be clobbered by any other command
531 static struct passwd
*
532 sgetpwnam(char *name
)
534 static struct passwd save
;
537 if ((p
= k_getpwnam(name
)) == NULL
)
541 free(save
.pw_passwd
);
547 save
.pw_name
= sgetsave(p
->pw_name
);
548 save
.pw_passwd
= sgetsave(p
->pw_passwd
);
549 save
.pw_gecos
= sgetsave(p
->pw_gecos
);
550 save
.pw_dir
= sgetsave(p
->pw_dir
);
551 save
.pw_shell
= sgetsave(p
->pw_shell
);
555 static int login_attempts
; /* number of failed login attempts */
556 static int askpasswd
; /* had user command, ask for passwd */
557 static char curname
[10]; /* current USER name */
564 * Sets global passwd pointer pw if named account exists and is acceptable;
565 * sets askpasswd if a PASS command is expected. If logged in previously,
566 * need to reset state. If name is "ftp" or "anonymous", the name is not in
567 * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
568 * If account doesn't exist, ask for passwd anyway. Otherwise, check user
569 * requesting login privileges. Disallow anyone who does not have a standard
570 * shell as returned by getusershell(). Disallow anyone mentioned in the file
571 * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
578 if(auth_level
== 0 && !auth_complete
){
579 reply(530, "No login allowed without authorization.");
585 reply(530, "Can't change user from guest login.");
587 } else if (dochroot
) {
588 reply(530, "Can't change user from chroot user.");
595 if (strcmp(name
, "ftp") == 0 || strcmp(name
, "anonymous") == 0) {
596 if ((auth_level
& AUTH_FTP
) == 0 ||
597 checkaccess("ftp") ||
598 checkaccess("anonymous"))
599 reply(530, "User %s access denied.", name
);
600 else if ((pw
= sgetpwnam("ftp")) != NULL
) {
602 defumask
= guest_umask
; /* paranoia for incoming */
604 reply(331, "Guest login ok, type your name as password.");
606 reply(530, "User %s unknown.", name
);
607 if (!askpasswd
&& logging
)
609 "ANONYMOUS FTP LOGIN REFUSED FROM %s(%s)",
610 remotehost
, inet_ntoa(his_addr
.sin_addr
));
613 if((auth_level
& AUTH_PLAIN
) == 0 && !auth_complete
){
614 reply(530, "Only authorized and anonymous login allowed.");
617 if ((pw
= sgetpwnam(name
))) {
618 if ((shell
= pw
->pw_shell
) == NULL
|| *shell
== 0)
619 shell
= _PATH_BSHELL
;
620 while ((cp
= getusershell()) != NULL
)
621 if (strcmp(cp
, shell
) == 0)
625 if (cp
== NULL
|| checkaccess(name
)) {
626 reply(530, "User %s access denied.", name
);
629 "FTP LOGIN REFUSED FROM %s(%s), %s",
631 inet_ntoa(his_addr
.sin_addr
),
633 pw
= (struct passwd
*) NULL
;
638 strncpy(curname
, name
, sizeof(curname
)-1);
645 if (otp_challenge(&otp_ctx
, name
, ss
, sizeof(ss
)) == 0) {
646 reply(331, "Password %s for %s required.",
651 if ((auth_level
& AUTH_OTP
) == 0) {
652 reply(331, "Password required for %s.", name
);
658 if (s
= otp_error (&otp_ctx
))
659 lreply(530, "OTP: %s", s
);
662 "Only authorized, anonymous"
671 * Delay before reading passwd after first failed
672 * attempt to slow down passwd-guessing programs.
675 sleep(login_attempts
);
679 * Check if a user is in the file "fname"
682 checkuser(char *fname
, char *name
)
686 char *p
, line
[BUFSIZ
];
688 if ((fd
= fopen(fname
, "r")) != NULL
) {
689 while (fgets(line
, sizeof(line
), fd
) != NULL
)
690 if ((p
= strchr(line
, '\n')) != NULL
) {
694 if (strcmp(line
, name
) == 0) {
706 * Determine whether a user has access, based on information in
707 * _PATH_FTPUSERS. The users are listed one per line, with `allow'
708 * or `deny' after the username. If anything other than `allow', or
709 * just nothing, is given after the username, `deny' is assumed.
711 * If the user is not found in the file, but the pseudo-user `*' is,
712 * the permission is taken from that line.
714 * This preserves the old semantics where if a user was listed in the
715 * file he was denied, otherwise he was allowed.
717 * Return 1 if the user is denied, or 0 if he is allowed. */
720 match(const char *pattern
, const char *string
)
723 return fnmatch(pattern
, string
, FNM_NOESCAPE
);
725 return strcmp(pattern
, "*") != 0 && strcmp(pattern
, string
) != 0;
730 checkaccess(char *name
)
733 #define NOT_ALLOWED 1
735 int allowed
= ALLOWED
;
736 char *user
, *perm
, line
[BUFSIZ
];
739 fd
= fopen(_PATH_FTPUSERS
, "r");
744 while (fgets(line
, sizeof(line
), fd
) != NULL
) {
746 user
= strtok_r(line
, " \t\n", &foo
);
747 if (user
== NULL
|| user
[0] == '#')
749 perm
= strtok_r(NULL
, " \t\n", &foo
);
750 if (match(user
, name
) == 0){
751 if(perm
&& strcmp(perm
, "allow") == 0)
754 allowed
= NOT_ALLOWED
;
764 int do_login(int code
, char *passwd
)
767 login_attempts
= 0; /* this time successful */
768 if (setegid((gid_t
)pw
->pw_gid
) < 0) {
769 reply(550, "Can't set gid.");
772 initgroups(pw
->pw_name
, pw
->pw_gid
);
774 /* open wtmp before chroot */
775 logwtmp(ttyline
, pw
->pw_name
, remotehost
);
778 dochroot
= checkuser(_PATH_FTPCHROOT
, pw
->pw_name
);
781 * We MUST do a chdir() after the chroot. Otherwise
782 * the old current directory will be accessible as "."
783 * outside the new root!
785 if (chroot(pw
->pw_dir
) < 0 || chdir("/") < 0) {
786 reply(550, "Can't set guest privileges.");
789 } else if (dochroot
) {
790 if (chroot(pw
->pw_dir
) < 0 || chdir("/") < 0) {
791 reply(550, "Can't change root.");
794 } else if (chdir(pw
->pw_dir
) < 0) {
795 if (chdir("/") < 0) {
796 reply(530, "User %s: can't change directory to %s.",
797 pw
->pw_name
, pw
->pw_dir
);
800 lreply(code
, "No directory! Logging in with home=/");
802 if (seteuid((uid_t
)pw
->pw_uid
) < 0) {
803 reply(550, "Can't set uid.");
807 * Display a login message, if it exists.
808 * N.B. reply(code,) must follow the message.
810 if ((fd
= fopen(_PATH_FTPLOGINMESG
, "r")) != NULL
) {
811 char *cp
, line
[LINE_MAX
];
813 while (fgets(line
, sizeof(line
), fd
) != NULL
) {
814 if ((cp
= strchr(line
, '\n')) != NULL
)
816 lreply(code
, "%s", line
);
820 reply(code
, "Guest login ok, access restrictions apply.");
821 #ifdef HAVE_SETPROCTITLE
822 snprintf (proctitle
, sizeof(proctitle
),
826 #endif /* HAVE_SETPROCTITLE */
828 syslog(LOG_INFO
, "ANONYMOUS FTP LOGIN FROM %s(%s), %s",
830 inet_ntoa(his_addr
.sin_addr
),
833 reply(code
, "User %s logged in.", pw
->pw_name
);
834 #ifdef HAVE_SETPROCTITLE
835 snprintf(proctitle
, sizeof(proctitle
), "%s: %s", remotehost
, pw
->pw_name
);
836 setproctitle(proctitle
);
837 #endif /* HAVE_SETPROCTITLE */
839 syslog(LOG_INFO
, "FTP LOGIN FROM %s(%s) as %s",
841 inet_ntoa(his_addr
.sin_addr
),
849 * Terminate login as previous user, if any, resetting state;
850 * used when USER command is given or login fails.
858 logwtmp(ttyline
, "", "");
870 /* some clients insists on sending a password */
871 if (logged_in
&& askpasswd
== 0){
872 reply(230, "Dumpucko!");
876 if (logged_in
|| askpasswd
== 0) {
877 reply(503, "Login with USER first.");
882 if (!guest
) { /* "ftp" is only account allowed no password */
884 rval
= 1; /* failure below */
886 else if (otp_verify_user (&otp_ctx
, passwd
) == 0) {
890 else if((auth_level
& AUTH_OTP
) == 0) {
891 char realm
[REALM_SZ
];
892 if((rval
= krb_get_lrealm(realm
, 1)) == KSUCCESS
)
893 rval
= krb_verify_user(pw
->pw_name
, "", realm
,
895 if (rval
== KSUCCESS
) {
896 chown (tkt_string(), pw
->pw_uid
, pw
->pw_gid
);
900 rval
= unix_verify_user(pw
->pw_name
, passwd
);
905 if (s
= otp_error(&otp_ctx
))
906 lreply(530, "OTP: %s", s
);
909 memset (passwd
, 0, strlen(passwd
));
912 * If rval == 1, the user failed the authentication
913 * check above. If rval == 0, either Kerberos or
914 * local authentication succeeded.
917 reply(530, "Login incorrect.");
920 "FTP LOGIN FAILED FROM %s(%s), %s",
922 inet_ntoa(his_addr
.sin_addr
),
925 if (login_attempts
++ >= 5) {
927 "repeated login failures from %s(%s)",
929 inet_ntoa(his_addr
.sin_addr
));
935 if(!do_login(230, passwd
))
938 /* Forget all about it... */
943 retrieve(char *cmd
, char *name
)
945 FILE *fin
= NULL
, *dout
;
947 int (*closefunc
) (FILE *);
952 fin
= fopen(name
, "r");
960 {".tar", "/bin/gtar cPf - %s"},
961 {".tar.gz", "/bin/gtar zcPf - %s"},
962 {".tar.Z", "/bin/gtar ZcPf - %s"},
963 {".gz", "/bin/gzip -c %s"},
964 {".Z", "/bin/compress -c %s"},
968 for(p
= cmds
; p
->ext
; p
++){
969 char *tail
= name
+ strlen(name
) - strlen(p
->ext
);
972 if(strcmp(tail
, p
->ext
) == 0 &&
974 access(name
, R_OK
) == 0){
975 snprintf (line
, sizeof(line
), p
->cmd
, name
);
982 fin
= ftpd_popen(line
, "r", 0, 0);
983 closefunc
= ftpd_pclose
;
989 snprintf(line
, sizeof(line
), cmd
, name
);
991 fin
= ftpd_popen(line
, "r", 1, 0);
992 closefunc
= ftpd_pclose
;
997 perror_reply(550, name
);
1006 if(fstat(fileno(fin
), &st
) < 0 || !S_ISREG(st
.st_mode
)) {
1007 reply(550, "%s: not a plain file.", name
);
1011 if (restart_point
) {
1012 if (type
== TYPE_A
) {
1019 if ((c
=getc(fin
)) == EOF
) {
1020 perror_reply(550, name
);
1026 } else if (lseek(fileno(fin
), restart_point
, SEEK_SET
) < 0) {
1027 perror_reply(550, name
);
1031 dout
= dataconn(name
, st
.st_size
, "w");
1034 set_buffer_size(fileno(dout
), 0);
1035 send_data(fin
, dout
);
1041 LOGBYTES("get", name
, byte_count
);
1045 /* filename sanity check */
1048 filename_check(char *filename
)
1050 static const char good_chars
[] = "+-=_,.";
1053 p
= strrchr(filename
, '/');
1061 while(*p
&& (isalnum(*p
) || strchr(good_chars
, *p
)))
1066 lreply(553, "\"%s\" is an illegal filename.", filename
);
1067 lreply(553, "The filename must start with an alphanumeric "
1068 "character and must only");
1069 reply(553, "consist of alphanumeric characters or any of the following: %s",
1075 do_store(char *name
, char *mode
, int unique
)
1079 int (*closefunc
) (FILE *);
1081 if(guest
&& filename_check(name
))
1083 if (unique
&& stat(name
, &st
) == 0 &&
1084 (name
= gunique(name
)) == NULL
) {
1085 LOGCMD(*mode
== 'w' ? "put" : "append", name
);
1091 fout
= fopen(name
, mode
);
1094 perror_reply(553, name
);
1095 LOGCMD(*mode
== 'w' ? "put" : "append", name
);
1099 if (restart_point
) {
1100 if (type
== TYPE_A
) {
1107 if ((c
=getc(fout
)) == EOF
) {
1108 perror_reply(550, name
);
1115 * We must do this seek to "current" position
1116 * because we are changing from reading to
1119 if (fseek(fout
, 0L, SEEK_CUR
) < 0) {
1120 perror_reply(550, name
);
1123 } else if (lseek(fileno(fout
), restart_point
, SEEK_SET
) < 0) {
1124 perror_reply(550, name
);
1128 din
= dataconn(name
, (off_t
)-1, "r");
1131 set_buffer_size(fileno(din
), 1);
1132 if (receive_data(din
, fout
) == 0) {
1134 reply(226, "Transfer complete (unique file name:%s).",
1137 reply(226, "Transfer complete.");
1143 LOGBYTES(*mode
== 'w' ? "put" : "append", name
, byte_count
);
1148 getdatasock(char *mode
)
1150 int on
= 1, s
, t
, tries
;
1153 return (fdopen(data
, mode
));
1155 s
= socket(AF_INET
, SOCK_STREAM
, 0);
1158 #if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT)
1159 if (setsockopt(s
, SOL_SOCKET
, SO_REUSEADDR
,
1160 (void *) &on
, sizeof(on
)) < 0)
1163 /* anchor socket to avoid multi-homing problems */
1164 data_source
.sin_family
= AF_INET
;
1165 data_source
.sin_addr
= ctrl_addr
.sin_addr
;
1166 for (tries
= 1; ; tries
++) {
1167 if (bind(s
, (struct sockaddr
*)&data_source
,
1168 sizeof(data_source
)) >= 0)
1170 if (errno
!= EADDRINUSE
|| tries
> 10)
1174 seteuid((uid_t
)pw
->pw_uid
);
1175 #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
1176 on
= IPTOS_THROUGHPUT
;
1177 if (setsockopt(s
, IPPROTO_IP
, IP_TOS
, (void *)&on
, sizeof(int)) < 0)
1178 syslog(LOG_WARNING
, "setsockopt (IP_TOS): %m");
1180 return (fdopen(s
, mode
));
1182 /* Return the real value of errno (close may change it) */
1184 seteuid((uid_t
)pw
->pw_uid
);
1191 dataconn(char *name
, off_t size
, char *mode
)
1199 if (size
!= (off_t
) -1)
1200 snprintf(sizebuf
, sizeof(sizebuf
), " (%ld bytes)", size
);
1202 strcpy(sizebuf
, "");
1204 struct sockaddr_in from
;
1205 int s
, fromlen
= sizeof(from
);
1207 s
= accept(pdata
, (struct sockaddr
*)&from
, &fromlen
);
1209 reply(425, "Can't open data connection.");
1216 #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT)
1217 tos
= IPTOS_THROUGHPUT
;
1218 setsockopt(s
, IPPROTO_IP
, IP_TOS
, (void *)&tos
,
1221 reply(150, "Opening %s mode data connection for '%s'%s.",
1222 type
== TYPE_A
? "ASCII" : "BINARY", name
, sizebuf
);
1223 return (fdopen(pdata
, mode
));
1226 reply(125, "Using existing data connection for '%s'%s.",
1229 return (fdopen(data
, mode
));
1232 data_dest
= his_addr
;
1234 file
= getdatasock(mode
);
1236 reply(425, "Can't create data socket (%s,%d): %s.",
1237 inet_ntoa(data_source
.sin_addr
),
1238 ntohs(data_source
.sin_port
), strerror(errno
));
1241 data
= fileno(file
);
1242 while (connect(data
, (struct sockaddr
*)&data_dest
,
1243 sizeof(data_dest
)) < 0) {
1244 if (errno
== EADDRINUSE
&& retry
< swaitmax
) {
1245 sleep((unsigned) swaitint
);
1249 perror_reply(425, "Can't build data connection");
1254 reply(150, "Opening %s mode data connection for '%s'%s.",
1255 type
== TYPE_A
? "ASCII" : "BINARY", name
, sizebuf
);
1260 * Tranfer the contents of "instr" to "outstr" peer using the appropriate
1261 * encapsulation of the data subject * to Mode, Structure, and Type.
1263 * NB: Form isn't handled.
1266 send_data(FILE *instr
, FILE *outstr
)
1268 int c
, cnt
, filefd
, netfd
;
1270 static size_t bufsize
;
1275 if (setjmp(urgcatch
)) {
1282 while ((c
= getc(instr
)) != EOF
) {
1285 auth_write(fileno(outstr
), s
, i
);
1293 auth_write(fileno(outstr
), s
, i
);
1294 auth_write(fileno(outstr
), s
, 0);
1301 reply(226, "Transfer complete.");
1308 #define MAP_FAILED (-1)
1313 int in
= fileno(instr
);
1314 if(fstat(in
, &st
) == 0 && S_ISREG(st
.st_mode
)) {
1315 chunk
= mmap(0, st
.st_size
, PROT_READ
, MAP_SHARED
, in
, 0);
1316 if(chunk
!= (void *)MAP_FAILED
) {
1317 cnt
= st
.st_size
- restart_point
;
1318 auth_write(fileno(outstr
),
1319 chunk
+ restart_point
,
1321 munmap(chunk
, st
.st_size
);
1322 auth_write(fileno(outstr
), NULL
, 0);
1333 netfd
= fileno(outstr
);
1334 filefd
= fileno(instr
);
1335 buf
= alloc_buffer (buf
, &bufsize
,
1336 fstat(filefd
, &st
) >= 0 ? &st
: NULL
);
1339 perror_reply(451, "Local resource failure: malloc");
1342 while ((cnt
= read(filefd
, buf
, bufsize
)) > 0 &&
1343 auth_write(netfd
, buf
, cnt
) == cnt
)
1345 auth_write(netfd
, buf
, 0); /* to end an encrypted stream */
1353 reply(226, "Transfer complete.");
1357 reply(550, "Unimplemented TYPE %d in send_data", type
);
1363 perror_reply(426, "Data connection");
1368 perror_reply(551, "Error on input file");
1372 * Transfer data from peer to "outstr" using the appropriate encapulation of
1373 * the data subject to Mode, Structure, and Type.
1375 * N.B.: Form isn't handled.
1378 receive_data(FILE *instr
, FILE *outstr
)
1380 int cnt
, bare_lfs
= 0;
1382 static size_t bufsize
;
1386 if (setjmp(urgcatch
)) {
1391 buf
= alloc_buffer (buf
, &bufsize
,
1392 fstat(fileno(outstr
), &st
) >= 0 ? &st
: NULL
);
1395 perror_reply(451, "Local resource failure: malloc");
1403 while ((cnt
= auth_read(fileno(instr
), buf
, bufsize
)) > 0) {
1404 if (write(fileno(outstr
), buf
, cnt
) != cnt
)
1414 reply(553, "TYPE E not implemented.");
1422 while ((cnt
= auth_read(fileno(instr
),
1424 bufsize
- cr_flag
)) > 0){
1428 for(p
= buf
, q
= buf
; p
< buf
+ cnt
;) {
1432 if(p
== buf
+ cnt
- 1){
1436 }else if(p
[1] == '\n'){
1443 fwrite(buf
, q
- buf
, 1, outstr
);
1456 lreply(226, "WARNING! %d bare linefeeds received in ASCII mode\r\n"
1457 " File may not have transferred correctly.\r\n",
1463 reply(550, "Unimplemented TYPE %d in receive_data", type
);
1470 perror_reply(426, "Data Connection");
1475 perror_reply(452, "Error writing file");
1480 statfilecmd(char *filename
)
1484 char line
[LINE_MAX
];
1486 snprintf(line
, sizeof(line
), "/bin/ls -la %s", filename
);
1487 fin
= ftpd_popen(line
, "r", 1, 0);
1488 lreply(211, "status of %s:", filename
);
1489 while ((c
= getc(fin
)) != EOF
) {
1491 if (ferror(stdout
)){
1492 perror_reply(421, "control connection");
1498 perror_reply(551, filename
);
1507 reply(211, "End of Status");
1514 struct sockaddr_in
*sin
;
1517 lreply(211, "%s FTP server status:", hostname
, version
);
1518 printf(" %s\r\n", version
);
1519 printf(" Connected to %s", remotehost
);
1520 if (!isdigit(remotehost
[0]))
1521 printf(" (%s)", inet_ntoa(his_addr
.sin_addr
));
1525 printf(" Logged in anonymously\r\n");
1527 printf(" Logged in as %s\r\n", pw
->pw_name
);
1528 } else if (askpasswd
)
1529 printf(" Waiting for password\r\n");
1531 printf(" Waiting for user name\r\n");
1532 printf(" TYPE: %s", typenames
[type
]);
1533 if (type
== TYPE_A
|| type
== TYPE_E
)
1534 printf(", FORM: %s", formnames
[form
]);
1537 printf(" %d", NBBY
);
1539 printf(" %d", bytesize
); /* need definition! */
1541 printf("; STRUcture: %s; transfer MODE: %s\r\n",
1542 strunames
[stru
], modenames
[mode
]);
1544 printf(" Data connection open\r\n");
1545 else if (pdata
!= -1) {
1546 printf(" in Passive mode");
1549 } else if (usedefault
== 0) {
1553 a
= (u_char
*) &sin
->sin_addr
;
1554 p
= (u_char
*) &sin
->sin_port
;
1555 #define UC(b) (((int) b) & 0xff)
1556 printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a
[0]),
1557 UC(a
[1]), UC(a
[2]), UC(a
[3]), UC(p
[0]), UC(p
[1]));
1560 printf(" No data connection\r\n");
1562 reply(211, "End of status");
1569 reply(451, "Error in server: %s\n", s
);
1570 reply(221, "Closing connection due to server error.");
1576 int_reply(int, char *, const char *, va_list)
1578 __attribute__ ((format (printf
, 3, 0)))
1583 int_reply(int n
, char *c
, const char *fmt
, va_list ap
)
1589 snprintf(p
, sizeof(buf
), "%d%s", n
, c
);
1592 vsnprintf(p
, sizeof(buf
) - strlen(p
), fmt
, ap
);
1594 snprintf(p
, sizeof(buf
) - strlen(p
), "\r\n");
1596 auth_printf("%s", buf
);
1599 syslog(LOG_DEBUG
, "<--- %s- ", buf
);
1603 reply(int n
, const char *fmt
, ...)
1607 int_reply(n
, " ", fmt
, ap
);
1608 delete_ftp_command();
1613 lreply(int n
, const char *fmt
, ...)
1617 int_reply(n
, "-", fmt
, ap
);
1622 nreply(const char *fmt
, ...)
1626 int_reply(0, NULL
, fmt
, ap
);
1634 reply(250, "%s command successful.", s
);
1641 reply(502, "%s command not implemented.", s
);
1650 if ((cp
= strchr(cbuf
,'\n')))
1652 reply(500, "'%s': command not understood.", cbuf
);
1656 do_delete(char *name
)
1660 LOGCMD("delete", name
);
1661 if (stat(name
, &st
) < 0) {
1662 perror_reply(550, name
);
1665 if ((st
.st_mode
&S_IFMT
) == S_IFDIR
) {
1666 if (rmdir(name
) < 0) {
1667 perror_reply(550, name
);
1672 if (unlink(name
) < 0) {
1673 perror_reply(550, name
);
1684 if (chdir(path
) < 0)
1685 perror_reply(550, path
);
1694 LOGCMD("mkdir", name
);
1695 if(guest
&& filename_check(name
))
1697 if (mkdir(name
, 0777) < 0)
1698 perror_reply(550, name
);
1701 chmod(name
, 0700); /* guest has umask 777 */
1702 reply(257, "MKD command successful.");
1707 removedir(char *name
)
1710 LOGCMD("rmdir", name
);
1711 if (rmdir(name
) < 0)
1712 perror_reply(550, name
);
1720 char path
[MaxPathLen
+ 1];
1723 /* SunOS has a broken getcwd that does popen(pwd) (!!!), this
1724 * failes miserably when running chroot
1726 ret
= getcwd(path
, sizeof(path
));
1728 reply(550, "%s.", strerror(errno
));
1730 reply(257, "\"%s\" is current directory.", path
);
1734 renamefrom(char *name
)
1738 if (stat(name
, &st
) < 0) {
1739 perror_reply(550, name
);
1742 reply(350, "File exists, ready for destination name");
1747 renamecmd(char *from
, char *to
)
1750 LOGCMD2("rename", from
, to
);
1751 if(guest
&& filename_check(to
))
1753 if (rename(from
, to
) < 0)
1754 perror_reply(550, "rename");
1760 dolog(struct sockaddr_in
*sin
)
1762 inaddr2str (sin
->sin_addr
, remotehost
, sizeof(remotehost
));
1763 #ifdef HAVE_SETPROCTITLE
1764 snprintf(proctitle
, sizeof(proctitle
), "%s: connected", remotehost
);
1765 setproctitle(proctitle
);
1766 #endif /* HAVE_SETPROCTITLE */
1769 syslog(LOG_INFO
, "connection from %s(%s)",
1771 inet_ntoa(his_addr
.sin_addr
));
1775 * Record logout in wtmp file
1776 * and exit with supplied status.
1779 dologout(int status
)
1784 logwtmp(ttyline
, "", "");
1787 /* beware of flushing buffers after a SIGPIPE */
1806 /* only process if transfer occurring */
1810 /* This is all XXX */
1812 /* if the command resulted in a new command,
1813 parse that as well */
1816 } while(ftp_command
);
1821 if (getline(cp
, 7) == NULL
) {
1822 reply(221, "You could at least say goodbye.");
1826 if (strcmp(cp
, "ABOR\r\n") == 0) {
1828 reply(426, "Transfer aborted. Data connection closed.");
1829 reply(226, "Abort successful");
1830 longjmp(urgcatch
, 1);
1832 if (strcmp(cp
, "STAT\r\n") == 0) {
1833 if (file_size
!= (off_t
) -1)
1834 reply(213, "Status: %ld of %ld bytes transferred",
1838 reply(213, "Status: %ld bytes transferred"
1845 * Note: a response of 425 is not mentioned as a possible response to
1846 * the PASV command in RFC959. However, it has been blessed as
1847 * a legitimate response by Jon Postel in a telephone conversation
1848 * with Rick Adams on 25 Jan 89.
1856 pdata
= socket(AF_INET
, SOCK_STREAM
, 0);
1858 perror_reply(425, "Can't open passive connection");
1861 pasv_addr
= ctrl_addr
;
1862 pasv_addr
.sin_port
= 0;
1864 if (bind(pdata
, (struct sockaddr
*)&pasv_addr
, sizeof(pasv_addr
)) < 0) {
1865 seteuid((uid_t
)pw
->pw_uid
);
1868 seteuid((uid_t
)pw
->pw_uid
);
1869 len
= sizeof(pasv_addr
);
1870 if (getsockname(pdata
, (struct sockaddr
*) &pasv_addr
, &len
) < 0)
1872 if (listen(pdata
, 1) < 0)
1874 a
= (char *) &pasv_addr
.sin_addr
;
1875 p
= (char *) &pasv_addr
.sin_port
;
1877 #define UC(b) (((int) b) & 0xff)
1879 reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a
[0]),
1880 UC(a
[1]), UC(a
[2]), UC(a
[3]), UC(p
[0]), UC(p
[1]));
1886 perror_reply(425, "Can't open passive connection");
1891 * Generate unique name for file with basename "local".
1892 * The file named "local" is already known to exist.
1893 * Generates failure reply on error.
1896 gunique(char *local
)
1898 static char new[MaxPathLen
];
1903 cp
= strrchr(local
, '/');
1906 if (stat(cp
? local
: ".", &st
) < 0) {
1907 perror_reply(553, cp
? local
: ".");
1912 for (count
= 1; count
< 100; count
++) {
1913 snprintf (new, sizeof(new), "%s.%d", local
, count
);
1914 if (stat(new, &st
) < 0)
1917 reply(452, "Unique file name cannot be created.");
1922 * Format and send reply containing system error number.
1925 perror_reply(int code
, char *string
)
1927 reply(code
, "%s: %s.", string
, strerror(errno
));
1930 static char *onefile
[] = {
1936 send_file_list(char *whichf
)
1942 char **dirlist
, *dirname
;
1946 char buf
[MaxPathLen
];
1948 if (strpbrk(whichf
, "~{[*?") != NULL
) {
1949 int flags
= GLOB_BRACE
|GLOB_NOCHECK
|GLOB_QUOTE
|GLOB_TILDE
;
1951 memset(&gl
, 0, sizeof(gl
));
1953 if (glob(whichf
, flags
, 0, &gl
)) {
1954 reply(550, "not found");
1956 } else if (gl
.gl_pathc
== 0) {
1958 perror_reply(550, whichf
);
1961 dirlist
= gl
.gl_pathv
;
1963 onefile
[0] = whichf
;
1968 if (setjmp(urgcatch
)) {
1972 while ((dirname
= *dirlist
++)) {
1973 if (stat(dirname
, &st
) < 0) {
1975 * If user typed "ls -l", etc, and the client
1976 * used NLST, do what the user meant.
1978 if (dirname
[0] == '-' && *dirlist
== NULL
&&
1980 retrieve("/bin/ls %s", dirname
);
1983 perror_reply(550, whichf
);
1993 if (S_ISREG(st
.st_mode
)) {
1995 dout
= dataconn("file list", (off_t
)-1, "w");
2000 snprintf(buf
, sizeof(buf
), "%s%s\n", dirname
,
2001 type
== TYPE_A
? "\r" : "");
2002 auth_write(fileno(dout
), buf
, strlen(buf
));
2003 byte_count
+= strlen(dirname
) + 1;
2005 } else if (!S_ISDIR(st
.st_mode
))
2008 if ((dirp
= opendir(dirname
)) == NULL
)
2011 while ((dir
= readdir(dirp
)) != NULL
) {
2012 char nbuf
[MaxPathLen
];
2014 if (!strcmp(dir
->d_name
, "."))
2016 if (!strcmp(dir
->d_name
, ".."))
2019 snprintf(nbuf
, sizeof(nbuf
), "%s/%s", dirname
, dir
->d_name
);
2022 * We have to do a stat to insure it's
2023 * not a directory or special file.
2025 if (simple
|| (stat(nbuf
, &st
) == 0 &&
2026 S_ISREG(st
.st_mode
))) {
2028 dout
= dataconn("file list", (off_t
)-1, "w");
2033 if(strncmp(nbuf
, "./", 2) == 0)
2034 snprintf(buf
, sizeof(buf
), "%s%s\n", nbuf
+2,
2035 type
== TYPE_A
? "\r" : "");
2037 snprintf(buf
, sizeof(buf
), "%s%s\n", nbuf
,
2038 type
== TYPE_A
? "\r" : "");
2039 auth_write(fileno(dout
), buf
, strlen(buf
));
2040 byte_count
+= strlen(nbuf
) + 1;
2046 reply(550, "No files found.");
2047 else if (ferror(dout
) != 0)
2048 perror_reply(550, "Data connection");
2050 reply(226, "Transfer complete.");
2054 auth_write(fileno(dout
), buf
, 0); /* XXX flush */
2074 snprintf(line
, sizeof(line
),
2075 "/bin/locate -d %s %s",
2076 ftp_rooted("/etc/locatedb"),
2078 f
= ftpd_popen(line
, "r", 1, 1);
2080 perror_reply(550, "/bin/locate");
2083 lreply(200, "Output from find.");
2084 while(fgets(line
, sizeof(line
), f
)){
2085 if(line
[strlen(line
)-1] == '\n')
2086 line
[strlen(line
)-1] = 0;