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