diff options
Diffstat (limited to 'src/port/getpeereid.c')
-rw-r--r-- | src/port/getpeereid.c | 80 |
1 files changed, 80 insertions, 0 deletions
diff --git a/src/port/getpeereid.c b/src/port/getpeereid.c new file mode 100644 index 0000000..56ae141 --- /dev/null +++ b/src/port/getpeereid.c @@ -0,0 +1,80 @@ +/*------------------------------------------------------------------------- + * + * getpeereid.c + * get peer userid for UNIX-domain socket connection + * + * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group + * + * + * IDENTIFICATION + * src/port/getpeereid.c + * + *------------------------------------------------------------------------- + */ + +#include "c.h" + +#include <sys/param.h> +#include <sys/socket.h> +#include <unistd.h> +#ifdef HAVE_SYS_UN_H +#include <sys/un.h> +#endif +#ifdef HAVE_UCRED_H +#include <ucred.h> +#endif +#ifdef HAVE_SYS_UCRED_H +#include <sys/ucred.h> +#endif + + +/* + * BSD-style getpeereid() for platforms that lack it. + */ +int +getpeereid(int sock, uid_t *uid, gid_t *gid) +{ +#if defined(SO_PEERCRED) + /* Linux: use getsockopt(SO_PEERCRED) */ + struct ucred peercred; + socklen_t so_len = sizeof(peercred); + + if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 || + so_len != sizeof(peercred)) + return -1; + *uid = peercred.uid; + *gid = peercred.gid; + return 0; +#elif defined(LOCAL_PEERCRED) + /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */ + struct xucred peercred; + socklen_t so_len = sizeof(peercred); + + if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 || + so_len != sizeof(peercred) || + peercred.cr_version != XUCRED_VERSION) + return -1; + *uid = peercred.cr_uid; + *gid = peercred.cr_gid; + return 0; +#elif defined(HAVE_GETPEERUCRED) + /* Solaris: use getpeerucred() */ + ucred_t *ucred; + + ucred = NULL; /* must be initialized to NULL */ + if (getpeerucred(sock, &ucred) == -1) + return -1; + + *uid = ucred_geteuid(ucred); + *gid = ucred_getegid(ucred); + ucred_free(ucred); + + if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1)) + return -1; + return 0; +#else + /* No implementation available on this platform */ + errno = ENOSYS; + return -1; +#endif +} |