]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/libsystemd/sd-bus/bus-socket.c
Merge pull request #1269 from zonque/netcls
[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;
30494563
TG
267 size_t len;
268 int r;
2181a7f5
LP
269
270 if (!b->anonymous_auth)
271 return 0;
272
273 if (l <= 0)
274 return 1;
275
276 assert(p[0] == ' ');
277 p++; l--;
278
279 if (l % 2 != 0)
280 return 0;
2181a7f5 281
30494563
TG
282 r = unhexmem(p, l, (void **) &token, &len);
283 if (r < 0)
284 return 0;
285
286 if (memchr(token, 0, len))
2181a7f5
LP
287 return 0;
288
289 return !!utf8_is_valid(token);
290}
291
292static int verify_external_token(sd_bus *b, const char *p, size_t l) {
293 _cleanup_free_ char *token = NULL;
30494563 294 size_t len;
2181a7f5
LP
295 uid_t u;
296 int r;
297
298 /* We don't do any real authentication here. Instead, we if
299 * the owner of this bus wanted authentication he should have
300 * checked SO_PEERCRED before even creating the bus object. */
301
8411d2a2 302 if (!b->anonymous_auth && !b->ucred_valid)
2181a7f5
LP
303 return 0;
304
305 if (l <= 0)
306 return 1;
307
308 assert(p[0] == ' ');
309 p++; l--;
310
311 if (l % 2 != 0)
312 return 0;
313
30494563
TG
314 r = unhexmem(p, l, (void**) &token, &len);
315 if (r < 0)
316 return 0;
2181a7f5 317
30494563 318 if (memchr(token, 0, len))
2181a7f5
LP
319 return 0;
320
321 r = parse_uid(token, &u);
322 if (r < 0)
323 return 0;
324
8411d2a2
LP
325 /* We ignore the passed value if anonymous authentication is
326 * on anyway. */
327 if (!b->anonymous_auth && u != b->ucred.uid)
2181a7f5
LP
328 return 0;
329
330 return 1;
331}
332
333static int bus_socket_auth_write(sd_bus *b, const char *t) {
334 char *p;
335 size_t l;
336
337 assert(b);
338 assert(t);
339
340 /* We only make use of the first iovec */
341 assert(b->auth_index == 0 || b->auth_index == 1);
342
343 l = strlen(t);
344 p = malloc(b->auth_iovec[0].iov_len + l);
345 if (!p)
346 return -ENOMEM;
347
348 memcpy(p, b->auth_iovec[0].iov_base, b->auth_iovec[0].iov_len);
349 memcpy(p + b->auth_iovec[0].iov_len, t, l);
350
351 b->auth_iovec[0].iov_base = p;
352 b->auth_iovec[0].iov_len += l;
353
354 free(b->auth_buffer);
355 b->auth_buffer = p;
356 b->auth_index = 0;
357 return 0;
358}
359
360static int bus_socket_auth_write_ok(sd_bus *b) {
361 char t[3 + 32 + 2 + 1];
362
363 assert(b);
364
5ffa8c81 365 xsprintf(t, "OK " SD_ID128_FORMAT_STR "\r\n", SD_ID128_FORMAT_VAL(b->server_id));
2181a7f5
LP
366
367 return bus_socket_auth_write(b, t);
368}
369
370static int bus_socket_auth_verify_server(sd_bus *b) {
371 char *e;
372 const char *line;
373 size_t l;
374 bool processed = false;
375 int r;
376
377 assert(b);
378
2b4ac889 379 if (b->rbuffer_size < 1)
2181a7f5
LP
380 return 0;
381
382 /* First char must be a NUL byte */
383 if (*(char*) b->rbuffer != 0)
384 return -EIO;
385
2b4ac889
LP
386 if (b->rbuffer_size < 3)
387 return 0;
388
2181a7f5
LP
389 /* Begin with the first line */
390 if (b->auth_rbegin <= 0)
391 b->auth_rbegin = 1;
392
393 for (;;) {
394 /* Check if line is complete */
395 line = (char*) b->rbuffer + b->auth_rbegin;
396 e = memmem(line, b->rbuffer_size - b->auth_rbegin, "\r\n", 2);
397 if (!e)
398 return processed;
399
400 l = e - line;
401
402 if (line_begins(line, l, "AUTH ANONYMOUS")) {
403
404 r = verify_anonymous_token(b, line + 14, l - 14);
405 if (r < 0)
406 return r;
407 if (r == 0)
408 r = bus_socket_auth_write(b, "REJECTED\r\n");
409 else {
410 b->auth = BUS_AUTH_ANONYMOUS;
411 r = bus_socket_auth_write_ok(b);
412 }
413
414 } else if (line_begins(line, l, "AUTH EXTERNAL")) {
415
416 r = verify_external_token(b, line + 13, l - 13);
417 if (r < 0)
418 return r;
419 if (r == 0)
420 r = bus_socket_auth_write(b, "REJECTED\r\n");
421 else {
422 b->auth = BUS_AUTH_EXTERNAL;
423 r = bus_socket_auth_write_ok(b);
424 }
425
426 } else if (line_begins(line, l, "AUTH"))
427 r = bus_socket_auth_write(b, "REJECTED EXTERNAL ANONYMOUS\r\n");
428 else if (line_equals(line, l, "CANCEL") ||
429 line_begins(line, l, "ERROR")) {
430
431 b->auth = _BUS_AUTH_INVALID;
432 r = bus_socket_auth_write(b, "REJECTED\r\n");
433
434 } else if (line_equals(line, l, "BEGIN")) {
435
436 if (b->auth == _BUS_AUTH_INVALID)
437 r = bus_socket_auth_write(b, "ERROR\r\n");
438 else {
439 /* We can't leave from the auth phase
440 * before we haven't written
441 * everything queued, so let's check
442 * that */
443
444 if (bus_socket_auth_needs_write(b))
445 return 1;
446
447 b->rbuffer_size -= (e + 2 - (char*) b->rbuffer);
448 memmove(b->rbuffer, e + 2, b->rbuffer_size);
449 return bus_start_running(b);
450 }
451
452 } else if (line_begins(line, l, "DATA")) {
453
454 if (b->auth == _BUS_AUTH_INVALID)
455 r = bus_socket_auth_write(b, "ERROR\r\n");
456 else {
457 if (b->auth == BUS_AUTH_ANONYMOUS)
458 r = verify_anonymous_token(b, line + 4, l - 4);
459 else
460 r = verify_external_token(b, line + 4, l - 4);
461
462 if (r < 0)
463 return r;
464 if (r == 0) {
465 b->auth = _BUS_AUTH_INVALID;
466 r = bus_socket_auth_write(b, "REJECTED\r\n");
467 } else
468 r = bus_socket_auth_write_ok(b);
469 }
470 } else if (line_equals(line, l, "NEGOTIATE_UNIX_FD")) {
264ad849 471 if (b->auth == _BUS_AUTH_INVALID || !(b->hello_flags & KDBUS_HELLO_ACCEPT_FD))
2181a7f5
LP
472 r = bus_socket_auth_write(b, "ERROR\r\n");
473 else {
474 b->can_fds = true;
475 r = bus_socket_auth_write(b, "AGREE_UNIX_FD\r\n");
476 }
477 } else
478 r = bus_socket_auth_write(b, "ERROR\r\n");
479
480 if (r < 0)
481 return r;
482
483 b->auth_rbegin = e + 2 - (char*) b->rbuffer;
484
485 processed = true;
486 }
487}
488
489static int bus_socket_auth_verify(sd_bus *b) {
490 assert(b);
491
492 if (b->is_server)
493 return bus_socket_auth_verify_server(b);
494 else
495 return bus_socket_auth_verify_client(b);
496}
497
a7e3212d
LP
498static int bus_socket_read_auth(sd_bus *b) {
499 struct msghdr mh;
7f4e6a1c 500 struct iovec iov = {};
a7e3212d
LP
501 size_t n;
502 ssize_t k;
503 int r;
504 void *p;
2181a7f5
LP
505 union {
506 struct cmsghdr cmsghdr;
d868f2a3 507 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
2181a7f5 508 } control;
15d5af81 509 bool handle_cmsg = false;
a7e3212d
LP
510
511 assert(b);
2181a7f5 512 assert(b->state == BUS_AUTHENTICATING);
a7e3212d
LP
513
514 r = bus_socket_auth_verify(b);
515 if (r != 0)
516 return r;
517
9607d947 518 n = MAX(256u, b->rbuffer_size * 2);
a7e3212d
LP
519
520 if (n > BUS_AUTH_SIZE_MAX)
521 n = BUS_AUTH_SIZE_MAX;
522
523 if (b->rbuffer_size >= n)
524 return -ENOBUFS;
525
526 p = realloc(b->rbuffer, n);
527 if (!p)
528 return -ENOMEM;
529
530 b->rbuffer = p;
531
a7e3212d
LP
532 iov.iov_base = (uint8_t*) b->rbuffer + b->rbuffer_size;
533 iov.iov_len = n - b->rbuffer_size;
534
15d5af81
LP
535 if (b->prefer_readv)
536 k = readv(b->input_fd, &iov, 1);
537 else {
538 zero(mh);
539 mh.msg_iov = &iov;
540 mh.msg_iovlen = 1;
541 mh.msg_control = &control;
542 mh.msg_controllen = sizeof(control);
543
544 k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
545 if (k < 0 && errno == ENOTSOCK) {
546 b->prefer_readv = true;
547 k = readv(b->input_fd, &iov, 1);
548 } else
549 handle_cmsg = true;
550 }
a7e3212d
LP
551 if (k < 0)
552 return errno == EAGAIN ? 0 : -errno;
553 if (k == 0)
554 return -ECONNRESET;
555
556 b->rbuffer_size += k;
557
2a1288ff
LP
558 if (handle_cmsg) {
559 struct cmsghdr *cmsg;
560
561 CMSG_FOREACH(cmsg, &mh)
15d5af81
LP
562 if (cmsg->cmsg_level == SOL_SOCKET &&
563 cmsg->cmsg_type == SCM_RIGHTS) {
564 int j;
565
566 /* Whut? We received fds during the auth
567 * protocol? Somebody is playing games with
568 * us. Close them all, and fail */
569 j = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
570 close_many((int*) CMSG_DATA(cmsg), j);
571 return -EIO;
d868f2a3
ZJS
572 } else
573 log_debug("Got unexpected auxiliary data with level=%d and type=%d",
574 cmsg->cmsg_level, cmsg->cmsg_type);
2a1288ff 575 }
2181a7f5 576
a7e3212d
LP
577 r = bus_socket_auth_verify(b);
578 if (r != 0)
579 return r;
580
581 return 1;
582}
583
8f04d2eb 584void bus_socket_setup(sd_bus *b) {
a7e3212d
LP
585 assert(b);
586
aec6d91f
LP
587 /* Increase the buffers to 8 MB */
588 fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
589 fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
a7e3212d 590
e1d337d4
LP
591 b->is_kernel = false;
592 b->message_version = 1;
0f437184 593 b->message_endian = 0;
8f04d2eb 594}
e1d337d4 595
8f04d2eb 596static void bus_get_peercred(sd_bus *b) {
c4e6556c
ZJS
597 int r;
598
8f04d2eb
LP
599 assert(b);
600
601 /* Get the peer for socketpair() sockets */
eff05270 602 b->ucred_valid = getpeercred(b->input_fd, &b->ucred) >= 0;
c4e6556c
ZJS
603
604 /* Get the SELinux context of the peer */
605 r = getpeersec(b->input_fd, &b->label);
606 if (r < 0 && r != -EOPNOTSUPP)
607 log_debug_errno(r, "Failed to determine peer security context: %m");
a7e3212d
LP
608}
609
2181a7f5 610static int bus_socket_start_auth_client(sd_bus *b) {
a7e3212d 611 size_t l;
2181a7f5 612 const char *auth_suffix, *auth_prefix;
a7e3212d
LP
613
614 assert(b);
615
2181a7f5
LP
616 if (b->anonymous_auth) {
617 auth_prefix = "\0AUTH ANONYMOUS ";
a7e3212d 618
2181a7f5
LP
619 /* For ANONYMOUS auth we send some arbitrary "trace" string */
620 l = 9;
621 b->auth_buffer = hexmem("anonymous", l);
622 } else {
5ffa8c81 623 char text[DECIMAL_STR_MAX(uid_t) + 1];
a7e3212d 624
2181a7f5 625 auth_prefix = "\0AUTH EXTERNAL ";
a7e3212d 626
5ffa8c81 627 xsprintf(text, UID_FMT, geteuid());
a7e3212d 628
2181a7f5
LP
629 l = strlen(text);
630 b->auth_buffer = hexmem(text, l);
631 }
632
633 if (!b->auth_buffer)
a7e3212d
LP
634 return -ENOMEM;
635
264ad849 636 if (b->hello_flags & KDBUS_HELLO_ACCEPT_FD)
2181a7f5
LP
637 auth_suffix = "\r\nNEGOTIATE_UNIX_FD\r\nBEGIN\r\n";
638 else
639 auth_suffix = "\r\nBEGIN\r\n";
a7e3212d
LP
640
641 b->auth_iovec[0].iov_base = (void*) auth_prefix;
2181a7f5
LP
642 b->auth_iovec[0].iov_len = 1 + strlen(auth_prefix + 1);
643 b->auth_iovec[1].iov_base = (void*) b->auth_buffer;
a7e3212d
LP
644 b->auth_iovec[1].iov_len = l * 2;
645 b->auth_iovec[2].iov_base = (void*) auth_suffix;
646 b->auth_iovec[2].iov_len = strlen(auth_suffix);
a7e3212d
LP
647
648 return bus_socket_write_auth(b);
649}
650
a7893c6b 651int bus_socket_start_auth(sd_bus *b) {
2181a7f5
LP
652 assert(b);
653
8f04d2eb
LP
654 bus_get_peercred(b);
655
2181a7f5
LP
656 b->state = BUS_AUTHENTICATING;
657 b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
658
9ab32f9d 659 if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
264ad849 660 b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
2181a7f5 661
9ab32f9d
LP
662 if (b->output_fd != b->input_fd)
663 if (sd_is_socket(b->output_fd, AF_UNIX, 0, 0) <= 0)
264ad849 664 b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
e82c9509 665
2181a7f5
LP
666 if (b->is_server)
667 return bus_socket_read_auth(b);
668 else
669 return bus_socket_start_auth_client(b);
670}
671
a7e3212d
LP
672int bus_socket_connect(sd_bus *b) {
673 int r;
674
675 assert(b);
e82c9509
LP
676 assert(b->input_fd < 0);
677 assert(b->output_fd < 0);
a7e3212d
LP
678 assert(b->sockaddr.sa.sa_family != AF_UNSPEC);
679
e82c9509
LP
680 b->input_fd = socket(b->sockaddr.sa.sa_family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
681 if (b->input_fd < 0)
a7e3212d
LP
682 return -errno;
683
e82c9509
LP
684 b->output_fd = b->input_fd;
685
8f04d2eb 686 bus_socket_setup(b);
a7e3212d 687
e82c9509 688 r = connect(b->input_fd, &b->sockaddr.sa, b->sockaddr_size);
a7e3212d
LP
689 if (r < 0) {
690 if (errno == EINPROGRESS)
691 return 1;
692
693 return -errno;
694 }
695
696 return bus_socket_start_auth(b);
697}
698
699int bus_socket_exec(sd_bus *b) {
e82c9509 700 int s[2], r;
a7e3212d
LP
701 pid_t pid;
702
703 assert(b);
e82c9509
LP
704 assert(b->input_fd < 0);
705 assert(b->output_fd < 0);
a7e3212d
LP
706 assert(b->exec_path);
707
e82c9509
LP
708 r = socketpair(AF_UNIX, SOCK_STREAM|SOCK_NONBLOCK|SOCK_CLOEXEC, 0, s);
709 if (r < 0)
a7e3212d
LP
710 return -errno;
711
712 pid = fork();
713 if (pid < 0) {
3d94f76c 714 safe_close_pair(s);
a7e3212d
LP
715 return -errno;
716 }
717 if (pid == 0) {
718 /* Child */
719
ce30c8dc
LP
720 (void) reset_all_signal_handlers();
721 (void) reset_signal_mask();
e82c9509
LP
722
723 close_all_fds(s+1, 1);
a7e3212d
LP
724
725 assert_se(dup3(s[1], STDIN_FILENO, 0) == STDIN_FILENO);
726 assert_se(dup3(s[1], STDOUT_FILENO, 0) == STDOUT_FILENO);
727
728 if (s[1] != STDIN_FILENO && s[1] != STDOUT_FILENO)
03e334a1 729 safe_close(s[1]);
a7e3212d
LP
730
731 fd_cloexec(STDIN_FILENO, false);
732 fd_cloexec(STDOUT_FILENO, false);
733 fd_nonblock(STDIN_FILENO, false);
734 fd_nonblock(STDOUT_FILENO, false);
735
736 if (b->exec_argv)
737 execvp(b->exec_path, b->exec_argv);
738 else {
739 const char *argv[] = { b->exec_path, NULL };
740 execvp(b->exec_path, (char**) argv);
741 }
742
743 _exit(EXIT_FAILURE);
744 }
745
03e334a1 746 safe_close(s[1]);
e82c9509 747 b->output_fd = b->input_fd = s[0];
a7e3212d 748
8f04d2eb 749 bus_socket_setup(b);
e1d337d4 750
a7e3212d
LP
751 return bus_socket_start_auth(b);
752}
753
754int bus_socket_take_fd(sd_bus *b) {
a7e3212d
LP
755 assert(b);
756
8f04d2eb 757 bus_socket_setup(b);
a7e3212d
LP
758
759 return bus_socket_start_auth(b);
760}
761
762int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
a7e3212d
LP
763 struct iovec *iov;
764 ssize_t k;
765 size_t n;
766 unsigned j;
bc7fd8cd 767 int r;
a7e3212d
LP
768
769 assert(bus);
770 assert(m);
771 assert(idx);
772 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
773
6629161f 774 if (*idx >= BUS_MESSAGE_SIZE(m))
a7e3212d 775 return 0;
a7e3212d 776
bc7fd8cd
LP
777 r = bus_message_setup_iovec(m);
778 if (r < 0)
779 return r;
2100fa10 780
a7e3212d
LP
781 n = m->n_iovec * sizeof(struct iovec);
782 iov = alloca(n);
783 memcpy(iov, m->iovec, n);
784
785 j = 0;
786 iovec_advance(iov, &j, *idx);
787
15d5af81
LP
788 if (bus->prefer_writev)
789 k = writev(bus->output_fd, iov, m->n_iovec);
790 else {
7f4e6a1c
ZJS
791 struct msghdr mh = {
792 .msg_iov = iov,
793 .msg_iovlen = m->n_iovec,
794 };
15d5af81
LP
795
796 if (m->n_fds > 0) {
797 struct cmsghdr *control;
15d5af81 798
7f4e6a1c
ZJS
799 mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
800 mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
15d5af81
LP
801 control->cmsg_level = SOL_SOCKET;
802 control->cmsg_type = SCM_RIGHTS;
15d5af81
LP
803 memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
804 }
805
15d5af81
LP
806 k = sendmsg(bus->output_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL);
807 if (k < 0 && errno == ENOTSOCK) {
808 bus->prefer_writev = true;
809 k = writev(bus->output_fd, iov, m->n_iovec);
810 }
811 }
a7e3212d 812
a7e3212d
LP
813 if (k < 0)
814 return errno == EAGAIN ? 0 : -errno;
815
816 *idx += (size_t) k;
817 return 1;
818}
819
820static int bus_socket_read_message_need(sd_bus *bus, size_t *need) {
821 uint32_t a, b;
822 uint8_t e;
823 uint64_t sum;
824
825 assert(bus);
826 assert(need);
827 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
828
829 if (bus->rbuffer_size < sizeof(struct bus_header)) {
830 *need = sizeof(struct bus_header) + 8;
831
832 /* Minimum message size:
833 *
834 * Header +
835 *
836 * Method Call: +2 string headers
837 * Signal: +3 string headers
838 * Method Error: +1 string headers
839 * +1 uint32 headers
840 * Method Reply: +1 uint32 headers
841 *
842 * A string header is at least 9 bytes
843 * A uint32 header is at least 8 bytes
844 *
845 * Hence the minimum message size of a valid message
846 * is header + 8 bytes */
847
848 return 0;
849 }
850
851 a = ((const uint32_t*) bus->rbuffer)[1];
852 b = ((const uint32_t*) bus->rbuffer)[3];
853
854 e = ((const uint8_t*) bus->rbuffer)[0];
0461f8cd 855 if (e == BUS_LITTLE_ENDIAN) {
a7e3212d
LP
856 a = le32toh(a);
857 b = le32toh(b);
0461f8cd 858 } else if (e == BUS_BIG_ENDIAN) {
a7e3212d
LP
859 a = be32toh(a);
860 b = be32toh(b);
861 } else
862 return -EBADMSG;
863
864 sum = (uint64_t) sizeof(struct bus_header) + (uint64_t) ALIGN_TO(b, 8) + (uint64_t) a;
865 if (sum >= BUS_MESSAGE_SIZE_MAX)
866 return -ENOBUFS;
867
868 *need = (size_t) sum;
869 return 0;
870}
871
7d22c717 872static int bus_socket_make_message(sd_bus *bus, size_t size) {
a7e3212d
LP
873 sd_bus_message *t;
874 void *b;
875 int r;
876
877 assert(bus);
a7e3212d
LP
878 assert(bus->rbuffer_size >= size);
879 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
880
7adc46fc
LP
881 r = bus_rqueue_make_room(bus);
882 if (r < 0)
883 return r;
884
a7e3212d
LP
885 if (bus->rbuffer_size > size) {
886 b = memdup((const uint8_t*) bus->rbuffer + size,
887 bus->rbuffer_size - size);
888 if (!b)
889 return -ENOMEM;
890 } else
891 b = NULL;
892
df2d202e
LP
893 r = bus_message_from_malloc(bus,
894 bus->rbuffer, size,
a7e3212d 895 bus->fds, bus->n_fds,
038f9863 896 NULL,
a7e3212d
LP
897 &t);
898 if (r < 0) {
899 free(b);
900 return r;
901 }
902
903 bus->rbuffer = b;
904 bus->rbuffer_size -= size;
905
906 bus->fds = NULL;
907 bus->n_fds = 0;
908
7adc46fc 909 bus->rqueue[bus->rqueue_size++] = t;
7d22c717 910
a7e3212d
LP
911 return 1;
912}
913
7d22c717 914int bus_socket_read_message(sd_bus *bus) {
a7e3212d 915 struct msghdr mh;
7f4e6a1c 916 struct iovec iov = {};
a7e3212d
LP
917 ssize_t k;
918 size_t need;
919 int r;
920 void *b;
921 union {
922 struct cmsghdr cmsghdr;
d868f2a3 923 uint8_t buf[CMSG_SPACE(sizeof(int) * BUS_FDS_MAX)];
a7e3212d 924 } control;
4d3a5b10 925 bool handle_cmsg = false;
a7e3212d
LP
926
927 assert(bus);
a7e3212d
LP
928 assert(bus->state == BUS_RUNNING || bus->state == BUS_HELLO);
929
930 r = bus_socket_read_message_need(bus, &need);
931 if (r < 0)
932 return r;
933
934 if (bus->rbuffer_size >= need)
7d22c717 935 return bus_socket_make_message(bus, need);
a7e3212d
LP
936
937 b = realloc(bus->rbuffer, need);
938 if (!b)
939 return -ENOMEM;
940
941 bus->rbuffer = b;
942
a7e3212d
LP
943 iov.iov_base = (uint8_t*) bus->rbuffer + bus->rbuffer_size;
944 iov.iov_len = need - bus->rbuffer_size;
945
15d5af81
LP
946 if (bus->prefer_readv)
947 k = readv(bus->input_fd, &iov, 1);
948 else {
949 zero(mh);
950 mh.msg_iov = &iov;
951 mh.msg_iovlen = 1;
952 mh.msg_control = &control;
953 mh.msg_controllen = sizeof(control);
954
955 k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
956 if (k < 0 && errno == ENOTSOCK) {
957 bus->prefer_readv = true;
958 k = readv(bus->input_fd, &iov, 1);
959 } else
960 handle_cmsg = true;
961 }
a7e3212d
LP
962 if (k < 0)
963 return errno == EAGAIN ? 0 : -errno;
964 if (k == 0)
965 return -ECONNRESET;
966
967 bus->rbuffer_size += k;
968
2a1288ff
LP
969 if (handle_cmsg) {
970 struct cmsghdr *cmsg;
971
972 CMSG_FOREACH(cmsg, &mh)
15d5af81
LP
973 if (cmsg->cmsg_level == SOL_SOCKET &&
974 cmsg->cmsg_type == SCM_RIGHTS) {
975 int n, *f;
976
977 n = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
978
979 if (!bus->can_fds) {
980 /* Whut? We received fds but this
981 * isn't actually enabled? Close them,
982 * and fail */
983
984 close_many((int*) CMSG_DATA(cmsg), n);
985 return -EIO;
986 }
987
988 f = realloc(bus->fds, sizeof(int) + (bus->n_fds + n));
989 if (!f) {
990 close_many((int*) CMSG_DATA(cmsg), n);
991 return -ENOMEM;
992 }
993
994 memcpy(f + bus->n_fds, CMSG_DATA(cmsg), n * sizeof(int));
995 bus->fds = f;
996 bus->n_fds += n;
d868f2a3
ZJS
997 } else
998 log_debug("Got unexpected auxiliary data with level=%d and type=%d",
999 cmsg->cmsg_level, cmsg->cmsg_type);
2a1288ff 1000 }
a7e3212d
LP
1001
1002 r = bus_socket_read_message_need(bus, &need);
1003 if (r < 0)
1004 return r;
1005
1006 if (bus->rbuffer_size >= need)
7d22c717 1007 return bus_socket_make_message(bus, need);
a7e3212d
LP
1008
1009 return 1;
1010}
1011
1012int bus_socket_process_opening(sd_bus *b) {
1013 int error = 0;
1014 socklen_t slen = sizeof(error);
b92bea5d
ZJS
1015 struct pollfd p = {
1016 .fd = b->output_fd,
1017 .events = POLLOUT,
1018 };
a7e3212d
LP
1019 int r;
1020
a7e3212d
LP
1021 assert(b->state == BUS_OPENING);
1022
a7e3212d
LP
1023 r = poll(&p, 1, 0);
1024 if (r < 0)
1025 return -errno;
1026
1027 if (!(p.revents & (POLLOUT|POLLERR|POLLHUP)))
1028 return 0;
1029
e82c9509 1030 r = getsockopt(b->output_fd, SOL_SOCKET, SO_ERROR, &error, &slen);
a7e3212d
LP
1031 if (r < 0)
1032 b->last_connect_error = errno;
1033 else if (error != 0)
1034 b->last_connect_error = error;
1035 else if (p.revents & (POLLERR|POLLHUP))
1036 b->last_connect_error = ECONNREFUSED;
1037 else
1038 return bus_socket_start_auth(b);
1039
1040 return bus_next_address(b);
1041}
1042
1043int bus_socket_process_authenticating(sd_bus *b) {
1044 int r;
1045
1046 assert(b);
1047 assert(b->state == BUS_AUTHENTICATING);
1048
1049 if (now(CLOCK_MONOTONIC) >= b->auth_timeout)
1050 return -ETIMEDOUT;
1051
1052 r = bus_socket_write_auth(b);
1053 if (r != 0)
1054 return r;
1055
1056 return bus_socket_read_auth(b);
1057}