From 8996f80a5e3b205cb580aba34aa21d165ef78cfb Mon Sep 17 00:00:00 2001 From: Alan Coopersmith Date: Wed, 15 Feb 2017 14:42:48 +0000 Subject: Rework local client id finding code to be more uniform Backport of X.org commit: commit 2d93e69690d2c5d4a89a795ede6423796528e5df Author: Alan Coopersmith Date: Thu Sep 27 16:47:06 2007 -0700 Rework local client id finding code to be more uniform Backported-to-NX-by: Mike Gabriel Note: This commit also switches client_uid_string's size from 32 to 64 chars, as found in this X.org commit (spotted by Mihai Moldovan during code review): commit a7b944f0d96c3e0e15e75378a04def1ac96089fb Author: Alan Coopersmith Date: Wed Nov 1 16:17:49 2006 -0800 If getpeerucred() is available, include pid & zoneid in audit messages too --- nx-X11/programs/Xserver/include/os.h | 18 ++++ nx-X11/programs/Xserver/os/Imakefile | 4 +- nx-X11/programs/Xserver/os/access.c | 161 ++++++++++++++++++++------------ nx-X11/programs/Xserver/os/connection.c | 46 +++++++-- 4 files changed, 160 insertions(+), 69 deletions(-) diff --git a/nx-X11/programs/Xserver/include/os.h b/nx-X11/programs/Xserver/include/os.h index 99003922f..af84f54c0 100644 --- a/nx-X11/programs/Xserver/include/os.h +++ b/nx-X11/programs/Xserver/include/os.h @@ -321,6 +321,24 @@ extern int LocalClient(ClientPtr /* client */); extern int LocalClientCred(ClientPtr, int *, int *); +#define LCC_UID_SET (1 << 0) +#define LCC_GID_SET (1 << 1) +#define LCC_PID_SET (1 << 2) +#define LCC_ZID_SET (1 << 3) + +typedef struct { + int fieldsSet; /* Bit mask of fields set */ + int euid; /* Effective uid */ + int egid; /* Primary effective group id */ + int nSuppGids; /* Number of supplementary group ids */ + int *pSuppGids; /* Array of supplementary group ids */ + int pid; /* Process id */ + int zoneid; /* Only set on Solaris 10 & later */ +} LocalClientCredRec; + +extern int GetLocalClientCreds(ClientPtr, LocalClientCredRec **); +extern void FreeLocalClientCreds(LocalClientCredRec *); + extern int ChangeAccessControl(ClientPtr /*client*/, int /*fEnabled*/); extern int GetAccessControl(void); diff --git a/nx-X11/programs/Xserver/os/Imakefile b/nx-X11/programs/Xserver/os/Imakefile index c2e1e8699..144cb5a55 100644 --- a/nx-X11/programs/Xserver/os/Imakefile +++ b/nx-X11/programs/Xserver/os/Imakefile @@ -31,6 +31,8 @@ NULL = * If you have any extra files to be put into the library, define them here. */ +ZONEID_DEFINES = -UHAVE_GETZONEID + #if NXLibraries NX_INCLUDES = -I../../../../nxcomp @@ -235,7 +237,7 @@ alloca.o: $(PWLIB) ar x $(PWLIB) alloca.o #endif /* NEED_ALLOCA_FROM_LIBPW */ -SpecialCObjectRule(access,$(ICONFIGFILES),$(XDMCP_DEFINES) $(SOCK_DEFINES) $(IFADDRS_DEFINES)) +SpecialCObjectRule(access,$(ICONFIGFILES),$(XDMCP_DEFINES) $(SOCK_DEFINES) $(IFADDRS_DEFINES) $(ZONEID_DEFINES)) SpecialCObjectRule(auth,$(ICONFIGFILES),$(XDMCP_DEFINES)) SpecialCObjectRule(xdmauth,$(ICONFIGFILES),$(XDMCP_DEFINES)) SpecialCObjectRule(xdmcp,$(ICONFIGFILES),$(SOCK_DEFINES) $(XDMCP_DEFINES)) diff --git a/nx-X11/programs/Xserver/os/access.c b/nx-X11/programs/Xserver/os/access.c index 34e193bbd..152287889 100644 --- a/nx-X11/programs/Xserver/os/access.c +++ b/nx-X11/programs/Xserver/os/access.c @@ -204,10 +204,6 @@ static Bool NewHost(int /*family*/, int /*len*/, int /* addingLocalHosts */); -int LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, - int **pSuppGids, int *nSuppGids); - - /* XFree86 bug #156: To keep track of which hosts were explicitly requested in /etc/X.hosts, we've added a requested field to the HOST struct, and a LocalHostRequested variable. These default to FALSE, but are set @@ -1264,38 +1260,51 @@ Bool LocalClient(ClientPtr client) /* * Return the uid and gid of a connected local client - * or the uid/gid for nobody those ids cannot be determined * * Used by XShm to test access rights to shared memory segments */ int LocalClientCred(ClientPtr client, int *pUid, int *pGid) { - return LocalClientCredAndGroups(client, pUid, pGid, NULL, NULL); + LocalClientCredRec *lcc; + int ret = GetLocalClientCreds(client, &lcc); + + if (ret == 0) { +#ifdef HAVE_GETZONEID /* only local if in the same zone */ + if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { + FreeLocalClientCreds(lcc); + return -1; + } +#endif + if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL)) + *pUid = lcc->euid; + if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL)) + *pGid = lcc->egid; + FreeLocalClientCreds(lcc); + } + return ret; } /* * Return the uid and all gids of a connected local client - * or the uid/gid for nobody those ids cannot be determined + * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds * - * If the caller passes non-NULL values for pSuppGids & nSuppGids, - * they are responsible for calling XFree(*pSuppGids) to release the - * memory allocated for the supplemental group ids list. - * * Used by localuser & localgroup ServerInterpreted access control forms below + * Used by AuthAudit to log where local connections came from */ int -LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, - int **pSuppGids, int *nSuppGids) +GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp) { #if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED) int fd; XtransConnInfo ci; + LocalClientCredRec *lcc; #ifdef HAS_GETPEEREID uid_t uid; gid_t gid; #elif defined(HAS_GETPEERUCRED) ucred_t *peercred = NULL; + const gid_t *gids; #elif defined(SO_PEERCRED) struct ucred peercred; socklen_t so_len = sizeof(peercred); @@ -1314,57 +1323,64 @@ LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, } #endif - if (pSuppGids != NULL) - *pSuppGids = NULL; - if (nSuppGids != NULL) - *nSuppGids = 0; + *lccp = calloc(1, sizeof(LocalClientCredRec)); + if (*lccp == NULL) + return -1; + lcc = *lccp; fd = _XSERVTransGetConnectionNumber(ci); #ifdef HAS_GETPEEREID - if (getpeereid(fd, &uid, &gid) == -1) - return -1; - if (pUid != NULL) - *pUid = uid; - if (pGid != NULL) - *pGid = gid; + if (getpeereid(fd, &uid, &gid) == -1) { + FreeLocalClientCreds(lcc); + return -1; + } + lcc->euid = uid; + lcc->egid = gid; + lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET; return 0; #elif defined(HAS_GETPEERUCRED) - if (getpeerucred(fd, &peercred) < 0) - return -1; -#ifdef sun /* Ensure process is in the same zone */ - if (getzoneid() != ucred_getzoneid(peercred)) { - ucred_free(peercred); + if (getpeerucred(fd, &peercred) < 0) { + FreeLocalClientCreds(lcc); return -1; - } -#endif - if (pUid != NULL) - *pUid = ucred_geteuid(peercred); - if (pGid != NULL) - *pGid = ucred_getegid(peercred); - if (pSuppGids != NULL && nSuppGids != NULL) { - const gid_t *gids; - *nSuppGids = ucred_getgroups(peercred, &gids); - if (*nSuppGids > 0) { - *pSuppGids = malloc(sizeof(int) * (*nSuppGids)); - if (*pSuppGids == NULL) { - *nSuppGids = 0; - } else { - int i; - for (i = 0 ; i < *nSuppGids; i++) { - (*pSuppGids)[i] = (int) gids[i]; - } + lcc->euid = ucred_geteuid(peercred); + if (lcc->euid != -1) + lcc->fieldsSet |= LCC_UID_SET; + lcc->egid = ucred_getegid(peercred); + if (lcc->egid != -1) + lcc->fieldsSet |= LCC_GID_SET; + lcc->pid = ucred_getpid(peercred); + if (lcc->pid != -1) + lcc->fieldsSet |= LCC_PID_SET; +#ifdef HAVE_GETZONEID + lcc->zoneid = ucred_getzoneid(peercred); + if (lcc->zoneid != -1) + lcc->fieldsSet |= LCC_ZID_SET; +#endif + lcc->nSuppGids = ucred_getgroups(peercred, &gids); + if (lcc->nSuppGids > 0) { + lcc->pSuppGids = calloc((lcc->nSuppGids), sizeof(int)); + if (lcc->pSuppGids == NULL) { + lcc->nSuppGids = 0; + } else { + int i; + for (i = 0 ; i < lcc->nSuppGids; i++) { + (lcc->pSuppGids)[i] = (int) gids[i]; } } + } else { + lcc->nSuppGids = 0; } ucred_free(peercred); return 0; #elif defined(SO_PEERCRED) - if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) - return -1; - if (pUid != NULL) - *pUid = peercred.uid; - if (pGid != NULL) - *pGid = peercred.gid; + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) { + FreeLocalClientCreds(lcc); + return -1; + } + lcc->euid = peercred.uid; + lcc->egid = peercred.gid; + lcc->pid = peercred.pid; + lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET; return 0; #endif #else @@ -1374,6 +1390,17 @@ LocalClientCredAndGroups(ClientPtr client, int *pUid, int *pGid, #endif } +void +FreeLocalClientCreds(LocalClientCredRec *lcc) +{ + if (lcc != NULL) { + if (lcc->nSuppGids > 0) { + free(lcc->pSuppGids); + } + free(lcc); + } +} + static Bool AuthorizedClient(ClientPtr client) { @@ -2177,38 +2204,48 @@ static Bool siLocalCredAddrMatch(int family, void * addr, int len, const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv) { - int connUid, connGid, *connSuppGids, connNumSuppGids, siAddrId; + int siAddrId; + LocalClientCredRec *lcc; siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv; - if (LocalClientCredAndGroups(client, &connUid, &connGid, - &connSuppGids, &connNumSuppGids) == -1) { + if (GetLocalClientCreds(client, &lcc) == -1) { return FALSE; } +#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */ + if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) { + FreeLocalClientCreds(lcc); + return FALSE; + } +#endif + if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) { + FreeLocalClientCreds(lcc); return FALSE; } if (lcPriv->credType == LOCAL_USER) { - if (connUid == siAddrId) { + if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) { + FreeLocalClientCreds(lcc); return TRUE; } } else { - if (connGid == siAddrId) { + if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) { + FreeLocalClientCreds(lcc); return TRUE; } - if (connSuppGids != NULL) { + if (lcc->pSuppGids != NULL) { int i; - for (i = 0 ; i < connNumSuppGids; i++) { - if (connSuppGids[i] == siAddrId) { - free(connSuppGids); + for (i = 0 ; i < lcc->nSuppGids; i++) { + if (lcc->pSuppGids[i] == siAddrId) { + FreeLocalClientCreds(lcc); return TRUE; } } - free(connSuppGids); } } + FreeLocalClientCreds(lcc); return FALSE; } diff --git a/nx-X11/programs/Xserver/os/connection.c b/nx-X11/programs/Xserver/os/connection.c index 151605cfb..538996198 100644 --- a/nx-X11/programs/Xserver/os/connection.c +++ b/nx-X11/programs/Xserver/os/connection.c @@ -534,8 +534,8 @@ AuthAudit (ClientPtr client, Bool letin, char addr[128]; char *out = addr; - int client_uid; - char client_uid_string[32]; + char client_uid_string[64]; + LocalClientCredRec *lcc; if (!len) strcpy(out, "local host"); @@ -567,10 +567,44 @@ AuthAudit (ClientPtr client, Bool letin, strcpy(out, "unknown address"); } - if (LocalClientCred(client, &client_uid, NULL) != -1) { - snprintf(client_uid_string, sizeof(client_uid_string), - " (uid %d)", client_uid); - } else { + if (GetLocalClientCreds(client, &lcc) != -1) { + int slen; /* length written to client_uid_string */ + + strcpy(client_uid_string, " ( "); + slen = 3; + + if (lcc->fieldsSet & LCC_UID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "uid=%ld ", (long) lcc->euid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_GID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "gid=%ld ", (long) lcc->egid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_PID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "pid=%ld ", (long) lcc->pid); + slen = strlen(client_uid_string); + } + + if (lcc->fieldsSet & LCC_ZID_SET) { + snprintf(client_uid_string + slen, + sizeof(client_uid_string) - slen, + "zoneid=%ld ", (long) lcc->zoneid); + slen = strlen(client_uid_string); + } + + snprintf(client_uid_string + slen, sizeof(client_uid_string) - slen, ")"); + FreeLocalClientCreds(lcc); + } + else { client_uid_string[0] = '\0'; } -- cgit v1.2.3