[proftpd] Cumulative bug fix update

Paul Howarth pghmcfc at fedoraproject.org
Tue Feb 28 21:15:50 UTC 2012


commit 8abab907d538e0bf386195d67c2ca7a83467bf2b
Author: Paul Howarth <paul at city-fan.org>
Date:   Tue Feb 28 21:06:47 2012 +0000

    Cumulative bug fix update
    
    - Document SELinux configuration for ProFTPD in proftpd.conf (#785443)
    - Add support for basic and administrative controls actions using ftpdctl by
      default (#786623)
    - Add trace logging directives in proftpd.conf but disable them by default as
      they impair performance
    - Fix ftpwho/ftptop not showing command arguments (bug 3714)
    - Fix MLSD/MLST fail with "DirFakeUser off" or "DirFakeGroup off" (bug 3715)
    - Fix proftpd fails to run with "Abort trap" error message (bug 3717)
    - Fix LIST -R can loop endlessly if bad directory symlink exists (bug 3719)
    - Fix overly restrictive module logfile permissions (bug 3720)
    - Fix mod_memcache segfault on server restart (bug 3723)
    - Fix unloading mod_quotatab causes segfault (#757311, bug 3724)
    - Fix mod_exec does not always capture stdout/stderr output from executed
      command (bug 3726)
    - Fix mod_wrap2 causes unexpected LogFormat %u expansion for SFTP connections
      (bug 3727)
    - Fix mod_ldap segfault when LDAPUsers is used with no optional filters
      (bug 3729)
    - Fix DirFakeUser/DirFakeGroup off with name causes SIGSEGV for MLSD/MLST
      commands (bug 3734)
    - Fix improper handling of self-signed certificate in client-sent cert list
      when "TLSVerifyClient on" is used (bug 3742)
    - Fix random stalls/segfaults seen when transferring large files via SFTP
      (bug 3743)
    - Support ls(1) -1 option for LIST command (bug 3744)
    - Reject PASV command if no IPv4 address available (bug 3745)
    - Support applying ListOptions only to NLST or to LIST commands (bug 3746)
    - Support option for displaying symlinks via MLSD using syntax preferred by
      FileZilla (bug 3747)
    - Fix mod_ban not closing and reopening the BanLog/BanTable file descriptors
      on restart, causing a file descriptor leak (bug 3751)
    - Fix mod_ctrls no longer listening on ControlsSocket after restart (bug 3756)

 proftpd-1.3.4a-bug3714.patch |   49 ++++++
 proftpd-1.3.4a-bug3715.patch |   55 ++++++
 proftpd-1.3.4a-bug3717.patch |  147 ++++++++++++++++
 proftpd-1.3.4a-bug3719.patch |   31 ++++
 proftpd-1.3.4a-bug3720.patch |  160 ++++++++++++++++++
 proftpd-1.3.4a-bug3723.patch |   86 ++++++++++
 proftpd-1.3.4a-bug3724.patch |   20 +++
 proftpd-1.3.4a-bug3726.patch |   36 ++++
 proftpd-1.3.4a-bug3727.patch |  133 +++++++++++++++
 proftpd-1.3.4a-bug3729.patch |   27 +++
 proftpd-1.3.4a-bug3734.patch |   90 ++++++++++
 proftpd-1.3.4a-bug3742.patch |   33 ++++
 proftpd-1.3.4a-bug3743.patch |   48 ++++++
 proftpd-1.3.4a-bug3744.patch |  380 ++++++++++++++++++++++++++++++++++++++++++
 proftpd-1.3.4a-bug3745.patch |   35 ++++
 proftpd-1.3.4a-bug3746.patch |  157 +++++++++++++++++
 proftpd-1.3.4a-bug3747.patch |  193 +++++++++++++++++++++
 proftpd-1.3.4a-bug3751.patch |   93 ++++++++++
 proftpd-1.3.4a-bug3756.patch |  185 ++++++++++++++++++++
 proftpd.conf                 |   91 ++++++++++-
 proftpd.spec                 |  131 ++++++++++++++-
 21 files changed, 2178 insertions(+), 2 deletions(-)
---
diff --git a/proftpd-1.3.4a-bug3714.patch b/proftpd-1.3.4a-bug3714.patch
new file mode 100644
index 0000000..cebc7b2
--- /dev/null
+++ b/proftpd-1.3.4a-bug3714.patch
@@ -0,0 +1,49 @@
+Index: src/cmd.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/src/cmd.c,v
+retrieving revision 1.8
+diff -u -r1.8 cmd.c
+--- src/cmd.c	23 May 2011 21:22:24 -0000	1.8
++++ src/cmd.c	16 Nov 2011 19:57:43 -0000
+@@ -245,8 +245,13 @@
+   }
+ 
+   res = pr_table_get(cmd->notes, "displayable-str", NULL);
+-  if (res)
++  if (res) {
++    if (str_len != NULL) {
++      *str_len = strlen(res);
++    }
++
+     return res;
++  }
+ 
+   argc = cmd->argc;
+   argv = cmd->argv;
+Index: src/main.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/src/main.c,v
+retrieving revision 1.437
+diff -u -r1.437 main.c
+--- src/main.c	9 Nov 2011 17:32:35 -0000	1.437
++++ src/main.c	16 Nov 2011 19:57:43 -0000
+@@ -318,7 +318,18 @@
+ 
+         /* The client has successfully authenticated... */
+         if (session.user) {
+-          char *args = memchr(cmdargstr, ' ', cmdargstrlen);
++          char *args = NULL;
++
++          /* Be defensive, and check whether cmdargstrlen has a value.
++           * If it's zero, assume we need to use strchr(3), rather than
++           * memchr(2); see Bug#3714.
++           */
++          if (cmdargstrlen > 0) {
++            args = memchr(cmdargstr, ' ', cmdargstrlen);
++
++          } else {
++            args = strchr(cmdargstr, ' ');
++          }
+ 
+           pr_scoreboard_entry_update(session.pid,
+             PR_SCORE_CMD, "%s", cmd->argv[0], NULL, NULL);
diff --git a/proftpd-1.3.4a-bug3715.patch b/proftpd-1.3.4a-bug3715.patch
new file mode 100644
index 0000000..f01972f
--- /dev/null
+++ b/proftpd-1.3.4a-bug3715.patch
@@ -0,0 +1,55 @@
+Index: modules/mod_facts.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_facts.c,v
+retrieving revision 1.45
+diff -u -r1.45 mod_facts.c
+--- modules/mod_facts.c	23 May 2011 21:11:56 -0000	1.45
++++ modules/mod_facts.c	16 Nov 2011 23:42:05 -0000
+@@ -1034,13 +1034,19 @@
+   c = find_config(get_dir_ctxt(cmd->tmp_pool, (char *) best_path), CONF_PARAM,
+     "DirFakeUser", FALSE);
+   if (c) {
+-    const char *fake_user;
++    const char *fake_user = NULL;
+ 
+-    fake_user = c->argv[0];
+-    if (strncmp(fake_user, "~", 2) != 0) {
+-      fake_uid = pr_auth_name2uid(cmd->tmp_pool, fake_user);
++    if (c->argc > 0) {
++      fake_user = c->argv[0];
++      if (strncmp(fake_user, "~", 2) != 0) {
++        fake_uid = pr_auth_name2uid(cmd->tmp_pool, fake_user);
++
++      } else {
++        fake_uid = session.uid;
++      }
+ 
+     } else {
++      /* Handle the "DirFakeUser off" case (Bug#3715). */
+       fake_uid = session.uid;
+     }
+   }
+@@ -1048,13 +1054,19 @@
+   c = find_config(get_dir_ctxt(cmd->tmp_pool, (char *) best_path), CONF_PARAM,
+     "DirFakeGroup", FALSE);
+   if (c) {
+-    const char *fake_group;
++    const char *fake_group = NULL;
+ 
+-    fake_group = c->argv[0];
+-    if (strncmp(fake_group, "~", 2) != 0) {
+-      fake_gid = pr_auth_name2gid(cmd->tmp_pool, fake_group);
++    if (c->argc > 0) {
++      fake_group = c->argv[0];
++      if (strncmp(fake_group, "~", 2) != 0) {
++        fake_gid = pr_auth_name2gid(cmd->tmp_pool, fake_group);
++
++      } else {
++        fake_gid = session.gid;
++      }
+ 
+     } else {
++      /* Handle the "DirFakeGroup off" case (Bug#3715). */
+       fake_gid = session.gid;
+     }
+   }
diff --git a/proftpd-1.3.4a-bug3717.patch b/proftpd-1.3.4a-bug3717.patch
new file mode 100644
index 0000000..589f366
--- /dev/null
+++ b/proftpd-1.3.4a-bug3717.patch
@@ -0,0 +1,147 @@
+Index: contrib/mod_tls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_tls.c,v
+retrieving revision 1.262
+diff -u -r1.262 mod_tls.c
+--- contrib/mod_tls.c	11 Nov 2011 23:14:13 -0000	1.262
++++ contrib/mod_tls.c	17 Nov 2011 21:26:30 -0000
+@@ -1941,13 +1941,13 @@
+   k = (tls_pkey_t *) data;
+ 
+   if ((k->flags & TLS_PKEY_USE_RSA) && k->rsa_pkey) {
+-    strncpy(buf, k->rsa_pkey, buflen);
++    sstrncpy(buf, k->rsa_pkey, buflen);
+     buf[buflen - 1] = '\0';
+     return strlen(buf);
+   }
+ 
+   if ((k->flags & TLS_PKEY_USE_DSA) && k->dsa_pkey) {
+-    strncpy(buf, k->dsa_pkey, buflen);
++    sstrncpy(buf, k->dsa_pkey, buflen);
+     buf[buflen - 1] = '\0';
+     return strlen(buf);
+   }
+Index: contrib/mod_sftp/keys.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_sftp/keys.c,v
+retrieving revision 1.16
+diff -u -r1.16 keys.c
+--- contrib/mod_sftp/keys.c	23 May 2011 21:03:12 -0000	1.16
++++ contrib/mod_sftp/keys.c	17 Nov 2011 21:26:30 -0000
+@@ -718,7 +718,7 @@
+   k = (struct sftp_pkey *) d;
+ 
+   if (k->host_pkey) {
+-    strncpy(buf, k->host_pkey, buflen);
++    sstrncpy(buf, k->host_pkey, buflen);
+     buf[buflen - 1] = '\0';
+     return strlen(buf);
+   }
+Index: lib/pr-syslog.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/lib/pr-syslog.c,v
+retrieving revision 1.24
+diff -u -r1.24 pr-syslog.c
+--- lib/pr-syslog.c	1 May 2011 04:32:27 -0000	1.24
++++ lib/pr-syslog.c	17 Nov 2011 21:26:30 -0000
+@@ -324,17 +324,17 @@
+        * hold more data than 14 bytes, so...
+        */
+       if (sizeof(syslog_addr.sa_data) >= (strlen(PR_PATH_LOG) + 1)) {
+-        strncpy(syslog_addr.sa_data, PR_PATH_LOG, sizeof(syslog_addr.sa_data));
++        sstrncpy(syslog_addr.sa_data, PR_PATH_LOG, sizeof(syslog_addr.sa_data));
+         syslog_addr.sa_data[sizeof(syslog_addr.sa_data)-1] = '\0';
+         addrlen = sizeof(syslog_addr);
+ 
+       } else {
+-        strncpy(syslog_addr.sa_data, PR_PATH_LOG, strlen(PR_PATH_LOG) + 1);
++        sstrncpy(syslog_addr.sa_data, PR_PATH_LOG, strlen(PR_PATH_LOG) + 1);
+         addrlen = sizeof(syslog_addr) +
+           ((strlen(PR_PATH_LOG) + 1) - sizeof(syslog_addr.sa_data));
+       }
+ # else
+-      strncpy(syslog_addr.sa_data, PR_PATH_LOG, sizeof(syslog_addr.sa_data));
++      sstrncpy(syslog_addr.sa_data, PR_PATH_LOG, sizeof(syslog_addr.sa_data));
+       syslog_addr.sa_data[sizeof(syslog_addr.sa_data)-1] = '\0';
+       addrlen = sizeof(syslog_addr);
+ # endif /* !Mac OSX */
+Index: lib/pwgrent.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/lib/pwgrent.c,v
+retrieving revision 1.16
+diff -u -r1.16 pwgrent.c
+--- lib/pwgrent.c	23 May 2011 21:08:34 -0000	1.16
++++ lib/pwgrent.c	17 Nov 2011 21:26:30 -0000
+@@ -62,7 +62,7 @@
+   buffer = pwdbuf;
+   pwd = &pwent;
+ 
+-  strncpy(buffer, buf, BUFSIZ-1);
++  sstrncpy(buffer, buf, BUFSIZ-1);
+   buffer[BUFSIZ-1] = '\0';
+ 
+   for(cp = buffer, i = 0; i < NPWDFIELDS && cp; i++) {
+Index: modules/mod_auth_file.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_auth_file.c,v
+retrieving revision 1.40
+diff -u -r1.40 mod_auth_file.c
+--- modules/mod_auth_file.c	23 May 2011 21:11:56 -0000	1.40
++++ modules/mod_auth_file.c	17 Nov 2011 21:26:30 -0000
+@@ -109,7 +109,7 @@
+   buffer = pwdbuf;
+   pwd = &pwent;
+ 
+-  strncpy(buffer, buf, BUFSIZ-1);
++  sstrncpy(buffer, buf, BUFSIZ-1);
+   buffer[BUFSIZ-1] = '\0';
+ 
+   for (cp = buffer, i = 0; i < NPWDFIELDS && cp; i++) {
+Index: modules/mod_ctrls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_ctrls.c,v
+retrieving revision 1.50
+diff -u -r1.50 mod_ctrls.c
+--- modules/mod_ctrls.c	31 Jul 2011 22:07:03 -0000	1.50
++++ modules/mod_ctrls.c	17 Nov 2011 21:26:30 -0000
+@@ -486,7 +486,7 @@
+   memset(&sock, 0, sizeof(sock));
+ 
+   sock.sun_family = AF_UNIX;
+-  strncpy(sock.sun_path, sock_file, strlen(sock_file));
++  sstrncpy(sock.sun_path, sock_file, strlen(sock_file));
+ 
+   len = sizeof(sock);
+ 
+Index: src/ctrls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/src/ctrls.c,v
+retrieving revision 1.30
+diff -u -r1.30 ctrls.c
+--- src/ctrls.c	5 Jun 2011 22:45:14 -0000	1.30
++++ src/ctrls.c	17 Nov 2011 21:26:30 -0000
+@@ -982,7 +982,7 @@
+   memset(&ctrl_sock, 0, sizeof(ctrl_sock));
+ 
+   ctrl_sock.sun_family = AF_UNIX;
+-  strncpy(ctrl_sock.sun_path, socket_file, strlen(socket_file));
++  sstrncpy(ctrl_sock.sun_path, socket_file, strlen(socket_file));
+   len = sizeof(ctrl_sock);
+ 
+   if (connect(sockfd, (struct sockaddr *) &ctrl_sock, len) < 0) {
+Index: utils/ftptop.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/utils/ftptop.c,v
+retrieving revision 1.42
+diff -u -r1.42 ftptop.c
+--- utils/ftptop.c	23 May 2011 20:46:20 -0000	1.42
++++ utils/ftptop.c	17 Nov 2011 21:26:30 -0000
+@@ -524,7 +524,7 @@
+       exit(1);
+     }
+ 
+-    strncpy(ftp_sessions[ftp_nsessions++], buf, strlen(buf) + 1);
++    util_sstrncpy(ftp_sessions[ftp_nsessions++], buf, strlen(buf) + 1);
+   }
+ 
+   scoreboard_close();
diff --git a/proftpd-1.3.4a-bug3719.patch b/proftpd-1.3.4a-bug3719.patch
new file mode 100644
index 0000000..d4f363b
--- /dev/null
+++ b/proftpd-1.3.4a-bug3719.patch
@@ -0,0 +1,31 @@
+Index: modules/mod_ls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_ls.c,v
+retrieving revision 1.190
+diff -u -r1.190 mod_ls.c
+--- modules/mod_ls.c	19 Nov 2011 02:40:12 -0000	1.190
++++ modules/mod_ls.c	21 Nov 2011 21:56:05 -0000
+@@ -460,6 +460,11 @@
+ 
+         m[len] = '\0';
+ 
++        /* If the symlink points to either '.' or '..', skip it (Bug#3719). */
++        if (is_dotdir(m)) {
++          return 0;
++        }
++
+         if (!ls_perms_full(p, cmd, m, NULL)) {
+           return 0;
+         }
+@@ -478,6 +483,11 @@
+ 
+       l[len] = '\0';
+ 
++      /* If the symlink points to either '.' or '..', skip it (Bug#3719). */
++      if (is_dotdir(l)) {
++        return 0;
++      }
++
+       if (!ls_perms_full(p, cmd, l, &hidden)) {
+         return 0;
+       }
diff --git a/proftpd-1.3.4a-bug3720.patch b/proftpd-1.3.4a-bug3720.patch
new file mode 100644
index 0000000..d6fe638
--- /dev/null
+++ b/proftpd-1.3.4a-bug3720.patch
@@ -0,0 +1,160 @@
+Index: contrib/mod_deflate.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_deflate.c,v
+retrieving revision 1.8
+diff -u -r1.8 mod_deflate.c
+--- contrib/mod_deflate.c	10 Jun 2011 02:57:35 -0000	1.8
++++ contrib/mod_deflate.c	23 Nov 2011 17:58:21 -0000
+@@ -898,7 +898,7 @@
+ 
+     pr_signals_block();
+     PRIVS_ROOT
+-    res = pr_log_openfile(c->argv[0], &deflate_logfd, 0640);
++    res = pr_log_openfile(c->argv[0], &deflate_logfd, PR_LOG_SYSTEM_MODE);
+     PRIVS_RELINQUISH
+     pr_signals_unblock();
+ 
+Index: contrib/mod_exec.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_exec.c,v
+retrieving revision 1.20
+diff -u -r1.20 mod_exec.c
+--- contrib/mod_exec.c	24 Sep 2011 06:44:36 -0000	1.20
++++ contrib/mod_exec.c	23 Nov 2011 17:58:21 -0000
+@@ -192,7 +192,7 @@
+ 
+   pr_signals_block();
+   PRIVS_ROOT
+-  res = pr_log_openfile(exec_logname, &exec_logfd, 0640);
++  res = pr_log_openfile(exec_logname, &exec_logfd, PR_LOG_SYSTEM_MODE);
+   PRIVS_RELINQUISH
+   pr_signals_unblock();
+ 
+Index: contrib/mod_quotatab.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_quotatab.c,v
+retrieving revision 1.76
+diff -u -r1.76 mod_quotatab.c
+--- contrib/mod_quotatab.c	26 May 2011 23:14:01 -0000	1.76
++++ contrib/mod_quotatab.c	23 Nov 2011 17:58:21 -0000
+@@ -429,7 +429,7 @@
+ 
+   pr_signals_block();
+   PRIVS_ROOT
+-  res = pr_log_openfile(quota_logname, &quota_logfd, 0640);
++  res = pr_log_openfile(quota_logname, &quota_logfd, PR_LOG_SYSTEM_MODE);
+   PRIVS_RELINQUISH
+   pr_signals_unblock();
+ 
+Index: contrib/mod_radius.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_radius.c,v
+retrieving revision 1.66
+diff -u -r1.66 mod_radius.c
+--- contrib/mod_radius.c	16 Aug 2011 16:13:02 -0000	1.66
++++ contrib/mod_radius.c	23 Nov 2011 17:58:21 -0000
+@@ -1825,7 +1825,7 @@
+ 
+   pr_signals_block();
+   PRIVS_ROOT
+-  res = pr_log_openfile(radius_logname, &radius_logfd, 0640);
++  res = pr_log_openfile(radius_logname, &radius_logfd, PR_LOG_SYSTEM_MODE);
+   PRIVS_RELINQUISH
+   pr_signals_unblock();
+ 
+Index: contrib/mod_sql.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_sql.c,v
+retrieving revision 1.218
+diff -u -r1.218 mod_sql.c
+--- contrib/mod_sql.c	4 Oct 2011 05:27:18 -0000	1.218
++++ contrib/mod_sql.c	23 Nov 2011 17:58:22 -0000
+@@ -5383,7 +5383,7 @@
+ 
+   pr_signals_block();
+   PRIVS_ROOT
+-  res = pr_log_openfile(sql_logfile, &sql_logfd, 0640);
++  res = pr_log_openfile(sql_logfile, &sql_logfd, PR_LOG_SYSTEM_MODE);
+   PRIVS_RELINQUISH
+   pr_signals_unblock();
+ 
+Index: contrib/mod_tls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_tls.c,v
+retrieving revision 1.264
+diff -u -r1.264 mod_tls.c
+--- contrib/mod_tls.c	19 Nov 2011 02:54:13 -0000	1.264
++++ contrib/mod_tls.c	23 Nov 2011 17:58:22 -0000
+@@ -6152,7 +6152,7 @@
+ 
+   pr_signals_block();
+   PRIVS_ROOT
+-  res = pr_log_openfile(tls_logname, &tls_logfd, 0600);
++  res = pr_log_openfile(tls_logname, &tls_logfd, PR_LOG_SYSTEM_MODE);
+   PRIVS_RELINQUISH
+   pr_signals_unblock();
+ 
+Index: contrib/mod_sftp/mod_sftp.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_sftp/mod_sftp.c,v
+retrieving revision 1.61
+diff -u -r1.61 mod_sftp.c
+--- contrib/mod_sftp/mod_sftp.c	12 Oct 2011 17:15:56 -0000	1.61
++++ contrib/mod_sftp/mod_sftp.c	23 Nov 2011 17:58:22 -0000
+@@ -1675,7 +1675,7 @@
+ 
+     pr_signals_block();
+     PRIVS_ROOT
+-    res = pr_log_openfile(sftp_logname, &sftp_logfd, 0600);
++    res = pr_log_openfile(sftp_logname, &sftp_logfd, PR_LOG_SYSTEM_MODE);
+     PRIVS_RELINQUISH
+     pr_signals_unblock();
+ 
+Index: contrib/mod_wrap2/mod_wrap2.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_wrap2/mod_wrap2.c,v
+retrieving revision 1.39
+diff -u -r1.39 mod_wrap2.c
+--- contrib/mod_wrap2/mod_wrap2.c	6 Nov 2011 21:56:12 -0000	1.39
++++ contrib/mod_wrap2/mod_wrap2.c	23 Nov 2011 17:58:22 -0000
+@@ -150,7 +150,7 @@
+ 
+   pr_signals_block();
+   PRIVS_ROOT
+-  res = pr_log_openfile(wrap2_logname, &wrap2_logfd, 0640);
++  res = pr_log_openfile(wrap2_logname, &wrap2_logfd, PR_LOG_SYSTEM_MODE);
+   PRIVS_RELINQUISH
+   pr_signals_unblock();
+ 
+Index: modules/mod_ctrls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_ctrls.c,v
+retrieving revision 1.51
+diff -u -r1.51 mod_ctrls.c
+--- modules/mod_ctrls.c	17 Nov 2011 23:40:28 -0000	1.51
++++ modules/mod_ctrls.c	23 Nov 2011 17:58:22 -0000
+@@ -110,7 +110,7 @@
+     return 0;
+ 
+   PRIVS_ROOT
+-  res = pr_log_openfile(ctrls_logname, &logfd, 0640);
++  res = pr_log_openfile(ctrls_logname, &logfd, PR_LOG_SYSTEM_MODE);
+   PRIVS_RELINQUISH
+ 
+   if (res == 0) {
+Index: modules/mod_memcache.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_memcache.c,v
+retrieving revision 1.15
+diff -u -r1.15 mod_memcache.c
+--- modules/mod_memcache.c	23 May 2011 21:11:56 -0000	1.15
++++ modules/mod_memcache.c	23 Nov 2011 17:58:22 -0000
+@@ -347,7 +347,7 @@
+ 
+       pr_signals_block();
+       PRIVS_ROOT
+-      res = pr_log_openfile(path, &memcache_logfd, 0600);
++      res = pr_log_openfile(path, &memcache_logfd, PR_LOG_SYSTEM_MODE);
+       PRIVS_RELINQUISH
+       pr_signals_unblock();
+ 
diff --git a/proftpd-1.3.4a-bug3723.patch b/proftpd-1.3.4a-bug3723.patch
new file mode 100644
index 0000000..30457b1
--- /dev/null
+++ b/proftpd-1.3.4a-bug3723.patch
@@ -0,0 +1,86 @@
+Index: modules/mod_memcache.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_memcache.c,v
+retrieving revision 1.15
+diff -u -r1.15 mod_memcache.c
+--- modules/mod_memcache.c	23 May 2011 21:11:56 -0000	1.15
++++ modules/mod_memcache.c	1 Dec 2011 00:54:11 -0000
+@@ -41,6 +41,8 @@
+ module memcache_module;
+ 
+ static int memcache_logfd = -1;
++static pool *memcache_pool = NULL;
++static array_header *memcache_server_lists = NULL;
+ 
+ /* Configuration handlers
+  */
+@@ -174,7 +176,7 @@
+   config_rec *c;
+   char *str = "";
+   int ctxt;
+-  memcached_server_st *memcache_servers;
++  memcached_server_st *memcache_servers = NULL;
+ 
+   if (cmd->argc-1 < 1) {
+     CONF_ERROR(cmd, "wrong number of parameters");
+@@ -204,6 +206,9 @@
+   }
+ 
+   c->argv[0] = memcache_servers;
++
++  /* Add the libmemcached-allocated pointer to a list, for later freeing. */
++  *((memcached_server_st **) push_array(memcache_server_lists)) = memcache_servers;
+   return PR_HANDLED(cmd);
+ }
+ 
+@@ -281,19 +286,27 @@
+ }
+ 
+ static void mcache_restart_ev(const void *event_data, void *user_data) {
+-  server_rec *s;
++  register unsigned int i;
++  memcached_server_st **mcache_servers = NULL;
+ 
+-  for (s = (server_rec *) server_list->xas_list; s; s = s->next) {
+-    config_rec *c;
++  mcache_servers = memcache_server_lists->elts;
++  for (i = 0; i < memcache_server_lists->nelts; i++) {
++    memcached_server_list_free(mcache_servers[i]);
++  }
+ 
+-    c = find_config(s->conf, CONF_PARAM, "MemcacheServers", FALSE);
+-    if (c) {
+-      memcached_server_st *memcache_servers;
++  /* Make sure to clear the pointer in the Memcache API as well, to prevent
++   * a dangling pointer situation.
++   */
++  memcache_set_servers(NULL);
+ 
+-      memcache_servers = c->argv[0];
+-      memcached_server_list_free(memcache_servers);
+-    }
+-  }
++  /* Now we can recycle the mod_memcache pool and its associated resources. */
++  destroy_pool(memcache_pool);
++
++  memcache_pool = make_sub_pool(permanent_pool);
++  pr_pool_tag(memcache_pool, MOD_MEMCACHE_VERSION);
++
++  memcache_server_lists = make_array(memcache_pool, 2,
++    sizeof(memcached_server_st **));
+ }
+ 
+ /* Initialization functions
+@@ -302,6 +315,12 @@
+ static int mcache_init(void) {
+   const char *version;
+ 
++  memcache_pool = make_sub_pool(permanent_pool);
++  pr_pool_tag(memcache_pool, MOD_MEMCACHE_VERSION);
++
++  memcache_server_lists = make_array(memcache_pool, 2,
++    sizeof(memcached_server_st **));
++
+   memcache_init();
+ 
+   pr_event_register(&memcache_module, "core.restart", mcache_restart_ev, NULL);
diff --git a/proftpd-1.3.4a-bug3724.patch b/proftpd-1.3.4a-bug3724.patch
new file mode 100644
index 0000000..96c6ced
--- /dev/null
+++ b/proftpd-1.3.4a-bug3724.patch
@@ -0,0 +1,20 @@
+Index: contrib/mod_quotatab.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_quotatab.c,v
+retrieving revision 1.77
+diff -u -r1.77 mod_quotatab.c
+--- contrib/mod_quotatab.c	23 Nov 2011 18:04:37 -0000	1.77
++++ contrib/mod_quotatab.c	5 Dec 2011 19:49:15 -0000
+@@ -3940,7 +3940,11 @@
+ static void quotatab_mod_unload_ev(const void *event_data, void *user_data) {
+   if (strcmp("mod_quotatab.c", (const char *) event_data) == 0) {
+     pr_event_unregister(&quotatab_module, NULL, NULL);
+-    pr_regex_free(NULL, quota_exclude_pre);
++
++    if (quota_exclude_pre != NULL) {
++      pr_regexp_free(NULL, quota_exclude_pre);
++      quota_exclude_pre = NULL;
++    }
+ 
+     if (quotatab_pool) {
+       destroy_pool(quotatab_pool);
diff --git a/proftpd-1.3.4a-bug3726.patch b/proftpd-1.3.4a-bug3726.patch
new file mode 100644
index 0000000..3cc6ed4
--- /dev/null
+++ b/proftpd-1.3.4a-bug3726.patch
@@ -0,0 +1,36 @@
+Index: contrib/mod_exec.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_exec.c,v
+retrieving revision 1.24
+diff -u -r1.24 mod_exec.c
+--- contrib/mod_exec.c	12 Dec 2011 19:22:37 -0000	1.24
++++ contrib/mod_exec.c	13 Dec 2011 21:29:25 -0000
+@@ -626,7 +626,7 @@
+ 
+     (void) close(exec_stderr_pipe[1]);
+     exec_stderr_pipe[1] = -1;
+-   
++  
+     if ((exec_opts & EXEC_OPT_LOG_STDOUT) ||
+         (exec_opts & EXEC_OPT_LOG_STDERR) ||
+         (exec_opts & EXEC_OPT_SEND_STDOUT) ||
+@@ -636,7 +636,10 @@
+       struct timeval tv;
+       time_t start_time = time(NULL);
+ 
+-      res = waitpid(pid, &status, WNOHANG);
++      /* We set the result value to zero initially, so that at least one
++       * pass through the stdout/stderr reading code happens.
++       */
++      res = 0;
+       while (res <= 0) {
+         if (res < 0) {
+           if (errno != EINTR) {
+@@ -698,7 +701,6 @@
+         tv.tv_usec = 0L;
+ 
+         fds = select(maxfd + 1, &readfds, NULL, NULL, &tv);
+-
+         if (fds == -1 &&
+             errno == EINTR) {
+           pr_signals_handle();
diff --git a/proftpd-1.3.4a-bug3727.patch b/proftpd-1.3.4a-bug3727.patch
new file mode 100644
index 0000000..290c2c0
--- /dev/null
+++ b/proftpd-1.3.4a-bug3727.patch
@@ -0,0 +1,133 @@
+Index: contrib/mod_sftp/auth.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_sftp/auth.c,v
+retrieving revision 1.40
+diff -u -r1.40 auth.c
+--- contrib/mod_sftp/auth.c	11 Dec 2011 02:33:14 -0000	1.40
++++ contrib/mod_sftp/auth.c	14 Dec 2011 18:45:53 -0000
+@@ -961,12 +961,12 @@
+      * queried.
+      */
+     if (send_userauth_methods() < 0) {
+-      pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
+-      pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
+-
+       pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
+       pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);
+ 
++      pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
++      pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
++
+       return -1;
+     }
+ 
+@@ -984,12 +984,12 @@
+       pr_trace_msg(trace_channel, 10, "auth method '%s' not enabled", method);
+ 
+       if (send_userauth_methods() < 0) {
+-        pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
+-        pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
+-
+         pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
+         pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);
+ 
++        pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
++        pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
++
+         return -1;
+       }
+ 
+@@ -1009,12 +1009,12 @@
+       pr_trace_msg(trace_channel, 10, "auth method '%s' not enabled", method);
+ 
+       if (send_userauth_methods() < 0) {
+-        pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
+-        pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
+-
+         pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
+         pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);
+ 
++        pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
++        pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
++
+         return -1;
+       }
+ 
+@@ -1034,12 +1034,12 @@
+       pr_trace_msg(trace_channel, 10, "auth method '%s' not enabled", method);
+ 
+       if (send_userauth_methods() < 0) {
+-        pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
+-        pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
+-
+         pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
+         pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);
+ 
++        pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
++        pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
++
+         return -1;
+       }
+ 
+@@ -1059,12 +1059,12 @@
+       pr_trace_msg(trace_channel, 10, "auth method '%s' not enabled", method);
+ 
+       if (send_userauth_methods() < 0) {
+-        pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
+-        pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
+-
+         pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
+         pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);
+ 
++        pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
++        pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
++
+         return -1;
+       }
+ 
+@@ -1076,12 +1076,12 @@
+     }
+ 
+   } else {
+-    pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
+-    pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
+-
+     pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
+     pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);
+ 
++    pr_cmd_dispatch_phase(cmd, POST_CMD_ERR, 0);
++    pr_cmd_dispatch_phase(cmd, LOG_CMD_ERR, 0);
++
+     (void) pr_log_writefile(sftp_logfd, MOD_SFTP_VERSION,
+       "unsupported authentication method '%s' requested", method);
+     return -1;
+@@ -1095,6 +1095,9 @@
+   if (res <= 0) {
+     int xerrno = errno;
+ 
++    pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0);
++    pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0);
++
+     pr_cmd_dispatch_phase(cmd, res == 0 ? POST_CMD : POST_CMD_ERR, 0);
+     pr_cmd_dispatch_phase(cmd, res == 0 ? LOG_CMD : LOG_CMD_ERR, 0);
+ 
+Index: contrib/mod_wrap2/mod_wrap2.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_wrap2/mod_wrap2.c,v
+retrieving revision 1.40
+diff -u -r1.40 mod_wrap2.c
+--- contrib/mod_wrap2/mod_wrap2.c	23 Nov 2011 18:04:38 -0000	1.40
++++ contrib/mod_wrap2/mod_wrap2.c	14 Dec 2011 18:45:53 -0000
+@@ -1844,6 +1844,12 @@
+   if (!wrap2_engine)
+     return PR_DECLINED(cmd);
+ 
++  /* Clear the values from the session struct as well, specifically
++   * session.user.  Failure to do so caused Bug#3727.
++   */
++  session.user = NULL;
++  session.group = NULL;
++   
+   wrap2_ctxt = NULL;
+   wrap2_allow_table = NULL;
+   wrap2_deny_table = NULL;
diff --git a/proftpd-1.3.4a-bug3729.patch b/proftpd-1.3.4a-bug3729.patch
new file mode 100644
index 0000000..b342e10
--- /dev/null
+++ b/proftpd-1.3.4a-bug3729.patch
@@ -0,0 +1,27 @@
+Index: contrib/mod_ldap.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_ldap.c,v
+retrieving revision 1.94
+diff -u -r1.94 mod_ldap.c
+--- contrib/mod_ldap.c	18 Nov 2011 17:34:02 -0000	1.94
++++ contrib/mod_ldap.c	7 Dec 2011 22:38:07 -0000
+@@ -1978,15 +1979,17 @@
+     ldap_do_users = 1;
+     ldap_user_basedn = pstrdup(session.pool, c->argv[0]);
+ 
+-    if (c->argv[1]) {
++    if (c->argc > 1) {
+       ldap_user_name_filter = pstrdup(session.pool, c->argv[1]);
++
+     } else {
+       ldap_user_name_filter = pstrcat(session.pool,
+         "(&(", ldap_attr_uid, "=%v)(objectclass=posixAccount))", NULL);
+     }
+ 
+-    if (c->argv[2]) {
++    if (c->argc > 2) {
+       ldap_user_uid_filter = pstrdup(session.pool, c->argv[2]);
++
+     } else {
+       ldap_user_uid_filter = pstrcat(session.pool,
+         "(&(", ldap_attr_uidnumber, "=%v)(objectclass=posixAccount))", NULL);
diff --git a/proftpd-1.3.4a-bug3734.patch b/proftpd-1.3.4a-bug3734.patch
new file mode 100644
index 0000000..9778030
--- /dev/null
+++ b/proftpd-1.3.4a-bug3734.patch
@@ -0,0 +1,90 @@
+Index: modules/mod_facts.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_facts.c,v
+retrieving revision 1.45
+diff -u -r1.45 mod_facts.c
+--- modules/mod_facts.c	23 May 2011 21:11:56 -0000	1.45
++++ modules/mod_facts.c	17 Jan 2012 00:26:59 -0000
+@@ -1034,11 +1034,12 @@
+   c = find_config(get_dir_ctxt(cmd->tmp_pool, (char *) best_path), CONF_PARAM,
+     "DirFakeUser", FALSE);
+   if (c) {
+-    const char *fake_user = NULL;
+-
+     if (c->argc > 0) {
++      const char *fake_user = NULL;
++
+       fake_user = c->argv[0];
+-      if (strncmp(fake_user, "~", 2) != 0) {
++      if (fake_user != NULL &&
++          strncmp(fake_user, "~", 2) != 0) {
+         fake_uid = pr_auth_name2uid(cmd->tmp_pool, fake_user);
+ 
+       } else {
+@@ -1054,11 +1055,12 @@
+   c = find_config(get_dir_ctxt(cmd->tmp_pool, (char *) best_path), CONF_PARAM,
+     "DirFakeGroup", FALSE);
+   if (c) {
+-    const char *fake_group = NULL;
+-
+     if (c->argc > 0) {
++      const char *fake_group = NULL;
++
+       fake_group = c->argv[0];
+-      if (strncmp(fake_group, "~", 2) != 0) {
++      if (fake_group != NULL &&
++          strncmp(fake_group, "~", 2) != 0) {
+         fake_gid = pr_auth_name2gid(cmd->tmp_pool, fake_group);
+ 
+       } else {
+@@ -1213,13 +1215,20 @@
+   c = find_config(get_dir_ctxt(cmd->tmp_pool, (char *) decoded_path),
+     CONF_PARAM, "DirFakeUser", FALSE);
+   if (c) {
+-    const char *fake_user;
++    if (c->argc > 0) {
++      const char *fake_user;
+ 
+-    fake_user = c->argv[0];
+-    if (strncmp(fake_user, "~", 2) != 0) {
+-      fake_uid = pr_auth_name2uid(cmd->tmp_pool, fake_user);
++      fake_user = c->argv[0];
++      if (fake_user != NULL &&
++          strncmp(fake_user, "~", 2) != 0) {
++        fake_uid = pr_auth_name2uid(cmd->tmp_pool, fake_user);
++
++      } else {
++        fake_uid = session.uid;
++      }
+ 
+     } else {
++      /* Handle the "DirFakeUser off" case (Bug#3715). */
+       fake_uid = session.uid;
+     }
+   }
+@@ -1227,13 +1236,20 @@
+   c = find_config(get_dir_ctxt(cmd->tmp_pool, (char *) decoded_path),
+     CONF_PARAM, "DirFakeGroup", FALSE);
+   if (c) {
+-    const char *fake_group;
++    if (c->argc > 0) {
++      const char *fake_group;
++
++      fake_group = c->argv[0];
++      if (fake_group != NULL &&
++          strncmp(fake_group, "~", 2) != 0) {
++        fake_gid = pr_auth_name2gid(cmd->tmp_pool, fake_group);
+ 
+-    fake_group = c->argv[0];
+-    if (strncmp(fake_group, "~", 2) != 0) {
+-      fake_gid = pr_auth_name2gid(cmd->tmp_pool, fake_group);
++      } else {
++        fake_gid = session.gid;
++      }
+ 
+     } else {
++      /* Handle the "DirFakeGroup off" case (Bug#3715). */
+       fake_gid = session.gid;
+     }
+   }
+
diff --git a/proftpd-1.3.4a-bug3742.patch b/proftpd-1.3.4a-bug3742.patch
new file mode 100644
index 0000000..316e335
--- /dev/null
+++ b/proftpd-1.3.4a-bug3742.patch
@@ -0,0 +1,33 @@
+Index: contrib/mod_tls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_tls.c,v
+retrieving revision 1.268
+diff -u -r1.268 mod_tls.c
+--- contrib/mod_tls.c	23 Jan 2012 01:53:28 -0000	1.268
++++ contrib/mod_tls.c	10 Feb 2012 02:12:23 -0000
+@@ -4415,6 +4415,7 @@
+       case X509_V_ERR_CERT_HAS_EXPIRED:
+       case X509_V_ERR_CERT_REVOKED:
+       case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
++      case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+       case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
+       case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
+       case X509_V_ERR_APPLICATION_VERIFICATION:
+@@ -4439,17 +4440,6 @@
+         break;
+       }
+ 
+-      case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
+-        /* XXX this is strange. we get this error for certain clients
+-         * (i.e. Jeff Altman's kftp) when all is ok. I think it's because the
+-         * client is actually sending the whole CA cert. This must be figured
+-         * out, but we let it pass for now. If the CA cert isn't available
+-         * locally, we will fail anyway.
+-         */
+-        tls_log("%s", X509_verify_cert_error_string(ctx->error));
+-        ok = 1;
+-        break;
+-
+       default:
+         tls_log("error verifying client certificate: [%d] %s",
+           ctx->error, X509_verify_cert_error_string(ctx->error));
diff --git a/proftpd-1.3.4a-bug3743.patch b/proftpd-1.3.4a-bug3743.patch
new file mode 100644
index 0000000..30438d1
--- /dev/null
+++ b/proftpd-1.3.4a-bug3743.patch
@@ -0,0 +1,48 @@
+Index: contrib/mod_sftp/fxp.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_sftp/fxp.c,v
+retrieving revision 1.139
+diff -u -r1.139 fxp.c
+--- contrib/mod_sftp/fxp.c	15 Feb 2012 22:10:56 -0000	1.139
++++ contrib/mod_sftp/fxp.c	15 Feb 2012 22:30:19 -0000
+@@ -2511,7 +2511,18 @@
+       fxp_packet_data_allocsz += sz;
+     }
+ 
+-    memcpy(curr_buf, data, datalen);
++    /* We explicitly want to use memmove(3) here rather than memcpy(3),
++     * since it is possible (and likely) that after reading data out
++     * of this buffer, there will be leftover data which is put back into
++     * the buffer, only at a different offset.  This means that the
++     * source and destination pointers CAN overlap; using memcpy(3) would
++     * lead to subtle memory copy issue (e.g. Bug#3743).
++     *
++     * This manifested as hard-to-reproduce SFTP upload/download stalls,
++     * segfaults, etc, due to corrupted memory being read out as
++     * packet lengths and such.
++     */
++    memmove(curr_buf, data, datalen);
+     curr_buflen = datalen;
+ 
+     return;
+@@ -2556,8 +2567,18 @@
+       }
+     }
+ 
+-    /* Append the SSH2 data to the current unconsumed buffer. */
+-    memcpy(curr_buf + curr_buflen, data, datalen);
++    /* We explicitly want to use memmove(3) here rather than memcpy(3),
++     * since it is possible (and likely) that after reading data out
++     * of this buffer, there will be leftover data which is put back into
++     * the buffer, only at a different offset.  This means that the
++     * source and destination pointers CAN overlap; using memcpy(3) would
++     * lead to subtle memory copy issue (e.g. Bug#3743).
++     *
++     * This manifested as hard-to-reproduce SFTP upload/download stalls,
++     * segfaults, etc, due to corrupted memory being read out as
++     * packet lengths and such.
++     */
++    memmove(curr_buf + curr_buflen, data, datalen);
+     curr_buflen += datalen;
+   }
+ 
diff --git a/proftpd-1.3.4a-bug3744.patch b/proftpd-1.3.4a-bug3744.patch
new file mode 100644
index 0000000..dc7ecac
--- /dev/null
+++ b/proftpd-1.3.4a-bug3744.patch
@@ -0,0 +1,380 @@
+Index: modules/mod_ls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_ls.c,v
+retrieving revision 1.187
+diff -u -r1.187 mod_ls.c
+--- modules/mod_ls.c	5 Nov 2011 23:01:58 -0000	1.187
++++ modules/mod_ls.c	1 Feb 2012 18:57:20 -0000
+@@ -81,6 +81,7 @@
+ 
+ /* ls options */
+ static int
++    opt_1 = 0,
+     opt_a = 0,
+     opt_A = 0,
+     opt_B = 0,
+@@ -395,7 +396,6 @@
+     p = cmd->tmp_pool;
+ 
+   if (pr_fsio_lstat(name, &st) == 0) {
+-
+     char *display_name = NULL;
+ 
+     suffix[0] = suffix[1] = '\0';
+@@ -493,21 +493,24 @@
+         break;
+     }
+ 
+-    if (list_times_gmt)
++    if (list_times_gmt) {
+       t = pr_gmtime(p, (time_t *) &sort_time);
+-    else
++
++    } else {
+       t = pr_localtime(p, (time_t *) &sort_time);
++    }
+ 
+     if (opt_F) {
+-      if (S_ISLNK(st.st_mode))
++      if (S_ISLNK(st.st_mode)) {
+         suffix[0] = '@';
+ 
+-      else if (S_ISDIR(st.st_mode)) {
++      } else if (S_ISDIR(st.st_mode)) {
+         suffix[0] = '/';
+         rval = 1;
+ 
+-      } else if (st.st_mode & 0111)
++      } else if (st.st_mode & 0111) {
+         suffix[0] = '*';
++      }
+     }
+ 
+     if (opt_l) {
+@@ -576,32 +579,38 @@
+         m[2] = (mode & S_IWUSR) ? 'w' : '-';
+         m[1] = (mode & S_IRUSR) ? 'r' : '-';
+ 
+-        if (ls_curtime - sort_time > 180 * 24 * 60 * 60)
++        if (ls_curtime - sort_time > 180 * 24 * 60 * 60) {
+           snprintf(timeline, sizeof(timeline), "%5d", t->tm_year+1900);
+ 
+-        else
++        } else {
+           snprintf(timeline, sizeof(timeline), "%02d:%02d", t->tm_hour,
+             t->tm_min);
++        }
+ 
+         ls_fmt_filesize(s, sizeof(s), st.st_size);
+ 
+-        if (!opt_n) {
+-
+-          /* Format nameline using user/group names. */
+-          snprintf(nameline, sizeof(nameline)-1,
+-            "%s %3d %-8s %-8s %s %s %2d %s %s", m, (int) st.st_nlink,
+-            MAP_UID(st.st_uid), MAP_GID(st.st_gid), s,
+-            months[t->tm_mon], t->tm_mday, timeline,
++        if (opt_1) {
++          /* One file per line, with no info other than the file name.  Easy. */
++          snprintf(nameline, sizeof(nameline)-1, "%s",
+             pr_fs_encode_path(cmd->tmp_pool, display_name));
+ 
+         } else {
+-
+-          /* Format nameline using user/group IDs. */
+-          snprintf(nameline, sizeof(nameline)-1,
+-            "%s %3d %-8u %-8u %s %s %2d %s %s", m, (int) st.st_nlink,
+-            (unsigned) st.st_uid, (unsigned) st.st_gid, s,
+-            months[t->tm_mon], t->tm_mday, timeline,
+-            pr_fs_encode_path(cmd->tmp_pool, name));
++          if (!opt_n) {
++            /* Format nameline using user/group names. */
++            snprintf(nameline, sizeof(nameline)-1,
++              "%s %3d %-8s %-8s %s %s %2d %s %s", m, (int) st.st_nlink,
++              MAP_UID(st.st_uid), MAP_GID(st.st_gid), s,
++              months[t->tm_mon], t->tm_mday, timeline,
++              pr_fs_encode_path(cmd->tmp_pool, display_name));
++
++          } else {
++            /* Format nameline using user/group IDs. */
++            snprintf(nameline, sizeof(nameline)-1,
++              "%s %3d %-8u %-8u %s %s %2d %s %s", m, (int) st.st_nlink,
++              (unsigned) st.st_uid, (unsigned) st.st_gid, s,
++              months[t->tm_mon], t->tm_mday, timeline,
++              pr_fs_encode_path(cmd->tmp_pool, name));
++          }
+         }
+ 
+         nameline[sizeof(nameline)-1] = '\0';
+@@ -611,40 +620,45 @@
+ 
+           suffix[0] = '\0';
+           if (opt_F && pr_fsio_stat(name, &st) == 0) {
+-            if (S_ISLNK(st.st_mode))
++            if (S_ISLNK(st.st_mode)) {
+               suffix[0] = '@';
+ 
+-            else if (S_ISDIR(st.st_mode))
++            } else if (S_ISDIR(st.st_mode)) {
+               suffix[0] = '/';
+ 
+-            else if (st.st_mode & 0111)
++            } else if (st.st_mode & 0111) {
+               suffix[0] = '*';
++            }
+           }
+ 
+           if (!opt_L && list_show_symlinks) {
+-            if (sizeof(nameline) - strlen(nameline) > 4)
++            if (sizeof(nameline) - strlen(nameline) > 4) {
+               snprintf(buf, sizeof(nameline) - strlen(nameline) - 4,
+                 " -> %s", l);
+-            else
++            } else {
+               pr_log_pri(PR_LOG_NOTICE, "notice: symlink '%s' yields an "
+                 "excessive string, ignoring", name);
++            }
+           }
+ 
+           nameline[sizeof(nameline)-1] = '\0';
+         }
+ 
+-        if (opt_STAT)
++        if (opt_STAT) {
+           pr_response_add(R_211, "%s%s", nameline, suffix);
+-        else
++
++        } else {
+           addfile(cmd, nameline, suffix, sort_time, st.st_size);
++        }
+       }
+ 
+     } else {
+       if (S_ISREG(st.st_mode) ||
+           S_ISDIR(st.st_mode) ||
+-          S_ISLNK(st.st_mode))
++          S_ISLNK(st.st_mode)) {
+            addfile(cmd, pr_fs_encode_path(cmd->tmp_pool, name), suffix,
+              sort_time, st.st_size);
++      }
+     }
+   }
+ 
+@@ -1302,6 +1316,7 @@
+       switch (**opt) {
+         case '1':
+           if (strcmp(session.curr_cmd, C_STAT) != 0) {
++            opt_1 = 1;
+             opt_l = opt_C = 0;
+           }
+           break;
+@@ -1354,6 +1369,7 @@
+           if (strcmp(session.curr_cmd, C_NLST) != 0) {
+             opt_l = 1;
+             opt_C = 0;
++            opt_1 = 0;
+           }
+           break;
+ 
+@@ -1422,7 +1438,7 @@
+     while ((*opt)++ && isalnum((int) **opt)) {
+       switch (**opt) {
+         case '1':
+-          opt_l = opt_C = 0;
++          opt_1 = opt_l = opt_C = 0;
+           break;
+ 
+         case 'A':
+@@ -1571,8 +1587,8 @@
+   ls_curtime = time(NULL);
+ 
+   if (clearflags) {
+-    opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_h = opt_n = opt_r =
+-      opt_R = opt_S = opt_t = opt_STAT = opt_L = 0;
++    opt_1 = opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_h = opt_n =
++      opt_r = opt_R = opt_S = opt_t = opt_STAT = opt_L = 0;
+   }
+ 
+   if (have_options(cmd, arg)) {
+@@ -1671,8 +1687,10 @@
+ 
+     /* Open data connection */
+     if (!opt_STAT) {
+-      if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0)
++      if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) {
+         return -1;
++      }
++
+       session.sf_flags |= SF_ASCII_OVERRIDE;
+     }
+ 
+@@ -1705,7 +1723,6 @@
+       skiparg = TRUE;
+ 
+     } else {
+-
+       skiparg = FALSE;
+ 
+       if (use_globbing &&
+@@ -1945,6 +1962,10 @@
+     return -1;
+   }
+ 
++  /* XXX Note that "NLST <glob>" was sent, we might be receiving paths
++   * here, not just file names.  And that is not what dir_hide_file() is
++   * expecting.
++   */
+   if (dir_hide_file(file))
+     return 1;
+ 
+@@ -1970,6 +1991,25 @@
+   }
+ #endif /* PR_USE_NLS */
+ 
++  if (opt_1) {
++    char *ptr;
++
++    /* If the -1 option is configured, we want to make sure that we only
++     * display a file, not a path.  And it's possible that we given a path
++     * here.
++     */
++    ptr = strrchr(display_name, '/');
++    if (ptr != NULL) {
++      size_t display_namelen;
++
++      display_namelen = strlen(display_name);
++      if (display_namelen > 1) {
++        /* Make sure that we handle a possible display_name of '/' properly. */
++        display_name = ptr + 1;
++      }
++    }
++  }
++
+   /* Be sure to flush the output */
+   res = sendline(0, "%s\n", pr_fs_encode_path(cmd->tmp_pool, display_name));
+   if (res < 0)
+@@ -2098,8 +2138,16 @@
+         continue;
+ 
+       if (!curdir) {
+-        char *str = pr_fs_encode_path(cmd->tmp_pool,
+-          pdircat(cmd->tmp_pool, dir, p, NULL));
++        char *str = NULL;
++
++        if (opt_1) {
++          /* Send just the file name, not the path. */
++          str = pr_fs_encode_path(cmd->tmp_pool, p);
++
++        } else {
++          str = pr_fs_encode_path(cmd->tmp_pool,
++            pdircat(cmd->tmp_pool, dir, p, NULL));
++        }
+ 
+         if (sendline(0, "%s\n", str) < 0) {
+           count = -1;
+@@ -2204,26 +2252,32 @@
+   fakeuser = get_param_ptr(CURRENT_CONF, "DirFakeUser", FALSE);
+ 
+   /* Check for a configured "logged in user" DirFakeUser. */
+-  if (fakeuser && strcmp(fakeuser, "~") == 0)
++  if (fakeuser != NULL &&
++      strcmp(fakeuser, "~") == 0) {
+     fakeuser = session.user;
++  }
+ 
+   fakegroup = get_param_ptr(CURRENT_CONF, "DirFakeGroup", FALSE);
+ 
+   /* Check for a configured "logged in user" DirFakeGroup. */
+-  if (fakegroup && strcmp(fakegroup, "~") == 0)
++  if (fakegroup != NULL &&
++      strcmp(fakegroup, "~") == 0) {
+     fakegroup = session.group;
++  }
+ 
+   fake_mode = get_param_ptr(CURRENT_CONF, "DirFakeMode", FALSE);
+   if (fake_mode) {
+     fakemode = *fake_mode;
+     have_fake_mode = TRUE;
+ 
+-  } else
++  } else {
+     have_fake_mode = FALSE;
++  }
+ 
+   tmp = get_param_ptr(TOPLEVEL_CONF, "TimesGMT", FALSE);
+-  if (tmp != NULL)
++  if (tmp != NULL) {
+     list_times_gmt = *tmp;
++  }
+ 
+   res = dolist(cmd, pr_fs_decode_path(cmd->tmp_pool, cmd->arg), TRUE);
+ 
+@@ -2231,8 +2285,9 @@
+     pr_data_abort(0, 0);
+     res = -1;
+ 
+-  } else if (session.sf_flags & SF_XFER)
++  } else if (session.sf_flags & SF_XFER) {
+     ls_done(cmd);
++  }
+ 
+   opt_l = 0;
+ 
+@@ -2415,8 +2470,9 @@
+   list_nfiles.logged = list_ndirs.logged = list_ndepth.logged = FALSE;
+ 
+   tmp = get_param_ptr(TOPLEVEL_CONF, "ShowSymlinks", FALSE);
+-  if (tmp != NULL)
++  if (tmp != NULL) {
+     list_show_symlinks = *tmp;
++  }
+ 
+   target = cmd->argc == 1 ? "." :
+     pr_fs_decode_path(cmd->tmp_pool, cmd->arg);
+@@ -2444,8 +2500,8 @@
+   }
+ 
+   /* Clear the listing option flags. */
+-  opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_n = opt_r = opt_R =
+-    opt_S = opt_t = opt_STAT = opt_L = 0;
++  opt_1 = opt_A = opt_a = opt_B = opt_C = opt_d = opt_F = opt_n = opt_r =
++    opt_R = opt_S = opt_t = opt_STAT = opt_L = 0;
+ 
+   if (have_options(cmd, target)) {
+     if (!list_strict_opts) {
+@@ -2602,8 +2658,10 @@
+ 
+         } else {
+           if (list_flags & LS_FL_NO_ERROR_IF_ABSENT) {
+-            if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0)
++            if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) {
+               return PR_ERROR(cmd);
++            }
++
+             session.sf_flags |= SF_ASCII_OVERRIDE;
+             pr_response_add(R_226, _("Transfer complete"));
+             ls_done(cmd);
+@@ -2617,8 +2675,10 @@
+ 
+       } else {
+         if (list_flags & LS_FL_NO_ERROR_IF_ABSENT) {
+-          if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0)
++          if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) {
+             return PR_ERROR(cmd);
++          }
++
+           session.sf_flags |= SF_ASCII_OVERRIDE;
+           pr_response_add(R_226, _("Transfer complete"));
+           ls_done(cmd);
+@@ -2631,8 +2691,10 @@
+       }
+     }
+ 
+-    if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0)
++    if (pr_data_open(NULL, "file list", PR_NETIO_IO_WR, 0) < 0) {
+       return PR_ERROR(cmd);
++    }
++
+     session.sf_flags |= SF_ASCII_OVERRIDE;
+ 
+     /* Iterate through each matching entry */
diff --git a/proftpd-1.3.4a-bug3745.patch b/proftpd-1.3.4a-bug3745.patch
new file mode 100644
index 0000000..18ba9a4
--- /dev/null
+++ b/proftpd-1.3.4a-bug3745.patch
@@ -0,0 +1,35 @@
+Index: modules/mod_core.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_core.c,v
+retrieving revision 1.420
+diff -u -r1.420 mod_core.c
+--- modules/mod_core.c	5 Feb 2012 18:08:56 -0000	1.420
++++ modules/mod_core.c	5 Feb 2012 18:24:16 -0000
+@@ -3587,6 +3587,27 @@
+   }
+ 
+   if (pr_netaddr_get_family(session.c->local_addr) == pr_netaddr_get_family(session.c->remote_addr)) {
++
++#ifdef PR_USE_IPV6
++    if (pr_netaddr_use_ipv6()) {
++      /* Make sure that the family is NOT IPv6, even though the family of the
++       * local and remote ends match.  The PASV command cannot be used for
++       * IPv6 addresses (Bug#3745).
++       */
++      if (pr_netaddr_get_family(session.c->local_addr) == AF_INET6) {
++        int xerrno = EPERM;
++
++        pr_log_debug(DEBUG0,
++          "Unable to handle PASV for IPv6 address '%s', rejecting command",
++          pr_netaddr_get_ipstr(session.c->local_addr));
++        pr_response_add_err(R_501, "%s: %s", cmd->argv[0], strerror(xerrno));
++
++        errno = xerrno;
++        return PR_ERROR(cmd);
++      }
++    }
++#endif /* PR_USE_IPV6 */
++
+     bind_addr = session.c->local_addr;
+ 
+   } else {
diff --git a/proftpd-1.3.4a-bug3746.patch b/proftpd-1.3.4a-bug3746.patch
new file mode 100644
index 0000000..d023cd7
--- /dev/null
+++ b/proftpd-1.3.4a-bug3746.patch
@@ -0,0 +1,157 @@
+Index: modules/mod_ls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_ls.c,v
+retrieving revision 1.192
+diff -u -r1.192 mod_ls.c
+--- modules/mod_ls.c	1 Feb 2012 22:03:50 -0000	1.192
++++ modules/mod_ls.c	1 Feb 2012 23:13:14 -0000
+@@ -54,8 +54,10 @@
+ #endif
+ #define LS_SENDLINE_FL_FLUSH	0x0001
+ 
+-static unsigned long list_flags = 0;
+ #define LS_FL_NO_ERROR_IF_ABSENT	0x0001
++#define LS_FL_LIST_ONLY			0x0002
++#define LS_FL_NLST_ONLY			0x0004
++static unsigned long list_flags = 0;
+ 
+ static unsigned char list_strict_opts = FALSE;
+ static char *list_options = NULL;
+@@ -2273,15 +2275,28 @@
+   config_rec *c = NULL;
+ 
+   tmp = get_param_ptr(TOPLEVEL_CONF, "ShowSymlinks", FALSE);
+-  if (tmp != NULL)
++  if (tmp != NULL) {
+     list_show_symlinks = *tmp;
++  }
+ 
+   list_strict_opts = FALSE;
+-
+   list_nfiles.max = list_ndirs.max = list_ndepth.max = 0;
+ 
+   c = find_config(CURRENT_CONF, CONF_PARAM, "ListOptions", FALSE);
+-  if (c != NULL) {
++  while (c != NULL) {
++    pr_signals_handle();
++
++    list_flags = *((unsigned long *) c->argv[5]);
++
++    /* Make sure that this ListOptions can be applied to the LIST command.
++     * If not, keep looking for other applicable ListOptions.
++     */
++    if (list_flags & LS_FL_NLST_ONLY) {
++      pr_log_debug(DEBUG10, "%s: skipping NLSTOnly ListOptions", cmd->argv[0]);
++      c = find_config_next(c, c->next, CONF_PARAM, "ListOptions", FALSE);
++      continue;
++    }
++
+     list_options = c->argv[0];
+     list_strict_opts = *((unsigned char *) c->argv[1]);
+ 
+@@ -2299,7 +2314,7 @@
+     list_nfiles.max = *((unsigned int *) c->argv[3]);
+     list_ndirs.max = *((unsigned int *) c->argv[4]);
+ 
+-    list_flags = *((unsigned long *) c->argv[5]);
++    break;
+   }
+ 
+   fakeuser = get_param_ptr(CURRENT_CONF, "DirFakeUser", FALSE);
+@@ -2440,7 +2455,26 @@
+   list_ndepth.max = list_nfiles.max = list_ndirs.max = 0;
+ 
+   c = find_config(CURRENT_CONF, CONF_PARAM, "ListOptions", FALSE);
+-  if (c != NULL) {
++  while (c != NULL) {
++    pr_signals_handle();
++
++    list_flags = *((unsigned long *) c->argv[5]);
++
++    /* Make sure that this ListOptions can be applied to the STAT command.
++     * If not, keep looking for other applicable ListOptions.
++     */
++    if (list_flags & LS_FL_LIST_ONLY) {
++      pr_log_debug(DEBUG10, "%s: skipping LISTOnly ListOptions", cmd->argv[0]);
++      c = find_config_next(c, c->next, CONF_PARAM, "ListOptions", FALSE);
++      continue;
++    }
++
++    if (list_flags & LS_FL_NLST_ONLY) {
++      pr_log_debug(DEBUG10, "%s: skipping NLSTOnly ListOptions", cmd->argv[0]);
++      c = find_config_next(c, c->next, CONF_PARAM, "ListOptions", FALSE);
++      continue;
++    }
++
+     list_options = c->argv[0];
+     list_strict_opts = *((unsigned char *) c->argv[1]);
+ 
+@@ -2458,7 +2492,7 @@
+     list_nfiles.max = *((unsigned int *) c->argv[3]);
+     list_ndirs.max = *((unsigned int *) c->argv[4]);
+ 
+-    list_flags = *((unsigned long *) c->argv[5]);
++    break;
+   }
+ 
+   fakeuser = get_param_ptr(CURRENT_CONF, "DirFakeUser", FALSE);
+@@ -2535,7 +2569,20 @@
+     pr_fs_decode_path(cmd->tmp_pool, cmd->arg);
+ 
+   c = find_config(CURRENT_CONF, CONF_PARAM, "ListOptions", FALSE);
+-  if (c != NULL) {
++  while (c != NULL) {
++    pr_signals_handle();
++
++    list_flags = *((unsigned long *) c->argv[5]);
++    
++    /* Make sure that this ListOptions can be applied to the NLST command.
++     * If not, keep looking for other applicable ListOptions.
++     */
++    if (list_flags & LS_FL_LIST_ONLY) {
++      pr_log_debug(DEBUG10, "%s: skipping LISTOnly ListOptions", cmd->argv[0]);
++      c = find_config_next(c, c->next, CONF_PARAM, "ListOptions", FALSE);
++      continue;
++    }
++
+     list_options = c->argv[0];
+     list_strict_opts = *((unsigned char *) c->argv[1]);
+ 
+@@ -2554,6 +2601,8 @@
+     list_ndirs.max = *((unsigned int *) c->argv[4]);
+ 
+     list_flags = *((unsigned long *) c->argv[5]);
++
++    break;
+   }
+ 
+   /* Clear the listing option flags. */
+@@ -3019,7 +3068,6 @@
+ 
+   /* The default flags */
+   c->argv[5] = pcalloc(c->pool, sizeof(unsigned long));
+-  *((unsigned int *) c->argv[5]) = 0;
+  
+   /* Check for, and handle, optional arguments. */
+   if (cmd->argc-1 >= 2) {
+@@ -3060,6 +3108,12 @@
+ 
+           *((unsigned int *) c->argv[4]) = maxdirs;
+ 
++      } else if (strcasecmp(cmd->argv[i], "LISTOnly") == 0) {
++          flags |= LS_FL_LIST_ONLY;
++
++      } else if (strcasecmp(cmd->argv[i], "NLSTOnly") == 0) {
++          flags |= LS_FL_NLST_ONLY;
++
+       } else if (strcasecmp(cmd->argv[i], "NoErrorIfAbsent") == 0) {
+           flags |= LS_FL_NO_ERROR_IF_ABSENT;
+ 
+@@ -3071,7 +3125,6 @@
+   }
+ 
+   *((unsigned long *) c->argv[5]) = flags;
+-
+   return PR_HANDLED(cmd);
+ }
+ 
diff --git a/proftpd-1.3.4a-bug3747.patch b/proftpd-1.3.4a-bug3747.patch
new file mode 100644
index 0000000..80d933f
--- /dev/null
+++ b/proftpd-1.3.4a-bug3747.patch
@@ -0,0 +1,193 @@
+Index: modules/mod_facts.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_facts.c,v
+retrieving revision 1.47
+diff -u -r1.47 mod_facts.c
+--- modules/mod_facts.c	17 Jan 2012 00:51:02 -0000	1.47
++++ modules/mod_facts.c	3 Feb 2012 06:56:26 -0000
+@@ -46,7 +46,9 @@
+ #define FACTS_OPT_SHOW_UNIX_MODE	0x00040
+ #define FACTS_OPT_SHOW_UNIX_OWNER	0x00080
+ 
+-#define FACTS_MLINFO_FL_SHOW_SYMLINKS	0x00001
++static unsigned long facts_mlinfo_opts = 0;
++#define FACTS_MLINFO_FL_SHOW_SYMLINKS			0x00001
++#define FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK		0x00002
+ 
+ struct mlinfo {
+   pool *pool;
+@@ -339,7 +341,56 @@
+       info->st.st_ino = target_st.st_ino;
+ 
+       if (flags & FACTS_MLINFO_FL_SHOW_SYMLINKS) {
+-        info->type = "OS.unix=symlink";
++
++        /* Do we use the proper RFC 3659 syntax (i.e. following the BNF rules
++         * of RFC 3659), which would be:
++         *
++         *   type=OS.unix=symlink
++         *
++         * See:
++         *   http://www.rfc-editor.org/errata_search.php?rfc=3659
++         *
++         * and search for "OS.unix=slink".
++         *
++         * Or do we use the syntax in the _examples_ presented in RFC 3659,
++         * which is what clients such as FileZilla expect:
++         *
++         *   type=OS.unix=slink:<target>
++         *
++         * See:
++         *   http://trac.filezilla-project.org/ticket/4490
++         */
++
++        if (flags & FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK) {
++          char target[PR_TUNABLE_PATH_MAX+1];
++          int targetlen;
++
++          targetlen = pr_fsio_readlink(path, target, sizeof(target)-1);
++          if (targetlen < 0) { 
++            int xerrno = errno;
++
++            pr_log_debug(DEBUG4, MOD_FACTS_VERSION
++              ": error reading symlink '%s': %s", path, strerror(xerrno));
++
++            errno = xerrno;
++            return -1;
++          }
++
++          if (targetlen >= sizeof(target)-1) {
++            targetlen = sizeof(target)-1;
++          }
++
++          target[targetlen] = '\0';
++
++          info->type = pstrcat(info->pool, "OS.unix=slink:",
++            dir_best_path(info->pool, target), NULL);
++
++        } else {
++          /* Use the proper syntax.  Too bad for the not-really-compliant
++           * FileZilla.
++           */
++          info->type = "OS.unix=symlink";
++        }
+ 
+       } else {
+         info->type = "file";
+@@ -1024,6 +1075,10 @@
+   if (ptr &&
+       *ptr == TRUE) {
+     flags |= FACTS_MLINFO_FL_SHOW_SYMLINKS;
++
++    if (facts_mlinfo_opts & FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK) {
++      flags |= FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK;
++    }
+   }
+ 
+   best_path = dir_best_path(cmd->tmp_pool, decoded_path);
+@@ -1087,11 +1142,11 @@
+   }
+ 
+   /* Open data connection */
+-  session.sf_flags |= SF_ASCII_OVERRIDE;
+   if (pr_data_open(NULL, C_MLSD, PR_NETIO_IO_WR, 0) < 0) {
+     pr_fsio_closedir(dirh);
+     return PR_ERROR(cmd);
+   }
++  session.sf_flags |= SF_ASCII_OVERRIDE;
+ 
+   pr_fs_clear_cache();
+   facts_mlinfobuf_init();
+@@ -1207,6 +1262,10 @@
+   if (ptr &&
+       *ptr == TRUE) {
+     flags |= FACTS_MLINFO_FL_SHOW_SYMLINKS;
++
++    if (facts_mlinfo_opts & FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK) {
++      flags |= FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK;
++    }
+   }
+ 
+   fake_mode = get_param_ptr(get_dir_ctxt(cmd->tmp_pool, (char *) decoded_path),
+@@ -1274,10 +1333,15 @@
+   /* XXX What about chroots? */
+ 
+   if (flags & FACTS_MLINFO_FL_SHOW_SYMLINKS) {
+-    /* If we are supposed to symlinks, then use dir_best_path() to get the
+-     * full path, including dereferencing the symlink.
+-     */
+-    info.path = dir_best_path(cmd->tmp_pool, path);
++    if (flags & FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK) {
++      info.path = dir_canonical_path(cmd->tmp_pool, path);
++
++    } else {
++      /* If we are supposed to show symlinks, then use dir_best_path() to get
++       * the full path, including dereferencing the symlink.
++       */
++      info.path = dir_best_path(cmd->tmp_pool, path);
++    }
+ 
+   } else {
+     info.path = dir_canonical_path(cmd->tmp_pool, path);
+@@ -1407,6 +1471,36 @@
+   return PR_HANDLED(cmd);
+ }
+ 
++/* usage: FactsOptions opt1 ... optN */
++MODRET set_factsoptions(cmd_rec *cmd) {
++  register unsigned int i;
++  config_rec *c;
++  unsigned long opts = 0UL;
++
++  if (cmd->argc-1 == 0) {
++    CONF_ERROR(cmd, "wrong number of parameters");
++  }
++
++  CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL);
++
++  c = add_config_param(cmd->argv[0], 1, NULL);
++
++  for (i = 1; i < cmd->argc; i++) {
++    if (strncmp(cmd->argv[i], "UseSlink", 9) == 0) {
++      opts |= FACTS_MLINFO_FL_SHOW_SYMLINKS_USE_SLINK;
++
++    } else {
++      CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ": unknown FactsOption '",
++        cmd->argv[i], "'", NULL));
++    }
++  }
++
++  c->argv[0] = palloc(c->pool, sizeof(unsigned long));
++  *((unsigned long *) c->argv[0]) = opts;
++
++  return PR_HANDLED(cmd);
++}
++
+ /* Initialization functions
+  */
+ 
+@@ -1426,8 +1520,14 @@
+     advertise = *((int *) c->argv[0]);
+   }
+ 
+-  if (advertise == FALSE)
++  if (advertise == FALSE) {
+     return 0;
++  }
++
++  c = find_config(main_server->conf, CONF_PARAM, "FactsOptions", FALSE);
++  if (c) {
++    facts_mlinfo_opts = *((unsigned long *) c->argv[0]);
++  }
+ 
+   facts_opts = FACTS_OPT_SHOW_MODIFY|FACTS_OPT_SHOW_PERM|FACTS_OPT_SHOW_SIZE|
+     FACTS_OPT_SHOW_TYPE|FACTS_OPT_SHOW_UNIQUE|FACTS_OPT_SHOW_UNIX_GROUP|
+@@ -1451,6 +1551,7 @@
+ 
+ static conftable facts_conftab[] = {
+   { "FactsAdvertise",	set_factsadvertise,	NULL },
++  { "FactsOptions",	set_factsoptions,	NULL },
+   { NULL }
+ };
+ 
+
diff --git a/proftpd-1.3.4a-bug3751.patch b/proftpd-1.3.4a-bug3751.patch
new file mode 100644
index 0000000..68350ec
--- /dev/null
+++ b/proftpd-1.3.4a-bug3751.patch
@@ -0,0 +1,93 @@
+Index: contrib/mod_ban.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_ban.c,v
+retrieving revision 1.55
+diff -u -r1.55 mod_ban.c
+--- contrib/mod_ban.c	12 Dec 2011 19:14:45 -0000	1.55
++++ contrib/mod_ban.c	15 Feb 2012 19:20:45 -0000
+@@ -2819,39 +2819,21 @@
+   pr_event_unregister(&ban_module, "mod_auth.max-users-per-host", NULL);
+   pr_event_unregister(&ban_module, "mod_ban.client-connect-rate", NULL);
+ 
+-  /* "Bounce" the log file descriptor */
++  /* Close the BanLog file descriptor; it will be reopened by the postparse
++   * event listener.
++   */
+   close(ban_logfd);
+   ban_logfd = -1;
+ 
+-  if (ban_log &&
+-      strcasecmp(ban_log, "none") != 0) {
+-    int res;
+-
+-    PRIVS_ROOT
+-    res = pr_log_openfile(ban_log, &ban_logfd, 0660);
+-    PRIVS_RELINQUISH
+-
+-    switch (res) {
+-      case 0:
+-        break;
+-
+-      case -1:
+-        pr_log_debug(DEBUG1, MOD_BAN_VERSION ": unable to open BanLog '%s': %s",
+-          ban_log, strerror(errno));
+-        break;
+-
+-      case PR_LOG_SYMLINK:
+-        pr_log_debug(DEBUG1, MOD_BAN_VERSION ": unable to open BanLog '%s': %s",
+-          ban_log, "is a symlink");
+-        break;
+-
+-      case PR_LOG_WRITABLE_DIR:
+-        pr_log_debug(DEBUG1, MOD_BAN_VERSION ": unable to open BanLog '%s': %s",
+-          ban_log, "parent directory is world-writable");
+-        break;
+-    }
++  /* Close the BanTable file descriptor; it will be reopened by the postparse
++   * event listener.
++   */
++  if (ban_tabfh != NULL) {
++    pr_fsio_close(ban_tabfh);
++    ban_tabfh = NULL;
+   }
+ 
++  /* Remove the timer. */
+   if (ban_timerno > 0) {
+     (void) pr_timer_remove(ban_timerno, &ban_module);
+     ban_timerno = -1;
+Index: contrib/mod_ban.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/contrib/mod_ban.c,v
+retrieving revision 1.55
+diff -u -r1.55 mod_ban.c
+--- contrib/mod_ban.c	12 Dec 2011 19:14:45 -0000	1.55
++++ contrib/mod_ban.c	22 Feb 2012 01:53:52 -0000
+@@ -2762,12 +2763,27 @@
+   ban_tabfh = pr_fsio_open(ban_table, O_RDWR|O_CREAT); 
+   PRIVS_RELINQUISH
+ 
+-  if (!ban_tabfh) {
++  if (ban_tabfh == NULL) {
+     pr_log_pri(PR_LOG_NOTICE, MOD_BAN_VERSION
+       ": unable to open BanTable '%s': %s", ban_table, strerror(errno));
+     pr_session_disconnect(&ban_module, PR_SESS_DISCONNECT_BAD_CONFIG, NULL);
+   }
+ 
++  if (ban_tabfh->fh_fd <= STDERR_FILENO) {
++    int usable_fd;
++
++    usable_fd = pr_fs_get_usable_fd(ban_tabfh->fh_fd);
++    if (usable_fd < 0) {
++      pr_log_debug(DEBUG0, MOD_BAN_VERSION
++        "warning: unable to find good fd for BanTable %s: %s", ban_table,
++        strerror(errno));
++
++    } else {
++      close(ban_tabfh->fh_fd);
++      ban_tabfh->fh_fd = usable_fd;
++    }
++  } 
++
+   /* Get the shm for storing all of our ban info. */
+   lists = ban_get_shm(ban_tabfh);
+   if (lists == NULL &&
diff --git a/proftpd-1.3.4a-bug3756.patch b/proftpd-1.3.4a-bug3756.patch
new file mode 100644
index 0000000..67c6988
--- /dev/null
+++ b/proftpd-1.3.4a-bug3756.patch
@@ -0,0 +1,185 @@
+Index: modules/mod_ctrls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/modules/mod_ctrls.c,v
+retrieving revision 1.53
+diff -u -r1.53 mod_ctrls.c
+--- modules/mod_ctrls.c	12 Dec 2011 04:23:33 -0000	1.53
++++ modules/mod_ctrls.c	23 Feb 2012 22:18:37 -0000
+@@ -492,19 +492,20 @@
+     /* Make sure the path to which we want to bind this socket doesn't already
+      * exist.
+      */
+-    unlink(sock_file);
++    (void) unlink(sock_file);
+   }
+ 
+   /* Fill in the socket structure fields */
+   memset(&sock, 0, sizeof(sock));
+ 
+   sock.sun_family = AF_UNIX;
+-  sstrncpy(sock.sun_path, sock_file, strlen(sock_file));
++  sstrncpy(sock.sun_path, sock_file, sizeof(sock.sun_path));
+ 
+   len = sizeof(sock);
+ 
+   /* Bind the name to the descriptor */
+-  pr_trace_msg(trace_channel, 1, "binding ctrls socket to '%s'", sock.sun_path);
++  pr_trace_msg(trace_channel, 1, "binding ctrls socket fd %d to path '%s'",
++    sockfd, sock.sun_path);
+   if (bind(sockfd, (struct sockaddr *) &sock, len) < 0) {
+     int xerrno = errno;
+ 
+@@ -708,9 +709,10 @@
+     close(ctrls_sockfd);
+     ctrls_sockfd = -1;
+ 
+-    if (is_master)
++    if (is_master) {
+       /* Remove the local socket path as well */
+-      unlink(ctrls_sock_file);
++      (void) unlink(ctrls_sock_file);
++    }
+ 
+     return 0;
+   }
+@@ -1159,9 +1161,30 @@
+     }
+   }
+ 
++  close(ctrls_sockfd);
++  ctrls_sockfd = -1;
++
++  /* Remove the local socket path as well */
++  (void) unlink(ctrls_sock_file);
+   return;
+ }
+ 
++static void ctrls_postparse_ev(const void *event_data, void *user_data) {
++  if (!ctrls_engine) {
++    return;
++  }
++
++  /* Start listening on the ctrl socket */
++  PRIVS_ROOT
++  ctrls_sockfd = ctrls_listen(ctrls_sock_file, CTRLS_LISTEN_FL_REMOVE_SOCKET);
++  PRIVS_RELINQUISH
++
++  /* Start a timer for the checking/processing of the ctrl socket.  */
++  pr_timer_remove(CTRLS_TIMER_ID, &ctrls_module);
++  pr_timer_add(ctrls_interval, CTRLS_TIMER_ID, &ctrls_module, ctrls_timer_cb,
++    "Controls polling");
++}
++
+ static void ctrls_restart_ev(const void *event_data, void *user_data) {
+   register unsigned int i;
+ 
+@@ -1209,26 +1232,11 @@
+     pr_ctrls_init_acl(ctrls_acttab[i].act_acl);
+   }
+ 
++  pr_timer_remove(CTRLS_TIMER_ID, &ctrls_module);
+   pr_alarms_unblock();
+   return;
+ }
+ 
+-static void ctrls_startup_ev(const void *event_data, void *user_data) {
+-  if (!ctrls_engine) {
+-    return;
+-  }
+-
+-  /* Start listening on the ctrl socket */
+-  PRIVS_ROOT
+-  ctrls_sockfd = ctrls_listen(ctrls_sock_file, CTRLS_LISTEN_FL_REMOVE_SOCKET);
+-  PRIVS_RELINQUISH
+-
+-  /* Start a timer for the checking/processing of the ctrl socket.  */
+-  pr_timer_remove(CTRLS_TIMER_ID, &ctrls_module);
+-  pr_timer_add(ctrls_interval, CTRLS_TIMER_ID, &ctrls_module, ctrls_timer_cb,
+-    "Controls polling");
+-}
+-
+ /* Initialization routines
+  */
+ 
+@@ -1262,7 +1270,7 @@
+ 
+   pr_event_register(&ctrls_module, "core.restart", ctrls_restart_ev, NULL);
+   pr_event_register(&ctrls_module, "core.shutdown", ctrls_shutdown_ev, NULL);
+-  pr_event_register(&ctrls_module, "core.startup", ctrls_startup_ev, NULL);
++  pr_event_register(&ctrls_module, "core.postparse", ctrls_postparse_ev, NULL);
+ 
+   return 0;
+ }
+Index: src/ctrls.c
+===================================================================
+RCS file: /cvsroot/proftp/proftpd/src/ctrls.c,v
+retrieving revision 1.32
+diff -u -r1.32 ctrls.c
+--- src/ctrls.c	12 Dec 2011 04:23:33 -0000	1.32
++++ src/ctrls.c	23 Feb 2012 22:18:37 -0000
+@@ -942,7 +942,11 @@
+   /* Create a Unix domain socket */
+   sockfd = socket(AF_UNIX, SOCK_STREAM, 0);
+   if (sockfd < 0) {
++    int xerrno = errno;
++
+     pr_signals_unblock();
++
++    errno = xerrno;
+     return -1;
+   }
+ 
+@@ -975,15 +979,23 @@
+ 
+   /* Make it a socket */
+   if (bind(sockfd, (struct sockaddr *) &cl_sock, len) < 0) {
++    int xerrno = errno;
++
+     unlink(cl_sock.sun_path);
+     pr_signals_unblock();
++
++    errno = xerrno;
+     return -1;
+   }
+ 
+   /* Set the proper mode */
+   if (chmod(cl_sock.sun_path, PR_CTRLS_CL_MODE) < 0) {
++    int xerrno = errno;
++
+     unlink(cl_sock.sun_path);
+     pr_signals_unblock();
++
++    errno = xerrno;
+     return -1;
+   }
+ 
+@@ -991,20 +1003,28 @@
+   memset(&ctrl_sock, 0, sizeof(ctrl_sock));
+ 
+   ctrl_sock.sun_family = AF_UNIX;
+-  sstrncpy(ctrl_sock.sun_path, socket_file, strlen(socket_file));
++  sstrncpy(ctrl_sock.sun_path, socket_file, sizeof(ctrl_sock.sun_path));
+   len = sizeof(ctrl_sock);
+ 
+   if (connect(sockfd, (struct sockaddr *) &ctrl_sock, len) < 0) {
++    int xerrno = errno;
++
+     unlink(cl_sock.sun_path);
+     pr_signals_unblock();
++
++    errno = xerrno;
+     return -1;
+   }
+ 
+ #if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID) && \
+     !defined(HAVE_GETPEERUCRED) && defined(LOCAL_CREDS)
+   if (ctrls_connect_local_creds(sockfd) < 0) {
++    int xerrno = errno;
++
+     unlink(cl_sock.sun_path);
+     pr_signals_unblock();
++
++    errno = xerrno;
+     return -1;
+   }
+ #endif /* LOCAL_CREDS */
diff --git a/proftpd.conf b/proftpd.conf
index e6e64f9..b61c5c2 100644
--- a/proftpd.conf
+++ b/proftpd.conf
@@ -2,9 +2,78 @@
 #
 # See: http://www.proftpd.org/docs/directives/linked/by-name.html
 
+# Security-Enhanced Linux (SELinux) Notes:
+#
+# In Fedora and Red Hat Enterprise Linux, ProFTPD runs confined by SELinux
+# in order to mitigate the effects of an attacker taking advantage of an
+# unpatched vulnerability and getting control of the ftp server. By default,
+# ProFTPD cannot read or write most files on a system nor connect to many
+# external network services, but these restrictions can be relaxed by
+# setting SELinux booleans as follows:
+#
+# setsebool -P allow_ftpd_anon_write=1
+#   This allows the ftp daemon to write to files and directories labelled
+#   with the public_content_rw_t context type; the daemon would only have
+#   read access to these files normally. Files to be made available by ftp
+#   but not writeable should be labelled public_content_t.
+#
+# setsebool -P allow_ftpd_full_access=1
+#   This allows the ftp daemon to read and write all files on the system.
+#
+# setsebool -P allow_ftpd_use_cifs=1
+#   This allows the ftp daemon to read and write files on CIFS-mounted
+#   filesystems.
+#
+# setsebool -P allow_ftpd_use_nfs=1
+#   This allows the ftp daemon to read and write files on NFS-mounted
+#   filesystems.
+#
+# setsebool -P ftp_home_dir=1
+#   This allows the ftp daemon to read and write files in users' home
+#   directories.
+#
+# setsebool -P ftpd_connect_all_unreserved=1
+#   This setting is only available from Fedora 16/RHEL-7 onwards, and is
+#   necessary for active-mode ftp transfers to work reliably with non-Linux
+#   clients (see http://bugzilla.redhat.com/782177), which may choose to
+#   use port numbers outside the "ephemeral port" range of 32768-61000.
+#
+# setsebool -P ftpd_connect_db=1
+#   This setting allows the ftp daemon to connect to commonly-used database
+#   ports over the network, which is necessary if you are using a database
+#   back-end for user authentication, etc.
+#
+# setsebool -P ftpd_is_daemon=1
+#   This setting is available only in Fedora releases 4 to 6 and Red Hat
+#   Enterprise Linux 5. It should be set if ProFTPD is running in standalone
+#   mode, and unset if running in inetd mode.
+#
+# setsebool -P ftpd_disable_trans=1
+#   This setting is available only in Fedora releases 4 to 6 and Red Hat
+#   Enterprise Linux 5, and when set it removes the SELinux confinement of the
+#   ftp daemon. Needless to say, its use is not recommended.
+#
+# All of these booleans are unset by default.
+#
+# See also the "ftpd_selinux" manpage.
+#
+# Note that the "-P" option to setsebool makes the setting permanent, i.e.
+# it will still be in effect after a reboot; without the "-P" option, the
+# effect only lasts until the next reboot.
+#
+# Restrictions imposed by SELinux are on top of those imposed by ordinary
+# file ownership and access permissions; in normal operation, the ftp daemon
+# will not be able to read and/or write a file unless *all* of the ownership,
+# permission and SELinux restrictions allow it.
+
 # Server Config - config used for anything outside a <VirtualHost> or <Global> context
 # See: http://www.proftpd.org/docs/howto/Vhost.html
 
+# Trace logging, disabled by default for performance reasons
+# (http://www.proftpd.org/docs/howto/Tracing.html)
+#TraceLog			/var/log/proftpd/trace.log
+#Trace				DEFAULT:0
+
 ServerName			"ProFTPD server"
 ServerIdent			on "FTP Server ready."
 ServerAdmin			root at localhost
@@ -95,7 +164,7 @@ LogFormat			auth	"%v [%P] %h %t \"%r\" %s"
 #
 # Administrative control actions for the ftpdctl program
 # (http://www.proftpd.org/docs/contrib/mod_ctrls_admin.html)
-#   LoadModule mod_ctrls_admin.c
+LoadModule mod_ctrls_admin.c
 #
 # Support for MODE Z commands, which allows FTP clients and servers to
 # compress data for transfer
@@ -194,6 +263,26 @@ LoadModule mod_vroot.c
 # (http://www.proftpd.org/docs/contrib/mod_ifsession.html)
 #   LoadModule mod_ifsession.c
 
+# Allow only user root to load and unload modules, but allow everyone
+# to see which modules have been loaded
+# (http://www.proftpd.org/docs/modules/mod_dso.html#ModuleControlsACLs)
+ModuleControlsACLs		insmod,rmmod allow user root
+ModuleControlsACLs		lsmod allow user *
+
+# Enable basic controls via ftpdctl
+# (http://www.proftpd.org/docs/modules/mod_ctrls.html)
+ControlsEngine			on
+ControlsACLs			all allow user root
+ControlsSocketACL		allow user *
+ControlsLog			/var/log/proftpd/controls.log
+
+# Enable admin controls via ftpdctl
+# (http://www.proftpd.org/docs/contrib/mod_ctrls_admin.html)
+<IfModule mod_ctrls_admin.c>
+  AdminControlsEngine		on
+  AdminControlsACLs		all allow user root
+</IfModule>
+
 # Enable mod_vroot by default for better compatibility with PAM
 # (http://bugzilla.redhat.com/506735)
 <IfModule mod_vroot.c>
diff --git a/proftpd.spec b/proftpd.spec
index 75c6b46..f98ef5d 100644
--- a/proftpd.spec
+++ b/proftpd.spec
@@ -41,7 +41,7 @@
 %endif
 
 #global prever rc3
-%global rpmrel 4
+%global rpmrel 5
 
 Summary:		Flexible, stable and highly-configurable FTP server
 Name:			proftpd
@@ -66,6 +66,25 @@ Patch1:			proftpd-1.3.4rc3-mysql-password.patch
 Patch2:			proftpd.conf-no-memcached.patch
 Patch4:			proftpd-1.3.4rc1-mod_vroot-test.patch
 Patch5:			proftpd-1.3.4-utf8.patch
+Patch10:		proftpd-1.3.4a-bug3714.patch
+Patch11:		proftpd-1.3.4a-bug3715.patch
+Patch12:		proftpd-1.3.4a-bug3717.patch
+Patch13:		proftpd-1.3.4a-bug3719.patch
+Patch14:		proftpd-1.3.4a-bug3720.patch
+Patch15:		proftpd-1.3.4a-bug3723.patch
+Patch16:		proftpd-1.3.4a-bug3724.patch
+Patch17:		proftpd-1.3.4a-bug3726.patch
+Patch18:		proftpd-1.3.4a-bug3727.patch
+Patch19:		proftpd-1.3.4a-bug3729.patch
+Patch20:		proftpd-1.3.4a-bug3734.patch
+Patch21:		proftpd-1.3.4a-bug3742.patch
+Patch22:		proftpd-1.3.4a-bug3743.patch
+Patch23:		proftpd-1.3.4a-bug3744.patch
+Patch24:		proftpd-1.3.4a-bug3745.patch
+Patch25:		proftpd-1.3.4a-bug3746.patch
+Patch26:		proftpd-1.3.4a-bug3747.patch
+Patch27:		proftpd-1.3.4a-bug3751.patch
+Patch28:		proftpd-1.3.4a-bug3756.patch
 BuildRoot:		%{_tmppath}/%{name}-%{version}-%{release}-root
 Requires(preun):	coreutils, findutils
 %if %{use_systemd}
@@ -209,6 +228,82 @@ cp -p mod_geoip/mod_geoip.html doc/contrib/
 # Fix character encoding in docs
 %patch5 -p1 -b .utf8
 
+# ftpwho/ftptop not showing command arguments
+# http://bugs.proftpd.org/show_bug.cgi?id=3714
+%patch10 -p0
+
+# MLSD/MLST fail when "DirFakeUser off" or "DirFakeGroup off" used
+# http://bugs.proftpd.org/show_bug.cgi?id=3715
+%patch11 -p0
+
+# proftpd fails to run with "Abort trap" error message
+# http://bugs.proftpd.org/show_bug.cgi?id=3717
+%patch12 -p0
+
+# LIST -R can loop endlessly if bad directory symlink exists
+# http://bugs.proftpd.org/show_bug.cgi?id=3719
+%patch13 -p0
+
+# Various module logfile permissions are 0600 instead of 0640
+# http://bugs.proftpd.org/show_bug.cgi?id=3720
+%patch14 -p0
+
+# mod_memcache segfault on server restart
+# http://bugs.proftpd.org/show_bug.cgi?id=3723
+%patch15 -p0
+
+# Unloading mod_quotatab causes segfault
+# http://bugs.proftpd.org/show_bug.cgi?id=3724 (#757311)
+%patch16 -p0
+
+# mod_exec does not always capture stdout/stderr output from executed command
+# http://bugs.proftpd.org/show_bug.cgi?id=3726
+%patch17 -p0
+
+# mod_wrap2 causes unexpected LogFormat %u expansion for SFTP connections
+# http://bugs.proftpd.org/show_bug.cgi?id=3727
+%patch18 -p0
+
+# mod_ldap can segfault when LDAPUsers is used with no optional filters
+# http://bugs.proftpd.org/show_bug.cgi?id=3729
+%patch19 -p0
+
+# DirFakeUser/DirFakeGroup off with name causes SIGSEGV for MLSD/MLST commands
+# http://bugs.proftpd.org/show_bug.cgi?id=3734
+%patch20 -p0
+
+# Improper handling of self-signed certificate in client-sent cert list when "TLSVerifyClient on" is used
+# http://bugs.proftpd.org/show_bug.cgi?id=3742
+%patch21 -p0
+
+# Random stalls/segfaults seen when transferring large files via SFTP
+# http://bugs.proftpd.org/show_bug.cgi?id=3743
+%patch22 -p0
+
+# Support ls(1) -1 option for LIST command
+# http://bugs.proftpd.org/show_bug.cgi?id=3744
+%patch23 -p0
+
+# Reject PASV command if no IPv4 address available
+# http://bugs.proftpd.org/show_bug.cgi?id=3745
+%patch24 -p0
+
+# Support applying ListOptions only to NLST or to LIST commands
+# http://bugs.proftpd.org/show_bug.cgi?id=3746
+%patch25 -p0
+
+# Support option for displaying symlinks via MLSD using syntax preferred by FileZilla
+# http://bugs.proftpd.org/show_bug.cgi?id=3747
+%patch26 -p0
+
+# mod_ban does not close/reopen the BanLog/BanTable file descriptors on restart, causing a file descriptor leak
+# http://bugs.proftpd.org/show_bug.cgi?id=3751
+%patch27 -p0
+
+# mod_ctrls no longer listens on ControlsSocket after restart
+# http://bugs.proftpd.org/show_bug.cgi?id=3756
+%patch28 -p0
+
 # Avoid documentation name conflicts
 mv contrib/README contrib/README.contrib
 
@@ -506,6 +601,40 @@ fi
 %{_mandir}/man1/ftpwho.1*
 
 %changelog
+* Tue Feb 28 2012 Paul Howarth <paul at city-fan.org> 1.3.4a-5
+- Document SELinux configuration for ProFTPD in proftpd.conf (#785443)
+- Add support for basic and administrative controls actions using ftpdctl by
+  default (#786623)
+- Add trace logging directives in proftpd.conf but disable them by default as
+  they impair performance
+- Fix ftpwho/ftptop not showing command arguments (bug 3714)
+- Fix MLSD/MLST fail with "DirFakeUser off" or "DirFakeGroup off" (bug 3715)
+- Fix proftpd fails to run with "Abort trap" error message (bug 3717)
+- Fix LIST -R can loop endlessly if bad directory symlink exists (bug 3719)
+- Fix overly restrictive module logfile permissions (bug 3720)
+- Fix mod_memcache segfault on server restart (bug 3723)
+- Fix unloading mod_quotatab causes segfault (#757311, bug 3724)
+- Fix mod_exec does not always capture stdout/stderr output from executed
+  command (bug 3726)
+- Fix mod_wrap2 causes unexpected LogFormat %u expansion for SFTP connections
+  (bug 3727)
+- Fix mod_ldap segfault when LDAPUsers is used with no optional filters
+  (bug 3729)
+- Fix DirFakeUser/DirFakeGroup off with name causes SIGSEGV for MLSD/MLST
+  commands (bug 3734)
+- Fix improper handling of self-signed certificate in client-sent cert list
+  when "TLSVerifyClient on" is used (bug 3742)
+- Fix random stalls/segfaults seen when transferring large files via SFTP
+  (bug 3743)
+- Support ls(1) -1 option for LIST command (bug 3744)
+- Reject PASV command if no IPv4 address available (bug 3745)
+- Support applying ListOptions only to NLST or to LIST commands (bug 3746)
+- Support option for displaying symlinks via MLSD using syntax preferred by
+  FileZilla (bug 3747)
+- Fix mod_ban not closing and reopening the BanLog/BanTable file descriptors
+  on restart, causing a file descriptor leak (bug 3751)
+- Fix mod_ctrls no longer listening on ControlsSocket after restart (bug 3756)
+
 * Thu Feb  9 2012 Paul Howarth <paul at city-fan.org> 1.3.4a-4
 - Rebuild for new libpcre in Rawhide
 


More information about the scm-commits mailing list