]> git.ipfire.org Git - thirdparty/apache/httpd.git/commitdiff
Merge r1892782 from trunk:
authorStefan Eissing <icing@apache.org>
Wed, 1 Sep 2021 13:22:19 +0000 (13:22 +0000)
committerStefan Eissing <icing@apache.org>
Wed, 1 Sep 2021 13:22:19 +0000 (13:22 +0000)
  * mod_md: Certificate/keys pairs are verified as matching before a renewal is accepted
    as successful or a staged renewal is replacing the existing certificates.
    This avoid potential mess ups in the md store file system to render the active
    certificates non-working. [@mkauf]

git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/branches/2.4.x@1892783 13f79535-47bb-0310-9956-ffa450edef68

changes-entries/md_check_keys.txt [new file with mode: 0644]
modules/md/md_acme_drive.c
modules/md/md_crypt.c
modules/md/md_crypt.h
modules/md/md_version.h

diff --git a/changes-entries/md_check_keys.txt b/changes-entries/md_check_keys.txt
new file mode 100644 (file)
index 0000000..259c96c
--- /dev/null
@@ -0,0 +1,4 @@
+  * mod_md: Certificate/keys pairs are verified as matching before a renewal is accepted
+    as successful or a staged renewal is replacing the existing certificates.
+    This avoid potential mess ups in the md store file system to render the active
+    certificates non-working. [@mkauf]
index 4956a06aab8b44eb26cb9c11d9392e1263064423..5e3b48cf91e4e6e7ee1cf9e5dde6beb49ed7731a 100644 (file)
@@ -767,6 +767,27 @@ static apr_status_t acme_renew(md_proto_driver_t *d, md_result_t *result)
                     }
                     
                     if (!md_array_is_empty(ad->cred->chain)) {
+
+                        if (!ad->cred->pkey) {
+                            rv = md_pkey_load(d->store, MD_SG_STAGING, d->md->name, ad->cred->spec, &ad->cred->pkey, d->p);
+                            if (APR_SUCCESS != rv) {
+                                md_result_printf(result, rv, "Loading the private key.");
+                                goto out;
+                            }
+                        }
+
+                        if (ad->cred->pkey) {
+                            rv = md_check_cert_and_pkey(ad->cred->chain, ad->cred->pkey);
+                            if (APR_SUCCESS != rv) {
+                                md_result_printf(result, rv, "Certificate and private key do not match.");
+
+                                /* Delete the order */
+                                md_acme_order_purge(d->store, d->p, MD_SG_STAGING, d->md->name, d->env);
+
+                                goto out;
+                            }
+                        }
+
                         rv = md_pubcert_save(d->store, d->p, MD_SG_STAGING, d->md->name, 
                                              ad->cred->spec, ad->cred->chain, 0);
                         if (APR_SUCCESS != rv) {
@@ -901,6 +922,10 @@ static apr_status_t acme_preload(md_proto_driver_t *d, md_store_group_t load_gro
             md_result_printf(result, rv, "no certificate in staged credentials #%d", i);
             goto leave;
         }
+        if (APR_SUCCESS != (rv = md_check_cert_and_pkey(creds->chain, creds->pkey))) {
+            md_result_printf(result, rv, "certificate and private key do not match in staged credentials #%d", i);
+            goto leave;
+        }
         APR_ARRAY_PUSH(all_creds, md_credentials_t*) = creds;
     }
     
index 13c7edde5b9d2e4d4d1c7f88d422083e5ee50ea3..55826be86017b2ee5329bbb08e028465ba3ceabb 100644 (file)
@@ -2014,3 +2014,19 @@ cleanup:
     return rv;
 }
 
+apr_status_t md_check_cert_and_pkey(struct apr_array_header_t *certs, md_pkey_t *pkey)
+{
+    const md_cert_t *cert;
+
+    if (certs->nelts == 0) {
+        return APR_ENOENT;
+    }
+
+    cert = APR_ARRAY_IDX(certs, 0, const md_cert_t*);
+
+    if (1 != X509_check_private_key(cert->x509, pkey->pkey)) {
+        return APR_EGENERAL;
+    }
+
+    return APR_SUCCESS;
+}
index 3aa03fc5a8b3c4330bc6e2825be5f3e3fb149f0f..85e45e4e449d35bec56a611f50b0bdce844ad4f9 100644 (file)
@@ -218,6 +218,9 @@ apr_status_t md_cert_get_ct_scts(apr_array_header_t *scts, apr_pool_t *p, const
 
 apr_status_t md_cert_get_ocsp_responder_url(const char **purl, apr_pool_t *p, const md_cert_t *cert);
 
+apr_status_t md_check_cert_and_pkey(struct apr_array_header_t *certs, md_pkey_t *pkey);
+
+
 /**************************************************************************************************/
 /* X509 certificate transparency */
 
index 53377b840d08e9312f34f2743e2c7a937f2723e1..f76ed708c2489e9a64221ac52e72dde034d8bd4b 100644 (file)
@@ -27,7 +27,7 @@
  * @macro
  * Version number of the md module as c string
  */
-#define MOD_MD_VERSION "2.4.4"
+#define MOD_MD_VERSION "2.4.5"
 
 /**
  * @macro