From: "Daniel P. Berrange" <berrange@xxxxxxxxxx> Add APIs which allow storage of a real & effective identity on all server clients. Also add an API which allows creation of an initial identity based on the results of client authentication processes like TLS, x509, SASL, SO_PEERCRED --- src/rpc/virnetserverclient.c | 152 ++++++++++++++++++++++++++++++++++++++++++ src/rpc/virnetserverclient.h | 11 +++ 2 files changed, 163 insertions(+), 0 deletions(-) diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c index 1e9d3db..9647ac3 100644 --- a/src/rpc/virnetserverclient.c +++ b/src/rpc/virnetserverclient.c @@ -75,6 +75,10 @@ struct _virNetServerClient int sockTimer; /* Timer to be fired upon cached data, * so we jump out from poll() immediately */ + + virIdentityPtr realIdentity; + virIdentityPtr effectiveIdentity; + /* Count of messages in the 'tx' queue, * and the server worker pool queue * ie RPC calls in progress. Does not count @@ -487,6 +491,149 @@ int virNetServerClientGetUNIXIdentity(virNetServerClientPtr client, } +virIdentityPtr virNetServerClientGetIdentity(virNetServerClientPtr client) +{ + char *processid = NULL; + char *username = NULL; + char *groupname = NULL; +#if HAVE_SASL + char *saslname = NULL; +#endif + char *x509dname = NULL; + char *seccontext = NULL; + virIdentityPtr ret = NULL; + virNetSASLSessionPtr sasl; + virNetTLSSessionPtr tls; + + if (virNetServerClientIsLocal(client)) { + gid_t gid; + uid_t uid; + pid_t pid; + if (virNetServerClientGetUNIXIdentity(client, &uid, &gid, &pid) < 0) + goto cleanup; + + if (!(username = virGetUserName(uid))) + goto cleanup; + if (!(groupname = virGetGroupName(gid))) + goto cleanup; + if (virAsprintf(&processid, "%d", (int)pid) < 0) + goto cleanup; + } + +#if HAVE_SASL + if ((sasl = virNetServerClientGetSASLSession(client))) { + const char *identity = virNetSASLSessionGetIdentity(sasl); + if (identity && + !(saslname = strdup(identity))) { + virReportOOMError(); + goto cleanup; + } + } +#endif + + if ((tls = virNetServerClientGetTLSSession(client))) { + const char *identity = virNetTLSSessionGetX509DName(tls); + if (identity && + !(x509dname = strdup(identity))) { + virReportOOMError(); + goto cleanup; + } + } + + if (virNetServerClientGetSecurityContext(client, &seccontext) < 0) + goto cleanup; + + if (!(ret = virIdentityNew())) + goto cleanup; + + if (username && + virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_USER_NAME, username) < 0) + goto error; + if (groupname && + virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_GROUP_NAME, groupname) < 0) + goto error; + if (processid && + virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_UNIX_PROCESS_ID, processid) < 0) + goto error; +#if HAVE_SASL + if (saslname && + virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_SASL_USER_NAME, saslname) < 0) + goto error; +#endif + if (x509dname && + virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_X509_DISTINGUISHED_NAME, x509dname) < 0) + goto error; + if (seccontext && + virIdentitySetAttr(ret, VIR_IDENTITY_ATTR_SECURITY_CONTEXT, seccontext) < 0) + goto error; + +cleanup: + VIR_FREE(username); + VIR_FREE(groupname); + VIR_FREE(processid); + VIR_FREE(seccontext); +#if HAVE_SASL + VIR_FREE(saslname); +#endif + VIR_FREE(x509dname); + return ret; + +error: + virIdentityFree(ret); + ret = NULL; + goto cleanup; +} + + +virIdentityPtr virNetServerClientGetRealIdentity(virNetServerClientPtr client) +{ + virIdentityPtr ret; + virNetServerClientLock(client); + ret = client->realIdentity; + if (ret) + virIdentityRef(ret); + virNetServerClientUnlock(client); + return ret; +} + + +virIdentityPtr virNetServerClientGetEffectiveIdentity(virNetServerClientPtr client) +{ + virIdentityPtr ret; + virNetServerClientLock(client); + ret = client->effectiveIdentity; + if (ret) + virIdentityRef(ret); + virNetServerClientUnlock(client); + return ret; +} + + +void virNetServerClientSetRealIdentity(virNetServerClientPtr client, + virIdentityPtr ident) +{ + virNetServerClientLock(client); + if (client->realIdentity) + virIdentityFree(client->realIdentity); + if (ident) + virIdentityRef(ident); + client->realIdentity = ident; + virNetServerClientUnlock(client); +} + +void virNetServerClientSetEffectiveIdentity(virNetServerClientPtr client, + virIdentityPtr ident) +{ + virNetServerClientLock(client); + if (client->effectiveIdentity) + virIdentityFree(client->effectiveIdentity); + if (ident) + virIdentityRef(ident); + client->effectiveIdentity = ident; + virNetServerClientUnlock(client); +} + + int virNetServerClientGetSecurityContext(virNetServerClientPtr client, char **context) { @@ -625,6 +772,11 @@ void virNetServerClientFree(virNetServerClientPtr client) return; } + if (client->realIdentity) + virIdentityFree(client->realIdentity); + if (client->effectiveIdentity) + virIdentityFree(client->effectiveIdentity); + if (client->privateData && client->privateDataFreeFunc) client->privateDataFreeFunc(client->privateData); diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h index a3b37a3..7435eee 100644 --- a/src/rpc/virnetserverclient.h +++ b/src/rpc/virnetserverclient.h @@ -77,6 +77,17 @@ int virNetServerClientGetUNIXIdentity(virNetServerClientPtr client, int virNetServerClientGetSecurityContext(virNetServerClientPtr client, char **context); +virIdentityPtr virNetServerClientGetIdentity(virNetServerClientPtr client); + +virIdentityPtr virNetServerClientGetRealIdentity(virNetServerClientPtr client); +virIdentityPtr virNetServerClientGetEffectiveIdentity(virNetServerClientPtr client); + +void virNetServerClientSetRealIdentity(virNetServerClientPtr client, + virIdentityPtr ident); +void virNetServerClientSetEffectiveIdentity(virNetServerClientPtr client, + virIdentityPtr iden); + + void virNetServerClientRef(virNetServerClientPtr client); typedef void (*virNetServerClientFreeFunc)(void *data); -- 1.7.7.5 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list