diff --git a/src/libvirt_remote.syms b/src/libvirt_remote.syms index 3307d74324..0493467f46 100644 --- a/src/libvirt_remote.syms +++ b/src/libvirt_remote.syms @@ -178,6 +178,7 @@ virNetServerClientSetAuthLocked; virNetServerClientSetAuthPendingLocked; virNetServerClientSetCloseHook; virNetServerClientSetDispatcher; +virNetServerClientSetIdentity; virNetServerClientSetQuietEOF; virNetServerClientSetReadonly; virNetServerClientStartKeepAlive; diff --git a/src/remote/remote_daemon_dispatch.c b/src/remote/remote_daemon_dispatch.c index ecde959088..dbd2985c38 100644 --- a/src/remote/remote_daemon_dispatch.c +++ b/src/remote/remote_daemon_dispatch.c @@ -51,6 +51,7 @@ #include "virpolkit.h" #include "virthreadjob.h" #include "configmake.h" +#include "access/viraccessapicheck.h" #define VIR_FROM_THIS VIR_FROM_RPC @@ -1945,10 +1946,16 @@ static void remoteClientCloseFunc(virNetServerClientPtr client) static int remoteOpenConn(const char *uri, bool readonly, + bool preserveIdentity, virConnectPtr *conn) { - VIR_DEBUG("Getting secondary uri=%s readonly=%d conn=%p", - NULLSTR(uri), readonly, conn); + virTypedParameterPtr params = NULL; + int nparams = 0; + int ret = -1; + + VIR_DEBUG("Getting secondary uri=%s readonly=%d preserveIdent=%d conn=%p", + NULLSTR(uri), readonly, preserveIdentity, conn); + if (*conn) return 0; @@ -1957,16 +1964,43 @@ remoteOpenConn(const char *uri, return -1; } + if (preserveIdentity) { + VIR_AUTOUNREF(virIdentityPtr) ident = NULL; + + if (!(ident = virIdentityGetCurrent())) + return -1; + + if (virIdentityGetParameters(ident, ¶ms, &nparams) < 0) + goto error; + } + VIR_DEBUG("Opening driver %s", uri); if (readonly) *conn = virConnectOpenReadOnly(uri); else *conn = virConnectOpen(uri); if (!*conn) - return -1; + goto error; VIR_DEBUG("Opened driver %p", *conn); - return 0; + if (preserveIdentity) { + if (virConnectSetIdentity(*conn, params, nparams, 0) < 0) + goto error; + + VIR_DEBUG("Forwarded current identity to secondary driver"); + } + + ret = 0; + cleanup: + virTypedParamsFree(params, nparams); + return ret; + + error: + if (*conn) { + virConnectClose(*conn); + *conn = NULL; + } + goto cleanup; } @@ -1993,6 +2027,7 @@ remoteGetInterfaceConn(virNetServerClientPtr client) if (remoteOpenConn(priv->interfaceURI, priv->readonly, + true, &priv->interfaceConn) < 0) return NULL; @@ -2008,6 +2043,7 @@ remoteGetNetworkConn(virNetServerClientPtr client) if (remoteOpenConn(priv->networkURI, priv->readonly, + true, &priv->networkConn) < 0) return NULL; @@ -2023,6 +2059,7 @@ remoteGetNodeDevConn(virNetServerClientPtr client) if (remoteOpenConn(priv->nodedevURI, priv->readonly, + true, &priv->nodedevConn) < 0) return NULL; @@ -2038,6 +2075,7 @@ remoteGetNWFilterConn(virNetServerClientPtr client) if (remoteOpenConn(priv->nwfilterURI, priv->readonly, + true, &priv->nwfilterConn) < 0) return NULL; @@ -2053,6 +2091,7 @@ remoteGetSecretConn(virNetServerClientPtr client) if (remoteOpenConn(priv->secretURI, priv->readonly, + true, &priv->secretConn) < 0) return NULL; @@ -2068,6 +2107,7 @@ remoteGetStorageConn(virNetServerClientPtr client) if (remoteOpenConn(priv->storageURI, priv->readonly, + true, &priv->storageConn) < 0) return NULL; @@ -2237,6 +2277,7 @@ remoteDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED, #ifdef MODULE_NAME const char *type = NULL; #endif /* !MODULE_NAME */ + bool preserveIdentity = false; VIR_DEBUG("priv=%p conn=%p", priv, priv->conn); virMutexLock(&priv->lock); @@ -2264,16 +2305,16 @@ remoteDispatchConnectOpen(virNetServerPtr server ATTRIBUTE_UNUSED, name = probeduri; } -#endif + + preserveIdentity = true; +#endif /* VIRTPROXYD */ VIR_DEBUG("Opening driver %s", name); - if (priv->readonly) { - if (!(priv->conn = virConnectOpenReadOnly(name))) - goto cleanup; - } else { - if (!(priv->conn = virConnectOpen(name))) - goto cleanup; - } + if (remoteOpenConn(name, + priv->readonly, + preserveIdentity, + &priv->conn) < 0) + goto cleanup; VIR_DEBUG("Opened %p", priv->conn); #ifdef MODULE_NAME @@ -2384,6 +2425,53 @@ remoteDispatchConnectClose(virNetServerPtr server ATTRIBUTE_UNUSED, } +static int +remoteDispatchConnectSetIdentity(virNetServerPtr server ATTRIBUTE_UNUSED, + virNetServerClientPtr client, + virNetMessagePtr msg ATTRIBUTE_UNUSED, + virNetMessageErrorPtr rerr, + remote_connect_set_identity_args *args) +{ + virTypedParameterPtr params = NULL; + int nparams = 0; + int rv = -1; + virConnectPtr conn = remoteGetHypervisorConn(client); + VIR_AUTOUNREF(virIdentityPtr) ident = NULL; + if (!conn) + goto cleanup; + + VIR_DEBUG("Received forwarded identity"); + if (virTypedParamsDeserialize((virTypedParameterRemotePtr) args->params.params_val, + args->params.params_len, + REMOTE_CONNECT_IDENTITY_PARAMS_MAX, + ¶ms, + &nparams) < 0) + goto cleanup; + + VIR_TYPED_PARAMS_DEBUG(params, nparams); + + if (virConnectSetIdentityEnsureACL(conn) < 0) + goto cleanup; + + if (!(ident = virIdentityNew())) + goto cleanup; + + if (virIdentitySetParameters(ident, params, nparams) < 0) + goto cleanup; + + virNetServerClientSetIdentity(client, ident); + + rv = 0; + + cleanup: + virTypedParamsFree(params, nparams); + if (rv < 0) + virNetMessageSaveError(rerr); + return rv; +} + + + static int remoteDispatchDomainGetSchedulerType(virNetServerPtr server ATTRIBUTE_UNUSED, virNetServerClientPtr client, diff --git a/src/remote/remote_driver.c b/src/remote/remote_driver.c index 2b86f55035..8789c5da00 100644 --- a/src/remote/remote_driver.c +++ b/src/remote/remote_driver.c @@ -8507,6 +8507,7 @@ static virHypervisorDriver hypervisor_driver = { .name = "remote", .connectOpen = remoteConnectOpen, /* 0.3.0 */ .connectClose = remoteConnectClose, /* 0.3.0 */ + .connectSetIdentity = remoteConnectSetIdentity, /* 5.8.0 */ .connectSupportsFeature = remoteConnectSupportsFeature, /* 0.3.0 */ .connectGetType = remoteConnectGetType, /* 0.3.0 */ .connectGetVersion = remoteConnectGetVersion, /* 0.3.0 */ diff --git a/src/remote/remote_protocol.x b/src/remote/remote_protocol.x index 75c2bc69ff..f4e3392212 100644 --- a/src/remote/remote_protocol.x +++ b/src/remote/remote_protocol.x @@ -53,6 +53,9 @@ typedef string remote_nonnull_string; /* A long string, which may be NULL. */ typedef remote_nonnull_string *remote_string; +/* Upper limit on identity parameters */ +const REMOTE_CONNECT_IDENTITY_PARAMS_MAX = 20; + /* Upper limit on lists of domains. */ const REMOTE_DOMAIN_LIST_MAX = 16384; @@ -3736,6 +3739,11 @@ struct remote_domain_get_guest_info_ret { remote_typed_param params; }; +struct remote_connect_set_identity_args { + remote_typed_param params; + unsigned int flags; +}; + /*----- Protocol. -----*/ /* Define the program number, protocol version and procedure numbers here. */ @@ -6603,5 +6611,11 @@ enum remote_procedure { * @generate: none * @acl: domain:write */ - REMOTE_PROC_DOMAIN_GET_GUEST_INFO = 418 + REMOTE_PROC_DOMAIN_GET_GUEST_INFO = 418, + + /** + * @generate: client + * @acl: connect:write + */ + REMOTE_PROC_CONNECT_SET_IDENTITY = 419 }; diff --git a/src/remote_protocol-structs b/src/remote_protocol-structs index 616c3d5d52..eb689b3574 100644 --- a/src/remote_protocol-structs +++ b/src/remote_protocol-structs @@ -3116,6 +3116,13 @@ struct remote_domain_get_guest_info_ret { remote_typed_param * params_val; } params; }; +struct remote_connect_set_identity_args { + struct { + u_int params_len; + remote_typed_param * params_val; + } params; + u_int flags; +}; enum remote_procedure { REMOTE_PROC_CONNECT_OPEN = 1, REMOTE_PROC_CONNECT_CLOSE = 2, @@ -3535,4 +3542,5 @@ enum remote_procedure { REMOTE_PROC_DOMAIN_CHECKPOINT_GET_PARENT = 416, REMOTE_PROC_DOMAIN_CHECKPOINT_DELETE = 417, REMOTE_PROC_DOMAIN_GET_GUEST_INFO = 418, + REMOTE_PROC_CONNECT_SET_IDENTITY = 419, }; diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c index 1b96d0339b..171ee636dd 100644 --- a/src/rpc/virnetserverclient.c +++ b/src/rpc/virnetserverclient.c @@ -844,6 +844,18 @@ virIdentityPtr virNetServerClientGetIdentity(virNetServerClientPtr client) } +void virNetServerClientSetIdentity(virNetServerClientPtr client, + virIdentityPtr identity) +{ + virObjectLock(client); + virObjectUnref(client->identity); + client->identity = identity; + if (client->identity) + virObjectRef(client->identity); + virObjectUnlock(client); +} + + int virNetServerClientGetSELinuxContext(virNetServerClientPtr client, char **context) { diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h index 1b01bedbcb..1c520fef6b 100644 --- a/src/rpc/virnetserverclient.h +++ b/src/rpc/virnetserverclient.h @@ -123,6 +123,8 @@ int virNetServerClientGetSELinuxContext(virNetServerClientPtr client, char **context); virIdentityPtr virNetServerClientGetIdentity(virNetServerClientPtr client); +void virNetServerClientSetIdentity(virNetServerClientPtr client, + virIdentityPtr identity); void *virNetServerClientGetPrivateData(virNetServerClientPtr client);