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