summaryrefslogtreecommitdiffstats
path: root/libexec
diff options
context:
space:
mode:
authoryar <yar@FreeBSD.org>2003-01-26 19:02:56 +0000
committeryar <yar@FreeBSD.org>2003-01-26 19:02:56 +0000
commit411365f15d431cee967e5d16b04ee1687c259a3c (patch)
treedc49b88ce40df8ea4f9fd4260336ea4f3855c206 /libexec
parentd3dc53e828a4947398b7352bad769336a1fc1da2 (diff)
downloadFreeBSD-src-411365f15d431cee967e5d16b04ee1687c259a3c.zip
FreeBSD-src-411365f15d431cee967e5d16b04ee1687c259a3c.tar.gz
Extend the format of /etc/ftpchroot so an alternative chroot
directory can be specified for a user or a group. Add the manpage ftpchroot(5) since the file's format has grown complex enough. PR: bin/45327 Portions submitted by: Hideki SAKAMOTO <sakamoto@hlla.is.tsukuba.ac.jp> MFC after: 1 week
Diffstat (limited to 'libexec')
-rw-r--r--libexec/ftpd/Makefile2
-rw-r--r--libexec/ftpd/ftpchroot.5109
-rw-r--r--libexec/ftpd/ftpd.87
-rw-r--r--libexec/ftpd/ftpd.c77
4 files changed, 171 insertions, 24 deletions
diff --git a/libexec/ftpd/Makefile b/libexec/ftpd/Makefile
index 0a3ffc5..b6c8ed9 100644
--- a/libexec/ftpd/Makefile
+++ b/libexec/ftpd/Makefile
@@ -2,7 +2,7 @@
# $FreeBSD$
PROG= ftpd
-MAN= ftpd.8
+MAN= ftpd.8 ftpchroot.5
SRCS= ftpd.c ftpcmd.y logwtmp.c popen.c
CFLAGS+=-DSETPROCTITLE -DLOGIN_CAP -DVIRTUAL_HOSTING
diff --git a/libexec/ftpd/ftpchroot.5 b/libexec/ftpd/ftpchroot.5
new file mode 100644
index 0000000..8c8f629
--- /dev/null
+++ b/libexec/ftpd/ftpchroot.5
@@ -0,0 +1,109 @@
+.\" Copyright (c) 2003 FreeBSD Project
+.\" 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.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND 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 THE AUTHOR OR 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.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 26, 2003
+.Dt FTPCHROOT 5
+.Os
+.Sh NAME
+.Nm ftpchroot
+.Nd list users and groups subject to FTP access restrictions
+.Sh DESCRIPTION
+The file
+.Nm
+is read by
+.Xr ftpd 8
+at the beginning of an FTP session, after having authenticated the user.
+Each line in
+.Nm
+corresponds to a user or group. If a line in
+.Nm
+matches the current user or a group he is a member of,
+access restrictions will be applied to this
+session by changing its root directory with
+.Xr chroot 2
+to that specified on the line or to the user's login directory.
+.Pp
+The order of records in
+.Nm
+is important because the first match will be used.
+Fields on each line are separated by tabs or spaces.
+.Pp
+The first field specifies a user or group name.
+If it is prefixed by an
+.Qq at
+sign,
+.Ql \&@ ,
+it specifies a group name;
+the line will match each user who is a member of this group.
+As a special case, a single
+.Ql \&@
+in this field will match any user.
+A username is specified otherwise.
+.Pp
+The optional second field describes the directory for the user
+or each member of the group to be locked up in using
+.Xr chroot 2 .
+If it is not an absolute pathname, then it will be relative
+to the user's login directory.
+Be this field omitted, the user's login directory will be used.
+.Sh FILES
+.Bl -tag -width /etc/ftpchroot -compact
+.It Pa /etc/ftpchroot
+.El
+.Sh EXAMPLES
+These lines in
+.Nm
+will lock up the user
+.Qq webuser
+and each member of the group
+.Qq hostee
+in their respective login directories:
+.Bd -literal -offset indent
+webuser
+@hostee
+.Ed
+.Pp
+And this line will lock up the user
+.Qq joe
+in
+.Pa /var/spool/ftp :
+.Bd -literal -offset indent
+joe /var/spool/ftp
+.Ed
+.Pp
+And finally the following line will lock up every user connecting
+through FTP in his respective
+.Pa \&~/public_html ,
+thus lowering possible impact on the system
+from intrinsic insecurity of FTP:
+.Bd -literal -offset indent
+@ public_html
+.Ed
+.Sh SEE ALSO
+.Xr chroot 2 ,
+.Xr group 5 ,
+.Xr passwd 5 ,
+.Xr ftpd 8 .
diff --git a/libexec/ftpd/ftpd.8 b/libexec/ftpd/ftpd.8
index b995b8a..9d9fd82 100644
--- a/libexec/ftpd/ftpd.8
+++ b/libexec/ftpd/ftpd.8
@@ -358,13 +358,17 @@ If the user name appears in the file
or the user is a member of a group with a group entry in this file,
i.e. one prefixed with
.Ql \&@ ,
-the session's root will be changed to the user's login directory by
+the session's root will be changed to the directory specified
+in this file or to the user's login directory by
.Xr chroot 2
as for an
.Dq anonymous
or
.Dq ftp
account (see next item).
+See
+.Xr ftpchroot 5
+for a detailed description of the format of this file.
This facility may also be triggered by enabling the boolean "ftp-chroot"
capability in
.Xr login.conf 5 .
@@ -518,6 +522,7 @@ Default place for session logs.
.Xr key 1 ,
.Xr umask 2 ,
.Xr getusershell 3 ,
+.Xr ftpchroot 5 ,
.Xr login.conf 5 ,
.Xr inetd 8 ,
.Xr syslogd 8
diff --git a/libexec/ftpd/ftpd.c b/libexec/ftpd/ftpd.c
index ca1e348..71fca60 100644
--- a/libexec/ftpd/ftpd.c
+++ b/libexec/ftpd/ftpd.c
@@ -239,7 +239,7 @@ static void selecthost(union sockunion *);
static void ack(char *);
static void sigurg(int);
static void myoob(void);
-static int checkuser(char *, char *, int);
+static int checkuser(char *, char *, int, char **);
static FILE *dataconn(char *, off_t, char *);
static void dolog(struct sockaddr *);
static char *curdir(void);
@@ -1000,8 +1000,8 @@ user(char *name)
guest = 0;
if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
- if (checkuser(_PATH_FTPUSERS, "ftp", 0) ||
- checkuser(_PATH_FTPUSERS, "anonymous", 0))
+ if (checkuser(_PATH_FTPUSERS, "ftp", 0, NULL) ||
+ checkuser(_PATH_FTPUSERS, "anonymous", 0, NULL))
reply(530, "User %s access denied.", name);
#ifdef VIRTUAL_HOSTING
else if ((pw = sgetpwnam(thishost->anonuser)) != NULL) {
@@ -1032,7 +1032,7 @@ user(char *name)
break;
endusershell();
- if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1)) {
+ if (cp == NULL || checkuser(_PATH_FTPUSERS, name, 1, NULL)) {
reply(530, "User %s access denied.", name);
if (logging)
syslog(LOG_NOTICE,
@@ -1069,10 +1069,12 @@ user(char *name)
}
/*
- * Check if a user is in the file "fname"
+ * Check if a user is in the file "fname",
+ * return a pointer to a malloc'd string with the rest
+ * of the matching line in "residue" if not NULL.
*/
static int
-checkuser(char *fname, char *name, int pwset)
+checkuser(char *fname, char *name, int pwset, char **residue)
{
FILE *fd;
int found = 0;
@@ -1106,26 +1108,40 @@ checkuser(char *fname, char *name, int pwset)
int i = 0;
struct group *grp;
- if ((grp = getgrnam(p+1)) == NULL)
- goto nextline;
- /*
- * Check user's default group
- */
- if (pwset && grp->gr_gid == pw->pw_gid)
+ if (p[1] == '\0') /* single @ matches anyone */
found = 1;
- /*
- * Check supplementary groups
- */
- while (!found && grp->gr_mem[i])
- found = strcmp(name,
- grp->gr_mem[i++])
- == 0;
+ else {
+ if ((grp = getgrnam(p+1)) == NULL)
+ goto nextline;
+ /*
+ * Check user's default group
+ */
+ if (pwset && grp->gr_gid == pw->pw_gid)
+ found = 1;
+ /*
+ * Check supplementary groups
+ */
+ while (!found && grp->gr_mem[i])
+ found = strcmp(name,
+ grp->gr_mem[i++])
+ == 0;
+ }
}
/*
* Otherwise, just check for username match
*/
else
found = strcmp(p, name) == 0;
+ /*
+ * Save the rest of line to "residue" if matched
+ */
+ if (found && residue) {
+ if ((p = strtok(NULL, "")) != NULL) {
+ if ((*residue = strdup(p)) == NULL)
+ fatalerror("Ran out of memory.");
+ } else
+ *residue = NULL;
+ }
nextline:
if (mp)
free(mp);
@@ -1331,6 +1347,7 @@ pass(char *passwd)
#ifdef USE_PAM
int e;
#endif
+ char *chrootdir;
char *xpasswd;
if (logged_in || askpasswd == 0) {
@@ -1447,10 +1464,11 @@ skip:
stats = 0;
dochroot =
+ checkuser(_PATH_FTPCHROOT, pw->pw_name, 1, &chrootdir)
#ifdef LOGIN_CAP /* Allow login.conf configuration as well */
- login_getcapbool(lc, "ftp-chroot", 0) ||
+ || login_getcapbool(lc, "ftp-chroot", 0)
#endif
- checkuser(_PATH_FTPCHROOT, pw->pw_name, 1);
+ ;
if (guest) {
/*
* We MUST do a chdir() after the chroot. Otherwise
@@ -1462,10 +1480,25 @@ skip:
goto bad;
}
} else if (dochroot) {
- if (chroot(pw->pw_dir) < 0 || chdir("/") < 0) {
+ if (chrootdir) { /* chroot dir set in ftpchroot(5) */
+ if (chrootdir[0] != '/') { /* relative to homedir */
+ char *p;
+
+ asprintf(&p, "%s/%s", pw->pw_dir, chrootdir);
+ if (p == NULL)
+ fatalerror("Ran out of memory.");
+ free(chrootdir);
+ chrootdir = p;
+ }
+ } else
+ if ((chrootdir = strdup(pw->pw_dir)) == NULL)
+ fatalerror("Ran out of memory.");
+ if (chroot(chrootdir) < 0 || chdir("/") < 0) {
reply(550, "Can't change root.");
+ free(chrootdir);
goto bad;
}
+ free(chrootdir);
} else if (chdir(pw->pw_dir) < 0) {
if (chdir("/") < 0) {
reply(530, "User %s: can't change directory to %s.",
OpenPOWER on IntegriCloud