diff --git a/08ba2f63.patch b/08ba2f63.patch new file mode 100644 index 0000000..cd1c1eb --- /dev/null +++ b/08ba2f63.patch @@ -0,0 +1,78 @@ +From 08ba2f630c8eebd023ae68d8e2abd1e7170468af Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Sun, 14 May 2017 14:09:23 -0700 +Subject: [PATCH] Issue #501: Avoid a spurious "Address already in use" error + on startup because we are listening on a local socket twice. + +--- + modules/mod_ctrls.c | 22 +++++++--------------- + 1 file changed, 7 insertions(+), 15 deletions(-) + +diff --git a/modules/mod_ctrls.c b/modules/mod_ctrls.c +index 25ea723..8efd8b4 100644 +--- a/modules/mod_ctrls.c ++++ b/modules/mod_ctrls.c +@@ -2,8 +2,7 @@ + * ProFTPD: mod_ctrls -- a module implementing the ftpdctl local socket + * server, as well as several utility functions for other Controls + * modules +- * +- * Copyright (c) 2000-2016 TJ Saunders ++ * Copyright (c) 2000-2017 TJ Saunders + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -81,8 +80,6 @@ static ctrls_acl_t ctrls_sock_acl; + + static unsigned char ctrls_engine = TRUE; + +-#define CTRLS_LISTEN_FL_REMOVE_SOCKET 0x0001 +- + /* Necessary prototypes */ + static int ctrls_setblock(int sockfd); + static int ctrls_setnonblock(int sockfd); +@@ -437,7 +434,7 @@ static int ctrls_cls_write(void) { + } + + /* Create a listening local socket */ +-static int ctrls_listen(const char *sock_file, int flags) { ++static int ctrls_listen(const char *sock_file) { + int sockfd = -1, len = 0; + struct sockaddr_un sock; + #if !defined(SO_PEERCRED) && !defined(HAVE_GETPEEREID) && \ +@@ -497,12 +494,10 @@ static int ctrls_listen(const char *sock_file, int flags) { + return -1; + } + +- if (flags & CTRLS_LISTEN_FL_REMOVE_SOCKET) { +- /* Make sure the path to which we want to bind this socket doesn't already +- * exist. +- */ +- (void) unlink(sock_file); +- } ++ /* Make sure the path to which we want to bind this socket doesn't already ++ * exist. ++ */ ++ (void) unlink(sock_file); + + /* Fill in the socket structure fields */ + memset(&sock, 0, sizeof(sock)); +@@ -1206,7 +1201,7 @@ static void ctrls_postparse_ev(const void *event_data, void *user_data) { + + /* Start listening on the ctrl socket */ + PRIVS_ROOT +- ctrls_sockfd = ctrls_listen(ctrls_sock_file, CTRLS_LISTEN_FL_REMOVE_SOCKET); ++ ctrls_sockfd = ctrls_listen(ctrls_sock_file); + PRIVS_RELINQUISH + + /* Start a timer for the checking/processing of the ctrl socket. */ +@@ -1298,9 +1293,6 @@ static int ctrls_init(void) { + memset(&ctrls_sock_acl, '\0', sizeof(ctrls_acl_t)); + ctrls_sock_acl.acl_usrs.allow = ctrls_sock_acl.acl_grps.allow = FALSE; + +- /* Start listening on the ctrl socket */ +- ctrls_sockfd = ctrls_listen(ctrls_sock_file, 0); +- + 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.postparse", ctrls_postparse_ev, NULL); diff --git a/1825a2b8.patch b/1825a2b8.patch new file mode 100644 index 0000000..c6cc9b7 --- /dev/null +++ b/1825a2b8.patch @@ -0,0 +1,23 @@ +From ee528a5c6513932c6dbe7cf69fdcda3fbf009621 Mon Sep 17 00:00:00 2001 +From: Paul Howarth +Date: Wed, 19 Apr 2017 15:23:30 +0100 +Subject: [PATCH] fsio: fix test in xattr-copying loop + +Fixes segfaults in fsio file copying tests (Issue #483) +--- + src/fsio.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/fsio.c b/src/fsio.c +index a54c64d..91ad0d7 100644 +--- a/src/fsio.c ++++ b/src/fsio.c +@@ -2063,7 +2063,7 @@ int pr_fs_copy_file2(const char *src, const char *dst, int flags, + const char **names; + + names = xattrs->elts; +- for (i = 0; xattrs->nelts; i++) { ++ for (i = 0; i < xattrs->nelts; i++) { + ssize_t valsz; + + /* First, find out how much memory we need for this attribute's diff --git a/389cc579.patch b/389cc579.patch new file mode 100644 index 0000000..56c61f2 --- /dev/null +++ b/389cc579.patch @@ -0,0 +1,206 @@ +From 389cc579bc8d5704f9dcc2fd01ffd6307aee6b2b Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Mon, 17 Apr 2017 20:01:47 -0700 +Subject: [PATCH] Address some nits in the unit tests, to help make more + repeatable builds on the variety of testing platforms; addresses Issue #483. + +--- + tests/api/data.c | 5 +++-- + tests/api/fsio.c | 28 ++++++++++++++++++++-------- + tests/api/inet.c | 19 ++++++++++--------- + tests/api/pool.c | 7 ++++++- + 4 files changed, 39 insertions(+), 20 deletions(-) + +diff --git a/tests/api/data.c b/tests/api/data.c +index e4442ab..223a3af 100644 +--- a/tests/api/data.c ++++ b/tests/api/data.c +@@ -313,8 +313,9 @@ START_TEST (data_sendfile_test) { + mark_point(); + res = pr_data_sendfile(fd, &offset, strlen(text)); + if (res < 0) { +- fail_unless(errno == ENOTSOCK, "Expected ENOTSOCK (%d), got %s (%d)", +- ENOTSOCK, strerror(errno), errno); ++ fail_unless(errno == ENOTSOCK || errno == EINVAL, ++ "Expected ENOTSOCK (%d) or EINVAL (%d), got %s (%d)", ENOTSOCK, EINVAL, ++ strerror(errno), errno); + } + + (void) close(fd); +diff --git a/tests/api/fsio.c b/tests/api/fsio.c +index 508ca46..4677d8f 100644 +--- a/tests/api/fsio.c ++++ b/tests/api/fsio.c +@@ -34,6 +34,8 @@ static const char *fsio_test2_path = "/tmp/prt-foo.bar.baz.quxx.quzz"; + static const char *fsio_unlink_path = "/tmp/prt-fsio-link.dat"; + static const char *fsio_link_path = "/tmp/prt-fsio-symlink.lnk"; + static const char *fsio_testdir_path = "/tmp/prt-fsio-test.d"; ++static const char *fsio_copy_src_path = "/tmp/prt-fs-src.dat"; ++static const char *fsio_copy_dst_path = "/tmp/prt-fs-dst.dat"; + + /* Fixtures */ + +@@ -1010,8 +1012,12 @@ START_TEST (fsio_sys_access_dir_test) { + strerror(errno)); + + if (getenv("TRAVIS") == NULL) { +- uid_t other_uid = 1000; +- gid_t other_gid = 1000; ++ uid_t other_uid; ++ gid_t other_gid; ++ ++ /* Deliberately use IDs other than the current ones. */ ++ other_uid = uid - 1; ++ other_gid = gid - 1; + + /* Next, check that others can access the directory. */ + pr_fs_clear_cache2(fsio_testdir_path); +@@ -3297,7 +3303,7 @@ END_TEST + + START_TEST (fs_copy_file_test) { + int res; +- char *src_path, *dst_path, *text; ++ char *src_path = NULL, *dst_path = NULL, *text; + pr_fh_t *fh; + + res = pr_fs_copy_file(NULL, NULL); +@@ -3305,15 +3311,15 @@ START_TEST (fs_copy_file_test) { + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); + +- src_path = "/tmp/prt-fs-src.dat"; ++ src_path = fsio_copy_src_path; + res = pr_fs_copy_file(src_path, NULL); + fail_unless(res < 0, "Failed to handle null destination path"); + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); + +- dst_path = "/tmp/prt-fs-dst.dat"; ++ dst_path = fsio_copy_dst_path; + res = pr_fs_copy_file(src_path, dst_path); +- fail_unless(res < 0, "Failed to handle null destination path"); ++ fail_unless(res < 0, "Failed to handle nonexistent source path"); + fail_unless(errno == ENOENT, "Expected ENOENT (%d), got %s (%d)", ENOENT, + strerror(errno), errno); + +@@ -3322,6 +3328,7 @@ START_TEST (fs_copy_file_test) { + fail_unless(errno == EISDIR, "Expected EISDIR (%d), got %s (%d)", EISDIR, + strerror(errno), errno); + ++ (void) unlink(src_path); + fh = pr_fsio_open(src_path, O_CREAT|O_EXCL|O_WRONLY); + fail_unless(fh != NULL, "Failed to open '%s': %s", src_path, strerror(errno)); + +@@ -3347,6 +3354,8 @@ START_TEST (fs_copy_file_test) { + res = pr_fs_copy_file(src_path, src_path); + fail_unless(res == 0, "Failed to copy file to itself: %s", strerror(errno)); + ++ (void) unlink(dst_path); ++ + mark_point(); + res = pr_fs_copy_file(src_path, dst_path); + fail_unless(res == 0, "Failed to copy file: %s", strerror(errno)); +@@ -3366,10 +3375,13 @@ START_TEST (fs_copy_file2_test) { + char *src_path, *dst_path, *text; + pr_fh_t *fh; + +- src_path = "/tmp/prt-fs-src.dat"; +- dst_path = "/tmp/prt-fs-dst.dat"; ++ src_path = fsio_copy_src_path; ++ dst_path = fsio_copy_dst_path; + flags = PR_FSIO_COPY_FILE_FL_NO_DELETE_ON_FAILURE; + ++ (void) unlink(src_path); ++ (void) unlink(dst_path); ++ + fh = pr_fsio_open(src_path, O_CREAT|O_EXCL|O_WRONLY); + fail_unless(fh != NULL, "Failed to open '%s': %s", src_path, strerror(errno)); + +diff --git a/tests/api/inet.c b/tests/api/inet.c +index b75c839..03c4781 100644 +--- a/tests/api/inet.c ++++ b/tests/api/inet.c +@@ -508,7 +508,7 @@ START_TEST (inet_connect_ipv4_test) { + conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE); + fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); + +- res = pr_inet_connect(p, conn, NULL, 80); ++ res = pr_inet_connect(p, conn, NULL, 180); + fail_unless(res < 0, "Failed to handle null address"); + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); +@@ -517,8 +517,8 @@ START_TEST (inet_connect_ipv4_test) { + fail_unless(addr != NULL, "Failed to resolve '127.0.0.1': %s", + strerror(errno)); + +- res = pr_inet_connect(p, conn, addr, 80); +- fail_unless(res < 0, "Connected to 127.0.0.1#80 unexpectedly"); ++ res = pr_inet_connect(p, conn, addr, 180); ++ fail_unless(res < 0, "Connected to 127.0.0.1#180 unexpectedly"); + fail_unless(errno == ECONNREFUSED, "Expected ECONNREFUSED (%d), got %s (%d)", + ECONNREFUSED, strerror(errno), errno); + +@@ -573,8 +573,8 @@ START_TEST (inet_connect_ipv6_test) { + fail_unless(addr != NULL, "Failed to resolve '::1': %s", + strerror(errno)); + +- res = pr_inet_connect(p, conn, addr, 80); +- fail_unless(res < 0, "Connected to ::1#80 unexpectedly"); ++ res = pr_inet_connect(p, conn, addr, 180); ++ fail_unless(res < 0, "Connected to ::1#180 unexpectedly"); + fail_unless(errno == ECONNREFUSED || errno == ENETUNREACH || errno == EADDRNOTAVAIL, + "Expected ECONNREFUSED (%d), ENETUNREACH (%d), or EADDRNOTAVAIL (%d), got %s (%d)", + ECONNREFUSED, ENETUNREACH, EADDRNOTAVAIL, strerror(errno), errno); +@@ -637,7 +637,7 @@ START_TEST (inet_connect_nowait_test) { + conn = pr_inet_create_conn(p, sockfd, NULL, port, FALSE); + fail_unless(conn != NULL, "Failed to create conn: %s", strerror(errno)); + +- res = pr_inet_connect_nowait(p, conn, NULL, 80); ++ res = pr_inet_connect_nowait(p, conn, NULL, 180); + fail_unless(res < 0, "Failed to handle null address"); + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); +@@ -646,8 +646,8 @@ START_TEST (inet_connect_nowait_test) { + fail_unless(addr != NULL, "Failed to resolve '127.0.0.1': %s", + strerror(errno)); + +- res = pr_inet_connect_nowait(p, conn, addr, 80); +- fail_unless(res != -1, "Connected to 127.0.0.1#80 unexpectedly"); ++ res = pr_inet_connect_nowait(p, conn, addr, 180); ++ fail_unless(res != -1, "Connected to 127.0.0.1#180 unexpectedly"); + + /* Try connecting to Google's DNS server. */ + +@@ -657,7 +657,8 @@ START_TEST (inet_connect_nowait_test) { + + res = pr_inet_connect_nowait(p, conn, addr, 53); + if (res < 0 && +- errno != ECONNREFUSED) { ++ errno != ECONNREFUSED && ++ errno != EBADF) { + fail_unless(res != -1, "Failed to connect to 8.8.8.8#53: %s", + strerror(errno)); + } +diff --git a/tests/api/pool.c b/tests/api/pool.c +index 8008f1c..d2f4c0d 100644 +--- a/tests/api/pool.c ++++ b/tests/api/pool.c +@@ -52,12 +52,17 @@ START_TEST (pool_destroy_pool_test) { + p = make_sub_pool(permanent_pool); + destroy_pool(p); + +-#if !defined(PR_USE_DEVEL) + /* What happens if we destroy an already-destroyed pool? Answer: IFF + * --enable-devel was used, THEN destroying an already-destroyed pool + * will result in an exit(2) call from within pool.c, via the + * chk_on_blk_list() function. How impolite. ++ * ++ * And if --enable-devel was NOT used, on SOME systems, this test tickles ++ * other libc/malloc/free behaviors, which are unsettling. ++ * ++ * Sigh. So for now, I'll just leave this here, but commented out. + */ ++#if 0 + mark_point(); + destroy_pool(p); + #endif diff --git a/41ecb7dc.patch b/41ecb7dc.patch new file mode 100644 index 0000000..efdbcea --- /dev/null +++ b/41ecb7dc.patch @@ -0,0 +1,326 @@ +From 41ecb7dc3932dd57bac52980982c76bf036ccfd8 Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Wed, 12 Jul 2017 23:14:59 -0700 +Subject: [PATCH] Bug#4309: Allow SFTP/SCP logins to succeed properly when + "AllowEmptyPasswords off" in effect. + +Also ensure that a truly empty SFTP/SCP password IS properly rejected in such +a configuration. +--- + contrib/mod_sftp/auth-password.c | 41 +++++++- + modules/mod_auth.c | 55 +++++++---- + tests/t/lib/ProFTPD/Tests/Modules/mod_sftp.pm | 132 ++++++++++++++++++++++++++ + 3 files changed, 205 insertions(+), 23 deletions(-) + +diff --git a/contrib/mod_sftp/auth-password.c b/contrib/mod_sftp/auth-password.c +index 2605af7f6..8fb9804bd 100644 +--- a/contrib/mod_sftp/auth-password.c ++++ b/contrib/mod_sftp/auth-password.c +@@ -1,6 +1,6 @@ + /* + * ProFTPD - mod_sftp 'password' user authentication +- * Copyright (c) 2008-2015 TJ Saunders ++ * Copyright (c) 2008-2017 TJ Saunders + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -37,6 +37,7 @@ int sftp_auth_password(struct ssh2_packet *pkt, cmd_rec *pass_cmd, + char *passwd; + int have_new_passwd, res; + struct passwd *pw; ++ size_t passwd_len; + + cipher_algo = sftp_cipher_get_read_algo(); + mac_algo = sftp_mac_get_read_algo(); +@@ -77,6 +78,7 @@ int sftp_auth_password(struct ssh2_packet *pkt, cmd_rec *pass_cmd, + + passwd = sftp_msg_read_string(pkt->pool, buf, buflen); + passwd = sftp_utf8_decode_str(pkt->pool, passwd); ++ passwd_len = strlen(passwd); + + pass_cmd->arg = passwd; + +@@ -92,7 +94,7 @@ int sftp_auth_password(struct ssh2_packet *pkt, cmd_rec *pass_cmd, + pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0); + pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0); + +- pr_memscrub(passwd, strlen(passwd)); ++ pr_memscrub(passwd, passwd_len); + + *send_userauth_fail = TRUE; + errno = EPERM; +@@ -109,15 +111,46 @@ int sftp_auth_password(struct ssh2_packet *pkt, cmd_rec *pass_cmd, + session.c->remote_name, pr_netaddr_get_ipstr(session.c->remote_addr), + pr_netaddr_get_ipstr(session.c->local_addr), session.c->local_port); + +- pr_memscrub(passwd, strlen(passwd)); ++ pr_memscrub(passwd, passwd_len); + + *send_userauth_fail = TRUE; + errno = ENOENT; + return 0; + } + ++ if (passwd_len == 0) { ++ config_rec *c; ++ int allow_empty_passwords = TRUE; ++ ++ c = find_config(main_server->conf, CONF_PARAM, "AllowEmptyPasswords", ++ FALSE); ++ if (c != NULL) { ++ allow_empty_passwords = *((int *) c->argv[0]); ++ } ++ ++ if (allow_empty_passwords == FALSE) { ++ pr_log_debug(DEBUG5, ++ "Refusing empty password from user '%s' (AllowEmptyPasswords false)", ++ user); ++ pr_log_auth(PR_LOG_NOTICE, ++ "Refusing empty password from user '%s'", user); ++ ++ pr_event_generate("mod_auth.empty-password", user); ++ pr_response_add_err(R_501, "Login incorrect."); ++ ++ pr_cmd_dispatch_phase(pass_cmd, POST_CMD_ERR, 0); ++ pr_cmd_dispatch_phase(pass_cmd, LOG_CMD_ERR, 0); ++ ++ pr_memscrub(passwd, passwd_len); ++ ++ *send_userauth_fail = TRUE; ++ errno = EPERM; ++ return 0; ++ } ++ } ++ + res = pr_auth_authenticate(pkt->pool, user, passwd); +- pr_memscrub(passwd, strlen(passwd)); ++ pr_memscrub(passwd, passwd_len); + + switch (res) { + case PR_AUTH_OK: +diff --git a/modules/mod_auth.c b/modules/mod_auth.c +index 2b76070f7..b60cea5a9 100644 +--- a/modules/mod_auth.c ++++ b/modules/mod_auth.c +@@ -2636,35 +2636,52 @@ MODRET auth_pre_pass(cmd_rec *cmd) { + + allow_empty_passwords = *((int *) c->argv[0]); + if (allow_empty_passwords == FALSE) { ++ const char *proto; ++ int reject_empty_passwd = FALSE, using_ssh2 = FALSE; + size_t passwd_len = 0; + ++ proto = pr_session_get_protocol(0); ++ if (strcmp(proto, "ssh2") == 0) { ++ using_ssh2 = TRUE; ++ } ++ + if (cmd->argc > 1) { + if (cmd->arg != NULL) { + passwd_len = strlen(cmd->arg); + } + } + +- /* Make sure to NOT enforce 'AllowEmptyPasswords off' if e.g. +- * the AllowDotLogin TLSOption is in effect. +- */ +- if (cmd->argc == 1 || +- passwd_len == 0) { +- +- if (session.auth_mech == NULL || +- strcmp(session.auth_mech, "mod_tls.c") != 0) { +- pr_log_debug(DEBUG5, +- "Refusing empty password from user '%s' (AllowEmptyPasswords " +- "false)", user); +- pr_log_auth(PR_LOG_NOTICE, +- "Refusing empty password from user '%s'", user); +- +- pr_event_generate("mod_auth.empty-password", user); +- pr_response_add_err(R_501, _("Login incorrect.")); +- return PR_ERROR(cmd); ++ if (passwd_len == 0) { ++ reject_empty_passwd = TRUE; ++ ++ /* Make sure to NOT enforce 'AllowEmptyPasswords off' if e.g. ++ * the AllowDotLogin TLSOption is in effect, or if the protocol is ++ * SSH2 (for mod_sftp uses "fake" PASS commands for the SSH login ++ * protocol). ++ */ ++ ++ if (session.auth_mech != NULL && ++ strcmp(session.auth_mech, "mod_tls.c") == 0) { ++ pr_log_debug(DEBUG9, "%s", "'AllowEmptyPasswords off' in effect, " ++ "BUT client authenticated via the AllowDotLogin TLSOption"); ++ reject_empty_passwd = FALSE; + } + +- pr_log_debug(DEBUG9, "%s", "'AllowEmptyPasswords off' in effect, " +- "BUT client authenticated via the AllowDotLogin TLSOption"); ++ if (using_ssh2 == TRUE) { ++ reject_empty_passwd = FALSE; ++ } ++ } ++ ++ if (reject_empty_passwd == TRUE) { ++ pr_log_debug(DEBUG5, ++ "Refusing empty password from user '%s' (AllowEmptyPasswords " ++ "false)", user); ++ pr_log_auth(PR_LOG_NOTICE, ++ "Refusing empty password from user '%s'", user); ++ ++ pr_event_generate("mod_auth.empty-password", user); ++ pr_response_add_err(R_501, _("Login incorrect.")); ++ return PR_ERROR(cmd); + } + } + } +diff --git a/tests/t/lib/ProFTPD/Tests/Modules/mod_sftp.pm b/tests/t/lib/ProFTPD/Tests/Modules/mod_sftp.pm +index c919844ea..c608e76fc 100644 +--- a/tests/t/lib/ProFTPD/Tests/Modules/mod_sftp.pm ++++ b/tests/t/lib/ProFTPD/Tests/Modules/mod_sftp.pm +@@ -1279,6 +1279,11 @@ my $TESTS = { + test_class => [qw(bug forking sftp ssh2)], + }, + ++ sftp_config_allow_empty_passwords_off_bug4309 => { ++ order => ++$order, ++ test_class => [qw(bug forking sftp ssh2)], ++ }, ++ + sftp_multi_channels => { + order => ++$order, + test_class => [qw(forking sftp ssh2)], +@@ -41885,6 +41890,133 @@ sub sftp_config_insecure_hostkey_perms_bug4098 { + test_cleanup($setup->{log_file}, $ex); + } + ++sub sftp_config_allow_empty_passwords_off_bug4309 { ++ my $self = shift; ++ my $tmpdir = $self->{tmpdir}; ++ my $setup = test_setup($tmpdir, 'sftp'); ++ ++ my $other_user = 'nopassword'; ++ my $other_passwd = ''; ++ my $other_uid = 1000; ++ my $other_gid = 1000; ++ ++ auth_user_write($setup->{auth_user_file}, $other_user, $other_passwd, ++ $other_uid, $other_gid, $setup->{home_dir}, '/bin/bash'); ++ auth_group_write($setup->{auth_group_file}, $setup->{group}, $setup->{gid}, ++ $other_user); ++ ++ my $rsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_rsa_key'); ++ my $dsa_host_key = File::Spec->rel2abs('t/etc/modules/mod_sftp/ssh_host_dsa_key'); ++ ++ my $config = { ++ PidFile => $setup->{pid_file}, ++ ScoreboardFile => $setup->{scoreboard_file}, ++ SystemLog => $setup->{log_file}, ++ TraceLog => $setup->{log_file}, ++ Trace => 'DEFAULT:10 ssh2:20 sftp:20', ++ ++ AuthUserFile => $setup->{auth_user_file}, ++ AuthGroupFile => $setup->{auth_group_file}, ++ ++ IfModules => { ++ 'mod_delay.c' => { ++ DelayEngine => 'off', ++ }, ++ ++ 'mod_sftp.c' => [ ++ "SFTPEngine on", ++ "SFTPLog $setup->{log_file}", ++ "SFTPHostKey $rsa_host_key", ++ "SFTPHostKey $dsa_host_key", ++ "AllowEmptyPasswords off", ++ ], ++ }, ++ }; ++ ++ my ($port, $config_user, $config_group) = config_write($setup->{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: $!"); ++ } ++ ++ require Net::SSH2; ++ ++ my $ex; ++ ++ # Fork child ++ $self->handle_sigchld(); ++ defined(my $pid = fork()) or die("Can't fork: $!"); ++ if ($pid) { ++ eval { ++ my $ssh2 = Net::SSH2->new(); ++ ++ sleep(1); ++ ++ # First, we'll try to login with normal user/password; this should ++ # succeed. ++ unless ($ssh2->connect('127.0.0.1', $port)) { ++ my ($err_code, $err_name, $err_str) = $ssh2->error(); ++ die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str"); ++ } ++ ++ unless ($ssh2->auth_password($setup->{user}, $setup->{passwd})) { ++ my ($err_code, $err_name, $err_str) = $ssh2->error(); ++ die("Can't login to SSH2 server: [$err_name] ($err_code) $err_str"); ++ } ++ ++ my $sftp = $ssh2->sftp(); ++ unless ($sftp) { ++ my ($err_code, $err_name, $err_str) = $ssh2->error(); ++ die("Can't use SFTP on SSH2 server: [$err_name] ($err_code) $err_str"); ++ } ++ ++ $sftp = undef; ++ $ssh2->disconnect(); ++ $ssh2 = undef; ++ ++ # Then, we'll try to login with an empty password; this should fail. ++ ++ $ssh2 = Net::SSH2->new(); ++ unless ($ssh2->connect('127.0.0.1', $port)) { ++ my ($err_code, $err_name, $err_str) = $ssh2->error(); ++ die("Can't connect to SSH2 server: [$err_name] ($err_code) $err_str"); ++ } ++ ++ if ($ssh2->auth_password($other_user, $other_passwd)) { ++ die("Login with empty password succeeded unexpectedly"); ++ } ++ ++ $ssh2->disconnect(); ++ }; ++ if ($@) { ++ $ex = $@; ++ } ++ ++ $wfh->print("done\n"); ++ $wfh->flush(); ++ ++ } else { ++ eval { server_wait($setup->{config_file}, $rfh) }; ++ if ($@) { ++ warn($@); ++ exit 1; ++ } ++ ++ exit 0; ++ } ++ ++ # Stop server ++ server_stop($setup->{pid_file}); ++ $self->assert_child_ok($pid); ++ ++ test_cleanup($setup->{log_file}, $ex); ++} ++ + sub sftp_multi_channel_downloads { + my $self = shift; + my $tmpdir = $self->{tmpdir}; diff --git a/459693c7.patch b/459693c7.patch new file mode 100644 index 0000000..2dbb55f --- /dev/null +++ b/459693c7.patch @@ -0,0 +1,31 @@ +From 459693c70c83b7d173ec10bb8089d4ce4e59d301 Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Tue, 2 May 2017 19:56:39 -0700 +Subject: [PATCH] Bug#4306: AllowChrootSymlinks off could cause login failures + depending on filesystem permissions. + +Use the IDs of the logging-in user to perform the directory walk, looking +for symlinks, to be more consistent with similar checks done during login. +--- + modules/mod_auth.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/modules/mod_auth.c b/modules/mod_auth.c +index d93c630..2b76070 100644 +--- a/modules/mod_auth.c ++++ b/modules/mod_auth.c +@@ -936,9 +936,13 @@ static int get_default_root(pool *p, int allow_symlinks, const char **root) { + path[pathlen-1] = '\0'; + } + ++ PRIVS_USER + res = is_symlink_path(p, path, pathlen); ++ xerrno = errno; ++ PRIVS_RELINQUISH ++ + if (res < 0) { +- if (errno == EPERM) { ++ if (xerrno == EPERM) { + pr_log_pri(PR_LOG_WARNING, "error: DefaultRoot %s is a symlink " + "(denied by AllowChrootSymlinks config)", path); + } diff --git a/6cc96b5f.patch b/6cc96b5f.patch new file mode 100644 index 0000000..9529c31 --- /dev/null +++ b/6cc96b5f.patch @@ -0,0 +1,37 @@ +From 48012e5ab7969fc77d0724769b1e737343ed654d Mon Sep 17 00:00:00 2001 +From: Paul Howarth +Date: Wed, 10 May 2017 10:10:40 +0100 +Subject: [PATCH] Switch to Type = simple and add configuration test + +Upstream recommends Type = simple if possible rather than Type = forking: +http://0pointer.de/public/systemd-man/daemon.html#Integration%20with%20Systemd + +Also add configuration test prior to starting the daemon, to help diagnose +start-up problems. +--- + contrib/dist/rpm/proftpd.service | 9 ++++----- + 1 file changed, 4 insertions(+), 5 deletions(-) + +diff --git a/contrib/dist/rpm/proftpd.service b/contrib/dist/rpm/proftpd.service +index 07802ca..8a4df33 100644 +--- a/contrib/dist/rpm/proftpd.service ++++ b/contrib/dist/rpm/proftpd.service +@@ -3,14 +3,13 @@ Description = ProFTPD FTP Server + After = network.target nss-lookup.target local-fs.target remote-fs.target + + [Service] +-Type = forking +-PIDFile = /run/proftpd/proftpd.pid ++Type = simple + Environment = PROFTPD_OPTIONS= + EnvironmentFile = -/etc/sysconfig/proftpd +-ExecStart = /usr/sbin/proftpd $PROFTPD_OPTIONS +-ExecStartPost = /usr/bin/touch /var/lock/subsys/proftpd +-ExecStopPost = /bin/rm -f /var/lock/subsys/proftpd ++ExecStartPre = /usr/sbin/proftpd --configtest ++ExecStart = /usr/sbin/proftpd --nodaemon $PROFTPD_OPTIONS + ExecReload = /bin/kill -HUP $MAINPID ++PIDFile = /run/proftpd/proftpd.pid + + [Install] + WantedBy = multi-user.target diff --git a/73887e02.patch b/73887e02.patch new file mode 100644 index 0000000..9b29991 --- /dev/null +++ b/73887e02.patch @@ -0,0 +1,66 @@ +From 73887e02dbcc9e6e94b26f30c3ef89acb8016f2d Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Sun, 21 May 2017 13:25:50 -0700 +Subject: [PATCH] Merge pull request #510 from pghmcfc/32-bit-fixes + +32 bit fixes +--- + src/trace.c | 16 ++++++++++++++++ + tests/api/misc.c | 2 +- + 2 files changed, 17 insertions(+), 1 deletion(-) + +diff --git a/src/trace.c b/src/trace.c +index 1c29cc6bf..dc22e9e89 100644 +--- a/src/trace.c ++++ b/src/trace.c +@@ -273,7 +273,13 @@ int pr_trace_parse_levels(char *str, int *min_level, int *max_level) { + ptr = strchr(str, '-'); + if (ptr == NULL) { + /* Just a single value. */ ++ errno = 0; + high = (int) strtol(str, &ptr, 10); ++ if (errno == ERANGE) { ++ errno = EINVAL; ++ return -1; ++ } ++ + if (ptr && *ptr) { + errno = EINVAL; + return -1; +@@ -302,6 +308,11 @@ int pr_trace_parse_levels(char *str, int *min_level, int *max_level) { + *ptr = '\0'; + + low = (int) strtol(str, &tmp, 10); ++ if (errno == ERANGE) { ++ errno = EINVAL; ++ return -1; ++ } ++ + if (tmp && *tmp) { + *ptr = '-'; + errno = EINVAL; +@@ -316,6 +327,11 @@ int pr_trace_parse_levels(char *str, int *min_level, int *max_level) { + + tmp = NULL; + high = (int) strtol(ptr + 1, &tmp, 10); ++ if (errno == ERANGE) { ++ errno = EINVAL; ++ return -1; ++ } ++ + if (tmp && *tmp) { + errno = EINVAL; + return -1; +diff --git a/tests/api/misc.c b/tests/api/misc.c +index 16d56cb71..926d9b3e3 100644 +--- a/tests/api/misc.c ++++ b/tests/api/misc.c +@@ -702,7 +702,7 @@ START_TEST (check_shutmsg_test) { + + (void) unlink(path); + res = write_shutmsg(path, +- "2340 1 1 0 0 0 0000 0000\nGoodbye, cruel world!\n"); ++ "2037 1 1 0 0 0 0000 0000\nGoodbye, cruel world!\n"); + fail_unless(res == 0, "Failed to write '%s': %s", path, strerror(errno)); + + mark_point(); diff --git a/757b9633.patch b/757b9633.patch new file mode 100644 index 0000000..22f57c4 --- /dev/null +++ b/757b9633.patch @@ -0,0 +1,119 @@ +From 757b9633191eafa32a86ab8ec032e743d0227093 Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Wed, 5 Jul 2017 23:33:16 -0700 +Subject: [PATCH] Bug#4308: When authorizing a user, check for any shadow + information for that user, and use such information as part of the + authorization check. + +--- + modules/mod_auth_unix.c | 67 +++++++++++++++++++++++++++++++++++++++---------- + 1 file changed, 54 insertions(+), 13 deletions(-) + +diff --git a/modules/mod_auth_unix.c b/modules/mod_auth_unix.c +index 788b4c549..7d7a994d7 100644 +--- a/modules/mod_auth_unix.c ++++ b/modules/mod_auth_unix.c +@@ -715,34 +715,40 @@ static char *get_pwd_info(pool *p, const char *u, time_t *lstchg, time_t *min, + MODRET pw_auth(cmd_rec *cmd) { + int res; + time_t now; +- char *cpw; +- time_t lstchg = -1, max = -1, inact = -1, disable = -1; ++ char *cleartxt_passwd; ++ time_t lstchg = -1, max = -1, inact = -1, expire = -1; + const char *name; ++ size_t cleartxt_passwdlen; + + name = cmd->argv[0]; +- time(&now); + +- cpw = get_pwd_info(cmd->tmp_pool, name, &lstchg, NULL, &max, NULL, &inact, +- &disable); +- if (cpw == NULL) { ++ cleartxt_passwd = get_pwd_info(cmd->tmp_pool, name, &lstchg, NULL, &max, ++ NULL, &inact, &expire); ++ if (cleartxt_passwd == NULL) { + return PR_DECLINED(cmd); + } + +- res = pr_auth_check(cmd->tmp_pool, cpw, cmd->argv[0], cmd->argv[1]); ++ res = pr_auth_check(cmd->tmp_pool, cleartxt_passwd, cmd->argv[0], ++ cmd->argv[1]); ++ cleartxt_passwdlen = strlen(cleartxt_passwd); ++ pr_memscrub(cleartxt_passwd, cleartxt_passwdlen); ++ + if (res < PR_AUTH_OK) { + return PR_ERROR_INT(cmd, res); + } + ++ time(&now); ++ + if (lstchg > (time_t) 0 && + max > (time_t) 0 && + inact > (time_t) 0) { +- if (now > lstchg + max + inact) { ++ if (now > (lstchg + max + inact)) { + return PR_ERROR_INT(cmd, PR_AUTH_AGEPWD); + } + } + +- if (disable > (time_t) 0 && +- now > disable) { ++ if (expire > (time_t) 0 && ++ now > expire) { + return PR_ERROR_INT(cmd, PR_AUTH_DISABLEDPWD); + } + +@@ -751,14 +757,49 @@ MODRET pw_auth(cmd_rec *cmd) { + } + + MODRET pw_authz(cmd_rec *cmd) { ++ time_t now; ++ char *user, *cleartxt_passwd; ++ time_t lstchg = -1, max = -1, inact = -1, expire = -1; ++ size_t cleartxt_passwdlen; ++ ++ user = cmd->argv[0]; ++ ++ cleartxt_passwd = get_pwd_info(cmd->tmp_pool, user, &lstchg, NULL, &max, ++ NULL, &inact, &expire); ++ if (cleartxt_passwd == NULL) { ++ pr_log_auth(LOG_WARNING, "no password information found for user '%.100s'", ++ user); ++ return PR_ERROR_INT(cmd, PR_AUTH_NOPWD); ++ } ++ ++ cleartxt_passwdlen = strlen(cleartxt_passwd); ++ pr_memscrub(cleartxt_passwd, cleartxt_passwdlen); ++ ++ time(&now); ++ ++ if (lstchg > (time_t) 0 && ++ max > (time_t) 0 && ++ inact > (time_t) 0) { ++ if (now > (lstchg + max + inact)) { ++ pr_log_auth(LOG_WARNING, ++ "account for user '%.100s' disabled due to inactivity", user); ++ return PR_ERROR_INT(cmd, PR_AUTH_AGEPWD); ++ } ++ } ++ ++ if (expire > (time_t) 0 && ++ now > expire) { ++ pr_log_auth(LOG_WARNING, ++ "account for user '%.100s' disabled due to password expiration", user); ++ return PR_ERROR_INT(cmd, PR_AUTH_DISABLEDPWD); ++ } ++ + /* XXX Any other implementations here? */ + + #ifdef HAVE_LOGINRESTRICTIONS + if (!(auth_unix_opts & AUTH_UNIX_OPT_AIX_NO_RLOGIN)) { + int res, xerrno, code = 0; +- char *user = NULL, *reason = NULL; +- +- user = cmd->argv[0]; ++ char *reason = NULL; + + /* Check for account login restrictions and such using AIX-specific + * functions. diff --git a/7907aa65.patch b/7907aa65.patch new file mode 100644 index 0000000..7ff1f2e --- /dev/null +++ b/7907aa65.patch @@ -0,0 +1,47 @@ +From 925ee5b8f636ab2fd5a3e02af79ba49f54a85b8d Mon Sep 17 00:00:00 2001 +From: Paul Howarth +Date: Fri, 5 May 2017 15:38:59 +0100 +Subject: [PATCH] Don't touch TLSCipherSuite when using system profiles + +Fedora and possibly other Linux distributions support system-wide +crypto policies to enable sane defaults to be specified in an ever +changing world of different cipher recommendations. In order to use +such a policy, OpenSSL users just set their cipher selection to +"PROFILE=SYSTEM", and the system-wide policy will be selected +(which can itself be set to various values, for best compatibility, +best strength, a compromise of the two, etc.). + +See: +https://fedoraproject.org/wiki/Packaging:CryptoPolicies +https://fedoraproject.org/wiki/Changes/CryptoPolicy + +The "PROFILE=SYSTEM" string cannot be used in conjunction with other +cipher selections, so prepending it with "!EXPORT:" results in: + +mod_tls/2.7[xxxxx]: unable to accept TLS connection: client does not support +any cipher from 'TLSCipherSuite !EXPORT:PROFILE=SYSTEM' (see `openssl ciphers +!EXPORT:PROFILE=SYSTEM` for full list) + +Hence, do not touch the supplied TLSCipherSuite if it starts with "PROFILE=". +--- + contrib/mod_tls.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/contrib/mod_tls.c b/contrib/mod_tls.c +index 3ff8ee2..c38ecac 100644 +--- a/contrib/mod_tls.c ++++ b/contrib/mod_tls.c +@@ -11985,7 +11985,12 @@ MODRET set_tlsciphersuite(cmd_rec *cmd) { + c = add_config_param(cmd->argv[0], 1, NULL); + + /* Make sure that EXPORT ciphers cannot be used, per Bug#4163. */ +- ciphersuite = pstrcat(c->pool, "!EXPORT:", ciphersuite, NULL); ++ /* This breaks system profiles though, so don't change them. */ ++ if (strncmp(ciphersuite, "PROFILE=", 8) == 0) { ++ ciphersuite = pstrdup(c->pool, ciphersuite); ++ } else { ++ ciphersuite = pstrcat(c->pool, "!EXPORT:", ciphersuite, NULL); ++ } + + /* Check that our construct ciphersuite is acceptable. */ + ctx = SSL_CTX_new(SSLv23_server_method()); diff --git a/8a186e2d.patch b/8a186e2d.patch new file mode 100644 index 0000000..28d9b29 --- /dev/null +++ b/8a186e2d.patch @@ -0,0 +1,147 @@ +From 2f563aa12cf1ed199671821e2fba7088ab36b681 Mon Sep 17 00:00:00 2001 +From: Paul Howarth +Date: Thu, 18 May 2017 15:38:46 +0100 +Subject: [PATCH] Use /etc/hosts rather than /etc/resolv.conf in fsio unit + tests + +The fsio unit tests require a read-only system file to test that +files can be read, can't be written or deleted etc. The file +/etc/resolv.conf is currently used for this, but does not exist +in the minimum build environment used on Fedora's koji build +servers, resulting in test failures. Using /etc/hosts, which does +exist there and should be equally ubiquitous, fixes this issue. +--- + tests/api/fsio.c | 40 ++++++++++++++++++++-------------------- + 1 file changed, 20 insertions(+), 20 deletions(-) + +diff --git a/tests/api/fsio.c b/tests/api/fsio.c +index bacd306..3cb1741 100644 +--- a/tests/api/fsio.c ++++ b/tests/api/fsio.c +@@ -119,8 +119,8 @@ START_TEST (fsio_sys_open_test) { + + mark_point(); + flags = O_RDONLY; +- fh = pr_fsio_open("/etc/resolv.conf", flags); +- fail_unless(fh != NULL, "Failed to /etc/resolv.conf: %s", strerror(errno)); ++ fh = pr_fsio_open("/etc/hosts", flags); ++ fail_unless(fh != NULL, "Failed to open /etc/hosts: %s", strerror(errno)); + + (void) pr_fsio_close(fh); + } +@@ -144,8 +144,8 @@ START_TEST (fsio_sys_open_canon_test) { + strerror(errno), errno); + + flags = O_RDONLY; +- fh = pr_fsio_open_canon("/etc/resolv.conf", flags); +- fail_unless(fh != NULL, "Failed to /etc/resolv.conf: %s", strerror(errno)); ++ fh = pr_fsio_open_canon("/etc/hosts", flags); ++ fail_unless(fh != NULL, "Failed to open /etc/hosts: %s", strerror(errno)); + + (void) pr_fsio_close(fh); + } +@@ -159,7 +159,7 @@ START_TEST (fsio_sys_open_chroot_guard_test) { + res = pr_fsio_guard_chroot(TRUE); + fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res); + +- path = "/etc/resolv.conf"; ++ path = "/etc/hosts"; + flags = O_CREAT|O_RDONLY; + fh = pr_fsio_open(path, flags); + if (fh != NULL) { +@@ -203,7 +203,7 @@ START_TEST (fsio_sys_open_chroot_guard_test) { + + (void) pr_fsio_guard_chroot(FALSE); + +- path = "/etc/resolv.conf"; ++ path = "/etc/hosts"; + flags = O_RDONLY; + fh = pr_fsio_open(path, flags); + fail_unless(fh != NULL, "Failed to open '%s': %s", path, strerror(errno)); +@@ -220,8 +220,8 @@ START_TEST (fsio_sys_close_test) { + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s %d", EINVAL, + strerror(errno), errno); + +- fh = pr_fsio_open("/etc/resolv.conf", O_RDONLY); +- fail_unless(fh != NULL, "Failed to open /etc/resolv.conf: %s", ++ fh = pr_fsio_open("/etc/hosts", O_RDONLY); ++ fail_unless(fh != NULL, "Failed to open /etc/hosts: %s", + strerror(errno)); + + res = pr_fsio_close(fh); +@@ -265,8 +265,8 @@ START_TEST (fsio_sys_unlink_chroot_guard_test) { + res = pr_fsio_guard_chroot(TRUE); + fail_unless(res == FALSE, "Expected FALSE (%d), got %d", FALSE, res); + +- res = pr_fsio_unlink("/etc/resolv.conf"); +- fail_unless(res < 0, "Deleted /etc/resolv.conf unexpectedly"); ++ res = pr_fsio_unlink("/etc/hosts"); ++ fail_unless(res < 0, "Deleted /etc/hosts unexpectedly"); + fail_unless(errno == EACCES, "Expected EACCES (%d), got %s %d", EACCES, + strerror(errno), errno); + +@@ -352,12 +352,12 @@ START_TEST (fsio_sys_fstat_test) { + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); + +- fh = pr_fsio_open("/etc/resolv.conf", O_RDONLY); +- fail_unless(fh != NULL, "Failed to open /etc/resolv.conf: %s", ++ fh = pr_fsio_open("/etc/hosts", O_RDONLY); ++ fail_unless(fh != NULL, "Failed to open /etc/hosts: %s", + strerror(errno)); + + res = pr_fsio_fstat(fh, &st); +- fail_unless(res == 0, "Failed to fstat /etc/resolv.conf: %s", ++ fail_unless(res == 0, "Failed to fstat /etc/hosts: %s", + strerror(errno)); + (void) pr_fsio_close(fh); + } +@@ -374,8 +374,8 @@ START_TEST (fsio_sys_read_test) { + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); + +- fh = pr_fsio_open("/etc/resolv.conf", O_RDONLY); +- fail_unless(fh != NULL, "Failed to open /etc/resolv.conf: %s", ++ fh = pr_fsio_open("/etc/hosts", O_RDONLY); ++ fail_unless(fh != NULL, "Failed to open /etc/hosts: %s", + strerror(errno)); + + res = pr_fsio_read(fh, NULL, 0); +@@ -443,8 +443,8 @@ START_TEST (fsio_sys_lseek_test) { + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); + +- fh = pr_fsio_open("/etc/resolv.conf", O_RDONLY); +- fail_unless(fh != NULL, "Failed to open /etc/resolv.conf: %s", ++ fh = pr_fsio_open("/etc/hosts", O_RDONLY); ++ fail_unless(fh != NULL, "Failed to open /etc/hosts: %s", + strerror(errno)); + + res = pr_fsio_lseek(fh, 0, 0); +@@ -2083,7 +2083,7 @@ START_TEST (fsio_sys_chdir_test) { + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); + +- res = pr_fsio_chdir("/etc/resolv.conf", FALSE); ++ res = pr_fsio_chdir("/etc/hosts", FALSE); + fail_unless(res < 0, "Failed to handle file argument"); + fail_unless(errno == EINVAL || errno == ENOTDIR, + "Expected EINVAL (%d) or ENOTDIR (%d), got %s (%d)", EINVAL, ENOTDIR, +@@ -2145,7 +2145,7 @@ START_TEST (fsio_sys_opendir_test) { + strerror(errno), errno); + + mark_point(); +- path = "/etc/resolv.conf"; ++ path = "/etc/hosts"; + res = pr_fsio_opendir(path); + fail_unless(res == NULL, "Failed to handle file argument"); + fail_unless(errno == ENOTDIR, "Expected ENOTDIR (%d), got %s (%d)", ENOTDIR, +@@ -2175,7 +2175,7 @@ START_TEST (fsio_sys_readdir_test) { + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); + +- dent = pr_fsio_readdir("/etc/resolv.conf"); ++ dent = pr_fsio_readdir("/etc/hosts"); + fail_unless(dent == NULL, "Failed to handle file argument"); + fail_unless(errno == ENOTDIR, "Expected ENOTDIR (%d), got %s (%d)", ENOTDIR, + strerror(errno), errno); diff --git a/a2c02a6b.patch b/a2c02a6b.patch new file mode 100644 index 0000000..042fb43 --- /dev/null +++ b/a2c02a6b.patch @@ -0,0 +1,58 @@ +From a2c02a6baf555fea10ea0bccdcc4e632fb9d4711 Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Sun, 27 May 2018 16:11:24 -0700 +Subject: [PATCH] Issue #674: Update mod_sftp to handle changed APIs in OpenSSL + 1.1.x releases. + +--- + contrib/mod_sftp/keys.c | 10 +++++----- + 1 file changed, 5 insertions(+), 5 deletions(-) + +diff --git a/contrib/mod_sftp/keys.c b/contrib/mod_sftp/keys.c +index 19bf8edf5..191dbabb9 100644 +--- a/contrib/mod_sftp/keys.c ++++ b/contrib/mod_sftp/keys.c +@@ -1,6 +1,6 @@ + /* + * ProFTPD - mod_sftp key mgmt (keys) +- * Copyright (c) 2008-2017 TJ Saunders ++ * Copyright (c) 2008-2018 TJ Saunders + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -2780,7 +2780,7 @@ static const unsigned char *dsa_sign_data(pool *p, const unsigned char *data, + + #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(HAVE_LIBRESSL) +- DSA_SIG_get0(&sig_r, &sig_s, sig); ++ DSA_SIG_get0(sig, &sig_r, &sig_s); + #else + sig_r = sig->r; + sig_s = sig->s; +@@ -2960,7 +2960,7 @@ static const unsigned char *ecdsa_sign_data(pool *p, const unsigned char *data, + + #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(HAVE_LIBRESSL) +- ECDSA_SIG_get0(&sig_r, &sig_s, sig); ++ ECDSA_SIG_get0(sig, &sig_r, &sig_s); + #else + sig_r = sig->r; + sig_s = sig->s; +@@ -3307,7 +3307,7 @@ int sftp_keys_verify_signed_data(pool *p, const char *pubkey_algo, + dsa_sig = DSA_SIG_new(); + #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(HAVE_LIBRESSL) +- DSA_SIG_get0(&sig_r, &sig_s, dsa_sig); ++ DSA_SIG_get0(sig, &sig_r, &sig_s); + #else + sig_r = dsa_sig->r; + sig_s = dsa_sig->s; +@@ -3426,7 +3426,7 @@ int sftp_keys_verify_signed_data(pool *p, const char *pubkey_algo, + + #if OPENSSL_VERSION_NUMBER >= 0x10100000L && \ + !defined(HAVE_LIBRESSL) +- ECDSA_SIG_get0(&sig_r, &sig_s, ecdsa_sig); ++ ECDSA_SIG_get0(ecdsa_sig, &sig_r, &sig_s); + #else + sig_r = ecdsa_sig->r; + sig_s = ecdsa_sig->s; diff --git a/aa85f127.patch b/aa85f127.patch new file mode 100644 index 0000000..73db308 --- /dev/null +++ b/aa85f127.patch @@ -0,0 +1,159 @@ +From aa85f127d31346a28c619ee426090f1f23fd2249 Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Fri, 5 May 2017 09:24:10 -0700 +Subject: [PATCH] Improve detection of badly configured ciphersuites (e.g. + unsupported/misspelled cipher suites) at startup time. + +--- + contrib/mod_tls.c | 21 +++++++++++- + doc/contrib/mod_tls.html | 21 +++++++++++- + tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm | 50 ++++++++++++++++++++++++++++ + 3 files changed, 90 insertions(+), 2 deletions(-) + +diff --git a/contrib/mod_tls.c b/contrib/mod_tls.c +index 7a2a74f..3ff8ee2 100644 +--- a/contrib/mod_tls.c ++++ b/contrib/mod_tls.c +@@ -11976,6 +11976,7 @@ MODRET set_tlscertchain(cmd_rec *cmd) { + MODRET set_tlsciphersuite(cmd_rec *cmd) { + config_rec *c = NULL; + char *ciphersuite = NULL; ++ SSL_CTX *ctx; + + CHECK_ARGS(cmd, 1); + CHECK_CONF(cmd, CONF_ROOT|CONF_VIRTUAL|CONF_GLOBAL); +@@ -11984,8 +11985,26 @@ MODRET set_tlsciphersuite(cmd_rec *cmd) { + c = add_config_param(cmd->argv[0], 1, NULL); + + /* Make sure that EXPORT ciphers cannot be used, per Bug#4163. */ +- c->argv[0] = pstrcat(c->pool, "!EXPORT:", ciphersuite, NULL); ++ ciphersuite = pstrcat(c->pool, "!EXPORT:", ciphersuite, NULL); ++ ++ /* Check that our construct ciphersuite is acceptable. */ ++ ctx = SSL_CTX_new(SSLv23_server_method()); ++ if (ctx != NULL) { ++ if (SSL_CTX_set_cipher_list(ctx, ciphersuite) != 1) { ++ /* Note: tls_get_errors() relies on session.pool, so temporarily set ++ * it to our temporary pool. ++ */ ++ session.pool = cmd->tmp_pool; ++ ++ CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, ++ "unable to use configured TLSCipherSuite '", ciphersuite, "': ", ++ tls_get_errors(), NULL)); ++ } ++ ++ SSL_CTX_free(ctx); ++ } + ++ c->argv[0] = ciphersuite; + return PR_HANDLED(cmd); + } + +diff --git a/doc/contrib/mod_tls.html b/doc/contrib/mod_tls.html +index c1d3f2d..cc88946 100644 +--- a/doc/contrib/mod_tls.html ++++ b/doc/contrib/mod_tls.html +@@ -295,7 +295,13 @@ + Compatibility: 1.2.7rc1 and later + +

+-Default cipher list is "DEFAULT:!ADH:!EXPORT:!DES". ++Sets the list of SSL/TLS ciphersuites for use. Default cipher list is ++"DEFAULT:!ADH:!EXPORT:!DES". ++ ++

++Note that mod_tls will automatically prepend the ++configured cipher-list with "!EXPORT", in order to prevent the ++use of the insecure "export grade" ciphers. + +

+ How to put together a cipher list parameter: +@@ -2215,6 +2221,19 @@ + TLSDHParamFile /path/to/dh1024.pem + + ++

++Question: I tried to configure a specific ciphersuite ++using TLSCipherSuite, but ProFTPD fails on startup with this error: ++

++  fatal: TLSCipherSuite: unable to use configured TLSCipherSuite '!EXPORT:MYCIPHER':
++  (1) error:1410D0B9:SSL routines:SSL_CTX_set_cipher_list:no cipher match on line 16 of '/etc/proftpd/tls.conf'
++
++Answer: This error indicates that the version of OpenSSL ++does not recognize/support one of the ciphers that you configured in your ++TLSCipherSuite list. Unfortunately the OpenSSL error reporting ++does not pinpoint which is the offending ciphersuite; experimenting ++with your cipher list will reveal which ones are problematic. ++ +

+


+

Installation

+diff --git a/tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm b/tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm +index f7cd171..226d47c 100644 +--- a/tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm ++++ b/tests/t/lib/ProFTPD/Tests/Modules/mod_tls.pm +@@ -299,6 +299,11 @@ my $TESTS = { + test_class => [qw(bug forking)], + }, + ++ tls_config_tlsciphersuite_bad_cipher => { ++ order => ++$order, ++ test_class => [qw(forking)], ++ }, ++ + tls_session_cache_off_bug3869 => { + order => ++$order, + test_class => [qw(bug forking)], +@@ -8983,6 +8988,51 @@ sub tls_config_tlsdhparamfile_bug3868 { + unlink($log_file); + } + ++sub tls_config_tlsciphersuite_bad_cipher { ++ my $self = shift; ++ my $tmpdir = $self->{tmpdir}; ++ my $setup = test_setup($tmpdir, 'tls'); ++ ++ my $cert_file = File::Spec->rel2abs('t/etc/modules/mod_tls/server-cert.pem'); ++ my $ca_file = File::Spec->rel2abs('t/etc/modules/mod_tls/ca-cert.pem'); ++ ++ my $config = { ++ PidFile => $setup->{pid_file}, ++ ScoreboardFile => $setup->{scoreboard_file}, ++ SystemLog => $setup->{log_file}, ++ ++ IfModules => { ++ 'mod_delay.c' => { ++ DelayEngine => 'off', ++ }, ++ ++ 'mod_tls.c' => { ++ TLSEngine => 'on', ++ TLSLog => $setup->{log_file}, ++ TLSRSACertificateFile => $cert_file, ++ TLSCACertificateFile => $ca_file, ++ TLSCipherSuite => 'FOOBAR', ++ }, ++ }, ++ }; ++ ++ my ($port, $config_user, $config_group) = config_write($setup->{config_file}, ++ $config); ++ ++ my $ex; ++ ++ # This should silently fail. ++ server_start($setup->{config_file}); ++ ++ # This is where we detect the actual problem. ++ eval { server_stop($setup->{pid_file}) }; ++ unless ($@) { ++ $ex = "Server start with bad config unexpectedly"; ++ } ++ ++ test_cleanup($setup->{log_file}, $ex); ++} ++ + sub tls_session_cache_off_bug3869 { + my $self = shift; + my $tmpdir = $self->{tmpdir}; diff --git a/ad786eaa.patch b/ad786eaa.patch new file mode 100644 index 0000000..7e5dd2e --- /dev/null +++ b/ad786eaa.patch @@ -0,0 +1,23 @@ +From ad786eaa8a232795470dbeab2380dc8d8ac803af Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Fri, 27 Oct 2017 09:28:19 -0700 +Subject: [PATCH] Merge pull request #617 from pghmcfc/systemd-network-online + +systemd: use network-online.target +--- + contrib/dist/rpm/proftpd.service | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/contrib/dist/rpm/proftpd.service b/contrib/dist/rpm/proftpd.service +index 8a4df33c9..6c81db398 100644 +--- a/contrib/dist/rpm/proftpd.service ++++ b/contrib/dist/rpm/proftpd.service +@@ -1,6 +1,7 @@ + [Unit] + Description = ProFTPD FTP Server +-After = network.target nss-lookup.target local-fs.target remote-fs.target ++Wants=network-online.target ++After=network-online.target nss-lookup.target local-fs.target remote-fs.target + + [Service] + Type = simple diff --git a/adfdc01d.patch b/adfdc01d.patch new file mode 100644 index 0000000..afb5851 --- /dev/null +++ b/adfdc01d.patch @@ -0,0 +1,25 @@ +From 84549ece3a839161794deee1721fc0cf9bf9eb9c Mon Sep 17 00:00:00 2001 +From: Paul Howarth +Date: Mon, 8 May 2017 10:16:32 +0100 +Subject: [PATCH] Use absolute pathnames for executables in systemd unit files + +Otherwise, systemd complains about them and ignores the commands. +--- + contrib/dist/rpm/proftpd.service | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/contrib/dist/rpm/proftpd.service b/contrib/dist/rpm/proftpd.service +index c2fd401..07802ca 100644 +--- a/contrib/dist/rpm/proftpd.service ++++ b/contrib/dist/rpm/proftpd.service +@@ -8,8 +8,8 @@ PIDFile = /run/proftpd/proftpd.pid + Environment = PROFTPD_OPTIONS= + EnvironmentFile = -/etc/sysconfig/proftpd + ExecStart = /usr/sbin/proftpd $PROFTPD_OPTIONS +-ExecStartPost = touch /var/lock/subsys/proftpd +-ExecStopPost = rm -f /var/lock/subsys/proftpd ++ExecStartPost = /usr/bin/touch /var/lock/subsys/proftpd ++ExecStopPost = /bin/rm -f /var/lock/subsys/proftpd + ExecReload = /bin/kill -HUP $MAINPID + + [Install] diff --git a/c3e5d75f.patch b/c3e5d75f.patch new file mode 100644 index 0000000..faf9ef6 --- /dev/null +++ b/c3e5d75f.patch @@ -0,0 +1,97 @@ +From c3e5d75f9c8a60af42646319fcca832d5f1a55d4 Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Sun, 21 May 2017 13:44:23 -0700 +Subject: [PATCH] Merge pull request #513 from pghmcfc/similars + +Fix pr_str_get_similars +--- + src/str.c | 4 ++-- + tests/api/str.c | 36 +++++++++++++++++++----------------- + 2 files changed, 21 insertions(+), 19 deletions(-) + +diff --git a/src/str.c b/src/str.c +index eeed096ef..0a59f2379 100644 +--- a/src/str.c ++++ b/src/str.c +@@ -725,11 +725,11 @@ static int distance_cmp(const void *a, const void *b) { + const char *s1, *s2; + int distance1, distance2; + +- cand1 = a; ++ cand1 = * (const struct candidate **) a; + s1 = cand1->s; + distance1 = cand1->distance; + +- cand2 = b; ++ cand2 = * (const struct candidate **) b; + s2 = cand2->s; + distance2 = cand2->distance; + +diff --git a/tests/api/str.c b/tests/api/str.c +index 7c6e11000..9dce95820 100644 +--- a/tests/api/str.c ++++ b/tests/api/str.c +@@ -1469,25 +1469,23 @@ START_TEST (similars_test) { + mark_point(); + similars = (const char **) res->elts; + +- /* Note: We see different results here due to (I think) different +- * qsort(3) implementations. ++ /* ++ * Note: expected distances are as follows: ++ * ++ * Candidate Case-Sensitive Case-Insensitive ++ * fools 0 0 ++ * odd 5 5 ++ * bar 5 5 ++ * FOO 5 0 + */ + +- expected = "FOO"; +- if (strcmp(similars[0], expected) != 0) { +- expected = "fools"; +- } ++ expected = "fools"; + + fail_unless(strcmp(similars[0], expected) == 0, + "Expected similar '%s', got '%s'", expected, similars[0]); + +- expected = "fools"; +- if (strcmp(similars[1], expected) != 0) { +- expected = "FOO"; +- } +- +- fail_unless(strcmp(similars[1], expected) == 0, +- "Expected similar '%s', got '%s'", expected, similars[1]); ++ fail_unless(strcmp(similars[1], expected) != 0, ++ "Unexpectedly got similar '%s'", similars[1]); + + mark_point(); + res = pr_str_get_similars(p, s, candidates, 0, PR_STR_FL_IGNORE_CASE); +@@ -1499,18 +1497,22 @@ START_TEST (similars_test) { + mark_point(); + similars = (const char **) res->elts; + ++ /* ++ * similars[0] and similars[1] should be "FOO" and "fools", but ++ * not necessarily in that order ++ */ + expected = "FOO"; + if (strcmp(similars[0], expected) != 0) { +- expected = "fools"; ++ expected = similars[0]; ++ similars[0] = similars[1]; ++ similars[1] = expected; ++ expected = "FOO"; + } + + fail_unless(strcmp(similars[0], expected) == 0, + "Expected similar '%s', got '%s'", expected, similars[0]); + + expected = "fools"; +- if (strcmp(similars[1], expected) != 0) { +- expected = "FOO"; +- } + + fail_unless(strcmp(similars[1], expected) == 0, + "Expected similar '%s', got '%s'", expected, similars[1]); diff --git a/fa378a8f.patch b/fa378a8f.patch new file mode 100644 index 0000000..ddfb05e --- /dev/null +++ b/fa378a8f.patch @@ -0,0 +1,31 @@ +From fa378a8f2bc1b24ab93c157495960080aa788299 Mon Sep 17 00:00:00 2001 +From: TJ Saunders +Date: Wed, 8 Aug 2018 11:15:21 -0700 +Subject: [PATCH] Bug#4356: Fix infinite loop by actually iterating properly + for the next configuration record. Oops. + +--- + contrib/mod_sftp/mod_sftp.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/contrib/mod_sftp/mod_sftp.c b/contrib/mod_sftp/mod_sftp.c +index b7fdfa541..655b12af1 100644 +--- a/contrib/mod_sftp/mod_sftp.c ++++ b/contrib/mod_sftp/mod_sftp.c +@@ -1,6 +1,6 @@ + /* + * ProFTPD - mod_sftp +- * Copyright (c) 2008-2017 TJ Saunders ++ * Copyright (c) 2008-2018 TJ Saunders + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by +@@ -1211,6 +1211,8 @@ MODRET set_sftphostkey(cmd_rec *cmd) { + insecure_hostkey_perms = TRUE; + break; + } ++ ++ c = find_config_next(c, c->next, CONF_PARAM, "SFTPOptions", FALSE); + } + + if (insecure_hostkey_perms) { diff --git a/proftpd-1.3.4rc1-mod_vroot-test.patch b/proftpd-1.3.4rc1-mod_vroot-test.patch new file mode 100644 index 0000000..e2314cc --- /dev/null +++ b/proftpd-1.3.4rc1-mod_vroot-test.patch @@ -0,0 +1,14 @@ +--- proftpd-1.3.4rc1/tests/tests.pl 2010-12-15 00:57:04.000000000 +0000 ++++ proftpd-1.3.4rc1/tests/tests.pl 2011-01-11 09:22:57.746669659 +0000 +@@ -283,6 +283,11 @@ + test_class => [qw(mod_unique_id)], + }, + ++ 't/modules/mod_vroot.t' => { ++ order => ++$order, ++ test_class => [qw(mod_vroot)], ++ }, ++ + 't/modules/mod_wrap.t' => { + order => ++$order, + test_class => [qw(mod_wrap)], diff --git a/proftpd-1.3.6-ENOATTR.patch b/proftpd-1.3.6-ENOATTR.patch new file mode 100644 index 0000000..18e3bf7 --- /dev/null +++ b/proftpd-1.3.6-ENOATTR.patch @@ -0,0 +1,15 @@ +--- proftpd-1.3.6/tests/api/fsio.c ++++ proftpd-1.3.6/tests/api/fsio.c +@@ -26,6 +26,12 @@ + + #include "tests.h" + ++#ifdef PR_USE_XATTR ++#ifndef ENOATTR ++# define ENOATTR ENODATA ++#endif ++#endif ++ + static pool *p = NULL; + + static char *fsio_cwd = NULL; diff --git a/proftpd-1.3.6-add-enable-tests-nonetwork-option.patch b/proftpd-1.3.6-add-enable-tests-nonetwork-option.patch new file mode 100644 index 0000000..b98eb42 --- /dev/null +++ b/proftpd-1.3.6-add-enable-tests-nonetwork-option.patch @@ -0,0 +1,187 @@ +From 49ef73f7193242eac07de27c2e853d9e805162ec Mon Sep 17 00:00:00 2001 +From: Paul Howarth +Date: Wed, 3 May 2017 11:57:23 +0100 +Subject: [PATCH] Add --enable-tests=nonetwork option + +This disables API tests that involve resolving/connecting to external +network services such as Google, which may not be possible in some +build environments. + +Tested using systemd-nspawn --private-network +--- + config.h.in | 3 +++ + configure.in | 5 ++++- + tests/api/inet.c | 6 ++++++ + tests/api/netaddr.c | 6 ++++++ + 4 files changed, 19 insertions(+), 1 deletion(-) + +diff --git a/config.h.in b/config.h.in +index a38734a..229c9db 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -1068,6 +1068,9 @@ + /* Define if ncursesw support, if available, should be used. */ + #undef PR_USE_NCURSESW + ++/* Define if non-local network tests are enabled. */ ++#undef PR_USE_NETWORK_TESTS ++ + /* Define if using nonblocking open of log files. */ + #undef PR_USE_NONBLOCKING_LOG_OPEN + +diff --git a/configure.in b/configure.in +index 1e39c37..dba39ba 100644 +--- a/configure.in ++++ b/configure.in +@@ -985,7 +985,7 @@ AC_ARG_ENABLE(tests, + [--enable-tests], + [enable unit tests (default=no)]) + ], +- [ if test x"$enableval" = x"yes" ; then ++ [ if test x"$enableval" = x"yes" || test x"$enableval" = x"nonetwork" ; then + AC_CHECK_HEADERS(check.h) + + AC_CHECK_LIB(check, tcase_create, +@@ -997,6 +997,9 @@ AC_ARG_ENABLE(tests, + AC_MSG_ERROR([libcheck support, required for tests, not present -- aborting]) + ] + ) ++ if test x"$enableval" != x"nonetwork" ; then ++ AC_DEFINE(PR_USE_NETWORK_TESTS, 1, [Define if non-local network tests are enabled.]) ++ fi + fi + ]) + +diff -up a/configure b/configure +--- a/configure ++++ b/configure +@@ -20423,7 +20423,7 @@ fi + ENABLE_TESTS="\"\"" + # Check whether --enable-tests was given. + if test "${enable_tests+set}" = set; then +- enableval=$enable_tests; if test x"$enableval" = x"yes" ; then ++ enableval=$enable_tests; if test x"$enableval" = x"yes" || test x"$enableval" = x"nonetwork" ; then + + for ac_header in check.h + do +@@ -20648,6 +20648,13 @@ echo "$as_me: error: libcheck support, r + + fi + ++ if test x"$enableval" != x"nonetwork" ; then ++ ++cat >>confdefs.h <<\_ACEOF ++#define PR_USE_NETWORK_TESTS 1 ++_ACEOF ++ ++ fi + fi + + fi +diff --git a/tests/api/inet.c b/tests/api/inet.c +index 03c4781..c111629 100644 +--- a/tests/api/inet.c ++++ b/tests/api/inet.c +@@ -522,6 +522,7 @@ START_TEST (inet_connect_ipv4_test) { + fail_unless(errno == ECONNREFUSED, "Expected ECONNREFUSED (%d), got %s (%d)", + ECONNREFUSED, strerror(errno), errno); + ++#if defined(PR_USE_NETWORK_TESTS) + /* Try connecting to Google's DNS server. */ + + addr = pr_netaddr_get_addr(p, "8.8.8.8", NULL); +@@ -551,6 +552,7 @@ START_TEST (inet_connect_ipv4_test) { + fail_unless(errno == EISCONN, "Expected EISCONN (%d), got %s (%d)", + EISCONN, strerror(errno), errno); + pr_inet_close(p, conn); ++#endif + } + END_TEST + +@@ -579,6 +581,7 @@ START_TEST (inet_connect_ipv6_test) { + "Expected ECONNREFUSED (%d), ENETUNREACH (%d), or EADDRNOTAVAIL (%d), got %s (%d)", + ECONNREFUSED, ENETUNREACH, EADDRNOTAVAIL, strerror(errno), errno); + ++#if defined(PR_USE_NETWORK_TESTS) + /* Try connecting to Google's DNS server. */ + + addr = pr_netaddr_get_addr(p, "2001:4860:4860::8888", NULL); +@@ -614,6 +617,7 @@ START_TEST (inet_connect_ipv6_test) { + fail_unless(errno == EISCONN || errno == EHOSTUNREACH || errno == ENETUNREACH || errno == EADDRNOTAVAIL, + "Expected EISCONN (%d) or EHOSTUNREACH (%d) or ENETUNREACH (%d) or EADDRNOTAVAIL (%d), got %s (%d)", EISCONN, EHOSTUNREACH, ENETUNREACH, EADDRNOTAVAIL, strerror(errno), errno); + pr_inet_close(p, conn); ++#endif + + pr_inet_set_default_family(p, AF_INET); + +@@ -649,6 +653,7 @@ START_TEST (inet_connect_nowait_test) { + res = pr_inet_connect_nowait(p, conn, addr, 180); + fail_unless(res != -1, "Connected to 127.0.0.1#180 unexpectedly"); + ++#if defined(PR_USE_NETWORK_TESTS) + /* Try connecting to Google's DNS server. */ + + addr = pr_netaddr_get_addr(p, "8.8.8.8", NULL); +@@ -664,6 +669,7 @@ START_TEST (inet_connect_nowait_test) { + } + + pr_inet_close(p, conn); ++#endif + + /* Restore the default family to AF_INET, for other tests. */ + pr_inet_set_default_family(p, AF_INET); +diff --git a/tests/api/netaddr.c b/tests/api/netaddr.c +index 80d3327..124dc39 100644 +--- a/tests/api/netaddr.c ++++ b/tests/api/netaddr.c +@@ -146,6 +146,7 @@ START_TEST (netaddr_get_addr_test) { + fail_unless(res->na_family == AF_INET, "Expected family %d, got %d", + AF_INET, res->na_family); + ++#if defined(PR_USE_NETWORK_TESTS) + /* Google: the Dial Tone of the Internet. */ + name = "www.google.com"; + +@@ -161,6 +162,7 @@ START_TEST (netaddr_get_addr_test) { + strerror(errno)); + fail_unless(res->na_family == AF_INET, "Expected family %d, got %d", + AF_INET, res->na_family); ++#endif + + name = "127.0.0.1"; + +@@ -903,6 +905,7 @@ START_TEST (netaddr_get_dnsstr_list_test) { + + pr_netaddr_clear_cache(); + ++#if defined(PR_USE_NETWORK_TESTS) + addr = pr_netaddr_get_addr(p, "www.google.com", &addrs); + fail_unless(addr != NULL, "Failed to resolve 'www.google.com': %s", + strerror(errno)); +@@ -921,6 +924,7 @@ START_TEST (netaddr_get_dnsstr_list_test) { + /* Ideally we would check that res->nelts > 0, BUT this turns out to + * a fragile test condition, dependent on DNS vagaries. + */ ++#endif + + pr_netaddr_set_reverse_dns(reverse_dns); + } +@@ -1082,6 +1086,7 @@ START_TEST (netaddr_is_loopback_test) { + fail_unless(errno == EINVAL, "Expected EINVAL (%d), got %s (%d)", EINVAL, + strerror(errno), errno); + ++#if defined(PR_USE_NETWORK_TESTS) + name = "www.google.com"; + addr = pr_netaddr_get_addr(p, name, NULL); + fail_unless(addr != NULL, "Failed to resolve '%s': %s", name, +@@ -1089,6 +1094,7 @@ START_TEST (netaddr_is_loopback_test) { + + res = pr_netaddr_is_loopback(addr); + fail_unless(res == FALSE, "Expected FALSE, got %d", res); ++#endif + + name = "127.0.0.1"; + addr = pr_netaddr_get_addr(p, name, NULL); +-- +2.9.3 + diff --git a/proftpd-1.3.6-shellbang.patch b/proftpd-1.3.6-shellbang.patch new file mode 100644 index 0000000..63e5b64 --- /dev/null +++ b/proftpd-1.3.6-shellbang.patch @@ -0,0 +1,40 @@ +--- contrib/ftpasswd ++++ contrib/ftpasswd +@@ -1,4 +1,4 @@ +-#!/usr/bin/env perl ++#!/usr/bin/perl + # --------------------------------------------------------------------------- + # Copyright (C) 2000-2015 TJ Saunders + # +--- contrib/ftpmail ++++ contrib/ftpmail +@@ -1,4 +1,4 @@ +-#!/usr/bin/env perl ++#!/usr/bin/perl + # --------------------------------------------------------------------------- + # Copyright (C) 2008-2013 TJ Saunders + # +--- contrib/ftpquota ++++ contrib/ftpquota +@@ -1,4 +1,4 @@ +-#!/usr/bin/env perl ++#!/usr/bin/perl + # ------------------------------------------------------------------------- + # Copyright (C) 2000-2017 TJ Saunders + # +--- contrib/xferstats.holger-preiss ++++ contrib/xferstats.holger-preiss +@@ -1,4 +1,4 @@ +-#!/usr/bin/env perl ++#!/usr/bin/perl + # --------------------------------------------------------------------------- + # + # USAGE: xferstats +--- src/prxs.in ++++ src/prxs.in +@@ -1,4 +1,4 @@ +-#!/usr/bin/env perl ++#!/usr/bin/perl + + # --------------------------------------------------------------------------- + # Copyright (C) 2008-2012 TJ Saunders diff --git a/proftpd-welcome.msg b/proftpd-welcome.msg new file mode 100644 index 0000000..8210b52 --- /dev/null +++ b/proftpd-welcome.msg @@ -0,0 +1,8 @@ + + *** Welcome to this anonymous ftp server! *** + + You are user %N out of a maximum of %M authorized anonymous logins. + The current time here is %T. + If you experience any problems here, contact : %E + + diff --git a/proftpd.conf b/proftpd.conf new file mode 100644 index 0000000..0e1230d --- /dev/null +++ b/proftpd.conf @@ -0,0 +1,431 @@ +# This is the ProFTPD configuration file +# +# 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 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. +# On older systems this boolean was called allow_ftpd_anon_write. +# +# setsebool -P ftpd_full_access=1 +# This allows the ftp daemon to read and write all files on the system. +# On older systems this boolean was called allow_ftpd_full_access, and there +# was a separate boolean ftp_home_dir to allow the ftp daemon access to +# files in users' home directories. +# +# setsebool -P ftpd_use_cifs=1 +# This allows the ftp daemon to read and write files on CIFS-mounted +# filesystems. +# On older systems this boolean was called allow_ftpd_use_cifs. +# +# setsebool -P ftpd_use_fusefs=1 +# This allows the ftp daemon to read and write files on ntfs/fusefs-mounted +# filesystems. +# +# setsebool -P ftpd_use_nfs=1 +# This allows the ftp daemon to read and write files on NFS-mounted +# filesystems. +# On older systems this boolean was called allow_ftpd_use_nfs. +# +# 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_use_passive_mode=1 +# This setting allows the ftp daemon to bind to all unreserved ports for +# passive mode. +# +# 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 or 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@localhost +DefaultServer on + +# Cause every FTP user except adm to be chrooted into their home directory +DefaultRoot ~ !adm + +# Use pam to authenticate (default) and be authoritative +AuthPAMConfig proftpd +AuthOrder mod_auth_pam.c* mod_auth_unix.c +# If you use NIS/YP/LDAP you may need to disable PersistentPasswd +#PersistentPasswd off + +# Don't do reverse DNS lookups (hangs on DNS problems) +UseReverseDNS off + +# Set the user and group that the server runs as +User nobody +Group nobody + +# To prevent DoS attacks, set the maximum number of child processes +# to 20. If you need to allow more than 20 concurrent connections +# at once, simply increase this value. Note that this ONLY works +# in standalone mode; in inetd mode you should use an inetd server +# that allows you to limit maximum number of processes per service +# (such as xinetd) +MaxInstances 20 + +# Disable sendfile by default since it breaks displaying the download speeds in +# ftptop and ftpwho +UseSendfile off + +# Define the log formats +LogFormat default "%h %l %u %t \"%r\" %s %b" +LogFormat auth "%v [%P] %h %t \"%r\" %s" + +# Dynamic Shared Object (DSO) loading +# See README.DSO and howto/DSO.html for more details +# +# General database support (http://www.proftpd.org/docs/contrib/mod_sql.html) +# LoadModule mod_sql.c +# +# Support for base-64 or hex encoded MD5 and SHA1 passwords from SQL tables +# (contrib/mod_sql_passwd.html) +# LoadModule mod_sql_passwd.c +# +# Mysql support (requires proftpd-mysql package) +# (http://www.proftpd.org/docs/contrib/mod_sql.html) +# LoadModule mod_sql_mysql.c +# +# Postgresql support (requires proftpd-postgresql package) +# (http://www.proftpd.org/docs/contrib/mod_sql.html) +# LoadModule mod_sql_postgres.c +# +# SQLite support (requires proftpd-sqlite package) +# (http://www.proftpd.org/docs/contrib/mod_sql.html, +# http://www.proftpd.org/docs/contrib/mod_sql_sqlite.html) +# LoadModule mod_sql_sqlite.c +# +# Quota support (http://www.proftpd.org/docs/contrib/mod_quotatab.html) +# LoadModule mod_quotatab.c +# +# File-specific "driver" for storing quota table information in files +# (http://www.proftpd.org/docs/contrib/mod_quotatab_file.html) +# LoadModule mod_quotatab_file.c +# +# SQL database "driver" for storing quota table information in SQL tables +# (http://www.proftpd.org/docs/contrib/mod_quotatab_sql.html) +# LoadModule mod_quotatab_sql.c +# +# LDAP support (requires proftpd-ldap package) +# (http://www.proftpd.org/docs/directives/linked/config_ref_mod_ldap.html) +# LoadModule mod_ldap.c +# +# LDAP quota support (requires proftpd-ldap package) +# (http://www.proftpd.org/docs/contrib/mod_quotatab_ldap.html) +# LoadModule mod_quotatab_ldap.c +# +# Support for authenticating users using the RADIUS protocol +# (http://www.proftpd.org/docs/contrib/mod_radius.html) +# LoadModule mod_radius.c +# +# Retrieve quota limit table information from a RADIUS server +# (http://www.proftpd.org/docs/contrib/mod_quotatab_radius.html) +# LoadModule mod_quotatab_radius.c +# +# SITE CPFR and SITE CPTO commands (analogous to RNFR and RNTO), which can be +# used to copy files/directories from one place to another on the server +# without having to transfer the data to the client and back +# (http://www.castaglia.org/proftpd/modules/mod_copy.html) +# LoadModule mod_copy.c +# +# Administrative control actions for the ftpdctl program +# (http://www.proftpd.org/docs/contrib/mod_ctrls_admin.html) +LoadModule mod_ctrls_admin.c +# +# Support for MODE Z commands, which allows FTP clients and servers to +# compress data for transfer +# (http://www.castaglia.org/proftpd/modules/mod_deflate.html) +# LoadModule mod_deflate.c +# +# Execute external programs or scripts at various points in the process +# of handling FTP commands +# (http://www.castaglia.org/proftpd/modules/mod_exec.html) +# LoadModule mod_exec.c +# +# Support for POSIX ACLs +# (http://www.proftpd.org/docs/modules/mod_facl.html) +# LoadModule mod_facl.c +# +# Support for using the GeoIP library to look up geographical information on +# the connecting client and using that to set access controls for the server +# (http://www.castaglia.org/proftpd/modules/mod_geoip.html) +# LoadModule mod_geoip.c +# +# Allow for version-specific configuration sections of the proftpd config file, +# useful for using the same proftpd config across multiple servers where +# different proftpd versions may be in use +# (http://www.castaglia.org/proftpd/modules/mod_ifversion.html) +# LoadModule mod_ifversion.c +# +# Configure server availability based on system load +# (http://www.proftpd.org/docs/contrib/mod_load.html) +# LoadModule mod_load.c +# +# Limit downloads to a multiple of upload volume (see README.ratio) +# LoadModule mod_ratio.c +# +# Rewrite FTP commands sent by clients on-the-fly, +# using regular expression matching and substitution +# (http://www.proftpd.org/docs/contrib/mod_rewrite.html) +# LoadModule mod_rewrite.c +# +# Support for the SSH2, SFTP, and SCP protocols, for secure file transfer over +# an SSH2 connection (http://www.castaglia.org/proftpd/modules/mod_sftp.html) +# LoadModule mod_sftp.c +# +# Use PAM to provide a 'keyboard-interactive' SSH2 authentication method for +# mod_sftp (http://www.castaglia.org/proftpd/modules/mod_sftp_pam.html) +# LoadModule mod_sftp_pam.c +# +# Use SQL (via mod_sql) for looking up authorized SSH2 public keys for user +# and host based authentication +# (http://www.castaglia.org/proftpd/modules/mod_sftp_sql.html) +# LoadModule mod_sftp_sql.c +# +# Provide data transfer rate "shaping" across the entire server +# (http://www.castaglia.org/proftpd/modules/mod_shaper.html) +# LoadModule mod_shaper.c +# +# Support for miscellaneous SITE commands such as SITE MKDIR, SITE SYMLINK, +# and SITE UTIME (http://www.proftpd.org/docs/contrib/mod_site_misc.html) +# LoadModule mod_site_misc.c +# +# Provide an external SSL session cache using shared memory +# (contrib/mod_tls_shmcache.html) +# LoadModule mod_tls_shmcache.c +# +# Provide a memcached-based implementation of an external SSL session cache +# (contrib/mod_tls_memcache.html) +# LoadModule mod_tls_memcache.c +# +# Use the /etc/hosts.allow and /etc/hosts.deny files, or other allow/deny +# files, for IP-based access control +# (http://www.proftpd.org/docs/contrib/mod_wrap.html) +# LoadModule mod_wrap.c +# +# Use the /etc/hosts.allow and /etc/hosts.deny files, or other allow/deny +# files, as well as SQL-based access rules, for IP-based access control +# (http://www.proftpd.org/docs/contrib/mod_wrap2.html) +# LoadModule mod_wrap2.c +# +# Support module for mod_wrap2 that handles access rules stored in specially +# formatted files on disk +# (http://www.proftpd.org/docs/contrib/mod_wrap2_file.html) +# LoadModule mod_wrap2_file.c +# +# Support module for mod_wrap2 that handles access rules stored in SQL +# database tables (http://www.proftpd.org/docs/contrib/mod_wrap2_sql.html) +# LoadModule mod_wrap2_sql.c +# +# Implement a virtual chroot capability that does not require root privileges +# (http://www.castaglia.org/proftpd/modules/mod_vroot.html) +# Using this module rather than the kernel's chroot() system call works +# around issues with PAM and chroot (http://bugzilla.redhat.com/506735) +LoadModule mod_vroot.c +# +# Provide a flexible way of specifying that certain configuration directives +# only apply to certain sessions, based on credentials such as connection +# class, user, or group membership +# (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) + + AdminControlsEngine on + AdminControlsACLs all allow user root + + +# Enable mod_vroot by default for better compatibility with PAM +# (http://bugzilla.redhat.com/506735) + + VRootEngine on + + +# TLS (http://www.castaglia.org/proftpd/modules/mod_tls.html) + + TLSEngine on + TLSRequired off + TLSCertificateChainFile /etc/pki/tls/certs/proftpd-chain.pem + TLSRSACertificateFile /etc/pki/tls/certs/proftpd-cert.pem + TLSRSACertificateKeyFile /etc/pki/tls/private/proftpd-key.pem + TLSCipherSuite PROFILE=SYSTEM + # Relax the requirement that the SSL session be re-used for data transfers + TLSOptions NoSessionReuseRequired + TLSLog /var/log/proftpd/tls.log + + TLSSessionCache shm:/file=/var/run/proftpd/sesscache + + + +# Dynamic ban lists (http://www.proftpd.org/docs/contrib/mod_ban.html) +# Enable this with PROFTPD_OPTIONS=-DDYNAMIC_BAN_LISTS in /etc/sysconfig/proftpd + + LoadModule mod_ban.c + BanEngine on + BanLog /var/log/proftpd/ban.log + BanTable /var/run/proftpd/ban.tab + + # If the same client reaches the MaxLoginAttempts limit 2 times + # within 10 minutes, automatically add a ban for that client that + # will expire after one hour. + BanOnEvent MaxLoginAttempts 2/00:10:00 01:00:00 + + # Inform the user that it's not worth persisting + BanMessage "Host %a has been banned" + + # Allow the FTP admin to manually add/remove bans + BanControlsACLs all allow user ftpadm + + +# Set networking-specific "Quality of Service" (QoS) bits on the packets used +# by the server (contrib/mod_qos.html) + + LoadModule mod_qos.c + # RFC791 TOS parameter compatibility + QoSOptions dataqos throughput ctrlqos lowdelay + # For a DSCP environment (may require tweaking) + #QoSOptions dataqos CS2 ctrlqos AF41 + + +# Global Config - config common to Server Config and all virtual hosts +# See: http://www.proftpd.org/docs/howto/Vhost.html + + + # Umask 022 is a good standard umask to prevent new dirs and files + # from being group and world writable + Umask 022 + + # Allow users to overwrite files and change permissions + AllowOverwrite yes + + AllowAll + + + + +# A basic anonymous configuration, with an upload directory +# Enable this with PROFTPD_OPTIONS=-DANONYMOUS_FTP in /etc/sysconfig/proftpd + + + User ftp + Group ftp + AccessGrantMsg "Anonymous login ok, restrictions apply." + + # We want clients to be able to login with "anonymous" as well as "ftp" + UserAlias anonymous ftp + + # Limit the maximum number of anonymous logins + MaxClients 10 "Sorry, max %m users -- try again later" + + # Put the user into /pub right after login + #DefaultChdir /pub + + # We want 'welcome.msg' displayed at login, '.message' displayed in + # each newly chdired directory and tell users to read README* files. + DisplayLogin /welcome.msg + DisplayChdir .message + DisplayReadme README* + + # Cosmetic option to make all files appear to be owned by user "ftp" + DirFakeUser on ftp + DirFakeGroup on ftp + + # Limit WRITE everywhere in the anonymous chroot + + DenyAll + + + # An upload directory that allows storing files but not retrieving + # or creating directories. + # + # Directory specification is slightly different if mod_vroot is in + # use: see http://sourceforge.net/p/proftp/mailman/message/31728570/ + # https://bugzilla.redhat.com/show_bug.cgi?id=1045922 + + + AllowOverwrite no + + DenyAll + + + + AllowAll + + + + + + AllowOverwrite no + + DenyAll + + + + AllowAll + + + + + # Don't write anonymous accesses to the system wtmp file (good idea!) + WtmpLog off + + # Logging for the anonymous transfers + ExtendedLog /var/log/proftpd/access.log WRITE,READ default + ExtendedLog /var/log/proftpd/auth.log AUTH auth + + + + diff --git a/proftpd.conf-no-memcached.patch b/proftpd.conf-no-memcached.patch new file mode 100644 index 0000000..8ef6703 --- /dev/null +++ b/proftpd.conf-no-memcached.patch @@ -0,0 +1,13 @@ +--- proftpd.conf 2011-04-05 11:59:10.491108239 +0100 ++++ proftpd.conf 2010-12-23 15:19:13.667374844 +0000 +@@ -167,10 +167,6 @@ + # (contrib/mod_tls_shmcache.html) + # LoadModule mod_tls_shmcache.c + # +-# Provide a memcached-based implementation of an external SSL session cache +-# (contrib/mod_tls_memcache.html) +-# LoadModule mod_tls_memcache.c +-# + # Use the /etc/hosts.allow and /etc/hosts.deny files, or other allow/deny + # files, for IP-based access control + # (http://www.proftpd.org/docs/contrib/mod_wrap.html) diff --git a/proftpd.spec b/proftpd.spec new file mode 100644 index 0000000..40f444d --- /dev/null +++ b/proftpd.spec @@ -0,0 +1,452 @@ +%global use_systemd 1 +%global rundir /run +%global rundir_tmpfs 1 +%global systemd_units systemd +%global preset_support 1 +%global mysql_lib mariadb +%global mysql_devel_pkg mariadb-connector-c-devel +%global postgresql_devel_pkg libpq-devel +%global _hardened_build 1 +%undefine _strict_symbol_defs_build +%global rpmrel 20 +%global mod_vroot_version 0.9.5 + +Name: proftpd +Version: 1.3.6 +Release: 1 +Summary: Flexible, stable and highly-configurable FTP server +License: GPLv2+ +URL: https://github.com/proftpd/proftpd +Source0: https://github.com/proftpd/proftpd/archive/v%{version}.tar.gz +Source1: proftpd.conf +Source5: proftpd-welcome.msg +Source9: proftpd.sysconfig +Source10: http://github.com/Castaglia/proftpd-mod_vroot/archive/v%{mod_vroot_version}.tar.gz +Patch1: proftpd-1.3.6-shellbang.patch +Patch2: proftpd.conf-no-memcached.patch +Patch3: proftpd-1.3.4rc1-mod_vroot-test.patch +# https://github.com/proftpd/proftpd/commit/459693c7.patch +Patch100: 459693c7.patch +# https://github.com/proftpd/proftpd/commit/389cc579.patch +Patch101: 389cc579.patch +# https://github.com/proftpd/proftpd/commit/1825a2b8.patch +Patch102: 1825a2b8.patch +# https://github.com/proftpd/proftpd/commit/73887e02.patch +Patch103: 73887e02.patch +# https://github.com/proftpd/proftpd/commit/8a186e2d.patch +Patch104: 8a186e2d.patch +# https://github.com/proftpd/proftpd/commit/c3e5d75f.patch +Patch105: c3e5d75f.patch +Patch106: proftpd-1.3.6-add-enable-tests-nonetwork-option.patch +# https://github.com/proftpd/proftpd/commit/adfdc01d.patch +Patch107: adfdc01d.patch +# https://github.com/proftpd/proftpd/commit/6cc96b5f.patch +Patch108: 6cc96b5f.patch +# https://github.com/proftpd/proftpd/commit/aa85f127.patch +Patch109: aa85f127.patch +# https://github.com/proftpd/proftpd/commit/7907aa65.patch +Patch110: 7907aa65.patch +# https://github.com/proftpd/proftpd/commit/08ba2f63.patch +Patch111: 08ba2f63.patch +# https://github.com/proftpd/proftpd/commit/757b9633.patch +Patch112: 757b9633.patch +# https://github.com/proftpd/proftpd/commit/41ecb7dc.patch +Patch113: 41ecb7dc.patch +# https://github.com/proftpd/proftpd/commit/ad786eaa.patch +Patch114: ad786eaa.patch +# https://github.com/proftpd/proftpd/commit/a2c02a6b.patch +Patch115: a2c02a6b.patch +Patch116: proftpd-1.3.6-ENOATTR.patch +# https://github.com/proftpd/proftpd/commit/fa378a8f.patch +Patch117: fa378a8f.patch +BuildRequires: coreutils gcc GeoIP-devel gettext libacl-devel libcap-devel +%if 0%{?have_libmemcached:1} +BuildRequires: libmemcached-devel >= 0.41 +%endif +BuildRequires: %{mysql_devel_pkg} ncurses-devel openldap-devel openssl-devel +BuildRequires: pam-devel pcre-devel >= 7.0 perl-generators +BuildRequires: perl-interpreter +BuildRequires: pkgconfig %{postgresql_devel_pkg} sqlite-devel tar +%if 0%{?libwrap_support:1} +BuildRequires: tcp_wrappers-devel +%endif +BuildRequires: zlib-devel +BuildRequires: check-devel +%if 0%{?_with_integrationtests:1} +BuildRequires: perl(Compress::Zlib) perl(Digest::MD5) perl(HTTP::Request) +BuildRequires: perl(IO::Socket::SSL) perl(LWP::UserAgent) perl(Net::FTPSSL) +BuildRequires: perl(Net::SSLeay) perl(Net::Telnet) perl(Sys::HostAddr) perl(Test::Harness) +BuildRequires: perl(Test::Unit) >= 0.25 perl(Time::HiRes) +%endif +%if %{rundir_tmpfs} +Requires: %{systemd_units} +%endif +Requires(preun): coreutils, findutils +%if %{use_systemd} +BuildRequires: %{systemd_units} +%{?systemd_requires} +%else +Requires(post): chkconfig +Requires(preun): chkconfig, initscripts +Requires(postun): initscripts +%endif +Provides: ftpserver +%description +ProFTPD is an enhanced FTP server with a focus toward simplicity, security, +and ease of configuration. It features a very Apache-like configuration +syntax, and a highly customizable server infrastructure, including support for +multiple 'virtual' FTP servers, anonymous FTP, and permission-based directory +visibility. +%if %{use_systemd} +This package defaults to the standalone behavior of ProFTPD, but all the +needed scripts to have it run by systemd instead are included. +%else +This package defaults to the standalone behavior of ProFTPD, but all the +needed scripts to have it run by xinetd instead are included. +%endif + +%package devel +Summary: ProFTPD - Tools and header files for developers +Requires: %{name} = %{version}-%{release} gcc, libtool GeoIP-devel libacl-devel +Requires: libcap-devel +%if 0%{?have_libmemcached:1} +Requires: libmemcached-devel >= 0.41 +%endif +Requires: %{mysql_devel_pkg} ncurses-devel openldap-devel openssl-devel pam-devel +Requires: pcre-devel pkgconfig %{postgresql_devel_pkg} sqlite-devel +%if 0%{?libwrap_support:1} +Requires: tcp_wrappers-devel +%endif +Requires: zlib-devel +%description devel +This package is required to build additional modules for ProFTPD. + +%package ldap +Summary: Module to add LDAP support to the ProFTPD FTP server +Requires: %{name} = %{version}-%{release} +%description ldap +Module to add LDAP support to the ProFTPD FTP server. + +%package mysql +Summary: Module to add MySQL support to the ProFTPD FTP server +Requires: %{name} = %{version}-%{release} +%description mysql +Module to add MySQL support to the ProFTPD FTP server. + +%package postgresql +Summary: Module to add PostgreSQL support to the ProFTPD FTP server +Requires: %{name} = %{version}-%{release} +%description postgresql +Module to add PostgreSQL support to the ProFTPD FTP server. + +%package sqlite +Summary: Module to add SQLite support to the ProFTPD FTP server +Requires: %{name} = %{version}-%{release} +%description sqlite +Module to add SQLite support to the ProFTPD FTP server. + +%package utils +Summary: ProFTPD - Additional utilities +Requires: %{name} = %{version}-%{release} perl-interpreter +BuildRequires: perl(Crypt::Cracklib) +Requires: perl(Crypt::Cracklib) +%description utils +This package contains additional utilities for monitoring and configuring the +ProFTPD server: +* ftpasswd: generate passwd(5) files for use with AuthUserFile +* ftpcount: show the current number of connections per server/virtualhost +* ftpmail: monitor transfer log and send email when files uploaded +* ftpquota: manipulate quota tables +* ftptop: show the current status of FTP sessions +* ftpwho: show the current process information for each FTP session + +%prep +%setup -q -n %{name}-%{version}%{?prever} +cd contrib +tar xfz %{SOURCE10} +mv proftpd-mod_vroot-%{mod_vroot_version} mod_vroot +cd - +cp -p %{SOURCE1} proftpd.conf +mv contrib/README contrib/README.contrib +%patch1 +%if 0%{!?have_libmemcached:1} +%patch2 +%endif +%patch3 -p1 -b .test_vroot +%patch100 -p1 +%patch101 -p1 +%patch102 -p1 +%patch103 -p1 +%patch104 -p1 +%patch105 -p1 +%patch106 -p1 +%patch107 -p1 +%patch108 -p1 +%patch109 -p1 +%patch110 -p1 +%patch111 -p1 +%patch112 -p1 +%patch113 -p1 +%patch114 -p1 +%patch115 -p1 +%patch116 -p1 +%patch117 -p1 +%if %{use_systemd} +sed -i -e '/killall/s/test.*/systemctl reload proftpd.service/' \ + contrib/dist/rpm/proftpd.logrotate +%endif +chmod -c -x contrib/xferstats.holger-preiss +chmod -c -x include/hanson-tpl.h lib/hanson-tpl.c +find doc/ contrib/ -name '*.orig' -delete +sed -i '867,877d' tests/api/netaddr.c +sed -i '408,413d' tests/api/netaddr.c +sed -i '755,760d' tests/api/netacl.c +sed -i '766,771d' tests/api/netacl.c +sed -i '786,791d' tests/api/netacl.c +sed -i '797,802d' tests/api/netacl.c + +%build +SMOD1=mod_sql:mod_sql_passwd:mod_sql_mysql:mod_sql_postgres:mod_sql_sqlite +SMOD2=mod_quotatab:mod_quotatab_file:mod_quotatab_ldap:mod_quotatab_radius:mod_quotatab_sql +SMOD3=mod_ldap:mod_ban%{?libwrap_support::mod_wrap}:mod_ctrls_admin:mod_facl:mod_load:mod_vroot +SMOD4=mod_radius:mod_ratio:mod_rewrite:mod_site_misc:mod_exec:mod_shaper:mod_geoip +SMOD5=mod_wrap2:mod_wrap2_file:mod_wrap2_sql:mod_copy:mod_deflate:mod_ifversion:mod_qos +SMOD6=mod_sftp:mod_sftp_pam:mod_sftp_sql:mod_tls_shmcache%{?have_libmemcached::mod_tls_memcache} +%configure \ + --libexecdir="%{_libexecdir}/proftpd" \ + --localstatedir="%{rundir}/proftpd" \ + --disable-strip \ + --enable-ctrls \ + --enable-dso \ + --enable-facl \ + --enable-ipv6 \ +%{?have_libmemcached: --enable-memcache} \ + --enable-nls \ + --enable-openssl \ + --disable-pcre \ + --disable-redis \ + --enable-shadow \ + --enable-tests=nonetwork \ + --with-libraries="%{_libdir}/%{mysql_lib}" \ + --with-includes="%{_includedir}/mysql" \ + --with-modules=mod_readme:mod_auth_pam:mod_tls \ + --with-shared=${SMOD1}:${SMOD2}:${SMOD3}:${SMOD4}:${SMOD5}:${SMOD6}:mod_ifsession +make %{?_smp_mflags} + +%install +make install DESTDIR=%{buildroot} \ + rundir="%{rundir}/proftpd" \ + INSTALL_USER=`id -un` \ + INSTALL_GROUP=`id -gn` +install -D -p -m 640 proftpd.conf %{buildroot}%{_sysconfdir}/proftpd.conf +install -D -p -m 644 contrib/dist/rpm/proftpd.pam \ + %{buildroot}%{_sysconfdir}/pam.d/proftpd +%if %{use_systemd} +install -D -p -m 644 contrib/dist/rpm/proftpd.service \ + %{buildroot}%{_unitdir}/proftpd.service +install -D -p -m 644 contrib/dist/systemd/proftpd.socket \ + %{buildroot}%{_unitdir}/proftpd.socket +install -D -p -m 644 contrib/dist/systemd/proftpd@.service \ + %{buildroot}%{_unitdir}/proftpd@.service +%else +install -D -p -m 755 contrib/dist/rpm/proftpd.init.d \ + %{buildroot}%{_sysconfdir}/rc.d/init.d/proftpd +install -D -p -m 644 contrib/dist/rpm/xinetd \ + %{buildroot}%{_sysconfdir}/xinetd.d/xproftpd +%endif +install -D -p -m 644 contrib/dist/rpm/proftpd.logrotate \ + %{buildroot}%{_sysconfdir}/logrotate.d/proftpd +install -D -p -m 644 %{SOURCE5} %{buildroot}%{_localstatedir}/ftp/welcome.msg +install -D -p -m 644 %{SOURCE9} %{buildroot}%{_sysconfdir}/sysconfig/proftpd +mkdir -p %{buildroot}%{_localstatedir}/{ftp/{pub,uploads},log/proftpd} +touch %{buildroot}%{_sysconfdir}/ftpusers +%if %{rundir_tmpfs} +install -d -m 755 %{buildroot}%{_prefix}/lib/tmpfiles.d +install -p -m 644 contrib/dist/rpm/proftpd-tmpfs.conf \ + %{buildroot}%{_prefix}/lib/tmpfiles.d/proftpd.conf +%endif +%find_lang proftpd + +%check +%if 0%{?_with_integrationtests:1} +ln ftpdctl tests/ +make check +%else +if ! make -C tests api-tests; then + # Diagnostics to report upstream + cat tests/api-tests.log + ./proftpd -V + # Fail the build + false +fi +%endif + +%post +%if %{use_systemd} +systemctl daemon-reload &>/dev/null || : +%endif +if [ $1 -eq 1 ]; then + # Initial installation +%if ! %{use_systemd} + chkconfig --add proftpd || : +%endif +%if %{preset_support} + systemctl preset proftpd.service &>/dev/null || : +%endif + IFS=":"; cat /etc/passwd | \ + while { read username nu nu gid nu nu nu nu; }; do \ + if [ $gid -lt 100 -a "$username" != "ftp" ]; then + echo $username >> %{_sysconfdir}/ftpusers + fi + done +fi + +%preun +if [ $1 -eq 0 ]; then + # Package removal, not upgrade +%if %{use_systemd} + systemctl --no-reload disable proftpd.service &>/dev/null || : + systemctl stop proftpd.service &>/dev/null || : +%else + service proftpd stop &>/dev/null || : + chkconfig --del proftpd || : +%endif + find %{rundir}/proftpd -depth -mindepth 1 | + xargs rm -rf &>/dev/null || : +fi + +%postun +%if %{use_systemd} +systemctl daemon-reload &>/dev/null || : +%endif +if [ $1 -ge 1 ]; then + # Package upgrade, not uninstall +%if %{use_systemd} + systemctl try-restart proftpd.service &>/dev/null || : +%else + service proftpd condrestart &>/dev/null || : +else + # Package removal, not upgrade + service xinetd reload &>/dev/null || : +%endif +fi + +%files -f proftpd.lang +%if 0%{?_licensedir:1} +%license COPYING +%else +%doc COPYING +%endif +%doc CREDITS ChangeLog NEWS README.md +%doc README.DSO README.modules README.IPv6 README.PAM +%doc README.capabilities README.classes README.controls README.facl +%doc contrib/README.contrib contrib/README.ratio +%doc doc/* sample-configurations/ +%dir %{_localstatedir}/ftp/ +%dir %{_localstatedir}/ftp/pub/ +%dir %{rundir}/proftpd/ +%config(noreplace) %{_localstatedir}/ftp/welcome.msg +%config(noreplace) %{_sysconfdir}/blacklist.dat +%config(noreplace) %{_sysconfdir}/dhparams.pem +%config(noreplace) %{_sysconfdir}/ftpusers +%config(noreplace) %{_sysconfdir}/logrotate.d/proftpd +%config(noreplace) %{_sysconfdir}/pam.d/proftpd +%config(noreplace) %{_sysconfdir}/proftpd.conf +%config(noreplace) %{_sysconfdir}/sysconfig/proftpd +%if %{use_systemd} +%{_unitdir}/proftpd.service +%{_unitdir}/proftpd.socket +%{_unitdir}/proftpd@.service +%else +%config(noreplace) %{_sysconfdir}/xinetd.d/xproftpd +%{_sysconfdir}/rc.d/init.d/proftpd +%endif +%if %{rundir_tmpfs} +%{_prefix}/lib/tmpfiles.d/proftpd.conf +%endif +%{_bindir}/ftpdctl +%{_sbindir}/ftpscrub +%{_sbindir}/ftpshut +%{_sbindir}/in.proftpd +%{_sbindir}/proftpd +%{_mandir}/man5/proftpd.conf.5* +%{_mandir}/man5/xferlog.5* +%{_mandir}/man8/ftpdctl.8* +%{_mandir}/man8/ftpscrub.8* +%{_mandir}/man8/ftpshut.8* +%{_mandir}/man8/proftpd.8* +%dir %{_libexecdir}/proftpd/ +%{_libexecdir}/proftpd/mod_ban.so +%{_libexecdir}/proftpd/mod_ctrls_admin.so +%{_libexecdir}/proftpd/mod_copy.so +%{_libexecdir}/proftpd/mod_deflate.so +%{_libexecdir}/proftpd/mod_exec.so +%{_libexecdir}/proftpd/mod_facl.so +%{_libexecdir}/proftpd/mod_geoip.so +%{_libexecdir}/proftpd/mod_ifsession.so +%{_libexecdir}/proftpd/mod_ifversion.so +%{_libexecdir}/proftpd/mod_load.so +%{_libexecdir}/proftpd/mod_qos.so +%{_libexecdir}/proftpd/mod_quotatab.so +%{_libexecdir}/proftpd/mod_quotatab_file.so +%{_libexecdir}/proftpd/mod_quotatab_radius.so +%{_libexecdir}/proftpd/mod_quotatab_sql.so +%{_libexecdir}/proftpd/mod_radius.so +%{_libexecdir}/proftpd/mod_ratio.so +%{_libexecdir}/proftpd/mod_rewrite.so +%{_libexecdir}/proftpd/mod_sftp.so +%{_libexecdir}/proftpd/mod_sftp_pam.so +%{_libexecdir}/proftpd/mod_sftp_sql.so +%{_libexecdir}/proftpd/mod_shaper.so +%{_libexecdir}/proftpd/mod_site_misc.so +%{_libexecdir}/proftpd/mod_sql.so +%{_libexecdir}/proftpd/mod_sql_passwd.so +%{?have_libmemcached:%{_libexecdir}/proftpd/mod_tls_memcache.so} +%{_libexecdir}/proftpd/mod_tls_shmcache.so +%{_libexecdir}/proftpd/mod_vroot.so +%{?libwrap_support:%{_libexecdir}/proftpd/mod_wrap.so} +%{_libexecdir}/proftpd/mod_wrap2.so +%{_libexecdir}/proftpd/mod_wrap2_file.so +%{_libexecdir}/proftpd/mod_wrap2_sql.so +%exclude %{_libexecdir}/proftpd/*.a +%exclude %{_libexecdir}/proftpd/*.la +%attr(331, ftp, ftp) %dir %{_localstatedir}/ftp/uploads/ +%attr(750, root, root) %dir %{_localstatedir}/log/proftpd/ + +%files devel +%{_bindir}/prxs +%{_includedir}/proftpd/ +%{_libdir}/pkgconfig/proftpd.pc + +%files ldap +%doc README.LDAP contrib/mod_quotatab_ldap.ldif contrib/mod_quotatab_ldap.schema +%{_libexecdir}/proftpd/mod_ldap.so +%{_libexecdir}/proftpd/mod_quotatab_ldap.so + +%files mysql +%{_libexecdir}/proftpd/mod_sql_mysql.so + +%files postgresql +%{_libexecdir}/proftpd/mod_sql_postgres.so + +%files sqlite +%{_libexecdir}/proftpd/mod_sql_sqlite.so + +%files utils +%doc contrib/xferstats.holger-preiss +%{_bindir}/ftpasswd +%{_bindir}/ftpcount +%{_bindir}/ftpmail +%{_bindir}/ftpquota +%{_bindir}/ftptop +%{_bindir}/ftpwho +%{_mandir}/man1/ftpasswd.1* +%{_mandir}/man1/ftpcount.1* +%{_mandir}/man1/ftpmail.1* +%{_mandir}/man1/ftpquota.1* +%{_mandir}/man1/ftptop.1* +%{_mandir}/man1/ftpwho.1* + +%changelog +* Wed Oct 14 2020 chengzihan - 1.3.6-1 +- Package init diff --git a/proftpd.sysconfig b/proftpd.sysconfig new file mode 100644 index 0000000..fcef206 --- /dev/null +++ b/proftpd.sysconfig @@ -0,0 +1,12 @@ +# Set PROFTPD_OPTIONS to add command-line options for proftpd. +# See proftpd(8) for a comprehensive list of what can be used. +# +# The following "Defines" can be used with the default configuration file: +# -DANONYMOUS_FTP : Enable anonymous FTP +# -DDYNAMIC_BAN_LISTS : Enable dynamic ban lists (mod_ban) +# -DQOS : Enable QoS bits on server traffic (mod_qos) +# -DTLS : Enable TLS (mod_tls) +# +# For example, for anonymous FTP and dynamic ban list support: +# PROFTPD_OPTIONS="-DANONYMOUS_FTP -DDYNAMIC_BAN_LISTS" +PROFTPD_OPTIONS="" diff --git a/proftpd.yaml b/proftpd.yaml new file mode 100644 index 0000000..56cb824 --- /dev/null +++ b/proftpd.yaml @@ -0,0 +1,4 @@ +version_control: github +src_repoo: proftpd/protpd +tag_prefix: "^v" +separator: "." diff --git a/v0.9.5.tar.gz b/v0.9.5.tar.gz new file mode 100644 index 0000000..9bd3b76 Binary files /dev/null and b/v0.9.5.tar.gz differ diff --git a/v1.3.6.tar.gz b/v1.3.6.tar.gz new file mode 100644 index 0000000..5250af5 Binary files /dev/null and b/v1.3.6.tar.gz differ