Header And Logo

PostgreSQL
| The world's most advanced open source database.

getpeereid.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * getpeereid.c
00004  *      get peer userid for UNIX-domain socket connection
00005  *
00006  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00007  *
00008  *
00009  * IDENTIFICATION
00010  *    src/port/getpeereid.c
00011  *
00012  *-------------------------------------------------------------------------
00013  */
00014 
00015 #include "c.h"
00016 
00017 #include <sys/param.h>
00018 #include <sys/socket.h>
00019 #include <unistd.h>
00020 #ifdef HAVE_SYS_UN_H
00021 #include <sys/un.h>
00022 #endif
00023 #ifdef HAVE_UCRED_H
00024 #include <ucred.h>
00025 #endif
00026 #ifdef HAVE_SYS_UCRED_H
00027 #include <sys/ucred.h>
00028 #endif
00029 
00030 
00031 /*
00032  * BSD-style getpeereid() for platforms that lack it.
00033  */
00034 int
00035 getpeereid(int sock, uid_t *uid, gid_t *gid)
00036 {
00037 #if defined(SO_PEERCRED)
00038     /* Linux: use getsockopt(SO_PEERCRED) */
00039     struct ucred peercred;
00040     ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
00041 
00042     if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
00043         so_len != sizeof(peercred))
00044         return -1;
00045     *uid = peercred.uid;
00046     *gid = peercred.gid;
00047     return 0;
00048 #elif defined(LOCAL_PEERCRED)
00049     /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
00050     struct xucred peercred;
00051     ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
00052 
00053     if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
00054         so_len != sizeof(peercred) ||
00055         peercred.cr_version != XUCRED_VERSION)
00056         return -1;
00057     *uid = peercred.cr_uid;
00058     *gid = peercred.cr_gid;
00059     return 0;
00060 #elif defined(HAVE_GETPEERUCRED)
00061     /* Solaris: use getpeerucred() */
00062     ucred_t    *ucred;
00063 
00064     ucred = NULL;               /* must be initialized to NULL */
00065     if (getpeerucred(sock, &ucred) == -1)
00066         return -1;
00067 
00068     *uid = ucred_geteuid(ucred);
00069     *gid = ucred_getegid(ucred);
00070     ucred_free(ucred);
00071 
00072     if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1))
00073         return -1;
00074     return 0;
00075 #else
00076     /* No implementation available on this platform */
00077     errno = ENOSYS;
00078     return -1;
00079 #endif
00080 }