1 | /*------------------------------------------------------------------------- |
2 | * |
3 | * getpeereid.c |
4 | * get peer userid for UNIX-domain socket connection |
5 | * |
6 | * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group |
7 | * |
8 | * |
9 | * IDENTIFICATION |
10 | * src/port/getpeereid.c |
11 | * |
12 | *------------------------------------------------------------------------- |
13 | */ |
14 | |
15 | #include "c.h" |
16 | |
17 | #include <sys/param.h> |
18 | #include <sys/socket.h> |
19 | #include <unistd.h> |
20 | #ifdef HAVE_SYS_UN_H |
21 | #include <sys/un.h> |
22 | #endif |
23 | #ifdef HAVE_UCRED_H |
24 | #include <ucred.h> |
25 | #endif |
26 | #ifdef HAVE_SYS_UCRED_H |
27 | #include <sys/ucred.h> |
28 | #endif |
29 | |
30 | |
31 | /* |
32 | * BSD-style getpeereid() for platforms that lack it. |
33 | */ |
34 | int |
35 | getpeereid(int sock, uid_t *uid, gid_t *gid) |
36 | { |
37 | #if defined(SO_PEERCRED) |
38 | /* Linux: use getsockopt(SO_PEERCRED) */ |
39 | struct ucred peercred; |
40 | ACCEPT_TYPE_ARG3 so_len = sizeof(peercred); |
41 | |
42 | if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 || |
43 | so_len != sizeof(peercred)) |
44 | return -1; |
45 | *uid = peercred.uid; |
46 | *gid = peercred.gid; |
47 | return 0; |
48 | #elif defined(LOCAL_PEERCRED) |
49 | /* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */ |
50 | struct xucred peercred; |
51 | ACCEPT_TYPE_ARG3 so_len = sizeof(peercred); |
52 | |
53 | if (getsockopt(sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 || |
54 | so_len != sizeof(peercred) || |
55 | peercred.cr_version != XUCRED_VERSION) |
56 | return -1; |
57 | *uid = peercred.cr_uid; |
58 | *gid = peercred.cr_gid; |
59 | return 0; |
60 | #elif defined(HAVE_GETPEERUCRED) |
61 | /* Solaris: use getpeerucred() */ |
62 | ucred_t *ucred; |
63 | |
64 | ucred = NULL; /* must be initialized to NULL */ |
65 | if (getpeerucred(sock, &ucred) == -1) |
66 | return -1; |
67 | |
68 | *uid = ucred_geteuid(ucred); |
69 | *gid = ucred_getegid(ucred); |
70 | ucred_free(ucred); |
71 | |
72 | if (*uid == (uid_t) (-1) || *gid == (gid_t) (-1)) |
73 | return -1; |
74 | return 0; |
75 | #else |
76 | /* No implementation available on this platform */ |
77 | errno = ENOSYS; |
78 | return -1; |
79 | #endif |
80 | } |
81 | |