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