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