==> dovecot-1.0.7-nocomp-and-cipher-preference.patch <== --- dovecot-1.0.7.orig/src/login-common/ssl-proxy-openssl.c 2016-05-22 17:31:47.000000000 +0200 +++ dovecot-1.0.7/src/login-common/ssl-proxy-openssl.c 2016-05-22 17:34:08.000000000 +0200 @@ -799,7 +799,7 @@ protocols = getenv("SSL_PROTOCOLS"); /* disable old protocols; ignore errors/don't check bitmask */ - SSL_CTX_set_options(ssl_ctx, (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3)); + SSL_CTX_set_options(ssl_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_SINGLE_DH_USE | SSL_OP_NO_COMPRESSION | SSL_OP_CIPHER_SERVER_PREFERENCE); cipher_list = getenv("SSL_CIPHER_LIST"); if (cipher_list == NULL) ==> dovecot-1.0.7-dh2048-and-ecdh.patch <== --- dovecot-1.0.7/src/login-common/ssl-proxy-openssl.c.dh2048-and-ecdh 2016-03-05 22:37:15.000000000 +0100 +++ dovecot-1.0.7/src/login-common/ssl-proxy-openssl.c 2016-03-06 00:37:05.000000000 +0100 @@ -25,6 +25,8 @@ #define DOVECOT_SSL_DEFAULT_CIPHER_LIST "ALL:!LOW" /* Check every 30 minutes if parameters file has been updated */ #define SSL_PARAMFILE_CHECK_INTERVAL (60*30) +/* different approach besides ssl-paramaters file: */ +#define DHPARAMS_FILE SYSCONFDIR"/dovecot.dh_params" enum ssl_io_action { SSL_ADD_INPUT, @@ -59,7 +61,9 @@ time_t last_mtime, last_check; int fd; - DH *dh_512, *dh_1024; + DH *dh_params; + DH *dh_params_default; + time_t ts_dh_params; }; static int extdata_index; @@ -73,6 +77,7 @@ static void ssl_step(void *context); static void ssl_proxy_destroy(struct ssl_proxy *proxy); static void ssl_proxy_unref(struct ssl_proxy *proxy); +static DH *get_dh2048(); static void read_next(struct ssl_parameters *params, void *data, size_t size) { @@ -106,14 +111,7 @@ read_next(params, buf, len); cbuf = buf; - switch (bits) { - case 512: - params->dh_512 = d2i_DHparams(NULL, &cbuf, len); - break; - case 1024: - params->dh_1024 = d2i_DHparams(NULL, &cbuf, len); - break; - } + /* params->dh_params = d2i_DHparams(NULL, &cbuf, len); */ i_free(buf); return TRUE; @@ -121,13 +119,9 @@ static void ssl_free_parameters(struct ssl_parameters *params) { - if (params->dh_512 != NULL) { - DH_free(params->dh_512); - params->dh_512 = NULL; - } - if (params->dh_1024 != NULL) { - DH_free(params->dh_1024); - params->dh_1024 = NULL; + if ((params->dh_params != NULL) && (params->dh_params != params->dh_params_default)) { + DH_free(params->dh_params); + params->dh_params = NULL; } } @@ -604,15 +598,50 @@ return RSA_generate_key(keylength, RSA_F4, NULL, NULL); } +static void readget_dh_params() +{ + struct stat sb; + FILE *file; + + if (ssl_params.dh_params_default == 0) { + /* get_dh2048() must be appended to this file on build time by: */ + /* openssl dhparam -C 2048 -noout >>src/login-common/ssl-proxy-openssl.c */ + ssl_params.dh_params_default = get_dh2048(); + } + if (ssl_params.dh_params == 0) { + ssl_params.dh_params = ssl_params.dh_params_default; + } + + if (stat(DHPARAMS_FILE, &sb) == 0) { + if (ssl_params.ts_dh_params != sb.st_mtime) { + /* timestamp has changed */ + file = fopen(DHPARAMS_FILE, "r"); + if (file) { + if (ssl_params.dh_params != ssl_params.dh_params_default) { + DH_free(ssl_params.dh_params); + } + ssl_params.ts_dh_params = sb.st_mtime; + ssl_params.dh_params = PEM_read_DHparams(file, 0, 0, 0); + fclose(file); + } + } + } + return; +} + static DH *ssl_tmp_dh_callback(SSL *ssl __attr_unused__, int is_export, int keylength) { /* Well, I'm not exactly sure why the logic in here is this. It's the same as in Postfix, so it can't be too wrong. */ + /* Well, actually you should have checked this. I will ignore len and return the default 2048 */ + /* if (is_export && keylength == 512 && ssl_params.dh_512 != NULL) return ssl_params.dh_512; + */ - return ssl_params.dh_1024; + readget_dh_params(); + return ssl_params.dh_params; } static void ssl_info_callback(const SSL *ssl, int where, int ret) @@ -741,6 +770,10 @@ const char *cafile, *certfile, *keyfile, *cipher_list, *protocols; char *password; unsigned char buf; +#if defined(SSL_TXT_ECDH) && !defined(SSL_CTRL_SET_ECDH_AUTO) + EC_KEY *ecdh; + int nid; +#endif memset(&ssl_params, 0, sizeof(ssl_params)); @@ -765,7 +798,8 @@ protocols = getenv("SSL_PROTOCOLS"); - SSL_CTX_set_options(ssl_ctx, SSL_OP_ALL); + /* disable old protocols; ignore errors/don't check bitmask */ + SSL_CTX_set_options(ssl_ctx, (SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3)); cipher_list = getenv("SSL_CIPHER_LIST"); if (cipher_list == NULL) @@ -797,10 +831,34 @@ keyfile, ssl_last_error()); } + /* WTF? */ if (SSL_CTX_need_tmp_RSA(ssl_ctx)) SSL_CTX_set_tmp_rsa_callback(ssl_ctx, ssl_gen_rsa_key); SSL_CTX_set_tmp_dh_callback(ssl_ctx, ssl_tmp_dh_callback); +#ifdef SSL_TXT_ECDH + SSL_CTX_set_options(ssl_ctx, SSL_OP_SINGLE_ECDH_USE); +#ifdef SSL_CTRL_SET_ECDH_AUTO + /* OpenSSL >= 1.0.2 */ + SSL_CTX_set_ecdh_auto(ssl_ctx, 1); +#else + /* insecure and compatible curves, see http://safecurves.cr.yp.to/ */ + ecdh = EC_KEY_new_by_curve_name(NID_secp521r1); + if (ecdh == NULL) { + /* NIST P-384 / AES-256 */ + ecdh = EC_KEY_new_by_curve_name(NID_secp384r1); + } + if (ecdh == NULL) { + /* NIST P-256 / AES-128 */ + ecdh = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); + } + if (ecdh != NULL) { + SSL_CTX_set_tmp_ecdh(ssl_ctx, ecdh); + EC_KEY_free(ecdh); + } +#endif +#endif + if (verbose_ssl) SSL_CTX_set_info_callback(ssl_ctx, ssl_info_callback); --- dovecot-1.0.7/src/login-common/Makefile.am.dh2048-and-ecdh 2007-10-28 02:09:24.000000000 +0200 +++ dovecot-1.0.7/src/login-common/Makefile.am 2016-03-06 00:34:38.000000000 +0100 @@ -3,6 +3,7 @@ AM_CPPFLAGS = \ -I$(top_srcdir)/src/lib \ -I$(top_srcdir)/src/lib-auth \ + -DSYSCONFDIR=\""$(sysconfdir)"\" \ -DPKG_RUNDIR=\""$(rundir)"\" \ -DSBINDIR=\""$(sbindir)"\"