diff --git a/SOURCES/vsftpd-3.0.2-dh.patch b/SOURCES/vsftpd-3.0.2-dh.patch new file mode 100644 index 0000000..13151cc --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-dh.patch @@ -0,0 +1,205 @@ +diff -up vsftpd-3.0.2/parseconf.c.dh vsftpd-3.0.2/parseconf.c +--- vsftpd-3.0.2/parseconf.c.dh 2014-06-04 10:24:57.512748573 +0200 ++++ vsftpd-3.0.2/parseconf.c 2014-06-04 10:24:57.532748566 +0200 +@@ -175,6 +175,7 @@ parseconf_str_array[] = + { "email_password_file", &tunable_email_password_file }, + { "rsa_cert_file", &tunable_rsa_cert_file }, + { "dsa_cert_file", &tunable_dsa_cert_file }, ++ { "dh_param_file", &tunable_dh_param_file }, + { "ssl_ciphers", &tunable_ssl_ciphers }, + { "rsa_private_key_file", &tunable_rsa_private_key_file }, + { "dsa_private_key_file", &tunable_dsa_private_key_file }, +diff -up vsftpd-3.0.2/ssl.c.dh vsftpd-3.0.2/ssl.c +--- vsftpd-3.0.2/ssl.c.dh 2012-04-03 02:23:42.000000000 +0200 ++++ vsftpd-3.0.2/ssl.c 2014-06-04 10:24:57.533748565 +0200 +@@ -28,6 +28,8 @@ + #include + #include + #include ++#include ++#include + #include + #include + +@@ -38,6 +40,7 @@ static void setup_bio_callbacks(); + static long bio_callback( + BIO* p_bio, int oper, const char* p_arg, int argi, long argl, long retval); + static int ssl_verify_callback(int verify_ok, X509_STORE_CTX* p_ctx); ++static DH *ssl_tmp_dh_callback(SSL *ssl, int is_export, int keylength); + static int ssl_cert_digest( + SSL* p_ssl, struct vsf_session* p_sess, struct mystr* p_str); + static void maybe_log_shutdown_state(struct vsf_session* p_sess); +@@ -51,6 +54,60 @@ static int ssl_read_common(struct vsf_se + static int ssl_inited; + static struct mystr debug_str; + ++ ++// Grab prime number from OpenSSL; ++// (get_rfc*) for all available primes. ++// wraps selection of comparable algorithm strength ++#if !defined(match_dh_bits) ++ #define match_dh_bits(keylen) \ ++ keylen >= 8191 ? 8192 : \ ++ keylen >= 6143 ? 6144 : \ ++ keylen >= 4095 ? 4096 : \ ++ keylen >= 3071 ? 3072 : \ ++ keylen >= 2047 ? 2048 : \ ++ keylen >= 1535 ? 1536 : \ ++ keylen >= 1023 ? 1024 : 768 ++#endif ++ ++#if !defined(DH_get_prime) ++ BIGNUM * ++ DH_get_prime(int bits) ++ { ++ switch (bits) { ++ case 768: return get_rfc2409_prime_768(NULL); ++ case 1024: return get_rfc2409_prime_1024(NULL); ++ case 1536: return get_rfc3526_prime_1536(NULL); ++ case 2048: return get_rfc3526_prime_2048(NULL); ++ case 3072: return get_rfc3526_prime_3072(NULL); ++ case 4096: return get_rfc3526_prime_4096(NULL); ++ case 6144: return get_rfc3526_prime_6144(NULL); ++ case 8192: return get_rfc3526_prime_8192(NULL); ++ // shouldn't happen when used match_dh_bits; strict compiler ++ default: return NULL; ++ } ++} ++#endif ++ ++#if !defined(DH_get_dh) ++ // Grab DH parameters ++ DH * ++ DH_get_dh(int size) ++ { ++ DH *dh = DH_new(); ++ if (!dh) { ++ return NULL; ++ } ++ dh->p = DH_get_prime(match_dh_bits(size)); ++ BN_dec2bn(&dh->g, "2"); ++ if (!dh->p || !dh->g) ++ { ++ DH_free(dh); ++ return NULL; ++ } ++ return dh; ++ } ++#endif ++ + void + ssl_init(struct vsf_session* p_sess) + { +@@ -65,7 +122,7 @@ ssl_init(struct vsf_session* p_sess) + { + die("SSL: could not allocate SSL context"); + } +- options = SSL_OP_ALL; ++ options = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE; + if (!tunable_sslv2) + { + options |= SSL_OP_NO_SSLv2; +@@ -111,6 +168,25 @@ ssl_init(struct vsf_session* p_sess) + die("SSL: cannot load DSA private key"); + } + } ++ if (tunable_dh_param_file) ++ { ++ BIO *bio; ++ DH *dhparams = NULL; ++ if ((bio = BIO_new_file(tunable_dh_param_file, "r")) == NULL) ++ { ++ die("SSL: cannot load custom DH params"); ++ } ++ else ++ { ++ dhparams = PEM_read_bio_DHparams(bio, NULL, NULL, NULL); ++ BIO_free(bio); ++ ++ if (!SSL_CTX_set_tmp_dh(p_ctx, dhparams)) ++ { ++ die("SSL: setting custom DH params failed"); ++ } ++ } ++ } + if (tunable_ssl_ciphers && + SSL_CTX_set_cipher_list(p_ctx, tunable_ssl_ciphers) != 1) + { +@@ -156,6 +232,9 @@ ssl_init(struct vsf_session* p_sess) + /* Ensure cached session doesn't expire */ + SSL_CTX_set_timeout(p_ctx, INT_MAX); + } ++ ++ SSL_CTX_set_tmp_dh_callback(p_ctx, ssl_tmp_dh_callback); ++ + p_sess->p_ssl_ctx = p_ctx; + ssl_inited = 1; + } +@@ -675,6 +754,18 @@ ssl_verify_callback(int verify_ok, X509_ + return 1; + } + ++#define UNUSED(x) ( (void)(x) ) ++ ++static DH * ++ssl_tmp_dh_callback(SSL *ssl, int is_export, int keylength) ++{ ++ // strict compiler bypassing ++ UNUSED(ssl); ++ UNUSED(is_export); ++ ++ return DH_get_dh(keylength); ++} ++ + void + ssl_add_entropy(struct vsf_session* p_sess) + { +diff -up vsftpd-3.0.2/tunables.c.dh vsftpd-3.0.2/tunables.c +--- vsftpd-3.0.2/tunables.c.dh 2014-06-04 10:24:57.530748566 +0200 ++++ vsftpd-3.0.2/tunables.c 2014-06-04 10:24:57.533748565 +0200 +@@ -139,6 +139,7 @@ const char* tunable_user_sub_token; + const char* tunable_email_password_file; + const char* tunable_rsa_cert_file; + const char* tunable_dsa_cert_file; ++const char* tunable_dh_param_file; + const char* tunable_ssl_ciphers; + const char* tunable_rsa_private_key_file; + const char* tunable_dsa_private_key_file; +@@ -286,7 +287,9 @@ tunables_load_defaults() + install_str_setting("/usr/share/ssl/certs/vsftpd.pem", + &tunable_rsa_cert_file); + install_str_setting(0, &tunable_dsa_cert_file); +- install_str_setting("AES128-SHA:DES-CBC3-SHA", &tunable_ssl_ciphers); ++ install_str_setting(0, &tunable_dh_param_file); ++ install_str_setting("AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA", ++ &tunable_ssl_ciphers); + install_str_setting(0, &tunable_rsa_private_key_file); + install_str_setting(0, &tunable_dsa_private_key_file); + install_str_setting(0, &tunable_ca_certs_file); +diff -up vsftpd-3.0.2/tunables.h.dh vsftpd-3.0.2/tunables.h +--- vsftpd-3.0.2/tunables.h.dh 2014-06-04 10:24:57.511748573 +0200 ++++ vsftpd-3.0.2/tunables.h 2014-06-04 10:24:57.533748565 +0200 +@@ -141,6 +141,7 @@ extern const char* tunable_user_sub_toke + extern const char* tunable_email_password_file; + extern const char* tunable_rsa_cert_file; + extern const char* tunable_dsa_cert_file; ++extern const char* tunable_dh_param_file; + extern const char* tunable_ssl_ciphers; + extern const char* tunable_rsa_private_key_file; + extern const char* tunable_dsa_private_key_file; +diff -up vsftpd-3.0.2/vsftpd.conf.5.dh vsftpd-3.0.2/vsftpd.conf.5 +--- vsftpd-3.0.2/vsftpd.conf.5.dh 2014-06-04 10:24:57.523748569 +0200 ++++ vsftpd-3.0.2/vsftpd.conf.5 2014-06-04 10:24:57.533748565 +0200 +@@ -884,6 +884,12 @@ to be in the same file as the certificat + + Default: (none) + .TP ++.B dh_param_file ++This option specifies the location of the custom parameters used for ++ephemeral Diffie-Hellman key exchange in SSL. ++ ++Default: (none - use built in parameters appropriate for certificate key size) ++.TP + .B email_password_file + This option can be used to provide an alternate file for usage by the + .BR secure_email_list_enable diff --git a/SOURCES/vsftpd-3.0.2-ecdh.patch b/SOURCES/vsftpd-3.0.2-ecdh.patch new file mode 100644 index 0000000..629e878 --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-ecdh.patch @@ -0,0 +1,115 @@ +diff -up vsftpd-3.0.2/parseconf.c.ecdh vsftpd-3.0.2/parseconf.c +--- vsftpd-3.0.2/parseconf.c.ecdh 2014-06-04 10:25:36.786735755 +0200 ++++ vsftpd-3.0.2/parseconf.c 2014-06-04 10:25:36.812735747 +0200 +@@ -176,6 +176,7 @@ parseconf_str_array[] = + { "rsa_cert_file", &tunable_rsa_cert_file }, + { "dsa_cert_file", &tunable_dsa_cert_file }, + { "dh_param_file", &tunable_dh_param_file }, ++ { "ecdh_param_file", &tunable_ecdh_param_file }, + { "ssl_ciphers", &tunable_ssl_ciphers }, + { "rsa_private_key_file", &tunable_rsa_private_key_file }, + { "dsa_private_key_file", &tunable_dsa_private_key_file }, +diff -up vsftpd-3.0.2/ssl.c.ecdh vsftpd-3.0.2/ssl.c +--- vsftpd-3.0.2/ssl.c.ecdh 2014-06-04 10:25:36.786735755 +0200 ++++ vsftpd-3.0.2/ssl.c 2014-06-04 10:25:36.812735747 +0200 +@@ -122,7 +122,7 @@ ssl_init(struct vsf_session* p_sess) + { + die("SSL: could not allocate SSL context"); + } +- options = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE; ++ options = SSL_OP_ALL | SSL_OP_SINGLE_DH_USE | SSL_OP_SINGLE_ECDH_USE; + if (!tunable_sslv2) + { + options |= SSL_OP_NO_SSLv2; +@@ -235,6 +235,41 @@ ssl_init(struct vsf_session* p_sess) + + SSL_CTX_set_tmp_dh_callback(p_ctx, ssl_tmp_dh_callback); + ++ if (tunable_ecdh_param_file) ++ { ++ BIO *bio; ++ int nid; ++ EC_GROUP *ecparams = NULL; ++ EC_KEY *eckey; ++ ++ if ((bio = BIO_new_file(tunable_ecdh_param_file, "r")) == NULL) ++ die("SSL: cannot load custom ec params"); ++ else ++ { ++ ecparams = PEM_read_bio_ECPKParameters(bio, NULL, NULL, NULL); ++ BIO_free(bio); ++ ++ if (ecparams && (nid = EC_GROUP_get_curve_name(ecparams)) && ++ (eckey = EC_KEY_new_by_curve_name(nid))) ++ { ++ if (!SSL_CTX_set_tmp_ecdh(p_ctx, eckey)) ++ die("SSL: setting custom EC params failed"); ++ } ++ else ++ { ++ die("SSL: getting ec group or key failed"); ++ } ++ } ++ } ++ else ++ { ++#if defined(SSL_CTX_set_ecdh_auto) ++ SSL_CTX_set_ecdh_auto(p_ctx, 1); ++#else ++ SSL_CTX_set_tmp_ecdh(p_ctx, EC_KEY_new_by_curve_name(NID_X9_62_prime256v1)); ++#endif ++ } ++ + p_sess->p_ssl_ctx = p_ctx; + ssl_inited = 1; + } +diff -up vsftpd-3.0.2/tunables.c.ecdh vsftpd-3.0.2/tunables.c +--- vsftpd-3.0.2/tunables.c.ecdh 2014-06-04 10:25:36.787735755 +0200 ++++ vsftpd-3.0.2/tunables.c 2014-06-04 10:25:36.813735747 +0200 +@@ -140,6 +140,7 @@ const char* tunable_email_password_file; + const char* tunable_rsa_cert_file; + const char* tunable_dsa_cert_file; + const char* tunable_dh_param_file; ++const char* tunable_ecdh_param_file; + const char* tunable_ssl_ciphers; + const char* tunable_rsa_private_key_file; + const char* tunable_dsa_private_key_file; +@@ -288,7 +289,8 @@ tunables_load_defaults() + &tunable_rsa_cert_file); + install_str_setting(0, &tunable_dsa_cert_file); + install_str_setting(0, &tunable_dh_param_file); +- install_str_setting("AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA", ++ install_str_setting(0, &tunable_ecdh_param_file); ++ install_str_setting("AES128-SHA:DES-CBC3-SHA:DHE-RSA-AES256-SHA:ECDHE-RSA-AES128-SHA", + &tunable_ssl_ciphers); + install_str_setting(0, &tunable_rsa_private_key_file); + install_str_setting(0, &tunable_dsa_private_key_file); +diff -up vsftpd-3.0.2/tunables.h.ecdh vsftpd-3.0.2/tunables.h +--- vsftpd-3.0.2/tunables.h.ecdh 2014-06-04 10:25:36.787735755 +0200 ++++ vsftpd-3.0.2/tunables.h 2014-06-04 10:25:36.813735747 +0200 +@@ -142,6 +142,7 @@ extern const char* tunable_email_passwor + extern const char* tunable_rsa_cert_file; + extern const char* tunable_dsa_cert_file; + extern const char* tunable_dh_param_file; ++extern const char* tunable_ecdh_param_file; + extern const char* tunable_ssl_ciphers; + extern const char* tunable_rsa_private_key_file; + extern const char* tunable_dsa_private_key_file; +diff -up vsftpd-3.0.2/vsftpd.conf.5.ecdh vsftpd-3.0.2/vsftpd.conf.5 +--- vsftpd-3.0.2/vsftpd.conf.5.ecdh 2014-06-04 10:25:36.787735755 +0200 ++++ vsftpd-3.0.2/vsftpd.conf.5 2014-06-04 10:25:36.813735747 +0200 +@@ -890,6 +890,14 @@ ephemeral Diffie-Hellman key exchange in + + Default: (none - use built in parameters appropriate for certificate key size) + .TP ++.B ecdh_param_file ++This option specifies the location of custom parameters for ephemeral ++Elliptic Curve Diffie-Hellman (ECDH) key exchange. ++ ++Default: (none - use built in parameters, NIST P-256 with OpenSSL 1.0.1 and ++automatically selected curve based on client preferences with OpenSSL 1.0.2 ++and later) ++.TP + .B email_password_file + This option can be used to provide an alternate file for usage by the + .BR secure_email_list_enable diff --git a/SOURCES/vsftpd-3.0.2-wnohang.patch b/SOURCES/vsftpd-3.0.2-wnohang.patch new file mode 100644 index 0000000..6e0902d --- /dev/null +++ b/SOURCES/vsftpd-3.0.2-wnohang.patch @@ -0,0 +1,62 @@ +diff -up vsftpd-3.0.2/sysutil.c.wnohang vsftpd-3.0.2/sysutil.c +--- vsftpd-3.0.2/sysutil.c.wnohang 2015-08-03 07:35:33.619620425 +0200 ++++ vsftpd-3.0.2/sysutil.c 2015-08-03 07:35:33.626620480 +0200 +@@ -608,13 +608,13 @@ vsf_sysutil_exit(int exit_code) + } + + struct vsf_sysutil_wait_retval +-vsf_sysutil_wait(void) ++vsf_sysutil_wait(int hang) + { + struct vsf_sysutil_wait_retval retval; + vsf_sysutil_memclr(&retval, sizeof(retval)); + while (1) + { +- int sys_ret = wait(&retval.exit_status); ++ int sys_ret = waitpid(-1, &retval.exit_status, hang ? 0 : WNOHANG); + if (sys_ret < 0 && errno == EINTR) + { + vsf_sysutil_check_pending_actions(kVSFSysUtilUnknown, 0, 0); +diff -up vsftpd-3.0.2/sysutil.h.wnohang vsftpd-3.0.2/sysutil.h +--- vsftpd-3.0.2/sysutil.h.wnohang 2015-08-03 07:35:33.610620354 +0200 ++++ vsftpd-3.0.2/sysutil.h 2015-08-03 07:35:33.626620480 +0200 +@@ -176,7 +176,7 @@ struct vsf_sysutil_wait_retval + int PRIVATE_HANDS_OFF_syscall_retval; + int PRIVATE_HANDS_OFF_exit_status; + }; +-struct vsf_sysutil_wait_retval vsf_sysutil_wait(void); ++struct vsf_sysutil_wait_retval vsf_sysutil_wait(int hang); + int vsf_sysutil_wait_reap_one(void); + int vsf_sysutil_wait_get_retval( + const struct vsf_sysutil_wait_retval* p_waitret); +diff -up vsftpd-3.0.2/twoprocess.c.wnohang vsftpd-3.0.2/twoprocess.c +--- vsftpd-3.0.2/twoprocess.c.wnohang 2012-09-16 09:15:49.000000000 +0200 ++++ vsftpd-3.0.2/twoprocess.c 2015-08-03 07:35:33.626620480 +0200 +@@ -47,8 +47,17 @@ static void + handle_sigchld(void* duff) + { + +- struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(); ++ struct vsf_sysutil_wait_retval wait_retval = vsf_sysutil_wait(0); + (void) duff; ++ if (!vsf_sysutil_wait_get_exitcode(&wait_retval) && ++ !vsf_sysutil_wait_get_retval(&wait_retval)) ++ /* There was nobody to wait for, possibly caused by underlying library ++ * which created a new process through fork()/vfork() and already picked ++ * it up, e.g. by pam_exec.so or integrity check routines for libraries ++ * when FIPS mode is on (nss freebl), which can lead to calling prelink ++ * if the prelink package is installed. ++ */ ++ return; + /* Child died, so we'll do the same! Report it as an error unless the child + * exited normally with zero exit code + */ +@@ -390,7 +399,7 @@ common_do_login(struct vsf_session* p_se + priv_sock_send_result(p_sess->parent_fd, PRIV_SOCK_RESULT_OK); + if (!p_sess->control_use_ssl) + { +- (void) vsf_sysutil_wait(); ++ (void) vsf_sysutil_wait(1); + } + else + { diff --git a/SPECS/vsftpd.spec b/SPECS/vsftpd.spec index 415fc4c..f67f290 100644 --- a/SPECS/vsftpd.spec +++ b/SPECS/vsftpd.spec @@ -3,7 +3,7 @@ Name: vsftpd Version: 3.0.2 -Release: 9%{?dist} +Release: 10%{?dist} Summary: Very Secure Ftp Daemon Group: System Environment/Daemons @@ -62,6 +62,9 @@ Patch24: vsftpd-3.0.0-xferlog.patch Patch25: vsftpd-3.0.0-logrotate.patch Patch26: vsftpd-3.0.2-seccomp.patch Patch27: vsftpd-3.0.2-mrate.patch +Patch28: vsftpd-3.0.2-wnohang.patch +Patch29: vsftpd-3.0.2-dh.patch +Patch30: vsftpd-3.0.2-ecdh.patch %description vsftpd is a Very Secure FTP daemon. It was written completely from @@ -104,6 +107,9 @@ cp %{SOURCE1} . %patch25 -p1 -b .logrotate %patch26 -p1 -b .seccomp %patch27 -p1 -b .mrate +%patch28 -p1 -b .wnohang +%patch29 -p1 -b .dh +%patch30 -p1 -b .ecdh %build %ifarch s390x sparcv9 sparc64 @@ -174,6 +180,11 @@ rm -rf $RPM_BUILD_ROOT %{_sysconfdir}/rc.d/init.d/vsftpd %changelog +* Mon Aug 03 2015 Martin Osvald - 3.0.2-10 +- Resolves: #1058704 - vsftpd does not support DHE cipher suites +- Resolves: #1058712 - vsftpd does not support ECDHE cipher suites +- Resolves: #1198259 - The vsftpd hangs in a SIGCHLD handler when the pam_exec.so is used in pam.d configuration + * Fri Mar 07 2014 Jiri Skala - 3.0.2-9 - Resolves: #1063402 - vsftpd local_max_rate option doesn't work as expected