Compare commits

..

No commits in common. "c8" and "imports/c8-beta/vsftpd-3.0.3-28.el8" have entirely different histories.

15 changed files with 6 additions and 1065 deletions

1
.vsftpd.metadata Normal file
View File

@ -0,0 +1 @@
d5f5a180dbecd0fbcdc92bf0ba2fc001c962b55a SOURCES/vsftpd-3.0.3.tar.gz

View File

@ -1,151 +0,0 @@
From 6a4dc470e569df38b8a7ea09ee6aace3c73b7353 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
Date: Wed, 28 Mar 2018 09:06:34 +0200
Subject: [PATCH] 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

View File

@ -1,46 +0,0 @@
From 40fea4552377504ce69935149e64e39a595f4600 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
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

View File

@ -1,25 +0,0 @@
From ab797dcffc855b05c9e7c8db4e5be2fc7510831b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
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

View File

@ -1,53 +0,0 @@
From 96698a525784ad91cb27b572dd5f871c183fdfa5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
Date: Sun, 28 Jul 2019 12:25:35 +0200
Subject: [PATCH 1/3] 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

View File

@ -1,107 +0,0 @@
From e679a3ce0f2cf1558da31e0bccd9e2398b89c7e9 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
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

View File

@ -1,105 +0,0 @@
From 896b3694ca062d747cd67e9e9ba246adb3fc706b Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
Date: Mon, 5 Aug 2019 13:55:37 +0200
Subject: [PATCH 2/3] 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

View File

@ -1,109 +0,0 @@
From 7957425ef5ab365fc96ea0615f99705581c6dbd8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Ond=C5=99ej=20Lyson=C4=9Bk?= <olysonek@redhat.com>
Date: Mon, 12 Aug 2019 18:15:36 +0200
Subject: [PATCH 3/3] 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

View File

@ -1,75 +0,0 @@
diff -urN a/parseconf.c b/parseconf.c
--- a/parseconf.c 2021-05-29 23:39:19.000000000 +0200
+++ b/parseconf.c 2023-03-03 10:22:38.256439634 +0100
@@ -185,6 +185,7 @@
{ "dsa_cert_file", &tunable_dsa_cert_file },
{ "dh_param_file", &tunable_dh_param_file },
{ "ecdh_param_file", &tunable_ecdh_param_file },
+ { "ssl_ciphersuites", &tunable_ssl_ciphersuites },
{ "ssl_ciphers", &tunable_ssl_ciphers },
{ "rsa_private_key_file", &tunable_rsa_private_key_file },
{ "dsa_private_key_file", &tunable_dsa_private_key_file },
diff -urN a/ssl.c b/ssl.c
--- a/ssl.c 2021-08-02 08:24:35.000000000 +0200
+++ b/ssl.c 2023-03-03 10:28:05.989757655 +0100
@@ -135,6 +135,11 @@
{
die("SSL: could not set cipher list");
}
+ if (tunable_ssl_ciphersuites &&
+ SSL_CTX_set_ciphersuites(p_ctx, tunable_ssl_ciphersuites) != 1)
+ {
+ die("SSL: could not set ciphersuites list");
+ }
if (RAND_status() != 1)
{
die("SSL: RNG is not seeded");
diff -urN a/tunables.c b/tunables.c
--- a/tunables.c 2021-05-29 23:39:00.000000000 +0200
+++ b/tunables.c 2023-03-03 10:13:30.566868026 +0100
@@ -154,6 +154,7 @@
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_ssl_ciphersuites;
const char* tunable_rsa_private_key_file;
const char* tunable_dsa_private_key_file;
@@ -293,6 +293,7 @@
install_str_setting(0, &tunable_dh_param_file);
install_str_setting(0, &tunable_ecdh_param_file);
install_str_setting("PROFILE=SYSTEM", &tunable_ssl_ciphers);
+ install_str_setting("TLS_AES_256_GCM_SHA384", &tunable_ssl_ciphersuites);
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 -urN a/tunables.h b/tunables.h
--- a/tunables.h
+++ b/tunables.h
@@ -144,6 +144,7 @@
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_ssl_ciphersuites;
extern const char* tunable_rsa_private_key_file;
extern const char* tunable_dsa_private_key_file;
--- a/vsftpd.conf.5
+++ b/vsftpd.conf.5
@@ -1009,6 +1009,16 @@
Default: PROFILE=SYSTEM
.TP
+.B ssl_ciphersuites
+This option can be used to select which SSL cipher suites vsftpd will allow for
+encrypted SSL connections with TLSv1.3. See the
+.BR ciphers
+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: TLS_AES_256_GCM_SHA384
+.TP
.B user_config_dir
This powerful option allows the override of any config option specified in
the manual page, on a per-user basis. Usage is simple, and is best illustrated

View File

@ -1,215 +0,0 @@
diff --git a/logging.c b/logging.c
index 9e86808..613ff4b 100644
--- a/logging.c
+++ b/logging.c
@@ -171,7 +171,14 @@ vsf_log_do_log_to_file(int fd, struct mystr* p_str)
return;
}
}
- str_replace_unprintable(p_str, '?');
+ if (tunable_wc_logs_enable)
+ {
+ str_replace_unprintable_with_hex_wc(p_str);
+ }
+ else
+ {
+ str_replace_unprintable_with_hex(p_str);
+ }
str_append_char(p_str, '\n');
/* Ignore write failure; maybe the disk filled etc. */
(void) str_write_loop(p_str, fd);
diff --git a/parseconf.c b/parseconf.c
index 3cfe7da..3729818 100644
--- a/parseconf.c
+++ b/parseconf.c
@@ -113,6 +113,7 @@ parseconf_bool_array[] =
{ "allow_writeable_chroot", &tunable_allow_writeable_chroot },
{ "better_stou", &tunable_better_stou },
{ "log_die", &tunable_log_die },
+ { "wc_logs_enable", &tunable_wc_logs_enable },
{ 0, 0 }
};
diff --git a/str.c b/str.c
index 82b8ae4..c03e7d8 100644
--- a/str.c
+++ b/str.c
@@ -20,6 +20,11 @@
#include "utility.h"
#include "sysutil.h"
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
/* File local functions */
static void str_split_text_common(struct mystr* p_src, struct mystr* p_rhs,
const char* p_text, int is_reverse);
@@ -723,6 +728,102 @@ str_replace_unprintable(struct mystr* p_str, char new_char)
}
}
+void
+str_replace_unprintable_with_hex(struct mystr* p_str)
+{
+ unsigned int ups_size = sizeof(unsigned int) * (p_str->len);
+ if (ups_size < p_str->len)
+ {
+ str_replace_unprintable(p_str, '?');
+ str_append_text(p_str, ": BUG: string is too long");
+ bug(p_str->p_buf);
+ }
+ unsigned int* ups = vsf_sysutil_malloc(ups_size);
+ unsigned int up_count = 0;
+ for (unsigned int i=0; i < p_str->len; i++)
+ {
+ if (!vsf_sysutil_isprint(p_str->p_buf[i]))
+ {
+ ups[up_count++] = i;
+ }
+ }
+ str_replace_positions_with_hex(p_str, ups, up_count);
+ vsf_sysutil_free(ups);
+}
+
+void str_replace_unprintable_with_hex_wc(struct mystr* p_str)
+{
+ unsigned int ups_size = sizeof(unsigned int) * (p_str->len);
+ if (ups_size < p_str->len)
+ {
+ str_replace_unprintable(p_str, '?');
+ str_append_text(p_str, ": BUG: string is too long");
+ bug(p_str->p_buf);
+ }
+ unsigned int* ups = vsf_sysutil_malloc(ups_size);
+ unsigned int up_count = 0;
+
+ size_t current = 0;
+ wchar_t pwc;
+ mbstate_t ps;
+ memset(&ps, 0, sizeof(ps));
+ ssize_t len = 0;
+ while ((len = mbrtowc(&pwc, p_str->p_buf, p_str->len - current, &ps)) > 0)
+ {
+ if (!iswprint(pwc))
+ {
+ for (int i = 0; i < len; i++)
+ {
+ ups[up_count++] = current++;
+ }
+ }
+ else
+ {
+ current += len;
+ }
+ }
+ if (len < 0)
+ {
+ while (current < p_str->len)
+ {
+ ups[up_count++] = current++;
+ }
+ }
+ str_replace_positions_with_hex(p_str, ups, up_count);
+ vsf_sysutil_free(ups);
+}
+
+void
+str_replace_positions_with_hex(struct mystr* p_str, const unsigned int* poss, const unsigned int pos_count)
+{
+ if (pos_count == 0)
+ return;
+
+ struct mystr tmp_str = INIT_MYSTR;
+ str_reserve(&tmp_str, p_str->len + 3 * pos_count);
+ unsigned int current = 0;
+
+ for (unsigned int i=0; i < pos_count; i++)
+ {
+ unsigned int pos = poss[i];
+
+ if (current < pos)
+ private_str_append_memchunk(&tmp_str, p_str->p_buf + current, pos - current);
+
+ char hex_buf[5];
+ memset(hex_buf, 0, sizeof(hex_buf));
+ sprintf(hex_buf, "\\x%02X", (unsigned char) p_str->p_buf[pos]);
+ str_append_text(&tmp_str, hex_buf);
+ current = pos + 1;
+ }
+
+ if (current < p_str->len)
+ private_str_append_memchunk(&tmp_str, p_str->p_buf + current, p_str->len - current);
+
+ str_copy(p_str, &tmp_str);
+ str_free(&tmp_str);
+}
+
void
str_basename (struct mystr* d_str, const struct mystr* path)
{
diff --git a/str.h b/str.h
index 44270da..95a83b5 100644
--- a/str.h
+++ b/str.h
@@ -98,6 +98,10 @@ int str_contains_space(const struct mystr* p_str);
int str_all_space(const struct mystr* p_str);
int str_contains_unprintable(const struct mystr* p_str);
void str_replace_unprintable(struct mystr* p_str, char new_char);
+void str_replace_unprintable_with_hex(struct mystr* p_str);
+void str_replace_unprintable_with_hex_wc(struct mystr* p_str);
+void str_replace_positions_with_hex(struct mystr* p_str, const unsigned int* poss,
+ const unsigned int pos_count);
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);
diff --git a/tunables.c b/tunables.c
index a7ce9c8..c96c1ac 100644
--- a/tunables.c
+++ b/tunables.c
@@ -94,6 +94,7 @@ int tunable_seccomp_sandbox;
int tunable_allow_writeable_chroot;
int tunable_better_stou;
int tunable_log_die;
+int tunable_wc_logs_enable;
unsigned int tunable_accept_timeout;
unsigned int tunable_connect_timeout;
@@ -244,6 +245,7 @@ tunables_load_defaults()
tunable_allow_writeable_chroot = 0;
tunable_better_stou = 0;
tunable_log_die = 0;
+ tunable_wc_logs_enable = 0;
tunable_accept_timeout = 60;
tunable_connect_timeout = 60;
diff --git a/tunables.h b/tunables.h
index 029d645..8d50150 100644
--- a/tunables.h
+++ b/tunables.h
@@ -98,6 +98,7 @@ extern int tunable_better_stou; /* Use better file name generation
*/
extern int tunable_log_die; /* Log calls to die(), die2()
* and bug() */
+extern int tunable_wc_logs_enable; /* Allow non ASCII characters in logs */
/* Integer/numeric defines */
extern unsigned int tunable_accept_timeout;
diff --git a/vsftpd.conf.5 b/vsftpd.conf.5
index ce3fba3..815773f 100644
--- a/vsftpd.conf.5
+++ b/vsftpd.conf.5
@@ -735,6 +735,12 @@ 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
+.TP
+.B wc_logs_enable
+If enabled, logs will be treated as wide-character strings and not just
+ASCII strings when filtering out non-printable characters.
+
+Default: NO
.SH NUMERIC OPTIONS
Below is a list of numeric options. A numeric option must be set to a non

View File

@ -1,132 +0,0 @@
diff --git a/features.c b/features.c
index d024366..3a60b88 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 || tunable_tlsv1_1 || tunable_tlsv1_2)
+ if (tunable_tlsv1 || tunable_tlsv1_1 || tunable_tlsv1_2 || tunable_tlsv1_3)
{
vsf_cmdio_write_raw(p_sess, " AUTH TLS\r\n");
}
diff --git a/parseconf.c b/parseconf.c
index 3729818..2c5ffe6 100644
--- a/parseconf.c
+++ b/parseconf.c
@@ -87,6 +87,7 @@ parseconf_bool_array[] =
{ "ssl_tlsv1", &tunable_tlsv1 },
{ "ssl_tlsv1_1", &tunable_tlsv1_1 },
{ "ssl_tlsv1_2", &tunable_tlsv1_2 },
+ { "ssl_tlsv1_3", &tunable_tlsv1_3 },
{ "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 09ec96a..5d9c595 100644
--- a/ssl.c
+++ b/ssl.c
@@ -178,6 +178,10 @@ ssl_init(struct vsf_session* p_sess)
{
options |= SSL_OP_NO_TLSv1_2;
}
+ if (!tunable_tlsv1_3)
+ {
+ options |= SSL_OP_NO_TLSv1_3;
+ }
SSL_CTX_set_options(p_ctx, options);
if (tunable_rsa_cert_file)
{
diff --git a/tunables.c b/tunables.c
index c96c1ac..e6fbb9d 100644
--- a/tunables.c
+++ b/tunables.c
@@ -68,6 +68,7 @@ int tunable_sslv3;
int tunable_tlsv1;
int tunable_tlsv1_1;
int tunable_tlsv1_2;
+int tunable_tlsv1_3;
int tunable_tilde_user_enable;
int tunable_force_anon_logins_ssl;
int tunable_force_anon_data_ssl;
@@ -217,8 +218,9 @@ tunables_load_defaults()
tunable_sslv3 = 0;
tunable_tlsv1 = 0;
tunable_tlsv1_1 = 0;
- /* Only TLSv1.2 is enabled by default */
+ /* Only TLSv1.2 and TLSv1.3 are enabled by default */
tunable_tlsv1_2 = 1;
+ tunable_tlsv1_3 = 1;
tunable_tilde_user_enable = 0;
tunable_force_anon_logins_ssl = 0;
tunable_force_anon_data_ssl = 0;
diff --git a/tunables.h b/tunables.h
index 8d50150..6e1d301 100644
--- a/tunables.h
+++ b/tunables.h
@@ -69,6 +69,7 @@ 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_tlsv1_3; /* Allow TLSv1.3 */
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 815773f..c37a536 100644
--- a/vsftpd.conf.5
+++ b/vsftpd.conf.5
@@ -555,7 +555,7 @@ Default: YES
Only applies if
.BR ssl_enable
is activated. If enabled, this option will permit SSL v2 protocol connections.
-TLS v1.2 connections are preferred.
+TLS v1.2 and TLS v1.3 connections are preferred.
Default: NO
.TP
@@ -563,7 +563,7 @@ Default: NO
Only applies if
.BR ssl_enable
is activated. If enabled, this option will permit SSL v3 protocol connections.
-TLS v1.2 connections are preferred.
+TLS v1.2 and TLS v1.3 connections are preferred.
Default: NO
.TP
@@ -571,7 +571,7 @@ Default: NO
Only applies if
.BR ssl_enable
is activated. If enabled, this option will permit TLS v1 protocol connections.
-TLS v1.2 connections are preferred.
+TLS v1.2 and TLS v1.3 connections are preferred.
Default: NO
.TP
@@ -579,7 +579,7 @@ Default: NO
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.
+TLS v1.2 and TLS v1.3 connections are preferred.
Default: NO
.TP
@@ -587,7 +587,15 @@ Default: NO
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.
+TLS v1.2 and TLS v1.3 connections are preferred.
+
+Default: YES
+.TP
+.B ssl_tlsv1_3
+Only applies if
+.BR ssl_enable
+is activated. If enabled, this option will permit TLS v1.3 protocol connections.
+TLS v1.2 and TLS v1.3 connections are preferred.
Default: YES
.TP

View File

@ -1,6 +1,6 @@
[Unit]
Description=Vsftpd ftp daemon
After=network-online.target
After=network.target
[Service]
Type=forking

View File

@ -1,6 +1,6 @@
[Unit]
Description=FTP daemon
After=network-online.target
After=network.target
[Install]
WantedBy=multi-user.target

View File

@ -1,6 +1,6 @@
[Unit]
Description=Vsftpd ftp daemon
After=network-online.target
After=network.target
PartOf=vsftpd.target
[Service]

View File

@ -2,7 +2,7 @@
Name: vsftpd
Version: 3.0.3
Release: 36%{?dist}
Release: 28%{?dist}
Summary: Very Secure Ftp Daemon
Group: System Environment/Daemons
@ -88,16 +88,7 @@ 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
Patch60: 0001-Move-closing-standard-FDs-after-listen.patch
Patch61: 0002-Prevent-recursion-in-bug.patch
Patch62: 0001-Set-s_uwtmp_inserted-only-after-record-insertion-rem.patch
Patch63: 0002-Repeat-pututxline-if-it-fails-with-EINTR.patch
Patch64: 0003-Repeat-pututxline-until-it-succeeds-if-it-fails-with.patch
Patch65: 0001-Fix-timestamp-handling-in-MDTM.patch
Patch66: 0001-Remove-a-hint-about-the-ftp_home_dir-SELinux-boolean.patch
Patch67: vsftpd-3.0.3-enable_wc_logs-replace_unprintable_with_hex.patch
Patch68: vsftpd-3.0.3-option_to_disable_TLSv1_3.patch
Patch69: vsftpd-3.0.3-add-option-for-tlsv1.3-ciphersuites.patch
%description
vsftpd is a Very Secure FTP daemon. It was written completely from
scratch.
@ -165,39 +156,6 @@ mkdir -p $RPM_BUILD_ROOT/%{_var}/ftp/pub
%{_var}/ftp
%changelog
* Thu Apr 06 2023 Richard Lescak <rlescak@redhat.com> -3.0.3-36
- add patch to provide option for TLSv1.3 ciphersuites
- Resolves: rhbz#2069733
* Fri Dec 03 2021 Artem Egorenkov <aegorenk@redhat.com> - 3.0.3-35
- add option to disable TLSv1.3
- Resolves: rhbz#1638375
* Mon Apr 12 2021 Artem Egorenkov <aegorenk@redhat.com> - 3.0.3-34
- Enable support for wide-character strings in logs
- Replace unprintables with HEX code, not question marks
- Resolves: rhbz#1947900
* Mon Nov 02 2020 Artem Egorenkov <aegorenk@redhat.com> - 3.0.3-33
- Unit files fixed "After=network-online.target"
- Resolves: rhbz#1893636
* Tue Mar 17 2020 Ondřej Lysoněk <olysonek@redhat.com> - 3.0.3-32
- 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 <olysonek@redhat.com> - 3.0.3-31
- Fix timestamp handling in MDTM
- Resolves: rhbz#1567855
* Thu Nov 28 2019 Ondřej Lysoněk <olysonek@redhat.com> - 3.0.3-30
- Fix a problem with bad utmp entries when pututxline() fails
- Resolves: rhbz#1688852
* Thu Nov 28 2019 Ondřej Lysoněk <olysonek@redhat.com> - 3.0.3-29
- Fix segfault when listen() returns an error
- Resolves: rhbz#1734340
* Wed Jul 25 2018 Ondřej Lysoněk <olysonek@redhat.com> - 3.0.3-28
- Rebuilt, switched to SHA512 source tarball hash