Package: pure-ftpd Version: 1.0.21-11.4 Severity: wishlist Tags: patch I needed to enable the external authentication daemon pure-authd.
Found out about /etc/pure-ftpd/conf/ExtAuth, but the FTP daemon would not start, because the socket (which gets created by pure-authd) was missing. It seemed illogical to create another init script, since the upload handler is already started from the pure-ftpd init script. The auth daemon has to be started before pure-ftpd because it needs to create the authentication socket first (configured in ExtAuth, but in my opinion it should be static, the ExtAuth value changed to boolean, like CallUploadScript[B) I'm attaching the diff from the old init script (I did this on Lenny, but I checked the sid init script and it doesn't seem like anything changed). I'm also attaching an example python external authentication script which could be a little more polished, but it was just a proof of concept for me. If you're interested in including it, I'm willing to spruce it up a little. There are also a few new variables to be set in /etc/default/pure-ftpd-common: AUTHDSCRIPT=/path/to/authhandler[B AUTHDUID= AUTHDGID= in line with the variables used for upload handler. -- System Information: Debian Release: 5.0.8 APT prefers oldstable APT policy: (500, 'oldstable') Architecture: amd64 (x86_64) Kernel: Linux 2.6.26-2-xen-amd64 (SMP w/2 CPU cores) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages pure-ftpd depends on: ii libc6 2.7-18lenny7 GNU C Library: Shared libraries ii libcap1 1:1.10-14 support for getting/setting POSIX. ii libpam0g 1.0.1-5+lenny1 Pluggable Authentication Modules l ii libssl0.9.8 0.9.8g-15+lenny11 SSL shared libraries ii pure-ftpd-common 1.0.21-11.4 Pure-FTPd FTP server (Common Files pure-ftpd recommends no packages. pure-ftpd suggests no packages. -- no debconf information
#!/usr/bin/python """ pure-authd authentication handler Checks for username/password files on the filesystem which allow chrooted FTP access to a directory. """ import sys import os from os import environ as env from syslog import * # Requires getent - hg clone https://bitbucket.org/maze/getent import getent openlog('pure-authhandler.py[%s]' % os.getpid(),LOG_INFO,LOG_DAEMON) syslog('starting operation.') try: AUTHD_ACCOUNT = env['AUTHD_ACCOUNT'] AUTHD_PASSWORD = env['AUTHD_PASSWORD'] AUTHD_LOCAL_IP = env['AUTHD_LOCAL_IP'] AUTHD_LOCAL_PORT = env['AUTHD_LOCAL_PORT'] AUTHD_REMOTE_IP = env['AUTHD_REMOTE_IP'] except KeyError, e: syslog('Parameter error: missing environment variable %s' % e) print "auth_ok:0\nend" sys.exit(1) # Split the username on @ try: (subuser,sysuser) = AUTHD_ACCOUNT.split('@') except ValueError, e: syslog('username %s not in subuser@systemuser format: %s' % (AUTHD_ACCOUNT, e)) print "auth_ok:0\nend" sys.exit(0) try: website = getent.passwd(sysuser) if not website: syslog('user/website %s does not exist' % sysuser) print "auth_ok:0\nend" sys.exit(0) if website.uid < 1000: syslog('uid of user %s is less than 1000 (%s), denied' % (sysuser, website.uid) ) print "auth_ok:-1\nend" sys.exit(0) subdir = website.dir + '/FTP/' + subuser subpassfile = subdir + '.passwd' if os.path.isdir(subdir) and os.path.isfile(subpassfile): passfile = open(subpassfile) password = passfile.readline().rstrip() if password != AUTHD_PASSWORD: #syslog('Password for user %s does not match: is %s, should be %s' % (AUTHD_ACCOUNT,password,AUTHD_PASSWORD) ) syslog('Authentication failure for user %s: wrong password' % AUTHD_ACCOUNT ) print "auth_ok:-1\nend" sys.exit(0) else: syslog('User %s successfully authenticated' % AUTHD_ACCOUNT) print "auth_ok:1\nuid:%s\ngid:%s\ndir:%s\nend" % (website.uid,website.gid,subdir+'/./') sys.exit(0) else: syslog('subuser %s does not exist' % AUTHD_ACCOUNT) print "auth_ok:0\nend" sys.exit(0) except Exception, e: syslog('Exception checking credentials: %s' % e) print "auth_ok:0\nend" sys.exit(0)
--- /etc/init.d/pure-ftpd.ORIG 2011-03-25 13:59:43.000000000 +0100 +++ /etc/init.d/pure-ftpd 2011-03-25 14:21:04.000000000 +0100 @@ -18,6 +18,10 @@ UDDESC="ftp upload handler" WRAPPER=/usr/sbin/pure-ftpd-wrapper +AUTHDAEMON=/usr/sbin/pure-authd +ADNAME=pure-authd +ADDESC="external authentication daemon" + # try to figure with suffix this script is called, # $0 might be a symlink pointing to this script if [ -h $0 ]; then @@ -65,9 +69,23 @@ fi } +start_authd() { + if [ -x "$AUTHDSCRIPT" -a "$STANDALONE_OR_INETD" != inetd ] + then + AOPTS="" + test "$AUTHDUID" && AOPTS="$UOPTS -u $AUTHDUID" + test "$AUTHDGID" && AOPTS="$UOPTS -u $AUTHDGID" + echo -n "$1 $ADDESC: " + start-stop-daemon --start $SSDAEMONLOGOPTS --oknodo \ + --exec $AUTHDAEMON -- -r "$AUTHDSCRIPT" -B -s `head -1 /etc/pure-ftpd/conf/ExtAuth` $AOPTS + echo "$ADNAME." + fi +} + case "$1" in start) test "$STANDALONE_OR_INETD" = standalone || exit 0 + start_authd Starting echo -n "Starting $DESC: " start-stop-daemon --start $SSDAEMONLOGOPTS --pidfile /var/run/pure-ftpd/pure-ftpd.pid \ --exec $WRAPPER -- $SUFFIX @@ -78,6 +96,7 @@ start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo \ --pidfile /var/run/pure-ftpd/pure-ftpd.pid start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo --exec $UPLOADDAEMON + start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo --exec $AUTHDAEMON echo "$NAME." ;; restart|force-reload) @@ -86,10 +105,12 @@ start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo \ --pidfile /var/run/pure-ftpd/pure-ftpd.pid start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo --exec $UPLOADDAEMON + start-stop-daemon --stop $SSDAEMONLOGOPTS --oknodo --exec $AUTHDAEMON sleep 1 start-stop-daemon --start $SSDAEMONLOGOPTS --pidfile \ /var/run/pure-ftpd/pure-ftpd.pid --exec $WRAPPER -- $SUFFIX start_uploadscript Restarting + start_authd Restarting ;; *) N=/etc/init.d/$NAME