From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762440831; cv=none; d=zohomail.com; s=zohoarc; b=GBZno52haioC1Stfz877m2V7jUldZ42eLwlDqdGcagfXRSZ2wN9kyYgB/DQw3dYmRrUcd6Eph9iuNuMVL3ELKLIKgbWbBLqrbWeRY9xMHELbgYk94wDyxlrWYglV4greZvKxv5STA0MlcxjVVp9IUlEIcEpxw9ULXuoGtHpJlDU= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762440831; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=q7XOoN/jcZyT7tLQPViBnEqRLl6o73urn+OYku2Qfgk=; b=ZErXuqWJMTUEacitS5b/+rholD5077vaWw9xEHwMs6kC+Ejb3pGgA6p0ZEIlqK8+EviVJwEpXDLEvB1J3hYQ51IbebtH3oFLsGbuWg8KwTD7zFYwBUdBwIYZK0TDtnTGKeN2CLAnaM69CAu2SIpAg/oTTnOF8A1gKO9BdqsDSVM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762440831284720.3869260617299; Thu, 6 Nov 2025 06:53:51 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 93C4044203; Thu, 6 Nov 2025 09:53:50 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id DE0EB44226; Thu, 6 Nov 2025 09:51:53 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 539F0418F9; Thu, 6 Nov 2025 09:50:57 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 9D94E41988 for ; Thu, 6 Nov 2025 09:50:56 -0500 (EST) Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-304-G2PqPWrLO62ecw7hGWrZWQ-1; Thu, 06 Nov 2025 09:50:54 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 0A68D180034A for ; Thu, 6 Nov 2025 14:50:54 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id AE1F8180049F; Thu, 6 Nov 2025 14:50:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440656; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=q7XOoN/jcZyT7tLQPViBnEqRLl6o73urn+OYku2Qfgk=; b=XjQLeoUH62Z8MGFN7kzpchiZUgSS9ZMt8LtPA2gGn1pbbA4PTYIc7sJAHN+0aAWdBc3yCn dseLsFz1JNCDN7Xfp4S0XCUuoH189f/UZE5wXDMOOBsSNYTSmB/B2yo/Ex6YBiqEdJxxIX y8P1TGGL6q9GDHVVZZyDZBLz7xvbAQU= X-MC-Unique: G2PqPWrLO62ecw7hGWrZWQ-1 X-Mimecast-MFC-AGG-ID: G2PqPWrLO62ecw7hGWrZWQ_1762440654 To: devel@lists.libvirt.org Subject: [PATCH 01/10] remote: use g_strfreev for free()ing lists of strings Date: Thu, 6 Nov 2025 14:50:41 +0000 Message-ID: <20251106145050.1851526-2-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: x1GjULAhh9-yD9lHq9lZhRsYo3WxjD7ViyMbS4FMWO4_1762440654 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: G7HGAMVMAZWRYADZQRNBALLZWIT3NONO X-Message-ID-Hash: G7HGAMVMAZWRYADZQRNBALLZWIT3NONO X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762440832412154100 From: Daniel P. Berrang=C3=A9 Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/remote/remote_daemon_config.c | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/src/remote/remote_daemon_config.c b/src/remote/remote_daemon_c= onfig.c index 2a41c27dfc..c1e75444e1 100644 --- a/src/remote/remote_daemon_config.c +++ b/src/remote/remote_daemon_config.c @@ -168,8 +168,6 @@ daemonConfigNew(bool privileged G_GNUC_UNUSED) void daemonConfigFree(struct daemonConfig *data) { - char **tmp; - if (!data) return; =20 @@ -179,12 +177,7 @@ daemonConfigFree(struct daemonConfig *data) g_free(data->tcp_port); #endif /* ! WITH_IP */ =20 - tmp =3D data->access_drivers; - while (tmp && *tmp) { - g_free(*tmp); - tmp++; - } - g_free(data->access_drivers); + g_strfreev(data->access_drivers); =20 g_free(data->unix_sock_admin_perms); g_free(data->unix_sock_ro_perms); @@ -192,20 +185,10 @@ daemonConfigFree(struct daemonConfig *data) g_free(data->unix_sock_group); g_free(data->unix_sock_dir); =20 - tmp =3D data->sasl_allowed_username_list; - while (tmp && *tmp) { - g_free(*tmp); - tmp++; - } - g_free(data->sasl_allowed_username_list); + g_strfreev(data->sasl_allowed_username_list); =20 #ifdef WITH_IP - tmp =3D data->tls_allowed_dn_list; - while (tmp && *tmp) { - g_free(*tmp); - tmp++; - } - g_free(data->tls_allowed_dn_list); + g_strfreev(data->tls_allowed_dn_list); =20 g_free(data->tls_priority); =20 --=20 2.51.1 From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762440890; cv=none; d=zohomail.com; s=zohoarc; b=ODrp2rMi6aCCKXObBKrAx7p2X1FsRmbzdHLXHshWpiJLNm2mPMyvDTA3LMapiu+bj7DKQT7fOpff9Dzx4OIFeyJBxoOf/8T/F0l/caE6QMYQboBuPkWbNblEPmXvZ/wAmWxQ3aEEidKU0Kh3GNYSNJcT6JpJwsU3ef1p+AG453k= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762440890; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=NncVV7PlF1uzQTurF9tZ53W0FcqUFjHJ7UYs/X141rI=; b=DBM6WBbr87AM6MbrUN8y63gX4Ow/UTS6kkuXugrT6o1fgNAtY5qfTgN44uSaIT5pnfYI1Lk7ypcLRyYe6Jmvb17MCX46g2huA9KpNinoJEyvQTRs7p3hKjoNshDIrI32B9v5x8aM61dCpOTTiaf2183hY5cV6adXyufh7iZkowU= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762440890593346.9715208566158; Thu, 6 Nov 2025 06:54:50 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id EF71544377; Thu, 6 Nov 2025 09:54:49 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 6D5FA44265; Thu, 6 Nov 2025 09:51:58 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id DEEF4418F9; Thu, 6 Nov 2025 09:50:59 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id DCA6941988 for ; Thu, 6 Nov 2025 09:50:58 -0500 (EST) Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-541-dOxMzxfiPAG_sTSAAN0byg-1; Thu, 06 Nov 2025 09:50:56 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 64F4C1956070 for ; Thu, 6 Nov 2025 14:50:55 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 855CB1800451; Thu, 6 Nov 2025 14:50:54 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440658; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=NncVV7PlF1uzQTurF9tZ53W0FcqUFjHJ7UYs/X141rI=; b=W7QS7Vmuyl+8Ngzow9iM0JtBs7ZdtSu3xW7sT8bEOBFAUXtuMaW3ZyzFBE3it8a6yVPpe4 Lg7ObX2JJ3KHiWJCsCPsc83DLVZTqUOGteC10t9rz2R575hkMIqKQeH76Jo5LHI8Y02EM1 3bRm5D/fzhmXlw+QH4V+vPjBNWl9Y7Y= X-MC-Unique: dOxMzxfiPAG_sTSAAN0byg-1 X-Mimecast-MFC-AGG-ID: dOxMzxfiPAG_sTSAAN0byg_1762440655 To: devel@lists.libvirt.org Subject: [PATCH 02/10] rpc: change 'isServer' parameter from 'int' to 'bool' Date: Thu, 6 Nov 2025 14:50:42 +0000 Message-ID: <20251106145050.1851526-3-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: kk2aqI8h1sLnN3vYPjcdvvLq4JFEQEz4MQyy8nowV-4_1762440655 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 4HZESDOODK24FN5EL5I7HKYHYHEFXFW5 X-Message-ID-Hash: 4HZESDOODK24FN5EL5I7HKYHYHEFXFW5 X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762440892997154100 From: Daniel P. Berrang=C3=A9 The callers are all passing in a 'bool' value, and this type should be maintained rather than cast to 'int' and then inpreted as a bool again later. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/rpc/virnettlsconfig.c | 14 +++++++------- src/rpc/virnettlsconfig.h | 13 +++++++------ 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/src/rpc/virnettlsconfig.c b/src/rpc/virnettlsconfig.c index d020083d6a..ffab3b4fc8 100644 --- a/src/rpc/virnettlsconfig.c +++ b/src/rpc/virnettlsconfig.c @@ -49,7 +49,7 @@ static void virNetTLSConfigTrust(const char *cacertdir, VIR_DEBUG("TLS CA CRL %s", *cacrl); } =20 -static void virNetTLSConfigIdentity(int isServer, +static void virNetTLSConfigIdentity(bool isServer, const char *certdir, const char *keydir, char **cert, @@ -102,7 +102,7 @@ void virNetTLSConfigSystemTrust(char **cacert, } =20 void virNetTLSConfigCustomIdentity(const char *pkipath, - int isServer, + bool isServer, char **cert, char **key) { @@ -114,7 +114,7 @@ void virNetTLSConfigCustomIdentity(const char *pkipath, key); } =20 -void virNetTLSConfigUserIdentity(int isServer, +void virNetTLSConfigUserIdentity(bool isServer, char **cert, char **key) { @@ -129,7 +129,7 @@ void virNetTLSConfigUserIdentity(int isServer, key); } =20 -void virNetTLSConfigSystemIdentity(int isServer, +void virNetTLSConfigSystemIdentity(bool isServer, char **cert, char **key) { @@ -143,7 +143,7 @@ void virNetTLSConfigSystemIdentity(int isServer, } =20 void virNetTLSConfigCustomCreds(const char *pkipath, - int isServer, + bool isServer, char **cacert, char **cacrl, char **cert, @@ -161,7 +161,7 @@ void virNetTLSConfigCustomCreds(const char *pkipath, key); } =20 -void virNetTLSConfigUserCreds(int isServer, +void virNetTLSConfigUserCreds(bool isServer, char **cacert, char **cacrl, char **cert, @@ -182,7 +182,7 @@ void virNetTLSConfigUserCreds(int isServer, key); } =20 -void virNetTLSConfigSystemCreds(int isServer, +void virNetTLSConfigSystemCreds(bool isServer, char **cacert, char **cacrl, char **cert, diff --git a/src/rpc/virnettlsconfig.h b/src/rpc/virnettlsconfig.h index 797b3e3ac5..a9378c18b7 100644 --- a/src/rpc/virnettlsconfig.h +++ b/src/rpc/virnettlsconfig.h @@ -20,6 +20,7 @@ =20 #pragma once =20 +#include "internal.h" #include "configmake.h" =20 #define LIBVIRT_PKI_DIR SYSCONFDIR "/pki" @@ -39,29 +40,29 @@ void virNetTLSConfigSystemTrust(char **cacert, char **cacrl); =20 void virNetTLSConfigCustomIdentity(const char *pkipath, - int isServer, + bool isServer, char **cert, char **key); -void virNetTLSConfigUserIdentity(int isServer, +void virNetTLSConfigUserIdentity(bool isServer, char **cert, char **key); -void virNetTLSConfigSystemIdentity(int isServer, +void virNetTLSConfigSystemIdentity(bool isServer, char **cert, char **key); =20 =20 void virNetTLSConfigCustomCreds(const char *pkipath, - int isServer, + bool isServer, char **cacert, char **cacrl, char **cert, char **key); -void virNetTLSConfigUserCreds(int isServer, +void virNetTLSConfigUserCreds(bool isServer, char **cacert, char **cacrl, char **cert, char **key); -void virNetTLSConfigSystemCreds(int isServer, +void virNetTLSConfigSystemCreds(bool isServer, char **cacert, char **cacrl, char **cert, --=20 2.51.1 From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762441095; cv=none; d=zohomail.com; s=zohoarc; b=M17hcxoU5LuT6jFK2EQjTYXz2N/FrK2PckjkhPhcaJ1EMv8Kk5Pxga9uGC8GO+rxr+w3Y4OOTKXa/g5RW/UmRnwomAvlf/dUCfeQsTAk7g13U7l1kE1IhnMLANLoidU2YfiR40g83V+E4M6A34Xk81M4yTo5Ek8AP0kQ0afKONg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762441095; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=RWZsjJPrPxO1Tez6nzN1ZJa9A0bj9Cl0yhG9jW1qHFo=; b=aE2xuqpH9rlmACkxaJvB38V9zfUhDawrecVGq4wIpYYtxdhFqdEXqMKfRv6oiAmXDTy6C68C99X1KlmFBf33rNRLspKPw5VFgz8ZqyhAuwCbRmePE0SXSXrZh3j+H/J4MPg1rR08oKjg5i6sSuTEfq2kwEhJ3Z/JQQGh67VPKaY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762441095879291.6096382340712; Thu, 6 Nov 2025 06:58:15 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 3E93D44103; Thu, 6 Nov 2025 09:58:15 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 5C96A4415E; Thu, 6 Nov 2025 09:52:33 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id BA618418F9; Thu, 6 Nov 2025 09:51:04 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 29C40418F9 for ; Thu, 6 Nov 2025 09:51:03 -0500 (EST) Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-452-Y7PrB8c-Payp6rvzcGre7Q-1; Thu, 06 Nov 2025 09:50:57 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C6FA2180034A for ; Thu, 6 Nov 2025 14:50:56 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D56C61800451; Thu, 6 Nov 2025 14:50:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440662; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=RWZsjJPrPxO1Tez6nzN1ZJa9A0bj9Cl0yhG9jW1qHFo=; b=Fzf96aP7b6Omc7q0fSuhIm6eyMJWdMiavmGPUFydHgUyQ007ofUy4nraTrsUnYcbSqDxSu I/hIBcRiM4KApPuvLa4oS5GxtzQng0/gsnoLf2U28Rgbp8XFYGeaPuk00CzD3jlhTO8zM1 zjBtCzAr2AieuyX2GEUKam0pMSanQdc= X-MC-Unique: Y7PrB8c-Payp6rvzcGre7Q-1 X-Mimecast-MFC-AGG-ID: Y7PrB8c-Payp6rvzcGre7Q_1762440656 To: devel@lists.libvirt.org Subject: [PATCH 03/10] rpc: refactor TLS sanity checking to support many cert files Date: Thu, 6 Nov 2025 14:50:43 +0000 Message-ID: <20251106145050.1851526-4-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: z40hrGnkm0UnxpaqEigwvhte0RxA6OLGlLXa3kHP2TE_1762440656 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: EX65CXHDMF7ZC2N5H3EH3P2IPKN6SKUY X-Message-ID-Hash: EX65CXHDMF7ZC2N5H3EH3P2IPKN6SKUY X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762441098501154100 From: Daniel P. Berrang=C3=A9 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. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/rpc/virnettlscert.c | 35 ++++++++++++++++++++++------------- src/rpc/virnettlscert.h | 2 +- src/rpc/virnettlscontext.c | 6 ++++-- tools/virt-pki-validate.c | 3 ++- 4 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/rpc/virnettlscert.c b/src/rpc/virnettlscert.c index 3efc4f0716..6f20b2601b 100644 --- a/src/rpc/virnettlscert.c +++ b/src/rpc/virnettlscert.c @@ -440,40 +440,49 @@ int virNetTLSCertLoadListFromFile(const char *certFil= e, #define MAX_CERTS 16 int virNetTLSCertSanityCheck(bool isServer, const char *cacertFile, - const char *certFile) + const char *const *certFiles) { - gnutls_x509_crt_t cert =3D NULL; + gnutls_x509_crt_t *certs =3D NULL; gnutls_x509_crt_t cacerts[MAX_CERTS] =3D { 0 }; size_t ncacerts =3D 0; size_t i; int ret =3D -1; =20 - if ((access(certFile, R_OK) =3D=3D 0) && - !(cert =3D virNetTLSCertLoadFromFile(certFile, isServer))) - goto cleanup; + certs =3D g_new0(gnutls_x509_crt_t, g_strv_length((gchar **)certFiles)= ); + for (i =3D 0; certFiles[i] !=3D NULL; i++) { + if ((access(certFiles[i], R_OK) =3D=3D 0) && + !(certs[i] =3D virNetTLSCertLoadFromFile(certFiles[i], isServe= r))) + goto cleanup; + } if ((access(cacertFile, R_OK) =3D=3D 0) && virNetTLSCertLoadListFromFile(cacertFile, cacerts, MAX_CERTS, &ncacerts) < 0) goto cleanup; =20 - if (cert && - virNetTLSCertCheck(cert, certFile, isServer, false) < 0) - goto cleanup; + for (i =3D 0; certFiles[i] !=3D NULL; i++) { + if (certs[i] && + virNetTLSCertCheck(certs[i], certFiles[i], isServer, false) < = 0) + goto cleanup; + } =20 for (i =3D 0; i < ncacerts; i++) { if (virNetTLSCertCheck(cacerts[i], cacertFile, isServer, true) < 0) goto cleanup; } =20 - if (cert && ncacerts && - virNetTLSCertCheckPair(cert, certFile, cacerts, ncacerts, cacertFi= le, isServer) < 0) - goto cleanup; + for (i =3D 0; certFiles[i] !=3D NULL && ncacerts; i++) { + if (certs[i] && ncacerts && + virNetTLSCertCheckPair(certs[i], certFiles[i], cacerts, ncacer= ts, cacertFile, isServer) < 0) + goto cleanup; + } =20 ret =3D 0; =20 cleanup: - if (cert) - gnutls_x509_crt_deinit(cert); + for (i =3D 0; certFiles[i] !=3D NULL; i++) { + if (certs[i]) + gnutls_x509_crt_deinit(certs[i]); + } for (i =3D 0; i < ncacerts; i++) gnutls_x509_crt_deinit(cacerts[i]); return ret; diff --git a/src/rpc/virnettlscert.h b/src/rpc/virnettlscert.h index a2f591d172..086d8dc7d6 100644 --- a/src/rpc/virnettlscert.h +++ b/src/rpc/virnettlscert.h @@ -28,7 +28,7 @@ =20 int virNetTLSCertSanityCheck(bool isServer, const char *cacertFile, - const char *certFile); + const char *const *certFiles); =20 int virNetTLSCertValidateCA(gnutls_x509_crt_t cert, bool isServer); diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c index f857bb2339..bb9db90dff 100644 --- a/src/rpc/virnettlscontext.c +++ b/src/rpc/virnettlscontext.c @@ -199,6 +199,7 @@ static virNetTLSContext *virNetTLSContextNew(const char= *cacert, { virNetTLSContext *ctxt; int err; + const char *certs[] =3D { cert, NULL }; =20 if (virNetTLSContextInitialize() < 0) return NULL; @@ -224,7 +225,7 @@ static virNetTLSContext *virNetTLSContextNew(const char= *cacert, } =20 if (sanityCheckCert && - virNetTLSCertSanityCheck(isServer, cacert, cert) < 0) + virNetTLSCertSanityCheck(isServer, cacert, certs) < 0) goto error; =20 if (virNetTLSContextLoadCredentials(ctxt, isServer, cacert, cacrl, cer= t, key) < 0) @@ -367,6 +368,7 @@ int virNetTLSContextReloadForServer(virNetTLSContext *c= txt, g_autofree char *cacrl =3D NULL; g_autofree char *cert =3D NULL; g_autofree char *key =3D NULL; + const char *certs[] =3D { cert, NULL }; =20 x509credBak =3D g_steal_pointer(&ctxt->x509cred); =20 @@ -382,7 +384,7 @@ int virNetTLSContextReloadForServer(virNetTLSContext *c= txt, goto error; } =20 - if (virNetTLSCertSanityCheck(true, cacert, cert)) + if (virNetTLSCertSanityCheck(true, cacert, certs)) goto error; =20 if (virNetTLSContextLoadCredentials(ctxt, true, cacert, cacrl, cert, k= ey)) diff --git a/tools/virt-pki-validate.c b/tools/virt-pki-validate.c index e693ffaed6..0df289256e 100644 --- a/tools/virt-pki-validate.c +++ b/tools/virt-pki-validate.c @@ -163,6 +163,7 @@ virPKIValidateIdentity(bool isServer, bool system, cons= t char *path) { g_autofree char *cacert =3D NULL, *cacrl =3D NULL; g_autofree char *cert =3D NULL, *key =3D NULL; + const char *certs[] =3D { cert, NULL }; bool ok =3D true; const char *scope =3D isServer ? "SERVER" : "CLIENT"; =20 @@ -274,7 +275,7 @@ virPKIValidateIdentity(bool isServer, bool system, cons= t char *path) =20 if (virNetTLSCertSanityCheck(isServer, cacert, - cert) < 0) { + certs) < 0) { virValidateFail(VIR_VALIDATE_FAIL, "%s", virGetLastErrorMessage()); ok =3D false; --=20 2.51.1 From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762440974; cv=none; d=zohomail.com; s=zohoarc; b=m5Aw8py1ePjxwYPu70itYzpIIDsBzPe6sQlXVneuR58Fr9GJYcBhBjj1+vc3JOpULKI8Dcg4C0++lwmHc0e9g6WBA6Cq1yTc6LcNEACkVd/2drh7DmNjvoABavdYgYB1Fp7/Njmo1fG4S78HyeNwiIUz8EDfoAm+3oBkHmFY9rA= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762440974; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=U6rN1M84Jv3rrVJYApPeMG1V1JqMOjq0KMYulgCd33E=; b=UMjwWBpRZxgAagu9ePIURGR7fD+1QfWd6yEgG9q2Y0gQJ8uJpSr3NqFj4UUcYyW+qrS1WYJT6hRqVby72PyeB1pYlA/mf1Gz+WsnQKZtxVIXuQPhYnm933LXs8W00MuzoADgxXAYalU/EobbmgJdyEzEIV8q83HrtRP/MlMI5lQ= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762440974603945.885815928218; Thu, 6 Nov 2025 06:56:14 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 10DB24420D; Thu, 6 Nov 2025 09:56:14 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id A42DE4425B; Thu, 6 Nov 2025 09:52:03 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id E6383418F9; Thu, 6 Nov 2025 09:51:02 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id A1A9941988 for ; Thu, 6 Nov 2025 09:51:01 -0500 (EST) Received: from mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-370-2HmAZ2V9N7CvSljXnQljCA-1; Thu, 06 Nov 2025 09:51:00 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-01.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 3D83D19539A7 for ; Thu, 6 Nov 2025 14:50:58 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 2F2C3180049F; Thu, 6 Nov 2025 14:50:57 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440661; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=U6rN1M84Jv3rrVJYApPeMG1V1JqMOjq0KMYulgCd33E=; b=bSeW6WWZgymMHfH4fTlebMs6JPm8eXXmftjs08wH5EGeqlFGu+g23tDD2Lz+EGiZNwd4tQ m/Ckm6LvrJTwSNoxcyRi9cpbnt7L0/UBxd7T7KE0/Bdrv1cENnXd8LUnOEehtPwBisI1Gv VuYjMrdoNWtxBjGMt0QXSU73DP6E8ZU= X-MC-Unique: 2HmAZ2V9N7CvSljXnQljCA-1 X-Mimecast-MFC-AGG-ID: 2HmAZ2V9N7CvSljXnQljCA_1762440658 To: devel@lists.libvirt.org Subject: [PATCH 04/10] rpc: add support for loading multiple certs & keys Date: Thu, 6 Nov 2025 14:50:44 +0000 Message-ID: <20251106145050.1851526-5-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: h31e2dCFqrIRpTkKxSJkSzzWDS8yMteg2vZt8w4wop4_1762440658 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: EER4EFB3Z3X67DXNWKW3U6R7B67AIJQK X-Message-ID-Hash: EER4EFB3Z3X67DXNWKW3U6R7B67AIJQK X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762440975665154100 From: Daniel P. Berrang=C3=A9 In the transition to Post-Quantum Cryptography, it will often be desirable to load multiple sets of certificates, some with RSA/ECC and some with MLDSA. This extends the TLS context code to support the loading of many certs, passed as a NULL terminated array. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/libvirt_probes.d | 3 ++- src/remote/remote_daemon.c | 6 +++-- src/rpc/virnettlscontext.c | 51 ++++++++++++++++++++---------------- src/rpc/virnettlscontext.h | 26 +++++++++--------- tests/virnettlscontexttest.c | 10 ++++--- tests/virnettlssessiontest.c | 9 ++++--- 6 files changed, 58 insertions(+), 47 deletions(-) diff --git a/src/libvirt_probes.d b/src/libvirt_probes.d index 6fac10a2bf..d9e75d9797 100644 --- a/src/libvirt_probes.d +++ b/src/libvirt_probes.d @@ -54,7 +54,8 @@ provider libvirt { # file: src/rpc/virnettlscontext.c # prefix: rpc probe rpc_tls_context_new(void *ctxt, const char *cacert, const char *cac= rl, - const char *cert, const char *key, int sanityCheckCert, int requireV= alidCert, int isServer); + const char **cert, const char **keys, + int sanityCheckCert, int requireValidCert, int isServer); probe rpc_tls_context_dispose(void *ctxt); probe rpc_tls_context_session_allow(void *ctxt, void *sess, const char *d= name); probe rpc_tls_context_session_deny(void *ctxt, void *sess, const char *dn= ame); diff --git a/src/remote/remote_daemon.c b/src/remote/remote_daemon.c index 2973813548..e7c8f587c4 100644 --- a/src/remote/remote_daemon.c +++ b/src/remote/remote_daemon.c @@ -327,6 +327,9 @@ daemonSetupNetworking(virNetServer *srv, if (config->ca_file || config->cert_file || config->key_file) { + const char *certs[] =3D { config->cert_file, NULL }; + const char *keys[] =3D { config->key_file, NULL }; + if (!config->ca_file) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", _("No CA certificate path set to match serv= er key/cert")); @@ -346,8 +349,7 @@ daemonSetupNetworking(virNetServer *srv, config->ca_file, config->cert_file, config->key_file= ); if (!(ctxt =3D virNetTLSContextNewServer(config->ca_file, config->crl_file, - config->cert_file, - config->key_file, + certs, keys, (const char *const*)con= fig->tls_allowed_dn_list, config->tls_priority, config->tls_no_sanity_c= ertificate ? false : true, diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c index bb9db90dff..5e9c262b48 100644 --- a/src/rpc/virnettlscontext.c +++ b/src/rpc/virnettlscontext.c @@ -115,10 +115,11 @@ static int virNetTLSContextLoadCredentials(virNetTLSC= ontext *ctxt, bool isServer, const char *cacert, const char *cacrl, - const char *cert, - const char *key) + const char *const *certs, + const char *const *keys) { int err; + size_t i; =20 if (cacert && cacert[0] !=3D '\0') { if (virNetTLSContextCheckCertFile("CA certificate", cacert, false)= < 0) @@ -157,29 +158,29 @@ static int virNetTLSContextLoadCredentials(virNetTLSC= ontext *ctxt, } } =20 - if (cert && cert[0] !=3D '\0' && key && key[0] !=3D '\0') { + for (i =3D 0; certs[i] !=3D NULL && keys[i] !=3D NULL; i++) { int rv; - if ((rv =3D virNetTLSContextCheckCertFile("certificate", cert, !is= Server)) < 0) + if ((rv =3D virNetTLSContextCheckCertFile("certificate", certs[i],= !isServer)) < 0) return -1; if (rv =3D=3D 0 && - (rv =3D virNetTLSContextCheckCertFile("private key", key, !isS= erver)) < 0) + (rv =3D virNetTLSContextCheckCertFile("private key", keys[i], = !isServer)) < 0) return -1; =20 if (rv =3D=3D 0) { - VIR_DEBUG("loading cert and key from %s and %s", cert, key); + VIR_DEBUG("loading cert and key from %s and %s", certs[i], key= s[i]); err =3D gnutls_certificate_set_x509_key_file(ctxt->x509cred, - cert, key, + certs[i], keys[i], GNUTLS_X509_FMT_PEM); if (err < 0) { virReportError(VIR_ERR_SYSTEM_ERROR, _("Unable to set x509 key and certificate: = %1$s, %2$s: %3$s"), - key, cert, gnutls_strerror(err)); + keys[i], certs[i], gnutls_strerror(err)); return -1; } } else { VIR_DEBUG("Skipping non-existent cert %s key %s on client", - cert, key); + certs[i], keys[i]); } } =20 @@ -189,8 +190,8 @@ static int virNetTLSContextLoadCredentials(virNetTLSCon= text *ctxt, =20 static virNetTLSContext *virNetTLSContextNew(const char *cacert, const char *cacrl, - const char *cert, - const char *key, + const char *const *certs, + const char *const *keys, const char *const *x509dnACL, const char *priority, bool sanityCheckCert, @@ -199,7 +200,6 @@ static virNetTLSContext *virNetTLSContextNew(const char= *cacert, { virNetTLSContext *ctxt; int err; - const char *certs[] =3D { cert, NULL }; =20 if (virNetTLSContextInitialize() < 0) return NULL; @@ -228,7 +228,8 @@ static virNetTLSContext *virNetTLSContextNew(const char= *cacert, virNetTLSCertSanityCheck(isServer, cacert, certs) < 0) goto error; =20 - if (virNetTLSContextLoadCredentials(ctxt, isServer, cacert, cacrl, cer= t, key) < 0) + if (virNetTLSContextLoadCredentials(ctxt, isServer, cacert, cacrl, + certs, keys) < 0) goto error; =20 ctxt->requireValidCert =3D requireValidCert; @@ -236,8 +237,8 @@ static virNetTLSContext *virNetTLSContextNew(const char= *cacert, ctxt->isServer =3D isServer; =20 PROBE(RPC_TLS_CONTEXT_NEW, - "ctxt=3D%p cacert=3D%s cacrl=3D%s cert=3D%s key=3D%s sanityCheck= Cert=3D%d requireValidCert=3D%d isServer=3D%d", - ctxt, cacert, NULLSTR(cacrl), cert, key, sanityCheckCert, requir= eValidCert, isServer); + "ctxt=3D%p cacert=3D%s cacrl=3D%s cert=3D%p key=3D%p sanityCheck= Cert=3D%d requireValidCert=3D%d isServer=3D%d", + ctxt, cacert, NULLSTR(cacrl), certs, keys, sanityCheckCert, requ= ireValidCert, isServer); =20 return ctxt; =20 @@ -313,12 +314,14 @@ static virNetTLSContext *virNetTLSContextNewPath(cons= t char *pkipath, g_autofree char *cacrl =3D NULL; g_autofree char *key =3D NULL; g_autofree char *cert =3D NULL; + const char *certs[] =3D { cert, NULL }; + const char *keys[] =3D { key, NULL }; =20 if (virNetTLSContextLocateCredentials(pkipath, tryUserPkiPath, isServe= r, &cacert, &cacrl, &cert, &key) < = 0) return NULL; =20 - return virNetTLSContextNew(cacert, cacrl, cert, key, + return virNetTLSContextNew(cacert, cacrl, certs, keys, x509dnACL, priority, sanityCheckCert, requireValidCert, isServer); } @@ -347,14 +350,14 @@ virNetTLSContext *virNetTLSContextNewClientPath(const= char *pkipath, =20 virNetTLSContext *virNetTLSContextNewServer(const char *cacert, const char *cacrl, - const char *cert, - const char *key, + const char *const *certs, + const char *const *keys, const char *const *x509dnACL, const char *priority, bool sanityCheckCert, bool requireValidCert) { - return virNetTLSContextNew(cacert, cacrl, cert, key, x509dnACL, priori= ty, + return virNetTLSContextNew(cacert, cacrl, certs, keys, x509dnACL, prio= rity, sanityCheckCert, requireValidCert, true); } =20 @@ -369,6 +372,7 @@ int virNetTLSContextReloadForServer(virNetTLSContext *c= txt, g_autofree char *cert =3D NULL; g_autofree char *key =3D NULL; const char *certs[] =3D { cert, NULL }; + const char *keys[] =3D { key, NULL }; =20 x509credBak =3D g_steal_pointer(&ctxt->x509cred); =20 @@ -387,7 +391,8 @@ int virNetTLSContextReloadForServer(virNetTLSContext *c= txt, if (virNetTLSCertSanityCheck(true, cacert, certs)) goto error; =20 - if (virNetTLSContextLoadCredentials(ctxt, true, cacert, cacrl, cert, k= ey)) + if (virNetTLSContextLoadCredentials(ctxt, true, cacert, cacrl, + certs, keys)) goto error; =20 gnutls_certificate_free_credentials(x509credBak); @@ -404,13 +409,13 @@ int virNetTLSContextReloadForServer(virNetTLSContext = *ctxt, =20 virNetTLSContext *virNetTLSContextNewClient(const char *cacert, const char *cacrl, - const char *cert, - const char *key, + const char *const *certs, + const char *const *keys, const char *priority, bool sanityCheckCert, bool requireValidCert) { - return virNetTLSContextNew(cacert, cacrl, cert, key, NULL, priority, + return virNetTLSContextNew(cacert, cacrl, certs, keys, NULL, priority, sanityCheckCert, requireValidCert, false); } =20 diff --git a/src/rpc/virnettlscontext.h b/src/rpc/virnettlscontext.h index 11c954ce4b..1e67171e3e 100644 --- a/src/rpc/virnettlscontext.h +++ b/src/rpc/virnettlscontext.h @@ -44,21 +44,21 @@ virNetTLSContext *virNetTLSContextNewClientPath(const c= har *pkipath, bool requireValidCert); =20 virNetTLSContext *virNetTLSContextNewServer(const char *cacert, - const char *cacrl, - const char *cert, - const char *key, - const char *const *x509dnACL, - const char *priority, - bool sanityCheckCert, - bool requireValidCert); + const char *cacrl, + const char *const *certs, + const char *const *keys, + const char *const *x509dnACL, + const char *priority, + bool sanityCheckCert, + bool requireValidCert); =20 virNetTLSContext *virNetTLSContextNewClient(const char *cacert, - const char *cacrl, - const char *cert, - const char *key, - const char *priority, - bool sanityCheckCert, - bool requireValidCert); + const char *cacrl, + const char *const *certs, + const char *const *keys, + const char *priority, + bool sanityCheckCert, + bool requireValidCert); =20 int virNetTLSContextReloadForServer(virNetTLSContext *ctxt, bool tryUserPkiPath); diff --git a/tests/virnettlscontexttest.c b/tests/virnettlscontexttest.c index 48bdefdd76..47675bffd0 100644 --- a/tests/virnettlscontexttest.c +++ b/tests/virnettlscontexttest.c @@ -56,12 +56,14 @@ static int testTLSContextInit(const void *opaque) struct testTLSContextData *data =3D (struct testTLSContextData *)opaqu= e; virNetTLSContext *ctxt =3D NULL; int ret =3D -1; + const char *certs[] =3D { data->crt, NULL }; + const char *keys[] =3D { KEYFILE, NULL }; =20 if (data->isServer) { ctxt =3D virNetTLSContextNewServer(data->cacrt, NULL, - data->crt, - KEYFILE, + certs, + keys, NULL, "NORMAL", true, @@ -69,8 +71,8 @@ static int testTLSContextInit(const void *opaque) } else { ctxt =3D virNetTLSContextNewClient(data->cacrt, NULL, - data->crt, - KEYFILE, + certs, + keys, "NORMAL", true, true); diff --git a/tests/virnettlssessiontest.c b/tests/virnettlssessiontest.c index 459e17c52c..e8d64c7da0 100644 --- a/tests/virnettlssessiontest.c +++ b/tests/virnettlssessiontest.c @@ -81,6 +81,9 @@ static int testTLSSessionInit(const void *opaque) int channel[2]; bool clientShake =3D false; bool serverShake =3D false; + const char *keys[] =3D { KEYFILE, NULL }; + const char *clientcerts[] =3D { data->clientcrt, NULL }; + const char *servercerts[] =3D { data->servercrt, NULL }; =20 =20 /* We'll use this for our fake client-server connection */ @@ -102,8 +105,7 @@ static int testTLSSessionInit(const void *opaque) */ serverCtxt =3D virNetTLSContextNewServer(data->servercacrt, NULL, - data->servercrt, - KEYFILE, + servercerts, keys, data->wildcards, "NORMAL", false, @@ -111,8 +113,7 @@ static int testTLSSessionInit(const void *opaque) =20 clientCtxt =3D virNetTLSContextNewClient(data->clientcacrt, NULL, - data->clientcrt, - KEYFILE, + clientcerts, keys, "NORMAL", false, true); --=20 2.51.1 From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762441039; cv=none; d=zohomail.com; s=zohoarc; b=FlZ91ZA6rPhSl60o1QFxDcO6Dt7uH8ii6IqP8R7NcBV4BYHlk9f8x7lY78YKVy355xR6Sx7CvDcMepqbp0/29Lv6xNrDr8qcI4OR6J+TLRK+5uhy+/aRY9bcn3+/For1CZZOB1u/nLEfyYbY7gvMTiQbiLlnioqWroaGEzagNHk= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762441039; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=2d9390SXb5Gl235SqR9mvhbiro7OQzvqvzTB/izdu98=; b=ebd0iTH56lkuKma286Bj/fzBcJU4DCTS5+85njGuQADCPW01vgSzWOV3YZFR1bMXdqDdBEVcM8MwttGGfRtilJINvxHVb/sKgtJ6GpvDobVV6cXOrzZckCv+MMtRdmHBmdMW4iCXoZf2gfCvsH00PBters7g63BAZDIiQx64uIA= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762441038912774.9531596579922; Thu, 6 Nov 2025 06:57:18 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 4570D41881; Thu, 6 Nov 2025 09:57:18 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 08B0B44212; Thu, 6 Nov 2025 09:52:23 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 33F27440F9; Thu, 6 Nov 2025 09:51:04 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id AD9E7440C2 for ; Thu, 6 Nov 2025 09:51:02 -0500 (EST) Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-79-zF7yCI4HO6q_vMNxKBBKow-1; Thu, 06 Nov 2025 09:51:01 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 76E7A195608F for ; Thu, 6 Nov 2025 14:50:59 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 9B8DD1800361; Thu, 6 Nov 2025 14:50:58 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440662; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=2d9390SXb5Gl235SqR9mvhbiro7OQzvqvzTB/izdu98=; b=SJCEHZ69kEOW5eUGvyFYbCW2ZGMI3gcX5mnCMrFHCvC5PbsP1BdIzPdgmPkhNu5UzY9n8b IwB/mItE94/eWQO+HC8sytJydsXqK3CVDuoSvUbUvznwgAMH6Cf+XDljH+r/0r7gbp9utG efnSYgwd634/ZfEaC7oR1/5EIvWBg1U= X-MC-Unique: zF7yCI4HO6q_vMNxKBBKow-1 X-Mimecast-MFC-AGG-ID: zF7yCI4HO6q_vMNxKBBKow_1762440659 To: devel@lists.libvirt.org Subject: [PATCH 05/10] remote: support specifying multiple keys/certs in libvirtd.conf Date: Thu, 6 Nov 2025 14:50:45 +0000 Message-ID: <20251106145050.1851526-6-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: SxOpgUf2_kh8vIM_PV9tpRP54YgEcUNZ-27TRsolz24_1762440659 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: B74Z23REYQI4PAQYI46I64LHDX7MUQC2 X-Message-ID-Hash: B74Z23REYQI4PAQYI46I64LHDX7MUQC2 X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762441040429154100 From: Daniel P. Berrang=C3=A9 The 'cert_file' and 'key_file' parameters in libvirtd.conf only permit a single cert/key. To support hybrid deployments for PQC, we need to be able to request multiple certs/keys. This involves new 'cert_files' and 'key_files' config parameters that accept a list of filenames. The new parameters are mutually exclusive with the old parameters. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/remote/libvirtd.aug.in | 2 ++ src/remote/libvirtd.conf.in | 16 ++++++++++++ src/remote/remote_daemon.c | 26 +++++++++---------- src/remote/remote_daemon_config.c | 43 +++++++++++++++++++++++++++---- src/remote/remote_daemon_config.h | 4 +-- src/remote/test_libvirtd.aug.in | 8 ++++++ 6 files changed, 79 insertions(+), 20 deletions(-) diff --git a/src/remote/libvirtd.aug.in b/src/remote/libvirtd.aug.in index d744548f41..1f3bb5d0e2 100644 --- a/src/remote/libvirtd.aug.in +++ b/src/remote/libvirtd.aug.in @@ -47,6 +47,8 @@ module @DAEMON_NAME_UC@ =3D =20 let certificate_entry =3D str_entry "key_file" | str_entry "cert_file" + | str_array_entry "key_files" + | str_array_entry "cert_files" | str_entry "ca_file" | str_entry "crl_file" =20 diff --git a/src/remote/libvirtd.conf.in b/src/remote/libvirtd.conf.in index 32a680317a..e4460e61ef 100644 --- a/src/remote/libvirtd.conf.in +++ b/src/remote/libvirtd.conf.in @@ -244,12 +244,28 @@ =20 # Override the default server key file path # +# This parameter is mutually exclusive with 'key_files' +# #key_file =3D "@sysconfdir@/pki/libvirt/private/serverkey.pem" =20 +# Override the default server key file path(s) +# +# This parameter is mutually exclusive with 'key_file' +# +#key_files =3D ["@sysconfdir@/pki/libvirt/private/serverkey-0.pem", "@sysc= onfdir@/pki/libvirt/private/serverkey-1.pem"] + # Override the default server certificate file path # +# This parameter is mutually exclusive with 'cert_files' +# #cert_file =3D "@sysconfdir@/pki/libvirt/servercert.pem" =20 +# Override the default server certificate file path(s) +# +# This parameter is mutually exclusive with 'cert_file' +# +#cert_files =3D ["@sysconfdir@/pki/libvirt/servercert-0.pem", "@sysconfdir= @/pki/libvirt/servercert-1.pem"] + # Override the default CA certificate path # #ca_file =3D "@sysconfdir@/pki/CA/cacert.pem" diff --git a/src/remote/remote_daemon.c b/src/remote/remote_daemon.c index e7c8f587c4..ee3d10bc23 100644 --- a/src/remote/remote_daemon.c +++ b/src/remote/remote_daemon.c @@ -325,31 +325,31 @@ daemonSetupNetworking(virNetServer *srv, virNetTLSContext *ctxt =3D NULL; =20 if (config->ca_file || - config->cert_file || - config->key_file) { - const char *certs[] =3D { config->cert_file, NULL }; - const char *keys[] =3D { config->key_file, NULL }; - + config->cert_files || + config->key_files) { + g_autofree char *certs =3D g_strjoinv(", ", config->cert_files= ); + g_autofree char *keys =3D g_strjoinv(", ", config->key_files); if (!config->ca_file) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("No CA certificate path set to match serv= er key/cert")); + _("No CA certificate path set to match serv= er key(s)/cert(s)")); return -1; } - if (!config->cert_file) { + if (!config->cert_files) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("No server certificate path set to match = server key")); + _("No server certificate path(s) set to mat= ch server key(s)")); return -1; } - if (!config->key_file) { + if (!config->key_files) { virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", - _("No server key path set to match server c= ert")); + _("No server key path(s) set to match serve= r cert(s)")); return -1; } - VIR_DEBUG("Using CA=3D'%s' cert=3D'%s' key=3D'%s'", - config->ca_file, config->cert_file, config->key_file= ); + VIR_DEBUG("Using CA=3D'%s' certs=3D'%s' keys=3D'%s'", + config->ca_file, certs, keys); if (!(ctxt =3D virNetTLSContextNewServer(config->ca_file, config->crl_file, - certs, keys, + (const char *const*)con= fig->cert_files, + (const char *const*)con= fig->key_files, (const char *const*)con= fig->tls_allowed_dn_list, config->tls_priority, config->tls_no_sanity_c= ertificate ? false : true, diff --git a/src/remote/remote_daemon_config.c b/src/remote/remote_daemon_c= onfig.c index c1e75444e1..bb6078967f 100644 --- a/src/remote/remote_daemon_config.c +++ b/src/remote/remote_daemon_config.c @@ -192,9 +192,9 @@ daemonConfigFree(struct daemonConfig *data) =20 g_free(data->tls_priority); =20 - g_free(data->key_file); + g_strfreev(data->key_files); g_free(data->ca_file); - g_free(data->cert_file); + g_strfreev(data->cert_files); g_free(data->crl_file); #endif /* ! WITH_IP */ =20 @@ -212,8 +212,12 @@ daemonConfigLoadOptions(struct daemonConfig *data, virConf *conf) { int rc G_GNUC_UNUSED; - #ifdef WITH_IP + g_autofree char *cert_file =3D NULL; + g_autofree char *key_file =3D NULL; + size_t ncerts; + size_t nkeys; + if (virConfGetValueBool(conf, "listen_tcp", &data->listen_tcp) < 0) return -1; if (virConfGetValueBool(conf, "listen_tls", &data->listen_tls) < 0) @@ -269,10 +273,39 @@ daemonConfigLoadOptions(struct daemonConfig *data, if (virConfGetValueBool(conf, "tls_no_verify_certificate", &data->tls_= no_verify_certificate) < 0) return -1; =20 - if (virConfGetValueString(conf, "key_file", &data->key_file) < 0) + if (virConfGetValueString(conf, "key_file", &key_file) < 0) + return -1; + if (virConfGetValueString(conf, "cert_file", &cert_file) < 0) + return -1; + if (virConfGetValueStringList(conf, "key_files", false, &data->key_fil= es) < 0) + return -1; + if (virConfGetValueStringList(conf, "cert_files", false, &data->cert_f= iles) < 0) + return -1; + if ((cert_file && data->cert_files) || + (key_file && data->key_files)) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s", + _("cert_file/key_file are mutually exclusive with c= ert_files/key_files")); return -1; - if (virConfGetValueString(conf, "cert_file", &data->cert_file) < 0) + } + if (cert_file) { + data->cert_files =3D g_new0(char *, 2); + data->cert_files[0] =3D g_steal_pointer(&cert_file); + data->cert_files[1] =3D NULL; + } + if (key_file) { + data->key_files =3D g_new0(char *, 2); + data->key_files[0] =3D g_steal_pointer(&key_file); + data->key_files[1] =3D NULL; + } + ncerts =3D data->cert_files ? g_strv_length(data->cert_files) : 0; + nkeys =3D data->key_files ? g_strv_length(data->key_files) : 0; + if (ncerts !=3D nkeys) { + virReportError(VIR_ERR_CONFIG_UNSUPPORTED, + _("Number of certificates (%1$zu) must match number= of keys (%2$zu)"), + ncerts, nkeys); return -1; + } + if (virConfGetValueString(conf, "ca_file", &data->ca_file) < 0) return -1; if (virConfGetValueString(conf, "crl_file", &data->crl_file) < 0) diff --git a/src/remote/remote_daemon_config.h b/src/remote/remote_daemon_c= onfig.h index 9f9e54e838..e699889191 100644 --- a/src/remote/remote_daemon_config.h +++ b/src/remote/remote_daemon_config.h @@ -58,8 +58,8 @@ struct daemonConfig { char *tls_priority; unsigned int tcp_min_ssf; =20 - char *key_file; - char *cert_file; + char **key_files; + char **cert_files; char *ca_file; char *crl_file; #endif /* ! WITH_IP */ diff --git a/src/remote/test_libvirtd.aug.in b/src/remote/test_libvirtd.aug= .in index c27680e130..a37b0daa55 100644 --- a/src/remote/test_libvirtd.aug.in +++ b/src/remote/test_libvirtd.aug.in @@ -26,7 +26,15 @@ module Test_@DAEMON_NAME@ =3D } @CUT_ENABLE_IP@ { "key_file" =3D "@sysconfdir@/pki/libvirt/private/serverkey.pem" } + { "key_files" + { "1" =3D "@sysconfdir@/pki/libvirt/private/serverkey-0.pem" } + { "2" =3D "@sysconfdir@/pki/libvirt/private/serverkey-1.pem" } + } { "cert_file" =3D "@sysconfdir@/pki/libvirt/servercert.pem" } + { "cert_files" + { "1" =3D "@sysconfdir@/pki/libvirt/servercert-0.pem" } + { "2" =3D "@sysconfdir@/pki/libvirt/servercert-1.pem" } + } { "ca_file" =3D "@sysconfdir@/pki/CA/cacert.pem" } { "crl_file" =3D "@sysconfdir@/pki/CA/crl.pem" } { "tls_no_sanity_certificate" =3D "1" } --=20 2.51.1 From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762441137; cv=none; d=zohomail.com; s=zohoarc; b=nYOO1nuKZPHgcmBfzet7HCmqLTfPSsaW21MHkh4niiluY1OVuc1CVxf0FME9eT+kuYa0JVF7517IBhsZx91NNCA7owEMHxdkbZmMhRpK237rNRezD85RNjAMF14WV9HW9a5dFiogLUDJ6sBtqDHbLPpxoKlDIq2C7rw8rDBPBps= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762441137; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=r3LXN3CAwu/Jn30zhueYvM00GA+zql+vklFjUl8ASlE=; b=LfEbryjLFErjigHvJRj7fSqS8S3GltbAYTKQizRSIrhBeNE/6fxJZ2Rx1dc14FimfQjI1SZkxIRACb/j8aq9KXOzSJNEcyTRy5M4swgeZRw5M0mop9E4uDCX/P7ff96VYp5GnUrs1eguGuLdgvMz4sROjTtmt+L5Ggy9TI5UOqo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762441137282307.5256466582822; Thu, 6 Nov 2025 06:58:57 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 97AD44415C; Thu, 6 Nov 2025 09:58:56 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id BA713441E8; Thu, 6 Nov 2025 09:52:42 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id 4808A418F9; Thu, 6 Nov 2025 09:51:05 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id 96B85440C0 for ; Thu, 6 Nov 2025 09:51:03 -0500 (EST) Received: from mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-58-SuXdat8VNleJd9BumoWQPw-1; Thu, 06 Nov 2025 09:51:01 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-03.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id C7D431956050 for ; Thu, 6 Nov 2025 14:51:00 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id D39E31800451; Thu, 6 Nov 2025 14:50:59 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440663; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=r3LXN3CAwu/Jn30zhueYvM00GA+zql+vklFjUl8ASlE=; b=aoeyf1PyxIUm7rzMACvZl7QYhcHcyCsv6kc6vO4Sz1qfJBxMlBZhpmmng7+2sSsxTc3Hb1 zMBlBZ/q0bf/WHPZoobHWRV5Yi2weJ8LvQ83D3r8bUo8fUo2ClgLqeWUHnLvSbiQyAeX+2 OQIn+S/I0mZQAspVGKhDCmnGhvn1/rE= X-MC-Unique: SuXdat8VNleJd9BumoWQPw-1 X-Mimecast-MFC-AGG-ID: SuXdat8VNleJd9BumoWQPw_1762440660 To: devel@lists.libvirt.org Subject: [PATCH 06/10] rpc: skip fallback when using custom PKI path Date: Thu, 6 Nov 2025 14:50:46 +0000 Message-ID: <20251106145050.1851526-7-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: Ergz4aWHAIzyVkRCuvFMgby3FtfoJVjG0uUDxCA-MVg_1762440660 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: STGVK2CN3G6GJTYEPO4RDT4AAERUFVYJ X-Message-ID-Hash: STGVK2CN3G6GJTYEPO4RDT4AAERUFVYJ X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762441138875154100 From: Daniel P. Berrang=C3=A9 The virNetTLSConfigCustomCreds will always set the cert paths to non-NULL strings. This in turn means that the later call to virNetTLSConfigSystemCreds will be a no-op aside from duplicating log information. Refactor the conditions so that the call to find system credentials is skipped when using custom credentials. While this patch could have just done an early "return 0" after the virNetTLSConfigCustomCreds call, an "} else {" branch is instead added, since this will facilitate a later patch in this series which prefers a common return path. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/rpc/virnettlscontext.c | 50 ++++++++++++++++++++------------------ 1 file changed, 26 insertions(+), 24 deletions(-) diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c index 5e9c262b48..37f635f47f 100644 --- a/src/rpc/virnettlscontext.c +++ b/src/rpc/virnettlscontext.c @@ -271,32 +271,34 @@ static int virNetTLSContextLocateCredentials(const ch= ar *pkipath, virNetTLSConfigCustomCreds(pkipath, isServer, cacert, cacrl, cert, key); - } else if (tryUserPkiPath) { - virNetTLSConfigUserCreds(isServer, - cacert, cacrl, - cert, key); - - /* - * If some of the files can't be found, fallback - * to the global location for them - */ - if (!virFileExists(*cacert)) - VIR_FREE(*cacert); - if (!virFileExists(*cacrl)) - VIR_FREE(*cacrl); - - /* Check these as a pair, since it they are - * mutually dependent - */ - if (!virFileExists(*key) || !virFileExists(*cert)) { - VIR_FREE(*key); - VIR_FREE(*cert); + } else { + if (tryUserPkiPath) { + virNetTLSConfigUserCreds(isServer, + cacert, cacrl, + cert, key); + + /* + * If some of the files can't be found, fallback + * to the global location for them + */ + if (!virFileExists(*cacert)) + VIR_FREE(*cacert); + if (!virFileExists(*cacrl)) + VIR_FREE(*cacrl); + + /* Check these as a pair, since it they are + * mutually dependent + */ + if (!virFileExists(*key) || !virFileExists(*cert)) { + VIR_FREE(*key); + VIR_FREE(*cert); + } } - } =20 - virNetTLSConfigSystemCreds(isServer, - cacert, cacrl, - cert, key); + virNetTLSConfigSystemCreds(isServer, + cacert, cacrl, + cert, key); + } =20 return 0; } --=20 2.51.1 From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762441224; cv=none; d=zohomail.com; s=zohoarc; b=KiX2wmpe1lf6GoffEbD/iFKYmtgCkRVfKHxqK81gxlLqu1dADMUxYPtJ3gXZMS8rhsO4vmTsUAbQBSoXcfRXfSefIQf5Kz3QeU9fdUrczM6pi6LpOUrREUsVbpeSqitAal17EcjXyxPl0TExuqSXVYtQeVeo0/BiiUhrYld9UTI= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762441224; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=AXiQohW9GVHabBo8HCSfjvlkpMZ2tuwrWFFFBmeVp5A=; b=mvNiRjfVGKoWW4GjjSAOp3YkFmnsmfaUz8bbSyrhpooBshIr8+LVoBu9e7N1LwIdaC5TSHlZLPvp2uaIvGuTV+DOEQ0k6ersrwG7/+zFUBWvm+0lnT4mQQGQTbqOFfLYNf990vKR90lA8Rkcmh7wkwxSR8B6HZGCiykwZfCNi5Y= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762441224827623.1333045633976; Thu, 6 Nov 2025 07:00:24 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id C9B13441DB; Thu, 6 Nov 2025 10:00:23 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 57A0444387; Thu, 6 Nov 2025 09:53:22 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id EBB3B418F9; Thu, 6 Nov 2025 09:51:05 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id B2F46440C1 for ; Thu, 6 Nov 2025 09:51:04 -0500 (EST) Received: from mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-605-ZuB5KrcLP2SC2CohATrDxA-1; Thu, 06 Nov 2025 09:51:03 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-06.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 50BBE180057A for ; Thu, 6 Nov 2025 14:51:02 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 3085A1800451; Thu, 6 Nov 2025 14:51:00 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440664; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=AXiQohW9GVHabBo8HCSfjvlkpMZ2tuwrWFFFBmeVp5A=; b=aizbKvoUFmEs1Tsrm5d3aZBN4mcgS5M8TCEz4QnxY7Q0l8JK7IVQkOqiW6bJCF2YjgDx8C kAD1BL4ss2ZY++EVvaQNEoMw5dCtGEH7o7KTTRZLzxqkQzVzQ9M/Er8a2jP0kndEmmEI3W D1fc0Xv6eHGhaSJpfzoN+0dldR+qm50= X-MC-Unique: ZuB5KrcLP2SC2CohATrDxA-1 X-Mimecast-MFC-AGG-ID: ZuB5KrcLP2SC2CohATrDxA_1762440662 To: devel@lists.libvirt.org Subject: [PATCH 07/10] rpc: move file access checks into TLS config API Date: Thu, 6 Nov 2025 14:50:47 +0000 Message-ID: <20251106145050.1851526-8-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: wodLYTXkhxxTk-cM6GluQENolPCQ2bMqAJ2K_lcsFZA_1762440662 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 3JYE46P4FGAEYPX4FJPCW65ETYZGVI4Q X-Message-ID-Hash: 3JYE46P4FGAEYPX4FJPCW65ETYZGVI4Q X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762441226231158500 From: Daniel P. Berrang=C3=A9 A future patch will require fule access checks to be done as part of locating the certificate files, as we will have the ability to load many more files, most of which will be optional. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- po/POTFILES | 1 + src/rpc/virnettlsconfig.c | 168 +++++++++++++++++++++++++++++++++---- src/rpc/virnettlsconfig.h | 37 ++++---- src/rpc/virnettlscontext.c | 161 ++++++++++++++--------------------- 4 files changed, 236 insertions(+), 131 deletions(-) diff --git a/po/POTFILES b/po/POTFILES index 23da794f84..f0aad35c8c 100644 --- a/po/POTFILES +++ b/po/POTFILES @@ -230,6 +230,7 @@ src/rpc/virnetserverservice.c src/rpc/virnetsocket.c src/rpc/virnetsshsession.c src/rpc/virnettlscert.c +src/rpc/virnettlsconfig.c src/rpc/virnettlscontext.c src/secret/secret_driver.c src/security/security_apparmor.c diff --git a/src/rpc/virnettlsconfig.c b/src/rpc/virnettlsconfig.c index ffab3b4fc8..1479eb01ae 100644 --- a/src/rpc/virnettlsconfig.c +++ b/src/rpc/virnettlsconfig.c @@ -21,12 +21,15 @@ #include =20 #include "virnettlsconfig.h" +#include "viralloc.h" #include "virlog.h" #include "virutil.h" +#include "virfile.h" +#include "virerror.h" =20 #define VIR_FROM_THIS VIR_FROM_RPC =20 -VIR_LOG_INIT("rpc.nettlscontext"); +VIR_LOG_INIT("rpc.nettlsconfig"); =20 char *virNetTLSConfigUserPKIBaseDir(void) { @@ -142,30 +145,143 @@ void virNetTLSConfigSystemIdentity(bool isServer, key); } =20 -void virNetTLSConfigCustomCreds(const char *pkipath, - bool isServer, - char **cacert, - char **cacrl, - char **cert, - char **key) + +int virNetTLSConfigCheckTrust(const char *cacert, const char *cacrl, + bool *cacertExists, bool *cacrlExists, + bool allowMissingCA) +{ + if (cacertExists) + *cacertExists =3D true; + if (cacrlExists) + *cacrlExists =3D true; + VIR_DEBUG("Checking CA certificate '%s' and CRL '%s'", cacert, NULLSTR= (cacrl)); + if (!virFileExists(cacert)) { + if (allowMissingCA) { + VIR_DEBUG("CA certificate '%s' does not exist", cacert); + if (cacertExists) + *cacertExists =3D false; + } else { + virReportSystemError(errno, _("CA certificate '%1$s' does not = exist"), + cacert); + return -1; + } + } + if (cacrl !=3D NULL && !virFileExists(cacrl)) { + VIR_DEBUG("CA CRL '%s' does not exist", cacrl); + if (cacrlExists) + *cacrlExists =3D false; + } + return 0; +} + +static int virNetTLSConfigEnsureTrust(char **cacert, char **cacrl, + bool allowMissingCA) +{ + bool cacertExists, cacrlExists; + + if (virNetTLSConfigCheckTrust(*cacert, *cacrl, + &cacertExists, &cacrlExists, + allowMissingCA) < 0) + return -1; + + if (!cacertExists) + VIR_FREE(*cacert); + if (!cacrlExists) + VIR_FREE(*cacrl); + + return 0; +} + +int virNetTLSConfigCheckIdentity(const char *cert, const char *key, + bool *identityExists, bool allowMissing) +{ + if (identityExists) + *identityExists =3D true; + VIR_DEBUG("Checking certificate '%s' and key '%s'", cert, key); + if (!virFileExists(cert)) { + int saved_errno =3D errno; + if (allowMissing) { + if (virFileExists(key)) { + virReportSystemError( + saved_errno, + _("Certificate '%1$s' does not exist, but key '%2$s' d= oes"), + cert, key); + return -1; + } + if (identityExists) + *identityExists =3D false; + VIR_DEBUG("Missing cert '%s' / key '%s'", cert, key); + return 0; + } else { + virReportSystemError(saved_errno, _("Certificate '%1$s' does n= ot exist"), + cert); + return -1; + } + } else { + if (!virFileExists(key)) { + virReportSystemError(errno, + _("Key '%1$s' does not exist, but certifi= cate '%2$s' does"), + key, cert); + return -1; + } + } + + return 0; +} + + +static int virNetTLSConfigEnsureIdentity(char **cert, char **key, + bool allowMissing) +{ + bool identityExists; + + if (virNetTLSConfigCheckIdentity(*cert, *key, &identityExists, + allowMissing) < 0) + return -1; + + if (!identityExists) { + VIR_FREE(*cert); + VIR_FREE(*key); + } + + return 0; +} + + +int virNetTLSConfigCustomCreds(const char *pkipath, + bool isServer, + char **cacert, + char **cacrl, + char **cert, + char **key) { VIR_DEBUG("Locating creds in custom dir %s", pkipath); virNetTLSConfigTrust(pkipath, pkipath, cacert, cacrl); + + if (virNetTLSConfigEnsureTrust(cacert, cacrl, false) < 0) + return -1; + virNetTLSConfigIdentity(isServer, pkipath, pkipath, cert, key); + + + if (virNetTLSConfigEnsureIdentity(cert, key, !isServer) < 0) + return -1; + + return 0; } =20 -void virNetTLSConfigUserCreds(bool isServer, - char **cacert, - char **cacrl, - char **cert, - char **key) +int virNetTLSConfigUserCreds(bool isServer, + char **cacert, + char **cacrl, + char **cert, + char **key) { g_autofree char *pkipath =3D virNetTLSConfigUserPKIBaseDir(); =20 @@ -175,18 +291,27 @@ void virNetTLSConfigUserCreds(bool isServer, pkipath, cacert, cacrl); + + if (virNetTLSConfigEnsureTrust(cacert, cacrl, true) < 0) + return -1; + virNetTLSConfigIdentity(isServer, pkipath, pkipath, cert, key); + + if (virNetTLSConfigEnsureIdentity(cert, key, true) < 0) + return -1; + + return 0; } =20 -void virNetTLSConfigSystemCreds(bool isServer, - char **cacert, - char **cacrl, - char **cert, - char **key) +int virNetTLSConfigSystemCreds(bool isServer, + char **cacert, + char **cacrl, + char **cert, + char **key) { VIR_DEBUG("Locating creds in system dir %s", LIBVIRT_PKI_DIR); =20 @@ -194,9 +319,18 @@ void virNetTLSConfigSystemCreds(bool isServer, LIBVIRT_CACRL_DIR, cacert, cacrl); + + if (virNetTLSConfigEnsureTrust(cacert, cacrl, false) < 0) + return -1; + virNetTLSConfigIdentity(isServer, LIBVIRT_CERT_DIR, LIBVIRT_KEY_DIR, cert, key); + + if (virNetTLSConfigEnsureIdentity(cert, key, !isServer) < 0) + return -1; + + return 0; } diff --git a/src/rpc/virnettlsconfig.h b/src/rpc/virnettlsconfig.h index a9378c18b7..9ad213fe06 100644 --- a/src/rpc/virnettlsconfig.h +++ b/src/rpc/virnettlsconfig.h @@ -50,20 +50,25 @@ void virNetTLSConfigSystemIdentity(bool isServer, char **cert, char **key); =20 +int virNetTLSConfigCheckIdentity(const char *cert, const char *key, + bool *identityExists, bool allowMissing); +int virNetTLSConfigCheckTrust(const char *cacert, const char *cacrl, + bool *cacertExists, bool *cacrlExists, + bool allowMissingCA); =20 -void virNetTLSConfigCustomCreds(const char *pkipath, - bool isServer, - char **cacert, - char **cacrl, - char **cert, - char **key); -void virNetTLSConfigUserCreds(bool isServer, - char **cacert, - char **cacrl, - char **cert, - char **key); -void virNetTLSConfigSystemCreds(bool isServer, - char **cacert, - char **cacrl, - char **cert, - char **key); +int virNetTLSConfigCustomCreds(const char *pkipath, + bool isServer, + char **cacert, + char **cacrl, + char **cert, + char **key); +int virNetTLSConfigUserCreds(bool isServer, + char **cacert, + char **cacrl, + char **cert, + char **key); +int virNetTLSConfigSystemCreds(bool isServer, + char **cacert, + char **cacrl, + char **cert, + char **key); diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c index 37f635f47f..7061eb5953 100644 --- a/src/rpc/virnettlscontext.c +++ b/src/rpc/virnettlscontext.c @@ -31,7 +31,6 @@ #include "virnettlscert.h" #include "virstring.h" =20 -#include "viralloc.h" #include "virerror.h" #include "virfile.h" #include "virutil.h" @@ -88,22 +87,6 @@ static int virNetTLSContextOnceInit(void) VIR_ONCE_GLOBAL_INIT(virNetTLSContext); =20 =20 -static int -virNetTLSContextCheckCertFile(const char *type, const char *file, bool all= owMissing) -{ - if (!virFileExists(file)) { - if (allowMissing) - return 1; - - virReportSystemError(errno, - _("Cannot read %1$s '%2$s'"), - type, file); - return -1; - } - return 0; -} - - static void virNetTLSLog(int level G_GNUC_UNUSED, const char *str G_GNUC_UNUSED) { @@ -112,7 +95,6 @@ static void virNetTLSLog(int level G_GNUC_UNUSED, =20 =20 static int virNetTLSContextLoadCredentials(virNetTLSContext *ctxt, - bool isServer, const char *cacert, const char *cacrl, const char *const *certs, @@ -121,66 +103,42 @@ static int virNetTLSContextLoadCredentials(virNetTLSC= ontext *ctxt, int err; size_t i; =20 - if (cacert && cacert[0] !=3D '\0') { - if (virNetTLSContextCheckCertFile("CA certificate", cacert, false)= < 0) - return -1; + VIR_DEBUG("loading CA cert from %s", cacert); + err =3D gnutls_certificate_set_x509_trust_file(ctxt->x509cred, + cacert, + GNUTLS_X509_FMT_PEM); + if (err < 0) { + virReportError(VIR_ERR_SYSTEM_ERROR, + _("Unable to set x509 CA certificate: %1$s: %2$s"), + cacert, gnutls_strerror(err)); + return -1; + } =20 - VIR_DEBUG("loading CA cert from %s", cacert); - err =3D gnutls_certificate_set_x509_trust_file(ctxt->x509cred, - cacert, - GNUTLS_X509_FMT_PEM); + if (cacrl) { + VIR_DEBUG("loading CRL from %s", cacrl); + err =3D gnutls_certificate_set_x509_crl_file(ctxt->x509cred, + cacrl, + GNUTLS_X509_FMT_PEM); if (err < 0) { virReportError(VIR_ERR_SYSTEM_ERROR, - _("Unable to set x509 CA certificate: %1$s: %2$= s"), - cacert, gnutls_strerror(err)); - return -1; - } - } - - if (cacrl && cacrl[0] !=3D '\0') { - int rv; - if ((rv =3D virNetTLSContextCheckCertFile("CA revocation list", ca= crl, true)) < 0) + _("Unable to set x509 certificate revocation li= st: %1$s: %2$s"), + cacrl, gnutls_strerror(err)); return -1; - - if (rv =3D=3D 0) { - VIR_DEBUG("loading CRL from %s", cacrl); - err =3D gnutls_certificate_set_x509_crl_file(ctxt->x509cred, - cacrl, - GNUTLS_X509_FMT_PEM= ); - if (err < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("Unable to set x509 certificate revocatio= n list: %1$s: %2$s"), - cacrl, gnutls_strerror(err)); - return -1; - } - } else { - VIR_DEBUG("Skipping non-existent CA CRL %s", cacrl); } + } else { + VIR_DEBUG("no CRL file to load"); } =20 for (i =3D 0; certs[i] !=3D NULL && keys[i] !=3D NULL; i++) { - int rv; - if ((rv =3D virNetTLSContextCheckCertFile("certificate", certs[i],= !isServer)) < 0) - return -1; - if (rv =3D=3D 0 && - (rv =3D virNetTLSContextCheckCertFile("private key", keys[i], = !isServer)) < 0) + VIR_DEBUG("loading cert and key from %s and %s", certs[i], keys[i]= ); + err =3D gnutls_certificate_set_x509_key_file(ctxt->x509cred, + certs[i], keys[i], + GNUTLS_X509_FMT_PEM); + if (err < 0) { + virReportError(VIR_ERR_SYSTEM_ERROR, + _("Unable to set x509 key and certificate: %1$s= , %2$s: %3$s"), + keys[i], certs[i], gnutls_strerror(err)); return -1; - - if (rv =3D=3D 0) { - VIR_DEBUG("loading cert and key from %s and %s", certs[i], key= s[i]); - err =3D - gnutls_certificate_set_x509_key_file(ctxt->x509cred, - certs[i], keys[i], - GNUTLS_X509_FMT_PEM); - if (err < 0) { - virReportError(VIR_ERR_SYSTEM_ERROR, - _("Unable to set x509 key and certificate: = %1$s, %2$s: %3$s"), - keys[i], certs[i], gnutls_strerror(err)); - return -1; - } - } else { - VIR_DEBUG("Skipping non-existent cert %s key %s on client", - certs[i], keys[i]); } } =20 @@ -200,6 +158,15 @@ static virNetTLSContext *virNetTLSContextNew(const cha= r *cacert, { virNetTLSContext *ctxt; int err; + g_autofree char *certlist =3D certs ? g_strjoinv(", ", (char **)certs)= : NULL; + g_autofree char *keylist =3D keys ? g_strjoinv(", ", (char **)keys) : = NULL; + g_autofree char *acllist =3D x509dnACL ? g_strjoinv(", ", (char **)x50= 9dnACL) : NULL; + + VIR_DEBUG("CA cert=3D%s CRL=3D%s certs=3D'%s' keys=3D'%s' ACL=3D'%s' " + "priority=3D%s sanity-check=3D%d require-valid=3D%d is-serve= r=3D%d", + cacert, NULLSTR(cacrl), NULLSTR(certlist), NULLSTR(keylist), + NULLSTR(acllist), priority, sanityCheckCert, requireValidCer= t, + isServer); =20 if (virNetTLSContextInitialize() < 0) return NULL; @@ -228,7 +195,7 @@ static virNetTLSContext *virNetTLSContextNew(const char= *cacert, virNetTLSCertSanityCheck(isServer, cacert, certs) < 0) goto error; =20 - if (virNetTLSContextLoadCredentials(ctxt, isServer, cacert, cacrl, + if (virNetTLSContextLoadCredentials(ctxt, cacert, cacrl, certs, keys) < 0) goto error; =20 @@ -268,38 +235,22 @@ static int virNetTLSContextLocateCredentials(const ch= ar *pkipath, * files actually exist there */ if (pkipath) { - virNetTLSConfigCustomCreds(pkipath, isServer, - cacert, cacrl, - cert, key); + if (virNetTLSConfigCustomCreds(pkipath, isServer, + cacert, cacrl, + cert, key) < 0) + return -1; } else { - if (tryUserPkiPath) { + if (tryUserPkiPath && virNetTLSConfigUserCreds(isServer, cacert, cacrl, - cert, key); - - /* - * If some of the files can't be found, fallback - * to the global location for them - */ - if (!virFileExists(*cacert)) - VIR_FREE(*cacert); - if (!virFileExists(*cacrl)) - VIR_FREE(*cacrl); - - /* Check these as a pair, since it they are - * mutually dependent - */ - if (!virFileExists(*key) || !virFileExists(*cert)) { - VIR_FREE(*key); - VIR_FREE(*cert); - } - } + cert, key) < 0) + return -1; =20 - virNetTLSConfigSystemCreds(isServer, - cacert, cacrl, - cert, key); + if (virNetTLSConfigSystemCreds(isServer, + cacert, cacrl, + cert, key) < 0) + return -1; } - return 0; } =20 @@ -359,6 +310,13 @@ virNetTLSContext *virNetTLSContextNewServer(const char= *cacert, bool sanityCheckCert, bool requireValidCert) { + size_t i; + if (virNetTLSConfigCheckTrust(cacert, cacrl, NULL, NULL, false) < 0) + return NULL; + for (i =3D 0; certs[i] !=3D NULL && keys[i] !=3D NULL; i++) { + if (virNetTLSConfigCheckIdentity(certs[i], keys[i], NULL, false) <= 0) + return NULL; + } return virNetTLSContextNew(cacert, cacrl, certs, keys, x509dnACL, prio= rity, sanityCheckCert, requireValidCert, true); } @@ -393,7 +351,7 @@ int virNetTLSContextReloadForServer(virNetTLSContext *c= txt, if (virNetTLSCertSanityCheck(true, cacert, certs)) goto error; =20 - if (virNetTLSContextLoadCredentials(ctxt, true, cacert, cacrl, + if (virNetTLSContextLoadCredentials(ctxt, cacert, cacrl, certs, keys)) goto error; =20 @@ -417,6 +375,13 @@ virNetTLSContext *virNetTLSContextNewClient(const char= *cacert, bool sanityCheckCert, bool requireValidCert) { + size_t i; + if (virNetTLSConfigCheckTrust(cacert, cacrl, NULL, NULL, false) < 0) + return NULL; + for (i =3D 0; certs[i] !=3D NULL && keys[i] !=3D NULL; i++) { + if (virNetTLSConfigCheckIdentity(certs[i], keys[i], NULL, false) <= 0) + return NULL; + } return virNetTLSContextNew(cacert, cacrl, certs, keys, NULL, priority, sanityCheckCert, requireValidCert, false); } --=20 2.51.1 From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762441296; cv=none; d=zohomail.com; s=zohoarc; b=NR23sijTsdbZJLublWkIdtys1RY8pOg2RjrtNMnhrx/oR//io6MZFkIW+FHcz/+uOI3LifqoKte1IFlciSW/D+FnZUx/OnkBtJ3A90R1Q/8sUnNTkfpVm7WWBVCICuWv4a0wwbq8tGg5njhOO3LlAawOA/Wb+WRz9xswwmQFt+M= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762441296; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=hhj6uIN7K7Ssy1Cenk9iT/Z3Vt28606B/ZOvx+utOW0=; b=KMWGvliK3q1vNpxxBN7kUU12uewVYMYnLaVh/Vnfh6mLnnfoSpZKxAmuFwHeN6Lpyv8RDTST6xYL9OlgEU6ija684rIBOwKJKb86M771ihOE0rxuaBtUY8W4/O8wS+t2QUIvUk9ESsu9uUVyVYG06bzdcH8HHUeJp6VGfd0aIfc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762441288790888.326224610438; Thu, 6 Nov 2025 07:01:28 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 7FB0D417D3; Thu, 6 Nov 2025 10:01:22 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id E85CC44205; Thu, 6 Nov 2025 09:53:41 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id AEC7043DF6; Thu, 6 Nov 2025 09:51:06 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id EE53A41988 for ; Thu, 6 Nov 2025 09:51:05 -0500 (EST) Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-643-R5uYuYl-OHi9EC72NvvSPA-1; Thu, 06 Nov 2025 09:51:04 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8155218002CC for ; Thu, 6 Nov 2025 14:51:03 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id B33901800240; Thu, 6 Nov 2025 14:51:02 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440665; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hhj6uIN7K7Ssy1Cenk9iT/Z3Vt28606B/ZOvx+utOW0=; b=h2pIXTBUCvpT0VbIiXcdO6pjYRcmJOyL8+Lat7rqHaAA2xExnfAyK4NfwkcwTjr9PXJDlF kYEb57nuISMAMntdpfmfjUPitYjxieglcVRDjt3CavN4ubohhmsfWGZVPBDrx1/VoHtA0H MlZA1t73L+wAAJu1wPQQumOroKWitWU= X-MC-Unique: R5uYuYl-OHi9EC72NvvSPA-1 X-Mimecast-MFC-AGG-ID: R5uYuYl-OHi9EC72NvvSPA_1762440663 To: devel@lists.libvirt.org Subject: [PATCH 08/10] rpc: reduce duplication when locating credentials Date: Thu, 6 Nov 2025 14:50:48 +0000 Message-ID: <20251106145050.1851526-9-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: QK5xXHCyfOZFAsezSDylTpMy-qVuAJUhdx_Iko4V26o_1762440663 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 2UZLNMD23RTR643NGU47OY3BRWJFP6YV X-Message-ID-Hash: 2UZLNMD23RTR643NGU47OY3BRWJFP6YV X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762441300189154100 From: Daniel P. Berrang=C3=A9 The three different APIs for locating credentials differ only in what directories they search and their policy for missing files. Their code can be collapsed onto a single helper method. This will greatly facilitate the subsequent patch that expands the logic to locate many certificate files. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/rpc/virnettlsconfig.c | 103 ++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 50 deletions(-) diff --git a/src/rpc/virnettlsconfig.c b/src/rpc/virnettlsconfig.c index 1479eb01ae..59cb8c2566 100644 --- a/src/rpc/virnettlsconfig.c +++ b/src/rpc/virnettlsconfig.c @@ -248,35 +248,58 @@ static int virNetTLSConfigEnsureIdentity(char **cert,= char **key, } =20 =20 -int virNetTLSConfigCustomCreds(const char *pkipath, - bool isServer, - char **cacert, - char **cacrl, - char **cert, - char **key) +static int virNetTLSConfigCreds(const char *cacertdir, + const char *cacrldir, + const char *certdir, + const char *keydir, + bool isServer, + bool allowMissingCA, + bool allowMissingIdentity, + char **cacert, + char **cacrl, + char **cert, + char **key) { - VIR_DEBUG("Locating creds in custom dir %s", pkipath); - virNetTLSConfigTrust(pkipath, - pkipath, + virNetTLSConfigTrust(cacertdir, + cacrldir, cacert, cacrl); =20 - if (virNetTLSConfigEnsureTrust(cacert, cacrl, false) < 0) + if (virNetTLSConfigEnsureTrust(cacert, cacrl, allowMissingCA) < 0) return -1; =20 virNetTLSConfigIdentity(isServer, - pkipath, - pkipath, + certdir, + keydir, cert, key); =20 - - if (virNetTLSConfigEnsureIdentity(cert, key, !isServer) < 0) + if (virNetTLSConfigEnsureIdentity(cert, key, allowMissingIdentity) < 0) return -1; =20 return 0; } =20 + +int virNetTLSConfigCustomCreds(const char *pkipath, + bool isServer, + char **cacert, + char **cacrl, + char **cert, + char **key) +{ + VIR_DEBUG("Locating creds in custom dir %s", pkipath); + + return virNetTLSConfigCreds(pkipath, pkipath, + pkipath, pkipath, + isServer, + false, + !isServer, + cacert, cacrl, + cert, key); +} + + int virNetTLSConfigUserCreds(bool isServer, char **cacert, char **cacrl, @@ -287,24 +310,13 @@ int virNetTLSConfigUserCreds(bool isServer, =20 VIR_DEBUG("Locating creds in user dir %s", pkipath); =20 - virNetTLSConfigTrust(pkipath, - pkipath, - cacert, - cacrl); - - if (virNetTLSConfigEnsureTrust(cacert, cacrl, true) < 0) - return -1; - - virNetTLSConfigIdentity(isServer, - pkipath, - pkipath, - cert, - key); - - if (virNetTLSConfigEnsureIdentity(cert, key, true) < 0) - return -1; - - return 0; + return virNetTLSConfigCreds(pkipath, pkipath, + pkipath, pkipath, + isServer, + true, + true, + cacert, cacrl, + cert, key); } =20 int virNetTLSConfigSystemCreds(bool isServer, @@ -315,22 +327,13 @@ int virNetTLSConfigSystemCreds(bool isServer, { VIR_DEBUG("Locating creds in system dir %s", LIBVIRT_PKI_DIR); =20 - virNetTLSConfigTrust(LIBVIRT_CACERT_DIR, - LIBVIRT_CACRL_DIR, - cacert, - cacrl); - - if (virNetTLSConfigEnsureTrust(cacert, cacrl, false) < 0) - return -1; - - virNetTLSConfigIdentity(isServer, - LIBVIRT_CERT_DIR, - LIBVIRT_KEY_DIR, - cert, - key); - - if (virNetTLSConfigEnsureIdentity(cert, key, !isServer) < 0) - return -1; - - return 0; + return virNetTLSConfigCreds(LIBVIRT_CACERT_DIR, + LIBVIRT_CACRL_DIR, + LIBVIRT_CERT_DIR, + LIBVIRT_KEY_DIR, + isServer, + false, + !isServer, + cacert, cacrl, + cert, key); } --=20 2.51.1 From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762441432; cv=none; d=zohomail.com; s=zohoarc; b=IcPUjcmYlz6SEiB2liv5nAQ8KkyWgegswx3hYWu5vDiUVmpzdMDXQJbs2UQuHv21cWU+qAynHNWy0cpmL6po+43ptCJTv0q30AI/eHtmNP6O0iq4OXHv8DsY3YK7vuf5BIuDUtZdMsS27GfT2ROVjJktffEoN9gZ+KEcwisfXT4= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762441432; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=hXNW4w3KF28K8IOPKO1E+GGPnvtcAwvi4OSBT5lBWSA=; b=LGyrrleuN3Gr+yt9meoDCBDU0jsslEQN4zToolD0QYdFcpfvNOtK37sulKa/dKWkPcpnmDz8ENB4WvFHFIApkN1AbotfmID99sMrCP3AK12cVrYO59ksE9xh6m5nNm4ToGdfnaDAvOBnYTVarJxCyU22srOdJ/JDouzCNf7YEU4= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762441432055205.67512189636523; Thu, 6 Nov 2025 07:03:52 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id EE31B440F9; Thu, 6 Nov 2025 10:03:50 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 51750444B7; Thu, 6 Nov 2025 09:53:53 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id A1289418F9; Thu, 6 Nov 2025 09:51:13 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id A689841988 for ; Thu, 6 Nov 2025 09:51:12 -0500 (EST) Received: from mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (ec2-35-165-154-97.us-west-2.compute.amazonaws.com [35.165.154.97]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-645-o4AYYa8OOf-1BsMPei2vvQ-1; Thu, 06 Nov 2025 09:51:05 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 01FBE180057D for ; Thu, 6 Nov 2025 14:51:05 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 122141800451; Thu, 6 Nov 2025 14:51:03 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440672; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=hXNW4w3KF28K8IOPKO1E+GGPnvtcAwvi4OSBT5lBWSA=; b=S12nLdT7ccn/+rOySkN643CpPFp10QdwrGifppPxAgB0zrd0x10BxgL4Av9pQNRF93ZHTf KpzGzcIYs64juoZRdkhccvUCcaSuTLzHEO2WQxFpsTgEqCgGbtvRdmON/qIwV1DadKPwd8 cVy043gP7Xm/7L1YF/mEx1eQvloSiMU= X-MC-Unique: o4AYYa8OOf-1BsMPei2vvQ-1 X-Mimecast-MFC-AGG-ID: o4AYYa8OOf-1BsMPei2vvQ_1762440665 To: devel@lists.libvirt.org Subject: [PATCH 09/10] rpc: support loading multiple certificate identities Date: Thu, 6 Nov 2025 14:50:49 +0000 Message-ID: <20251106145050.1851526-10-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: 0Gu0a_yvYecirTNtn3Y01tPlCACPPAAHv1_NacNa6SQ_1762440665 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: THGIKUUMFDBF4R4HBNWA7VDS6I2KDPT3 X-Message-ID-Hash: THGIKUUMFDBF4R4HBNWA7VDS6I2KDPT3 X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762441434323158501 From: Daniel P. Berrang=C3=A9 In addition to servercert.pem / serverkey.pem, we now also support loading servercert{N}.pem / serverkey{N}.pem, for values of {N} between 0 and 3 inclusive. If servercert0.pem is provided, then using servercert.pem becomes optional. The first missing index terminates the loading process. eg if servercert1.pem is NOT present, then it will NOT attempt to look for servercert2.pem / servercert3.pem. This also applies to clientcert.pem / clientkey.pem. This facilitates the transition to post-quantum cryptography by allowing loading of certificates with different algorithms, eg traditional RSA based cert, and optional ECC based cert or MLDSA based cert for PQC. The use of CA cert files is unchanged with only a single cacert.pem loaded. WHen multiple CAs are needed they must be concatenated in the single cacert.pem file. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- src/rpc/virnettlsconfig.c | 111 +++++++++++++++++++++++++++++++------ src/rpc/virnettlsconfig.h | 12 ++-- src/rpc/virnettlscontext.c | 51 ++++++++++------- 3 files changed, 130 insertions(+), 44 deletions(-) diff --git a/src/rpc/virnettlsconfig.c b/src/rpc/virnettlsconfig.c index 59cb8c2566..eec20cf6b7 100644 --- a/src/rpc/virnettlsconfig.c +++ b/src/rpc/virnettlsconfig.c @@ -31,6 +31,9 @@ =20 VIR_LOG_INIT("rpc.nettlsconfig"); =20 + +#define VIR_NET_TLS_CONFIG_MAX_INDEXED 4 + char *virNetTLSConfigUserPKIBaseDir(void) { g_autofree char *userdir =3D virGetUserDirectory(); @@ -69,6 +72,24 @@ static void virNetTLSConfigIdentity(bool isServer, VIR_DEBUG("TLS cert %s", *cert); } =20 +static void virNetTLSConfigIdentityIndexed(bool isServer, + const char *certdir, + const char *keydir, + size_t idx, + char **cert, + char **key) +{ + if (!*key) + *key =3D g_strdup_printf("%s/%skey%zu.pem", keydir, + (isServer ? "server" : "client"), idx); + if (!*cert) + *cert =3D g_strdup_printf("%s/%scert%zu.pem", certdir, + (isServer ? "server" : "client"), idx); + + VIR_DEBUG("TLS key %s", *key); + VIR_DEBUG("TLS cert %s", *cert); +} + void virNetTLSConfigCustomTrust(const char *pkipath, char **cacert, char **cacrl) @@ -257,8 +278,8 @@ static int virNetTLSConfigCreds(const char *cacertdir, bool allowMissingIdentity, char **cacert, char **cacrl, - char **cert, - char **key) + char ***certs, + char ***keys) { virNetTLSConfigTrust(cacertdir, cacrldir, @@ -268,14 +289,68 @@ static int virNetTLSConfigCreds(const char *cacertdir, if (virNetTLSConfigEnsureTrust(cacert, cacrl, allowMissingCA) < 0) return -1; =20 - virNetTLSConfigIdentity(isServer, - certdir, - keydir, - cert, - key); + if (!*certs && !*keys) { + g_auto(GStrv) certlist =3D + g_new0(char *, VIR_NET_TLS_CONFIG_MAX_INDEXED + 2); + g_auto(GStrv) keylist =3D + g_new0(char *, VIR_NET_TLS_CONFIG_MAX_INDEXED + 2); + size_t i; + + /* + * When searching for indexed certs/keys, the first + * missing index terminates the search, so we don't + * get gaps in the returned array. All indexed files + * are optional, as if they're all missing, we'll + * still honour the traditional file names + */ + for (i =3D 0; i < VIR_NET_TLS_CONFIG_MAX_INDEXED; i++) { + virNetTLSConfigIdentityIndexed(isServer, + certdir, + keydir, + i, + &(certlist[i + 1]), + &(keylist[i + 1])); + + if (virNetTLSConfigEnsureIdentity(&(certlist[i + 1]), + &(keylist[i + 1]), true) < 0) + return -1; =20 - if (virNetTLSConfigEnsureIdentity(cert, key, allowMissingIdentity) < 0) - return -1; + if (certlist[i + 1] =3D=3D NULL) { + break; + } + } + + /* + * If we find index 0, then allow the traditional + * default files to be optional + */ + if (certlist[1] !=3D NULL) + allowMissingIdentity =3D true; + + virNetTLSConfigIdentity(isServer, + certdir, + keydir, + &(certlist[0]), + &(keylist[0])); + + if (virNetTLSConfigEnsureIdentity(&(certlist[0]), + &(keylist[0]), allowMissingIdent= ity) < 0) + return -1; + + if (certlist[0] =3D=3D NULL) { + memmove(certlist, certlist + 1, + VIR_NET_TLS_CONFIG_MAX_INDEXED * sizeof(char *)); + memmove(keylist, keylist + 1, + VIR_NET_TLS_CONFIG_MAX_INDEXED * sizeof(char *)); + certlist[VIR_NET_TLS_CONFIG_MAX_INDEXED] =3D NULL; + keylist[VIR_NET_TLS_CONFIG_MAX_INDEXED] =3D NULL; + } + + if (certlist[0] !=3D NULL) { + *certs =3D g_steal_pointer(&certlist); + *keys =3D g_steal_pointer(&keylist); + } + } =20 return 0; } @@ -285,8 +360,8 @@ int virNetTLSConfigCustomCreds(const char *pkipath, bool isServer, char **cacert, char **cacrl, - char **cert, - char **key) + char ***certs, + char ***keys) { VIR_DEBUG("Locating creds in custom dir %s", pkipath); =20 @@ -296,15 +371,15 @@ int virNetTLSConfigCustomCreds(const char *pkipath, false, !isServer, cacert, cacrl, - cert, key); + certs, keys); } =20 =20 int virNetTLSConfigUserCreds(bool isServer, char **cacert, char **cacrl, - char **cert, - char **key) + char ***certs, + char ***keys) { g_autofree char *pkipath =3D virNetTLSConfigUserPKIBaseDir(); =20 @@ -316,14 +391,14 @@ int virNetTLSConfigUserCreds(bool isServer, true, true, cacert, cacrl, - cert, key); + certs, keys); } =20 int virNetTLSConfigSystemCreds(bool isServer, char **cacert, char **cacrl, - char **cert, - char **key) + char ***certs, + char ***keys) { VIR_DEBUG("Locating creds in system dir %s", LIBVIRT_PKI_DIR); =20 @@ -335,5 +410,5 @@ int virNetTLSConfigSystemCreds(bool isServer, false, !isServer, cacert, cacrl, - cert, key); + certs, keys); } diff --git a/src/rpc/virnettlsconfig.h b/src/rpc/virnettlsconfig.h index 9ad213fe06..c0bf604950 100644 --- a/src/rpc/virnettlsconfig.h +++ b/src/rpc/virnettlsconfig.h @@ -60,15 +60,15 @@ int virNetTLSConfigCustomCreds(const char *pkipath, bool isServer, char **cacert, char **cacrl, - char **cert, - char **key); + char ***certs, + char ***keys); int virNetTLSConfigUserCreds(bool isServer, char **cacert, char **cacrl, - char **cert, - char **key); + char ***certs, + char ***keys); int virNetTLSConfigSystemCreds(bool isServer, char **cacert, char **cacrl, - char **cert, - char **key); + char ***certs, + char ***keys); diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c index 7061eb5953..dfe793e5db 100644 --- a/src/rpc/virnettlscontext.c +++ b/src/rpc/virnettlscontext.c @@ -220,13 +220,13 @@ static int virNetTLSContextLocateCredentials(const ch= ar *pkipath, bool isServer, char **cacert, char **cacrl, - char **cert, - char **key) + char ***certs, + char ***keys) { *cacert =3D NULL; *cacrl =3D NULL; - *key =3D NULL; - *cert =3D NULL; + *keys =3D NULL; + *certs =3D NULL; =20 VIR_DEBUG("pkipath=3D%s isServer=3D%d tryUserPkiPath=3D%d", pkipath, isServer, tryUserPkiPath); @@ -237,20 +237,31 @@ static int virNetTLSContextLocateCredentials(const ch= ar *pkipath, if (pkipath) { if (virNetTLSConfigCustomCreds(pkipath, isServer, cacert, cacrl, - cert, key) < 0) + certs, keys) < 0) return -1; } else { if (tryUserPkiPath && virNetTLSConfigUserCreds(isServer, cacert, cacrl, - cert, key) < 0) + certs, keys) < 0) return -1; =20 if (virNetTLSConfigSystemCreds(isServer, cacert, cacrl, - cert, key) < 0) + certs, keys) < 0) return -1; } + + /* + * Ensure the cert list is always non-NULL, even + * if it is an empty list, so that callers don't + * need to have repeated checks for a NULL array. + */ + if (*certs =3D=3D NULL) + *certs =3D g_new0(char *, 1); + if (*keys =3D=3D NULL) + *keys =3D g_new0(char *, 1); + return 0; } =20 @@ -265,16 +276,16 @@ static virNetTLSContext *virNetTLSContextNewPath(cons= t char *pkipath, { g_autofree char *cacert =3D NULL; g_autofree char *cacrl =3D NULL; - g_autofree char *key =3D NULL; - g_autofree char *cert =3D NULL; - const char *certs[] =3D { cert, NULL }; - const char *keys[] =3D { key, NULL }; + g_auto(GStrv) keys =3D NULL; + g_auto(GStrv) certs =3D NULL; =20 if (virNetTLSContextLocateCredentials(pkipath, tryUserPkiPath, isServe= r, - &cacert, &cacrl, &cert, &key) < = 0) + &cacert, &cacrl, &certs, &keys) = < 0) return NULL; =20 - return virNetTLSContextNew(cacert, cacrl, certs, keys, + return virNetTLSContextNew(cacert, cacrl, + (const char *const *)certs, + (const char *const *)keys, x509dnACL, priority, sanityCheckCert, requireValidCert, isServer); } @@ -329,15 +340,13 @@ int virNetTLSContextReloadForServer(virNetTLSContext = *ctxt, int err; g_autofree char *cacert =3D NULL; g_autofree char *cacrl =3D NULL; - g_autofree char *cert =3D NULL; - g_autofree char *key =3D NULL; - const char *certs[] =3D { cert, NULL }; - const char *keys[] =3D { key, NULL }; + g_auto(GStrv) certs =3D NULL; + g_auto(GStrv) keys =3D NULL; =20 x509credBak =3D g_steal_pointer(&ctxt->x509cred); =20 if (virNetTLSContextLocateCredentials(NULL, tryUserPkiPath, true, - &cacert, &cacrl, &cert, &key)) + &cacert, &cacrl, &certs, &keys)) goto error; =20 err =3D gnutls_certificate_allocate_credentials(&ctxt->x509cred); @@ -348,11 +357,13 @@ int virNetTLSContextReloadForServer(virNetTLSContext = *ctxt, goto error; } =20 - if (virNetTLSCertSanityCheck(true, cacert, certs)) + if (virNetTLSCertSanityCheck(true, cacert, + (const char *const *)certs)) goto error; =20 if (virNetTLSContextLoadCredentials(ctxt, cacert, cacrl, - certs, keys)) + (const char *const *)certs, + (const char *const *)keys)) goto error; =20 gnutls_certificate_free_credentials(x509credBak); --=20 2.51.1 From nobody Fri Nov 21 10:00:05 2025 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) client-ip=8.43.85.245; envelope-from=devel-bounces@lists.libvirt.org; helo=lists.libvirt.org; Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass(p=reject dis=none) header.from=lists.libvirt.org ARC-Seal: i=1; a=rsa-sha256; t=1762441340; cv=none; d=zohomail.com; s=zohoarc; b=NtEnpi/ROtsDp4u++MtIhDmEfBM2j3rVaESaWsEqj49lB38rhmoON/kgOIXEWv+5Bo6xFwt0yM1KsU+cIasSoFGbYatzlB2N9rPK2QRMmqkiyI20LQxwazo9i8brxIy0C4NVLVckDhaZQVbkGbozEdGQmUNcTox0AWkPYpaP1Wg= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1762441340; h=Content-Type:Content-Transfer-Encoding:Date:Date:From:From:In-Reply-To:List-Subscribe:List-Post:List-Owner:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:Reply-To:References:Subject:Subject:To:To:Message-Id:Cc; bh=M/VFQoYftGS/KuQgWPJNz0wMUoCxSpuTVCH2mekeys8=; b=QtivuJ06IQpoAGGT4bXF2saZnQXoh3GIlpCDWBTDFcv0NDJhzZMnyz3mt8x5Jh/fEJT53a1hSV5sXPZfGhAp4uWSz9xACaD+CuxgnlTTdC4E/AkB++Gv5e2R0/EaLsLW899MmGqxgFC8fZY2A+4aoaAx7qZwVvkGYSCVeFBf1Tc= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of lists.libvirt.org designates 8.43.85.245 as permitted sender) smtp.mailfrom=devel-bounces@lists.libvirt.org; dmarc=pass header.from= (p=reject dis=none) Return-Path: Received: from lists.libvirt.org (lists.libvirt.org [8.43.85.245]) by mx.zohomail.com with SMTPS id 1762441340981251.52230554822563; Thu, 6 Nov 2025 07:02:20 -0800 (PST) Received: by lists.libvirt.org (Postfix, from userid 993) id 7767041C76; Thu, 6 Nov 2025 10:02:20 -0500 (EST) Received: from [172.19.199.29] (lists.libvirt.org [8.43.85.245]) by lists.libvirt.org (Postfix) with ESMTP id 5B1DE443F8; Thu, 6 Nov 2025 09:53:49 -0500 (EST) Received: by lists.libvirt.org (Postfix, from userid 993) id CBD4343DF6; Thu, 6 Nov 2025 09:51:10 -0500 (EST) Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (3072 bits) server-digest SHA256) (No client certificate requested) by lists.libvirt.org (Postfix) with ESMTPS id E329541988 for ; Thu, 6 Nov 2025 09:51:09 -0500 (EST) Received: from mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (ec2-54-186-198-63.us-west-2.compute.amazonaws.com [54.186.198.63]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-520-PWbeHe06MR6A-4a_oUuUmQ-1; Thu, 06 Nov 2025 09:51:07 -0500 Received: from mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com [10.30.177.111]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mx-prod-mc-05.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTPS id 8764A1955DD0 for ; Thu, 6 Nov 2025 14:51:06 +0000 (UTC) Received: from toolbx.redhat.com (unknown [10.42.28.39]) by mx-prod-int-08.mail-002.prod.us-west-2.aws.redhat.com (Postfix) with ESMTP id 7AD8D1800451; Thu, 6 Nov 2025 14:51:05 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 4.0.1 (2024-03-26) on lists.libvirt.org X-Spam-Level: X-Spam-Status: No, score=-5.0 required=5.0 tests=BAYES_00,DKIM_INVALID, DKIM_SIGNED,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED, RCVD_IN_VALIDITY_CERTIFIED_BLOCKED,RCVD_IN_VALIDITY_RPBL_BLOCKED, RCVD_IN_VALIDITY_SAFE_BLOCKED,SPF_PASS autolearn=unavailable autolearn_force=no version=4.0.1 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1762440669; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=M/VFQoYftGS/KuQgWPJNz0wMUoCxSpuTVCH2mekeys8=; b=TzJR6PYVy3vtGcsiaqxbdSq+cctJYJh/oXXfD3SRdTKhEDjJAqIhp192UzOaXqmWYNTI6X t8N05wq2d54GdHNLODzGpts+uSTNur7Jea3jvbrDwna2G1IaWRQDBn1dlCgRjkY4bw78Aw Bc1UKlaDU2B9Gwef9c6ecJWfDBuSJ3g= X-MC-Unique: PWbeHe06MR6A-4a_oUuUmQ-1 X-Mimecast-MFC-AGG-ID: PWbeHe06MR6A-4a_oUuUmQ_1762440666 To: devel@lists.libvirt.org Subject: [PATCH 10/10] docs: describe support for multiple certs & PQC config Date: Thu, 6 Nov 2025 14:50:50 +0000 Message-ID: <20251106145050.1851526-11-berrange@redhat.com> In-Reply-To: <20251106145050.1851526-1-berrange@redhat.com> References: <20251106145050.1851526-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.30.177.111 X-Mimecast-Spam-Score: 0 X-Mimecast-MFC-PROC-ID: gVoFZSBCStKsSkGB5sVEUk8_f5VQNHbEbMeMDKGxCZE_1762440666 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-ID-Hash: 5NFSKYRJP4FKC4WLGY2WNLPM5JPUZR4J X-Message-ID-Hash: 5NFSKYRJP4FKC4WLGY2WNLPM5JPUZR4J X-MailFrom: berrange@redhat.com X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; header-match-devel.lists.libvirt.org-0; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header X-Mailman-Version: 3.3.10 Precedence: list List-Id: Development discussions about the libvirt library & tools Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: =?utf-8?q?Daniel_P=2E_Berrang=C3=A9_via_Devel?= Reply-To: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= X-ZohoMail-DKIM: fail (Header signature does not verify) X-ZM-MESSAGEID: 1762441342585154100 From: Daniel P. Berrang=C3=A9 This describes the new index based certificate naming scheme, and how to create & deploy certificates for post-quantum cryptography. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Michal Privoznik --- docs/kbase/tlscerts.rst | 88 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) diff --git a/docs/kbase/tlscerts.rst b/docs/kbase/tlscerts.rst index c10ab11b7f..db962d0f46 100644 --- a/docs/kbase/tlscerts.rst +++ b/docs/kbase/tlscerts.rst @@ -75,6 +75,25 @@ in the path specified, otherwise the connection will fai= l with a fatal error. If =20 - For the root user, the global default locations will always be used. =20 +Multiple parallel certificate identities +---------------------------------------- + +Any scenario that requires a certificate identify (``servercert.pem`` / +``serverkey.pem`` and ``clientcert.pem`` / ``clientkey.pem``) can optional= ly +provide multiple parallel identities via a new indexed file naming +scheme. The new filenames are ``servercertNN.pem`` / ``serverkeyNN.pem`` +and ``clientcertNN.pem`` / ``clientkeyNN.pem``, for values of ``NN`` betwe= en +0 and 3 inclusive. + +The new naming can be used instead of the old naming, or concurrently +with the old naming. The old file names will be loaded first (if +present), followed by the indexed file names. Loading will stop at +the first missing index value. ie if ``servercert1.pem`` is not present, +then no attempt will be made to load ``servercert2.pem`` or ``servercert3.= pem``. + +If multiple CA certificates are required they must all be concatenated +into the single ``cacert.pem`` file. + Background to TLS certificates ------------------------------ =20 @@ -326,6 +345,75 @@ briefly cover the steps. cp clientkey.pem /etc/pki/libvirt/private/clientkey.pem cp clientcert.pem /etc/pki/libvirt/clientcert.pem =20 +Configuring for Post-Quantum Cryptography +----------------------------------------- + +Given a new enough gnutls release, suitably integrated & configured with t= he +operating system crypto policies, libvirt is able to support post-quantum +crytography on TLS enabled services, either exclusively or in a hybrid mod= e. + +In exclusive mode, only a single set of certificates need to be configured +for libvirt, with PQC compliant algorithms. Such a libvirt configuration w= ill +only be able to interoperate with other libvirt daemons that also have PQC +enabled. This can result in compatibility concerns during the period of +transition over to PQC compliant algorithms. + +In hybrid mode, multiple sets of certificates need to be configured for li= bvirt, +at least one set with traditional (non-PQC compliant) algorithms, and at l= east +one other set with modern (PQC compliant) algorithms. At time of the TLS +handshake, the GNUTLS algorithm priorities should ensure that PQC compliant +algorithms are negotiated if both sides of the connection support PQC. If = one +side lacks PQC, the TLS handshake should fallback to the non-PQC algorithm= s. +This can assist with interoperability during the transition to PQC, but ha= s a +potential weakness wrt downgrade attacks forcing use of non-PQC algorithms. +Exclusive PQC mode should be preferred where both peers in the TLS connect= ions +are known to support PQC. + +Key generation parameters +^^^^^^^^^^^^^^^^^^^^^^^^^ + +To create certificates with PQC compliant algorithms, the ``--key-type`` +argument must be passed to ``certtool`` when creating private keys. No +extra arguments are required for the other ``certtool`` commands, as +their behaviour will be determined by the private key type. + +The typical PQC compliant algorithms to use are ``ML-DSA-44``, ``ML-DSA-65= `` +and ``ML-DSA-87``, with ``ML-DSA-65`` being a suitable default choice in +the absence of explicit requirements. + +Taking the example earlier, for creating a key for a client certificate, +to use ``ML-DSA-65`` the command line would be modified to look like:: + + # certtool --generate-privkey --key-type=3Dmldsa65 > clientkey.pem + +The equivalent modification applies to the creation of the private keys +used for server certs, or root/intermediate CA certs. + +For hybrid mode, the additional indexed certificate naming must be used. +If multiple configured certificates are compatible with the mutually +supported crypto algorithms between the client and server, then the +first matching certificate will be used. + +IOW, to ensure that PQC certificates are preferred, they must use a +non-index based filename, or use an index that is smaller than any +non-PQC certificates. ie, ``servercert.pem`` for PQC and ``servercert0.pem= `` +for non-PQC, or ``servercert0.pem`` for PQC and ``servercert1.pem`` for +non-PQC. + +Force disabling PQC via crypto priority +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +If the OS configuration for system crypto algorithm priorities has +enabled PQC, this can (optionally) be overriden in libvirt server +configuration. To disable use of PQC set the ``tls_priority`` +parameter in the ``libvirtd.conf`` / ``virtproxyd.conf`` files: + + tls_priority =3D "@SYSTEM:-SIGN-ML-DSA-65:-SIGN-ML-DSA-44:-SIGN-ML-DSA-8= 7:-GROUP-X25519-MLKEM768:-GROUP-SECP256R1-MLKEM768:-GROUP-SECP384R1-MLKEM10= 24" + +On the client side this can be overriden using the ``tls_priority`` +URI parameter in the libvirt connection address. + + Troubleshooting TLS certificate problems ---------------------------------------- =20 --=20 2.51.1