]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/bus-proxyd/bus-proxyd.c
bus-proxyd: enforce policy for Hello messages
[thirdparty/systemd.git] / src / bus-proxyd / bus-proxyd.c
1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
2
3 /***
4 This file is part of systemd.
5
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
9
10 systemd is free software; you can redistribute it and/or modify it
11 under the terms of the GNU Lesser General Public License as published by
12 the Free Software Foundation; either version 2.1 of the License, or
13 (at your option) any later version.
14
15 systemd is distributed in the hope that it will be useful, but
16 WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 Lesser General Public License for more details.
19
20 You should have received a copy of the GNU Lesser General Public License
21 along with systemd; If not, see <http://www.gnu.org/licenses/>.
22 ***/
23
24 #include <sys/socket.h>
25 #include <sys/un.h>
26 #include <sys/types.h>
27 #include <fcntl.h>
28 #include <unistd.h>
29 #include <string.h>
30 #include <errno.h>
31 #include <sys/poll.h>
32 #include <stddef.h>
33 #include <getopt.h>
34
35 #include "log.h"
36 #include "util.h"
37 #include "socket-util.h"
38 #include "sd-daemon.h"
39 #include "sd-bus.h"
40 #include "bus-internal.h"
41 #include "bus-message.h"
42 #include "bus-util.h"
43 #include "build.h"
44 #include "strv.h"
45 #include "def.h"
46 #include "capability.h"
47 #include "bus-policy.h"
48
49 static char *arg_address = NULL;
50 static char *arg_command_line_buffer = NULL;
51 static bool arg_drop_privileges = false;
52 static char **arg_configuration = NULL;
53
54 static Hashmap *names_hash = NULL;
55
56 static int help(void) {
57
58 printf("%s [OPTIONS...]\n\n"
59 "Connect STDIO or a socket to a given bus address.\n\n"
60 " -h --help Show this help\n"
61 " --version Show package version\n"
62 " --drop-privileges Drop privileges\n"
63 " --configuration=PATH Configuration file or directory\n"
64 " --machine=MACHINE Connect to specified machine\n"
65 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
66 " (default: " DEFAULT_SYSTEM_BUS_PATH ")\n",
67 program_invocation_short_name);
68
69 return 0;
70 }
71
72 static int parse_argv(int argc, char *argv[]) {
73
74 enum {
75 ARG_VERSION = 0x100,
76 ARG_ADDRESS,
77 ARG_DROP_PRIVILEGES,
78 ARG_CONFIGURATION,
79 ARG_MACHINE,
80 };
81
82 static const struct option options[] = {
83 { "help", no_argument, NULL, 'h' },
84 { "version", no_argument, NULL, ARG_VERSION },
85 { "address", required_argument, NULL, ARG_ADDRESS },
86 { "drop-privileges", no_argument, NULL, ARG_DROP_PRIVILEGES },
87 { "configuration", required_argument, NULL, ARG_CONFIGURATION },
88 { "machine", required_argument, NULL, ARG_MACHINE },
89 {},
90 };
91
92 int c, r;
93
94 assert(argc >= 0);
95 assert(argv);
96
97 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
98
99 switch (c) {
100
101 case 'h':
102 help();
103 return 0;
104
105 case ARG_VERSION:
106 puts(PACKAGE_STRING);
107 puts(SYSTEMD_FEATURES);
108 return 0;
109
110 case ARG_ADDRESS: {
111 char *a;
112
113 a = strdup(optarg);
114 if (!a)
115 return log_oom();
116
117 free(arg_address);
118 arg_address = a;
119 break;
120 }
121
122 case ARG_DROP_PRIVILEGES:
123 arg_drop_privileges = true;
124 break;
125
126 case ARG_CONFIGURATION:
127 r = strv_extend(&arg_configuration, optarg);
128 if (r < 0)
129 return log_oom();
130 break;
131
132 case ARG_MACHINE: {
133 _cleanup_free_ char *e = NULL;
134 char *a;
135
136 e = bus_address_escape(optarg);
137 if (!e)
138 return log_oom();
139
140 #ifdef ENABLE_KDBUS
141 a = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL);
142 #else
143 a = strjoin("x-container-unix:machine=", e, NULL);
144 #endif
145 if (!a)
146 return log_oom();
147
148 free(arg_address);
149 arg_address = a;
150
151 break;
152 }
153
154 case '?':
155 return -EINVAL;
156
157 default:
158 assert_not_reached("Unhandled option");
159 }
160
161 /* If the first command line argument is only "x" characters
162 * we'll write who we are talking to into it, so that "ps" is
163 * explanatory */
164 arg_command_line_buffer = argv[optind];
165 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
166 log_error("Too many arguments");
167 return -EINVAL;
168 }
169
170 if (!arg_address) {
171 arg_address = strdup(DEFAULT_SYSTEM_BUS_PATH);
172 if (!arg_address)
173 return log_oom();
174 }
175
176 return 1;
177 }
178
179 static int rename_service(sd_bus *a, sd_bus *b) {
180 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
181 _cleanup_free_ char *p = NULL, *name = NULL;
182 const char *comm;
183 char **cmdline;
184 uid_t uid;
185 pid_t pid;
186 int r;
187
188 assert(a);
189 assert(b);
190
191 r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds);
192 if (r < 0)
193 return r;
194
195 r = sd_bus_creds_get_uid(creds, &uid);
196 if (r < 0)
197 return r;
198
199 r = sd_bus_creds_get_pid(creds, &pid);
200 if (r < 0)
201 return r;
202
203 r = sd_bus_creds_get_cmdline(creds, &cmdline);
204 if (r < 0)
205 return r;
206
207 r = sd_bus_creds_get_comm(creds, &comm);
208 if (r < 0)
209 return r;
210
211 name = uid_to_name(uid);
212 if (!name)
213 return -ENOMEM;
214
215 p = strv_join(cmdline, " ");
216 if (!p)
217 return -ENOMEM;
218
219 /* The status string gets the full command line ... */
220 sd_notifyf(false,
221 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
222 pid, p,
223 uid, name);
224
225 /* ... and the argv line only the short comm */
226 if (arg_command_line_buffer) {
227 size_t m, w;
228
229 m = strlen(arg_command_line_buffer);
230 w = snprintf(arg_command_line_buffer, m,
231 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
232 pid, comm,
233 uid, name);
234
235 if (m > w)
236 memzero(arg_command_line_buffer + w, m - w);
237 }
238
239 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
240 pid, p,
241 uid, name,
242 a->unique_name);
243
244 return 0;
245 }
246
247 static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
248 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
249 const char *name, *old_owner, *new_owner;
250 int r;
251
252 assert(a);
253 assert(b);
254 assert(m);
255
256 /* If we get NameOwnerChanged for our own name, we need to
257 * synthesize NameLost/NameAcquired, since socket clients need
258 * that, even though it is obsoleted on kdbus */
259
260 if (!a->is_kernel)
261 return 0;
262
263 if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") ||
264 !streq_ptr(m->path, "/org/freedesktop/DBus") ||
265 !streq_ptr(m->sender, "org.freedesktop.DBus"))
266 return 0;
267
268 r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner);
269 if (r < 0)
270 return r;
271
272 r = sd_bus_message_rewind(m, true);
273 if (r < 0)
274 return r;
275
276 if (streq(old_owner, a->unique_name)) {
277
278 r = sd_bus_message_new_signal(
279 b,
280 &n,
281 "/org/freedesktop/DBus",
282 "org.freedesktop.DBus",
283 "NameLost");
284
285 } else if (streq(new_owner, a->unique_name)) {
286
287 r = sd_bus_message_new_signal(
288 b,
289 &n,
290 "/org/freedesktop/DBus",
291 "org.freedesktop.DBus",
292 "NameAcquired");
293 } else
294 return 0;
295
296 if (r < 0)
297 return r;
298
299 r = sd_bus_message_append(n, "s", name);
300 if (r < 0)
301 return r;
302
303 r = bus_message_append_sender(n, "org.freedesktop.DBus");
304 if (r < 0)
305 return r;
306
307 r = bus_seal_synthetic_message(b, n);
308 if (r < 0)
309 return r;
310
311 return sd_bus_send(b, n, NULL);
312 }
313
314 static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m) {
315 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
316 int r;
317
318 assert(a);
319 assert(b);
320 assert(m);
321
322 if (!a->is_kernel)
323 return 0;
324
325 if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "GetAll"))
326 return 0;
327
328 if (!streq_ptr(m->path, "/org/gnome/DisplayManager/Slave"))
329 return 0;
330
331 r = sd_bus_message_new_method_errorf(m, &n, SD_BUS_ERROR_ACCESS_DENIED, "gdm, you are stupid");
332 if (r < 0)
333 return r;
334
335 r = bus_message_append_sender(n, "org.freedesktop.DBus");
336 if (r < 0) {
337 log_error("Failed to append sender to gdm reply: %s", strerror(-r));
338 return r;
339 }
340
341 r = bus_seal_synthetic_message(b, n);
342 if (r < 0) {
343 log_error("Failed to seal gdm reply: %s", strerror(-r));
344 return r;
345 }
346
347 r = sd_bus_send(b, n, NULL);
348 if (r < 0) {
349 log_error("Failed to send gdm reply: %s", strerror(-r));
350 return r;
351 }
352
353 return 1;
354 }
355
356 static int synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
357 int r;
358
359 assert(b);
360 assert(m);
361
362 r = bus_message_append_sender(m, "org.freedesktop.DBus");
363 if (r < 0)
364 return r;
365
366 r = bus_seal_synthetic_message(b, m);
367 if (r < 0)
368 return r;
369
370 return sd_bus_send(b, m, NULL);
371 }
372
373 static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
374 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
375 int r;
376
377 assert(call);
378
379 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
380 return 0;
381
382 r = sd_bus_message_new_method_error(call, &m, e);
383 if (r < 0)
384 return r;
385
386 return synthetic_driver_send(call->bus, m);
387 }
388
389 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
390
391 _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
392
393 assert(call);
394
395 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
396 return 0;
397
398 if (sd_bus_error_is_set(p))
399 return synthetic_reply_method_error(call, p);
400
401 sd_bus_error_set_errno(&berror, error);
402
403 return synthetic_reply_method_error(call, &berror);
404 }
405
406 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
407 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
408 int r;
409
410 assert(call);
411
412 if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
413 return 0;
414
415 r = sd_bus_message_new_method_return(call, &m);
416 if (r < 0)
417 return r;
418
419 if (!isempty(types)) {
420 va_list ap;
421
422 va_start(ap, types);
423 r = bus_message_append_ap(m, types, ap);
424 va_end(ap);
425 if (r < 0)
426 return r;
427 }
428
429 return synthetic_driver_send(call->bus, m);
430 }
431
432 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
433 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
434 int r;
435
436 assert(call);
437
438 r = sd_bus_message_new_method_return(call, &m);
439 if (r < 0)
440 return synthetic_reply_method_errno(call, r, NULL);
441
442 r = sd_bus_message_append_strv(m, l);
443 if (r < 0)
444 return synthetic_reply_method_errno(call, r, NULL);
445
446 return synthetic_driver_send(call->bus, m);
447 }
448
449 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
450 _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
451 int r;
452
453 assert(bus);
454 assert(name);
455 assert(_creds);
456
457 assert_return(service_name_is_valid(name), -EINVAL);
458
459 r = sd_bus_get_name_creds(bus, name, mask, &c);
460 if (r == -ESRCH || r == -ENXIO)
461 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
462 if (r < 0)
463 return r;
464
465 if ((c->mask & mask) != mask)
466 return -ENOTSUP;
467
468 *_creds = c;
469 c = NULL;
470
471 return 0;
472 }
473
474 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
475 const char *name;
476 int r;
477
478 assert(bus);
479 assert(m);
480 assert(_creds);
481
482 r = sd_bus_message_read(m, "s", &name);
483 if (r < 0)
484 return r;
485
486 return get_creds_by_name(bus, name, mask, _creds, error);
487 }
488
489 static int peer_is_privileged(sd_bus *bus, sd_bus_message *m) {
490 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
491 uid_t uid;
492 int r;
493
494 r = get_creds_by_message(bus, m, SD_BUS_CREDS_UID, &creds, NULL);
495 if (r < 0)
496 return r;
497
498 r = sd_bus_creds_get_uid(creds, &uid);
499 if (r < 0)
500 return r;
501
502 r = sd_bus_creds_has_effective_cap(creds, CAP_SYS_ADMIN);
503 if (r > 0)
504 return true;
505
506 if (uid == getuid())
507 return true;
508
509 return false;
510 }
511
512 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) {
513 int r;
514
515 assert(a);
516 assert(b);
517 assert(m);
518
519 if (!a->is_kernel)
520 return 0;
521
522 if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
523 return 0;
524
525 if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
526 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
527 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
528
529 r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
530
531 return synthetic_reply_method_errno(m, r, &error);
532 }
533
534 return synthetic_reply_method_return(m, "s",
535 "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
536 "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
537 "<node>\n"
538 " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
539 " <method name=\"Introspect\">\n"
540 " <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
541 " </method>\n"
542 " </interface>\n"
543 " <interface name=\"org.freedesktop.DBus\">\n"
544 " <method name=\"AddMatch\">\n"
545 " <arg type=\"s\" direction=\"in\"/>\n"
546 " </method>\n"
547 " <method name=\"RemoveMatch\">\n"
548 " <arg type=\"s\" direction=\"in\"/>\n"
549 " </method>\n"
550 " <method name=\"GetConnectionSELinuxSecurityContext\">\n"
551 " <arg type=\"s\" direction=\"in\"/>\n"
552 " <arg type=\"ay\" direction=\"out\"/>\n"
553 " </method>\n"
554 " <method name=\"GetConnectionUnixProcessID\">\n"
555 " <arg type=\"s\" direction=\"in\"/>\n"
556 " <arg type=\"u\" direction=\"out\"/>\n"
557 " </method>\n"
558 " <method name=\"GetConnectionUnixUser\">\n"
559 " <arg type=\"s\" direction=\"in\"/>\n"
560 " <arg type=\"u\" direction=\"out\"/>\n"
561 " </method>\n"
562 " <method name=\"GetId\">\n"
563 " <arg type=\"s\" direction=\"out\"/>\n"
564 " </method>\n"
565 " <method name=\"GetNameOwner\">\n"
566 " <arg type=\"s\" direction=\"in\"/>\n"
567 " <arg type=\"s\" direction=\"out\"/>\n"
568 " </method>\n"
569 " <method name=\"Hello\">\n"
570 " <arg type=\"s\" direction=\"out\"/>\n"
571 " </method>\n"
572 " <method name=\"ListActivatableNames\">\n"
573 " <arg type=\"as\" direction=\"out\"/>\n"
574 " </method>\n"
575 " <method name=\"ListNames\">\n"
576 " <arg type=\"as\" direction=\"out\"/>\n"
577 " </method>\n"
578 " <method name=\"ListQueuedOwners\">\n"
579 " <arg type=\"s\" direction=\"in\"/>\n"
580 " <arg type=\"as\" direction=\"out\"/>\n"
581 " </method>\n"
582 " <method name=\"NameHasOwner\">\n"
583 " <arg type=\"s\" direction=\"in\"/>\n"
584 " <arg type=\"b\" direction=\"out\"/>\n"
585 " </method>\n"
586 " <method name=\"ReleaseName\">\n"
587 " <arg type=\"s\" direction=\"in\"/>\n"
588 " <arg type=\"u\" direction=\"out\"/>\n"
589 " </method>\n"
590 " <method name=\"ReloadConfig\">\n"
591 " </method>\n"
592 " <method name=\"RequestName\">\n"
593 " <arg type=\"s\" direction=\"in\"/>\n"
594 " <arg type=\"u\" direction=\"in\"/>\n"
595 " <arg type=\"u\" direction=\"out\"/>\n"
596 " </method>\n"
597 " <method name=\"StartServiceByName\">\n"
598 " <arg type=\"s\" direction=\"in\"/>\n"
599 " <arg type=\"u\" direction=\"in\"/>\n"
600 " <arg type=\"u\" direction=\"out\"/>\n"
601 " </method>\n"
602 " <method name=\"UpdateActivationEnvironment\">\n"
603 " <arg type=\"a{ss}\" direction=\"in\"/>\n"
604 " </method>\n"
605 " <signal name=\"NameAcquired\">\n"
606 " <arg type=\"s\"/>\n"
607 " </signal>\n"
608 " <signal name=\"NameLost\">\n"
609 " <arg type=\"s\"/>\n"
610 " </signal>\n"
611 " <signal name=\"NameOwnerChanged\">\n"
612 " <arg type=\"s\"/>\n"
613 " <arg type=\"s\"/>\n"
614 " <arg type=\"s\"/>\n"
615 " </signal>\n"
616 " </interface>\n"
617 "</node>\n");
618
619 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
620 const char *match;
621
622 r = sd_bus_message_read(m, "s", &match);
623 if (r < 0)
624 return synthetic_reply_method_errno(m, r, NULL);
625
626 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
627 if (r < 0)
628 return synthetic_reply_method_errno(m, r, NULL);
629
630 return synthetic_reply_method_return(m, NULL);
631
632 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
633 const char *match;
634
635 r = sd_bus_message_read(m, "s", &match);
636 if (r < 0)
637 return synthetic_reply_method_errno(m, r, NULL);
638
639 r = bus_remove_match_by_string(a, match, NULL, NULL);
640 if (r == 0)
641 return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
642 if (r < 0)
643 return synthetic_reply_method_errno(m, r, NULL);
644
645 return synthetic_reply_method_return(m, NULL);
646
647 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
648 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
649 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
650
651 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
652 if (r < 0)
653 return synthetic_reply_method_errno(m, r, &error);
654
655 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
656
657 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
658 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
659 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
660
661 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
662 if (r < 0)
663 return synthetic_reply_method_errno(m, r, &error);
664
665 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
666
667 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
668 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
669 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
670
671 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
672 if (r < 0)
673 return synthetic_reply_method_errno(m, r, &error);
674
675 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
676
677 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
678 sd_id128_t server_id;
679 char buf[SD_ID128_STRING_MAX];
680
681 r = sd_bus_get_owner_id(a, &server_id);
682 if (r < 0)
683 return synthetic_reply_method_errno(m, r, NULL);
684
685 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
686
687 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
688 const char *name;
689 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
690 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
691
692 r = sd_bus_message_read(m, "s", &name);
693 if (r < 0)
694 return synthetic_reply_method_errno(m, r, NULL);
695
696 if (streq(name, "org.freedesktop.DBus"))
697 return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
698
699 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
700 if (r < 0)
701 return synthetic_reply_method_errno(m, r, &error);
702
703 return synthetic_reply_method_return(m, "s", creds->unique_name);
704
705 /* "Hello" is handled in process_hello() */
706
707 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
708 _cleanup_strv_free_ char **names = NULL;
709
710 r = sd_bus_list_names(a, NULL, &names);
711 if (r < 0)
712 return synthetic_reply_method_errno(m, r, NULL);
713
714 /* Let's sort the names list to make it stable */
715 strv_sort(names);
716
717 return synthetic_reply_return_strv(m, names);
718
719 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
720 _cleanup_strv_free_ char **names = NULL;
721
722 r = sd_bus_list_names(a, &names, NULL);
723 if (r < 0)
724 return synthetic_reply_method_errno(m, r, NULL);
725
726 r = strv_extend(&names, "org.freedesktop.DBus");
727 if (r < 0)
728 return synthetic_reply_method_errno(m, r, NULL);
729
730 /* Let's sort the names list to make it stable */
731 strv_sort(names);
732
733 return synthetic_reply_return_strv(m, names);
734
735 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
736 struct kdbus_cmd_name_list cmd = {};
737 struct kdbus_name_list *name_list;
738 struct kdbus_cmd_free cmd_free;
739 struct kdbus_name_info *name;
740 _cleanup_strv_free_ char **owners = NULL;
741 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
742 char *arg0;
743 int err = 0;
744
745 r = sd_bus_message_read(m, "s", &arg0);
746 if (r < 0)
747 return synthetic_reply_method_errno(m, r, NULL);
748
749 if (!service_name_is_valid(arg0))
750 return synthetic_reply_method_errno(m, -EINVAL, NULL);
751
752 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
753 if (r == -ESRCH || r == -ENXIO) {
754 sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
755 return synthetic_reply_method_errno(m, r, &error);
756 }
757 if (r < 0)
758 return synthetic_reply_method_errno(m, r, NULL);
759
760 cmd.flags = KDBUS_NAME_LIST_QUEUED;
761 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
762 if (r < 0)
763 return synthetic_reply_method_errno(m, -errno, NULL);
764
765 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
766
767 KDBUS_ITEM_FOREACH(name, name_list, names) {
768 const char *entry_name = NULL;
769 struct kdbus_item *item;
770 char *n;
771
772 KDBUS_ITEM_FOREACH(item, name, items)
773 if (item->type == KDBUS_ITEM_OWNED_NAME)
774 entry_name = item->name.name;
775
776 if (!streq_ptr(entry_name, arg0))
777 continue;
778
779 if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
780 err = -ENOMEM;
781 break;
782 }
783
784 r = strv_consume(&owners, n);
785 if (r < 0) {
786 err = r;
787 break;
788 }
789 }
790
791 cmd_free.flags = 0;
792 cmd_free.offset = cmd.offset;
793
794 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
795 if (r < 0)
796 return synthetic_reply_method_errno(m, r, NULL);
797
798 if (err < 0)
799 return synthetic_reply_method_errno(m, err, NULL);
800
801 return synthetic_reply_return_strv(m, owners);
802
803 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
804 const char *name;
805
806 r = sd_bus_message_read(m, "s", &name);
807 if (r < 0)
808 return synthetic_reply_method_errno(m, r, NULL);
809
810 if (!service_name_is_valid(name))
811 return synthetic_reply_method_errno(m, -EINVAL, NULL);
812
813 if (streq(name, "org.freedesktop.DBus"))
814 return synthetic_reply_method_return(m, "b", true);
815
816 r = sd_bus_get_name_creds(a, name, 0, NULL);
817 if (r < 0 && r != -ESRCH && r != -ENXIO)
818 return synthetic_reply_method_errno(m, r, NULL);
819
820 return synthetic_reply_method_return(m, "b", r >= 0);
821
822 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
823 const char *name;
824
825 r = sd_bus_message_read(m, "s", &name);
826 if (r < 0)
827 return synthetic_reply_method_errno(m, r, NULL);
828
829 if (!service_name_is_valid(name))
830 return synthetic_reply_method_errno(m, -EINVAL, NULL);
831
832 r = sd_bus_release_name(a, name);
833 if (r < 0) {
834 if (r == -ESRCH)
835 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
836 if (r == -EADDRINUSE)
837 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
838
839 return synthetic_reply_method_errno(m, r, NULL);
840 }
841
842 hashmap_remove(names_hash, name);
843
844 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
845
846 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
847 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
848
849 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
850
851 return synthetic_reply_method_errno(m, r, &error);
852
853 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
854 const char *name;
855 uint32_t flags, param;
856 bool in_queue;
857
858 r = sd_bus_message_read(m, "su", &name, &flags);
859 if (r < 0)
860 return synthetic_reply_method_errno(m, r, NULL);
861
862 if (!service_name_is_valid(name))
863 return synthetic_reply_method_errno(m, -EINVAL, NULL);
864 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
865 return synthetic_reply_method_errno(m, -EINVAL, NULL);
866
867 param = 0;
868 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
869 param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
870 if (flags & BUS_NAME_REPLACE_EXISTING)
871 param |= SD_BUS_NAME_REPLACE_EXISTING;
872 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
873 param |= SD_BUS_NAME_QUEUE;
874
875 r = sd_bus_request_name(a, name, param);
876 if (r < 0) {
877 if (r == -EEXIST)
878 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
879 if (r == -EALREADY)
880 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
881 return synthetic_reply_method_errno(m, r, NULL);
882 }
883
884 in_queue = (r == 0);
885
886 r = hashmap_put(names_hash, name, NULL);
887 if (r < 0)
888 return synthetic_reply_method_errno(m, r, NULL);
889
890 if (in_queue)
891 return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
892
893 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
894
895 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
896 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
897 const char *name;
898 uint32_t flags;
899
900 r = sd_bus_message_read(m, "su", &name, &flags);
901 if (r < 0)
902 return synthetic_reply_method_errno(m, r, NULL);
903
904 if (!service_name_is_valid(name))
905 return synthetic_reply_method_errno(m, -EINVAL, NULL);
906 if (flags != 0)
907 return synthetic_reply_method_errno(m, -EINVAL, NULL);
908
909 r = sd_bus_get_name_creds(a, name, 0, NULL);
910 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
911 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
912 if (r != -ESRCH)
913 return synthetic_reply_method_errno(m, r, NULL);
914
915 r = sd_bus_message_new_method_call(
916 a,
917 &msg,
918 name,
919 "/",
920 "org.freedesktop.DBus.Peer",
921 "Ping");
922 if (r < 0)
923 return synthetic_reply_method_errno(m, r, NULL);
924
925 r = sd_bus_send(a, msg, NULL);
926 if (r < 0)
927 return synthetic_reply_method_errno(m, r, NULL);
928
929 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
930
931 } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
932 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
933 _cleanup_strv_free_ char **args = NULL;
934
935 if (!peer_is_privileged(a, m))
936 return synthetic_reply_method_errno(m, -EPERM, NULL);
937
938 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
939 if (r < 0)
940 return synthetic_reply_method_errno(m, r, NULL);
941
942 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
943 _cleanup_free_ char *s = NULL;
944 const char *key;
945 const char *value;
946
947 r = sd_bus_message_read(m, "ss", &key, &value);
948 if (r < 0)
949 return synthetic_reply_method_errno(m, r, NULL);
950
951 s = strjoin(key, "=", value, NULL);
952 if (!s)
953 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
954
955 r = strv_extend(&args, s);
956 if (r < 0)
957 return synthetic_reply_method_errno(m, r, NULL);
958
959 r = sd_bus_message_exit_container(m);
960 if (r < 0)
961 return synthetic_reply_method_errno(m, r, NULL);
962 }
963
964 r = sd_bus_message_exit_container(m);
965 if (r < 0)
966 return synthetic_reply_method_errno(m, r, NULL);
967
968 if (!args)
969 return synthetic_reply_method_errno(m, -EINVAL, NULL);
970
971 r = sd_bus_message_new_method_call(
972 a,
973 &msg,
974 "org.freedesktop.systemd1",
975 "/org/freedesktop/systemd1",
976 "org.freedesktop.systemd1.Manager",
977 "SetEnvironment");
978 if (r < 0)
979 return synthetic_reply_method_errno(m, r, NULL);
980
981 r = sd_bus_message_append_strv(msg, args);
982 if (r < 0)
983 return synthetic_reply_method_errno(m, r, NULL);
984
985 r = sd_bus_call(a, msg, 0, NULL, NULL);
986 if (r < 0)
987 return synthetic_reply_method_errno(m, r, NULL);
988
989 return synthetic_reply_method_return(m, NULL);
990
991 } else {
992 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
993
994 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
995
996 return synthetic_reply_method_errno(m, r, &error);
997 }
998 }
999
1000 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, bool *got_hello) {
1001 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1002 bool is_hello;
1003 int r;
1004
1005 assert(a);
1006 assert(b);
1007 assert(m);
1008 assert(got_hello);
1009
1010 /* As reaction to hello we need to respond with two messages:
1011 * the callback reply and the NameAcquired for the unique
1012 * name, since hello is otherwise obsolete on kdbus. */
1013
1014 is_hello =
1015 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1016 streq_ptr(m->destination, "org.freedesktop.DBus");
1017
1018 if (!is_hello) {
1019
1020 if (*got_hello)
1021 return 0;
1022
1023 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1024 return -EIO;
1025 }
1026
1027 if (*got_hello) {
1028 log_error("Got duplicate hello, aborting.");
1029 return -EIO;
1030 }
1031
1032 if (!policy_check_hello(policy, ucred)) {
1033 log_error("Policy denied HELLO");
1034 return -EPERM;
1035 }
1036
1037 *got_hello = true;
1038
1039 if (!a->is_kernel)
1040 return 0;
1041
1042 r = sd_bus_message_new_method_return(m, &n);
1043 if (r < 0) {
1044 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1045 return r;
1046 }
1047
1048 r = sd_bus_message_append(n, "s", a->unique_name);
1049 if (r < 0) {
1050 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1051 return r;
1052 }
1053
1054 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1055 if (r < 0) {
1056 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1057 return r;
1058 }
1059
1060 r = bus_seal_synthetic_message(b, n);
1061 if (r < 0) {
1062 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1063 return r;
1064 }
1065
1066 r = sd_bus_send(b, n, NULL);
1067 if (r < 0) {
1068 log_error("Failed to send HELLO reply: %s", strerror(-r));
1069 return r;
1070 }
1071
1072 n = sd_bus_message_unref(n);
1073 r = sd_bus_message_new_signal(
1074 b,
1075 &n,
1076 "/org/freedesktop/DBus",
1077 "org.freedesktop.DBus",
1078 "NameAcquired");
1079 if (r < 0) {
1080 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1081 return r;
1082 }
1083
1084 r = sd_bus_message_append(n, "s", a->unique_name);
1085 if (r < 0) {
1086 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1087 return r;
1088 }
1089
1090 r = bus_message_append_sender(n, "org.freedesktop.DBus");
1091 if (r < 0) {
1092 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1093 return r;
1094 }
1095
1096 r = bus_seal_synthetic_message(b, n);
1097 if (r < 0) {
1098 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1099 return r;
1100 }
1101
1102 r = sd_bus_send(b, n, NULL);
1103 if (r < 0) {
1104 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1105 return r;
1106 }
1107
1108 return 1;
1109 }
1110
1111 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1112 char **well_known = NULL;
1113 sd_bus_creds *c;
1114 int r;
1115
1116 assert(a);
1117 assert(m);
1118
1119 if (!a->is_kernel)
1120 return 0;
1121
1122 /* We will change the sender of messages from the bus driver
1123 * so that they originate from the bus driver. This is a
1124 * speciality originating from dbus1, where the bus driver did
1125 * not have a unique id, but only the well-known name. */
1126
1127 c = sd_bus_message_get_creds(m);
1128 if (!c)
1129 return 0;
1130
1131 r = sd_bus_creds_get_well_known_names(c, &well_known);
1132 if (r < 0)
1133 return r;
1134
1135 if (strv_contains(well_known, "org.freedesktop.DBus"))
1136 m->sender = "org.freedesktop.DBus";
1137
1138 return 0;
1139 }
1140
1141 int main(int argc, char *argv[]) {
1142
1143 _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1144 sd_id128_t server_id;
1145 int r, in_fd, out_fd;
1146 bool got_hello = false;
1147 bool is_unix;
1148 struct ucred ucred = {};
1149 _cleanup_free_ char *peersec = NULL;
1150 Policy policy = {};
1151
1152 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1153 log_parse_environment();
1154 log_open();
1155
1156 r = parse_argv(argc, argv);
1157 if (r <= 0)
1158 goto finish;
1159
1160 r = policy_load(&policy, arg_configuration);
1161 if (r < 0) {
1162 log_error("Failed to load policy: %s", strerror(-r));
1163 goto finish;
1164 }
1165
1166 /* policy_dump(&policy); */
1167
1168 r = sd_listen_fds(0);
1169 if (r == 0) {
1170 in_fd = STDIN_FILENO;
1171 out_fd = STDOUT_FILENO;
1172 } else if (r == 1) {
1173 in_fd = SD_LISTEN_FDS_START;
1174 out_fd = SD_LISTEN_FDS_START;
1175 } else {
1176 log_error("Illegal number of file descriptors passed");
1177 goto finish;
1178 }
1179
1180 is_unix =
1181 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1182 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1183
1184 if (is_unix) {
1185 (void) getpeercred(in_fd, &ucred);
1186 (void) getpeersec(in_fd, &peersec);
1187 }
1188
1189 if (arg_drop_privileges) {
1190 const char *user = "systemd-bus-proxy";
1191 uid_t uid;
1192 gid_t gid;
1193
1194 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1195 if (r < 0) {
1196 log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1197 goto finish;
1198 }
1199
1200 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1201 if (r < 0)
1202 goto finish;
1203 }
1204
1205 names_hash = hashmap_new(&string_hash_ops);
1206 if (!names_hash) {
1207 log_oom();
1208 goto finish;
1209 }
1210
1211 r = sd_bus_new(&a);
1212 if (r < 0) {
1213 log_error("Failed to allocate bus: %s", strerror(-r));
1214 goto finish;
1215 }
1216
1217 r = sd_bus_set_description(a, "sd-proxy");
1218 if (r < 0) {
1219 log_error("Failed to set bus name: %s", strerror(-r));
1220 goto finish;
1221 }
1222
1223 r = sd_bus_set_address(a, arg_address);
1224 if (r < 0) {
1225 log_error("Failed to set address to connect to: %s", strerror(-r));
1226 goto finish;
1227 }
1228
1229 r = sd_bus_negotiate_fds(a, is_unix);
1230 if (r < 0) {
1231 log_error("Failed to set FD negotiation: %s", strerror(-r));
1232 goto finish;
1233 }
1234
1235 if (ucred.pid > 0) {
1236 a->fake_creds.pid = ucred.pid;
1237 a->fake_creds.uid = ucred.uid;
1238 a->fake_creds.gid = ucred.gid;
1239 a->fake_creds_valid = true;
1240 }
1241
1242 if (peersec) {
1243 a->fake_label = peersec;
1244 peersec = NULL;
1245 }
1246
1247 a->manual_peer_interface = true;
1248
1249 r = sd_bus_start(a);
1250 if (r < 0) {
1251 log_error("Failed to start bus client: %s", strerror(-r));
1252 goto finish;
1253 }
1254
1255 r = sd_bus_get_owner_id(a, &server_id);
1256 if (r < 0) {
1257 log_error("Failed to get server ID: %s", strerror(-r));
1258 goto finish;
1259 }
1260
1261 r = sd_bus_new(&b);
1262 if (r < 0) {
1263 log_error("Failed to allocate bus: %s", strerror(-r));
1264 goto finish;
1265 }
1266
1267 r = sd_bus_set_fd(b, in_fd, out_fd);
1268 if (r < 0) {
1269 log_error("Failed to set fds: %s", strerror(-r));
1270 goto finish;
1271 }
1272
1273 r = sd_bus_set_server(b, 1, server_id);
1274 if (r < 0) {
1275 log_error("Failed to set server mode: %s", strerror(-r));
1276 goto finish;
1277 }
1278
1279 r = sd_bus_negotiate_fds(b, is_unix);
1280 if (r < 0) {
1281 log_error("Failed to set FD negotiation: %s", strerror(-r));
1282 goto finish;
1283 }
1284
1285 r = sd_bus_set_anonymous(b, true);
1286 if (r < 0) {
1287 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1288 goto finish;
1289 }
1290
1291 b->manual_peer_interface = true;
1292
1293 r = sd_bus_start(b);
1294 if (r < 0) {
1295 log_error("Failed to start bus client: %s", strerror(-r));
1296 goto finish;
1297 }
1298
1299 r = rename_service(a, b);
1300 if (r < 0)
1301 log_debug("Failed to rename process: %s", strerror(-r));
1302
1303 if (a->is_kernel) {
1304 _cleanup_free_ char *match = NULL;
1305 const char *unique;
1306
1307 r = sd_bus_get_unique_name(a, &unique);
1308 if (r < 0) {
1309 log_error("Failed to get unique name: %s", strerror(-r));
1310 goto finish;
1311 }
1312
1313 match = strjoin("type='signal',"
1314 "sender='org.freedesktop.DBus',"
1315 "path='/org/freedesktop/DBus',"
1316 "interface='org.freedesktop.DBus',"
1317 "member='NameOwnerChanged',"
1318 "arg1='",
1319 unique,
1320 "'",
1321 NULL);
1322 if (!match) {
1323 log_oom();
1324 goto finish;
1325 }
1326
1327 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1328 if (r < 0) {
1329 log_error("Failed to add match for NameLost: %s", strerror(-r));
1330 goto finish;
1331 }
1332
1333 free(match);
1334 match = strjoin("type='signal',"
1335 "sender='org.freedesktop.DBus',"
1336 "path='/org/freedesktop/DBus',"
1337 "interface='org.freedesktop.DBus',"
1338 "member='NameOwnerChanged',"
1339 "arg2='",
1340 unique,
1341 "'",
1342 NULL);
1343 if (!match) {
1344 log_oom();
1345 goto finish;
1346 }
1347
1348 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1349 if (r < 0) {
1350 log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1351 goto finish;
1352 }
1353 }
1354
1355 for (;;) {
1356 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1357 int events_a, events_b, fd;
1358 uint64_t timeout_a, timeout_b, t;
1359 struct timespec _ts, *ts;
1360 struct pollfd *pollfd;
1361 int k;
1362
1363 if (got_hello) {
1364 r = sd_bus_process(a, &m);
1365 if (r < 0) {
1366 /* treat 'connection reset by peer' as clean exit condition */
1367 if (r == -ECONNRESET)
1368 r = 0;
1369 else
1370 log_error("Failed to process bus a: %s", strerror(-r));
1371
1372 goto finish;
1373 }
1374
1375 if (m) {
1376 /* We officially got EOF, let's quit */
1377 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1378 r = 0;
1379 goto finish;
1380 }
1381
1382 k = synthesize_name_acquired(a, b, m);
1383 if (k < 0) {
1384 r = k;
1385 log_error("Failed to synthesize message: %s", strerror(-r));
1386 goto finish;
1387 }
1388
1389 patch_sender(a, m);
1390
1391 k = sd_bus_send(b, m, NULL);
1392 if (k < 0) {
1393 if (k == -ECONNRESET)
1394 r = 0;
1395 else {
1396 r = k;
1397 log_error("Failed to send message: %s", strerror(-r));
1398 }
1399
1400 goto finish;
1401 }
1402 }
1403
1404 if (r > 0)
1405 continue;
1406 }
1407
1408 r = sd_bus_process(b, &m);
1409 if (r < 0) {
1410 /* treat 'connection reset by peer' as clean exit condition */
1411 if (r == -ECONNRESET)
1412 r = 0;
1413 else
1414 log_error("Failed to process bus b: %s", strerror(-r));
1415
1416 goto finish;
1417 }
1418
1419 if (m) {
1420 /* We officially got EOF, let's quit */
1421 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1422 r = 0;
1423 goto finish;
1424 }
1425
1426 k = process_hello(a, b, m, &policy, &ucred, &got_hello);
1427 if (k < 0) {
1428 r = k;
1429 log_error("Failed to process HELLO: %s", strerror(-r));
1430 goto finish;
1431 }
1432
1433 if (k > 0)
1434 r = k;
1435 else {
1436 k = process_policy(a, b, m);
1437 if (k < 0) {
1438 r = k;
1439 log_error("Failed to process policy: %s", strerror(-r));
1440 goto finish;
1441 }
1442
1443 k = process_driver(a, b, m);
1444 if (k < 0) {
1445 r = k;
1446 log_error("Failed to process driver calls: %s", strerror(-r));
1447 goto finish;
1448 }
1449
1450 if (k > 0)
1451 r = k;
1452 else {
1453 k = sd_bus_send(a, m, NULL);
1454 if (k < 0) {
1455 if (k == -ECONNRESET)
1456 r = 0;
1457 else {
1458 r = k;
1459 log_error("Failed to send message: %s", strerror(-r));
1460 }
1461
1462 goto finish;
1463 }
1464 }
1465 }
1466 }
1467
1468 if (r > 0)
1469 continue;
1470
1471 fd = sd_bus_get_fd(a);
1472 if (fd < 0) {
1473 log_error("Failed to get fd: %s", strerror(-r));
1474 goto finish;
1475 }
1476
1477 events_a = sd_bus_get_events(a);
1478 if (events_a < 0) {
1479 log_error("Failed to get events mask: %s", strerror(-r));
1480 goto finish;
1481 }
1482
1483 r = sd_bus_get_timeout(a, &timeout_a);
1484 if (r < 0) {
1485 log_error("Failed to get timeout: %s", strerror(-r));
1486 goto finish;
1487 }
1488
1489 events_b = sd_bus_get_events(b);
1490 if (events_b < 0) {
1491 log_error("Failed to get events mask: %s", strerror(-r));
1492 goto finish;
1493 }
1494
1495 r = sd_bus_get_timeout(b, &timeout_b);
1496 if (r < 0) {
1497 log_error("Failed to get timeout: %s", strerror(-r));
1498 goto finish;
1499 }
1500
1501 t = timeout_a;
1502 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1503 t = timeout_b;
1504
1505 if (t == (uint64_t) -1)
1506 ts = NULL;
1507 else {
1508 usec_t nw;
1509
1510 nw = now(CLOCK_MONOTONIC);
1511 if (t > nw)
1512 t -= nw;
1513 else
1514 t = 0;
1515
1516 ts = timespec_store(&_ts, t);
1517 }
1518
1519 pollfd = (struct pollfd[3]) {
1520 {.fd = fd, .events = events_a, },
1521 {.fd = in_fd, .events = events_b & POLLIN, },
1522 {.fd = out_fd, .events = events_b & POLLOUT, }
1523 };
1524
1525 r = ppoll(pollfd, 3, ts, NULL);
1526 if (r < 0) {
1527 log_error("ppoll() failed: %m");
1528 goto finish;
1529 }
1530 }
1531
1532 finish:
1533 sd_notify(false,
1534 "STOPPING=1\n"
1535 "STATUS=Shutting down.");
1536
1537 policy_free(&policy);
1538 strv_free(arg_configuration);
1539 hashmap_free(names_hash);
1540 free(arg_address);
1541
1542 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1543 }