]> git.ipfire.org Git - thirdparty/dovecot/core.git/commitdiff
ssl-proxy: Use ssl_dh setting from config
authorAki Tuomi <aki.tuomi@dovecot.fi>
Thu, 3 Mar 2016 10:41:24 +0000 (12:41 +0200)
committerGitLab <gitlab@git.dovecot.net>
Thu, 11 Aug 2016 09:31:19 +0000 (12:31 +0300)
src/login-common/ssl-proxy-openssl.c

index fc9ef65ae28c3f4ed01e3ea703c9a94273c41d7b..3d7fa02963bf969bff4194a3ff24627b34ab93d5 100644 (file)
 #  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;