aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--contrib/lukemftpd/src/Makefile21
-rw-r--r--contrib/lukemftpd/src/cmds.c8
-rw-r--r--contrib/lukemftpd/src/conf.c42
-rw-r--r--contrib/lukemftpd/src/extern.h33
-rw-r--r--contrib/lukemftpd/src/ftpcmd.y43
-rw-r--r--contrib/lukemftpd/src/ftpd.8100
-rw-r--r--contrib/lukemftpd/src/ftpd.c568
-rw-r--r--contrib/lukemftpd/src/ftpd.conf.540
-rw-r--r--contrib/lukemftpd/src/logutmp.c6
-rw-r--r--contrib/lukemftpd/src/logwtmp.c39
-rw-r--r--contrib/lukemftpd/src/pathnames.h12
-rw-r--r--contrib/lukemftpd/src/popen.c10
-rw-r--r--contrib/lukemftpd/src/version.h4
13 files changed, 729 insertions, 197 deletions
diff --git a/contrib/lukemftpd/src/Makefile b/contrib/lukemftpd/src/Makefile
index 82c37d119e0b..5f92b3679c65 100644
--- a/contrib/lukemftpd/src/Makefile
+++ b/contrib/lukemftpd/src/Makefile
@@ -1,11 +1,11 @@
-# $NetBSD: Makefile,v 1.51 2003-07-23 08:01:27 itojun Exp $
+# $NetBSD: Makefile,v 1.56 2006/03/23 20:14:16 wiz Exp $
# @(#)Makefile 8.2 (Berkeley) 4/4/94
.include <bsd.own.mk>
PROG= ftpd
SRCS= cmds.c conf.c ftpd.c ftpcmd.y logutmp.c logwtmp.c popen.c
-CPPFLAGS+=-I${.CURDIR} -DSUPPORT_UTMP -DSUPPORT_UTMPX
+CPPFLAGS+=-I${.CURDIR} -DSUPPORT_UTMP -DSUPPORT_UTMPX -DLOGIN_CAP
DPADD+= ${LIBCRYPT} ${LIBUTIL}
LDADD+= -lcrypt -lutil
MAN= ftpd.conf.5 ftpusers.5 ftpd.8
@@ -15,8 +15,9 @@ MLINKS= ftpusers.5 ftpchroot.5
SRCS+= ls.c cmp.c print.c stat_flags.c util.c
.PATH: ${NETBSDSRCDIR}/bin/ls
+.if (${USE_INET6} != "no")
CPPFLAGS+=-DINET6
-.include <bsd.own.mk>
+.endif
WARNS=2
@@ -25,6 +26,11 @@ CPPFLAGS+=-DSKEY
DPADD+= ${LIBSKEY}
LDADD+= -lskey
.endif
+.if (${USE_PAM} != "no")
+CPPFLAGS+=-DUSE_PAM
+DPADD+= ${LIBPAM} ${PAM_STATIC_DPADD}
+LDADD+= -lpam ${PAM_STATIC_LDADD}
+.endif
ftpd.o ftpcmd.o: version.h
@@ -38,13 +44,8 @@ ftpd.o ftpcmd.o: version.h
#DPADD+= ${LIBKRB5} ${LIBASN1}
#LDADD+= -lkrb5 -lasn1
#
-#SRCS+= klogin.c
-#CPPFLAGS+=-DKERBEROS -I${DESTDIR}/usr/include/kerberosIV
-#DPADD+= ${LIBKRB}
-#LDADD+= -lkrb
-#
-#DPADD+= ${LIBCRYPTO} ${LIBROKEN} ${LIBCOM_ERR}
-#LDADD+= -lcrypto -lroken -lcom_err
+#DPADD+= ${LIBCRYPTO} ${{LIBCRYPT} ${LIBROKEN} ${LIBCOM_ERR}
+#LDADD+= -lcrypto -lcrypt -lroken -lcom_err
#
#.endif
diff --git a/contrib/lukemftpd/src/cmds.c b/contrib/lukemftpd/src/cmds.c
index 7c8e2afe1471..0864110d82f2 100644
--- a/contrib/lukemftpd/src/cmds.c
+++ b/contrib/lukemftpd/src/cmds.c
@@ -1,4 +1,4 @@
-/* $NetBSD: cmds.c,v 1.23 2004-08-09 12:56:47 lukem Exp $ */
+/* $NetBSD: cmds.c,v 1.24 2006/02/01 14:20:12 christos Exp $ */
/*
* Copyright (c) 1999-2004 The NetBSD Foundation, Inc.
@@ -97,7 +97,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: cmds.c,v 1.23 2004-08-09 12:56:47 lukem Exp $");
+__RCSID("$NetBSD: cmds.c,v 1.24 2006/02/01 14:20:12 christos Exp $");
#endif /* not lint */
#include <sys/param.h>
@@ -391,7 +391,7 @@ opts(const char *command)
/* default cases */
if (ep != NULL && *ep != '\0')
- REASSIGN(c->options, xstrdup(ep));
+ REASSIGN(c->options, ftpd_strdup(ep));
if (c->options != NULL)
reply(200, "Options for %s are '%s'.", c->name,
c->options);
@@ -438,7 +438,7 @@ renamefrom(const char *name)
return (NULL);
}
reply(350, "File exists, ready for destination name");
- return (xstrdup(name));
+ return (ftpd_strdup(name));
}
void
diff --git a/contrib/lukemftpd/src/conf.c b/contrib/lukemftpd/src/conf.c
index 0c142fcc9374..35953074d8f1 100644
--- a/contrib/lukemftpd/src/conf.c
+++ b/contrib/lukemftpd/src/conf.c
@@ -1,7 +1,7 @@
-/* $NetBSD: conf.c,v 1.52 2004-08-09 12:56:47 lukem Exp $ */
+/* $NetBSD: conf.c,v 1.57 2006/02/01 14:20:12 christos Exp $ */
/*-
- * Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
+ * Copyright (c) 1997-2005 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -38,7 +38,7 @@
#include <sys/cdefs.h>
#ifndef lint
-__RCSID("$NetBSD: conf.c,v 1.52 2004-08-09 12:56:47 lukem Exp $");
+__RCSID("$NetBSD: conf.c,v 1.57 2006/02/01 14:20:12 christos Exp $");
#endif /* not lint */
#include <sys/types.h>
@@ -77,7 +77,7 @@ static int filetypematch(char *, int);
#define DEFAULT_MAXFILESIZE -1 /* unlimited file size */
#define DEFAULT_MAXTIMEOUT 7200 /* 2 hours */
#define DEFAULT_TIMEOUT 900 /* 15 minutes */
-#define DEFAULT_UMASK 027 /* 15 minutes */
+#define DEFAULT_UMASK 027 /* rw-r----- */
/*
* Initialise curclass to an `empty' state
@@ -109,7 +109,7 @@ init_curclass(void)
curclass.maxrateget = 0;
curclass.maxrateput = 0;
curclass.maxtimeout = DEFAULT_MAXTIMEOUT;
- REASSIGN(curclass.motd, xstrdup(_PATH_FTPLOGINMESG));
+ REASSIGN(curclass.motd, ftpd_strdup(_NAME_FTPLOGINMESG));
REASSIGN(curclass.notify, NULL);
curclass.portmin = 0;
curclass.portmax = 0;
@@ -126,6 +126,7 @@ init_curclass(void)
CURCLASS_FLAGS_SET(checkportcmd);
CURCLASS_FLAGS_CLR(denyquick);
+ CURCLASS_FLAGS_CLR(hidesymlinks);
CURCLASS_FLAGS_SET(modify);
CURCLASS_FLAGS_SET(passive);
CURCLASS_FLAGS_CLR(private);
@@ -152,14 +153,14 @@ parse_conf(const char *findclass)
struct ftpconv *conv, *cnext;
init_curclass();
- REASSIGN(curclass.classname, xstrdup(findclass));
+ REASSIGN(curclass.classname, ftpd_strdup(findclass));
/* set more guest defaults */
if (strcasecmp(findclass, "guest") == 0) {
CURCLASS_FLAGS_CLR(modify);
curclass.umask = 0707;
}
- infile = conffilename(_PATH_FTPDCONF);
+ infile = conffilename(_NAME_FTPDCONF);
if ((f = fopen(infile, "r")) == NULL)
return;
@@ -205,7 +206,7 @@ parse_conf(const char *findclass)
if (none || EMPTYSTR(arg)) \
arg = NULL; \
else \
- arg = xstrdup(arg); \
+ arg = ftpd_strdup(arg); \
REASSIGN(curclass.Field, arg); \
} while (0)
@@ -310,16 +311,16 @@ parse_conf(const char *findclass)
convcmd = p;
if (convcmd)
convcmd += strspn(convcmd, " \t");
- suffix = xstrdup(arg);
+ suffix = ftpd_strdup(arg);
if (none || EMPTYSTR(types) ||
EMPTYSTR(disable) || EMPTYSTR(convcmd)) {
types = NULL;
disable = NULL;
convcmd = NULL;
} else {
- types = xstrdup(types);
- disable = xstrdup(disable);
- convcmd = xstrdup(convcmd);
+ types = ftpd_strdup(types);
+ disable = ftpd_strdup(disable);
+ convcmd = ftpd_strdup(convcmd);
}
for (conv = curclass.conversions; conv != NULL;
conv = conv->next) {
@@ -354,6 +355,9 @@ parse_conf(const char *findclass)
} else if (strcasecmp(word, "display") == 0) {
CONF_STRING(display);
+ } else if (strcasecmp(word, "hidesymlinks") == 0) {
+ CONF_FLAG(hidesymlinks);
+
} else if (strcasecmp(word, "homedir") == 0) {
CONF_STRING(homedir);
@@ -362,7 +366,7 @@ parse_conf(const char *findclass)
REASSIGN(curclass.limitfile, NULL);
CONF_LL(limit, arg, -1, LLTMAX);
REASSIGN(curclass.limitfile,
- EMPTYSTR(p) ? NULL : xstrdup(p));
+ EMPTYSTR(p) ? NULL : ftpd_strdup(p));
} else if (strcasecmp(word, "maxfilesize") == 0) {
curclass.maxfilesize = DEFAULT_MAXFILESIZE;
@@ -385,6 +389,10 @@ parse_conf(const char *findclass)
curclass.writesize = 0;
CONF_LL(writesize, arg, 0, LLTMAX);
+ } else if (strcasecmp(word, "recvbufsize") == 0) {
+ curclass.recvbufsize = 0;
+ CONF_LL(recvbufsize, arg, 0, LLTMAX);
+
} else if (strcasecmp(word, "sendbufsize") == 0) {
curclass.sendbufsize = 0;
CONF_LL(sendbufsize, arg, 0, LLTMAX);
@@ -464,7 +472,7 @@ parse_conf(const char *findclass)
} else if (strcasecmp(word, "template") == 0) {
if (none)
continue;
- REASSIGN(template, EMPTYSTR(arg) ? NULL : xstrdup(arg));
+ REASSIGN(template, EMPTYSTR(arg) ? NULL : ftpd_strdup(arg));
} else if (strcasecmp(word, "umask") == 0) {
u_long fumask;
@@ -547,7 +555,7 @@ show_chdir_messages(int code)
if (sl_find(slist, curwd) != NULL)
return;
- cp = xstrdup(curwd);
+ cp = ftpd_strdup(curwd);
if (sl_add(slist, cp) == -1)
syslog(LOG_WARNING, "can't add `%s' to stringlist", cp);
@@ -846,13 +854,13 @@ do_conversion(const char *fname)
/* Split up command into an argv */
if ((sl = sl_init()) == NULL)
goto cleanup_do_conv;
- cmd = xstrdup(cp->command);
+ cmd = ftpd_strdup(cp->command);
p = cmd;
while (p) {
NEXTWORD(p, lp);
if (strcmp(lp, "%s") == 0)
lp = base;
- if (sl_add(sl, xstrdup(lp)) == -1)
+ if (sl_add(sl, ftpd_strdup(lp)) == -1)
goto cleanup_do_conv;
}
diff --git a/contrib/lukemftpd/src/extern.h b/contrib/lukemftpd/src/extern.h
index 9da3da4ca018..2d0210600d29 100644
--- a/contrib/lukemftpd/src/extern.h
+++ b/contrib/lukemftpd/src/extern.h
@@ -1,4 +1,4 @@
-/* $NetBSD: extern.h,v 1.50 2004-08-09 12:56:47 lukem Exp $ */
+/* $NetBSD: extern.h,v 1.55 2006/02/01 14:20:12 christos Exp $ */
/*-
* Copyright (c) 1992, 1993
@@ -32,7 +32,7 @@
*/
/*-
- * Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
+ * Copyright (c) 1997-2005 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -174,22 +174,27 @@ void statfilecmd(const char *);
void statxfer(void);
void store(const char *, const char *, int);
void user(const char *);
-char *xstrdup(const char *);
+char *ftpd_strdup(const char *);
void yyerror(char *);
#ifdef SUPPORT_UTMP
struct utmp;
+void ftpd_initwtmp(void);
void ftpd_logwtmp(const char *, const char *, const char *);
-void ftpd_login(const struct utmp *ut);
-int ftpd_logout(const char *line);
+void ftpd_login(const struct utmp *);
+int ftpd_logout(const char *);
#endif
#ifdef SUPPORT_UTMPX
struct utmpx;
+struct sockinet;
+void ftpd_initwtmpx(void);
+void ftpd_logwtmpx(const char *, const char *, const char *,
+ struct sockinet *, int, int);
void ftpd_loginx(const struct utmpx *);
-void ftpd_logwtmpx(const char *, const char *, const char *, int, int);
+int ftpd_logoutx(const char *, int, int);
#endif
#include <netinet/in.h>
@@ -251,12 +256,15 @@ typedef enum {
typedef enum {
FLAG_checkportcmd = 1<<0, /* Check port commands */
FLAG_denyquick = 1<<1, /* Check ftpusers(5) before PASS */
- FLAG_modify = 1<<2, /* Allow CHMOD, DELE, MKD, RMD, RNFR,
+ FLAG_hidesymlinks = 1<<2, /* For symbolic links, list the file
+ or directory the link references
+ rather than the link itself */
+ FLAG_modify = 1<<3, /* Allow CHMOD, DELE, MKD, RMD, RNFR,
UMASK */
- FLAG_passive = 1<<3, /* Allow PASV mode */
- FLAG_private = 1<<4, /* Don't publish class info in STAT */
- FLAG_sanenames = 1<<5, /* Restrict names of uploaded files */
- FLAG_upload = 1<<6, /* As per modify, but also allow
+ FLAG_passive = 1<<4, /* Allow PASV mode */
+ FLAG_private = 1<<5, /* Don't publish class info in STAT */
+ FLAG_sanenames = 1<<6, /* Restrict names of uploaded files */
+ FLAG_upload = 1<<7, /* As per modify, but also allow
APPE, STOR, STOU */
} classflag_t;
@@ -290,6 +298,7 @@ struct ftpclass {
LLT mmapsize; /* mmap window size */
LLT readsize; /* data read size */
LLT writesize; /* data write size */
+ LLT recvbufsize; /* SO_RCVBUF size */
LLT sendbufsize; /* SO_SNDBUF size */
LLT sendlowat; /* SO_SNDLOWAT size */
};
@@ -309,7 +318,7 @@ GLOBAL struct sockinet his_addr;
GLOBAL struct sockinet pasv_addr;
GLOBAL int connections;
GLOBAL struct ftpclass curclass;
-GLOBAL int debug;
+GLOBAL int ftpd_debug;
GLOBAL char *emailaddr;
GLOBAL int form;
GLOBAL int gidcount; /* number of entries in gidlist[] */
diff --git a/contrib/lukemftpd/src/ftpcmd.y b/contrib/lukemftpd/src/ftpcmd.y
index 484398d678dc..804a26b2b49a 100644
--- a/contrib/lukemftpd/src/ftpcmd.y
+++ b/contrib/lukemftpd/src/ftpcmd.y
@@ -1,7 +1,7 @@
-/* $NetBSD: ftpcmd.y,v 1.80 2004-08-09 12:56:47 lukem Exp $ */
+/* $NetBSD: ftpcmd.y,v 1.84 2006/02/01 14:20:12 christos Exp $ */
/*-
- * Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
+ * Copyright (c) 1997-2005 The NetBSD Foundation, Inc.
* All rights reserved.
*
* This code is derived from software contributed to The NetBSD Foundation
@@ -79,7 +79,7 @@
#if 0
static char sccsid[] = "@(#)ftpcmd.y 8.3 (Berkeley) 4/6/94";
#else
-__RCSID("$NetBSD: ftpcmd.y,v 1.80 2004-08-09 12:56:47 lukem Exp $");
+__RCSID("$NetBSD: ftpcmd.y,v 1.84 2006/02/01 14:20:12 christos Exp $");
#endif
#endif /* not lint */
@@ -118,6 +118,14 @@ char cbuf[FTP_BUFLEN];
char *cmdp;
char *fromname;
+extern int epsvall;
+struct tab sitetab[];
+
+static int check_write(const char *, int);
+static void help(struct tab *, const char *);
+static void port_check(const char *, int);
+ int yylex(void);
+
%}
%union {
@@ -503,6 +511,8 @@ cmd
{
char *argv[] = { INTERNAL_LS, "-lgA", NULL };
+ if (CURCLASS_FLAGS_ISSET(hidesymlinks))
+ argv[1] = "-LlgA";
if ($2)
retrieve(argv, "");
}
@@ -511,6 +521,8 @@ cmd
{
char *argv[] = { INTERNAL_LS, "-lgA", NULL, NULL };
+ if (CURCLASS_FLAGS_ISSET(hidesymlinks))
+ argv[1] = "-LlgA";
if ($2 && $4 != NULL) {
argv[2] = $4;
retrieve(argv, $4);
@@ -1293,13 +1305,6 @@ struct tab sitetab[] = {
{ NULL, 0, 0, 0, NULL }
};
-static int check_write(const char *, int);
-static void help(struct tab *, const char *);
-static void port_check(const char *, int);
- int yylex(void);
-
-extern int epsvall;
-
/*
* Check if a filename is allowed to be modified (isupload == 0) or
* uploaded (isupload == 1), and if necessary, check the filename is `sane'.
@@ -1333,7 +1338,7 @@ check_write(const char *file, int isupload)
if (file[0] == '.')
goto insane_name;
for (p = file; *p; p++) {
- if (isalnum(*p) || *p == '-' || *p == '+' ||
+ if (isalnum((unsigned char)*p) || *p == '-' || *p == '+' ||
*p == ',' || *p == '.' || *p == '_')
continue;
insane_name:
@@ -1371,7 +1376,7 @@ getline(char *s, int n, FILE *iop)
*cs++ = tmpline[c];
if (tmpline[c] == '\n') {
*cs++ = '\0';
- if (debug)
+ if (ftpd_debug)
syslog(LOG_DEBUG, "command: %s", s);
tmpline[0] = '\0';
return(s);
@@ -1419,7 +1424,7 @@ getline(char *s, int n, FILE *iop)
if (c == EOF && cs == s)
return (NULL);
*cs++ = '\0';
- if (debug) {
+ if (ftpd_debug) {
if ((curclass.type != CLASS_GUEST &&
strncasecmp(s, "PASS ", 5) == 0) ||
strncasecmp(s, "ACCT ", 5) == 0) {
@@ -1571,7 +1576,7 @@ yylex(void)
*/
if (n > 1 && cmdp[cpos] == '\n') {
cmdp[cpos] = '\0';
- yylval.s = xstrdup(cp);
+ yylval.s = ftpd_strdup(cp);
cmdp[cpos] = '\n';
state = ARGS;
return (STRING);
@@ -1583,9 +1588,9 @@ yylex(void)
cpos++;
return (SP);
}
- if (isdigit(cmdp[cpos])) {
+ if (isdigit((unsigned char)cmdp[cpos])) {
cp = &cmdp[cpos];
- while (isdigit(cmdp[++cpos]))
+ while (isdigit((unsigned char)cmdp[++cpos]))
;
c = cmdp[cpos];
cmdp[cpos] = '\0';
@@ -1598,9 +1603,9 @@ yylex(void)
goto dostr1;
case ARGS:
- if (isdigit(cmdp[cpos])) {
+ if (isdigit((unsigned char)cmdp[cpos])) {
cp = &cmdp[cpos];
- while (isdigit(cmdp[++cpos]))
+ while (isdigit((unsigned char)cmdp[++cpos]))
;
c = cmdp[cpos];
cmdp[cpos] = '\0';
@@ -1610,7 +1615,7 @@ yylex(void)
return (NUMBER);
}
if (strncasecmp(&cmdp[cpos], "ALL", 3) == 0
- && !isalnum(cmdp[cpos + 3])) {
+ && !isalnum((unsigned char)cmdp[cpos + 3])) {
cpos += 3;
return (ALL);
}
diff --git a/contrib/lukemftpd/src/ftpd.8 b/contrib/lukemftpd/src/ftpd.8
index 76e7e007f709..304e49dec6ec 100644
--- a/contrib/lukemftpd/src/ftpd.8
+++ b/contrib/lukemftpd/src/ftpd.8
@@ -1,4 +1,4 @@
-.\" $NetBSD: ftpd.8,v 1.74 2003-08-07 09:46:39 agc Exp $
+.\" $NetBSD: ftpd.8,v 1.76 2005/08/07 11:13:34 wiz Exp $
.\"
.\" Copyright (c) 1997-2003 The NetBSD Foundation, Inc.
.\" All rights reserved.
@@ -63,7 +63,7 @@
.\"
.\" @(#)ftpd.8 8.2 (Berkeley) 4/19/94
.\"
-.Dd February 26, 2003
+.Dd August 4, 2005
.Dt FTPD 8
.Os
.Sh NAME
@@ -72,10 +72,10 @@
Internet File Transfer Protocol server
.Sh SYNOPSIS
.Nm
-.Op Fl dHlqQrsuUwWX
+.Op Fl 46DdHlQqrsUuWwX
.Op Fl a Ar anondir
-.Op Fl c Ar confdir
.Op Fl C Ar user
+.Op Fl c Ar confdir
.Op Fl e Ar emailaddr
.Op Fl h Ar hostname
.Op Fl L Ar xferlogfile
@@ -93,6 +93,14 @@ service specification; see
.Pp
Available options:
.Bl -tag -width Ds
+.It Fl 4
+When
+.Fl D
+is specified, bind to IPv4 addresses only.
+.It Fl 6
+When
+.Fl D
+is specified, bind to IPv6 addresses only.
.It Fl a Ar anondir
Define
.Ar anondir
@@ -104,6 +112,16 @@ This can also be specified with the
.Xr ftpd.conf 5
.Sy chroot
directive.
+.It Fl C Ar user
+Check whether
+.Ar user
+would be granted access under
+the restrictions given in
+.Xr ftpusers 5
+and exit without attempting a connection.
+.Nm
+exits with an exit code of 0 if access would be granted, or 1 otherwise.
+This can be useful for testing configurations.
.It Fl c Ar confdir
Change the root directory of the configuration files from
.Dq Pa /etc
@@ -118,16 +136,16 @@ and the file specified by the
.Xr ftpd.conf 5
.Sy limit
directive.
-.It Fl C Ar user
-Check whether
-.Ar user
-would be granted access under
-the restrictions given in
-.Xr ftpusers 5
-and exit without attempting a connection.
+.It Fl D
+Run as daemon.
.Nm
-exits with an exit code of 0 if access would be granted, or 1 otherwise.
-This can be useful for testing configurations.
+will listen on the default FTP port for incoming connections
+and fork a child for each connection.
+This is lower overhead than starting
+.Nm
+from
+.Xr inetd 8
+and thus might be useful on busy servers to reduce load.
.It Fl d
Debugging information is written to the syslog using a facility of
.Dv LOG_FTP .
@@ -138,6 +156,12 @@ for the
.Dq "\&%E"
escape sequence (see
.Sx Display file escape sequences )
+.It Fl H
+Equivalent to
+.Do
+-h
+`hostname`
+.Dc .
.It Fl h Ar hostname
Explicitly set the hostname to advertise as to
.Ar hostname .
@@ -155,12 +179,13 @@ servers, each listening on separate addresses as separate names.
Refer to
.Xr inetd.conf 5
for more information on starting services to listen on specific IP addresses.
-.It Fl H
-Equivalent to
-.Do
--h
-`hostname`
-.Dc .
+.It Fl L Ar xferlogfile
+Log
+.Tn wu-ftpd
+style
+.Sq xferlog
+entries to
+.Ar xferlogfile .
.It Fl l
Each successful and failed
.Tn FTP
@@ -169,13 +194,6 @@ session is logged using syslog with a facility of
If this option is specified more than once, the retrieve (get), store (put),
append, delete, make directory, remove directory and rename operations and
their file name arguments are also logged.
-.It Fl L Ar xferlogfile
-Log
-.Tn wu-ftpd
-style
-.Sq xferlog
-entries to
-.Ar xferlogfile .
.It Fl P Ar dataport
Use
.Ar dataport
@@ -183,16 +201,16 @@ as the data port, overriding the default of using the port one less
that the port
.Nm
is listening on.
-.It Fl q
-Enable the use of pid files for keeping track of the number of logged-in
-users per class.
-This is the default.
.It Fl Q
Disable the use of pid files for keeping track of the number of logged-in
users per class.
This may reduce the load on heavily loaded
.Tn FTP
servers.
+.It Fl q
+Enable the use of pid files for keeping track of the number of logged-in
+users per class.
+This is the default.
.It Fl r
Permanently drop root privileges once the user is logged in.
The use of this option may result in the server using a port other
@@ -206,6 +224,12 @@ See
below for more details.
.It Fl s
Require a secure authentication mechanism like Kerberos or S/Key to be used.
+.It Fl U
+Don't log each concurrent
+.Tn FTP
+session to
+.Pa /var/run/utmp .
+This is the default.
.It Fl u
Log each concurrent
.Tn FTP
@@ -213,12 +237,6 @@ session to
.Pa /var/run/utmp ,
making them visible to commands such as
.Xr who 1 .
-.It Fl U
-Don't log each concurrent
-.Tn FTP
-session to
-.Pa /var/run/utmp .
-This is the default.
.It Fl V Ar version
Use
.Ar version
@@ -232,6 +250,11 @@ If
is empty or
.Sq -
then don't display any version information.
+.It Fl W
+Don't log each
+.Tn FTP
+session to
+.Pa /var/log/wtmp .
.It Fl w
Log each
.Tn FTP
@@ -240,11 +263,6 @@ session to
making them visible to commands such as
.Xr last 1 .
This is the default.
-.It Fl W
-Don't log each
-.Tn FTP
-session to
-.Pa /var/log/wtmp .
.It Fl X
Log
.Tn wu-ftpd
diff --git a/contrib/lukemftpd/src/ftpd.c b/contrib/lukemftpd/src/ftpd.c
index db89e873ede3..e3b283522945 100644
--- a/contrib/lukemftpd/src/ftpd.c
+++ b/contrib/lukemftpd/src/ftpd.c
@@ -1,4 +1,4 @@
-/* $NetBSD: ftpd.c,v 1.158 2004-08-09 12:56:47 lukem Exp $ */
+/* $NetBSD: ftpd.c,v 1.176 2006/05/09 20:18:06 mrg Exp $ */
/*
* Copyright (c) 1997-2004 The NetBSD Foundation, Inc.
@@ -105,7 +105,7 @@ __COPYRIGHT(
#if 0
static char sccsid[] = "@(#)ftpd.c 8.5 (Berkeley) 4/28/95";
#else
-__RCSID("$NetBSD: ftpd.c,v 1.158 2004-08-09 12:56:47 lukem Exp $");
+__RCSID("$NetBSD: ftpd.c,v 1.176 2006/05/09 20:18:06 mrg Exp $");
#endif
#endif /* not lint */
@@ -140,6 +140,7 @@ __RCSID("$NetBSD: ftpd.c,v 1.158 2004-08-09 12:56:47 lukem Exp $");
#include <limits.h>
#include <netdb.h>
#include <pwd.h>
+#include <poll.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
@@ -164,6 +165,14 @@ __RCSID("$NetBSD: ftpd.c,v 1.158 2004-08-09 12:56:47 lukem Exp $");
#include <krb5/krb5.h>
#endif
+#ifdef LOGIN_CAP
+#include <login_cap.h>
+#endif
+
+#ifdef USE_PAM
+#include <security/pam_appl.h>
+#endif
+
#define GLOBAL
#include "extern.h"
#include "pathnames.h"
@@ -173,6 +182,7 @@ volatile sig_atomic_t transflag;
volatile sig_atomic_t urgflag;
int data;
+int Dflag;
int sflag;
int stru; /* avoid C keyword */
int mode;
@@ -187,6 +197,12 @@ int mapped; /* IPv4 connection on AF_INET6 socket */
off_t file_size;
off_t byte_count;
static char ttyline[20];
+
+#ifdef USE_PAM
+static int auth_pam(struct passwd **, const char *);
+pam_handle_t *pamh = NULL;
+#endif
+
#ifdef SUPPORT_UTMP
static struct utmp utmp; /* for utmp */
#endif
@@ -236,7 +252,8 @@ static int checkpassword(const struct passwd *, const char *);
static void end_login(void);
static FILE *getdatasock(const char *);
static char *gunique(const char *);
-static void login_utmp(const char *, const char *, const char *);
+static void login_utmp(const char *, const char *, const char *,
+ struct sockinet *);
static void logremotehost(struct sockinet *);
static void lostconn(int);
static void toolong(int);
@@ -269,7 +286,8 @@ void k5destroy(void);
int
main(int argc, char *argv[])
{
- int addrlen, ch, on = 1, tos, keepalive;
+ int ch, on = 1, tos, keepalive;
+ socklen_t addrlen;
#ifdef KERBEROS5
krb5_error_code kerror;
#endif
@@ -277,11 +295,13 @@ main(int argc, char *argv[])
const char *xferlogname = NULL;
long l;
struct sigaction sa;
+ sa_family_t af = AF_UNSPEC;
connections = 1;
- debug = 0;
+ ftpd_debug = 0;
logging = 0;
pdata = -1;
+ Dflag = 0;
sflag = 0;
dataport = 0;
dopidfile = 1; /* default: DO use a pid file to count users */
@@ -305,9 +325,17 @@ main(int argc, char *argv[])
*/
openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
- while ((ch = getopt(argc, argv, "a:c:C:de:h:HlL:P:qQrst:T:uUvV:wWX"))
- != -1) {
+ while ((ch = getopt(argc, argv,
+ "46a:c:C:Dde:h:HlL:P:qQrst:T:uUvV:wWX")) != -1) {
switch (ch) {
+ case '4':
+ af = AF_INET;
+ break;
+
+ case '6':
+ af = AF_INET6;
+ break;
+
case 'a':
anondir = optarg;
break;
@@ -321,9 +349,13 @@ main(int argc, char *argv[])
exit(checkaccess(optarg) ? 0 : 1);
/* NOTREACHED */
+ case 'D':
+ Dflag = 1;
+ break;
+
case 'd':
case 'v': /* deprecated */
- debug = 1;
+ ftpd_debug = 1;
break;
case 'e':
@@ -397,7 +429,7 @@ main(int argc, char *argv[])
if (EMPTYSTR(optarg) || strcmp(optarg, "-") == 0)
version = NULL;
else
- version = xstrdup(optarg);
+ version = ftpd_strdup(optarg);
break;
case 'w':
@@ -422,6 +454,14 @@ main(int argc, char *argv[])
if (EMPTYSTR(confdir))
confdir = _DEFAULT_CONFDIR;
+ if (dowtmp) {
+#ifdef SUPPORT_UTMPX
+ ftpd_initwtmpx();
+#endif
+#ifdef SUPPORT_UTMP
+ ftpd_initwtmp();
+#endif
+ }
errno = 0;
l = sysconf(_SC_LOGIN_NAME_MAX);
if (l == -1 && errno != 0) {
@@ -439,6 +479,108 @@ main(int argc, char *argv[])
}
curname[0] = '\0';
+ if (Dflag) {
+ int error, fd, i, n, *socks;
+ struct pollfd *fds;
+ struct addrinfo hints, *res, *res0;
+
+ if (daemon(1, 0) == -1) {
+ syslog(LOG_ERR, "failed to daemonize: %m");
+ exit(1);
+ }
+ (void)memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = SA_NOCLDWAIT;
+ sigemptyset(&sa.sa_mask);
+ (void)sigaction(SIGCHLD, &sa, NULL);
+
+ (void)memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_PASSIVE;
+ hints.ai_family = af;
+ hints.ai_socktype = SOCK_STREAM;
+ error = getaddrinfo(NULL, "ftp", &hints, &res0);
+ if (error) {
+ syslog(LOG_ERR, "getaddrinfo: %s", gai_strerror(error));
+ exit(1);
+ }
+
+ for (n = 0, res = res0; res != NULL; res = res->ai_next)
+ n++;
+ if (n == 0) {
+ syslog(LOG_ERR, "no addresses available");
+ exit(1);
+ }
+ socks = malloc(n * sizeof(int));
+ fds = malloc(n * sizeof(struct pollfd));
+ if (socks == NULL || fds == NULL) {
+ syslog(LOG_ERR, "malloc: %m");
+ exit(1);
+ }
+
+ for (n = 0, res = res0; res != NULL; res = res->ai_next) {
+ socks[n] = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (socks[n] == -1)
+ continue;
+ (void)setsockopt(socks[n], SOL_SOCKET, SO_REUSEADDR,
+ &on, sizeof(on));
+ if (bind(socks[n], res->ai_addr, res->ai_addrlen)
+ == -1) {
+ (void)close(socks[n]);
+ continue;
+ }
+ if (listen(socks[n], 12) == -1) {
+ (void)close(socks[n]);
+ continue;
+ }
+
+ fds[n].fd = socks[n];
+ fds[n].events = POLLIN;
+ n++;
+ }
+ if (n == 0) {
+ syslog(LOG_ERR, "%m");
+ exit(1);
+ }
+ freeaddrinfo(res0);
+
+ if (pidfile(NULL) == -1)
+ syslog(LOG_ERR, "failed to write a pid file: %m");
+
+ for (;;) {
+ if (poll(fds, n, INFTIM) == -1) {
+ if (errno == EINTR)
+ continue;
+ syslog(LOG_ERR, "poll: %m");
+ exit(1);
+ }
+ for (i = 0; i < n; i++) {
+ if (fds[i].revents & POLLIN) {
+ fd = accept(fds[i].fd, NULL, NULL);
+ if (fd == -1) {
+ syslog(LOG_ERR, "accept: %m");
+ continue;
+ }
+ switch (fork()) {
+ case -1:
+ syslog(LOG_ERR, "fork: %m");
+ break;
+ case 0:
+ goto child;
+ /* NOTREACHED */
+ }
+ (void)close(fd);
+ }
+ }
+ }
+ child:
+ (void)dup2(fd, STDIN_FILENO);
+ (void)dup2(fd, STDOUT_FILENO);
+ (void)dup2(fd, STDERR_FILENO);
+ for (i = 0; i < n; i++)
+ (void)close(socks[i]);
+ }
+
memset((char *)&his_addr, 0, sizeof(his_addr));
addrlen = sizeof(his_addr.si_su);
if (getpeername(0, (struct sockaddr *)&his_addr.si_su, &addrlen) < 0) {
@@ -587,7 +729,7 @@ main(int argc, char *argv[])
reply(530, "System not available.");
exit(0);
}
- (void)display_file(conffilename(_PATH_FTPWELCOME), 220);
+ (void)display_file(conffilename(_NAME_FTPWELCOME), 220);
/* reply(220,) must follow */
if (EMPTYSTR(version))
reply(220, "%s FTP server ready.", hostname);
@@ -612,7 +754,7 @@ static void
lostconn(int signo)
{
- if (debug)
+ if (ftpd_debug)
syslog(LOG_DEBUG, "lost connection");
dologout(1);
}
@@ -635,7 +777,7 @@ static void
sigquit(int signo)
{
- if (debug)
+ if (ftpd_debug)
syslog(LOG_DEBUG, "got signal %d", signo);
dologout(1);
}
@@ -670,11 +812,11 @@ sgetpwnam(const char *name)
free((char *)save.pw_shell);
}
save = *p;
- save.pw_name = xstrdup(p->pw_name);
- save.pw_passwd = xstrdup(p->pw_passwd);
- save.pw_gecos = xstrdup(p->pw_gecos);
- save.pw_dir = xstrdup(p->pw_dir);
- save.pw_shell = xstrdup(p->pw_shell);
+ save.pw_name = ftpd_strdup(p->pw_name);
+ save.pw_passwd = ftpd_strdup(p->pw_passwd);
+ save.pw_gecos = ftpd_strdup(p->pw_gecos);
+ save.pw_dir = ftpd_strdup(p->pw_dir);
+ save.pw_shell = ftpd_strdup(p->pw_shell);
return (&save);
}
@@ -687,16 +829,19 @@ static int permitted; /* USER permitted */
* Sets global passwd pointer pw if named account exists and is acceptable;
* sets askpasswd if a PASS command is expected. If logged in previously,
* need to reset state. If name is "ftp" or "anonymous", the name is not in
- * _PATH_FTPUSERS, and ftp account exists, set guest and pw, then just return.
+ * _NAME_FTPUSERS, and ftp account exists, set guest and pw, then just return.
* If account doesn't exist, ask for passwd anyway. Otherwise, check user
* requesting login privileges. Disallow anyone who does not have a standard
* shell as returned by getusershell(). Disallow anyone mentioned in the file
- * _PATH_FTPUSERS to allow people such as root and uucp to be avoided.
+ * _NAME_FTPUSERS to allow people such as root and uucp to be avoided.
*/
void
user(const char *name)
{
char *class;
+#ifdef LOGIN_CAP
+ login_cap_t *lc = NULL;
+#endif
class = NULL;
if (logged_in) {
@@ -757,14 +902,19 @@ user(const char *name)
strlcpy(curname, name, curname_len);
/* check user in /etc/ftpusers, and setup class */
- permitted = checkuser(_PATH_FTPUSERS, curname, 1, 0, &class);
+ permitted = checkuser(_NAME_FTPUSERS, curname, 1, 0, &class);
/* check user in /etc/ftpchroot */
- if (checkuser(_PATH_FTPCHROOT, curname, 0, 0, NULL)) {
+ lc = login_getpwclass(pw);
+ if (checkuser(_NAME_FTPCHROOT, curname, 0, 0, NULL)
+#ifdef LOGIN_CAP /* Allow login.conf configuration as well */
+ || login_getcapbool(lc, "ftp-chroot", 0)
+#endif
+ ) {
if (curclass.type == CLASS_GUEST) {
syslog(LOG_NOTICE,
"Can't change guest user to chroot class; remove entry in %s",
- _PATH_FTPCHROOT);
+ _NAME_FTPCHROOT);
exit(1);
}
curclass.type = CLASS_CHROOT;
@@ -773,13 +923,13 @@ user(const char *name)
if (class == NULL) {
switch (curclass.type) {
case CLASS_GUEST:
- class = xstrdup("guest");
+ class = ftpd_strdup("guest");
break;
case CLASS_CHROOT:
- class = xstrdup("chroot");
+ class = ftpd_strdup("chroot");
break;
case CLASS_REAL:
- class = xstrdup("real");
+ class = ftpd_strdup("real");
break;
default:
syslog(LOG_ERR, "unknown curclass.type %d; aborting",
@@ -832,6 +982,9 @@ user(const char *name)
}
cleanup_user:
+#ifdef LOGIN_CAP
+ login_close(lc);
+#endif
/*
* Delay before reading passwd after first failed
* attempt to slow down passwd-guessing programs.
@@ -916,7 +1069,7 @@ checkuser(const char *fname, const char *name, int def, int nofile,
*p++ = '\0';
/* check against network or CIDR */
- if (isdigit(*p) &&
+ if (isdigit((unsigned char)*p) &&
(bits = inet_net_pton(AF_INET, p,
&net, sizeof(net))) != -1) {
net = ntohl(net);
@@ -979,7 +1132,7 @@ checkuser(const char *fname, const char *name, int def, int nofile,
else
retval = !def;
if (!EMPTYSTR(class) && retclass != NULL)
- *retclass = xstrdup(class);
+ *retclass = ftpd_strdup(class);
free(buf);
break;
}
@@ -997,11 +1150,12 @@ static int
checkaccess(const char *name)
{
- return (checkuser(_PATH_FTPUSERS, name, 1, 0, NULL));
+ return (checkuser(_NAME_FTPUSERS, name, 1, 0, NULL));
}
static void
-login_utmp(const char *line, const char *name, const char *host)
+login_utmp(const char *line, const char *name, const char *host,
+ struct sockinet *haddr)
{
#if defined(SUPPORT_UTMPX) || defined(SUPPORT_UTMP)
struct timeval tv;
@@ -1020,10 +1174,11 @@ login_utmp(const char *line, const char *name, const char *host)
(void)strncpy(utmpx.ut_name, name, sizeof(utmpx.ut_name));
(void)strncpy(utmpx.ut_line, line, sizeof(utmpx.ut_line));
(void)strncpy(utmpx.ut_host, host, sizeof(utmpx.ut_host));
+ (void)memcpy(&utmpx.ut_ss, &haddr->si_su, haddr->su_len);
ftpd_loginx(&utmpx);
}
if (dowtmp)
- ftpd_logwtmpx(line, name, host, 0, USER_PROCESS);
+ ftpd_logwtmpx(line, name, host, haddr, 0, USER_PROCESS);
#endif
#ifdef SUPPORT_UTMP
if (doutmp) {
@@ -1042,24 +1197,25 @@ login_utmp(const char *line, const char *name, const char *host)
static void
logout_utmp(void)
{
- int okwtmp = dowtmp;
- if (logged_in) {
- if (doutmp) {
#ifdef SUPPORT_UTMPX
- okwtmp = logoutx(ttyline, 0, DEAD_PROCESS) & dowtmp;
+ int okwtmpx = dowtmp;
#endif
#ifdef SUPPORT_UTMP
- okwtmp = ftpd_logout(ttyline) & dowtmp;
+ int okwtmp = dowtmp;
#endif
- }
- if (okwtmp) {
+ if (logged_in) {
#ifdef SUPPORT_UTMPX
- ftpd_logwtmpx(ttyline, "", "", 0, DEAD_PROCESS);
+ if (doutmp)
+ okwtmpx &= ftpd_logoutx(ttyline, 0, DEAD_PROCESS);
+ if (okwtmpx)
+ ftpd_logwtmpx(ttyline, "", "", NULL, 0, DEAD_PROCESS);
#endif
#ifdef SUPPORT_UTMP
+ if (doutmp)
+ okwtmp &= ftpd_logout(ttyline);
+ if (okwtmp)
ftpd_logwtmp(ttyline, "", "");
#endif
- }
}
}
@@ -1070,6 +1226,9 @@ logout_utmp(void)
static void
end_login(void)
{
+#ifdef USE_PAM
+ int e;
+#endif
logout_utmp();
show_chdir_messages(-1); /* flush chdir cache */
if (pw != NULL && pw->pw_passwd != NULL)
@@ -1082,6 +1241,23 @@ end_login(void)
gidcount = 0;
curclass.type = CLASS_REAL;
(void) seteuid((uid_t)0);
+#ifdef LOGIN_CAP
+ setusercontext(NULL, getpwuid(0), 0,
+ LOGIN_SETPRIORITY|LOGIN_SETRESOURCES|LOGIN_SETUMASK);
+#endif
+#ifdef USE_PAM
+ if (pamh) {
+ if ((e = pam_setcred(pamh, PAM_DELETE_CRED)) != PAM_SUCCESS)
+ syslog(LOG_ERR, "pam_setcred: %s",
+ pam_strerror(pamh, e));
+ if ((e = pam_close_session(pamh,0)) != PAM_SUCCESS)
+ syslog(LOG_ERR, "pam_close_session: %s",
+ pam_strerror(pamh, e));
+ if ((e = pam_end(pamh, e)) != PAM_SUCCESS)
+ syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
+ pamh = NULL;
+ }
+#endif
}
void
@@ -1089,7 +1265,12 @@ pass(const char *passwd)
{
int rval;
char root[MAXPATHLEN];
-
+#ifdef LOGIN_CAP
+ login_cap_t *lc = NULL;
+#endif
+#ifdef USE_PAM
+ int e;
+#endif
if (logged_in || askpasswd == 0) {
reply(503, "Login with USER first.");
return;
@@ -1101,6 +1282,18 @@ pass(const char *passwd)
rval = 1; /* failure below */
goto skip;
}
+#ifdef USE_PAM
+ rval = auth_pam(&pw, passwd);
+#ifdef notdef
+ /* If PAM fails, we proceed with other authentications */
+ if (rval >= 0) {
+ goto skip;
+ }
+#else
+ /* If PAM fails, that's it */
+ goto skip;
+#endif
+#endif
#if defined(KERBEROS)
if (klogin(pw, "", hostname, (char *)passwd) == 0) {
rval = 0;
@@ -1118,7 +1311,7 @@ pass(const char *passwd)
char *p;
int r;
- p = xstrdup(passwd);
+ p = ftpd_strdup(passwd);
r = skey_passcheck(pw->pw_name, p);
free(p);
if (r != -1) {
@@ -1174,8 +1367,51 @@ pass(const char *passwd)
reply(550, "Can't set gid.");
goto bad;
}
+#ifdef LOGIN_CAP
+ if ((lc = login_getpwclass(pw)) != NULL) {
+#ifdef notyet
+ char remote_ip[NI_MAXHOST];
+
+ if (getnameinfo((struct sockaddr *)&his_addr, his_addr.su_len,
+ remote_ip, sizeof(remote_ip) - 1, NULL, 0,
+ NI_NUMERICHOST))
+ *remote_ip = 0;
+ remote_ip[sizeof(remote_ip) - 1] = 0;
+ if (!auth_hostok(lc, remotehost, remote_ip)) {
+ syslog(LOG_INFO|LOG_AUTH,
+ "FTP LOGIN FAILED (HOST) as %s: permission denied.",
+ pw->pw_name);
+ reply(530, "Permission denied.");
+ pw = NULL;
+ return;
+ }
+ if (!auth_timeok(lc, time(NULL))) {
+ reply(530, "Login not available right now.");
+ pw = NULL;
+ return;
+ }
+#endif
+ }
+ setsid();
+ setusercontext(lc, pw, 0,
+ LOGIN_SETLOGIN|LOGIN_SETGROUP|LOGIN_SETPRIORITY|
+ LOGIN_SETRESOURCES|LOGIN_SETUMASK);
+#else
(void) initgroups(pw->pw_name, pw->pw_gid);
/* cache groups for cmds.c::matchgroup() */
+#endif
+#ifdef USE_PAM
+ if (pamh) {
+ if ((e = pam_open_session(pamh, 0)) != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_open_session: %s",
+ pam_strerror(pamh, e));
+ } else if ((e = pam_setcred(pamh, PAM_ESTABLISH_CRED))
+ != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_setcred: %s",
+ pam_strerror(pamh, e));
+ }
+ }
+#endif
gidcount = getgroups(0, NULL);
if (gidlist)
free(gidlist);
@@ -1183,7 +1419,7 @@ pass(const char *passwd)
gidcount = getgroups(gidcount, gidlist);
/* open utmp/wtmp before chroot */
- login_utmp(ttyline, pw->pw_name, remotehost);
+ login_utmp(ttyline, pw->pw_name, remotehost, &his_addr);
logged_in = 1;
@@ -1262,7 +1498,7 @@ pass(const char *passwd)
}
break;
case CLASS_REAL:
- /* only chroot REAL if explictly requested */
+ /* only chroot REAL if explicitly requested */
if (! EMPTYSTR(curclass.chroot)) {
format_path(root, curclass.chroot);
if (EMPTYSTR(root) || chroot(root) < 0) {
@@ -1294,8 +1530,10 @@ pass(const char *passwd)
}
break;
}
+#ifndef LOGIN_CAP
setsid();
setlogin(pw->pw_name);
+#endif
if (dropprivs ||
(curclass.type != CLASS_REAL &&
ntohs(ctrl_addr.su_port) > IPPORT_RESERVED + 1)) {
@@ -1341,9 +1579,9 @@ pass(const char *passwd)
remotehost, passwd,
curclass.classname, CURCLASSTYPE);
/* store guest password reply into pw_passwd */
- REASSIGN(pw->pw_passwd, xstrdup(passwd));
+ REASSIGN(pw->pw_passwd, ftpd_strdup(passwd));
for (p = pw->pw_passwd; *p; p++)
- if (!isgraph(*p))
+ if (!isgraph((unsigned char)*p))
*p = '_';
} else {
reply(230, "User %s logged in.", pw->pw_name);
@@ -1359,9 +1597,15 @@ pass(const char *passwd)
curclass.classname, CURCLASSTYPE);
}
(void) umask(curclass.umask);
+#ifdef LOGIN_CAP
+ login_close(lc);
+#endif
return;
bad:
+#ifdef LOGIN_CAP
+ login_close(lc);
+#endif
/* Forget all about it... */
end_login();
}
@@ -1672,7 +1916,8 @@ dataconn(const char *name, off_t size, const char *fmode)
sizebuf[0] = '\0';
if (pdata >= 0) {
struct sockinet from;
- int s, fromlen = sizeof(from.su_len);
+ int s;
+ socklen_t fromlen = sizeof(from.su_len);
(void) alarm(curclass.timeout);
s = accept(pdata, (struct sockaddr *)&from.si_su, &fromlen);
@@ -1737,6 +1982,7 @@ dataconn(const char *name, off_t size, const char *fmode)
break;
conerrno = errno;
(void) fclose(file);
+ file = NULL;
data = -1;
if (conerrno == EADDRINUSE) {
sleep((unsigned) swaitint);
@@ -1882,7 +2128,7 @@ send_data_with_mmap(int filefd, int netfd, const struct stat *st, int isdata)
winsize = curclass.mmapsize;
filesize = st->st_size;
- if (debug)
+ if (ftpd_debug)
syslog(LOG_INFO, "mmapsize = %ld, writesize = %ld",
(long)winsize, (long)curclass.writesize);
if (winsize == 0)
@@ -2040,8 +2286,10 @@ receive_data(FILE *instr, FILE *outstr)
{
int c, bare_lfs, netfd, filefd, rval;
off_t byteswritten;
- char buf[BUFSIZ];
+ char *buf;
+ size_t readsize;
struct sigaction sa, sa_saved;
+ struct stat st;
#ifdef __GNUC__
(void) &bare_lfs;
#endif
@@ -2057,6 +2305,7 @@ receive_data(FILE *instr, FILE *outstr)
transflag = 1;
rval = -1;
byteswritten = 0;
+ buf = NULL;
#define FILESIZECHECK(x) \
do { \
@@ -2074,6 +2323,16 @@ receive_data(FILE *instr, FILE *outstr)
netfd = fileno(instr);
filefd = fileno(outstr);
(void) alarm(curclass.timeout);
+ if (curclass.readsize)
+ readsize = curclass.readsize;
+ else if (fstat(filefd, &st))
+ readsize = (size_t)st.st_blksize;
+ else
+ readsize = BUFSIZ;
+ if ((buf = malloc(readsize)) == NULL) {
+ perror_reply(451, "Local resource failure: malloc");
+ goto cleanup_recv_data;
+ }
if (curclass.rateput) {
while (1) {
int d;
@@ -2084,7 +2343,7 @@ receive_data(FILE *instr, FILE *outstr)
errno = c = d = 0;
for (bufrem = curclass.rateput; bufrem > 0; ) {
if ((c = read(netfd, buf,
- MIN(sizeof(buf), bufrem))) <= 0)
+ MIN(readsize, bufrem))) <= 0)
goto recvdone;
if (urgflag && handleoobcmd())
goto cleanup_recv_data;
@@ -2105,7 +2364,7 @@ receive_data(FILE *instr, FILE *outstr)
usleep(1000000 - td.tv_usec);
}
} else {
- while ((c = read(netfd, buf, sizeof(buf))) > 0) {
+ while ((c = read(netfd, buf, readsize)) > 0) {
if (urgflag && handleoobcmd())
goto cleanup_recv_data;
FILESIZECHECK(byte_count + c);
@@ -2201,6 +2460,8 @@ receive_data(FILE *instr, FILE *outstr)
cleanup_recv_data:
(void) alarm(0);
(void) sigaction(SIGALRM, &sa_saved, NULL);
+ if (buf)
+ free(buf);
transflag = 0;
urgflag = 0;
total_files_in++;
@@ -2267,11 +2528,12 @@ statcmd(void)
ispassive = 1;
goto printaddr;
} else if (usedefault == 0) {
+ su = (struct sockinet *)&data_dest;
+
if (epsvall) {
reply(0, "EPSV only mode (EPSV ALL)");
goto epsvonly;
}
- su = (struct sockinet *)&data_dest;
printaddr:
/* PASV/PORT */
if (su->su_family == AF_INET) {
@@ -2448,6 +2710,11 @@ statcmd(void)
reply(0, "Write size: " LLF, (LLT)curclass.writesize);
else
reply(0, "Write size: default");
+ if (curclass.recvbufsize)
+ reply(0, "Receive buffer size: " LLF,
+ (LLT)curclass.recvbufsize);
+ else
+ reply(0, "Receive buffer size: default");
if (curclass.sendbufsize)
reply(0, "Send buffer size: " LLF,
(LLT)curclass.sendbufsize);
@@ -2508,7 +2775,7 @@ reply(int n, const char *fmt, ...)
va_end(ap);
cprintf(stdout, "%s\r\n", msg);
(void)fflush(stdout);
- if (debug)
+ if (ftpd_debug)
syslog(LOG_DEBUG, "<--- %s", msg);
}
@@ -2667,7 +2934,7 @@ bind_pasv_addr(void)
void
passive(void)
{
- int len;
+ socklen_t len, recvbufsize;
char *p, *a;
if (pdata >= 0)
@@ -2685,6 +2952,13 @@ passive(void)
if (getsockname(pdata, (struct sockaddr *) &pasv_addr.si_su, &len) < 0)
goto pasv_error;
pasv_addr.su_len = len;
+ if (curclass.recvbufsize) {
+ recvbufsize = curclass.recvbufsize;
+ if (setsockopt(pdata, SOL_SOCKET, SO_RCVBUF, &recvbufsize,
+ sizeof(int)) == -1)
+ syslog(LOG_WARNING, "setsockopt(SO_RCVBUF, %d): %m",
+ recvbufsize);
+ }
if (listen(pdata, 1) < 0)
goto pasv_error;
if (curclass.advertise.su_len != 0)
@@ -2780,7 +3054,7 @@ af2epsvproto(int af)
void
long_passive(char *cmd, int pf)
{
- int len;
+ socklen_t len;
char *p, *a;
if (!logged_in) {
@@ -2884,7 +3158,7 @@ extended_port(const char *arg)
int i;
unsigned long proto;
- tmp = xstrdup(arg);
+ tmp = ftpd_strdup(arg);
p = tmp;
delim = p[0];
p++;
@@ -2952,8 +3226,6 @@ extended_port(const char *arg)
usedefault = 1;
if (tmp != NULL)
free(tmp);
- if (res)
- freeaddrinfo(res);
return -1;
}
@@ -3055,16 +3327,16 @@ send_file_list(const char *whichf)
memset(&gl, 0, sizeof(gl));
freeglob = 1;
if (glob(whichf, flags, 0, &gl)) {
- reply(550, "not found");
+ reply(450, "Not found");
goto cleanup_send_file_list;
} else if (gl.gl_pathc == 0) {
errno = ENOENT;
- perror_reply(550, whichf);
+ perror_reply(450, whichf);
goto cleanup_send_file_list;
}
dirlist = gl.gl_pathv;
} else {
- notglob = xstrdup(whichf);
+ notglob = ftpd_strdup(whichf);
onefile[0] = notglob;
dirlist = onefile;
simple = 1;
@@ -3088,7 +3360,7 @@ send_file_list(const char *whichf)
retrieve(argv, dirname);
goto cleanup_send_file_list;
}
- perror_reply(550, whichf);
+ perror_reply(450, whichf);
goto cleanup_send_file_list;
}
@@ -3158,9 +3430,9 @@ send_file_list(const char *whichf)
}
if (dout == NULL)
- reply(550, "No files found.");
+ reply(450, "No files found.");
else if (ferror(dout) != 0)
- perror_reply(550, "Data connection");
+ perror_reply(451, "Data connection");
else
reply(226, "Transfer complete.");
@@ -3204,7 +3476,8 @@ void
logxfer(const char *command, off_t bytes, const char *file1, const char *file2,
const struct timeval *elapsed, const char *error)
{
- char buf[MAXPATHLEN * 2 + 100], realfile[MAXPATHLEN];
+ char buf[MAXPATHLEN * 2 + 100];
+ char realfile1[MAXPATHLEN], realfile2[MAXPATHLEN];
const char *r1, *r2;
char direction;
size_t len;
@@ -3214,10 +3487,10 @@ logxfer(const char *command, off_t bytes, const char *file1, const char *file2,
return;
r1 = r2 = NULL;
- if ((r1 = realpath(file1, realfile)) == NULL)
+ if ((r1 = realpath(file1, realfile1)) == NULL)
r1 = file1;
if (file2 != NULL)
- if ((r2 = realpath(file2, realfile)) == NULL)
+ if ((r2 = realpath(file2, realfile2)) == NULL)
r2 = file2;
/*
@@ -3321,14 +3594,16 @@ int
checkpassword(const struct passwd *pwent, const char *password)
{
char *orig, *new;
- time_t expire;
+ time_t change, expire, now;
- expire = 0;
+ change = expire = 0;
if (pwent == NULL)
return 1;
+ time(&now);
orig = pwent->pw_passwd; /* save existing password */
expire = pwent->pw_expire;
+ change = (pwent->pw_change == _PASSWORD_CHGNOW)? now : pwent->pw_change;
if (orig[0] == '\0') /* don't allow empty passwords */
return 1;
@@ -3337,14 +3612,14 @@ checkpassword(const struct passwd *pwent, const char *password)
if (strcmp(new, orig) != 0) /* compare */
return 1;
- if (expire && time(NULL) >= expire)
+ if ((expire && now >= expire) || (change && now >= change))
return 2; /* check if expired */
return 0; /* OK! */
}
char *
-xstrdup(const char *s)
+ftpd_strdup(const char *s)
{
char *new = strdup(s);
@@ -3370,3 +3645,156 @@ cprintf(FILE *fd, const char *fmt, ...)
total_bytes += b;
total_bytes_out += b;
}
+
+#ifdef USE_PAM
+/*
+ * the following code is stolen from imap-uw PAM authentication module and
+ * login.c
+ */
+#define COPY_STRING(s) (s ? strdup(s) : NULL)
+
+struct cred_t {
+ const char *uname; /* user name */
+ const char *pass; /* password */
+};
+typedef struct cred_t cred_t;
+
+static int
+auth_conv(int num_msg, const struct pam_message **msg,
+ struct pam_response **resp, void *appdata)
+{
+ int i;
+ cred_t *cred = (cred_t *) appdata;
+ struct pam_response *myreply;
+
+ myreply = calloc(num_msg, sizeof *myreply);
+ if (myreply == NULL)
+ return PAM_BUF_ERR;
+
+ for (i = 0; i < num_msg; i++) {
+ switch (msg[i]->msg_style) {
+ case PAM_PROMPT_ECHO_ON: /* assume want user name */
+ myreply[i].resp_retcode = PAM_SUCCESS;
+ myreply[i].resp = COPY_STRING(cred->uname);
+ /* PAM frees resp. */
+ break;
+ case PAM_PROMPT_ECHO_OFF: /* assume want password */
+ myreply[i].resp_retcode = PAM_SUCCESS;
+ myreply[i].resp = COPY_STRING(cred->pass);
+ /* PAM frees resp. */
+ break;
+ case PAM_TEXT_INFO:
+ case PAM_ERROR_MSG:
+ myreply[i].resp_retcode = PAM_SUCCESS;
+ myreply[i].resp = NULL;
+ break;
+ default: /* unknown message style */
+ free(myreply);
+ return PAM_CONV_ERR;
+ }
+ }
+
+ *resp = myreply;
+ return PAM_SUCCESS;
+}
+
+/*
+ * Attempt to authenticate the user using PAM. Returns 0 if the user is
+ * authenticated, or 1 if not authenticated. If some sort of PAM system
+ * error occurs (e.g., the "/etc/pam.conf" file is missing) then this
+ * function returns -1. This can be used as an indication that we should
+ * fall back to a different authentication mechanism.
+ */
+static int
+auth_pam(struct passwd **ppw, const char *pwstr)
+{
+ const char *tmpl_user;
+ const void *item;
+ int rval;
+ int e;
+ cred_t auth_cred = { (*ppw)->pw_name, pwstr };
+ struct pam_conv conv = { &auth_conv, &auth_cred };
+
+ e = pam_start("ftpd", (*ppw)->pw_name, &conv, &pamh);
+ if (e != PAM_SUCCESS) {
+ /*
+ * In OpenPAM, it's OK to pass NULL to pam_strerror()
+ * if context creation has failed in the first place.
+ */
+ syslog(LOG_ERR, "pam_start: %s", pam_strerror(NULL, e));
+ return -1;
+ }
+
+ e = pam_set_item(pamh, PAM_RHOST, remotehost);
+ if (e != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_set_item(PAM_RHOST): %s",
+ pam_strerror(pamh, e));
+ if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
+ }
+ pamh = NULL;
+ return -1;
+ }
+
+ e = pam_authenticate(pamh, 0);
+ switch (e) {
+ case PAM_SUCCESS:
+ /*
+ * With PAM we support the concept of a "template"
+ * user. The user enters a login name which is
+ * authenticated by PAM, usually via a remote service
+ * such as RADIUS or TACACS+. If authentication
+ * succeeds, a different but related "template" name
+ * is used for setting the credentials, shell, and
+ * home directory. The name the user enters need only
+ * exist on the remote authentication server, but the
+ * template name must be present in the local password
+ * database.
+ *
+ * This is supported by two various mechanisms in the
+ * individual modules. However, from the application's
+ * point of view, the template user is always passed
+ * back as a changed value of the PAM_USER item.
+ */
+ if ((e = pam_get_item(pamh, PAM_USER, &item)) ==
+ PAM_SUCCESS) {
+ tmpl_user = (const char *) item;
+ if (strcmp((*ppw)->pw_name, tmpl_user) != 0)
+ *ppw = sgetpwnam(tmpl_user);
+ } else
+ syslog(LOG_ERR, "Couldn't get PAM_USER: %s",
+ pam_strerror(pamh, e));
+ rval = 0;
+ break;
+
+ case PAM_AUTH_ERR:
+ case PAM_USER_UNKNOWN:
+ case PAM_MAXTRIES:
+ rval = 1;
+ break;
+
+ default:
+ syslog(LOG_ERR, "pam_authenticate: %s", pam_strerror(pamh, e));
+ rval = -1;
+ break;
+ }
+
+ if (rval == 0) {
+ e = pam_acct_mgmt(pamh, 0);
+ if (e != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_acct_mgmt: %s",
+ pam_strerror(pamh, e));
+ rval = 1;
+ }
+ }
+
+ if (rval != 0) {
+ if ((e = pam_end(pamh, e)) != PAM_SUCCESS) {
+ syslog(LOG_ERR, "pam_end: %s", pam_strerror(pamh, e));
+ }
+ pamh = NULL;
+ }
+ return rval;
+}
+
+#endif /* USE_PAM */
diff --git a/contrib/lukemftpd/src/ftpd.conf.5 b/contrib/lukemftpd/src/ftpd.conf.5
index 4d22bc6aaeb9..ff34eea330a1 100644
--- a/contrib/lukemftpd/src/ftpd.conf.5
+++ b/contrib/lukemftpd/src/ftpd.conf.5
@@ -1,6 +1,6 @@
-.\" $NetBSD: ftpd.conf.5,v 1.28 2003-06-27 18:59:54 wiz Exp $
+.\" $NetBSD: ftpd.conf.5,v 1.32 2005/09/11 23:31:46 wiz Exp $
.\"
-.\" Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
+.\" Copyright (c) 1997-2001, 2005 The NetBSD Foundation, Inc.
.\" All rights reserved.
.\"
.\" This code is derived from software contributed to The NetBSD Foundation
@@ -34,7 +34,7 @@
.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
.\" POSSIBILITY OF SUCH DAMAGE.
.\"
-.Dd November 30, 2002
+.Dd August 24, 2005
.Dt FTPD.CONF 5
.Os
.Sh NAME
@@ -121,7 +121,6 @@ directive is set for the class.
.Pp
Each configuration line may be one of:
.Bl -tag -width 4n
-.It Sy advertise Ar class Op Ar host
.It Sy advertize Ar class Op Ar host
Set the address to advertise in the response to the
.Sy PASV
@@ -304,6 +303,26 @@ Escape sequences are supported; refer to
in
.Xr ftpd 8
for more information.
+.It Sy hidesymlinks Ar class Op Sy off
+If
+.Ar class
+is
+.Dq none
+or
+.Sy off
+is specified, disable this feature.
+Otherwise, the
+.Sy LIST
+command lists symbolic links as the file or directory the link
+references
+.Pq Dq Li "ls -LlA" .
+Servers which run an anonymous service may wish to enable this
+feature for
+.Sy GUEST
+users, so that symbolic links do not leak names in
+directories that are not searchable by
+.Sy GUEST
+users.
.It Sy homedir Ar class Op Sy pathformat
If
.Ar pathformat
@@ -558,6 +577,19 @@ is
or
.Ar size
is not specified, use the default.
+.It Sy recvbufsize Ar class Op Ar size
+Set the size of the socket receive buffer.
+An optional suffix may be provided as per
+.Sy rateget .
+The default is zero and the system default value will be used.
+This option affects only passive transfers.
+If
+.Ar class
+is
+.Dq none
+or
+.Ar size
+is not specified, use the default.
.It Sy sanenames Ar class Op Sy off
If
.Ar class
diff --git a/contrib/lukemftpd/src/logutmp.c b/contrib/lukemftpd/src/logutmp.c
index c93a8ebd347a..71ee558245c3 100644
--- a/contrib/lukemftpd/src/logutmp.c
+++ b/contrib/lukemftpd/src/logutmp.c
@@ -154,4 +154,10 @@ ftpd_loginx(const struct utmpx *ut)
{
(void)pututxline(ut);
}
+
+int
+ftpd_logoutx(const char *line, int status, int mode)
+{
+ return logoutx(line, status, mode);
+}
#endif
diff --git a/contrib/lukemftpd/src/logwtmp.c b/contrib/lukemftpd/src/logwtmp.c
index 93b61a919dbe..33d73deea57c 100644
--- a/contrib/lukemftpd/src/logwtmp.c
+++ b/contrib/lukemftpd/src/logwtmp.c
@@ -1,4 +1,4 @@
-/* $NetBSD: logwtmp.c,v 1.22 2004-08-09 12:56:48 lukem Exp $ */
+/* $NetBSD: logwtmp.c,v 1.24 2005/06/23 04:20:41 christos Exp $ */
/*
* Copyright (c) 1988, 1993
@@ -36,7 +36,7 @@
#if 0
static char sccsid[] = "@(#)logwtmp.c 8.1 (Berkeley) 6/4/93";
#else
-__RCSID("$NetBSD: logwtmp.c,v 1.22 2004-08-09 12:56:48 lukem Exp $");
+__RCSID("$NetBSD: logwtmp.c,v 1.24 2005/06/23 04:20:41 christos Exp $");
#endif
#endif /* not lint */
@@ -51,8 +51,11 @@ __RCSID("$NetBSD: logwtmp.c,v 1.22 2004-08-09 12:56:48 lukem Exp $");
#include <stdio.h>
#include <string.h>
#include <time.h>
+#include <syslog.h>
#include <unistd.h>
+#ifdef SUPPORT_UTMP
#include <utmp.h>
+#endif
#ifdef SUPPORT_UTMPX
#include <utmpx.h>
#endif
@@ -64,10 +67,16 @@ __RCSID("$NetBSD: logwtmp.c,v 1.22 2004-08-09 12:56:48 lukem Exp $");
#include "extern.h"
+#ifdef SUPPORT_UTMP
static int fd = -1;
-#ifdef SUPPORT_UTMPX
-static int fdx = -1;
-#endif
+
+void
+ftpd_initwtmp(void)
+{
+ const char *wf = _PATH_WTMP;
+ if ((fd = open(wf, O_WRONLY|O_APPEND, 0)) == -1)
+ syslog(LOG_ERR, "Cannot open `%s' (%m)", wf);
+}
/*
* Modified version of logwtmp that holds wtmp file open
@@ -92,20 +101,36 @@ ftpd_logwtmp(const char *line, const char *name, const char *host)
(void)ftruncate(fd, buf.st_size);
}
}
+#endif
#ifdef SUPPORT_UTMPX
+static int fdx = -1;
+
+void
+ftpd_initwtmpx(void)
+{
+ const char *wf = _PATH_WTMPX;
+ if ((fd = open(wf, O_WRONLY|O_APPEND, 0)) == -1)
+ syslog(LOG_ERR, "Cannot open `%s' (%m)", wf);
+}
+
void
-ftpd_logwtmpx(const char *line, const char *name, const char *host, int status, int utx_type)
+ftpd_logwtmpx(const char *line, const char *name, const char *host,
+ struct sockinet *haddr, int status, int utx_type)
{
struct utmpx ut;
struct stat buf;
- if (fdx < 0 && (fdx = open(_PATH_WTMPX, O_WRONLY|O_APPEND, 0)) < 0)
+ if (fdx < 0)
return;
if (fstat(fdx, &buf) == 0) {
(void)strncpy(ut.ut_line, line, sizeof(ut.ut_line));
(void)strncpy(ut.ut_name, name, sizeof(ut.ut_name));
(void)strncpy(ut.ut_host, host, sizeof(ut.ut_host));
+ if (haddr)
+ (void)memcpy(&ut.ut_ss, &haddr->si_su, haddr->su_len);
+ else
+ (void)memset(&ut.ut_ss, 0, sizeof(ut.ut_ss));
ut.ut_type = utx_type;
if (WIFEXITED(status))
ut.ut_exit.e_exit = (uint16_t)WEXITSTATUS(status);
diff --git a/contrib/lukemftpd/src/pathnames.h b/contrib/lukemftpd/src/pathnames.h
index f2a48111c2ad..9e127bb9fd7f 100644
--- a/contrib/lukemftpd/src/pathnames.h
+++ b/contrib/lukemftpd/src/pathnames.h
@@ -1,4 +1,4 @@
-/* $NetBSD: pathnames.h,v 1.11 2003-08-07 09:46:40 agc Exp $ */
+/* $NetBSD: pathnames.h,v 1.12 2004/12/11 18:37:26 christos Exp $ */
/*
* Copyright (c) 1989, 1993
@@ -37,11 +37,11 @@
#define _DEFAULT_CONFDIR "/etc"
#endif
-#define _PATH_FTPCHROOT "ftpchroot"
-#define _PATH_FTPDCONF "ftpd.conf"
-#define _PATH_FTPLOGINMESG "motd"
-#define _PATH_FTPUSERS "ftpusers"
-#define _PATH_FTPWELCOME "ftpwelcome"
+#define _NAME_FTPCHROOT "ftpchroot"
+#define _NAME_FTPDCONF "ftpd.conf"
+#define _NAME_FTPLOGINMESG "motd"
+#define _NAME_FTPUSERS "ftpusers"
+#define _NAME_FTPWELCOME "ftpwelcome"
#define _PATH_CLASSPIDS "/var/run/ftpd.pids-"
diff --git a/contrib/lukemftpd/src/popen.c b/contrib/lukemftpd/src/popen.c
index a987475e5581..e7aeb3c8ef79 100644
--- a/contrib/lukemftpd/src/popen.c
+++ b/contrib/lukemftpd/src/popen.c
@@ -1,4 +1,4 @@
-/* $NetBSD: popen.c,v 1.30 2004-08-09 12:56:48 lukem Exp $ */
+/* $NetBSD: popen.c,v 1.31 2006/02/01 14:20:14 christos Exp $ */
/*-
* Copyright (c) 1999-2004 The NetBSD Foundation, Inc.
@@ -74,7 +74,7 @@
#if 0
static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 4/6/94";
#else
-__RCSID("$NetBSD: popen.c,v 1.30 2004-08-09 12:56:48 lukem Exp $");
+__RCSID("$NetBSD: popen.c,v 1.31 2006/02/01 14:20:14 christos Exp $");
#endif
#endif /* not lint */
@@ -138,7 +138,7 @@ ftpd_popen(char *argv[], const char *ptype, int stderrfd)
goto pfree;
/* glob each piece */
- if (sl_add(sl, xstrdup(argv[0])) == -1)
+ if (sl_add(sl, ftpd_strdup(argv[0])) == -1)
goto pfree;
for (argc = 1; argv[argc]; argc++) {
glob_t gl;
@@ -146,13 +146,13 @@ ftpd_popen(char *argv[], const char *ptype, int stderrfd)
memset(&gl, 0, sizeof(gl));
if (glob(argv[argc], flags, NULL, &gl)) {
- if (sl_add(sl, xstrdup(argv[argc])) == -1) {
+ if (sl_add(sl, ftpd_strdup(argv[argc])) == -1) {
globfree(&gl);
goto pfree;
}
} else {
for (pop = gl.gl_pathv; *pop; pop++) {
- if (sl_add(sl, xstrdup(*pop)) == -1) {
+ if (sl_add(sl, ftpd_strdup(*pop)) == -1) {
globfree(&gl);
goto pfree;
}
diff --git a/contrib/lukemftpd/src/version.h b/contrib/lukemftpd/src/version.h
index d18fc73dc572..8e26c52b4ff6 100644
--- a/contrib/lukemftpd/src/version.h
+++ b/contrib/lukemftpd/src/version.h
@@ -1,4 +1,4 @@
-/* $NetBSD: version.h,v 1.57 2004-08-09 12:56:48 lukem Exp $ */
+/* $NetBSD: version.h,v 1.64 2005/11/24 23:47:23 lukem Exp $ */
/*-
* Copyright (c) 1999-2004 The NetBSD Foundation, Inc.
* All rights reserved.
@@ -36,5 +36,5 @@
*/
#ifndef FTPD_VERSION
-#define FTPD_VERSION "NetBSD-ftpd 20040809"
+#define FTPD_VERSION "NetBSD-ftpd 20051124"
#endif