summaryrefslogtreecommitdiffstats
path: root/crypto/kerberosIV/appl/ftp/ftpd
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/kerberosIV/appl/ftp/ftpd')
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/Makefile.am3
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/Makefile.in6
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/extern.h16
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ftpcmd.y134
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ftpd.c873
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ftpd_locl.h16
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/gss_userok.c9
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/kauth.c25
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/logwtmp.c9
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/ls.c572
-rw-r--r--crypto/kerberosIV/appl/ftp/ftpd/popen.c6
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;
}
OpenPOWER on IntegriCloud