debian/0000755000000000000000000000000011564740370007175 5ustar debian/changelog0000644000000000000000000004657611564740370011071 0ustar linux-ftpd-ssl (0.17.33+0.3-1build1) oneiric; urgency=low * Rebuild for OpenSSL 1.0.0. -- Colin Watson Wed, 18 May 2011 13:52:00 +0100 linux-ftpd-ssl (0.17.33+0.3-1) unstable; urgency=low * Update to linux-ftpd 0.17-33. * Drop hard-coded dependency on libssl0.9.8. * Standards-Version: 3.9.1 (no changes). -- Ian Beckwith Wed, 20 Apr 2011 02:46:14 +0100 linux-ftpd (0.17-33) unstable; urgency=low * Correct implementation of EPSV for IPv4. + debian/patches/020-support_ipv6.diff: Updated file. * [lintian] Addition of DEP-3 header: + debian/patches/030-manpage_typos.diff: Description added. * debian/control: Spelling of 'kFreeBSD'. * Bumped Standards to 3.9.1. -- Mats Erik Andersson Wed, 06 Apr 2011 22:34:30 +0200 linux-ftpd-ssl (0.17.32+0.3-1) unstable; urgency=low * Update to linux-ftpd 0.17-32. * Standards-Version: 3.9.0 (no changes). -- Ian Beckwith Sun, 25 Jul 2010 01:32:41 +0100 linux-ftpd (0.17-32) unstable; urgency=low * Fixed minor typos in ftpd.8. * Renamed patches to avoid future clashes with linux-ftpd-ssl. * Bumped Standards to 3.9.0 -- Alberto Gonzalez Iniesta Thu, 08 Jul 2010 13:28:07 +0200 linux-ftpd-ssl (0.17.31+0.3-1) unstable; urgency=low * Update to linux-ftpd 0.17-31 + IPv6 support! Thanks to Mats Erik Andersson . * Convert to format 3.0 (quilt). * Extract source changes to patches in debian/patch/, annotate patches in DEP3 format. SSL patches start at 500, patches below that are imported unchanged from the debian linux-ftpd package. * debian/rules: add -fno-strict-align to CFLAGS. * ftpd.8: typo fixes. * Switch to debhelper compat level 7. * debian/watch: check for new debian package of linux-ftpd. * Update maintainer email. * Remove DM-Upload-Allowed flag. * Standards-Version: 3.8.4 (no changes). -- Ian Beckwith Mon, 14 Jun 2010 02:14:27 +0100 linux-ftpd (0.17-31) unstable; urgency=low [Mats Erik Andersson] * debian/control: Expanded description. * debian/copyright: Added explicit license for the two IPv6-patches. * Describe effects of recent changes on three inetd-servers. + debian/NEWS: Short text addition. + debian/README.Debian: Added an extended discussion. * FTBFS GNU/kfreebsd, GNU/Hurd: * debian/patches/26-support_glibc_bsd_and_gnu.diff: New file. * debian/{postinst,prerm}: Use option '--multi' with 'update-inetd'. -- Mats Erik Andersson Tue, 25 May 2010 20:05:34 +0200 linux-ftpd (0.17-30) unstable; urgency=low * Migration to format "3.0 (quilt)". + Identified source code patches: + debian/patches/01-from_hamm.diff + debian/patches/02-from_sarge.diff + debian/patches/03-from_etch.diff + debian/patches/10-ftpd_csrf.diff * Standard 3.8.4, debhelper compatibility 7: + Using dh_prep. * debian/control: + Build depend includes ${misc:Depends} and 'debhelper (>= 7). + Source homepage stanza pointing to download site. * debian/watch: New file. * debian/postinst: Suppress error message if '/etc/inetd.conf' is missing. + Print a hint to the example xinetd configuration, if applicable. * debian/ftpd.examples: + debian/ftpd.xinetd: Configuration for use with xinetd. * Prepare migration to IPv6 support: + debian/rules: Use compiler flag '-fno-strict-aliasing'. + debian/patches/14-adjust_infrastruct.diff: New file. + debian/patches/16-family_independence.diff: New file. * Implement active IPv6 support: (Closes: #580251) + debian/patches/20-support_ipv6.diff: New file. + debian/NEWS: New file. + debian/README.Debian: A short explanation is added. * Uninitialized va_list causes segmentation faults on amd64: + debian/patches/24-failing_va_list.diff: New file. * [lintian] maintainer-script-without-set-e: + debian/{preinst,prerm,postinst,postrm} modified. * [lintian] debian-rules-ignores-make-clean-error: + debian/rules modified. * agi: Added Mats Erik Andersson as Uploader. -- Mats Erik Andersson Sun, 09 May 2010 16:17:20 +0200 linux-ftpd (0.17-29) unstable; urgency=high * Ian Beckwith: - Patch to fix cross-site request forgery (CSRF) attacks. CVE-2008-4247 (Closes: #500278) * Updated package description. (Closes: #493433) -- Alberto Gonzalez Iniesta Fri, 17 Oct 2008 20:34:17 +0200 linux-ftpd (0.17-28) unstable; urgency=low * Patch postrm/postinst files to handle update-inetd better. Thanks Ian Beckwith for the patch. (Closes: #482912) -- Alberto Gonzalez Iniesta Tue, 22 Jul 2008 17:13:19 +0200 linux-ftpd-ssl (0.17.27+0.3-3) unstable; urgency=high * Fix command line split CSRF (Closes: #500518) Addresses CVE-2008-4242 and CVE-2008-4247. -- Ian Beckwith Thu, 16 Oct 2008 22:13:23 +0100 linux-ftpd-ssl (0.17.27+0.3-2) unstable; urgency=low * Create debian/NEWS with details of openssl problems and key rollover. * Explicitly depend/build-depend on fixed openssl. * ftpd/ftpd.c: Set default ssl key/cert file to /etc/ftpd-ssl/ftpd.pem. * postinst: + On new installs don't bother with -z cert and -z key, as we can now use the defaults. + Revert to update-inetd logic from linux-ftpd. * postrm: Only remove inetd entry on purge, and only if it is commented out. * Add private copy of openssl.cnf from openssl 0.9.8g-10 (See #372105). * debian/control: + Added DM-Upload-Allowed: yes. -- Ian Beckwith Sun, 25 May 2008 19:24:55 +0100 linux-ftpd-ssl (0.17.27+0.3-1) unstable; urgency=low * New maintainer (Closes: #476132). * Update to linux-ftpd 0.17-27. * Fix all warnings in source. * ftpd.8: Document SSL options, fix typo. * debian/control: + Standards-Version: 3.7.3 (no changes). * debian/rules: + Support DEB_BUILD_OPTIONS=noopt. + Added -Wl,-z,defs -Wl,--as-needed to LDFLAGS. + Fixed make distclean invocation. + Removed unused install-stamp. + Removed unnecessary debhelper calls. * debian/postinst: worked round checkbashism false positive. * debian/postrm: fixed wording of error message. * debian/copyright: added copyright info for SSL patches. * Bumped debhelper compat level to 5. * Use linux-ftpd_0.17.orig.tar.gz as our orig.tar.gz. -- Ian Beckwith Wed, 23 Apr 2008 01:06:35 +0100 linux-ftpd (0.17-27) unstable; urgency=low * Ignore missing ../MCONFIG in clean target. (Closes: #436720) -- Alberto Gonzalez Iniesta Wed, 08 Aug 2007 20:49:22 +0200 linux-ftpd (0.17-26) unstable; urgency=low * Removed Depends on update-inetd, since it should be provided by inetd-superserver. -- Alberto Gonzalez Iniesta Tue, 07 Aug 2007 18:02:11 +0200 linux-ftpd (0.17-25) unstable; urgency=low * Condition the call to update-inetd in postrm. (Closes: #416745) * Moved netbase dependency to openbsd-inetd | inet-superserver. * Added Depends on update-inetd * Moved to debhelper compat 4. (Removed debian/conffiles) * Bumped Standards-Version to 3.7.2.2. No change -- Alberto Gonzalez Iniesta Sat, 31 Mar 2007 19:43:37 +0200 linux-ftpd (0.17-24) unstable; urgency=low * pam.d/ftpd. Updated PAM configuration to used common-* files. Thanks a lot Pierre Gaufillet for the patch (Closes: #308651) -- Alberto Gonzalez Iniesta Thu, 14 Dec 2006 12:14:53 +0100 linux-ftpd (0.17-23) unstable; urgency=high * Urgency set due to security fix. * Corrected typo in patch used in previous upload that made the server run some commands with EGID 'root'. Thanks to Matt Power (for finding out) and Stefan Cornelius from Gentoo (for warning me). -- Alberto Gonzalez Iniesta Sat, 25 Nov 2006 18:54:59 +0100 linux-ftpd (0.17-22) unstable; urgency=high * Fixing two security bugs: - Fixed ftpd from doing chdir while running as root. (Closes: #384454) Thanks a lot to Paul Szabo for finding out and the patch. - Check the return value from setuid calls to avoid running code as root. Thanks Paul Szabo for the patch. -- Alberto Gonzalez Iniesta Fri, 15 Sep 2006 13:14:25 +0200 linux-ftpd (0.17-21) unstable; urgency=low * Patched ftpcmd.y to allow building on amd64 with gcc-4.0. Thanks Andreas Jochens for the patch. (Closes: #300245) -- Alberto Gonzalez Iniesta Sun, 10 Jul 2005 08:48:19 +0200 linux-ftpd (0.17-20) unstable; urgency=low * New maintainer. -- Alberto Gonzalez Iniesta Sat, 12 Mar 2005 12:07:29 +0100 linux-ftpd (0.17-19) unstable; urgency=low * Add -n option to log numeric IPs rather than doing reverse lookup (for improved log forensics in the event an attacker has control of their reverse DNS.). Thanks Dean Gaudet. (Closes: #258369) * Fix Build-Depends to avoid relying on virtual package 'libpam-dev' exclussively. * Convert changelog to UTF-8. -- Robert Millan Wed, 11 Aug 2004 22:08:44 +0200 linux-ftpd-ssl (0.17.18+0.3-9.1) unstable; urgency=high * Non-maintainer upload by the testing-security team. * Fix remote denial of service cause by passing an uninitialized file stream to fopen().Initializing file with NULL and checking for NULL before calling fclose() fixes this (CVE-2007-6263; Closes: #454733). -- Nico Golde Mon, 10 Dec 2007 18:34:40 +0100 linux-ftpd-ssl (0.17.18+0.3-9) unstable; urgency=low * debian/postrm: invoke update-inetd if it is present. (Closes: #416746) -- Cai Qian Mon, 3 Apr 2007 00:00:00 +0800 linux-ftpd-ssl (0.17.18+0.3-8) unstable; urgency=low * debian/control: dropped update-inetd,as netbase has already provided it. * debian/postrm: replaced update-inetd with sed. (Closes: #416746) * debian/conffile: dropped it. -- Cai Qian Mon, 2 Apr 2007 16:00:00 +0800 linux-ftpd-ssl (0.17.18+0.3-7) unstable; urgency=low * debian/control: depends on update-inetd. (Closes: #351204, #416746) -- Cai Qian Fri, 30 Mar 2007 16:00:00 +0800 linux-ftpd-ssl (0.17.18+0.3-6) unstable; urgency=low * Move the certificate file to /etc/ftpd-ssl. Patch from James Westby . (Closes: #368420) * Remove debian/conffile -- Cai Qian Sat, 01 July 2006 12:27:01 +0100 linux-ftpd-ssl (0.17.18+0.3-5) unstable; urgency=high * applied security patch for CVE-2005-3524. (Closes: #339074) -- Cai Qian Fri, 18 Nov 2005 17:27:01 +0000 linux-ftpd-ssl (0.17.18+0.3-4) unstable; urgency=low * applied gcc4/amd64 patch by Andreas Jochens (Closes: #300247) -- Cai Qian Wed, 28 Sep 2005 01:04:00 +0100 linux-ftpd-ssl (0.17.18+0.3-3) unstable; urgency=low * encoded changelog to UTF-8 * followed debhelper V4 -- Cai Qian Mon, 15 Nov 2004 22:45:00 +0800 linux-ftpd-ssl (0.17.18+0.3-2) unstable; urgency=low * New maintainer (Closes: #250711) * Change debian/rules to fix missing ftpd.8 -- Cai Qian Sun, 27 Sep 2004 01:45:00 +0800 linux-ftpd-ssl (0.17.18+0.3-1) unstable; urgency=low * Bring linux-ftpd in line with current netkit-telnet * Build for sid/sarge * Make ftp-ssl protocol compatible with http://www.ietf.org/internet-drafts/draft-murray-auth-ftp-ssl-09.txt or http://www.ietf.org/rfc/rfc2228.txt. This can break compatiblility with older ftp-ssl (closes: #154138) -- Christoph Martin Thu, 27 May 2004 15:00:27 +0200 linux-ftpd (0.17-18) unstable; urgency=low * New maintainer. (Closes: #249709) - control (Maintainer): Set myself. -- Robert Millan Wed, 19 May 2004 02:09:10 +0200 linux-ftpd (0.17-17) unstable; urgency=low * Documented the need for libnss_files.so.2 (closes: #241687). -- Herbert Xu Sat, 24 Apr 2004 17:48:37 +1000 linux-ftpd (0.17-16) unstable; urgency=low * Fixed ftpd entry existence test in postinst. * Added missing -q for last grep in postinst. * Removed debconf message about globbing attacks. * Fixed type-punning warning in pam_doit. * Removed stamp files for build and install. * Fixed const cast warning in ftpcmd.y. -- Herbert Xu Sat, 21 Jun 2003 14:20:35 +1000 linux-ftpd (0.17-15) unstable; urgency=low * Removed description of bogus -p option (closes: #180652). -- Herbert Xu Thu, 6 Mar 2003 20:26:16 +1100 linux-ftpd (0.17-14) unstable; urgency=low * Added Spanish debconf translation (Carlos Valdivia Yagüe, closes: #143956). * Call ls without -g (closes #156992). -- Herbert Xu Sun, 25 Aug 2002 10:09:07 +1000 linux-ftpd (0.17-13) unstable; urgency=low * Added Russian debconf translation (Ilgiz Kalmetev, closes: #135840). -- Herbert Xu Thu, 18 Apr 2002 19:18:28 +1000 linux-ftpd-ssl (0.17.12+0.3-2) unstable; urgency=low * moved from nonus to main -- Christoph Martin Sat, 23 Mar 2002 12:18:50 +0100 linux-ftpd-ssl (0.17.12+0.3-1) unstable; urgency=low * Fixed REST/STOR combination with OpenBSD patch (#132974). * REST now accepts intmax_t (#126766). * Built with support for large files (#122961). * Added sample limits.conf entry against globbing (#121074). * Added Brazilian debconf template (Andre Luis Lopes, #120835). * Always specify the syslog facility explicitly (#121644). -- Christoph Martin Thu, 7 Mar 2002 09:57:26 +0100 linux-ftpd (0.17-12) unstable; urgency=low * Fixed REST/STOR combination with OpenBSD patch (closes: #132974). -- Herbert Xu Sat, 9 Feb 2002 14:50:45 +1100 linux-ftpd (0.17-11) unstable; urgency=low * REST now accepts intmax_t (closes: #126766). -- Herbert Xu Sun, 20 Jan 2002 19:03:22 +1100 linux-ftpd (0.17-10) unstable; urgency=low * Built with support for large files (closes: #122961). -- Herbert Xu Sun, 9 Dec 2001 17:45:53 +1100 linux-ftpd (0.17-9) unstable; urgency=low * Added sample limits.conf entry against globbing (closes: #121074). * Added Brazilian debconf template (Andre Luis Lopes, closes: #120835). * Always specify the syslog facility explicitly (closes: #121644). -- Herbert Xu Sat, 1 Dec 2001 18:28:51 +1100 linux-ftpd-ssl (0.17.8+0.3-1) unstable; urgency=low * bring in line with linux-ftpd * Debconf (see 113611) * pam_limits used -- Christoph Martin Wed, 21 Nov 2001 16:05:54 +0100 linux-ftpd (0.17-8) unstable; urgency=low * Added German debconf template (Sebastian Feltel, closes: #113611). -- Herbert Xu Sat, 13 Oct 2001 08:13:55 +1000 linux-ftpd (0.17-7) unstable; urgency=low * Added debconf about globbing attacks. -- Herbert Xu Thu, 23 Aug 2001 19:49:01 +1000 linux-ftpd (0.17-6) unstable; urgency=low * Register sessions with PAM. * Use pam_limits by default. * Documented the procedure to counter globbing attacks. -- Herbert Xu Sat, 9 Jun 2001 13:25:27 +1000 linux-ftpd-ssl (0.17.5+0.3-1) unstable; urgency=low * Remove Provides ftpd (closes: #93532) * Bring in line with linux-ftpd (see 96640 and 93217) * new upstream patch (0.3) brings working -z secure (closes: #92873) which can now force ftpd to only accept secure connections * add SSL options to manpage (closes: #92602) -- Christoph Martin Sun, 13 May 2001 13:44:58 +0200 linux-ftpd (0.17-5) unstable; urgency=low * Removed duplicate authentication error message (closes: #96640). -- Herbert Xu Mon, 7 May 2001 22:08:29 +1000 linux-ftpd (0.17-4) unstable; urgency=low * The value of unique is now passed to dataconn (closes: #93217). -- Herbert Xu Sun, 22 Apr 2001 09:33:26 +1000 linux-ftpd-ssl (0.17.4+0.2-1) unstable; urgency=low * bring linux-ftpd updates to -ssl * builddepends on libssl-dev -- Christoph Martin Sat, 10 Mar 2001 17:48:45 +0100 linux-ftpd (0.17-3) unstable; urgency=low * Fixed anonymous authentication bug when PAM is disabled (Liviu Daia, Abraham vd Merwe, Rainer Weikusat, closes: #88837). * Fixed patterns used to check for existing ftp services (closes: #85579). -- Herbert Xu Fri, 9 Mar 2001 22:30:37 +1100 linux-ftpd-ssl (0.17.2+0.2-1) unstable; urgency=low * initial linux-ftpd-ssl version -- Christoph Martin Sun, 18 Feb 2001 14:27:54 +0100 linux-ftpd (0.17-2) unstable; urgency=high * Applied bug fix from OpenBSD (closes: #78973). -- Herbert Xu Thu, 7 Dec 2000 19:47:47 +1100 linux-ftpd (0.17-1) unstable; urgency=low * New upstream release (identical to 0.16-2). -- Herbert Xu Sat, 12 Aug 2000 13:29:38 +1000 linux-ftpd (0.16-2) unstable; urgency=high * Fixed a security hole discovered by OpenBSD, thanks to Thomas Roessler for notifying me (closes: #66832). * Added build-time dependency on debhelper. -- Herbert Xu Fri, 7 Jul 2000 10:15:38 +1000 linux-ftpd (0.16-1) unstable; urgency=low * New upstream release. * Added Source-Depends on bison (closes: #61160). * Removed checks on the remote address of the data connection which violated RFC 959 (closes: #59251). -- Herbert Xu Mon, 24 Apr 2000 20:46:00 +1000 linux-ftpd (0.11-9) frozen unstable; urgency=low * Added Bource-Depends on libpam0g-dev (closes: #49917). -- Herbert Xu Sat, 18 Mar 2000 12:50:14 +1100 linux-ftpd (0.11-8) unstable; urgency=low * Added entry for ~ftp/lib in in.ftpd(8) (closes: #49035). -- Herbert Xu Sat, 6 Nov 1999 12:21:37 +1100 linux-ftpd (0.11-7) unstable; urgency=low * Added missing dependencies on netbase and libpam-modules (closes: #48411). -- Herbert Xu Wed, 27 Oct 1999 09:25:59 +1000 linux-ftpd (0.11-6) unstable; urgency=low * Anonymous users other than ftp should work now (closes: #48252). -- Herbert Xu Mon, 25 Oct 1999 16:38:16 +1000 linux-ftpd (0.11-5) unstable; urgency=low * Installed files according to the FHS. * Applied PAM patch from Olaf Kirch. * Renamed PAM file to ftp. -- Herbert Xu Thu, 7 Oct 1999 22:19:58 +1000 linux-ftpd (0.11-4) unstable; urgency=low * Rewritten PAM code to remove hack for ftp prompt. * Provide/conflict with ftp-server (fixes #42412). -- Herbert Xu Fri, 10 Sep 1999 10:32:04 +1000 linux-ftpd (0.11-3) unstable; urgency=low * Fixed incorrect usage of update-inetd in postinst (fixes #40771). -- Herbert Xu Mon, 5 Jul 1999 17:46:41 +1000 linux-ftpd (0.11-2) unstable; urgency=low * Don't use absoluet paths in PAM configuration file (fixes #38985). -- Herbert Xu Sat, 19 Jun 1999 12:10:03 +1000 linux-ftpd (0.11-1) unstable; urgency=low * Split from netstd. * Added support for PAM. * Pad with zeros instead of spaces in setproctitle. * Add a note about ftp-bugs in README (fixes #29733). * Made response to STOU commands conform to RFC 1123 (fixes #32490). -- Herbert Xu Thu, 1 Apr 1999 13:45:20 +1000 debian/rules0000755000000000000000000000325111553435453010257 0ustar #!/usr/bin/make -f # Sample debian/rules that uses debhelper. GNU copyright 1997 by Joey Hess. # Uncomment this to turn on verbose mode. #export DH_VERBOSE=1 ifneq (,$(findstring noopt,$(DEB_BUILD_OPTIONS))) CONFIGUREARGS=--with-debug else CONFIGUREARGS= endif CDEFS := -D_FILE_OFFSET_BITS=64 -g LDDEFS := -Wl,-z,defs -Wl,--as-needed build: dh_testdir if [ ! -f MCONFIG ]; then \ USE_PAM=1 ./configure $(CONFIGUREARGS); \ sed -e 's/^CFLAGS=\(.*\)$$/CFLAGS=$(CDEFS) \1 -fno-strict-aliasing/' \ -e 's/^LDFLAGS=\(.*\)$$/LDFLAGS=$(LDDEFS) \1/' \ MCONFIG > MCONFIG.new; \ mv MCONFIG.new MCONFIG; \ echo CFLAGS+=-DUSE_PAM >> MCONFIG; \ echo LIBS+=-lpam >> MCONFIG; \ fi $(MAKE) clean: dh_testdir dh_testroot [ ! -f MCONFIG ] || $(MAKE) distclean dh_clean install: build dh_testdir dh_testroot dh_prep dh_installdirs cp ftpd/ftpd debian/ftpd-ssl/usr/sbin/in.ftpd cp ftpd/ftpd.8 debian/ftpd-ssl/usr/share/man/man8/in.ftpd.8 cp ftpd/*.5 debian/*.5 debian/ftpd-ssl/usr/share/man/man5 ln -sf in.ftpd.8 debian/ftpd-ssl/usr/share/man/man8/ftpd.8 cp debian/ftpchroot debian/ftpusers debian/ftpd-ssl/etc cp debian/pam.d/ftp debian/ftpd-ssl/etc/pam.d cp debian/openssl.cnf debian/ftpd-ssl/etc/ftpd-ssl/ # Build architecture-independent files here. binary-indep: build install # We have nothing to do by default. # Build architecture-dependent files here. binary-arch: build install dh_testdir dh_testroot dh_installdocs dh_installchangelogs ChangeLog dh_strip dh_compress dh_fixperms dh_installdeb dh_shlibdeps dh_gencontrol dh_md5sums dh_builddeb binary: binary-indep binary-arch .PHONY: build clean binary-indep binary-arch binary install debian/watch0000644000000000000000000000035411553435453010231 0ustar version=3 # check for new debian package of our upstream, linux-ftpd # the other possible upstreams are long dead opts="uversionmangle=s/(.*)-(.*)/$1.$2+0.3/" http://www.uk.debian.org/debian/pool/main/l/linux-ftpd/linux-ftpd_(.*).dsc debian/ftpusers0000644000000000000000000000013311553435453010771 0ustar # /etc/ftpusers: list of users disallowed ftp access. See ftpusers(5). root ftp anonymous debian/openssl.cnf0000644000000000000000000002223611553435453011356 0ustar # # OpenSSL example configuration file. # This is mostly being used for generation of certificate requests. # # This definition stops the following lines choking if HOME isn't # defined. HOME = . RANDFILE = $ENV::HOME/.rnd # Extra OBJECT IDENTIFIER info: #oid_file = $ENV::HOME/.oid oid_section = new_oids # To use this configuration file with the "-extfile" option of the # "openssl x509" utility, name here the section containing the # X.509v3 extensions to use: # extensions = # (Alternatively, use a configuration file that has only # X.509v3 extensions in its main [= default] section.) [ new_oids ] # We can add new OIDs in here for use by 'ca' and 'req'. # Add a simple OID like this: # testoid1=1.2.3.4 # Or use config file substitution like this: # testoid2=${testoid1}.5.6 #################################################################### [ ca ] default_ca = CA_default # The default ca section #################################################################### [ CA_default ] dir = ./demoCA # Where everything is kept certs = $dir/certs # Where the issued certs are kept crl_dir = $dir/crl # Where the issued crl are kept database = $dir/index.txt # database index file. #unique_subject = no # Set to 'no' to allow creation of # several ctificates with same subject. new_certs_dir = $dir/newcerts # default place for new certs. certificate = $dir/cacert.pem # The CA certificate serial = $dir/serial # The current serial number crlnumber = $dir/crlnumber # the current crl number # must be commented out to leave a V1 CRL crl = $dir/crl.pem # The current CRL private_key = $dir/private/cakey.pem# The private key RANDFILE = $dir/private/.rand # private random number file x509_extensions = usr_cert # The extentions to add to the cert # Comment out the following two lines for the "traditional" # (and highly broken) format. name_opt = ca_default # Subject Name options cert_opt = ca_default # Certificate field options # Extension copying option: use with caution. # copy_extensions = copy # Extensions to add to a CRL. Note: Netscape communicator chokes on V2 CRLs # so this is commented out by default to leave a V1 CRL. # crlnumber must also be commented out to leave a V1 CRL. # crl_extensions = crl_ext default_days = 365 # how long to certify for default_crl_days= 30 # how long before next CRL default_md = sha1 # which md to use. preserve = no # keep passed DN ordering # A few difference way of specifying how similar the request should look # For type CA, the listed attributes must be the same, and the optional # and supplied fields are just that :-) policy = policy_match # For the CA policy [ policy_match ] countryName = match stateOrProvinceName = match organizationName = match organizationalUnitName = optional commonName = supplied emailAddress = optional # For the 'anything' policy # At this point in time, you must list all acceptable 'object' # types. [ policy_anything ] countryName = optional stateOrProvinceName = optional localityName = optional organizationName = optional organizationalUnitName = optional commonName = supplied emailAddress = optional #################################################################### [ req ] default_bits = 1024 default_keyfile = privkey.pem distinguished_name = req_distinguished_name attributes = req_attributes x509_extensions = v3_ca # The extentions to add to the self signed cert # Passwords for private keys if not present they will be prompted for # input_password = secret # output_password = secret # This sets a mask for permitted string types. There are several options. # default: PrintableString, T61String, BMPString. # pkix : PrintableString, BMPString. # utf8only: only UTF8Strings. # nombstr : PrintableString, T61String (no BMPStrings or UTF8Strings). # MASK:XXXX a literal mask value. # WARNING: current versions of Netscape crash on BMPStrings or UTF8Strings # so use this option with caution! string_mask = nombstr # req_extensions = v3_req # The extensions to add to a certificate request [ req_distinguished_name ] countryName = Country Name (2 letter code) countryName_default = AU countryName_min = 2 countryName_max = 2 stateOrProvinceName = State or Province Name (full name) stateOrProvinceName_default = Some-State localityName = Locality Name (eg, city) 0.organizationName = Organization Name (eg, company) 0.organizationName_default = Internet Widgits Pty Ltd # we can do this but it is not needed normally :-) #1.organizationName = Second Organization Name (eg, company) #1.organizationName_default = World Wide Web Pty Ltd organizationalUnitName = Organizational Unit Name (eg, section) #organizationalUnitName_default = commonName = Common Name (eg, YOUR name) commonName_max = 64 emailAddress = Email Address emailAddress_max = 64 # SET-ex3 = SET extension number 3 [ req_attributes ] challengePassword = A challenge password challengePassword_min = 4 challengePassword_max = 20 unstructuredName = An optional company name [ usr_cert ] # These extensions are added when 'ca' signs a request. # This goes against PKIX guidelines but some CAs do it and some software # requires this to avoid interpreting an end user certificate as a CA. basicConstraints=CA:FALSE # Here are some examples of the usage of nsCertType. If it is omitted # the certificate can be used for anything *except* object signing. # This is OK for an SSL server. # nsCertType = server # For an object signing certificate this would be used. # nsCertType = objsign # For normal client use this is typical # nsCertType = client, email # and for everything including object signing: # nsCertType = client, email, objsign # This is typical in keyUsage for a client certificate. # keyUsage = nonRepudiation, digitalSignature, keyEncipherment # This will be displayed in Netscape's comment listbox. nsComment = "OpenSSL Generated Certificate" # PKIX recommendations harmless if included in all certificates. subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer # This stuff is for subjectAltName and issuerAltname. # Import the email address. # subjectAltName=email:copy # An alternative to produce certificates that aren't # deprecated according to PKIX. # subjectAltName=email:move # Copy subject details # issuerAltName=issuer:copy #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem #nsBaseUrl #nsRevocationUrl #nsRenewalUrl #nsCaPolicyUrl #nsSslServerName [ v3_req ] # Extensions to add to a certificate request basicConstraints = CA:FALSE keyUsage = nonRepudiation, digitalSignature, keyEncipherment [ v3_ca ] # Extensions for a typical CA # PKIX recommendation. subjectKeyIdentifier=hash authorityKeyIdentifier=keyid:always,issuer:always # This is what PKIX recommends but some broken software chokes on critical # extensions. #basicConstraints = critical,CA:true # So we do this instead. basicConstraints = CA:true # Key usage: this is typical for a CA certificate. However since it will # prevent it being used as an test self-signed certificate it is best # left out by default. # keyUsage = cRLSign, keyCertSign # Some might want this also # nsCertType = sslCA, emailCA # Include email address in subject alt name: another PKIX recommendation # subjectAltName=email:copy # Copy issuer details # issuerAltName=issuer:copy # DER hex encoding of an extension: beware experts only! # obj=DER:02:03 # Where 'obj' is a standard or added object # You can even override a supported extension: # basicConstraints= critical, DER:30:03:01:01:FF [ crl_ext ] # CRL extensions. # Only issuerAltName and authorityKeyIdentifier make any sense in a CRL. # issuerAltName=issuer:copy authorityKeyIdentifier=keyid:always,issuer:always [ proxy_cert_ext ] # These extensions should be added when creating a proxy certificate # This goes against PKIX guidelines but some CAs do it and some software # requires this to avoid interpreting an end user certificate as a CA. basicConstraints=CA:FALSE # Here are some examples of the usage of nsCertType. If it is omitted # the certificate can be used for anything *except* object signing. # This is OK for an SSL server. # nsCertType = server # For an object signing certificate this would be used. # nsCertType = objsign # For normal client use this is typical # nsCertType = client, email # and for everything including object signing: # nsCertType = client, email, objsign # This is typical in keyUsage for a client certificate. # keyUsage = nonRepudiation, digitalSignature, keyEncipherment # This will be displayed in Netscape's comment listbox. nsComment = "OpenSSL Generated Certificate" # PKIX recommendations harmless if included in all certificates. subjectKeyIdentifier=hash authorityKeyIdentifier=keyid,issuer:always # This stuff is for subjectAltName and issuerAltname. # Import the email address. # subjectAltName=email:copy # An alternative to produce certificates that aren't # deprecated according to PKIX. # subjectAltName=email:move # Copy subject details # issuerAltName=issuer:copy #nsCaRevocationUrl = http://www.domain.dom/ca-crl.pem #nsBaseUrl #nsRevocationUrl #nsRenewalUrl #nsCaPolicyUrl #nsSslServerName # This really needs to be in place for it to be a proxy certificate. proxyCertInfo=critical,language:id-ppl-anyLanguage,pathlen:3,policy:foo debian/ftpchroot.50000644000000000000000000000155411553435453011301 0ustar .\" Copyright (c) 1999 Herbert Xu (herbert@gondor.apana.org.au), .\" Copyright (c) 1994 Peter Tobias (tobias@server.et-inf.fho-emden.de), .\" This file may be distributed under the GNU General Public License. .TH FTPCHROOT 5 "1999 April 1st" "Linux" "Linux Programmer's Manual" .SH NAME ftpchroot \- file which lists users who need to be chrooted .SH DESCRIPTION \fB/etc/ftpchroot\fP is used by .BR ftpd(8); the file contains a list of users who need to be chrooted before the ftp service is offered. Blank lines and lines beginning with "#" are ignored. Remember that the whole line will be used for the username, so please don't use the "#" character after a name to comment this entry. .SH EXAMPLES .B /etc/ftpchroot may contain the following entries: .sp # .br # /etc/ftpusers .br # .br not_so_anonymous .SH FILES /etc/ftpchroot .SH "SEE ALSO" .BR ftp "(1), " ftpd "(8)" debian/preinst0000644000000000000000000000037311553435453010610 0ustar #!/bin/sh # $Id: preinst,v 1.1 1999/10/07 12:48:39 herbert Exp $ set -e # Rename old PAM conffile. if [ -n "$2" ] && dpkg --compare-versions "$2" lt 0.11-5; then cd /etc/pam.d if [ -f ftpd -a ! -f ftp ]; then cp -p ftpd ftp fi fi #DEBHELPER# debian/ftpd.xinetd0000644000000000000000000000030311553435453011344 0ustar service ftp { disable = no flags = IPv6 socket_type = stream wait = no user = root server = /usr/sbin/in.ftpd server_args = -l log_type = SYSLOG daemon info log_on_failure = HOST } debian/ftpd.examples0000644000000000000000000000002311553435453011666 0ustar debian/ftpd.xinetd debian/compat0000644000000000000000000000000211553435453010374 0ustar 7 debian/README.Debian0000644000000000000000000000656511553435453011253 0ustar ftpd for Debian --------------- (May 4th, 2010) ftpd is now able to use IPv4 and IPv6 for data transport, in active and in passive mode. The default behaviour is to service both address families. Two options, '-4' and '-6', are introduced to restrict traffic to a single addressing mode. (Prior to October 2008) ftpd now supports PAM. It is recommended that you leave the pam_ftp entry alone in the pam configuration file since ftpd uses it to figure out prompts and determining anonymity. The best way to disable anonymous ftp is to place ftp and anonymous in /etc/ftpusers. Removing the user ftp from the system also works. The -A option no longer has any effect since authentication is done by PAM. To recover its functionality, just uncomment the ftpchroot line in the pam configuration file. If you wish to receive reports from users of your ftp server, you should setup an alias for ftp-bugs@name.of.your.ftp.server. Cooperation with inetd-servers. ------------------------------- Once the address families IPv4 and IPv6 are mixed, the three usual super-servers 'openbsd-inetd', 'xinetd', and 'inetutils-inetd' behave each in its own way. The easiest one to use would be 'xinetd' in non-compatibility mode. A typical configuration is included in /usr/share/doc/ftpd/examples/ftpd.xinetd. Also 'inetutils-inetd' can use a drop-in snippet configuration deposited in '/etc/inetd.d/', but the text corresponds to the lines discussed here. The following comments concern entries in '/etc/inetd.conf'. These observations are written with 'net.ipv6.bindv6only=1' in effect. * openbsd-inetd (formerly netkit-inetd) Here 'tcp' and 'udp' are restricted to IPv4 sockets. Their counterparts are 'tcp6' and 'udp6'. Thus a dual listener needs a configuration similar to this: # /etc/inetd.conf ftp stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.ftpd -l ftp stream tcp6 nowait root /usr/sbin/tcpd /usr/sbin/in.ftpd -l Observe the minute difference compared to 'inetutils-inetd' as stated below, only one 'tcp6' versus one 'tcp4'. * xinetd When this server is used in compatibility mode (controlled by INETD_COMPAT=Yes in '/etc/default/xinetd') and when an IPv6 enabled host is detected, the protocols 'tcp' and 'udp', as used in '/etc/inetd.conf', will automatically activate IPv4 as well as IPv6. To single out one address family, use 'tcp4' or 'tcp6'. * inetutils-inetd On a dual stacked system, 'inetutils-inetd' considers 'tcp' and 'tcp6' to be synonymous. Thus, to listen for both address families one must write two entries: # /etc/inetd.conf ftp stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.ftpd ftp stream tcp4 nowait root /usr/sbin/tcpd /usr/sbin/in.ftpd Globbing Attacks ---------------- Globbing attacks aimed at exhausting memory/CPU resources (e.g., ls ../*/../*/../*/../*/../*/../*/../*/../*/../*/../*/../*/../*/../*) can be countered by setting the appropriate resource limits in /etc/security/limits.conf. To do so, you need to make sure that /etc/pam.d/ftp contains the line session required pam_limits.so Which is the case by default. The limits which are most important on Linux are "as" and "cpu". For example, to limit the memory usage to 10MB, you should put ftp hard as 10240 in /etc/security/limits.conf. Herbert $Id: README.Debian,v 1.4 2002/10/06 22:23:49 herbert Exp $ debian/source/0000755000000000000000000000000011553435453010476 5ustar debian/source/format0000644000000000000000000000001411553435453011704 0ustar 3.0 (quilt) debian/ftpchroot0000644000000000000000000000011411553435453011125 0ustar # /etc/ftpchroot: list of users who needs to be chrooted. See ftpchroot(5). debian/prerm0000644000000000000000000000022711553435453010247 0ustar #!/bin/sh # $Id: prerm,v 1.1 1999/04/16 07:00:29 herbert Exp $ set -e update-inetd --pattern '/usr/sbin/in\.ftpd' --multi --disable ftp #DEBHELPER# debian/control0000644000000000000000000000161311553435453010602 0ustar Source: linux-ftpd-ssl Section: net Priority: extra Maintainer: Ian Beckwith Build-Depends: bison, debhelper (>= 7), libpam0g-dev | libpam-dev, libssl-dev (>= 0.9.8g-9) Standards-Version: 3.9.1 Package: ftpd-ssl Architecture: any Depends: openbsd-inetd | inet-superserver, libpam-modules, openssl (>= 0.9.8g-9), ${shlibs:Depends}, ${misc:Depends} Provides: ftp-server Conflicts: ftp-server, ftpd Replaces: ftpd Description: FTP server with SSL encryption support This is the netkit ftp server with encryption support. . ftpd-ssl replaces normal ftpd using SSL authentication and encryption. It interoperates with normal ftp. It checks if the other side is also talking SSL, if not it falls back to normal ftp protocol. . Advantages over normal ftp(d): Your passwords and the data you send will not go in cleartext over the line. Nobody can get it with tcpdump or similar tools. debian/patches/0000755000000000000000000000000011553435453010625 5ustar debian/patches/550-fix_warnings.diff0000644000000000000000000000372411553435453014472 0ustar Description: Fix all warnings in source Author: Ian Beckwith Index: linux-ftpd-ssl/ftpd/ftpcmd.y =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpcmd.y 2010-06-14 01:33:25.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpcmd.y 2010-06-14 01:33:25.000000000 +0100 @@ -113,6 +113,7 @@ typedef struct ssl_st SSL; int SSL_write(SSL *ssl,const char *buf,int num); extern int do_ssl_start(void); +extern int ssl_getc(SSL *ssl_con); extern int ssl_secure_flag; extern int ssl_active_flag; extern SSL *ssl_con; Index: linux-ftpd-ssl/ftpd/ftpd.c =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpd.c 2010-06-14 01:33:25.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpd.c 2010-06-14 01:33:25.000000000 +0100 @@ -185,6 +185,8 @@ #include "ssl_port.h" +int +do_ssl_start(void); int ssl_getc(SSL *ssl_con); static int Index: linux-ftpd-ssl/ftpd/ssl_port.h =================================================================== --- linux-ftpd-ssl.orig/ftpd/ssl_port.h 2010-06-14 01:33:25.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ssl_port.h 2010-06-14 01:33:25.000000000 +0100 @@ -19,6 +19,7 @@ #include #define OLDPROTO NOPROTO +#undef NOPROTO #define NOPROTO #include #undef NOPROTO Index: linux-ftpd-ssl/ftpd/sslapp.c =================================================================== --- linux-ftpd-ssl.orig/ftpd/sslapp.c 2010-06-14 01:33:25.000000000 +0100 +++ linux-ftpd-ssl/ftpd/sslapp.c 2010-06-14 01:33:25.000000000 +0100 @@ -34,7 +34,7 @@ /* fwd decl */ static void -client_info_callback(SSL *s, int where, int ret); +client_info_callback(const SSL *s, int where, int ret); int do_ssleay_init(int server) @@ -155,7 +155,7 @@ static void -client_info_callback(SSL *s, int where, int ret) +client_info_callback(const SSL *s, int where, int ret) { if (where==SSL_CB_CONNECT_LOOP) { BIO_printf(bio_err,"SSL_connect:%s %s\r\n", debian/patches/002-from_sarge.diff0000644000000000000000000001475311553435453014114 0ustar Description: Patches taken from linux-ftpd_0.17-20sarge2.diff.gz. Difference constructed against linux-ftpd_0.17-13.diff.gz. Author: Herber Xu Robert Millan Alberto Gonzalez Iniesta X-Comment: Contributions by Dean Gaudet and Paul Szabo. Forwarded: no Last-Update: 2006-09-25 diff -u linux-ftpd-0.17/ftpd/ftpcmd.y linux-ftpd-0.17/ftpd/ftpcmd.y --- linux-ftpd-0.17/ftpd/ftpcmd.y +++ linux-ftpd-0.17/ftpd/ftpcmd.y @@ -114,6 +114,7 @@ %union { intmax_t i; char *s; + const char *cs; } %token @@ -313,12 +314,12 @@ | LIST check_login CRLF { if ($2) - retrieve("/bin/ls -lgA", ""); + retrieve("/bin/ls -lA", ""); } | LIST check_login SP pathname CRLF { if ($2 && $4 != NULL) - retrieve("/bin/ls -lgA %s", $4); + retrieve("/bin/ls -lA %s", $4); if ($4 != NULL) free($4); } @@ -1053,7 +1054,7 @@ /* NOTREACHED */ } state = p->state; - yylval.s = (char *)p->name; /* XXX */ + yylval.cs = p->name; return (p->token); } break; @@ -1079,7 +1080,7 @@ /* NOTREACHED */ } state = p->state; - yylval.s = (char *) p->name; /* XXX */ + yylval.cs = p->name; return (p->token); } state = CMD; diff -u linux-ftpd-0.17/ftpd/ftpd.8 linux-ftpd-0.17/ftpd/ftpd.8 --- linux-ftpd-0.17/ftpd/ftpd.8 +++ linux-ftpd-0.17/ftpd/ftpd.8 @@ -46,7 +46,7 @@ Internet File Transfer Protocol server .Sh SYNOPSIS .Nm ftpd -.Op Fl AdDhlMPSU +.Op Fl AdDhlMnPSU .Op Fl T Ar maxtimeout .Op Fl t Ar timeout .Op Fl u Ar mask @@ -105,12 +105,8 @@ the IP number the client connected to, and located inside .Pa ~ftp is used instead. -.It Fl p -Disable passive mode ftp connections. This is useful if you are behind -a firewall that refuses connections to arbitrary high numbered ports. -Many ftp clients try passive mode first and do not always react gracefully -to a server that refuses connections to the port it asked the client to -connect to. +.It Fl n +Use numeric IP addresses in logs instead of doing hostname lookup. .It Fl P Permit illegal port numbers or addresses for PORT command initiated connects. By default @@ -369,7 +365,15 @@ (or whatever your .Xr ls command is linked to) -must be present. Note that if you're using a 2.2.* or later Linux kernel, +must be present. +In order to read +.Xr passwd 5 +and +.Xr group 5 , +the library +.Xr libnss_files.so.2 +is also needed. +Note that if you're using a 2.2.* or later Linux kernel, .Xr ld-linux.so.2 must be executable as well as readable (555). All other files should be mode 444. diff -u linux-ftpd-0.17/ftpd/ftpd.c linux-ftpd-0.17/ftpd/ftpd.c --- linux-ftpd-0.17/ftpd/ftpd.c +++ linux-ftpd-0.17/ftpd/ftpd.c @@ -165,7 +165,8 @@ #endif int debug = 0; int timeout = 900; /* timeout after 15 minutes of inactivity */ -int maxtimeout = 7200;/* don't allow idle time to be set beyond 2 hours */ +int maxtimeout = 7200; /* don't allow idle time to be set beyond 2 hours */ +int numeric_hosts = 0; /* log numeric IP rather than doing lookup */ int logging; int high_data_ports = 0; int anon_only = 0; @@ -312,7 +313,7 @@ socklen_t addrlen; char *cp, line[LINE_MAX]; FILE *fd; - const char *argstr = "AdDhlMSt:T:u:UvP"; + const char *argstr = "AdDhlMnSt:T:u:UvP"; struct hostent *hp; #ifdef __linux__ @@ -372,6 +373,10 @@ multihome = 1; break; + case 'n': + numeric_hosts = 1; + break; + case 'S': stats = 1; break; @@ -906,7 +911,6 @@ static int pam_doit(void) { - char *user; int error; error = pam_authenticate(pamh, 0); @@ -926,6 +930,8 @@ return 1; } if (error == PAM_SUCCESS) { + const void *vp; + /* Alright, we got it */ error = pam_acct_mgmt(pamh, 0); if (error == PAM_SUCCESS) @@ -933,8 +939,10 @@ if (error == PAM_SUCCESS) error = pam_setcred(pamh, PAM_ESTABLISH_CRED); if (error == PAM_SUCCESS) - error = pam_get_item(pamh, PAM_USER, (const void **) &user); + error = pam_get_item(pamh, PAM_USER, &vp); if (error == PAM_SUCCESS) { + const char *user = vp; + if (strcmp(user, "ftp") == 0) { guest = 1; } @@ -1151,6 +1159,13 @@ } strcpy(pw->pw_dir, "/"); setenv("HOME", "/", 1); + } + /* PSz 25 Aug 06 chdir for real users done after setting UID */ + if (seteuid((uid_t)pw->pw_uid) < 0) { + reply(550, "Can't set uid."); + goto bad; + } + if (guest || dochroot) { /* do nothing, handled above */ } else if (chdir(pw->pw_dir) < 0) { if (chdir("/") < 0) { reply(530, "User %s: can't change directory to %s.", @@ -1159,10 +1174,7 @@ } else lreply(230, "No directory! Logging in with home=/"); } - if (seteuid((uid_t)pw->pw_uid) < 0) { - reply(550, "Can't set uid."); - goto bad; - } + sigfillset(&allsigs); sigprocmask(SIG_UNBLOCK,&allsigs,NULL); @@ -1400,7 +1412,8 @@ goto bad; sleep(tries); } - (void) seteuid((uid_t)pw->pw_uid); +/* PSz 25 Aug 06 Check return status */ + if (seteuid((uid_t)pw->pw_uid) != 0) _exit(1); sigfillset(&allsigs); sigprocmask (SIG_UNBLOCK, &allsigs, NULL); @@ -1432,7 +1445,8 @@ bad: /* Return the real value of errno (close may change it) */ t = errno; - (void) seteuid((uid_t)pw->pw_uid); +/* PSz 25 Aug 06 Check return status */ + if (seteuid((uid_t)pw->pw_uid) != 0) _exit(1); sigfillset (&allsigs); sigprocmask (SIG_UNBLOCK, &allsigs, NULL); (void) close(s); @@ -1786,7 +1800,7 @@ int c; char line[LINE_MAX]; - (void)snprintf(line, sizeof(line), "/bin/ls -lgA %s", filename); + (void)snprintf(line, sizeof(line), "/bin/ls -lA %s", filename); fin = ftpd_popen(line, "r"); lreply(211, "status of %s:", filename); while ((c = getc(fin)) != EOF) { @@ -2063,10 +2077,11 @@ static void dolog(struct sockaddr_in *sn) { - struct hostent *hp = gethostbyaddr((char *)&sn->sin_addr, - sizeof(struct in_addr), AF_INET); + struct hostent *hp; - if (hp) + if (!numeric_hosts && + (hp = gethostbyaddr((char *)&sn->sin_addr, + sizeof(struct in_addr), AF_INET))) (void) strncpy(remotehost, hp->h_name, sizeof(remotehost)-1); else (void) strncpy(remotehost, inet_ntoa(sn->sin_addr), --- linux-ftpd-0.17.orig/ftpd/popen.c +++ linux-ftpd-0.17/ftpd/popen.c @@ -169,8 +169,13 @@ * XXX: this doesn't seem right... and shouldn't * we initgroups, or at least setgroups(0,0)? */ - setgid(getegid()); - setuid(i); + +/* + * PSz 25 Aug 06 Must check the return status of these setgid/setuid calls, + * see http://www.bress.net/blog/archives/34-setuid-madness.html + */ + if ( setgid(geteuid()) != 0 ) _exit(1); + if ( setuid(i) != 0 ) _exit(1); #ifndef __linux__ /* debian/patches/030-manpage_typos.diff0000644000000000000000000000165511553435453014634 0ustar Description: Spelling error in manual page. Author: Alberto Gonzalez Iniesta Forwarded: not-needed Last-Update: 2010-07-08 --- linux-ftpd-0.17.orig/ftpd/ftpd.8 2010-07-08 13:34:37.251457013 +0200 +++ linux-ftpd-0.17/ftpd/ftpd.8 2010-07-08 13:35:05.667542648 +0200 @@ -65,13 +65,13 @@ Available options: .Bl -tag -width Ds .It Fl 4 -Use IPv4 addressing only. Th default is to offer service for both families, IPv6 and IPv4. +Use IPv4 addressing only. The default is to offer service for both families, IPv6 and IPv4. .It Fl 6 Only provide IPv6 addressing capability. .It Fl A Permit only anonymous ftp connections or accounts listed in .Pa /etc/ftpchroot. -Other connection attempts are refused. This option is nolonger effective if +Other connection attempts are refused. This option is no longer effective if PAM is enabled. Please refer to the README file for instructions to doing this with PAM. .It Fl d debian/patches/024-failing_va_list.diff0000644000000000000000000000233511553435453015117 0ustar Description: Reinitialize variable argument list for vsyslog(). The use of vprintf(fmt, ap) leaves the second argument in an undefined state after execution. On a system using the amd64 architecture, this leads consistently to segmentation faults. The solution is to insert the required initialization before the call to vsyslog(). Author: Mats Erik Andersson Forwarded: no Last-Update: 2010-05-09 --- linux-ftpd-0.17/ftpd/ftpd.c.no-va_start +++ linux-ftpd-0.17/ftpd/ftpd.c @@ -2051,10 +2051,17 @@ reply(int n, char *fmt, va_dcl va_alist) (void)printf("%d ", n); (void)vprintf(fmt, ap); (void)printf("\r\n"); + va_end(ap); (void)fflush(stdout); if (debug) { +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif syslog(LOG_FTP | LOG_DEBUG, "<--- %d ", n); vsyslog(LOG_FTP | LOG_DEBUG, fmt, ap); + va_end(ap); } } @@ -2077,10 +2084,17 @@ lreply(n, fmt, va_alist) (void)printf("%d- ", n); (void)vprintf(fmt, ap); (void)printf("\r\n"); + va_end(ap); (void)fflush(stdout); if (debug) { +#ifdef __STDC__ + va_start(ap, fmt); +#else + va_start(ap); +#endif syslog(LOG_FTP | LOG_DEBUG, "<--- %d- ", n); vsyslog(LOG_FTP | LOG_DEBUG, fmt, ap); + va_end(ap); } } debian/patches/016-family_independence.diff0000644000000000000000000005134111553435453015751 0ustar Description: Make the TCP transport code independent of address family. Make sure to eliminate as much outdated dependency on AF_INET, even before migrating to true support for AF_INET6. . 1. Rewrite dolog() and check_host(). . 2. Eliminate inet_ntoa(), gethostbyname(), gethostbyaddr(). . 3. Introduce helper functions get_port() and set_port() in order to hide family dependency, as well as representation in network byte order. This isolates use of ntohs() and htons() to the above two functions, with a single exception. . 4. Make sure that the daemon initialization depends only on a single AF_INET used for getaddrinfo(). This will later be replaced by AF_UNSPEC. . 5. Make name and address lookup in main() independent of address family. . 6. Reconstruct passive() to inherit address family from the controlling socket, then building the listening socket in an address independent manner. . 7. Let statcmd() and passive() report on IPv6 sockets using the EPSV semantics '(|||portnum|)'. . 8. Let the parser in ftpcmd.y use getaddrinfo() with NI_NUMERICHOST when constructing the IP-address, instead of manipulating byte fields. Likewise, hide port extraction in get_port(). Author: Mats Erik Andersson X-Comment: This code is fully independent of any USAGI code, which is in use by the OpenBSD strand of this software. Forwarded: not-needed Last-Update: 2010-04-30 --- linux-ftpd-0.17.debian/ftpd/ftpd.c +++ linux-ftpd-0.17/ftpd/ftpd.c @@ -157,6 +157,7 @@ int daemon_mode = 0; int data; +in_port_t data_port; jmp_buf errcatch, urgcatch; int logged_in; struct passwd *pw; @@ -259,7 +260,7 @@ static void myoob __P((int)); static int checkuser __P((const char *, const char *)); static FILE *dataconn __P((const char *, off_t, const char *, int)); -static void dolog __P((struct sockaddr_in *)); +static void dolog __P((struct sockaddr *)); static const char *curdir __P((void)); static void end_login __P((void)); static FILE *getdatasock __P((const char *)); @@ -276,7 +277,7 @@ static void authentication_setup(const char *); #if defined(TCPWRAPPERS) -static int check_host __P((struct sockaddr_in *)); +static int check_host __P((struct sockaddr *)); #endif void logxfer __P((const char *, off_t, time_t)); @@ -306,6 +307,63 @@ curdir(void) return (guest ? path+1 : path); } +static uint32_t +get_ipv4address(struct sockaddr * ss) +{ + if (ss->sa_family == AF_INET) + return ntohl(((struct sockaddr_in *) ss)->sin_addr.s_addr); + else if(ss->sa_family == AF_INET6) { + return ntohl(((struct sockaddr_in6 *) ss)->sin6_addr.s6_addr32[3]); + } else + /* Should Never happen. Sensible return value? */ + return (uint32_t) -2; +} /* get_ipv4address( struct sockaddr_storage * ) */ + +static int +get_port(struct sockaddr * sa) +{ + switch (sa->sa_family) { + case AF_INET6: + return ntohs(((struct sockaddr_in6 *) sa)->sin6_port); + break; + case AF_INET: + default: + return ntohs(((struct sockaddr_in *) sa)->sin_port); + } +} /* get_port( struct sockaddr * ) */ + +static void +set_port(struct sockaddr * sa, short int port) +{ + switch (sa->sa_family) { + case AF_INET6: + ((struct sockaddr_in6 *) sa)->sin6_port = htons(port); + break; + case AF_INET: + default: + ((struct sockaddr_in *) sa)->sin_port = htons(port); + } +} /* set_port( struct sockaddr *, short int ) */ + +#ifdef BREAKRFC +static int +cmp_addresses(struct sockaddr * left, struct sockaddr * right) +{ + if (left->sa_family != right->sa_family) + /* Should mapped or compatible IPv4 be handled? */ + return 1; + + if (left->sa_family == AF_INET6) + return IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *) left)->sin6_addr, + &((struct sockaddr_in6 *) right)->sin6_addr) + ? 0 : 1; + + return (memcmp(&((struct sockaddr_in *) left)->sin_addr, + &((struct sockaddr_in *) right)->sin_addr, + sizeof(struct in_addr))); +} /* cmp_addresses(struct sockaddr *, struct sockaddr *) */ +#endif + int main(int argc, char *argv[], char **envp) { @@ -314,7 +372,7 @@ main(int argc, char *argv[], char **envp char *cp, line[LINE_MAX]; FILE *fd; const char *argstr = "AdDhlMnSt:T:u:UvP"; - struct hostent *hp; + struct addrinfo hints, *aiptr; #ifdef __linux__ initsetproctitle(argc, argv, envp); @@ -431,8 +489,9 @@ main(int argc, char *argv[], char **envp openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP); if (daemon_mode) { - int ctl_sock, fd2; + int ctl_sock, fd2, rc; struct servent *sv; + struct addrinfo hints, *ai, *aiptr; /* * Detach from parent. @@ -452,31 +511,53 @@ main(int argc, char *argv[], char **envp exit(1); } /* - * Open a socket, bind it to the FTP port, and start - * listening. + * Open a socket, bind it to the FTP port, + * and begin listening for calls. */ - ctl_sock = socket(AF_INET, SOCK_STREAM, 0); - if (ctl_sock < 0) { - syslog(LOG_FTP | LOG_ERR, "control socket: %m"); + memset(&hints, 0, sizeof(hints)); + hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_INET; + + if ((rc = getaddrinfo(NULL, "ftp", &hints, &aiptr))) { + syslog(LOG_FTP | LOG_ERR, + "getaddrinfo for ftp failed (%s)", + gai_strerror(rc)); exit(1); } - if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR, - (char *)&on, sizeof(on)) < 0) - syslog(LOG_FTP | LOG_ERR, "control setsockopt: %m");; - server_addr.sin_family = AF_INET; - server_addr.sin_addr.s_addr = INADDR_ANY; - server_addr.sin_port = sv->s_port; - if (bind(ctl_sock, (struct sockaddr *)&server_addr, - sizeof(server_addr))) { - syslog(LOG_FTP | LOG_ERR, "control bind: %m"); - exit(1); + /* Loop over possible alternatives. */ + for (ai = aiptr; ai; ai = ai->ai_next) { + if ((ctl_sock = socket(ai->ai_family, + ai->ai_socktype, ai->ai_protocol)) + < 0) + continue; + if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR, + (char *)&on, sizeof(on)) < 0) + syslog(LOG_FTP | LOG_ERR, "control setsockopt: %m");; + + if (bind(ctl_sock, ai->ai_addr, ai->ai_addrlen)) { + close(ctl_sock); + continue; + } + if (listen(ctl_sock, 32) < 0) { + close(ctl_sock); + continue; + } + + /* Socket successfully established: bound and listening. */ + break; } - if (listen(ctl_sock, 32) < 0) { - syslog(LOG_FTP | LOG_ERR, "control listen: %m"); + + freeaddrinfo(aiptr); + + if (ai == NULL) { + /* Failure, no socket established. */ + syslog(LOG_FTP | LOG_ERR, "listening socket failed"); exit(1); } + /* - * Loop forever accepting connection requests and forking off + * Loop forever, accepting connection requests, and forking off * children to handle them. */ while (1) { @@ -495,7 +576,7 @@ main(int argc, char *argv[], char **envp #if defined(TCPWRAPPERS) /* ..in the child. */ - if (!check_host(&his_addr)) + if (!check_host((struct sockaddr *) &his_addr)) exit(1); #endif /* TCPWRAPPERS */ } else { @@ -527,7 +608,7 @@ main(int argc, char *argv[], char **envp if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) syslog(LOG_FTP | LOG_WARNING, "setsockopt (IP_TOS): %m"); #endif - data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); + data_port = get_port((struct sockaddr *) &ctrl_addr) - 1; /* Try to handle urgent data inline */ #ifdef SO_OOBINLINE @@ -539,7 +620,7 @@ main(int argc, char *argv[], char **envp if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) syslog(LOG_FTP | LOG_ERR, "fcntl F_SETOWN: %m"); #endif - dolog(&his_addr); + dolog((struct sockaddr *) &his_addr); /* * Set up default state */ @@ -574,22 +655,21 @@ main(int argc, char *argv[], char **envp } (void) gethostname(hostname, sizeof(hostname)); + memset(&hints, 0, sizeof(hints)); + hints.ai_socktype = SOCK_STREAM; + hints.ai_family = AF_UNSPEC; + hints.ai_flags = AI_ADDRCONFIG | AI_CANONNAME; + /* Make sure hostname is fully qualified. */ - hp = gethostbyname(hostname); - if (hp != NULL) - strcpy(hostname, hp->h_name); - - if (multihome) { - hp = gethostbyaddr((char *) &ctrl_addr.sin_addr, - sizeof (struct in_addr), AF_INET); - if (hp != NULL) { - strcpy(dhostname, hp->h_name); - } else { - /* Default. */ - strcpy(dhostname, inet_ntoa(ctrl_addr.sin_addr)); - } + if (getaddrinfo(hostname, NULL, &hints, &aiptr) == 0) { + strncpy(hostname, aiptr->ai_canonname, sizeof(hostname)); + freeaddrinfo(aiptr); } + if (multihome) + (void) getnameinfo((struct sockaddr *) &ctrl_addr, addrlen, + dhostname, sizeof(dhostname), NULL, 0, 0); + reply(220, "%s FTP server (%s) ready.", (multihome ? dhostname : hostname), version); (void) setjmp(errcatch); @@ -1392,21 +1472,19 @@ static FILE * getdatasock(const char *mo sigfillset(&allsigs); sigprocmask (SIG_BLOCK, &allsigs, NULL); (void) seteuid((uid_t)0); - s = socket(AF_INET, SOCK_STREAM, 0); + s = socket(his_addr.sin_family, SOCK_STREAM, 0); if (s < 0) goto bad; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0) goto bad; /* anchor socket to avoid multi-homing problems */ -#ifndef __linux__ - data_source.sin_len = sizeof(struct sockaddr_in); -#endif - data_source.sin_family = AF_INET; - data_source.sin_addr = ctrl_addr.sin_addr; + memcpy(&data_source, &ctrl_addr, sizeof(data_source)); + set_port((struct sockaddr *) &data_source, data_port); + for (tries = 1; ; tries++) { if (bind(s, (struct sockaddr *)&data_source, - sizeof(data_source)) >= 0) + sizeof(data_source)) >= 0) break; if (errno != EADDRINUSE || tries > 10) goto bad; @@ -1468,7 +1546,7 @@ static FILE * dataconn(const char *name, } else sizebuf[0] = '\0'; if (pdata >= 0) { - struct sockaddr_in from; + struct sockaddr_storage from; int s; socklen_t fromlen = sizeof(from); @@ -1482,7 +1560,7 @@ static FILE * dataconn(const char *name, pdata = -1; return (NULL); } - if (ntohs(from.sin_port) < IPPORT_RESERVED) { + if (get_port((struct sockaddr *) &from) < IPPORT_RESERVED) { perror_reply(425, "Can't build data connection"); (void) close(pdata); (void) close(s); @@ -1490,7 +1568,9 @@ static FILE * dataconn(const char *name, return (NULL); } #ifdef BREAKRFC - if (from.sin_addr.s_addr != his_addr.sin_addr.s_addr) { + //if (from.sin_addr.s_addr != his_addr.sin_addr.s_addr) { + if (cmp_addresses((struct sockaddr *) &from, + (struct sockaddr *) &his_addr)) { perror_reply(435, "Can't build data connection"); (void) close(pdata); (void) close(s); @@ -1527,13 +1607,19 @@ static FILE * dataconn(const char *name, return (fdopen(data, mode)); } if (usedefault) - data_dest = his_addr; + memcpy(&data_dest, &his_addr, sizeof(data_dest)); usedefault = 1; file = getdatasock(mode); if (file == NULL) { + char ipaddr[INET6_ADDRSTRLEN], port[12]; + + (void) getnameinfo((struct sockaddr *) &data_source, + sizeof(struct sockaddr_storage), + ipaddr, sizeof(ipaddr), port, sizeof(port), + NI_NUMERICHOST); + reply(425, "Can't create data socket (%s,%d): %s.", - inet_ntoa(data_source.sin_addr), - ntohs(data_source.sin_port), strerror(errno)); + ipaddr, port, strerror(errno)); return (NULL); } data = fileno(file); @@ -1542,15 +1628,17 @@ static FILE * dataconn(const char *name, * attempt to connect to reserved port on client machine; * this looks like an attack */ - if (ntohs(data_dest.sin_port) < IPPORT_RESERVED || - ntohs(data_dest.sin_port) == 2049) { /* XXX */ + if (get_port((struct sockaddr *) &data_dest) < IPPORT_RESERVED || + get_port((struct sockaddr *) &data_dest) == 2049) { /* XXX */ perror_reply(425, "Can't build data connection"); (void) fclose(file); data = -1; return NULL; } #ifdef BREAKRFC - if (data_dest.sin_addr.s_addr != his_addr.sin_addr.s_addr) { + //if (data_dest.sin_addr.s_addr != his_addr.sin_addr.s_addr) { + if (cmp_addresses((struct sockaddr *) &data_dest, + (struct sockaddr *) &his_addr)) { perror_reply(435, "Can't build data connection"); (void) fclose(file); data = -1; @@ -1826,14 +1914,19 @@ void statcmd(void) { - struct sockaddr_in *sn; - u_char *a, *p; + struct sockaddr *sn; + char ipaddr[INET6_ADDRSTRLEN]; lreply(211, "%s FTP server status:", hostname, version); printf(" %s\r\n", version); printf(" Connected to %s", remotehost); - if (!isdigit(remotehost[0])) - printf(" (%s)", inet_ntoa(his_addr.sin_addr)); + if (!isdigit(remotehost[0])) { + (void) getnameinfo((struct sockaddr *) &his_addr, + sizeof(struct sockaddr_storage), + ipaddr, sizeof(ipaddr), NULL, 0, + NI_NUMERICHOST); + printf(" (%s)", ipaddr); + } printf("\r\n"); if (logged_in) { if (guest) @@ -1859,17 +1952,24 @@ void statcmd(void) printf(" Data connection open\r\n"); else if (pdata != -1) { printf(" in Passive mode"); - sn = &pasv_addr; + sn = (struct sockaddr *) &pasv_addr; goto printaddr; } else if (usedefault == 0) { printf(" PORT"); - sn = &data_dest; + sn = (struct sockaddr *) &data_dest; printaddr: - a = (u_char *) &sn->sin_addr; - p = (u_char *) &sn->sin_port; #define UC(b) (((int) b) & 0xff) - printf(" (%d,%d,%d,%d,%d,%d)\r\n", UC(a[0]), - UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); + if (sn->sa_family == AF_INET6) + printf(" (|||%d|)\r\n", get_port(sn)); + else { + uint32_t ip4ad = get_ipv4address(sn); + in_port_t port = get_port(sn); + + printf(" (%d,%d,%d,%d,%d,%d)\r\n", + UC(ip4ad >> 24), UC(ip4ad >> 16), + UC(ip4ad >> 8), UC(ip4ad), + UC(port >> 8), UC(port)); + } #undef UC } else printf(" No data connection\r\n"); @@ -2075,18 +2175,17 @@ ack("RNTO"); } -static void dolog(struct sockaddr_in *sn) +static void dolog(struct sockaddr *sa) { - struct hostent *hp; + char host[NI_MAXHOST]; - if (!numeric_hosts && - (hp = gethostbyaddr((char *)&sn->sin_addr, - sizeof(struct in_addr), AF_INET))) - (void) strncpy(remotehost, hp->h_name, sizeof(remotehost)-1); - else - (void) strncpy(remotehost, inet_ntoa(sn->sin_addr), - sizeof(remotehost)-1); + getnameinfo(sa, sizeof(struct sockaddr_storage), + host, sizeof(host), NULL, 0, + numeric_hosts ? NI_NUMERICHOST : 0); + + (void) strncpy(remotehost, host, sizeof(remotehost)-1); remotehost[sizeof(remotehost)-1] = '\0'; + #ifdef HASSETPROCTITLE snprintf(proctitle, sizeof(proctitle), "%s: connected", remotehost); setproctitle("%s", proctitle); @@ -2158,9 +2257,8 @@ void passive(void) #ifdef IP_PORTRANGE int on; #else - u_short port; + in_port_t port; #endif - char *p, *a; if (pw == NULL) { reply(530, "Please login with USER and PASS"); @@ -2168,12 +2266,14 @@ void passive(void) } if (pdata >= 0) close(pdata); - pdata = socket(AF_INET, SOCK_STREAM, 0); + pdata = socket(his_addr.sin_family, SOCK_STREAM, 0); if (pdata < 0) { perror_reply(425, "Can't open passive connection"); return; } + memcpy(&pasv_addr, &ctrl_addr, sizeof(pasv_addr)); + #ifdef IP_PORTRANGE on = high_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, @@ -2184,8 +2284,8 @@ void passive(void) #define FTP_DATA_TOP 44999 if (high_data_ports) { for (port = FTP_DATA_BOTTOM; port <= FTP_DATA_TOP; port++) { - pasv_addr = ctrl_addr; - pasv_addr.sin_port = htons(port); + set_port((struct sockaddr *) &pasv_addr, port); + if (bind(pdata, (struct sockaddr *) &pasv_addr, sizeof(pasv_addr)) == 0) break; @@ -2198,8 +2298,7 @@ void passive(void) else #endif { - pasv_addr = ctrl_addr; - pasv_addr.sin_port = 0; + set_port((struct sockaddr *) &pasv_addr, 0); if (bind(pdata, (struct sockaddr *)&pasv_addr, sizeof(pasv_addr)) < 0) goto pasv_error; @@ -2210,13 +2309,24 @@ void passive(void) goto pasv_error; if (listen(pdata, 1) < 0) goto pasv_error; - a = (char *) &pasv_addr.sin_addr; - p = (char *) &pasv_addr.sin_port; #define UC(b) (((int) b) & 0xff) - reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", UC(a[0]), - UC(a[1]), UC(a[2]), UC(a[3]), UC(p[0]), UC(p[1])); + if (((struct sockaddr *) &pasv_addr)->sa_family == AF_INET6) + reply(229, "Extended Passive Mode OK (|||%d|)", + get_port((struct sockaddr *) &pasv_addr)); + else { + uint32_t ip4ad = get_ipv4address((struct sockaddr *) &pasv_addr); + in_port_t port = get_port((struct sockaddr *) &pasv_addr); + + reply(227, "Entering Passive Mode (%d,%d,%d,%d,%d,%d)", + UC(ip4ad >> 24), UC(ip4ad >> 16), + UC(ip4ad >> 8), UC(ip4ad), + UC(port >> 8), UC(port)); + } + +#undef UC + return; pasv_error: @@ -2476,23 +2586,25 @@ } #if defined(TCPWRAPPERS) -static int check_host(struct sockaddr_in *sin) +static int check_host(struct sockaddr *sa) { - struct hostent *hp = gethostbyaddr((char *)&sin->sin_addr, - sizeof(struct in_addr), AF_INET); - char *addr = inet_ntoa(sin->sin_addr); + char ipaddr[INET6_ADDRSTRLEN]; + char host[NI_MAXHOST]; + + getnameinfo(sa, sizeof(struct sockaddr_storage), + ipaddr, sizeof(ipaddr), NULL, 0, NI_NUMERICHOST); - if (hp) { - if (!hosts_ctl("ftpd", hp->h_name, addr, STRING_UNKNOWN)) { + if (! getnameinfo(sa, sizeof(struct sockaddr_storage), + host, sizeof(host), NULL, 0, NI_NAMEREQD) ) { + if (!hosts_ctl("ftpd", host, ipaddr, STRING_UNKNOWN)) { syslog(LOG_FTP | LOG_NOTICE, - "tcpwrappers rejected: %s [%s]", - hp->h_name, addr); + "tcpwrappers rejected: %s [%s]", host, ipaddr); return (0); } } else { - if (!hosts_ctl("ftpd", STRING_UNKNOWN, addr, STRING_UNKNOWN)) { + if (!hosts_ctl("ftpd", STRING_UNKNOWN, ipaddr, STRING_UNKNOWN)) { syslog(LOG_FTP | LOG_NOTICE, - "tcpwrappers rejected: [%s]", addr); + "tcpwrappers rejected: [%s]", ipaddr); return (0); } } --- linux-ftpd-0.17.debian/ftpd/ftpcmd.y +++ linux-ftpd-0.17/ftpd/ftpcmd.y @@ -51,6 +51,7 @@ #include #include +#include #include #include @@ -116,6 +117,35 @@ extern struct tab cmdtab[]; extern struct tab sitetab[]; +static int +get_port(struct sockaddr * sa) +{ + switch (sa->sa_family) { + case AF_INET6: + return (ntohs(((struct sockaddr_in6 *) sa)->sin6_port)); + break; + case AF_INET: + default: + return (ntohs(((struct sockaddr_in *) sa)->sin_port)); + } +} /* get_port( struct sockaddr * ) */ + +static int +cmp_addresses(struct sockaddr * left, struct sockaddr * right) +{ + if (left->sa_family != right->sa_family) + return 1; + + if (left->sa_family == AF_INET6) + return IN6_ARE_ADDR_EQUAL(&((struct sockaddr_in6 *) left)->sin6_addr, + &((struct sockaddr_in6 *) right)->sin6_addr) + ? 0 : 1; + + return (memcmp(&((struct sockaddr_in *) left)->sin_addr, + &((struct sockaddr_in *) right)->sin_addr, + sizeof(struct in_addr))); +} /* cmp_addresses( struct sockaddr *, struct sockaddr * ) */ + %} %union { @@ -184,14 +214,13 @@ cmd reply(500, "Illegal PORT rejected (range errors)."); } else if (portcheck && - ntohs(data_dest.sin_port) < IPPORT_RESERVED) { + get_port((struct sockaddr *) &data_dest) < IPPORT_RESERVED) { usedefault = 1; reply(500, "Illegal PORT rejected (reserved port)."); } else if (portcheck && - memcmp(&data_dest.sin_addr, - &his_addr.sin_addr, - sizeof data_dest.sin_addr)) { + cmp_addresses((struct sockaddr *) &data_dest, + (struct sockaddr *) &his_addr)) { usedefault = 1; reply(500, "Illegal PORT rejected (address wrong)."); @@ -201,6 +230,7 @@ cmd (void) close(pdata); pdata = -1; } + /* Valid remote address in 'data_dest'. */ reply(200, "PORT command successful."); } } @@ -632,22 +662,32 @@ host_port : NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER COMMA NUMBER { - char *a, *p; + char ipaddr[INET6_ADDRSTRLEN], port[12]; + struct addrinfo hints, *aiptr; if ($1 < 0 || $1 > 255 || $3 < 0 || $3 > 255 || $5 < 0 || $5 > 255 || $7 < 0 || $7 > 255 || $9 < 0 || $9 > 255 || $11 < 0 || $11 > 255) { $$ = 1; } else { -#ifndef __linux__ - data_dest.sin_len = sizeof(struct sockaddr_in); -#endif - data_dest.sin_family = AF_INET; - p = (char *)&data_dest.sin_port; - p[0] = $9; p[1] = $11; - a = (char *)&data_dest.sin_addr; - a[0] = $1; a[1] = $3; a[2] = $5; a[3] = $7; - $$ = 0; + snprintf(ipaddr, sizeof(ipaddr), "%ju.%ju.%ju.%ju", + $1, $3, $5, $7); + snprintf(port, sizeof(port), "%ju", 256 * $9 + $11); + + memset(&hints, 0, sizeof(hints)); + hints.ai_family = AF_INET; /* Enable mapped addressing? */ + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST | AI_NUMERICSERV; + + if (getaddrinfo(ipaddr, port, &hints, &aiptr)) { + $$ = 1; + } else { + /* Store the generated address in 'data_dest'. + * This is the remote host! */ + memcpy(&data_dest, aiptr->ai_addr, aiptr->ai_addrlen); + freeaddrinfo(aiptr); + $$ = 0; + } } } ; debian/patches/500-ssl.diff0000644000000000000000000011434111553435453012566 0ustar Description: Base SSL patch The original ssl patch, modified to apply to debian's linux-ftpd package. Origin: ftp://ftp.uni-mainz.de/pub/software/security/ssl/SSL-MZapps/linux-ftpd-0.17+ssl-0.3.diff.gz Forwarded: not-needed Author: Tim Hudson Last-Update: 2010-06-21 Index: linux-ftpd-ssl/ftpd/Makefile =================================================================== --- linux-ftpd-ssl.orig/ftpd/Makefile 2010-06-08 19:16:05.000000000 +0100 +++ linux-ftpd-ssl/ftpd/Makefile 2010-06-08 19:16:05.000000000 +0100 @@ -1,7 +1,7 @@ include ../MCONFIG -CFLAGS+=-I../support -LIBS+=-L../support -lsupport +CFLAGS+=-I../support -DUSE_SSL -g +LIBS+=-L../support -lsupport -lssl -lcrypto OBJS=ftpd.o ftpcmd.o logutmp.o logwtmp.o popen.o Index: linux-ftpd-ssl/ftpd/ftpcmd.y =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpcmd.y 2010-06-08 19:16:05.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpcmd.y 2010-06-09 01:19:32.000000000 +0100 @@ -1,3 +1,15 @@ +/* + * The modifications to support SSLeay we done by Tim Hudson + * tjh@mincom.oz.au + * + * You can do whatever you like with these patches except pretend that + * you wrote them. + * + * Email ssl-users-request@mincom.oz.au to get instructions on how to + * join the mailing list that discusses SSLeay and also these patches. + * + */ + /* * Copyright (c) 1985, 1988, 1993, 1994 * The Regents of the University of California. All rights reserved. @@ -96,6 +108,19 @@ extern int use_ipv4; extern struct sockaddr_storage his_addr; +#ifdef USE_SSL +/*#include "ssl_port.h"*/ +typedef struct ssl_st SSL; +int SSL_write(SSL *ssl,const char *buf,int num); +extern int do_ssl_start(void); +extern int ssl_secure_flag; +extern int ssl_active_flag; +extern SSL *ssl_con; +#define FFLUSH(X) (ssl_active_flag && (((X)==cin)||((X)==cout)) ? 1 : fflush((X)) ) +#define GETC(X) (ssl_active_flag && (((X)==cin)||((X)==cout)) ? ssl_getc(ssl_con) : getc((X)) ) +extern FILE *cin, *cout; +#endif /* USE_SSL */ + off_t restart_point; static int cmd_type; @@ -171,7 +196,7 @@ CDUP STOU SMNT SYST SIZE MDTM EPRT EPSV - UMASK IDLE CHMOD + UMASK IDLE CHMOD AUTH LEXERR @@ -180,7 +205,7 @@ %type check_login octal_number byte_size %type struct_code mode_code type_code form_code -%type pathstring pathname password username transport +%type pathstring pathname password username transport auth_type %type host_port %start cmd_list @@ -198,13 +223,43 @@ ; cmd - : USER SP username CRLF + : AUTH SP auth_type CRLF + { + if (!strncmp((char *) $3,"SSL",3)) { +#ifdef USE_SSL + reply(334, "AUTH SSL OK."); + + /* now do all the hard work :-) */ + do_ssl_start(); + +#else /* !USE_SSL */ + reply(504,"AUTH type not supported."); +#endif /* USE_SSL */ + } else { + reply(504,"AUTH type not supported."); + } + if ($3 != NULL) + free((char *)$3); + } + | USER SP username CRLF { +#ifdef USE_SSL + if (ssl_secure_flag && !ssl_active_flag) { + reply(504,"SSL is mandatory."); + break; + } +#endif /* USE_SSL */ user($3); free($3); } | PASS SP password CRLF { +#ifdef USE_SSL + if (ssl_secure_flag && !ssl_active_flag) { + reply(504,"SSL is mandatory."); + break; + } +#endif /* USE_SSL */ pass($3); memset($3, 0, strlen($3)); free($3); @@ -697,6 +752,10 @@ : STRING ; +auth_type + : STRING + ; + password : /* empty */ { @@ -943,6 +1002,7 @@ #define NSTR 8 /* Number followed by a string */ struct tab cmdtab[] = { /* In order defined in RFC 765 */ + { "AUTH", AUTH, STR1, 1, " auth_type" }, { "USER", USER, STR1, 1, " username" }, { "PASS", PASS, ZSTR1, 1, " password" }, { "ACCT", ACCT, STR1, 0, "(specify account)" }, @@ -1028,6 +1088,7 @@ { int c; register char *cs; + char buf[16]; cs = s; /* tmpline may contain saved command from urgent mode interruption */ @@ -1043,23 +1104,34 @@ if (c == 0) tmpline[0] = '\0'; } - while ((c = getc(iop)) != EOF) { + while ((c = GETC(iop)) != EOF) { c &= 0377; if (c == IAC) { - if ((c = getc(iop)) != EOF) { + if ((c = GETC(iop)) != EOF) { c &= 0377; switch (c) { case WILL: case WONT: - c = getc(iop); - printf("%c%c%c", IAC, DONT, 0377&c); - (void) fflush(stdout); + c = GETC(iop); + sprintf(buf,"%c%c%c", IAC, DONT, 0377&c); +#ifdef USE_SSL + if (ssl_active_flag) + SSL_write(ssl_con,buf,strlen(buf)); + else +#endif /* USE_SSL */ + fwrite(buf,strlen(buf),1,stdout); + (void) FFLUSH(stdout); continue; case DO: case DONT: - c = getc(iop); - printf("%c%c%c", IAC, WONT, 0377&c); - (void) fflush(stdout); + c = GETC(iop); + sprintf(buf,"%c%c%c", IAC, WONT, 0377&c); +#ifdef USE_SSL + if (ssl_active_flag) + SSL_write(ssl_con,buf,strlen(buf)); + else +#endif /* USE_SSL */ + (void) FFLUSH(stdout); continue; case IAC: break; @@ -1076,7 +1148,7 @@ * This prevents the command to be split up into * multiple commands. */ - while (c != '\n' && (c = getc(iop)) != EOF) + while (c != '\n' && (c = GETC(iop)) != EOF) ; return (-2); } Index: linux-ftpd-ssl/ftpd/ftpd.c =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpd.c 2010-06-08 19:16:05.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpd.c 2010-06-09 01:19:24.000000000 +0100 @@ -1,3 +1,15 @@ +/* + * The modifications to support SSLeay were done by Tim Hudson + * tjh@cryptsoft.com + * + * You can do whatever you like with these patches except pretend that + * you wrote them. + * + * Email ssl-users-request@lists.cryptsoft.com to get instructions on how to + * join the mailing list that discusses SSLeay and also these patches. + * + */ + /* * Copyright (c) 1985, 1988, 1990, 1992, 1993, 1994 * The Regents of the University of California. All rights reserved. @@ -125,6 +137,63 @@ #include "pathnames.h" #include "extern.h" +#ifdef USE_SSL + +#include "sslapp.c" + +BIO *bio_err; +SSL *ssl_data_con; +int ssl_auto_login=0; + +#if 0 +#include "rsa.h" /* extra ... */ +/* +#include "asn1.h" +*/ +#include +#include +#include +/* +#include "ssl_err.h" +*/ + +SSL *ssl_con; +SSL_CTX *ssl_ctx; +int ssl_debug_flag=0; +int ssl_only_flag=0; +int ssl_active_flag=0; +int ssl_secure_flag=0; +int ssl_verify_flag=SSL_VERIFY_NONE; +int ssl_certsok_flag=0; +#endif + +static char *auth_ssl_name=NULL; +FILE *cin, *cout; + +int ssl_data_active_flag=0; + +/* for the moment this is a compile time option only --tjh */ +int ssl_encrypt_data=1; + +char ssl_file_path[1024]; /* don't look at that nasty value to the left */ + +X509 *ssl_public_cert; +RSA *ssl_private_key; + +static char *my_ssl_key_file=NULL; +static char *my_ssl_cert_file=NULL; + +#include "ssl_port.h" + +int +ssl_getc(SSL *ssl_con); +static int +ssl_putc(SSL *ssl_con,int oneint); +static int +ssl_putc_flush(SSL *ssl_con); + +#endif /* USE_SSL */ + #ifdef __STDC__ #include #else @@ -373,7 +442,7 @@ socklen_t addrlen; char *cp, line[LINE_MAX]; FILE *fd; - const char *argstr = "AdDhlMnSt:T:u:UvP46"; + const char *argstr = "AdDhlMnSt:T:u:UvP46z:"; struct addrinfo hints, *aiptr; #if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) @@ -483,12 +552,200 @@ use_ipv4 = 1; break; +#ifdef USE_SSL + case 'z': + if (strcmp(optarg, "debug") == 0 ) { + ssl_debug_flag=1; + } + if (strcmp(optarg, "verbose") == 0 ) { + ssl_verbose_flag=1; + } + if (strcmp(optarg, "ssl") == 0 ) { + ssl_only_flag=1; + } + if (strcmp(optarg, "secure") == 0 ) { + ssl_secure_flag=1; + } + if (strcmp(optarg, "certsok") == 0) { + ssl_certsok_flag=1; + } + if (strncmp(optarg, "verify=", strlen("verify=")) == 0 ) { + ssl_verify_flag=atoi(optarg+strlen("verify=")); + + } + if (strncmp(optarg, "cert=", strlen("cert=")) == 0 ) { + my_ssl_cert_file=optarg+strlen("cert="); + } + if (strncmp(optarg, "key=", strlen("key=")) == 0 ) { + my_ssl_key_file=optarg+strlen("key="); + } + /* we have swallowed an extra arg */ + /*argc--; + argv++;*/ + break; +#endif /* USE_SSL */ + default: warnx("unknown flag -%c ignored", optopt); break; } } +#ifdef USE_SSL + /* make sure we have access to the required certificate + * and key files now ... before we perhaps chroot and + * do the other "muck" for anon-ftp style setup ... though + * why we want to run SSL for anon I don't know + */ + + { +#if 0 + int i; + FILE *fp; + char *filename; +#endif + + /* keep the macros that are common between the client + * and the server happy + */ + cin=stdin; + cout=stderr; + + /* do things the "default" way */ + if (my_ssl_cert_file==NULL) { + sprintf(ssl_file_path,"%s/%s",X509_get_default_cert_dir(), + "ftpd.pem"); + ssl_cert_file=ssl_file_path; + } else { + ssl_cert_file=my_ssl_cert_file; + } + + if (!do_ssleay_init(1)) { + fprintf(stderr,"ftpd: SSLeay initialisation failed\n"); + fflush(stderr); + sleep(1); + exit(1); + } + +#if 0 + /* if we are not running in debug then any error + * stuff from SSL debug *must* not go down + * the socket (which 0,1,2 are all pointing to by + * default) + */ + if (ssl_debug_flag) { + if (standalone) { + SSL_ERR=stderr; + SSL_LOG=stderr; + } else { + (void)freopen("ftpd.err","w",stderr); + SSL_ERR=stderr; + SSL_LOG=NULL; + SSL_debug("ftpd.log"); + if (SSL_LOG==NULL) { + SSL_LOG=fopen("ftpd.log","w"); + if (SSL_LOG==NULL) + SSL_LOG=stderr; + } + } + } else { + /* disable all the debug and trace */ + SSL_LOG=SSL_ERR=NULL; /**/ + } + + if (ssl_debug_flag) { + if (SSL_LOG!=NULL) { + fprintf(SSL_LOG,"SSL_LOG started\n"); + fflush(SSL_LOG); + } + if (SSL_ERR!=NULL) { + fprintf(SSL_ERR,"SSL_ERR started\n"); + fflush(SSL_ERR); + } + } + + SSL_load_error_strings(); + + ssl_ctx=SSL_CTX_new(); + + /* I really should syslog any of the following + * errors but I haven't bothered at this stage + * as that can wait + */ +/* + if (!X509_set_default_verify_paths(ssl_ctx->cert)) +*/ + if (!SSL_set_default_verify_paths(ssl_ctx)) { + fprintf(stderr,"ftpd: cannot set default path via X509_set_default_verify_paths\n"); + fflush(stderr); + sleep(1); + exit(1); + } + +#if 0 + sprintf(ssl_file_path,"%s/%s",X509_get_default_cert_dir(), + "ftpd.cert"); +#endif + + sprintf(ssl_file_path,"%s/%s",X509_get_default_cert_dir(), + "ftpd.pem"); + + filename=my_ssl_cert_file==NULL?ssl_file_path:my_ssl_cert_file; + fp=fopen(filename,"r"); + if (fp==NULL) { + fprintf(stderr,"ftpd: cannot open public cert file \"%s\"\n",filename); + fflush(stderr); + exit(1); + } + + ssl_public_cert=X509_new(); + if (PEM_read_X509(fp,&ssl_public_cert,NULL)==NULL) { + fprintf(stderr,"ftpd: error reading public cert - %s\n", + ERR_error_string(ERR_get_error(),NULL)); + fflush(stderr); + exit(1); + } + fclose(fp); + + if (ssl_debug_flag) { + fprintf(SSL_LOG,"ftpd: got public cert\n"); + fflush(SSL_LOG); + } + +#if 0 + sprintf(ssl_file_path,"%s/private/%s",X509_get_default_cert_area(), + "ftpd.key"); +#endif + + sprintf(ssl_file_path,"%s/%s",X509_get_default_cert_dir(), + "ftpd.pem"); + + filename=my_ssl_key_file==NULL?ssl_file_path:my_ssl_key_file; + fp=fopen(filename,"r"); + if (fp==NULL) { + fprintf(stderr,"ftpd: cannot open private key file \"%s\"\n",filename); + fflush(stderr); + exit(1); + } + + ssl_private_key=RSA_new(); + if (PEM_read_RSAPrivateKey(fp,&ssl_private_key,NULL)==0) { + fprintf(stderr,"ftpd: error reading private key - %s\n", + ERR_error_string(ERR_get_error(),NULL)); + fflush(stderr); + exit(1); + } + fclose(fp); + + if (ssl_debug_flag) { + fprintf(SSL_LOG,"ftpd: got private key\n"); + fflush(SSL_LOG); + } +#endif + + } +#endif /* USE_SSL */ + (void) freopen(_PATH_DEVNULL, "w", stderr); /* @@ -782,6 +1039,9 @@ static int askpasswd; /* had user command, ask for passwd */ static char curname[16]; /* current USER name */ +int +good_ssl_user(char *name); + /* * USER command. * Sets global passwd pointer pw if named account exists and is acceptable; @@ -856,6 +1116,12 @@ return; } } +#ifdef USE_SSL + if (pw && good_ssl_user(name)) { + reply(331, "Send dummy password to login."); + ssl_auto_login = 1; + } else +#endif #ifdef SKEY if (!skey_haskey(name)) { char *myskey, *skey_keyinfo __P((char *name)); @@ -1156,7 +1422,11 @@ } askpasswd = 0; #ifndef USE_PAM - if (!guest) { /* "ftp" is only account allowed no password */ + if (!guest +#ifdef USE_SSL + && !ssl_auto_login +#endif + ) { /* "ftp" is only account allowed no password */ #endif /* * Try to authenticate the user @@ -1429,6 +1699,15 @@ (restart_point == 0 && cmd == 0 && S_ISREG(st.st_mode))); if ((cmd == 0) && stats) logxfer(name, st.st_size, start); + +#ifdef USE_SSL + if (ssl_data_active_flag && (ssl_data_con!=NULL)) { + SSL_free(ssl_data_con); + ssl_data_active_flag=0; + ssl_data_con=NULL; + } +#endif /* USE_SSL */ + (void) fclose(dout); data = -1; pdata = -1; @@ -1650,6 +1929,69 @@ (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)); /* Errors silently ignored: GNU/kfreebsd. */ #endif +#ifdef USE_SSL + /* time to negotiate SSL on the data connection ... + * do this via SSL_accept (as we are still the server + * even though things are started around the other way) + * + * note: we really *must* make sure the session stuff + * is copied correctly as we cannot afford a full + * SSL negotiation for each data socket! + */ + /* TODO XXXX fill in the blanks :-) + */ + ssl_data_active_flag=0; + if (ssl_active_flag && ssl_encrypt_data) { + /* do SSL */ + + reply(150, "Opening %s mode SSL data connection for %s%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + + if (ssl_data_con!=NULL) { + SSL_free(ssl_data_con); + ssl_data_con=NULL; + } + ssl_data_con=(SSL *)SSL_new(ssl_ctx); + + /* copy session details ... */ + SSL_copy_session_id(ssl_data_con,ssl_con); + + /* for 0.5.2 - want to change the timeout value etc ... */ + + SSL_set_fd(ssl_data_con,pdata); + SSL_set_verify(ssl_data_con,ssl_verify_flag,NULL); + + /* if is "safe" to read ahead */ + /* SSL_set_read_ahead(ssl_data_con,1); */ + + if (ssl_debug_flag) + BIO_printf(bio_err,"===>START SSL_accept on DATA\n"); + + if (SSL_accept(ssl_data_con)<=0) { + static char errbuf[1024]; + + sprintf(errbuf,"ftpd: SSL_accept DATA error %s\n", + ERR_error_string(ERR_get_error(),NULL)); + perror_reply(425, errbuf); + /* abort time methinks ... */ + fclose(file); + return NULL; + } else { + if (ssl_debug_flag) { + BIO_printf(bio_err,"[SSL DATA Cipher %s]\n", + SSL_get_cipher(ssl_con)); + } + ssl_data_active_flag=1; + } + + if (ssl_debug_flag) + BIO_printf(bio_err,"===>DONE SSL_accept on DATA\n"); + + } else { + reply(150, "Opening %s mode data connection for %s%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + } +#else /* !USE_SSL */ if (stou) { reply(150, "FILE: %s", name); } else { @@ -1658,6 +2000,7 @@ type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); } +#endif /* USE_SSL */ return (fdopen(pdata, mode)); } if (data >= 0) { @@ -1721,6 +2064,68 @@ data = -1; return (NULL); } +#ifdef USE_SSL + /* time to negotiate SSL on the data connection ... + * do this via SSL_accept (as we are still the server + * even though things are started around the other way) + * + * note: we really *must* make sure the session stuff + * is copied correctly as we cannot afford a full + * SSL negotiation for each data socket! + */ + /* TODO XXXX fill in the blanks :-) + */ + ssl_data_active_flag=0; + if (ssl_active_flag && ssl_encrypt_data) { + /* do SSL */ + + reply(150, "Opening %s mode SSL data connection for %s%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + + if (ssl_data_con!=NULL) { + SSL_free(ssl_data_con); + ssl_data_con=NULL; + } + ssl_data_con=(SSL *)SSL_new(ssl_ctx); + + /* copy session details ... */ + SSL_copy_session_id(ssl_data_con,ssl_con); + + /* for 0.5.2 - want to change the timeout value etc ... */ + + SSL_set_fd(ssl_data_con,data); + SSL_set_verify(ssl_data_con,ssl_verify_flag,NULL); + + /* if is "safe" to read ahead */ + /* SSL_set_read_ahead(ssl_data_con,1); */ + + if (ssl_debug_flag) + BIO_printf(bio_err,"===>START SSL_accept on DATA\n"); + + if (SSL_accept(ssl_data_con)<=0) { + static char errbuf[1024]; + + sprintf(errbuf,"ftpd: SSL_accept DATA error %s\n", + ERR_error_string(ERR_get_error(),NULL)); + perror_reply(425, errbuf); + /* abort time methinks ... */ + fclose(file); + return NULL; + } else { + if (ssl_debug_flag) + BIO_printf(bio_err,"[SSL DATA Cipher %s]\n", + SSL_get_cipher(ssl_con)); + ssl_data_active_flag=1; + } + + if (ssl_debug_flag) + BIO_printf(bio_err,"===>DONE SSL_accept on DATA\n"); + + } else { + reply(150, "Opening %s mode data connection for %s%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + } +#else /* !USE_SSL */ if (stou) { reply(150, "FILE: %s", name); } else { @@ -1729,6 +2134,7 @@ type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); } +#endif /* USE_SSL */ return (file); } @@ -1757,11 +2163,11 @@ if (c == '\n') { if (ferror(outstr)) goto data_err; - (void) putc('\r', outstr); + (void) DATAPUTC('\r', outstr); } - (void) putc(c, outstr); + (void) DATAPUTC(c, outstr); } - fflush(outstr); + DATAFLUSH(outstr); transflag = 0; if (ferror(instr)) goto file_err; @@ -1779,7 +2185,11 @@ netfd = fileno(outstr); filefd = fileno(instr); - if (isreg && filesize < (off_t)16 * 1024 * 1024) { + if ( +#ifdef USE_SSL + !ssl_data_active_flag && +#endif /* USE_SSL */ + isreg && filesize < (off_t)16 * 1024 * 1024) { buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd, (off_t)0); if (buf==MAP_FAILED || buf==NULL) { @@ -1820,6 +2230,13 @@ /* failure is harmless */ } #endif +#ifdef USE_SSL + if (ssl_data_active_flag) { + while ((cnt = read(filefd, buf, (u_int)blksize)) > 0 && + SSL_write(ssl_data_con, buf, cnt) == cnt) + byte_count += cnt; + } else +#endif /* USE_SSL */ while ((cnt = read(filefd, buf, size)) > 0 && write(netfd, buf, cnt) == cnt) byte_count += cnt; @@ -1878,6 +2295,16 @@ case TYPE_L: signal (SIGALRM, lostconn); +#ifdef USE_SSL + if (ssl_data_active_flag) { + while ((cnt = SSL_read(ssl_data_con,buf,sizeof buf)) > 0) { + if (write(fileno(outstr), buf, cnt) != cnt) + goto file_err; + byte_count += cnt; + } + } else +#endif /* !USE_SSL */ + { do { (void) alarm ((unsigned) timeout); cnt = read(fileno(instr), buf, sizeof(buf)); @@ -1889,6 +2316,7 @@ byte_count += cnt; } } while (cnt > 0); + } if (cnt < 0) goto data_err; transflag = 0; @@ -1900,14 +2328,14 @@ return (-1); case TYPE_A: - while ((c = getc(instr)) != EOF) { + while ((c = DATAGETC(instr)) != EOF) { byte_count++; if (c == '\n') bare_lfs++; while (c == '\r') { if (ferror(outstr)) goto data_err; - if ((c = getc(instr)) != '\n') { + if ((c = DATAGETC(instr)) != '\n') { (void) putc ('\r', outstr); if (c == '\0' || c == EOF) goto contin2; @@ -2056,12 +2484,33 @@ reply(int n, char *fmt, va_dcl va_alist) #endif { +#ifdef USE_SSL + char outputbuf[2048]; /* allow for a 2k command string */ +#endif /* USE_SSL */ va_list ap; #ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); #endif +#ifdef USE_SSL + /* assemble the output into a buffer */ + sprintf(outputbuf,"%d ",n); + vsprintf(outputbuf+strlen(outputbuf),fmt,ap); + strcat(outputbuf,"\r\n"); + + if (ssl_debug_flag) + BIO_printf(bio_err,"\n<--- %s",outputbuf); + + if (ssl_active_flag) { + SSL_write(ssl_con,outputbuf,strlen(outputbuf)); + } else { + fprintf(stdout,"%s",outputbuf); + fflush(stdout); + } + if (debug) + syslog(LOG_DEBUG, "<--- %s ", outputbuf); +#else /* !USE_SSL */ (void)printf("%d ", n); (void)vprintf(fmt, ap); (void)printf("\r\n"); @@ -2077,6 +2526,8 @@ vsyslog(LOG_FTP | LOG_DEBUG, fmt, ap); va_end(ap); } +#endif /* USE_SSL */ + va_end(ap); } void @@ -2089,12 +2540,34 @@ va_dcl #endif { +#ifdef USE_SSL + char outputbuf[2048]; /* allow for a 2k command string */ +#endif /* USE_SSL */ va_list ap; #ifdef __STDC__ va_start(ap, fmt); #else va_start(ap); #endif + +#ifdef USE_SSL + /* assemble the output into a buffer */ + sprintf(outputbuf,"%d- ",n); + vsprintf(outputbuf+strlen(outputbuf),fmt,ap); + strcat(outputbuf,"\r\n"); + + if (ssl_debug_flag) + BIO_printf(bio_err,"\n<--- %s",outputbuf); + + if (ssl_active_flag) { + SSL_write(ssl_con,outputbuf,strlen(outputbuf)); + } else { + fprintf(stdout,"%s",outputbuf); + fflush(stdout); + } + if (debug) + syslog(LOG_DEBUG, "<--- %s ", outputbuf); +#else /* !USE_SSL */ (void)printf("%d- ", n); (void)vprintf(fmt, ap); (void)printf("\r\n"); @@ -2110,6 +2583,8 @@ vsyslog(LOG_FTP | LOG_DEBUG, fmt, ap); va_end(ap); } +#endif /* USE_SSL */ + va_end(ap); } static void ack(const char *s) @@ -2582,6 +3057,7 @@ volatile int simple = 0; volatile int freeglob = 0; glob_t gl; + char buf[1024]; /* XXX: should the { go away if __linux__? */ if (strpbrk(whichf, "~{[*?") != NULL) { @@ -2642,8 +3118,14 @@ goto out; transflag++; } - fprintf(dout, "%s%s\n", dirname, + sprintf(buf,"%s%s\n", dirname, type == TYPE_A ? "\r" : ""); +#ifdef USE_SSL + if (ssl_active_flag) + SSL_write(ssl_data_con,buf,strlen(buf)); + else +#endif /* USE_SSL */ + fwrite(buf,strlen(buf),1,dout); byte_count += strlen(dirname) + 1; continue; } else if (!S_ISDIR(st.st_mode)) @@ -2685,11 +3167,17 @@ transflag++; } if (nbuf[0] == '.' && nbuf[1] == '/') - fprintf(dout, "%s%s\n", &nbuf[2], + sprintf(buf, "%s%s\n", &nbuf[2], type == TYPE_A ? "\r" : ""); else - fprintf(dout, "%s%s\n", nbuf, + sprintf(buf, "%s%s\n", nbuf, type == TYPE_A ? "\r" : ""); +#ifdef USE_SSL + if (ssl_active_flag) + SSL_write(ssl_data_con,buf,strlen(buf)); + else +#endif /* USE_SSL */ + fwrite(buf,strlen(buf),1,dout); byte_count += strlen(nbuf) + 1; } } @@ -2705,6 +3193,13 @@ transflag = 0; if (dout != NULL) +#ifdef USE_SSL + if (ssl_data_active_flag && (ssl_data_con!=NULL)) { + SSL_free(ssl_data_con); + ssl_data_active_flag=0; + ssl_data_con=NULL; + } +#endif /* USE_SSL */ (void) fclose(dout); data = -1; pdata = -1; @@ -2792,3 +3287,223 @@ } #endif /* TCPWRAPPERS */ +#ifdef USE_SSL + +static +int +verify_callback(int ok, + X509_STORE_CTX *ctx); + +int +do_ssl_start(void) +{ + static char errstr[1024]; + + if (ssl_debug_flag) + BIO_printf(bio_err,"do_ssl_start triggered\n"); + + /* do the SSL stuff now ... before we play with pty's */ + ssl_con=(SSL *)SSL_new(ssl_ctx); + + /* we are working with stdin (inetd based) by default */ + SSL_set_fd(ssl_con,0); + +#if 0 + if (SSL_use_RSAPrivateKey(ssl_con,ssl_private_key)==0) { + sprintf(errstr,"ftpd: SSL_use_RSAPrivateKey %s",ERR_error_string(ERR_get_error(),NULL)); + perror_reply(421, errstr); + dologout(1); + } + + if (SSL_use_certificate(ssl_con,ssl_public_cert)==0) { + sprintf(errstr,"ftpd: SSL_use_certificate %s",ERR_error_string(ERR_get_error(),NULL)); + perror_reply(421, errstr); + dologout(1); + } +#endif + + SSL_set_verify(ssl_con,ssl_verify_flag, + ssl_certsok_flag ? verify_callback : NULL); + + if (SSL_accept(ssl_con)<=0) { + sprintf(errstr,"ftpd: SSL_accept %s",ERR_error_string(ERR_get_error(),NULL)); + + perror_reply(421, errstr); + dologout(1); + + SSL_free(ssl_con); + ssl_con=NULL; + + /* we will probably want to know this sort of stuff ... + * at least for the moment I'd like to keep track of + * who is using SSL - later I will probably make this + * just a debug option and only log after the user has + * actually connected --tjh + */ + if (logging) + syslog(LOG_NOTICE, "SSL FAILED WITH %s", remotehost); + + } else { + ssl_active_flag=1; + + if (logging) { + if (auth_ssl_name) + syslog(LOG_NOTICE, "SSL SUCCEEDED WITH %s as %s", remotehost, + auth_ssl_name); + else + syslog(LOG_NOTICE, "SSL SUCCEEDED WITH %s", remotehost); + } + } + + /* ssl_fprintf calls require that this be null to test + * for being an ssl stream + */ + if (!ssl_active_flag) { + if (ssl_con!=NULL) + SSL_free(ssl_con); + ssl_con=NULL; + } + + return 0; + +} + +/* we really shouldn't have code like this! --tjh */ +int +ssl_getc(SSL *ssl_con) +{ + char onebyte; + + if (SSL_read(ssl_con,&onebyte,1)!=1) + return -1; + else { + if (ssl_debug_flag) + BIO_printf(bio_err,"ssl_getc: SSL_read %d (%c) ",onebyte & 0xff,isprint(onebyte)?onebyte:'.'); + return onebyte & 0xff; + } +} + + +/* got back to this an implemented some rather "simple" buffering */ +static char putc_buf[BUFSIZ]; +static int putc_buf_pos=0; + +static int +ssl_putc_flush(SSL *ssl_con) +{ + if (putc_buf_pos>0) { + if (SSL_write(ssl_con,putc_buf,putc_buf_pos)!=putc_buf_pos) { + if (ssl_debug_flag) + BIO_printf(bio_err,"ssl_putc_flush: WRITE FAILED\n"); + putc_buf_pos=0; + return -1; + } + } + putc_buf_pos=0; + return 0; +} + +static int +ssl_putc(SSL *ssl_con,int oneint) +{ + char onebyte; + + onebyte = oneint & 0xff; + + /* make sure there is space */ + if (putc_buf_pos>=BUFSIZ) + if (ssl_putc_flush(ssl_con)!=0) + return EOF; + putc_buf[putc_buf_pos++]=onebyte; + + return onebyte; +} + +static +int +verify_callback(int ok, + X509_STORE_CTX *ctx) +{ + int depth,error; + X509 *xs; + + depth=ctx->error_depth; + error=ctx->error; + xs=X509_STORE_CTX_get_current_cert(ctx); + + /* + * If the verification fails, then don't remember the name. However, + * if we don't require a certificate, then return success which will + * still allow us to set up an encrypted session. + * + */ + if (!ok) { + /* If we can't verify the issuer, then don't accept the name. */ + if (depth != 0 && auth_ssl_name) { + free(auth_ssl_name); + auth_ssl_name = 0; + } + ok=ssl_verify_flag & SSL_VERIFY_FAIL_IF_NO_PEER_CERT ? 0 : 1; + goto done; + } + if (depth == 0) + auth_ssl_name = + (char *)ONELINE_NAME(X509_get_subject_name(xs)); +done: ; + + if (ssl_debug_flag) + BIO_printf(bio_err,"verify_callback: returning %d\n",ok); + + return ok; +} + +/* return true if this auth_ssl_name is authorized to use name. */ +int +good_ssl_user(char *name) +{ + FILE *user_fp; + char buf[2048]; + + if (!auth_ssl_name) + return 0; + if (!ssl_certsok_flag) + return 0; /* can't happen */ + user_fp = fopen("/etc/ssl.users", "r"); + if (!user_fp) + return 0; + while (fgets(buf, sizeof buf, user_fp)) { + char *cp; + char *n; + + /* allow for comments in the file ... always nice + * to be able to add a little novel in files and + * also disable easily --tjh + */ + if (buf[0]=='#') + continue; + + if ((cp = strchr(buf, '\n'))) + *cp = '\0'; + cp = strchr(buf, ':'); + if (!cp) + continue; + *cp++ = '\0'; + if (strcasecmp(cp, auth_ssl_name) == 0) { + n = buf; + while (n) { + cp = strchr(n, ','); + if (cp) + *cp++ = '\0'; + if (!strcmp(name, n)) { + fclose(user_fp); + return 1; + } + n = cp; + } + } + } + fclose(user_fp); + return 0; +} + +#endif /* USE_SSL */ Index: linux-ftpd-ssl/ftpd/ssl_port.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-ftpd-ssl/ftpd/ssl_port.h 2010-06-09 01:19:24.000000000 +0100 @@ -0,0 +1,85 @@ +/* ssl_port.h - standard porting things + * + * The modifications to support SSLeay were done by Tim Hudson + * tjh@mincom.oz.au + * + * You can do whatever you like with these patches except pretend that + * you wrote them. + * + * Email ssl-users-request@mincom.oz.au to get instructions on how to + * join the mailing list that discusses SSLeay and also these patches. + * + */ + +#ifndef HEADER_SSL_PORT_H +#define HEADER_SSL_PORT_H + +#ifdef USE_SSL + +#include + +#define OLDPROTO NOPROTO +#define NOPROTO +#include +#undef NOPROTO +#define NOPROTO OLDPROTO + +#include +#include +#include + +extern SSL *ssl_con; +extern SSL_CTX *ssl_ctx; +extern int ssl_debug_flag; +extern int ssl_only_flag; +extern int ssl_active_flag; +extern int ssl_verify_flag; +extern int ssl_secure_flag; +extern int ssl_enabled; + +extern int ssl_encrypt_data; +extern SSL *ssl_data_con; +extern int ssl_data_active_flag; + +extern char *my_ssl_cert_file; +extern char *my_ssl_key_file; +extern int ssl_certsok_flag; + +extern int set_ssl_trace(SSL *s); + +extern FILE *cin, *cout; + +#define is_ssl_fd(X,Y) ( (SSL_get_fd((X))==0) || \ + (SSL_get_fd((X))==1) || \ + (SSL_get_fd((X))==pdata) || \ + (SSL_get_fd((X))==(Y)) \ + ) + +#define is_ssl_fp(X,Y) ( ( (SSL_get_fd((X))==0) && (fileno((Y))==0) ) || \ + ( (SSL_get_fd((X))==1) && (fileno((Y))==1) ) || \ + ( (SSL_get_fd((X))==pdata) && \ + (fileno((Y))==pdata) ) || \ + (SSL_get_fd((X))==fileno(Y)) \ + ) + +/* these macros make things much easier to handle ... */ + +#define FFLUSH(X) (ssl_active_flag && (((X)==cin)||((X)==cout)) ? 1 : fflush((X)) ) + +#define GETC(X) (ssl_active_flag && (((X)==cin)||((X)==cout)) ? ssl_getc(ssl_con) : getc((X)) ) + +#define DATAGETC(X) (ssl_data_active_flag && ((fileno(X)==data)||(fileno(X)==pdata)) ? ssl_getc(ssl_data_con) : getc((X)) ) +#define DATAPUTC(X,Y) (ssl_data_active_flag && ((fileno(Y)==data)||(fileno(Y)==pdata)) ? ssl_putc(ssl_data_con,(X)) : putc((X),(Y)) ) +#define DATAFLUSH(X) (ssl_data_active_flag && ((fileno(X)==data)||(fileno(X)==pdata)) ? ssl_putc_flush(ssl_data_con) : fflush((X)) ) + +#else + +#define GETC(X) getc((X)) +#define DATAGETC(X) getc((X)) +#define DATAPUTC(X,Y) putc((X),(Y)) +#define DATAFLUSH(X) fflush((X)) +#define FFLUSH(X) fflush((X)) + +#endif /* USE_SSL */ + +#endif /* HEADER_SSL_PORT_H */ Index: linux-ftpd-ssl/ftpd/sslapp.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-ftpd-ssl/ftpd/sslapp.c 2010-06-09 01:19:24.000000000 +0100 @@ -0,0 +1,186 @@ +/* sslapp.c - ssl application code */ + +/* + * The modifications to support SSLeay were done by Tim Hudson + * tjh@cryptsoft.com + * + * You can do whatever you like with these patches except pretend that + * you wrote them. + * + * Email ssl-users-request@lists.cryptsoft.com to get instructions on how to + * join the mailing list that discusses SSLeay and also these patches. + * + */ + +#ifdef USE_SSL + +#include "sslapp.h" + +SSL_CTX *ssl_ctx; +SSL *ssl_con; +int ssl_debug_flag=0; +int ssl_only_flag=0; +int ssl_active_flag=0; +int ssl_verify_flag=SSL_VERIFY_NONE; +int ssl_secure_flag=0; +int ssl_certsok_flag=0; +int ssl_cert_required=0; +int ssl_verbose_flag=0; +int ssl_disabled_flag=0; +char *ssl_cert_file=NULL; +char *ssl_key_file=NULL; +char *ssl_cipher_list=NULL; +char *ssl_log_file=NULL; + +/* fwd decl */ +static void +client_info_callback(SSL *s, int where, int ret); + +int +do_ssleay_init(int server) +{ + char *p; + + /* make sure we have somewhere we can log errors to */ + if (bio_err==NULL) { + if ((bio_err=BIO_new(BIO_s_file()))!=NULL) { + if (ssl_log_file==NULL) + BIO_set_fp(bio_err,stderr,BIO_NOCLOSE); + else { + if (BIO_write_filename(bio_err,ssl_log_file)<=0) { + /* not a lot we can do */ + } + } + } + } + + /* rather simple things these days ... the old SSL_LOG and SSL_ERR + * vars are long gone now SSLeay8 has rolled around and we have + * a clean interface for doing things + */ + if (ssl_debug_flag) + BIO_printf(bio_err,"SSL_DEBUG_FLAG on\r\n"); + + + /* init things so we will get meaningful error messages + * rather than numbers + */ + SSL_load_error_strings(); + + SSLeay_add_ssl_algorithms(); + ssl_ctx=(SSL_CTX *)SSL_CTX_new(SSLv23_method()); + + /* we may require a temp 512 bit RSA key because of the + * wonderful way export things work ... if so we generate + * one now! + */ + if (server) { + if (SSL_CTX_need_tmp_RSA(ssl_ctx)) { + RSA *rsa; + + if (ssl_debug_flag) + BIO_printf(bio_err,"Generating temp (512 bit) RSA key ...\r\n"); + rsa=RSA_generate_key(512,RSA_F4,NULL,NULL); + if (ssl_debug_flag) + BIO_printf(bio_err,"Generation of temp (512 bit) RSA key done\r\n"); + + if (!SSL_CTX_set_tmp_rsa(ssl_ctx,rsa)) { + BIO_printf(bio_err,"Failed to assign generated temp RSA key!\r\n"); + } + RSA_free(rsa); + if (ssl_debug_flag) + BIO_printf(bio_err,"Assigned temp (512 bit) RSA key\r\n"); + } + } + + /* also switch on all the interoperability and bug + * workarounds so that we will communicate with people + * that cannot read poorly written specs :-) + */ + SSL_CTX_set_options(ssl_ctx,SSL_OP_ALL); + + /* the user can set whatever ciphers they want to use */ + if (ssl_cipher_list==NULL) { + p=getenv("SSL_CIPHER"); + if (p!=NULL) + SSL_CTX_set_cipher_list(ssl_ctx,p); + } else + SSL_CTX_set_cipher_list(ssl_ctx,ssl_cipher_list); + + /* for verbose we use the 0.6.x info callback that I got + * eric to finally add into the code :-) --tjh + */ + if (ssl_verbose_flag) { + SSL_CTX_set_info_callback(ssl_ctx,client_info_callback); + } + + /* Add in any certificates if you want to here ... */ + if (ssl_cert_file) { + if (!SSL_CTX_use_certificate_file(ssl_ctx, ssl_cert_file, + X509_FILETYPE_PEM)) { + BIO_printf(bio_err,"Error loading %s: ",ssl_cert_file); + ERR_print_errors(bio_err); + BIO_printf(bio_err,"\r\n"); + return(0); + } else { + if (!ssl_key_file) + ssl_key_file = ssl_cert_file; + if (!SSL_CTX_use_RSAPrivateKey_file(ssl_ctx, ssl_key_file, + X509_FILETYPE_PEM)) { + BIO_printf(bio_err,"Error loading %s: ",ssl_key_file); + ERR_print_errors(bio_err); + BIO_printf(bio_err,"\r\n"); + return(0); + } + } + } + + /* make sure we will find certificates in the standard + * location ... otherwise we don't look anywhere for + * these things which is going to make client certificate + * exchange rather useless :-) + */ + SSL_CTX_set_default_verify_paths(ssl_ctx); + + /* now create a connection */ + ssl_con=(SSL *)SSL_new(ssl_ctx); + SSL_set_verify(ssl_con,ssl_verify_flag,NULL); + +#if 0 + SSL_set_verify(ssl_con,ssl_verify_flag,client_verify_callback); +#endif + + return(1); +} + + +static void +client_info_callback(SSL *s, int where, int ret) +{ + if (where==SSL_CB_CONNECT_LOOP) { + BIO_printf(bio_err,"SSL_connect:%s %s\r\n", + SSL_state_string(s),SSL_state_string_long(s)); + } else if (where==SSL_CB_CONNECT_EXIT) { + if (ret == 0) { + BIO_printf(bio_err,"SSL_connect:failed in %s %s\r\n", + SSL_state_string(s),SSL_state_string_long(s)); + } else if (ret < 0) { + BIO_printf(bio_err,"SSL_connect:error in %s %s\r\n", + SSL_state_string(s),SSL_state_string_long(s)); + } + } +} + + +#else /* !USE_SSL */ + +/* something here to stop warnings if we build without SSL support */ +static int dummy_func() +{ + int i; + + i++; +} + +#endif /* USE_SSL */ + Index: linux-ftpd-ssl/ftpd/sslapp.h =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ linux-ftpd-ssl/ftpd/sslapp.h 2010-06-08 19:16:05.000000000 +0100 @@ -0,0 +1,63 @@ +/* sslapp.h - ssl application code */ + +/* + * The modifications to support SSLeay were done by Tim Hudson + * tjh@cryptsoft.com + * + * You can do whatever you like with these patches except pretend that + * you wrote them. + * + * Email ssl-users-request@mincom.oz.au to get instructions on how to + * join the mailing list that discusses SSLeay and also these patches. + * + */ + +#ifdef USE_SSL + +#include + +#include + +#define SSL_set_pref_cipher(c,n) SSL_set_cipher_list(c,n) +#define ONELINE_NAME(X) X509_NAME_oneline(X,NULL,0) + +#define OLDPROTO NOPROTO +#define NOPROTO +#include +#undef NOPROTO +#define NOPROTO OLDPROTO +#undef OLDPROTO +#include + +#include +#include +#include + +extern BIO *bio_err; +extern SSL *ssl_con; +extern SSL_CTX *ssl_ctx; +extern int ssl_debug_flag; +extern int ssl_only_flag; +extern int ssl_active_flag; +extern int ssl_verify_flag; +extern int ssl_secure_flag; +extern int ssl_verbose_flag; +extern int ssl_disabled_flag; +extern int ssl_cert_required; +extern int ssl_certsok_flag; + +extern char *ssl_log_file; +extern char *ssl_cert_file; +extern char *ssl_key_file; +extern char *ssl_cipher_list; + +/* we hide all the initialisation code in a separate file now */ +extern int do_ssleay_init(int server); + +/*extern int display_connect_details(); +extern int server_verify_callback(); +extern int client_verify_callback();*/ + +#endif /* USE_SSL */ + + debian/patches/014-adjust_infrastruct.diff0000644000000000000000000000075611553435453015707 0ustar Description: Corrections to infrastructure for builds. Insert harmless omission that eases tailored builds. Author: Mats Erik Andersson Forwarded: no Last-Update: 2010-04-26 --- linux-ftpd-0.17.debian/ftpd/Makefile +++ linux-ftpd-0.17/ftpd/Makefile @@ -26,7 +26,7 @@ -mv -f y.tab.c $@ ftpd: $(OBJS) - $(CC) $(LDFLAGS) $^ $(LIBS) -o $@ + $(CC) $(LDFLAGS) $^ $(LIBS) $(LDADD) -o $@ install: ftpd install -s -m$(DAEMONMODE) ftpd $(INSTALLROOT)$(SBINDIR)/in.ftpd debian/patches/026-support_glibc_bsd_and_gnu.diff0000644000000000000000000001672211553435453017173 0ustar Description: Implement changes to support GNU/Hurd and GNU/kfreebsd. Several conditionals on '__linux__' are altered to react identical to '__GLIBC__' and '__GNU__'. This should produce working code also for the Debian ports GNU/kfreebsd and GNU/Hurd. . GNU/kfreebsd uses distinct options IP_PORTRANGE and IPV6_PORTRANGE depending on address family. . Use IP_TOS only for IPv4 when compiling for non-Linux. Author: Mats Erik Andersson Forwarded: not-needed Last-Update: 2010-05-25 --- linux-ftpd-0.17.debian/ftpd/extern.h +++ linux-ftpd-0.17/ftpd/extern.h @@ -74,7 +74,7 @@ struct utmp; void login(const struct utmp *); int logout(const char *line); -#ifdef __linux__ +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) #include "daemon.h" #include "setproctitle.h" #endif --- linux-ftpd-0.17.debian/ftpd/ftpcmd.y +++ linux-ftpd-0.17/ftpd/ftpcmd.y @@ -67,7 +67,7 @@ char ftpcmd_rcsid[] = #include #include -#ifndef __linux__ +#if !defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU__) #include #else #define TM_YEAR_BASE 1900 @@ -851,7 +851,7 @@ pathname */ if (logged_in && $1 && strchr($1, '~') != NULL) { glob_t gl; -#ifdef __linux__ +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) /* see popen.c */ int flags = GLOB_NOCHECK; #else --- linux-ftpd-0.17.debian/ftpd/ftpd.c +++ linux-ftpd-0.17/ftpd/ftpd.c @@ -49,7 +49,7 @@ char copyright[] = * FTP server. */ -#ifdef __linux__ +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) #define _GNU_SOURCE #endif @@ -90,7 +90,7 @@ char copyright[] = #include #include -#ifndef __linux__ +#if !defined( __linux__) && !defined(__GLIBC__) && !defined(__GNU__) #include #include #else @@ -284,7 +284,7 @@ static int check_host __P((struct socka void logxfer __P((const char *, off_t, time_t)); -#ifdef __linux__ +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) static void warnx(const char *format, ...) { va_list ap; @@ -376,7 +376,7 @@ main(int argc, char *argv[], char **envp const char *argstr = "AdDhlMnSt:T:u:UvP46"; struct addrinfo hints, *aiptr; -#ifdef __linux__ +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) initsetproctitle(argc, argv, envp); srandom(time(NULL)^(getpid()<<8)); @@ -627,9 +627,16 @@ main(int argc, char *argv[], char **envp } #ifdef IP_TOS tos = IPTOS_LOWDELAY; +# if defined(__GLIBC__) && ! defined(__linux__) + if ( (his_addr.ss_family == AF_INET) + && (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, + sizeof(int)) < 0) ) + syslog(LOG_FTP | LOG_WARNING, "setsockopt (IP_TOS): %m"); +# else /* __linux__ */ if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) syslog(LOG_FTP | LOG_WARNING, "setsockopt (IP_TOS): %m"); -#endif +# endif /* GNU/kfreebsd */ +#endif /* IP_TOS */ data_port = get_port((struct sockaddr *) &ctrl_addr) - 1; /* Try to handle urgent data inline */ @@ -1108,7 +1115,7 @@ static int authenticate(char *passwd) useconds_t us; /* Sleep between 1 and 3 seconds to emulate a crypt. */ -#ifndef __linux__ +#if !defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU__) us = arc4random() % 3000000; #else us = random() % 3000000; @@ -1549,9 +1556,16 @@ static FILE * getdatasock(const char *mo #ifdef IP_TOS on = IPTOS_THROUGHPUT; +# if defined(__GLIBC__) && ! defined(__linux__) + if ( (his_addr.ss_family == AF_INET) + && (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, + sizeof(on)) < 0) ) + syslog(LOG_FTP | LOG_WARNING, "setsockopt (IP_TOS): %m"); +# else /* __linux__ */ if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) syslog(LOG_FTP | LOG_WARNING, "setsockopt (IP_TOS): %m"); -#endif +# endif /* GNU/kfreebsd */ +#endif /* IP_TOS */ #ifdef TCP_NOPUSH /* * Turn off push flag to keep sender TCP from sending short packets @@ -1634,7 +1648,7 @@ static FILE * dataconn(const char *name, #ifdef IP_TOS tos = IPTOS_THROUGHPUT; (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, - sizeof(int)); + sizeof(int)); /* Errors silently ignored: GNU/kfreebsd. */ #endif if (stou) { reply(150, "FILE: %s", name); @@ -2347,10 +2361,17 @@ void passive(void) memcpy(&pasv_addr, &ctrl_addr, sizeof(pasv_addr)); #ifdef IP_PORTRANGE - on = high_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; - if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, - (char *)&on, sizeof(on)) < 0) - goto pasv_error; + if (his_addr.ss_family == AF_INET6) { + on = high_data_ports ? IPV6_PORTRANGE_HIGH : IPV6_PORTRANGE_DEFAULT; + if (setsockopt(pdata, IPPROTO_IPV6, IPV6_PORTRANGE, + (char *)&on, sizeof(on)) < 0) + goto pasv_error; + } else { + on = high_data_ports ? IP_PORTRANGE_HIGH : IP_PORTRANGE_DEFAULT; + if (setsockopt(pdata, IPPROTO_IP, IP_PORTRANGE, + (char *)&on, sizeof(on)) < 0) + goto pasv_error; + } #else #define FTP_DATA_BOTTOM 40000 #define FTP_DATA_TOP 44999 @@ -2564,7 +2585,7 @@ void send_file_list(const char *whichf) /* XXX: should the { go away if __linux__? */ if (strpbrk(whichf, "~{[*?") != NULL) { -#ifdef __linux__ +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) /* see popen.c */ int flags = GLOB_NOCHECK; #else @@ -2634,7 +2655,7 @@ void send_file_list(const char *whichf) while ((dir = readdir(dirp)) != NULL) { char nbuf[MAXPATHLEN]; -#ifdef __linux__ +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) if (!strcmp(dir->d_name, ".")) continue; if (!strcmp(dir->d_name, "..")) --- linux-ftpd-0.17.debian/ftpd/logutmp.c +++ linux-ftpd-0.17/ftpd/logutmp.c @@ -47,14 +47,14 @@ char logutmp_rcsid[] = #include #include #include -#ifndef __linux__ +#if !defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU__) #include #endif #include "extern.h" typedef struct utmp UTMP; -#ifndef __linux__ +#if !defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU__) static int fd = -1; static int topslot = -1; #endif @@ -67,7 +67,7 @@ static int topslot = -1; void login(const UTMP *ut) { -#ifndef __linux__ +#if !defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU__) UTMP ubuf; /* @@ -110,7 +110,7 @@ login(const UTMP *ut) int logout(register const char *line) { -#ifndef __linux__ +#if !defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU__) UTMP ut; int rval; --- linux-ftpd-0.17.debian/ftpd/popen.c +++ linux-ftpd-0.17/ftpd/popen.c @@ -102,7 +102,7 @@ ftpd_popen(char *program, const char *ty gargv[0] = argv[0]; for (gargc = argc = 1; argv[argc]; argc++) { glob_t gl; -#ifdef __linux__ +#if defined(__linux__) || defined(__GLIBC__) || defined(__GNU__) /* * GLOB_QUOTE is default behavior. GLOB_BRACE and GLOB_TILDE * aren't available... @@ -177,7 +177,7 @@ ftpd_popen(char *program, const char *ty if ( setgid(getegid()) != 0 ) _exit(1); if ( setuid(i) != 0 ) _exit(1); -#ifndef __linux__ +#if !defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU__) /* * Not yet. Porting BSD ls to Linux would be a big and irritating job, * and we can't use GNU ls because of licensing. --- linux-ftpd-0.17.debian/support/vis.c +++ linux-ftpd-0.17/support/vis.c @@ -40,7 +40,7 @@ char vis_rcsid[] = \ #include #include #include -#ifndef __linux__ +#if !defined(__linux__) && !defined(__GLIBC__) && !defined(__GNU__) #include #else #include "vis.h" debian/patches/540-docs.diff0000644000000000000000000000155311553435453012721 0ustar Description: Document SSL options in manpage, fix typo Author: Ian Beckwith Index: linux-ftpd-ssl/ftpd/ftpd.8 =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpd.8 2010-07-25 01:25:02.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpd.8 2010-07-25 01:25:10.000000000 +0100 @@ -50,6 +50,14 @@ .Op Fl T Ar maxtimeout .Op Fl t Ar timeout .Op Fl u Ar mask +.Op Fl z Ar debug +.Op Fl z Ar certsok +.Op Fl z Ar certrequired +.Op Fl z Ar secure +.Op Fl z Ar verify=flags +.Op Fl z Ar cert=certfile +.Op Fl z Ar key=keyfile +.Op Fl z Ar ciper=list .Sh DESCRIPTION .Nm Ftpd is the @@ -161,7 +169,7 @@ .Ic -z ssl . (Not yet implemented) .It Ic nossl, !ssl -switch of SSL negotiation +switch off SSL negotiation .It Ic certsok Look username up in /etc/ssl.users. The format of this file is lines of this form: debian/patches/530-CVE-2007-6263.diff0000644000000000000000000000157311553435453013373 0ustar Description: Fix CVE-2007-6263 - remote denial of service Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=454733 Author: Nico Golde Index: linux-ftpd-ssl/ftpd/ftpd.c =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpd.c 2010-06-14 01:29:56.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpd.c 2010-06-14 01:29:56.000000000 +0100 @@ -1884,7 +1884,7 @@ static FILE * dataconn(const char *name, off_t size, const char *mode, int stou) { char sizebuf[32]; - FILE *file; + FILE *file = NULL; int retry = 0, tos; file_size = size; @@ -1978,7 +1978,10 @@ ERR_error_string(ERR_get_error(),NULL)); perror_reply(425, errbuf); /* abort time methinks ... */ - fclose(file); + if(file != NULL){ + fclose(file); + file = NULL; + } return NULL; } else { if (ssl_debug_flag) { debian/patches/520-CVE-2005-3524.diff0000644000000000000000000000146711553435453013367 0ustar Description: Fix CVE-2005-3524 - a remotely exploitable buffer overflow. Bug-Debian: http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=339074 Author: James Longstreet Index: linux-ftpd-ssl/ftpd/ftpd.c =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpd.c 2010-06-14 01:29:01.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpd.c 2010-06-14 01:29:01.000000000 +0100 @@ -2496,9 +2496,9 @@ va_start(ap); #endif #ifdef USE_SSL - /* assemble the output into a buffer */ + /* assemble the output into a buffer, checking for length */ sprintf(outputbuf,"%d ",n); - vsprintf(outputbuf+strlen(outputbuf),fmt,ap); + vsnprintf(outputbuf+strlen(outputbuf),2048-(strlen(outputbuf) + 3),fmt,ap); strcat(outputbuf,"\r\n"); if (ssl_debug_flag) debian/patches/001-from_hamm.diff0000644000000000000000000006674411553435453013743 0ustar Description: Patching recovered from linux-ftpd_0.17-13.diff.gz Author: Herbert Xu X-Comment: Bug #88837 contributed by Liviu Daia, Abraham van der Merwe, and Rainer Weikusat Forwarded: no Last-Update: 2002-02-09 --- linux-ftpd-0.17.orig/ftpd/ftpcmd.y +++ linux-ftpd-0.17/ftpd/ftpcmd.y @@ -55,6 +55,7 @@ #include #include #include +#include #include #include #include @@ -111,8 +112,8 @@ %} %union { - int i; - char *s; + intmax_t i; + char *s; } %token @@ -595,9 +596,9 @@ { if ($2) { fromname = (char *) 0; - restart_point = $4; /* XXX $4 is only "int" */ - reply(350, "Restarting at %qd. %s", - (quad_t) restart_point, + restart_point = $4; + reply(350, "Restarting at %jd. %s", + (intmax_t) restart_point, "Send STORE or RETRIEVE to initiate transfer."); } } @@ -931,7 +932,7 @@ if (tmpline[c] == '\n') { *cs++ = '\0'; if (debug) - syslog(LOG_DEBUG, "command: %s", s); + syslog(LOG_FTP | LOG_DEBUG, "command: %s", s); tmpline[0] = '\0'; return(s); } @@ -973,7 +974,7 @@ if (debug) { if (!guest && strncasecmp("pass ", s, 5) == 0) { /* Don't syslog passwords */ - syslog(LOG_DEBUG, "command: %.5s ???", s); + syslog(LOG_FTP | LOG_DEBUG, "command: %.5s ???", s); } else { register char *cp; register int len; @@ -985,7 +986,7 @@ --cp; --len; } - syslog(LOG_DEBUG, "command: %.*s", len, s); + syslog(LOG_FTP | LOG_DEBUG, "command: %.*s", len, s); } } return (s); @@ -998,7 +999,7 @@ reply(421, "Timeout (%d seconds): closing control connection.", timeout); if (logging) - syslog(LOG_INFO, "User %s timed out after %d seconds", + syslog(LOG_FTP | LOG_INFO, "User %s timed out after %d seconds", (pw ? pw -> pw_name : "unknown"), timeout); dologout(1); } @@ -1143,7 +1144,7 @@ ; c = cbuf[cpos]; cbuf[cpos] = '\0'; - yylval.i = atoi(cp); + yylval.i = strtoimax(cp, 0, 10); cbuf[cpos] = c; state = STR1; return (NUMBER); @@ -1158,7 +1159,7 @@ ; c = cbuf[cpos]; cbuf[cpos] = '\0'; - yylval.i = atoi(cp); + yylval.i = strtoimax(cp, 0, 10); cbuf[cpos] = c; return (NUMBER); } @@ -1314,7 +1315,7 @@ if (stat(filename, &stbuf) < 0 || !S_ISREG(stbuf.st_mode)) reply(550, "%s: not a plain file.", filename); else - reply(213, "%qu", (quad_t) stbuf.st_size); + reply(213, "%ju", (uintmax_t) stbuf.st_size); break; } case TYPE_A: { FILE *fin; @@ -1340,7 +1341,7 @@ } (void) fclose(fin); - reply(213, "%qd", (quad_t) count); + reply(213, "%jd", (intmax_t) count); break; } default: reply(504, "SIZE not implemented for Type %c.", "?AEIL"[type]); --- linux-ftpd-0.17.orig/ftpd/ftpd.8 +++ linux-ftpd-0.17/ftpd/ftpd.8 @@ -67,7 +67,9 @@ .It Fl A Permit only anonymous ftp connections or accounts listed in .Pa /etc/ftpchroot. -Other connection attempts are refused. +Other connection attempts are refused. This option is nolonger effective if +PAM is enabled. Please refer to the README file for instructions to doing +this with PAM. .It Fl d Debugging information is written to the syslog using LOG_FTP. .It Fl D @@ -356,6 +358,21 @@ .Pa motd , if present, will be printed after a successful login. These files should be mode 444. +.It Pa ~ftp/lib +Make this directory owned by +.Dq root +and unwritable by anyone (mode 511). +The libraries +.Xr ld-linux.so.2 +and +.Xr libc.so.6 +(or whatever your +.Xr ls +command is linked to) +must be present. Note that if you're using a 2.2.* or later Linux kernel, +.Xr ld-linux.so.2 +must be executable as well as readable (555). All other files should be mode +444. .It Pa ~ftp/pub Make this directory mode 555 and owned by .Dq root . --- linux-ftpd-0.17.orig/ftpd/ftpd.c +++ linux-ftpd-0.17/ftpd/ftpd.c @@ -80,6 +80,7 @@ #include #include #include +#include #include #include #include @@ -95,8 +96,6 @@ #else #include /* for initgroups() */ /* #include * for L_SET et al. * <--- not used? */ -/*typedef int64_t quad_t;*/ -typedef unsigned int useconds_t; #endif #include "../version.h" @@ -132,6 +131,16 @@ #include #endif +#ifdef USE_PAM +#include +#include +#include +/* backward compatibility hack for libpam < 0.58 */ +#ifndef PAM_ESTABLISH_CRED +#define PAM_ESTABLISH_CRED PAM_CRED_ESTABLISH +#endif +#endif + static char versionpre[] = "Version 6.4/OpenBSD/Linux"; static char version[sizeof(versionpre)+sizeof(pkg)]; @@ -218,29 +227,37 @@ char proctitle[BUFSIZ]; /* initial part of title */ #endif /* HASSETPROCTITLE */ +#ifdef USE_PAM +static pam_handle_t *pamh; +static char *PAM_username; +static char *PAM_password; +static char *PAM_message; +static int PAM_accepted; +#endif + #define LOGCMD(cmd, file) \ if (logging > 1) \ - syslog(LOG_INFO,"%s %s%s", cmd, \ + syslog(LOG_FTP | LOG_INFO,"%s %s%s", cmd, \ *(file) == '/' ? "" : curdir(), file); #define LOGCMD2(cmd, file1, file2) \ if (logging > 1) \ - syslog(LOG_INFO,"%s %s%s %s%s", cmd, \ + syslog(LOG_FTP | LOG_INFO,"%s %s%s %s%s", cmd, \ *(file1) == '/' ? "" : curdir(), file1, \ *(file2) == '/' ? "" : curdir(), file2); #define LOGBYTES(cmd, file, cnt) \ if (logging > 1) { \ if (cnt == (off_t)-1) \ - syslog(LOG_INFO,"%s %s%s", cmd, \ + syslog(LOG_FTP | LOG_INFO,"%s %s%s", cmd, \ *(file) == '/' ? "" : curdir(), file); \ else \ - syslog(LOG_INFO, "%s %s%s = %qd bytes", cmd, \ - *(file) == '/' ? "" : curdir(), file, (quad_t)(cnt)); \ + syslog(LOG_FTP | LOG_INFO, "%s %s%s = %jd bytes", cmd, \ + *(file) == '/' ? "" : curdir(), file, (intmax_t)(cnt)); \ } static void ack __P((const char *)); static void myoob __P((int)); static int checkuser __P((const char *, const char *)); -static FILE *dataconn __P((const char *, off_t, const char *)); +static FILE *dataconn __P((const char *, off_t, const char *, int)); static void dolog __P((struct sockaddr_in *)); static const char *curdir __P((void)); static void end_login __P((void)); @@ -255,6 +272,7 @@ sgetpwnam __P((const char *)); static char *sgetsave __P((char *)); static void reapchild __P((int)); +static void authentication_setup(const char *); #if defined(TCPWRAPPERS) static int check_host __P((struct sockaddr_in *)); @@ -415,7 +433,7 @@ * Detach from parent. */ if (daemon(1, 1) < 0) { - syslog(LOG_ERR, "failed to become a daemon"); + syslog(LOG_FTP | LOG_ERR, "failed to become a daemon"); exit(1); } (void) signal(SIGCHLD, reapchild); @@ -424,7 +442,8 @@ */ sv = getservbyname("ftp", "tcp"); if (sv == NULL) { - syslog(LOG_ERR, "getservbyname for ftp failed"); + syslog(LOG_FTP | LOG_ERR, + "getservbyname for ftp failed"); exit(1); } /* @@ -433,22 +452,22 @@ */ ctl_sock = socket(AF_INET, SOCK_STREAM, 0); if (ctl_sock < 0) { - syslog(LOG_ERR, "control socket: %m"); + syslog(LOG_FTP | LOG_ERR, "control socket: %m"); exit(1); } if (setsockopt(ctl_sock, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) < 0) - syslog(LOG_ERR, "control setsockopt: %m");; + syslog(LOG_FTP | LOG_ERR, "control setsockopt: %m");; server_addr.sin_family = AF_INET; server_addr.sin_addr.s_addr = INADDR_ANY; server_addr.sin_port = sv->s_port; if (bind(ctl_sock, (struct sockaddr *)&server_addr, sizeof(server_addr))) { - syslog(LOG_ERR, "control bind: %m"); + syslog(LOG_FTP | LOG_ERR, "control bind: %m"); exit(1); } if (listen(ctl_sock, 32) < 0) { - syslog(LOG_ERR, "control listen: %m"); + syslog(LOG_FTP | LOG_ERR, "control listen: %m"); exit(1); } /* @@ -478,7 +497,8 @@ addrlen = sizeof(his_addr); if (getpeername(0, (struct sockaddr *)&his_addr, &addrlen) < 0) { - syslog(LOG_ERR, "getpeername (%s): %m", argv[0]); + syslog(LOG_FTP | LOG_ERR, "getpeername (%s): %m", + argv[0]); exit(1); } } @@ -490,29 +510,29 @@ (void) signal(SIGPIPE, lostconn); (void) signal(SIGCHLD, SIG_IGN); if (signal(SIGURG, myoob) == SIG_ERR) - syslog(LOG_ERR, "signal: %m"); + syslog(LOG_FTP | LOG_ERR, "signal: %m"); addrlen = sizeof(ctrl_addr); if (getsockname(0, (struct sockaddr *)&ctrl_addr, &addrlen) < 0) { - syslog(LOG_ERR, "getsockname (%s): %m", argv[0]); + syslog(LOG_FTP | LOG_ERR, "getsockname (%s): %m", argv[0]); exit(1); } #ifdef IP_TOS tos = IPTOS_LOWDELAY; if (setsockopt(0, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)) < 0) - syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + syslog(LOG_FTP | LOG_WARNING, "setsockopt (IP_TOS): %m"); #endif data_source.sin_port = htons(ntohs(ctrl_addr.sin_port) - 1); /* Try to handle urgent data inline */ #ifdef SO_OOBINLINE if (setsockopt(0, SOL_SOCKET, SO_OOBINLINE, (char *)&on, sizeof(on)) < 0) - syslog(LOG_ERR, "setsockopt: %m"); + syslog(LOG_FTP | LOG_ERR, "setsockopt: %m"); #endif #ifdef F_SETOWN if (fcntl(fileno(stdin), F_SETOWN, getpid()) == -1) - syslog(LOG_ERR, "fcntl F_SETOWN: %m"); + syslog(LOG_FTP | LOG_ERR, "fcntl F_SETOWN: %m"); #endif dolog(&his_addr); /* @@ -583,13 +603,13 @@ (void)signo; if (debug) - syslog(LOG_DEBUG, "lost connection"); + syslog(LOG_FTP | LOG_DEBUG, "lost connection"); dologout(-1); } static void sigquit(int signo) { - syslog(LOG_ERR, "got signal %s", strsignal(signo)); + syslog(LOG_FTP | LOG_ERR, "got signal %s", strsignal(signo)); dologout(-1); } @@ -658,10 +678,15 @@ * 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. + * + * pw maybe unset if we're using PAM and the login turns out to be anonymous. + * -- herbert */ void user(char *name) { +#ifndef USE_PAM const char *cp, *shell; +#endif if (logged_in) { if (guest) { @@ -674,6 +699,9 @@ end_login(); } +#ifdef USE_PAM + authentication_setup(name); +#else guest = 0; if (strcmp(name, "ftp") == 0 || strcmp(name, "anonymous") == 0) { if (checkuser(_PATH_FTPUSERS, "ftp") || @@ -687,7 +715,7 @@ } else reply(530, "User %s unknown.", name); if (!askpasswd && logging) - syslog(LOG_NOTICE, + syslog(LOG_FTP | LOG_NOTICE, "ANONYMOUS FTP LOGIN REFUSED FROM %s", remotehost); return; } @@ -707,17 +735,13 @@ if (cp == NULL || checkuser(_PATH_FTPUSERS, name)) { reply(530, "User %s access denied.", name); if (logging) - syslog(LOG_NOTICE, + syslog(LOG_FTP | LOG_NOTICE, "FTP LOGIN REFUSED FROM %s, %s", remotehost, name); pw = (struct passwd *) NULL; return; } } - if (logging) { - strncpy(curname, name, sizeof(curname)-1); - curname[sizeof(curname)-1] = '\0'; - } #ifdef SKEY if (!skey_haskey(name)) { char *myskey, *skey_keyinfo __P((char *name)); @@ -728,6 +752,11 @@ } else #endif reply(331, "Password required for %s.", name); +#endif + if (logging) { + strncpy(curname, name, sizeof(curname)-1); + curname[sizeof(curname)-1] = '\0'; + } askpasswd = 1; /* @@ -774,9 +803,19 @@ sigprocmask (SIG_BLOCK, &allsigs, NULL); (void) seteuid((uid_t)0); if (logged_in) { +#ifdef USE_PAM + int error; + error = pam_close_session(pamh, 0); + pam_end(pamh, error); + pamh = 0; +#endif ftpdlogwtmp(ttyline, "", ""); if (doutmp) logout(utmp.ut_line); +#if defined(KERBEROS) + if (!notickets && krbtkfile_env) + unlink(krbtkfile_env); +#endif } pw = NULL; logged_in = 0; @@ -784,9 +823,211 @@ dochroot = 0; } +#ifdef USE_PAM +/* + * PAM authentication, now using the PAM's async feature. + */ +static int PAM_conv (int num_msg, const struct pam_message **msg, + struct pam_response **resp, void *appdata_ptr) +{ + struct pam_response *repl = NULL; + int retval, count = 0, replies = 0; + int size = sizeof(struct pam_response); + +#define GET_MEM \ + if (!(repl = realloc(repl, size))) \ + return PAM_CONV_ERR; \ + size += sizeof(struct pam_response) +#define COPY_STRING(s) (s) ? strdup(s) : NULL + + (void) appdata_ptr; + retval = PAM_SUCCESS; + for (count = 0; count < num_msg; count++) { + int savemsg = 0; + + switch (msg[count]->msg_style) { + case PAM_PROMPT_ECHO_ON: + GET_MEM; + repl[replies].resp_retcode = PAM_SUCCESS; + repl[replies].resp = COPY_STRING(PAM_username); + replies++; + break; + case PAM_PROMPT_ECHO_OFF: + GET_MEM; + if (PAM_password == 0) { + savemsg = 1; + retval = PAM_CONV_AGAIN; + } else { + repl[replies].resp_retcode = PAM_SUCCESS; + repl[replies].resp = COPY_STRING(PAM_password); + replies++; + } + break; + case PAM_TEXT_INFO: + savemsg = 1; + break; + case PAM_ERROR_MSG: + default: + /* Must be an error of some sort... */ + retval = PAM_CONV_ERR; + } + + if (savemsg) { + char *sp; + + if (PAM_message) { + /* XXX: make sure we split newlines correctly */ + lreply(331, "%s", PAM_message); + free(PAM_message); + } + PAM_message = COPY_STRING(msg[count]->msg); + + /* Remove trailing `: ' */ + sp = PAM_message + strlen(PAM_message); + while (sp > PAM_message && strchr(" \t\n:", *--sp)) + *sp = '\0'; + } + + /* In case of error, drop responses and return */ + if (retval) { + _pam_drop_reply(repl, replies); + return retval; + } + } + if (repl) + *resp = repl; + return PAM_SUCCESS; +} + +static struct pam_conv PAM_conversation = { + &PAM_conv, + NULL +}; + +static int pam_doit(void) +{ + char *user; + int error; + + error = pam_authenticate(pamh, 0); + if (error == PAM_CONV_AGAIN || error == PAM_INCOMPLETE) { + /* Avoid overly terse passwd messages */ + if (PAM_message && !strcasecmp(PAM_message, "password")) { + free(PAM_message); + PAM_message = 0; + } + if (PAM_message == 0) { + reply(331, "Password required for %s.", PAM_username); + } else { + reply(331, "%s", PAM_message); + free(PAM_message); + PAM_message = 0; + } + return 1; + } + if (error == PAM_SUCCESS) { + /* Alright, we got it */ + error = pam_acct_mgmt(pamh, 0); + if (error == PAM_SUCCESS) + error = pam_open_session(pamh, 0); + if (error == PAM_SUCCESS) + error = pam_setcred(pamh, PAM_ESTABLISH_CRED); + if (error == PAM_SUCCESS) + error = pam_get_item(pamh, PAM_USER, (const void **) &user); + if (error == PAM_SUCCESS) { + if (strcmp(user, "ftp") == 0) { + guest = 1; + } + pw = sgetpwnam(user); + } + if (error == PAM_SUCCESS && pw) + PAM_accepted = 1; + } + + return (error == PAM_SUCCESS); +} + + +static void authentication_setup(const char *username) +{ + int error; + + if (pamh != 0) { + pam_end(pamh, PAM_ABORT); + pamh = 0; + } + + if (PAM_username) + free(PAM_username); + PAM_username = strdup(username); + PAM_password = 0; + PAM_message = 0; + PAM_accepted = 0; + + error = pam_start("ftp", PAM_username, &PAM_conversation, &pamh); + if (error == PAM_SUCCESS) + error = pam_set_item(pamh, PAM_RHOST, remotehost); + if (error != PAM_SUCCESS) { + reply(550, "Authentication failure"); + pam_end(pamh, error); + pamh = 0; + } + + if (pamh && !pam_doit()) + reply(550, "Authentication failure"); +} + +static int authenticate(char *passwd) +{ + if (PAM_accepted) + return 1; + + if (pamh == 0) + return 0; + + PAM_password = passwd; + pam_doit(); + PAM_password = 0; + return PAM_accepted; +} + +#else /* !USE_PAM */ +static int authenticate(char *passwd) +{ + if (pw == NULL) { + useconds_t us; + + /* Sleep between 1 and 3 seconds to emulate a crypt. */ +#ifndef __linux__ + us = arc4random() % 3000000; +#else + us = random() % 3000000; +#endif + usleep(us); + return 0; + } + +#if defined(KERBEROS) + if (klogin(pw, "", hostname, passwd) == 0) + return 1; +#endif +#ifdef SKEY + if (skey_haskey(pw->pw_name) == 0 && + (skey_passcheck(pw->pw_name, passwd) != -1)) + return 1; +#endif + /* the strcmp does not catch null passwords! */ + if (pw == NULL || *pw->pw_passwd == '\0' || + strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd)) + return 0; /* failure */ + + return 1; +} +#endif /* !USE_PAM */ + + void pass(char *passwd) { - int rval; FILE *fd; static char homedir[MAXPATHLEN]; char rootdir[MAXPATHLEN]; @@ -797,84 +1038,54 @@ return; } askpasswd = 0; +#ifndef USE_PAM if (!guest) { /* "ftp" is only account allowed no password */ - if (pw == NULL) { - useconds_t us; - - /* Sleep between 1 and 3 seconds to emulate a crypt. */ -#ifndef __linux__ - us = arc4random() % 3000000; -#else - us = random() % 3000000; -#endif - usleep(us); - rval = 1; /* failure below */ - goto skip; - } -#if defined(KERBEROS) - rval = klogin(pw, "", hostname, passwd); - if (rval == 0) - goto skip; -#endif -#ifdef SKEY - if (skey_haskey(pw->pw_name) == 0 && - (skey_passcheck(pw->pw_name, passwd) != -1)) { - rval = 0; - goto skip; - } #endif - /* the strcmp does not catch null passwords! */ - if (strcmp(crypt(passwd, pw->pw_passwd), pw->pw_passwd) || - *pw->pw_passwd == '\0') { - rval = 1; /* failure */ - goto skip; - } - rval = 0; - -skip: /* - * If rval == 1, the user failed the authentication check - * above. If rval == 0, either Kerberos or local authentication - * succeeded. + * Try to authenticate the user */ - if (rval) { + if (!authenticate(passwd)) { reply(530, "Login incorrect."); if (logging) - syslog(LOG_NOTICE, + syslog(LOG_FTP | LOG_NOTICE, "FTP LOGIN FAILED FROM %s, %s", remotehost, curname); pw = NULL; if (login_attempts++ >= 5) { - syslog(LOG_NOTICE, + syslog(LOG_FTP | LOG_NOTICE, "repeated login failures from %s", remotehost); exit(0); } return; } +#ifdef USE_PAM + if (guest) { +#else } else { +#endif /* Save anonymous' password. */ guestpw = strdup(passwd); if (guestpw == (char *)NULL) fatal("Out of memory"); } login_attempts = 0; /* this time successful */ -#ifdef USE_SHADOW +#if defined(USE_SHADOW) && !defined(USE_PAM) switch (isexpired(spw)) { case 0: /* success */ break; case 1: - syslog(LOG_NOTICE, "expired password from %s, %s", + syslog(LOG_FTP | LOG_NOTICE, "expired password from %s, %s", remotehost, pw->pw_name); reply(530, "Please change your password and try again."); return; case 2: - syslog(LOG_NOTICE, "inactive login from %s, %s", + syslog(LOG_FTP | LOG_NOTICE, "inactive login from %s, %s", remotehost, pw->pw_name); reply(530, "Login inactive -- contact administrator."); return; case 3: - syslog(LOG_NOTICE, "expired login from %s, %s", + syslog(LOG_FTP | LOG_NOTICE, "expired login from %s, %s", remotehost, pw->pw_name); reply(530, "Account expired -- contact administrator."); return; @@ -991,7 +1202,8 @@ setproctitle("%s", proctitle); #endif /* HASSETPROCTITLE */ if (logging) - syslog(LOG_INFO, "ANONYMOUS FTP LOGIN FROM %s, %s", + syslog(LOG_FTP | LOG_INFO, + "ANONYMOUS FTP LOGIN FROM %s, %s", remotehost, passwd); } else { reply(230, "User %s logged in.", pw->pw_name); @@ -1001,7 +1213,7 @@ setproctitle("%s", proctitle); #endif /* HASSETPROCTITLE */ if (logging) - syslog(LOG_INFO, "FTP LOGIN FROM %s as %s", + syslog(LOG_FTP | LOG_INFO, "FTP LOGIN FROM %s as %s", remotehost, pw->pw_name); } (void) umask(defumask); @@ -1064,7 +1276,7 @@ goto done; } } - dout = dataconn(name, st.st_size, "w"); + dout = dataconn(name, st.st_size, "w", 0); if (dout == NULL) goto done; time(&start); @@ -1088,6 +1300,9 @@ struct stat st; int fd; + if (restart_point && *mode != 'a') + mode = "r+"; + if (unique && stat(name, &st) == 0) { char *nam; @@ -1097,8 +1312,6 @@ return; } name = nam; - if (restart_point) - mode = "r+"; fout = fdopen(fd, mode); } else fout = fopen(name, mode); @@ -1139,7 +1352,7 @@ goto done; } } - din = dataconn(name, (off_t)-1, "r"); + din = dataconn(name, (off_t)-1, "r", unique); if (din == NULL) goto done; if (receive_data(din, fout) == 0) { @@ -1194,7 +1407,7 @@ #ifdef IP_TOS on = IPTOS_THROUGHPUT; if (setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&on, sizeof(int)) < 0) - syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); + syslog(LOG_FTP | LOG_WARNING, "setsockopt (IP_TOS): %m"); #endif #ifdef TCP_NOPUSH /* @@ -1205,13 +1418,13 @@ */ on = 1; if (setsockopt(s, IPPROTO_TCP, TCP_NOPUSH, (char *)&on, sizeof on) < 0) - syslog(LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); + syslog(LOG_FTP | LOG_WARNING, "setsockopt (TCP_NOPUSH): %m"); #endif #if 0 /* Respect the user's settings */ #ifdef SO_SNDBUF on = 65536; if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char *)&on, sizeof on) < 0) - syslog(LOG_WARNING, "setsockopt (SO_SNDBUF): %m"); + syslog(LOG_FTP | LOG_WARNING, "setsockopt (SO_SNDBUF): %m"); #endif #endif @@ -1227,7 +1440,7 @@ return (NULL); } -static FILE * dataconn(const char *name, off_t size, const char *mode) +static FILE * dataconn(const char *name, off_t size, const char *mode, int stou) { char sizebuf[32]; FILE *file; @@ -1236,8 +1449,8 @@ file_size = size; byte_count = 0; if (size != (off_t) -1) { - (void) snprintf(sizebuf, sizeof(sizebuf), " (%lld bytes)", - (quad_t) size); + (void) snprintf(sizebuf, sizeof(sizebuf), " (%jd bytes)", + (intmax_t) size); } else sizebuf[0] = '\0'; if (pdata >= 0) { @@ -1262,6 +1475,7 @@ pdata = -1; return (NULL); } +#ifdef BREAKRFC if (from.sin_addr.s_addr != his_addr.sin_addr.s_addr) { perror_reply(435, "Can't build data connection"); (void) close(pdata); @@ -1269,6 +1483,7 @@ pdata = -1; return (NULL); } +#endif (void) close(pdata); pdata = s; #ifdef IP_TOS @@ -1276,13 +1491,24 @@ (void) setsockopt(s, IPPROTO_IP, IP_TOS, (char *)&tos, sizeof(int)); #endif - reply(150, "Opening %s mode data connection for '%s'%s.", - type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + if (stou) { + reply(150, "FILE: %s", name); + } else { + reply(150, + "Opening %s mode data connection for '%s'%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, + sizebuf); + } return (fdopen(pdata, mode)); } if (data >= 0) { - reply(125, "Using existing data connection for '%s'%s.", - name, sizebuf); + if (stou) { + reply(125, "FILE: %s", name); + } else { + reply(125, + "Using existing data connection for '%s'%s.", + name, sizebuf); + } usedefault = 1; return (fdopen(data, mode)); } @@ -1309,12 +1535,14 @@ data = -1; return NULL; } +#ifdef BREAKRFC if (data_dest.sin_addr.s_addr != his_addr.sin_addr.s_addr) { perror_reply(435, "Can't build data connection"); (void) fclose(file); data = -1; return NULL; } +#endif while (connect(data, (struct sockaddr *)&data_dest, sizeof(data_dest)) < 0) { if (errno == EADDRINUSE && retry < swaitmax) { @@ -1327,8 +1555,14 @@ data = -1; return (NULL); } - reply(150, "Opening %s mode data connection for '%s'%s.", - type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); + if (stou) { + reply(150, "FILE: %s", name); + } else { + reply(150, + "Opening %s mode data connection for '%s'%s.", + type == TYPE_A ? "ASCII" : "BINARY", name, + sizebuf); + } return (file); } @@ -1383,7 +1617,7 @@ buf = mmap(0, filesize, PROT_READ, MAP_SHARED, filefd, (off_t)0); if (buf==MAP_FAILED || buf==NULL) { - syslog(LOG_WARNING, "mmap(%lu): %m", + syslog(LOG_FTP | LOG_WARNING, "mmap(%lu): %m", (unsigned long)filesize); goto oldway; } @@ -1655,8 +1889,8 @@ (void)printf("\r\n"); (void)fflush(stdout); if (debug) { - syslog(LOG_DEBUG, "<--- %d ", n); - vsyslog(LOG_DEBUG, fmt, ap); + syslog(LOG_FTP | LOG_DEBUG, "<--- %d ", n); + vsyslog(LOG_FTP | LOG_DEBUG, fmt, ap); } } @@ -1681,8 +1915,8 @@ (void)printf("\r\n"); (void)fflush(stdout); if (debug) { - syslog(LOG_DEBUG, "<--- %d- ", n); - vsyslog(LOG_DEBUG, fmt, ap); + syslog(LOG_FTP | LOG_DEBUG, "<--- %d- ", n); + vsyslog(LOG_FTP | LOG_DEBUG, fmt, ap); } } @@ -1758,15 +1992,21 @@ void replydirname(const char *name, const char *message) { + char *p, *ep; char npath[MAXPATHLEN]; - int i; - for (i = 0; *name != '\0' && i < (int)sizeof(npath) - 1; i++, name++) { - npath[i] = *name; - if (*name == '"') - npath[++i] = '"'; + p = npath; + ep = &npath[sizeof(npath) - 1]; + while (*name) { + if (*name == '"' && ep - p >= 2) { + *p++ = *name++; + *p++ = '"'; + } else if (ep - p >= 1) + *p++ = *name++; + else + break; } - npath[i] = '\0'; + *p = '\0'; reply(257, "\"%s\" %s", npath, message); } @@ -1838,7 +2078,7 @@ #endif /* HASSETPROCTITLE */ if (logging) - syslog(LOG_INFO, "connection from %s", remotehost); + syslog(LOG_FTP | LOG_INFO, "connection from %s", remotehost); } /* @@ -1847,22 +2087,8 @@ */ void dologout(int status) { - sigset_t allsigs; - transflag = 0; - - if (logged_in) { - sigfillset(&allsigs); - sigprocmask(SIG_BLOCK, &allsigs, NULL); - (void) seteuid((uid_t)0); - ftpdlogwtmp(ttyline, "", ""); - if (doutmp) - logout(utmp.ut_line); -#if defined(KERBEROS) - if (!notickets && krbtkfile_env) - unlink(krbtkfile_env); -#endif - } + end_login(); /* beware of flushing buffers after a SIGPIPE */ _exit(status); } @@ -1891,11 +2117,11 @@ } if (strcmp(cp, "STAT\r\n") == 0) { if (file_size != (off_t) -1) - reply(213, "Status: %qd of %qd bytes transferred", - (quad_t) byte_count, (quad_t) file_size); + reply(213, "Status: %jd of %jd bytes transferred", + (intmax_t) byte_count, (intmax_t) file_size); else - reply(213, "Status: %qd bytes transferred", - (quad_t)byte_count); + reply(213, "Status: %jd bytes transferred", + (intmax_t)byte_count); } errno = save_errno; } @@ -2101,7 +2327,7 @@ if (S_ISREG(st.st_mode)) { if (dout == NULL) { - dout = dataconn("file list", (off_t)-1, "w"); + dout = dataconn("file list", (off_t)-1, "w", 0); if (dout == NULL) goto out; transflag++; @@ -2143,7 +2369,7 @@ S_ISREG(st.st_mode))) { if (dout == NULL) { dout = dataconn("file list", (off_t)-1, - "w"); + "w", 0); if (dout == NULL) goto out; transflag++; @@ -2238,13 +2464,15 @@ if (hp) { if (!hosts_ctl("ftpd", hp->h_name, addr, STRING_UNKNOWN)) { - syslog(LOG_NOTICE, "tcpwrappers rejected: %s [%s]", + syslog(LOG_FTP | LOG_NOTICE, + "tcpwrappers rejected: %s [%s]", hp->h_name, addr); return (0); } } else { if (!hosts_ctl("ftpd", STRING_UNKNOWN, addr, STRING_UNKNOWN)) { - syslog(LOG_NOTICE, "tcpwrappers rejected: [%s]", addr); + syslog(LOG_FTP | LOG_NOTICE, + "tcpwrappers rejected: [%s]", addr); return (0); } } --- linux-ftpd-0.17.orig/ftpd/logwtmp.c +++ linux-ftpd-0.17/ftpd/logwtmp.c @@ -41,7 +41,6 @@ "$Id: logwtmp.c,v 1.5 1999/07/16 00:34:29 dholland Exp $"; #include -#include #include #include @@ -49,6 +48,7 @@ #include #include #include +#include #include "extern.h" static int fd = -1; --- linux-ftpd-0.17.orig/support/Makefile +++ linux-ftpd-0.17/support/Makefile @@ -1,6 +1,6 @@ include ../MCONFIG -OBJS=daemon.o setproctitle.o isexpired.o vis.o +OBJS=setproctitle.o isexpired.o vis.o all: libsupport.a @@ -16,4 +16,3 @@ rm -f *.o libsupport.a setproctitle.o: setproctitle.h -daemon.o: daemon.h --- linux-ftpd-0.17.orig/support/setproctitle.c +++ linux-ftpd-0.17/support/setproctitle.c @@ -139,7 +139,7 @@ (void) strcpy(Argv[0], buf); p = &Argv[0][i]; while (p < LastArgv) - *p++ = ' '; + *p++ = '\0'; Argv[1] = NULL; } debian/patches/560-set_default_key_and_cert.diff0000644000000000000000000000311611553435453016776 0ustar Description: Set default SSL key/cert file to /etc/ftpd-ssl/ftpd.pem Author: Ian Beckwith Index: linux-ftpd-ssl/ftpd/ftpd.c =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpd.c 2010-06-14 01:34:02.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpd.c 2010-06-14 01:34:02.000000000 +0100 @@ -175,6 +175,7 @@ /* for the moment this is a compile time option only --tjh */ int ssl_encrypt_data=1; +#define DEFAULT_SSL_FILE "/etc/ftpd-ssl/ftpd.pem" char ssl_file_path[1024]; /* don't look at that nasty value to the left */ X509 *ssl_public_cert; @@ -613,10 +614,8 @@ cin=stdin; cout=stderr; - /* do things the "default" way */ if (my_ssl_cert_file==NULL) { - sprintf(ssl_file_path,"%s/%s",X509_get_default_cert_dir(), - "ftpd.pem"); + strcpy(ssl_file_path,DEFAULT_SSL_FILE); ssl_cert_file=ssl_file_path; } else { ssl_cert_file=my_ssl_cert_file; @@ -689,8 +688,7 @@ "ftpd.cert"); #endif - sprintf(ssl_file_path,"%s/%s",X509_get_default_cert_dir(), - "ftpd.pem"); + strcpy(ssl_file_path,DEFAULT_SSL_FILE); filename=my_ssl_cert_file==NULL?ssl_file_path:my_ssl_cert_file; fp=fopen(filename,"r"); @@ -719,8 +717,7 @@ "ftpd.key"); #endif - sprintf(ssl_file_path,"%s/%s",X509_get_default_cert_dir(), - "ftpd.pem"); + strcpy(ssl_file_path,DEFAULT_SSL_FILE); filename=my_ssl_key_file==NULL?ssl_file_path:my_ssl_key_file; fp=fopen(filename,"r"); debian/patches/020-support_ipv6.diff0000644000000000000000000004544211553435453014447 0ustar Description: Activate support for IPv6 transport. This patch supplies working services for: . 1. Mixed IPv4 and IPv6 in inetd mode. . 2. Mixed IPv4 and IPv6 in standalone daemon mode. . 3. Selectable options '-4' and '-6' to activate a single address family. . 4. Registration in wtmp of the caller's address structure. This field in 'struct utmp' was earlier ignored, as it it an extension particular to Linux. . 5. Implementation of ABOR for use in idle state. . 6. Conversion of second time length in case a compatibility layer between 32 bits and 64 bits are in effect. . Testing was performed using xinetd and net.ipv6.bindv6only=1, on architectures i386 and amd64. Author: Mats Erik Andersson X-Depends: linux-ftpd-0.17/debian/patches/16-family_independence.diff X-Comment: This code is fully independent of any USAGI code, which is in use by the OpenBSD strand of this software. Forwarded: not-needed Last-Update: 2011-04-06 --- linux-ftpd-0.17.debian/ftpd/extern.h 2010-04-25 21:52:13.000000000 +0200 +++ linux-ftpd-0.17/ftpd/extern.h 2011-04-06 20:39:37.000000000 +0200 @@ -35,6 +35,8 @@ * $Id: extern.h,v 1.5 1999/07/16 01:12:54 dholland Exp $ */ +struct sockaddr_storage; + void blkfree __P((char **)); char **copyblk __P((char **)); void cwd __P((const char *)); @@ -44,12 +46,12 @@ void fatal __P((const char *)); int ftpd_pclose __P((FILE *)); FILE *ftpd_popen __P((char *, const char *)); int ftpd_getline __P((char *, int, FILE *)); -void ftpdlogwtmp __P((const char *, const char *, const char *)); +void ftpdlogwtmp __P((const char *, const char *, const char *, const struct sockaddr_storage *)); void lreply __P((int, const char *, ...)); void makedir __P((char *)); void nack __P((const char *)); void pass __P((char *)); -void passive __P((void)); +void passive __P((int)); void perror_reply __P((int, const char *)); void pwd __P((void)); void removedir __P((char *)); @@ -61,6 +63,7 @@ void send_file_list __P((const char *)); void statcmd __P((void)); void statfilecmd __P((char *)); void store __P((const char *, const char *, int)); +int test_eprt_string __P((char *)); void upper __P((char *)); void user __P((char *)); void yyerror __P((char *)); --- linux-ftpd-0.17.debian/ftpd/ftpcmd.y 2010-04-30 14:45:33.000000000 +0200 +++ linux-ftpd-0.17/ftpd/ftpcmd.y 2011-04-06 20:40:27.000000000 +0200 @@ -75,7 +75,7 @@ char ftpcmd_rcsid[] = #include "extern.h" -extern struct sockaddr_in data_dest; +extern struct sockaddr_storage data_dest; extern int logged_in; extern struct passwd *pw; extern int guest; @@ -92,7 +92,9 @@ extern int usedefault; extern int transflag; extern char tmpline[]; extern int portcheck; -extern struct sockaddr_in his_addr; +extern int use_ipv6; +extern int use_ipv4; +extern struct sockaddr_storage his_addr; off_t restart_point; @@ -167,6 +169,7 @@ cmp_addresses(struct sockaddr * left, st ABOR DELE CWD LIST NLST SITE STAT HELP NOOP MKD RMD PWD CDUP STOU SMNT SYST SIZE MDTM + EPRT EPSV UMASK IDLE CHMOD @@ -177,7 +180,7 @@ cmp_addresses(struct sockaddr * left, st %type check_login octal_number byte_size %type struct_code mode_code type_code form_code -%type pathstring pathname password username +%type pathstring pathname password username transport %type host_port %start cmd_list @@ -219,6 +222,7 @@ cmd reply(500, "Illegal PORT rejected (reserved port)."); } else if (portcheck && + data_dest.ss_family == his_addr.ss_family && cmp_addresses((struct sockaddr *) &data_dest, (struct sockaddr *) &his_addr)) { usedefault = 1; @@ -235,10 +239,49 @@ cmd } } } + | EPRT check_login SP transport CRLF + { + if ($2) { + int rc = test_eprt_string($4); + + switch (rc) { + case 1: /* Syntax error. */ + reply(500, "Syntax error, command unrecognized."); + break; + case 2: /* Protocol family error. */ + reply(522, "Network protocol not supported, use (%c).", + his_addr.ss_family == AF_INET6 ? '2' : '1'); + break; + case 3: /* Invalid address and port combination. */ + reply(501, "Illegal EPRT rejected (address wrong)."); + break; + case 0: /* Successful parsing. */ + reply(200, "EPRT command successful."); + } + } + } | PASV check_login CRLF { if ($2) { - passive(); + passive(0); + } + } + | EPSV check_login CRLF + { + if ($2) { + passive(1); + } + } + | EPSV check_login SP NUMBER CRLF + { + if ($2) { + if ( ($4 == 1 && his_addr.ss_family == AF_INET) + || ($4 == 2 && his_addr.ss_family == AF_INET6) ) + passive(1); + else + reply(501, + "Not a compatible address family, use (%c)", + his_addr.ss_family == AF_INET6 ? '2' : '1'); } } | TYPE check_login SP type_code CRLF @@ -395,8 +438,16 @@ cmd } | ABOR check_login CRLF { - if ($2) - reply(225, "ABOR command successful."); + if ($2) { + if (pdata >= 0) { + close(pdata); + pdata = -1; + usedefault = 1; + reply(226, "Closing data connection."); + } else { + reply(226, "ABOR command caused no action."); + } + } } | CWD check_login CRLF { @@ -675,10 +726,16 @@ host_port snprintf(port, sizeof(port), "%ju", 256 * $9 + $11); memset(&hints, 0, sizeof(hints)); - hints.ai_family = AF_INET; /* Enable mapped addressing? */ + hints.ai_family = AF_INET; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST | AI_NUMERICSERV; + if (his_addr.ss_family == AF_INET6) { + hints.ai_family = AF_INET6; + if (use_ipv4) + hints.ai_flags |= AI_V4MAPPED; + } + if (getaddrinfo(ipaddr, port, &hints, &aiptr)) { $$ = 1; } else { @@ -692,6 +749,10 @@ host_port } ; +transport + : STRING + ; + form_code : N { @@ -890,6 +951,9 @@ struct tab cmdtab[] = { /* In order def { "QUIT", QUIT, ARGS, 1, "(terminate service)", }, { "PORT", PORT, ARGS, 1, " b0, b1, b2, b3, b4" }, { "PASV", PASV, ARGS, 1, "(set server in passive mode)" }, + /* Extensions introduced in RFC 2428: EPRT, EPSV. */ + { "EPRT", EPRT, STR1, 1, " addr_fam addr port " }, + { "EPSV", EPSV, ARGS, 1, "[ addr-fam ]"}, { "TYPE", TYPE, ARGS, 1, " [ A | E | I | L ]" }, { "STRU", STRU, ARGS, 1, "(specify file structure)" }, { "MODE", MODE, ARGS, 1, "(specify transfer mode)" }, --- linux-ftpd-0.17.debian/ftpd/ftpd.8 2010-04-25 21:52:13.000000000 +0200 +++ linux-ftpd-0.17/ftpd/ftpd.8 2010-05-08 01:23:15.000000000 +0200 @@ -64,6 +64,10 @@ service specification; see .Pp Available options: .Bl -tag -width Ds +.It Fl 4 +Use IPv4 addressing only. Th default is to offer service for both families, IPv6 and IPv4. +.It Fl 6 +Only provide IPv6 addressing capability. .It Fl A Permit only anonymous ftp connections or accounts listed in .Pa /etc/ftpchroot. @@ -180,6 +184,8 @@ The case of the requests is ignored. .It CDUP Ta "change to parent of current working directory" .It CWD Ta "change working directory" .It DELE Ta "delete a file" +.It EPRT Ta "specify data connection port, either IPv4 or IPv6" +.It EPSV Ta "ask for a server port for fetching data" .It HELP Ta "give help information" .It LIST Ta "give list files in a directory" Pq Dq Li "ls -lgA" .It MKD Ta "make a directory" --- linux-ftpd-0.17.debian/ftpd/ftpd.c 2010-04-30 14:46:19.000000000 +0200 +++ linux-ftpd-0.17/ftpd/ftpd.c 2011-04-06 20:43:42.000000000 +0200 @@ -148,12 +148,12 @@ static char version[sizeof(versionpre)+s extern off_t restart_point; extern char cbuf[]; -struct sockaddr_in server_addr; -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 server_addr; +struct sockaddr_storage ctrl_addr; +struct sockaddr_storage data_source; +struct sockaddr_storage data_dest; +struct sockaddr_storage his_addr; +struct sockaddr_storage pasv_addr; int daemon_mode = 0; int data; @@ -169,6 +169,8 @@ int timeout = 900; /* timeout after 1 int maxtimeout = 7200; /* don't allow idle time to be set beyond 2 hours */ int numeric_hosts = 0; /* log numeric IP rather than doing lookup */ int logging; +int use_ipv6 = 1; /* Let listening socket use IPv6. */ +int use_ipv4 = 1; /* Let listening socket use IPv4. */ int high_data_ports = 0; int anon_only = 0; int multihome = 0; @@ -371,7 +373,7 @@ main(int argc, char *argv[], char **envp socklen_t addrlen; char *cp, line[LINE_MAX]; FILE *fd; - const char *argstr = "AdDhlMnSt:T:u:UvP"; + const char *argstr = "AdDhlMnSt:T:u:UvP46"; struct addrinfo hints, *aiptr; #ifdef __linux__ @@ -471,6 +473,16 @@ main(int argc, char *argv[], char **envp debug = 1; break; + case '6': + use_ipv6 = 1; + use_ipv4 = 0; + break; + + case '4': + use_ipv6 = 0; + use_ipv4 = 1; + break; + default: warnx("unknown flag -%c ignored", optopt); break; @@ -517,7 +529,7 @@ main(int argc, char *argv[], char **envp memset(&hints, 0, sizeof(hints)); hints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG; hints.ai_socktype = SOCK_STREAM; - hints.ai_family = AF_INET; + hints.ai_family = use_ipv6 ? AF_INET6 : AF_INET; if ((rc = getaddrinfo(NULL, "ftp", &hints, &aiptr))) { syslog(LOG_FTP | LOG_ERR, @@ -535,6 +547,16 @@ main(int argc, char *argv[], char **envp (char *)&on, sizeof(on)) < 0) syslog(LOG_FTP | LOG_ERR, "control setsockopt: %m");; + /* Should the listening control socket be dual stacked? + * Only one case needs this: use_ipv6 = use_ipv4 = 1. */ + if (ai->ai_family == AF_INET6 && use_ipv4) { + socklen_t off = 0; + + if (setsockopt(ctl_sock, IPPROTO_IPV6, IPV6_V6ONLY, + &off, sizeof(off))) + syslog(LOG_FTP | LOG_ERR, "control setsockopt: %m"); + } + if (bind(ctl_sock, ai->ai_addr, ai->ai_addrlen)) { close(ctl_sock); continue; @@ -894,7 +916,7 @@ static void end_login(void) pam_end(pamh, error); pamh = 0; #endif - ftpdlogwtmp(ttyline, "", ""); + ftpdlogwtmp(ttyline, "", "", NULL); if (doutmp) logout(utmp.ut_line); #if defined(KERBEROS) @@ -1186,15 +1208,39 @@ void pass(char *passwd) (void) initgroups(pw->pw_name, pw->pw_gid); /* open wtmp before chroot */ - ftpdlogwtmp(ttyline, pw->pw_name, remotehost); + ftpdlogwtmp(ttyline, pw->pw_name, remotehost, &his_addr); /* open utmp before chroot */ if (doutmp) { memset((void *)&utmp, 0, sizeof(utmp)); + +#if __WORDSIZE == 64 && __WORDSIZE_COMPAT32 + /* Length of 'time_t' is 64 bits, but 'utmp.ut_time' has 32 bits.*/ + time_t now; + + (void)time(&now); + utmp.ut_time = now & 0xffffffff; /* Discard the upper 32 bits. */ +#else + /* Equal size time representations. */ (void)time(&utmp.ut_time); +#endif /* Mixed 64 and 32 bits time */ + (void)strncpy(utmp.ut_name, pw->pw_name, sizeof(utmp.ut_name)); (void)strncpy(utmp.ut_host, remotehost, sizeof(utmp.ut_host)); (void)strncpy(utmp.ut_line, ttyline, sizeof(utmp.ut_line)); + switch (his_addr.ss_family) { + case AF_INET6: + memcpy(&utmp.ut_addr, + &((struct sockaddr_in6 *) &his_addr)->sin6_addr, + sizeof(struct in6_addr)); + break; + case AF_INET: + memcpy(&utmp.ut_addr, + &((struct sockaddr_in *) &his_addr)->sin_addr, + sizeof(struct in_addr)); + default: + break; + } login(&utmp); } @@ -1465,6 +1511,7 @@ done: static FILE * getdatasock(const char *mode) { int on = 1, s, t, tries; + socklen_t off = 0; sigset_t allsigs; if (data >= 0) @@ -1472,12 +1519,17 @@ static FILE * getdatasock(const char *mo sigfillset(&allsigs); sigprocmask (SIG_BLOCK, &allsigs, NULL); (void) seteuid((uid_t)0); - s = socket(his_addr.sin_family, SOCK_STREAM, 0); + s = socket(his_addr.ss_family, SOCK_STREAM, 0); if (s < 0) goto bad; if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, (char *) &on, sizeof(on)) < 0) goto bad; + if (his_addr.ss_family == AF_INET6 && use_ipv4) + if (setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, + &off, sizeof(off))) + syslog(LOG_FTP | LOG_ERR, "getdatasock(), setsockopt: %m"); + /* anchor socket to avoid multi-homing problems */ memcpy(&data_source, &ctrl_addr, sizeof(data_source)); set_port((struct sockaddr *) &data_source, data_port); @@ -1568,7 +1620,6 @@ static FILE * dataconn(const char *name, return (NULL); } #ifdef BREAKRFC - //if (from.sin_addr.s_addr != his_addr.sin_addr.s_addr) { if (cmp_addresses((struct sockaddr *) &from, (struct sockaddr *) &his_addr)) { perror_reply(435, "Can't build data connection"); @@ -1636,7 +1687,6 @@ static FILE * dataconn(const char *name, return NULL; } #ifdef BREAKRFC - //if (data_dest.sin_addr.s_addr != his_addr.sin_addr.s_addr) { if (cmp_addresses((struct sockaddr *) &data_dest, (struct sockaddr *) &his_addr)) { perror_reply(435, "Can't build data connection"); @@ -2245,15 +2295,19 @@ static void myoob(int signo) errno = save_errno; } +#define IS_MAPPED_IPV4(a) \ + (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *) (a))->sin6_addr) || \ + IN6_IS_ADDR_V4COMPAT(&((struct sockaddr_in6 *) (a))->sin6_addr)) + /* * Note: a response of 425 is not mentioned as a possible response to * the PASV command in RFC959. However, it has been blessed as * a legitimate response by Jon Postel in a telephone conversation * with Rick Adams on 25 Jan 89. */ -void passive(void) +void passive(int extend) { - socklen_t len; + socklen_t len, off = 0; #ifdef IP_PORTRANGE int on; #else @@ -2266,11 +2320,15 @@ void passive(void) } if (pdata >= 0) close(pdata); - pdata = socket(his_addr.sin_family, SOCK_STREAM, 0); + pdata = socket(his_addr.ss_family, SOCK_STREAM, 0); if (pdata < 0) { perror_reply(425, "Can't open passive connection"); return; } + if (his_addr.ss_family == AF_INET6 && use_ipv4) + if (setsockopt(pdata, IPPROTO_IPV6, IPV6_V6ONLY, + &off, sizeof(off))) + syslog(LOG_FTP | LOG_ERR, "passive(), setsockopt: %m"); memcpy(&pasv_addr, &ctrl_addr, sizeof(pasv_addr)); @@ -2312,10 +2370,7 @@ void passive(void) #define UC(b) (((int) b) & 0xff) - if (((struct sockaddr *) &pasv_addr)->sa_family == AF_INET6) - reply(229, "Extended Passive Mode OK (|||%d|)", - get_port((struct sockaddr *) &pasv_addr)); - else { + if (!extend && (pasv_addr.ss_family == AF_INET || IS_MAPPED_IPV4(&pasv_addr))) { uint32_t ip4ad = get_ipv4address((struct sockaddr *) &pasv_addr); in_port_t port = get_port((struct sockaddr *) &pasv_addr); @@ -2323,6 +2378,9 @@ void passive(void) UC(ip4ad >> 24), UC(ip4ad >> 16), UC(ip4ad >> 8), UC(ip4ad), UC(port >> 8), UC(port)); + } else { + reply(229, "Extended Passive Mode OK (|||%d|)", + get_port((struct sockaddr *) &pasv_addr)); } #undef UC @@ -2337,6 +2395,93 @@ pasv_error: } /* + * test_eprt_string(char *) + * + * Parse the transport string used in EPRT command. + * + * Return values: + * + * 0: Success. Valid address in data_dest. + * 1: Syntax error. + * 2: Incorrect protocol family. + * 3: Invalid address, or port, specification. + */ +int test_eprt_string(char * trans) +{ + char delim, ipaddr[INET6_ADDRSTRLEN], portstr[12]; + int pf, port; + unsigned int j = 0; + struct addrinfo hints, *aiptr; + + /* Easy sanity checks first. */ + if ( ! trans || strlen(trans) < 10 ) + return 1; /* Syntax error. */ + + /* Parse the contents. */ + delim = *(trans++); + if ( *trans != '1' && *trans != '2') + return 2; /* Protocol family error. */ + + if ( *(trans+1) != delim ) + return 1; /* Syntax error. */ + + pf = *trans - '0'; /* The character is '1' or '2'. */ + + /* Check that address families match the claimed protocol. */ + if ((pf != 1 && his_addr.ss_family == AF_INET) + || (pf != 2 && his_addr.ss_family == AF_INET6)) + return 2; /* Protocol family error. */ + + trans += 2; /* Jump to IP address portion, and extract it. */ + while (*trans && (j < sizeof(ipaddr) - 1) && + strchr("0123456789abcdefABCDEF.:", *trans)) + ipaddr[j++] = *(trans++); + + ipaddr[j] = '\0'; + + if (*trans != delim) + return 1; /* Syntax error. */ + + ++trans; + + /* A port number should be next. */ + if (sscanf(trans, "%u", &port) != 1) + return 1; /* Syntax error. */ + + while (isdigit(*trans)) + ++trans; + + /* Last delimiter, at least one digit present by previous test. */ + if (*trans != delim) + return 1; /* Syntax error. */ + + /* All components are parsed. Now try establishing the address. */ + sprintf(portstr, "%d", port); + memset(&hints, 0, sizeof(hints)); + hints.ai_family = his_addr.ss_family; + hints.ai_socktype = SOCK_STREAM; + hints.ai_flags = AI_ADDRCONFIG | AI_NUMERICHOST | AI_NUMERICSERV; + + if (getaddrinfo(ipaddr, portstr, &hints, &aiptr)) + return 3; /* Invalid address and port combination. */ + + /* Record the established address. */ + memcpy(&data_dest, aiptr->ai_addr, aiptr->ai_addrlen); + freeaddrinfo(aiptr); + + /* Close any previous passive socket. */ + if (pdata >= 0) { + close(pdata); + pdata = -1; + } + + /* Turn standard listening mechanism off. A valid address exists! */ + usedefault = 0; + + return 0; /* Success. */ +} /* test_eprt_string(char *) */ + +/* * Generate unique name for file with basename "local". * The file named "local" is already known to exist. * Generates failure reply on error. --- linux-ftpd-0.17.debian/ftpd/logwtmp.c 2010-04-25 21:52:13.000000000 +0200 +++ linux-ftpd-0.17/ftpd/logwtmp.c 2010-05-09 02:06:48.000000000 +0200 @@ -49,6 +49,7 @@ char logwtmp_rcsid[] = #include #include #include +#include #include "extern.h" static int fd = -1; @@ -59,7 +60,8 @@ static int fd = -1; * after login, but before logout). */ void -ftpdlogwtmp(const char *line, const char *name, const char *host) +ftpdlogwtmp(const char *line, const char *name, + const char *host, const struct sockaddr_storage *ss) { struct utmp ut; struct stat buf; @@ -72,10 +74,36 @@ ftpdlogwtmp(const char *line, const char ut.ut_type = *name ? USER_PROCESS : DEAD_PROCESS; ut.ut_pid = getpid(); #endif + +#if __WORDSIZE == 64 && __WORDSIZE_COMPAT32 + /* Length of 'time_t' is 64 bits, but 'ut.ut_time' has 32 bits.*/ + time_t now; + + (void)time(&now); + ut.ut_time = now & 0xffffffff; /* Discard the upper 32 bits. */ +#else + /* Equal size time representations. */ + (void)time(&ut.ut_time); +#endif /* Mixed 64 and 32 bits time */ + (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)); - (void)time(&ut.ut_time); + if (ss) { + switch (ss->ss_family) { + case AF_INET6: + memcpy(&ut.ut_addr, + &((const struct sockaddr_in6 *) ss)->sin6_addr, + sizeof(struct in6_addr)); + break; + case AF_INET: + memcpy(&ut.ut_addr, + &((const struct sockaddr_in *) ss)->sin_addr, + sizeof(struct in_addr)); + default: + break; + } + } if (write(fd, (char *)&ut, sizeof(struct utmp)) != sizeof(struct utmp)) (void)ftruncate(fd, buf.st_size); debian/patches/010-ftpd_csrf.diff0000644000000000000000000000666611553435453013745 0ustar Description: Fix cross-site request forgery (CSRF) attacks. Author: Ian Beckwith X-Original-Location: http://bugs.debian.org/cgi-bin/bugreport.cgi?msg=29;filename=ftpd-csrf.patch;att=1;bug=500278 X-Closes: Bug #500278 X-Comment: Recovered as interdiff between linux-ftpd_0.17-23.diff.gz and linux-ftpd_0.17-29.diff.gz. Forwarded: no Last-Update: 2008-10-17 --- linux-ftpd-0.17.orig/ftpd/extern.h +++ linux-ftpd-0.17/ftpd/extern.h @@ -43,7 +43,7 @@ void fatal __P((const char *)); int ftpd_pclose __P((FILE *)); FILE *ftpd_popen __P((char *, const char *)); -char *ftpd_getline __P((char *, int, FILE *)); +int ftpd_getline __P((char *, int, FILE *)); void ftpdlogwtmp __P((const char *, const char *, const char *)); void lreply __P((int, const char *, ...)); void makedir __P((char *)); diff -u linux-ftpd-0.17/ftpd/ftpcmd.y linux-ftpd-0.17/ftpd/ftpcmd.y --- linux-ftpd-0.17/ftpd/ftpcmd.y +++ linux-ftpd-0.17/ftpd/ftpcmd.y @@ -920,7 +920,7 @@ /* * getline - a hacked up version of fgets to ignore TELNET escape codes. */ -char * ftpd_getline(char *s, int n, FILE *iop) +int ftpd_getline(char *s, int n, FILE *iop) { int c; register char *cs; @@ -934,7 +934,7 @@ if (debug) syslog(LOG_FTP | LOG_DEBUG, "command: %s", s); tmpline[0] = '\0'; - return(s); + return(0); } if (c == 0) tmpline[0] = '\0'; @@ -965,11 +965,22 @@ } } *cs++ = c; - if (--n <= 0 || c == '\n') + if (--n <= 0) { + /* + * If command doesn't fit into buffer, discard the + * rest of the command and indicate truncation. + * This prevents the command to be split up into + * multiple commands. + */ + while (c != '\n' && (c = getc(iop)) != EOF) + ; + return (-2); + } + if (c == '\n') break; } if (c == EOF && cs == s) - return (NULL); + return (-1); *cs++ = '\0'; if (debug) { if (!guest && strncasecmp("pass ", s, 5) == 0) { @@ -989,7 +1000,7 @@ syslog(LOG_FTP | LOG_DEBUG, "command: %.*s", len, s); } } - return (s); + return (0); } void toolong(int signo) @@ -1018,9 +1029,14 @@ case CMD: (void) signal(SIGALRM, toolong); (void) alarm((unsigned) timeout); - if (ftpd_getline(cbuf, sizeof(cbuf)-1, stdin)==NULL) { - reply(221, "You could at least say goodbye."); - dologout(0); + n=ftpd_getline(cbuf, sizeof(cbuf)-1, stdin); + if (n == -1) { + reply(221, "You could at least say goodbye."); + dologout(0); + } else if (n == -2) { + reply(500, "Command too long."); + alarm(0); + continue; } (void) alarm(0); if ((cp = strchr(cbuf, '\r'))) { diff -u linux-ftpd-0.17/ftpd/ftpd.c linux-ftpd-0.17/ftpd/ftpd.c --- linux-ftpd-0.17/ftpd/ftpd.c +++ linux-ftpd-0.17/ftpd/ftpd.c @@ -2111,6 +2111,7 @@ static void myoob(int signo) { char *cp; + int ret; int save_errno = errno; (void)signo; @@ -2119,9 +2120,13 @@ if (!transflag) return; cp = tmpline; - if (ftpd_getline(cp, 7, stdin) == NULL) { + ret=ftpd_getline(cp, 7, stdin); + if (ret == -1) { reply(221, "You could at least say goodbye."); dologout(0); + } else if (ret == -2) { + /* Ignore truncated command */ + return; } upper(cp); if (strcmp(cp, "ABOR\r\n") == 0) { debian/patches/510-old_patches.diff0000644000000000000000000000737011553435453014256 0ustar Description: Patches up to linux-ftpd-ssl 0.17.18+0.3-3 Author: Christoph Martin Cai Qian and probably others Last-Update: 2010-06-09 Index: linux-ftpd-ssl/ftpd/ftpd.8 =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpd.8 2010-07-25 01:21:47.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpd.8 2010-07-25 01:21:47.000000000 +0100 @@ -148,6 +148,53 @@ .It Fl u Change the default umask from 027 to .Ar mask . +.It Fl z Ar SSL-parameter +This option is only valid if +.Nm ftpd +has been built with SSL (Secure Socket Layer) support. +.Bl -tag -width Fl +.It Ic debug +Enable SSL related debugging. +.It Ic ssl +Negotiate SSL at first, then use ftp protocol. In this mode ftpd +only accepts connections from SSL enhanced ftp with option +.Ic -z ssl . +(Not yet implemented) +.It Ic nossl, !ssl +switch of SSL negotiation +.It Ic certsok +Look username up in /etc/ssl.users. The format of this file is lines +of this form: +.Ar user1,user2:/C=US/..... +where user1 and user2 are usernames. If client certificate is valid, +authenticate without password. +.It Ic certrequired +client certificate is mandatory +.It Ic secure +Don't switch back to unencrypted mode (no SSL) if SSL is not available. +.It Ic verify=int +.\" TODO +Set the SSL verify flags (SSL_VERIFY_* in +.Ar ssl/ssl.h +). +.\" TODO +.It Ic cert=cert_file +.\" TODO +Use the certificate(s) in +.Ar cert_file . +.It Ic key=key_file +.\" TODO +Use the key(s) in +.Ar key_file . +.It Ic cipher=ciph_list +.\" TODO +Set the preferred ciphers to +.Ar ciph_list . +.\" TODO: possible values; comma-separated list? +(See +.Ar ssl/ssl.h +). +.El .El .Pp The file Index: linux-ftpd-ssl/ftpd/ftpd.c =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpd.c 2010-07-25 01:21:47.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpd.c 2010-07-25 01:21:47.000000000 +0100 @@ -1426,7 +1426,7 @@ #ifdef USE_SSL && !ssl_auto_login #endif - ) { /* "ftp" is only account allowed no password */ + ) { /* "ftp" is only account allowed no password */ #endif /* * Try to authenticate the user @@ -1447,7 +1447,11 @@ return; } #ifdef USE_PAM - if (guest) { + if (guest +#ifdef USE_SSL + || ssl_auto_login +#endif + ) { #else } else { #endif @@ -1988,10 +1992,7 @@ BIO_printf(bio_err,"===>DONE SSL_accept on DATA\n"); } else { - reply(150, "Opening %s mode data connection for %s%s.", - type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); - } -#else /* !USE_SSL */ +#endif /* USE_SSL */ if (stou) { reply(150, "FILE: %s", name); } else { @@ -2000,6 +2001,8 @@ type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); } +#ifdef USE_SSL + } #endif /* USE_SSL */ return (fdopen(pdata, mode)); } @@ -2122,10 +2125,7 @@ BIO_printf(bio_err,"===>DONE SSL_accept on DATA\n"); } else { - reply(150, "Opening %s mode data connection for %s%s.", - type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); - } -#else /* !USE_SSL */ +#endif /* USE_SSL */ if (stou) { reply(150, "FILE: %s", name); } else { @@ -2134,6 +2134,8 @@ type == TYPE_A ? "ASCII" : "BINARY", name, sizebuf); } +#ifdef USE_SSL + } #endif /* USE_SSL */ return (file); } Index: linux-ftpd-ssl/ftpd/ftpcmd.y =================================================================== --- linux-ftpd-ssl.orig/ftpd/ftpcmd.y 2010-07-25 01:21:47.000000000 +0100 +++ linux-ftpd-ssl/ftpd/ftpcmd.y 2010-07-25 01:21:47.000000000 +0100 @@ -227,7 +227,7 @@ { if (!strncmp((char *) $3,"SSL",3)) { #ifdef USE_SSL - reply(334, "AUTH SSL OK."); + reply(234, "AUTH SSL OK."); /* now do all the hard work :-) */ do_ssl_start(); debian/patches/series0000644000000000000000000000060511553435453012043 0ustar 001-from_hamm.diff 002-from_sarge.diff 003-from_etch.diff 010-ftpd_csrf.diff 014-adjust_infrastruct.diff 016-family_independence.diff 020-support_ipv6.diff 024-failing_va_list.diff 026-support_glibc_bsd_and_gnu.diff 030-manpage_typos.diff 500-ssl.diff 510-old_patches.diff 520-CVE-2005-3524.diff 530-CVE-2007-6263.diff 540-docs.diff 550-fix_warnings.diff 560-set_default_key_and_cert.diff debian/patches/003-from_etch.diff0000644000000000000000000000312211553435453013723 0ustar Description: Patches recovered from linux-ftpd_0.17-23.diff.gz. Interdiff against linux-ftpd_0.17-20sarge2.diff.gz. Author: Alberto Gonzalaez Iniesta X-Comment: Contribution by Matt Power, Stefan Cornelius, Paul Szabo, and Andreas Jochens. Forwarded: no Last-Update: 2006-11-25 diff -u linux-ftpd-0.17/ftpd/ftpcmd.y linux-ftpd-0.17/ftpd/ftpcmd.y --- linux-ftpd-0.17/ftpd/ftpcmd.y +++ linux-ftpd-0.17/ftpd/ftpcmd.y @@ -101,7 +101,14 @@ char cbuf[512]; char *fromname; -struct tab; +struct tab { + const char *name; + short token; + short state; + short implemented; /* 1 if command is implemented */ + const char *help; +}; + static int yylex __P((void)); static void sizecmd __P((char *)); static void help __P((struct tab *, char *)); @@ -834,14 +841,6 @@ #define SITECMD 7 /* SITE command */ #define NSTR 8 /* Number followed by a string */ -struct tab { - const char *name; - short token; - short state; - short implemented; /* 1 if command is implemented */ - const char *help; -}; - struct tab cmdtab[] = { /* In order defined in RFC 765 */ { "USER", USER, STR1, 1, " username" }, { "PASS", PASS, ZSTR1, 1, " password" }, diff -u linux-ftpd-0.17/ftpd/popen.c linux-ftpd-0.17/ftpd/popen.c --- linux-ftpd-0.17/ftpd/popen.c +++ linux-ftpd-0.17/ftpd/popen.c @@ -174,7 +174,7 @@ * PSz 25 Aug 06 Must check the return status of these setgid/setuid calls, * see http://www.bress.net/blog/archives/34-setuid-madness.html */ - if ( setgid(geteuid()) != 0 ) _exit(1); + if ( setgid(getegid()) != 0 ) _exit(1); if ( setuid(i) != 0 ) _exit(1); #ifndef __linux__ debian/pam.d/0000755000000000000000000000000011553435453010175 5ustar debian/pam.d/ftp0000644000000000000000000000063011553435453010710 0ustar # Standard behaviour for ftpd(8). auth required pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed # This line is required by ftpd(8). auth sufficient pam_ftp.so # Uncomment this to achieve what used to be ftpd -A. #auth required pam_listfile.so item=user sense=allow file=/etc/ftpchroot onerr=fail # Standard blurb. @include common-auth @include common-account @include common-session debian/NEWS0000644000000000000000000000327711553435453007706 0ustar linux-ftpd-ssl (0.17.31+0.3-1) unstable; urgency=low The recent IPv6 capability is handled in distinct ways by the three usual super-servers: openbsd-inetd, xinetd, and inetutils-inetd. The differences are discussed in the file README.Debian. Depending on your old setup, 'update-inetd' might complain about multiple instances of 'ftp' in '/etc/inetd.conf'. The present version tries to counter-act this at future upgrades by inserting '--multi' in the maintainer scripts. -- Mats Erik Andersson Tue, 25 May 2010 20:12:28 +0200 linux-ftpd-ssl (0.17.30+0.3-1) unstable; urgency=low This packaging of linux-ftpd incorporates working support for the IPv6 address family, in stand alone mode, as well as under the control of a super server like xinetd. The records made in wtmp now include the caller's address structure, thus improving the prospects of tracing clients. -- Mats Erik Andersson Sat, 08 May 2010 19:54:28 +0200 linux-ftpd-ssl (0.17.27+0.3-2) unstable; urgency=low * SSL keys/certificates generated since 2006-09-17 with Debian's openssl package are vulnerable due to a predictable random number generator. For more details see: http://www.debian.org/security/2008/dsa-1571 http://www.debian.org/security/key-rollover/ http://wiki.debian.org/SSLkeys * To generate new keys using the default ftpd-ssl setup (as root): rm -f /etc/ftpd-ssl/ftpd.pem /etc/ssl/certs/ftpd.pem dpkg-reconfigure ftpd-ssl * If you have set up any SSL infrastructure beyond this, it will also need to be regenerated. -- Ian Beckwith Wed, 21 May 2008 18:48:51 +0100 debian/dirs0000644000000000000000000000010611553435453010057 0ustar etc/pam.d usr/share/man/man5 usr/share/man/man8 usr/sbin etc/ftpd-ssl debian/copyright0000644000000000000000000000355711553435453011143 0ustar This package was split from netstd by Herbert Xu herbert@debian.org on Thu, 1 Apr 1999 16:42:48 +1000. netstd was created by Peter Tobias tobias@et-inf.fho-emden.de on Wed, 20 Jul 1994 17:23:21 +0200. It was downloaded from ftp://ftp.uk.linux.org/pub/linux/Networking/netkit/. Copyright: /************************************************************************ Copyright 1988, 1991 by Carnegie Mellon University All Rights Reserved Permission to use, copy, modify, and distribute this software and its documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that both that copyright notice and this permission notice appear in supporting documentation, and that the name of Carnegie Mellon University not be used in advertising or publicity pertaining to distribution of the software without specific, written prior permission. CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL CMU BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ************************************************************************/ /* * The modifications to support SSLeay were done by Tim Hudson * tjh@cryptsoft.com * * You can do whatever you like with these patches except pretend that * you wrote them. * */ Files: debian/patches/16-family_independence.diff debian/patches/20-support_ipv6.diff Copyright: 2010, Mats Erik Andersson License: BSD X-Comment: The license of the original software applies to these patches. debian/postinst0000644000000000000000000000200611553435453011002 0ustar #!/bin/sh # $Id: postinst,v 1.7 2003/06/21 02:31:44 herbert Exp $ set -e if grep -q '[[:blank:]]/usr/sbin/in\.ftpd.*-z' /etc/inetd.conf 2>/dev/null; then update-inetd --pattern '/usr/sbin/in\.ftpd' --remove ".*ftp" fi if grep -q '[[:blank:]]/usr/sbin/in\.ftpd\>' /etc/inetd.conf 2>/dev/null; then if ! grep -q '^ftp\>' /etc/inetd.conf; then update-inetd --pattern '/usr/sbin/in\.ftpd' --multi --enable ftp fi else FTPENTRY="ftp stream tcp nowait root /usr/sbin/tcpd /usr/sbin/in.ftpd" if grep -q '^ftp\>' /etc/inetd.conf 2>/dev/null; then update-inetd --group STANDARD --add "## $FTPENTRY" else update-inetd --group STANDARD --add "$FTPENTRY" fi fi if [ ! -f /etc/inetd.conf -a -d /etc/xinetd.d -a -x /usr/sbin/xinetd ]; then cat <<-TEXT ------------------------------------------------ There is an example configuration for using ftpd under the control of xinetd. It is delivered as /usr/share/doc/fptd/examples/ftpd.xinetd ------------------------------------------------ TEXT fi #DEBHELPER# debian/docs0000644000000000000000000000000711553435453010046 0ustar README debian/postrm0000644000000000000000000000035611553435453010451 0ustar #!/bin/sh # $Id: postrm,v 1.1 1999/04/16 07:00:28 herbert Exp $ set -e if [ "$1" = purge ]; then if command -v update-inetd >/dev/null 2>&1; then update-inetd --pattern '/usr/sbin/in\.ftpd' --remove "## ftp" fi fi #DEBHELPER# debian/README.SSL0000644000000000000000000000102311553435453010512 0ustar The SSL patches were downloaded from ftp://ftp.uni-mainz.de/pub/software/security/ssl/SSL-MZapps/linux-ftpd-0.17+ssl-0.3.diff.gz The packages was build in the following way: apt-get source linux-ftpd mv linux-ftpd-0.17 linux-ftpd-ssl-0.17.18+0.3 cd linux-ftpd-ssl-0.17.18+0.3 zcat ../linux-ftpd-0.17+ssl-0.3.diff.gz | patch -p1 #don't fix problems with applied patches ! cd .. cp -a linux-ftpd-ssl-0.17.18+0.3 linux-ftpd-ssl-0.17.18+0.3.orig cd linux-ftpd-ssl-0.17.18+0.3 zcat ../linux-ftpd-ssl_0.17.12+0.3-2.diff.gz | patch -p1