diff --git a/src/login-common/ssl-proxy-openssl.c b/src/login-common/ssl-proxy-openssl.c index fc9ef65ae2..3d7fa02963 100644 --- a/src/login-common/ssl-proxy-openssl.c +++ b/src/login-common/ssl-proxy-openssl.c @@ -33,11 +33,6 @@ # define HAVE_ECDH #endif -/* Check every 30 minutes if parameters file has been updated */ -#define SSL_PARAMFILE_CHECK_INTERVAL (60*30) - -#define SSL_PARAMETERS_PATH "ssl-params" - #ifndef SSL_CTRL_SET_TLSEXT_HOSTNAME /* FIXME: this may be unnecessary.. */ # undef HAVE_SSL_GET_SERVERNAME #endif @@ -84,11 +79,7 @@ struct ssl_proxy { }; struct ssl_parameters { - const char *path; - time_t last_refresh; - int fd; - - DH *dh_512, *dh_default; + DH *dh_default; }; struct ssl_server_context { @@ -98,6 +89,7 @@ struct ssl_server_context { const char *cert; const char *key; const char *ca; + const char *dh; const char *cipher_list; const char *protocols; bool verify_client_cert; @@ -172,103 +164,14 @@ static int ssl_server_context_cmp(const struct ssl_server_context *ctx1, return ctx1->verify_client_cert == ctx2->verify_client_cert ? 0 : 1; } -static void ssl_params_corrupted(const char *reason) -{ - i_fatal("Corrupted SSL ssl-parameters.dat in state_dir: %s", reason); -} - -static void read_next(struct ssl_parameters *params, void *data, size_t size) -{ - int ret; - - if ((ret = read_full(params->fd, data, size)) < 0) - i_fatal("read(%s) failed: %m", params->path); - if (ret == 0) - ssl_params_corrupted("Truncated file"); -} - -static bool read_dh_parameters_next(struct ssl_parameters *params) -{ - unsigned char *buf; - const unsigned char *cbuf; - unsigned int len; - int bits; - - /* read bit size. 0 ends the DH parameters list. */ - read_next(params, &bits, sizeof(bits)); - - if (bits == 0) - return FALSE; - - /* read data size. */ - read_next(params, &len, sizeof(len)); - if (len > 1024*100) /* should be enough? */ - ssl_params_corrupted("File too large"); - - buf = i_malloc(len); - read_next(params, buf, len); - - cbuf = buf; - switch (bits) { - case 512: - if (params->dh_512 != NULL) - ssl_params_corrupted("Duplicate 512bit parameters"); - params->dh_512 = d2i_DHparams(NULL, &cbuf, len); - break; - default: - if (params->dh_default != NULL) - ssl_params_corrupted("Duplicate default parameters"); - params->dh_default = d2i_DHparams(NULL, &cbuf, len); - break; - } - - i_free(buf); - return TRUE; -} - 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_default != NULL) { DH_free(params->dh_default); params->dh_default = NULL; } } -static void ssl_refresh_parameters(struct ssl_parameters *params) -{ - char c; - int ret; - - if (params->last_refresh > ioloop_time - SSL_PARAMFILE_CHECK_INTERVAL) - return; - params->last_refresh = ioloop_time; - - params->fd = net_connect_unix(params->path); - if (params->fd == -1) { - i_error("connect(%s) failed: %m", params->path); - return; - } - net_set_nonblock(params->fd, FALSE); - - ssl_free_parameters(params); - while (read_dh_parameters_next(params)) ; - - if ((ret = read_full(params->fd, &c, 1)) < 0) - i_fatal("read(%s) failed: %m", params->path); - else if (ret != 0) { - /* more data than expected */ - ssl_params_corrupted("More data than expected"); - } - - if (close(params->fd) < 0) - i_error("close(%s) failed: %m", params->path); - params->fd = -1; -} - static void ssl_set_io(struct ssl_proxy *proxy, enum ssl_io_action action) { switch (action) { @@ -556,7 +459,7 @@ ssl_proxy_alloc_common(SSL_CTX *ssl_ctx, int fd, const struct ip_addr *ip, return -1; } - ssl_refresh_parameters(&ssl_params); + ssl = SSL_new(ssl_ctx); if (ssl == NULL) { @@ -829,15 +732,6 @@ static RSA *ssl_gen_rsa_key(SSL *ssl ATTR_UNUSED, return RSA_generate_key(keylength, RSA_F4, NULL, NULL); } -static DH *ssl_tmp_dh_callback(SSL *ssl ATTR_UNUSED, - int is_export, int keylength) -{ - if (is_export != 0 && keylength == 512 && ssl_params.dh_512 != NULL) - return ssl_params.dh_512; - - return ssl_params.dh_default; -} - static void ssl_info_callback(const SSL *ssl, int where, int ret) { struct ssl_proxy *proxy; @@ -1025,7 +919,6 @@ ssl_proxy_ctx_set_crypto_params(SSL_CTX *ssl_ctx, #endif if (SSL_CTX_need_tmp_RSA(ssl_ctx) != 0) 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 HAVE_ECDH /* In the non-recommended situation where ECDH cipher suites are being used instead of ECDHE, do not reuse the same ECDH key pair for @@ -1101,6 +994,24 @@ ssl_proxy_load_key(const char *key, const char *password) return pkey; } +static DH * +ssl_proxy_load_dh(const char *dhparam) +{ + DH *dh; + BIO *bio; + + bio = BIO_new_mem_buf(t_strdup_noconst(dhparam), strlen(dhparam)); + if (bio == NULL) + i_fatal("BIO_new_mem_buf() failed"); + dh = NULL; + dh = PEM_read_bio_DHparams(bio, &dh, NULL, NULL); + if (dh == NULL) + i_fatal("Couldn't parse DH parameters: %s", + openssl_iostream_key_load_error()); + BIO_free(bio); + return dh; +} + static void ssl_proxy_ctx_use_key(SSL_CTX *ctx, const struct master_service_ssl_settings *set) @@ -1116,6 +1027,18 @@ ssl_proxy_ctx_use_key(SSL_CTX *ctx, EVP_PKEY_free(pkey); } +static void +ssl_proxy_ctx_use_dh(SSL_CTX *ctx, + const struct master_service_ssl_settings *set) +{ + DH *dh; + + dh = ssl_proxy_load_dh(set->ssl_dh); + if (SSL_CTX_set_tmp_dh(ctx, dh) != 1) + i_fatal("Can't load DH parameters: %s", openssl_iostream_key_load_error()); + DH_free(dh); +} + #if defined(HAVE_ECDH) && !defined(SSL_CTRL_SET_ECDH_AUTO) static int ssl_proxy_ctx_get_pkey_ec_curve_name(const struct master_service_ssl_settings *set) @@ -1237,6 +1160,7 @@ ssl_server_context_init(const struct login_settings *login_set, ctx->cert = p_strdup(pool, ssl_set->ssl_cert); ctx->key = p_strdup(pool, ssl_set->ssl_key); ctx->ca = p_strdup(pool, ssl_set->ssl_ca); + ctx->dh = p_strdup(pool, ssl_set->ssl_dh); ctx->cipher_list = p_strdup(pool, ssl_set->ssl_cipher_list); ctx->protocols = p_strdup(pool, ssl_set->ssl_protocols); ctx->verify_client_cert = ssl_set->ssl_verify_client_cert || @@ -1273,6 +1197,7 @@ ssl_server_context_init(const struct login_settings *login_set, #endif ssl_proxy_ctx_use_key(ctx->ctx, ssl_set); + ssl_proxy_ctx_use_dh(ctx->ctx, ssl_set); if (ctx->verify_client_cert) ssl_proxy_ctx_verify_client(ctx->ctx, xnames); @@ -1374,7 +1299,6 @@ void ssl_proxy_init(void) (void)RAND_bytes(&buf, 1); memset(&ssl_params, 0, sizeof(ssl_params)); - ssl_params.path = SSL_PARAMETERS_PATH; ssl_proxy_count = 0; ssl_proxies = NULL;