diff --git a/.gitignore b/.gitignore index 05195ca..6b65d8e 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ -# master/f31/epel8-playground (split configuration) -/proftpd-1.3.6b.tar.gz +# master/f32/f31/epel8 (split configuration) +/proftpd-1.3.6c.tar.gz /v0.9.5.tar.gz -# f30/f29 (monolithic configuration) -/proftpd-1.3.6b.tar.gz +# f30 (monolithic configuration) +/proftpd-1.3.6c.tar.gz /v0.9.5.tar.gz # el7 (monolithic configuration) /proftpd-1.3.5e.tar.gz diff --git a/proftpd-1.3.3g-issue-903.patch b/proftpd-1.3.3g-issue-903.patch new file mode 100644 index 0000000..068ca46 --- /dev/null +++ b/proftpd-1.3.3g-issue-903.patch @@ -0,0 +1,135 @@ +--- include/proftpd.h ++++ include/proftpd.h +@@ -133,7 +133,7 @@ typedef struct { + struct config_struc *anon_config; /* Anonymous FTP configuration */ + char *anon_user; /* E-mail address sent to us */ + +- char *curr_cmd; /* Current FTP command */ ++ const char *curr_cmd; /* Current FTP command */ + int curr_phase; /* Current handler phase */ + + off_t restart_pos; /* Restart marked position */ +--- src/data.c ++++ src/data.c +@@ -653,7 +653,7 @@ void pr_data_close(int quiet) { + */ + void pr_data_cleanup(void) { + /* sanity check */ +- if (session.d) { ++ if (session.d != NULL) { + pr_inet_lingering_close(session.pool, session.d, timeout_linger); + session.d = NULL; + } +@@ -675,7 +675,7 @@ void pr_data_abort(int err, int quiet) { + int true_abort = XFER_ABORTED; + nstrm = NULL; + +- if (session.d) { ++ if (session.d != NULL) { + if (!true_abort) + pr_inet_lingering_close(session.pool, session.d, timeout_linger); + +@@ -856,6 +856,11 @@ void pr_data_abort(int err, int quiet) { + */ + if (!true_abort) + pr_response_add_err(respcode, _("Transfer aborted. %s"), msg ? msg : ""); ++ ++ /* Forcibly clear the data-transfer instigating command pool from the ++ * Response API. ++ */ ++ pr_response_set_pool(NULL); + } + + if (true_abort) +@@ -939,8 +944,8 @@ int pr_data_xfer(char *cl_buf, int cl_si + + pr_response_flush(&resp_err_list); + +- destroy_pool(cmd->pool); + pr_response_set_pool(resp_pool); ++ destroy_pool(cmd->pool); + + /* We don't want to actually dispatch the NOOP command, since that + * would overwrite the scoreboard with the NOOP state; admins probably +@@ -965,13 +970,13 @@ int pr_data_xfer(char *cl_buf, int cl_si + + pr_response_flush(&resp_list); + +- destroy_pool(cmd->pool); + pr_response_set_pool(resp_pool); ++ destroy_pool(cmd->pool); + + } else { + char *title_buf = NULL; + int title_len = -1; +- const char *sce_cmd = NULL, *sce_cmd_arg = NULL; ++ const char *curr_cmd = NULL, *sce_cmd = NULL, *sce_cmd_arg = NULL; + + pr_trace_msg(trace_channel, 5, + "client sent '%s' command during data transfer, dispatching", +@@ -983,6 +988,7 @@ int pr_data_xfer(char *cl_buf, int cl_si + pr_proctitle_get(title_buf, title_len + 1); + } + ++ curr_cmd = session.curr_cmd; + sce_cmd = pr_scoreboard_entry_get(PR_SCORE_CMD); + sce_cmd_arg = pr_scoreboard_entry_get(PR_SCORE_CMD_ARG); + +@@ -998,6 +1004,7 @@ int pr_data_xfer(char *cl_buf, int cl_si + } + + destroy_pool(cmd->pool); ++ session.curr_cmd = curr_cmd; + } + + } else { +--- src/main.c ++++ src/main.c +@@ -940,9 +940,10 @@ static void cmd_loop(server_rec *server, + pr_timer_reset(PR_TIMER_IDLE, ANY_MODULE); + } + +- if (cmd) { ++ if (cmd != NULL) { + pr_cmd_dispatch(cmd); + destroy_pool(cmd->pool); ++ session.curr_cmd = NULL; + + } else { + pr_response_send(R_500, _("Invalid command: try being more creative")); +--- src/response.c ++++ src/response.c +@@ -194,6 +194,16 @@ void pr_response_add_err(const char *num + pr_response_t *resp = NULL, **head = NULL; + va_list msg; + ++ if (fmt == NULL) { ++ return; ++ } ++ ++ if (resp_pool == NULL) { ++ pr_trace_msg(trace_channel, 1, ++ "no response pool set, ignoring added %s error response", numeric); ++ return; ++ } ++ + va_start(msg, fmt); + vsnprintf(resp_buf, sizeof(resp_buf), fmt, msg); + va_end(msg); +@@ -239,6 +249,16 @@ void pr_response_add(const char *numeric + pr_response_t *resp = NULL, **head = NULL; + va_list msg; + ++ if (fmt == NULL) { ++ return; ++ } ++ ++ if (resp_pool == NULL) { ++ pr_trace_msg(trace_channel, 1, ++ "no response pool set, ignoring added %s response", numeric); ++ return; ++ } ++ + va_start(msg, fmt); + vsnprintf(resp_buf, sizeof(resp_buf), fmt, msg); + va_end(msg); diff --git a/proftpd.spec b/proftpd.spec index a00ca45..e2c57e5 100644 --- a/proftpd.spec +++ b/proftpd.spec @@ -12,7 +12,7 @@ %endif #global prever rc4 -%global rpmrel 13 +%global rpmrel 14 Summary: Flexible, stable and highly-configurable FTP server Name: proftpd @@ -44,6 +44,7 @@ Patch8: proftpd-mod_tls-bug4230.patch Patch9: proftpd-1.3.3g-issue-846.patch Patch10: proftpd-1.3.3g-mysql8.patch Patch11: proftpd-1.3.3g-CVE-2019-19269.patch +Patch12: proftpd-1.3.3g-issue-903.patch Requires(post): /sbin/chkconfig Requires(preun): /sbin/service, /sbin/chkconfig, coreutils, findutils Requires(postun): /sbin/service @@ -174,6 +175,11 @@ mv contrib/README contrib/README.contrib # CVE-2019-19269 %patch11 +# Fix use-after-free vulnerability in memory pools during data transfer +# https://github.com/proftpd/proftpd/issues/903 +# CVE-2020-9273 +%patch12 + # Set up directory names in config file sed -e 's#@PKIDIR@#%{pkidir}#g' \ %{SOURCE1} > proftpd.conf @@ -385,6 +391,10 @@ fi %{_mandir}/man1/ftpwho.1* %changelog +* Thu Feb 20 2020 Paul Howarth - 1.3.3g-14 +- Fix use-after-free vulnerability in memory pools during data transfer + (CVE-2020-9273, https://github.com/proftpd/proftpd/issues/903) + * Fri Nov 29 2019 Paul Howarth - 1.3.3g-13 - Fix handling of CRL lookups by guarding against null pointers (CVE-2019-19269, https://github.com/proftpd/proftpd/issues/861)