Source-Changes-HG archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

[src/trunk]: src/libexec/ftpd Add two new ftpd.conf(5) directives:



details:   https://anonhg.NetBSD.org/src/rev/50643daa8823
branches:  trunk
changeset: 518698:50643daa8823
user:      lukem <lukem%NetBSD.org@localhost>
date:      Tue Dec 04 13:54:12 2001 +0000

description:
Add two new ftpd.conf(5) directives:
- 'denyquick'; deny a connection so tagged by ftpusers(5) after the USER
  command instead of the PASS command. whilst this might provide some
  info leakage of accounts names if you have some `real' or `chroot'
  users enabled and not others, it does prevent accidental entering of
  such passwords if you have all such users denied. This option is
  strongly recommended on anonymous-only servers.
  Functionality requested by Rob Windsor in [bin/12602]
- 'private'; don't display class related information in the output of STAT.
  For paranoid admins.

diffstat:

 libexec/ftpd/conf.c      |   12 ++-
 libexec/ftpd/extern.h    |   12 +-
 libexec/ftpd/ftpd.c      |  181 ++++++++++++++++++++++++++++------------------
 libexec/ftpd/ftpd.conf.5 |   49 +++++++++++-
 libexec/ftpd/version.h   |    4 +-
 5 files changed, 172 insertions(+), 86 deletions(-)

diffs (truncated from 480 to 300 lines):

diff -r 2b27b4e26b5a -r 50643daa8823 libexec/ftpd/conf.c
--- a/libexec/ftpd/conf.c       Tue Dec 04 13:12:23 2001 +0000
+++ b/libexec/ftpd/conf.c       Tue Dec 04 13:54:12 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: conf.c,v 1.45 2001/12/01 10:25:29 lukem Exp $  */
+/*     $NetBSD: conf.c,v 1.46 2001/12/04 13:54:12 lukem Exp $  */
 
 /*-
  * Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
@@ -38,7 +38,7 @@
 
 #include <sys/cdefs.h>
 #ifndef lint
-__RCSID("$NetBSD: conf.c,v 1.45 2001/12/01 10:25:29 lukem Exp $");
+__RCSID("$NetBSD: conf.c,v 1.46 2001/12/04 13:54:12 lukem Exp $");
 #endif /* not lint */
 
 #include <sys/types.h>
@@ -121,8 +121,10 @@
        curclass.umask =        DEFAULT_UMASK;
 
        CURCLASS_FLAGS_SET(checkportcmd);
+       CURCLASS_FLAGS_CLR(denyquick);
        CURCLASS_FLAGS_SET(modify);
        CURCLASS_FLAGS_SET(passive);
+       CURCLASS_FLAGS_CLR(private);
        CURCLASS_FLAGS_CLR(sanenames);
        CURCLASS_FLAGS_SET(upload);
 }
@@ -330,6 +332,9 @@
                        REASSIGN(conv->disable, disable);
                        REASSIGN(conv->command, convcmd);
 
+               } else if (strcasecmp(word, "denyquick") == 0) {
+                       CONF_FLAG(denyquick);
+
                } else if (strcasecmp(word, "display") == 0) {
                        CONF_STRING(display);
 
@@ -446,6 +451,9 @@
                        curclass.portmin = minport;
                        curclass.portmax = maxport;
 
+               } else if (strcasecmp(word, "private") == 0) {
+                       CONF_FLAG(private);
+
                } else if (strcasecmp(word, "rateget") == 0) {
                        curclass.maxrateget = 0;
                        curclass.rateget = 0;
diff -r 2b27b4e26b5a -r 50643daa8823 libexec/ftpd/extern.h
--- a/libexec/ftpd/extern.h     Tue Dec 04 13:12:23 2001 +0000
+++ b/libexec/ftpd/extern.h     Tue Dec 04 13:54:12 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: extern.h,v 1.42 2001/07/13 05:37:49 lukem Exp $        */
+/*     $NetBSD: extern.h,v 1.43 2001/12/04 13:54:12 lukem Exp $        */
 
 /*-
  * Copyright (c) 1992, 1993
@@ -239,11 +239,13 @@
 
 typedef enum {
        FLAG_checkportcmd =     1<<0,   /* Check port commands */
-       FLAG_modify =           1<<1,   /* Allow CHMOD, DELE, MKD, RMD, RNFR,
+       FLAG_denyquick =        1<<1,   /* Check ftpusers(5) before PASS */
+       FLAG_modify =           1<<2,   /* Allow CHMOD, DELE, MKD, RMD, RNFR,
                                           UMASK */
-       FLAG_passive =          1<<2,   /* Allow PASV mode */
-       FLAG_sanenames =        1<<3,   /* Restrict names of uploaded files */ 
-       FLAG_upload =           1<<4    /* As per modify, but also allow
+       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
                                           APPE, STOR, STOU */
 } classflag_t;
 
diff -r 2b27b4e26b5a -r 50643daa8823 libexec/ftpd/ftpd.c
--- a/libexec/ftpd/ftpd.c       Tue Dec 04 13:12:23 2001 +0000
+++ b/libexec/ftpd/ftpd.c       Tue Dec 04 13:54:12 2001 +0000
@@ -1,4 +1,4 @@
-/*     $NetBSD: ftpd.c,v 1.132 2001/12/01 10:25:30 lukem Exp $ */
+/*     $NetBSD: ftpd.c,v 1.133 2001/12/04 13:54:12 lukem Exp $ */
 
 /*
  * Copyright (c) 1997-2001 The NetBSD Foundation, Inc.
@@ -109,7 +109,7 @@
 #if 0
 static char sccsid[] = "@(#)ftpd.c     8.5 (Berkeley) 4/28/95";
 #else
-__RCSID("$NetBSD: ftpd.c,v 1.132 2001/12/01 10:25:30 lukem Exp $");
+__RCSID("$NetBSD: ftpd.c,v 1.133 2001/12/04 13:54:12 lukem Exp $");
 #endif
 #endif /* not lint */
 
@@ -561,7 +561,8 @@
 }
 
 static int     login_attempts; /* number of failed login attempts */
-static int     askpasswd;      /* had user command, ask for passwd */
+static int     askpasswd;      /* had USER command, ask for PASSwd */
+static int     permitted;      /* USER permitted */
 static char    curname[10];    /* current USER name */
 
 /*
@@ -578,6 +579,9 @@
 void
 user(const char *name)
 {
+       char    *class;
+
+       class = NULL;
        if (logged_in) {
                switch (curclass.type) {
                case CLASS_GUEST:
@@ -606,6 +610,9 @@
 #endif
 
        curclass.type = CLASS_REAL;
+       askpasswd = 0;
+       permitted = 0;
+
        if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) {
                        /* need `pw' setup for checkaccess() and checkuser () */
                if ((pw = sgetpwnam("ftp")) == NULL)
@@ -618,34 +625,106 @@
                        reply(331,
                            "Guest login ok, type your name as password.");
                }
-               if (!askpasswd && logging)
-                       syslog(LOG_NOTICE,
-                           "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost);
-               return;
-       }
+               if (!askpasswd) {
+                       if (logging)
+                               syslog(LOG_NOTICE,
+                                   "ANONYMOUS FTP LOGIN REFUSED FROM %s",
+                                   remotehost);
+                       end_login();
+                       goto cleanup_user;
+               }
+               name = "ftp";
+       } else
+               pw = sgetpwnam(name);
 
-       pw = sgetpwnam(name);
        if (logging)
                strlcpy(curname, name, sizeof(curname));
 
-#ifdef SKEY
-       if (skey_haskey(name) == 0) {
-               const char *myskey;
+                       /* check user in /etc/ftpusers, and setup class */
+       permitted = checkuser(_PATH_FTPUSERS, curname, 1, 0, &class);
 
-               myskey = skey_keyinfo(name);
-               reply(331, "Password [%s] required for %s.",
-                   myskey ? myskey : "error getting challenge", name);
-       } else
+                       /* check user in /etc/ftpchroot */
+       if (checkuser(_PATH_FTPCHROOT, curname, 0, 0, NULL)) {
+               if (curclass.type == CLASS_GUEST) {
+                       syslog(LOG_NOTICE,
+           "Can't change guest user to chroot class; remove entry in %s",
+                           _PATH_FTPCHROOT);
+                       exit(1);
+               }
+               curclass.type = CLASS_CHROOT;
+       }
+                       /* determine default class */
+       if (class == NULL) {
+               switch (curclass.type) {
+               case CLASS_GUEST:
+                       class = xstrdup("guest");
+                       break;
+               case CLASS_CHROOT:
+                       class = xstrdup("chroot");
+                       break;
+               case CLASS_REAL:
+                       class = xstrdup("real");
+                       break;
+               default:
+                       syslog(LOG_ERR, "unknown curclass.type %d; aborting",
+                           curclass.type);
+                       abort();
+               }
+       }
+                       /* parse ftpd.conf, setting up various parameters */
+       parse_conf(class);
+                       /* if not guest user, check for valid shell */
+       if (pw == NULL)
+               permitted = 0;
+       else {
+               const char      *cp, *shell;
+
+               if ((shell = pw->pw_shell) == NULL || *shell == 0)
+                       shell = _PATH_BSHELL;
+               while ((cp = getusershell()) != NULL)
+                       if (strcmp(cp, shell) == 0)
+                               break;
+               endusershell();
+               if (cp == NULL && curclass.type != CLASS_GUEST)
+                       permitted = 0;
+       }
+
+                       /* deny quickly (after USER not PASS) if requested */
+       if (CURCLASS_FLAGS_ISSET(denyquick) && !permitted) {
+               reply(530, "User %s may not use FTP.", curname);
+               if (logging)
+                       syslog(LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s",
+                           remotehost, curname);
+               end_login();
+               goto cleanup_user;
+       }
+
+                       /* if haven't asked yet (i.e, not anon), ask now */
+       if (!askpasswd) {
+               askpasswd = 1;
+#ifdef SKEY
+               if (skey_haskey(curname) == 0) {
+                       const char *myskey;
+
+                       myskey = skey_keyinfo(curname);
+                       reply(331, "Password [%s] required for %s.",
+                           myskey ? myskey : "error getting challenge",
+                           curname);
+               } else
 #endif
-               reply(331, "Password required for %s.", name);
+                       reply(331, "Password required for %s.", curname);
+       }
 
-       askpasswd = 1;
+ cleanup_user:
        /*
         * Delay before reading passwd after first failed
         * attempt to slow down passwd-guessing programs.
         */
        if (login_attempts)
                sleep((unsigned) login_attempts);
+
+       if (class)
+               free(class);
 }
 
 /*
@@ -740,6 +819,8 @@
                        gid_t   *groups, *ng;
                        int      gsize, i, found;
 
+                       if (pw == NULL)
+                               continue;       /* no match for unknown user */
                        *p++ = '\0';
                        groups = NULL;
                        gsize = 16;
@@ -823,6 +904,8 @@
                memset(pw->pw_passwd, 0, strlen(pw->pw_passwd));
        pw = NULL;
        logged_in = 0;
+       askpasswd = 0;
+       permitted = 0;
        quietmessages = 0;
        gidcount = 0;
        curclass.type = CLASS_REAL;
@@ -833,10 +916,8 @@
 pass(const char *passwd)
 {
        int              rval;
-       const char      *cp, *shell;
-       char            *class, root[MAXPATHLEN];
+       char             root[MAXPATHLEN];
 
-       class = NULL;
        if (logged_in || askpasswd == 0) {
                reply(503, "Login with USER first.");
                return;
@@ -907,22 +988,8 @@
                }
        }
 
-                       /* password ok; see if anything else prevents login */
-       if (! checkuser(_PATH_FTPUSERS, pw->pw_name, 1, 0, &class)) {
-               reply(530, "User %s may not use FTP.", pw->pw_name);
-               if (logging)
-                       syslog(LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s",
-                           remotehost, pw->pw_name);
-               goto bad;
-       }
-                       /* if not guest user, check for valid shell */
-       if ((shell = pw->pw_shell) == NULL || *shell == 0)
-               shell = _PATH_BSHELL;
-       while ((cp = getusershell()) != NULL)
-               if (strcmp(cp, shell) == 0)
-                       break;
-       endusershell();
-       if (cp == NULL && curclass.type != CLASS_GUEST) {
+                       /* password ok; check if anything else prevents login */
+       if (! permitted) {
                reply(530, "User %s may not use FTP.", pw->pw_name);
                if (logging)



Home | Main Index | Thread Index | Old Index