1 /* $OpenBSD: getpeereid_test.c,v 1.1 2006/10/23 15:18:47 espie 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, 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 unlink(path); 89 rmdir(dir); 90 err(1, "listen"); 91 } 92 fd = accept(s, (struct sockaddr *)&client_addr, &client_len); 93 if (fd == -1) { 94 unlink(path); 95 rmdir(dir); 96 err(1, "accept"); 97 } 98 problem = check_id(fd); 99 if (problem) { 100 unlink(path); 101 rmdir(dir); 102 errx(1, problem); 103 } 104 unlink(path); 105 rmdir(dir); 106 } 107 108 109 110 int 111 main() 112 { 113 pid_t pid; 114 struct sockaddr_un sun; 115 char dir_template[] = "/tmp/peer.XXXXXX"; 116 117 dir = mkdtemp(dir_template); 118 if (!dir) 119 err(1, "mkdtemp"); 120 snprintf(path, sizeof path, "%s/%s", dir, "socket"); 121 122 memset(&sun, 0, sizeof(struct sockaddr_un)); 123 if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >= 124 sizeof(sun.sun_path)) 125 errx(1, "Memory error"); 126 sun.sun_len = sizeof(sun); 127 sun.sun_family = AF_UNIX; 128 129 /* let's make those two rendez-vous, a bit artificial */ 130 pid = fork(); 131 if (pid == -1) 132 err(1, "can't fork"); 133 if (pid == 0) { 134 client(&sun); 135 exit(0); 136 } else { 137 int status; 138 139 server(&sun); 140 waitpid(pid, &status, 0); 141 if (WIFEXITED(status) && WEXITSTATUS(status) == 0) { 142 printf("getpeereid test okay\n"); 143 exit(0); 144 } else 145 errx(1, "Problem with child\n"); 146 } 147 } 148