From 51997e50fa9a54c4bfce3cb2dd43b53418135d18 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Fri, 20 Jan 2012 17:18:28 +0000 Subject: [PATCH] Add APIs to get at more client security data A socket object has various pieces of security data associated with it, such as the SELinux context, the SASL username and the x509 distinguished name. Add new APIs to virNetServerClient and related modules to access this data. Signed-off-by: Daniel P. Berrange --- src/libvirt_gnutls.syms | 2 ++ src/libvirt_private.syms | 3 +++ src/libvirt_sasl.syms | 1 + src/rpc/virnetserverclient.c | 46 ++++++++++++++++++++++++++++++++++++ src/rpc/virnetserverclient.h | 7 ++++++ src/rpc/virnetsocket.c | 44 ++++++++++++++++++++++++++++++++++ src/rpc/virnetsocket.h | 2 ++ src/rpc/virnettlscontext.c | 18 ++++++++++++++ src/rpc/virnettlscontext.h | 2 ++ 9 files changed, 125 insertions(+) diff --git a/src/libvirt_gnutls.syms b/src/libvirt_gnutls.syms index bd4f950c81..6eb674101f 100644 --- a/src/libvirt_gnutls.syms +++ b/src/libvirt_gnutls.syms @@ -13,6 +13,7 @@ virNetServerSetTLSContext; # rpc/virnetserverclient.h virNetServerClientGetTLSKeySize; +virNetServerClientGetTLSSession; virNetServerClientHasTLSSession; @@ -33,6 +34,7 @@ virNetTLSContextNewServerPath; virNetTLSInit; virNetTLSSessionGetHandshakeStatus; virNetTLSSessionGetKeySize; +virNetTLSSessionGetX509DName; virNetTLSSessionHandshake; virNetTLSSessionNew; virNetTLSSessionRead; diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 5cad990076..369701ee17 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -854,11 +854,13 @@ virNetServerClientGetAuth; virNetServerClientGetFD; virNetServerClientGetPrivateData; virNetServerClientGetReadonly; +virNetServerClientGetSecurityContext; virNetServerClientGetUNIXIdentity; virNetServerClientImmediateClose; virNetServerClientInit; virNetServerClientInitKeepAlive; virNetServerClientIsClosed; +virNetServerClientIsLocal; virNetServerClientIsSecure; virNetServerClientLocalAddrString; virNetServerClientNeedAuth; @@ -923,6 +925,7 @@ virNetSocketClose; virNetSocketDupFD; virNetSocketGetFD; virNetSocketGetPort; +virNetSocketGetSecurityContext; virNetSocketGetUNIXIdentity; virNetSocketHasCachedData; virNetSocketHasPassFD; diff --git a/src/libvirt_sasl.syms b/src/libvirt_sasl.syms index beb8825a58..1241884b77 100644 --- a/src/libvirt_sasl.syms +++ b/src/libvirt_sasl.syms @@ -26,6 +26,7 @@ virNetSASLSessionServerStep; # rpc/virnetserverclient.h +virNetServerClientGetSASLSession; virNetServerClientSetSASLSession; diff --git a/src/rpc/virnetserverclient.c b/src/rpc/virnetserverclient.c index 19063ef146..3edcd3c3c1 100644 --- a/src/rpc/virnetserverclient.c +++ b/src/rpc/virnetserverclient.c @@ -587,6 +587,16 @@ bool virNetServerClientHasTLSSession(virNetServerClientPtr client) return has; } + +virNetTLSSessionPtr virNetServerClientGetTLSSession(virNetServerClientPtr client) +{ + virNetTLSSessionPtr tls; + virObjectLock(client); + tls = client->tls; + virObjectUnlock(client); + return tls; +} + int virNetServerClientGetTLSKeySize(virNetServerClientPtr client) { int size = 0; @@ -608,6 +618,18 @@ int virNetServerClientGetFD(virNetServerClientPtr client) return fd; } + +bool virNetServerClientIsLocal(virNetServerClientPtr client) +{ + bool local = false; + virObjectLock(client); + if (client->sock) + local = virNetSocketIsLocal(client->sock); + virObjectUnlock(client); + return local; +} + + int virNetServerClientGetUNIXIdentity(virNetServerClientPtr client, uid_t *uid, gid_t *gid, pid_t *pid) { @@ -619,6 +641,20 @@ int virNetServerClientGetUNIXIdentity(virNetServerClientPtr client, return ret; } + +int virNetServerClientGetSecurityContext(virNetServerClientPtr client, + char **context) +{ + int ret = 0; + *context = NULL; + virObjectLock(client); + if (client->sock) + ret = virNetSocketGetSecurityContext(client->sock, context); + virObjectUnlock(client); + return ret; +} + + bool virNetServerClientIsSecure(virNetServerClientPtr client) { bool secure = false; @@ -651,6 +687,16 @@ void virNetServerClientSetSASLSession(virNetServerClientPtr client, client->sasl = virObjectRef(sasl); virObjectUnlock(client); } + + +virNetSASLSessionPtr virNetServerClientGetSASLSession(virNetServerClientPtr client) +{ + virNetSASLSessionPtr sasl; + virObjectLock(client); + sasl = client->sasl; + virObjectUnlock(client); + return sasl; +} #endif diff --git a/src/rpc/virnetserverclient.h b/src/rpc/virnetserverclient.h index 31414bc4d5..f8643f5873 100644 --- a/src/rpc/virnetserverclient.h +++ b/src/rpc/virnetserverclient.h @@ -81,21 +81,28 @@ bool virNetServerClientGetReadonly(virNetServerClientPtr client); # ifdef WITH_GNUTLS bool virNetServerClientHasTLSSession(virNetServerClientPtr client); +virNetTLSSessionPtr virNetServerClientGetTLSSession(virNetServerClientPtr client); int virNetServerClientGetTLSKeySize(virNetServerClientPtr client); # endif # ifdef WITH_SASL void virNetServerClientSetSASLSession(virNetServerClientPtr client, virNetSASLSessionPtr sasl); +virNetSASLSessionPtr virNetServerClientGetSASLSession(virNetServerClientPtr client); # endif int virNetServerClientGetFD(virNetServerClientPtr client); bool virNetServerClientIsSecure(virNetServerClientPtr client); +bool virNetServerClientIsLocal(virNetServerClientPtr client); + int virNetServerClientGetUNIXIdentity(virNetServerClientPtr client, uid_t *uid, gid_t *gid, pid_t *pid); +int virNetServerClientGetSecurityContext(virNetServerClientPtr client, + char **context); + void *virNetServerClientGetPrivateData(virNetServerClientPtr client); typedef void (*virNetServerClientCloseFunc)(virNetServerClientPtr client); diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index fe4ac715d3..68aca1b2e9 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -40,6 +40,10 @@ #endif #include "c-ctype.h" +#ifdef HAVE_SELINUX +# include +#endif + #include "virnetsocket.h" #include "virutil.h" #include "viralloc.h" @@ -1156,6 +1160,46 @@ int virNetSocketGetUNIXIdentity(virNetSocketPtr sock ATTRIBUTE_UNUSED, } #endif +#ifdef HAVE_SELINUX +int virNetSocketGetSecurityContext(virNetSocketPtr sock, + char **context) +{ + security_context_t seccon = NULL; + int ret = -1; + + *context = NULL; + + virMutexLock(&sock->lock); + if (getpeercon(sock->fd, &seccon) < 0) { + if (errno == ENOSYS) { + ret = 0; + goto cleanup; + } + virReportSystemError(errno, "%s", + _("Unable to query peer security context")); + goto cleanup; + } + + if (!(*context = strdup(seccon))) { + virReportOOMError(); + goto cleanup; + } + + ret = 0; +cleanup: + freecon(seccon); + virMutexUnlock(&sock->lock); + return ret; +} +#else +int virNetSocketGetSecurityContext(virNetSocketPtr sock ATTRIBUTE_UNUSED, + char **context) +{ + *context = NULL; + return 0; +} +#endif + int virNetSocketSetBlocking(virNetSocketPtr sock, bool blocking) diff --git a/src/rpc/virnetsocket.h b/src/rpc/virnetsocket.h index 13583f846c..7392c722bf 100644 --- a/src/rpc/virnetsocket.h +++ b/src/rpc/virnetsocket.h @@ -114,6 +114,8 @@ int virNetSocketGetUNIXIdentity(virNetSocketPtr sock, uid_t *uid, gid_t *gid, pid_t *pid); +int virNetSocketGetSecurityContext(virNetSocketPtr sock, + char **context); int virNetSocketSetBlocking(virNetSocketPtr sock, bool blocking); diff --git a/src/rpc/virnettlscontext.c b/src/rpc/virnettlscontext.c index ece4620297..eed0439c32 100644 --- a/src/rpc/virnettlscontext.c +++ b/src/rpc/virnettlscontext.c @@ -71,6 +71,7 @@ struct _virNetTLSSession { virNetTLSSessionWriteFunc writeFunc; virNetTLSSessionReadFunc readFunc; void *opaque; + char *x509dname; }; static virClassPtr virNetTLSContextClass; @@ -1026,6 +1027,10 @@ static int virNetTLSContextValidCertificate(virNetTLSContextPtr ctxt, "[session]", gnutls_strerror(ret)); goto authfail; } + if (!(sess->x509dname = strdup(dname))) { + virReportOOMError(); + goto authfail; + } VIR_DEBUG("Peer DN is %s", dname); if (virNetTLSContextCheckCertDN(cert, "[session]", sess->hostname, dname, @@ -1364,6 +1369,18 @@ cleanup: return ssf; } +const char *virNetTLSSessionGetX509DName(virNetTLSSessionPtr sess) +{ + const char *ret = NULL; + + virObjectLock(sess); + + ret = sess->x509dname; + + virObjectUnlock(sess); + + return ret; +} void virNetTLSSessionDispose(void *obj) { @@ -1372,6 +1389,7 @@ void virNetTLSSessionDispose(void *obj) PROBE(RPC_TLS_SESSION_DISPOSE, "sess=%p", sess); + VIR_FREE(sess->x509dname); VIR_FREE(sess->hostname); gnutls_deinit(sess->session); } diff --git a/src/rpc/virnettlscontext.h b/src/rpc/virnettlscontext.h index 5910ceb9e9..21539adb99 100644 --- a/src/rpc/virnettlscontext.h +++ b/src/rpc/virnettlscontext.h @@ -94,4 +94,6 @@ virNetTLSSessionGetHandshakeStatus(virNetTLSSessionPtr sess); int virNetTLSSessionGetKeySize(virNetTLSSessionPtr sess); +const char *virNetTLSSessionGetX509DName(virNetTLSSessionPtr sess); + #endif