From a8586df39bafb9c8934a28b981d08a318a34a21b Mon Sep 17 00:00:00 2001 From: Marko Kreen Date: Fri, 13 Apr 2007 12:45:54 +0000 Subject: [PATCH] Standardise UNIX socket UID lookup to getpeeruid() Where it does not exists use SO_PEERCRED or getpeerucred(). --- configure.ac | 2 +- src/admin.c | 9 +++++---- src/pooler.c | 5 +++-- src/util.c | 38 +++++++++++++++++++++----------------- src/util.h | 5 ++++- 5 files changed, 34 insertions(+), 25 deletions(-) diff --git a/configure.ac b/configure.ac index 652c0c4..7cfdef1 100644 --- a/configure.ac +++ b/configure.ac @@ -51,7 +51,7 @@ AC_TYPE_UINT64_T AC_SYS_LARGEFILE dnl Checks for library functions. -AC_CHECK_FUNCS(strlcpy strlcat) +AC_CHECK_FUNCS(strlcpy strlcat getpeereid getpeerucred) AC_SEARCH_LIBS(crypt, crypt, [], AC_MSG_ERROR([crypt not found])) dnl Find libevent diff --git a/src/admin.c b/src/admin.c index 323c467..cbb5c61 100644 --- a/src/admin.c +++ b/src/admin.c @@ -807,8 +807,9 @@ bool admin_handle_client(PgSocket *admin, MBuf *pkt, int pkt_type, int pkt_len) */ bool admin_pre_login(PgSocket *client) { - uid_t peer_uid = 0; - bool res; + uid_t peer_uid = -1; + gid_t peer_gid = -1; + int res; const char *username = client->auth_user->name; client->admin_user = 0; @@ -816,8 +817,8 @@ bool admin_pre_login(PgSocket *client) /* tag same uid as special */ if (client->addr.is_unix) { - res = get_unix_peer_uid(sbuf_socket(&client->sbuf), &peer_uid); - if (res && peer_uid == getuid() + res = getpeereid(sbuf_socket(&client->sbuf), &peer_uid, &peer_gid); + if (res >= 0 && peer_uid == getuid() && strcmp("pgbouncer", username) == 0) { client->own_user = 1; diff --git a/src/pooler.c b/src/pooler.c index 2f26e49..753d4b0 100644 --- a/src/pooler.c +++ b/src/pooler.c @@ -199,11 +199,12 @@ pool_accept(int sock, short flags, void *is_unix) log_debug("P: new unix client"); { uid_t uid; + gid_t gid; log_noise("getuid(): %d", (int)getuid()); - if (get_unix_peer_uid(fd, &uid)) + if (getpeereid(fd, &uid, &gid) >= 0) log_noise("unix peer uid: %d", (int)uid); else - log_noise("unix peer uid failed"); + log_warning("unix peer uid failed: %s", strerror(errno)); } accept_client(fd, NULL, true); } else { diff --git a/src/util.c b/src/util.c index 9b9225d..04116da 100644 --- a/src/util.c +++ b/src/util.c @@ -403,32 +403,36 @@ void reset_time_cache(void) } /* - * get other side's uid. + * Get other side's uid for UNIX socket. + * + * Standardise on getpeereid() from BSDs. */ -bool get_unix_peer_uid(int fd, uid_t *uid_p) +#ifndef HAVE_GETPEEREID +int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p) { - int res = -1; #ifdef SO_PEERCRED struct ucred cred; socklen_t len = sizeof(cred); - res = getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len); - if (res >= 0) + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) >= 0) { *uid_p = cred.uid; - else - log_error("getsockopt(SO_PEERCRED): %s", strerror(errno)); + *gid_p = cred.gid; + return 0; + } #else /* !SO_PEERCRED */ -#ifdef LOCAL_PEERCRED - struct xucred cred; - socklen_t len = sizeof(cred); - res = getsockopt(fd, AF_UNIX, LOCAL_PEERCRED, &cred, &len); - if (res >= 0) - *uid_p = cred.cr_uid; - else - log_error("getsockopt(LOCAL_PEERCRED): %s", strerror(errno)); -#endif /* !LOCAL_PEERCRED */ +#ifdef HAVE_GETPEERUCRED + ucred_t *cred = NULL; + if (getpeerucred(fd, &cred) >= 0) { + *uid_p = ucred_geteuid(cred); + *gid_p = ucred_getegid(cred); + ucred_free(cred); + if (*uid_p >= 0 && *gid_p >= 0) + return 0; + } +#endif /* HAVE_GETPEERUCRED */ #endif /* !SO_PEERCRED */ - return (res >= 0); + return -1; } +#endif /* !HAVE_GETPEEREID */ void socket_set_nonblocking(int fd, int val) { diff --git a/src/util.h b/src/util.h index fee4d66..dbefcf3 100644 --- a/src/util.h +++ b/src/util.h @@ -105,7 +105,10 @@ size_t strlcat(char *dst, const char *src, size_t n); /* * socket option handling */ -bool get_unix_peer_uid(int fd, uid_t *uid_p); +#ifndef HAVE_GETPEEREID +int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p); +#endif + void socket_set_nonblocking(int fd, int val); void tune_socket(int sock, bool is_unix); -- 2.50.1