diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..885598e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/vsftpd-3.0.2.tar.gz diff --git a/.vsftpd.metadata b/.vsftpd.metadata new file mode 100644 index 0000000..c4d0d19 --- /dev/null +++ b/.vsftpd.metadata @@ -0,0 +1 @@ +f36976bb1c5df25ac236d8a29e965ba2b825ccd0 SOURCES/vsftpd-3.0.2.tar.gz diff --git a/SOURCES/0001-Add-new-filename-generation-algorithm-for-STOU-comma.patch b/SOURCES/0001-Add-new-filename-generation-algorithm-for-STOU-comma.patch new file mode 100644 index 0000000..6a557b7 --- /dev/null +++ b/SOURCES/0001-Add-new-filename-generation-algorithm-for-STOU-comma.patch @@ -0,0 +1,328 @@ +From ec60588d36f06acdd6a1b3c5959d2102f4f5b230 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 6 Feb 2018 13:30:44 +0100 +Subject: [PATCH] Add new filename generation algorithm for STOU command + +A new configuration option 'better_stou' can be used to enable +a better algorithm for generating unique filenames. + +Resolves: rhbz#1479237 +--- + parseconf.c | 1 + + postlogin.c | 177 +++++++++++++++++++++++++++++++++++++++++++++++++--------- + sysutil.c | 3 + + sysutil.h | 3 +- + tunables.c | 2 + + tunables.h | 3 + + vsftpd.conf.5 | 10 ++++ + 7 files changed, 172 insertions(+), 27 deletions(-) + +diff --git a/parseconf.c b/parseconf.c +index 33a1349..47b54f1 100644 +--- a/parseconf.c ++++ b/parseconf.c +@@ -111,6 +111,7 @@ parseconf_bool_array[] = + { "http_enable", &tunable_http_enable }, + { "seccomp_sandbox", &tunable_seccomp_sandbox }, + { "allow_writeable_chroot", &tunable_allow_writeable_chroot }, ++ { "better_stou", &tunable_better_stou }, + { 0, 0 } + }; + +diff --git a/postlogin.c b/postlogin.c +index 869c2a2..3b50af2 100644 +--- a/postlogin.c ++++ b/postlogin.c +@@ -29,6 +29,7 @@ + #include "opts.h" + + #include ++#include + + /* Private local functions */ + static void handle_pwd(struct vsf_session* p_sess); +@@ -1021,6 +1022,115 @@ handle_stor(struct vsf_session* p_sess) + handle_upload_common(p_sess, 0, 0); + } + ++/* Based on __gen_tempname() from glibc - thanks, glibc! Relicensed ++ * from LGPL2.1+ to GPL2. ++ */ ++static int ++create_unique_file(struct vsf_session* p_sess, struct mystr* p_outstr, ++ const struct mystr* p_base_str, ++ int (*access_checker)(const struct mystr*)) ++{ ++ struct mystr s_result = INIT_MYSTR; ++ const int suffix_len = 6; ++ unsigned int count; ++ static unsigned long long int value; ++ unsigned long long int random_time_bits; ++ int fd = -1; ++ /* These are the characters used in temporary file names. */ ++ struct mystr s_letters = INIT_MYSTR; ++ unsigned int s_letters_len; ++ int base_len; ++ ++ str_alloc_text(&s_letters, ++ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"); ++ s_letters_len = str_getlen(&s_letters); ++ ++ /* A lower bound on the number of temporary files to attempt to ++ generate. The maximum total number of temporary file names that ++ can exist for a given template is 62**6. It should never be ++ necessary to try all of these combinations. Instead if a reasonable ++ number of names is tried (we define reasonable as 62**3) fail to ++ give the system administrator the chance to remove the problems. */ ++#define ATTEMPTS_MIN (62 * 62 * 62) ++ ++ /* The number of times to attempt to generate a temporary file. */ ++#if ATTEMPTS_MIN < TMP_MAX ++ unsigned int attempts = TMP_MAX; ++#else ++ unsigned int attempts = ATTEMPTS_MIN; ++#endif ++#undef ATTEMPTS_MIN ++ ++ { ++ long sec = vsf_sysutil_get_time_sec(); ++ long usec = vsf_sysutil_get_time_usec(); ++ random_time_bits = ((unsigned long long int) usec << 16) ^ sec; ++ value += random_time_bits ^ vsf_sysutil_getpid(); ++ } ++ ++ if (str_isempty(p_base_str)) ++ { ++ const char *base = "STOU."; ++ base_len = vsf_sysutil_strlen(base); ++ str_reserve(&s_result, base_len + suffix_len); ++ str_alloc_text(&s_result, base); ++ } ++ else ++ { ++ str_reserve(&s_result, str_getlen(p_base_str) + suffix_len + 1); ++ str_copy(&s_result, p_base_str); ++ str_append_char(&s_result, '.'); ++ base_len = str_getlen(&s_result); ++ } ++ ++ for (count = 0; count < attempts; value += 7777, ++count) ++ { ++ unsigned long long v = value; ++ int i; ++ str_trunc(&s_result, base_len); ++ for (i = 0; i < suffix_len; ++i) ++ { ++ char c; ++ c = str_get_char_at(&s_letters, v % s_letters_len); ++ v /= s_letters_len; ++ str_append_char(&s_result, c); ++ } ++ if (!access_checker(&s_result)) ++ { ++ /* If we generate a filename which is not allowed, we fail immediatelly, ++ * without trying any other possibilities. This is to prevent attackers ++ * from keeping us busy. ++ */ ++ vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied."); ++ break; ++ } ++ fd = str_create_exclusive(&s_result); ++ if (vsf_sysutil_retval_is_error(fd)) ++ { ++ if (kVSFSysUtilErrEXIST == vsf_sysutil_get_error()) ++ { ++ continue; ++ } ++ else ++ { ++ vsf_cmdio_write(p_sess, FTP_UPLOADFAIL, "Could not create file."); ++ break; ++ } ++ } ++ else ++ { ++ break; ++ } ++ } ++ if (!vsf_sysutil_retval_is_error(fd)) ++ { ++ str_copy(p_outstr, &s_result); ++ } ++ str_free(&s_letters); ++ str_free(&s_result); ++ return fd; ++} ++ + static void + handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique) + { +@@ -1042,41 +1152,56 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique) + return; + } + resolve_tilde(&p_sess->ftp_arg_str, p_sess); +- p_filename = &p_sess->ftp_arg_str; +- if (is_unique) +- { +- get_unique_filename(&s_filename, p_filename); +- p_filename = &s_filename; +- } + vsf_log_start_entry(p_sess, kVSFLogEntryUpload); + str_copy(&p_sess->log_str, &p_sess->ftp_arg_str); + prepend_path_to_filename(&p_sess->log_str); +- if (!vsf_access_check_file(p_filename)) +- { +- vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied."); +- return; +- } +- /* NOTE - actual file permissions will be governed by the tunable umask */ +- /* XXX - do we care about race between create and chown() of anonymous +- * upload? +- */ +- if (is_unique || (p_sess->is_anonymous && !tunable_anon_other_write_enable)) ++ p_filename = &p_sess->ftp_arg_str; ++ if (is_unique && tunable_better_stou) + { +- new_file_fd = str_create_exclusive(p_filename); ++ new_file_fd = create_unique_file(p_sess, &s_filename, p_filename, ++ vsf_access_check_file); ++ if (vsf_sysutil_retval_is_error(new_file_fd)) ++ { ++ return; ++ } ++ p_filename = &s_filename; + } + else + { +- /* For non-anonymous, allow open() to overwrite or append existing files */ +- new_file_fd = str_create(p_filename); +- if (!is_append && offset == 0) ++ if (is_unique) + { +- do_truncate = 1; ++ get_unique_filename(&s_filename, p_filename); ++ p_filename = &s_filename; ++ } ++ if (!vsf_access_check_file(p_filename)) ++ { ++ vsf_cmdio_write(p_sess, FTP_NOPERM, "Permission denied."); ++ return; ++ } ++ /* NOTE - actual file permissions will be governed by the tunable umask */ ++ /* XXX - do we care about race between create and chown() of anonymous ++ * upload? ++ */ ++ if (is_unique || (p_sess->is_anonymous && !tunable_anon_other_write_enable)) ++ { ++ new_file_fd = str_create_exclusive(p_filename); ++ } ++ else ++ { ++ /* For non-anonymous, allow open() to overwrite or append existing ++ * files ++ */ ++ new_file_fd = str_create(p_filename); ++ if (!is_append && offset == 0) ++ { ++ do_truncate = 1; ++ } ++ } ++ if (vsf_sysutil_retval_is_error(new_file_fd)) ++ { ++ vsf_cmdio_write(p_sess, FTP_UPLOADFAIL, "Could not create file."); ++ return; + } +- } +- if (vsf_sysutil_retval_is_error(new_file_fd)) +- { +- vsf_cmdio_write(p_sess, FTP_UPLOADFAIL, "Could not create file."); +- return; + } + created = 1; + vsf_sysutil_fstat(new_file_fd, &s_p_statbuf); +diff --git a/sysutil.c b/sysutil.c +index e97f3bd..e6d88dc 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -1663,6 +1663,9 @@ vsf_sysutil_get_error(void) + case ENOENT: + retval = kVSFSysUtilErrNOENT; + break; ++ case EEXIST: ++ retval = kVSFSysUtilErrEXIST; ++ break; + default: + break; + } +diff --git a/sysutil.h b/sysutil.h +index b745d4a..15d4020 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -18,7 +18,8 @@ enum EVSFSysUtilError + kVSFSysUtilErrINVAL, + kVSFSysUtilErrOPNOTSUPP, + kVSFSysUtilErrACCES, +- kVSFSysUtilErrNOENT ++ kVSFSysUtilErrNOENT, ++ kVSFSysUtilErrEXIST + }; + enum EVSFSysUtilError vsf_sysutil_get_error(void); + +diff --git a/tunables.c b/tunables.c +index 9680528..5ec2bdc 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -92,6 +92,7 @@ int tunable_ftp_enable; + int tunable_http_enable; + int tunable_seccomp_sandbox; + int tunable_allow_writeable_chroot; ++int tunable_better_stou; + + unsigned int tunable_accept_timeout; + unsigned int tunable_connect_timeout; +@@ -239,6 +240,7 @@ tunables_load_defaults() + tunable_http_enable = 0; + tunable_seccomp_sandbox = 0; + tunable_allow_writeable_chroot = 0; ++ tunable_better_stou = 0; + + tunable_accept_timeout = 60; + tunable_connect_timeout = 60; +diff --git a/tunables.h b/tunables.h +index a466427..85ea1a8 100644 +--- a/tunables.h ++++ b/tunables.h +@@ -93,6 +93,9 @@ extern int tunable_ftp_enable; /* Allow FTP protocol */ + extern int tunable_http_enable; /* Allow HTTP protocol */ + extern int tunable_seccomp_sandbox; /* seccomp filter sandbox */ + extern int tunable_allow_writeable_chroot; /* Allow misconfiguration */ ++extern int tunable_better_stou; /* Use better file name generation ++ * algorithm for the STOU command ++ */ + + /* Integer/numeric defines */ + extern unsigned int tunable_accept_timeout; +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 43b0435..e9ae474 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -65,6 +65,16 @@ creates an 'etc' directory in the new root directory, they could potentially + trick the C library into loading a user-created configuration file from the + /etc/ directory. + ++Default: NO ++.TP ++.B better_stou ++Use a better file name generation algorithm for the STOU command. The default ++original algorithm simply adds an increasing number suffix to the file name, ++which is prone to race conditions if multiple uploaders use the STOU command ++with the same file name simultaneously, which can result in failure of the ++command. The new algorithm adds a unique random six character suffix to ++the file name, which works much better in face of concurrent uploads. ++ + Default: NO + .TP + .B anon_mkdir_write_enable +-- +2.14.3 + diff --git a/SOURCES/0001-Document-allow_writeable_chroot-in-the-man-page.patch b/SOURCES/0001-Document-allow_writeable_chroot-in-the-man-page.patch new file mode 100644 index 0000000..e07a0ac --- /dev/null +++ b/SOURCES/0001-Document-allow_writeable_chroot-in-the-man-page.patch @@ -0,0 +1,32 @@ +From 35ec3be5427a54facd5f6299fda2da4c146d4846 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Fri, 24 Nov 2017 11:22:43 +0100 +Subject: [PATCH] Document allow_writeable_chroot in the man page + +--- + vsftpd.conf.5 | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 45b3f9c..d1f0db5 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -56,6 +56,15 @@ Only applies if + is active. If set to YES, anonymous users will be allowed to use secured SSL + connections. + ++Default: NO ++.TP ++.B allow_writeable_chroot ++Allow chroot()'ing a user to a directory writable by that user. Note that ++setting this to YES is potentially dangerous. For example, if the user ++creates an 'etc' directory in the new root directory, they could potentially ++trick the C library into loading a user-created configuration file from the ++/etc/ directory. ++ + Default: NO + .TP + .B anon_mkdir_write_enable +-- +2.14.3 + diff --git a/SOURCES/0001-Document-the-relationship-of-text_userdb_names-and-c.patch b/SOURCES/0001-Document-the-relationship-of-text_userdb_names-and-c.patch new file mode 100644 index 0000000..2f0c21a --- /dev/null +++ b/SOURCES/0001-Document-the-relationship-of-text_userdb_names-and-c.patch @@ -0,0 +1,29 @@ +From 221f35f302d53f5a89f8e79592492e7cb322e81a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Thu, 26 Oct 2017 13:08:32 +0200 +Subject: [PATCH] Document the relationship of text_userdb_names and + chroot_local_user + +Note in vsftpd.conf(5) that text_userdb_names may not work when +chroot_local_user is set to YES. +--- + vsftpd.conf.5 | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index a3d569e..45b3f9c 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -578,6 +578,9 @@ Default: NO + By default, numeric IDs are shown in the user and group fields of directory + listings. You can get textual names by enabling this parameter. It is off + by default for performance reasons. ++Note that textual names are not guaranteed when ++.BR chroot_local_user ++is set to YES. + + Default: NO + .TP +-- +2.14.3 + diff --git a/SOURCES/0001-Fix-rDNS-with-IPv6.patch b/SOURCES/0001-Fix-rDNS-with-IPv6.patch new file mode 100644 index 0000000..f52df92 --- /dev/null +++ b/SOURCES/0001-Fix-rDNS-with-IPv6.patch @@ -0,0 +1,195 @@ +From 01b646d2af0ed885d01d31a6479898a3c423a630 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Thu, 26 Apr 2018 10:00:19 +0200 +Subject: [PATCH] Fix rDNS with IPv6 + +Previously IPv6 addresses were not translated to hostnames for PAM to use. +--- + privops.c | 3 ++- + sysdeputil.c | 28 +++++++++++++++------------- + sysdeputil.h | 5 ++++- + sysutil.c | 35 +++++++++++++++++++++++++++++++++++ + sysutil.h | 4 ++++ + 5 files changed, 60 insertions(+), 15 deletions(-) + +diff --git a/privops.c b/privops.c +index f27c5c4..e577a27 100644 +--- a/privops.c ++++ b/privops.c +@@ -383,7 +383,8 @@ handle_local_login(struct vsf_session* p_sess, + struct mystr* p_user_str, + const struct mystr* p_pass_str) + { +- if (!vsf_sysdep_check_auth(p_user_str, p_pass_str, &p_sess->remote_ip_str)) ++ if (!vsf_sysdep_check_auth(p_sess, p_user_str, p_pass_str, ++ &p_sess->remote_ip_str)) + { + return kVSFLoginFail; + } +diff --git a/sysdeputil.c b/sysdeputil.c +index 2063c87..4fe56c2 100644 +--- a/sysdeputil.c ++++ b/sysdeputil.c +@@ -16,10 +16,6 @@ + #include "tunables.h" + #include "builddefs.h" + +-/* For gethostbyaddr, inet_addr */ +-#include +-#include +- + /* For Linux, this adds nothing :-) */ + #include "port/porting_junk.h" + +@@ -242,13 +238,15 @@ void vsf_remove_uwtmp(void); + + #ifndef VSF_SYSDEP_HAVE_PAM + int +-vsf_sysdep_check_auth(struct mystr* p_user_str, ++vsf_sysdep_check_auth(struct vsf_session* p_sess, ++ struct mystr* p_user_str, + const struct mystr* p_pass_str, + const struct mystr* p_remote_host) + { + const char* p_crypted; + const struct passwd* p_pwd = getpwnam(str_getbuf(p_user_str)); + (void) p_remote_host; ++ (void) p_sess; + if (p_pwd == NULL) + { + return 0; +@@ -322,14 +320,14 @@ static int pam_conv_func(int nmsg, const struct pam_message** p_msg, + static void vsf_auth_shutdown(void); + + int +-vsf_sysdep_check_auth(struct mystr* p_user_str, ++vsf_sysdep_check_auth(struct vsf_session* p_sess, ++ struct mystr* p_user_str, + const struct mystr* p_pass_str, + const struct mystr* p_remote_host) + { + int retval = -1; + #ifdef PAM_RHOST +- struct sockaddr_in sin; +- struct hostent *host; ++ struct mystr hostname = INIT_MYSTR; + #endif + pam_item_t item; + const char* pam_user_name = 0; +@@ -354,13 +352,17 @@ vsf_sysdep_check_auth(struct mystr* p_user_str, + return 0; + } + #ifdef PAM_RHOST +- if (tunable_reverse_lookup_enable) { +- sin.sin_addr.s_addr = inet_addr(str_getbuf(p_remote_host)); +- host = gethostbyaddr((char*)&sin.sin_addr.s_addr,sizeof(struct in_addr),AF_INET); +- if (host != (struct hostent*)0) +- retval = pam_set_item(s_pamh, PAM_RHOST, host->h_name); ++ if (tunable_reverse_lookup_enable) ++ { ++ if (vsf_sysutil_get_hostname(p_sess->p_remote_addr, &hostname) == 0) ++ { ++ retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(&hostname)); ++ str_free(&hostname); ++ } + else ++ { + retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); ++ } + } else { + retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); + } +diff --git a/sysdeputil.h b/sysdeputil.h +index 3b6b30a..6f2aa0a 100644 +--- a/sysdeputil.h ++++ b/sysdeputil.h +@@ -5,6 +5,8 @@ + #include "filesize.h" + #endif + ++#include "session.h" ++ + /* VSF_SYSDEPUTIL_H: + * Support for highly system dependent features, and querying for support + * or lack thereof +@@ -15,7 +17,8 @@ struct mystr; + + /* Authentication of local users */ + /* Return 0 for fail, 1 for success */ +-int vsf_sysdep_check_auth(struct mystr* p_user, ++int vsf_sysdep_check_auth(struct vsf_session* p_sess, ++ struct mystr* p_user, + const struct mystr* p_pass, + const struct mystr* p_remote_host); + +diff --git a/sysutil.c b/sysutil.c +index e847650..b68583b 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -2356,6 +2356,41 @@ vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr** p_sockptr, + } + } + ++int ++vsf_sysutil_get_hostname(struct vsf_sysutil_sockaddr *p_addr, ++ struct mystr* p_str) ++{ ++ struct sockaddr *sa; ++ socklen_t sa_len = 0; ++ char hostname[NI_MAXHOST]; ++ int res; ++ ++ sa = &p_addr->u.u_sockaddr; ++ if (sa->sa_family == AF_INET) ++ { ++ sa_len = sizeof(struct sockaddr_in); ++ } ++ else if (sa->sa_family == AF_INET6) ++ { ++ sa_len = sizeof(struct sockaddr_in6); ++ } ++ else ++ { ++ die("can only support ipv4 and ipv6 currently"); ++ } ++ res = getnameinfo(sa, sa_len, hostname, sizeof(hostname), NULL, 0, ++ NI_NAMEREQD); ++ if (res == 0) ++ { ++ str_alloc_text(p_str, hostname); ++ return 0; ++ } ++ else ++ { ++ return -1; ++ } ++} ++ + struct vsf_sysutil_user* + vsf_sysutil_getpwuid(const unsigned int uid) + { +diff --git a/sysutil.h b/sysutil.h +index 7a59f13..2df14ed 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -7,6 +7,8 @@ + #include "filesize.h" + #endif + ++#include "str.h" ++ + /* Return value queries */ + int vsf_sysutil_retval_is_error(int retval); + enum EVSFSysUtilError +@@ -266,6 +268,8 @@ int vsf_sysutil_connect_timeout(int fd, + unsigned int wait_seconds); + void vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr** p_sockptr, + const char* p_name); ++int vsf_sysutil_get_hostname(struct vsf_sysutil_sockaddr *p_addr, ++ struct mystr* p_str); + /* Option setting on sockets */ + void vsf_sysutil_activate_keepalive(int fd); + void vsf_sysutil_rcvtimeo(int fd); +-- +2.14.3 + diff --git a/SOURCES/0001-Improve-documentation-of-ascii_-options.patch b/SOURCES/0001-Improve-documentation-of-ascii_-options.patch new file mode 100644 index 0000000..7a9e2d7 --- /dev/null +++ b/SOURCES/0001-Improve-documentation-of-ascii_-options.patch @@ -0,0 +1,64 @@ +From a423831f25396c54f92cdfc6f92a104ed77c2ee6 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Fri, 24 Nov 2017 11:26:37 +0100 +Subject: [PATCH] Improve documentation of ascii_* options + +Resolves: rhbz#1517227 +--- + vsftpd.conf | 3 ++- + vsftpd.conf.5 | 20 ++++++++++++++++++++ + 2 files changed, 22 insertions(+), 1 deletion(-) + +diff --git a/vsftpd.conf b/vsftpd.conf +index 39d1955..acbc1e9 100644 +--- a/vsftpd.conf ++++ b/vsftpd.conf +@@ -73,7 +73,8 @@ xferlog_std_format=YES + # + # By default the server will pretend to allow ASCII mode but in fact ignore + # the request. Turn on the below options to have the server actually do ASCII +-# mangling on files when in ASCII mode. ++# mangling on files when in ASCII mode. The vsftpd.conf(5) man page explains ++# the behaviour when these options are disabled. + # Beware that on some FTP servers, ASCII support allows a denial of service + # attack (DoS) via the command "SIZE /big/file" in ASCII mode. vsftpd + # predicted this attack and has always been safe, reporting the size of the +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index d1f0db5..b6ddf05 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -113,11 +113,31 @@ Default: YES + .TP + .B ascii_download_enable + When enabled, ASCII mode data transfers will be honoured on downloads. ++When disabled, the server will pretend to allow ASCII mode but in fact ++ignore requests to activate it. So the client will think the ASCII mode ++is active and therefore may still translate any ++.BR ++character sequences in the received file. See the following article for ++a detailed explanation of the behaviour: ++https://access.redhat.com/articles/3250241. ++ ++Turn this option on to have the server actually do ++ASCII mangling on files when in ASCII mode. + + Default: NO + .TP + .B ascii_upload_enable + When enabled, ASCII mode data transfers will be honoured on uploads. ++When disabled, the server will pretend to allow ASCII mode but in fact ++ignore requests to activate it. So the client will think the ASCII mode ++is active and will translate native line terminators to the standard ++.BR ++line terminators for transmission, but the server will not do ++any translation. See the following article for a detailed explanation ++of the behaviour: https://access.redhat.com/articles/3250241. ++ ++Turn this option on to have the server actually do ++ASCII mangling on files when in ASCII mode. + + Default: NO + .TP +-- +2.14.3 + diff --git a/SOURCES/0001-Log-die-calls-to-syslog.patch b/SOURCES/0001-Log-die-calls-to-syslog.patch new file mode 100644 index 0000000..d6aa2f8 --- /dev/null +++ b/SOURCES/0001-Log-die-calls-to-syslog.patch @@ -0,0 +1,206 @@ +From ee6af258e8cb1a7fada5e6d3e54429b89f12b158 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Fri, 15 Jun 2018 12:02:21 +0200 +Subject: [PATCH 1/3] Log die() calls to syslog + +Pass messages given to die(), die2() and bug() to syslog. Currently this +functionality requires waiting for a short amount of time (1 second is +used) after logging the message and before exiting. This is a workaround +for the following systemd bug: +https://github.com/systemd/systemd/issues/2913 + +The need for this workaround is the main reason why I decided not to +enable this functionality by default. + +Resolves: rhbz#1318198 +Resolves: rhbz#1582672 +--- + logging.c | 13 +++++++++---- + logging.h | 2 ++ + main.c | 4 ++++ + parseconf.c | 1 + + tcpwrap.c | 3 --- + tunables.c | 2 ++ + tunables.h | 2 ++ + utility.c | 11 +++++++++++ + vsftpd.conf.5 | 10 ++++++++++ + 9 files changed, 41 insertions(+), 7 deletions(-) + +diff --git a/logging.c b/logging.c +index c4461f7..9e86808 100644 +--- a/logging.c ++++ b/logging.c +@@ -30,10 +30,6 @@ static void vsf_log_do_log_to_file(int fd, struct mystr* p_str); + void + vsf_log_init(struct vsf_session* p_sess) + { +- if (tunable_syslog_enable || tunable_tcp_wrappers) +- { +- vsf_sysutil_openlog(0); +- } + if (!tunable_xferlog_enable && !tunable_dual_log_enable) + { + return; +@@ -389,3 +385,12 @@ vsf_log_do_log_vsftpd_format(struct vsf_session* p_sess, struct mystr* p_str, + } + } + ++void ++vsf_log_die(const char* p_text) ++{ ++ struct mystr log_str = INIT_MYSTR; ++ ++ str_append_text(&log_str, "ERROR: "); ++ str_append_text(&log_str, p_text); ++ str_syslog(&log_str, 1); ++} +diff --git a/logging.h b/logging.h +index 1ff57d1..75f06c1 100644 +--- a/logging.h ++++ b/logging.h +@@ -91,5 +91,7 @@ void vsf_log_line(struct vsf_session* p_sess, enum EVSFLogEntryType what, + void vsf_log_failed_line(struct vsf_session* p_sess, enum EVSFLogEntryType what, + struct mystr* p_str); + ++void vsf_log_die(const char* p_text); ++ + #endif /* VSF_LOGGING_H */ + +diff --git a/main.c b/main.c +index f039081..1178d44 100644 +--- a/main.c ++++ b/main.c +@@ -120,6 +120,10 @@ main(int argc, const char* argv[]) + } + vsf_sysutil_free(p_statbuf); + } ++ if (tunable_log_die || tunable_syslog_enable || tunable_tcp_wrappers) ++ { ++ vsf_sysutil_openlog(0); ++ } + /* Resolve pasv_address if required */ + if (tunable_pasv_address && tunable_pasv_addr_resolve) + { +diff --git a/parseconf.c b/parseconf.c +index 47b54f1..aeb401a 100644 +--- a/parseconf.c ++++ b/parseconf.c +@@ -112,6 +112,7 @@ parseconf_bool_array[] = + { "seccomp_sandbox", &tunable_seccomp_sandbox }, + { "allow_writeable_chroot", &tunable_allow_writeable_chroot }, + { "better_stou", &tunable_better_stou }, ++ { "log_die", &tunable_log_die }, + { 0, 0 } + }; + +diff --git a/tcpwrap.c b/tcpwrap.c +index 5bf57d3..132b771 100644 +--- a/tcpwrap.c ++++ b/tcpwrap.c +@@ -27,15 +27,12 @@ int + vsf_tcp_wrapper_ok(int remote_fd) + { + struct request_info req; +- vsf_sysutil_openlog(0); + request_init(&req, RQ_DAEMON, "vsftpd", RQ_FILE, remote_fd, 0); + fromhost(&req); + if (!hosts_access(&req)) + { +- vsf_sysutil_closelog(); + return 0; + } +- vsf_sysutil_closelog(); + return 1; + } + +diff --git a/tunables.c b/tunables.c +index 5ec2bdc..63de8e6 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -93,6 +93,7 @@ int tunable_http_enable; + int tunable_seccomp_sandbox; + int tunable_allow_writeable_chroot; + int tunable_better_stou; ++int tunable_log_die; + + unsigned int tunable_accept_timeout; + unsigned int tunable_connect_timeout; +@@ -241,6 +242,7 @@ tunables_load_defaults() + tunable_seccomp_sandbox = 0; + tunable_allow_writeable_chroot = 0; + tunable_better_stou = 0; ++ tunable_log_die = 0; + + tunable_accept_timeout = 60; + tunable_connect_timeout = 60; +diff --git a/tunables.h b/tunables.h +index 85ea1a8..8a4b8b2 100644 +--- a/tunables.h ++++ b/tunables.h +@@ -96,6 +96,8 @@ extern int tunable_allow_writeable_chroot; /* Allow misconfiguration */ + extern int tunable_better_stou; /* Use better file name generation + * algorithm for the STOU command + */ ++extern int tunable_log_die; /* Log calls to die(), die2() ++ * and bug() */ + + /* Integer/numeric defines */ + extern unsigned int tunable_accept_timeout; +diff --git a/utility.c b/utility.c +index 5fd714d..75e5bdd 100644 +--- a/utility.c ++++ b/utility.c +@@ -9,6 +9,8 @@ + #include "sysutil.h" + #include "str.h" + #include "defs.h" ++#include "logging.h" ++#include "tunables.h" + + #define DIE_DEBUG + +@@ -41,11 +43,20 @@ void + bug(const char* p_text) + { + /* Rats. Try and write the reason to the network for diagnostics */ ++ if (tunable_log_die) ++ { ++ vsf_log_die(p_text); ++ } + vsf_sysutil_activate_noblock(VSFTP_COMMAND_FD); + (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, "500 OOPS: ", 10); + (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, p_text, + vsf_sysutil_strlen(p_text)); + (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, "\r\n", 2); ++ if (tunable_log_die) ++ { ++ /* Workaround for https://github.com/systemd/systemd/issues/2913 */ ++ vsf_sysutil_sleep(1.0); ++ } + vsf_sysutil_exit(2); + } + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index e9ae474..f246906 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -358,6 +358,16 @@ wanting to e.g. append a file. + + Default: YES + .TP ++.B log_die ++Log an error to syslog when some error condition occurs and vsftpd decides ++to quit. Internally, the error messages given to the functions die(), die2() ++and bug() are passed to syslog. Currently this functionality requires waiting ++for a short amount of time (1 second is used) after logging the message and ++before exiting. This is a workaround for the following systemd bug: ++https://github.com/systemd/systemd/issues/2913 ++ ++Default: NO ++.TP + .B log_ftp_protocol + When enabled, all FTP requests and responses are logged, providing the option + xferlog_std_format is not enabled. Useful for debugging. +-- +2.14.4 + diff --git a/SOURCES/0001-Move-closing-standard-FDs-after-listen.patch b/SOURCES/0001-Move-closing-standard-FDs-after-listen.patch new file mode 100644 index 0000000..12511e7 --- /dev/null +++ b/SOURCES/0001-Move-closing-standard-FDs-after-listen.patch @@ -0,0 +1,46 @@ +From 40fea4552377504ce69935149e64e39a595f4600 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Sat, 3 Aug 2019 17:50:14 +0200 +Subject: [PATCH 1/2] Move closing standard FDs after listen() + +The vsf_sysutil_close() calls need to be moved a bit further so that +die() works properly in case listen() fails. + +I see no reason the calls should be placed before listen() +specifically, as they are now. My guess is that the author who added +the calls thought that listen() is a blocking call, which is not the +case. The only thing we need to satisfy is that close() is called +before accept, because that is a blocking call. That's all that is +needed to fix the bug that was fixed by adding the close() calls. + +Resolves: rhbz#1666380 +--- + standalone.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/standalone.c b/standalone.c +index 3f35e9e..b358ca1 100644 +--- a/standalone.c ++++ b/standalone.c +@@ -152,15 +152,15 @@ vsf_standalone_main(void) + vsf_sysutil_kill(vsf_sysutil_getppid(), kVSFSysUtilSigUSR1); + } + } +- vsf_sysutil_close(0); +- vsf_sysutil_close(1); +- vsf_sysutil_close(2); + retval = vsf_sysutil_listen(listen_sock, VSFTP_LISTEN_BACKLOG); + if (vsf_sysutil_retval_is_error(retval)) + { + die("could not listen"); + } + vsf_sysutil_sockaddr_alloc(&p_accept_addr); ++ vsf_sysutil_close(0); ++ vsf_sysutil_close(1); ++ vsf_sysutil_close(2); + while (1) + { + struct vsf_client_launch child_info; +-- +2.20.1 + diff --git a/SOURCES/0001-Redefine-VSFTP_COMMAND_FD-to-1.patch b/SOURCES/0001-Redefine-VSFTP_COMMAND_FD-to-1.patch new file mode 100644 index 0000000..f1003e8 --- /dev/null +++ b/SOURCES/0001-Redefine-VSFTP_COMMAND_FD-to-1.patch @@ -0,0 +1,29 @@ +From 18e0ab25a0d66088728b506cf64f5545637eda26 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 5 Sep 2017 14:26:08 +0200 +Subject: [PATCH] Redefine VSFTP_COMMAND_FD to 1 + +Redefine VSFTP_COMMAND_FD to 1 (stdout) so that error messages generated +during startup are picked up by systemd. + +Resolves: rhbz#1443055 +--- + defs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/defs.h b/defs.h +index bde3232..315f0f0 100644 +--- a/defs.h ++++ b/defs.h +@@ -3,7 +3,7 @@ + + #define VSFTP_DEFAULT_CONFIG "/etc/vsftpd/vsftpd.conf" + +-#define VSFTP_COMMAND_FD 0 ++#define VSFTP_COMMAND_FD 1 + + #define VSFTP_PASSWORD_MAX 128 + #define VSFTP_USERNAME_MAX 128 +-- +2.14.3 + diff --git a/SOURCES/0001-Set-s_uwtmp_inserted-only-after-record-insertion-rem.patch b/SOURCES/0001-Set-s_uwtmp_inserted-only-after-record-insertion-rem.patch new file mode 100644 index 0000000..00bf82c --- /dev/null +++ b/SOURCES/0001-Set-s_uwtmp_inserted-only-after-record-insertion-rem.patch @@ -0,0 +1,53 @@ +From 96698a525784ad91cb27b572dd5f871c183fdfa5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Sun, 28 Jul 2019 12:25:35 +0200 +Subject: [PATCH 1/2] Set s_uwtmp_inserted only after record insertion/removal + +pututxline() is the function that actually inserts the new record, so +setting 's_uwtmp_inserted' before calling pututxline() doesn't make +sense. + +We'll need this change for other fixes. +--- + sysdeputil.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sysdeputil.c b/sysdeputil.c +index 4fe56c2..bd1e8c9 100644 +--- a/sysdeputil.c ++++ b/sysdeputil.c +@@ -1224,7 +1224,6 @@ vsf_insert_uwtmp(const struct mystr* p_user_str, + sizeof(s_utent.ut_line)); + str_free(&line_str); + } +- s_uwtmp_inserted = 1; + s_utent.ut_type = USER_PROCESS; + s_utent.ut_pid = vsf_sysutil_getpid(); + vsf_sysutil_strcpy(s_utent.ut_user, str_getbuf(p_user_str), +@@ -1235,6 +1234,7 @@ vsf_insert_uwtmp(const struct mystr* p_user_str, + setutxent(); + (void) pututxline(&s_utent); + endutxent(); ++ s_uwtmp_inserted = 1; + updwtmpx(WTMPX_FILE, &s_utent); + } + +@@ -1245,7 +1245,6 @@ vsf_remove_uwtmp(void) + { + return; + } +- s_uwtmp_inserted = 0; + s_utent.ut_type = DEAD_PROCESS; + vsf_sysutil_memclr(s_utent.ut_user, sizeof(s_utent.ut_user)); + vsf_sysutil_memclr(s_utent.ut_host, sizeof(s_utent.ut_host)); +@@ -1253,6 +1252,7 @@ vsf_remove_uwtmp(void) + setutxent(); + (void) pututxline(&s_utent); + endutxent(); ++ s_uwtmp_inserted = 0; + s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec(); + updwtmpx(WTMPX_FILE, &s_utent); + } +-- +2.20.1 + diff --git a/SOURCES/0002-Improve-error-message-when-max-number-of-bind-attemp.patch b/SOURCES/0002-Improve-error-message-when-max-number-of-bind-attemp.patch new file mode 100644 index 0000000..221a2de --- /dev/null +++ b/SOURCES/0002-Improve-error-message-when-max-number-of-bind-attemp.patch @@ -0,0 +1,27 @@ +From 380e40930661d643c865bace4e1791ca8f9d74cf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Mon, 18 Jun 2018 14:01:46 +0200 +Subject: [PATCH 2/3] Improve error message when max number of bind attempts is + exceeded + +Resolves: rhbz#1318198 +--- + privops.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/privops.c b/privops.c +index e577a27..010d28d 100644 +--- a/privops.c ++++ b/privops.c +@@ -183,7 +183,7 @@ vsf_privop_pasv_listen(struct vsf_session* p_sess) + } + if (!bind_retries) + { +- die("vsf_sysutil_bind"); ++ die("vsf_sysutil_bind, maximum number of attempts to find a listening port exceeded"); + } + return the_port; + } +-- +2.14.4 + diff --git a/SOURCES/0002-Prevent-recursion-in-bug.patch b/SOURCES/0002-Prevent-recursion-in-bug.patch new file mode 100644 index 0000000..061fd1e --- /dev/null +++ b/SOURCES/0002-Prevent-recursion-in-bug.patch @@ -0,0 +1,107 @@ +From e679a3ce0f2cf1558da31e0bccd9e2398b89c7e9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 30 Jul 2019 16:07:01 +0200 +Subject: [PATCH 2/2] Prevent recursion in bug() + +Resolves: rhbz#1666380 +--- + sysutil.c | 35 +++++++++++++++++++++++++++++++---- + sysutil.h | 1 + + utility.c | 12 +++++++----- + 3 files changed, 39 insertions(+), 9 deletions(-) + +diff --git a/sysutil.c b/sysutil.c +index fd07d99..e2df671 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -774,21 +774,48 @@ vsf_sysutil_deactivate_linger_failok(int fd) + (void) setsockopt(fd, SOL_SOCKET, SO_LINGER, &the_linger, sizeof(the_linger)); + } + +-void +-vsf_sysutil_activate_noblock(int fd) ++static int ++vsf_sysutil_activate_noblock_internal(int fd, int return_err) + { + int retval; + int curr_flags = fcntl(fd, F_GETFL); + if (vsf_sysutil_retval_is_error(curr_flags)) + { +- die("fcntl"); ++ if (return_err) ++ { ++ return -1; ++ } ++ else ++ { ++ die("fcntl"); ++ } + } + curr_flags |= O_NONBLOCK; + retval = fcntl(fd, F_SETFL, curr_flags); + if (retval != 0) + { +- die("fcntl"); ++ if (return_err) ++ { ++ return -1; ++ } ++ else ++ { ++ die("fcntl"); ++ } + } ++ return 0; ++} ++ ++void ++vsf_sysutil_activate_noblock(int fd) ++{ ++ (void) vsf_sysutil_activate_noblock_internal(fd, 0); ++} ++ ++int ++vsf_sysutil_activate_noblock_no_die(int fd) ++{ ++ return vsf_sysutil_activate_noblock_internal(fd, 1); + } + + void +diff --git a/sysutil.h b/sysutil.h +index 2df14ed..0772423 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -281,6 +281,7 @@ void vsf_sysutil_activate_oobinline(int fd); + void vsf_sysutil_activate_linger(int fd); + void vsf_sysutil_deactivate_linger_failok(int fd); + void vsf_sysutil_activate_noblock(int fd); ++int vsf_sysutil_activate_noblock_no_die(int fd); + void vsf_sysutil_deactivate_noblock(int fd); + /* This does SHUT_RDWR */ + void vsf_sysutil_shutdown_failok(int fd); +diff --git a/utility.c b/utility.c +index 75e5bdd..5619a04 100644 +--- a/utility.c ++++ b/utility.c +@@ -47,11 +47,13 @@ bug(const char* p_text) + { + vsf_log_die(p_text); + } +- vsf_sysutil_activate_noblock(VSFTP_COMMAND_FD); +- (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, "500 OOPS: ", 10); +- (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, p_text, +- vsf_sysutil_strlen(p_text)); +- (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, "\r\n", 2); ++ if (vsf_sysutil_activate_noblock_no_die(VSFTP_COMMAND_FD) == 0) ++ { ++ (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, "500 OOPS: ", 10); ++ (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, p_text, ++ vsf_sysutil_strlen(p_text)); ++ (void) vsf_sysutil_write_loop(VSFTP_COMMAND_FD, "\r\n", 2); ++ } + if (tunable_log_die) + { + /* Workaround for https://github.com/systemd/systemd/issues/2913 */ +-- +2.20.1 + diff --git a/SOURCES/0002-Repeat-pututxline-if-it-fails-with-EINTR.patch b/SOURCES/0002-Repeat-pututxline-if-it-fails-with-EINTR.patch new file mode 100644 index 0000000..e89efcf --- /dev/null +++ b/SOURCES/0002-Repeat-pututxline-if-it-fails-with-EINTR.patch @@ -0,0 +1,105 @@ +From 896b3694ca062d747cd67e9e9ba246adb3fc706b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Mon, 5 Aug 2019 13:55:37 +0200 +Subject: [PATCH 2/2] Repeat pututxline() if it fails with EINTR + +This is a partial fix for rhbz#1688848. We cannot resolve it +completely until glibc bug rhbz#1734791 is fixed. See +https://bugzilla.redhat.com/show_bug.cgi?id=1688848#c13. + +The maximum number of attempts is currently 2, which might seem +low. However setting it to 2 was a decision based on data - see +https://bugzilla.redhat.com/show_bug.cgi?id=1688848#c16. + +Resolves: rhbz#1688848 +--- + sysdeputil.c | 53 +++++++++++++++++++++++++++++++++++++++++++++------- + 1 file changed, 46 insertions(+), 7 deletions(-) + +diff --git a/sysdeputil.c b/sysdeputil.c +index bd1e8c9..4fbcca7 100644 +--- a/sysdeputil.c ++++ b/sysdeputil.c +@@ -1203,6 +1203,8 @@ void + vsf_insert_uwtmp(const struct mystr* p_user_str, + const struct mystr* p_host_str) + { ++ int attempts; ++ + if (sizeof(s_utent.ut_line) < 16) + { + return; +@@ -1231,16 +1233,35 @@ vsf_insert_uwtmp(const struct mystr* p_user_str, + vsf_sysutil_strcpy(s_utent.ut_host, str_getbuf(p_host_str), + sizeof(s_utent.ut_host)); + s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec(); +- setutxent(); +- (void) pututxline(&s_utent); +- endutxent(); +- s_uwtmp_inserted = 1; ++ for (attempts = 2; attempts > 0; --attempts) ++ { ++ struct utmpx* p_res; ++ setutxent(); ++ p_res = pututxline(&s_utent); ++ /* For now we'll ignore errors other than EINTR and EAGAIN */ ++ if (p_res != NULL || (errno != EINTR && errno != EAGAIN)) ++ { ++ break; ++ } ++ } ++ if (attempts == 0) ++ { ++ /* This makes us skip pututxline() in vsf_remove_uwtmp() */ ++ s_uwtmp_inserted = -1; ++ } ++ else ++ { ++ s_uwtmp_inserted = 1; ++ endutxent(); ++ } + updwtmpx(WTMPX_FILE, &s_utent); + } + + void + vsf_remove_uwtmp(void) + { ++ int attempts; ++ + if (!s_uwtmp_inserted) + { + return; +@@ -1249,9 +1270,27 @@ vsf_remove_uwtmp(void) + vsf_sysutil_memclr(s_utent.ut_user, sizeof(s_utent.ut_user)); + vsf_sysutil_memclr(s_utent.ut_host, sizeof(s_utent.ut_host)); + s_utent.ut_tv.tv_sec = 0; +- setutxent(); +- (void) pututxline(&s_utent); +- endutxent(); ++ if (s_uwtmp_inserted == 1) ++ { ++ for (attempts = 2; attempts > 0; --attempts) ++ { ++ struct utmpx* p_res; ++ setutxent(); ++ p_res = pututxline(&s_utent); ++ /* For now we'll ignore errors other than EINTR and EAGAIN */ ++ if (p_res != NULL || (errno != EINTR && errno != EAGAIN)) ++ { ++ break; ++ } ++ } ++ if (attempts != 0) ++ { ++ endutxent(); ++ } ++ } ++ /* Set s_uwtmp_inserted to 0 regardless of the result of ++ * pututxline() to make sure we won't run this function twice. ++ */ + s_uwtmp_inserted = 0; + s_utent.ut_tv.tv_sec = vsf_sysutil_get_time_sec(); + updwtmpx(WTMPX_FILE, &s_utent); +-- +2.20.1 + diff --git a/SOURCES/0003-Make-the-max-number-of-bind-retries-tunable.patch b/SOURCES/0003-Make-the-max-number-of-bind-retries-tunable.patch new file mode 100644 index 0000000..533bd29 --- /dev/null +++ b/SOURCES/0003-Make-the-max-number-of-bind-retries-tunable.patch @@ -0,0 +1,103 @@ +From be7c2d639127dd8af0139caf94f8c29f431d3753 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Mon, 18 Jun 2018 10:13:48 +0200 +Subject: [PATCH 3/3] Make the max number of bind retries tunable + +Resolves: rhbz#1318198 +--- + parseconf.c | 1 + + privops.c | 8 ++++++-- + tunables.c | 2 ++ + tunables.h | 1 + + vsftpd.conf.5 | 5 +++++ + 5 files changed, 15 insertions(+), 2 deletions(-) + +diff --git a/parseconf.c b/parseconf.c +index aeb401a..3cfe7da 100644 +--- a/parseconf.c ++++ b/parseconf.c +@@ -143,6 +143,7 @@ parseconf_uint_array[] = + { "delay_successful_login", &tunable_delay_successful_login }, + { "max_login_fails", &tunable_max_login_fails }, + { "chown_upload_mode", &tunable_chown_upload_mode }, ++ { "bind_retries", &tunable_bind_retries }, + { 0, 0 } + }; + +diff --git a/privops.c b/privops.c +index 010d28d..83b25c7 100644 +--- a/privops.c ++++ b/privops.c +@@ -120,8 +120,8 @@ unsigned short + vsf_privop_pasv_listen(struct vsf_session* p_sess) + { + static struct vsf_sysutil_sockaddr* s_p_sockaddr; +- int bind_retries = 10; +- unsigned short the_port; ++ int bind_retries = tunable_bind_retries + 1; ++ unsigned short the_port = 0; + /* IPPORT_RESERVED */ + unsigned short min_port = 1024; + unsigned short max_port = 65535; +@@ -131,6 +131,10 @@ vsf_privop_pasv_listen(struct vsf_session* p_sess) + die("listed fd already active"); + } + ++ if (bind_retries < 2) ++ { ++ bind_retries = 2; ++ } + if (tunable_pasv_min_port > min_port && tunable_pasv_min_port <= max_port) + { + min_port = (unsigned short) tunable_pasv_min_port; +diff --git a/tunables.c b/tunables.c +index 63de8e6..a7ce9c8 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -115,6 +115,7 @@ unsigned int tunable_delay_failed_login; + unsigned int tunable_delay_successful_login; + unsigned int tunable_max_login_fails; + unsigned int tunable_chown_upload_mode; ++unsigned int tunable_bind_retries; + + const char* tunable_secure_chroot_dir; + const char* tunable_ftp_username; +@@ -268,6 +269,7 @@ tunables_load_defaults() + tunable_max_login_fails = 3; + /* -rw------- */ + tunable_chown_upload_mode = 0600; ++ tunable_bind_retries = 9; + + install_str_setting("/usr/share/empty", &tunable_secure_chroot_dir); + install_str_setting("ftp", &tunable_ftp_username); +diff --git a/tunables.h b/tunables.h +index 8a4b8b2..029d645 100644 +--- a/tunables.h ++++ b/tunables.h +@@ -120,6 +120,7 @@ extern unsigned int tunable_delay_failed_login; + extern unsigned int tunable_delay_successful_login; + extern unsigned int tunable_max_login_fails; + extern unsigned int tunable_chown_upload_mode; ++extern unsigned int tunable_bind_retries; + + /* String defines */ + extern const char* tunable_secure_chroot_dir; +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index f246906..ce3fba3 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -760,6 +760,11 @@ value will be treated as a base 10 integer! + + Default: 077 + .TP ++.B bind_retries ++Maximum number of attempts to find a free listening port in passive mode. ++ ++Default: 9 ++.TP + .B chown_upload_mode + The file mode to force for chown()ed anonymous uploads. (Added in v2.0.6). + +-- +2.14.4 + diff --git a/SOURCES/vsftpd-2.0.5-fix_qm.patch b/SOURCES/vsftpd-2.0.5-fix_qm.patch new file mode 100644 index 0000000..00f7358 --- /dev/null +++ b/SOURCES/vsftpd-2.0.5-fix_qm.patch @@ -0,0 +1,13 @@ +diff -up vsftpd-2.0.5/ls.c.fix_qm vsftpd-2.0.5/ls.c +--- vsftpd-2.0.5/ls.c.fix_qm 2012-03-02 12:59:01.303249397 +0100 ++++ vsftpd-2.0.5/ls.c 2012-03-02 13:00:03.792145117 +0100 +@@ -454,7 +454,8 @@ vsf_filename_passes_filter(const struct + must_match_at_current_pos = 0; + } + } while (locate_result.found && +- str_getlen(&name_remain_str) > 0 && last_token != '*'); ++ str_getlen(&name_remain_str) > 0 && ++ last_token != '*' && last_token != '?'); + } + /* Any incoming string left means no match unless we ended on the correct + * type of wildcard. diff --git a/SOURCES/vsftpd-2.1.0-build_ssl.patch b/SOURCES/vsftpd-2.1.0-build_ssl.patch new file mode 100644 index 0000000..e2ca633 --- /dev/null +++ b/SOURCES/vsftpd-2.1.0-build_ssl.patch @@ -0,0 +1,12 @@ +diff -up vsftpd-2.1.0/builddefs.h.build_ssl vsftpd-2.1.0/builddefs.h +--- vsftpd-2.1.0/builddefs.h.build_ssl 2009-01-08 18:49:33.000000000 +0100 ++++ vsftpd-2.1.0/builddefs.h 2009-01-08 18:49:41.000000000 +0100 +@@ -3,7 +3,7 @@ + + #undef VSF_BUILD_TCPWRAPPERS + #define VSF_BUILD_PAM +-#undef VSF_BUILD_SSL ++#define VSF_BUILD_SSL + + #endif /* VSF_BUILDDEFS_H */ + diff --git a/SOURCES/vsftpd-2.1.0-configuration.patch b/SOURCES/vsftpd-2.1.0-configuration.patch new file mode 100644 index 0000000..5f04dea --- /dev/null +++ b/SOURCES/vsftpd-2.1.0-configuration.patch @@ -0,0 +1,447 @@ +diff -up vsftpd-2.2.0/defs.h.configuration vsftpd-2.2.0/defs.h +--- vsftpd-2.2.0/defs.h.configuration 2009-01-07 21:22:22.000000000 +0100 ++++ vsftpd-2.2.0/defs.h 2009-08-04 07:37:01.000000000 +0200 +@@ -1,7 +1,7 @@ + #ifndef VSF_DEFS_H + #define VSF_DEFS_H + +-#define VSFTP_DEFAULT_CONFIG "/etc/vsftpd.conf" ++#define VSFTP_DEFAULT_CONFIG "/etc/vsftpd/vsftpd.conf" + + #define VSFTP_COMMAND_FD 0 + +diff -up vsftpd-2.2.0/EXAMPLE/INTERNET_SITE_NOINETD/README.configuration vsftpd-2.2.0/EXAMPLE/INTERNET_SITE_NOINETD/README +--- vsftpd-2.2.0/EXAMPLE/INTERNET_SITE_NOINETD/README.configuration 2008-02-02 02:30:40.000000000 +0100 ++++ vsftpd-2.2.0/EXAMPLE/INTERNET_SITE_NOINETD/README 2009-08-04 07:37:01.000000000 +0200 +@@ -17,7 +17,7 @@ even per-connect-IP configurability. + + To use this example config: + +-1) Copy the vsftpd.conf file in this directory to /etc/vsftpd.conf. ++1) Copy the vsftpd.conf file in this directory to /etc/vsftpd/vsftpd.conf. + + 2) Start up vsftpd, e.g. + vsftpd & +@@ -51,5 +51,5 @@ in the vsftpd.conf: + listen_address=192.168.1.2 + + And launch vsftpd with a specific config file like this: +-vsftpd /etc/vsftpd.conf.site1 & ++vsftpd /etc/vsftpd/vsftpd.conf.site1 & + +diff -up vsftpd-2.2.0/EXAMPLE/INTERNET_SITE/README.configuration vsftpd-2.2.0/EXAMPLE/INTERNET_SITE/README +--- vsftpd-2.2.0/EXAMPLE/INTERNET_SITE/README.configuration 2008-02-02 02:30:40.000000000 +0100 ++++ vsftpd-2.2.0/EXAMPLE/INTERNET_SITE/README 2009-08-04 07:37:01.000000000 +0200 +@@ -41,13 +41,13 @@ no_access = 192.168.1.3 + As an example of how to ban certain sites from connecting, 192.168.1.3 will + be denied access. + +-banner_fail = /etc/vsftpd.busy_banner ++banner_fail = /etc/vsftpd/busy_banner + + This is the file to display to users if the connection is refused for whatever + reason (too many users, IP banned). + + Example of how to populate it: +-echo "421 Server busy, please try later." > /etc/vsftpd.busy_banner ++echo "421 Server busy, please try later." > /etc/vsftpd/busy_banner + + log_on_success += PID HOST DURATION + log_on_failure += HOST +@@ -62,7 +62,7 @@ Step 2) Set up your vsftpd configuration + + An example file is supplied. Install it like this: + +-cp vsftpd.conf /etc ++cp vsftpd.conf /etc/vsftpd + + Let's example the contents of the file: + +diff -up vsftpd-2.2.0/EXAMPLE/PER_IP_CONFIG/README.configuration vsftpd-2.2.0/EXAMPLE/PER_IP_CONFIG/README +--- vsftpd-2.2.0/EXAMPLE/PER_IP_CONFIG/README.configuration 2008-02-02 02:30:40.000000000 +0100 ++++ vsftpd-2.2.0/EXAMPLE/PER_IP_CONFIG/README 2009-08-04 07:37:01.000000000 +0200 +@@ -20,12 +20,12 @@ directory: hosts.allow. It lives at /etc + + Let's have a look at the example: + +-vsftpd: 192.168.1.3: setenv VSFTPD_LOAD_CONF /etc/vsftpd_tcp_wrap.conf ++vsftpd: 192.168.1.3: setenv VSFTPD_LOAD_CONF /etc/vsftpd/tcp_wrap.conf + vsftpd: 192.168.1.4: DENY + + The first line: + If a client connects from 192.168.1.3, then vsftpd will apply the vsftpd +-config file /etc/vsftpd_tcp_wrap.conf to the session! These settings are ++config file /etc/vsftpd/tcp_wrap.conf to the session! These settings are + applied ON TOP of the default vsftpd.conf. + This is obviously very powerful. You might use this to apply different + access restrictions for some IPs (e.g. the ability to upload). +diff -up vsftpd-2.2.0/EXAMPLE/VIRTUAL_USERS/README.configuration vsftpd-2.2.0/EXAMPLE/VIRTUAL_USERS/README +--- vsftpd-2.2.0/EXAMPLE/VIRTUAL_USERS/README.configuration 2008-02-02 02:30:40.000000000 +0100 ++++ vsftpd-2.2.0/EXAMPLE/VIRTUAL_USERS/README 2009-08-04 07:37:01.000000000 +0200 +@@ -15,7 +15,7 @@ See example file "logins.txt" - this spe + "fred" with password "bar". + Whilst logged in as root, create the actual database file like this: + +-db_load -T -t hash -f logins.txt /etc/vsftpd_login.db ++db_load -T -t hash -f logins.txt /etc/vsftpd/login.db + (Requires the Berkeley db program installed). + NOTE: Many systems have multiple versions of "db" installed, so you may + need to use e.g. db3_load for correct operation. This is known to affect +@@ -23,10 +23,10 @@ some Debian systems. The core issue is t + database to be a specific db version (often db3, whereas db4 may be installed + on your system). + +-This will create /etc/vsftpd_login.db. Obviously, you may want to make sure ++This will create /etc/vsftpd/login.db. Obviously, you may want to make sure + the permissions are restricted: + +-chmod 600 /etc/vsftpd_login.db ++chmod 600 /etc/vsftpd/login.db + + For more information on maintaing your login database, look around for + documentation on "Berkeley DB", e.g. +@@ -37,8 +37,8 @@ Step 2) Create a PAM file which uses you + + See the example file vsftpd.pam. It contains two lines: + +-auth required /lib/security/pam_userdb.so db=/etc/vsftpd_login +-account required /lib/security/pam_userdb.so db=/etc/vsftpd_login ++auth required /lib/security/pam_userdb.so db=/etc/vsftpd/login ++account required /lib/security/pam_userdb.so db=/etc/vsftpd/login + + This tells PAM to authenticate users using our new database. Copy this PAM + file to the PAM directory - typically /etc/pam.d/ +@@ -108,9 +108,9 @@ pasv_max_port=30999 + These put a port range on passive FTP incoming requests - very useful if + you are configuring a firewall. + +-Copy the example vsftpd.conf file to /etc: ++Copy the example vsftpd.conf file to /etc/vsftpd: + +-cp vsftpd.conf /etc/ ++cp vsftpd.conf /etc/vsftpd/ + + + Step 5) Start up vsftpd. +diff -up vsftpd-2.2.0/FAQ.configuration vsftpd-2.2.0/FAQ +--- vsftpd-2.2.0/FAQ.configuration 2009-02-18 23:33:04.000000000 +0100 ++++ vsftpd-2.2.0/FAQ 2009-08-04 07:37:01.000000000 +0200 +@@ -34,7 +34,7 @@ needs this user to run bits of itself wi + Q) Help! Local users cannot log in. + A) There are various possible problems. + A1) By default, vsftpd disables any logins other than anonymous logins. Put +-local_enable=YES in your /etc/vsftpd.conf to allow local users to log in. ++local_enable=YES in your /etc/vsftpd/vsftpd.conf to allow local users to log in. + A2) vsftpd tries to link with PAM. (Run "ldd vsftpd" and look for libpam to + find out whether this has happened or not). If vsftpd links with PAM, then + you will need to have a PAM file installed for the vsftpd service. There is +@@ -46,12 +46,12 @@ system have a "shadow.h" file in the inc + A4) If you are not using PAM, then vsftpd will do its own check for a valid + user shell in /etc/shells. You may need to disable this if you use an invalid + shell to disable logins other than FTP logins. Put check_shell=NO in your +-/etc/vsftpd.conf. ++/etc/vsftpd/vsftpd.conf. + + Q) Help! Uploads or other write commands give me "500 Unknown command.". + A) By default, write commands, including uploads and new directories, are + disabled. This is a security measure. To enable writes, put write_enable=YES +-in your /etc/vsftpd.conf. ++in your /etc/vsftpd/vsftpd.conf. + + Q) Help! What are the security implications referred to in the + "chroot_local_user" option? +@@ -87,7 +87,7 @@ A2) Alternatively, run as many copies as + mode. Use "listen_address=x.x.x.x" to set the virtual IP. + + Q) Help! Does vsftpd support virtual users? +-A) Yes, via PAM integration. Set "guest_enable=YES" in /etc/vsftpd.conf. This ++A) Yes, via PAM integration. Set "guest_enable=YES" in /etc/vsftpd/vsftpd.conf. This + has the effect of mapping every non-anonymous successful login to the local + username specified in "guest_username". Then, use PAM and (e.g.) its pam_userdb + module to provide authentication against an external (i.e. non-/etc/passwd) +diff -up vsftpd-2.2.0/INSTALL.configuration vsftpd-2.2.0/INSTALL +--- vsftpd-2.2.0/INSTALL.configuration 2008-02-02 02:30:39.000000000 +0100 ++++ vsftpd-2.2.0/INSTALL 2009-08-04 07:37:01.000000000 +0200 +@@ -56,14 +56,14 @@ cp vsftpd.8 /usr/local/man/man8 + + "make install" doesn't copy the sample config file. It is recommended you + do this: +-cp vsftpd.conf /etc ++cp vsftpd.conf /etc/vsftpd + + Step 4) Smoke test (without an inetd). + + vsftpd can run standalone or via an inetd (such as inetd or xinetd). You will + typically get more control running vsftpd from an inetd. But first we will run + it without, so we can check things are going well so far. +-Edit /etc/vsftpd.conf, and add this line at the bottom: ++Edit /etc/vsftpd/vsftpd.conf, and add this line at the bottom: + + listen=YES + +@@ -135,11 +135,11 @@ cp RedHat/vsftpd.pam /etc/pam.d/ftp + Step 7) Customize your configuration + + As well as the above three pre-requisites, you are recommended to install a +-config file. The default location for the config file is /etc/vsftpd.conf. ++config file. The default location for the config file is /etc/vsftpd/vsftpd.conf. + There is a sample vsftpd.conf in the distribution tarball. You probably want +-to copy that to /etc/vsftpd.conf as a basis for modification, i.e.: ++to copy that to /etc/vsftpd/vsftpd.conf as a basis for modification, i.e.: + +-cp vsftpd.conf /etc ++cp vsftpd.conf /etc/vsftpd + + The default configuration allows neither local user logins nor anonymous + uploads. You may wish to change these defaults. +diff -up vsftpd-2.2.0/README.configuration vsftpd-2.2.0/README +--- vsftpd-2.2.0/README.configuration 2009-07-07 22:23:22.000000000 +0200 ++++ vsftpd-2.2.0/README 2009-08-04 07:37:01.000000000 +0200 +@@ -37,3 +37,8 @@ All configuration options are documented + Various example configurations are discussed in the EXAMPLE directory. + Frequently asked questions are tackled in the FAQ file. + ++Important Note ++============== ++The location of configuration files was changed to /etc/vsftpd/. If you want ++to migrate your old conf files from /etc (files vsftpd.xxxx.rpmsave) use ++/etc/vsfptd/vsftpd_conf_migrate.sh +diff -up vsftpd-2.2.0/tunables.c.configuration vsftpd-2.2.0/tunables.c +--- vsftpd-2.2.0/tunables.c.configuration 2009-07-15 22:08:27.000000000 +0200 ++++ vsftpd-2.2.0/tunables.c 2009-08-04 07:37:01.000000000 +0200 +@@ -186,7 +186,7 @@ tunables_load_defaults() + tunable_listen_ipv6 = 0; + tunable_dual_log_enable = 0; + tunable_syslog_enable = 0; +- tunable_background = 0; ++ tunable_background = 1; + tunable_virtual_use_local_privs = 0; + tunable_session_support = 0; + tunable_download_enable = 1; +@@ -254,11 +254,11 @@ tunables_load_defaults() + install_str_setting(".message", &tunable_message_file); + install_str_setting("nobody", &tunable_nopriv_user); + install_str_setting(0, &tunable_ftpd_banner); +- install_str_setting("/etc/vsftpd.banned_emails", &tunable_banned_email_file); +- install_str_setting("/etc/vsftpd.chroot_list", &tunable_chroot_list_file); ++ install_str_setting("/etc/vsftpd/banned_emails", &tunable_banned_email_file); ++ install_str_setting("/etc/vsftpd/chroot_list", &tunable_chroot_list_file); + install_str_setting("ftp", &tunable_pam_service_name); + install_str_setting("ftp", &tunable_guest_username); +- install_str_setting("/etc/vsftpd.user_list", &tunable_userlist_file); ++ install_str_setting("/etc/vsftpd/user_list", &tunable_userlist_file); + install_str_setting(0, &tunable_anon_root); + install_str_setting(0, &tunable_local_root); + install_str_setting(0, &tunable_banner_file); +@@ -271,7 +271,7 @@ tunables_load_defaults() + install_str_setting(0, &tunable_hide_file); + install_str_setting(0, &tunable_deny_file); + install_str_setting(0, &tunable_user_sub_token); +- install_str_setting("/etc/vsftpd.email_passwords", ++ install_str_setting("/etc/vsftpd/email_passwords", + &tunable_email_password_file); + install_str_setting("/usr/share/ssl/certs/vsftpd.pem", + &tunable_rsa_cert_file); +diff -up vsftpd-2.2.0/vsftpd.8.configuration vsftpd-2.2.0/vsftpd.8 +--- vsftpd-2.2.0/vsftpd.8.configuration 2009-07-17 22:56:23.000000000 +0200 ++++ vsftpd-2.2.0/vsftpd.8 2009-08-04 07:40:27.000000000 +0200 +@@ -21,7 +21,7 @@ itself will listen on the network. This + recommended. It is activated by setting + .Pa listen=YES + in +-.Pa /etc/vsftpd.conf . ++.Pa /etc/vsftpd/vsftpd.conf . + Direct execution of the + .Nm vsftpd + binary will then launch the FTP service ready for immediate client connections. +@@ -33,7 +33,7 @@ as root. Any command line option not sta + as a config file that will be loaded. Note that config files are loaded in the + strict order that they are encountered on the command line. + If no config files are specified, the default configuration file of +-.Pa /etc/vsftpd.conf ++.Pa /etc/vsftpd/vsftpd.conf + will be loaded, after all other command line options are processed. + .Pp + Supported options are: +@@ -47,14 +47,14 @@ their appearance on the command line, in + config files. + .El + .Sh EXAMPLES +-vsftpd -olisten=NO /etc/vsftpd.conf -oftpd_banner=blah ++vsftpd -olisten=NO /etc/vsftpd/vsftpd.conf -oftpd_banner=blah + .Pp + That example overrides vsftpd's built-in default for the "listen" option to be +-NO, but then loads /etc/vsftpd.conf which may override that setting. Finally, ++NO, but then loads /etc/vsftpd/vsftpd.conf which may override that setting. Finally, + the "ftpd_banner" setting is set to "blah", which overrides any default vsftpd + setting and any identical setting that was in the config file. + .Sh FILES +-.Pa /etc/vsftpd.conf ++.Pa /etc/vsftpd/vsftpd.conf + .Sh SEE ALSO + .Xr vsftpd.conf 5 + .end +diff -up vsftpd-2.2.0/vsftpd.conf.5.configuration vsftpd-2.2.0/vsftpd.conf.5 +--- vsftpd-2.2.0/vsftpd.conf.5.configuration 2009-07-17 22:57:04.000000000 +0200 ++++ vsftpd-2.2.0/vsftpd.conf.5 2009-08-04 07:37:01.000000000 +0200 +@@ -4,7 +4,7 @@ vsftpd.conf \- config file for vsftpd + .SH DESCRIPTION + vsftpd.conf may be used to control various aspects of vsftpd's behaviour. By + default, vsftpd looks for this file at the location +-.BR /etc/vsftpd.conf . ++.BR /etc/vsftpd/vsftpd.conf . + However, you may override this by specifying a command line argument to + vsftpd. The command line argument is the pathname of the configuration file + for vsftpd. This behaviour is useful because you may wish to use an advanced +@@ -110,7 +110,7 @@ When enabled, and vsftpd is started in " + the listener process. i.e. control will immediately be returned to the shell + which launched vsftpd. + +-Default: NO ++Default: YES + .TP + .B check_shell + Note! This option only has an effect for non-PAM builds of vsftpd. If disabled, +@@ -138,7 +138,7 @@ chroot() jail in their home directory up + different if chroot_local_user is set to YES. In this case, the list becomes + a list of users which are NOT to be placed in a chroot() jail. + By default, the file containing this list is +-/etc/vsftpd.chroot_list, but you may override this with the ++/etc/vsftpd/chroot_list, but you may override this with the + .BR chroot_list_file + setting. + +@@ -177,7 +177,7 @@ Default: NO + .B deny_email_enable + If activated, you may provide a list of anonymous password e-mail responses + which cause login to be denied. By default, the file containing this list is +-/etc/vsftpd.banned_emails, but you may override this with the ++/etc/vsftpd/banned_emails, but you may override this with the + .BR banned_email_file + setting. + +@@ -433,7 +433,7 @@ anonymous logins are prevented unless th + file specified by the + .BR email_password_file + setting. The file format is one password per line, no extra whitespace. The +-default filename is /etc/vsftpd.email_passwords. ++default filename is /etc/vsftpd/email_passwords. + + Default: NO + .TP +@@ -764,7 +764,7 @@ passwords which are not permitted. This + .BR deny_email_enable + is enabled. + +-Default: /etc/vsftpd.banned_emails ++Default: /etc/vsftpd/banned_emails + .TP + .B banner_file + This option is the name of a file containing text to display when someone +@@ -801,7 +801,7 @@ is enabled. If the option + is enabled, then the list file becomes a list of users to NOT place in a + chroot() jail. + +-Default: /etc/vsftpd.chroot_list ++Default: /etvsftpd.confc/vsftpd.chroot_list + .TP + .B cmds_allowed + This options specifies a comma separated list of allowed FTP commands (post +@@ -862,7 +862,7 @@ This option can be used to provide an al + .BR secure_email_list_enable + setting. + +-Default: /etc/vsftpd.email_passwords ++Default: /etc/vsftpd/email_passwords + .TP + .B ftp_username + This is the name of the user we use for handling anonymous FTP. The home +@@ -985,10 +985,10 @@ the manual page, on a per-user basis. Us + with an example. If you set + .BR user_config_dir + to be +-.BR /etc/vsftpd_user_conf ++.BR /etc/vsftpd/user_conf + and then log on as the user "chris", then vsftpd will apply the settings in + the file +-.BR /etc/vsftpd_user_conf/chris ++.BR /etc/vsftpd/user_conf/chris + for the duration of the session. The format of this file is as detailed in + this manual page! PLEASE NOTE that not all settings are effective on a + per-user basis. For example, many settings only prior to the user's session +@@ -1024,7 +1024,7 @@ This option is the name of the file load + .BR userlist_enable + option is active. + +-Default: /etc/vsftpd.user_list ++Default: /etc/vsftpd/user_list + .TP + .B vsftpd_log_file + This option is the name of the file to which we write the vsftpd style +--- vsftpd-2.2.2/vsftpd.conf.configuration 2009-10-19 04:04:23.000000000 +0200 ++++ vsftpd-2.2.2/vsftpd.conf 2010-08-06 09:28:44.891173995 +0200 +@@ -1,4 +1,4 @@ +-# Example config file /etc/vsftpd.conf ++# Example config file /etc/vsftpd/vsftpd.conf + # + # The default compiled in settings are fairly paranoid. This sample file + # loosens things up a bit, to make the ftp daemon more usable. +@@ -12,18 +12,20 @@ + anonymous_enable=YES + # + # Uncomment this to allow local users to log in. +-#local_enable=YES ++# When SELinux is enforcing check for SE bool ftp_home_dir ++local_enable=YES + # + # Uncomment this to enable any form of FTP write command. +-#write_enable=YES ++write_enable=YES + # + # Default umask for local users is 077. You may wish to change this to 022, + # if your users expect that (022 is used by most other ftpd's) +-#local_umask=022 ++local_umask=022 + # + # Uncomment this to allow the anonymous FTP user to upload files. This only + # has an effect if the above global write enable is activated. Also, you will + # obviously need to create a directory writable by the FTP user. ++# When SELinux is enforcing check for SE bool allow_ftpd_anon_write, allow_ftpd_full_access + #anon_upload_enable=YES + # + # Uncomment this if you want the anonymous FTP user to be able to create +@@ -52,7 +54,7 @@ + # + # If you want, you can have your log file in standard ftpd xferlog format. + # Note that the default log file location is /var/log/xferlog in this case. +-#xferlog_std_format=YES ++xferlog_std_format=YES + # + # You may change the default value for timing out an idle session. + #idle_session_timeout=600 +@@ -87,7 +89,7 @@ + # useful for combatting certain DoS attacks. + #deny_email_enable=YES + # (default follows) +-#banned_email_file=/etc/vsftpd.banned_emails ++#banned_email_file=/etc/vsftpd/banned_emails + # + # You may specify an explicit list of local users to chroot() to their home + # directory. If chroot_local_user is YES, then this list becomes a list of +@@ -95,7 +97,7 @@ + #chroot_local_user=YES + #chroot_list_enable=YES + # (default follows) +-#chroot_list_file=/etc/vsftpd.chroot_list ++#chroot_list_file=/etc/vsftpd/chroot_list + # + # You may activate the "-R" option to the builtin ls. This is disabled by + # default to avoid remote users being able to cause excessive I/O on large +@@ -112,3 +114,7 @@ + # sockets, you must run two copies of vsftpd with two configuration files. + # Make sure, that one of the listen options is commented !! + #listen_ipv6=YES ++ ++pam_service_name=vsftpd ++userlist_enable=YES ++tcp_wrappers=YES diff --git a/SOURCES/vsftpd-2.1.0-filter.patch b/SOURCES/vsftpd-2.1.0-filter.patch new file mode 100644 index 0000000..26b6489 --- /dev/null +++ b/SOURCES/vsftpd-2.1.0-filter.patch @@ -0,0 +1,66 @@ +diff -up vsftpd-2.1.0/ls.c.filter vsftpd-2.1.0/ls.c +--- vsftpd-2.1.0/ls.c.filter 2008-02-02 02:30:41.000000000 +0100 ++++ vsftpd-2.1.0/ls.c 2009-01-08 19:31:15.000000000 +0100 +@@ -239,9 +239,31 @@ vsf_filename_passes_filter(const struct + int ret = 0; + char last_token = 0; + int must_match_at_current_pos = 1; ++ ++ + str_copy(&filter_remain_str, p_filter_str); +- str_copy(&name_remain_str, p_filename_str); +- ++ ++ if (!str_isempty (&filter_remain_str) && !str_isempty(p_filename_str)) { ++ if (str_get_char_at(p_filter_str, 0) == '/') { ++ if (str_get_char_at(p_filename_str, 0) != '/') { ++ str_getcwd (&name_remain_str); ++ ++ if (str_getlen(&name_remain_str) > 1) /* cwd != root dir */ ++ str_append_char (&name_remain_str, '/'); ++ ++ str_append_str (&name_remain_str, p_filename_str); ++ } ++ else ++ str_copy (&name_remain_str, p_filename_str); ++ } else { ++ if (str_get_char_at(p_filter_str, 0) != '{') ++ str_basename (&name_remain_str, p_filename_str); ++ else ++ str_copy (&name_remain_str, p_filename_str); ++ } ++ } else ++ str_copy(&name_remain_str, p_filename_str); ++ + while (!str_isempty(&filter_remain_str) && *iters < VSFTP_MATCHITERS_MAX) + { + static struct mystr s_match_needed_str; +diff -up vsftpd-2.1.0/str.c.filter vsftpd-2.1.0/str.c +--- vsftpd-2.1.0/str.c.filter 2008-12-17 06:54:16.000000000 +0100 ++++ vsftpd-2.1.0/str.c 2009-01-08 19:31:15.000000000 +0100 +@@ -680,3 +680,14 @@ str_replace_unprintable(struct mystr* p_ + } + } + ++void ++str_basename (struct mystr* d_str, const struct mystr* path) ++{ ++ static struct mystr tmp; ++ ++ str_copy (&tmp, path); ++ str_split_char_reverse(&tmp, d_str, '/'); ++ ++ if (str_isempty(d_str)) ++ str_copy (d_str, path); ++} +diff -up vsftpd-2.1.0/str.h.filter vsftpd-2.1.0/str.h +--- vsftpd-2.1.0/str.h.filter 2008-12-17 06:53:23.000000000 +0100 ++++ vsftpd-2.1.0/str.h 2009-01-08 19:32:14.000000000 +0100 +@@ -100,6 +100,7 @@ void str_replace_unprintable(struct myst + int str_atoi(const struct mystr* p_str); + filesize_t str_a_to_filesize_t(const struct mystr* p_str); + unsigned int str_octal_to_uint(const struct mystr* p_str); ++void str_basename (struct mystr* d_str, const struct mystr* path); + + /* PURPOSE: Extract a line of text (delimited by \n or EOF) from a string + * buffer, starting at character position 'p_pos'. The extracted line will diff --git a/SOURCES/vsftpd-2.1.0-libs.patch b/SOURCES/vsftpd-2.1.0-libs.patch new file mode 100644 index 0000000..062ac6f --- /dev/null +++ b/SOURCES/vsftpd-2.1.0-libs.patch @@ -0,0 +1,12 @@ +diff -up vsftpd-3.0.0/Makefile.libs vsftpd-3.0.0/Makefile +--- vsftpd-3.0.0/Makefile.libs 2012-04-03 09:21:18.000000000 +0200 ++++ vsftpd-3.0.0/Makefile 2012-04-10 21:20:39.377248990 +0200 +@@ -8,7 +8,7 @@ CFLAGS = -O2 -fPIE -fstack-protector --p + -D_FORTIFY_SOURCE=2 \ + #-pedantic -Wconversion + +-LIBS = `./vsf_findlibs.sh` ++LIBS = -lwrap -lnsl -lpam -lcap -ldl -lcrypto + LINK = -Wl,-s + LDFLAGS = -fPIE -pie -Wl,-z,relro -Wl,-z,now + diff --git a/SOURCES/vsftpd-2.1.0-pam_hostname.patch b/SOURCES/vsftpd-2.1.0-pam_hostname.patch new file mode 100644 index 0000000..c3d8b1e --- /dev/null +++ b/SOURCES/vsftpd-2.1.0-pam_hostname.patch @@ -0,0 +1,57 @@ +diff -up vsftpd-2.2.0/sysdeputil.c.pam_hostname vsftpd-2.2.0/sysdeputil.c +--- vsftpd-2.2.0/sysdeputil.c.pam_hostname 2009-08-08 03:51:10.000000000 +0200 ++++ vsftpd-2.2.0/sysdeputil.c 2009-08-24 12:24:07.220623773 +0200 +@@ -16,6 +16,10 @@ + #include "tunables.h" + #include "builddefs.h" + ++/* For gethostbyaddr, inet_addr */ ++#include ++#include ++ + /* For Linux, this adds nothing :-) */ + #include "port/porting_junk.h" + +@@ -325,6 +329,10 @@ vsf_sysdep_check_auth(struct mystr* p_us + const struct mystr* p_remote_host) + { + int retval = -1; ++#ifdef PAM_RHOST ++ struct sockaddr_in sin; ++ struct hostent *host; ++#endif + pam_item_t item; + const char* pam_user_name = 0; + struct pam_conv the_conv = +@@ -345,7 +353,12 @@ vsf_sysdep_check_auth(struct mystr* p_us + return 0; + } + #ifdef PAM_RHOST +- retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); ++ sin.sin_addr.s_addr = inet_addr(str_getbuf(p_remote_host)); ++ host = gethostbyaddr((char*)&sin.sin_addr.s_addr,sizeof(struct in_addr),AF_INET); ++ if (host != (struct hostent*)0) ++ retval = pam_set_item(s_pamh, PAM_RHOST, host->h_name); ++ else ++ retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); + if (retval != PAM_SUCCESS) + { + (void) pam_end(s_pamh, retval); +@@ -558,7 +571,7 @@ vsf_sysdep_has_capabilities(void) + } + return s_runtime_has_caps; + } +- ++ + #ifndef VSF_SYSDEP_HAVE_LIBCAP + static int + do_checkcap(void) +@@ -1080,7 +1093,7 @@ vsf_sysutil_recv_fd(const int sock_fd) + msg.msg_flags = 0; + /* In case something goes wrong, set the fd to -1 before the syscall */ + p_fd = (int*)CMSG_DATA(CMSG_FIRSTHDR(&msg)); +- *p_fd = -1; ++ *p_fd = -1; + retval = recvmsg(sock_fd, &msg, 0); + if (retval != 1) + { diff --git a/SOURCES/vsftpd-2.1.0-tcp_wrappers.patch b/SOURCES/vsftpd-2.1.0-tcp_wrappers.patch new file mode 100644 index 0000000..dc0bbce --- /dev/null +++ b/SOURCES/vsftpd-2.1.0-tcp_wrappers.patch @@ -0,0 +1,12 @@ +diff -up vsftpd-2.1.0/builddefs.h.tcp_wrappers vsftpd-2.1.0/builddefs.h +--- vsftpd-2.1.0/builddefs.h.tcp_wrappers 2009-01-08 18:52:46.000000000 +0100 ++++ vsftpd-2.1.0/builddefs.h 2009-01-08 18:52:56.000000000 +0100 +@@ -1,7 +1,7 @@ + #ifndef VSF_BUILDDEFS_H + #define VSF_BUILDDEFS_H + +-#undef VSF_BUILD_TCPWRAPPERS ++#define VSF_BUILD_TCPWRAPPERS + #define VSF_BUILD_PAM + #define VSF_BUILD_SSL + diff --git a/SOURCES/vsftpd-2.1.0-trim.patch b/SOURCES/vsftpd-2.1.0-trim.patch new file mode 100644 index 0000000..d80616d --- /dev/null +++ b/SOURCES/vsftpd-2.1.0-trim.patch @@ -0,0 +1,78 @@ +diff -up vsftpd-2.2.0/parseconf.c.trim vsftpd-2.2.0/parseconf.c +--- vsftpd-2.2.0/parseconf.c.trim 2009-08-04 08:01:10.000000000 +0200 ++++ vsftpd-2.2.0/parseconf.c 2009-08-04 08:10:49.000000000 +0200 +@@ -275,7 +275,7 @@ vsf_parseconf_load_setting(const char* p + } + else + { +- *p_curr_setting = str_strdup(&s_value_str); ++ *p_curr_setting = str_strdup_trimmed(&s_value_str); + } + return; + } +diff -up vsftpd-2.2.0/str.c.trim vsftpd-2.2.0/str.c +--- vsftpd-2.2.0/str.c.trim 2009-08-04 08:01:10.000000000 +0200 ++++ vsftpd-2.2.0/str.c 2009-08-04 08:01:10.000000000 +0200 +@@ -89,6 +89,18 @@ str_strdup(const struct mystr* p_str) + return vsf_sysutil_strdup(str_getbuf(p_str)); + } + ++const char* ++str_strdup_trimmed(const struct mystr* p_str) ++{ ++ const char* p_trimmed = str_getbuf(p_str); ++ int h, t, newlen; ++ ++ for (h = 0; h < (int)str_getlen(p_str) && vsf_sysutil_isspace(p_trimmed[h]); h++) ; ++ for (t = str_getlen(p_str) - 1; t >= 0 && vsf_sysutil_isspace(p_trimmed[t]); t--) ; ++ newlen = t - h + 1; ++ return newlen ? vsf_sysutil_strndup(p_trimmed+h, (unsigned int)newlen) : 0L; ++} ++ + void + str_alloc_alt_term(struct mystr* p_str, const char* p_src, char term) + { +diff -up vsftpd-2.2.0/str.h.trim vsftpd-2.2.0/str.h +--- vsftpd-2.2.0/str.h.trim 2009-08-04 08:01:10.000000000 +0200 ++++ vsftpd-2.2.0/str.h 2009-08-04 08:01:10.000000000 +0200 +@@ -31,6 +31,7 @@ void str_alloc_ulong(struct mystr* p_str + void str_alloc_filesize_t(struct mystr* p_str, filesize_t the_filesize); + void str_copy(struct mystr* p_dest, const struct mystr* p_src); + const char* str_strdup(const struct mystr* p_str); ++const char* str_strdup_trimmed(const struct mystr* p_str); + void str_empty(struct mystr* p_str); + void str_free(struct mystr* p_str); + void str_trunc(struct mystr* p_str, unsigned int trunc_len); +diff -up vsftpd-2.2.0/sysutil.c.trim vsftpd-2.2.0/sysutil.c +--- vsftpd-2.2.0/sysutil.c.trim 2009-07-16 05:32:21.000000000 +0200 ++++ vsftpd-2.2.0/sysutil.c 2009-08-04 08:01:10.000000000 +0200 +@@ -1032,6 +1032,18 @@ vsf_sysutil_strdup(const char* p_str) + return strdup(p_str); + } + ++char* ++vsf_sysutil_strndup(const char* p_str, unsigned int p_len) ++{ ++ char *new = (char *)malloc(p_len+1); ++ ++ if (new == NULL) ++ return NULL; ++ ++ new[p_len]='\0'; ++ return (char *)memcpy(new, p_str, p_len); ++} ++ + void + vsf_sysutil_memclr(void* p_dest, unsigned int size) + { +diff -up vsftpd-2.2.0/sysutil.h.trim vsftpd-2.2.0/sysutil.h +--- vsftpd-2.2.0/sysutil.h.trim 2009-07-16 05:31:53.000000000 +0200 ++++ vsftpd-2.2.0/sysutil.h 2009-08-04 08:01:10.000000000 +0200 +@@ -186,6 +186,7 @@ int vsf_sysutil_wait_get_exitcode( + /* Various string functions */ + unsigned int vsf_sysutil_strlen(const char* p_text); + char* vsf_sysutil_strdup(const char* p_str); ++char* vsf_sysutil_strndup(const char* p_str, unsigned int p_len); + void vsf_sysutil_memclr(void* p_dest, unsigned int size); + void vsf_sysutil_memcpy(void* p_dest, const void* p_src, + const unsigned int size); diff --git a/SOURCES/vsftpd-2.1.0-userlist_log.patch b/SOURCES/vsftpd-2.1.0-userlist_log.patch new file mode 100644 index 0000000..b435724 --- /dev/null +++ b/SOURCES/vsftpd-2.1.0-userlist_log.patch @@ -0,0 +1,120 @@ +diff -up vsftpd-2.1.0/logging.c.userlist_log vsftpd-2.1.0/logging.c +--- vsftpd-2.1.0/logging.c.userlist_log 2008-12-17 20:56:45.000000000 +0100 ++++ vsftpd-2.1.0/logging.c 2009-02-24 09:12:42.000000000 +0100 +@@ -95,6 +95,13 @@ vsf_log_line(struct vsf_session* p_sess, + vsf_log_common(p_sess, 1, what, p_str); + } + ++void ++vsf_log_failed_line(struct vsf_session* p_sess, enum EVSFLogEntryType what, ++ struct mystr* p_str) ++{ ++ vsf_log_common(p_sess, 0, what, p_str); ++} ++ + int + vsf_log_entry_pending(struct vsf_session* p_sess) + { +diff -up vsftpd-2.1.0/logging.h.userlist_log vsftpd-2.1.0/logging.h +--- vsftpd-2.1.0/logging.h.userlist_log 2008-07-30 03:29:21.000000000 +0200 ++++ vsftpd-2.1.0/logging.h 2009-02-24 09:12:42.000000000 +0100 +@@ -80,5 +80,16 @@ void vsf_log_do_log(struct vsf_session* + void vsf_log_line(struct vsf_session* p_sess, enum EVSFLogEntryType what, + struct mystr* p_str); + ++/* vsf_log_failed_line() ++ * PURPOSE ++ * Same as vsf_log_line(), except that it logs the line as failed operation. ++ * PARAMETERS ++ * p_sess - the current session object ++ * what - the type of operation to log ++ * p_str - the string to log ++ */ ++void vsf_log_failed_line(struct vsf_session* p_sess, enum EVSFLogEntryType what, ++ struct mystr* p_str); ++ + #endif /* VSF_LOGGING_H */ + +diff -up vsftpd-2.1.0/parseconf.c.userlist_log vsftpd-2.1.0/parseconf.c +--- vsftpd-2.1.0/parseconf.c.userlist_log 2008-12-18 07:21:41.000000000 +0100 ++++ vsftpd-2.1.0/parseconf.c 2009-02-24 09:12:42.000000000 +0100 +@@ -96,6 +96,7 @@ parseconf_bool_array[] = + { "mdtm_write", &tunable_mdtm_write }, + { "lock_upload_files", &tunable_lock_upload_files }, + { "pasv_addr_resolve", &tunable_pasv_addr_resolve }, ++ { "userlist_log", &tunable_userlist_log }, + { "debug_ssl", &tunable_debug_ssl }, + { "require_cert", &tunable_require_cert }, + { "validate_cert", &tunable_validate_cert }, +diff -up vsftpd-2.1.0/prelogin.c.userlist_log vsftpd-2.1.0/prelogin.c +--- vsftpd-2.1.0/prelogin.c.userlist_log 2009-02-18 23:23:53.000000000 +0100 ++++ vsftpd-2.1.0/prelogin.c 2009-02-24 09:17:41.000000000 +0100 +@@ -220,6 +220,20 @@ handle_user_command(struct vsf_session* + check_login_delay(); + vsf_cmdio_write(p_sess, FTP_LOGINERR, "Permission denied."); + check_login_fails(p_sess); ++ if (tunable_userlist_log) ++ { ++ struct mystr str_log_line = INIT_MYSTR; ++ if (tunable_userlist_deny) ++ { ++ str_alloc_text(&str_log_line, "User is in the deny user list."); ++ } ++ else ++ { ++ str_alloc_text(&str_log_line, "User is not in the allow user list."); ++ } ++ vsf_log_failed_line(p_sess, kVSFLogEntryLogin, &str_log_line); ++ str_free(&str_log_line); ++ } + str_empty(&p_sess->user_str); + return; + } +diff -up vsftpd-2.1.0/tunables.c.userlist_log vsftpd-2.1.0/tunables.c +--- vsftpd-2.1.0/tunables.c.userlist_log 2009-02-24 09:12:42.000000000 +0100 ++++ vsftpd-2.1.0/tunables.c 2009-02-24 09:12:42.000000000 +0100 +@@ -72,6 +72,7 @@ int tunable_force_anon_data_ssl; + int tunable_mdtm_write; + int tunable_lock_upload_files; + int tunable_pasv_addr_resolve; ++int tunable_userlist_log; + int tunable_debug_ssl; + int tunable_require_cert; + int tunable_validate_cert; +@@ -206,6 +207,7 @@ tunables_load_defaults() + tunable_mdtm_write = 1; + tunable_lock_upload_files = 1; + tunable_pasv_addr_resolve = 0; ++ tunable_userlist_log = 0; + tunable_debug_ssl = 0; + tunable_require_cert = 0; + tunable_validate_cert = 0; +diff -up vsftpd-2.1.0/tunables.h.userlist_log vsftpd-2.1.0/tunables.h +--- vsftpd-2.1.0/tunables.h.userlist_log 2008-12-17 06:47:11.000000000 +0100 ++++ vsftpd-2.1.0/tunables.h 2009-02-24 09:12:42.000000000 +0100 +@@ -73,6 +73,7 @@ extern int tunable_force_anon_data_ssl; + extern int tunable_mdtm_write; /* Allow MDTM to set timestamps */ + extern int tunable_lock_upload_files; /* Lock uploading files */ + extern int tunable_pasv_addr_resolve; /* DNS resolve pasv_addr */ ++extern int tunable_userlist_log; /* Log every failed login attempt */ + extern int tunable_debug_ssl; /* Verbose SSL logging */ + extern int tunable_require_cert; /* SSL client cert required */ + extern int tunable_validate_cert; /* SSL certs must be valid */ +diff -up vsftpd-2.1.0/vsftpd.conf.5.userlist_log vsftpd-2.1.0/vsftpd.conf.5 +--- vsftpd-2.1.0/vsftpd.conf.5.userlist_log 2009-02-24 09:12:42.000000000 +0100 ++++ vsftpd-2.1.0/vsftpd.conf.5 2009-02-24 09:12:42.000000000 +0100 +@@ -585,6 +585,14 @@ Self-signed certs do not constitute OK v + + Default: NO + .TP ++.B userlist_log ++This option is examined if ++.BR userlist_enable ++is activated. If enabled, every login denial based on the user list will be ++logged. ++ ++Default: NO ++.TP + .B virtual_use_local_privs + If enabled, virtual users will use the same privileges as local users. By + default, virtual users will use the same privileges as anonymous users, which diff --git a/SOURCES/vsftpd-2.1.1-daemonize_plus.patch b/SOURCES/vsftpd-2.1.1-daemonize_plus.patch new file mode 100644 index 0000000..5f89068 --- /dev/null +++ b/SOURCES/vsftpd-2.1.1-daemonize_plus.patch @@ -0,0 +1,191 @@ +diff -up vsftpd-2.1.1/standalone.c.daemonize_plus vsftpd-2.1.1/standalone.c +--- vsftpd-2.1.1/standalone.c.daemonize_plus 2009-05-10 22:11:24.000000000 +0200 ++++ vsftpd-2.1.1/standalone.c 2009-05-10 22:11:24.000000000 +0200 +@@ -26,6 +26,8 @@ static unsigned int s_ipaddr_size; + + static void handle_sigchld(void* duff); + static void handle_sighup(void* duff); ++static void handle_sigusr1(int sig); ++static void handle_sigalrm(int sig); + static void prepare_child(int sockfd); + static unsigned int handle_ip_count(void* p_raw_addr); + static void drop_ip_count(void* p_raw_addr); +@@ -46,11 +48,23 @@ vsf_standalone_main(void) + } + if (tunable_background) + { ++ vsf_sysutil_sigaction(kVSFSysUtilSigALRM, handle_sigalrm); ++ vsf_sysutil_sigaction(kVSFSysUtilSigUSR1, handle_sigusr1); ++ + int forkret = vsf_sysutil_fork(); + if (forkret > 0) + { + /* Parent, just exit */ +- vsf_sysutil_exit(0); ++ vsf_sysutil_set_alarm(3); ++ vsf_sysutil_pause(); ++ ++ vsf_sysutil_exit(1); ++ } ++ else if (forkret == 0) ++ { ++ // Son, restore original signal handler ++ vsf_sysutil_sigaction(kVSFSysUtilSigALRM, 0L); ++ vsf_sysutil_sigaction(kVSFSysUtilSigUSR1, 0L); + } + /* Son, close standard FDs to avoid SSH hang-on-exit */ + vsf_sysutil_reopen_standard_fds(); +@@ -98,6 +112,10 @@ vsf_standalone_main(void) + { + die("could not bind listening IPv4 socket"); + } ++ if (tunable_background) ++ { ++ vsf_sysutil_kill(vsf_sysutil_getppid(), kVSFSysUtilSigUSR1); ++ } + } + else + { +@@ -127,6 +145,10 @@ vsf_standalone_main(void) + { + die("could not bind listening IPv6 socket"); + } ++ if (tunable_background) ++ { ++ vsf_sysutil_kill(vsf_sysutil_getppid(), kVSFSysUtilSigUSR1); ++ } + } + vsf_sysutil_close(0); + vsf_sysutil_close(1); +@@ -252,6 +274,20 @@ handle_sighup(void* duff) + vsf_parseconf_load_file(0, 0); + } + ++static void ++handle_sigalrm(int sig) ++{ ++ (void)sig; // avoid unused parameter error ++ vsf_sysutil_exit(1); ++} ++ ++static void ++handle_sigusr1(int sig) ++{ ++ (void)sig; // avoid unused parameter error ++ vsf_sysutil_exit(0); ++} ++ + static unsigned int + hash_ip(unsigned int buckets, void* p_key) + { +diff -up vsftpd-2.1.1/sysutil.c.daemonize_plus vsftpd-2.1.1/sysutil.c +--- vsftpd-2.1.1/sysutil.c.daemonize_plus 2009-05-10 22:11:24.000000000 +0200 ++++ vsftpd-2.1.1/sysutil.c 2009-05-10 22:11:59.000000000 +0200 +@@ -202,6 +202,9 @@ vsf_sysutil_translate_sig(const enum EVS + case kVSFSysUtilSigHUP: + realsig = SIGHUP; + break; ++ case kVSFSysUtilSigUSR1: ++ realsig = SIGUSR1; ++ break; + default: + bug("unknown signal in vsf_sysutil_translate_sig"); + break; +@@ -539,6 +542,12 @@ vsf_sysutil_getpid(void) + return (unsigned int) s_current_pid; + } + ++unsigned int ++vsf_sysutil_getppid(void) ++{ ++ return (unsigned int)getppid(); ++} ++ + int + vsf_sysutil_fork(void) + { +@@ -2807,3 +2816,53 @@ vsf_sysutil_set_no_fds() + s_sig_details[i].pending = 0; + } + } ++ ++static struct sigaction sigalr, sigusr1; ++ ++void ++vsf_sysutil_sigaction(const enum EVSFSysUtilSignal sig, void (*p_handlefunc)(int)) ++{ ++ int realsig = vsf_sysutil_translate_sig(sig); ++ int retval; ++ struct sigaction sigact, *origsigact=NULL; ++ if (realsig==SIGALRM) ++ { ++ origsigact = &sigalr; ++ } ++ else if (realsig==SIGUSR1) ++ { ++ origsigact = &sigusr1; ++ } ++ vsf_sysutil_memclr(&sigact, sizeof(sigact)); ++ if (p_handlefunc != NULL) ++ { ++ sigact.sa_handler = p_handlefunc; ++ retval = sigfillset(&sigact.sa_mask); ++ if (retval != 0) ++ { ++ die("sigfillset"); ++ } ++ retval = sigaction(realsig, &sigact, origsigact); ++ } ++ else ++ { ++ retval = sigaction(realsig, origsigact, NULL); ++ } ++ if (retval != 0) ++ { ++ die("sigaction"); ++ } ++} ++ ++int ++vsf_sysutil_kill(int pid, int sig) ++{ ++ int realsig = vsf_sysutil_translate_sig(sig); ++ return kill(pid, realsig); ++} ++ ++int ++vsf_sysutil_pause() ++{ ++ return pause(); ++} +diff -up vsftpd-2.1.1/sysutil.h.daemonize_plus vsftpd-2.1.1/sysutil.h +--- vsftpd-2.1.1/sysutil.h.daemonize_plus 2009-05-10 22:11:24.000000000 +0200 ++++ vsftpd-2.1.1/sysutil.h 2009-05-10 22:11:24.000000000 +0200 +@@ -29,7 +29,8 @@ enum EVSFSysUtilSignal + kVSFSysUtilSigCHLD, + kVSFSysUtilSigPIPE, + kVSFSysUtilSigURG, +- kVSFSysUtilSigHUP ++ kVSFSysUtilSigHUP, ++ kVSFSysUtilSigUSR1 + }; + enum EVSFSysUtilInterruptContext + { +@@ -165,6 +165,7 @@ void vsf_sysutil_free(void* p_ptr); + + /* Process creation/exit/process handling */ + unsigned int vsf_sysutil_getpid(void); ++unsigned int vsf_sysutil_getppid(void); + void vsf_sysutil_post_fork(void); + int vsf_sysutil_fork(void); + int vsf_sysutil_fork_failok(void); +@@ -182,6 +184,9 @@ int vsf_sysutil_wait_exited_normally( + const struct vsf_sysutil_wait_retval* p_waitret); + int vsf_sysutil_wait_get_exitcode( + const struct vsf_sysutil_wait_retval* p_waitret); ++void vsf_sysutil_sigaction(const enum EVSFSysUtilSignal sig, void (*p_handlefunc)(int)); ++int vsf_sysutil_kill(int pid, int sig); ++int vsf_sysutil_pause(); + + /* Various string functions */ + unsigned int vsf_sysutil_strlen(const char* p_text); diff --git a/SOURCES/vsftpd-2.2.0-wildchar.patch b/SOURCES/vsftpd-2.2.0-wildchar.patch new file mode 100644 index 0000000..ca8480e --- /dev/null +++ b/SOURCES/vsftpd-2.2.0-wildchar.patch @@ -0,0 +1,24 @@ +diff -up vsftpd-2.3.2/ls.c.tmp vsftpd-2.3.2/ls.c +--- vsftpd-2.3.2/ls.c.tmp 2010-08-20 13:18:54.397583558 +0200 ++++ vsftpd-2.3.2/ls.c 2010-08-20 13:14:59.047831385 +0200 +@@ -305,6 +305,20 @@ vsf_filename_passes_filter(const struct + { + goto out; + } ++ if (!must_match_at_current_pos && last_token == 0) ++ { ++ struct mystr last_str = INIT_MYSTR; ++ str_mid_to_end(&name_remain_str, &last_str, ++ str_getlen(&name_remain_str) - str_getlen(&s_match_needed_str)); ++ locate_result = str_locate_str(&last_str, &s_match_needed_str); ++ str_free(&last_str); ++ ++ if (locate_result.found) ++ { ++ ret = 1; ++ } ++ goto out; ++ } + /* Chop matched string out of remainder */ + str_mid_to_end(&name_remain_str, &temp_str, + indexx + str_getlen(&s_match_needed_str)); diff --git a/SOURCES/vsftpd-2.2.2-blank-chars-overflow.patch b/SOURCES/vsftpd-2.2.2-blank-chars-overflow.patch new file mode 100644 index 0000000..067f7fe --- /dev/null +++ b/SOURCES/vsftpd-2.2.2-blank-chars-overflow.patch @@ -0,0 +1,13 @@ +diff --git a/str.c b/str.c +index 41b27db..82b8ae4 100644 +--- a/str.c ++++ b/str.c +@@ -113,7 +113,7 @@ str_strdup_trimmed(const struct mystr* p_str) + for (h = 0; h < (int)str_getlen(p_str) && vsf_sysutil_isspace(p_trimmed[h]); h++) ; + for (t = str_getlen(p_str) - 1; t >= 0 && vsf_sysutil_isspace(p_trimmed[t]); t--) ; + newlen = t - h + 1; +- return newlen ? vsf_sysutil_strndup(p_trimmed+h, (unsigned int)newlen) : 0L; ++ return (newlen > 0) ? vsf_sysutil_strndup(p_trimmed+h, (unsigned int)newlen) : 0L; + } + + void diff --git a/SOURCES/vsftpd-2.2.2-clone.patch b/SOURCES/vsftpd-2.2.2-clone.patch new file mode 100644 index 0000000..b2a275f --- /dev/null +++ b/SOURCES/vsftpd-2.2.2-clone.patch @@ -0,0 +1,21 @@ +diff -up vsftpd-2.2.2/sysdeputil.c.clone vsftpd-2.2.2/sysdeputil.c +--- vsftpd-2.2.2/sysdeputil.c.clone 2010-05-13 13:26:32.099358732 +0200 ++++ vsftpd-2.2.2/sysdeputil.c 2010-05-13 13:26:43.894359985 +0200 +@@ -1279,7 +1279,7 @@ vsf_sysutil_fork_isolate_failok() + static int cloneflags_work = 1; + if (cloneflags_work) + { +- int ret = syscall(__NR_clone, CLONE_NEWPID | CLONE_NEWIPC | SIGCHLD, NULL); ++ int ret = clone(NULL, NULL, CLONE_NEWPID | CLONE_NEWIPC | SIGCHLD, NULL); + if (ret != -1 || (errno != EINVAL && errno != EPERM)) + { + if (ret == 0) +@@ -1301,7 +1301,7 @@ vsf_sysutil_fork_newnet() + static int cloneflags_work = 1; + if (cloneflags_work) + { +- int ret = syscall(__NR_clone, CLONE_NEWNET | SIGCHLD, NULL); ++ int ret = clone(NULL, NULL, CLONE_NEWNET | SIGCHLD, NULL); + if (ret != -1 || (errno != EINVAL && errno != EPERM)) + { + if (ret == 0) diff --git a/SOURCES/vsftpd-2.2.2-man-pages.patch b/SOURCES/vsftpd-2.2.2-man-pages.patch new file mode 100644 index 0000000..87b2405 --- /dev/null +++ b/SOURCES/vsftpd-2.2.2-man-pages.patch @@ -0,0 +1,14 @@ +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 721b325..868ec94 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -478,7 +478,8 @@ Default: NO + .TP + .B ssl_request_cert + If enabled, vsftpd will request (but not necessarily require; see +-.BR require_cert) a certificate on incoming SSL connections. Normally this ++.BR require_cert ) ++a certificate on incoming SSL connections. Normally this + should not cause any trouble at all, but IBM zOS seems to have issues. + (New in v2.0.7). + diff --git a/SOURCES/vsftpd-2.2.2-nfs-fail.patch b/SOURCES/vsftpd-2.2.2-nfs-fail.patch new file mode 100644 index 0000000..1439275 --- /dev/null +++ b/SOURCES/vsftpd-2.2.2-nfs-fail.patch @@ -0,0 +1,129 @@ +diff --git a/ftpcodes.h b/ftpcodes.h +index 995788a..22c3c9b 100644 +--- a/ftpcodes.h ++++ b/ftpcodes.h +@@ -73,6 +73,7 @@ + #define FTP_NOHANDLEPROT 536 + #define FTP_FILEFAIL 550 + #define FTP_NOPERM 550 ++#define FTP_DISKQUOTA 552 + #define FTP_UPLOADFAIL 553 + + #endif /* VSF_FTPCODES_H */ +diff --git a/postlogin.c b/postlogin.c +index e1f080f..ffe0f38 100644 +--- a/postlogin.c ++++ b/postlogin.c +@@ -28,6 +28,8 @@ + #include "vsftpver.h" + #include "opts.h" + ++#include ++ + /* Private local functions */ + static void handle_pwd(struct vsf_session* p_sess); + static void handle_cwd(struct vsf_session* p_sess); +@@ -996,8 +998,10 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique) + struct vsf_transfer_ret trans_ret; + int new_file_fd; + int remote_fd; ++ int close_errno; + int success = 0; + int created = 0; ++ int closed = 0; + int do_truncate = 0; + filesize_t offset = p_sess->restart_pos; + p_sess->restart_pos = 0; +@@ -1110,6 +1114,18 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique) + trans_ret = vsf_ftpdataio_transfer_file(p_sess, remote_fd, + new_file_fd, 1, 0); + } ++ ++ /* Need to check close operation here because some errors ++ * like EIO, EDQUOT, ENOSPC can be detected only on close ++ * when using NFS ++ */ ++ close_errno = vsf_sysutil_close_errno(new_file_fd); ++ closed = 1; ++ if (close_errno != 0) ++ { ++ trans_ret.retval = -1; ++ } ++ + if (vsf_ftpdataio_dispose_transfer_fd(p_sess) != 1 && trans_ret.retval == 0) + { + trans_ret.retval = -2; +@@ -1122,7 +1138,16 @@ handle_upload_common(struct vsf_session* p_sess, int is_append, int is_unique) + } + if (trans_ret.retval == -1) + { +- vsf_cmdio_write(p_sess, FTP_BADSENDFILE, "Failure writing to local file."); ++ /* Disk quota exceeded */ ++ if (close_errno == EDQUOT) ++ { ++ vsf_cmdio_write(p_sess, FTP_DISKQUOTA, "Disk quota exceeded."); ++ } ++ /* any other local error */ ++ else ++ { ++ vsf_cmdio_write(p_sess, FTP_BADSENDFILE, "Failure writing to local file."); ++ } + } + else if (trans_ret.retval == -2) + { +@@ -1144,7 +1169,10 @@ port_pasv_cleanup_out: + { + str_unlink(p_filename); + } +- vsf_sysutil_close(new_file_fd); ++ if (!closed) ++ { ++ vsf_sysutil_close(new_file_fd); ++ } + } + + static void +diff --git a/sysutil.c b/sysutil.c +index 01a726d..2c3659b 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -1271,6 +1271,27 @@ vsf_sysutil_close(int fd) + } + + int ++vsf_sysutil_close_errno(int fd) ++{ ++ while (1) ++ { ++ int retval = close(fd); ++ if (retval != 0) ++ { ++ if (errno == EINTR) ++ { ++ vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); ++ continue; ++ } ++ else { ++ return errno; ++ } ++ } ++ return 0; ++ } ++} ++ ++int + vsf_sysutil_close_failok(int fd) + { + return close(fd); +diff --git a/sysutil.h b/sysutil.h +index 92fb7a9..c9ca9e4 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -92,6 +92,7 @@ int vsf_sysutil_create_append_file(const char* p_filename); + int vsf_sysutil_create_or_open_file(const char* p_filename, unsigned int mode); + void vsf_sysutil_dupfd2(int old_fd, int new_fd); + void vsf_sysutil_close(int fd); ++int vsf_sysutil_close_errno(int fd); + int vsf_sysutil_close_failok(int fd); + int vsf_sysutil_unlink(const char* p_dead); + int vsf_sysutil_write_access(const char* p_filename); diff --git a/SOURCES/vsftpd-2.2.2-syslog.patch b/SOURCES/vsftpd-2.2.2-syslog.patch new file mode 100644 index 0000000..47c592e --- /dev/null +++ b/SOURCES/vsftpd-2.2.2-syslog.patch @@ -0,0 +1,13 @@ +diff --git a/logging.c b/logging.c +index 99671b4..c4461f7 100644 +--- a/logging.c ++++ b/logging.c +@@ -32,7 +32,7 @@ vsf_log_init(struct vsf_session* p_sess) + { + if (tunable_syslog_enable || tunable_tcp_wrappers) + { +- vsf_sysutil_openlog(1); ++ vsf_sysutil_openlog(0); + } + if (!tunable_xferlog_enable && !tunable_dual_log_enable) + { diff --git a/SOURCES/vsftpd-2.2.2-tlsv1_2.patch b/SOURCES/vsftpd-2.2.2-tlsv1_2.patch new file mode 100644 index 0000000..349b403 --- /dev/null +++ b/SOURCES/vsftpd-2.2.2-tlsv1_2.patch @@ -0,0 +1,116 @@ +diff --git a/parseconf.c b/parseconf.c +index a2c715b..33a1349 100644 +--- a/parseconf.c ++++ b/parseconf.c +@@ -85,6 +85,8 @@ parseconf_bool_array[] = + { "ssl_sslv2", &tunable_sslv2 }, + { "ssl_sslv3", &tunable_sslv3 }, + { "ssl_tlsv1", &tunable_tlsv1 }, ++ { "ssl_tlsv1_1", &tunable_tlsv1_1 }, ++ { "ssl_tlsv1_2", &tunable_tlsv1_2 }, + { "tilde_user_enable", &tunable_tilde_user_enable }, + { "force_anon_logins_ssl", &tunable_force_anon_logins_ssl }, + { "force_anon_data_ssl", &tunable_force_anon_data_ssl }, +diff --git a/ssl.c b/ssl.c +index da23f87..94c2b6b 100644 +--- a/ssl.c ++++ b/ssl.c +@@ -135,6 +135,14 @@ ssl_init(struct vsf_session* p_sess) + { + options |= SSL_OP_NO_TLSv1; + } ++ if (!tunable_tlsv1_1) ++ { ++ options |= SSL_OP_NO_TLSv1_1; ++ } ++ if (!tunable_tlsv1_2) ++ { ++ options |= SSL_OP_NO_TLSv1_2; ++ } + SSL_CTX_set_options(p_ctx, options); + if (tunable_rsa_cert_file) + { +diff --git a/tunables.c b/tunables.c +index 742284e..08d5490 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -66,6 +66,8 @@ int tunable_force_local_data_ssl; + int tunable_sslv2; + int tunable_sslv3; + int tunable_tlsv1; ++int tunable_tlsv1_1; ++int tunable_tlsv1_2; + int tunable_tilde_user_enable; + int tunable_force_anon_logins_ssl; + int tunable_force_anon_data_ssl; +@@ -209,7 +211,9 @@ tunables_load_defaults() + tunable_force_local_data_ssl = 1; + tunable_sslv2 = 0; + tunable_sslv3 = 0; +- tunable_tlsv1 = 1; ++ tunable_tlsv1 = 0; ++ tunable_tlsv1_1 = 0; ++ tunable_tlsv1_2 = 1; + tunable_tilde_user_enable = 0; + tunable_force_anon_logins_ssl = 0; + tunable_force_anon_data_ssl = 0; +diff --git a/tunables.h b/tunables.h +index 3e2d40c..a466427 100644 +--- a/tunables.h ++++ b/tunables.h +@@ -67,6 +67,8 @@ extern int tunable_force_local_data_ssl; /* Require local data uses SSL */ + extern int tunable_sslv2; /* Allow SSLv2 */ + extern int tunable_sslv3; /* Allow SSLv3 */ + extern int tunable_tlsv1; /* Allow TLSv1 */ ++extern int tunable_tlsv1_1; /* Allow TLSv1.1 */ ++extern int tunable_tlsv1_2; /* Allow TLSv1.2 */ + extern int tunable_tilde_user_enable; /* Support e.g. ~chris */ + extern int tunable_force_anon_logins_ssl; /* Require anon logins use SSL */ + extern int tunable_force_anon_data_ssl; /* Require anon data uses SSL */ +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index cf1ae34..6f36b1b 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -506,7 +506,7 @@ Default: YES + Only applies if + .BR ssl_enable + is activated. If enabled, this option will permit SSL v2 protocol connections. +-TLS v1 connections are preferred. ++TLS v1.2 connections are preferred. + + Default: NO + .TP +@@ -514,7 +514,7 @@ Default: NO + Only applies if + .BR ssl_enable + is activated. If enabled, this option will permit SSL v3 protocol connections. +-TLS v1 connections are preferred. ++TLS v1.2 connections are preferred. + + Default: NO + .TP +@@ -522,7 +522,23 @@ Default: NO + Only applies if + .BR ssl_enable + is activated. If enabled, this option will permit TLS v1 protocol connections. +-TLS v1 connections are preferred. ++TLS v1.2 connections are preferred. ++ ++Default: NO ++.TP ++.B ssl_tlsv1_1 ++Only applies if ++.BR ssl_enable ++is activated. If enabled, this option will permit TLS v1.1 protocol connections. ++TLS v1.2 connections are preferred. ++ ++Default: NO ++.TP ++.B ssl_tlsv1_2 ++Only applies if ++.BR ssl_enable ++is activated. If enabled, this option will permit TLS v1.2 protocol connections. ++TLS v1.2 connections are preferred. + + Default: YES + .TP diff --git a/SOURCES/vsftpd-2.3.4-listen_ipv6.patch b/SOURCES/vsftpd-2.3.4-listen_ipv6.patch new file mode 100644 index 0000000..8686574 --- /dev/null +++ b/SOURCES/vsftpd-2.3.4-listen_ipv6.patch @@ -0,0 +1,37 @@ +--- vsftpd-2.3.4/vsftpd.conf~ 2011-11-21 13:15:03.888357116 +0000 ++++ vsftpd-2.3.4/vsftpd.conf 2011-11-21 13:17:43.676136602 +0000 +@@ -108,12 +108,16 @@ xferlog_std_format=YES + # When "listen" directive is enabled, vsftpd runs in standalone mode and + # listens on IPv4 sockets. This directive cannot be used in conjunction + # with the listen_ipv6 directive. +-listen=YES ++listen=NO + # +-# This directive enables listening on IPv6 sockets. To listen on IPv4 and IPv6 +-# sockets, you must run two copies of vsftpd with two configuration files. ++# This directive enables listening on IPv6 sockets. By default, listening ++# on the IPv6 "any" address (::) will accept connections from both IPv6 ++# and IPv4 clients. It is not necessary to listen on *both* IPv4 and IPv6 ++# sockets. If you want that (perhaps because you want to listen on specific ++# addresses) then you must run two copies of vsftpd with two configuration ++# files. + # Make sure, that one of the listen options is commented !! +-#listen_ipv6=YES ++listen_ipv6=YES + + pam_service_name=vsftpd + userlist_enable=YES +--- vsftpd-2.3.4/vsftpd.conf.5~ 2011-11-21 13:15:03.905357305 +0000 ++++ vsftpd-2.3.4/vsftpd.conf.5 2011-11-21 13:18:31.771672385 +0000 +@@ -281,8 +281,9 @@ Default: NO + .TP + .B listen_ipv6 + Like the listen parameter, except vsftpd will listen on an IPv6 socket instead +-of an IPv4 one. This parameter and the listen parameter are mutually +-exclusive. ++of an IPv4 one. Note that a socket listening on the IPv6 "any" address (::) ++will accept both IPv6 and IPv4 connections by default. This parameter and the ++listen parameter are mutually exclusive. + + Default: NO + .TP diff --git a/SOURCES/vsftpd-2.3.4-sd.patch b/SOURCES/vsftpd-2.3.4-sd.patch new file mode 100644 index 0000000..706365a --- /dev/null +++ b/SOURCES/vsftpd-2.3.4-sd.patch @@ -0,0 +1,69 @@ +diff -up vsftpd-3.0.2/vsftpd.8.sd vsftpd-3.0.2/vsftpd.8 +--- vsftpd-3.0.2/vsftpd.8.sd 2013-09-04 13:04:40.383348837 +0200 ++++ vsftpd-3.0.2/vsftpd.8 2013-09-04 13:45:00.370277842 +0200 +@@ -25,6 +25,23 @@ in + Direct execution of the + .Nm vsftpd + binary will then launch the FTP service ready for immediate client connections. ++.Pp ++Systemd changes the vsftpd daemon start-up. The vsftpd package contains vsftpd-generator script generating symbolic links to /var/run/systemd/generator/vsftpd.target.wants directory. The generator is called during e.g. 'systemctl --system daemon-reload'. All these symbolic links link /usr/lib/systemd/system/vsftpd@.service file. ++The vsftpd daemon(s) is/are controlled by one of following ways: ++.Pp ++1. Single daemon using default /etc/vsftpd/vsftpd.conf configuration file ++.br ++# systemctl {start,stop,...} vsftpd[.service] ++.Pp ++2. Single daemon using /etc/vsftpd/.conf ++.br ++# systemctl {start,stop,...} vsftpd@[.service] ++.Pp ++3. All instances together ++.br ++# systemctl {restart,stop} vsftpd.target ++.Pp ++See systemd.unit(5), systemd.target(5) for further details. + .Sh OPTIONS + An optional + configuration file or files +@@ -55,6 +72,13 @@ the "ftpd_banner" setting is set to "bla + setting and any identical setting that was in the config file. + .Sh FILES + .Pa /etc/vsftpd/vsftpd.conf ++.Pp ++.Pa /usr/lib/systemd/system/vsftpd.service ++.Pp ++.Pa /usr/lib/systemd/system/vsftpd@.service ++.Pp ++.Pa /usr/lib/systemd/system/vsftpd.target + .Sh SEE ALSO + .Xr vsftpd.conf 5 ++.Xr systemd.unit 5 + .end +diff -up vsftpd-3.0.2/vsftpd.conf.5.sd vsftpd-3.0.2/vsftpd.conf.5 +--- vsftpd-3.0.2/vsftpd.conf.5.sd 2013-09-04 13:04:40.391348915 +0200 ++++ vsftpd-3.0.2/vsftpd.conf.5 2013-09-04 13:44:57.573250302 +0200 +@@ -12,7 +12,23 @@ inetd such as + .BR xinetd + to launch vsftpd with different configuration files on a per virtual host + basis. +- ++.P ++Systemd changes the vsftpd daemon start-up. The vsftpd package contains vsftpd-generator script generating symbolic links to /var/run/systemd/generator/vsftpd.target.wants directory. The generator is called during e. g. 'systemctl --system daemon-reload'. All these symbolic links link /usr/lib/systemd/system/vsftpd@.service file. ++The vsftpd daemon(s) is/are controlled by one of following ways: ++.P ++1. Single daemon using default /etc/vsftpd/vsftpd.conf configuration file ++.br ++# systemctl {start,stop,...} vsftpd[.service] ++.P ++2. Single daemon using /etc/vsftpd/.conf ++.br ++# systemctl {start,stop,...} vsftpd@[.service] ++.P ++3. All instances together ++.br ++# systemctl {restart,stop} vsftpd.target ++.P ++See systemd.unit(5), systemd.target(5) for further details. + .SH FORMAT + The format of vsftpd.conf is very simple. Each line is either a comment or + a directive. Comment lines start with a # and are ignored. A directive line diff --git a/SOURCES/vsftpd-2.3.4-sqb.patch b/SOURCES/vsftpd-2.3.4-sqb.patch new file mode 100644 index 0000000..a788c77 --- /dev/null +++ b/SOURCES/vsftpd-2.3.4-sqb.patch @@ -0,0 +1,265 @@ +diff -up vsftpd-3.0.2/ls.c.sqb vsftpd-3.0.2/ls.c +--- vsftpd-3.0.2/ls.c.sqb 2014-07-04 13:41:16.421185690 +0200 ++++ vsftpd-3.0.2/ls.c 2014-07-04 13:52:35.920369390 +0200 +@@ -246,7 +246,7 @@ vsf_filename_passes_filter(const struct + int ret = 0; + char last_token = 0; + int must_match_at_current_pos = 1; +- ++ int matched = 0; + + str_copy(&filter_remain_str, p_filter_str); + +@@ -276,7 +276,7 @@ vsf_filename_passes_filter(const struct + static struct mystr s_match_needed_str; + /* Locate next special token */ + struct str_locate_result locate_result = +- str_locate_chars(&filter_remain_str, "*?{"); ++ str_locate_chars(&filter_remain_str, "*?{["); + (*iters)++; + /* Isolate text leading up to token (if any) - needs to be matched */ + if (locate_result.found) +@@ -294,94 +294,172 @@ vsf_filename_passes_filter(const struct + str_empty(&filter_remain_str); + last_token = 0; + } +- if (!str_isempty(&s_match_needed_str)) +- { +- /* Need to match something.. could be a match which has to start at +- * current position, or we could allow it to start anywhere +- */ +- unsigned int indexx; +- locate_result = str_locate_str(&name_remain_str, &s_match_needed_str); +- if (!locate_result.found) ++ ++ matched = 0; ++ do { ++ if (!str_isempty(&s_match_needed_str)) + { +- /* Fail */ +- goto out; ++ if (!matched) ++ { ++ matched = 1; ++ } ++ /* Need to match something.. could be a match which has to start at ++ * current position, or we could allow it to start anywhere ++ */ ++ unsigned int indexx; ++ locate_result = str_locate_str(&name_remain_str, &s_match_needed_str); ++ if (!locate_result.found) ++ { ++ /* Fail */ ++ goto out; ++ } ++ indexx = locate_result.index; ++ if (must_match_at_current_pos && indexx > 0) ++ { ++ goto out; ++ } ++ if (!must_match_at_current_pos && last_token == 0) ++ { ++ struct mystr last_str = INIT_MYSTR; ++ str_mid_to_end(&name_remain_str, &last_str, ++ str_getlen(&name_remain_str) - str_getlen(&s_match_needed_str)); ++ locate_result = str_locate_str(&last_str, &s_match_needed_str); ++ str_free(&last_str); ++ ++ if (locate_result.found) ++ { ++ ret = 1; ++ } ++ goto out; ++ } ++ /* Chop matched string out of remainder */ ++ str_mid_to_end(&name_remain_str, &temp_str, ++ indexx + str_getlen(&s_match_needed_str)); ++ str_copy(&name_remain_str, &temp_str); + } +- indexx = locate_result.index; +- if (must_match_at_current_pos && indexx > 0) ++ if (last_token == '?') + { +- goto out; ++ if (str_isempty(&name_remain_str)) ++ { ++ goto out; ++ } ++ str_right(&name_remain_str, &temp_str, str_getlen(&name_remain_str) - 1); ++ str_copy(&name_remain_str, &temp_str); ++ must_match_at_current_pos = 1; + } +- if (!must_match_at_current_pos && last_token == 0) ++ else if (last_token == '{') + { +- struct mystr last_str = INIT_MYSTR; +- str_mid_to_end(&name_remain_str, &last_str, +- str_getlen(&name_remain_str) - str_getlen(&s_match_needed_str)); +- locate_result = str_locate_str(&last_str, &s_match_needed_str); +- str_free(&last_str); ++ struct str_locate_result end_brace = ++ str_locate_char(&filter_remain_str, '}'); ++ must_match_at_current_pos = 1; ++ if (end_brace.found) ++ { ++ int entire = (*iters == 1 && last_token == '{'); + +- if (locate_result.found) ++ str_split_char(&filter_remain_str, &temp_str, '}'); ++ str_copy(&brace_list_str, &filter_remain_str); ++ str_copy(&filter_remain_str, &temp_str); ++ str_split_char(&brace_list_str, &temp_str, ','); ++ while (!str_isempty(&brace_list_str)) ++ { ++ str_empty(&new_filter_str); ++ if (!matched && !entire) ++ { ++ str_append_char(&new_filter_str, '*'); ++ } ++ str_append_str(&new_filter_str, &brace_list_str); ++ str_append_str(&new_filter_str, &filter_remain_str); ++ if (vsf_filename_passes_filter(&name_remain_str, &new_filter_str, ++ iters)) ++ { ++ ret = 1; ++ goto out; ++ } ++ str_copy(&brace_list_str, &temp_str); ++ str_split_char(&brace_list_str, &temp_str, ','); ++ } ++ goto out; ++ } ++ else if (str_isempty(&name_remain_str) || ++ str_get_char_at(&name_remain_str, 0) != '{') + { +- ret = 1; ++ goto out; ++ } ++ else ++ { ++ str_right(&name_remain_str, &temp_str, ++ str_getlen(&name_remain_str) - 1); ++ str_copy(&name_remain_str, &temp_str); + } +- goto out; +- } +- /* Chop matched string out of remainder */ +- str_mid_to_end(&name_remain_str, &temp_str, +- indexx + str_getlen(&s_match_needed_str)); +- str_copy(&name_remain_str, &temp_str); +- } +- if (last_token == '?') +- { +- if (str_isempty(&name_remain_str)) +- { +- goto out; + } +- str_right(&name_remain_str, &temp_str, str_getlen(&name_remain_str) - 1); +- str_copy(&name_remain_str, &temp_str); +- must_match_at_current_pos = 1; +- } +- else if (last_token == '{') +- { +- struct str_locate_result end_brace = +- str_locate_char(&filter_remain_str, '}'); +- must_match_at_current_pos = 1; +- if (end_brace.found) ++ else if (last_token == '[') + { +- str_split_char(&filter_remain_str, &temp_str, '}'); +- str_copy(&brace_list_str, &filter_remain_str); +- str_copy(&filter_remain_str, &temp_str); +- str_split_char(&brace_list_str, &temp_str, ','); +- while (!str_isempty(&brace_list_str)) +- { +- str_copy(&new_filter_str, &brace_list_str); +- str_append_str(&new_filter_str, &filter_remain_str); +- if (vsf_filename_passes_filter(&name_remain_str, &new_filter_str, +- iters)) ++ struct str_locate_result end_sqb = ++ str_locate_char(&filter_remain_str, ']'); ++ must_match_at_current_pos = 1; ++ if (end_sqb.found) ++ { ++ unsigned int cur_pos; ++ char stch, ench; ++ const char *p_brace; ++ ++ str_split_char(&filter_remain_str, &temp_str, ']'); ++ str_copy(&brace_list_str, &filter_remain_str); ++ str_copy(&filter_remain_str, &temp_str); ++ p_brace = str_getbuf(&brace_list_str); ++ for (cur_pos = 0; cur_pos < str_getlen(&brace_list_str);) + { +- ret = 1; +- goto out; ++ stch = p_brace[cur_pos]; ++ // char vers. range ++ if (cur_pos + 2 < str_getlen(&brace_list_str) && ++ p_brace[cur_pos+1] == '-') ++ { ++ ench = p_brace[cur_pos+2]; ++ cur_pos += 3; ++ } ++ else ++ { ++ ench = stch; ++ cur_pos++; ++ } ++ // expand char[s] ++ for (;stch <= ench && !str_isempty(&brace_list_str); stch++) ++ { ++ str_empty(&new_filter_str); ++ if (!matched) ++ { ++ str_append_char(&new_filter_str, '*'); ++ } ++ str_append_char(&new_filter_str, stch); ++ str_append_str(&new_filter_str, &filter_remain_str); ++ if (vsf_filename_passes_filter(&name_remain_str, &new_filter_str, ++ iters)) ++ { ++ ret = 1; ++ goto out; ++ } ++ } + } +- str_copy(&brace_list_str, &temp_str); +- str_split_char(&brace_list_str, &temp_str, ','); ++ goto out; ++ } ++ else if (str_isempty(&name_remain_str) || ++ str_get_char_at(&name_remain_str, 0) != '[') ++ { ++ goto out; ++ } ++ else ++ { ++ str_right(&name_remain_str, &temp_str, ++ str_getlen(&name_remain_str) - 1); ++ str_copy(&name_remain_str, &temp_str); + } +- goto out; +- } +- else if (str_isempty(&name_remain_str) || +- str_get_char_at(&name_remain_str, 0) != '{') +- { +- goto out; + } + else + { +- str_right(&name_remain_str, &temp_str, +- str_getlen(&name_remain_str) - 1); +- str_copy(&name_remain_str, &temp_str); ++ must_match_at_current_pos = 0; + } +- } +- else +- { +- must_match_at_current_pos = 0; +- } ++ } while (locate_result.found && ++ str_getlen(&name_remain_str) > 0 && last_token != '*'); + } + /* Any incoming string left means no match unless we ended on the correct + * type of wildcard. diff --git a/SOURCES/vsftpd-2.3.5-aslim.patch b/SOURCES/vsftpd-2.3.5-aslim.patch new file mode 100644 index 0000000..ba317b8 --- /dev/null +++ b/SOURCES/vsftpd-2.3.5-aslim.patch @@ -0,0 +1,12 @@ +diff -up vsftpd-2.3.5/defs.h.aslim vsftpd-2.3.5/defs.h +--- vsftpd-2.3.5/defs.h.aslim 2012-02-09 07:40:04.916658587 +0100 ++++ vsftpd-2.3.5/defs.h 2012-02-09 07:50:18.365278392 +0100 +@@ -19,7 +19,7 @@ + /* Must be at least the size of VSFTP_MAX_COMMAND_LINE, VSFTP_DIR_BUFSIZE and + VSFTP_DATA_BUFSIZE*2 */ + #define VSFTP_PRIVSOCK_MAXSTR VSFTP_DATA_BUFSIZE * 2 +-#define VSFTP_AS_LIMIT 100UL * 1024 * 1024 ++#define VSFTP_AS_LIMIT 400UL * 1024 * 1024 + + #endif /* VSF_DEFS_H */ + diff --git a/SOURCES/vsftpd-3.0.0-logrotate.patch b/SOURCES/vsftpd-3.0.0-logrotate.patch new file mode 100644 index 0000000..06dc6b9 --- /dev/null +++ b/SOURCES/vsftpd-3.0.0-logrotate.patch @@ -0,0 +1,13 @@ +diff -up vsftpd-3.0.0/RedHat/vsftpd.log.logrotate vsftpd-3.0.0/RedHat/vsftpd.log +--- vsftpd-3.0.0/RedHat/vsftpd.log.logrotate 2012-07-17 11:08:28.484061640 +0200 ++++ vsftpd-3.0.0/RedHat/vsftpd.log 2012-07-17 11:09:08.000020510 +0200 +@@ -3,3 +3,9 @@ + nocompress + missingok + } ++ ++/var/log/xferlog { ++ # ftpd doesn't handle SIGHUP properly ++ nocompress ++ missingok ++} diff --git a/SOURCES/vsftpd-3.0.0-tz.patch b/SOURCES/vsftpd-3.0.0-tz.patch new file mode 100644 index 0000000..81a083d --- /dev/null +++ b/SOURCES/vsftpd-3.0.0-tz.patch @@ -0,0 +1,146 @@ +diff -up vsftpd-2.2.2/sysutil.c.tz vsftpd-2.2.2/sysutil.c +--- vsftpd-2.2.2/sysutil.c.tz 2012-04-26 12:45:21.095145878 +0200 ++++ vsftpd-2.2.2/sysutil.c 2012-04-26 12:48:08.729618686 +0200 +@@ -26,8 +26,10 @@ + /* For Linux, this adds nothing :-) */ + #include "port/porting_junk.h" + ++#define F_LOCALTIME "/etc/localtime" ++#define BUFTZSIZ 64 ++ + #include +-#include + #include + #include + #include +@@ -55,6 +57,11 @@ + #include + #include + #include ++ ++#ifndef __USE_GNU ++ #define __USE_GNU ++#endif ++#include + + /* Private variables to this file */ + /* Current umask() */ +@@ -2558,49 +2565,92 @@ error: + die("reopening standard file descriptors to /dev/null failed"); + } + ++char* vsf_sysutil_get_tz() ++{ ++ char *ret_tz = NULL; ++ char buff[BUFTZSIZ]; ++ off_t s_pos, e_pos; ++ size_t rcnt, rest; ++ int fd; ++ ++ if ((fd = open(F_LOCALTIME, O_RDONLY)) > -1) ++ { ++ if ((e_pos = lseek(fd, 0, SEEK_END)) <= 0) ++ { ++ close(fd); ++ return NULL; ++ } ++ s_pos = e_pos > BUFTZSIZ ? e_pos - BUFTZSIZ : 0; ++ lseek(fd, s_pos, SEEK_SET); ++ rcnt = read(fd, buff, BUFTZSIZ); ++ ++ if (rcnt && buff[rcnt-1] == '\n') ++ { ++ buff[rcnt-1] = 0; ++ e_pos--; ++ } ++ ++ do { ++ char *nl = memrchr(buff, '\n', rcnt); ++ if (rcnt && nl) ++ { ++ int offset = (++nl) - buff; ++ int len = e_pos - s_pos - offset; ++ if (len) ++ { ++ lseek(fd, s_pos + offset, SEEK_SET); ++ ret_tz = calloc(1, len+4); ++ memcpy(ret_tz, "TZ=", 3); ++ rcnt = read(fd, ret_tz+3, len); ++ } ++ break; ++ } ++ if (!s_pos) ++ { ++ break; ++ } ++ rest = s_pos > BUFTZSIZ ? s_pos - BUFTZSIZ : 0; ++ s_pos -= rest; ++ lseek(fd, s_pos, SEEK_SET); ++ rcnt = read(fd, buff, rest); ++ } while (rcnt > 0); ++ ++ close (fd); ++ } ++ ++ return ret_tz; ++} ++ + void + vsf_sysutil_tzset(void) + { + int retval; +- char tzbuf[sizeof("+HHMM!")]; ++ char *tz=NULL, tzbuf[sizeof("+HHMM!")]; + time_t the_time = time(NULL); + struct tm* p_tm; ++ ++ /* Set our timezone in the TZ environment variable to cater for the fact ++ * that modern glibc does not cache /etc/localtime (which becomes inaccessible ++ * when we chroot(). ++ */ ++ tz = vsf_sysutil_get_tz();; ++ if (tz) ++ { ++ putenv(tz); ++ } + tzset(); + p_tm = localtime(&the_time); + if (p_tm == NULL) + { + die("localtime"); + } +- /* Set our timezone in the TZ environment variable to cater for the fact +- * that modern glibc does not cache /etc/localtime (which becomes inaccessible +- * when we chroot(). +- */ + retval = strftime(tzbuf, sizeof(tzbuf), "%z", p_tm); + tzbuf[sizeof(tzbuf) - 1] = '\0'; + if (retval == 5) + { +- /* Static because putenv() does not copy the string. */ +- static char envtz[sizeof("TZ=UTC-hh:mm")]; +- /* Insert a colon so we have e.g. -05:00 instead of -0500 */ +- tzbuf[5] = tzbuf[4]; +- tzbuf[4] = tzbuf[3]; +- tzbuf[3] = ':'; +- /* Invert the sign - we just got the offset _from_ UTC but for TZ, we need +- * the offset _to_ UTC. +- */ +- if (tzbuf[0] == '+') +- { +- tzbuf[0] = '-'; +- } +- else +- { +- tzbuf[0] = '+'; +- } +- snprintf(envtz, sizeof(envtz), "TZ=UTC%s", tzbuf); +- putenv(envtz); + s_timezone = ((tzbuf[1] - '0') * 10 + (tzbuf[2] - '0')) * 60 * 60; +- s_timezone += ((tzbuf[4] - '0') * 10 + (tzbuf[5] - '0')) * 60; +- if (tzbuf[0] == '-') ++ s_timezone += ((tzbuf[3] - '0') * 10 + (tzbuf[4] - '0')) * 60; ++ if (tzbuf[0] == '+') + { + s_timezone *= -1; + } diff --git a/SOURCES/vsftpd-3.0.0-xferlog.patch b/SOURCES/vsftpd-3.0.0-xferlog.patch new file mode 100644 index 0000000..54c563b --- /dev/null +++ b/SOURCES/vsftpd-3.0.0-xferlog.patch @@ -0,0 +1,12 @@ +diff -up vsftpd-3.0.0/vsftpd.conf.xferlog vsftpd-3.0.0/vsftpd.conf +--- vsftpd-3.0.0/vsftpd.conf.xferlog 2012-07-17 10:38:14.022601998 +0200 ++++ vsftpd-3.0.0/vsftpd.conf 2012-07-17 10:41:09.311073484 +0200 +@@ -50,7 +50,7 @@ connect_from_port_20=YES + # + # You may override where the log file goes if you like. The default is shown + # below. +-#xferlog_file=/var/log/vsftpd.log ++#xferlog_file=/var/log/xferlog + # + # If you want, you can have your log file in standard ftpd xferlog format. + # Note that the default log file location is /var/log/xferlog in this case. diff --git a/SOURCES/vsftpd-3.0.2-defaulttls.patch b/SOURCES/vsftpd-3.0.2-defaulttls.patch new file mode 100644 index 0000000..c7850fa --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-defaulttls.patch @@ -0,0 +1,12 @@ +diff -up vsftpd-3.0.2/features.c.defaulttls vsftpd-3.0.2/features.c +--- vsftpd-3.0.2/features.c.defaulttls 2017-03-23 13:52:03.775952599 +0100 ++++ vsftpd-3.0.2/features.c 2017-03-23 13:55:37.919726920 +0100 +@@ -22,7 +22,7 @@ handle_feat(struct vsf_session* p_sess) + { + vsf_cmdio_write_raw(p_sess, " AUTH SSL\r\n"); + } +- if (tunable_tlsv1) ++ if (tunable_tlsv1 || tunable_tlsv1_1 || tunable_tlsv1_2) + { + vsf_cmdio_write_raw(p_sess, " AUTH TLS\r\n"); + } diff --git a/SOURCES/vsftpd-3.0.2-del-upl.patch b/SOURCES/vsftpd-3.0.2-del-upl.patch new file mode 100644 index 0000000..15f511e --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-del-upl.patch @@ -0,0 +1,118 @@ +diff --git a/ftpcodes.h b/ftpcodes.h +index 93290c0..995788a 100644 +--- a/ftpcodes.h ++++ b/ftpcodes.h +@@ -15,7 +15,8 @@ + #define FTP_PBSZOK 200 + #define FTP_PROTOK 200 + #define FTP_OPTSOK 200 +-#define FTP_ALLOOK 202 ++#define FTP_ALLOOK 200 ++#define FTP_ALLOIGN 202 + #define FTP_FEAT 211 + #define FTP_STATOK 211 + #define FTP_SIZEOK 213 +diff --git a/ftpdataio.c b/ftpdataio.c +index ffb2e23..08b0628 100644 +--- a/ftpdataio.c ++++ b/ftpdataio.c +@@ -244,6 +244,10 @@ init_data_sock_params(struct vsf_session* p_sess, int sock_fd) + /* Start the timeout monitor */ + vsf_sysutil_install_io_handler(handle_io, p_sess); + start_data_alarm(p_sess); ++ if(tunable_delete_failed_uploads) ++ { ++ vsf_sysutil_rcvtimeo(sock_fd); ++ } + } + + static void +@@ -617,6 +621,10 @@ do_file_recv(struct vsf_session* p_sess, int file_fd, int is_ascii) + else if (retval == 0 && !prev_cr) + { + /* Transfer done, nifty */ ++ if (tunable_delete_failed_uploads && ++ !is_ascii && p_sess->upload_size > 0 && ++ p_sess->upload_size != ret_struct.transferred) ++ ret_struct.retval = -2; + return ret_struct; + } + num_to_write = (unsigned int) retval; +diff --git a/main.c b/main.c +index f1e2f69..f039081 100644 +--- a/main.c ++++ b/main.c +@@ -44,7 +44,7 @@ main(int argc, const char* argv[]) + /* Login */ + 1, 0, INIT_MYSTR, INIT_MYSTR, + /* Protocol state */ +- 0, 1, INIT_MYSTR, 0, 0, ++ 0, 0, 1, INIT_MYSTR, 0, 0, + /* HTTP hacks */ + 0, INIT_MYSTR, + /* Session state */ +diff --git a/postlogin.c b/postlogin.c +index 8a83164..4ca7f2c 100644 +--- a/postlogin.c ++++ b/postlogin.c +@@ -356,7 +356,14 @@ process_post_login(struct vsf_session* p_sess) + } + else if (str_equal_text(&p_sess->ftp_cmd_str, "ALLO")) + { +- vsf_cmdio_write(p_sess, FTP_ALLOOK, "ALLO command ignored."); ++ if (tunable_delete_failed_uploads && !p_sess->is_ascii) ++ { ++ p_sess->upload_size = (filesize_t)vsf_sysutil_atoi(str_getbuf(&p_sess->ftp_cmd_str)+5); ++ vsf_cmdio_write(p_sess, FTP_ALLOOK, "The filesize has been allocated."); ++ } ++ else { ++ vsf_cmdio_write(p_sess, FTP_ALLOIGN, "ALLO command ignored."); ++ } + } + else if (str_equal_text(&p_sess->ftp_cmd_str, "REIN")) + { +diff --git a/session.h b/session.h +index 8123ffc..b60e098 100644 +--- a/session.h ++++ b/session.h +@@ -41,6 +41,7 @@ struct vsf_session + struct mystr anon_pass_str; + + /* Details of the FTP protocol state */ ++ filesize_t upload_size; + filesize_t restart_pos; + int is_ascii; + struct mystr rnfr_filename_str; +diff --git a/sysutil.c b/sysutil.c +index af41e32..927174f 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -681,6 +681,16 @@ vsf_sysutil_activate_keepalive(int fd) + } + + void ++vsf_sysutil_rcvtimeo(int fd) ++{ ++ struct timeval tv; ++ ++ tv.tv_sec = tunable_data_connection_timeout; ++ tv.tv_usec = 0; ++ setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); ++} ++ ++void + vsf_sysutil_activate_reuseaddr(int fd) + { + int reuseaddr = 1; +diff --git a/sysutil.h b/sysutil.h +index 959fdf4..bb55063 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -265,6 +265,7 @@ void vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr** p_sockptr, + const char* p_name); + /* Option setting on sockets */ + void vsf_sysutil_activate_keepalive(int fd); ++void vsf_sysutil_rcvtimeo(int fd); + void vsf_sysutil_set_iptos_throughput(int fd); + void vsf_sysutil_activate_reuseaddr(int fd); + void vsf_sysutil_set_nodelay(int fd); diff --git a/SOURCES/vsftpd-3.0.2-dh.patch b/SOURCES/vsftpd-3.0.2-dh.patch new file mode 100644 index 0000000..13151cc --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-dh.patch @@ -0,0 +1,205 @@ +diff -up vsftpd-3.0.2/parseconf.c.dh vsftpd-3.0.2/parseconf.c +--- vsftpd-3.0.2/parseconf.c.dh 2014-06-04 10:24:57.512748573 +0200 ++++ vsftpd-3.0.2/parseconf.c 2014-06-04 10:24:57.532748566 +0200 +@@ -175,6 +175,7 @@ parseconf_str_array[] = + { "email_password_file", &tunable_email_password_file }, + { "rsa_cert_file", &tunable_rsa_cert_file }, + { "dsa_cert_file", &tunable_dsa_cert_file }, ++ { "dh_param_file", &tunable_dh_param_file }, + { "ssl_ciphers", &tunable_ssl_ciphers }, + { "rsa_private_key_file", &tunable_rsa_private_key_file }, + { "dsa_private_key_file", &tunable_dsa_private_key_file }, +diff -up vsftpd-3.0.2/ssl.c.dh vsftpd-3.0.2/ssl.c +--- vsftpd-3.0.2/ssl.c.dh 2012-04-03 02:23:42.000000000 +0200 ++++ vsftpd-3.0.2/ssl.c 2014-06-04 10:24:57.533748565 +0200 +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + +@@ -38,6 +40,7 @@ static void setup_bio_callbacks(); + static long bio_callback( + BIO* p_bio, int oper, const char* p_arg, int argi, long argl, long retval); + static int ssl_verify_callback(int verify_ok, X509_STORE_CTX* p_ctx); ++static DH *ssl_tmp_dh_callback(SSL *ssl, int is_export, int keylength); + static int ssl_cert_digest( + SSL* p_ssl, struct vsf_session* p_sess, struct mystr* p_str); + static void maybe_log_shutdown_state(struct vsf_session* p_sess); +@@ -51,6 +54,60 @@ static int ssl_read_common(struct vsf_se + static int ssl_inited; + static struct mystr debug_str; + ++ ++// Grab prime number from OpenSSL; ++// (get_rfc*) for all available primes. ++// wraps selection of comparable algorithm strength ++#if !defined(match_dh_bits) ++ #define match_dh_bits(keylen) \ ++ keylen >= 8191 ? 8192 : \ ++ keylen >= 6143 ? 6144 : \ ++ keylen >= 4095 ? 4096 : \ ++ keylen >= 3071 ? 3072 : \ ++ keylen >= 2047 ? 2048 : \ ++ keylen >= 1535 ? 1536 : \ ++ keylen >= 1023 ? 1024 : 768 ++#endif ++ ++#if !defined(DH_get_prime) ++ BIGNUM * ++ DH_get_prime(int bits) ++ { ++ switch (bits) { ++ case 768: return get_rfc2409_prime_768(NULL); ++ case 1024: return get_rfc2409_prime_1024(NULL); ++ case 1536: return get_rfc3526_prime_1536(NULL); ++ case 2048: return get_rfc3526_prime_2048(NULL); ++ case 3072: return get_rfc3526_prime_3072(NULL); ++ case 4096: return get_rfc3526_prime_4096(NULL); ++ case 6144: return get_rfc3526_prime_6144(NULL); ++ case 8192: return get_rfc3526_prime_8192(NULL); ++ // shouldn't happen when used match_dh_bits; strict compiler ++ default: return NULL; ++ } ++} ++#endif ++ ++#if !defined(DH_get_dh) ++ // Grab DH parameters ++ DH * ++ DH_get_dh(int size) ++ { ++ DH *dh = DH_new(); ++ if (!dh) { ++ return NULL; ++ } ++ dh->p = DH_get_prime(match_dh_bits(size)); ++ BN_dec2bn(&dh->g, "2"); ++ if (!dh->p || !dh->g) ++ { ++ DH_free(dh); ++ return NULL; ++ } ++ return dh; ++ } ++#endif ++ + void + ssl_init(struct vsf_session* p_sess) + { +@@ -65,7 +122,7 @@ ssl_init(struct vsf_session* p_sess) + { + die("SSL: could not allocate SSL context"); + } +- options = SSL_OP_ALL; ++ options = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE; + if (!tunable_sslv2) + { + options |= SSL_OP_NO_SSLv2; +@@ -111,6 +168,25 @@ ssl_init(struct vsf_session* p_sess) + die("SSL: cannot load DSA private key"); + } + } ++ if (tunable_dh_param_file) ++ { ++ BIO *bio; ++ DH *dhparams = NULL; ++ if ((bio = BIO_new_file(tunable_dh_param_file, "r")) == NULL) ++ { ++ die("SSL: cannot load custom DH params"); ++ } ++ else ++ { ++ dhparams = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); ++ BIO_free(bio); ++ ++ if (!SSL_CTX_set_tmp_dh(p_ctx, dhparams)) ++ { ++ die("SSL: setting custom DH params failed"); ++ } ++ } ++ } + if (tunable_ssl_ciphers && + SSL_CTX_set_cipher_list(p_ctx, tunable_ssl_ciphers) != 1) + { +@@ -156,6 +232,9 @@ ssl_init(struct vsf_session* p_sess) + /* Ensure cached session doesn't expire */ + SSL_CTX_set_timeout(p_ctx, INT_MAX); + } ++ ++ SSL_CTX_set_tmp_dh_callback(p_ctx, ssl_tmp_dh_callback); ++ + p_sess->p_ssl_ctx = p_ctx; + ssl_inited = 1; + } +@@ -675,6 +754,18 @@ ssl_verify_callback(int verify_ok, X509_ + return 1; + } + ++#define UNUSED(x) ( (void)(x) ) ++ ++static DH * ++ssl_tmp_dh_callback(SSL *ssl, int is_export, int keylength) ++{ ++ // strict compiler bypassing ++ UNUSED(ssl); ++ UNUSED(is_export); ++ ++ return DH_get_dh(keylength); ++} ++ + void + ssl_add_entropy(struct vsf_session* p_sess) + { +diff -up vsftpd-3.0.2/tunables.c.dh vsftpd-3.0.2/tunables.c +--- vsftpd-3.0.2/tunables.c.dh 2014-06-04 10:24:57.530748566 +0200 ++++ vsftpd-3.0.2/tunables.c 2014-06-04 10:24:57.533748565 +0200 +@@ -139,6 +139,7 @@ const char* tunable_user_sub_token; + const char* tunable_email_password_file; + const char* tunable_rsa_cert_file; + const char* tunable_dsa_cert_file; ++const char* tunable_dh_param_file; + const char* tunable_ssl_ciphers; + const char* tunable_rsa_private_key_file; + const char* tunable_dsa_private_key_file; +@@ -286,7 +287,9 @@ tunables_load_defaults() + install_str_setting("/usr/share/ssl/certs/vsftpd.pem", + &tunable_rsa_cert_file); + install_str_setting(0, &tunable_dsa_cert_file); +- install_str_setting("AES128-SHA:DES-CBC3-SHA", &tunable_ssl_ciphers); ++ install_str_setting(0, &tunable_dh_param_file); ++ install_str_setting("AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA", ++ &tunable_ssl_ciphers); + install_str_setting(0, &tunable_rsa_private_key_file); + install_str_setting(0, &tunable_dsa_private_key_file); + install_str_setting(0, &tunable_ca_certs_file); +diff -up vsftpd-3.0.2/tunables.h.dh vsftpd-3.0.2/tunables.h +--- vsftpd-3.0.2/tunables.h.dh 2014-06-04 10:24:57.511748573 +0200 ++++ vsftpd-3.0.2/tunables.h 2014-06-04 10:24:57.533748565 +0200 +@@ -141,6 +141,7 @@ extern const char* tunable_user_sub_toke + extern const char* tunable_email_password_file; + extern const char* tunable_rsa_cert_file; + extern const char* tunable_dsa_cert_file; ++extern const char* tunable_dh_param_file; + extern const char* tunable_ssl_ciphers; + extern const char* tunable_rsa_private_key_file; + extern const char* tunable_dsa_private_key_file; +diff -up vsftpd-3.0.2/vsftpd.conf.5.dh vsftpd-3.0.2/vsftpd.conf.5 +--- vsftpd-3.0.2/vsftpd.conf.5.dh 2014-06-04 10:24:57.523748569 +0200 ++++ vsftpd-3.0.2/vsftpd.conf.5 2014-06-04 10:24:57.533748565 +0200 +@@ -884,6 +884,12 @@ to be in the same file as the certificat + + Default: (none) + .TP ++.B dh_param_file ++This option specifies the location of the custom parameters used for ++ephemeral Diffie-Hellman key exchange in SSL. ++ ++Default: (none - use built in parameters appropriate for certificate key size) ++.TP + .B email_password_file + This option can be used to provide an alternate file for usage by the + .BR secure_email_list_enable diff --git a/SOURCES/vsftpd-3.0.2-docupd.patch b/SOURCES/vsftpd-3.0.2-docupd.patch new file mode 100644 index 0000000..6c03703 --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-docupd.patch @@ -0,0 +1,49 @@ +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 10e9f45..cf1ae34 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -653,6 +653,21 @@ change it with the setting + .BR xferlog_file . + + Default: NO ++.TP ++.B isolate_network ++If enabled, use CLONE_NEWNET to isolate the untrusted processes so that ++they can't do arbitrary connect() and instead have to ask the privileged ++process for sockets ( ++.BR port_promiscuous ++have to be disabled). ++ ++Default: YES ++.TP ++.B isolate ++If enabled, use CLONE_NEWPID and CLONE_NEWIPC to isolate processes to their ++ipc and pid namespaces. So separated processes can not interact with each other. ++ ++Default: YES + + .SH NUMERIC OPTIONS + Below is a list of numeric options. A numeric option must be set to a non +@@ -750,8 +765,9 @@ Default: 077 + .B max_clients + If vsftpd is in standalone mode, this is the maximum number of clients which + may be connected. Any additional clients connecting will get an error message. ++The value 0 switches off the limit. + +-Default: 0 (unlimited) ++Default: 2000 + .TP + .B max_login_fails + After this many login failures, the session is killed. +@@ -761,9 +777,9 @@ Default: 3 + .B max_per_ip + If vsftpd is in standalone mode, this is the maximum number of clients which + may be connected from the same source internet address. A client will get an +-error message if they go over this limit. ++error message if they go over this limit. The value 0 switches off the limit. + +-Default: 0 (unlimited) ++Default: 50 + .TP + .B pasv_max_port + The maximum port to allocate for PASV style data connections. Can be used to diff --git a/SOURCES/vsftpd-3.0.2-ecdh.patch b/SOURCES/vsftpd-3.0.2-ecdh.patch new file mode 100644 index 0000000..629e878 --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-ecdh.patch @@ -0,0 +1,115 @@ +diff -up vsftpd-3.0.2/parseconf.c.ecdh vsftpd-3.0.2/parseconf.c +--- vsftpd-3.0.2/parseconf.c.ecdh 2014-06-04 10:25:36.786735755 +0200 ++++ vsftpd-3.0.2/parseconf.c 2014-06-04 10:25:36.812735747 +0200 +@@ -176,6 +176,7 @@ parseconf_str_array[] = + { "rsa_cert_file", &tunable_rsa_cert_file }, + { "dsa_cert_file", &tunable_dsa_cert_file }, + { "dh_param_file", &tunable_dh_param_file }, ++ { "ecdh_param_file", &tunable_ecdh_param_file }, + { "ssl_ciphers", &tunable_ssl_ciphers }, + { "rsa_private_key_file", &tunable_rsa_private_key_file }, + { "dsa_private_key_file", &tunable_dsa_private_key_file }, +diff -up vsftpd-3.0.2/ssl.c.ecdh vsftpd-3.0.2/ssl.c +--- vsftpd-3.0.2/ssl.c.ecdh 2014-06-04 10:25:36.786735755 +0200 ++++ vsftpd-3.0.2/ssl.c 2014-06-04 10:25:36.812735747 +0200 +@@ -122,7 +122,7 @@ ssl_init(struct vsf_session* p_sess) + { + die("SSL: could not allocate SSL context"); + } +- options = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE; ++ options = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE; + if (!tunable_sslv2) + { + options |= SSL_OP_NO_SSLv2; +@@ -235,6 +235,41 @@ ssl_init(struct vsf_session* p_sess) + + SSL_CTX_set_tmp_dh_callback(p_ctx, ssl_tmp_dh_callback); + ++ if (tunable_ecdh_param_file) ++ { ++ BIO *bio; ++ int nid; ++ EC_GROUP *ecparams = NULL; ++ EC_KEY *eckey; ++ ++ if ((bio = BIO_new_file(tunable_ecdh_param_file, "r")) == NULL) ++ die("SSL: cannot load custom ec params"); ++ else ++ { ++ ecparams = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL); ++ BIO_free(bio); ++ ++ if (ecparams && (nid = EC_GROUP_get_curve_name(ecparams)) && ++ (eckey = EC_KEY_new_by_curve_name(nid))) ++ { ++ if (!SSL_CTX_set_tmp_ecdh(p_ctx, eckey)) ++ die("SSL: setting custom EC params failed"); ++ } ++ else ++ { ++ die("SSL: getting ec group or key failed"); ++ } ++ } ++ } ++ else ++ { ++#if defined(SSL_CTX_set_ecdh_auto) ++ SSL_CTX_set_ecdh_auto(p_ctx, 1); ++#else ++ SSL_CTX_set_tmp_ecdh(p_ctx, EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); ++#endif ++ } ++ + p_sess->p_ssl_ctx = p_ctx; + ssl_inited = 1; + } +diff -up vsftpd-3.0.2/tunables.c.ecdh vsftpd-3.0.2/tunables.c +--- vsftpd-3.0.2/tunables.c.ecdh 2014-06-04 10:25:36.787735755 +0200 ++++ vsftpd-3.0.2/tunables.c 2014-06-04 10:25:36.813735747 +0200 +@@ -140,6 +140,7 @@ const char* tunable_email_password_file; + const char* tunable_rsa_cert_file; + const char* tunable_dsa_cert_file; + const char* tunable_dh_param_file; ++const char* tunable_ecdh_param_file; + const char* tunable_ssl_ciphers; + const char* tunable_rsa_private_key_file; + const char* tunable_dsa_private_key_file; +@@ -288,7 +289,8 @@ tunables_load_defaults() + &tunable_rsa_cert_file); + install_str_setting(0, &tunable_dsa_cert_file); + install_str_setting(0, &tunable_dh_param_file); +- install_str_setting("AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA", ++ install_str_setting(0, &tunable_ecdh_param_file); ++ install_str_setting("AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA", + &tunable_ssl_ciphers); + install_str_setting(0, &tunable_rsa_private_key_file); + install_str_setting(0, &tunable_dsa_private_key_file); +diff -up vsftpd-3.0.2/tunables.h.ecdh vsftpd-3.0.2/tunables.h +--- vsftpd-3.0.2/tunables.h.ecdh 2014-06-04 10:25:36.787735755 +0200 ++++ vsftpd-3.0.2/tunables.h 2014-06-04 10:25:36.813735747 +0200 +@@ -142,6 +142,7 @@ extern const char* tunable_email_passwor + extern const char* tunable_rsa_cert_file; + extern const char* tunable_dsa_cert_file; + extern const char* tunable_dh_param_file; ++extern const char* tunable_ecdh_param_file; + extern const char* tunable_ssl_ciphers; + extern const char* tunable_rsa_private_key_file; + extern const char* tunable_dsa_private_key_file; +diff -up vsftpd-3.0.2/vsftpd.conf.5.ecdh vsftpd-3.0.2/vsftpd.conf.5 +--- vsftpd-3.0.2/vsftpd.conf.5.ecdh 2014-06-04 10:25:36.787735755 +0200 ++++ vsftpd-3.0.2/vsftpd.conf.5 2014-06-04 10:25:36.813735747 +0200 +@@ -890,6 +890,14 @@ ephemeral Diffie-Hellman key exchange in + + Default: (none - use built in parameters appropriate for certificate key size) + .TP ++.B ecdh_param_file ++This option specifies the location of custom parameters for ephemeral ++Elliptic Curve Diffie-Hellman (ECDH) key exchange. ++ ++Default: (none - use built in parameters, NIST P-256 with OpenSSL 1.0.1 and ++automatically selected curve based on client preferences with OpenSSL 1.0.2 ++and later) ++.TP + .B email_password_file + This option can be used to provide an alternate file for usage by the + .BR secure_email_list_enable diff --git a/SOURCES/vsftpd-3.0.2-mrate.patch b/SOURCES/vsftpd-3.0.2-mrate.patch new file mode 100644 index 0000000..d1495c2 --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-mrate.patch @@ -0,0 +1,72 @@ +diff -up vsftpd-3.0.2/ftpdataio.c.mrate vsftpd-3.0.2/ftpdataio.c +--- vsftpd-3.0.2/ftpdataio.c.mrate 2014-03-06 16:22:44.547366196 +0100 ++++ vsftpd-3.0.2/ftpdataio.c 2014-03-07 10:14:33.681097022 +0100 +@@ -251,7 +251,7 @@ handle_io(int retval, int fd, void* p_pr + { + long curr_sec; + long curr_usec; +- unsigned int bw_rate; ++ unsigned long bw_rate; + double elapsed; + double pause_time; + double rate_ratio; +@@ -278,19 +278,16 @@ handle_io(int retval, int fd, void* p_pr + { + elapsed = (double) 0.01; + } +- bw_rate = (unsigned int) ((double) retval / elapsed); +- if (bw_rate <= p_sess->bw_rate_max) ++ p_sess->bw_retval += retval; ++ bw_rate = (unsigned long) ((double) p_sess->bw_retval / elapsed); ++ if (bw_rate <= p_sess->bw_rate_max || p_sess->bw_retval < (unsigned long)(10*retval)) + { +- p_sess->bw_send_start_sec = curr_sec; +- p_sess->bw_send_start_usec = curr_usec; + return; + } + /* Tut! Rate exceeded, calculate a pause to bring things back into line */ + rate_ratio = (double) bw_rate / (double) p_sess->bw_rate_max; + pause_time = (rate_ratio - (double) 1) * elapsed; + vsf_sysutil_sleep(pause_time); +- p_sess->bw_send_start_sec = vsf_sysutil_get_time_sec(); +- p_sess->bw_send_start_usec = vsf_sysutil_get_time_usec(); + } + + int +@@ -443,6 +440,9 @@ struct vsf_transfer_ret + vsf_ftpdataio_transfer_file(struct vsf_session* p_sess, int remote_fd, + int file_fd, int is_recv, int is_ascii) + { ++ p_sess->bw_send_start_sec = vsf_sysutil_get_time_sec(); ++ p_sess->bw_send_start_usec = vsf_sysutil_get_time_usec(); ++ p_sess->bw_retval = 0; + if (!is_recv) + { + if (is_ascii || p_sess->data_use_ssl) +diff -up vsftpd-3.0.2/main.c.mrate vsftpd-3.0.2/main.c +--- vsftpd-3.0.2/main.c.mrate 2014-03-06 16:22:28.475362449 +0100 ++++ vsftpd-3.0.2/main.c 2014-03-06 16:24:27.056384556 +0100 +@@ -40,7 +40,7 @@ main(int argc, const char* argv[]) + /* Control connection */ + 0, 0, 0, 0, 0, + /* Data connection */ +- -1, 0, -1, 0, 0, 0, 0, ++ -1, 0, -1, 0, 0, 0, 0, 0, + /* Login */ + 1, 0, INIT_MYSTR, INIT_MYSTR, + /* Protocol state */ +diff -up vsftpd-3.0.2/session.h.mrate vsftpd-3.0.2/session.h +--- vsftpd-3.0.2/session.h.mrate 2014-03-06 16:22:15.376359081 +0100 ++++ vsftpd-3.0.2/session.h 2014-03-06 16:23:58.860379868 +0100 +@@ -29,9 +29,10 @@ struct vsf_session + struct vsf_sysutil_sockaddr* p_port_sockaddr; + int data_fd; + int data_progress; +- unsigned int bw_rate_max; ++ unsigned long bw_rate_max; + long bw_send_start_sec; + long bw_send_start_usec; ++ unsigned long bw_retval; + + /* Details of the login */ + int is_anonymous; diff --git a/SOURCES/vsftpd-3.0.2-reverse-lookup.patch b/SOURCES/vsftpd-3.0.2-reverse-lookup.patch new file mode 100644 index 0000000..8f5e5a6 --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-reverse-lookup.patch @@ -0,0 +1,85 @@ +diff -up vsftpd-3.0.2/parseconf.c.lookup vsftpd-3.0.2/parseconf.c +--- vsftpd-3.0.2/parseconf.c.lookup 2014-04-17 10:01:50.862951491 +0200 ++++ vsftpd-3.0.2/parseconf.c 2014-04-17 10:02:42.343955443 +0200 +@@ -91,6 +91,7 @@ parseconf_bool_array[] = + { "mdtm_write", &tunable_mdtm_write }, + { "lock_upload_files", &tunable_lock_upload_files }, + { "pasv_addr_resolve", &tunable_pasv_addr_resolve }, ++ { "reverse_lookup_enable", &tunable_reverse_lookup_enable }, + { "userlist_log", &tunable_userlist_log }, + { "debug_ssl", &tunable_debug_ssl }, + { "require_cert", &tunable_require_cert }, +diff -up vsftpd-3.0.2/sysdeputil.c.lookup vsftpd-3.0.2/sysdeputil.c +--- vsftpd-3.0.2/sysdeputil.c.lookup 2014-04-17 09:57:02.111933144 +0200 ++++ vsftpd-3.0.2/sysdeputil.c 2014-04-17 10:01:31.069950498 +0200 +@@ -354,12 +354,16 @@ vsf_sysdep_check_auth(struct mystr* p_us + return 0; + } + #ifdef PAM_RHOST +- sin.sin_addr.s_addr = inet_addr(str_getbuf(p_remote_host)); +- host = gethostbyaddr((char*)&sin.sin_addr.s_addr,sizeof(struct in_addr),AF_INET); +- if (host != (struct hostent*)0) +- retval = pam_set_item(s_pamh, PAM_RHOST, host->h_name); +- else ++ if (tunable_reverse_lookup_enable) { ++ sin.sin_addr.s_addr = inet_addr(str_getbuf(p_remote_host)); ++ host = gethostbyaddr((char*)&sin.sin_addr.s_addr,sizeof(struct in_addr),AF_INET); ++ if (host != (struct hostent*)0) ++ retval = pam_set_item(s_pamh, PAM_RHOST, host->h_name); ++ else ++ retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); ++ } else { + retval = pam_set_item(s_pamh, PAM_RHOST, str_getbuf(p_remote_host)); ++ } + if (retval != PAM_SUCCESS) + { + (void) pam_end(s_pamh, retval); +diff -up vsftpd-3.0.2/tunables.c.lookup vsftpd-3.0.2/tunables.c +--- vsftpd-3.0.2/tunables.c.lookup 2014-04-17 10:03:22.766958324 +0200 ++++ vsftpd-3.0.2/tunables.c 2014-04-17 10:04:52.004964675 +0200 +@@ -72,6 +72,7 @@ int tunable_force_anon_data_ssl; + int tunable_mdtm_write; + int tunable_lock_upload_files; + int tunable_pasv_addr_resolve; ++int tunable_reverse_lookup_enable; + int tunable_userlist_log; + int tunable_debug_ssl; + int tunable_require_cert; +@@ -213,6 +214,7 @@ tunables_load_defaults() + tunable_mdtm_write = 1; + tunable_lock_upload_files = 1; + tunable_pasv_addr_resolve = 0; ++ tunable_reverse_lookup_enable = 1; + tunable_userlist_log = 0; + tunable_debug_ssl = 0; + tunable_require_cert = 0; +diff -up vsftpd-3.0.2/tunables.h.lookup vsftpd-3.0.2/tunables.h +--- vsftpd-3.0.2/tunables.h.lookup 2014-04-17 10:03:27.405958676 +0200 ++++ vsftpd-3.0.2/tunables.h 2014-04-17 10:04:22.763963824 +0200 +@@ -73,6 +73,7 @@ extern int tunable_force_anon_data_ssl; + extern int tunable_mdtm_write; /* Allow MDTM to set timestamps */ + extern int tunable_lock_upload_files; /* Lock uploading files */ + extern int tunable_pasv_addr_resolve; /* DNS resolve pasv_addr */ ++extern int tunable_reverse_lookup_enable; /* Get hostname before pam auth */ + extern int tunable_userlist_log; /* Log every failed login attempt */ + extern int tunable_debug_ssl; /* Verbose SSL logging */ + extern int tunable_require_cert; /* SSL client cert required */ +diff -up vsftpd-3.0.2/vsftpd.conf.5.lookup vsftpd-3.0.2/vsftpd.conf.5 +--- vsftpd-3.0.2/vsftpd.conf.5.lookup 2014-04-17 10:05:30.956969003 +0200 ++++ vsftpd-3.0.2/vsftpd.conf.5 2014-04-17 10:06:36.586971828 +0200 +@@ -425,6 +425,15 @@ http://scarybeastsecurity.blogspot.com/2 + + Default: YES + .TP ++.B reverse_lookup_enable ++Set to YES if you want vsftpd to transform the ip address into the hostname, ++before pam authentication. This is useful if you use pam_access including the ++hostname. If you want vsftpd to run on the environment where the reverse lookup ++for some hostname is available and the name server doesn't respond for a while, ++you should set this to NO to avoid a performance issue. ++ ++Default: YES ++.TP + .B run_as_launching_user + Set to YES if you want vsftpd to run as the user which launched vsftpd. This is + useful where root access is not available. MASSIVE WARNING! Do NOT enable this diff --git a/SOURCES/vsftpd-3.0.2-seccomp.patch b/SOURCES/vsftpd-3.0.2-seccomp.patch new file mode 100644 index 0000000..29618de --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-seccomp.patch @@ -0,0 +1,12 @@ +diff -up vsftpd-3.0.2/tunables.c.seccomp_default vsftpd-3.0.2/tunables.c +--- vsftpd-3.0.2/tunables.c.seccomp_default 2012-11-21 10:07:23.336130468 +0100 ++++ vsftpd-3.0.2/tunables.c 2012-11-21 10:07:31.329130552 +0100 +@@ -228,7 +228,7 @@ tunables_load_defaults() + tunable_isolate_network = 1; + tunable_ftp_enable = 1; + tunable_http_enable = 0; +- tunable_seccomp_sandbox = 1; ++ tunable_seccomp_sandbox = 0; + tunable_allow_writeable_chroot = 0; + + tunable_accept_timeout = 60; diff --git a/SOURCES/vsftpd-3.0.2-uint-uidgid.patch b/SOURCES/vsftpd-3.0.2-uint-uidgid.patch new file mode 100644 index 0000000..452bb57 --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-uint-uidgid.patch @@ -0,0 +1,234 @@ +diff --git a/ls.c b/ls.c +index 0898576..e9829d9 100644 +--- a/ls.c ++++ b/ls.c +@@ -502,7 +502,7 @@ build_dir_line(struct mystr* p_str, const struct mystr* p_filename_str, + } + else + { +- int uid = vsf_sysutil_statbuf_get_uid(p_stat); ++ unsigned int uid = vsf_sysutil_statbuf_get_uid(p_stat); + struct vsf_sysutil_user* p_user = 0; + if (tunable_text_userdb_names) + { +@@ -527,7 +527,7 @@ build_dir_line(struct mystr* p_str, const struct mystr* p_filename_str, + } + else + { +- int gid = vsf_sysutil_statbuf_get_gid(p_stat); ++ unsigned int gid = vsf_sysutil_statbuf_get_gid(p_stat); + struct vsf_sysutil_group* p_group = 0; + if (tunable_text_userdb_names) + { +diff --git a/privops.c b/privops.c +index 21d7267..f27c5c4 100644 +--- a/privops.c ++++ b/privops.c +@@ -236,8 +236,7 @@ vsf_privop_do_file_chown(struct vsf_session* p_sess, int fd) + /* Drop it like a hot potato unless it's a regular file owned by + * the the anonymous ftp user + */ +- if (p_sess->anon_upload_chown_uid == -1 || +- !vsf_sysutil_statbuf_is_regfile(s_p_statbuf) || ++ if (!vsf_sysutil_statbuf_is_regfile(s_p_statbuf) || + (vsf_sysutil_statbuf_get_uid(s_p_statbuf) != p_sess->anon_ftp_uid && + vsf_sysutil_statbuf_get_uid(s_p_statbuf) != p_sess->guest_user_uid)) + { +diff --git a/session.h b/session.h +index b60e098..4eccf46 100644 +--- a/session.h ++++ b/session.h +@@ -56,9 +56,9 @@ struct vsf_session + struct mystr_list* p_visited_dir_list; + + /* Details of userids which are interesting to us */ +- int anon_ftp_uid; +- int guest_user_uid; +- int anon_upload_chown_uid; ++ unsigned int anon_ftp_uid; ++ unsigned int guest_user_uid; ++ unsigned int anon_upload_chown_uid; + + /* Things we need to cache before we chroot() */ + struct mystr banned_email_str; +diff --git a/sysutil.c b/sysutil.c +index 24c4a81..954e901 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -1485,14 +1485,14 @@ vsf_sysutil_statbuf_get_size(const struct vsf_sysutil_statbuf* p_statbuf) + return p_stat->st_size; + } + +-int ++unsigned int + vsf_sysutil_statbuf_get_uid(const struct vsf_sysutil_statbuf* p_statbuf) + { + const struct stat* p_stat = (const struct stat*) p_statbuf; + return p_stat->st_uid; + } + +-int ++unsigned int + vsf_sysutil_statbuf_get_gid(const struct vsf_sysutil_statbuf* p_statbuf) + { + const struct stat* p_stat = (const struct stat*) p_statbuf; +@@ -1533,7 +1533,7 @@ vsf_sysutil_statbuf_get_sortkey_mtime( + } + + void +-vsf_sysutil_fchown(const int fd, const int uid, const int gid) ++vsf_sysutil_fchown(const int fd, const unsigned int uid, const unsigned int gid) + { + if (fchown(fd, uid, gid) != 0) + { +@@ -2351,13 +2351,9 @@ vsf_sysutil_dns_resolve(struct vsf_sysutil_sockaddr** p_sockptr, + } + + struct vsf_sysutil_user* +-vsf_sysutil_getpwuid(const int uid) ++vsf_sysutil_getpwuid(const unsigned int uid) + { +- if (uid < 0) +- { +- bug("negative uid in vsf_sysutil_getpwuid"); +- } +- return (struct vsf_sysutil_user*) getpwuid((unsigned int) uid); ++ return (struct vsf_sysutil_user*) getpwuid(uid); + } + + struct vsf_sysutil_user* +@@ -2380,14 +2376,14 @@ vsf_sysutil_user_get_homedir(const struct vsf_sysutil_user* p_user) + return p_passwd->pw_dir; + } + +-int ++unsigned int + vsf_sysutil_user_getuid(const struct vsf_sysutil_user* p_user) + { + const struct passwd* p_passwd = (const struct passwd*) p_user; + return p_passwd->pw_uid; + } + +-int ++unsigned int + vsf_sysutil_user_getgid(const struct vsf_sysutil_user* p_user) + { + const struct passwd* p_passwd = (const struct passwd*) p_user; +@@ -2395,13 +2391,9 @@ vsf_sysutil_user_getgid(const struct vsf_sysutil_user* p_user) + } + + struct vsf_sysutil_group* +-vsf_sysutil_getgrgid(const int gid) ++vsf_sysutil_getgrgid(const unsigned int gid) + { +- if (gid < 0) +- { +- die("negative gid in vsf_sysutil_getgrgid"); +- } +- return (struct vsf_sysutil_group*) getgrgid((unsigned int) gid); ++ return (struct vsf_sysutil_group*) getgrgid(gid); + } + + const char* +@@ -2476,25 +2468,17 @@ vsf_sysutil_setgid_numeric(int gid) + } + } + +-int ++unsigned int + vsf_sysutil_geteuid(void) + { +- int retval = geteuid(); +- if (retval < 0) +- { +- die("geteuid"); +- } ++ unsigned int retval = geteuid(); + return retval; + } + +-int ++unsigned int + vsf_sysutil_getegid(void) + { +- int retval = getegid(); +- if (retval < 0) +- { +- die("getegid"); +- } ++ unsigned int retval = getegid(); + return retval; + } + +@@ -2885,7 +2869,7 @@ vsf_sysutil_ftruncate(int fd) + } + } + +-int ++unsigned int + vsf_sysutil_getuid(void) + { + return getuid(); +diff --git a/sysutil.h b/sysutil.h +index 399c921..b745d4a 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -130,15 +130,15 @@ const char* vsf_sysutil_statbuf_get_numeric_date( + const struct vsf_sysutil_statbuf* p_stat, int use_localtime); + unsigned int vsf_sysutil_statbuf_get_links( + const struct vsf_sysutil_statbuf* p_stat); +-int vsf_sysutil_statbuf_get_uid(const struct vsf_sysutil_statbuf* p_stat); +-int vsf_sysutil_statbuf_get_gid(const struct vsf_sysutil_statbuf* p_stat); ++unsigned int vsf_sysutil_statbuf_get_uid(const struct vsf_sysutil_statbuf* p_stat); ++unsigned int vsf_sysutil_statbuf_get_gid(const struct vsf_sysutil_statbuf* p_stat); + int vsf_sysutil_statbuf_is_readable_other( + const struct vsf_sysutil_statbuf* p_stat); + const char* vsf_sysutil_statbuf_get_sortkey_mtime( + const struct vsf_sysutil_statbuf* p_stat); + + int vsf_sysutil_chmod(const char* p_filename, unsigned int mode); +-void vsf_sysutil_fchown(const int fd, const int uid, const int gid); ++void vsf_sysutil_fchown(const int fd, const unsigned int uid, const unsigned int gid); + void vsf_sysutil_fchmod(const int fd, unsigned int mode); + int vsf_sysutil_readlink(const char* p_filename, char* p_dest, + unsigned int bufsiz); +@@ -292,15 +292,15 @@ int vsf_sysutil_inet_aton( + struct vsf_sysutil_user; + struct vsf_sysutil_group; + +-struct vsf_sysutil_user* vsf_sysutil_getpwuid(const int uid); ++struct vsf_sysutil_user* vsf_sysutil_getpwuid(const unsigned int uid); + struct vsf_sysutil_user* vsf_sysutil_getpwnam(const char* p_user); + const char* vsf_sysutil_user_getname(const struct vsf_sysutil_user* p_user); + const char* vsf_sysutil_user_get_homedir( + const struct vsf_sysutil_user* p_user); +-int vsf_sysutil_user_getuid(const struct vsf_sysutil_user* p_user); +-int vsf_sysutil_user_getgid(const struct vsf_sysutil_user* p_user); ++unsigned int vsf_sysutil_user_getuid(const struct vsf_sysutil_user* p_user); ++unsigned int vsf_sysutil_user_getgid(const struct vsf_sysutil_user* p_user); + +-struct vsf_sysutil_group* vsf_sysutil_getgrgid(const int gid); ++struct vsf_sysutil_group* vsf_sysutil_getgrgid(const unsigned int gid); + const char* vsf_sysutil_group_getname(const struct vsf_sysutil_group* p_group); + + /* More random things */ +@@ -318,7 +318,7 @@ void vsf_sysutil_qsort(void* p_base, unsigned int num_elem, + char* vsf_sysutil_getenv(const char* p_var); + typedef void (*exitfunc_t)(void); + void vsf_sysutil_set_exit_func(exitfunc_t exitfunc); +-int vsf_sysutil_getuid(void); ++unsigned int vsf_sysutil_getuid(void); + + /* Syslogging (bah) */ + void vsf_sysutil_openlog(int force); +@@ -331,8 +331,8 @@ void vsf_sysutil_setuid(const struct vsf_sysutil_user* p_user); + void vsf_sysutil_setgid(const struct vsf_sysutil_user* p_user); + void vsf_sysutil_setuid_numeric(int uid); + void vsf_sysutil_setgid_numeric(int gid); +-int vsf_sysutil_geteuid(void); +-int vsf_sysutil_getegid(void); ++unsigned int vsf_sysutil_geteuid(void); ++unsigned int vsf_sysutil_getegid(void); + void vsf_sysutil_seteuid(const struct vsf_sysutil_user* p_user); + void vsf_sysutil_setegid(const struct vsf_sysutil_user* p_user); + void vsf_sysutil_seteuid_numeric(int uid); diff --git a/SOURCES/vsftpd-3.0.2-wnohang.patch b/SOURCES/vsftpd-3.0.2-wnohang.patch new file mode 100644 index 0000000..6e0902d --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-wnohang.patch @@ -0,0 +1,62 @@ +diff -up vsftpd-3.0.2/sysutil.c.wnohang vsftpd-3.0.2/sysutil.c +--- vsftpd-3.0.2/sysutil.c.wnohang 2015-08-03 07:35:33.619620425 +0200 ++++ vsftpd-3.0.2/sysutil.c 2015-08-03 07:35:33.626620480 +0200 +@@ -608,13 +608,13 @@ vsf_sysutil_exit(int exit_code) + } + + struct vsf_sysutil_wait_retval +-vsf_sysutil_wait(void) ++vsf_sysutil_wait(int hang) + { + struct vsf_sysutil_wait_retval retval; + vsf_sysutil_memclr(&retval, sizeof(retval)); + while (1) + { +- int sys_ret = wait(&retval.exit_status); ++ int sys_ret = waitpid(-1, &retval.exit_status, hang ? 0 : WNOHANG); + if (sys_ret < 0 && errno == EINTR) + { + vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); +diff -up vsftpd-3.0.2/sysutil.h.wnohang vsftpd-3.0.2/sysutil.h +--- vsftpd-3.0.2/sysutil.h.wnohang 2015-08-03 07:35:33.610620354 +0200 ++++ vsftpd-3.0.2/sysutil.h 2015-08-03 07:35:33.626620480 +0200 +@@ -176,7 +176,7 @@ struct vsf_sysutil_wait_retval + int PRIVATE_HANDS_OFF_syscall_retval; + int PRIVATE_HANDS_OFF_exit_status; + }; +-struct vsf_sysutil_wait_retval vsf_sysutil_wait(void); ++struct vsf_sysutil_wait_retval vsf_sysutil_wait(int hang); + int vsf_sysutil_wait_reap_one(void); + int vsf_sysutil_wait_get_retval( + const struct vsf_sysutil_wait_retval* p_waitret); +diff -up vsftpd-3.0.2/twoprocess.c.wnohang vsftpd-3.0.2/twoprocess.c +--- vsftpd-3.0.2/twoprocess.c.wnohang 2012-09-16 09:15:49.000000000 +0200 ++++ vsftpd-3.0.2/twoprocess.c 2015-08-03 07:35:33.626620480 +0200 +@@ -47,8 +47,17 @@ static void + handle_sigchld(void* duff) + { + +- struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(); ++ struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(0); + (void) duff; ++ if (!vsf_sysutil_wait_get_exitcode(&wait_retval) && ++ !vsf_sysutil_wait_get_retval(&wait_retval)) ++ /* There was nobody to wait for, possibly caused by underlying library ++ * which created a new process through fork()/vfork() and already picked ++ * it up, e.g. by pam_exec.so or integrity check routines for libraries ++ * when FIPS mode is on (nss freebl), which can lead to calling prelink ++ * if the prelink package is installed. ++ */ ++ return; + /* Child died, so we'll do the same! Report it as an error unless the child + * exited normally with zero exit code + */ +@@ -390,7 +399,7 @@ common_do_login(struct vsf_session* p_se + priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK); + if (!p_sess->control_use_ssl) + { +- (void) vsf_sysutil_wait(); ++ (void) vsf_sysutil_wait(1); + } + else + { diff --git a/SOURCES/vsftpd-close-std-fds.patch b/SOURCES/vsftpd-close-std-fds.patch new file mode 100644 index 0000000..73da6af --- /dev/null +++ b/SOURCES/vsftpd-close-std-fds.patch @@ -0,0 +1,13 @@ +diff -up vsftpd-2.0.7/standalone.c.close-fds vsftpd-2.0.7/standalone.c +--- vsftpd-2.0.7/standalone.c.close-fds 2008-09-08 23:36:32.000000000 -0400 ++++ vsftpd-2.0.7/standalone.c 2008-09-08 23:37:53.000000000 -0400 +@@ -131,6 +131,9 @@ vsf_standalone_main(void) + die("could not bind listening IPv6 socket"); + } + } ++ vsf_sysutil_close(0); ++ vsf_sysutil_close(1); ++ vsf_sysutil_close(2); + retval = vsf_sysutil_listen(listen_sock, VSFTP_LISTEN_BACKLOG); + if (vsf_sysutil_retval_is_error(retval)) + { diff --git a/SOURCES/vsftpd-generator b/SOURCES/vsftpd-generator new file mode 100755 index 0000000..f1c4cdc --- /dev/null +++ b/SOURCES/vsftpd-generator @@ -0,0 +1,15 @@ +#!/bin/bash + +confdir=/etc/vsftpd +unitdir=/usr/lib/systemd/system +targetdir=$1/vsftpd.target.wants + +mkdir -p ${targetdir} + +for f in $(ls -1 ${confdir}/*.conf | awk -F "." '{print $1}' | awk -F "/" '{print $4}') +do + echo "Generating systemd units for $f" + ln -s ${unitdir}/vsftpd\@.service ${targetdir}/vsftpd\@$f.service > /dev/null 2>&1 +done + +exit 0 diff --git a/SOURCES/vsftpd.ftpusers b/SOURCES/vsftpd.ftpusers new file mode 100644 index 0000000..096142f --- /dev/null +++ b/SOURCES/vsftpd.ftpusers @@ -0,0 +1,15 @@ +# Users that are not allowed to login via ftp +root +bin +daemon +adm +lp +sync +shutdown +halt +mail +news +uucp +operator +games +nobody diff --git a/SOURCES/vsftpd.init b/SOURCES/vsftpd.init new file mode 100755 index 0000000..91c23e9 --- /dev/null +++ b/SOURCES/vsftpd.init @@ -0,0 +1,106 @@ +#!/bin/bash +# +### BEGIN INIT INFO +# Provides: vsftpd +# Required-Start: $local_fs $network $named $remote_fs $syslog +# Required-Stop: $local_fs $network $named $remote_fs $syslog +# Short-Description: Very Secure Ftp Daemon +# Description: vsftpd is a Very Secure FTP daemon. It was written completely from +# scratch +### END INIT INFO + +# vsftpd This shell script takes care of starting and stopping +# standalone vsftpd. +# +# chkconfig: - 60 50 +# description: Vsftpd is a ftp daemon, which is the program \ +# that answers incoming ftp service requests. +# processname: vsftpd +# config: /etc/vsftpd/vsftpd.conf + +# Source function library. +. /etc/rc.d/init.d/functions + +# Source networking configuration. +. /etc/sysconfig/network + +RETVAL=0 +prog="vsftpd" + +start() { + # Start daemons. + + # Check that networking is up. + [ ${NETWORKING} = "no" ] && exit 1 + + [ -x /usr/sbin/vsftpd ] || exit 1 + + if [ -d /etc/vsftpd ] ; then + CONFS=`ls /etc/vsftpd/*.conf 2>/dev/null` + [ -z "$CONFS" ] && exit 6 + PROC_FAILED=0 + for i in $CONFS; do + site=`basename $i .conf` + echo -n $"Starting $prog for $site: " + daemon /usr/sbin/vsftpd $i + RETVAL=$? + echo + if [ $RETVAL -eq 0 ] && [ ! -f /var/lock/subsys/$prog ]; then + touch /var/lock/subsys/$prog + elif [ $RETVAL -ne 0 ]; then + ps -FC vsftpd | grep "$i" > /dev/null + RETVAL=$? + if [ $PROC_FAILED -eq 0 ] && [ $RETVAL -ne 0 ]; then + PROC_FAILED=1 + fi + fi + done + if [ $RETVAL -eq 0 ] && [ $PROC_FAILED -ne 0 ]; then + RETVAL=1 + fi + else + RETVAL=1 + fi + return $RETVAL +} + +stop() { + # Stop daemons. + echo -n $"Shutting down $prog: " + killproc $prog + RETVAL=$? + echo + [ $RETVAL -eq 0 ] && rm -f /var/lock/subsys/$prog + return $RETVAL +} + +# See how we were called. +case "$1" in + start) + start + ;; + stop) + stop + ;; + restart|reload) + stop + start + RETVAL=$? + ;; + condrestart|try-restart|force-reload) + if [ -f /var/lock/subsys/$prog ]; then + stop + start + RETVAL=$? + fi + ;; + status) + status $prog + RETVAL=$? + ;; + *) + echo $"Usage: $0 {start|stop|restart|try-restart|force-reload|status}" + exit 1 +esac + +exit $RETVAL diff --git a/SOURCES/vsftpd.pam b/SOURCES/vsftpd.pam new file mode 100644 index 0000000..080abc3 --- /dev/null +++ b/SOURCES/vsftpd.pam @@ -0,0 +1,8 @@ +#%PAM-1.0 +session optional pam_keyinit.so force revoke +auth required pam_listfile.so item=user sense=deny file=/etc/vsftpd/ftpusers onerr=succeed +auth required pam_shells.so +auth include password-auth +account include password-auth +session required pam_loginuid.so +session include password-auth diff --git a/SOURCES/vsftpd.service b/SOURCES/vsftpd.service new file mode 100644 index 0000000..8ebae44 --- /dev/null +++ b/SOURCES/vsftpd.service @@ -0,0 +1,10 @@ +[Unit] +Description=Vsftpd ftp daemon +After=network.target + +[Service] +Type=forking +ExecStart=/usr/sbin/vsftpd /etc/vsftpd/vsftpd.conf + +[Install] +WantedBy=multi-user.target diff --git a/SOURCES/vsftpd.target b/SOURCES/vsftpd.target new file mode 100644 index 0000000..3f0a942 --- /dev/null +++ b/SOURCES/vsftpd.target @@ -0,0 +1,6 @@ +[Unit] +Description=FTP daemon +After=network.target + +[Install] +WantedBy=multi-user.target diff --git a/SOURCES/vsftpd.user_list b/SOURCES/vsftpd.user_list new file mode 100644 index 0000000..3e2760f --- /dev/null +++ b/SOURCES/vsftpd.user_list @@ -0,0 +1,20 @@ +# vsftpd userlist +# If userlist_deny=NO, only allow users in this file +# If userlist_deny=YES (default), never allow users in this file, and +# do not even prompt for a password. +# Note that the default vsftpd pam config also checks /etc/vsftpd/ftpusers +# for users that are denied. +root +bin +daemon +adm +lp +sync +shutdown +halt +mail +news +uucp +operator +games +nobody diff --git a/SOURCES/vsftpd.xinetd b/SOURCES/vsftpd.xinetd new file mode 100644 index 0000000..9b22b5b --- /dev/null +++ b/SOURCES/vsftpd.xinetd @@ -0,0 +1,14 @@ +# default: off +# description: The vsftpd FTP server serves FTP connections. It uses \ +# normal, unencrypted usernames and passwords for authentication. +service ftp +{ + socket_type = stream + wait = no + user = root + server = /usr/sbin/vsftpd + server_args = /etc/vsftpd/vsftpd.conf + nice = 10 + disable = yes + flags = IPv4 +} diff --git a/SOURCES/vsftpd@.service b/SOURCES/vsftpd@.service new file mode 100644 index 0000000..f3a7a16 --- /dev/null +++ b/SOURCES/vsftpd@.service @@ -0,0 +1,11 @@ +[Unit] +Description=Vsftpd ftp daemon +After=network.target +PartOf=vsftpd.target + +[Service] +Type=forking +ExecStart=/usr/sbin/vsftpd /etc/vsftpd/%i.conf + +[Install] +WantedBy=vsftpd.target diff --git a/SOURCES/vsftpd_conf_migrate.sh b/SOURCES/vsftpd_conf_migrate.sh new file mode 100755 index 0000000..47abeb8 --- /dev/null +++ b/SOURCES/vsftpd_conf_migrate.sh @@ -0,0 +1,12 @@ +#!/bin/bash +#move old config files and symlink them +#shipped with vsftpd-2.0.1-6 +PREFIX="vsftpd" +for file in $( ls /etc/${PREFIX}.* ); do + if [ ! -L $file ]; then + new=`echo $file | sed s/${PREFIX}\./${PREFIX}\\\\//g | sed s/\.rpmsave//g` + mv -f ${file} ${new} + ln -s ${new} ${file} + echo $file moved to $new + fi +done diff --git a/SPECS/vsftpd.spec b/SPECS/vsftpd.spec new file mode 100644 index 0000000..4ec101e --- /dev/null +++ b/SPECS/vsftpd.spec @@ -0,0 +1,827 @@ +%{!?tcp_wrappers:%define tcp_wrappers 1} +%define _generatorsdir %{_prefix}/lib/systemd/system-generators + +Name: vsftpd +Version: 3.0.2 +Release: 27%{?dist} +Summary: Very Secure Ftp Daemon + +Group: System Environment/Daemons +# OpenSSL link exception +License: GPLv2 with exceptions +URL: https://security.appspot.com/vsftpd.html +Source0: https://security.appspot.com/downloads/%{name}-%{version}.tar.gz +Source1: vsftpd.xinetd +Source2: vsftpd.pam +Source3: vsftpd.ftpusers +Source4: vsftpd.user_list +Source5: vsftpd.init +Source6: vsftpd_conf_migrate.sh +Source7: vsftpd.service +Source8: vsftpd@.service +Source9: vsftpd.target +Source10: vsftpd-generator + +BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n) + +BuildRequires: pam-devel +BuildRequires: libcap-devel +BuildRequires: openssl-devel +BuildRequires: systemd +%if %{tcp_wrappers} +BuildRequires: tcp_wrappers-devel +%endif + +Requires: logrotate + +# Build patches +Patch1: vsftpd-2.1.0-libs.patch +Patch2: vsftpd-2.1.0-build_ssl.patch +Patch3: vsftpd-2.1.0-tcp_wrappers.patch + +# Use /etc/vsftpd/ instead of /etc/ +Patch4: vsftpd-2.1.0-configuration.patch + +# These need review +Patch5: vsftpd-2.1.0-pam_hostname.patch +Patch6: vsftpd-close-std-fds.patch +Patch7: vsftpd-2.1.0-filter.patch +Patch9: vsftpd-2.1.0-userlist_log.patch + +Patch10: vsftpd-2.1.0-trim.patch +Patch12: vsftpd-2.1.1-daemonize_plus.patch +Patch14: vsftpd-2.2.0-wildchar.patch + +Patch16: vsftpd-2.2.2-clone.patch +Patch19: vsftpd-2.3.4-sd.patch +Patch20: vsftpd-2.3.4-sqb.patch +Patch21: vsftpd-2.3.4-listen_ipv6.patch +Patch22: vsftpd-2.3.5-aslim.patch +Patch23: vsftpd-3.0.0-tz.patch +Patch24: vsftpd-3.0.0-xferlog.patch +Patch25: vsftpd-3.0.0-logrotate.patch +Patch26: vsftpd-3.0.2-seccomp.patch +Patch27: vsftpd-3.0.2-mrate.patch +Patch28: vsftpd-3.0.2-wnohang.patch +Patch29: vsftpd-3.0.2-dh.patch +Patch30: vsftpd-3.0.2-ecdh.patch +Patch31: vsftpd-2.0.5-fix_qm.patch +Patch32: vsftpd-3.0.2-reverse-lookup.patch +Patch33: vsftpd-3.0.2-del-upl.patch +Patch34: vsftpd-2.2.2-nfs-fail.patch +Patch35: vsftpd-2.2.2-man-pages.patch +Patch36: vsftpd-3.0.2-uint-uidgid.patch +Patch37: vsftpd-2.2.2-blank-chars-overflow.patch +Patch38: vsftpd-2.2.2-syslog.patch +Patch39: vsftpd-3.0.2-docupd.patch +Patch40: vsftpd-2.2.2-tlsv1_2.patch +Patch41: vsftpd-3.0.2-defaulttls.patch +Patch42: 0001-Redefine-VSFTP_COMMAND_FD-to-1.patch +Patch43: 0001-Document-the-relationship-of-text_userdb_names-and-c.patch +Patch44: 0001-Document-allow_writeable_chroot-in-the-man-page.patch +Patch45: 0001-Improve-documentation-of-ascii_-options.patch +Patch46: 0001-Add-new-filename-generation-algorithm-for-STOU-comma.patch +Patch47: 0001-Fix-rDNS-with-IPv6.patch +Patch48: 0001-Log-die-calls-to-syslog.patch +Patch49: 0002-Improve-error-message-when-max-number-of-bind-attemp.patch +Patch50: 0003-Make-the-max-number-of-bind-retries-tunable.patch +Patch51: 0001-Move-closing-standard-FDs-after-listen.patch +Patch52: 0002-Prevent-recursion-in-bug.patch +Patch53: 0001-Set-s_uwtmp_inserted-only-after-record-insertion-rem.patch +Patch54: 0002-Repeat-pututxline-if-it-fails-with-EINTR.patch + +%description +vsftpd is a Very Secure FTP daemon. It was written completely from +scratch. + +%package sysvinit +Group: System Environment/Daemons +Summary: SysV initscript for vsftpd daemon +Requires: %{name} = %{version}-%{release} +Requires(preun): /sbin/service +Requires(postun): /sbin/service + +%description sysvinit +The vsftpd-sysvinit contains SysV initscritps support. + +%prep +%setup -q -n %{name}-%{version} +cp %{SOURCE1} . + +%patch1 -p1 -b .libs +%patch2 -p1 -b .build_ssl +%if %{tcp_wrappers} +%patch3 -p1 -b .tcp_wrappers +%endif +%patch4 -p1 -b .configuration +%patch5 -p1 -b .pam_hostname +%patch6 -p1 -b .close_fds +%patch7 -p1 -b .filter +%patch9 -p1 -b .userlist_log +%patch10 -p1 -b .trim +%patch12 -p1 -b .daemonize_plus +%patch14 -p1 -b .wildchar +%patch16 -p1 -b .clone +%patch19 -p1 -b .sd +%patch20 -p1 -b .sqb +%patch21 -p1 -b .listen_ipv6 +%patch22 -p1 -b .aslim +%patch23 -p1 -b .tz +%patch24 -p1 -b .xferlog +%patch25 -p1 -b .logrotate +%patch26 -p1 -b .seccomp +%patch27 -p1 -b .mrate +%patch28 -p1 -b .wnohang +%patch29 -p1 -b .dh +%patch30 -p1 -b .ecdh +%patch31 -p1 -b .fix_qm +%patch32 -p1 -b .reverse-lookup +%patch33 -p1 -b .del-upl +%patch34 -p1 -b .nfs-fail +%patch35 -p1 -b .man_pages +%patch36 -p1 -b .uint-uidgid +%patch37 -p1 -b .blank-char-overflow +%patch38 -p1 -b .syslog +%patch39 -p1 -b .docup +%patch40 -p1 -b .tls_version +%patch41 -p1 -b .defaulttls +%patch42 -p1 -b .command-fd +%patch43 -p1 -b .text-userdb-names +%patch44 -p1 -b .allow-writeable-chroot +%patch45 -p1 -b .ascii +%patch46 -p1 -b .better-stou +%patch47 -p1 -b .ipv6-rdns +%patch48 -p1 -b .errors-to-syslog +%patch49 -p1 -b .improve-error-message +%patch50 -p1 -b .bind-retries-configurable +%patch51 -p1 -b .move-close +%patch52 -p1 -b .prevent-bug-recursion +%patch53 -p1 -b .move-variable-assignment +%patch54 -p1 -b .repeat-pututxline + +%build +%ifarch s390x sparcv9 sparc64 +make CFLAGS="$RPM_OPT_FLAGS -fPIE -pipe -Wextra -Werror" \ +%else +make CFLAGS="$RPM_OPT_FLAGS -fpie -pipe -Wextra -Werror" \ +%endif + LINK="-pie -lssl" %{?_smp_mflags} + + +%install +rm -rf $RPM_BUILD_ROOT +mkdir -p $RPM_BUILD_ROOT%{_sbindir} +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir} +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/{vsftpd,pam.d,logrotate.d,rc.d/init.d} +mkdir -p $RPM_BUILD_ROOT%{_mandir}/man{5,8} +mkdir -p $RPM_BUILD_ROOT%{_unitdir} +mkdir -p $RPM_BUILD_ROOT%{_generatorsdir} +install -m 755 vsftpd $RPM_BUILD_ROOT%{_sbindir}/vsftpd +install -m 600 vsftpd.conf $RPM_BUILD_ROOT%{_sysconfdir}/vsftpd/vsftpd.conf +install -m 644 vsftpd.conf.5 $RPM_BUILD_ROOT/%{_mandir}/man5/ +install -m 644 vsftpd.8 $RPM_BUILD_ROOT/%{_mandir}/man8/ +install -m 644 RedHat/vsftpd.log $RPM_BUILD_ROOT%{_sysconfdir}/logrotate.d/vsftpd +install -m 644 %{SOURCE2} $RPM_BUILD_ROOT%{_sysconfdir}/pam.d/vsftpd +install -m 600 %{SOURCE3} $RPM_BUILD_ROOT%{_sysconfdir}/vsftpd/ftpusers +install -m 600 %{SOURCE4} $RPM_BUILD_ROOT%{_sysconfdir}/vsftpd/user_list +install -m 755 %{SOURCE5} $RPM_BUILD_ROOT%{_sysconfdir}/rc.d/init.d/vsftpd +install -m 744 %{SOURCE6} $RPM_BUILD_ROOT%{_sysconfdir}/vsftpd/vsftpd_conf_migrate.sh +install -m 644 %{SOURCE7} $RPM_BUILD_ROOT%{_unitdir} +install -m 644 %{SOURCE8} $RPM_BUILD_ROOT%{_unitdir} +install -m 644 %{SOURCE9} $RPM_BUILD_ROOT%{_unitdir} +install -m 755 %{SOURCE10} $RPM_BUILD_ROOT%{_generatorsdir} + +mkdir -p $RPM_BUILD_ROOT/%{_var}/ftp/pub + +%clean +rm -rf $RPM_BUILD_ROOT + +%post +%systemd_post vsftpd.service + +%preun +%systemd_preun vsftpd.service +%systemd_preun vsftpd.target + +%postun +%systemd_postun_with_restart vsftpd.service + +%files +%defattr(-,root,root,-) +%{_unitdir}/* +%{_generatorsdir}/* +%{_sbindir}/vsftpd +%dir %{_sysconfdir}/vsftpd +%{_sysconfdir}/vsftpd/vsftpd_conf_migrate.sh +%config(noreplace) %{_sysconfdir}/vsftpd/ftpusers +%config(noreplace) %{_sysconfdir}/vsftpd/user_list +%config(noreplace) %{_sysconfdir}/vsftpd/vsftpd.conf +%config(noreplace) %{_sysconfdir}/pam.d/vsftpd +%config(noreplace) %{_sysconfdir}/logrotate.d/vsftpd +%doc FAQ INSTALL BUGS AUDIT Changelog LICENSE README README.security REWARD +%doc SPEED TODO BENCHMARKS COPYING SECURITY/ EXAMPLE/ TUNING SIZE vsftpd.xinetd +%{_mandir}/man5/vsftpd.conf.* +%{_mandir}/man8/vsftpd.* +%{_var}/ftp + +%files sysvinit +%{_sysconfdir}/rc.d/init.d/vsftpd + +%changelog +* Mon Aug 05 2019 Ondřej Lysoněk - 3.0.2-27 +- Partially fix problem with bad utmp entries when pututxline() fails +- Resolves: rhbz#1688848 + +* Mon Aug 05 2019 Ondřej Lysoněk - 3.0.2-26 +- Fix segfault when listen() returns an error +- Resolves: rhbz#1666380 + +* Thu Jun 21 2018 Ondřej Lysoněk - 3.0.2-25 +- Add config option log_die allowing to pass error messages to syslog +- Add config option bind_retries allowing to change the max number +- of attempts to find a listening port for the PASV/EPSV command +- Resolves: rhbz#1318198 + +* Wed May 16 2018 Ondřej Lysoněk - 3.0.2-24 +- Fix reverse hostname lookup with IPv6 +- Resolves: rhbz#1576705 + +* Thu Apr 05 2018 Ondřej Lysoněk - 3.0.2-23 +- Redefine VSFTP_COMMAND_FD to 1 +- Resolves: rhbz#1443055 +- Document the relationship of text_userdb_names and chroot_local_user +- Resolves: rhbz#1508021 +- Document allow_writeable_chroot in the man page +- Resolves: rhbz#1508022 +- Improve documentation of ascii_* options +- Resolves: rhbz#1517227 +- Add new filename generation algorithm for STOU command +- Resolves: rhbz#1479237 + +* Thu Mar 23 2017 Zdenek Dohnal - 3.0.2-22 +- Resolves: #1432054 - secure ftp stopped working with default TLS settings in the new vsftpd package + +* Thu Jun 02 2016 Martin Sehnoutka - 3.0.2-21 +- Resolves: #1318947 vsftpd should permit specified TLS versions only + +* Thu Apr 07 2016 Martin Sehnoutka - 3.0.2-20 +- Resolves: #1147551 - Missing isolate_* options, incorrect default values of + max_clients, max_per_ip in man vsftpd.conf + +* Tue Apr 05 2016 Martin Sehnoutka - 3.0.2-19 +- Resolves: #1311562 - Message is not logged to syslog when syslog_enable=yes in + vsftpd.conf + +* Tue Apr 05 2016 Martin Sehnoutka - 3.0.2-18 +- Resolves: #1311600 - vsftpd segfaults in vsf_sysutil_strndup + +* Fri Apr 01 2016 Martin Sehnoutka - 3.0.2-17 +- Resolves: #1116385 - deny_file, hide_file + +* Tue Mar 29 2016 Martin Sehnoutka - 3.0.2-16 +- Resolves: #1087868 - uid and gid is not correctly shown + +* Tue Mar 29 2016 Martin Sehnoutka - 3.0.2-15 +- Resolves: #1147550 ssl_request_cert paragraph in the vsftpd.conf man page gets + rendered incorrectly + +* Tue Mar 29 2016 Martin Sehnoutka - 3.0.2-14 +- Resolves: #1317891 Handle errors when calling close() + +* Thu Mar 24 2016 Martin Sehnoutka - 3.0.2-13 +- Resolves: #1148872 - The vsftpd doesn't remove failed upload when the + delete_failed_uploads is enabled and the network cable is unplagged + +* Tue Mar 22 2016 Martin Sehnoutka - 3.0.2-12 +- Resolves: #1087834 - missing reverse_lookup_enable option + +* Tue Feb 23 2016 Pavel Šimerda - 3.0.2-11 +- Resolves: #1166741 - Wildcard ? does not work correctly in vsftpd-3.0.2-9.el7 + +* Mon Aug 03 2015 Martin Osvald - 3.0.2-10 +- Resolves: #1058704 - vsftpd does not support DHE cipher suites +- Resolves: #1058712 - vsftpd does not support ECDHE cipher suites +- Resolves: #1198259 - The vsftpd hangs in a SIGCHLD handler when the pam_exec.so is used in pam.d configuration + +* Fri Mar 07 2014 Jiri Skala - 3.0.2-9 +- Resolves: #1063402 - vsftpd local_max_rate option doesn't work as expected + +* Fri Jan 24 2014 Daniel Mach - 3.0.2-8 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 3.0.2-7 +- Mass rebuild 2013-12-27 + +* Fri Sep 13 2013 Jiri Skala - 3.0.2-6 +- Resolves: #833093 - multiple instances - improved service, target unit files, man page + +* Thu Aug 29 2013 Ondrej Vasik - 3.0.2-5 +- Readd seccomp disabled by default (#860951) + +* Thu Aug 15 2013 Jiri Skala - 3.0.2-4 +- Resolves: #833093 - vsftpd service does not start more than one daemon + +* Mon Feb 25 2013 Jiri Skala - 3.0.2-3 +- fixes #913519 - login fails (increased AS_LIMIT) + +* Fri Feb 15 2013 Fedora Release Engineering - 3.0.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_19_Mass_Rebuild + +* Wed Sep 19 2012 Jiri Skala - 3.0.2-2 +- update to latest upstream 3.0.2 + +* Mon Sep 17 2012 Jiri Skala - 3.0.1-1 +- update to latest upstream 3.0.1 +- fixes #851441 - Introduce new systemd-rpm macros in vsftpd spec file +- fixes #845980 - vsftpd seccomp filter is too strict + +* Sun Jul 22 2012 Fedora Release Engineering - 3.0.0-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jul 17 2012 Jiri Skala - 3.0.0-3 +- changed default value of xferlog_file to /var/log/xferlog +- added rotating xferlog + +* Thu Apr 26 2012 Jiri Skala - 3.0.0-2 +- corrected time zone handling - especially DST flag +- fixed default value of option 'listen' + +* Tue Apr 10 2012 Jiri Skala - 3.0.0-1 +- updated to latest upstream 3.0.0 + +* Thu Feb 09 2012 Jiri Skala - 2.3.5-3 +- fixes #788812 - authentication failure on x86_64 when using nss_pgsql + +* Sat Jan 14 2012 Fedora Release Engineering - 2.3.5-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_17_Mass_Rebuild + +* Mon Dec 19 2011 Jiri Skala - 2.3.5-1 +- updated to latest upstream 2.3.5 + +* Mon Nov 28 2011 Jiri Skala - 2.3.4-7 +- added patch from BZ#450853#c23 + +* Tue Nov 15 2011 Jiri Skala - 2.3.4-6 +- fixes #753365 - multiple issues with vsftpd's systemd unit +- removes exclusivity between listen and listen_ipv6 BZ#450853 +- ls wildchars supports square brackets + +* Wed Aug 03 2011 Jiri Skala - 2.3.4-5 +- fixes #719434 - Provide native systemd unit file +- moving SysV initscript into subpackage + +* Mon Aug 01 2011 Jiri Skala - 2.3.4-4 +- rebuild for libcap + +* Mon Jul 04 2011 Nils Philippsen - 2.3.4-3 +- update upstream and source URL + +* Wed Feb 16 2011 Jiri Skala - 2.3.4-2 +- fixes #717412 - Connection failures - patched by Takayuki Nagata + +* Wed Feb 16 2011 Jiri Skala - 2.3.4-1 +- updated to latest upstream 2.3.4 + +* Mon Feb 07 2011 Fedora Release Engineering - 2.3.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Fri Aug 20 2010 Jiri Skala - 2.3.2-1 +- fixes #625404 - vsftpd-2.3.1 is available +- joined patches (libs+dso, wildchar+greedy) + +* Fri Aug 06 2010 Jiri Skala - 2.2.2-8 +- fixes #472880 - Configuration can cause confusion because of selinux labels + +* Mon May 17 2010 Jiri Skala - 2.2.2-7 +- when listen_ipv6=YES sets socket option to listen IPv6 only + +* Fri May 14 2010 Jiri Skala - 2.2.2-6 +- syscall(__NR_clone) replaced by clone() to fix incorrect order of params on s390 arch + +* Wed Apr 07 2010 Jiri Skala - 2.2.2-5 +- corrected daemonize_plus patch - don't try kill parent when vsftpd isn't daemonized + +* Tue Mar 16 2010 Jiri Skala - 2.2.2-4 +- fixes #544251 - /etc/rc.d/init.d/vsftpd does not start more than one daemon + +* Mon Feb 15 2010 Jiri Skala - 2.2.2-3 +- fixes #565067 - FTBFS: ImplicitDSOLinking + +* Thu Dec 17 2009 Jiri Skala - 2.2.2-2 +- corrected two patches due to fuzz 0 + +* Thu Dec 17 2009 Jiri Skala - 2.2.2-1 +- update to latest upstream + +* Mon Nov 23 2009 Jiri Skala - 2.2.0-6 +- added lost default values of vsftpd.conf (rh patch) + +* Wed Sep 16 2009 Tomas Mraz - 2.2.0-5 +- use password-auth common PAM configuration instead of system-auth + +* Mon Sep 14 2009 Jiri Skala - 2.2.0-4 +- modified init script to be LSB compliant + +* Tue Sep 08 2009 Jiri Skala - 2.2.0-3 +- fixed bug messaged in RHEL-4 #479774 - Wildcard failures with vsftpd + +* Thu Aug 27 2009 Tomas Mraz - 2.2.0-2 +- rebuilt with new openssl + +* Tue Aug 24 2009 Martin Nagy - 2.2.0-1 +- update to latest upstream release 2.2.0 + +* Tue Aug 04 2009 Martin Nagy - 2.2.0-0.1.pre4 +- update to latest upstream release + +* Sun Jul 26 2009 Fedora Release Engineering - 2.1.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Tue Jun 02 2009 Jiri Skala - 2.1.2-1 +- updated to latest upstream version + +* Thu May 21 2009 Jiri Skala - 2.1.1-0.3 +- fixed daemonize_plus patch +- fixed test in initscript [ -z "CONFS" ] + +* Mon May 04 2009 Jiri Skala - 2.1.1-0.2 +- fixes daemonize patch + +* Wed Apr 22 2009 Jiri Skala - 2.1.0-3 +- updated to latest upstream version +- improved daemonizing - init script gets correct return code if binding fails +- trim white spaces from option values +- fixed #483604 - vsftpd not honouring delay_failed_login when userlist active + +* Wed Feb 25 2009 Fedora Release Engineering - 2.1.0-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_11_Mass_Rebuild + +* Tue Feb 24 2009 Martin Nagy - 2.1.0-1 +- update to latest upstream release + +* Fri Jan 23 2009 Martin Nagy - 2.1.0-0.3.pre4 +- update to latest upstream release +- enable ptrace sandbox again +- don't mark vsftpd_conf_migrate.sh as a config file + +* Fri Jan 16 2009 Martin Nagy - 2.1.0-0.2.pre3 +- disable ptrace sandbox to fix build on i386 + +* Fri Jan 16 2009 Martin Nagy - 2.1.0-0.1.pre3 +- update to latest upstream release +- cleanup the spec file +- drop patches fixed upstream: + vsftpd-1.0.1-missingok.patch + vsftpd-1.2.1-nonrootconf.patch + vsftpd-2.0.1-tcp_wrappers.patch + vsftpd-2.0.2-signal.patch + vsftpd-2.0.3-daemonize_fds.patch + vsftpd-2.0.5-correct_comments.patch + vsftpd-2.0.5-pasv_dot.patch + vsftpd-2.0.5-write_race.patch + vsftpd-2.0.5-fix_unique.patch + vsftpd-2.0.5-uname_size.patch + vsftpd-2.0.5-bind_denied.patch + vsftpd-2.0.5-pam_end.patch + vsftpd-2.0.5-underscore_uname.patch + vsftpd-2.0.6-listen.patch +- join all configuration patches into one: + vsftpd-1.1.3-rh.patch + vsftpd-1.2.1-conffile.patch + vsftpd-2.0.1-dir.patch + vsftpd-2.0.1-server_args.patch + vsftpd-2.0.3-background.patch + vsftpd-2.0.5-default_ipv6.patch + vsftpd-2.0.5-add_ipv6_option.patch + vsftpd-2.0.5-man.patch + +* Mon Sep 8 2008 Tom "spot" Callaway - 2.0.7-1 +- fix license tag +- update to 2.0.7 + +* Fri Jun 20 2008 Dennis Gilmore - 2.0.6-5 +- add sparc arches to -fPIE list + +* Wed May 21 2008 Martin Nagy - 2.0.6-4 +- fix a small memory leak (#397011) + +* Mon Mar 31 2008 Martin Nagy - 2.0.6-3 +- set option listen to default to YES + +* Mon Feb 25 2008 Martin Nagy - 2.0.6-2 +- fix init script (#431452) +- make the init script LSB compliant (#247093) + +* Fri Feb 22 2008 Martin Nagy - 2.0.6-1 +- rebase for new upstream version +- remove patches that were fixed in upstream: kickline, confspell, anon_umask + +* Mon Feb 11 2008 Martin Nagy - 2.0.5-22 +- rebuild for gcc-4.3 + +* Fri Nov 30 2007 Martin Nagy - 2.0.5-21 +- Remove uniq_rename patch. +- Correct create/lock race condition, original patch by + (#240550). +- Fix bad handling of unique files (#392231). +- Added userlist_log option. +- Allow usernames to begin with underscore or dot (#339911). +- Removed user_config patch. +- Fix nonrootconf patch (#400921). +- Increase maximum length of allowed username (#236326). +- Fix file listing issue with wildcard (#392181). +- Removed use_localtime patch (#243087). + +* Thu Nov 08 2007 Martin Nagy - 2.0.5-20 +- Correct calling of pam_end (#235843). + +* Wed Aug 29 2007 Fedora Release Engineering - 2.0.5-19 +- Rebuild for selinux ppc32 issue. + +* Tue Jul 10 2007 Maros Barabas - 2.0.5-18 +- Add comment for xferlog_std_format +- Resolves #218260 + +* Fri Jun 29 2007 Maros Barabas - 2.0.5-17 +- Fix pasv dot after pasv response (RFC 959 page 40) + +* Wed Apr 04 2007 Maros Barabas - 2.0.5-16 +- Merge review: - fix using %%{_var}, %%{_sbindir} and + %%{_sysconfigdir} macros for files and install + - fix BuildRoot + - dropped usermod, openssl & pam requirement + +* Tue Mar 20 2007 Florian La Roche - 2.0.5-15 +- fix BuildPrereq + +* Tue Jan 30 2007 Maros Barabas - 2.0.5-14 +- remove file upload permission problem +- change name of patch vsfptd-2.0.3-user_config +- Resolves #190193 + +* Fri Jan 19 2007 Maros Barabas - 2.0.5-13 +- add lost patch: don't die when no user config file is present +- Resolves #166986 + +* Thu Jan 18 2007 Radek Vokal - 2.0.5-12 +- add dist tag +- add buildrequires tcp_wrappers-devel + +* Wed Jan 17 2007 Maros Barabas - 2.0.5-11 +- add errno EACCES to not die by vsf_sysutil_bind +- Resolves #198677 + +* Thu Dec 14 2006 Maros Barabas - 2.0.5-10 +- correct man (5) pages +- Resolves: #216765 +- correct calling function stat +- Resolves: bz200763 + +* Mon Dec 04 2006 Maros Barabas - 2.0.5-9 +- change BuildRequires tcp_wrappers to tcp_wrappers-devel + +* Mon Aug 28 2006 Maros Barabas - 2.0.5-8 +- added forgotten patch to make filename filter (#174764) + +* Tue Aug 22 2006 Maros Barabas - 2.0.5-7 +- correct paths of configuration files on man pages + +* Tue Aug 15 2006 Maros Barabas - 2.0.5-6 +- correct comments + +* Tue Aug 08 2006 Maros Barabas - 2.0.5-5 +- option to change listening to IPv6 protocol + +* Thu Aug 01 2006 Maros Barabas - 2.0.5-4 +- listen to IPv4 connections in default conf file + +* Mon Jul 17 2006 Radek Vokal - 2.0.5-3 +- listen to IPv6 connections in default conf file + +* Thu Jul 13 2006 Radek Vokal - 2.0.5-2 +- add keyinit instructions to the vsftpd PAM script (#198637) + +* Wed Jul 12 2006 Radek Vokal - 2.0.5-1 +- upgrade to 2.0.5 +- IE should now show the login dialog again (#191147) + +* Wed Jul 12 2006 Jesse Keating - 2.0.4-1.2.1 +- rebuild + +* Fri Feb 10 2006 Jesse Keating - 2.0.4-1.2 +- bump again for double-long bug on ppc(64) + +* Tue Feb 07 2006 Jesse Keating - 2.0.4-1.1 +- rebuilt for new gcc4.1 snapshot and glibc changes + +* Thu Jan 12 2006 Radek Vokal 2.0.4-1 +- upgrade to 2.0.4 +- vsftpd now lock files for simultanous up/downloads (#162511) + +* Fri Dec 09 2005 Jesse Keating +- rebuilt + +* Wed Nov 09 2005 Radek Vokal 2.0.3-12 +- rebuilt against new openssl +- close std file descriptors + +* Tue Oct 04 2005 Radek Vokal 2.0.3-11 +- use include instead of pam_stack in pam config + +* Fri Sep 09 2005 Radek Vokal 2.0.3-10 +- vsfptd.log as a default log file has to be rotated (#167359) +- vsftpd does dns reverse before passing hosts to pam_access.so (#159745) + +* Wed Aug 31 2005 Radek Vokal 2.0.3-9 +- don't die when no user config file is present (#166986) + +* Tue Aug 09 2005 Radek Vokal 2.0.3-8 +- removed additional cmd line for ftp (#165083) + +* Thu Aug 04 2005 Radek Vokal 2.0.3-7 +- daemonize with file descriptors (#164998) + +* Thu Jun 30 2005 Radek Vokal 2.0.3-6 +- start in background as default, init script changed (#158714) + +* Mon Jun 27 2005 Radek Vokal 2.0.3-5 +- fixed requires for 64bit libs + +* Thu Jun 23 2005 Radek Vokal 2.0.3-4 +- fixed requires for pam_loginuid + +* Wed Jun 01 2005 Radek Vokal 2.0.3-3 +- vsftpd update for new audit system (#159223) + +* Fri May 27 2005 Radek Vokal 2.0.3-2 +- timezone fix, patch from suse.de (#158779) + +* Wed Mar 23 2005 Radek Vokal 2.0.3-1 +- new release, fixes #106416 and #134541 + +* Mon Mar 14 2005 Radek Vokal 2.0.3-pre2 +- prerelease, fixes IPv6 issues + +* Mon Mar 14 2005 Radek Vokal 2.0.2-1 +- update to new release, several bug fixes + +* Wed Mar 02 2005 Radek Vokal 2.0.1-10 +- rebuilt against gcc4 and new openssl + +* Mon Feb 07 2005 Radek Vokal 2.0.1-9 +- don't allow to read non-root config files (#145548) + +* Mon Jan 10 2005 Radek Vokal 2.0.1-8 +- use localtime also in logs (#143687) + +* Tue Dec 14 2004 Radek Vokal 2.0.1-7 +- fixing directory in vsftpd.pam file (#142805) + +* Mon Nov 11 2004 Radek Vokal 2.0.1-6 +- vsftpd. files moved to /etc/vsftpd +- added vsftpd_conf_migrate.sh script for moving conf files + +* Fri Oct 01 2004 Radek Vokal 2.0.1-5 +- vsftpd under xinetd reads its config file (#134314) + +* Thu Sep 16 2004 Radek Vokal 2.0.1-4 +- spec file changed, ftp dir change commented (#130119) +- added doc files (#113056) + +* Wed Sep 08 2004 Jan Kratochvil +- update for 2.0.1 for SSL + +* Fri Aug 27 2004 Radek Vokal 2.0.1-2 +- vsftpd.conf file changed, default IPv6 support + +* Fri Aug 20 2004 Radek Vokal 2.0.1-1 +- tcp_wrapper patch updated, signal patch updated +- upgrade to 2.0.1, fixes several bugs, RHEL and FC builds + +* Tue Jun 15 2004 Elliot Lee +- rebuilt + +* Wed May 19 2004 Bill Nottingham 1.2.1-6 +- fix the logrotate config (#116253) + +* Mon May 3 2004 Bill Nottingham 1.2.1-5 +- fix all references to vsftpd.conf to be /etc/vsftpd/vsftpd.conf, + including in the binary (#121199, #104075) + +* Thu Mar 25 2004 Bill Nottingham 1.2.1-4 +- don't call malloc()/free() in signal handlers (#119136, + ) + +* Fri Feb 13 2004 Elliot Lee +- rebuilt + +* Mon Nov 24 2003 Karsten Hopp 1.2.1-1 +- update to 1.2.1, which fixes #89765 and lot of other issues +- remove manpage patch, it isn't required anymore +- clean up init script +- don't use script to find libs to link with (lib64 issues) + +* Sun Oct 12 2003 Florian La Roche +- allow compiling without tcp_wrappers support + +* Mon Sep 15 2003 Bill Nottingham 1.2.0-4 +- fix errant newline (#104443) + +* Fri Aug 8 2003 Bill Nottingham 1.2.0-3 +- tweak man page (#84584, #72798) +- buildprereqs for pie (#99336) +- free ride through the build system to fix (#101582) + +* Thu Jun 26 2003 Bill Nottingham 1.2.0-2 +- update to 1.2.0 + +* Wed Jun 04 2003 Elliot Lee +- rebuilt + +* Mon Apr 28 2003 Bill Nottingham 1.1.3-9 +- fix tcp_wrappers usage (#89765, ) + +* Fri Feb 28 2003 Nalin Dahyabhai 1.1.3-8 +- enable use of tcp_wrappers + +* Tue Feb 11 2003 Bill Nottingham 1.1.3-7 +- provide /var/ftp & /var/ftp/pub. obsolete anonftp. + +* Mon Feb 10 2003 Bill Nottingham 1.1.3-6 +- clean up comments in init script (#83962) + +* Wed Jan 22 2003 Tim Powers +- rebuilt + +* Mon Dec 30 2002 Florian La Roche +- change to /etc/rc.d/init.d for better compatibility + +* Mon Dec 16 2002 Bill Nottingham 1.1.3-3 +- fix initscript perms +- fix typo in initscript (#76587) + +* Fri Dec 13 2002 Bill Nottingham 1.1.3-2 +- update to 1.1.3 +- run standalone, don't run by default +- fix reqs + +* Fri Nov 22 2002 Joe Orton 1.1.0-3 +- fix use with xinetd-ipv6; add flags=IPv4 in xinetd file (#78410) + +* Tue Nov 12 2002 Nalin Dahyabhai 1.0.1-9 +- remove absolute paths from PAM configuration so that the right modules get + used for whichever arch we're built for on multilib systems + +* Thu Aug 15 2002 Elliot Lee 1.0.1-8 +- -D_FILE_OFFSET_BITS=64 +- smp make +- remove forced optflags=-g for lack of supporting documentation + +* Fri Jun 21 2002 Tim Powers +- automated rebuild + +* Thu May 23 2002 Tim Powers +- automated rebuild + +* Wed Apr 10 2002 Bill Nottingham 1.0.1-5 +- don't spit out ugly errors if anonftp isn't installed (#62987) +- fix horribly broken userlist setup (#62321) + +* Thu Feb 28 2002 Trond Eivind Glomsrød 1.0.1-4 +- s/Copyright/License/ +- add "missingok" to the logrotate script, so we don't get errors + when nothing has happened + +* Wed Jan 09 2002 Tim Powers +- automated rebuild + +* Wed Nov 28 2001 Bill Nottingham +- initial packaging for RHL, munge included specfile + +* Thu Mar 22 2001 Seth Vidal +- updated to 0.0.15 +- added entry for vsftpd.8 man page +- added entry for vsftpd.log logrotate file +- added TUNING file to docs list + +* Wed Mar 7 2001 Seth Vidal +- Updated to 0.0.14 +- made %%files entry for man page + +* Wed Feb 21 2001 Seth Vidal +- Updated to 0.0.13 + +* Mon Feb 12 2001 Seth Vidal +- Updated to 0.0.12 + +* Wed Feb 7 2001 Seth Vidal +- updated to 0.0.11 + +* Fri Feb 1 2001 Seth Vidal +- Update to 0.0.10 + +* Fri Feb 1 2001 Seth Vidal +- First RPM packaging +- Stolen items from wu-ftpd's pam setup +- Separated rh 7 and rh 6.X's packages +- Built for Rh6