1 /* $OpenBSD: getpeereid_test.c,v 1.4 2017/03/08 19:28:47 deraadt 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 * 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 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 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 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\n"); 147 } 148 } 149