]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MEDIUM: ssl: load DH param in struct cert_key_and_chain
authorWilliam Lallemand <wlallemand@haproxy.com>
Tue, 23 Jul 2019 14:06:08 +0000 (16:06 +0200)
committerWilliam Lallemand <wlallemand@haproxy.org>
Mon, 29 Jul 2019 13:28:46 +0000 (15:28 +0200)
Load the DH param at the same time as the certificate, we don't need to
open the file once more and read it again. We store it in the ckch_node.

There is a minor change comparing to the previous way of loading the DH
param in a bundle. With a bundle, the DH param in a certificate file was
never loaded, it only used the global DH or the default DH, now it's
able to use the DH param from a certificate file.

src/ssl_sock.c

index 23f7fbb97fbb85d738cbafc9ff933a0157ec3d62..6cbd6da9c66d1a79b69237ce02d7701d0d4a5a77 100644 (file)
@@ -2738,55 +2738,6 @@ int ssl_sock_load_global_dh_param_from_file(const char *filename)
 
        return -1;
 }
-
-/* Loads Diffie-Hellman parameter from a file. Returns 1 if loaded, else -1
-   if an error occurred, and 0 if parameter not found. */
-int ssl_sock_load_dh_params(SSL_CTX *ctx, const char *file)
-{
-       int ret = -1;
-       DH *dh = ssl_sock_get_dh_from_file(file);
-
-       if (dh) {
-               ret = 1;
-               SSL_CTX_set_tmp_dh(ctx, dh);
-
-               if (ssl_dh_ptr_index >= 0) {
-                       /* store a pointer to the DH params to avoid complaining about
-                          ssl-default-dh-param not being set for this SSL_CTX */
-                       SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
-               }
-       }
-       else if (global_dh) {
-               SSL_CTX_set_tmp_dh(ctx, global_dh);
-               ret = 0; /* DH params not found */
-       }
-       else {
-               /* Clear openssl global errors stack */
-               ERR_clear_error();
-
-               if (global_ssl.default_dh_param <= 1024) {
-                       /* we are limited to DH parameter of 1024 bits anyway */
-                       if (local_dh_1024 == NULL)
-                               local_dh_1024 = ssl_get_dh_1024();
-
-                       if (local_dh_1024 == NULL)
-                               goto end;
-
-                       SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
-               }
-               else {
-                       SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
-               }
-
-               ret = 0; /* DH params not found */
-       }
-
-end:
-       if (dh)
-               DH_free(dh);
-
-       return ret;
-}
 #endif
 
 static int ssl_sock_add_cert_sni(SSL_CTX *ctx, struct bind_conf *s, struct ssl_bind_conf *conf,
@@ -2863,6 +2814,7 @@ struct cert_key_and_chain {
        unsigned int num_chain_certs;
        /* This is an array of X509 pointers */
        X509 **chain_certs;
+       DH *dh;
 };
 
 /*
@@ -2898,6 +2850,60 @@ struct sni_keytype {
 };
 
 
+/* Loads Diffie-Hellman parameter from a ckchn. Returns 1 if loaded, else -1
+   if an error occurred, and 0 if parameter not found. */
+#ifndef OPENSSL_NO_DH
+static int ssl_sock_load_dh_params(SSL_CTX *ctx, const struct cert_key_and_chain *ckch)
+{
+       int ret = -1;
+       DH *dh = NULL;
+
+       if (ckch)
+               dh = ckch->dh;
+
+       if (dh) {
+               ret = 1;
+               SSL_CTX_set_tmp_dh(ctx, dh);
+
+               if (ssl_dh_ptr_index >= 0) {
+                       /* store a pointer to the DH params to avoid complaining about
+                          ssl-default-dh-param not being set for this SSL_CTX */
+                       SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, dh);
+               }
+       }
+       else if (global_dh) {
+               SSL_CTX_set_tmp_dh(ctx, global_dh);
+               ret = 0; /* DH params not found */
+       }
+       else {
+               /* Clear openssl global errors stack */
+               ERR_clear_error();
+
+               if (global_ssl.default_dh_param <= 1024) {
+                       /* we are limited to DH parameter of 1024 bits anyway */
+                       if (local_dh_1024 == NULL)
+                               local_dh_1024 = ssl_get_dh_1024();
+
+                       if (local_dh_1024 == NULL)
+                               goto end;
+
+                       SSL_CTX_set_tmp_dh(ctx, local_dh_1024);
+               }
+               else {
+                       SSL_CTX_set_tmp_dh_callback(ctx, ssl_get_tmp_dh);
+               }
+
+               ret = 0; /* DH params not found */
+       }
+
+end:
+       if (dh)
+               DH_free(dh);
+
+       return ret;
+}
+#endif
+
 /* Frees the contents of a cert_key_and_chain
  */
 static void ssl_sock_free_cert_key_and_chain_contents(struct cert_key_and_chain *ckch)
@@ -2980,6 +2986,16 @@ static int ssl_sock_load_crt_file_into_ckch(const char *path, struct cert_key_an
                goto end;
        }
 
+       ckch->dh = PEM_read_bio_DHparams(in, NULL, NULL, NULL);
+       /* no need to check for NULL there, dh is not mandatory */
+
+       /* Seek back to beginning of file */
+       if (BIO_reset(in) == -1) {
+               memprintf(err, "%san error occurred while reading the file '%s'.\n",
+                         err && *err ? *err : "", path);
+               goto end;
+       }
+
        /* Read Certificate */
        ckch->cert = PEM_read_bio_X509_AUX(in, NULL, NULL, NULL);
        if (ckch->cert == NULL) {
@@ -3058,6 +3074,20 @@ static int ssl_sock_put_ckch_into_ctx(const char *path, const struct cert_key_an
                return 1;
        }
 
+#ifndef OPENSSL_NO_DH
+       /* store a NULL pointer to indicate we have not yet loaded
+          a custom DH param file */
+       if (ssl_dh_ptr_index >= 0) {
+               SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
+       }
+
+       if (ssl_sock_load_dh_params(ctx, ckch) < 0) {
+               memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
+                         err && *err ? *err : "", path);
+               return 1;
+       }
+#endif
+
        return 0;
 }
 
@@ -3341,22 +3371,6 @@ static int ssl_sock_load_multi_ckchn(const char *path, struct ckch_node *ckch_n,
                                }
                        }
 
-                       /* Load DH params into the ctx to support DHE keys */
-#ifndef OPENSSL_NO_DH
-                       /* TODO store DH in ckch */
-                       if (ssl_dh_ptr_index >= 0)
-                               SSL_CTX_set_ex_data(cur_ctx, ssl_dh_ptr_index, NULL);
-
-                       rv = ssl_sock_load_dh_params(cur_ctx, NULL);
-                       if (rv < 0) {
-                               if (err)
-                                       memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
-                                                       *err ? *err : "", path);
-                               rv = 1;
-                               goto end;
-                       }
-#endif
-
                        /* Update key_combos */
                        key_combos[i-1].ctx = cur_ctx;
                }
@@ -3498,21 +3512,6 @@ static int ssl_sock_load_ckchn(const char *path, struct ckch_node *ckch_n, struc
        /* we must not free the SSL_CTX anymore below, since it's already in
         * the tree, so it will be discovered and cleaned in time.
         */
-#ifndef OPENSSL_NO_DH
-       /* store a NULL pointer to indicate we have not yet loaded
-          a custom DH param file */
-       if (ssl_dh_ptr_index >= 0) {
-               SSL_CTX_set_ex_data(ctx, ssl_dh_ptr_index, NULL);
-       }
-
-       ret = ssl_sock_load_dh_params(ctx, path);
-       if (ret < 0) {
-               if (err)
-                       memprintf(err, "%sunable to load DH parameters from file '%s'.\n",
-                                 *err ? *err : "", path);
-               return 1;
-       }
-#endif
 
 #if (defined SSL_CTRL_SET_TLSEXT_STATUS_REQ_CB && !defined OPENSSL_NO_OCSP)
        ret = ssl_sock_load_ocsp(ctx, path);