-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathunix_cred_pass.c
More file actions
132 lines (128 loc) · 3.58 KB
/
Copy pathunix_cred_pass.c
File metadata and controls
132 lines (128 loc) · 3.58 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
#define _GNU_SOURCE
#define _POSIX_C_SOURCE 200809L
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <unistd.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__linux__)
#include <sys/uio.h>
#include <sys/prctl.h>
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
#include <sys/ucred.h>
#endif
static int make_server(const char *path)
{
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) return -1;
struct sockaddr_un addr;
memset(&addr, 0, sizeof addr);
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof addr.sun_path - 1);
unlink(path);
if (bind(fd, (struct sockaddr *)&addr, sizeof addr) < 0) {
close(fd);
return -1;
}
if (listen(fd, 1) < 0) {
close(fd);
return -1;
}
return fd;
}
static int make_client(const char *path)
{
int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) return -1;
struct sockaddr_un addr;
memset(&addr, 0, sizeof addr);
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, path, sizeof addr.sun_path - 1);
if (connect(fd, (struct sockaddr *)&addr, sizeof addr) < 0) {
close(fd);
return -1;
}
return fd;
}
int main(void)
{
const char *path = "unix_cred.sock";
int srv = make_server(path);
if (srv < 0) {
perror("make_server");
return 1;
}
pid_t pid = fork();
if (pid < 0) return 1;
if (pid == 0) {
int c = make_client(path);
if (c < 0) return 1;
const char *msg = "hello\n";
write(c, msg, strlen(msg));
close(c);
return 0;
} else {
int cli;
struct sockaddr_un addr;
socklen_t alen = sizeof addr;
cli = accept(srv, (struct sockaddr *)&addr, &alen);
if (cli < 0) {
perror("accept");
return 1;
}
#if defined(__linux__)
int opt = 1;
if (setsockopt(cli, SOL_SOCKET, SO_PASSCRED, &opt, sizeof opt) < 0) {
perror("setsockopt");
}
char buf[128];
struct iovec iov;
iov.iov_base = buf;
iov.iov_len = sizeof buf;
char cmsgbuf[CMSG_SPACE(sizeof(struct ucred))];
struct msghdr msg;
memset(&msg, 0, sizeof msg);
msg.msg_iov = &iov;
msg.msg_iovlen = 1;
msg.msg_control = cmsgbuf;
msg.msg_controllen = sizeof cmsgbuf;
ssize_t n = recvmsg(cli, &msg, 0);
if (n > 0) {
struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg);
if (cmsg && cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_CREDENTIALS) {
struct ucred *uc = (struct ucred *)CMSG_DATA(cmsg);
buf[n] = 0;
printf("got from pid=%d uid=%d gid=%d: %s", uc->pid, uc->uid, uc->gid, buf);
}
}
#elif defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__)
uid_t uid;
gid_t gid;
if (getpeereid(cli, &uid, &gid) == 0) {
char buf[128];
ssize_t n = read(cli, buf, sizeof buf - 1);
if (n > 0) {
buf[n] = 0;
printf("got from uid=%d gid=%d: %s", (int)uid, (int)gid, buf);
}
}
#else
char buf[128];
ssize_t n = read(cli, buf, sizeof buf - 1);
if (n > 0) {
buf[n] = 0;
printf("got: %s", buf);
}
#endif
close(cli);
close(srv);
unlink(path);
wait(NULL);
return 0;
}
}