1 /* $OpenBSD: getpeereid_test.c,v 1.5 2024/08/23 12:56:26 anton Exp $ */
2 /* Written by Marc Espie in 2006 */
3 /* Public domain */
4 #include <sys/types.h>
5 #include <sys/socket.h>
6 #include <sys/stat.h>
7 #include <sys/un.h>
8 #include <sys/wait.h>
9 #include <err.h>
10 #include <string.h>
11 #include <unistd.h>
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <errno.h>
15
16 char path[1024];
17 char *dir;
18
19 char *
check_id(int fd)20 check_id(int fd)
21 {
22 uid_t sockuid, myuid;
23 gid_t sockgid, mygid;
24 static char problem[1024];
25
26 if (getpeereid(fd, &sockuid, &sockgid) == -1) {
27 snprintf(problem, sizeof problem, "getpeereid: %s",
28 strerror(errno));
29 return problem;
30 }
31 myuid = geteuid();
32 mygid = getgid();
33 if (myuid != sockuid) {
34 snprintf(problem, sizeof problem, "uid discrepancy %ld vs %ld",
35 (long)myuid, (long)sockuid);
36 return problem;
37 }
38 if (mygid != sockgid) {
39 snprintf(problem, sizeof problem, "gid discrepancy %ld vs %ld",
40 (long)mygid, (long)sockgid);
41 return problem;
42 }
43 return NULL;
44 }
45
46 void
client(struct sockaddr_un * sun)47 client(struct sockaddr_un *sun)
48 {
49 int s;
50 int i;
51 int r;
52 char *problem;
53
54 s = socket(AF_UNIX, SOCK_STREAM, 0);
55 if (s == -1)
56 err(1, "Bad socket");
57
58 /* XXX make sure the server started alright */
59 for (i = 0; i < 10; i++) {
60 r = connect(s, (struct sockaddr *)sun, sizeof(*sun));
61 if (r == 0) {
62 problem = check_id(s);
63 if (problem)
64 errx(1, "%s", problem);
65 exit(0);
66 }
67 sleep(5);
68 }
69 errx(1, "Could not connect after 10 tries");
70 }
71
72
73 void
server(struct sockaddr_un * sun)74 server(struct sockaddr_un *sun)
75 {
76 int s, fd;
77 struct sockaddr_storage client_addr;
78 socklen_t client_len;
79 char *problem;
80
81 s = socket(AF_UNIX, SOCK_STREAM, 0);
82 if (s == -1)
83 err(1, "Bad socket");
84
85 if (bind(s, (struct sockaddr *)sun, sizeof(*sun)) != 0)
86 err(1, "bind");
87 if (listen(s, 5) != 0) {
88 int saved_errno = errno;
89 unlink(path);
90 rmdir(dir);
91 errc(1, saved_errno, "listen");
92 }
93 fd = accept(s, (struct sockaddr *)&client_addr, &client_len);
94 if (fd == -1) {
95 int saved_errno = errno;
96 unlink(path);
97 rmdir(dir);
98 errc(1, saved_errno, "accept");
99 }
100 problem = check_id(fd);
101 if (problem) {
102 unlink(path);
103 rmdir(dir);
104 errx(1, "%s", problem);
105 }
106 unlink(path);
107 rmdir(dir);
108 }
109
110
111
112 int
main()113 main()
114 {
115 pid_t pid;
116 struct sockaddr_un sun;
117 char dir_template[] = "/tmp/peer.XXXXXX";
118
119 dir = mkdtemp(dir_template);
120 if (!dir)
121 err(1, "mkdtemp");
122 snprintf(path, sizeof path, "%s/%s", dir, "socket");
123
124 memset(&sun, 0, sizeof(struct sockaddr_un));
125 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
126 sizeof(sun.sun_path))
127 errx(1, "Memory error");
128 sun.sun_family = AF_UNIX;
129
130 /* let's make those two rendez-vous, a bit artificial */
131 pid = fork();
132 if (pid == -1)
133 err(1, "can't fork");
134 if (pid == 0) {
135 client(&sun);
136 exit(0);
137 } else {
138 int status;
139
140 server(&sun);
141 waitpid(pid, &status, 0);
142 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) {
143 printf("getpeereid test okay\n");
144 exit(0);
145 } else {
146 errx(1, "Problem with child");
147 }
148 }
149 }
150