[proftpd] Add a number of fixes for bugs reported upstream
Paul Howarth
pghmcfc at fedoraproject.org
Tue May 17 14:03:49 UTC 2011
commit 9c2f73d95e50072de8dee4ba02d02c90c01cf4fc
Author: Paul Howarth <paul at city-fan.org>
Date: Tue May 17 14:02:24 2011 +0100
Add a number of fixes for bugs reported upstream
- Avoid spinning proftpd process if read(2) returns EAGAIN (bug 3639)
- SITE CPFR/CPTO does not update quota tally (bug 3641)
- Segfault in mod_sql_mysql if "SQLAuthenticate groupsetfast" used (bug 3642)
- Disable signal handling for exiting session processes (bug 3644)
- Ensure that SQLNamedConnectInfos with PERSESSION connection policies are
opened before chroot (bug 3645)
- MaxStoreFileSize can be bypassed using REST/APPE (bug 3649)
- Fix TCPAccessSyslogLevel directive (bug 3652)
- Segfault with "DefaultServer off" and no matching server for incoming IP
address (bug 3653)
proftpd-1.3.4rc2-bug3639.patch | 37 ++++++
proftpd-1.3.4rc2-bug3641.patch | 245 ++++++++++++++++++++++++++++++++++++++++
proftpd-1.3.4rc2-bug3642.patch | 18 +++
proftpd-1.3.4rc2-bug3644.patch | 42 +++++++
proftpd-1.3.4rc2-bug3645.patch | 104 +++++++++++++++++
proftpd-1.3.4rc2-bug3649.patch | 77 +++++++++++++
proftpd-1.3.4rc2-bug3652.patch | 75 ++++++++++++
proftpd-1.3.4rc2-bug3653.patch | 112 ++++++++++++++++++
proftpd.spec | 47 ++++++++-
9 files changed, 756 insertions(+), 1 deletions(-)
---
diff --git a/proftpd-1.3.4rc2-bug3639.patch b/proftpd-1.3.4rc2-bug3639.patch
new file mode 100644
index 0000000..438ff8f
--- /dev/null
+++ b/proftpd-1.3.4rc2-bug3639.patch
@@ -0,0 +1,37 @@
+--- proftpd/src/netio.c 2011/02/26 02:31:36 1.50
++++ proftpd/src/netio.c 2011/04/06 17:16:09 1.51
+@@ -23,7 +23,7 @@
+ */
+
+ /* NetIO routines
+- * $Id: netio.c,v 1.50 2011/02/26 02:31:36 castaglia Exp $
++ * $Id: netio.c,v 1.51 2011/04/06 17:16:09 castaglia Exp $
+ */
+
+ #include "conf.h"
+@@ -922,8 +922,24 @@
+ }
+
+ #ifdef EAGAIN
+- if (bread == -1 && errno == EAGAIN)
++ if (bread == -1 &&
++ errno == EAGAIN) {
++ int xerrno = EAGAIN;
++
++ /* Treat this as an interrupted call, call pr_signals_handle()
++ * (which will delay for a few msecs because of EINTR), and try
++ * again.
++ *
++ * This should avoid a tightly spinning loop if read(2) returns
++ * EAGAIN, as on a data transfer (Bug#3639).
++ */
++
++ errno = EINTR;
++ pr_signals_handle();
++
++ errno = xerrno;
+ goto polling;
++ }
+ #endif
+
+ } while (bread == -1 && errno == EINTR);
diff --git a/proftpd-1.3.4rc2-bug3641.patch b/proftpd-1.3.4rc2-bug3641.patch
new file mode 100644
index 0000000..fc922e6
--- /dev/null
+++ b/proftpd-1.3.4rc2-bug3641.patch
@@ -0,0 +1,245 @@
+--- proftpd/contrib/mod_copy.c 2010/03/10 19:24:04 1.2
++++ proftpd/contrib/mod_copy.c 2011/04/09 20:26:30 1.3
+@@ -2,7 +2,7 @@
+ * ProFTPD: mod_copy -- a module supporting copying of files on the server
+ * without transferring the data to the client and back
+ *
+- * Copyright (c) 2009-2010 TJ Saunders
++ * Copyright (c) 2009-2011 TJ Saunders
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -26,12 +26,12 @@
+ * This is mod_copy, contrib software for proftpd 1.3.x and above.
+ * For more information contact TJ Saunders <tj at castaglia.org>.
+ *
+- * $Id: mod_copy.c,v 1.2 2010/03/10 19:24:04 castaglia Exp $
++ * $Id: mod_copy.c,v 1.3 2011/04/09 20:26:30 castaglia Exp $
+ */
+
+ #include "conf.h"
+
+-#define MOD_COPY_VERSION "mod_copy/0.2"
++#define MOD_COPY_VERSION "mod_copy/0.3"
+
+ /* Make sure the version of proftpd is as necessary. */
+ #if PROFTPD_VERSION_NUMBER < 0x0001030401
+@@ -319,7 +319,7 @@
+ return PR_DECLINED(cmd);
+ }
+
+- if (strcasecmp(cmd->argv[1], "COPY") == 0) {
++ if (strncasecmp(cmd->argv[1], "COPY", 5) == 0) {
+ char *cmd_name, *from, *to;
+ unsigned char *authenticated;
+
+@@ -363,7 +363,7 @@
+ return PR_HANDLED(cmd);
+ }
+
+- if (strcasecmp(cmd->argv[1], "HELP") == 0) {
++ if (strncasecmp(cmd->argv[1], "HELP", 5) == 0) {
+ pr_response_add(R_214, _("CPFR <sp> pathname"));
+ pr_response_add(R_214, _("CPTO <sp> pathname"));
+ }
+@@ -376,7 +376,7 @@
+ int res;
+ char *path = "";
+
+- if (strcasecmp(cmd->argv[1], "CPFR") != 0) {
++ if (strncasecmp(cmd->argv[1], "CPFR", 5) != 0) {
+ return PR_DECLINED(cmd);
+ }
+
+@@ -430,7 +430,7 @@
+ register unsigned int i;
+ char *from, *to = "";
+
+- if (strcasecmp(cmd->argv[1], "CPTO") != 0) {
++ if (strncasecmp(cmd->argv[1], "CPTO", 5) != 0) {
+ return PR_DECLINED(cmd);
+ }
+
+@@ -459,12 +459,21 @@
+ return PR_ERROR(cmd);
+ }
+
+- pr_table_remove(session.notes, "mod_copy.cpfr-path", NULL);
+-
+ pr_response_add(R_250, _("Copy successful"));
+ return PR_HANDLED(cmd);
+ }
+
++MODRET copy_log_site(cmd_rec *cmd) {
++ if (strncasecmp(cmd->argv[1], "CPTO", 5) != 0) {
++ return PR_DECLINED(cmd);
++ }
++
++ /* Delete the stashed CPFR path from the session.notes table. */
++ (void) pr_table_remove(session.notes, "mod_copy.cpfr-path", NULL);
++
++ return PR_HANDLED(cmd);
++}
++
+ /* Initialization functions
+ */
+
+@@ -479,9 +488,12 @@
+ */
+
+ static cmdtable copy_cmdtab[] = {
+- { CMD, C_SITE, G_WRITE, copy_copy, FALSE, FALSE, CL_MISC },
+- { CMD, C_SITE, G_DIRS, copy_cpfr, FALSE, FALSE, CL_MISC },
+- { CMD, C_SITE, G_WRITE, copy_cpto, FALSE, FALSE, CL_MISC },
++ { CMD, C_SITE, G_WRITE, copy_copy, FALSE, FALSE, CL_MISC },
++ { CMD, C_SITE, G_DIRS, copy_cpfr, FALSE, FALSE, CL_MISC },
++ { CMD, C_SITE, G_WRITE, copy_cpto, FALSE, FALSE, CL_MISC },
++ { LOG_CMD, C_SITE, G_NONE, copy_log_site, FALSE, FALSE },
++ { LOG_CMD_ERR, C_SITE, G_NONE, copy_log_site, FALSE, FALSE },
++
+ { 0, NULL }
+ };
+
+--- proftpd/contrib/mod_quotatab.c 2011/03/21 01:01:34 1.72
++++ proftpd/contrib/mod_quotatab.c 2011/04/09 20:26:30 1.73
+@@ -28,7 +28,7 @@
+ * ftp://pooh.urbanrage.com/pub/c/. This module, however, has been written
+ * from scratch to implement quotas in a different way.
+ *
+- * $Id: mod_quotatab.c,v 1.72 2011/03/21 01:01:34 castaglia Exp $
++ * $Id: mod_quotatab.c,v 1.73 2011/04/09 20:26:30 castaglia Exp $
+ */
+
+ #include "mod_quotatab.h"
+@@ -3584,12 +3584,37 @@
+ if (cmd->argc < 2)
+ return PR_DECLINED(cmd);
+
+- if (strcasecmp(cmd->argv[1], "COPY") == 0) {
++ if (strncasecmp(cmd->argv[1], "COPY", 5) == 0) {
+ cmd_rec *copy_cmd;
+
+ copy_cmd = pr_cmd_alloc(cmd->tmp_pool, 3, cmd->argv[1], cmd->argv[2],
+ cmd->argv[3]);
+ return quotatab_pre_copy(copy_cmd);
++
++ } else if (strncasecmp(cmd->argv[1], "CPTO", 5) == 0) {
++ register unsigned int i;
++ cmd_rec *copy_cmd;
++ char *from, *to = "";
++
++ if (cmd->argc < 3)
++ return PR_DECLINED(cmd);
++
++ from = pr_table_get(session.notes, "mod_copy.cpfr-path", NULL);
++ if (from == NULL) {
++ pr_response_add_err(R_503, _("Bad sequence of commands"));
++ return PR_ERROR(cmd);
++ }
++
++ /* Construct the target file name by concatenating all the parameters after
++ * the "SITE CPTO", separating them with spaces.
++ */
++ for (i = 2; i <= cmd->argc-1; i++) {
++ to = pstrcat(cmd->tmp_pool, to, *to ? " " : "",
++ pr_fs_decode_path(cmd->tmp_pool, cmd->argv[i]), NULL);
++ }
++
++ copy_cmd = pr_cmd_alloc(cmd->tmp_pool, 3, "COPY", from, to);
++ return quotatab_pre_copy(copy_cmd);
+ }
+
+ return PR_DECLINED(cmd);
+@@ -3601,7 +3626,7 @@
+ if (cmd->argc < 2)
+ return PR_DECLINED(cmd);
+
+- if (strcasecmp(cmd->argv[1], "QUOTA") == 0) {
++ if (strncasecmp(cmd->argv[1], "QUOTA", 6) == 0) {
+ char *cmd_name;
+ unsigned char *authenticated = get_param_ptr(cmd->server->conf,
+ "authenticated", FALSE);
+@@ -3686,7 +3711,7 @@
+ return PR_HANDLED(cmd);
+ }
+
+- if (strcasecmp(cmd->argv[1], "HELP") == 0) {
++ if (strncasecmp(cmd->argv[1], "HELP", 5) == 0) {
+
+ /* Add a description of SITE QUOTA to the output. */
+ pr_response_add(R_214, "QUOTA");
+@@ -3701,12 +3726,37 @@
+ if (cmd->argc < 2)
+ return PR_DECLINED(cmd);
+
+- if (strcasecmp(cmd->argv[1], "COPY") == 0) {
++ if (strncasecmp(cmd->argv[1], "COPY", 5) == 0) {
+ cmd_rec *copy_cmd;
+
+ copy_cmd = pr_cmd_alloc(cmd->tmp_pool, 3, cmd->argv[1], cmd->argv[2],
+ cmd->argv[3]);
+ return quotatab_post_copy(copy_cmd);
++
++ } else if (strncasecmp(cmd->argv[1], "CPTO", 5) == 0) {
++ register unsigned int i;
++ cmd_rec *copy_cmd;
++ char *from, *to = "";
++
++ if (cmd->argc < 3)
++ return PR_DECLINED(cmd);
++
++ from = pr_table_get(session.notes, "mod_copy.cpfr-path", NULL);
++ if (from == NULL) {
++ pr_response_add_err(R_503, _("Bad sequence of commands"));
++ return PR_ERROR(cmd);
++ }
++
++ /* Construct the target file name by concatenating all the parameters after
++ * the "SITE CPTO", separating them with spaces.
++ */
++ for (i = 2; i <= cmd->argc-1; i++) {
++ to = pstrcat(cmd->tmp_pool, to, *to ? " " : "",
++ pr_fs_decode_path(cmd->tmp_pool, cmd->argv[i]), NULL);
++ }
++
++ copy_cmd = pr_cmd_alloc(cmd->tmp_pool, 3, "COPY", from, to);
++ return quotatab_post_copy(copy_cmd);
+ }
+
+ return PR_DECLINED(cmd);
+@@ -3718,12 +3768,34 @@
+ if (cmd->argc < 2)
+ return PR_DECLINED(cmd);
+
+- if (strcasecmp(cmd->argv[1], "COPY") == 0) {
++ if (strncasecmp(cmd->argv[1], "COPY", 5) == 0) {
+ cmd_rec *copy_cmd;
+
+ copy_cmd = pr_cmd_alloc(cmd->tmp_pool, 3, cmd->argv[1], cmd->argv[2],
+ cmd->argv[3]);
+ return quotatab_post_copy_err(copy_cmd);
++
++ } else if (strncasecmp(cmd->argv[1], "CPTO", 5) == 0) {
++ register unsigned int i;
++ cmd_rec *copy_cmd;
++ char *from, *to = "";
++
++ from = pr_table_get(session.notes, "mod_copy.cpfr-path", NULL);
++ if (from == NULL) {
++ pr_response_add_err(R_503, _("Bad sequence of commands"));
++ return PR_ERROR(cmd);
++ }
++
++ /* Construct the target file name by concatenating all the parameters after
++ * the "SITE CPTO", separating them with spaces.
++ */
++ for (i = 2; i <= cmd->argc-1; i++) {
++ to = pstrcat(cmd->tmp_pool, to, *to ? " " : "",
++ pr_fs_decode_path(cmd->tmp_pool, cmd->argv[i]), NULL);
++ }
++
++ copy_cmd = pr_cmd_alloc(cmd->tmp_pool, 3, "COPY", from, to);
++ return quotatab_post_copy_err(copy_cmd);
+ }
+
+ return PR_DECLINED(cmd);
diff --git a/proftpd-1.3.4rc2-bug3642.patch b/proftpd-1.3.4rc2-bug3642.patch
new file mode 100644
index 0000000..8c08e8b
--- /dev/null
+++ b/proftpd-1.3.4rc2-bug3642.patch
@@ -0,0 +1,18 @@
+Index: proftpd/contrib/mod_sql.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_sql.c,v
+retrieving revision 1.210
+diff -u -r1.210 mod_sql.c
+--- proftpd/contrib/mod_sql.c 26 Mar 2011 00:43:27 -0000 1.210
++++ proftpd/contrib/mod_sql.c 12 Apr 2011 22:07:41 -0000
+@@ -4045,8 +4045,8 @@
+ if (!cmap.groupcustomgroupsetfast) {
+ where = sql_prepare_where(0, cmd, 1, cmap.groupwhere, NULL);
+
+- mr = _sql_dispatch(_sql_make_cmd(cmd->tmp_pool, 6, MOD_SQL_DEF_CONN_NAME,
+- cmap.grptable, cmap.grpfields, where, NULL), "sql_select");
++ mr = _sql_dispatch(_sql_make_cmd(cmd->tmp_pool, 5, MOD_SQL_DEF_CONN_NAME,
++ cmap.grptable, cmap.grpfields, where, "1"), "sql_select");
+ if (check_response(mr) < 0) {
+ return mr;
+ }
diff --git a/proftpd-1.3.4rc2-bug3644.patch b/proftpd-1.3.4rc2-bug3644.patch
new file mode 100644
index 0000000..7b1336b
--- /dev/null
+++ b/proftpd-1.3.4rc2-bug3644.patch
@@ -0,0 +1,42 @@
+Index: proftpd/src/main.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/src/main.c,v
+retrieving revision 1.427
+diff -u -r1.427 main.c
+--- proftpd/src/main.c 14 Apr 2011 23:15:53 -0000 1.427
++++ proftpd/src/main.c 14 Apr 2011 23:20:11 -0000
+@@ -1868,12 +1868,6 @@
+
+ static RETSIGTYPE sig_terminate(int signo) {
+
+- /* Make sure the scoreboard slot is properly cleared. Note that this is
+- * possibly redundant, as it should already be handled properly in
+- * pr_session_end().
+- */
+- pr_scoreboard_entry_del(FALSE);
+-
+ /* Capture the signal number for later display purposes. */
+ term_signo = signo;
+
+@@ -1904,11 +1898,8 @@
+ pr_log_pri(PR_LOG_INFO, "%s session closed.",
+ pr_session_get_protocol(PR_SESS_PROTO_FL_LOGOUT));
+
+- /* Restore the default signal handlers. */
+ #ifdef PR_DEVEL_STACK_TRACE
+ install_stacktrace_handler();
+-#else
+- signal(signo, SIG_DFL);
+ #endif /* PR_DEVEL_STACK_TRACE */
+
+ } else if (signo == SIGTERM) {
+@@ -1917,6 +1908,9 @@
+ } else {
+ recvd_signal_flags |= RECEIVED_SIG_TERM_OTHER;
+ }
++
++ /* Ignore future occurrences of this signal; we'll be terminating anyway. */
++ signal(signo, SIG_IGN);
+ }
+
+ static void handle_chld(void) {
diff --git a/proftpd-1.3.4rc2-bug3645.patch b/proftpd-1.3.4rc2-bug3645.patch
new file mode 100644
index 0000000..733df2a
--- /dev/null
+++ b/proftpd-1.3.4rc2-bug3645.patch
@@ -0,0 +1,104 @@
+Index: proftpd/contrib/mod_sql.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_sql.c,v
+retrieving revision 1.212
+diff -u -r1.212 mod_sql.c
+--- proftpd/contrib/mod_sql.c 12 Apr 2011 22:47:46 -0000 1.212
++++ proftpd/contrib/mod_sql.c 15 Apr 2011 17:29:27 -0000
+@@ -256,6 +256,7 @@
+ struct sql_named_conn *next, *prev;
+ const char *conn_name;
+ const char *backend;
++ unsigned int conn_policy;
+ };
+
+ static struct sql_named_conn *sql_named_conns = NULL;
+@@ -5588,6 +5589,32 @@
+ /* Event handlers
+ */
+
++static void sql_chroot_ev(const void *event_data, void *user_data) {
++ /* Loop through our list of named connections, making sure that any
++ * with a connection policy of PERSESSION are opened.
++ */
++ if (sql_named_conns != NULL) {
++ pool *tmp_pool;
++ struct sql_named_conn *snc;
++
++ tmp_pool = make_sub_pool(session.pool);
++
++ for (snc = sql_named_conns; snc; snc = snc->next) {
++ if (snc->conn_policy == SQL_CONN_POLICY_PERSESSION) {
++ cmd_rec *cmd;
++ modret_t *mr;
++
++ cmd = _sql_make_cmd(tmp_pool, 1, snc->conn_name);
++ mr = _sql_dispatch(cmd, "sql_open");
++ (void) check_response(mr);
++ SQL_FREE_CMD(cmd);
++ }
++ }
++
++ destroy_pool(tmp_pool);
++ }
++}
++
+ static void sql_exit_ev(const void *event_data, void *user_data) {
+ config_rec *c;
+ cmd_rec *cmd;
+@@ -6113,11 +6140,11 @@
+ if (get_named_conn_backend(conn_name) == NULL) {
+ pr_sql_conn_policy = SQL_CONN_POLICY_PERSESSION;
+
+- if (strcasecmp(c->argv[5], "perconn") == 0 ||
+- strcasecmp(c->argv[5], "perconnection") == 0) {
++ if (strncasecmp(c->argv[5], "perconn", 8) == 0 ||
++ strncasecmp(c->argv[5], "perconnection", 14) == 0) {
+ pr_sql_conn_policy = SQL_CONN_POLICY_PERCONN;
+
+- } else if (strcasecmp(c->argv[5], "percall") == 0) {
++ } else if (strncasecmp(c->argv[5], "percall", 8) == 0) {
+ pr_sql_conn_policy = SQL_CONN_POLICY_PERCALL;
+ }
+
+@@ -6129,17 +6156,12 @@
+ return -1;
+ }
+
+- /* Restore the default connection policy. */
+- pr_sql_conn_policy = default_conn_policy;
+-
+- sql_log(DEBUG_INFO, "connection '%s' successfully established",
+- conn_name );
+-
+ /* Add the mapping of the connection name to the backend to the
+ * lookup list.
+ */
+ snc = pcalloc(sql_pool, sizeof(struct sql_named_conn));
+ snc->conn_name = conn_name;
++ snc->conn_policy = pr_sql_conn_policy;
+ snc->backend = c->argv[1];
+
+ if (sql_named_conns != NULL) {
+@@ -6149,6 +6171,12 @@
+
+ sql_named_conns = snc;
+
++ /* Restore the default connection policy. */
++ pr_sql_conn_policy = default_conn_policy;
++
++ sql_log(DEBUG_INFO, "connection '%s' successfully established",
++ conn_name );
++
+ } else {
+ sql_log(DEBUG_INFO, MOD_SQL_VERSION
+ ": unable to open SQLNamedConnectInfo '%s': another connection "
+@@ -6255,7 +6283,7 @@
+
+ destroy_pool(tmp_pool);
+
+- /* Add our exit handler */
++ pr_event_register(&sql_module, "core.chroot", sql_chroot_ev, NULL);
+ pr_event_register(&sql_module, "core.exit", sql_exit_ev, NULL);
+
+ return 0;
diff --git a/proftpd-1.3.4rc2-bug3649.patch b/proftpd-1.3.4rc2-bug3649.patch
new file mode 100644
index 0000000..0bd30ec
--- /dev/null
+++ b/proftpd-1.3.4rc2-bug3649.patch
@@ -0,0 +1,77 @@
+Index: proftpd/modules/mod_xfer.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_xfer.c,v
+retrieving revision 1.288
+diff -u -r1.288 mod_xfer.c
+--- proftpd/modules/mod_xfer.c 19 Mar 2011 23:39:29 -0000 1.288
++++ proftpd/modules/mod_xfer.c 28 Apr 2011 04:05:57 -0000
+@@ -1588,7 +1588,7 @@
+ }
+ }
+
+- if (stor_fh &&
++ if (stor_fh != NULL &&
+ session.restart_pos) {
+ int xerrno = 0;
+
+@@ -1612,7 +1612,7 @@
+ /* Make sure that the requested offset is valid (within the size of the
+ * file being resumed).
+ */
+- if (stor_fh &&
++ if (stor_fh != NULL &&
+ session.restart_pos > st.st_size) {
+ pr_response_add_err(R_554, _("%s: invalid REST argument"), cmd->arg);
+ (void) pr_fsio_close(stor_fh);
+@@ -1624,13 +1624,18 @@
+ session.restart_pos = 0L;
+ }
+
+- if (!stor_fh) {
++ if (stor_fh == NULL) {
+ pr_log_debug(DEBUG4, "unable to open '%s' for writing: %s", cmd->arg,
+ strerror(ferrno));
+ pr_response_add_err(R_550, "%s: %s", cmd->arg, strerror(ferrno));
+ return PR_ERROR(cmd);
+ }
+
++ /* Get the latest stats on the file. If the file already existed, we
++ * want to know its current size.
++ */
++ (void) pr_fsio_fstat(stor_fh, &st);
++
+ /* Perform the actual transfer now */
+ pr_data_init(cmd->arg, PR_NETIO_IO_RD);
+
+@@ -1659,10 +1664,13 @@
+ * This check is needed during the pr_data_xfer() loop, below, because
+ * the size of the file being uploaded isn't known in advance
+ */
+- if ((nbytes_max_store = find_max_nbytes("MaxStoreFileSize")) == 0UL)
++ nbytes_max_store = find_max_nbytes("MaxStoreFileSize");
++ if (nbytes_max_store == 0UL) {
+ have_limit = FALSE;
+- else
++
++ } else {
+ have_limit = TRUE;
++ }
+
+ /* Check the MaxStoreFileSize, and abort now if zero. */
+ if (have_limit &&
+@@ -1699,11 +1707,12 @@
+
+ nbytes_stored += len;
+
+- /* Double-check the current number of bytes stored against the
+- * MaxStoreFileSize, if configured.
++ /* If MaxStoreFileSize is configured, double-check the number of bytes
++ * uploaded so far against the configured limit. Also make sure that
++ * we take into account the size of the file, i.e. if it already existed.
+ */
+ if (have_limit &&
+- nbytes_stored > nbytes_max_store) {
++ (nbytes_stored + st.st_size > nbytes_max_store)) {
+
+ pr_log_pri(PR_LOG_INFO, "MaxStoreFileSize (%" PR_LU " bytes) reached: "
+ "aborting transfer of '%s'", (pr_off_t) nbytes_max_store, path);
diff --git a/proftpd-1.3.4rc2-bug3652.patch b/proftpd-1.3.4rc2-bug3652.patch
new file mode 100644
index 0000000..672527c
--- /dev/null
+++ b/proftpd-1.3.4rc2-bug3652.patch
@@ -0,0 +1,75 @@
+--- proftpd/contrib/mod_wrap.c 2009/12/10 17:59:14 1.23
++++ proftpd/contrib/mod_wrap.c 2011/05/11 02:14:25 1.25
+@@ -2,7 +2,7 @@
+ * ProFTPD: mod_wrap -- use Wietse Venema's TCP wrappers library for
+ * access control
+ *
+- * Copyright (c) 2000-2009 TJ Saunders
++ * Copyright (c) 2000-2011 TJ Saunders
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+@@ -24,10 +24,10 @@
+ *
+ * -- DO NOT MODIFY THE TWO LINES BELOW --
+ * $Libraries: -lwrap -lnsl$
+- * $Id: mod_wrap.c,v 1.23 2009/12/10 17:59:14 castaglia Exp $
++ * $Id: mod_wrap.c,v 1.25 2011/05/11 02:14:25 castaglia Exp $
+ */
+
+-#define MOD_WRAP_VERSION "mod_wrap/1.2.3"
++#define MOD_WRAP_VERSION "mod_wrap/1.2.4"
+
+ #include "conf.h"
+ #include "privs.h"
+@@ -157,13 +157,12 @@
+ return TRUE;
+ }
+
+-static void wrap_log_request_allowed(int priority,
++static void wrap_log_request_allowed(int severity,
+ struct request_info *request) {
+- int facility;
++ int priority;
+
+- /* Mask off the facility bit. */
+- facility = log_getfacility();
+- priority &= ~facility;
++ /* Mask off the facility bits. */
++ priority = (severity & PR_LOG_PRIMASK);
+
+ pr_log_pri(priority, MOD_WRAP_VERSION ": allowed connection from %s",
+ eval_client(request));
+@@ -172,13 +171,12 @@
+ return;
+ }
+
+-static void wrap_log_request_denied(int priority,
++static void wrap_log_request_denied(int severity,
+ struct request_info *request) {
+- int facility;
++ int priority;
+
+- /* Mask off the facility bit. */
+- facility = log_getfacility();
+- priority &= ~facility;
++ /* Mask off the facility bits. */
++ priority = (severity & PR_LOG_PRIMASK);
+
+ pr_log_pri(priority, MOD_WRAP_VERSION ": refused connection from %s",
+ eval_client(request));
+@@ -911,9 +909,13 @@
+ *
+ * "The priority argument is formed by ORing the facility and the level
+ * values..."
++ *
++ * Note that we do this OR here because the allow_severity/deny_severity
++ * values are ALSO used by the libwrap library; it is also why we need
++ * to mask off some bits later, when using proftpd's logging functions.
+ */
+ allow_severity = log_getfacility() | allow_severity;
+- deny_severity = log_getfacility() | deny_severity ;
++ deny_severity = log_getfacility() | deny_severity;
+
+ pr_log_debug(DEBUG4, MOD_WRAP_VERSION ": checking under service name '%s'",
+ wrap_service_name);
diff --git a/proftpd-1.3.4rc2-bug3653.patch b/proftpd-1.3.4rc2-bug3653.patch
new file mode 100644
index 0000000..b0928bc
--- /dev/null
+++ b/proftpd-1.3.4rc2-bug3653.patch
@@ -0,0 +1,112 @@
+Index: proftpd/src/main.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/src/main.c,v
+retrieving revision 1.428
+diff -u -r1.428 main.c
+--- proftpd/src/main.c 21 Apr 2011 16:27:08 -0000 1.428
++++ proftpd/src/main.c 13 May 2011 15:48:04 -0000
+@@ -1207,42 +1207,9 @@
+ /* Find the server for this connection. */
+ main_server = pr_ipbind_get_server(conn->local_addr, conn->local_port);
+
+- pr_inet_set_proto_opts(permanent_pool, conn, 0, 1, IPTOS_LOWDELAY, 0);
+-
+- /* The follow code was ostensibly used to conserve memory, to free all other
+- * servers and associated configurations. However, when large numbers of
+- * servers are configured, this process adds significant time to the
+- * establishment of a session. More importantly, I do not think it is
+- * really necessary; copy-on-write semantics mean that those portions of
+- * memory won't actually be in this process' space until changed. And if
+- * those configurations will never be reached, the only time the associated
+- * memory would change is now, when it is attempted to be freed.
+- *
+- * s = main_server;
+- * while (s) {
+- * s_saved = s->next;
+- * if (s != serv) {
+- * if (s->listen && s->listen != l) {
+- * if (s->listen->listen_fd == conn->rfd ||
+- * s->listen->listen_fd == conn->wfd)
+- * s->listen->listen_fd = -1;
+- * else
+- * inet_close(s->pool,s->listen);
+- * }
+- *
+- * if (s->listen) {
+- * if (s->listen->listen_fd == conn->rfd ||
+- * s->listen->listen_fd == conn->wfd)
+- * s->listen->listen_fd = -1;
+- * }
+- *
+- * xaset_remove(server_list,(xasetmember_t*)s);
+- * destroy_pool(s->pool);
+- * }
+- * s = s_saved;
+- * }
++ /* Make sure we allocate a session pool, even if this connection will
++ * dropped soon.
+ */
+-
+ session.pool = make_sub_pool(permanent_pool);
+ pr_pool_tag(session.pool, "Session Pool");
+
+@@ -1252,6 +1219,23 @@
+ session.sp_flags = 0;
+ session.proc_prefix = "(connecting)";
+
++ /* If no server is configured to handle the addr the user is connected to,
++ * drop them.
++ */
++ if (main_server == NULL) {
++ pr_log_debug(DEBUG2, "No server configuration found for IP address %s",
++ pr_netaddr_get_ipstr(conn->local_addr));
++ pr_log_debug(DEBUG2, "Use the DefaultServer directive to designate "
++ "a default server configuration to handle requests like this");
++
++ pr_response_send(R_500,
++ _("Sorry, no server available to handle request on %s"),
++ pr_netaddr_get_dnsstr(conn->local_addr));
++ exit(0);
++ }
++
++ pr_inet_set_proto_opts(permanent_pool, conn, 0, 1, IPTOS_LOWDELAY, 0);
++
+ /* Close the write side of the semaphore pipe to tell the parent
+ * we are all grown up and have finished housekeeping (closing
+ * former listen sockets).
+@@ -1284,9 +1268,9 @@
+ pr_netaddr_get_ipstr(session.c->local_addr) :
+ main_server->ServerAddress;
+
+- if ((c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
+- FALSE)) != NULL) {
+-
++ c = find_config(main_server->conf, CONF_PARAM, "MasqueradeAddress",
++ FALSE);
++ if (c != NULL) {
+ pr_netaddr_t *masq_addr = (pr_netaddr_t *) c->argv[0];
+ serveraddress = pr_netaddr_get_ipstr(masq_addr);
+ }
+@@ -1314,21 +1298,6 @@
+ }
+ }
+
+- /* If no server is configured to handle the addr the user is
+- * connected to, drop them.
+- */
+- if (!main_server) {
+- pr_log_debug(DEBUG2, "No server configuration found for IP address %s",
+- pr_netaddr_get_ipstr(conn->local_addr));
+- pr_log_debug(DEBUG2, "Use the DefaultServer directive to designate "
+- "a default server configuration to handle requests like this");
+-
+- pr_response_send(R_500,
+- _("Sorry, no server available to handle request on %s"),
+- pr_netaddr_get_dnsstr(conn->local_addr));
+- exit(0);
+- }
+-
+ if (main_server->listen) {
+ if (main_server->listen->listen_fd == conn->rfd ||
+ main_server->listen->listen_fd == conn->wfd)
+
diff --git a/proftpd.spec b/proftpd.spec
index 1bf168e..e09cebe 100644
--- a/proftpd.spec
+++ b/proftpd.spec
@@ -22,7 +22,7 @@
%endif
%global prever rc2
-%global rpmrel 8
+%global rpmrel 9
Summary: Flexible, stable and highly-configurable FTP server
Name: proftpd
@@ -54,6 +54,14 @@ Patch0: proftpd-1.3.2rc3-nostrip.patch
Patch1: proftpd-1.3.4rc2-apitests.patch
Patch2: proftpd.conf-no-memcached.patch
Patch4: proftpd-1.3.4rc1-mod_vroot-test.patch
+Patch5: proftpd-1.3.4rc2-bug3639.patch
+Patch6: proftpd-1.3.4rc2-bug3641.patch
+Patch7: proftpd-1.3.4rc2-bug3642.patch
+Patch8: proftpd-1.3.4rc2-bug3644.patch
+Patch9: proftpd-1.3.4rc2-bug3645.patch
+Patch10: proftpd-1.3.4rc2-bug3649.patch
+Patch11: proftpd-1.3.4rc2-bug3652.patch
+Patch12: proftpd-1.3.4rc2-bug3653.patch
BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root
Requires(post): /sbin/chkconfig
Requires(preun): /sbin/service, /sbin/chkconfig, coreutils, findutils
@@ -143,6 +151,30 @@ cp -p mod_geoip/mod_geoip.html doc/contrib/
# If we're running the full test suite, include the mod_vroot test
%patch4 -p1 -b .test_vroot
+# Avoid spinning proftpd process if read(2) returns EAGAIN (bug 3639)
+%patch5 -p1 -b .bug3639
+
+# SITE CPFR/CPTO does not update quota tally (bug 3641)
+%patch6 -p1 -b .bug3641
+
+# Segfault seen in mod_sql_mysql if "SQLAuthenticate groupsetfast" used (bug 3642)
+%patch7 -p1 -b .bug3642
+
+# Disable signal handling for exiting session processes (bug 3644)
+%patch8 -p1 -b .bug3644
+
+# Ensure that SQLNamedConnectInfos with PERSESSION connection policies are opened before chroot (bug 3645)
+%patch9 -p1 -b .bug3645
+
+# MaxStoreFileSize can be bypassed using REST/APPE (bug 3649)
+%patch10 -p1 -b .bug3649
+
+# Fix TCPAccessSyslogLevel directive (bug 3652)
+%patch11 -p1 -b .bug3652
+
+# Segfault with "DefaultServer off" and no matching server for incoming IP address (bug 3653)
+%patch12 -p1 -b .bug3653
+
# Avoid documentation name conflicts
mv contrib/README contrib/README.contrib
@@ -394,6 +426,19 @@ fi
%{_libexecdir}/proftpd/mod_sql_postgres.so
%changelog
+* Tue May 17 2011 Paul Howarth <paul at city-fan.org> 1.3.4-0.9.rc2
+- Add a number of fixes for bugs reported upstream:
+ - Avoid spinning proftpd process if read(2) returns EAGAIN (bug 3639)
+ - SITE CPFR/CPTO does not update quota tally (bug 3641)
+ - Segfault in mod_sql_mysql if "SQLAuthenticate groupsetfast" used (bug 3642)
+ - Disable signal handling for exiting session processes (bug 3644)
+ - Ensure that SQLNamedConnectInfos with PERSESSION connection policies are
+ opened before chroot (bug 3645)
+ - MaxStoreFileSize can be bypassed using REST/APPE (bug 3649)
+ - Fix TCPAccessSyslogLevel directive (bug 3652)
+ - Segfault with "DefaultServer off" and no matching server for incoming IP
+ address (bug 3653)
+
* Fri Apr 8 2011 Paul Howarth <paul at city-fan.org> 1.3.4-0.8.rc2
- Update mod_geoip to 0.3 (update for new regexp API)
- Drop patch for mod_geoip API fix
More information about the scm-commits
mailing list