diff options
Diffstat (limited to 'crypto/kerberosIV/appl/ftp/ftpd')
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/Makefile.am | 3 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/Makefile.in | 6 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/extern.h | 16 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y | 134 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/ftpd.c | 873 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h | 16 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c | 9 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/kauth.c | 25 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c | 9 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/ls.c | 572 | ||||
-rw-r--r-- | crypto/kerberosIV/appl/ftp/ftpd/popen.c | 6 |
11 files changed, 1264 insertions, 405 deletions
diff --git a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am index 187fca3..282cb3a 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am +++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.am @@ -1,4 +1,4 @@ -# $Id: Makefile.am,v 1.19 1999/04/25 13:24:55 assar Exp $ +# $Id: Makefile.am,v 1.20 1999/10/03 16:38:53 joda Exp $ include $(top_srcdir)/Makefile.am.common @@ -21,6 +21,7 @@ ftpd_SOURCES = \ ftpd.c \ ftpd_locl.h \ logwtmp.c \ + ls.c \ pathnames.h \ popen.c \ security.c \ diff --git a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in index 3b555a6..bc5c12e 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in +++ b/crypto/kerberosIV/appl/ftp/ftpd/Makefile.in @@ -1,5 +1,5 @@ # -# $Id: Makefile.in,v 1.40 1999/03/10 19:01:11 joda Exp $ +# $Id: Makefile.in,v 1.41 1999/10/03 16:39:27 joda Exp $ # srcdir = @srcdir@ @@ -47,8 +47,8 @@ LIBROKEN= -L$(LIBTOP)/roken -lroken PROGS = ftpd$(EXECSUFFIX) -ftpd_SOURCES = ftpd.c ftpcmd.c logwtmp.c popen.c security.c krb4.c kauth.c -ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o popen.o security.o krb4.o kauth.o +ftpd_SOURCES = ftpd.c ftpcmd.c logwtmp.c ls.c popen.c security.c krb4.c kauth.c +ftpd_OBJS = ftpd.o ftpcmd.o logwtmp.o ls.o popen.o security.o krb4.o kauth.o SOURCES = $(ftpd_SOURCES) OBJECTS = $(ftpd_OBJS) diff --git a/crypto/kerberosIV/appl/ftp/ftpd/extern.h b/crypto/kerberosIV/appl/ftp/ftpd/extern.h index e96809e..2e1e0d0 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/extern.h +++ b/crypto/kerberosIV/appl/ftp/ftpd/extern.h @@ -67,6 +67,8 @@ char **copyblk(char **); void cwd(char *); void do_delete(char *); void dologout(int); +void eprt(char *); +void epsv(char *); void fatal(char *); int filename_check(char *); int ftpd_pclose(FILE *); @@ -86,8 +88,8 @@ __attribute__ ((format (printf, 1, 2))) #endif ; void pass(char *); -void passive(void); -void perror_reply(int, char *); +void pasv(void); +void perror_reply(int, const char *); void pwd(void); void removedir(char *); void renamecmd(char *, char *); @@ -97,7 +99,7 @@ void reply(int, const char *, ...) __attribute__ ((format (printf, 2, 3))) #endif ; -void retrieve(char *, char *); +void retrieve(const char *, char *); void send_file_list(char *); void setproctitle(const char *, ...) #ifdef __GNUC__ @@ -111,6 +113,8 @@ void upper(char *); void user(char *); void yyerror(char *); +void list_file(char*); + void kauth(char *, char*); void klist(void); void cond_kdestroy(void); @@ -121,15 +125,17 @@ void afsunlog(void); int find(char *); +void builtin_ls(FILE*, const char*); + int do_login(int code, char *passwd); int klogin(char *name, char *password); const char *ftp_rooted(const char *path); -extern struct sockaddr_in ctrl_addr, his_addr; +extern struct sockaddr *ctrl_addr, *his_addr; extern char hostname[]; -extern struct sockaddr_in data_dest; +extern struct sockaddr *data_dest; extern int logged_in; extern struct passwd *pw; extern int guest; diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y index be36ea2..07ff9a5 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y @@ -43,7 +43,7 @@ %{ #include "ftpd_locl.h" -RCSID("$Id: ftpcmd.y,v 1.48 1999/05/08 02:22:43 assar Exp $"); +RCSID("$Id: ftpcmd.y,v 1.56 1999/10/26 11:56:23 assar Exp $"); off_t restart_point; @@ -98,6 +98,7 @@ static int yylex (void); ABOR DELE CWD LIST NLST SITE sTAT HELP NOOP MKD RMD PWD CDUP STOU SMNT SYST SIZE MDTM + EPRT EPSV UMASK IDLE CHMOD @@ -105,7 +106,9 @@ static int yylex (void); CONF ENC KAUTH KLIST KDESTROY KRBTKFILE AFSLOG - FIND URL + LOCATE URL + + FEAT OPTS LEXERR @@ -151,9 +154,23 @@ cmd } reply(200, "PORT command successful."); } + | EPRT SP STRING CRLF + { + eprt ($3); + free ($3); + } | PASV CRLF { - passive(); + pasv (); + } + | EPSV CRLF + { + epsv (NULL); + } + | EPSV SP STRING CRLF + { + epsv ($3); + free ($3); } | TYPE SP type_code CRLF { @@ -224,24 +241,30 @@ cmd } | RETR SP pathname CRLF check_login { - if ($5 && $3 != NULL) - retrieve(0, $3); - if ($3 != NULL) - free($3); + char *name = $3; + + if ($5 && name != NULL) + retrieve(0, name); + if (name != NULL) + free(name); } | STOR SP pathname CRLF check_login { - if ($5 && $3 != NULL) - do_store($3, "w", 0); - if ($3 != NULL) - free($3); + char *name = $3; + + if ($5 && name != NULL) + do_store(name, "w", 0); + if (name != NULL) + free(name); } | APPE SP pathname CRLF check_login { - if ($5 && $3 != NULL) - do_store($3, "a", 0); - if ($3 != NULL) - free($3); + char *name = $3; + + if ($5 && name != NULL) + do_store(name, "a", 0); + if (name != NULL) + free(name); } | NLST CRLF check_login { @@ -250,33 +273,23 @@ cmd } | NLST SP STRING CRLF check_login { - if ($5 && $3 != NULL) - send_file_list($3); - if ($3 != NULL) - free($3); + char *name = $3; + + if ($5 && name != NULL) + send_file_list(name); + if (name != NULL) + free(name); } | LIST CRLF check_login { -#ifdef HAVE_LS_A - char *cmd = "/bin/ls -lA"; -#else - char *cmd = "/bin/ls -la"; -#endif - if ($3) - retrieve(cmd, ""); - + if($3) + list_file("."); } | LIST SP pathname CRLF check_login { -#ifdef HAVE_LS_A - char *cmd = "/bin/ls -lA %s"; -#else - char *cmd = "/bin/ls -la %s"; -#endif - if ($5 && $3 != NULL) - retrieve(cmd, $3); - if ($3 != NULL) - free($3); + if($5) + list_file($3); + free($3); } | sTAT SP pathname CRLF check_login { @@ -388,6 +401,20 @@ cmd if ($3) cwd(".."); } + | FEAT CRLF + { + lreply(211, "Supported features:"); + lreply(0, " MDTM"); + lreply(0, " REST STREAM"); + lreply(0, " SIZE"); + reply(211, "End"); + } + | OPTS SP STRING CRLF + { + free ($3); + reply(501, "Bad options"); + } + | SITE SP HELP CRLF { help(sitetab, (char *) 0); @@ -522,16 +549,15 @@ cmd #ifdef KRB4 if(guest) reply(500, "Can't be done as guest."); - else if($7){ + else if($7) afslog($5); - } if($5) free($5); #else reply(500, "Command not implemented."); #endif } - | SITE SP FIND SP STRING CRLF check_login + | SITE SP LOCATE SP STRING CRLF check_login { if($7 && $5 != NULL) find($5); @@ -696,9 +722,11 @@ host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER { - data_dest.sin_family = AF_INET; - data_dest.sin_port = htons($9 * 256 + $11); - data_dest.sin_addr.s_addr = + struct sockaddr_in *sin = (struct sockaddr_in *)data_dest; + + sin->sin_family = AF_INET; + sin->sin_port = htons($9 * 256 + $11); + sin->sin_addr.s_addr = htonl(($1 << 24) | ($3 << 16) | ($5 << 8) | $7); } ; @@ -901,7 +929,9 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */ { "REIN", REIN, ARGS, 0, "(reinitialize server state)" }, { "QUIT", QUIT, ARGS, 1, "(terminate service)", }, { "PORT", PORT, ARGS, 1, "<sp> b0, b1, b2, b3, b4" }, + { "EPRT", EPRT, STR1, 1, "<sp> string" }, { "PASV", PASV, ARGS, 1, "(set server in passive mode)" }, + { "EPSV", EPSV, OSTR, 1, "[<sp> foo]" }, { "TYPE", TYPE, ARGS, 1, "<sp> [ A | E | I | L ]" }, { "STRU", STRU, ARGS, 1, "(specify file structure)" }, { "MODE", MODE, ARGS, 1, "(specify transfer mode)" }, @@ -952,6 +982,10 @@ struct tab cmdtab[] = { /* In order defined in RFC 765 */ { "CONF", CONF, STR1, 1, "<sp> confidentiality command" }, { "ENC", ENC, STR1, 1, "<sp> privacy command" }, + /* RFC2389 */ + { "FEAT", FEAT, ARGS, 1, "" }, + { "OPTS", OPTS, ARGS, 1, "<sp> command [<sp> options]" }, + { NULL, 0, 0, 0, 0 } }; @@ -967,7 +1001,8 @@ struct tab sitetab[] = { { "KRBTKFILE", KRBTKFILE, STR1, 1, "<sp> ticket-file" }, { "AFSLOG", AFSLOG, OSTR, 1, "[<sp> cell]" }, - { "FIND", FIND, STR1, 1, "<sp> globexpr" }, + { "LOCATE", LOCATE, STR1, 1, "<sp> globexpr" }, + { "FIND", LOCATE, STR1, 1, "<sp> globexpr" }, { "URL", URL, ARGS, 1, "?" }, @@ -996,7 +1031,7 @@ ftpd_getline(char *s, int n) cs = s; /* tmpline may contain saved command from urgent mode interruption */ if(ftp_command){ - strcpy_truncate(s, ftp_command, n); + strlcpy(s, ftp_command, n); if (debug) syslog(LOG_DEBUG, "command: %s", s); #ifdef XXX @@ -1162,7 +1197,10 @@ yylex(void) dostr1: if (cbuf[cpos] == ' ') { cpos++; - state = state == OSTR ? STR2 : ++state; + if(state == OSTR) + state = STR2; + else + state++; return (SP); } break; @@ -1335,7 +1373,7 @@ help(struct tab *ctab, char *s) columns = 1; lines = (NCMDS + columns - 1) / columns; for (i = 0; i < lines; i++) { - strcpy_truncate (buf, " ", sizeof(buf)); + strlcpy (buf, " ", sizeof(buf)); for (j = 0; j < columns; j++) { c = ctab + j * lines + i; snprintf (buf + strlen(buf), @@ -1347,13 +1385,13 @@ help(struct tab *ctab, char *s) break; w = strlen(c->name) + 1; while (w < width) { - strcat_truncate (buf, + strlcat (buf, " ", sizeof(buf)); w++; } } - lreply(214, buf); + lreply(214, "%s", buf); } reply(214, "Direct comments to kth-krb-bugs@pdc.kth.se"); return; diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c b/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c index fa87fc2..d3c9a6a 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd.c @@ -36,19 +36,29 @@ #ifdef KRB5 #include <krb5.h> #endif +#include "getarg.h" -RCSID("$Id: ftpd.c,v 1.115 1999/06/15 03:51:47 assar Exp $"); +RCSID("$Id: ftpd.c,v 1.131 1999/11/30 19:18:38 assar Exp $"); static char version[] = "Version 6.00"; extern off_t restart_point; extern char cbuf[]; -struct sockaddr_in ctrl_addr; -struct sockaddr_in data_source; -struct sockaddr_in data_dest; -struct sockaddr_in his_addr; -struct sockaddr_in pasv_addr; +struct sockaddr_storage ctrl_addr_ss; +struct sockaddr *ctrl_addr = (struct sockaddr *)&ctrl_addr_ss; + +struct sockaddr_storage data_source_ss; +struct sockaddr *data_source = (struct sockaddr *)&data_source_ss; + +struct sockaddr_storage data_dest_ss; +struct sockaddr *data_dest = (struct sockaddr *)&data_dest_ss; + +struct sockaddr_storage his_addr_ss; +struct sockaddr *his_addr = (struct sockaddr *)&his_addr_ss; + +struct sockaddr_storage pasv_addr_ss; +struct sockaddr *pasv_addr = (struct sockaddr *)&pasv_addr_ss; int data; jmp_buf errcatch, urgcatch; @@ -125,16 +135,15 @@ static void ack (char *); static void myoob (int); static int checkuser (char *, char *); static int checkaccess (char *); -static FILE *dataconn (char *, off_t, char *); -static void dolog (struct sockaddr_in *); +static FILE *dataconn (const char *, off_t, const char *); +static void dolog (struct sockaddr *); static void end_login (void); -static FILE *getdatasock (char *); +static FILE *getdatasock (const char *); static char *gunique (char *); static RETSIGTYPE lostconn (int); static int receive_data (FILE *, FILE *); static void send_data (FILE *, FILE *); static struct passwd * sgetpwnam (char *); -static void usage(void); static char * curdir(void) @@ -144,7 +153,7 @@ curdir(void) if (getcwd(path, sizeof(path)-1) == NULL) return (""); if (path[1] != '\0') /* special case for root dir. */ - strcat_truncate(path, "/", sizeof(path)); + strlcat(path, "/", sizeof(path)); /* For guest account, skip / since it's chrooted */ return (guest ? path+1 : path); } @@ -186,218 +195,231 @@ parse_auth_level(char *str) * Print usage and die. */ +static int debug_flag; +static int interactive_flag; +static char *guest_umask_string; +static char *port_string; +static char *umask_string; +static char *auth_string; + +int use_builtin_ls; + +static int help_flag; +static int version_flag; + +struct getargs args[] = { + { NULL, 'a', arg_string, &auth_string, "required authentication" }, + { NULL, 'i', arg_flag, &interactive_flag, "don't assume stdin is a socket" }, + { NULL, 'p', arg_string, &port_string, "what port to listen to" }, + { NULL, 'g', arg_string, &guest_umask_string, "umask for guest logins" }, + { NULL, 'l', arg_counter, &logging, "log more stuff", "" }, + { NULL, 't', arg_integer, &ftpd_timeout, "initial timeout" }, + { NULL, 'T', arg_integer, &maxtimeout, "max timeout" }, + { NULL, 'u', arg_string, &umask_string, "umask for user logins" }, + { NULL, 'd', arg_flag, &debug_flag, "enable debugging" }, + { NULL, 'v', arg_flag, &debug_flag, "enable debugging" }, + { "builtin-ls", 'B', arg_flag, &use_builtin_ls, "use built-in ls to list files" }, + { "version", 0, arg_flag, &version_flag }, + { "help", 'h', arg_flag, &help_flag } +}; + +static int num_args = sizeof(args) / sizeof(args[0]); + static void -usage (void) +usage (int code) { - fprintf (stderr, - "Usage: %s [-d] [-i] [-g guest_umask] [-l] [-p port]" - " [-t timeout] [-T max_timeout] [-u umask] [-v]" - " [-a auth_level] \n", - __progname); - exit (1); + arg_printusage(args, num_args, NULL, ""); + exit (code); } int main(int argc, char **argv) { - int addrlen, ch, on = 1, tos; - char *cp, line[LINE_MAX]; - FILE *fd; - int not_inetd = 0; - int port; - struct servent *sp; + int addrlen, on = 1, tos; + char *cp, line[LINE_MAX]; + FILE *fd; + int port; + struct servent *sp; + + int optind = 0; - set_progname (argv[0]); + set_progname (argv[0]); #ifdef KRB4 - /* detach from any tickets and tokens */ - { - char tkfile[1024]; - snprintf(tkfile, sizeof(tkfile), - "/tmp/ftp_%u", (unsigned)getpid()); - krb_set_tkt_string(tkfile); - if(k_hasafs()) - k_setpag(); - } + /* detach from any tickets and tokens */ + { + char tkfile[1024]; + snprintf(tkfile, sizeof(tkfile), + "/tmp/ftp_%u", (unsigned)getpid()); + krb_set_tkt_string(tkfile); + if(k_hasafs()) + k_setpag(); + } #endif + if(getarg(args, num_args, argc, argv, &optind)) + usage(1); + + if(help_flag) + usage(0); + + if(version_flag) { + print_version(NULL); + exit(0); + } + + if(auth_string) + auth_level = parse_auth_level(auth_string); + { + char *p; + long val = 0; + + if(guest_umask_string) { + val = strtol(guest_umask_string, &p, 8); + if (*p != '\0' || val < 0) + warnx("bad value for -g"); + else + guest_umask = val; + } + if(umask_string) { + val = strtol(umask_string, &p, 8); + if (*p != '\0' || val < 0) + warnx("bad value for -u"); + else + defumask = val; + } + } + if(port_string) { + sp = getservbyname(port_string, "tcp"); + if(sp) + port = sp->s_port; + else + if(isdigit(port_string[0])) + port = htons(atoi(port_string)); + else + warnx("bad value for -p"); + } else { sp = getservbyname("ftp", "tcp"); if(sp) port = sp->s_port; else port = htons(21); - - while ((ch = getopt(argc, argv, "a:dg:ilp:t:T:u:v")) != EOF) { - switch (ch) { - case 'a': - auth_level = parse_auth_level(optarg); - break; - case 'd': - debug = 1; - break; - - case 'i': - not_inetd = 1; - break; - case 'g': - { - long val = 0; - - val = strtol(optarg, &optarg, 8); - if (*optarg != '\0' || val < 0) - warnx("bad value for -g"); - else - guest_umask = val; - break; - } - case 'l': - logging++; /* > 1 == extra logging */ - break; - - case 'p': - sp = getservbyname(optarg, "tcp"); - if(sp) - port = sp->s_port; - else - if(isdigit(optarg[0])) - port = htons(atoi(optarg)); - else - warnx("bad value for -p"); - break; + } - case 't': - ftpd_timeout = atoi(optarg); - if (maxtimeout < ftpd_timeout) - maxtimeout = ftpd_timeout; - break; - - case 'T': - maxtimeout = atoi(optarg); - if (ftpd_timeout > maxtimeout) - ftpd_timeout = maxtimeout; - break; - - case 'u': - { - long val = 0; - - val = strtol(optarg, &optarg, 8); - if (*optarg != '\0' || val < 0) - warnx("bad value for -u"); - else - defumask = val; - break; - } + if (maxtimeout < ftpd_timeout) + maxtimeout = ftpd_timeout; - case 'v': - debug = 1; - break; +#if 0 + if (ftpd_timeout > maxtimeout) + ftpd_timeout = maxtimeout; +#endif - default: - usage (); - } - } - if(not_inetd) - mini_inetd (port); + if(interactive_flag) + mini_inetd (port); - /* - * LOG_NDELAY sets up the logging connection immediately, - * necessary for anonymous ftp's that chroot and can't do it later. - */ - openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); - addrlen = sizeof(his_addr); - if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { - syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); - exit(1); - } - addrlen = sizeof(ctrl_addr); - if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { - syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); - exit(1); - } + /* + * LOG_NDELAY sets up the logging connection immediately, + * necessary for anonymous ftp's that chroot and can't do it later. + */ + openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); + addrlen = sizeof(his_addr_ss); + if (getpeername(STDIN_FILENO, his_addr, &addrlen) < 0) { + syslog(LOG_ERR, "getpeername (%s): %m",argv[0]); + exit(1); + } + addrlen = sizeof(ctrl_addr_ss); + if (getsockname(STDIN_FILENO, ctrl_addr, &addrlen) < 0) { + syslog(LOG_ERR, "getsockname (%s): %m",argv[0]); + exit(1); + } #if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) - tos = IPTOS_LOWDELAY; - if (setsockopt(0, IPPROTO_IP, IP_TOS, (void *)&tos, sizeof(int)) < 0) - syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + tos = IPTOS_LOWDELAY; + if (setsockopt(STDIN_FILENO, IPPROTO_IP, IP_TOS, + (void *)&tos, sizeof(int)) < 0) + syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); #endif - data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); + data_source->sa_family = ctrl_addr->sa_family; + socket_set_port (data_source, + htons(ntohs(socket_get_port(ctrl_addr)) - 1)); - /* set this here so it can be put in wtmp */ - snprintf(ttyline, sizeof(ttyline), "ftp%u", (unsigned)getpid()); + /* set this here so it can be put in wtmp */ + snprintf(ttyline, sizeof(ttyline), "ftp%u", (unsigned)getpid()); - /* freopen(_PATH_DEVNULL, "w", stderr); */ - signal(SIGPIPE, lostconn); - signal(SIGCHLD, SIG_IGN); + /* freopen(_PATH_DEVNULL, "w", stderr); */ + signal(SIGPIPE, lostconn); + signal(SIGCHLD, SIG_IGN); #ifdef SIGURG - if (signal(SIGURG, myoob) == SIG_ERR) - syslog(LOG_ERR, "signal: %m"); + if (signal(SIGURG, myoob) == SIG_ERR) + syslog(LOG_ERR, "signal: %m"); #endif - /* Try to handle urgent data inline */ + /* Try to handle urgent data inline */ #if defined(SO_OOBINLINE) && defined(HAVE_SETSOCKOPT) - if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (void *)&on, - sizeof(on)) < 0) - syslog(LOG_ERR, "setsockopt: %m"); + if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (void *)&on, + sizeof(on)) < 0) + syslog(LOG_ERR, "setsockopt: %m"); #endif #ifdef F_SETOWN - if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) - syslog(LOG_ERR, "fcntl F_SETOWN: %m"); + if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) + syslog(LOG_ERR, "fcntl F_SETOWN: %m"); #endif - dolog(&his_addr); - /* - * Set up default state - */ - data = -1; - type = TYPE_A; - form = FORM_N; - stru = STRU_F; - mode = MODE_S; - tmpline[0] = '\0'; - - /* If logins are disabled, print out the message. */ - if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) { - while (fgets(line, sizeof(line), fd) != NULL) { - if ((cp = strchr(line, '\n')) != NULL) - *cp = '\0'; - lreply(530, "%s", line); - } - fflush(stdout); - fclose(fd); - reply(530, "System not available."); - exit(0); - } - if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) { - while (fgets(line, sizeof(line), fd) != NULL) { - if ((cp = strchr(line, '\n')) != NULL) - *cp = '\0'; - lreply(220, "%s", line); - } - fflush(stdout); - fclose(fd); - /* reply(220,) must follow */ + dolog(his_addr); + /* + * Set up default state + */ + data = -1; + type = TYPE_A; + form = FORM_N; + stru = STRU_F; + mode = MODE_S; + tmpline[0] = '\0'; + + /* If logins are disabled, print out the message. */ + if ((fd = fopen(_PATH_NOLOGIN,"r")) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + lreply(530, "%s", line); + } + fflush(stdout); + fclose(fd); + reply(530, "System not available."); + exit(0); + } + if ((fd = fopen(_PATH_FTPWELCOME, "r")) != NULL) { + while (fgets(line, sizeof(line), fd) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + lreply(220, "%s", line); } - gethostname(hostname, sizeof(hostname)); - reply(220, "%s FTP server (%s" + fflush(stdout); + fclose(fd); + /* reply(220,) must follow */ + } + gethostname(hostname, sizeof(hostname)); + + reply(220, "%s FTP server (%s" #ifdef KRB5 - "+%s" + "+%s" #endif #ifdef KRB4 - "+%s" + "+%s" #endif - ") ready.", hostname, version + ") ready.", hostname, version #ifdef KRB5 - ,heimdal_version + ,heimdal_version #endif #ifdef KRB4 - ,krb4_version + ,krb4_version #endif - ); - setjmp(errcatch); - for (;;) - yyparse(); - /* NOTREACHED */ + ); + + setjmp(errcatch); + for (;;) + yyparse(); + /* NOTREACHED */ } static RETSIGTYPE @@ -506,10 +528,19 @@ user(char *name) reply(331, "Guest login ok, type your name as password."); } else reply(530, "User %s unknown.", name); - if (!askpasswd && logging) + if (!askpasswd && logging) { + char data_addr[256]; + + if (inet_ntop (his_addr->sa_family, + socket_get_address(his_addr), + data_addr, sizeof(data_addr)) == NULL) + strlcpy (data_addr, "unknown address", + sizeof(data_addr)); + syslog(LOG_NOTICE, "ANONYMOUS FTP LOGIN REFUSED FROM %s(%s)", - remotehost, inet_ntoa(his_addr.sin_addr)); + remotehost, data_addr); + } return; } if((auth_level & AUTH_PLAIN) == 0 && !sec_complete){ @@ -526,18 +557,29 @@ user(char *name) if (cp == NULL || checkaccess(name)) { reply(530, "User %s access denied.", name); - if (logging) + if (logging) { + char data_addr[256]; + + if (inet_ntop (his_addr->sa_family, + socket_get_address(his_addr), + data_addr, + sizeof(data_addr)) == NULL) + strlcpy (data_addr, + "unknown address", + sizeof(data_addr)); + syslog(LOG_NOTICE, "FTP LOGIN REFUSED FROM %s(%s), %s", remotehost, - inet_ntoa(his_addr.sin_addr), + data_addr, name); + } pw = (struct passwd *) NULL; return; } } if (logging) - strcpy_truncate(curname, name, sizeof(curname)); + strlcpy(curname, name, sizeof(curname)); if(sec_complete) { if(sec_userok(name) == 0) do_login(232, name); @@ -662,88 +704,128 @@ checkaccess(char *name) #undef ALLOWED #undef NOT_ALLOWED -int do_login(int code, char *passwd) +/* output contents of /etc/issue.net, or /etc/issue */ +static void +show_issue(int code) { - FILE *fd; - login_attempts = 0; /* this time successful */ - if (setegid((gid_t)pw->pw_gid) < 0) { - reply(550, "Can't set gid."); - return -1; + FILE *f; + char buf[128]; + + f = fopen("/etc/issue.net", "r"); + if(f == NULL) + f = fopen("/etc/issue", "r"); + if(f){ + while(fgets(buf, sizeof(buf), f)){ + buf[strcspn(buf, "\r\n")] = '\0'; + lreply(code, "%s", buf); } - initgroups(pw->pw_name, pw->pw_gid); + fclose(f); + } +} - /* open wtmp before chroot */ - ftpd_logwtmp(ttyline, pw->pw_name, remotehost); - logged_in = 1; +int do_login(int code, char *passwd) +{ + FILE *fd; + login_attempts = 0; /* this time successful */ + if (setegid((gid_t)pw->pw_gid) < 0) { + reply(550, "Can't set gid."); + return -1; + } + initgroups(pw->pw_name, pw->pw_gid); - dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name); - if (guest) { - /* - * We MUST do a chdir() after the chroot. Otherwise - * the old current directory will be accessible as "." - * outside the new root! - */ - if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { - reply(550, "Can't set guest privileges."); - return -1; - } - } else if (dochroot) { - if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { - reply(550, "Can't change root."); - return -1; - } - } else if (chdir(pw->pw_dir) < 0) { - if (chdir("/") < 0) { - reply(530, "User %s: can't change directory to %s.", - pw->pw_name, pw->pw_dir); - return -1; - } else - lreply(code, "No directory! Logging in with home=/"); - } - if (seteuid((uid_t)pw->pw_uid) < 0) { - reply(550, "Can't set uid."); - return -1; - } + /* open wtmp before chroot */ + ftpd_logwtmp(ttyline, pw->pw_name, remotehost); + logged_in = 1; + + dochroot = checkuser(_PATH_FTPCHROOT, pw->pw_name); + if (guest) { /* - * Display a login message, if it exists. - * N.B. reply(code,) must follow the message. + * We MUST do a chdir() after the chroot. Otherwise + * the old current directory will be accessible as "." + * outside the new root! */ - if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { - char *cp, line[LINE_MAX]; + if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { + reply(550, "Can't set guest privileges."); + return -1; + } + } else if (dochroot) { + if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) { + reply(550, "Can't change root."); + return -1; + } + } else if (chdir(pw->pw_dir) < 0) { + if (chdir("/") < 0) { + reply(530, "User %s: can't change directory to %s.", + pw->pw_name, pw->pw_dir); + return -1; + } else + lreply(code, "No directory! Logging in with home=/"); + } + if (seteuid((uid_t)pw->pw_uid) < 0) { + reply(550, "Can't set uid."); + return -1; + } + /* + * Display a login message, if it exists. + * N.B. reply(code,) must follow the message. + */ + if ((fd = fopen(_PATH_FTPLOGINMESG, "r")) != NULL) { + char *cp, line[LINE_MAX]; - while (fgets(line, sizeof(line), fd) != NULL) { - if ((cp = strchr(line, '\n')) != NULL) - *cp = '\0'; - lreply(code, "%s", line); - } + while (fgets(line, sizeof(line), fd) != NULL) { + if ((cp = strchr(line, '\n')) != NULL) + *cp = '\0'; + lreply(code, "%s", line); } - if (guest) { - reply(code, "Guest login ok, access restrictions apply."); + } + if (guest) { + show_issue(code); + reply(code, "Guest login ok, access restrictions apply."); #ifdef HAVE_SETPROCTITLE - snprintf (proctitle, sizeof(proctitle), - "%s: anonymous/%s", - remotehost, - passwd); + snprintf (proctitle, sizeof(proctitle), + "%s: anonymous/%s", + remotehost, + passwd); + setproctitle(proctitle); #endif /* HAVE_SETPROCTITLE */ - if (logging) - syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s(%s), %s", - remotehost, - inet_ntoa(his_addr.sin_addr), - passwd); - } else { - reply(code, "User %s logged in.", pw->pw_name); + if (logging) { + char data_addr[256]; + + if (inet_ntop (his_addr->sa_family, + socket_get_address(his_addr), + data_addr, sizeof(data_addr)) == NULL) + strlcpy (data_addr, "unknown address", + sizeof(data_addr)); + + syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s(%s), %s", + remotehost, + data_addr, + passwd); + } + } else { + show_issue(code); + reply(code, "User %s logged in.", pw->pw_name); #ifdef HAVE_SETPROCTITLE - snprintf(proctitle, sizeof(proctitle), "%s: %s", remotehost, pw->pw_name); - setproctitle(proctitle); + snprintf(proctitle, sizeof(proctitle), "%s: %s", remotehost, pw->pw_name); + setproctitle(proctitle); #endif /* HAVE_SETPROCTITLE */ - if (logging) - syslog(LOG_INFO, "FTP LOGIN FROM %s(%s) as %s", - remotehost, - inet_ntoa(his_addr.sin_addr), - pw->pw_name); - } - umask(defumask); - return 0; + if (logging) { + char data_addr[256]; + + if (inet_ntop (his_addr->sa_family, + socket_get_address(his_addr), + data_addr, sizeof(data_addr)) == NULL) + strlcpy (data_addr, "unknown address", + sizeof(data_addr)); + + syslog(LOG_INFO, "FTP LOGIN FROM %s(%s) as %s", + remotehost, + data_addr, + pw->pw_name); + } + } + umask(defumask); + return 0; } /* @@ -819,19 +901,27 @@ pass(char *passwd) * local authentication succeeded. */ if (rval) { + char data_addr[256]; + + if (inet_ntop (his_addr->sa_family, + socket_get_address(his_addr), + data_addr, sizeof(data_addr)) == NULL) + strlcpy (data_addr, "unknown address", + sizeof(data_addr)); + reply(530, "Login incorrect."); if (logging) syslog(LOG_NOTICE, "FTP LOGIN FAILED FROM %s(%s), %s", remotehost, - inet_ntoa(his_addr.sin_addr), + data_addr, curname); pw = NULL; if (login_attempts++ >= 5) { syslog(LOG_NOTICE, "repeated login failures from %s(%s)", remotehost, - inet_ntoa(his_addr.sin_addr)); + data_addr); exit(0); } return; @@ -845,7 +935,7 @@ pass(char *passwd) } void -retrieve(char *cmd, char *name) +retrieve(const char *cmd, char *name) { FILE *fin = NULL, *dout; struct stat st; @@ -858,6 +948,7 @@ retrieve(char *cmd, char *name) closefunc = fclose; st.st_size = 0; if(fin == NULL){ + int save_errno = errno; struct cmds { const char *ext; const char *cmd; @@ -904,7 +995,8 @@ retrieve(char *cmd, char *name) closefunc = ftpd_pclose; st.st_size = -1; cmd = line; - } + } else + errno = save_errno; } } else { snprintf(line, sizeof(line), cmd, name); @@ -1066,37 +1158,33 @@ done: } static FILE * -getdatasock(char *mode) +getdatasock(const char *mode) { - int on = 1, s, t, tries; + int s, t, tries; if (data >= 0) return (fdopen(data, mode)); - seteuid((uid_t)0); - s = socket(AF_INET, SOCK_STREAM, 0); + seteuid(0); + s = socket(ctrl_addr->sa_family, SOCK_STREAM, 0); if (s < 0) goto bad; -#if defined(SO_REUSEADDR) && defined(HAVE_SETSOCKOPT) - if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, - (void *) &on, sizeof(on)) < 0) - goto bad; -#endif + socket_set_reuseaddr (s, 1); /* anchor socket to avoid multi-homing problems */ - data_source.sin_family = AF_INET; - data_source.sin_addr = ctrl_addr.sin_addr; + socket_set_address_and_port (data_source, + socket_get_address (ctrl_addr), + socket_get_port (data_source)); + for (tries = 1; ; tries++) { - if (bind(s, (struct sockaddr *)&data_source, - sizeof(data_source)) >= 0) + if (bind(s, data_source, + socket_sockaddr_size (data_source)) >= 0) break; if (errno != EADDRINUSE || tries > 10) goto bad; sleep(tries); } - seteuid((uid_t)pw->pw_uid); -#if defined(IP_TOS) && defined(HAVE_SETSOCKOPT) - on = IPTOS_THROUGHPUT; - if (setsockopt(s, IPPROTO_IP, IP_TOS, (void *)&on, sizeof(int)) < 0) - syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + seteuid(pw->pw_uid); +#ifdef IPTOS_THROUGHPUT + socket_set_tos (s, IPTOS_THROUGHPUT); #endif return (fdopen(s, mode)); bad: @@ -1109,7 +1197,7 @@ bad: } static FILE * -dataconn(char *name, off_t size, char *mode) +dataconn(const char *name, off_t size, const char *mode) { char sizebuf[32]; FILE *file; @@ -1122,10 +1210,12 @@ dataconn(char *name, off_t size, char *mode) else *sizebuf = '\0'; if (pdata >= 0) { - struct sockaddr_in from; - int s, fromlen = sizeof(from); + struct sockaddr_storage from_ss; + struct sockaddr *from = (struct sockaddr *)&from; + int s; + int fromlen = sizeof(from_ss); - s = accept(pdata, (struct sockaddr *)&from, &fromlen); + s = accept(pdata, from, &fromlen); if (s < 0) { reply(425, "Can't open data connection."); close(pdata); @@ -1157,16 +1247,25 @@ dataconn(char *name, off_t size, char *mode) usedefault = 1; file = getdatasock(mode); if (file == NULL) { + char data_addr[256]; + + if (inet_ntop (data_source->sa_family, + socket_get_address(data_source), + data_addr, sizeof(data_addr)) == NULL) + strlcpy (data_addr, "unknown address", + sizeof(data_addr)); + reply(425, "Can't create data socket (%s,%d): %s.", - inet_ntoa(data_source.sin_addr), - ntohs(data_source.sin_port), strerror(errno)); + data_addr, + socket_get_port (data_source), + strerror(errno)); return (NULL); } data = fileno(file); - while (connect(data, (struct sockaddr *)&data_dest, - sizeof(data_dest)) < 0) { + while (connect(data, data_dest, + socket_sockaddr_size(data_dest)) < 0) { if (errno == EADDRINUSE && retry < swaitmax) { - sleep((unsigned) swaitint); + sleep(swaitint); retry += swaitint; continue; } @@ -1226,23 +1325,26 @@ send_data(FILE *instr, FILE *outstr) struct stat st; char *chunk; int in = fileno(instr); - if(fstat(in, &st) == 0 && S_ISREG(st.st_mode)) { - chunk = mmap(0, st.st_size, PROT_READ, MAP_SHARED, in, 0); + if(fstat(in, &st) == 0 && S_ISREG(st.st_mode) + && st.st_size > 0) { + /* + * mmap zero bytes has potential of loosing, don't do it. + */ + chunk = mmap(0, st.st_size, PROT_READ, + MAP_SHARED, in, 0); if((void *)chunk != (void *)MAP_FAILED) { cnt = st.st_size - restart_point; - sec_write(fileno(outstr), - chunk + restart_point, - cnt); - munmap(chunk, st.st_size); + sec_write(fileno(outstr), chunk + restart_point, cnt); + if (munmap(chunk, st.st_size) < 0) + warn ("munmap"); sec_fflush(outstr); byte_count = cnt; transflag = 0; } } } - #endif - if(transflag){ + if(transflag) { struct stat st; netfd = fileno(outstr); @@ -1430,7 +1532,7 @@ statcmd(void) struct sockaddr_in *sin; u_char *a, *p; - lreply(211, "%s FTP server status:", hostname, version); + lreply(211, "%s FTP server (%s) status:", hostname, version); printf(" %s\r\n", version); printf(" Connected to %s", remotehost); if (!isdigit(remotehost[0])) @@ -1673,18 +1775,30 @@ renamecmd(char *from, char *to) } static void -dolog(struct sockaddr_in *sin) +dolog(struct sockaddr *sa) { + struct sockaddr_in *sin = (struct sockaddr_in *)sa; + inaddr2str (sin->sin_addr, remotehost, sizeof(remotehost)); #ifdef HAVE_SETPROCTITLE snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost); setproctitle(proctitle); #endif /* HAVE_SETPROCTITLE */ - if (logging) + if (logging) { + char data_addr[256]; + + if (inet_ntop (his_addr->sa_family, + socket_get_address(his_addr), + data_addr, sizeof(data_addr)) == NULL) + strlcpy (data_addr, "unknown address", + sizeof(data_addr)); + + syslog(LOG_INFO, "connection from %s(%s)", remotehost, - inet_ntoa(his_addr.sin_addr)); + data_addr); + } } /* @@ -1766,31 +1880,41 @@ myoob(int signo) * with Rick Adams on 25 Jan 89. */ void -passive(void) +pasv(void) { int len; char *p, *a; + struct sockaddr_in *sin; - pdata = socket(AF_INET, SOCK_STREAM, 0); + if (ctrl_addr->sa_family != AF_INET) { + reply(425, + "You cannot do PASV with something that's not IPv4"); + return; + } + + pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0); if (pdata < 0) { perror_reply(425, "Can't open passive connection"); return; } - pasv_addr = ctrl_addr; - pasv_addr.sin_port = 0; - seteuid((uid_t)0); - if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) { - seteuid((uid_t)pw->pw_uid); + pasv_addr->sa_family = ctrl_addr->sa_family; + socket_set_address_and_port (pasv_addr, + socket_get_address (ctrl_addr), + 0); + seteuid(0); + if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) { + seteuid(pw->pw_uid); goto pasv_error; } - seteuid((uid_t)pw->pw_uid); - len = sizeof(pasv_addr); - if (getsockname(pdata, (struct sockaddr *) &pasv_addr, &len) < 0) + seteuid(pw->pw_uid); + len = sizeof(pasv_addr_ss); + if (getsockname(pdata, pasv_addr, &len) < 0) goto pasv_error; if (listen(pdata, 1) < 0) goto pasv_error; - a = (char *) &pasv_addr.sin_addr; - p = (char *) &pasv_addr.sin_port; + sin = (struct sockaddr_in *)pasv_addr; + a = (char *) &sin->sin_addr; + p = (char *) &sin->sin_port; #define UC(b) (((int) b) & 0xff) @@ -1805,6 +1929,109 @@ pasv_error: return; } +void +epsv(char *proto) +{ + int len; + + pdata = socket(ctrl_addr->sa_family, SOCK_STREAM, 0); + if (pdata < 0) { + perror_reply(425, "Can't open passive connection"); + return; + } + pasv_addr->sa_family = ctrl_addr->sa_family; + socket_set_address_and_port (pasv_addr, + socket_get_address (ctrl_addr), + 0); + seteuid(0); + if (bind(pdata, pasv_addr, socket_sockaddr_size (pasv_addr)) < 0) { + seteuid(pw->pw_uid); + goto pasv_error; + } + seteuid(pw->pw_uid); + len = sizeof(pasv_addr_ss); + if (getsockname(pdata, pasv_addr, &len) < 0) + goto pasv_error; + if (listen(pdata, 1) < 0) + goto pasv_error; + + reply(229, "Entering Extended Passive Mode (|||%d|)", + ntohs(socket_get_port (pasv_addr))); + return; + +pasv_error: + close(pdata); + pdata = -1; + perror_reply(425, "Can't open passive connection"); + return; +} + +void +eprt(char *str) +{ + char *end; + char sep; + int af; + int ret; + int port; + + usedefault = 0; + if (pdata >= 0) { + close(pdata); + pdata = -1; + } + + sep = *str++; + if (sep == '\0') { + reply(500, "Bad syntax in EPRT"); + return; + } + af = strtol (str, &end, 0); + if (af == 0 || *end != sep) { + reply(500, "Bad syntax in EPRT"); + return; + } + str = end + 1; + switch (af) { +#ifdef HAVE_IPV6 + case 2 : + data_dest->sa_family = AF_INET6; + break; +#endif + case 1 : + data_dest->sa_family = AF_INET; + break; + default : + reply(522, "Network protocol %d not supported, use (1" +#ifdef HAVE_IPV6 + ",2" +#endif + ")", af); + return; + } + end = strchr (str, sep); + if (end == NULL) { + reply(500, "Bad syntax in EPRT"); + return; + } + *end = '\0'; + ret = inet_pton (data_dest->sa_family, str, + socket_get_address (data_dest)); + + if (ret != 1) { + reply(500, "Bad address syntax in EPRT"); + return; + } + str = end + 1; + port = strtol (str, &end, 0); + if (port == 0 || *end != sep) { + reply(500, "Bad port syntax in EPRT"); + return; + } + socket_set_port (data_dest, htons(port)); + reply(200, "EPRT command successful."); +} + /* * Generate unique name for file with basename "local". * The file named "local" is already known to exist. @@ -1840,7 +2067,7 @@ gunique(char *local) * Format and send reply containing system error number. */ void -perror_reply(int code, char *string) +perror_reply(int code, const char *string) { reply(code, "%s: %s.", string, strerror(errno)); } @@ -1851,6 +2078,30 @@ static char *onefile[] = { }; void +list_file(char *file) +{ + if(use_builtin_ls) { + FILE *dout; + dout = dataconn(file, -1, "w"); + if (dout == NULL) + return; + set_buffer_size(fileno(dout), 0); + builtin_ls(dout, file); + reply(226, "Transfer complete."); + fclose(dout); + data = -1; + pdata = -1; + } else { +#ifdef HAVE_LS_A + const char *cmd = "/bin/ls -lA %s"; +#else + const char *cmd = "/bin/ls -la %s"; +#endif + retrieve(cmd, file); + } +} + +void send_file_list(char *whichf) { struct stat st; diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h b/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h index 4bb3ad3..5cb4904 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h +++ b/crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h @@ -14,12 +14,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Kungliga Tekniska - * Högskolan and its contributors. - * - * 4. Neither the name of the Institute nor the names of its contributors + * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -36,7 +31,7 @@ * SUCH DAMAGE. */ -/* $Id: ftpd_locl.h,v 1.5.2.1 1999/07/22 03:24:42 assar Exp $ */ +/* $Id: ftpd_locl.h,v 1.9 1999/12/02 16:58:30 joda Exp $ */ #ifndef __ftpd_locl_h__ #define __ftpd_locl_h__ @@ -63,6 +58,9 @@ #if defined(HAVE_SYS_IOCTL_H) && SunOS != 40 #include <sys/ioctl.h> #endif +#ifdef HAVE_SYS_IOCCOM_H +#include <sys/ioccom.h> +#endif #ifdef TIME_WITH_SYS_TIME #include <sys/time.h> #include <time.h> @@ -159,6 +157,10 @@ extern int LIBPREFIX(fclose) (FILE *); #endif +/* SunOS doesn't have any declaration of fclose */ + +int fclose(FILE *stream); + int yyparse(); #ifndef LOG_FTP diff --git a/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c b/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c index 8a1a8e3..28e3596 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c @@ -14,12 +14,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Kungliga Tekniska - * Högskolan and its contributors. - * - * 4. Neither the name of the Institute nor the names of its contributors + * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -40,7 +35,7 @@ #include <gssapi.h> #include <krb5.h> -RCSID("$Id: gss_userok.c,v 1.1 1998/05/12 12:15:22 joda Exp $"); +RCSID("$Id: gss_userok.c,v 1.2 1999/12/02 16:58:31 joda Exp $"); /* XXX a bit too much of krb5 dependency here... What is the correct way to do this? diff --git a/crypto/kerberosIV/appl/ftp/ftpd/kauth.c b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c index 33795b6..dad4de5 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/kauth.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/kauth.c @@ -14,12 +14,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Kungliga Tekniska - * Högskolan and its contributors. - * - * 4. Neither the name of the Institute nor the names of its contributors + * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -38,7 +33,7 @@ #include "ftpd_locl.h" -RCSID("$Id: kauth.c,v 1.22 1999/06/29 21:19:33 bg Exp $"); +RCSID("$Id: kauth.c,v 1.25 1999/12/02 16:58:31 joda Exp $"); static KTEXT_ST cip; static unsigned int lifetime; @@ -85,7 +80,7 @@ store_ticket(KTEXT cip) return(INTK_BADPW); /* extract server's name */ - strcpy_truncate(sp.name, ptr, sizeof(sp.name)); + strlcpy(sp.name, ptr, sizeof(sp.name)); ptr += len + 1; left -= len + 1; @@ -94,7 +89,7 @@ store_ticket(KTEXT cip) return(INTK_BADPW); /* extract server's instance */ - strcpy_truncate(sp.instance, ptr, sizeof(sp.instance)); + strlcpy(sp.instance, ptr, sizeof(sp.instance)); ptr += len + 1; left -= len + 1; @@ -103,7 +98,7 @@ store_ticket(KTEXT cip) return(INTK_BADPW); /* extract server's realm */ - strcpy_truncate(sp.realm, ptr, sizeof(sp.realm)); + strlcpy(sp.realm, ptr, sizeof(sp.realm)); ptr += len + 1; left -= len + 1; @@ -176,6 +171,10 @@ kauth(char *principal, char *ticket) char *p; int ret; + if(get_command_prot() != prot_private) { + reply(500, "Request denied (bad protection level)"); + return; + } ret = krb_parse_name(principal, &pr); if(ret){ reply(500, "Bad principal: %s.", krb_get_err_text(ret)); @@ -304,12 +303,12 @@ klist(void) " Issued", " Expires", " Principal (kvno)"); header = 0; } - strcpy_truncate(buf1, short_date(c.issue_date), sizeof(buf1)); + strlcpy(buf1, short_date(c.issue_date), sizeof(buf1)); c.issue_date = krb_life_to_time(c.issue_date, c.lifetime); if (time(0) < (unsigned long) c.issue_date) - strcpy_truncate(buf2, short_date(c.issue_date), sizeof(buf2)); + strlcpy(buf2, short_date(c.issue_date), sizeof(buf2)); else - strcpy_truncate(buf2, ">>> Expired <<< ", sizeof(buf2)); + strlcpy(buf2, ">>> Expired <<< ", sizeof(buf2)); lreply(200, "%s %s %s (%d)", buf1, buf2, krb_unparse_name_long(c.service, c.instance, c.realm), c.kvno); } diff --git a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c index d948a5a..019cc2d 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c @@ -14,12 +14,7 @@ * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the Kungliga Tekniska - * Högskolan and its contributors. - * - * 4. Neither the name of the Institute nor the names of its contributors + * 3. Neither the name of the Institute nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * @@ -38,7 +33,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: logwtmp.c,v 1.13 1999/03/01 09:49:37 joda Exp $"); +RCSID("$Id: logwtmp.c,v 1.14 1999/12/02 16:58:31 joda Exp $"); #endif #include <stdio.h> diff --git a/crypto/kerberosIV/appl/ftp/ftpd/ls.c b/crypto/kerberosIV/appl/ftp/ftpd/ls.c new file mode 100644 index 0000000..97eb77e --- /dev/null +++ b/crypto/kerberosIV/appl/ftp/ftpd/ls.c @@ -0,0 +1,572 @@ +/* + * Copyright (c) 1999 Kungliga Tekniska Högskolan + * (Royal Institute of Technology, Stockholm, Sweden). + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * 3. Neither the name of KTH nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY KTH AND ITS CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KTH OR ITS CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, + * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ + +#include "ftpd_locl.h" + +RCSID("$Id: ls.c,v 1.13 1999/11/20 20:49:41 assar Exp $"); + +struct fileinfo { + struct stat st; + int inode; + int bsize; + char mode[11]; + int n_link; + char *user; + char *group; + char *size; + char *major; + char *minor; + char *date; + char *filename; + char *link; +}; + +#define LS_DIRS 1 +#define LS_IGNORE_DOT 2 +#define LS_SORT_MODE 12 +#define SORT_MODE(f) ((f) & LS_SORT_MODE) +#define LS_SORT_NAME 4 +#define LS_SORT_MTIME 8 +#define LS_SORT_SIZE 12 +#define LS_SORT_REVERSE 16 + +#define LS_SIZE 32 +#define LS_INODE 64 + +#ifndef S_ISTXT +#define S_ISTXT S_ISVTX +#endif + +#ifndef S_ISSOCK +#define S_ISSOCK(mode) (((mode) & _S_IFMT) == S_IFSOCK) +#endif + +#ifndef S_ISLNK +#define S_ISLNK(mode) (((mode) & _S_IFMT) == S_IFLNK) +#endif + +static void +make_fileinfo(const char *filename, struct fileinfo *file, int flags) +{ + char buf[128]; + struct stat *st = &file->st; + + file->inode = st->st_ino; +#ifdef S_BLKSIZE + file->bsize = st->st_blocks * S_BLKSIZE / 1024; +#else + file->bsize = st->st_blocks * 512 / 1024; +#endif + + if(S_ISDIR(st->st_mode)) + file->mode[0] = 'd'; + else if(S_ISCHR(st->st_mode)) + file->mode[0] = 'c'; + else if(S_ISBLK(st->st_mode)) + file->mode[0] = 'b'; + else if(S_ISREG(st->st_mode)) + file->mode[0] = '-'; + else if(S_ISFIFO(st->st_mode)) + file->mode[0] = 'p'; + else if(S_ISLNK(st->st_mode)) + file->mode[0] = 'l'; + else if(S_ISSOCK(st->st_mode)) + file->mode[0] = 's'; +#ifdef S_ISWHT + else if(S_ISWHT(st->st_mode)) + file->mode[0] = 'w'; +#endif + else + file->mode[0] = '?'; + { + char *x[] = { "---", "--x", "-w-", "-wx", + "r--", "r-x", "rw-", "rwx" }; + strcpy(file->mode + 1, x[(st->st_mode & S_IRWXU) >> 6]); + strcpy(file->mode + 4, x[(st->st_mode & S_IRWXG) >> 3]); + strcpy(file->mode + 7, x[(st->st_mode & S_IRWXO) >> 0]); + if((st->st_mode & S_ISUID)) { + if((st->st_mode & S_IXUSR)) + file->mode[3] = 's'; + else + file->mode[3] = 'S'; + } + if((st->st_mode & S_ISGID)) { + if((st->st_mode & S_IXGRP)) + file->mode[6] = 's'; + else + file->mode[6] = 'S'; + } + if((st->st_mode & S_ISTXT)) { + if((st->st_mode & S_IXOTH)) + file->mode[9] = 't'; + else + file->mode[9] = 'T'; + } + } + file->n_link = st->st_nlink; + { + struct passwd *pwd; + pwd = getpwuid(st->st_uid); + if(pwd == NULL) + asprintf(&file->user, "%u", (unsigned)st->st_uid); + else + file->user = strdup(pwd->pw_name); + } + { + struct group *grp; + grp = getgrgid(st->st_gid); + if(grp == NULL) + asprintf(&file->group, "%u", (unsigned)st->st_gid); + else + file->group = strdup(grp->gr_name); + } + + if(S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode)) { +#if defined(major) && defined(minor) + asprintf(&file->major, "%u", (unsigned)major(st->st_rdev)); + asprintf(&file->minor, "%u", (unsigned)minor(st->st_rdev)); +#else + /* Don't want to use the DDI/DKI crap. */ + asprintf(&file->major, "%u", (unsigned)st->st_rdev); + asprintf(&file->minor, "%u", 0); +#endif + } else + asprintf(&file->size, "%lu", (unsigned long)st->st_size); + + { + time_t t = time(NULL); + struct tm *tm = localtime(&st->st_mtime); + if((t - st->st_mtime > 6*30*24*60*60) || + (st->st_mtime - t > 6*30*24*60*60)) + strftime(buf, sizeof(buf), "%b %e %Y", tm); + else + strftime(buf, sizeof(buf), "%b %e %H:%M", tm); + file->date = strdup(buf); + } + { + const char *p = strrchr(filename, '/'); + if(p) + p++; + else + p = filename; + file->filename = strdup(p); + } + if(S_ISLNK(st->st_mode)) { + int n; + n = readlink((char *)filename, buf, sizeof(buf)); + if(n >= 0) { + buf[n] = '\0'; + file->link = strdup(buf); + } else + warn("%s: readlink", filename); + } +} + +static void +print_file(FILE *out, + int flags, + struct fileinfo *f, + int max_inode, + int max_bsize, + int max_n_link, + int max_user, + int max_group, + int max_size, + int max_major, + int max_minor, + int max_date) +{ + if(f->filename == NULL) + return; + + if(flags & LS_INODE) { + sec_fprintf2(out, "%*d", max_inode, f->inode); + sec_fprintf2(out, " "); + } + if(flags & LS_SIZE) { + sec_fprintf2(out, "%*d", max_bsize, f->bsize); + sec_fprintf2(out, " "); + } + sec_fprintf2(out, "%s", f->mode); + sec_fprintf2(out, " "); + sec_fprintf2(out, "%*d", max_n_link, f->n_link); + sec_fprintf2(out, " "); + sec_fprintf2(out, "%-*s", max_user, f->user); + sec_fprintf2(out, " "); + sec_fprintf2(out, "%-*s", max_group, f->group); + sec_fprintf2(out, " "); + if(f->major != NULL && f->minor != NULL) + sec_fprintf2(out, "%*s, %*s", max_major, f->major, max_minor, f->minor); + else + sec_fprintf2(out, "%*s", max_size, f->size); + sec_fprintf2(out, " "); + sec_fprintf2(out, "%*s", max_date, f->date); + sec_fprintf2(out, " "); + sec_fprintf2(out, "%s", f->filename); + if(f->link) + sec_fprintf2(out, " -> %s", f->link); + sec_fprintf2(out, "\r\n"); +} + +static int +compare_filename(struct fileinfo *a, struct fileinfo *b) +{ + if(a->filename == NULL) + return 1; + if(b->filename == NULL) + return -1; + return strcmp(a->filename, b->filename); +} + +static int +compare_mtime(struct fileinfo *a, struct fileinfo *b) +{ + if(a->filename == NULL) + return 1; + if(b->filename == NULL) + return -1; + return a->st.st_mtime - b->st.st_mtime; +} + +static int +compare_size(struct fileinfo *a, struct fileinfo *b) +{ + if(a->filename == NULL) + return 1; + if(b->filename == NULL) + return -1; + return a->st.st_size - b->st.st_size; +} + +static void +list_dir(FILE *out, const char *directory, int flags); + +static int +log10(int num) +{ + int i = 1; + while(num > 10) { + i++; + num /= 10; + } + return i; +} + +/* + * Operate as lstat but fake up entries for AFS mount points so we don't + * have to fetch them. + */ + +static int +lstat_file (const char *file, struct stat *sb) +{ +#ifdef KRB4 + if (k_hasafs() + && strcmp(file, ".") + && strcmp(file, "..")) + { + struct ViceIoctl a_params; + char *last; + char *path_bkp; + static ino_t ino_counter = 0, ino_last = 0; + int ret; + const int maxsize = 2048; + + path_bkp = strdup (file); + if (path_bkp == NULL) + return -1; + + a_params.out = malloc (maxsize); + if (a_params.out == NULL) { + free (path_bkp); + return -1; + } + + /* If path contains more than the filename alone - split it */ + + last = strrchr (path_bkp, '/'); + if (last != NULL) { + *last = '\0'; + a_params.in = last + 1; + } else + a_params.in = (char *)file; + + a_params.in_size = strlen (a_params.in) + 1; + a_params.out_size = maxsize; + + ret = k_pioctl (last ? path_bkp : "." , + VIOC_AFS_STAT_MT_PT, &a_params, 0); + free (a_params.out); + if (ret < 0) { + free (path_bkp); + + if (errno != EINVAL) + return ret; + else + /* if we get EINVAL this is probably not a mountpoint */ + return lstat (file, sb); + } + + /* + * wow this was a mountpoint, lets cook the struct stat + * use . as a prototype + */ + + ret = lstat (path_bkp, sb); + free (path_bkp); + if (ret < 0) + return ret; + + if (ino_last == sb->st_ino) + ino_counter++; + else { + ino_last = sb->st_ino; + ino_counter = 0; + } + sb->st_ino += ino_counter; + sb->st_nlink = 3; + + return 0; + } +#endif /* KRB4 */ + return lstat (file, sb); +} + +static void +list_files(FILE *out, char **files, int n_files, int flags) +{ + struct fileinfo *fi; + int i; + + fi = calloc(n_files, sizeof(*fi)); + if (fi == NULL) { + sec_fprintf2(out, "ouf of memory\r\n"); + return; + } + for(i = 0; i < n_files; i++) { + if(lstat_file(files[i], &fi[i].st) < 0) { + sec_fprintf2(out, "%s: %s\r\n", files[i], strerror(errno)); + fi[i].filename = NULL; + } else { + if((flags & LS_DIRS) == 0 && S_ISDIR(fi[i].st.st_mode)) { + if(n_files > 1) + sec_fprintf2(out, "%s:\r\n", files[i]); + list_dir(out, files[i], flags); + } else { + make_fileinfo(files[i], &fi[i], flags); + } + } + } + switch(SORT_MODE(flags)) { + case LS_SORT_NAME: + qsort(fi, n_files, sizeof(*fi), + (int (*)(const void*, const void*))compare_filename); + break; + case LS_SORT_MTIME: + qsort(fi, n_files, sizeof(*fi), + (int (*)(const void*, const void*))compare_mtime); + break; + case LS_SORT_SIZE: + qsort(fi, n_files, sizeof(*fi), + (int (*)(const void*, const void*))compare_size); + break; + } + { + int max_inode = 0; + int max_bsize = 0; + int max_n_link = 0; + int max_user = 0; + int max_group = 0; + int max_size = 0; + int max_major = 0; + int max_minor = 0; + int max_date = 0; + for(i = 0; i < n_files; i++) { + if(fi[i].filename == NULL) + continue; + if(fi[i].inode > max_inode) + max_inode = fi[i].inode; + if(fi[i].bsize > max_bsize) + max_bsize = fi[i].bsize; + if(fi[i].n_link > max_n_link) + max_n_link = fi[i].n_link; + if(strlen(fi[i].user) > max_user) + max_user = strlen(fi[i].user); + if(strlen(fi[i].group) > max_group) + max_group = strlen(fi[i].group); + if(fi[i].major != NULL && strlen(fi[i].major) > max_major) + max_major = strlen(fi[i].major); + if(fi[i].minor != NULL && strlen(fi[i].minor) > max_minor) + max_minor = strlen(fi[i].minor); + if(fi[i].size != NULL && strlen(fi[i].size) > max_size) + max_size = strlen(fi[i].size); + if(strlen(fi[i].date) > max_date) + max_date = strlen(fi[i].date); + } + if(max_size < max_major + max_minor + 2) + max_size = max_major + max_minor + 2; + else if(max_size - max_minor - 2 > max_major) + max_major = max_size - max_minor - 2; + max_inode = log10(max_inode); + max_bsize = log10(max_bsize); + max_n_link = log10(max_n_link); + + if(flags & LS_SORT_REVERSE) + for(i = n_files - 1; i >= 0; i--) + print_file(out, + flags, + &fi[i], + max_inode, + max_bsize, + max_n_link, + max_user, + max_group, + max_size, + max_major, + max_minor, + max_date); + else + for(i = 0; i < n_files; i++) + print_file(out, + flags, + &fi[i], + max_inode, + max_bsize, + max_n_link, + max_user, + max_group, + max_size, + max_major, + max_minor, + max_date); + } +} + +static void +free_files (char **files, int n) +{ + int i; + + for (i = 0; i < n; ++i) + free (files[i]); + free (files); +} + +static void +list_dir(FILE *out, const char *directory, int flags) +{ + DIR *d = opendir(directory); + struct dirent *ent; + char **files = NULL; + int n_files = 0; + + if(d == NULL) { + sec_fprintf2(out, "%s: %s\r\n", directory, strerror(errno)); + return; + } + while((ent = readdir(d)) != NULL) { + void *tmp; + + if(ent->d_name[0] == '.') { + if (flags & LS_IGNORE_DOT) + continue; + if (ent->d_name[1] == 0) /* Ignore . */ + continue; + if (ent->d_name[1] == '.' && ent->d_name[2] == 0) /* Ignore .. */ + continue; + } + tmp = realloc(files, (n_files + 1) * sizeof(*files)); + if (tmp == NULL) { + sec_fprintf2(out, "%s: out of memory\r\n", directory); + free_files (files, n_files); + closedir (d); + return; + } + files = tmp; + asprintf(&files[n_files], "%s/%s", directory, ent->d_name); + if (files[n_files] == NULL) { + sec_fprintf2(out, "%s: out of memory\r\n", directory); + free_files (files, n_files); + closedir (d); + return; + } + ++n_files; + } + closedir(d); + list_files(out, files, n_files, flags | LS_DIRS); +} + +void +builtin_ls(FILE *out, const char *file) +{ + int flags = LS_SORT_NAME; + + if(*file == '-') { + const char *p; + for(p = file + 1; *p; p++) { + switch(*p) { + case 'a': + case 'A': + flags &= ~LS_IGNORE_DOT; + break; + case 'C': + break; + case 'd': + flags |= LS_DIRS; + break; + case 'f': + flags = (flags & ~LS_SORT_MODE); + break; + case 'i': + flags |= flags | LS_INODE; + break; + case 'l': + break; + case 't': + flags = (flags & ~LS_SORT_MODE) | LS_SORT_MTIME; + break; + case 's': + flags |= LS_SIZE; + break; + case 'S': + flags = (flags & ~LS_SORT_MODE) | LS_SORT_SIZE; + break; + case 'r': + flags |= LS_SORT_REVERSE; + break; + } + } + file = "."; + } + list_files(out, &file, 1, flags); + sec_fflush(out); +} diff --git a/crypto/kerberosIV/appl/ftp/ftpd/popen.c b/crypto/kerberosIV/appl/ftp/ftpd/popen.c index 4bd5e04..5f36813 100644 --- a/crypto/kerberosIV/appl/ftp/ftpd/popen.c +++ b/crypto/kerberosIV/appl/ftp/ftpd/popen.c @@ -37,7 +37,7 @@ #ifdef HAVE_CONFIG_H #include <config.h> -RCSID("$Id: popen.c,v 1.18 1998/06/09 19:24:24 joda Exp $"); +RCSID("$Id: popen.c,v 1.19 1999/09/16 20:38:45 assar Exp $"); #endif #include <sys/types.h> @@ -89,10 +89,10 @@ ftp_rooted(const char *path) if(!home[0]) if((pwd = k_getpwnam("ftp"))) - strcpy_truncate(home, pwd->pw_dir, sizeof(home)); + strlcpy(home, pwd->pw_dir, sizeof(home)); snprintf(newpath, sizeof(newpath), "%s/%s", home, path); if(access(newpath, X_OK)) - strcpy_truncate(newpath, path, sizeof(newpath)); + strlcpy(newpath, path, sizeof(newpath)); return newpath; } |