]> git.ipfire.org Git - thirdparty/libvirt.git/commitdiff
rpc: refactor TLS sanity checking to support many cert files
authorDaniel P. Berrangé <berrange@redhat.com>
Mon, 3 Nov 2025 16:44:42 +0000 (16:44 +0000)
committerDaniel P. Berrangé <berrange@redhat.com>
Mon, 24 Nov 2025 15:05:09 +0000 (15:05 +0000)
Future patches will make it possible to load multiple certificate
files. This prepares the sanity checking code to support that by
taking a NUL terminated array of cert filenames.

Reviewed-by: Michal Privoznik <mprivozn@redhat.com>
Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
src/rpc/virnettlscert.c
src/rpc/virnettlscert.h
src/rpc/virnettlscontext.c
tools/virt-pki-validate.c

index 3efc4f071669a7558a504ac20d18b877ec9093e4..e09c8c08abb980dd6cd40c4340797bffcb3ced37 100644 (file)
@@ -440,40 +440,50 @@ int virNetTLSCertLoadListFromFile(const char *certFile,
 #define MAX_CERTS 16
 int virNetTLSCertSanityCheck(bool isServer,
                              const char *cacertFile,
-                             const char *certFile)
+                             const char *const *certFiles)
 {
-    gnutls_x509_crt_t cert = NULL;
+    gnutls_x509_crt_t *certs = NULL;
     gnutls_x509_crt_t cacerts[MAX_CERTS] = { 0 };
     size_t ncacerts = 0;
     size_t i;
     int ret = -1;
 
-    if ((access(certFile, R_OK) == 0) &&
-        !(cert = virNetTLSCertLoadFromFile(certFile, isServer)))
-        goto cleanup;
+    certs = g_new0(gnutls_x509_crt_t, g_strv_length((gchar **)certFiles));
+    for (i = 0; certFiles[i] != NULL; i++) {
+        if ((access(certFiles[i], R_OK) == 0) &&
+            !(certs[i] = virNetTLSCertLoadFromFile(certFiles[i], isServer)))
+            goto cleanup;
+    }
     if ((access(cacertFile, R_OK) == 0) &&
         virNetTLSCertLoadListFromFile(cacertFile, cacerts,
                                       MAX_CERTS, &ncacerts) < 0)
         goto cleanup;
 
-    if (cert &&
-        virNetTLSCertCheck(cert, certFile, isServer, false) < 0)
-        goto cleanup;
+    for (i = 0; certFiles[i] != NULL; i++) {
+        if (certs[i] &&
+            virNetTLSCertCheck(certs[i], certFiles[i], isServer, false) < 0)
+            goto cleanup;
+    }
 
     for (i = 0; i < ncacerts; i++) {
         if (virNetTLSCertCheck(cacerts[i], cacertFile, isServer, true) < 0)
             goto cleanup;
     }
 
-    if (cert && ncacerts &&
-        virNetTLSCertCheckPair(cert, certFile, cacerts, ncacerts, cacertFile, isServer) < 0)
-        goto cleanup;
+    for (i = 0; certFiles[i] != NULL && ncacerts; i++) {
+        if (certs[i] && ncacerts &&
+            virNetTLSCertCheckPair(certs[i], certFiles[i], cacerts, ncacerts, cacertFile, isServer) < 0)
+            goto cleanup;
+    }
 
     ret = 0;
 
  cleanup:
-    if (cert)
-        gnutls_x509_crt_deinit(cert);
+    for (i = 0; certFiles[i] != NULL; i++) {
+        if (certs[i])
+            gnutls_x509_crt_deinit(certs[i]);
+    }
+    g_free(certs);
     for (i = 0; i < ncacerts; i++)
         gnutls_x509_crt_deinit(cacerts[i]);
     return ret;
index a2f591d172c747e8f82c5414e4e2376e4e281ad1..086d8dc7d64412c3ca6b2c6ca24b0658efa64108 100644 (file)
@@ -28,7 +28,7 @@
 
 int virNetTLSCertSanityCheck(bool isServer,
                              const char *cacertFile,
-                             const char *certFile);
+                             const char *const *certFiles);
 
 int virNetTLSCertValidateCA(gnutls_x509_crt_t cert,
                             bool isServer);
index f857bb2339c796a3a999c05a9761e3f7e7f7ec07..bb9db90dff315bedf482aa747470d014dbe88ca1 100644 (file)
@@ -199,6 +199,7 @@ static virNetTLSContext *virNetTLSContextNew(const char *cacert,
 {
     virNetTLSContext *ctxt;
     int err;
+    const char *certs[] = { cert, NULL };
 
     if (virNetTLSContextInitialize() < 0)
         return NULL;
@@ -224,7 +225,7 @@ static virNetTLSContext *virNetTLSContextNew(const char *cacert,
     }
 
     if (sanityCheckCert &&
-        virNetTLSCertSanityCheck(isServer, cacert, cert) < 0)
+        virNetTLSCertSanityCheck(isServer, cacert, certs) < 0)
         goto error;
 
     if (virNetTLSContextLoadCredentials(ctxt, isServer, cacert, cacrl, cert, key) < 0)
@@ -367,6 +368,7 @@ int virNetTLSContextReloadForServer(virNetTLSContext *ctxt,
     g_autofree char *cacrl = NULL;
     g_autofree char *cert = NULL;
     g_autofree char *key = NULL;
+    const char *certs[] = { cert, NULL };
 
     x509credBak = g_steal_pointer(&ctxt->x509cred);
 
@@ -382,7 +384,7 @@ int virNetTLSContextReloadForServer(virNetTLSContext *ctxt,
         goto error;
     }
 
-    if (virNetTLSCertSanityCheck(true, cacert, cert))
+    if (virNetTLSCertSanityCheck(true, cacert, certs))
         goto error;
 
     if (virNetTLSContextLoadCredentials(ctxt, true, cacert, cacrl, cert, key))
index e693ffaed6c30959aa5351af097d3fc0feae370d..0df289256e1ea3ab6ae15f531518a1a5532729ed 100644 (file)
@@ -163,6 +163,7 @@ virPKIValidateIdentity(bool isServer, bool system, const char *path)
 {
     g_autofree char *cacert = NULL, *cacrl = NULL;
     g_autofree char *cert = NULL, *key = NULL;
+    const char *certs[] = { cert, NULL };
     bool ok = true;
     const char *scope = isServer ? "SERVER" : "CLIENT";
 
@@ -274,7 +275,7 @@ virPKIValidateIdentity(bool isServer, bool system, const char *path)
 
     if (virNetTLSCertSanityCheck(isServer,
                                  cacert,
-                                 cert) < 0) {
+                                 certs) < 0) {
         virValidateFail(VIR_VALIDATE_FAIL, "%s",
                         virGetLastErrorMessage());
         ok = false;