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