diff --git a/.gitignore b/.gitignore index 44bfd43..f9330d6 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,10 @@ # master/f22 -/proftpd-1.3.5.tar.gz +/proftpd-1.3.5a.tar.gz /proftpd-mod-geoip-0.3.tar.gz -/mod_vroot-0.9.3.tar.gz +/v0.9.4.tar.gz /Test-Unit-0.14.tar.gz # f21/el7 -/proftpd-1.3.5.tar.gz +/proftpd-1.3.5a.tar.gz /proftpd-mod-geoip-0.3.tar.gz /proftpd-mod-vroot-0.9.2.tar.gz /Test-Unit-0.14.tar.gz diff --git a/3a777567d403a407f9f8ae257ea41efe5313c625.diff b/3a777567d403a407f9f8ae257ea41efe5313c625.diff deleted file mode 100644 index 6454d9f..0000000 --- a/3a777567d403a407f9f8ae257ea41efe5313c625.diff +++ /dev/null @@ -1,31 +0,0 @@ -diff --git a/src/inet.c b/src/inet.c -index aa94975..1e9b959 100644 ---- a/src/inet.c -+++ b/src/inet.c -@@ -2,7 +2,7 @@ - * ProFTPD - FTP server daemon - * Copyright (c) 1997, 1998 Public Flood Software - * Copyright (c) 1999, 2000 MacGyver aka Habeeb J. Dihu -- * Copyright (c) 2001-2013 The ProFTPD Project team -+ * Copyright (c) 2001-2014 The ProFTPD Project team - * - * 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 -@@ -771,8 +771,15 @@ int pr_inet_set_proto_opts(pool *p, conn_t *c, int mss, int nodelay, - /* Only set TCLASS flags on IPv6 sockets; IPv4 sockets use TOS. */ - if (pr_netaddr_get_family(c->local_addr) == AF_INET6) { - if (c->listen_fd != -1) { -- if (setsockopt(c->listen_fd, ip_level, IPV6_TCLASS, (void *) &tos, -- sizeof(tos)) < 0) { -+ int res; -+ -+ res = setsockopt(c->listen_fd, ip_level, IPV6_TCLASS, (void *) &tos, -+ sizeof(tos)); -+ if (res < 0 -+#ifdef ENOPROTOOPT -+ && errno != ENOPROTOOPT -+#endif /* !ENOPROTOOPT */ -+ ) { - pr_log_pri(PR_LOG_NOTICE, "error setting listen fd IPV6_TCLASS: %s", - strerror(errno)); - } diff --git a/proftpd-1.3.5-CVE-2015-3306.patch b/proftpd-1.3.5-CVE-2015-3306.patch deleted file mode 100644 index 2690a1a..0000000 --- a/proftpd-1.3.5-CVE-2015-3306.patch +++ /dev/null @@ -1,589 +0,0 @@ ---- contrib/mod_copy.c -+++ contrib/mod_copy.c -@@ -31,7 +31,7 @@ - - #include "conf.h" - --#define MOD_COPY_VERSION "mod_copy/0.4" -+#define MOD_COPY_VERSION "mod_copy/0.5" - - /* Make sure the version of proftpd is as necessary. */ - #if PROFTPD_VERSION_NUMBER < 0x0001030401 -@@ -40,6 +40,8 @@ - - extern pr_response_t *resp_list, *resp_err_list; - -+static int copy_engine = TRUE; -+ - static const char *trace_channel = "copy"; - - /* These are copied largely from src/mkhome.c */ -@@ -471,10 +473,37 @@ static int copy_paths(pool *p, const cha - return 0; - } - -+/* Configuration handlers -+ */ -+ -+/* usage: CopyEngine on|off */ -+MODRET set_copyengine(cmd_rec *cmd) { -+ int engine = -1; -+ config_rec *c; -+ -+ CHECK_ARGS(cmd, 1); -+ CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL); -+ -+ engine = get_boolean(cmd, 1); -+ if (engine == -1) { -+ CONF_ERROR(cmd, "expected Boolean parameter"); -+ } -+ -+ c = add_config_param(cmd->argv[0], 1, NULL); -+ c->argv[0] = palloc(c->pool, sizeof(int)); -+ *((int *) c->argv[0]) = engine; -+ -+ return PR_HANDLED(cmd); -+} -+ - /* Command handlers - */ - - MODRET copy_copy(cmd_rec *cmd) { -+ if (copy_engine == FALSE) { -+ return PR_DECLINED(cmd); -+ } -+ - if (cmd->argc < 2) { - return PR_DECLINED(cmd); - } -@@ -539,12 +568,26 @@ MODRET copy_cpfr(cmd_rec *cmd) { - register unsigned int i; - int res; - char *path = ""; -+ unsigned char *authenticated = NULL; -+ -+ if (copy_engine == FALSE) { -+ return PR_DECLINED(cmd); -+ } - - if (cmd->argc < 3 || - strncasecmp(cmd->argv[1], "CPFR", 5) != 0) { - return PR_DECLINED(cmd); - } - -+ authenticated = get_param_ptr(cmd->server->conf, "authenticated", FALSE); -+ if (authenticated == NULL || -+ *authenticated == FALSE) { -+ pr_response_add_err(R_530, _("Please login with USER and PASS")); -+ -+ errno = EPERM; -+ return PR_ERROR(cmd); -+ } -+ - CHECK_CMD_MIN_ARGS(cmd, 3); - - /* Construct the target file name by concatenating all the parameters after -@@ -594,12 +637,26 @@ MODRET copy_cpfr(cmd_rec *cmd) { - MODRET copy_cpto(cmd_rec *cmd) { - register unsigned int i; - char *from, *to = ""; -+ unsigned char *authenticated = NULL; -+ -+ if (copy_engine == FALSE) { -+ return PR_DECLINED(cmd); -+ } - - if (cmd->argc < 3 || - strncasecmp(cmd->argv[1], "CPTO", 5) != 0) { - return PR_DECLINED(cmd); - } - -+ authenticated = get_param_ptr(cmd->server->conf, "authenticated", FALSE); -+ if (authenticated == NULL || -+ *authenticated == FALSE) { -+ pr_response_add_err(R_530, _("Please login with USER and PASS")); -+ -+ errno = EPERM; -+ return PR_ERROR(cmd); -+ } -+ - CHECK_CMD_MIN_ARGS(cmd, 3); - - from = pr_table_get(session.notes, "mod_copy.cpfr-path", NULL); -@@ -632,6 +689,10 @@ MODRET copy_cpto(cmd_rec *cmd) { - } - - MODRET copy_log_site(cmd_rec *cmd) { -+ if (copy_engine == FALSE) { -+ return PR_DECLINED(cmd); -+ } -+ - if (cmd->argc < 3 || - strncasecmp(cmd->argv[1], "CPTO", 5) != 0) { - return PR_DECLINED(cmd); -@@ -643,23 +704,58 @@ MODRET copy_log_site(cmd_rec *cmd) { - return PR_DECLINED(cmd); - } - -+MODRET copy_post_pass(cmd_rec *cmd) { -+ config_rec *c; -+ -+ if (copy_engine == FALSE) { -+ return PR_DECLINED(cmd); -+ } -+ -+ /* The CopyEngine directive may have been changed for this user by -+ * e.g. mod_ifsession, thus we check again. -+ */ -+ c = find_config(main_server->conf, CONF_PARAM, "CopyEngine", FALSE); -+ if (c != NULL) { -+ copy_engine = *((int *) c->argv[0]); -+ } -+ -+ return PR_DECLINED(cmd); -+} -+ - /* Initialization functions - */ - - static int copy_sess_init(void) { -+ config_rec *c; -+ -+ c = find_config(main_server->conf, CONF_PARAM, "CopyEngine", FALSE); -+ if (c != NULL) { -+ copy_engine = *((int *) c->argv[0]); -+ } -+ -+ if (copy_engine == FALSE) { -+ return 0; -+ } -+ - /* Advertise support for the SITE command */ - pr_feat_add("SITE COPY"); -- - return 0; - } - - /* Module API tables - */ - -+static conftable copy_conftab[] = { -+ { "CopyEngine", set_copyengine, NULL }, -+ -+ { NULL } -+}; -+ - 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 }, -+ { POST_CMD, C_PASS, G_NONE, copy_post_pass, FALSE, FALSE }, - { LOG_CMD, C_SITE, G_NONE, copy_log_site, FALSE, FALSE }, - { LOG_CMD_ERR, C_SITE, G_NONE, copy_log_site, FALSE, FALSE }, - -@@ -676,7 +772,7 @@ module copy_module = { - "copy", - - /* Module configuration handler table */ -- NULL, -+ copy_conftab, - - /* Module command handler table */ - copy_cmdtab, ---- doc/contrib/mod_copy.html -+++ doc/contrib/mod_copy.html -@@ -27,22 +27,40 @@ ProFTPD 1.3.x, and is not compile - instructions are discussed here. - -

--The most current version of mod_copy can be found at: --

--  http://www.castaglia.org/proftpd/
--
-+The most current version of mod_copy is distributed with the -+ProFTPD source code. - -

Author

-

- Please contact TJ Saunders <tj at castaglia.org> with any - questions, concerns, or suggestions regarding this module. - -+

Directives

-+ -+ -

SITE Commands

- - -+

-+


-+

CopyEngine

-+Syntax: CopyEngine on|off
-+Default: CopyEngine on
-+Context: server config, <VirtualHost>, <Global>
-+Module: mod_radius
-+Compatibility: 1.3.6rc1 and later -+ -+

-+The CopyEngine directive enables or disables the module's -+handling of SITE COPY et al commands. If it is set to -+off this module ignores these commands. -+ -+

-


-

SITE CPFR

- This SITE command specifies the source file/directory to use -@@ -118,13 +136,8 @@ your existing server: -

-



- --Author: $Author: castaglia $
--Last Updated: $Date: 2010/03/10 19:20:43 $
-- --

-- - --© Copyright 2009-2010 TJ Saunders
-+© Copyright 2009-2015 TJ Saunders
- All Rights Reserved
-
- ---- RELEASE_NOTES -+++ RELEASE_NOTES -@@ -6,6 +6,14 @@ This file contains a description of the - releases. More information on these changes can be found in the NEWS and - ChangeLog files. - -+Upcoming 1.3.5a -+--------------- -+ -+ + New Configuration Directives -+ -+ CopyEngine (Bug#4169) -+ -+ - 1.3.5 - --------- - ---- tests/t/lib/ProFTPD/Tests/Modules/mod_copy.pm -+++ tests/t/lib/ProFTPD/Tests/Modules/mod_copy.pm -@@ -21,6 +21,11 @@ my $TESTS = { - test_class => [qw(forking)], - }, - -+ copy_file_no_login => { -+ order => ++$order, -+ test_class => [qw(bug forking)], -+ }, -+ - copy_dir => { - order => ++$order, - test_class => [qw(forking)], -@@ -86,6 +91,11 @@ my $TESTS = { - test_class => [qw(forking)], - }, - -+ copy_cpfr_cpto_no_login => { -+ order => ++$order, -+ test_class => [qw(bug forking)], -+ }, -+ - copy_cpto_no_cpfr => { - order => ++$order, - test_class => [qw(forking)], -@@ -263,6 +273,137 @@ sub copy_file { - unlink($log_file); - } - -+sub copy_file_no_login { -+ my $self = shift; -+ my $tmpdir = $self->{tmpdir}; -+ -+ my $config_file = "$tmpdir/copy.conf"; -+ my $pid_file = File::Spec->rel2abs("$tmpdir/copy.pid"); -+ my $scoreboard_file = File::Spec->rel2abs("$tmpdir/copy.scoreboard"); -+ -+ my $log_file = File::Spec->rel2abs('tests.log'); -+ -+ my $auth_user_file = File::Spec->rel2abs("$tmpdir/copy.passwd"); -+ my $auth_group_file = File::Spec->rel2abs("$tmpdir/copy.group"); -+ -+ my $user = 'proftpd'; -+ my $passwd = 'test'; -+ my $group = 'ftpd'; -+ my $home_dir = File::Spec->rel2abs($tmpdir); -+ my $uid = 500; -+ my $gid = 500; -+ -+ # Make sure that, if we're running as root, that the home directory has -+ # permissions/privs set for the account we create -+ if ($< == 0) { -+ unless (chmod(0755, $home_dir)) { -+ die("Can't set perms on $home_dir to 0755: $!"); -+ } -+ -+ unless (chown($uid, $gid, $home_dir)) { -+ die("Can't set owner of $home_dir to $uid/$gid: $!"); -+ } -+ } -+ -+ auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, -+ '/bin/bash'); -+ auth_group_write($auth_group_file, $group, $gid, $user); -+ -+ my $src_file = File::Spec->rel2abs("$home_dir/foo.txt"); -+ if (open(my $fh, "> $src_file")) { -+ print $fh "Hello, World!\n"; -+ -+ unless (close($fh)) { -+ die("Can't write $src_file: $!"); -+ } -+ -+ } else { -+ die("Can't open $src_file: $!"); -+ } -+ -+ my $dst_file = File::Spec->rel2abs("$home_dir/bar.txt"); -+ -+ my $config = { -+ PidFile => $pid_file, -+ ScoreboardFile => $scoreboard_file, -+ SystemLog => $log_file, -+ -+ AuthUserFile => $auth_user_file, -+ AuthGroupFile => $auth_group_file, -+ -+ IfModules => { -+ 'mod_delay.c' => { -+ DelayEngine => 'off', -+ }, -+ }, -+ }; -+ -+ my ($port, $config_user, $config_group) = config_write($config_file, $config); -+ -+ # Open pipes, for use between the parent and child processes. Specifically, -+ # the child will indicate when it's done with its test by writing a message -+ # to the parent. -+ my ($rfh, $wfh); -+ unless (pipe($rfh, $wfh)) { -+ die("Can't open pipe: $!"); -+ } -+ -+ my $ex; -+ -+ # Fork child -+ $self->handle_sigchld(); -+ defined(my $pid = fork()) or die("Can't fork: $!"); -+ if ($pid) { -+ eval { -+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); -+ -+ eval { $client->site('COPY', 'foo.txt', 'bar.txt') }; -+ unless ($@) { -+ die("SITE COPY succeeded unexpectedly"); -+ } -+ -+ my $resp_code = $client->response_code(); -+ my $resp_msg = $client->response_msg(); -+ -+ my $expected; -+ $expected = 530; -+ $self->assert($expected == $resp_code, -+ test_msg("Expected response code $expected, got $resp_code")); -+ -+ $expected = "Please login with USER and PASS"; -+ $self->assert($expected eq $resp_msg, -+ test_msg("Expected response message '$expected', got '$resp_msg'")); -+ }; -+ -+ if ($@) { -+ $ex = $@; -+ } -+ -+ $wfh->print("done\n"); -+ $wfh->flush(); -+ -+ } else { -+ eval { server_wait($config_file, $rfh) }; -+ if ($@) { -+ warn($@); -+ exit 1; -+ } -+ -+ exit 0; -+ } -+ -+ # Stop server -+ server_stop($pid_file); -+ -+ $self->assert_child_ok($pid); -+ -+ if ($ex) { -+ die($ex); -+ } -+ -+ unlink($log_file); -+} -+ - sub copy_dir { - my $self = shift; - my $tmpdir = $self->{tmpdir}; -@@ -2578,6 +2719,153 @@ sub copy_cpfr_cpto { - }; - - if ($@) { -+ $ex = $@; -+ } -+ -+ $wfh->print("done\n"); -+ $wfh->flush(); -+ -+ } else { -+ eval { server_wait($config_file, $rfh) }; -+ if ($@) { -+ warn($@); -+ exit 1; -+ } -+ -+ exit 0; -+ } -+ -+ # Stop server -+ server_stop($pid_file); -+ -+ $self->assert_child_ok($pid); -+ -+ if ($ex) { -+ die($ex); -+ } -+ -+ unlink($log_file); -+} -+ -+sub copy_cpfr_cpto_no_login { -+ my $self = shift; -+ my $tmpdir = $self->{tmpdir}; -+ -+ my $config_file = "$tmpdir/copy.conf"; -+ my $pid_file = File::Spec->rel2abs("$tmpdir/copy.pid"); -+ my $scoreboard_file = File::Spec->rel2abs("$tmpdir/copy.scoreboard"); -+ -+ my $log_file = File::Spec->rel2abs('tests.log'); -+ -+ my $auth_user_file = File::Spec->rel2abs("$tmpdir/copy.passwd"); -+ my $auth_group_file = File::Spec->rel2abs("$tmpdir/copy.group"); -+ -+ my $user = 'proftpd'; -+ my $passwd = 'test'; -+ my $group = 'ftpd'; -+ my $home_dir = File::Spec->rel2abs($tmpdir); -+ my $uid = 500; -+ my $gid = 500; -+ -+ # Make sure that, if we're running as root, that the home directory has -+ # permissions/privs set for the account we create -+ if ($< == 0) { -+ unless (chmod(0755, $home_dir)) { -+ die("Can't set perms on $home_dir to 0755: $!"); -+ } -+ -+ unless (chown($uid, $gid, $home_dir)) { -+ die("Can't set owner of $home_dir to $uid/$gid: $!"); -+ } -+ } -+ -+ auth_user_write($auth_user_file, $user, $passwd, $uid, $gid, $home_dir, -+ '/bin/bash'); -+ auth_group_write($auth_group_file, $group, $gid, $user); -+ -+ my $src_file = File::Spec->rel2abs("$home_dir/foo.txt"); -+ if (open(my $fh, "> $src_file")) { -+ print $fh "Hello, World!\n"; -+ -+ unless (close($fh)) { -+ die("Can't write $src_file: $!"); -+ } -+ -+ } else { -+ die("Can't open $src_file: $!"); -+ } -+ -+ my $dst_file = File::Spec->rel2abs("$home_dir/bar.txt"); -+ -+ my $config = { -+ PidFile => $pid_file, -+ ScoreboardFile => $scoreboard_file, -+ SystemLog => $log_file, -+ -+ AuthUserFile => $auth_user_file, -+ AuthGroupFile => $auth_group_file, -+ -+ IfModules => { -+ 'mod_delay.c' => { -+ DelayEngine => 'off', -+ }, -+ }, -+ }; -+ -+ my ($port, $config_user, $config_group) = config_write($config_file, $config); -+ -+ # Open pipes, for use between the parent and child processes. Specifically, -+ # the child will indicate when it's done with its test by writing a message -+ # to the parent. -+ my ($rfh, $wfh); -+ unless (pipe($rfh, $wfh)) { -+ die("Can't open pipe: $!"); -+ } -+ -+ my $ex; -+ -+ # Fork child -+ $self->handle_sigchld(); -+ defined(my $pid = fork()) or die("Can't fork: $!"); -+ if ($pid) { -+ eval { -+ my $client = ProFTPD::TestSuite::FTP->new('127.0.0.1', $port); -+ -+ eval { $client->site('CPFR', 'foo.txt') }; -+ unless ($@) { -+ die("SITE CPFR succeeded unexpectedly"); -+ } -+ -+ my $resp_code = $client->response_code(); -+ my $resp_msg = $client->response_msg(); -+ -+ my $expected; -+ $expected = 530; -+ $self->assert($expected == $resp_code, -+ test_msg("Expected response code $expected, got $resp_code")); -+ -+ $expected = "Please login with USER and PASS"; -+ $self->assert($expected eq $resp_msg, -+ test_msg("Expected response message '$expected', got '$resp_msg'")); -+ -+ eval { $client->site('CPTO', 'bar.txt') }; -+ unless ($@) { -+ die("SITE CPTO succeeded unexpectedly"); -+ } -+ -+ $resp_code = $client->response_code(); -+ $resp_msg = $client->response_msg(); -+ -+ $expected = 530; -+ $self->assert($expected == $resp_code, -+ test_msg("Expected response code $expected, got $resp_code")); -+ -+ $expected = "Please login with USER and PASS"; -+ $self->assert($expected eq $resp_msg, -+ test_msg("Expected response message '$expected', got '$resp_msg'")); -+ }; -+ -+ if ($@) { - $ex = $@; - } - diff --git a/proftpd.spec b/proftpd.spec index 8cd624c..61a2b3b 100644 --- a/proftpd.spec +++ b/proftpd.spec @@ -41,11 +41,11 @@ %define _hardened_build 1 #global prever rc3 -%global rpmrel 5 +%global rpmrel 1 Summary: Flexible, stable and highly-configurable FTP server Name: proftpd -Version: 1.3.5 +Version: 1.3.5a Release: %{?prever:0.}%{rpmrel}%{?prever:.%{prever}}%{?dist} License: GPLv2+ Group: System Environment/Daemons @@ -65,9 +65,7 @@ Source13: http://search.cpan.org/CPAN/authors/id/C/CL/CLEMBURG/Test-Unit-0.14.t Patch2: proftpd.conf-no-memcached.patch Patch4: proftpd-1.3.4rc1-mod_vroot-test.patch Patch5: proftpd-1.3.4-utf8.patch -Patch20: https://github.com/proftpd/proftpd/commit/3a777567d403a407f9f8ae257ea41efe5313c625.diff Patch27: proftpd-mod-vroot-0.9.2-bug3841.patch -Patch31: proftpd-1.3.5-CVE-2015-3306.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root Requires(preun): coreutils, findutils %if %{use_systemd} @@ -208,21 +206,10 @@ cp -p %{SOURCE1} proftpd.conf # Fix character encoding in docs %patch5 -p1 -b .utf8 -# Upstream fix to ignore any ENOPROTOOPT errors when setting the IPv6 TCLASS (TOS) -# flags on the socket; they make for noisier logging without providing any -# actual value to the user/admin -# http://bugs.proftpd.org/show_bug.cgi?id=4055 -%patch20 -p1 - # Fix possible symlink race when applying UserOwner to newly created directory # http://bugs.proftpd.org/show_bug.cgi?id=3841 %patch27 -# Unauthenticated copying of files via SITE CPFR/CPTO allowed by mod_copy -# http://bugs.proftpd.org/show_bug.cgi?id=4169 -# CVE-2015-3306 -%patch31 - # Avoid documentation name conflicts mv contrib/README contrib/README.contrib @@ -505,6 +492,23 @@ fi %{_mandir}/man1/ftpwho.1* %changelog +* Thu May 28 2015 Paul Howarth - 1.3.5a-1 +- Update to 1.3.5a + - Fixed "stalled" SSL/TLS handshakes for data transfers + - Fixed handling of SSH keys with overlong Comment headers in mod_sftp_sql + - By default, mod_tls will no longer support SSLv3 connections; in order to + support SSLv3 connections (for sites that need to), you must explicitly + configure this via the TLSProtocol directive, e.g.: + TLSProtocol SSLv3 TLSv1 ... + - The mod_copy module is enabled by default; there may be cases where the + module should be disabled, without requiring a rebuild of the server, thus + mod_copy now supports a CopyEngine directive to enable/disable the module + - The DeleteAbortedStores directive (for Bug#3917) is only enabled when + HiddenStores is in effect, as intended when originally implemented, rather + than all the time + - Many other bug-fixes, see NEWS for details +- Drop upstreamed patches + * Tue Apr 28 2015 Paul Howarth - 1.3.5-5 - Unauthenticated copying of files via SITE CPFR/CPTO was allowed by mod_copy (CVE-2015-3306, http://bugs.proftpd.org/show_bug.cgi?id=4169) diff --git a/sources b/sources index 120c4d3..fa4fecb 100644 --- a/sources +++ b/sources @@ -1,4 +1,4 @@ -aff1bff40e675244d72c4667f203e5bb proftpd-1.3.5.tar.gz +b9d3092411478415b31d435f8e26d173 proftpd-1.3.5a.tar.gz cc0e479406436e474ca7d59994fa73bb proftpd-mod-geoip-0.3.tar.gz 6db495b25e9da2ba0c901e7c44e119bc proftpd-mod-vroot-0.9.2.tar.gz ad574713bcd00f62883ff2f9a84eec1f Test-Unit-0.14.tar.gz