]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd-bus/bus-socket.c
bus: ignore the passed UID on EXTERNAL auth if ANONYMOUS is allowed
[thirdparty/systemd.git] / src / libsystemd-bus / bus-socket.c
CommitLineData
a7e3212d
LP
1/*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3/***
4 This file is part of systemd.
5
6 Copyright 2013 Lennart Poettering
7
8 systemd is free software; you can redistribute it and/or modify it
9 under the terms of the GNU Lesser General Public License as published by
10 the Free Software Foundation; either version 2.1 of the License, or
11 (at your option) any later version.
12
13 systemd is distributed in the hope that it will be useful, but
14 WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public License
19 along with systemd; If not, see <http://www.gnu.org/licenses/>.
20***/
21
22#include <endian.h>
23#include <assert.h>
24#include <stdlib.h>
25#include <unistd.h>
26#include <sys/poll.h>
27#include <byteswap.h>
28
29#include "util.h"
30#include "macro.h"
31#include "missing.h"
32#include "strv.h"
2181a7f5 33#include "utf8.h"
9ab32f9d 34#include "sd-daemon.h"
a7e3212d
LP
35
36#include "sd-bus.h"
37#include "bus-socket.h"
38#include "bus-internal.h"
39#include "bus-message.h"
40
2181a7f5 41static void iovec_advance(struct iovec iov[], unsigned *idx, size_t size) {
a7e3212d
LP
42
43 while (size > 0) {
44 struct iovec *i = iov + *idx;
45
46 if (i->iov_len > size) {
47 i->iov_base = (uint8_t*) i->iov_base + size;
48 i->iov_len -= size;
49 return;
50 }
51
52 size -= i->iov_len;
53
54 i->iov_base = NULL;
55 i->iov_len = 0;
56
57 (*idx) ++;
58 }
59}
60
2181a7f5
LP
61bool bus_socket_auth_needs_write(sd_bus *b) {
62
63 unsigned i;
64
65 if (b->auth_index >= ELEMENTSOF(b->auth_iovec))
66 return false;
67
68 for (i = b->auth_index; i < ELEMENTSOF(b->auth_iovec); i++) {
69 struct iovec *j = b->auth_iovec + i;
70
71 if (j->iov_len > 0)
72 return true;
73 }
74
75 return false;
76}
77
a7e3212d 78static int bus_socket_write_auth(sd_bus *b) {
a7e3212d
LP
79 ssize_t k;
80
81 assert(b);
82 assert(b->state == BUS_AUTHENTICATING);
83
2181a7f5 84 if (!bus_socket_auth_needs_write(b))
a7e3212d
LP
85 return 0;
86
15d5af81
LP
87 if (b->prefer_writev)
88 k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
89 else {
90 struct msghdr mh;
91 zero(mh);
92
93 mh.msg_iov = b->auth_iovec + b->auth_index;
94 mh.msg_iovlen = ELEMENTSOF(b->auth_iovec) - b->auth_index;
95
96 k = sendmsg(b->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
97 if (k < 0 && errno == ENOTSOCK) {
98 b->prefer_writev = true;
99 k = writev(b->output_fd, b->auth_iovec + b->auth_index, ELEMENTSOF(b->auth_iovec) - b->auth_index);
100 }
101 }
a7e3212d 102
a7e3212d
LP
103 if (k < 0)
104 return errno == EAGAIN ? 0 : -errno;
105
106 iovec_advance(b->auth_iovec, &b->auth_index, (size_t) k);
a7e3212d
LP
107 return 1;
108}
109
2181a7f5 110static int bus_socket_auth_verify_client(sd_bus *b) {
a7e3212d
LP
111 char *e, *f, *start;
112 sd_id128_t peer;
113 unsigned i;
114 int r;
115
2181a7f5
LP
116 assert(b);
117
a7e3212d
LP
118 /* We expect two response lines: "OK" and possibly
119 * "AGREE_UNIX_FD" */
120
121 e = memmem(b->rbuffer, b->rbuffer_size, "\r\n", 2);
122 if (!e)
123 return 0;
124
125 if (b->negotiate_fds) {
126 f = memmem(e + 2, b->rbuffer_size - (e - (char*) b->rbuffer) - 2, "\r\n", 2);
127 if (!f)
128 return 0;
129
130 start = f + 2;
131 } else {
132 f = NULL;
133 start = e + 2;
134 }
135
136 /* Nice! We got all the lines we need. First check the OK
137 * line */
138
139 if (e - (char*) b->rbuffer != 3 + 32)
140 return -EPERM;
141
142 if (memcmp(b->rbuffer, "OK ", 3))
143 return -EPERM;
144
2181a7f5
LP
145 b->auth = b->anonymous_auth ? BUS_AUTH_ANONYMOUS : BUS_AUTH_EXTERNAL;
146
a7e3212d
LP
147 for (i = 0; i < 32; i += 2) {
148 int x, y;
149
150 x = unhexchar(((char*) b->rbuffer)[3 + i]);
151 y = unhexchar(((char*) b->rbuffer)[3 + i + 1]);
152
153 if (x < 0 || y < 0)
154 return -EINVAL;
155
156 peer.bytes[i/2] = ((uint8_t) x << 4 | (uint8_t) y);
157 }
158
98178d39
LP
159 if (!sd_id128_equal(b->server_id, SD_ID128_NULL) &&
160 !sd_id128_equal(b->server_id, peer))
a7e3212d
LP
161 return -EPERM;
162
98178d39 163 b->server_id = peer;
a7e3212d
LP
164
165 /* And possibly check the second line, too */
166
167 if (f)
168 b->can_fds =
169 (f - e == sizeof("\r\nAGREE_UNIX_FD") - 1) &&
170 memcmp(e + 2, "AGREE_UNIX_FD", sizeof("AGREE_UNIX_FD") - 1) == 0;
171
172 b->rbuffer_size -= (start - (char*) b->rbuffer);
173 memmove(b->rbuffer, start, b->rbuffer_size);
174
175 r = bus_start_running(b);
176 if (r < 0)
177 return r;
178
179 return 1;
180}
181
2181a7f5
LP
182static bool line_equals(const char *s, size_t m, const char *line) {
183 size_t l;
184
185 l = strlen(line);
186 if (l != m)
187 return false;
188
189 return memcmp(s, line, l) == 0;
190}
191
192static bool line_begins(const char *s, size_t m, const char *word) {
193 size_t l;
194
195 l = strlen(word);
196 if (m < l)
197 return false;
198
199 if (memcmp(s, word, l) != 0)
200 return false;
201
202 return m == l || (m > l && s[l] == ' ');
203}
204
205static int verify_anonymous_token(sd_bus *b, const char *p, size_t l) {
206 _cleanup_free_ char *token = NULL;
207
208 if (!b->anonymous_auth)
209 return 0;
210
211 if (l <= 0)
212 return 1;
213
214 assert(p[0] == ' ');
215 p++; l--;
216
217 if (l % 2 != 0)
218 return 0;
219 token = unhexmem(p, l);
220 if (!token)
221 return -ENOMEM;
222
223 if (memchr(token, 0, l/2))
224 return 0;
225
226 return !!utf8_is_valid(token);
227}
228
229static int verify_external_token(sd_bus *b, const char *p, size_t l) {
230 _cleanup_free_ char *token = NULL;
231 uid_t u;
232 int r;
233
234 /* We don't do any real authentication here. Instead, we if
235 * the owner of this bus wanted authentication he should have
236 * checked SO_PEERCRED before even creating the bus object. */
237
8411d2a2 238 if (!b->anonymous_auth && !b->ucred_valid)
2181a7f5
LP
239 return 0;
240
241 if (l <= 0)
242 return 1;
243
244 assert(p[0] == ' ');
245 p++; l--;
246
247 if (l % 2 != 0)
248 return 0;
249
250 token = unhexmem(p, l);
251 if (!token)
252 return -ENOMEM;
253
254 if (memchr(token, 0, l/2))
255 return 0;
256
257 r = parse_uid(token, &u);
258 if (r < 0)
259 return 0;
260
8411d2a2
LP
261 /* We ignore the passed value if anonymous authentication is
262 * on anyway. */
263 if (!b->anonymous_auth && u != b->ucred.uid)
2181a7f5
LP
264 return 0;
265
266 return 1;
267}
268
269static int bus_socket_auth_write(sd_bus *b, const char *t) {
270 char *p;
271 size_t l;
272
273 assert(b);
274 assert(t);
275
276 /* We only make use of the first iovec */
277 assert(b->auth_index == 0 || b->auth_index == 1);
278
279 l = strlen(t);
280 p = malloc(b->auth_iovec[0].iov_len + l);
281 if (!p)
282 return -ENOMEM;
283
284 memcpy(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
285 memcpy(p + b->auth_iovec[0].iov_len, t, l);
286
287 b->auth_iovec[0].iov_base = p;
288 b->auth_iovec[0].iov_len += l;
289
290 free(b->auth_buffer);
291 b->auth_buffer = p;
292 b->auth_index = 0;
293 return 0;
294}
295
296static int bus_socket_auth_write_ok(sd_bus *b) {
297 char t[3 + 32 + 2 + 1];
298
299 assert(b);
300
98178d39 301 snprintf(t, sizeof(t), "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id));
2181a7f5
LP
302 char_array_0(t);
303
304 return bus_socket_auth_write(b, t);
305}
306
307static int bus_socket_auth_verify_server(sd_bus *b) {
308 char *e;
309 const char *line;
310 size_t l;
311 bool processed = false;
312 int r;
313
314 assert(b);
315
316 if (b->rbuffer_size < 3)
317 return 0;
318
319 /* First char must be a NUL byte */
320 if (*(char*) b->rbuffer != 0)
321 return -EIO;
322
323 /* Begin with the first line */
324 if (b->auth_rbegin <= 0)
325 b->auth_rbegin = 1;
326
327 for (;;) {
328 /* Check if line is complete */
329 line = (char*) b->rbuffer + b->auth_rbegin;
330 e = memmem(line, b->rbuffer_size - b->auth_rbegin, "\r\n", 2);
331 if (!e)
332 return processed;
333
334 l = e - line;
335
336 if (line_begins(line, l, "AUTH ANONYMOUS")) {
337
338 r = verify_anonymous_token(b, line + 14, l - 14);
339 if (r < 0)
340 return r;
341 if (r == 0)
342 r = bus_socket_auth_write(b, "REJECTED\r\n");
343 else {
344 b->auth = BUS_AUTH_ANONYMOUS;
345 r = bus_socket_auth_write_ok(b);
346 }
347
348 } else if (line_begins(line, l, "AUTH EXTERNAL")) {
349
350 r = verify_external_token(b, line + 13, l - 13);
351 if (r < 0)
352 return r;
353 if (r == 0)
354 r = bus_socket_auth_write(b, "REJECTED\r\n");
355 else {
356 b->auth = BUS_AUTH_EXTERNAL;
357 r = bus_socket_auth_write_ok(b);
358 }
359
360 } else if (line_begins(line, l, "AUTH"))
361 r = bus_socket_auth_write(b, "REJECTED EXTERNAL ANONYMOUS\r\n");
362 else if (line_equals(line, l, "CANCEL") ||
363 line_begins(line, l, "ERROR")) {
364
365 b->auth = _BUS_AUTH_INVALID;
366 r = bus_socket_auth_write(b, "REJECTED\r\n");
367
368 } else if (line_equals(line, l, "BEGIN")) {
369
370 if (b->auth == _BUS_AUTH_INVALID)
371 r = bus_socket_auth_write(b, "ERROR\r\n");
372 else {
373 /* We can't leave from the auth phase
374 * before we haven't written
375 * everything queued, so let's check
376 * that */
377
378 if (bus_socket_auth_needs_write(b))
379 return 1;
380
381 b->rbuffer_size -= (e + 2 - (char*) b->rbuffer);
382 memmove(b->rbuffer, e + 2, b->rbuffer_size);
383 return bus_start_running(b);
384 }
385
386 } else if (line_begins(line, l, "DATA")) {
387
388 if (b->auth == _BUS_AUTH_INVALID)
389 r = bus_socket_auth_write(b, "ERROR\r\n");
390 else {
391 if (b->auth == BUS_AUTH_ANONYMOUS)
392 r = verify_anonymous_token(b, line + 4, l - 4);
393 else
394 r = verify_external_token(b, line + 4, l - 4);
395
396 if (r < 0)
397 return r;
398 if (r == 0) {
399 b->auth = _BUS_AUTH_INVALID;
400 r = bus_socket_auth_write(b, "REJECTED\r\n");
401 } else
402 r = bus_socket_auth_write_ok(b);
403 }
404 } else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
405 if (b->auth == _BUS_AUTH_INVALID || !b->negotiate_fds)
406 r = bus_socket_auth_write(b, "ERROR\r\n");
407 else {
408 b->can_fds = true;
409 r = bus_socket_auth_write(b, "AGREE_UNIX_FD\r\n");
410 }
411 } else
412 r = bus_socket_auth_write(b, "ERROR\r\n");
413
414 if (r < 0)
415 return r;
416
417 b->auth_rbegin = e + 2 - (char*) b->rbuffer;
418
419 processed = true;
420 }
421}
422
423static int bus_socket_auth_verify(sd_bus *b) {
424 assert(b);
425
426 if (b->is_server)
427 return bus_socket_auth_verify_server(b);
428 else
429 return bus_socket_auth_verify_client(b);
430}
431
a7e3212d
LP
432static int bus_socket_read_auth(sd_bus *b) {
433 struct msghdr mh;
434 struct iovec iov;
435 size_t n;
436 ssize_t k;
437 int r;
438 void *p;
2181a7f5
LP
439 union {
440 struct cmsghdr cmsghdr;
441 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX) +
442 CMSG_SPACE(sizeof(struct ucred)) +
443 CMSG_SPACE(NAME_MAX)]; /*selinux label */
444 } control;
445 struct cmsghdr *cmsg;
15d5af81 446 bool handle_cmsg = false;
a7e3212d
LP
447
448 assert(b);
2181a7f5 449 assert(b->state == BUS_AUTHENTICATING);
a7e3212d
LP
450
451 r = bus_socket_auth_verify(b);
452 if (r != 0)
453 return r;
454
2181a7f5 455 n = MAX(256, b->rbuffer_size * 2);
a7e3212d
LP
456
457 if (n > BUS_AUTH_SIZE_MAX)
458 n = BUS_AUTH_SIZE_MAX;
459
460 if (b->rbuffer_size >= n)
461 return -ENOBUFS;
462
463 p = realloc(b->rbuffer, n);
464 if (!p)
465 return -ENOMEM;
466
467 b->rbuffer = p;
468
469 zero(iov);
470 iov.iov_base = (uint8_t*) b->rbuffer + b->rbuffer_size;
471 iov.iov_len = n - b->rbuffer_size;
472
15d5af81
LP
473 if (b->prefer_readv)
474 k = readv(b->input_fd, &iov, 1);
475 else {
476 zero(mh);
477 mh.msg_iov = &iov;
478 mh.msg_iovlen = 1;
479 mh.msg_control = &control;
480 mh.msg_controllen = sizeof(control);
481
482 k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
483 if (k < 0 && errno == ENOTSOCK) {
484 b->prefer_readv = true;
485 k = readv(b->input_fd, &iov, 1);
486 } else
487 handle_cmsg = true;
488 }
a7e3212d
LP
489 if (k < 0)
490 return errno == EAGAIN ? 0 : -errno;
491 if (k == 0)
492 return -ECONNRESET;
493
494 b->rbuffer_size += k;
495
15d5af81
LP
496 if (handle_cmsg) {
497 for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
498 if (cmsg->cmsg_level == SOL_SOCKET &&
499 cmsg->cmsg_type == SCM_RIGHTS) {
500 int j;
501
502 /* Whut? We received fds during the auth
503 * protocol? Somebody is playing games with
504 * us. Close them all, and fail */
505 j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
506 close_many((int*) CMSG_DATA(cmsg), j);
507 return -EIO;
2181a7f5 508
15d5af81
LP
509 } else if (cmsg->cmsg_level == SOL_SOCKET &&
510 cmsg->cmsg_type == SCM_CREDENTIALS &&
511 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
2181a7f5 512
15d5af81
LP
513 memcpy(&b->ucred, CMSG_DATA(cmsg), sizeof(struct ucred));
514 b->ucred_valid = true;
2181a7f5 515
15d5af81
LP
516 } else if (cmsg->cmsg_level == SOL_SOCKET &&
517 cmsg->cmsg_type == SCM_SECURITY) {
2181a7f5 518
15d5af81
LP
519 size_t l;
520 l = cmsg->cmsg_len - CMSG_LEN(0);
521 memcpy(&b->label, CMSG_DATA(cmsg), l);
522 b->label[l] = 0;
523 }
2181a7f5
LP
524 }
525 }
526
a7e3212d
LP
527 r = bus_socket_auth_verify(b);
528 if (r != 0)
529 return r;
530
531 return 1;
532}
533
534static int bus_socket_setup(sd_bus *b) {
0f4b73c8 535 int enable;
a7e3212d
LP
536
537 assert(b);
538
d65ddaa4
LP
539 /* Enable SO_PASSCRED + SO_PASSEC. We try this on any
540 * socket, just in case. */
0f4b73c8 541 enable = !b->bus_client;
e82c9509
LP
542 setsockopt(b->input_fd, SOL_SOCKET, SO_PASSCRED, &enable, sizeof(enable));
543 setsockopt(b->input_fd, SOL_SOCKET, SO_PASSSEC, &enable, sizeof(enable));
a7e3212d
LP
544
545 /* Increase the buffers to a MB */
e82c9509
LP
546 fd_inc_rcvbuf(b->input_fd, 1024*1024);
547 fd_inc_sndbuf(b->output_fd, 1024*1024);
a7e3212d
LP
548
549 return 0;
550}
551
2181a7f5 552static int bus_socket_start_auth_client(sd_bus *b) {
a7e3212d 553 size_t l;
2181a7f5 554 const char *auth_suffix, *auth_prefix;
a7e3212d
LP
555
556 assert(b);
557
2181a7f5
LP
558 if (b->anonymous_auth) {
559 auth_prefix = "\0AUTH ANONYMOUS ";
a7e3212d 560
2181a7f5
LP
561 /* For ANONYMOUS auth we send some arbitrary "trace" string */
562 l = 9;
563 b->auth_buffer = hexmem("anonymous", l);
564 } else {
565 char text[20 + 1]; /* enough space for a 64bit integer plus NUL */
a7e3212d 566
2181a7f5 567 auth_prefix = "\0AUTH EXTERNAL ";
a7e3212d 568
2181a7f5
LP
569 snprintf(text, sizeof(text), "%lu", (unsigned long) geteuid());
570 char_array_0(text);
a7e3212d 571
2181a7f5
LP
572 l = strlen(text);
573 b->auth_buffer = hexmem(text, l);
574 }
575
576 if (!b->auth_buffer)
a7e3212d
LP
577 return -ENOMEM;
578
2181a7f5
LP
579 if (b->negotiate_fds)
580 auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
581 else
582 auth_suffix = "\r\nBEGIN\r\n";
a7e3212d
LP
583
584 b->auth_iovec[0].iov_base = (void*) auth_prefix;
2181a7f5
LP
585 b->auth_iovec[0].iov_len = 1 + strlen(auth_prefix + 1);
586 b->auth_iovec[1].iov_base = (void*) b->auth_buffer;
a7e3212d
LP
587 b->auth_iovec[1].iov_len = l * 2;
588 b->auth_iovec[2].iov_base = (void*) auth_suffix;
589 b->auth_iovec[2].iov_len = strlen(auth_suffix);
a7e3212d
LP
590
591 return bus_socket_write_auth(b);
592}
593
2181a7f5 594static int bus_socket_start_auth(sd_bus *b) {
2181a7f5
LP
595 assert(b);
596
597 b->state = BUS_AUTHENTICATING;
598 b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
599
9ab32f9d 600 if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
2181a7f5
LP
601 b->negotiate_fds = false;
602
9ab32f9d
LP
603 if (b->output_fd != b->input_fd)
604 if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
e82c9509 605 b->negotiate_fds = false;
e82c9509 606
2181a7f5
LP
607 if (b->is_server)
608 return bus_socket_read_auth(b);
609 else
610 return bus_socket_start_auth_client(b);
611}
612
a7e3212d
LP
613int bus_socket_connect(sd_bus *b) {
614 int r;
615
616 assert(b);
e82c9509
LP
617 assert(b->input_fd < 0);
618 assert(b->output_fd < 0);
a7e3212d
LP
619 assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
620
e82c9509
LP
621 b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
622 if (b->input_fd < 0)
a7e3212d
LP
623 return -errno;
624
e82c9509
LP
625 b->output_fd = b->input_fd;
626
a7e3212d
LP
627 r = bus_socket_setup(b);
628 if (r < 0)
629 return r;
630
e82c9509 631 r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
a7e3212d
LP
632 if (r < 0) {
633 if (errno == EINPROGRESS)
634 return 1;
635
636 return -errno;
637 }
638
639 return bus_socket_start_auth(b);
640}
641
642int bus_socket_exec(sd_bus *b) {
e82c9509 643 int s[2], r;
a7e3212d
LP
644 pid_t pid;
645
646 assert(b);
e82c9509
LP
647 assert(b->input_fd < 0);
648 assert(b->output_fd < 0);
a7e3212d
LP
649 assert(b->exec_path);
650
e82c9509
LP
651 r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
652 if (r < 0)
a7e3212d
LP
653 return -errno;
654
655 pid = fork();
656 if (pid < 0) {
657 close_pipe(s);
658 return -errno;
659 }
660 if (pid == 0) {
661 /* Child */
662
e82c9509
LP
663 reset_all_signal_handlers();
664
665 close_all_fds(s+1, 1);
a7e3212d
LP
666
667 assert_se(dup3(s[1], STDIN_FILENO, 0) == STDIN_FILENO);
668 assert_se(dup3(s[1], STDOUT_FILENO, 0) == STDOUT_FILENO);
669
670 if (s[1] != STDIN_FILENO && s[1] != STDOUT_FILENO)
671 close_nointr_nofail(s[1]);
672
673 fd_cloexec(STDIN_FILENO, false);
674 fd_cloexec(STDOUT_FILENO, false);
675 fd_nonblock(STDIN_FILENO, false);
676 fd_nonblock(STDOUT_FILENO, false);
677
678 if (b->exec_argv)
679 execvp(b->exec_path, b->exec_argv);
680 else {
681 const char *argv[] = { b->exec_path, NULL };
682 execvp(b->exec_path, (char**) argv);
683 }
684
685 _exit(EXIT_FAILURE);
686 }
687
688 close_nointr_nofail(s[1]);
e82c9509 689 b->output_fd = b->input_fd = s[0];
a7e3212d
LP
690
691 return bus_socket_start_auth(b);
692}
693
694int bus_socket_take_fd(sd_bus *b) {
695 int r;
696 assert(b);
697
698 r = bus_socket_setup(b);
699 if (r < 0)
700 return r;
701
702 return bus_socket_start_auth(b);
703}
704
705int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
a7e3212d
LP
706 struct iovec *iov;
707 ssize_t k;
708 size_t n;
709 unsigned j;
710
711 assert(bus);
712 assert(m);
713 assert(idx);
714 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
715
716 if (*idx >= m->size)
717 return 0;
a7e3212d
LP
718
719 n = m->n_iovec * sizeof(struct iovec);
720 iov = alloca(n);
721 memcpy(iov, m->iovec, n);
722
723 j = 0;
724 iovec_advance(iov, &j, *idx);
725
15d5af81
LP
726 if (bus->prefer_writev)
727 k = writev(bus->output_fd, iov, m->n_iovec);
728 else {
729 struct msghdr mh;
730 zero(mh);
731
732 if (m->n_fds > 0) {
733 struct cmsghdr *control;
734 control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
735
736 mh.msg_control = control;
737 control->cmsg_level = SOL_SOCKET;
738 control->cmsg_type = SCM_RIGHTS;
739 mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
740 memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
741 }
742
743 mh.msg_iov = iov;
744 mh.msg_iovlen = m->n_iovec;
745
746 k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
747 if (k < 0 && errno == ENOTSOCK) {
748 bus->prefer_writev = true;
749 k = writev(bus->output_fd, iov, m->n_iovec);
750 }
751 }
a7e3212d 752
a7e3212d
LP
753 if (k < 0)
754 return errno == EAGAIN ? 0 : -errno;
755
756 *idx += (size_t) k;
757 return 1;
758}
759
760static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
761 uint32_t a, b;
762 uint8_t e;
763 uint64_t sum;
764
765 assert(bus);
766 assert(need);
767 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
768
769 if (bus->rbuffer_size < sizeof(struct bus_header)) {
770 *need = sizeof(struct bus_header) + 8;
771
772 /* Minimum message size:
773 *
774 * Header +
775 *
776 * Method Call: +2 string headers
777 * Signal: +3 string headers
778 * Method Error: +1 string headers
779 * +1 uint32 headers
780 * Method Reply: +1 uint32 headers
781 *
782 * A string header is at least 9 bytes
783 * A uint32 header is at least 8 bytes
784 *
785 * Hence the minimum message size of a valid message
786 * is header + 8 bytes */
787
788 return 0;
789 }
790
791 a = ((const uint32_t*) bus->rbuffer)[1];
792 b = ((const uint32_t*) bus->rbuffer)[3];
793
794 e = ((const uint8_t*) bus->rbuffer)[0];
795 if (e == SD_BUS_LITTLE_ENDIAN) {
796 a = le32toh(a);
797 b = le32toh(b);
798 } else if (e == SD_BUS_BIG_ENDIAN) {
799 a = be32toh(a);
800 b = be32toh(b);
801 } else
802 return -EBADMSG;
803
804 sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a;
805 if (sum >= BUS_MESSAGE_SIZE_MAX)
806 return -ENOBUFS;
807
808 *need = (size_t) sum;
809 return 0;
810}
811
812static int bus_socket_make_message(sd_bus *bus, size_t size, sd_bus_message **m) {
813 sd_bus_message *t;
814 void *b;
815 int r;
816
817 assert(bus);
818 assert(m);
819 assert(bus->rbuffer_size >= size);
820 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
821
822 if (bus->rbuffer_size > size) {
823 b = memdup((const uint8_t*) bus->rbuffer + size,
824 bus->rbuffer_size - size);
825 if (!b)
826 return -ENOMEM;
827 } else
828 b = NULL;
829
830 r = bus_message_from_malloc(bus->rbuffer, size,
831 bus->fds, bus->n_fds,
0f4b73c8
LP
832 bus->ucred_valid ? &bus->ucred : NULL,
833 bus->label[0] ? bus->label : NULL,
a7e3212d
LP
834 &t);
835 if (r < 0) {
836 free(b);
837 return r;
838 }
839
840 bus->rbuffer = b;
841 bus->rbuffer_size -= size;
842
843 bus->fds = NULL;
844 bus->n_fds = 0;
845
846 *m = t;
847 return 1;
848}
849
850int bus_socket_read_message(sd_bus *bus, sd_bus_message **m) {
851 struct msghdr mh;
852 struct iovec iov;
853 ssize_t k;
854 size_t need;
855 int r;
856 void *b;
857 union {
858 struct cmsghdr cmsghdr;
859 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX) +
860 CMSG_SPACE(sizeof(struct ucred)) +
861 CMSG_SPACE(NAME_MAX)]; /*selinux label */
862 } control;
863 struct cmsghdr *cmsg;
15d5af81 864 bool handle_cmsg;
a7e3212d
LP
865
866 assert(bus);
867 assert(m);
868 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
869
870 r = bus_socket_read_message_need(bus, &need);
871 if (r < 0)
872 return r;
873
874 if (bus->rbuffer_size >= need)
875 return bus_socket_make_message(bus, need, m);
876
877 b = realloc(bus->rbuffer, need);
878 if (!b)
879 return -ENOMEM;
880
881 bus->rbuffer = b;
882
883 zero(iov);
884 iov.iov_base = (uint8_t*) bus->rbuffer + bus->rbuffer_size;
885 iov.iov_len = need - bus->rbuffer_size;
886
15d5af81
LP
887 if (bus->prefer_readv)
888 k = readv(bus->input_fd, &iov, 1);
889 else {
890 zero(mh);
891 mh.msg_iov = &iov;
892 mh.msg_iovlen = 1;
893 mh.msg_control = &control;
894 mh.msg_controllen = sizeof(control);
895
896 k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
897 if (k < 0 && errno == ENOTSOCK) {
898 bus->prefer_readv = true;
899 k = readv(bus->input_fd, &iov, 1);
900 } else
901 handle_cmsg = true;
902 }
a7e3212d
LP
903 if (k < 0)
904 return errno == EAGAIN ? 0 : -errno;
905 if (k == 0)
906 return -ECONNRESET;
907
908 bus->rbuffer_size += k;
909
15d5af81
LP
910 if (handle_cmsg) {
911 for (cmsg = CMSG_FIRSTHDR(&mh); cmsg; cmsg = CMSG_NXTHDR(&mh, cmsg)) {
912 if (cmsg->cmsg_level == SOL_SOCKET &&
913 cmsg->cmsg_type == SCM_RIGHTS) {
914 int n, *f;
915
916 n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
917
918 if (!bus->can_fds) {
919 /* Whut? We received fds but this
920 * isn't actually enabled? Close them,
921 * and fail */
922
923 close_many((int*) CMSG_DATA(cmsg), n);
924 return -EIO;
925 }
926
927 f = realloc(bus->fds, sizeof(int) + (bus->n_fds + n));
928 if (!f) {
929 close_many((int*) CMSG_DATA(cmsg), n);
930 return -ENOMEM;
931 }
932
933 memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
934 bus->fds = f;
935 bus->n_fds += n;
936 } else if (cmsg->cmsg_level == SOL_SOCKET &&
937 cmsg->cmsg_type == SCM_CREDENTIALS &&
938 cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
939
940 memcpy(&bus->ucred, CMSG_DATA(cmsg), sizeof(struct ucred));
941 bus->ucred_valid = true;
942
943 } else if (cmsg->cmsg_level == SOL_SOCKET &&
944 cmsg->cmsg_type == SCM_SECURITY) {
945
946 size_t l;
947 l = cmsg->cmsg_len - CMSG_LEN(0);
948 memcpy(&bus->label, CMSG_DATA(cmsg), l);
949 bus->label[l] = 0;
a7e3212d 950 }
a7e3212d
LP
951 }
952 }
953
954 r = bus_socket_read_message_need(bus, &need);
955 if (r < 0)
956 return r;
957
958 if (bus->rbuffer_size >= need)
959 return bus_socket_make_message(bus, need, m);
960
961 return 1;
962}
963
964int bus_socket_process_opening(sd_bus *b) {
965 int error = 0;
966 socklen_t slen = sizeof(error);
967 struct pollfd p;
968 int r;
969
970 assert(b);
971 assert(b->state == BUS_OPENING);
972
973 zero(p);
e82c9509 974 p.fd = b->output_fd;
a7e3212d
LP
975 p.events = POLLOUT;
976
977 r = poll(&p, 1, 0);
978 if (r < 0)
979 return -errno;
980
981 if (!(p.revents & (POLLOUT|POLLERR|POLLHUP)))
982 return 0;
983
e82c9509 984 r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen);
a7e3212d
LP
985 if (r < 0)
986 b->last_connect_error = errno;
987 else if (error != 0)
988 b->last_connect_error = error;
989 else if (p.revents & (POLLERR|POLLHUP))
990 b->last_connect_error = ECONNREFUSED;
991 else
992 return bus_socket_start_auth(b);
993
994 return bus_next_address(b);
995}
996
997int bus_socket_process_authenticating(sd_bus *b) {
998 int r;
999
1000 assert(b);
1001 assert(b->state == BUS_AUTHENTICATING);
1002
1003 if (now(CLOCK_MONOTONIC) >= b->auth_timeout)
1004 return -ETIMEDOUT;
1005
1006 r = bus_socket_write_auth(b);
1007 if (r != 0)
1008 return r;
1009
1010 return bus_socket_read_auth(b);
1011}