From nobody Fri Nov 21 10:08:31 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 --- 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