Add an API to update server's tls context before admin method can be
introduced.
---
include/libvirt/libvirt-admin.h | 8 ++++
src/libvirt_remote.syms | 1 +
src/rpc/virnetserver.c | 72 +++++++++++++++++++++++++++++++++
src/rpc/virnetserver.h | 3 ++
src/rpc/virnetserverclient.c | 4 ++
src/rpc/virnettlscontext.c | 41 +++++++++++++++++++
src/rpc/virnettlscontext.h | 2 +
7 files changed, 131 insertions(+)
diff --git a/include/libvirt/libvirt-admin.h b/include/libvirt/libvirt-admin.h
index abf2792926..3edc044490 100644
--- a/include/libvirt/libvirt-admin.h
+++ b/include/libvirt/libvirt-admin.h
@@ -392,6 +392,14 @@ int virAdmClientClose(virAdmClientPtr client, unsigned int flags);
# define VIR_SERVER_CLIENTS_UNAUTH_CURRENT "nclients_unauth"
+/* tls related filetype flags. */
+typedef enum {
+ VIR_TLS_FILE_TYPE_CA_CERT = (1U << 0),
+ VIR_TLS_FILE_TYPE_CA_CRL = (1U << 1),
+ VIR_TLS_FILE_TYPE_SERVER_CERT = (1U << 2),
+ VIR_TLS_FILE_TYPE_SERVER_KEY = (1U << 3),
+} virServerTlsFiletype;
+
int virAdmServerGetClientLimits(virAdmServerPtr srv,
virTypedParameterPtr *params,
int *nparams,
diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms
index 0493467f46..0018a0c41d 100644
--- a/src/libvirt_remote.syms
+++ b/src/libvirt_remote.syms
@@ -137,6 +137,7 @@ virNetServerSetClientLimits;
virNetServerSetThreadPoolParameters;
virNetServerSetTLSContext;
virNetServerUpdateServices;
+virNetServerUpdateTlsFiles;
# rpc/virnetserverclient.h
diff --git a/src/rpc/virnetserver.c b/src/rpc/virnetserver.c
index c87dade1a8..65ec677d0a 100644
--- a/src/rpc/virnetserver.c
+++ b/src/rpc/virnetserver.c
@@ -1207,3 +1207,75 @@ virNetServerSetClientLimits(virNetServerPtr srv,
virObjectUnlock(srv);
return ret;
}
+
+static virNetTLSContextPtr
+virNetServerGetTLSContext(virNetServerPtr srv)
+{
+ size_t i;
+ virNetTLSContextPtr ctxt = NULL;
+ virNetServerServicePtr svc = NULL;
+
+ /* find svcTLS from srv, get svcTLS->tls */
+ for (i = 0; i < srv->nservices; i++) {
+ svc = srv->services[i];
+ ctxt = virNetServerServiceGetTLSContext(svc);
+ if (ctxt != NULL)
+ break;
+ }
+
+ return ctxt;
+}
+
+static int virNetServerUpdateTlsFilesCheckParams(unsigned int filetypes)
+{
+ bool haveSrvCert = filetypes & VIR_TLS_FILE_TYPE_SERVER_CERT;
+ bool haveSrvKey = filetypes & VIR_TLS_FILE_TYPE_SERVER_KEY;
+
+ if ((haveSrvCert && !haveSrvKey) ||
+ (!haveSrvCert && haveSrvKey)) {
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("server cert/key must be updated together. "
+ "filetypes: %d"), filetypes);
+ return -1;
+ }
+
+ return 0;
+}
+
+int
+virNetServerUpdateTlsFiles(virNetServerPtr srv,
+ unsigned int filetypes)
+{
+ int ret = -1;
+#ifndef WITH_GNUTLS
+ virReportError(VIR_ERR_SYSTEM_ERROR,
+ _("Don't support GNUTLS, can't to update filetypes:
%d"),
+ filetypes);
+#else
+ virNetTLSContextPtr ctxt = NULL;
+
+ if (virNetServerUpdateTlsFilesCheckParams(filetypes))
+ return -1;
+
+ virObjectLock(srv);
+
+ ctxt = virNetServerGetTLSContext(srv);
+ if (!ctxt) {
+ VIR_ERROR(_("no tls svc found, can't to update filetypes: %d"),
+ filetypes);
+ goto cleanup;
+ }
+
+ if (virNetTLSContextReload(ctxt, filetypes)) {
+ VIR_ERROR(_("reload server's tls context fail"));
+ goto cleanup;
+ }
+
+ VIR_INFO("update all tls files complete, filetypes: %d", filetypes);
+ ret = 0;
+
+ cleanup:
+ virObjectUnlock(srv);
+#endif
+ return ret;
+}
diff --git a/src/rpc/virnetserver.h b/src/rpc/virnetserver.h
index 260c99b22d..99466dd041 100644
--- a/src/rpc/virnetserver.h
+++ b/src/rpc/virnetserver.h
@@ -133,3 +133,6 @@ size_t virNetServerGetCurrentUnauthClients(virNetServerPtr srv);
int virNetServerSetClientLimits(virNetServerPtr srv,
long long int maxClients,
long long int maxClientsUnauth);
+
+int virNetServerUpdateTlsFiles(virNetServerPtr srv,
+ unsigned int filetypes);
diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c
index 67b3bf9531..f0952cadde 100644
--- a/src/rpc/virnetserverclient.c
+++ b/src/rpc/virnetserverclient.c
@@ -1117,7 +1117,9 @@ int virNetServerClientInit(virNetServerClientPtr client)
client->tls);
/* Begin the TLS handshake. */
+ virObjectLock(client->tlsCtxt);
ret = virNetTLSSessionHandshake(client->tls);
+ virObjectUnlock(client->tlsCtxt);
if (ret == 0) {
/* Unlikely, but ... Next step is to check the certificate. */
if (virNetServerClientCheckAccess(client) < 0)
@@ -1438,7 +1440,9 @@ virNetServerClientDispatchHandshake(virNetServerClientPtr client)
{
int ret;
/* Continue the handshake. */
+ virObjectLock(client->tlsCtxt);
ret = virNetTLSSessionHandshake(client->tls);
+ virObjectUnlock(client->tlsCtxt);
if (ret == 0) {
/* Finished. Next step is to check the certificate. */
if (virNetServerClientCheckAccess(client) < 0)
diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c
index 12811bed78..8baa6a15b2 100644
--- a/src/rpc/virnettlscontext.c
+++ b/src/rpc/virnettlscontext.c
@@ -1139,6 +1139,47 @@ void virNetTLSContextDispose(void *obj)
gnutls_certificate_free_credentials(ctxt->x509cred);
}
+int virNetTLSContextReload(virNetTLSContextPtr ctxt,
+ unsigned int filetypes)
+{
+ int ret = -1;
+ char *cacert = NULL;
+ char *cacrl = NULL;
+ char *cert = NULL;
+ char *key = NULL;
+
+ virObjectLock(ctxt);
+
+ if (virNetTLSContextLocateCredentials(NULL, false, true,
+ &cacert, &cacrl, &cert, &key)
< 0)
+ goto cleanup;
+
+ if (filetypes & VIR_TLS_FILE_TYPE_CA_CERT) {
+ if (virNetTLSContextSetCACert(ctxt, cacert, false))
+ goto cleanup;
+ }
+
+ if (filetypes & VIR_TLS_FILE_TYPE_CA_CRL) {
+ if (virNetTLSContextSetCACRL(ctxt, cacrl, false))
+ goto cleanup;
+ }
+
+ if (filetypes & VIR_TLS_FILE_TYPE_SERVER_CERT) {
+ gnutls_certificate_free_keys(ctxt->x509cred);
+ if (virNetTLSContextSetCertAndKey(ctxt, cert, key, false))
+ goto cleanup;
+ }
+
+ ret = 0;
+
+ cleanup:
+ virObjectUnlock(ctxt);
+ VIR_FREE(cacert);
+ VIR_FREE(cacrl);
+ VIR_FREE(key);
+ VIR_FREE(cert);
+ return ret;
+}
static ssize_t
virNetTLSSessionPush(void *opaque, const void *buf, size_t len)
diff --git a/src/rpc/virnettlscontext.h b/src/rpc/virnettlscontext.h
index f3273bc26a..9e83caf255 100644
--- a/src/rpc/virnettlscontext.h
+++ b/src/rpc/virnettlscontext.h
@@ -65,6 +65,8 @@ virNetTLSContextPtr virNetTLSContextNewClient(const char *cacert,
int virNetTLSContextCheckCertificate(virNetTLSContextPtr ctxt,
virNetTLSSessionPtr sess);
+int virNetTLSContextReload(virNetTLSContextPtr ctxt,
+ unsigned int filetypes);
typedef ssize_t (*virNetTLSSessionWriteFunc)(const char *buf, size_t len,
void *opaque);
--
2.23.0.windows.1