1 /*
2 * Copyright (c) 2002,2004 Damien Miller <djm@mindrot.org>
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17 #include <config.h>
18 #include <stdio.h>
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <sys/socket.h>
22 #include <sys/un.h>
23 #include <sys/param.h>
24
25 #if !defined(HAVE_GETPEEREID)
26
27 #if defined(SO_PEERCRED)
28 int
getpeereid(int s,uid_t * euid,gid_t * gid)29 getpeereid(int s, uid_t *euid, gid_t *gid)
30 {
31 struct ucred cred;
32 socklen_t len = sizeof(cred);
33
34 if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0)
35 return (-1);
36 *euid = cred.uid;
37 *gid = cred.gid;
38
39 return (0);
40 }
41 #elif defined(LOCAL_CREDS) /* NetBSD */
42 int
getpeereid(int s,uid_t * euid,gid_t * gid)43 getpeereid(int s, uid_t *euid, gid_t *gid)
44 {
45 /* Credentials structure */
46 #ifdef __NetBSD__ /* XXX: should use autoconf */
47 #define HAVE_STRUCT_SOCKCRED
48 #endif
49 #if defined(HAVE_STRUCT_CMSGCRED)
50 typedef struct cmsgcred Cred;
51
52 #define cruid cmcred_euid
53 #define crgid cmcred_groups[0]
54 #elif defined(HAVE_STRUCT_FCRED)
55 typedef struct fcred Cred;
56
57 #define cruid fc_uid
58 #define crgid fc_gid
59 #elif defined(HAVE_STRUCT_SOCKCRED)
60 typedef struct sockcred Cred;
61
62 #define cruid sc_euid
63 #define crgid sc_egid
64 #endif
65 Cred *cred;
66
67 /* Compute size without padding */
68 char cmsgmem[CMSG_SPACE(sizeof(Cred))]; /* for NetBSD */
69
70 /* Point to start of first structure */
71 struct cmsghdr *cmsg = (struct cmsghdr *)cmsgmem;
72
73 struct iovec iov;
74 char buf;
75 struct msghdr msg;
76
77 memset(&msg, 0, sizeof(msg));
78 msg.msg_iov = &iov;
79 msg.msg_iovlen = 1;
80 msg.msg_control = (char *)cmsg;
81 msg.msg_controllen = sizeof(cmsgmem);
82 memset(cmsg, 0, sizeof(cmsgmem));
83
84 /*
85 * The one character which is received here is not meaningful; its
86 * purposes is only to make sure that recvmsg() blocks long enough for
87 * the other side to send its credentials.
88 */
89 iov.iov_base = &buf;
90 iov.iov_len = 1;
91
92 if (recvmsg(s, &msg, 0) < 0 ||
93 cmsg->cmsg_len < sizeof(cmsgmem) ||
94 cmsg->cmsg_type != SCM_CREDS)
95 {
96 return -1;
97 }
98
99 cred = (Cred *)CMSG_DATA(cmsg);
100 *euid = cred->cruid;
101 *gid = cred->crgid;
102
103 return 0;
104 }
105 #else
106 int
getpeereid(int s,uid_t * euid,gid_t * gid)107 getpeereid(int s, uid_t *euid, gid_t *gid)
108 {
109 *euid = geteuid();
110 *gid = getgid();
111
112 return (0);
113 }
114 #endif /* defined(SO_PEERCRED) */
115
116 #endif /* !defined(HAVE_GETPEEREID) */
117