let certificate_entry = 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"
# Override the default server key file path
#
+# This parameter is mutually exclusive with 'key_files'
+#
#key_file = "@sysconfdir@/pki/libvirt/private/serverkey.pem"
+# Override the default server key file path(s)
+#
+# This parameter is mutually exclusive with 'key_file'
+#
+#key_files = ["@sysconfdir@/pki/libvirt/private/serverkey-0.pem", "@sysconfdir@/pki/libvirt/private/serverkey-1.pem"]
+
# Override the default server certificate file path
#
+# This parameter is mutually exclusive with 'cert_files'
+#
#cert_file = "@sysconfdir@/pki/libvirt/servercert.pem"
+# Override the default server certificate file path(s)
+#
+# This parameter is mutually exclusive with 'cert_file'
+#
+#cert_files = ["@sysconfdir@/pki/libvirt/servercert-0.pem", "@sysconfdir@/pki/libvirt/servercert-1.pem"]
+
# Override the default CA certificate path
#
#ca_file = "@sysconfdir@/pki/CA/cacert.pem"
virNetTLSContext *ctxt = NULL;
if (config->ca_file ||
- config->cert_file ||
- config->key_file) {
- const char *certs[] = { config->cert_file, NULL };
- const char *keys[] = { config->key_file, NULL };
-
+ config->cert_files ||
+ config->key_files) {
+ g_autofree char *certs = g_strjoinv(", ", config->cert_files);
+ g_autofree char *keys = g_strjoinv(", ", config->key_files);
if (!config->ca_file) {
virReportError(VIR_ERR_CONFIG_UNSUPPORTED, "%s",
- _("No CA certificate path set to match server key/cert"));
+ _("No CA certificate path set to match server 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 match 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 cert"));
+ _("No server key path(s) set to match server cert(s)"));
return -1;
}
- VIR_DEBUG("Using CA='%s' cert='%s' key='%s'",
- config->ca_file, config->cert_file, config->key_file);
+ VIR_DEBUG("Using CA='%s' certs='%s' keys='%s'",
+ config->ca_file, certs, keys);
if (!(ctxt = virNetTLSContextNewServer(config->ca_file,
config->crl_file,
- certs, keys,
+ (const char *const*)config->cert_files,
+ (const char *const*)config->key_files,
(const char *const*)config->tls_allowed_dn_list,
config->tls_priority,
config->tls_no_sanity_certificate ? false : true,
g_free(data->tls_priority);
- 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 */
virConf *conf)
{
int rc G_GNUC_UNUSED;
-
#ifdef WITH_IP
+ g_autofree char *cert_file = NULL;
+ g_autofree char *key_file = 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)
if (virConfGetValueBool(conf, "tls_no_verify_certificate", &data->tls_no_verify_certificate) < 0)
return -1;
- 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_files) < 0)
+ return -1;
+ if (virConfGetValueStringList(conf, "cert_files", false, &data->cert_files) < 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 cert_files/key_files"));
return -1;
- if (virConfGetValueString(conf, "cert_file", &data->cert_file) < 0)
+ }
+ if (cert_file) {
+ data->cert_files = g_new0(char *, 2);
+ data->cert_files[0] = g_steal_pointer(&cert_file);
+ data->cert_files[1] = NULL;
+ }
+ if (key_file) {
+ data->key_files = g_new0(char *, 2);
+ data->key_files[0] = g_steal_pointer(&key_file);
+ data->key_files[1] = NULL;
+ }
+ ncerts = data->cert_files ? g_strv_length(data->cert_files) : 0;
+ nkeys = data->key_files ? g_strv_length(data->key_files) : 0;
+ if (ncerts != 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)
char *tls_priority;
unsigned int tcp_min_ssf;
- char *key_file;
- char *cert_file;
+ char **key_files;
+ char **cert_files;
char *ca_file;
char *crl_file;
#endif /* ! WITH_IP */
}
@CUT_ENABLE_IP@
{ "key_file" = "@sysconfdir@/pki/libvirt/private/serverkey.pem" }
+ { "key_files"
+ { "1" = "@sysconfdir@/pki/libvirt/private/serverkey-0.pem" }
+ { "2" = "@sysconfdir@/pki/libvirt/private/serverkey-1.pem" }
+ }
{ "cert_file" = "@sysconfdir@/pki/libvirt/servercert.pem" }
+ { "cert_files"
+ { "1" = "@sysconfdir@/pki/libvirt/servercert-0.pem" }
+ { "2" = "@sysconfdir@/pki/libvirt/servercert-1.pem" }
+ }
{ "ca_file" = "@sysconfdir@/pki/CA/cacert.pem" }
{ "crl_file" = "@sysconfdir@/pki/CA/crl.pem" }
{ "tls_no_sanity_certificate" = "1" }