diff --git a/.gitignore b/.gitignore index e69de29..811254b 100644 --- a/.gitignore +++ b/.gitignore @@ -0,0 +1,8 @@ +vsftpd-2.2.2.tar.gz +vsftpd-2.3.2.tar.gz +/vsftpd-2.3.4.tar.gz +/vsftpd-2.3.5.tar.gz +/vsftpd-3.0.0.tar.gz +/vsftpd-3.0.1.tar.gz +/vsftpd-3.0.2.tar.gz +/vsftpd-3.0.3.tar.gz diff --git a/0001-Don-t-use-the-provided-script-to-locate-libraries.patch b/0001-Don-t-use-the-provided-script-to-locate-libraries.patch new file mode 100644 index 0000000..f4a67e3 --- /dev/null +++ b/0001-Don-t-use-the-provided-script-to-locate-libraries.patch @@ -0,0 +1,27 @@ +From 7bd573d76e9c1996ad5a96f0289731a253a24301 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Tue, 6 Sep 2016 13:35:51 +0200 +Subject: [PATCH 01/59] Don't use the provided script to locate libraries. + +This branch is Fedora (RHEL) specific, so we know what +libraries we have and want to use. +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index c63ed1b..98118dc 100644 +--- a/Makefile ++++ b/Makefile +@@ -8,7 +8,7 @@ CFLAGS = -O2 -fPIE -fstack-protector --param=ssp-buffer-size=4 \ + -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 + +-- +2.14.4 + diff --git a/0001-Fix-assignment-of-an-enumerator-of-a-different-type.patch b/0001-Fix-assignment-of-an-enumerator-of-a-different-type.patch new file mode 100644 index 0000000..e20404a --- /dev/null +++ b/0001-Fix-assignment-of-an-enumerator-of-a-different-type.patch @@ -0,0 +1,33 @@ +From 8882c5f7788fc2ea7cae824a7fa09b82782fc81e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Fri, 7 Feb 2020 11:51:46 +0100 +Subject: [PATCH] Fix assignment of an enumerator of a different type + +The kVSFSysStrOpenUnknown enumerator is not part of the +EVSFSysUtilOpenMode enum. The assignment causes a build failure with +gcc 10. + +The open_mode variable need not be initialized, because the switch +statement either sets the variable or causes us to exit. + +Resolves: rhbz#1800239 +--- + sysstr.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/sysstr.c b/sysstr.c +index d86cdf1..ff2671b 100644 +--- a/sysstr.c ++++ b/sysstr.c +@@ -74,7 +74,7 @@ str_chdir(const struct mystr* p_str) + int + str_open(const struct mystr* p_str, const enum EVSFSysStrOpenMode mode) + { +- enum EVSFSysUtilOpenMode open_mode = kVSFSysStrOpenUnknown; ++ enum EVSFSysUtilOpenMode open_mode; + switch (mode) + { + case kVSFSysStrOpenReadOnly: +-- +2.24.1 + diff --git a/0001-Fix-timestamp-handling-in-MDTM.patch b/0001-Fix-timestamp-handling-in-MDTM.patch new file mode 100644 index 0000000..3975bf3 --- /dev/null +++ b/0001-Fix-timestamp-handling-in-MDTM.patch @@ -0,0 +1,151 @@ +From 6a4dc470e569df38b8a7ea09ee6aace3c73b7353 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Wed, 28 Mar 2018 09:06:34 +0200 +Subject: [PATCH 1/2] Fix timestamp handling in MDTM + +There were two problems with the timestamp handling with MDTM: + +1. In vsf_sysutil_parse_time(), the `the_time.tm_isdst` attribute was + always set to 0, regardless of whether DST (daylight saving time) + is active on the given date or not. + + This made glibc shift the timestamp when DST was in fact active on + the given date, in an attempt to correct the discrepancy between + the given timestamp and the `tm_isdst` attribute. The shifting + produced incorrect results however. + + We fix this by setting `tm_isdst` to -1 to let glibc decide if DST + is active or not at the time of the timestamp. glibc won't touch + the timestamp then. + +2. vsftpd used to record the offset from UTC of the current timezone + in the global variable `s_timezone`. This variable was then + subtracted from the variable `the_time` in vsf_sysutil_setmodtime() + when the config option use_localtime=NO was set. This was done to + compensate for the fact that mktime(), used in + vsf_sysutil_parse_time(), expects a timestamp expressed as local + time, whereas vsftpd is dealing with universal time. + + However, this did not work in the case when the offset stored in + `s_timezone` did not match the timezone of the timestamp given to + mktime() - this happens when DST is active at the current time, but + DST is not active at the time of the timestamp, or vice versa. + + We fix this by subtracting the real timezone offset directly in + vsf_sysutil_parse_time(). + + Note that the `tm_gmtoff` attribute, used in this fix, is a + BSD/glic extension. However, using `tm_gmtoff` seems like the + simplest solution and we need to make this work only with glibc + anyway. + +The fix was tested in the following way. We checked that the timestamp +given to the MDTM command when setting modification time exactly +matches the timestamp received as response from MDTM when reading back +the modification time. Additionally, we checked that the modification +time was set correctly on the given file on disk. + +These two checks were performed under various conditions - all the +combinations of DST/non-DST system time, DST/non-DST modification +time, use_localtime=YES/NO. + +Note that (I think) this will still not work if the rules for when DST +is active change. For example, if DST is ever completely cancelled in +the Europe/Prague timezone, and vsftpd is dealing with a timestamp +from a time when DST was active, it will produce incorrect results. I +think we would need the full zone file to fix this, but the zone file +is hard to provide when we're chroot-ed. + +Resolves: rhbz#1567855 +--- + postlogin.c | 5 +++-- + sysutil.c | 17 ++++++++++------- + sysutil.h | 4 ++-- + 3 files changed, 15 insertions(+), 11 deletions(-) + +diff --git a/postlogin.c b/postlogin.c +index 7c749ef..8a3d9d2 100644 +--- a/postlogin.c ++++ b/postlogin.c +@@ -1788,7 +1788,8 @@ handle_mdtm(struct vsf_session* p_sess) + if (do_write != 0) + { + str_split_char(&p_sess->ftp_arg_str, &s_filename_str, ' '); +- modtime = vsf_sysutil_parse_time(str_getbuf(&p_sess->ftp_arg_str)); ++ modtime = vsf_sysutil_parse_time( ++ str_getbuf(&p_sess->ftp_arg_str), tunable_use_localtime); + str_copy(&p_sess->ftp_arg_str, &s_filename_str); + } + resolve_tilde(&p_sess->ftp_arg_str, p_sess); +@@ -1809,7 +1810,7 @@ handle_mdtm(struct vsf_session* p_sess) + else + { + retval = vsf_sysutil_setmodtime( +- str_getbuf(&p_sess->ftp_arg_str), modtime, tunable_use_localtime); ++ str_getbuf(&p_sess->ftp_arg_str), modtime); + if (retval != 0) + { + vsf_cmdio_write(p_sess, FTP_FILEFAIL, +diff --git a/sysutil.c b/sysutil.c +index e847650..66d4c5e 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -2819,11 +2819,13 @@ vsf_sysutil_syslog(const char* p_text, int severe) + } + + long +-vsf_sysutil_parse_time(const char* p_text) ++vsf_sysutil_parse_time(const char* p_text, int is_localtime) + { ++ long res; + struct tm the_time; + unsigned int len = vsf_sysutil_strlen(p_text); + vsf_sysutil_memclr(&the_time, sizeof(the_time)); ++ the_time.tm_isdst = -1; + if (len >= 8) + { + char yr[5]; +@@ -2848,17 +2850,18 @@ vsf_sysutil_parse_time(const char* p_text) + the_time.tm_min = vsf_sysutil_atoi(mins); + the_time.tm_sec = vsf_sysutil_atoi(sec); + } +- return mktime(&the_time); ++ res = mktime(&the_time); ++ if (!is_localtime) ++ { ++ res += the_time.tm_gmtoff; ++ } ++ return res; + } + + int +-vsf_sysutil_setmodtime(const char* p_file, long the_time, int is_localtime) ++vsf_sysutil_setmodtime(const char* p_file, long the_time) + { + struct utimbuf new_times; +- if (!is_localtime) +- { +- the_time -= s_timezone; +- } + vsf_sysutil_memclr(&new_times, sizeof(new_times)); + new_times.actime = the_time; + new_times.modtime = the_time; +diff --git a/sysutil.h b/sysutil.h +index 7a59f13..b90f6ca 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -349,9 +349,9 @@ void vsf_sysutil_chroot(const char* p_root_path); + */ + long vsf_sysutil_get_time_sec(void); + long vsf_sysutil_get_time_usec(void); +-long vsf_sysutil_parse_time(const char* p_text); ++long vsf_sysutil_parse_time(const char* p_text, int is_localtime); + void vsf_sysutil_sleep(double seconds); +-int vsf_sysutil_setmodtime(const char* p_file, long the_time, int is_localtime); ++int vsf_sysutil_setmodtime(const char* p_file, long the_time); + + /* Limits */ + void vsf_sysutil_set_address_space_limit(unsigned long bytes); +-- +2.24.1 + diff --git a/0001-Move-closing-standard-FDs-after-listen.patch b/0001-Move-closing-standard-FDs-after-listen.patch new file mode 100644 index 0000000..12511e7 --- /dev/null +++ b/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/0001-Remove-a-hint-about-the-ftp_home_dir-SELinux-boolean.patch b/0001-Remove-a-hint-about-the-ftp_home_dir-SELinux-boolean.patch new file mode 100644 index 0000000..88640ac --- /dev/null +++ b/0001-Remove-a-hint-about-the-ftp_home_dir-SELinux-boolean.patch @@ -0,0 +1,25 @@ +From ab797dcffc855b05c9e7c8db4e5be2fc7510831b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 17 Mar 2020 12:57:36 +0100 +Subject: [PATCH] Remove a hint about the ftp_home_dir SELinux boolean + +The boolean has been removed from SELinux. +--- + vsftpd.conf | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/vsftpd.conf b/vsftpd.conf +index 6b8eebb..ea20a72 100644 +--- a/vsftpd.conf ++++ b/vsftpd.conf +@@ -12,7 +12,6 @@ + anonymous_enable=NO + # + # Uncomment this to allow local users to log in. +-# When SELinux is enforcing check for SE bool ftp_home_dir + local_enable=YES + # + # Uncomment this to enable any form of FTP write command. +-- +2.25.1 + diff --git a/0001-Repeat-pututxline-until-it-succeeds-if-it-fails-with.patch b/0001-Repeat-pututxline-until-it-succeeds-if-it-fails-with.patch new file mode 100644 index 0000000..63d555e --- /dev/null +++ b/0001-Repeat-pututxline-until-it-succeeds-if-it-fails-with.patch @@ -0,0 +1,108 @@ +From 7957425ef5ab365fc96ea0615f99705581c6dbd8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Mon, 12 Aug 2019 18:15:36 +0200 +Subject: [PATCH] Repeat pututxline() until it succeeds if it fails with EINTR + +Since the pututxline() bug rhbz#1749439 is now fixed in glibc in +Fedora and RHEL-8, we can implement a complete solution for the stale +utmp entries issue originally reported as rhbz#1688848. + +This patch is a followup to commit 896b3694ca062d7. + +Resolves: rhbz#1688852 +Resolves: rhbz#1737433 +--- + sysdeputil.c | 53 +++++++++++++--------------------------------------- + 1 file changed, 13 insertions(+), 40 deletions(-) + +diff --git a/sysdeputil.c b/sysdeputil.c +index 4fbcca7..75be680 100644 +--- a/sysdeputil.c ++++ b/sysdeputil.c +@@ -1203,7 +1203,7 @@ void + vsf_insert_uwtmp(const struct mystr* p_user_str, + const struct mystr* p_host_str) + { +- int attempts; ++ struct utmpx* p_res; + + if (sizeof(s_utent.ut_line) < 16) + { +@@ -1233,34 +1233,21 @@ 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(); +- for (attempts = 2; attempts > 0; --attempts) ++ setutxent(); ++ do + { +- 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(); +- } ++ } while (p_res == NULL && (errno == EINTR || errno == EAGAIN)); ++ s_uwtmp_inserted = 1; ++ endutxent(); + updwtmpx(WTMPX_FILE, &s_utent); + } + + void + vsf_remove_uwtmp(void) + { +- int attempts; ++ struct utmpx* p_res; + + if (!s_uwtmp_inserted) + { +@@ -1270,27 +1257,13 @@ 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; +- if (s_uwtmp_inserted == 1) ++ setutxent(); ++ do + { +- 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. +- */ ++ p_res = pututxline(&s_utent); ++ /* For now we'll ignore errors other than EINTR and EAGAIN */ ++ } while (p_res == NULL && (errno == EINTR || errno == EAGAIN)); ++ 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/0001-Set-s_uwtmp_inserted-only-after-record-insertion-rem.patch b/0001-Set-s_uwtmp_inserted-only-after-record-insertion-rem.patch new file mode 100644 index 0000000..00bf82c --- /dev/null +++ b/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/0002-Drop-an-unused-global-variable.patch b/0002-Drop-an-unused-global-variable.patch new file mode 100644 index 0000000..53af589 --- /dev/null +++ b/0002-Drop-an-unused-global-variable.patch @@ -0,0 +1,56 @@ +From d0045e35674d64d166d17c3c079ae03e8c2e6361 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Thu, 13 Feb 2020 17:29:06 +0100 +Subject: [PATCH 2/2] Drop an unused global variable + +The global variable `s_timezone` is not used anymore, so we can drop +it. +--- + sysutil.c | 17 +++-------------- + 1 file changed, 3 insertions(+), 14 deletions(-) + +diff --git a/sysutil.c b/sysutil.c +index 66d4c5e..0ccf551 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -72,8 +72,6 @@ static struct timeval s_current_time; + static int s_current_pid = -1; + /* Exit function */ + static exitfunc_t s_exit_func; +-/* Difference in timezone from GMT in seconds */ +-static long s_timezone; + + /* Our internal signal handling implementation details */ + static struct vsf_sysutil_sig_details +@@ -2661,7 +2659,6 @@ char* vsf_sysutil_get_tz() + void + vsf_sysutil_tzset(void) + { +- int retval; + char *tz=NULL, tzbuf[sizeof("+HHMM!")]; + time_t the_time = time(NULL); + struct tm* p_tm; +@@ -2681,17 +2678,9 @@ vsf_sysutil_tzset(void) + { + die("localtime"); + } +- retval = strftime(tzbuf, sizeof(tzbuf), "%z", p_tm); +- tzbuf[sizeof(tzbuf) - 1] = '\0'; +- if (retval == 5) +- { +- s_timezone = ((tzbuf[1] - '0') * 10 + (tzbuf[2] - '0')) * 60 * 60; +- s_timezone += ((tzbuf[3] - '0') * 10 + (tzbuf[4] - '0')) * 60; +- if (tzbuf[0] == '+') +- { +- s_timezone *= -1; +- } +- } ++ /* Not sure if the following call to strftime() has any desired side ++ effects, so I'm keeping it to be safe. */ ++ (void) strftime(tzbuf, sizeof(tzbuf), "%z", p_tm); + /* Call in to the time subsystem again now that TZ is set, trying to force + * caching of the actual zoneinfo for the timezone. + */ +-- +2.24.1 + diff --git a/0002-Enable-build-with-SSL.patch b/0002-Enable-build-with-SSL.patch new file mode 100644 index 0000000..e772099 --- /dev/null +++ b/0002-Enable-build-with-SSL.patch @@ -0,0 +1,25 @@ +From 6fe24bc56694808ac7f8038855883a971967f0fb Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Tue, 6 Sep 2016 13:40:53 +0200 +Subject: [PATCH 02/59] Enable build with SSL. + +--- + builddefs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/builddefs.h b/builddefs.h +index e908352..63cc62b 100644 +--- a/builddefs.h ++++ b/builddefs.h +@@ -3,7 +3,7 @@ + + #undef VSF_BUILD_TCPWRAPPERS + #define VSF_BUILD_PAM +-#undef VSF_BUILD_SSL ++#define VSF_BUILD_SSL + + #endif /* VSF_BUILDDEFS_H */ + +-- +2.14.4 + diff --git a/0002-Prevent-recursion-in-bug.patch b/0002-Prevent-recursion-in-bug.patch new file mode 100644 index 0000000..061fd1e --- /dev/null +++ b/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/0002-Repeat-pututxline-if-it-fails-with-EINTR.patch b/0002-Repeat-pututxline-if-it-fails-with-EINTR.patch new file mode 100644 index 0000000..e89efcf --- /dev/null +++ b/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/0003-Enable-build-with-TCP-Wrapper.patch b/0003-Enable-build-with-TCP-Wrapper.patch new file mode 100644 index 0000000..e656776 --- /dev/null +++ b/0003-Enable-build-with-TCP-Wrapper.patch @@ -0,0 +1,25 @@ +From 1e0e2b13836d40f5a3f4cb20f2b3ea8204115b51 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Tue, 6 Sep 2016 13:42:09 +0200 +Subject: [PATCH 03/59] Enable build with TCP Wrapper + +--- + builddefs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/builddefs.h b/builddefs.h +index 63cc62b..83de674 100644 +--- a/builddefs.h ++++ b/builddefs.h +@@ -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 + +-- +2.14.4 + diff --git a/0004-Use-etc-vsftpd-dir-for-config-files-instead-of-etc.patch b/0004-Use-etc-vsftpd-dir-for-config-files-instead-of-etc.patch new file mode 100644 index 0000000..e82cd84 --- /dev/null +++ b/0004-Use-etc-vsftpd-dir-for-config-files-instead-of-etc.patch @@ -0,0 +1,483 @@ +From fff93602a4b252be8d674e27083dde68a7acf038 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Tue, 6 Sep 2016 13:46:03 +0200 +Subject: [PATCH 04/59] Use /etc/vsftpd/ dir for config files instead of /etc. + +--- + EXAMPLE/INTERNET_SITE/README | 6 +++--- + EXAMPLE/INTERNET_SITE_NOINETD/README | 4 ++-- + EXAMPLE/PER_IP_CONFIG/README | 4 ++-- + EXAMPLE/VIRTUAL_USERS/README | 14 +++++++------- + FAQ | 8 ++++---- + INSTALL | 10 +++++----- + README | 5 +++++ + defs.h | 2 +- + tunables.c | 10 +++++----- + vsftpd.8 | 10 +++++----- + vsftpd.conf | 20 +++++++++++++------- + vsftpd.conf.5 | 22 +++++++++++----------- + 12 files changed, 63 insertions(+), 52 deletions(-) + +diff --git a/EXAMPLE/INTERNET_SITE/README b/EXAMPLE/INTERNET_SITE/README +index 12b10a5..fe3d7ca 100644 +--- a/EXAMPLE/INTERNET_SITE/README ++++ b/EXAMPLE/INTERNET_SITE/README +@@ -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 file. + + 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 --git a/EXAMPLE/INTERNET_SITE_NOINETD/README b/EXAMPLE/INTERNET_SITE_NOINETD/README +index ce17af2..9198c5f 100644 +--- a/EXAMPLE/INTERNET_SITE_NOINETD/README ++++ b/EXAMPLE/INTERNET_SITE_NOINETD/README +@@ -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 --git a/EXAMPLE/PER_IP_CONFIG/README b/EXAMPLE/PER_IP_CONFIG/README +index a9ef352..34924d5 100644 +--- a/EXAMPLE/PER_IP_CONFIG/README ++++ b/EXAMPLE/PER_IP_CONFIG/README +@@ -20,12 +20,12 @@ directory: hosts.allow. It lives at /etc/hosts.allow. + + 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 --git a/EXAMPLE/VIRTUAL_USERS/README b/EXAMPLE/VIRTUAL_USERS/README +index b48995d..72972fa 100644 +--- a/EXAMPLE/VIRTUAL_USERS/README ++++ b/EXAMPLE/VIRTUAL_USERS/README +@@ -15,7 +15,7 @@ See example file "logins.txt" - this specifies "tom" with password "foo" and + "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 that pam_userdb expects its login + 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 your new database. + + 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 --git a/FAQ b/FAQ +index 59fe56b..0142a0d 100644 +--- a/FAQ ++++ b/FAQ +@@ -35,7 +35,7 @@ needs this user to run bits of itself with no privilege. + 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 +@@ -47,12 +47,12 @@ system have a "shadow.h" file in the include path? + 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? +@@ -88,7 +88,7 @@ A2) Alternatively, run as many copies as vsftpd as necessary, in standalone + 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 --git a/INSTALL b/INSTALL +index 4f811aa..93a8a81 100644 +--- a/INSTALL ++++ b/INSTALL +@@ -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 --git a/README b/README +index 86643c1..adc7f42 100644 +--- a/README ++++ b/README +@@ -37,3 +37,8 @@ All configuration options are documented in the manual page vsftpd.conf.5. + 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 --git a/defs.h b/defs.h +index 0ff5864..ca11eac 100644 +--- a/defs.h ++++ b/defs.h +@@ -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 --git a/tunables.c b/tunables.c +index 284a10d..0ac4c34 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -190,7 +190,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; +@@ -262,11 +262,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); +@@ -279,7 +279,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 --git a/vsftpd.8 b/vsftpd.8 +index 6640b57..c920e7d 100644 +--- a/vsftpd.8 ++++ b/vsftpd.8 +@@ -21,7 +21,7 @@ itself will listen on the network. This latter mode is easier to use, and + 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 starting with a "-" character is treated + 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, including intermingling with loading of + 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 --git a/vsftpd.conf b/vsftpd.conf +index cc1c607..db44170 100644 +--- a/vsftpd.conf ++++ b/vsftpd.conf +@@ -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 @@ connect_from_port_20=YES + # + # 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 @@ connect_from_port_20=YES + # 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 +@@ -98,7 +100,7 @@ connect_from_port_20=YES + #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 +@@ -115,3 +117,7 @@ listen=YES + # 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/vsftpd.conf.5 b/vsftpd.conf.5 +index fcc6022..5e46a2f 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -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 "listen" mode, vsftpd will background + 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 upon login. The meaning is slightly + 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 the password provided is listed in the + 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 file is consulted if the option + .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 +@@ -803,7 +803,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 +@@ -864,7 +864,7 @@ This option can be used to provide an alternate file for usage by the + .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 +@@ -987,10 +987,10 @@ the manual page, on a per-user basis. Usage is simple, and is best illustrated + 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 +@@ -1026,7 +1026,7 @@ This option is the name of the file loaded when the + .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 +-- +2.14.4 + diff --git a/0005-Use-hostname-when-calling-PAM-authentication-module.patch b/0005-Use-hostname-when-calling-PAM-authentication-module.patch new file mode 100644 index 0000000..af842f5 --- /dev/null +++ b/0005-Use-hostname-when-calling-PAM-authentication-module.patch @@ -0,0 +1,75 @@ +From 08c49b78942d40c99fae8c40e7668aa73e1bd695 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Tue, 6 Sep 2016 15:01:23 +0200 +Subject: [PATCH 05/59] Use hostname when calling PAM authentication module. + +Currently the vsftpd passes all logins as IP addresses +into PAM. This prevents administrators from setting up +ACLs based on domain (e.g. .example.com). This patch +enables reverse host lookup and use hostname instead +of address if there is one. +--- + sysdeputil.c | 19 ++++++++++++++++--- + 1 file changed, 16 insertions(+), 3 deletions(-) + +diff --git a/sysdeputil.c b/sysdeputil.c +index 06f01f4..b2782da 100644 +--- a/sysdeputil.c ++++ b/sysdeputil.c +@@ -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" + +@@ -323,6 +327,10 @@ vsf_sysdep_check_auth(struct mystr* p_user_str, + 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 = +@@ -346,7 +354,12 @@ vsf_sysdep_check_auth(struct mystr* p_user_str, + 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); +@@ -559,7 +572,7 @@ vsf_sysdep_has_capabilities(void) + } + return s_runtime_has_caps; + } +- ++ + #ifndef VSF_SYSDEP_HAVE_LIBCAP + static int + do_checkcap(void) +@@ -1081,7 +1094,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) + { +-- +2.14.4 + diff --git a/0006-Close-stdin-out-err-before-listening-for-incoming-co.patch b/0006-Close-stdin-out-err-before-listening-for-incoming-co.patch new file mode 100644 index 0000000..f030f35 --- /dev/null +++ b/0006-Close-stdin-out-err-before-listening-for-incoming-co.patch @@ -0,0 +1,35 @@ +From 423cbf4ddca6578b87e0f8a3fc425688cd1ca89c Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Tue, 6 Sep 2016 16:18:39 +0200 +Subject: [PATCH 06/59] Close stdin/out/err before listening for incoming + connections. + +When running vsftpd as a stand-alone FTP daemon, vsftpd +did not close stdin/out/err. This caused the start script +to hang waiting for stdin to close. Before this patch was +applied, one had to hit ctrl+c in order to get shell prompt +back. Correct behavior: +$ /etc/init.d/vsftpd start | tee +Starting vsftpd for vsftpd: [ OK ] +$ +--- + standalone.c | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/standalone.c b/standalone.c +index ba01ab1..e0f2d5b 100644 +--- a/standalone.c ++++ b/standalone.c +@@ -130,6 +130,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)) + { +-- +2.14.4 + diff --git a/0007-Make-filename-filters-smarter.patch b/0007-Make-filename-filters-smarter.patch new file mode 100644 index 0000000..6db2d1a --- /dev/null +++ b/0007-Make-filename-filters-smarter.patch @@ -0,0 +1,102 @@ +From 548375b2122f83771dc0b8571f16e5b5adabba98 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 10:04:31 +0200 +Subject: [PATCH 07/59] Make filename filters smarter. + +In the original version vsftpd was not able to prevent +users from downloading for instance /etc/passwd by +defining filters such as deny_file=/etc/passwd or /etc* +or passwd. Example of erroneous behavior: +230 Login successful. +Remote system type is UNIX. +Using binary mode to transfer files. +ftp> cd / +250 Directory successfully changed. +ftp> cd /etc +550 Permission denied. +ftp> cd etc +250 Directory successfully changed. +ftp> get passwd +local: passwd remote: passwd +227 Entering Passive Mode (127,0,0,1,99,251) +150 Opening BINARY mode data connection for passwd (2813 bytes). +226 File send OK. +2813 bytes received in 0.00016 seconds (1.7e+04 Kbytes/s) +ftp> quit +221 Goodbye. +--- + ls.c | 24 +++++++++++++++++++++++- + str.c | 11 +++++++++++ + str.h | 1 + + 3 files changed, 35 insertions(+), 1 deletion(-) + +diff --git a/ls.c b/ls.c +index 7e1376d..f489478 100644 +--- a/ls.c ++++ b/ls.c +@@ -246,8 +246,30 @@ vsf_filename_passes_filter(const struct mystr* p_filename_str, + 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) + { +diff --git a/str.c b/str.c +index 6596204..ba4b92a 100644 +--- a/str.c ++++ b/str.c +@@ -711,3 +711,14 @@ str_replace_unprintable(struct mystr* p_str, char new_char) + } + } + ++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 --git a/str.h b/str.h +index ab0a9a4..3a21b50 100644 +--- a/str.h ++++ b/str.h +@@ -100,6 +100,7 @@ void str_replace_unprintable(struct mystr* p_str, char new_char); + 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 +-- +2.14.4 + diff --git a/0008-Write-denied-logins-into-the-log.patch b/0008-Write-denied-logins-into-the-log.patch new file mode 100644 index 0000000..5e16953 --- /dev/null +++ b/0008-Write-denied-logins-into-the-log.patch @@ -0,0 +1,147 @@ +From 75c172596aa9e7a9f32062579f7f98783341c924 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 10:17:17 +0200 +Subject: [PATCH 08/59] Write denied logins into the log. + +This patch adds a new option 'userlist_log'. If enabled, +every login denial based on the user list will be logged. +--- + logging.c | 7 +++++++ + logging.h | 11 +++++++++++ + parseconf.c | 1 + + prelogin.c | 14 ++++++++++++++ + tunables.c | 2 ++ + tunables.h | 1 + + vsftpd.conf.5 | 8 ++++++++ + 7 files changed, 44 insertions(+) + +diff --git a/logging.c b/logging.c +index ad531d6..99671b4 100644 +--- a/logging.c ++++ b/logging.c +@@ -103,6 +103,13 @@ vsf_log_line(struct vsf_session* p_sess, enum EVSFLogEntryType what, + 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 --git a/logging.h b/logging.h +index 48f88ec..1ff57d1 100644 +--- a/logging.h ++++ b/logging.h +@@ -80,5 +80,16 @@ void vsf_log_do_log(struct vsf_session* p_sess, int succeeded); + 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 --git a/parseconf.c b/parseconf.c +index ea2242b..385afd2 100644 +--- a/parseconf.c ++++ b/parseconf.c +@@ -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 }, ++ { "userlist_log", &tunable_userlist_log }, + { "debug_ssl", &tunable_debug_ssl }, + { "require_cert", &tunable_require_cert }, + { "validate_cert", &tunable_validate_cert }, +diff --git a/prelogin.c b/prelogin.c +index df4aade..1588bc1 100644 +--- a/prelogin.c ++++ b/prelogin.c +@@ -246,6 +246,20 @@ handle_user_command(struct vsf_session* p_sess) + 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 --git a/tunables.c b/tunables.c +index 0ac4c34..b30fca1 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -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; +@@ -212,6 +213,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 --git a/tunables.h b/tunables.h +index 05d2456..e44d64c 100644 +--- a/tunables.h ++++ b/tunables.h +@@ -73,6 +73,7 @@ extern int tunable_force_anon_data_ssl; /* Require anon data uses 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 --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 5e46a2f..9d767b1 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -586,6 +586,14 @@ Default: NO + If set to yes, all SSL client certificates received must validate OK. + Self-signed certs do not constitute OK validation. (New in v2.0.6). + ++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 +-- +2.14.4 + diff --git a/0009-Trim-whitespaces-when-reading-configuration.patch b/0009-Trim-whitespaces-when-reading-configuration.patch new file mode 100644 index 0000000..97f3e4f --- /dev/null +++ b/0009-Trim-whitespaces-when-reading-configuration.patch @@ -0,0 +1,99 @@ +From d024bc27cee40f21e6a3841266062408c44e56fb Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 10:35:54 +0200 +Subject: [PATCH 09/59] Trim whitespaces when reading configuration. + +--- + parseconf.c | 2 +- + str.c | 12 ++++++++++++ + str.h | 1 + + sysutil.c | 12 ++++++++++++ + sysutil.h | 1 + + 5 files changed, 27 insertions(+), 1 deletion(-) + +diff --git a/parseconf.c b/parseconf.c +index 385afd2..30df598 100644 +--- a/parseconf.c ++++ b/parseconf.c +@@ -280,7 +280,7 @@ vsf_parseconf_load_setting(const char* p_setting, int errs_fatal) + } + else + { +- *p_curr_setting = str_strdup(&s_value_str); ++ *p_curr_setting = str_strdup_trimmed(&s_value_str); + } + return; + } +diff --git a/str.c b/str.c +index ba4b92a..41b27db 100644 +--- a/str.c ++++ b/str.c +@@ -104,6 +104,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 --git a/str.h b/str.h +index 3a21b50..44270da 100644 +--- a/str.h ++++ b/str.h +@@ -31,6 +31,7 @@ void str_alloc_ulong(struct mystr* p_str, unsigned long the_ulong); + 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 --git a/sysutil.c b/sysutil.c +index 5cdb6ef..428a34a 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -1035,6 +1035,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 --git a/sysutil.h b/sysutil.h +index c34778c..c2ddd15 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -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); +-- +2.14.4 + diff --git a/0010-Improve-daemonizing.patch b/0010-Improve-daemonizing.patch new file mode 100644 index 0000000..d2de767 --- /dev/null +++ b/0010-Improve-daemonizing.patch @@ -0,0 +1,209 @@ +From 569e7078244470ac0fcc2af3947c2735338555ec Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 11:29:29 +0200 +Subject: [PATCH 10/59] Improve daemonizing + +Init script gets correct return code if binding fails. +--- + standalone.c | 38 +++++++++++++++++++++++++++++++++++++- + sysutil.c | 59 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + sysutil.h | 7 ++++++- + 3 files changed, 102 insertions(+), 2 deletions(-) + +diff --git a/standalone.c b/standalone.c +index e0f2d5b..3b65ea2 100644 +--- a/standalone.c ++++ b/standalone.c +@@ -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(); +@@ -99,6 +113,10 @@ vsf_standalone_main(void) + { + die("could not bind listening IPv4 socket"); + } ++ if (tunable_background) ++ { ++ vsf_sysutil_kill(vsf_sysutil_getppid(), kVSFSysUtilSigUSR1); ++ } + } + else + { +@@ -129,6 +147,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); +@@ -268,6 +290,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 --git a/sysutil.c b/sysutil.c +index 428a34a..c848356 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -201,6 +201,9 @@ vsf_sysutil_translate_sig(const enum EVSFSysUtilSignal sig) + case kVSFSysUtilSigHUP: + realsig = SIGHUP; + break; ++ case kVSFSysUtilSigUSR1: ++ realsig = SIGUSR1; ++ break; + default: + bug("unknown signal in vsf_sysutil_translate_sig"); + break; +@@ -549,6 +552,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) + { +@@ -2871,3 +2880,53 @@ vsf_sysutil_post_fork() + 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 --git a/sysutil.h b/sysutil.h +index c2ddd15..bfc92cb 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -30,7 +30,8 @@ enum EVSFSysUtilSignal + kVSFSysUtilSigCHLD, + kVSFSysUtilSigPIPE, + kVSFSysUtilSigURG, +- kVSFSysUtilSigHUP ++ kVSFSysUtilSigHUP, ++ kVSFSysUtilSigUSR1 + }; + enum EVSFSysUtilInterruptContext + { +@@ -165,6 +166,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); +-- +2.14.4 + diff --git a/0011-Fix-listing-with-more-than-one-star.patch b/0011-Fix-listing-with-more-than-one-star.patch new file mode 100644 index 0000000..a675978 --- /dev/null +++ b/0011-Fix-listing-with-more-than-one-star.patch @@ -0,0 +1,38 @@ +From 32e6642640635d7305969f808b5badb706a11bff Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 11:36:17 +0200 +Subject: [PATCH 11/59] Fix listing with more than one star '*'. + +This is a regression introduced by some previous patch. +--- + ls.c | 14 ++++++++++++++ + 1 file changed, 14 insertions(+) + +diff --git a/ls.c b/ls.c +index f489478..616b2d9 100644 +--- a/ls.c ++++ b/ls.c +@@ -311,6 +311,20 @@ vsf_filename_passes_filter(const struct mystr* p_filename_str, + { + 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)); +-- +2.14.4 + diff --git a/0012-Replace-syscall-__NR_clone-.-with-clone.patch b/0012-Replace-syscall-__NR_clone-.-with-clone.patch new file mode 100644 index 0000000..84d01e6 --- /dev/null +++ b/0012-Replace-syscall-__NR_clone-.-with-clone.patch @@ -0,0 +1,35 @@ +From 0c3a1123c391995ab46cfde603fa025ff180a819 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 11:43:54 +0200 +Subject: [PATCH 12/59] Replace syscall(__NR_clone ..) with clone () + +in order to fix incorrect order of params on s390 arch +--- + sysdeputil.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/sysdeputil.c b/sysdeputil.c +index b2782da..3bbabaa 100644 +--- a/sysdeputil.c ++++ b/sysdeputil.c +@@ -1306,7 +1306,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) +@@ -1328,7 +1328,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) +-- +2.14.4 + diff --git a/0013-Extend-man-pages-with-systemd-info.patch b/0013-Extend-man-pages-with-systemd-info.patch new file mode 100644 index 0000000..5dcd965 --- /dev/null +++ b/0013-Extend-man-pages-with-systemd-info.patch @@ -0,0 +1,86 @@ +From 813a4bc45d45f4af94c699893cb2d2ba998d5d31 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 11:53:07 +0200 +Subject: [PATCH 13/59] Extend man pages with systemd info. + +Man pages now reflect how is vsftpd used as +systemd service. +--- + vsftpd.8 | 24 ++++++++++++++++++++++++ + vsftpd.conf.5 | 18 +++++++++++++++++- + 2 files changed, 41 insertions(+), 1 deletion(-) + +diff --git a/vsftpd.8 b/vsftpd.8 +index c920e7d..fbeb1a2 100644 +--- a/vsftpd.8 ++++ b/vsftpd.8 +@@ -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 "blah", which overrides any default vsftpd + 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 --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 9d767b1..0744f85 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -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 +-- +2.14.4 + diff --git a/0014-Add-support-for-square-brackets-in-ls.patch b/0014-Add-support-for-square-brackets-in-ls.patch new file mode 100644 index 0000000..27f5374 --- /dev/null +++ b/0014-Add-support-for-square-brackets-in-ls.patch @@ -0,0 +1,277 @@ +From ba0520650ae7f9f63e48ba9fb3a94297aebe2d0c Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 14:22:21 +0200 +Subject: [PATCH 14/59] Add support for square brackets in ls. + +--- + ls.c | 222 +++++++++++++++++++++++++++++++++++++++++++++---------------------- + 1 file changed, 150 insertions(+), 72 deletions(-) + +diff --git a/ls.c b/ls.c +index 616b2d9..b840136 100644 +--- a/ls.c ++++ b/ls.c +@@ -246,7 +246,7 @@ vsf_filename_passes_filter(const struct mystr* p_filename_str, + 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 mystr* p_filename_str, + 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 mystr* p_filename_str, + 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)) ++ struct str_locate_result end_sqb = ++ str_locate_char(&filter_remain_str, ']'); ++ must_match_at_current_pos = 1; ++ if (end_sqb.found) + { +- 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)) ++ 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. +-- +2.14.4 + diff --git a/0015-Listen-on-IPv6-by-default.patch b/0015-Listen-on-IPv6-by-default.patch new file mode 100644 index 0000000..b762b09 --- /dev/null +++ b/0015-Listen-on-IPv6-by-default.patch @@ -0,0 +1,55 @@ +From c5daaedf1efe23b397a5950f5503f5cbfac871c8 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 14:25:28 +0200 +Subject: [PATCH 15/59] Listen on IPv6 by default. + +--- + vsftpd.conf | 14 +++++++++----- + vsftpd.conf.5 | 5 +++-- + 2 files changed, 12 insertions(+), 7 deletions(-) + +diff --git a/vsftpd.conf b/vsftpd.conf +index db44170..ae6c6c9 100644 +--- a/vsftpd.conf ++++ b/vsftpd.conf +@@ -111,12 +111,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 +-# +-# 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. ++listen=NO ++# ++# 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 +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 0744f85..72bb86f 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -297,8 +297,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 +-- +2.14.4 + diff --git a/0016-Increase-VSFTP_AS_LIMIT-from-200UL-to-400UL.patch b/0016-Increase-VSFTP_AS_LIMIT-from-200UL-to-400UL.patch new file mode 100644 index 0000000..fae6b9c --- /dev/null +++ b/0016-Increase-VSFTP_AS_LIMIT-from-200UL-to-400UL.patch @@ -0,0 +1,27 @@ +From 048208a4db5d7164d89ba5d7545e281d0a3472d3 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Wed, 7 Sep 2016 15:35:59 +0200 +Subject: [PATCH 16/59] Increase VSFTP_AS_LIMIT from 200UL to 400UL. + +When using a PAM module to get users from LDAP or database the old +limit was insufficient. +--- + defs.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/defs.h b/defs.h +index ca11eac..bde3232 100644 +--- a/defs.h ++++ b/defs.h +@@ -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 200UL * 1024 * 1024 ++#define VSFTP_AS_LIMIT 400UL * 1024 * 1024 + + #endif /* VSF_DEFS_H */ + +-- +2.14.4 + diff --git a/0017-Fix-an-issue-with-timestamps-during-DST.patch b/0017-Fix-an-issue-with-timestamps-during-DST.patch new file mode 100644 index 0000000..f331433 --- /dev/null +++ b/0017-Fix-an-issue-with-timestamps-during-DST.patch @@ -0,0 +1,161 @@ +From 5ec0b86e5c1ff060720b5a6cd1af9d93ec993650 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 29 Sep 2016 11:14:03 +0200 +Subject: [PATCH 17/59] Fix an issue with timestamps during DST. + +vsftpd now checks whether a file was uploaded during DST and +adjust the timestamp accordingly. +--- + sysutil.c | 104 ++++++++++++++++++++++++++++++++++++++++++++++---------------- + 1 file changed, 77 insertions(+), 27 deletions(-) + +diff --git a/sysutil.c b/sysutil.c +index c848356..2abdd13 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -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 +@@ -56,6 +58,11 @@ + #include + #include + ++#ifndef __USE_GNU ++ #define __USE_GNU ++#endif ++#include ++ + /* Private variables to this file */ + /* Current umask() */ + static unsigned int s_current_umask; +@@ -2574,49 +2581,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; + } +-- +2.14.4 + diff --git a/0018-Change-the-default-log-file-in-configuration.patch b/0018-Change-the-default-log-file-in-configuration.patch new file mode 100644 index 0000000..369a69c --- /dev/null +++ b/0018-Change-the-default-log-file-in-configuration.patch @@ -0,0 +1,43 @@ +From 61dac172bdb14c5a37713078828ea8c8f78c7eb6 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 29 Sep 2016 13:53:16 +0200 +Subject: [PATCH 18/59] Change the default log file in configuration. + +Previous "default" value was wrong. +tunables.c:262 => install_str_setting("/var/log/xferlog", +&tunable_xferlog_file); +--- + RedHat/vsftpd.log | 6 ++++++ + vsftpd.conf | 2 +- + 2 files changed, 7 insertions(+), 1 deletion(-) + +diff --git a/RedHat/vsftpd.log b/RedHat/vsftpd.log +index d338de8..14731c1 100644 +--- a/RedHat/vsftpd.log ++++ b/RedHat/vsftpd.log +@@ -3,3 +3,9 @@ + nocompress + missingok + } ++ ++/var/log/xferlog { ++ # ftpd doesn't handle SIGHUP properly ++ nocompress ++ missingok ++} +diff --git a/vsftpd.conf b/vsftpd.conf +index ae6c6c9..39d1955 100644 +--- a/vsftpd.conf ++++ b/vsftpd.conf +@@ -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. +-- +2.14.4 + diff --git a/0019-Introduce-reverse_lookup_enable-option.patch b/0019-Introduce-reverse_lookup_enable-option.patch new file mode 100644 index 0000000..85023c1 --- /dev/null +++ b/0019-Introduce-reverse_lookup_enable-option.patch @@ -0,0 +1,109 @@ +From 721de88621100f6ed33f1602415bc249f3ed3219 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 10:22:32 +0100 +Subject: [PATCH 19/59] Introduce reverse_lookup_enable option. + +vsftpd can transform IP address into hostname before +PAM authentication. You can disable it to prevent +performance issues. +--- + parseconf.c | 1 + + sysdeputil.c | 14 +++++++++----- + tunables.c | 2 ++ + tunables.h | 1 + + vsftpd.conf.5 | 9 +++++++++ + 5 files changed, 22 insertions(+), 5 deletions(-) + +diff --git a/parseconf.c b/parseconf.c +index 30df598..3e0dba4 100644 +--- a/parseconf.c ++++ b/parseconf.c +@@ -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 --git a/sysdeputil.c b/sysdeputil.c +index 3bbabaa..2063c87 100644 +--- a/sysdeputil.c ++++ b/sysdeputil.c +@@ -354,12 +354,16 @@ vsf_sysdep_check_auth(struct mystr* p_user_str, + 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 --git a/tunables.c b/tunables.c +index b30fca1..c737465 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -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 --git a/tunables.h b/tunables.h +index e44d64c..9553038 100644 +--- a/tunables.h ++++ b/tunables.h +@@ -73,6 +73,7 @@ extern int tunable_force_anon_data_ssl; /* Require anon data uses 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 --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 72bb86f..fb6324e 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -423,6 +423,15 @@ so you may want to disable it. For a discussion of the consequences, see + http://scarybeastsecurity.blogspot.com/2009/02/vsftpd-210-released.html + (Added in v2.1.0). + ++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 +-- +2.14.4 + diff --git a/0020-Use-unsigned-int-for-uid-and-gid-representation.patch b/0020-Use-unsigned-int-for-uid-and-gid-representation.patch new file mode 100644 index 0000000..ac3ac1f --- /dev/null +++ b/0020-Use-unsigned-int-for-uid-and-gid-representation.patch @@ -0,0 +1,250 @@ +From dcaaf1e0dd3985e229a87de18b83f301d30b6ce9 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 10:31:39 +0100 +Subject: [PATCH 20/59] Use unsigned int for uid and gid representation. + +--- + ls.c | 4 ++-- + privops.c | 3 +-- + session.h | 6 +++--- + sysutil.c | 44 ++++++++++++++------------------------------ + sysutil.h | 20 ++++++++++---------- + 5 files changed, 30 insertions(+), 47 deletions(-) + +diff --git a/ls.c b/ls.c +index b840136..3c0988c 100644 +--- a/ls.c ++++ b/ls.c +@@ -503,7 +503,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) + { +@@ -528,7 +528,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 27a488f..956bfb7 100644 +--- a/session.h ++++ b/session.h +@@ -54,9 +54,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 2abdd13..9881a66 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -1454,14 +1454,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; +@@ -1502,7 +1502,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) + { +@@ -2320,13 +2320,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* +@@ -2349,14 +2345,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; +@@ -2364,13 +2360,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* +@@ -2445,25 +2437,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; + } + +@@ -2854,7 +2838,7 @@ vsf_sysutil_ftruncate(int fd) + } + } + +-int ++unsigned int + vsf_sysutil_getuid(void) + { + return getuid(); +diff --git a/sysutil.h b/sysutil.h +index bfc92cb..79b5514 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -129,15 +129,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); +@@ -290,15 +290,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 */ +@@ -316,7 +316,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); +@@ -329,8 +329,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); +-- +2.14.4 + diff --git a/0021-Introduce-support-for-DHE-based-cipher-suites.patch b/0021-Introduce-support-for-DHE-based-cipher-suites.patch new file mode 100644 index 0000000..1abe1e4 --- /dev/null +++ b/0021-Introduce-support-for-DHE-based-cipher-suites.patch @@ -0,0 +1,226 @@ +From 4eac1dbb5f70a652d31847eec7c28d245f36cdbb Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 10:48:28 +0100 +Subject: [PATCH 21/59] Introduce support for DHE based cipher suites. + +--- + parseconf.c | 1 + + ssl.c | 93 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- + tunables.c | 5 +++- + tunables.h | 1 + + vsftpd.conf.5 | 6 ++++ + 5 files changed, 104 insertions(+), 2 deletions(-) + +diff --git a/parseconf.c b/parseconf.c +index 3e0dba4..38e3182 100644 +--- a/parseconf.c ++++ b/parseconf.c +@@ -176,6 +176,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 --git a/ssl.c b/ssl.c +index c362983..22b69b3 100644 +--- a/ssl.c ++++ b/ssl.c +@@ -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_session* p_sess, + 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) + { +@@ -165,6 +241,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; + } +@@ -702,6 +781,18 @@ ssl_verify_callback(int verify_ok, X509_STORE_CTX* p_ctx) + 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 --git a/tunables.c b/tunables.c +index c737465..1ea7227 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -140,6 +140,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; +@@ -288,7 +289,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("ECDHE-RSA-AES256-GCM-SHA384", &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 --git a/tunables.h b/tunables.h +index 9553038..3995472 100644 +--- a/tunables.h ++++ b/tunables.h +@@ -142,6 +142,7 @@ extern const char* tunable_user_sub_token; + 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 --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index fb6324e..ff94eca 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -893,6 +893,12 @@ to be in the same file as the certificate. + + 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 +-- +2.14.4 + diff --git a/0022-Introduce-support-for-EDDHE-based-cipher-suites.patch b/0022-Introduce-support-for-EDDHE-based-cipher-suites.patch new file mode 100644 index 0000000..1428b86 --- /dev/null +++ b/0022-Introduce-support-for-EDDHE-based-cipher-suites.patch @@ -0,0 +1,136 @@ +From a6d641a0ccba1033587f6faa0e5e6749fa35f5c4 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 10:49:22 +0100 +Subject: [PATCH 22/59] Introduce support for EDDHE based cipher suites. + +--- + parseconf.c | 1 + + ssl.c | 37 ++++++++++++++++++++++++++++++++++++- + tunables.c | 4 +++- + tunables.h | 1 + + vsftpd.conf.5 | 8 ++++++++ + 5 files changed, 49 insertions(+), 2 deletions(-) + +diff --git a/parseconf.c b/parseconf.c +index 38e3182..a2c715b 100644 +--- a/parseconf.c ++++ b/parseconf.c +@@ -177,6 +177,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 --git a/ssl.c b/ssl.c +index 22b69b3..96bf8ad 100644 +--- a/ssl.c ++++ b/ssl.c +@@ -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; +@@ -244,6 +244,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 --git a/tunables.c b/tunables.c +index 1ea7227..93f85b1 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -141,6 +141,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; +@@ -290,7 +291,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 --git a/tunables.h b/tunables.h +index 3995472..3e2d40c 100644 +--- a/tunables.h ++++ b/tunables.h +@@ -143,6 +143,7 @@ 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_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 --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index ff94eca..e242873 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -899,6 +899,14 @@ ephemeral Diffie-Hellman key exchange in SSL. + + 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 +-- +2.14.4 + diff --git a/0023-Add-documentation-for-isolate_-options.-Correct-defa.patch b/0023-Add-documentation-for-isolate_-options.-Correct-defa.patch new file mode 100644 index 0000000..7cc0bfa --- /dev/null +++ b/0023-Add-documentation-for-isolate_-options.-Correct-defa.patch @@ -0,0 +1,63 @@ +From 3d02ef3be17f37baf729e786a8f36af4982f70ad Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 10:52:16 +0100 +Subject: [PATCH 23/59] Add documentation for isolate_* options. Correct + default + +values of max_clients, max_per_ip. +--- + vsftpd.conf.5 | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index e242873..31d317f 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -652,6 +652,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 +@@ -749,8 +764,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. +@@ -760,9 +776,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 +-- +2.14.4 + diff --git a/0024-Introduce-new-return-value-450.patch b/0024-Introduce-new-return-value-450.patch new file mode 100644 index 0000000..86c5f8e --- /dev/null +++ b/0024-Introduce-new-return-value-450.patch @@ -0,0 +1,77 @@ +From 1d5cdf309387ff92988ab17d746f015d833a4b92 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 11:08:52 +0100 +Subject: [PATCH 24/59] Introduce new return value 450: + + *450 Requested file action not taken. + File unavailable (e.g., file busy). +--- + ftpcodes.h | 1 + + postlogin.c | 9 ++++++++- + sysutil.c | 3 +++ + sysutil.h | 3 ++- + 4 files changed, 14 insertions(+), 2 deletions(-) + +diff --git a/ftpcodes.h b/ftpcodes.h +index 93290c0..81e25c5 100644 +--- a/ftpcodes.h ++++ b/ftpcodes.h +@@ -52,6 +52,7 @@ + #define FTP_TLS_FAIL 421 + #define FTP_BADSENDCONN 425 + #define FTP_BADSENDNET 426 ++#define FTP_FILETMPFAIL 450 + #define FTP_BADSENDFILE 451 + + #define FTP_BADCMD 500 +diff --git a/postlogin.c b/postlogin.c +index bf12970..29958c0 100644 +--- a/postlogin.c ++++ b/postlogin.c +@@ -679,7 +679,14 @@ handle_retr(struct vsf_session* p_sess, int is_http) + opened_file = str_open(&p_sess->ftp_arg_str, kVSFSysStrOpenReadOnly); + if (vsf_sysutil_retval_is_error(opened_file)) + { +- vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file."); ++ if (kVSFSysUtilErrAGAIN == vsf_sysutil_get_error()) ++ { ++ vsf_cmdio_write(p_sess, FTP_FILETMPFAIL, "Temporarily failed to open file"); ++ } ++ else ++ { ++ vsf_cmdio_write(p_sess, FTP_FILEFAIL, "Failed to open file."); ++ } + return; + } + /* Lock file if required */ +diff --git a/sysutil.c b/sysutil.c +index 9881a66..6d7cb3f 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -1632,6 +1632,9 @@ vsf_sysutil_get_error(void) + case ENOENT: + retval = kVSFSysUtilErrNOENT; + break; ++ case EAGAIN: ++ retval = kVSFSysUtilErrAGAIN; ++ break; + default: + break; + } +diff --git a/sysutil.h b/sysutil.h +index 79b5514..c145bdf 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -18,7 +18,8 @@ enum EVSFSysUtilError + kVSFSysUtilErrINVAL, + kVSFSysUtilErrOPNOTSUPP, + kVSFSysUtilErrACCES, +- kVSFSysUtilErrNOENT ++ kVSFSysUtilErrNOENT, ++ kVSFSysUtilErrAGAIN + }; + enum EVSFSysUtilError vsf_sysutil_get_error(void); + +-- +2.14.4 + diff --git a/0025-Improve-local_max_rate-option.patch b/0025-Improve-local_max_rate-option.patch new file mode 100644 index 0000000..e78f825 --- /dev/null +++ b/0025-Improve-local_max_rate-option.patch @@ -0,0 +1,90 @@ +From 386db86fe865fb552b1867af4bf4b78dbf9080cf Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 12:44:26 +0100 +Subject: [PATCH 25/59] Improve local_max_rate option. + +Now it should work as expected. +--- + ftpdataio.c | 14 +++++++------- + main.c | 2 +- + session.h | 3 ++- + 3 files changed, 10 insertions(+), 9 deletions(-) + +diff --git a/ftpdataio.c b/ftpdataio.c +index 3e4e9c9..00f9021 100644 +--- a/ftpdataio.c ++++ b/ftpdataio.c +@@ -249,7 +249,7 @@ handle_io(int retval, int fd, void* p_private) + { + long curr_sec; + long curr_usec; +- unsigned int bw_rate; ++ unsigned long bw_rate; + double elapsed; + double pause_time; + double rate_ratio; +@@ -276,19 +276,16 @@ handle_io(int retval, int fd, void* p_private) + { + 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 +@@ -441,6 +438,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 --git a/main.c b/main.c +index eaba265..f1e2f69 100644 +--- a/main.c ++++ b/main.c +@@ -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 --git a/session.h b/session.h +index 956bfb7..3e8fdd5 100644 +--- a/session.h ++++ b/session.h +@@ -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; +-- +2.14.4 + diff --git a/0026-Prevent-hanging-in-SIGCHLD-handler.patch b/0026-Prevent-hanging-in-SIGCHLD-handler.patch new file mode 100644 index 0000000..f928cbc --- /dev/null +++ b/0026-Prevent-hanging-in-SIGCHLD-handler.patch @@ -0,0 +1,81 @@ +From 1e65a0a15f819b8bf1b551bd84f71d0da1f5a00c Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 13:02:27 +0100 +Subject: [PATCH 26/59] Prevent hanging in SIGCHLD handler. + +vsftpd can now handle pam_exec.so in pam.d config without hanging +in SIGCHLD handler. +--- + sysutil.c | 4 ++-- + sysutil.h | 2 +- + twoprocess.c | 13 +++++++++++-- + 3 files changed, 14 insertions(+), 5 deletions(-) + +diff --git a/sysutil.c b/sysutil.c +index 6d7cb3f..099748f 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -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 --git a/sysutil.h b/sysutil.h +index c145bdf..13153cd 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -177,7 +177,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 --git a/twoprocess.c b/twoprocess.c +index 33d84dc..b1891e7 100644 +--- a/twoprocess.c ++++ b/twoprocess.c +@@ -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_sess, const struct mystr* p_user_str, + 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 + { +-- +2.14.4 + diff --git a/0027-Delete-files-when-upload-fails.patch b/0027-Delete-files-when-upload-fails.patch new file mode 100644 index 0000000..94a00bf --- /dev/null +++ b/0027-Delete-files-when-upload-fails.patch @@ -0,0 +1,138 @@ +From 6224ecc5ac209323baa775880c0602c3fde3590a Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 13:10:41 +0100 +Subject: [PATCH 27/59] Delete files when upload fails. + +Previously the uploaded file wasn't removed when the network was +disconnected. Now it is successfully deleted. +--- + ftpcodes.h | 3 ++- + ftpdataio.c | 8 ++++++++ + main.c | 2 +- + postlogin.c | 9 ++++++++- + session.h | 1 + + sysutil.c | 10 ++++++++++ + sysutil.h | 1 + + 7 files changed, 31 insertions(+), 3 deletions(-) + +diff --git a/ftpcodes.h b/ftpcodes.h +index 81e25c5..54dfae7 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 00f9021..c859d80 100644 +--- a/ftpdataio.c ++++ b/ftpdataio.c +@@ -242,6 +242,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 +@@ -615,6 +619,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 29958c0..e473c34 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 3e8fdd5..4eccf46 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 099748f..42bcdf8 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -680,6 +680,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) + { +diff --git a/sysutil.h b/sysutil.h +index 13153cd..2886bbc 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -266,6 +266,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); +-- +2.14.4 + diff --git a/0028-Fix-man-page-rendering.patch b/0028-Fix-man-page-rendering.patch new file mode 100644 index 0000000..e91d6dc --- /dev/null +++ b/0028-Fix-man-page-rendering.patch @@ -0,0 +1,26 @@ +From ea99be1a7a5973bbe8ed798b65abe5ce3b92f5df Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 13:12:52 +0100 +Subject: [PATCH 28/59] Fix man page rendering. + +--- + vsftpd.conf.5 | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 31d317f..cf1ae34 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -495,7 +495,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). + +-- +2.14.4 + diff --git a/0029-Fix-segfault-in-config-file-parser.patch b/0029-Fix-segfault-in-config-file-parser.patch new file mode 100644 index 0000000..65cb571 --- /dev/null +++ b/0029-Fix-segfault-in-config-file-parser.patch @@ -0,0 +1,25 @@ +From 34b9e1d10c6be736f1b20be8795c655446f38c5e Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 13:14:55 +0100 +Subject: [PATCH 29/59] Fix segfault in config file parser. + +--- + str.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +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 +-- +2.14.4 + diff --git a/0030-Fix-logging-into-syslog-when-enabled-in-config.patch b/0030-Fix-logging-into-syslog-when-enabled-in-config.patch new file mode 100644 index 0000000..04669c7 --- /dev/null +++ b/0030-Fix-logging-into-syslog-when-enabled-in-config.patch @@ -0,0 +1,25 @@ +From 03ff061f18f555d7bec62fa6a597a275b4b3f1c7 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 13:18:22 +0100 +Subject: [PATCH 30/59] Fix logging into syslog when enabled in config. + +--- + logging.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +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) + { +-- +2.14.4 + diff --git a/0031-Fix-question-mark-wildcard-withing-a-file-name.patch b/0031-Fix-question-mark-wildcard-withing-a-file-name.patch new file mode 100644 index 0000000..acc8f6d --- /dev/null +++ b/0031-Fix-question-mark-wildcard-withing-a-file-name.patch @@ -0,0 +1,28 @@ +From 0da42468ac9518a544aad57d22d7697d6bdfa969 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 13:25:12 +0100 +Subject: [PATCH 31/59] Fix question mark wildcard withing a file name. + +Previously '?' worked only at the end of a file name, now it can +be used anywhere. +--- + ls.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/ls.c b/ls.c +index 3c0988c..35c15c7 100644 +--- a/ls.c ++++ b/ls.c +@@ -459,7 +459,8 @@ vsf_filename_passes_filter(const struct mystr* p_filename_str, + 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. +-- +2.14.4 + diff --git a/0032-Propagate-errors-from-nfs-with-quota-to-client.patch b/0032-Propagate-errors-from-nfs-with-quota-to-client.patch new file mode 100644 index 0000000..de56aa7 --- /dev/null +++ b/0032-Propagate-errors-from-nfs-with-quota-to-client.patch @@ -0,0 +1,147 @@ +From aa9cb48373018502ef99a57aad70b69c0c75ff65 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 13:29:59 +0100 +Subject: [PATCH 32/59] Propagate errors from nfs with quota to client. + +vsftpd now checks for errors when closing newly uploaded file and +forward errors to the client (e.g. when file system quota was +exceeded) +--- + ftpcodes.h | 1 + + postlogin.c | 32 ++++++++++++++++++++++++++++++-- + sysutil.c | 21 +++++++++++++++++++++ + sysutil.h | 1 + + 4 files changed, 53 insertions(+), 2 deletions(-) + +diff --git a/ftpcodes.h b/ftpcodes.h +index 54dfae7..97801f3 100644 +--- a/ftpcodes.h ++++ b/ftpcodes.h +@@ -74,6 +74,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 e473c34..8363c9c 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); +@@ -1035,8 +1037,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; +@@ -1149,6 +1153,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; +@@ -1161,7 +1177,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) + { +@@ -1183,7 +1208,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 42bcdf8..1c0422e 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -1268,6 +1268,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) + { +diff --git a/sysutil.h b/sysutil.h +index 2886bbc..be727f5 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -92,6 +92,7 @@ int vsf_sysutil_create_or_open_file_append(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); +-- +2.14.4 + diff --git a/0033-Introduce-TLSv1.1-and-TLSv1.2-options.patch b/0033-Introduce-TLSv1.1-and-TLSv1.2-options.patch new file mode 100644 index 0000000..8d6228e --- /dev/null +++ b/0033-Introduce-TLSv1.1-and-TLSv1.2-options.patch @@ -0,0 +1,153 @@ +From 01bef55a1987700af3d43cdc5f5be88d3843ab85 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Thu, 17 Nov 2016 13:36:17 +0100 +Subject: [PATCH 33/59] Introduce TLSv1.1 and TLSv1.2 options. + +Users can now enable a specific version of TLS protocol. +--- + parseconf.c | 2 ++ + ssl.c | 8 ++++++++ + tunables.c | 9 +++++++-- + tunables.h | 2 ++ + vsftpd.conf.5 | 24 ++++++++++++++++++++---- + 5 files changed, 39 insertions(+), 6 deletions(-) + +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 96bf8ad..ba8a613 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 93f85b1..78f2bcd 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,10 @@ tunables_load_defaults() + tunable_force_local_data_ssl = 1; + tunable_sslv2 = 0; + tunable_sslv3 = 0; ++ /* TLSv1 up to TLSv1.2 is enabled by default */ + tunable_tlsv1 = 1; ++ tunable_tlsv1_1 = 1; ++ tunable_tlsv1_2 = 1; + tunable_tilde_user_enable = 0; + tunable_force_anon_logins_ssl = 0; + tunable_force_anon_data_ssl = 0; +@@ -292,8 +297,8 @@ tunables_load_defaults() + install_str_setting(0, &tunable_dsa_cert_file); + install_str_setting(0, &tunable_dh_param_file); + 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("AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384", ++ &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 --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..a3d569e 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: YES ++.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: YES ++.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 +@@ -1044,7 +1060,7 @@ man page for further details. Note that restricting ciphers can be a useful + security precaution as it prevents malicious remote parties forcing a cipher + which they have found problems with. + +-Default: DES-CBC3-SHA ++Default: AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384 + .TP + .B user_config_dir + This powerful option allows the override of any config option specified in +-- +2.14.4 + diff --git a/0034-Turn-off-seccomp-sandbox-because-it-is-too-strict.patch b/0034-Turn-off-seccomp-sandbox-because-it-is-too-strict.patch new file mode 100644 index 0000000..0c0bdb7 --- /dev/null +++ b/0034-Turn-off-seccomp-sandbox-because-it-is-too-strict.patch @@ -0,0 +1,25 @@ +From 4922e60589326540b2ee4f0bdfd6cb95f645f3d5 Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Fri, 18 Nov 2016 10:23:29 +0100 +Subject: [PATCH 34/59] Turn off seccomp sandbox, because it is too strict. + +--- + tunables.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/tunables.c b/tunables.c +index 78f2bcd..5440c00 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -237,7 +237,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; +-- +2.14.4 + diff --git a/0035-Modify-DH-enablement-patch-to-build-with-OpenSSL-1.1.patch b/0035-Modify-DH-enablement-patch-to-build-with-OpenSSL-1.1.patch new file mode 100644 index 0000000..1cebc18 --- /dev/null +++ b/0035-Modify-DH-enablement-patch-to-build-with-OpenSSL-1.1.patch @@ -0,0 +1,74 @@ +From 6c8dd87f311e411bcb1c72c1c780497881a5621c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Mon, 4 Sep 2017 11:32:03 +0200 +Subject: [PATCH 35/59] Modify DH enablement patch to build with OpenSSL 1.1 + +--- + ssl.c | 41 ++++++++++++++++++++++++++++++++++++++--- + 1 file changed, 38 insertions(+), 3 deletions(-) + +diff --git a/ssl.c b/ssl.c +index ba8a613..09ec96a 100644 +--- a/ssl.c ++++ b/ssl.c +@@ -88,19 +88,54 @@ static struct mystr debug_str; + } + #endif + ++#if OPENSSL_VERSION_NUMBER < 0x10100000L ++int DH_set0_pqg(DH *dh, BIGNUM *p, BIGNUM *q, BIGNUM *g) ++{ ++ /* If the fields p and g in d are NULL, the corresponding input ++ * parameters MUST be non-NULL. q may remain NULL. ++ */ ++ if ((dh->p == NULL && p == NULL) ++ || (dh->g == NULL && g == NULL)) ++ return 0; ++ ++ if (p != NULL) { ++ BN_free(dh->p); ++ dh->p = p; ++ } ++ if (q != NULL) { ++ BN_free(dh->q); ++ dh->q = q; ++ } ++ if (g != NULL) { ++ BN_free(dh->g); ++ dh->g = g; ++ } ++ ++ if (q != NULL) { ++ dh->length = BN_num_bits(q); ++ } ++ ++ return 1; ++} ++#endif ++ + #if !defined(DH_get_dh) + // Grab DH parameters + DH * + DH_get_dh(int size) + { ++ BIGNUM *g = NULL; ++ BIGNUM *p = NULL; + 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) ++ p = DH_get_prime(match_dh_bits(size)); ++ BN_dec2bn(&g, "2"); ++ if (!p || !g || !DH_set0_pqg(dh, p, NULL, g)) + { ++ BN_free(g); ++ BN_free(p); + DH_free(dh); + return NULL; + } +-- +2.14.4 + diff --git a/0036-Redefine-VSFTP_COMMAND_FD-to-1.patch b/0036-Redefine-VSFTP_COMMAND_FD-to-1.patch new file mode 100644 index 0000000..4299b23 --- /dev/null +++ b/0036-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 36/59] 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.4 + diff --git a/0037-Document-the-relationship-of-text_userdb_names-and-c.patch b/0037-Document-the-relationship-of-text_userdb_names-and-c.patch new file mode 100644 index 0000000..ae188d7 --- /dev/null +++ b/0037-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 37/59] 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.4 + diff --git a/0038-Document-allow_writeable_chroot-in-the-man-page.patch b/0038-Document-allow_writeable_chroot-in-the-man-page.patch new file mode 100644 index 0000000..ca073d3 --- /dev/null +++ b/0038-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 38/59] 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.4 + diff --git a/0039-Improve-documentation-of-ASCII-mode-in-the-man-page.patch b/0039-Improve-documentation-of-ASCII-mode-in-the-man-page.patch new file mode 100644 index 0000000..307ce35 --- /dev/null +++ b/0039-Improve-documentation-of-ASCII-mode-in-the-man-page.patch @@ -0,0 +1,34 @@ +From 7d4b76abb437184fa692533cb5537318026a30e8 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 39/59] Improve documentation of ASCII mode in the man page + +--- + vsftpd.conf.5 | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index d1f0db5..3ca55e4 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -113,11 +113,17 @@ 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 the request. 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. ++See also ++.BR ascii_download_enable ++for more details. + + Default: NO + .TP +-- +2.14.4 + diff --git a/0040-Use-system-wide-crypto-policy.patch b/0040-Use-system-wide-crypto-policy.patch new file mode 100644 index 0000000..f59ba2b --- /dev/null +++ b/0040-Use-system-wide-crypto-policy.patch @@ -0,0 +1,27 @@ +From b83be8b4f86bf1a8a6de4802a9486d084c4a46cd Mon Sep 17 00:00:00 2001 +From: Martin Sehnoutka +Date: Tue, 29 Aug 2017 10:32:16 +0200 +Subject: [PATCH 40/59] Use system wide crypto policy + +Resolves: rhbz#1483970 +--- + tunables.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/tunables.c b/tunables.c +index 5440c00..354251c 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -297,8 +297,7 @@ tunables_load_defaults() + install_str_setting(0, &tunable_dsa_cert_file); + install_str_setting(0, &tunable_dh_param_file); + install_str_setting(0, &tunable_ecdh_param_file); +- install_str_setting("AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384", +- &tunable_ssl_ciphers); ++ install_str_setting("PROFILE=SYSTEM", &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); +-- +2.14.4 + diff --git a/0041-Document-the-new-default-for-ssl_ciphers-in-the-man-.patch b/0041-Document-the-new-default-for-ssl_ciphers-in-the-man-.patch new file mode 100644 index 0000000..8b26c7b --- /dev/null +++ b/0041-Document-the-new-default-for-ssl_ciphers-in-the-man-.patch @@ -0,0 +1,31 @@ +From 2369d1ea5144d525d315aba90da528e7d9bfd1cc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Thu, 21 Dec 2017 14:19:18 +0100 +Subject: [PATCH 41/59] Document the new default for ssl_ciphers in the man + page + +Related: rhbz#1483970 +--- + vsftpd.conf.5 | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 3ca55e4..2a7662e 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -1078,7 +1078,11 @@ man page for further details. Note that restricting ciphers can be a useful + security precaution as it prevents malicious remote parties forcing a cipher + which they have found problems with. + +-Default: AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384 ++By default, the system-wide crypto policy is used. See ++.BR update-crypto-policies(8) ++for further details. ++ ++Default: PROFILE=SYSTEM + .TP + .B user_config_dir + This powerful option allows the override of any config option specified in +-- +2.14.4 + diff --git a/0042-When-handling-FEAT-command-check-ssl_tlsv1_1-and-ssl.patch b/0042-When-handling-FEAT-command-check-ssl_tlsv1_1-and-ssl.patch new file mode 100644 index 0000000..250a44c --- /dev/null +++ b/0042-When-handling-FEAT-command-check-ssl_tlsv1_1-and-ssl.patch @@ -0,0 +1,32 @@ +From 1c280a0b04e58ec63ce9ab5eb8d0ffe5ebbae115 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Thu, 21 Dec 2017 14:29:25 +0100 +Subject: [PATCH 42/59] When handling FEAT command, check ssl_tlsv1_1 and + ssl_tlsv1_2 + +Send 'AUTH SSL' in reply to the FEAT command when the ssl_tlsv1_1 +or ssl_tlsv1_2 configuration option is enabled. + +The patch was written by Martin Sehnoutka. + +Resolves: rhbz#1432054 +--- + features.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/features.c b/features.c +index 1212980..d024366 100644 +--- a/features.c ++++ b/features.c +@@ -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"); + } +-- +2.14.4 + diff --git a/0043-Enable-only-TLSv1.2-by-default.patch b/0043-Enable-only-TLSv1.2-by-default.patch new file mode 100644 index 0000000..eb157f8 --- /dev/null +++ b/0043-Enable-only-TLSv1.2-by-default.patch @@ -0,0 +1,53 @@ +From 75c942c77aa575143c5b75637e64a925ad12641a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Thu, 21 Dec 2017 16:38:40 +0100 +Subject: [PATCH 43/59] Enable only TLSv1.2 by default + +Disable TLSv1 and TLSv1.1 - enable only TLSv1.2 by default. +--- + tunables.c | 6 +++--- + vsftpd.conf.5 | 4 ++-- + 2 files changed, 5 insertions(+), 5 deletions(-) + +diff --git a/tunables.c b/tunables.c +index 354251c..9680528 100644 +--- a/tunables.c ++++ b/tunables.c +@@ -211,9 +211,9 @@ tunables_load_defaults() + tunable_force_local_data_ssl = 1; + tunable_sslv2 = 0; + tunable_sslv3 = 0; +- /* TLSv1 up to TLSv1.2 is enabled by default */ +- tunable_tlsv1 = 1; +- tunable_tlsv1_1 = 1; ++ tunable_tlsv1 = 0; ++ tunable_tlsv1_1 = 0; ++ /* Only TLSv1.2 is enabled by default */ + tunable_tlsv1_2 = 1; + tunable_tilde_user_enable = 0; + tunable_force_anon_logins_ssl = 0; +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 2a7662e..df14027 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -539,7 +539,7 @@ Only applies if + is activated. If enabled, this option will permit TLS v1 protocol connections. + TLS v1.2 connections are preferred. + +-Default: YES ++Default: NO + .TP + .B ssl_tlsv1_1 + Only applies if +@@ -547,7 +547,7 @@ Only applies if + is activated. If enabled, this option will permit TLS v1.1 protocol connections. + TLS v1.2 connections are preferred. + +-Default: YES ++Default: NO + .TP + .B ssl_tlsv1_2 + Only applies if +-- +2.14.4 + diff --git a/0044-Disable-anonymous_enable-in-default-config-file.patch b/0044-Disable-anonymous_enable-in-default-config-file.patch new file mode 100644 index 0000000..4e62d76 --- /dev/null +++ b/0044-Disable-anonymous_enable-in-default-config-file.patch @@ -0,0 +1,26 @@ +From ffaeebcfdb56ba75392af21c68c0bac78a226b55 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 2 Jan 2018 09:54:43 +0100 +Subject: [PATCH 44/59] Disable anonymous_enable in default config file + +Resolves: rhbz#1338637 +--- + vsftpd.conf | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/vsftpd.conf b/vsftpd.conf +index 39d1955..4626c1b 100644 +--- a/vsftpd.conf ++++ b/vsftpd.conf +@@ -9,7 +9,7 @@ + # capabilities. + # + # Allow anonymous FTP? (Beware - allowed by default if you comment this out). +-anonymous_enable=YES ++anonymous_enable=NO + # + # Uncomment this to allow local users to log in. + # When SELinux is enforcing check for SE bool ftp_home_dir +-- +2.14.4 + diff --git a/0045-Expand-explanation-of-ascii_-options-behaviour-in-ma.patch b/0045-Expand-explanation-of-ascii_-options-behaviour-in-ma.patch new file mode 100644 index 0000000..2243790 --- /dev/null +++ b/0045-Expand-explanation-of-ascii_-options-behaviour-in-ma.patch @@ -0,0 +1,52 @@ +From 61327320b54a59e319c522151f7a61c74ec94f2f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 2 Jan 2018 16:25:55 +0100 +Subject: [PATCH 45/59] Expand explanation of ascii_* options behaviour in man + page + +--- + vsftpd.conf.5 | 22 ++++++++++++++++++---- + 1 file changed, 18 insertions(+), 4 deletions(-) + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index df14027..a5abeb2 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -114,16 +114,30 @@ Default: YES + .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 the request. Turn this option on to have the server actually do ++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. +-See also +-.BR ascii_download_enable +-for more details. ++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.4 + diff --git a/0046-vsftpd.conf-Refer-to-the-man-page-regarding-the-asci.patch b/0046-vsftpd.conf-Refer-to-the-man-page-regarding-the-asci.patch new file mode 100644 index 0000000..61ed691 --- /dev/null +++ b/0046-vsftpd.conf-Refer-to-the-man-page-regarding-the-asci.patch @@ -0,0 +1,27 @@ +From 446f7c1ec54e06b5da2e890e0cd8fbd7308322c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 2 Jan 2018 16:33:18 +0100 +Subject: [PATCH 46/59] vsftpd.conf: Refer to the man page regarding the + ascii_* options + +--- + vsftpd.conf | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/vsftpd.conf b/vsftpd.conf +index 4626c1b..e70bc6d 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 +-- +2.14.4 + diff --git a/0047-Disable-tcp_wrappers-support.patch b/0047-Disable-tcp_wrappers-support.patch new file mode 100644 index 0000000..f71aab0 --- /dev/null +++ b/0047-Disable-tcp_wrappers-support.patch @@ -0,0 +1,49 @@ +From b383ec42bb750419fea102fccf36af5216145eb2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Fri, 5 Jan 2018 09:17:13 +0100 +Subject: [PATCH 47/59] Disable tcp_wrappers support + +Resolves: rhbz#1518796 +--- + Makefile | 2 +- + builddefs.h | 1 - + vsftpd.conf | 1 - + 3 files changed, 1 insertion(+), 3 deletions(-) + +diff --git a/Makefile b/Makefile +index 98118dc..612994e 100644 +--- a/Makefile ++++ b/Makefile +@@ -8,7 +8,7 @@ CFLAGS = -O2 -fPIE -fstack-protector --param=ssp-buffer-size=4 \ + -D_FORTIFY_SOURCE=2 \ + #-pedantic -Wconversion + +-LIBS = -lwrap -lnsl -lpam -lcap -ldl -lcrypto ++LIBS = -lnsl -lpam -lcap -ldl -lcrypto + LINK = -Wl,-s + LDFLAGS = -fPIE -pie -Wl,-z,relro -Wl,-z,now + +diff --git a/builddefs.h b/builddefs.h +index 83de674..2aa3a4c 100644 +--- a/builddefs.h ++++ b/builddefs.h +@@ -1,7 +1,6 @@ + #ifndef VSF_BUILDDEFS_H + #define VSF_BUILDDEFS_H + +-#define VSF_BUILD_TCPWRAPPERS + #define VSF_BUILD_PAM + #define VSF_BUILD_SSL + +diff --git a/vsftpd.conf b/vsftpd.conf +index e70bc6d..6b8eebb 100644 +--- a/vsftpd.conf ++++ b/vsftpd.conf +@@ -125,4 +125,3 @@ listen_ipv6=YES + + pam_service_name=vsftpd + userlist_enable=YES +-tcp_wrappers=YES +-- +2.14.4 + diff --git a/0048-Fix-default-value-of-strict_ssl_read_eof-in-man-page.patch b/0048-Fix-default-value-of-strict_ssl_read_eof-in-man-page.patch new file mode 100644 index 0000000..513e128 --- /dev/null +++ b/0048-Fix-default-value-of-strict_ssl_read_eof-in-man-page.patch @@ -0,0 +1,29 @@ +From 9cba9e81aa96e1d64ae2eaaf88330e09dadfce79 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Fri, 5 Jan 2018 09:40:09 +0100 +Subject: [PATCH 48/59] Fix default value of strict_ssl_read_eof in man page + +--- + vsftpd.conf.5 | 5 ++--- + 1 file changed, 2 insertions(+), 3 deletions(-) + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index a5abeb2..43b0435 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -574,10 +574,9 @@ Default: YES + .B strict_ssl_read_eof + If enabled, SSL data uploads are required to terminate via SSL, not an + EOF on the socket. This option is required to be sure that an attacker did +-not terminate an upload prematurely with a faked TCP FIN. Unfortunately, it +-is not enabled by default because so few clients get it right. (New in v2.0.7). ++not terminate an upload prematurely with a faked TCP FIN. (New in v2.0.7). + +-Default: NO ++Default: YES + .TP + .B strict_ssl_write_shutdown + If enabled, SSL data downloads are required to terminate via SSL, not an +-- +2.14.4 + diff --git a/0049-Add-new-filename-generation-algorithm-for-STOU-comma.patch b/0049-Add-new-filename-generation-algorithm-for-STOU-comma.patch new file mode 100644 index 0000000..22745b5 --- /dev/null +++ b/0049-Add-new-filename-generation-algorithm-for-STOU-comma.patch @@ -0,0 +1,322 @@ +From 1203b943b369651d96d057f8190f14f015e6ff0b 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 49/59] 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 | 176 +++++++++++++++++++++++++++++++++++++++++++++++++--------- + sysutil.c | 3 + + sysutil.h | 3 +- + tunables.c | 2 + + tunables.h | 3 + + vsftpd.conf.5 | 5 ++ + 7 files changed, 166 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 8363c9c..7c749ef 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); +@@ -1028,6 +1029,114 @@ 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; ++ str_trunc(&s_result, base_len); ++ for (int 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) + { +@@ -1049,41 +1158,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 1c0422e..e847650 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -1666,6 +1666,9 @@ vsf_sysutil_get_error(void) + case EAGAIN: + retval = kVSFSysUtilErrAGAIN; + break; ++ case EEXIST: ++ retval = kVSFSysUtilErrEXIST; ++ break; + default: + break; + } +diff --git a/sysutil.h b/sysutil.h +index be727f5..7a59f13 100644 +--- a/sysutil.h ++++ b/sysutil.h +@@ -19,7 +19,8 @@ enum EVSFSysUtilError + kVSFSysUtilErrOPNOTSUPP, + kVSFSysUtilErrACCES, + kVSFSysUtilErrNOENT, +- kVSFSysUtilErrAGAIN ++ kVSFSysUtilErrAGAIN, ++ 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..6911a73 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -65,6 +65,11 @@ 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 better file name generation algorithm for the STOU command. ++ + Default: NO + .TP + .B anon_mkdir_write_enable +-- +2.14.4 + diff --git a/0050-Don-t-link-with-libnsl.patch b/0050-Don-t-link-with-libnsl.patch new file mode 100644 index 0000000..8b626bb --- /dev/null +++ b/0050-Don-t-link-with-libnsl.patch @@ -0,0 +1,27 @@ +From f8663f35d5d150f0533bb052e48306b9a5111d87 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 6 Feb 2018 18:04:53 +0100 +Subject: [PATCH 50/59] Don't link with libnsl + +Don't link with libnsl. It builds just fine without it and +vsf_findlibs.sh enables it only when tcp_wrappers is enabled. +--- + Makefile | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/Makefile b/Makefile +index 612994e..0f7411c 100644 +--- a/Makefile ++++ b/Makefile +@@ -8,7 +8,7 @@ CFLAGS = -O2 -fPIE -fstack-protector --param=ssp-buffer-size=4 \ + -D_FORTIFY_SOURCE=2 \ + #-pedantic -Wconversion + +-LIBS = -lnsl -lpam -lcap -ldl -lcrypto ++LIBS = -lpam -lcap -ldl -lcrypto + LINK = -Wl,-s + LDFLAGS = -fPIE -pie -Wl,-z,relro -Wl,-z,now + +-- +2.14.4 + diff --git a/0051-Improve-documentation-of-better_stou-in-the-man-page.patch b/0051-Improve-documentation-of-better_stou-in-the-man-page.patch new file mode 100644 index 0000000..c2593be --- /dev/null +++ b/0051-Improve-documentation-of-better_stou-in-the-man-page.patch @@ -0,0 +1,30 @@ +From 765f99b26705c8d6fe2be4feb07f4c91e7eb96f9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Thu, 5 Apr 2018 12:29:03 +0200 +Subject: [PATCH 51/59] Improve documentation of better_stou in the man page + +--- + vsftpd.conf.5 | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/vsftpd.conf.5 b/vsftpd.conf.5 +index 6911a73..e9ae474 100644 +--- a/vsftpd.conf.5 ++++ b/vsftpd.conf.5 +@@ -68,7 +68,12 @@ trick the C library into loading a user-created configuration file from the + Default: NO + .TP + .B better_stou +-Use better file name generation algorithm for the STOU command. ++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 +-- +2.14.4 + diff --git a/0052-Fix-rDNS-with-IPv6.patch b/0052-Fix-rDNS-with-IPv6.patch new file mode 100644 index 0000000..eca9474 --- /dev/null +++ b/0052-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 52/59] 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.4 + diff --git a/0053-Always-do-chdir-after-chroot.patch b/0053-Always-do-chdir-after-chroot.patch new file mode 100644 index 0000000..e1c0105 --- /dev/null +++ b/0053-Always-do-chdir-after-chroot.patch @@ -0,0 +1,32 @@ +From 315f9720db94af3319c9550feaf473b9cf09aeac Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Thu, 3 May 2018 13:20:28 +0200 +Subject: [PATCH 53/59] Always do chdir("/") after chroot() + +Always do chdir("/") after chroot() to be more sure we'll never get out +of it. This will not affect the working directory after calling +vsf_sysutil_chroot(), because in the current state vsftpd always calls +vsf_sysutil_chroot("."). +--- + sysutil.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/sysutil.c b/sysutil.c +index b68583b..3014c05 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -2588,6 +2588,11 @@ vsf_sysutil_chroot(const char* p_root_path) + { + die("chroot"); + } ++ retval = chdir("/"); ++ if (retval != 0) ++ { ++ die("chdir"); ++ } + } + + unsigned int +-- +2.14.4 + diff --git a/0054-vsf_sysutil_rcvtimeo-Check-return-value-of-setsockop.patch b/0054-vsf_sysutil_rcvtimeo-Check-return-value-of-setsockop.patch new file mode 100644 index 0000000..d67db00 --- /dev/null +++ b/0054-vsf_sysutil_rcvtimeo-Check-return-value-of-setsockop.patch @@ -0,0 +1,33 @@ +From ca27e6e34d89fc247a164ed7330735644f97d7d8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Wed, 9 May 2018 20:15:29 +0200 +Subject: [PATCH 54/59] vsf_sysutil_rcvtimeo: Check return value of setsockopt + +--- + sysutil.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/sysutil.c b/sysutil.c +index 3014c05..de5f876 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -684,10 +684,15 @@ void + vsf_sysutil_rcvtimeo(int fd) + { + struct timeval tv; ++ int retval; + + tv.tv_sec = tunable_data_connection_timeout; + tv.tv_usec = 0; +- setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); ++ retval = setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(struct timeval)); ++ if (retval != 0) ++ { ++ die("setsockopt: rcvtimeo"); ++ } + } + + void +-- +2.14.4 + diff --git a/0055-vsf_sysutil_get_tz-Check-the-return-value-of-syscall.patch b/0055-vsf_sysutil_get_tz-Check-the-return-value-of-syscall.patch new file mode 100644 index 0000000..85d4f2f --- /dev/null +++ b/0055-vsf_sysutil_get_tz-Check-the-return-value-of-syscall.patch @@ -0,0 +1,108 @@ +From c7ac05fdf2a7b53d901bfc3afeb9a61916aaaaf1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Wed, 9 May 2018 20:26:37 +0200 +Subject: [PATCH 55/59] vsf_sysutil_get_tz: Check the return value of syscalls + +Check the return value of syscalls. There's always the possibility that +they'll fail. (Failure of close() is not handled though, apart from EINTR. +The file is open read-only so it shouldn't fail, and even if it does, +it's not tragic.) + +We return NULL in case of syscall failure. One might be tempted to simply +call die() when any kind of error occurs when parsing the timezone data, +but I think it's more in line with the behaviour of tzset(3) not to do +anything drastic in such a case (tzset() will silently use UTC when +the value given in the TZ environment variable is invalid). +--- + sysutil.c | 46 +++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 37 insertions(+), 9 deletions(-) + +diff --git a/sysutil.c b/sysutil.c +index de5f876..fd07d99 100644 +--- a/sysutil.c ++++ b/sysutil.c +@@ -2647,12 +2647,12 @@ error: + die("reopening standard file descriptors to /dev/null failed"); + } + +-char* vsf_sysutil_get_tz() ++char* vsf_sysutil_get_tz(void) + { + char *ret_tz = NULL; + char buff[BUFTZSIZ]; + off_t s_pos, e_pos; +- size_t rcnt, rest; ++ ssize_t rcnt, rest; + int fd; + + if ((fd = open(F_LOCALTIME, O_RDONLY)) > -1) +@@ -2663,8 +2663,12 @@ char* vsf_sysutil_get_tz() + return NULL; + } + s_pos = e_pos > BUFTZSIZ ? e_pos - BUFTZSIZ : 0; +- lseek(fd, s_pos, SEEK_SET); +- rcnt = read(fd, buff, BUFTZSIZ); ++ if (lseek(fd, s_pos, SEEK_SET) == -1 || ++ (rcnt = vsf_sysutil_read(fd, buff, BUFTZSIZ)) == -1) ++ { ++ close(fd); ++ return NULL; ++ } + + if (rcnt && buff[rcnt-1] == '\n') + { +@@ -2680,10 +2684,25 @@ char* vsf_sysutil_get_tz() + int len = e_pos - s_pos - offset; + if (len) + { +- lseek(fd, s_pos + offset, SEEK_SET); ++ if (lseek(fd, s_pos + offset, SEEK_SET) == -1) ++ { ++ close(fd); ++ return NULL; ++ } + ret_tz = calloc(1, len+4); ++ if (ret_tz == NULL) ++ { ++ close(fd); ++ return NULL; ++ } + memcpy(ret_tz, "TZ=", 3); +- rcnt = read(fd, ret_tz+3, len); ++ rcnt = vsf_sysutil_read(fd, ret_tz+3, len); ++ if (rcnt == -1) ++ { ++ free(ret_tz); ++ close(fd); ++ return NULL; ++ } + } + break; + } +@@ -2693,11 +2712,20 @@ char* vsf_sysutil_get_tz() + } + rest = s_pos > BUFTZSIZ ? s_pos - BUFTZSIZ : 0; + s_pos -= rest; +- lseek(fd, s_pos, SEEK_SET); +- rcnt = read(fd, buff, rest); ++ if (lseek(fd, s_pos, SEEK_SET) == -1) ++ { ++ close(fd); ++ return NULL; ++ } ++ rcnt = vsf_sysutil_read(fd, buff, rest); ++ if (rcnt == -1) ++ { ++ close(fd); ++ return NULL; ++ } + } while (rcnt > 0); + +- close (fd); ++ (void) vsf_sysutil_close_errno(fd); + } + + return ret_tz; +-- +2.14.4 + diff --git a/0056-Log-die-calls-to-syslog.patch b/0056-Log-die-calls-to-syslog.patch new file mode 100644 index 0000000..46b93f6 --- /dev/null +++ b/0056-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 56/59] 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/0057-Improve-error-message-when-max-number-of-bind-attemp.patch b/0057-Improve-error-message-when-max-number-of-bind-attemp.patch new file mode 100644 index 0000000..3a0effe --- /dev/null +++ b/0057-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 57/59] 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/0058-Make-the-max-number-of-bind-retries-tunable.patch b/0058-Make-the-max-number-of-bind-retries-tunable.patch new file mode 100644 index 0000000..1350470 --- /dev/null +++ b/0058-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 58/59] 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/0059-Fix-SEGFAULT-when-running-in-a-container-as-PID-1.patch b/0059-Fix-SEGFAULT-when-running-in-a-container-as-PID-1.patch new file mode 100644 index 0000000..3adbd4c --- /dev/null +++ b/0059-Fix-SEGFAULT-when-running-in-a-container-as-PID-1.patch @@ -0,0 +1,58 @@ +From 970711fde95bee3de1e4a5e0b557c3132d0c3e3f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= +Date: Tue, 6 Feb 2018 11:39:01 +0100 +Subject: [PATCH 59/59] Fix SEGFAULT when running in a container as PID 1 + +When vsftpd is running in a container as PID 1, it is possible +that it will get SIGCHILD for processes, which were not directly +created by it, but by some of its children. These processes will +not be in the s_p_pid_ip_hash hash table, and thus trying to +delete the entry from the hash table in standalone.c:handle_sigchld() +will result in segmentation fault. + +I can quite easily reproduce it with the upstream vsftpd and default +configuration, except for isolate=NO and isolate_network=NO being set +(it seems to me that network namespaces take a long time to create +and destroy, which hides the race condition), on a quad-core machine. +When connecting to vsftpd in a loop like this: +$ while true; do echo -en '' | nc localhost 21; done + +vsftpd crashes after a couple of seconds. +--- + standalone.c | 18 +++++++++++++----- + 1 file changed, 13 insertions(+), 5 deletions(-) + +diff --git a/standalone.c b/standalone.c +index 3b65ea2..3f35e9e 100644 +--- a/standalone.c ++++ b/standalone.c +@@ -270,13 +270,21 @@ handle_sigchld(void* duff) + if (reap_one) + { + struct vsf_sysutil_ipaddr* p_ip; +- /* Account total number of instances */ +- --s_children; +- /* Account per-IP limit */ + p_ip = (struct vsf_sysutil_ipaddr*) + hash_lookup_entry(s_p_pid_ip_hash, (void*)&reap_one); +- drop_ip_count(p_ip); +- hash_free_entry(s_p_pid_ip_hash, (void*)&reap_one); ++ /* If we are running in a container as PID 1, it is possible ++ * that we will get SIGCHILD for processes, which were not ++ * created directly by our process and which are not in the ++ * s_p_pid_ip_hash hash table. ++ */ ++ if (p_ip) ++ { ++ /* Account total number of instances */ ++ --s_children; ++ /* Account per-IP limit */ ++ drop_ip_count(p_ip); ++ hash_free_entry(s_p_pid_ip_hash, (void*)&reap_one); ++ } + } + } + } +-- +2.14.4 + diff --git a/sources b/sources new file mode 100644 index 0000000..73f8cf5 --- /dev/null +++ b/sources @@ -0,0 +1 @@ +SHA512 (vsftpd-3.0.3.tar.gz) = 5a4410a88e72ecf6f60a60a89771bcec300c9f63c2ea83b219bdf65fd9749b9853f9579f7257205b55659aefcd5dab243eba878dbbd4f0ff8532dd6e60884df7 diff --git a/vsftpd-generator b/vsftpd-generator new file mode 100755 index 0000000..f1c4cdc --- /dev/null +++ b/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/vsftpd.ftpusers b/vsftpd.ftpusers new file mode 100644 index 0000000..096142f --- /dev/null +++ b/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/vsftpd.pam b/vsftpd.pam new file mode 100644 index 0000000..080abc3 --- /dev/null +++ b/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/vsftpd.service b/vsftpd.service new file mode 100644 index 0000000..8ebae44 --- /dev/null +++ b/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/vsftpd.spec b/vsftpd.spec new file mode 100644 index 0000000..d605550 --- /dev/null +++ b/vsftpd.spec @@ -0,0 +1,873 @@ +%global _generatorsdir %{_prefix}/lib/systemd/system-generators + +Name: vsftpd +Version: 3.0.3 +Release: 39%{?dist} +Summary: Very Secure Ftp Daemon + +# 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 +Source6: vsftpd_conf_migrate.sh +Source7: vsftpd.service +Source8: vsftpd@.service +Source9: vsftpd.target +Source10: vsftpd-generator + +BuildRequires: pam-devel +BuildRequires: libcap-devel +BuildRequires: openssl-devel +BuildRequires: systemd +BuildRequires: git +BuildRequires: gcc + +Requires: logrotate + +Patch1: 0001-Don-t-use-the-provided-script-to-locate-libraries.patch +Patch2: 0002-Enable-build-with-SSL.patch +Patch3: 0003-Enable-build-with-TCP-Wrapper.patch +Patch4: 0004-Use-etc-vsftpd-dir-for-config-files-instead-of-etc.patch +Patch5: 0005-Use-hostname-when-calling-PAM-authentication-module.patch +Patch6: 0006-Close-stdin-out-err-before-listening-for-incoming-co.patch +Patch7: 0007-Make-filename-filters-smarter.patch +Patch8: 0008-Write-denied-logins-into-the-log.patch +Patch9: 0009-Trim-whitespaces-when-reading-configuration.patch +Patch10: 0010-Improve-daemonizing.patch +Patch11: 0011-Fix-listing-with-more-than-one-star.patch +Patch12: 0012-Replace-syscall-__NR_clone-.-with-clone.patch +Patch13: 0013-Extend-man-pages-with-systemd-info.patch +Patch14: 0014-Add-support-for-square-brackets-in-ls.patch +Patch15: 0015-Listen-on-IPv6-by-default.patch +Patch16: 0016-Increase-VSFTP_AS_LIMIT-from-200UL-to-400UL.patch +Patch17: 0017-Fix-an-issue-with-timestamps-during-DST.patch +Patch18: 0018-Change-the-default-log-file-in-configuration.patch +Patch19: 0019-Introduce-reverse_lookup_enable-option.patch +Patch20: 0020-Use-unsigned-int-for-uid-and-gid-representation.patch +Patch21: 0021-Introduce-support-for-DHE-based-cipher-suites.patch +Patch22: 0022-Introduce-support-for-EDDHE-based-cipher-suites.patch +Patch23: 0023-Add-documentation-for-isolate_-options.-Correct-defa.patch +Patch24: 0024-Introduce-new-return-value-450.patch +Patch25: 0025-Improve-local_max_rate-option.patch +Patch26: 0026-Prevent-hanging-in-SIGCHLD-handler.patch +Patch27: 0027-Delete-files-when-upload-fails.patch +Patch28: 0028-Fix-man-page-rendering.patch +Patch29: 0029-Fix-segfault-in-config-file-parser.patch +Patch30: 0030-Fix-logging-into-syslog-when-enabled-in-config.patch +Patch31: 0031-Fix-question-mark-wildcard-withing-a-file-name.patch +Patch32: 0032-Propagate-errors-from-nfs-with-quota-to-client.patch +Patch33: 0033-Introduce-TLSv1.1-and-TLSv1.2-options.patch +Patch34: 0034-Turn-off-seccomp-sandbox-because-it-is-too-strict.patch +Patch35: 0035-Modify-DH-enablement-patch-to-build-with-OpenSSL-1.1.patch +Patch36: 0036-Redefine-VSFTP_COMMAND_FD-to-1.patch +Patch37: 0037-Document-the-relationship-of-text_userdb_names-and-c.patch +Patch38: 0038-Document-allow_writeable_chroot-in-the-man-page.patch +Patch39: 0039-Improve-documentation-of-ASCII-mode-in-the-man-page.patch +Patch40: 0040-Use-system-wide-crypto-policy.patch +Patch41: 0041-Document-the-new-default-for-ssl_ciphers-in-the-man-.patch +Patch42: 0042-When-handling-FEAT-command-check-ssl_tlsv1_1-and-ssl.patch +Patch43: 0043-Enable-only-TLSv1.2-by-default.patch +Patch44: 0044-Disable-anonymous_enable-in-default-config-file.patch +Patch45: 0045-Expand-explanation-of-ascii_-options-behaviour-in-ma.patch +Patch46: 0046-vsftpd.conf-Refer-to-the-man-page-regarding-the-asci.patch +Patch47: 0047-Disable-tcp_wrappers-support.patch +Patch48: 0048-Fix-default-value-of-strict_ssl_read_eof-in-man-page.patch +Patch49: 0049-Add-new-filename-generation-algorithm-for-STOU-comma.patch +Patch50: 0050-Don-t-link-with-libnsl.patch +Patch51: 0051-Improve-documentation-of-better_stou-in-the-man-page.patch +Patch52: 0052-Fix-rDNS-with-IPv6.patch +Patch53: 0053-Always-do-chdir-after-chroot.patch +Patch54: 0054-vsf_sysutil_rcvtimeo-Check-return-value-of-setsockop.patch +Patch55: 0055-vsf_sysutil_get_tz-Check-the-return-value-of-syscall.patch +Patch56: 0056-Log-die-calls-to-syslog.patch +Patch57: 0057-Improve-error-message-when-max-number-of-bind-attemp.patch +Patch58: 0058-Make-the-max-number-of-bind-retries-tunable.patch +Patch59: 0059-Fix-SEGFAULT-when-running-in-a-container-as-PID-1.patch +Patch61: 0001-Move-closing-standard-FDs-after-listen.patch +Patch62: 0002-Prevent-recursion-in-bug.patch +Patch63: 0001-Set-s_uwtmp_inserted-only-after-record-insertion-rem.patch +Patch64: 0002-Repeat-pututxline-if-it-fails-with-EINTR.patch +Patch65: 0001-Repeat-pututxline-until-it-succeeds-if-it-fails-with.patch +Patch66: 0001-Fix-assignment-of-an-enumerator-of-a-different-type.patch +Patch67: 0001-Fix-timestamp-handling-in-MDTM.patch +Patch68: 0002-Drop-an-unused-global-variable.patch +Patch69: 0001-Remove-a-hint-about-the-ftp_home_dir-SELinux-boolean.patch + +%description +vsftpd is a Very Secure FTP daemon. It was written completely from +scratch. + +%prep +%autosetup -S git +cp %{SOURCE1} . + +%build +%ifarch s390x sparcv9 sparc64 +%make_build CFLAGS="$RPM_OPT_FLAGS -fPIE -pipe -Wextra -Werror" \ +%else +%make_build CFLAGS="$RPM_OPT_FLAGS -fpie -pipe -Wextra -Werror" \ +%endif + LINK="-pie -lssl" %{?_smp_mflags} + +%install +mkdir -p $RPM_BUILD_ROOT%{_sbindir} +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir} +mkdir -p $RPM_BUILD_ROOT%{_sysconfdir}/{vsftpd,pam.d,logrotate.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 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 + +%post +%systemd_post vsftpd.service + +%preun +%systemd_preun vsftpd.service +%systemd_preun vsftpd.target + +%postun +%systemd_postun_with_restart vsftpd.service + +%files +%{_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 + +%changelog +* Wed Jul 29 2020 Fedora Release Engineering - 3.0.3-39 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild + +* Tue Mar 17 2020 Ondřej Lysoněk - 3.0.3-38 +- Removed a hint about the ftp_home_dir SELinux boolean from the config file +- Resolves: rhbz#1623424 + +* Thu Feb 13 2020 Ondřej Lysoněk - 3.0.3-37 +- Fix timestamp handling in MDTM +- Resolves: rhbz#1567855 + +* Fri Feb 07 2020 Ondřej Lysoněk - 3.0.3-36 +- Fix build with gcc 10 +- Resolves: rhbz#1800239 + +* Fri Jan 31 2020 Fedora Release Engineering - 3.0.3-35 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild + +* Fri Jan 17 2020 Tom Stellard - 3.0.3-34 +- Use make_build macro + +* Thu Nov 28 2019 Ondřej Lysoněk - 3.0.3-33 +- Finish up the fix to the problem with bad utmp entries when pututxline() fails +- Resolves: rhbz#1688852 +- Resolves: rhbz#1737433 + +* Mon Aug 05 2019 Ondřej Lysoněk - 3.0.3-32 +- Partially fix problem with bad utmp entries when pututxline() fails +- Resolves: rhbz#1688848 + +* Sat Aug 03 2019 Ondřej Lysoněk - 3.0.3-31 +- Fix segfault when listen() returns an error +- Resolves: rhbz#1666380 + +* Sat Jul 27 2019 Fedora Release Engineering - 3.0.3-30 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild + +* Sun Feb 03 2019 Fedora Release Engineering - 3.0.3-29 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild + +* Wed Jul 25 2018 Ondřej Lysoněk - 3.0.3-28 +- Rebuilt, switched to SHA512 source tarball hash + +* Wed Jul 25 2018 Ondřej Lysoněk - 3.0.3-27 +- Fix a segfault when running as PID 1 + +* Sat Jul 14 2018 Fedora Release Engineering - 3.0.3-26 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild + +* Tue Jun 19 2018 Ondřej Lysoněk - 3.0.3-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 + +* Fri Jun 01 2018 Ondřej Lysoněk - 3.0.3-24 +- Fix filename expansion in vsftpd_conf_migrate.sh ... again + +* Thu May 10 2018 Ondřej Lysoněk - 3.0.3-23 +- Fix issues found by Coverity Scan + +* Fri Apr 27 2018 Ondřej Lysoněk - 3.0.3-22 +- Fix filename expansion in vsftpd_conf_migrate.sh + +* Thu Apr 05 2018 Ondřej Lysoněk - 3.0.3-21 +- Improve documentation of better_stou in the man page + +* Mon Feb 19 2018 Ondřej Lysoněk - 3.0.3-20 +- Add gcc to BuildRequires + +* Tue Feb 06 2018 Ondřej Lysoněk - 3.0.3-19 +- Don't link with libnsl + +* Tue Feb 06 2018 Ondřej Lysoněk - 3.0.3-18 +- Add a new config option 'better_stou', which can be used to enable + a better algorithm for generating unique filenames for the STOU command. +- Resolves: rhbz#1479237 + +* Wed Jan 10 2018 Ondřej Lysoněk - 3.0.3-17 +- Add BuildRequires: libnsl2-devel +- https://fedoraproject.org/wiki/Changes/NISIPv6 + +* Fri Jan 05 2018 Ondřej Lysoněk - 3.0.3-16 +- Disable tcp_wrappers support +- Resolves: rhbz#1518796 +- Fix default value of strict_ssl_read_eof in man page + +* Tue Jan 02 2018 Ondřej Lysoněk - 3.0.3-15 +- Expand the explanation of the ascii_* options behaviour + +* Tue Jan 02 2018 Ondřej Lysoněk - 3.0.3-14 +- Disable anonymous_enable in default config file +- Resolves: rhbz#1338637 + +* Thu Dec 21 2017 Ondřej Lysoněk - 3.0.3-13 +- Document the new default for ssl_ciphers in the man page +- Related: rhbz#1483970 +- When handling FEAT command, check ssl_tlsv1_1 and ssl_tlsv1_2 +- Patch was written by Martin Sehnoutka +- Resolves: rhbz#1432054 +- Disable TLSv1 and TLSv1.1 - enable only TLSv1.2 by default + +* Thu Dec 21 2017 Ondřej Lysoněk - 3.0.3-12 +- Use system wide crypto policy +- Resolves: rhbz#1483970 + +* Fri Nov 24 2017 Ondřej Lysoněk - 3.0.3-11 +- Improve documentation of ASCII mode in the man page +- Resolves: rhbz#1139409 + +* Tue Oct 31 2017 Ondřej Lysoněk - 3.0.3-10 +- Document allow_writeable_chroot in the man page +- Resolves: rhbz#1507143 + +* Thu Oct 26 2017 Ondřej Lysoněk - 3.0.3-9 +- Document the relationship of text_userdb_names and chroot_local_user +- Resolves: rhbz#1439724 + +* Tue Sep 05 2017 Ondřej Lysoněk - 3.0.3-8 +- Build against OpenSSL 1.1 +- Redefine VSFTP_COMMAND_FD to 1 to get errors generated during +- startup picked up by systemd +- Resolves: rhbz#1443055 + +* Thu Aug 03 2017 Fedora Release Engineering - 3.0.3-7 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Thu Jul 27 2017 Fedora Release Engineering - 3.0.3-6 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Sat Feb 11 2017 Fedora Release Engineering - 3.0.3-5 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Dec 01 2016 Martin Sehnoutka - 3.0.3-4 +- Use OpenSSL compat library on rawhide + +* Thu Nov 17 2016 Martin Sehnoutka - 3.0.3-3 +- Review patches +- Add TLSv1.{1,2} options +- Fix question mark wildcard within a file name +- Seccomp patch removed + +* Fri Apr 08 2016 Martin Sehnoutka - 3.0.3-2 +- Applied patches: +- Readd seccomp disabled by default +- vsftpd local_max_rate option doesn't work as expected +- The vsftpd hangs in a SIGCHLD handler when the pam_exec.so is used in pam.d +- configuration +- The vsftpd doesn't remove failed upload when the delete_failed_uploads is +- enabled and the network cable is unplagged +- man pages bug +- vsftpd segfaults in vsf_sysutil_strndup +- Fix logging when syslog is used + +* Thu Mar 17 2016 Martin Sehnoutka - 3.0.3-1 +- Update to 3.0.3 version + +* Fri Feb 05 2016 Fedora Release Engineering - 3.0.2-15 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Fri Jun 19 2015 Fedora Release Engineering - 3.0.2-14 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Tue Sep 16 2014 Jiri Skala - 3.0.2-13 +- added appropriate values to ssl_ciphers (dh and ecdh patches) + +* Mon Aug 18 2014 Fedora Release Engineering - 3.0.2-12 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Fri Jul 04 2014 Jiri Skala - 3.0.2-11 +- fixed deny_file, hide_file options - updated sqb patch + +* Wed Jun 18 2014 Jiri Skala - 3.0.2-10 +- improves DH cipher +- implements ECDH cipher +- adds isolate* options to man vsftpd.conf +- corrects max_clients, max_per_ip default values in man vsftd.conf +- adds return code 450 when a file is temporarily unavailable + +* Sun Jun 08 2014 Fedora Release Engineering - 3.0.2-9 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue May 13 2014 Jiri Skala - 3.0.2-8 +- adds reverse lookup option to vsftpd.conf +- changes types of uid and gid to uint +- removes spare patch pasv-addr +- implements DH cipher +- gets rid init scirpt subpackage + +* Tue Sep 10 2013 Jiri Skala - 3.0.2-7 +- fixed #1005549 - vsftpd startup broken + +* Wed Sep 04 2013 Jiri Skala - 3.0.2-6 +- fixes usage pasv_address option in combination with external IP +- updated man pages - multile instances using vsftpd.target + +* Thu Aug 15 2013 Jiri Skala - 3.0.2-5 +- replaced systemd path by _unitdir macro +- fixes #7194344 - multiple instances (target, generator) + +* Sun Aug 04 2013 Fedora Release Engineering - 3.0.2-4 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_20_Mass_Rebuild + +* 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 + +* Mon 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 + +* Tue 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) + +* Thu 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 + +* Thu Feb 1 2001 Seth Vidal +- Update to 0.0.10 + +* Thu 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 diff --git a/vsftpd.target b/vsftpd.target new file mode 100644 index 0000000..3f0a942 --- /dev/null +++ b/vsftpd.target @@ -0,0 +1,6 @@ +[Unit] +Description=FTP daemon +After=network.target + +[Install] +WantedBy=multi-user.target diff --git a/vsftpd.user_list b/vsftpd.user_list new file mode 100644 index 0000000..3e2760f --- /dev/null +++ b/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/vsftpd.xinetd b/vsftpd.xinetd new file mode 100644 index 0000000..9b22b5b --- /dev/null +++ b/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/vsftpd@.service b/vsftpd@.service new file mode 100644 index 0000000..f3a7a16 --- /dev/null +++ b/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/vsftpd_conf_migrate.sh b/vsftpd_conf_migrate.sh new file mode 100755 index 0000000..582c20d --- /dev/null +++ b/vsftpd_conf_migrate.sh @@ -0,0 +1,13 @@ +#!/bin/bash +#move old config files and symlink them +#shipped with vsftpd-2.0.1-6 +shopt -s nullglob +PREFIX="vsftpd" +for file in /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