mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-03-03 07:33:50 +00:00
remote: pass identity across to newly opened daemons
When opening a connection to a second driver inside the daemon, we must ensure the identity of the current user is passed across. This allows the second daemon to perform access control checks against the real end users, instead of against the libvirt daemon that's proxying across the API calls. Reviewed-by: Michal Privoznik <mprivozn@redhat.com> Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
4471003836
commit
7d84ce059e
@ -178,6 +178,7 @@ virNetServerClientSetAuthLocked;
|
||||
virNetServerClientSetAuthPendingLocked;
|
||||
virNetServerClientSetCloseHook;
|
||||
virNetServerClientSetDispatcher;
|
||||
virNetServerClientSetIdentity;
|
||||
virNetServerClientSetQuietEOF;
|
||||
virNetServerClientSetReadonly;
|
||||
virNetServerClientStartKeepAlive;
|
||||
|
@ -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,
|
||||
|
@ -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 */
|
||||
|
@ -53,6 +53,9 @@ typedef string remote_nonnull_string<REMOTE_STRING_MAX>;
|
||||
/* 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<REMOTE_DOMAIN_GUEST_INFO_PARAMS_MAX>;
|
||||
};
|
||||
|
||||
struct remote_connect_set_identity_args {
|
||||
remote_typed_param params<REMOTE_CONNECT_IDENTITY_PARAMS_MAX>;
|
||||
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
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -123,6 +123,8 @@ int virNetServerClientGetSELinuxContext(virNetServerClientPtr client,
|
||||
char **context);
|
||||
|
||||
virIdentityPtr virNetServerClientGetIdentity(virNetServerClientPtr client);
|
||||
void virNetServerClientSetIdentity(virNetServerClientPtr client,
|
||||
virIdentityPtr identity);
|
||||
|
||||
void *virNetServerClientGetPrivateData(virNetServerClientPtr client);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user