diff --git a/proftpd-1.3.3g-tls-protocols.patch b/proftpd-1.3.3g-tls-protocols.patch new file mode 100644 index 0000000..8739a03 --- /dev/null +++ b/proftpd-1.3.3g-tls-protocols.patch @@ -0,0 +1,180 @@ +--- contrib/mod_tls.c ++++ contrib/mod_tls.c +@@ -376,6 +376,8 @@ static char *tls_passphrase_provider = N + + #define TLS_PROTO_SSL_V3 0x0001 + #define TLS_PROTO_TLS_V1 0x0002 ++#define TLS_PROTO_TLS_V1_1 0x0004 ++#define TLS_PROTO_TLS_V1_2 0x0008 + static unsigned int tls_protocol = TLS_PROTO_SSL_V3|TLS_PROTO_TLS_V1; + + static int tls_ssl_opts = SSL_OP_ALL|SSL_OP_NO_SSLv2|SSL_OP_SINGLE_DH_USE^SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; +@@ -2194,25 +2196,101 @@ static int tls_init_ctx(void) { + return 0; + } + ++static const char *tls_get_proto_str(pool *p, unsigned int protos, ++ unsigned int *count) { ++ char *proto_str = ""; ++ unsigned int nproto = 0; ++ ++ if (protos & TLS_PROTO_SSL_V3) { ++ proto_str = pstrcat(p, proto_str, *proto_str ? ", " : "", ++ "SSLv3", NULL); ++ nproto++; ++ } ++ ++ if (protos & TLS_PROTO_TLS_V1) { ++ proto_str = pstrcat(p, proto_str, *proto_str ? ", " : "", ++ "TLSv1", NULL); ++ nproto++; ++ } ++ ++ if (protos & TLS_PROTO_TLS_V1_1) { ++ proto_str = pstrcat(p, proto_str, *proto_str ? ", " : "", ++ "TLSv1.1", NULL); ++ nproto++; ++ } ++ ++ if (protos & TLS_PROTO_TLS_V1_2) { ++ proto_str = pstrcat(p, proto_str, *proto_str ? ", " : "", ++ "TLSv1.2", NULL); ++ nproto++; ++ } ++ ++ *count = nproto; ++ return proto_str; ++} ++ ++/* Construct the options value that disables all unsupported protocols. ++ */ ++static int get_disabled_protocols(unsigned int supported_protocols) { ++ int disabled_protocols; ++ ++ /* First, create an options value where ALL protocols are disabled. */ ++ disabled_protocols = (SSL_OP_NO_SSLv2|SSL_OP_NO_SSLv3|SSL_OP_NO_TLSv1); ++ ++#ifdef SSL_OP_NO_TLSv1_1 ++ disabled_protocols |= SSL_OP_NO_TLSv1_1; ++#endif ++#ifdef SSL_OP_NO_TLSv1_2 ++ disabled_protocols |= SSL_OP_NO_TLSv1_2; ++#endif ++ ++ /* Now, based on the given bitset of supported protocols, clear the ++ * necessary bits. ++ */ ++ ++ if (supported_protocols & TLS_PROTO_SSL_V3) { ++ disabled_protocols &= ~SSL_OP_NO_SSLv3; ++ } ++ ++ if (supported_protocols & TLS_PROTO_TLS_V1) { ++ disabled_protocols &= ~SSL_OP_NO_TLSv1; ++ } ++ ++#if OPENSSL_VERSION_NUMBER >= 0x10001000L ++ if (supported_protocols & TLS_PROTO_TLS_V1_1) { ++ disabled_protocols &= ~SSL_OP_NO_TLSv1_1; ++ } ++ ++ if (supported_protocols & TLS_PROTO_TLS_V1_2) { ++ disabled_protocols &= ~SSL_OP_NO_TLSv1_2; ++ } ++#endif /* OpenSSL-1.0.1 or later */ ++ ++ return disabled_protocols; ++} ++ + static int tls_init_server(void) { + #if OPENSSL_VERSION_NUMBER > 0x000907000L + config_rec *c = NULL; + #endif + char *tls_ca_cert = NULL, *tls_ca_path = NULL; ++ unsigned int enabled_proto_count = 0; ++ int disabled_proto; ++ const char *enabled_proto_str = NULL; ++ ++ disabled_proto = get_disabled_protocols(tls_protocol); ++ ++ /* Per the comments in , SSL_CTX_set_options() uses |= on ++ * the previous value. This means we can easily OR in our new option ++ * values with any previously set values. ++ */ ++ enabled_proto_str = tls_get_proto_str(main_server->pool, tls_protocol, ++ &enabled_proto_count); + +- if ((tls_protocol & TLS_PROTO_SSL_V3) && +- (tls_protocol & TLS_PROTO_TLS_V1)) { +- /* This is the default, so there is no need to do anything. */ +- pr_log_debug(DEBUG8, MOD_TLS_VERSION ": supporting SSLv3, TLSv1 protocols"); +- +- } else if (tls_protocol & TLS_PROTO_SSL_V3) { +- SSL_CTX_set_ssl_version(ssl_ctx, SSLv3_server_method()); +- pr_log_debug(DEBUG8, MOD_TLS_VERSION ": supporting SSLv3 protocol only"); +- +- } else if (tls_protocol & TLS_PROTO_TLS_V1) { +- SSL_CTX_set_ssl_version(ssl_ctx, TLSv1_server_method()); +- pr_log_debug(DEBUG8, MOD_TLS_VERSION ": supporting TLSv1 protocol only"); +- } ++ pr_log_debug(DEBUG8, MOD_TLS_VERSION ": supporting %s %s", ++ enabled_proto_str, ++ enabled_proto_count != 1 ? "protocols" : "protocol only"); ++ SSL_CTX_set_options(ssl_ctx, disabled_proto); + + tls_ca_cert = get_param_ptr(main_server->conf, "TLSCACertificateFile", FALSE); + tls_ca_path = get_param_ptr(main_server->conf, "TLSCACertificatePath", FALSE); +@@ -6319,16 +6397,30 @@ MODRET set_tlsprotocol(cmd_rec *cmd) { + tls_protocol = 0; + + for (i = 1; i < cmd->argc; i++) { +- if (strcasecmp(cmd->argv[i], "SSLv23") == 0) { ++ if (strncasecmp(cmd->argv[i], "SSLv23", 7) == 0) { + tls_protocol |= TLS_PROTO_SSL_V3; + tls_protocol |= TLS_PROTO_TLS_V1; + +- } else if (strcasecmp(cmd->argv[i], "SSLv3") == 0) { ++ } else if (strncasecmp(cmd->argv[i], "SSLv3", 6) == 0) { + tls_protocol |= TLS_PROTO_SSL_V3; + +- } else if (strcasecmp(cmd->argv[i], "TLSv1") == 0) { ++ } else if (strncasecmp(cmd->argv[i], "TLSv1", 6) == 0) { + tls_protocol |= TLS_PROTO_TLS_V1; + ++ } else if (strncasecmp(cmd->argv[i], "TLSv1.1", 8) == 0) { ++#if OPENSSL_VERSION_NUMBER >= 0x10001000L ++ tls_protocol |= TLS_PROTO_TLS_V1_1; ++#else ++ CONF_ERROR(cmd, "Your OpenSSL installation does not support TLSv1.1"); ++#endif /* OpenSSL 1.0.1 or later */ ++ ++ } else if (strncasecmp(cmd->argv[i], "TLSv1.2", 8) == 0) { ++#if OPENSSL_VERSION_NUMBER >= 0x10001000L ++ tls_protocol |= TLS_PROTO_TLS_V1_2; ++#else ++ CONF_ERROR(cmd, "Your OpenSSL installation does not support TLSv1.2"); ++#endif /* OpenSSL 1.0.1 or later */ ++ + } else { + CONF_ERROR(cmd, pstrcat(cmd->tmp_pool, "unknown protocol: '", + cmd->argv[i], "'", NULL)); +--- doc/contrib/mod_tls.html ++++ doc/contrib/mod_tls.html +@@ -999,6 +999,17 @@ The allowed protocols are: + TLSv1 + Allow only TLSv1 + ++ ++ ++ TLSv1.1 ++ Allow only TLSv1.1 ++ ++ ++ ++ TLSv1.2 ++ Allow only TLSv1.2 ++ ++ + + To support both SSLv3 and TLSv1, simply list both parameters for the + TLSProtocol directive, e.g.: diff --git a/proftpd.spec b/proftpd.spec index 47511e3..6631d74 100644 --- a/proftpd.spec +++ b/proftpd.spec @@ -7,7 +7,7 @@ %endif #global prever rc4 -%global rpmrel 4 +%global rpmrel 5 Summary: Flexible, stable and highly-configurable FTP server Name: proftpd @@ -31,6 +31,7 @@ Patch1: proftpd-mod-vroot-0.8.5-bug3841.patch Patch2: proftpd-1.3.3g-bug3973.patch Patch3: proftpd-1.3.3g-bz1044586.patch Patch4: proftpd-sftp-dh7680-bug4002.patch +Patch6: proftpd-1.3.3g-tls-protocols.patch BuildRoot: %{_tmppath}/%{name}-%{version}-%{release}-root Requires(post): /sbin/chkconfig Requires(preun): /sbin/service, /sbin/chkconfig, coreutils, findutils @@ -104,6 +105,9 @@ mv contrib/README contrib/README.contrib # http://bugs.proftpd.org/show_bug.cgi?id=4002 %patch4 +# Add support for specifying TLSv1.1 and TLSv1.2 (#1281493) +%patch6 + # Set up directory names in config file sed -e 's#@PKIDIR@#%{pkidir}#g' \ %{SOURCE1} > proftpd.conf @@ -293,6 +297,9 @@ fi %{_libexecdir}/proftpd/mod_sql_postgres.so %changelog +* Fri Nov 13 2015 Paul Howarth - 1.3.3g-5 +- Add support for specifying TLSv1.1 and TLSv1.2 (#1281493) + * Fri Dec 20 2013 Paul Howarth 1.3.3g-4 - Fix support for 8192-bit DH parameters (#1044586) - Add 3072-bit and 7680-bit DH parameters (upstream bug 4002)