diff --git a/.gitignore b/.gitignore index 1b740aa..64ab908 100644 --- a/.gitignore +++ b/.gitignore @@ -7,9 +7,4 @@ pure-ftpd-1.0.29.tar.bz2 /pure-ftpd-1.0.39.tar.bz2 /pure-ftpd-1.0.40.tar.bz2 /pure-ftpd-1.0.42.tar.bz2 -/pure-ftpd-1.0.46.tar.bz2 /pure-ftpd-1.0.47.tar.bz2 -/pure-ftpd-1.0.48.tar.bz2 -/pure-ftpd-1.0.49.tar.bz2 -/pure-ftpd-1.0.51.tar.bz2 -/pure-ftpd-1.0.52.tar.bz2 diff --git a/0001-Exit-when-given-an-invalid-cmdline-option.patch b/0001-Exit-when-given-an-invalid-cmdline-option.patch new file mode 100644 index 0000000..2e069d8 --- /dev/null +++ b/0001-Exit-when-given-an-invalid-cmdline-option.patch @@ -0,0 +1,25 @@ +From 8b6e9370ccbdff47107963c352caab24fdb0fcaa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Wed, 7 Feb 2018 13:28:02 +0100 +Subject: [PATCH 1/2] Exit when given an invalid cmdline option + +--- + src/ftpd.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ftpd.c b/src/ftpd.c +index e19d8de..5c77410 100644 +--- a/src/ftpd.c ++++ b/src/ftpd.c +@@ -6192,7 +6192,7 @@ int pureftpd_start(int argc, char *argv[], const char *home_directory_) + exit(EXIT_SUCCESS); + } + default: +- logfile(LOG_WARNING, MSG_ILLEGAL_OPTION); ++ die(421, LOG_ERR, MSG_ILLEGAL_OPTION); + } + } + #ifdef WITH_RFC2640 +-- +2.14.3 + diff --git a/0001-Fix-postgresql-authenticate-bug.patch b/0001-Fix-postgresql-authenticate-bug.patch new file mode 100644 index 0000000..b6044be --- /dev/null +++ b/0001-Fix-postgresql-authenticate-bug.patch @@ -0,0 +1,25 @@ +From 6a256a21e48177e1d73d7e70b2292c76ac40ffb7 Mon Sep 17 00:00:00 2001 +From: t-asaka +Date: Mon, 28 May 2018 22:29:25 +0900 +Subject: [PATCH] Fix postgresql authenticate bug + +--- + src/log_pgsql.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/log_pgsql.c b/src/log_pgsql.c +index 4df654e..3825afb 100644 +--- a/src/log_pgsql.c ++++ b/src/log_pgsql.c +@@ -504,7 +504,7 @@ void pw_pgsql_check(AuthResult * const result, + crypto_crypt++; + crypto_md5++; + crypto_sha1++; +- } else if (strcasecmp(crypto, PASSWD_SQL_ARGON2)) { ++ } else if (strcasecmp(crypto, PASSWD_SQL_ARGON2) == 0) { + crypto_argon2++; + } else if (strcasecmp(crypto, PASSWD_SQL_SCRYPT) == 0) { + crypto_scrypt++; +-- +2.20.1 + diff --git a/0001-Increase-MAX_DATA_SIZE-due-to-Argon2id-requirements.patch b/0001-Increase-MAX_DATA_SIZE-due-to-Argon2id-requirements.patch new file mode 100644 index 0000000..f9545bd --- /dev/null +++ b/0001-Increase-MAX_DATA_SIZE-due-to-Argon2id-requirements.patch @@ -0,0 +1,25 @@ +From 27a5c200f9643ce907118aad169279b3a66a9e8a Mon Sep 17 00:00:00 2001 +From: Frank Denis +Date: Sat, 4 Nov 2017 20:46:16 +0100 +Subject: [PATCH] Increase MAX_DATA_SIZE due to Argon2id requirements + +--- + src/ftpd.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/ftpd.h b/src/ftpd.h +index 1beeab8..5bb1f6b 100644 +--- a/src/ftpd.h ++++ b/src/ftpd.h +@@ -557,7 +557,7 @@ Your platform has a very large PATH_MAX, we should not trust it. + + #ifndef MAX_DATA_SIZE + # ifdef HAVE_LIBSODIUM +-# define MAX_DATA_SIZE (40 * 1024 * 1024) ++# define MAX_DATA_SIZE (70 * 1024 * 1024) + # elif defined(WITH_LDAP) || defined(WITH_MYSQL) || defined(WITH_PGSQL) + # define MAX_DATA_SIZE (16 * 1024 * 1024) /* Max memory usage - SQL/LDAP need more */ + # else +-- +2.14.3 + diff --git a/0001-Revert-After-20-years-say-goodbye-to-the-external-co.patch b/0001-Revert-After-20-years-say-goodbye-to-the-external-co.patch new file mode 100644 index 0000000..598b630 --- /dev/null +++ b/0001-Revert-After-20-years-say-goodbye-to-the-external-co.patch @@ -0,0 +1,406 @@ +From 54a54e837535f8582634ba18d9008d1ee84aadc1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Wed, 6 Feb 2019 09:31:01 +0100 +Subject: [PATCH] Revert "After 20 years, say goodbye to the external config + file parsers" + +This reverts commit 623796f70f336225eb27dee4a82c43b53b9cc466. +--- + Makefile.am | 2 + + configuration-file/Makefile.am | 3 + + configuration-file/pure-config.pl.in | 127 ++++++++++++++++++ + configuration-file/pure-config.py.in | 188 +++++++++++++++++++++++++++ + configure.ac | 11 ++ + 5 files changed, 331 insertions(+) + create mode 100644 configuration-file/Makefile.am + create mode 100644 configuration-file/pure-config.pl.in + create mode 100644 configuration-file/pure-config.py.in + +diff --git a/Makefile.am b/Makefile.am +index 87da26e..a3c769f 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -5,6 +5,7 @@ EXTRA_DIST = \ + CONTACT \ + FAQ \ + Makefile.gui \ ++ README.Configuration-File \ + README.LDAP \ + README.MySQL \ + README.PGSQL \ +@@ -27,6 +28,7 @@ SUBDIRS = \ + man \ + pam \ + gui \ ++ configuration-file \ + m4 + + sysconf_DATA = \ +diff --git a/configuration-file/Makefile.am b/configuration-file/Makefile.am +new file mode 100644 +index 0000000..4639909 +--- /dev/null ++++ b/configuration-file/Makefile.am +@@ -0,0 +1,3 @@ ++CLEANFILES = \ ++ pure-config.pl \ ++ pure-config.py +diff --git a/configuration-file/pure-config.pl.in b/configuration-file/pure-config.pl.in +new file mode 100644 +index 0000000..ea675c8 +--- /dev/null ++++ b/configuration-file/pure-config.pl.in +@@ -0,0 +1,127 @@ ++#! @PERL@ ++ ++# (C) 2001-2013 Aristotle Pagaltzis ++# derived from code (C) 2001-2002 Frank Denis and Matthias Andree ++ ++use strict; ++ ++my ($conffile, @flg) = @ARGV; ++ ++my $PUREFTPD; ++-x && ($PUREFTPD=$_, last) for qw( ++ ${exec_prefix}/sbin/pure-ftpd ++ /usr/local/pure-ftpd/sbin/pure-ftpd ++ /usr/local/pureftpd/sbin/pure-ftpd ++ /usr/local/sbin/pure-ftpd ++ /usr/sbin/pure-ftpd ++); ++ ++my %simple_switch_for = ( ++ IPV4Only => "-4", ++ IPV6Only => "-6", ++ ChrootEveryone => "-A", ++ BrokenClientsCompatibility => "-b", ++ Daemonize => "-B", ++ VerboseLog => "-d", ++ DisplayDotFiles => "-D", ++ AnonymousOnly => "-e", ++ NoAnonymous => "-E", ++ DontResolve => "-H", ++ AnonymousCanCreateDirs => "-M", ++ NATmode => "-N", ++ CallUploadScript => "-o", ++ AntiWarez => "-s", ++ AllowUserFXP => "-w", ++ AllowAnonymousFXP => "-W", ++ ProhibitDotFilesWrite => "-x", ++ ProhibitDotFilesRead => "-X", ++ AllowDotFiles => "-z", ++ AutoRename => "-r", ++ AnonymousCantUpload => "-i", ++ LogPID => "-1", ++ NoChmod => "-R", ++ KeepAllFiles => "-K", ++ CreateHomeDir => "-j", ++ NoRename => "-G", ++ CustomerProof => "-Z", ++ NoTruncate => "-0", ++); ++ ++my %string_switch_for = ( ++ FileSystemCharset => "-8", ++ ClientCharset => "-9", ++ SyslogFacility => "-f", ++ FortunesFile => "-F", ++ ForcePassiveIP => "-P", ++ Bind => "-S", ++ AnonymousBandwidth => "-t", ++ UserBandwidth => "-T", ++ TrustedIP => "-V", ++ AltLog => "-O", ++ PIDFile => "-g", ++ TLSCipherSuite => "-J", ++ CertFile => "-2", ++); ++ ++my %numeric_switch_for = ( ++ MaxIdleTime => "-I", ++ MaxDiskUsage => "-k", ++ TrustedGID => "-a", ++ MaxClientsNumber => "-c", ++ MaxClientsPerIP => "-C", ++ MaxLoad => "-m", ++ MinUID => "-u", ++ TLS => "-Y", ++); ++ ++my %numpairb_switch_for = ( ++ LimitRecursion => "-L", ++ PassivePortRange => "-p", ++ AnonymousRatio => "-q", ++ UserRatio => "-Q", ++); ++ ++my %numpairc_switch_for = ( ++ Umask => "-U", ++ Quota => "-n", ++ PerUserLimits => "-y", ++); ++ ++my %auth_method_for = ( ++ LDAPConfigFile => "ldap", ++ MySQLConfigFile => "mysql", ++ PGSQLConfigFile => "pgsql", ++ PureDB => "puredb", ++ ExtAuth => "extauth", ++); ++ ++my $simple_switch = qr/(@{[join "|", keys %simple_switch_for ]})\s+yes/i; ++my $string_switch = qr/(@{[join "|", keys %string_switch_for ]})\s+(\S+)/i; ++my $numeric_switch = qr/(@{[join "|", keys %numeric_switch_for ]})\s+(\d+)/i; ++my $numpairb_switch = qr/(@{[join "|", keys %numpairb_switch_for ]})\s+(\d+)\s+(\d+)/i; ++my $numpairc_switch = qr/(@{[join "|", keys %numpairc_switch_for ]})\s+(\d+):(\d+)/i; ++my $auth_method = qr/(@{[join "|", keys %auth_method_for ]})\s+(\S+)/i; ++ ++die "Usage: pure-config.pl [extra options]\n" ++ unless defined $conffile; ++ ++open CONF, "< $conffile" or die "Can't open $conffile: $!\n"; ++ ++!/^\s*(?:$|#)/ and (chomp, push @flg, ++ /$simple_switch/i ? ($simple_switch_for{$1}) : ++ /$string_switch/i ? ($string_switch_for{$1} . $2) : ++ /$numeric_switch/i ? ($numeric_switch_for{$1} . $2) : ++ /$numpairb_switch/i ? ($numpairb_switch_for{$1} . "$2:$3") : ++ /$numpairc_switch/i ? ($numpairc_switch_for{$1} . "$2:$3") : ++ /$auth_method/i ? ("-l" . "$auth_method_for{$1}:$2") : ++ /UnixAuthentication\s+yes/i ? ("-l" . "unix") : ++ /PAMAuthentication\s+yes/i ? ("-l" . "pam") : ++ () ++) while ; ++ ++close CONF; ++ ++if (-t STDOUT) { ++ print "Running: $PUREFTPD ", join(" ", @flg), "\n"; ++} ++exec { $PUREFTPD } ($PUREFTPD, @flg) or die "cannot exec $PUREFTPD: $!"; +diff --git a/configuration-file/pure-config.py.in b/configuration-file/pure-config.py.in +new file mode 100644 +index 0000000..c458a20 +--- /dev/null ++++ b/configuration-file/pure-config.py.in +@@ -0,0 +1,188 @@ ++#! @PYTHON@ ++ ++# Original pure-config.py by Frank Denis ++# Copyright 2001 by Joshua Rodman , ++# Modifications Copyright 2001-2009 by Matthias Andree ++# ++# All Rights Reserved ++# ++# Permission to use, copy, modify, and distribute this software ++# in original or modified form for any purpose and without fee ++# is hereby granted, provided that the above copyright notice ++# appear in all copies. ++# ++# Joshua Rodman DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS ++# SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY ++# AND FITNESS, IN NO EVENT SHALL Joshua Rodman 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. ++ ++"""Pure-FTPd configuration parser. ++ ++ Parse pure-ftpd configuration file to options. ++ If run directly, execute the program. ++ ++""" ++import re ++import os ++import sys ++ ++# autoconf stuff ++if '@sbindir@'[0] == '/': ++ pureftpd = '@sbindir@/pure-ftpd' ++else: ++ pureftpd = '@prefix@/sbin/pure-ftpd' ++ ++argv = sys.argv[1:] ++try: ++ conffile = argv.pop(0) ++except IndexError: ++ print("Usage:", sys.argv[0], " [extra options]") ++ sys.exit(1) ++ ++comment = re.compile("[ ]*#+.*") ++ ++# option_tuple members are lists as follows: ++# 0 - case insensitive regex to match ++# 1 - flag to use ++# remaining - 'None' are placeholders for items matched by the regex ++# the matched items and literal strings are concatenated ++# into a literal option which follows the flag ++ ++option_tuple = ( ++ ["IPV4Only[\s]+yes", "-4" ], ++ ["IPV6Only[\s]+yes", "-6" ], ++ ["FileSystemCharset\s+(\S+)", "-8", None ], ++ ["ClientCharset\s+(\S+)", "-9", None ], ++ ["ChrootEveryone[\s]+yes", "-A" ], ++ ["TrustedGID[\s]+([\d]+)", "-a", None ], ++ ["BrokenClientsCompatibility[\s]+yes", "-b" ], ++ ["MaxClientsNumber\s+(\d+)", "-c", None ], ++ ["Daemonize\s+yes", "-B" ], ++ ["MaxClientsPerIP\s+(\d+)", "-C", None ], ++ ["VerboseLog\s+yes", "-d" ], ++ ["DisplayDotFiles\s+yes", "-D" ], ++ ["AnonymousOnly\s+yes", "-e" ], ++ ["MaxDiskUsage\s+(\d+)", "-k", None ], ++ ["NoAnonymous\s+yes", "-E" ], ++ ["SyslogFacility\s+(\S+)", "-f", None ], ++ ["FortunesFile\s+(\S+)", "-F", None ], ++ ["DontResolve\s+yes", "-H" ], ++ ["MaxIdleTime\s+(\d+)", "-I", None ], ++ ["LDAPConfigFile\s+(\S+)", "-l", "ldap:", None ], ++ ["MySQLConfigFile\s+(\S+)", "-l", "mysql:", None ], ++ ["PGSQLConfigFile\s+(\S+)", "-l", "pgsql:", None ], ++ ["PureDB\s+(\S+)", "-l", "puredb:", None ], ++ ["ExtAuth\s+(\S+)", "-l", "extauth:",None ], ++ ["PAMAuthentication\s+yes", "-l", "pam" ], ++ ["UnixAuthentication\s+yes", "-l", "unix" ], ++ ["LimitRecursion\s+(\d+)\s+(\d+)", "-L", None, ":", None ], ++ ["AnonymousCanCreateDirs\s+yes", "-M" ], ++ ["MaxLoad\s+(\d+)", "-m", None ], ++ ["NATmode\s+yes", "-N" ], ++ ["CallUploadScript\s+yes", "-o" ], ++ ["PassivePortRange\s+(\d+)\s+(\d+)", "-p", None, ":", None ], ++ ["ForcePassiveIP\s+(\S+)", "-P", None ], ++ ["AnonymousRatio\s+(\d+)\s+(\d+)", "-q", None, ":", None ], ++ ["UserRatio\s+(\d+)\s+(\d+)", "-Q", None, ":", None ], ++ ["AntiWarez\s+yes", "-s" ], ++ ["Bind\s+(\S+)", "-S", None ], ++ ["AnonymousBandwidth\s+([:0-9]+)", "-t", None ], ++ ["UserBandwidth\s+([:0-9]+)", "-T", None ], ++ ["Quota\s+([:0-9]+)", "-n", None ], ++ ["Umask\s+(\d+):(\d+)", "-U", None, ":", None ], ++ ["MinUID\s+(\d+)", "-u", None ], ++ ["AllowUserFXP\s+yes", "-w" ], ++ ["AllowAnonymousFXP\s+yes", "-W" ], ++ ["ProhibitDotFilesWrite\s+yes", "-x" ], ++ ["ProhibitDotFilesRead\s+yes", "-X" ], ++ ["AllowDotFiles\s+yes", "-z" ], ++ ["AutoRename\s+yes", "-r" ], ++ ["AnonymousCantUpload\s+yes", "-i" ], ++ ["TrustedIP\s+(\S+)", "-V", None ], ++ ["LogPID\s+yes", "-1" ], ++ ["AltLog\s+(\S+)", "-O", None ], ++ ["NoChmod\s+yes", "-R" ], ++ ["KeepAllFiles\s+yes", "-K" ], ++ ["CreateHomeDir\s+yes", "-j" ], ++ ["NoRename\s+yes", "-G" ], ++ ["CustomerProof\s+yes", "-Z" ], ++ ["NoTruncate\s+yes", "-0" ], ++ ["PIDFile\s+(\S+)", "-g", None ], ++ ["TLSCipherSuite\s+(\S+)", "-J", None ], ++ ["PerUserLimits\s+([:0-9]+)", "-y", None ], ++ ["CertFile\s+(\S+)", "-2", None ], ++ ["TLS\s+(\d)", "-Y", None ]) ++ ++for option in option_tuple: ++ option[0] = re.compile(option[0], re.IGNORECASE) ++ ++ ++def build_argument(match, controls): ++ """construct an argument string ++ match: a match object containing argument values ++ controls: a list controlling the format of the argument ++ ++ Return parameter as string""" ++ ++ argument = "" ++ value = 1 ++ ++ for control in controls: ++ if control: ++ # concat the literal string ++ argument = argument + control ++ else: ++ # concat a value ++ argument = argument + match.group(value) ++ value = value + 1 ++ ++ return argument ++ ++ ++def parse(file_obj): ++ """parse/extract a pure-ftpd configuration ++ file_obj: a readlines() capable object containing the configurion ++ ++ Returns list of arguments as appropriate for exec()""" ++ ++ args = [pureftpd] ++ ++ for line in file_obj.readlines(): ++ if comment.search(line): ++ continue ++ ++ for option in option_tuple: ++ match = option[0].search(line) ++ if match: ++ args.append(option[1]) ++ ++ if len(option) <= 2: ++ # The option takes no argument ++ continue ++ ++ argument = build_argument(match, option[2:]) ++ args.append(argument) ++ ++ return args ++ ++ ++def parse_filename(filename=conffile): ++ """parse/extract a pure-ftpd from a named file ++ filename: text path to file ++ ++ Returns list of arguments as appropriate for exec()""" ++ ++ file_obj = open(filename) ++ return parse(file_obj) ++ ++if __name__ == '__main__': ++ args = parse_filename() ++ ++ if os.isatty(1): ++ print("Running:", args + argv) ++ ++ os.execv(pureftpd, args + argv) +diff --git a/configure.ac b/configure.ac +index 5d91d12..e66a578 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -91,6 +91,14 @@ AX_CHECK_LINK_FLAG([-Wl,-z,relro], [LDFLAGS="$LDFLAGS -Wl,-z,relro"]) + AX_CHECK_LINK_FLAG([-Wl,-z,now], [LDFLAGS="$LDFLAGS -Wl,-z,now"]) + AX_CHECK_LINK_FLAG([-Wl,-z,noexecstack], [LDFLAGS="$LDFLAGS -Wl,-z,noexecstack"]) + ++AC_ARG_VAR(PERL,local path to the perl interpreter) ++perl_possible_path="/usr/bin:/usr/local/bin:/bin:/opt/perl/bin:/opt/perl/usr/bin:/opt/perl/usr/local/bin" ++AC_PATH_PROG(PERL,perl,/usr/bin/env perl,$perl_possible_path) ++ ++AC_ARG_VAR(PYTHON,local path to the python interpreter) ++python_possible_path="/usr/bin:/usr/local/bin:/bin:/opt/python/bin:/opt/python/usr/bin:/opt/python/usr/local/bin" ++AC_PATH_PROG(PYTHON,python,/usr/bin/env python,$python_possible_path) ++ + if test -d /usr/local/include; then + CPPFLAGS="$CPPFLAGS -I/usr/local/include" + fi +@@ -1462,6 +1470,9 @@ AH_VERBATIM([NDEBUG], [/* Never ever ignore assertions */ + AC_CONFIG_FILES(Makefile src/Makefile pam/Makefile man/Makefile + gui/Makefile m4/Makefile pure-ftpd.conf puredb/Makefile + puredb/src/Makefile ++configuration-file/Makefile ++configuration-file/pure-config.pl ++configuration-file/pure-config.py + man/pure-ftpd.8 man/pure-ftpwho.8 man/pure-mrtginfo.8 man/pure-uploadscript.8 + man/pure-statsdecode.8 man/pure-quotacheck.8 man/pure-pw.8 man/pure-pwconvert.8 + man/pure-authd.8) +-- +2.20.1 + diff --git a/0001-Revert-No-more-contrib-Makefile.in.patch b/0001-Revert-No-more-contrib-Makefile.in.patch new file mode 100644 index 0000000..0511017 --- /dev/null +++ b/0001-Revert-No-more-contrib-Makefile.in.patch @@ -0,0 +1,26 @@ +From 889562eeec40e667d76007285aed5d87acae29e1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Wed, 6 Feb 2019 12:39:49 +0100 +Subject: [PATCH 1/3] Revert "No more contrib/Makefile.in" + +This reverts commit 86b1ec003b63a82f1bcb016f55f385c6cff89b6c. +--- + configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/configure.ac b/configure.ac +index e66a578..cc2534b 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1468,7 +1468,7 @@ AH_VERBATIM([NDEBUG], [/* Never ever ignore assertions */ + #endif]) + + AC_CONFIG_FILES(Makefile src/Makefile pam/Makefile man/Makefile +-gui/Makefile m4/Makefile pure-ftpd.conf puredb/Makefile ++gui/Makefile contrib/Makefile m4/Makefile pure-ftpd.conf puredb/Makefile + puredb/src/Makefile + configuration-file/Makefile + configuration-file/pure-config.pl +-- +2.20.1 + diff --git a/0001-Temporarily-disable-TLSv1.3-support.patch b/0001-Temporarily-disable-TLSv1.3-support.patch new file mode 100644 index 0000000..5297028 --- /dev/null +++ b/0001-Temporarily-disable-TLSv1.3-support.patch @@ -0,0 +1,30 @@ +From f9e232ffb44c96538f2a12c4bc4970f228f971cd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 12 Feb 2019 11:17:16 +0100 +Subject: [PATCH] Temporarily disable TLSv1.3 support + +Disable TLSv1.3 until support for it is fixed in pure-ftpd. This is a +workaround for the following issue: +https://github.com/jedisct1/pure-ftpd/issues/102 +--- + src/tls.c | 4 ++++ + 1 file changed, 4 insertions(+) + +diff --git a/src/tls.c b/src/tls.c +index c4e2a1b..41d619f 100644 +--- a/src/tls.c ++++ b/src/tls.c +@@ -301,6 +301,10 @@ int tls_init_library(void) + # endif + # ifdef SSL_OP_NO_TLSv1_2 + SSL_CTX_clear_options(tls_ctx, SSL_OP_NO_TLSv1_2); ++# endif ++ /* Disable TLSv1.3 support until it works properly in pure-ftpd */ ++# ifdef SSL_OP_NO_TLSv1_3 ++ SSL_CTX_set_options(tls_ctx, SSL_OP_NO_TLSv1_3); + # endif + if (tlsciphersuite != NULL) { + if (SSL_CTX_set_cipher_list(tls_ctx, tlsciphersuite) != 1) { +-- +2.20.1 + diff --git a/0001-diraliases-always-set-the-tail-of-the-list-to-NULL.patch b/0001-diraliases-always-set-the-tail-of-the-list-to-NULL.patch new file mode 100644 index 0000000..d5b2523 --- /dev/null +++ b/0001-diraliases-always-set-the-tail-of-the-list-to-NULL.patch @@ -0,0 +1,34 @@ +From 8d0d42542e2cb7a56d645fbe4d0ef436e38bcefa Mon Sep 17 00:00:00 2001 +From: Frank Denis +Date: Tue, 18 Feb 2020 18:36:58 +0100 +Subject: [PATCH] diraliases: always set the tail of the list to NULL + +Spotted and reported by Antonio Norales from GitHub Security Labs. +Thanks! +--- + src/diraliases.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/diraliases.c b/src/diraliases.c +index 4002a36..fb70273 100644 +--- a/src/diraliases.c ++++ b/src/diraliases.c +@@ -93,7 +93,6 @@ int init_aliases(void) + (tail->dir = strdup(dir)) == NULL) { + die_mem(); + } +- tail->next = NULL; + } else { + DirAlias *curr; + +@@ -105,6 +104,7 @@ int init_aliases(void) + tail->next = curr; + tail = curr; + } ++ tail->next = NULL; + } + fclose(fp); + aliases_up++; +-- +2.25.4 + diff --git a/0001-listdir-reuse-a-single-buffer-to-store-every-file-na.patch b/0001-listdir-reuse-a-single-buffer-to-store-every-file-na.patch new file mode 100644 index 0000000..b858686 --- /dev/null +++ b/0001-listdir-reuse-a-single-buffer-to-store-every-file-na.patch @@ -0,0 +1,70 @@ +From a9cb173c3c07e4cdb82c9bb90a28c28289207a4e Mon Sep 17 00:00:00 2001 +From: Frank Denis +Date: Mon, 30 Dec 2019 17:40:04 +0100 +Subject: [PATCH] listdir(): reuse a single buffer to store every file name to + display + +Allocating a new buffer for each entry is useless. + +And as these buffers are allocated on the stack, on systems with a +small stack size, with many entries, the limit can easily be reached, +causing a stack exhaustion and aborting the user session. + +Reported by Antonio Morales from the GitHub Security Lab team, thanks! +--- + src/ls.c | 15 ++++++++------- + 1 file changed, 8 insertions(+), 7 deletions(-) + +diff --git a/src/ls.c b/src/ls.c +index 9d01ecf..d4dd653 100644 +--- a/src/ls.c ++++ b/src/ls.c +@@ -695,6 +695,8 @@ static void listdir(unsigned int depth, int f, void * const tls_fd, + PureFileInfo *s; + PureFileInfo *r; + char *c_buf; ++ char *alloca_subdir; ++ size_t sizeof_subdir; + int d; + + if (depth >= max_ls_depth || matches >= max_ls_files) { +@@ -729,14 +731,12 @@ static void listdir(unsigned int depth, int f, void * const tls_fd, + } + outputfiles(f, tls_fd); + r = dir; ++ sizeof_subdir = PATH_MAX + 1U; ++ if ((alloca_subdir = ALLOCA(sizeof_subdir)) == NULL) { ++ goto toomany; ++ } + while (opt_R && r != s) { + if (r->name_offset != (size_t) -1 && !chdir(FI_NAME(r))) { +- char *alloca_subdir; +- const size_t sizeof_subdir = PATH_MAX + 1U; +- +- if ((alloca_subdir = ALLOCA(sizeof_subdir)) == NULL) { +- goto toomany; +- } + if (SNCHECK(snprintf(alloca_subdir, sizeof_subdir, "%s/%s", + name, FI_NAME(r)), sizeof_subdir)) { + goto nolist; +@@ -765,8 +765,8 @@ static void listdir(unsigned int depth, int f, void * const tls_fd, + free(c_buf); + #endif + listdir(depth + 1U, f, tls_fd, alloca_subdir); ++ + nolist: +- ALLOCA_FREE(alloca_subdir); + if (matches >= max_ls_files) { + goto toomany; + } +@@ -779,6 +779,7 @@ static void listdir(unsigned int depth, int f, void * const tls_fd, + r++; + } + toomany: ++ ALLOCA_FREE(alloca_subdir); + free(names); + free(dir); + names = NULL; +-- +2.25.4 + diff --git a/0001-pure_strcmp-len-s2-can-be-len-s1.patch b/0001-pure_strcmp-len-s2-can-be-len-s1.patch new file mode 100644 index 0000000..375b970 --- /dev/null +++ b/0001-pure_strcmp-len-s2-can-be-len-s1.patch @@ -0,0 +1,28 @@ +From bf6fcd4935e95128cf22af5924cdc8fe5c0579da Mon Sep 17 00:00:00 2001 +From: Frank Denis +Date: Mon, 24 Feb 2020 15:19:43 +0100 +Subject: [PATCH] pure_strcmp(): len(s2) can be > len(s1) + +Reported by Antonio Morales from GitHub Security Labs, thanks! +--- + src/utils.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/utils.c b/src/utils.c +index f41492d..5e88104 100644 +--- a/src/utils.c ++++ b/src/utils.c +@@ -45,5 +45,9 @@ int pure_memcmp(const void * const b1_, const void * const b2_, size_t len) + + int pure_strcmp(const char * const s1, const char * const s2) + { +- return pure_memcmp(s1, s2, strlen(s1) + 1U); ++ const size_t s1_len = strlen(s1); ++ const size_t s2_len = strlen(s2); ++ const size_t len = (s1_len < s2_len) ? s1_len : s2_len; ++ ++ return pure_memcmp(s1, s2, len + 1); + } +-- +2.25.4 + diff --git a/0002-Complain-when-both-options-and-config-file-are-given.patch b/0002-Complain-when-both-options-and-config-file-are-given.patch new file mode 100644 index 0000000..16fe41a --- /dev/null +++ b/0002-Complain-when-both-options-and-config-file-are-given.patch @@ -0,0 +1,237 @@ +From 4328fd5142d0f981687a484f4be34333432d27d1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Wed, 7 Feb 2018 15:05:25 +0100 +Subject: [PATCH 2/2] Complain when both options and config file are given on + cmdline + +--- + src/ftpd.c | 3 +++ + src/messages_cs_cz.h | 1 + + src/messages_da.h | 1 + + src/messages_de.h | 1 + + src/messages_en.h | 1 + + src/messages_es.h | 1 + + src/messages_fr.h | 1 + + src/messages_fr_funny.h | 1 + + src/messages_hu.h | 1 + + src/messages_it.h | 1 + + src/messages_kr.h | 1 + + src/messages_nl.h | 1 + + src/messages_no.h | 1 + + src/messages_pl.h | 1 + + src/messages_pt_br.h | 1 + + src/messages_ro.h | 1 + + src/messages_ru.h | 1 + + src/messages_sk.h | 1 + + src/messages_sv.h | 1 + + src/messages_tr.h | 1 + + src/messages_zh_cn.h | 1 + + src/messages_zh_tw.h | 1 + + 22 files changed, 24 insertions(+) + +diff --git a/src/ftpd.c b/src/ftpd.c +index 5c77410..3f474d2 100644 +--- a/src/ftpd.c ++++ b/src/ftpd.c +@@ -6195,6 +6195,9 @@ int pureftpd_start(int argc, char *argv[], const char *home_directory_) + die(421, LOG_ERR, MSG_ILLEGAL_OPTION); + } + } ++ if (optind < argc) { ++ die(421, LOG_ERR, MSG_INVALID_ARGUMENT, argv[optind]); ++ } + #ifdef WITH_RFC2640 + if (charset_fs == NULL) { + charset_fs = (char *) "utf-8"; +diff --git a/src/messages_cs_cz.h b/src/messages_cs_cz.h +index ef225ba..e103b37 100644 +--- a/src/messages_cs_cz.h ++++ b/src/messages_cs_cz.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Neplatn� argument: \"%s\"" +diff --git a/src/messages_da.h b/src/messages_da.h +index ed6f77c..c79ad5a 100644 +--- a/src/messages_da.h ++++ b/src/messages_da.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_de.h b/src/messages_de.h +index e7ae9a9..cd6bc08 100644 +--- a/src/messages_de.h ++++ b/src/messages_de.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_en.h b/src/messages_en.h +index e980131..cb9abf3 100644 +--- a/src/messages_en.h ++++ b/src/messages_en.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_es.h b/src/messages_es.h +index 0c27d4f..60ed849 100644 +--- a/src/messages_es.h ++++ b/src/messages_es.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_fr.h b/src/messages_fr.h +index 7f41dae..a012c05 100644 +--- a/src/messages_fr.h ++++ b/src/messages_fr.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT doit etre precede d'une commande PBSZ reussie" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP n'a pas retourne d'attribut userPassword, verifiez les droits d'acces LDAP." + #define MSG_LDAP_INVALID_AUTH_METHOD "Methode LDAPAuthMethod invalide dans le fichier de configuration. Ce doit etre 'bind' ou 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_fr_funny.h b/src/messages_fr_funny.h +index c77e5bc..dff760b 100644 +--- a/src/messages_fr_funny.h ++++ b/src/messages_fr_funny.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT ca marche qu'apres un PBSZ reussi" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP n'a pas retourne d'attribut userPassword, ptet que les droits d'acces LDAP chient." + #define MSG_LDAP_INVALID_AUTH_METHOD "LDAPAuthMethod dans le fichier de conf, ca doit etre 'bind' ou 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_hu.h b/src/messages_hu.h +index b3beead..7c5a101 100644 +--- a/src/messages_hu.h ++++ b/src/messages_hu.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_it.h b/src/messages_it.h +index 4e6e984..e30f517 100644 +--- a/src/messages_it.h ++++ b/src/messages_it.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_kr.h b/src/messages_kr.h +index 14d8300..c9faead 100644 +--- a/src/messages_kr.h ++++ b/src/messages_kr.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_nl.h b/src/messages_nl.h +index 77efbb4..5a60d9e 100644 +--- a/src/messages_nl.h ++++ b/src/messages_nl.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "Geen userPassword attribuut aangetroffen. Controleer de toegangsrechten." + #define MSG_LDAP_INVALID_AUTH_METHOD "Onjuiste LDAPAuthMethod in de configuratie. Moet 'bind' of 'password' zijn." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_no.h b/src/messages_no.h +index f0be1b4..4c84405 100644 +--- a/src/messages_no.h ++++ b/src/messages_no.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_pl.h b/src/messages_pl.h +index c0be4d8..89d5af1 100644 +--- a/src/messages_pl.h ++++ b/src/messages_pl.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_pt_br.h b/src/messages_pt_br.h +index e5557b9..1dcfb64 100644 +--- a/src/messages_pt_br.h ++++ b/src/messages_pt_br.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_ro.h b/src/messages_ro.h +index 7bbcefe..da16a49 100644 +--- a/src/messages_ro.h ++++ b/src/messages_ro.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_ru.h b/src/messages_ru.h +index e0c1842..f0e4031 100644 +--- a/src/messages_ru.h ++++ b/src/messages_ru.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_sk.h b/src/messages_sk.h +index 24eca1b..e0ddd2a 100644 +--- a/src/messages_sk.h ++++ b/src/messages_sk.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_sv.h b/src/messages_sv.h +index b55c474..be4bbc1 100644 +--- a/src/messages_sv.h ++++ b/src/messages_sv.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_tr.h b/src/messages_tr.h +index 7d6db57..3ee84d2 100644 +--- a/src/messages_tr.h ++++ b/src/messages_tr.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_zh_cn.h b/src/messages_zh_cn.h +index a8bfc6c..93844fd 100644 +--- a/src/messages_zh_cn.h ++++ b/src/messages_zh_cn.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +diff --git a/src/messages_zh_tw.h b/src/messages_zh_tw.h +index db99719..05581bb 100644 +--- a/src/messages_zh_tw.h ++++ b/src/messages_zh_tw.h +@@ -227,3 +227,4 @@ + #define MSG_PROT_BEFORE_PBSZ "PROT must be preceded by a successful PBSZ command" + #define MSG_WARN_LDAP_USERPASS_EMPTY "LDAP returned no userPassword attribute, check LDAP access rights." + #define MSG_LDAP_INVALID_AUTH_METHOD "Invalid LDAPAuthMethod in the configuration file. Should be 'bind' or 'password'." ++#define MSG_INVALID_ARGUMENT "Invalid argument: \"%s\"" +-- +2.14.3 + diff --git a/0002-Revert-Remove-contribs.-These-are-way-too-old-and-un.patch b/0002-Revert-Remove-contribs.-These-are-way-too-old-and-un.patch new file mode 100644 index 0000000..cc87ea1 --- /dev/null +++ b/0002-Revert-Remove-contribs.-These-are-way-too-old-and-un.patch @@ -0,0 +1,693 @@ +From 1956de44a6385a6a891a0f18468335884b30eb7c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Wed, 6 Feb 2019 12:39:54 +0100 +Subject: [PATCH 2/3] Revert "Remove contribs. These are way too old and + unmaintained." + +This reverts commit ba526ef1525c09d63a309f3e0c22ecf1308d9070. +--- + Makefile.am | 2 + + README.Contrib | 137 +++++++++++++++ + contrib/Makefile.am | 3 + + contrib/pure-stat.pl | 213 +++++++++++++++++++++++ + contrib/xml_python_processors.txt | 274 ++++++++++++++++++++++++++++++ + 5 files changed, 629 insertions(+) + create mode 100644 README.Contrib + create mode 100644 contrib/Makefile.am + create mode 100755 contrib/pure-stat.pl + create mode 100644 contrib/xml_python_processors.txt + +diff --git a/Makefile.am b/Makefile.am +index a3c769f..635181a 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -10,6 +10,7 @@ EXTRA_DIST = \ + README.MySQL \ + README.PGSQL \ + README.Configuration-File \ ++ README.Contrib \ + README.Virtual-Users \ + README.Authentication-Modules \ + README.Windows \ +@@ -25,6 +26,7 @@ EXTRA_DIST = \ + SUBDIRS = \ + puredb \ + src \ ++ contrib \ + man \ + pam \ + gui \ +diff --git a/README.Contrib b/README.Contrib +new file mode 100644 +index 0000000..0a23ab5 +--- /dev/null ++++ b/README.Contrib +@@ -0,0 +1,137 @@ ++ ++ ++You can send whatever you want to be included in that list to ++ or to the mailing list. ++ ++ Thank you, ++ ++ ++ -Frank. ++ ++----------------------------------------------------------------------------- ++ ++Warning: contributed packages haven't received any code audit. Please ++report bugs directly to authors. ++ ++----------------------------------------------------------------------------- ++ ++* Redmine Pure-FTPd plugin ++http://github.com/bytemine/redmine_pureftpd_user/ ++ ++This Redmine plugin maintains a table with pureftpd compatible users. ++ ++ ++* FTPd Auth Handler ++http://onrails.org/articles/2009/03/06/integrating-ftp-with-rails ++ ++An extauth handler in Ruby. ++ ++ ++* Domain technologie control panel, as used on GPLHost ++http://github.com/carlosl/dtc ++ ++ ++* PureFTPd Manager ++http://jeanmatthieu.free.fr/pureftpd/ ++ ++PureFTPd Manager is a small Cocoa frontend to PureFTPd for Mac OS X. It ++includes a wizard to easily set up your server, Rendezvous support to ++publish your server efficiently, and groovy interfaces for virtual users and ++hosts management. ++ ++ ++* PureAdmin ++http://purify.sourceforge.net/ ++ ++PureAdmin is a graphical tool used to make the management of PureFTPd a ++little easier. It is not dependent on a specific desktop environment such as ++GNOME or KDE, but is designed with the GNOME Human Interface Guidelines in ++mind. ++ ++ ++* Pure-FTPd PHP User Manager ++http://ppum.sourceforge.net/ ++ ++ppum (PureFTPd PHP User Manager) is a PureFTPD PHP User Management System ++designed for an easy Web-based administration of SQL stored and ++authenticated FTP users. ++ ++ ++* User manager for Pure-FTPd ++http://machiel.generaal.net/index.php?subject=user_manager_pureftpd ++ ++User manager for PureFTPd allows administrators to easily create, change, or ++delete 'virtual' PureFTPd users. It comes with a set of very good ++documentation to help with the setup of PureFTPd, MySQL, and this application. ++ ++ ++* PureUserAdmin ++http://pureuseradmin.sourceforge.net/ ++ ++PureUserAdmin is a PHP based webbased application. Sys admins can use it to ++easily manage the virtual users for their FTP server. PureUserAdmin is ++developed to be used with Pure-FTPd but it should be able to be used with ++other FTP servers as long as the FTP server gets the useraccount info from ++MySQL or PostgreSQL. ++ ++ ++* PurePostPro ++http://82.71.1.246/stuff/purepostpro/ ++ ++PurePostPro is a Perl/MySQL script that enables user uploads to be managed ++more easily. New uploads are logged in a MySQL database, and duplicate files ++are tracked using MD5 checksums. ++ ++ ++* MySQmail Pure-FTPd logger ++http://www.gplhost.com/software-mysqmail.html ++http://packages.debian.org/en/squeeze/mail/mysqmail-pure-ftpd-logger ++ ++MySQMail is a set of tiny daemon loggers for mail and FTP servers that save ++traffic information in a MySQL database. The information is split by domain ++and by user so that it's easy to measure all the traffic for a given domain ++name in real time. ++ ++This package provides a logger for FTP traffic handled by Pure-FTPd. ++ ++ ++ ++ ---------- ++ ++ ++ ++Current content of the "contrib" directory: ++ ++* xml_python_processors.txt (author: Jason Lunz): ++ ++ Two scripts to postprocess pure-ftpwho XML output. One returns a list of ++dicts with the ftpwho data, each dict representing a connected client's ++attribute. If you want to develop something related to ftpwho in Python, ++this is a very good base. ++ ++ The other script creates a web page similar to "pure-ftpwho -w", but ++better: you can choose which columns you want in which order and sort ++the rows on multiple fields. You can also see bandwidth totals per ++account. ++ ++* redhat.init (author: Bernhard Weisshuhn): ++ ++ A sample Red Hat init script. ++ ++* suse.init (author: Marc Thoben): ++ ++ A sample SuSE init script. ++ ++* pure-vpopauth.pl (author: Dan Caescu): ++ ++ An external authentication module for pure-ftpd using vpasswd ++vpopmail password files. ++ Run it the standard way with pure-authd. ++ ++* pure-stat.pl (author: Julien Andrieux): ++ ++ This script parses Apache-like log files and generates nice text summaries. ++ ++* Vidibus::Pureftpd (author: Andre Pankratz): ++ A Ruby gem that p rovides an ActiveModel-based abstraction of Pure-FTPd's ++virtual users. +diff --git a/contrib/Makefile.am b/contrib/Makefile.am +new file mode 100644 +index 0000000..5056d5f +--- /dev/null ++++ b/contrib/Makefile.am +@@ -0,0 +1,3 @@ ++EXTRA_DIST = \ ++ xml_python_processors.txt \ ++ pure-stat.pl +diff --git a/contrib/pure-stat.pl b/contrib/pure-stat.pl +new file mode 100755 +index 0000000..c26a4f8 +--- /dev/null ++++ b/contrib/pure-stat.pl +@@ -0,0 +1,213 @@ ++#!/usr/bin/env perl -w ++#-------------------------------------------------------------- ++# PROJECT : pure-ftpd statistics ++# FILE : pure-stat.pl ++# DESCRIPTION : see below (Purpose) ++# AUTHOR : Chill ++# DATE : 08/01/2002 ++# COMMENT: ++# PARAMETER : none ++# FROM FILE : none ++#-------------------------------------------------------------- ++# PURPOSE ++# get the log file $CONST_LOGFILE ++# parse it and generate stats ++# to avoid loading a huge log file, a summary file ($CONST_SUMFILE), ++# is generated ++ ++#CONSTANT DELCARATION ++my $CONST_USER=0; ++my $CONST_TUPLOAD=1; ++my $CONST_TDOWNLOAD=2; ++my $CONST_LCONNECTION=3; ++my $CONST_LOGFILE="/var/log/pureftpd.log"; ++my $CONST_SUMFILE="/var/log/pureftpd.stat.log"; ++ ++#FUNCTION DECLARATION ++sub castSize; ++ ++#CREATE USERS ARRAY (UGLY, BUT USEFUL FOR DISPLAY) ++my @users = (["login", "upload", "download", "last connection"]); ++ ++#MAIN VARIABLES INIT ++my $total_upload = 0; ++my $total_download = 0; ++ ++ ++#FUNCTION DEFINITION ++ ++#MODIFY 1234bytes => 1.2Mb... ++sub castSize ++{ ++ my $value = shift; ++ ++ if ($value > 1073741824) ++ { ++ $value = $value / 1073741824; ++ @fvalue = ($value, "Gb"); ++ } ++ elsif ($value > 1048576) ++ { ++ $value = $value / 1048576; ++ @fvalue = ($value, "Mb"); ++ } ++ elsif ($value > 1024) ++ { ++ $value = $value / 1024; ++ @fvalue = ($value, "Kb"); ++ } ++ else ++ { ++ @fvalue = ($value, "b"); ++ } ++ return @fvalue; ++} ++#END sub castSize ++ ++#LOAD SUMMARY FILE INTO ARRAY ++open(SUMF,$CONST_SUMFILE); ++my @sumlist = ; ++close SUMF; ++ ++#PARSING SUMMARY FILE INTO ARRAY ++foreach $sumentry (@sumlist) ++{ ++ ($slogin, $sbytes_ul, $sbytes_dl, $sdate) = $sumentry =~ m/^(\S+) (\S+) (\S+) \[([^\]\[]+)\]/; ++ push @users, [$slogin, $sbytes_ul, $sbytes_dl, $sdate]; ++ $total_upload += $sbytes_ul; ++ $total_download += $sbytes_dl; ++} ++ ++#LOAD LOG FILE INTO ARRAY ++open(LOG,$CONST_LOGFILE); ++my @loglist = ; ++close LOG; ++ ++#PARSING ARRAY IF NOT EMPTY ++if ($#loglist != -1) ++{ ++ #GENERATE FILE EXTENSION AS yearmonthmdayhourmin ++ @dlist = gmtime(time); ++ $ext = sprintf("%02d%02d%02d%02d%02d", $dlist[5], $dlist[4]+1, $dlist[3], $dlist[2]+2, $dlist[1]); ++ undef @dlist; ++ ++ #WE BACKUP THE LOG FILE ++ system ("gzip $CONST_LOGFILE -S .$ext.gz && touch $CONST_LOGFILE"); ++ ++ foreach $logentry (@loglist) ++ { ++ #LET'S GRAB THE LOG ENTRY ++ ($ip, $tiret, $login, $date, $request, $status, $bytes) = $logentry =~ m/^(\S+) (\S+) (\S+) \[([^\]\[]+)\] \"([^"]*)\" (\S+) (\S+)/; ++ ++ #ADD OR MODIFY USERS ++ #IS THE USER IN THE SUMMARY FILE ++ my $gotuser = 0; ++ my $indexuser = 0; ++ ++ for $i ( 1 .. $#users ) ++ { ++ if ($users[$i][$CONST_USER] eq $login) ++ { ++ $gotuser = 1; ++ $indexuser = $i; ++ last; ++ } ++ } ++ ++ #YES, WE DON'T ADD HIM, WE UPGRADE HIM ++ if ($gotuser) ++ { ++ if ( $request =~ "PUT") ++ { ++ #UPLOAD CASE ++ $users[$indexuser][$CONST_TUPLOAD] += $bytes; ++ $total_upload += $bytes; ++ } ++ elsif ( $request =~ "GET") ++ { ++ #DOWNLOAD CASE ++ $users[$indexuser][$CONST_TDOWNLOAD] += $bytes; ++ $total_download += $bytes; ++ } ++ #LAST CONNECTION ++ $users[$indexuser][$CONST_LCONNECTION] = $date; ++ } ++ else ++ { ++ #NOPE, WE ADD HIM ++ if ( $request =~ "GET") ++ { ++ #DOWNLOAD CASE ++ push @users, [$login, 0, $bytes, $date]; ++ $total_download += $bytes; ++ } ++ elsif ( $request =~ "PUT") ++ { ++ #UPLOAD CASE ++ push @users, [$login, $bytes, 0, $date]; ++ $total_upload += $bytes; ++ } ++ } ++ } ++} ++ ++#PRINT RESULTS ++#LET'S CLEAN THE SUMMARY FILE ++system ("rm -f $CONST_SUMFILE && touch $CONST_SUMFILE"); ++ ++#TABLE HEADER ++print "----------------------------------------------\n"; ++print "$users[$i][$CONST_USER]\t|\t$users[$i][$CONST_TUPLOAD]\t\t|\t$users[$i][$CONST_TDOWNLOAD]\t\t|\t$users[$i][$CONST_LCONNECTION]\n"; ++print "----------------------------------------------\n"; ++ ++#TABLE BODY ++for $i ( 1 .. $#users ) ++{ ++ if ($total_upload <= 0) ++ { ++ $percent_upload=0; ++ } else { ++ $percent_upload= 100*$users[$i][$CONST_TUPLOAD]/$total_upload; ++ } ++ if ($total_download <= 0) ++ { ++ $percent_download=0; ++ } else { ++ $percent_download= 100*$users[$i][$CONST_TDOWNLOAD]/$total_download; ++ } ++ ++ @actual_upload = castSize $users[$i][$CONST_TUPLOAD]; ++ @actual_download = castSize $users[$i][$CONST_TDOWNLOAD]; ++ ++ $strLogin = sprintf "%s", $users[$i][$CONST_USER]; ++ $strUl = sprintf "%.1f %s (%.1f%%)", ($actual_upload[0],$actual_upload[1],$percent_upload); ++ $strDl = sprintf "%.1f %s (%.1f%%)", ($actual_download[0],$actual_download[1],$percent_download); ++ $strDate = sprintf "%s", ($users[$i][$CONST_LCONNECTION]); ++ ++ #PRINT ON STDOUT ++ printf "%s\t|\t%s\t", ($strLogin, $strUl); ++ if ( length($strUl) < 8) ++ { ++ printf "\t"; ++ } ++ printf "|\t%s\t", $strDl; ++ if ( length($strDl) < 8) ++ { ++ printf "\t"; ++ } ++ printf "|\t%s\n", $strDate; ++ printf "\n"; ++ ++ #PRINT SUMMARY FILE ++ system ("echo -e '$users[$i][$CONST_USER] $users[$i][$CONST_TUPLOAD] $users[$i][$CONST_TDOWNLOAD] [$users[$i][$CONST_LCONNECTION]]' >> $CONST_SUMFILE"); ++} ++ ++#PREPARE BYTES, MBYTES OR GBYTES ++@ftotal_upload = castSize $total_upload; ++@ftotal_download = castSize $total_download; ++ ++#TABLE FOOTER ++print "----------------------------------------------\n"; ++printf "*\t|\t%.2f %s\t|\t%.2f %s\n", ($ftotal_upload[0],$ftotal_upload[1],$ftotal_download[0],$ftotal_download[1]); ++print "----------------------------------------------\n"; ++ +diff --git a/contrib/xml_python_processors.txt b/contrib/xml_python_processors.txt +new file mode 100644 +index 0000000..c4f7ba9 +--- /dev/null ++++ b/contrib/xml_python_processors.txt +@@ -0,0 +1,274 @@ ++From: Jason Lunz ++ ++I've been fooling around with parsing the XML output of "pure-ftpwho -x" ++in python and doing things with it. The results could be useful to a lot ++of people, so I'm posting everything here. Maybe it can become part of a ++contrib/ dir in the distribution. ++ ++mind you, none of this has been written with elegance or efficiency in ++mind. but it's a good basis for other work. ++ ++Here's a python module that parses the XML pure-ftpwho data and returns ++a list of dicts, with each dict representing a connected client's ++attributes: ++ ++ #! /usr/bin/env python2 ++ ++ import os ++ from xml.sax import handler, make_parser ++ ++ class ftpwho_handler(handler.ContentHandler): ++ def __init__(self): ++ handler.ContentHandler.__init__(self) ++ self.clear() ++ ++ def startElement(self, name, attrs): ++ if name != 'client': return ++ d = {} ++ for (k, v) in attrs.items(): ++ d[k] = v ++ self.clients.append(d) ++ ++ def clear(self): ++ self.clients = [] ++ ++ parser = make_parser() ++ fh = ftpwho_handler() ++ parser.setContentHandler(fh) ++ ++ def numberize(dicts): ++ for c in dicts: ++ for k in ('pid', 'time', 'localport', 'percentage', 'bandwidth'): ++ if c.has_key(k): ++ c[k] = int(c[k]) ++ for k in ('current_size', 'resume', 'total_size'): ++ if c.has_key(k): ++ c[k] = long(c[k]) ++ return dicts ++ ++ def clients(): ++ fh.clear() ++ parser.parse(os.popen('pure-ftpwho -x')) ++ return numberize(fh.clients) ++ ++ ++Building on that, I wrote html_ftpwho.py, which turns the aforementioned ++client list into HTML output. The output resembles what you get with ++"pure-ftpwho -w", but you can choose which columns you want in which ++order, and sort the rows on multiple fields. You also can see bandwidth ++totals per account. ++ ++ #! /usr/bin/env python2 ++ ++ import getopt ++ import pure_ftpwho ++ import sys ++ from string import capitalize, lower ++ ++ def range_idx(list, first = 1, cmp_func = cmp): ++ for i in range(first+1, len(list)): ++ if cmp_func(list[first], list[i]): ++ return i ++ return len(list) ++ ++ def dcmp(a, b, key): ++ if a.has_key(key): ++ if b.has_key(key): ++ return cmp(a[key], b[key]) ++ else: ++ return 1 ++ else: ++ if b.has_key(key): ++ return -1 ++ else: ++ return 0 ++ ++ def multisort(dicts, keys): ++ if not keys: ++ return dicts ++ dicts.sort(lambda x, y, key=keys[0]: dcmp(x, y, key)) ++ ret = [] ++ first = last = 0 ++ while last < len(dicts): ++ last = range_idx(dicts, first, lambda x, y, k=keys[0]: dcmp(x, y, k)) ++ add = multisort(dicts[first:last], keys[1:]) ++ if(add): ++ ret.extend(add) ++ first = last ++ return ret ++ ++ def col_heading(key): ++ headings = {'pid' : 'PID'} ++ if headings.has_key(key): ++ return headings[key] ++ else: ++ return capitalize(lower(key)) ++ ++ def size_abbrev(num, order=-1): ++ abbr = ['b', 'K', 'M', 'G', 'T'] ++ if order == -1: ++ q = 1 ++ for i in range(len(abbr)): ++ p = pow(1024, i+1) ++ if num < p: ++ return (float(num)/q, abbr[i], i) ++ q = p ++ else: ++ return (float(num)/pow(1024, order), abbr[order], order) ++ ++ def celltext(dict, type): ++ sizes = ['current_size', 'total_size', 'percentage', 'bandwidth'] ++ align = '' ++ ret = '' ++ if type == 'stats': ++ align = ' align="right"' ++ if filter(lambda k, d=dict: d.has_key(k), sizes): ++ bw, abbr, order = size_abbrev(dict['bandwidth']) ++ if order == 0: ++ format = '%d' ++ else: ++ format = '%.1f' ++ sf = format + '/' + format ++ sf += ' %s (%d%% - ' + format ++ sf += ' %s/s)' ++ ret = sf % (size_abbrev(dict['current_size'], order)[0], ++ size_abbrev(dict['total_size'], order)[0], ++ abbr, dict['percentage'], bw, abbr) ++ elif not dict.has_key(type): ++ ret = ' ' ++ elif type in sizes: ++ ret = size_abbrev(dict[type]) ++ elif type == 'time': ++ align = ' align="right"' ++ str = '' ++ minutes, seconds = divmod(dict[type], 60) ++ hours, minutes = divmod(minutes, 60) ++ days, hours = divmod(hours, 24) ++ if(days): ++ str += '%dd' % days ++ if(hours): ++ str += '%02d:' % hours ++ ret = str + '%02d:%02d' % (minutes, seconds) ++ else: ++ ret = dict[type] ++ return '%s' % (align, ret) ++ ++ def html(dicts, order, headings, stream, totals): ++ sorted = multisort(dicts, order) ++ stream.write(''' ++ ++ Pure-FTPd server status ++ ++ ''') ++ if(totals): ++ stream.write('') ++ stream.write('') ++ for k in totals.keys(): ++ stream.write('' % k) ++ stream.write('\n' % size_abbrev(totals[k])[:2]) ++ stream.write('
AccountTotal Bandwidth
%s%d %s/s

\n') ++ stream.write('
') ++ stream.write('') ++ for k in headings: ++ stream.write('' % col_heading(k)) ++ stream.write('\n') ++ for d in sorted: ++ stream.write('\n') ++ for k in headings: ++ stream.write('%s' % celltext(d, k)) ++ stream.write('\n\n') ++ stream.write('
%s
\n') ++ ++ def arg_expand(list, opts): ++ optmap = { ++ 'A':'account', ++ 'B':'bandwidth', ++ 'C':'current_size', ++ 'F':'file', ++ 'H':'host', ++ 'L':'localhost', ++ 'O':'localport', ++ 'P':'percentage', ++ 'D':'pid', ++ 'R':'resume', ++ 'S':'state', ++ 'T':'time', ++ 'X':'stats', ++ 'Z':'total_size' } ++ for l in opts: ++ if optmap.has_key(l): ++ list.append(optmap[l]) ++ else: ++ print 'unrecognized column %s' % l ++ sys.exit(1) ++ ++ def usage(): ++ print '''usage: html_ftpwho.py [options] ++ -c columns to output (default "AXTSHF") ++ -o sort order (default "SABT") ++ -t show totals per account ++ ++ is a string of letters, each representing a client attribute: ++ A - account ++ B - bandwidth ++ C - current_size ++ F - file ++ H - host ++ L - localhost ++ O - localport ++ P - percentage ++ D - pid ++ R - resume ++ S - state ++ T - time ++ X - stats ++ Z - total_size ++ ''' ++ sys.exit(1) ++ ++ try: ++ optlist, args = getopt.getopt(sys.argv[1:], 'hc:o:t') ++ except getopt.error, msg: ++ print msg ++ usage() ++ ++ ord_arg = '' ++ col_arg = '' ++ show_totals = 0 ++ for opt in optlist: ++ if '-c' == opt[0]: ++ col_arg += opt[1] ++ elif '-h' == opt[0]: ++ usage() ++ elif '-o' == opt[0]: ++ ord_arg += opt[1] ++ elif '-t' == opt[0]: ++ show_totals = 1 ++ else: ++ print 'unrecognized option "%s"' % opt[0] ++ usage() ++ ++ if not ord_arg: ++ ord_arg = 'SABT' ++ if not col_arg: ++ col_arg = 'AXTSHF' ++ order = [] ++ columns = [] ++ arg_expand(order, ord_arg) ++ arg_expand(columns, col_arg) ++ ++ cl = pure_ftpwho.clients() ++ totals = {} ++ if show_totals: ++ for c in cl: ++ if c.has_key('bandwidth'): ++ try: ++ totals[c['account']] += c['bandwidth'] ++ except KeyError: ++ totals[c['account']] = c['bandwidth'] ++ ++ html(cl, order, columns, sys.stdout, totals) ++ ++suggestions/patches welcome, ++ ++Jason +-- +2.20.1 + diff --git a/0003-Revert-Remove-pure-vpopauth.-That-script-is-terrible.patch b/0003-Revert-Remove-pure-vpopauth.-That-script-is-terrible.patch new file mode 100644 index 0000000..e506c3c --- /dev/null +++ b/0003-Revert-Remove-pure-vpopauth.-That-script-is-terrible.patch @@ -0,0 +1,81 @@ +From 88e305cf8a70b940f15a2dff496887f388dfd4a9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Wed, 6 Feb 2019 12:40:01 +0100 +Subject: [PATCH 3/3] Revert "Remove pure-vpopauth. That script is terrible." + +This reverts commit fe6419d70ccf5b4f3bfc5f8200f99f3915994a19. +--- + contrib/Makefile.am | 1 + + contrib/pure-vpopauth.pl | 51 ++++++++++++++++++++++++++++++++++++++++ + 2 files changed, 52 insertions(+) + create mode 100755 contrib/pure-vpopauth.pl + +diff --git a/contrib/Makefile.am b/contrib/Makefile.am +index 5056d5f..81aae9a 100644 +--- a/contrib/Makefile.am ++++ b/contrib/Makefile.am +@@ -1,3 +1,4 @@ + EXTRA_DIST = \ + xml_python_processors.txt \ ++ pure-vpopauth.pl \ + pure-stat.pl +diff --git a/contrib/pure-vpopauth.pl b/contrib/pure-vpopauth.pl +new file mode 100755 +index 0000000..6a59a41 +--- /dev/null ++++ b/contrib/pure-vpopauth.pl +@@ -0,0 +1,51 @@ ++#! /usr/bin/env perl -w ++ ++# - authentication module for pure-ftpd using vpasswd vpopmail password files. ++# - Saturday, 12 May 2002 - released ++# - copyright (c) Dan Caescu - daniel@guitar.ro , jamie_fd@yahoo.com ++# - vpopmail has to be compiled with clear text passwords in order for ++# - this to work. ++# - also, there would be great if you would run pure-ftpd with chroot flags ++# - 17 Nov 2002, added e-mail checking, a hint from Frank Jedi @ pureftpd ++# - I guess it works..? :) ++# - greets to Rox (Roxana Raluca) . ++ ++# Change the following settings according to your needs ++ ++$VPOPMAIL_PATH = '/usr/local/vpopmail'; ++$UID = 1000; ++$GID = 1000; ++ ++# Don't change anything below that line ++ ++$AUTHD_ACCOUNT = $ENV{AUTHD_ACCOUNT} or die; ++$AUTHD_PASSWORD = $ENV{AUTHD_PASSWORD} or die; ++ ++# Checking if AUTHD_ACCOUNT is like user@domain ++ ++$AUTHD_ACCOUNT =~ /^[^@]+\@([a-z0-9]+\.)+[a-z]+$/i or die; ++ ++# We take care of the user/domain pair 'cause the user comes ++# in the user@domain style ++ ++@user_domain = split('@', $AUTHD_ACCOUNT); ++ ++open (FILE, "$VPOPMAIL_PATH/domains/" . $user_domain[1] . '/vpasswd') or die; ++ ++# We take care of the user/pass from vpasswd ++ ++while () { ++ chomp; ++ @date_useri = split ':'; ++ if ($user_domain[0] eq $date_useri[0] && ++ $AUTHD_PASSWORD eq $date_useri[7]) { ++ print "auth_ok:1\n", ++ "uid:$UID\n", ++ "gid:$GID\n", ++ "dir:$date_useri[5]\n", ++ "end\n"; ++ last; ++ } ++} ++ ++close FILE; +-- +2.20.1 + diff --git a/0001-modify-pam.patch b/pure-ftpd-1.0.40-paminclude.patch similarity index 60% rename from 0001-modify-pam.patch rename to pure-ftpd-1.0.40-paminclude.patch index 094a5d1..83bcf70 100644 --- a/0001-modify-pam.patch +++ b/pure-ftpd-1.0.40-paminclude.patch @@ -1,17 +1,7 @@ -From 0cabf3b8b952c6117d575360f793ba63fb53c7ba Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Wed, 12 Jul 2017 12:09:38 +0200 -Subject: [PATCH 1/2] modify pam - ---- - pam/pure-ftpd | 9 +++++---- - 1 file changed, 5 insertions(+), 4 deletions(-) - -diff --git a/pam/pure-ftpd b/pam/pure-ftpd -index 6611b87..ece8733 100644 ---- a/pam/pure-ftpd -+++ b/pam/pure-ftpd -@@ -4,12 +4,13 @@ +diff -Naur pure-ftpd-1.0.40.orig/pam/pure-ftpd pure-ftpd-1.0.40/pam/pure-ftpd +--- pure-ftpd-1.0.40.orig/pam/pure-ftpd 2015-06-13 12:26:37.000000000 +0200 ++++ pure-ftpd-1.0.40/pam/pure-ftpd 2015-06-01 16:36:31.000000000 +0200 +@@ -4,12 +4,14 @@ # Install it in /etc/pam.d/pure-ftpd or add to /etc/pam.conf auth required pam_listfile.so item=user sense=deny file=/etc/ftpusers onerr=succeed @@ -23,12 +13,9 @@ index 6611b87..ece8733 100644 +account include password-auth -password required pam_stack.so service=system-auth -- --session required pam_stack.so service=system-auth +password include password-auth +-session required pam_stack.so service=system-auth +session required pam_loginuid.so +session include password-auth --- -2.13.0 - + diff --git a/0002-fedora-specific-config-file.patch b/pure-ftpd-1.0.47-config.patch similarity index 57% rename from 0002-fedora-specific-config-file.patch rename to pure-ftpd-1.0.47-config.patch index afa6fcf..725258f 100644 --- a/0002-fedora-specific-config-file.patch +++ b/pure-ftpd-1.0.47-config.patch @@ -1,100 +1,87 @@ -From 5dbbb2948bee45ec0115146efb4a090df00f5530 Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Thu, 14 Sep 2017 16:41:12 +0200 -Subject: [PATCH] fedora specific config file - ---- - pure-ftpd.conf.in | 31 +++++++++++++++---------------- - 1 file changed, 15 insertions(+), 16 deletions(-) - -diff --git a/pure-ftpd.conf.in b/pure-ftpd.conf.in -index aeb093a..e93053a 100644 ---- a/pure-ftpd.conf.in -+++ b/pure-ftpd.conf.in +diff -up a/pure-ftpd.conf.in b/pure-ftpd.conf.in +--- a/pure-ftpd.conf.in 2017-09-07 13:47:26.000000000 +0200 ++++ b/pure-ftpd.conf.in 2019-02-05 17:27:07.475603616 +0100 @@ -9,7 +9,7 @@ # instead of command-line options, please run the # following command : # --# @sbindir@/sbin/pure-ftpd @sysconfdir@/pure-ftpd.conf +-# @prefix@/sbin/pure-ftpd @sysconfdir@/etc/pure-ftpd.conf +# @sbindir@/pure-ftpd @sysconfdir@/pure-ftpd.conf # # Online documentation: # https://www.pureftpd.org/project/pure-ftpd/doc -@@ -42,7 +42,7 @@ MaxClientsNumber 50 - - - # Run as a background process -- -+# Important: this must be set to 'yes' for the systemd service to work. - Daemonize yes - - -@@ -106,34 +106,34 @@ MaxIdleTime 15 +@@ -106,34 +106,34 @@ # LDAP configuration file (see README.LDAP) -# LDAPConfigFile /etc/pureftpd-ldap.conf -+# LDAPConfigFile @sysconfigdir@/pureftpd-ldap.conf ++# LDAPConfigFile @sysconfdir@/pureftpd-ldap.conf # MySQL configuration file (see README.MySQL) -# MySQLConfigFile /etc/pureftpd-mysql.conf -+# MySQLConfigFile @sysconfigdir@/pureftpd-mysql.conf ++# MySQLConfigFile @sysconfdir@/pureftpd-mysql.conf # PostgreSQL configuration file (see README.PGSQL) -# PGSQLConfigFile /etc/pureftpd-pgsql.conf -+# PGSQLConfigFile @sysconfigdir@/pureftpd-pgsql.conf ++# PGSQLConfigFile @sysconfdir@/pureftpd-pgsql.conf # PureDB user database (see README.Virtual-Users) -# PureDB /etc/pureftpd.pdb -+# PureDB @sysconfigdir@/pureftpd.pdb ++# PureDB @sysconfdir@/pureftpd.pdb # Path to pure-authd socket (see README.Authentication-Modules) -# ExtAuth /var/run/ftpd.sock -+# ExtAuth @localstatedir@/run/ftpd.sock ++# ExtAuth @localstatedir@/run/ftpd.sock # If you want to enable PAM authentication, uncomment the following line -# PAMAuthentication yes -+PAMAuthentication yes ++PAMAuthentication yes -@@ -238,8 +238,7 @@ Umask 133:022 +@@ -238,7 +238,14 @@ # For example, a value of 100 prevents all users whose user id is below # 100 from logging in. If you want "root" to be able to log in, use 0. -MinUID 100 -- -+MinUID 1000 ++MinUID 1000 ++ ++ ++ ++# Do not use the /etc/ftpusers file to disable accounts. We're already ++# using MinUID to block users with uid < 1000 ++ ++UseFtpUsers no - # Allow FXP transfers for authenticated users. -@@ -277,7 +276,7 @@ AutoRename no + +@@ -277,7 +284,7 @@ # Prevent anonymous users from uploading new files (no = upload is allowed) -AnonymousCantUpload no -+AnonymousCantUpload yes ++AnonymousCantUpload yes -@@ -301,21 +300,21 @@ AnonymousCantUpload no +@@ -301,21 +308,21 @@ # fw.c9x.org - jedi [13/Apr/2017:19:36:39] "GET /ftp/linux.tar.bz2" 200 21809338 # This log file can then be processed by common HTTP traffic analyzers. -# AltLog clf:/var/log/pureftpd.log -+AltLog clf:@localstatedir@/log/pureftpd.log ++AltLog clf:@localstatedir@/log/pureftpd.log @@ -102,7 +89,7 @@ index aeb093a..e93053a 100644 # for statistic reports. -# AltLog stats:/var/log/pureftpd.log -+# AltLog stats:@localstatedir@/log/pureftpd.log ++# AltLog stats:@localstatedir@/log/pureftpd.log @@ -110,11 +97,11 @@ index aeb093a..e93053a 100644 # format (compatible with many HTTP log analyzers) -# AltLog w3c:/var/log/pureftpd.log -+# AltLog w3c:@localstatedir@/log/pureftpd.log ++# AltLog w3c:@localstatedir@/log/pureftpd.log -@@ -346,9 +345,9 @@ AnonymousCantUpload no +@@ -346,9 +353,9 @@ # If your pure-ftpd has been compiled with standalone support, you can change @@ -126,6 +113,3 @@ index aeb093a..e93053a 100644 --- -2.20.1 - diff --git a/pure-ftpd-with-tls-init.service b/pure-ftpd-with-tls-init.service deleted file mode 100644 index aab2191..0000000 --- a/pure-ftpd-with-tls-init.service +++ /dev/null @@ -1,10 +0,0 @@ -[Unit] -Description=One-time configuration for pure-ftpd - -ConditionPathExists=|!/etc/pki/pure-ftpd/pure-ftpd.pem - -[Service] -Type=oneshot -RemainAfterExit=no - -ExecStart=/usr/bin/sscg --ca-file /etc/pki/pure-ftpd/ca.crt --cert-file /etc/pki/pure-ftpd/pure-ftpd.pem --cert-key-file /etc/pki/pure-ftpd/pure-ftpd.pem diff --git a/pure-ftpd-with-tls.service b/pure-ftpd-with-tls.service deleted file mode 100644 index d7abfec..0000000 --- a/pure-ftpd-with-tls.service +++ /dev/null @@ -1,12 +0,0 @@ -[Unit] -Description=Pure-FTPd FTP server -After=syslog.target network.target pure-ftpd-init.service -Requires=pure-ftpd-init.service - -[Service] -Type=forking -PIDFile=/var/run/pure-ftpd.pid -ExecStart=/usr/sbin/pure-ftpd /etc/pure-ftpd/pure-ftpd.conf - -[Install] -WantedBy=multi-user.target diff --git a/pure-ftpd.pure-ftpwho.consoleapp b/pure-ftpd.pure-ftpwho.consoleapp new file mode 100644 index 0000000..8452f88 --- /dev/null +++ b/pure-ftpd.pure-ftpwho.consoleapp @@ -0,0 +1,3 @@ +USER=root +PROGRAM=/usr/sbin/pure-ftpwho +GUI=no diff --git a/pure-ftpd.pure-ftpwho.pam b/pure-ftpd.pure-ftpwho.pam new file mode 100644 index 0000000..268cc92 --- /dev/null +++ b/pure-ftpd.pure-ftpwho.pam @@ -0,0 +1,4 @@ +#%PAM-1.0 +auth sufficient pam_rootok.so +auth required pam_localuser.so +account required pam_permit.so diff --git a/pure-ftpd.service b/pure-ftpd.service index 05bb621..e0b3dba 100644 --- a/pure-ftpd.service +++ b/pure-ftpd.service @@ -5,7 +5,7 @@ After=syslog.target network.target [Service] Type=forking PIDFile=/var/run/pure-ftpd.pid -ExecStart=/usr/sbin/pure-ftpd /etc/pure-ftpd/pure-ftpd.conf +ExecStart=/usr/sbin/pure-config.pl /etc/pure-ftpd/pure-ftpd.conf --daemonize [Install] WantedBy=multi-user.target diff --git a/pure-ftpd.spec b/pure-ftpd.spec index 9159c7b..cfa2b0d 100644 --- a/pure-ftpd.spec +++ b/pure-ftpd.spec @@ -1,38 +1,60 @@ Name: pure-ftpd -Version: 1.0.52 -Release: 2%{?dist} +Version: 1.0.47 +Release: 4%{?dist} Summary: Lightweight, fast and secure FTP server -# Automatically converted from old format: BSD - review is highly recommended. -License: LicenseRef-Callaway-BSD -URL: http://www.pureftpd.org +Group: System Environment/Daemons +License: BSD +URL: http://www.pureftpd.org Source0: http://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-%{version}.tar.bz2 Source1: pure-ftpd.service Source2: pure-ftpd.logrotate +Source3: pure-ftpd.xinetd +Source4: pure-ftpd.pure-ftpwho.pam +Source5: pure-ftpd.pure-ftpwho.consoleapp Source6: pure-ftpd.README.SELinux Source7: pure-ftpd.pureftpd.te -Source8: pure-ftpd-with-tls-init.service -Source9: pure-ftpd-with-tls.service -Patch0: 0001-modify-pam.patch -Patch1: 0002-fedora-specific-config-file.patch +Patch0: pure-ftpd-1.0.47-config.patch +Patch1: pure-ftpd-1.0.40-paminclude.patch +# Upstream patch: +Patch2: 0001-Exit-when-given-an-invalid-cmdline-option.patch +# Upstream patch: +Patch3: 0002-Complain-when-both-options-and-config-file-are-given.patch +# Upstream patch: +Patch4: 0001-Increase-MAX_DATA_SIZE-due-to-Argon2id-requirements.patch +# Upstream patch: +Patch6: 0001-Fix-postgresql-authenticate-bug.patch + +# Revert pure-config.pl and contrib removal: +Patch7: 0001-Revert-After-20-years-say-goodbye-to-the-external-co.patch +Patch8: 0001-Revert-No-more-contrib-Makefile.in.patch +Patch9: 0002-Revert-Remove-contribs.-These-are-way-too-old-and-un.patch +Patch10: 0003-Revert-Remove-pure-vpopauth.-That-script-is-terrible.patch + +# Temporarily disable TLSv1.3 to workaround +# https://github.com/jedisct1/pure-ftpd/issues/102 +Patch11: 0001-Temporarily-disable-TLSv1.3-support.patch +# Upstream patch: +Patch12: 0001-listdir-reuse-a-single-buffer-to-store-every-file-na.patch +# Upstream patch: +Patch13: 0001-diraliases-always-set-the-tail-of-the-list-to-NULL.patch +# Upstream patch: +Patch14: 0001-pure_strcmp-len-s2-can-be-len-s1.patch Provides: ftpserver -BuildRequires: make -BuildRequires: pam-devel, libcap-devel -BuildRequires: libxcrypt-devel +BuildRequires: pam-devel, perl, python, libcap-devel %{!?_without_ldap:BuildRequires: openldap-devel} -%{!?_without_mysql:BuildRequires: mariadb-connector-c-devel} -%{!?_without_pgsql:BuildRequires: libpq-devel} +%{!?_without_mysql:BuildRequires: mysql-devel} +%{!?_without_pgsql:BuildRequires: postgresql-devel} %{!?_without_tls:BuildRequires: openssl-devel} BuildRequires: checkpolicy, selinux-policy-devel -BuildRequires: systemd -BuildRequires: git -BuildRequires: gcc -Requires(post): systemd -Requires(preun): systemd -Requires(postun): systemd -Requires: logrotate -%{!?_without_tls:Requires: sscg} +BuildRequires: systemd-units +BuildRequires: automake autoconf-archive +Requires(post): systemd-sysv +Requires(post): systemd-units +Requires(preun): systemd-units +Requires(postun): systemd-units +Requires: logrotate, usermode %description @@ -54,9 +76,10 @@ Rebuild switches: %package selinux Summary: SELinux support for Pure-FTPD +Group: System Environment/Daemons Requires: %{name} = %{version} -Requires(post): policycoreutils, %{name} -Requires(preun): policycoreutils, %{name} +Requires(post): policycoreutils, initscripts, %{name} +Requires(preun): policycoreutils, initscripts, %{name} Requires(postun): policycoreutils %description selinux @@ -67,17 +90,33 @@ Pure-FTPd to be protected in the same way other FTP servers are in Fedora %prep -%autosetup -S git +%setup -q +%patch0 -p1 -b .config +%patch1 -p1 -b .paminclude +%patch2 -p1 +%patch3 -p1 +%patch4 -p1 +%patch6 -p1 +%patch7 -p1 +%patch8 -p1 +%patch9 -p1 +%patch10 -p1 +%patch11 -p1 +%patch12 -p1 +%patch13 -p1 +%patch14 -p1 install -pm 644 %{SOURCE6} README.SELinux mkdir selinux cp -p %{SOURCE7} selinux/pureftpd.te %build +autoreconf -fi %configure \ --sysconfdir=%{_sysconfdir}/%{name} \ --with-capabilities \ --with-sendfile \ + --with-cork \ --with-paranoidmsg \ --with-altlog \ --with-puredb \ @@ -102,10 +141,11 @@ cp -p %{SOURCE7} selinux/pureftpd.te --with-rfc2640 \ --without-bonjour \ -%make_build +make %{?_smp_mflags} + %install -%make_install +make install DESTDIR=$RPM_BUILD_ROOT install -d -m 755 $RPM_BUILD_ROOT%{_mandir}/man8 install -d -m 755 $RPM_BUILD_ROOT%{_sbindir} @@ -115,7 +155,9 @@ install -d -m 755 $RPM_BUILD_ROOT%{_localstatedir}/ftp %{!?_without_tls:install -d -m 700 $RPM_BUILD_ROOT%{_sysconfdir}/pki/%{name}} # Conf +install -p -m 755 configuration-file/pure-config.pl $RPM_BUILD_ROOT%{_sbindir} install -p -m 644 pure-ftpd.conf $RPM_BUILD_ROOT%{_sysconfdir}/%{name} +install -p -m 755 configuration-file/pure-config.py $RPM_BUILD_ROOT%{_sbindir} install -p -m 644 pureftpd-ldap.conf $RPM_BUILD_ROOT%{_sysconfdir}/%{name} install -p -m 644 pureftpd-mysql.conf $RPM_BUILD_ROOT%{_sysconfdir}/%{name} install -p -m 644 pureftpd-pgsql.conf $RPM_BUILD_ROOT%{_sysconfdir}/%{name} @@ -131,13 +173,8 @@ install -p -m 644 man/pure-statsdecode.8 $RPM_BUILD_ROOT%{_mandir}/man8 install -p -m 644 man/pure-quotacheck.8 $RPM_BUILD_ROOT%{_mandir}/man8 install -p -m 644 man/pure-authd.8 $RPM_BUILD_ROOT%{_mandir}/man8 -# Systemd services -%if 0%{!?_without_tls:1} -install -p -m 644 %{SOURCE8} $RPM_BUILD_ROOT%{_unitdir}/pure-ftpd-init.service -install -p -m 644 %{SOURCE9} $RPM_BUILD_ROOT%{_unitdir}/pure-ftpd.service -%else -install -p -m 644 %{SOURCE1} $RPM_BUILD_ROOT%{_unitdir}/pure-ftpd.service -%endif +# Init script +install -p -m 644 %{SOURCE1} $RPM_BUILD_ROOT%{_unitdir}/%{name}.service # Pam install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/pam.d @@ -147,21 +184,36 @@ install -p -m 644 pam/pure-ftpd $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/ install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d install -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/%{name} +# xinetd support +install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d +install -p -m 644 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/xinetd.d/%{name} + +# pure-ftpwho and non-root users +install -d -m 755 $RPM_BUILD_ROOT%{_sysconfdir}/security/console.apps +install -p -m 644 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/pure-ftpwho +install -p -m 644 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/security/console.apps/pure-ftpwho +ln -s consolehelper $RPM_BUILD_ROOT%{_bindir}/pure-ftpwho + # SELinux support -pushd selinux +cd selinux echo "%{_sbindir}/pure-ftpd system_u:object_r:ftpd_exec_t:s0" > pureftpd.fc echo '%{_localstatedir}/log/pureftpd.log system_u:object_r:xferlog_t:s0' >> pureftpd.fc touch pureftpd.if make -f %{_datadir}/selinux/devel/Makefile install -p -m 644 -D pureftpd.pp $RPM_BUILD_ROOT%{_datadir}/selinux/packages/%{name}/pureftpd.pp -popd -# Remove unnecessary docs -rm $RPM_BUILD_ROOT%{_docdir}/%{name}/README.MacOS-X %post %systemd_post pure-ftpd.service +%if 0%{!?_without_tls:1} +# TLS Certificate +if [ ! -f %{_sysconfdir}/pki/%{name}/%{name}.pem ]; then + %{_sysconfdir}/pki/tls/certs/make-dummy-cert \ + %{_sysconfdir}/pki/%{name}/%{name}.pem +fi +%endif + %preun %systemd_preun pure-ftpd.service @@ -173,14 +225,14 @@ rm $RPM_BUILD_ROOT%{_docdir}/%{name}/README.MacOS-X if [ "$1" -le "1" ]; then # Fist install semodule -i %{_datadir}/selinux/packages/%{name}/pureftpd.pp 2>/dev/null || : fixfiles -R pure-ftpd restore || : - /bin/systemctl condrestart pure-ftpd > /dev/null 2>&1 || : + /sbin/service pure-ftpd condrestart > /dev/null 2>&1 || : fi %preun selinux if [ "$1" -lt "1" ]; then # Final removal semodule -r pureftpd 2>/dev/null || : fixfiles -R pure-ftpd restore || : - /bin/systemctl condrestart pure-ftpd > /dev/null 2>&1 || : + /sbin/service pure-ftpd condrestart > /dev/null 2>&1 || : fi %postun selinux @@ -191,24 +243,32 @@ if [ "$1" -ge "1" ]; then # Upgrade fi +%triggerun -- pure-ftpd < 1.0.32-2 +# Save the current service runlevel info +# User must manually run systemd-sysv-convert --apply pure-ftpd +# to migrate them to systemd targets +/usr/bin/systemd-sysv-convert --save pure-ftpd >/dev/null 2>&1 ||: + +# Run these because the SysV package being removed won't do them +/sbin/chkconfig --del pure-ftpd >/dev/null 2>&1 || : +/bin/systemctl try-restart pure-ftpd.service >/dev/null 2>&1 || : + + %files -%doc FAQ THANKS AUTHORS HISTORY NEWS +%doc FAQ THANKS AUTHORS CONTACT HISTORY NEWS %doc README README.Authentication-Modules README.Configuration-File -%doc README.Donations README.LDAP README.MySQL README.SELinux +%doc README.Contrib README.Donations README.LDAP README.MySQL %doc README.PGSQL README.TLS README.Virtual-Users -%doc pureftpd.schema -%doc %{_docdir}/%{name}/*.conf +%doc contrib/pure-vpopauth.pl pureftpd.schema contrib/pure-stat.pl %{_bindir}/pure-* %{_sbindir}/pure-* -%if 0%{!?_without_tls:1} -%{_unitdir}/pure-ftpd-init.service -%{_unitdir}/pure-ftpd.service -%else -%{_unitdir}/pure-ftpd.service -%endif +%{_unitdir}/%{name}.service %config(noreplace) %{_sysconfdir}/%{name} %config(noreplace) %{_sysconfdir}/pam.d/%{name} %config(noreplace) %{_sysconfdir}/logrotate.d/%{name} +%config(noreplace) %{_sysconfdir}/xinetd.d/%{name} +%config(noreplace) %{_sysconfdir}/pam.d/pure-ftpwho +%config(noreplace) %{_sysconfdir}/security/console.apps/pure-ftpwho %{!?_without_tls:%{_sysconfdir}/pki/%{name}} %{_mandir}/man8/* %dir /var/ftp/ @@ -220,160 +280,22 @@ fi %changelog -* Fri Jul 25 2025 Fedora Release Engineering - 1.0.52-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild - -* Tue May 20 2025 Jonathan Wright - 1.0.52-1 -- update to 1.0.52 rhbz#2313435 -- Fixes CVE-2024-48208 rhbz#2343476 - -* Sat Feb 01 2025 Björn Esser - 1.0.51-9 -- Add explicit BR: libxcrypt-devel - -* Sat Jan 18 2025 Fedora Release Engineering - 1.0.51-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild - -* Wed Sep 04 2024 Miroslav Suchý - 1.0.51-7 -- convert license to SPDX - -* Fri Jul 19 2024 Fedora Release Engineering - 1.0.51-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild - -* Fri Jan 26 2024 Fedora Release Engineering - 1.0.51-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Sun Jan 21 2024 Fedora Release Engineering - 1.0.51-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild - -* Fri Jul 21 2023 Fedora Release Engineering - 1.0.51-3 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild - -* Fri Jan 20 2023 Fedora Release Engineering - 1.0.51-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild - -* Thu Jul 21 2022 Jonathan Wright - 1.0.51-1 -- New version -- Resolves: rhbz#2026153 -- Remove usermode dependency and non-root "ftpwho" -- Resolves: rhbz#502754 - -* Fri Jan 21 2022 Fedora Release Engineering - 1.0.49-12 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild - -* Tue Sep 14 2021 Sahana Prasad - 1.0.49-11 -- Rebuilt with OpenSSL 3.0.0 - -* Fri Jul 23 2021 Fedora Release Engineering - 1.0.49-10 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild - -* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek - 1.0.49-9 -- Rebuilt for updated systemd-rpm-macros - See https://pagure.io/fesco/issue/2583. - -* Mon Feb 08 2021 Pavel Raiskup - 1.0.49-8 -- rebuild for libpq ABI fix rhbz#1908268 - -* Wed Jan 27 2021 Fedora Release Engineering - 1.0.49-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild - -* Tue Jul 28 2020 Fedora Release Engineering - 1.0.49-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild - -* Wed May 06 2020 Ondřej Lysoněk - 1.0.49-5 +* Wed May 06 2020 Ondřej Lysoněk - 1.0.47-4 - Fix CVE-2020-9365 and CVE-2020-9274 -- Resolves: rhbz#1828688 -- Resolves: rhbz#1831059 +- Resolves: rhbz#1828689 +- Resolves: rhbz#1831060 -* Thu Jan 30 2020 Fedora Release Engineering - 1.0.49-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild - -* Mon Jan 27 2020 Ondřej Lysoněk - 1.0.49-3 +* Mon Jan 27 2020 Ondřej Lysoněk - 1.0.47-3 - Fix potential stack exhaustion in function listdir (CVE-2019-20176) - Resolves: rhbz#1795152 -* Fri Jul 26 2019 Fedora Release Engineering - 1.0.49-2 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild - -* Wed Apr 03 2019 Ondřej Lysoněk - 1.0.49-1 -- New version -- Resolves: rhbz#1695561 - -* Fri Mar 29 2019 Ondřej Lysoněk - 1.0.48-1 -- New version -- Resolves: rhbz#1692539 -- Resolves: rhbz#1672494 -- Resolves: rhbz#1654838 - -* Tue Feb 12 2019 Ondřej Lysoněk - 1.0.47-10 +* Wed Feb 13 2019 Ondřej Lysoněk - 1.0.47-2 - Temporarily disable TLSv1.3 support until it's fully fixed -* Tue Feb 05 2019 Ondřej Lysoněk - 1.0.47-9 -- Fixed TLSv1.3 support -- Resolves: rhbz#1654838 -- Fixed postgresql authentication - -* Sat Feb 02 2019 Fedora Release Engineering - 1.0.47-8 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild - -* Mon Jan 14 2019 Björn Esser - 1.0.47-7 -- Rebuilt for libcrypt.so.2 (#1666033) - -* Mon Nov 19 2018 Peter Robinson 1.0.47-6 -- Fix for oversight in previous change - -* Sun Nov 18 2018 Peter Robinson 1.0.47-5 -- Drop sysv legacy bits - -* Fri Jul 13 2018 Fedora Release Engineering - 1.0.47-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild - -* Thu Mar 15 2018 Ondřej Lysoněk - 1.0.47-3 -- Apply upstream patch to increase the size limit of the process's data segment -- https://github.com/jedisct1/pure-ftpd/issues/82 -- Resolves: rhbz#1490354 - -* Mon Feb 19 2018 Ondřej Lysoněk - 1.0.47-2 -- Add gcc to BuildRequires - -* Tue Feb 13 2018 Ondřej Lysoněk - 1.0.47-1 +* Tue Feb 05 2019 Ondřej Lysoněk - 1.0.47-1 - New version -- Dropped patch 0003-Allow-having-both-options-and-config-file-on-command.patch - as it was rejected by upstream -- Complain when invalid or excessive arguments are given on the command line - -* Fri Feb 09 2018 Fedora Release Engineering - 1.0.46-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild - -* Sat Jan 20 2018 Björn Esser - 1.0.46-5 -- Rebuilt for switch to libxcrypt - -* Wed Oct 25 2017 Ondřej Lysoněk - 1.0.46-4 -- Depend on mariadb-connector-c-devel instead of mysql-devel -- Resolves: rhbz#1493658 - -* Wed Oct 25 2017 Ondřej Lysoněk - 1.0.46-3 -- Generate the TLS certificate using sscg in an initialization systemd service -- This is required by -- https://fedoraproject.org/wiki/Packaging:Initial_Service_Setup - -* Thu Sep 14 2017 Ondřej Lysoněk - 1.0.46-2 -- Fix loading the configuration file -- Drop unsupported UseFtpUsers option from configuration file - -* Mon Aug 14 2017 Martin Sehnoutka - 1.0.46-1 -- Rebase to 1.0.46 - -* Thu Aug 03 2017 Fedora Release Engineering - 1.0.42-7 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild - -* Thu Jul 27 2017 Fedora Release Engineering - 1.0.42-6 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild - -* Sat Feb 11 2017 Fedora Release Engineering - 1.0.42-5 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild - -* Thu Feb 04 2016 Fedora Release Engineering - 1.0.42-4 -- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild +- Resolves: rhbz#1397962 +- Resolves: rhbz#1576825 * Wed Dec 23 2015 Robert Scheck - 1.0.42-3 - Remove executable permission bits from pure-ftpd systemd unit diff --git a/pure-ftpd.xinetd b/pure-ftpd.xinetd new file mode 100644 index 0000000..e980e94 --- /dev/null +++ b/pure-ftpd.xinetd @@ -0,0 +1,17 @@ +# default: off +# description: pure-ftpd server, xinetd version. \ +# Don't run the standalone version if you run \ +# this and remember do set "Daemonize" to "no" \ +# in /etc/pure-ftpd/pure-ftpd.conf +service ftp +{ + disable = yes + socket_type = stream + wait = no + user = root + server = /usr/sbin/pure-config.pl + server_args = /etc/pure-ftpd/pure-ftpd.conf + log_on_success += DURATION USERID + log_on_failure += USERID + nice = 10 +} diff --git a/sources b/sources index 920b4eb..a5bbab1 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -SHA512 (pure-ftpd-1.0.52.tar.bz2) = c7b6f76c1429d2cbf9d740c3408464564e023716ebf8361231ba5021f81804575049910c9874970c83c98f927cd496899e5c30625e4dee6538497f9179632c23 +SHA512 (pure-ftpd-1.0.47.tar.bz2) = c1920a3f67f04635fde600fe226a7730b801e7e64658b25f1d9f9c0b35a704664be4adfb0b291594f7e0f10beade25eae9a5e6cc3b6777a3b413f3c2d9574e63