chiark / gitweb /
bus-proxyd: make policy checks optional
[elogind.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 synthetic_driver_send(sd_bus *b, sd_bus_message *m) {
315         int r;
316
317         assert(b);
318         assert(m);
319
320         r = bus_message_append_sender(m, "org.freedesktop.DBus");
321         if (r < 0)
322                 return r;
323
324         r = bus_seal_synthetic_message(b, m);
325         if (r < 0)
326                 return r;
327
328         return sd_bus_send(b, m, NULL);
329 }
330
331 static int synthetic_reply_method_error(sd_bus_message *call, const sd_bus_error *e) {
332         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
333         int r;
334
335         assert(call);
336
337         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
338                 return 0;
339
340         r = sd_bus_message_new_method_error(call, &m, e);
341         if (r < 0)
342                 return r;
343
344         return synthetic_driver_send(call->bus, m);
345 }
346
347 static int synthetic_reply_method_errno(sd_bus_message *call, int error, const sd_bus_error *p) {
348
349         _cleanup_bus_error_free_ sd_bus_error berror = SD_BUS_ERROR_NULL;
350
351         assert(call);
352
353         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
354                 return 0;
355
356         if (sd_bus_error_is_set(p))
357                 return synthetic_reply_method_error(call, p);
358
359         sd_bus_error_set_errno(&berror, error);
360
361         return synthetic_reply_method_error(call, &berror);
362 }
363
364 static int synthetic_reply_method_return(sd_bus_message *call, const char *types, ...) {
365         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
366         int r;
367
368         assert(call);
369
370         if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
371                 return 0;
372
373         r = sd_bus_message_new_method_return(call, &m);
374         if (r < 0)
375                 return r;
376
377         if (!isempty(types)) {
378                 va_list ap;
379
380                 va_start(ap, types);
381                 r = bus_message_append_ap(m, types, ap);
382                 va_end(ap);
383                 if (r < 0)
384                         return r;
385         }
386
387         return synthetic_driver_send(call->bus, m);
388 }
389
390 static int synthetic_reply_return_strv(sd_bus_message *call, char **l) {
391         _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
392         int r;
393
394         assert(call);
395
396         r = sd_bus_message_new_method_return(call, &m);
397         if (r < 0)
398                 return synthetic_reply_method_errno(call, r, NULL);
399
400         r = sd_bus_message_append_strv(m, l);
401         if (r < 0)
402                 return synthetic_reply_method_errno(call, r, NULL);
403
404         return synthetic_driver_send(call->bus, m);
405 }
406
407 static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
408         _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL;
409         int r;
410
411         assert(bus);
412         assert(name);
413         assert(_creds);
414
415         assert_return(service_name_is_valid(name), -EINVAL);
416
417         r = sd_bus_get_name_creds(bus, name, mask, &c);
418         if (r == -ESRCH || r == -ENXIO)
419                 return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name);
420         if (r < 0)
421                 return r;
422
423         if ((c->mask & mask) != mask)
424                 return -ENOTSUP;
425
426         *_creds = c;
427         c = NULL;
428
429         return 0;
430 }
431
432 static int get_creds_by_message(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) {
433         const char *name;
434         int r;
435
436         assert(bus);
437         assert(m);
438         assert(_creds);
439
440         r = sd_bus_message_read(m, "s", &name);
441         if (r < 0)
442                 return r;
443
444         return get_creds_by_name(bus, name, mask, _creds, error);
445 }
446
447 static int peer_is_privileged(sd_bus *bus, sd_bus_message *m) {
448         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
449         uid_t uid;
450         int r;
451
452         r = get_creds_by_message(bus, m, SD_BUS_CREDS_UID, &creds, NULL);
453         if (r < 0)
454                 return r;
455
456         r = sd_bus_creds_get_uid(creds, &uid);
457         if (r < 0)
458                 return r;
459
460         r = sd_bus_creds_has_effective_cap(creds, CAP_SYS_ADMIN);
461         if (r > 0)
462                 return true;
463
464         if (uid == getuid())
465                 return true;
466
467         return false;
468 }
469
470 static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
471         int r;
472         char **names_strv;
473
474         assert(a);
475         assert(b);
476         assert(m);
477
478         if (!policy)
479                 return 0;
480
481         if (b->is_kernel) {
482
483                 /* The message came from the kernel, and is sent to our legacy client. */
484                 r = sd_bus_creds_get_well_known_names(&m->creds, &names_strv);
485                 if (r < 0)
486                         return r;
487
488 /*
489                 if (!policy_check_recv(policy, ucred, names_hash, m->header->type, m->path, m->interface, m->member))
490                         return -EPERM;
491
492                 if (!policy_check_send(policy, ucred, names_strv, m->header->type, m->path, m->interface, m->member))
493                         return -EPERM;
494 */
495         } else {
496
497
498
499
500         }
501
502         return 0;
503 }
504
505 static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred) {
506         int r;
507
508         assert(a);
509         assert(b);
510         assert(m);
511
512         if (!a->is_kernel)
513                 return 0;
514
515         if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus"))
516                 return 0;
517
518         if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Introspectable", "Introspect")) {
519                 if (0 && !isempty(sd_bus_message_get_signature(m, true))) {
520                         _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
521
522                         r = sd_bus_error_setf(&error, SD_BUS_ERROR_INVALID_ARGS, "Expected no parameters");
523
524                         return synthetic_reply_method_errno(m, r, &error);
525                 }
526
527                 return synthetic_reply_method_return(m, "s",
528                         "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" "
529                           "\"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\">\n"
530                         "<node>\n"
531                         " <interface name=\"org.freedesktop.DBus.Introspectable\">\n"
532                         "  <method name=\"Introspect\">\n"
533                         "   <arg name=\"data\" type=\"s\" direction=\"out\"/>\n"
534                         "  </method>\n"
535                         " </interface>\n"
536                         " <interface name=\"org.freedesktop.DBus\">\n"
537                         "  <method name=\"AddMatch\">\n"
538                         "   <arg type=\"s\" direction=\"in\"/>\n"
539                         "  </method>\n"
540                         "  <method name=\"RemoveMatch\">\n"
541                         "   <arg type=\"s\" direction=\"in\"/>\n"
542                         "  </method>\n"
543                         "  <method name=\"GetConnectionSELinuxSecurityContext\">\n"
544                         "   <arg type=\"s\" direction=\"in\"/>\n"
545                         "   <arg type=\"ay\" direction=\"out\"/>\n"
546                         "  </method>\n"
547                         "  <method name=\"GetConnectionUnixProcessID\">\n"
548                         "   <arg type=\"s\" direction=\"in\"/>\n"
549                         "   <arg type=\"u\" direction=\"out\"/>\n"
550                         "  </method>\n"
551                         "  <method name=\"GetConnectionUnixUser\">\n"
552                         "   <arg type=\"s\" direction=\"in\"/>\n"
553                         "   <arg type=\"u\" direction=\"out\"/>\n"
554                         "  </method>\n"
555                         "  <method name=\"GetId\">\n"
556                         "   <arg type=\"s\" direction=\"out\"/>\n"
557                         "  </method>\n"
558                         "  <method name=\"GetNameOwner\">\n"
559                         "   <arg type=\"s\" direction=\"in\"/>\n"
560                         "   <arg type=\"s\" direction=\"out\"/>\n"
561                         "  </method>\n"
562                         "  <method name=\"Hello\">\n"
563                         "   <arg type=\"s\" direction=\"out\"/>\n"
564                         "  </method>\n"
565                         "  <method name=\"ListActivatableNames\">\n"
566                         "   <arg type=\"as\" direction=\"out\"/>\n"
567                         "  </method>\n"
568                         "  <method name=\"ListNames\">\n"
569                         "   <arg type=\"as\" direction=\"out\"/>\n"
570                         "  </method>\n"
571                         "  <method name=\"ListQueuedOwners\">\n"
572                         "   <arg type=\"s\" direction=\"in\"/>\n"
573                         "   <arg type=\"as\" direction=\"out\"/>\n"
574                         "  </method>\n"
575                         "  <method name=\"NameHasOwner\">\n"
576                         "   <arg type=\"s\" direction=\"in\"/>\n"
577                         "   <arg type=\"b\" direction=\"out\"/>\n"
578                         "  </method>\n"
579                         "  <method name=\"ReleaseName\">\n"
580                         "   <arg type=\"s\" direction=\"in\"/>\n"
581                         "   <arg type=\"u\" direction=\"out\"/>\n"
582                         "  </method>\n"
583                         "  <method name=\"ReloadConfig\">\n"
584                         "  </method>\n"
585                         "  <method name=\"RequestName\">\n"
586                         "   <arg type=\"s\" direction=\"in\"/>\n"
587                         "   <arg type=\"u\" direction=\"in\"/>\n"
588                         "   <arg type=\"u\" direction=\"out\"/>\n"
589                         "  </method>\n"
590                         "  <method name=\"StartServiceByName\">\n"
591                         "   <arg type=\"s\" direction=\"in\"/>\n"
592                         "   <arg type=\"u\" direction=\"in\"/>\n"
593                         "   <arg type=\"u\" direction=\"out\"/>\n"
594                         "  </method>\n"
595                         "  <method name=\"UpdateActivationEnvironment\">\n"
596                         "   <arg type=\"a{ss}\" direction=\"in\"/>\n"
597                         "  </method>\n"
598                         "  <signal name=\"NameAcquired\">\n"
599                         "   <arg type=\"s\"/>\n"
600                         "  </signal>\n"
601                         "  <signal name=\"NameLost\">\n"
602                         "   <arg type=\"s\"/>\n"
603                         "  </signal>\n"
604                         "  <signal name=\"NameOwnerChanged\">\n"
605                         "   <arg type=\"s\"/>\n"
606                         "   <arg type=\"s\"/>\n"
607                         "   <arg type=\"s\"/>\n"
608                         "  </signal>\n"
609                         " </interface>\n"
610                         "</node>\n");
611
612         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "AddMatch")) {
613                 const char *match;
614
615                 r = sd_bus_message_read(m, "s", &match);
616                 if (r < 0)
617                         return synthetic_reply_method_errno(m, r, NULL);
618
619                 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
620                 if (r < 0)
621                         return synthetic_reply_method_errno(m, r, NULL);
622
623                 return synthetic_reply_method_return(m, NULL);
624
625         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RemoveMatch")) {
626                 const char *match;
627
628                 r = sd_bus_message_read(m, "s", &match);
629                 if (r < 0)
630                         return synthetic_reply_method_errno(m, r, NULL);
631
632                 r = bus_remove_match_by_string(a, match, NULL, NULL);
633                 if (r == 0)
634                         return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule not found"));
635                 if (r < 0)
636                         return synthetic_reply_method_errno(m, r, NULL);
637
638                 return synthetic_reply_method_return(m, NULL);
639
640         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
641                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
642                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
643
644                 r = get_creds_by_message(a, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
645                 if (r < 0)
646                         return synthetic_reply_method_errno(m, r, &error);
647
648                 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
649
650         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
651                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
652                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
653
654                 r = get_creds_by_message(a, m, SD_BUS_CREDS_PID, &creds, &error);
655                 if (r < 0)
656                         return synthetic_reply_method_errno(m, r, &error);
657
658                 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
659
660         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
661                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
662                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
663
664                 r = get_creds_by_message(a, m, SD_BUS_CREDS_UID, &creds, &error);
665                 if (r < 0)
666                         return synthetic_reply_method_errno(m, r, &error);
667
668                 return synthetic_reply_method_return(m, "u", (uint32_t) creds->uid);
669
670         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
671                 sd_id128_t server_id;
672                 char buf[SD_ID128_STRING_MAX];
673
674                 r = sd_bus_get_owner_id(a, &server_id);
675                 if (r < 0)
676                         return synthetic_reply_method_errno(m, r, NULL);
677
678                 return synthetic_reply_method_return(m, "s", sd_id128_to_string(server_id, buf));
679
680         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetNameOwner")) {
681                 const char *name;
682                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
683                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
684
685                 r = sd_bus_message_read(m, "s", &name);
686                 if (r < 0)
687                         return synthetic_reply_method_errno(m, r, NULL);
688
689                 if (streq(name, "org.freedesktop.DBus"))
690                         return synthetic_reply_method_return(m, "s", "org.freedesktop.DBus");
691
692                 r = get_creds_by_name(a, name, SD_BUS_CREDS_UNIQUE_NAME, &creds, &error);
693                 if (r < 0)
694                         return synthetic_reply_method_errno(m, r, &error);
695
696                 return synthetic_reply_method_return(m, "s", creds->unique_name);
697
698         /* "Hello" is handled in process_hello() */
699
700         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
701                 _cleanup_strv_free_ char **names = NULL;
702
703                 r = sd_bus_list_names(a, NULL, &names);
704                 if (r < 0)
705                         return synthetic_reply_method_errno(m, r, NULL);
706
707                 /* Let's sort the names list to make it stable */
708                 strv_sort(names);
709
710                 return synthetic_reply_return_strv(m, names);
711
712         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
713                 _cleanup_strv_free_ char **names = NULL;
714
715                 r = sd_bus_list_names(a, &names, NULL);
716                 if (r < 0)
717                         return synthetic_reply_method_errno(m, r, NULL);
718
719                 r = strv_extend(&names, "org.freedesktop.DBus");
720                 if (r < 0)
721                         return synthetic_reply_method_errno(m, r, NULL);
722
723                 /* Let's sort the names list to make it stable */
724                 strv_sort(names);
725
726                 return synthetic_reply_return_strv(m, names);
727
728         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
729                 struct kdbus_cmd_name_list cmd = {};
730                 struct kdbus_name_list *name_list;
731                 struct kdbus_cmd_free cmd_free;
732                 struct kdbus_name_info *name;
733                 _cleanup_strv_free_ char **owners = NULL;
734                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
735                 char *arg0;
736                 int err = 0;
737
738                 r = sd_bus_message_read(m, "s", &arg0);
739                 if (r < 0)
740                         return synthetic_reply_method_errno(m, r, NULL);
741
742                 if (!service_name_is_valid(arg0))
743                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
744
745                 r = sd_bus_get_name_creds(a, arg0, 0, NULL);
746                 if (r == -ESRCH || r == -ENXIO) {
747                         sd_bus_error_setf(&error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Could not get owners of name '%s': no such name.", arg0);
748                         return synthetic_reply_method_errno(m, r, &error);
749                 }
750                 if (r < 0)
751                         return synthetic_reply_method_errno(m, r, NULL);
752
753                 cmd.flags = KDBUS_NAME_LIST_QUEUED;
754                 r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
755                 if (r < 0)
756                         return synthetic_reply_method_errno(m, -errno, NULL);
757
758                 name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
759
760                 KDBUS_ITEM_FOREACH(name, name_list, names) {
761                         const char *entry_name = NULL;
762                         struct kdbus_item *item;
763                         char *n;
764
765                         KDBUS_ITEM_FOREACH(item, name, items)
766                                 if (item->type == KDBUS_ITEM_OWNED_NAME)
767                                         entry_name = item->name.name;
768
769                         if (!streq_ptr(entry_name, arg0))
770                                 continue;
771
772                         if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
773                                 err  = -ENOMEM;
774                                 break;
775                         }
776
777                         r = strv_consume(&owners, n);
778                         if (r < 0) {
779                                 err = r;
780                                 break;
781                         }
782                 }
783
784                 cmd_free.flags = 0;
785                 cmd_free.offset = cmd.offset;
786
787                 r = ioctl(a->input_fd, KDBUS_CMD_FREE, &cmd_free);
788                 if (r < 0)
789                         return synthetic_reply_method_errno(m, r, NULL);
790
791                 if (err < 0)
792                         return synthetic_reply_method_errno(m, err, NULL);
793
794                 return synthetic_reply_return_strv(m, owners);
795
796         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
797                 const char *name;
798
799                 r = sd_bus_message_read(m, "s", &name);
800                 if (r < 0)
801                         return synthetic_reply_method_errno(m, r, NULL);
802
803                 if (!service_name_is_valid(name))
804                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
805
806                 if (streq(name, "org.freedesktop.DBus"))
807                         return synthetic_reply_method_return(m, "b", true);
808
809                 r = sd_bus_get_name_creds(a, name, 0, NULL);
810                 if (r < 0 && r != -ESRCH && r != -ENXIO)
811                         return synthetic_reply_method_errno(m, r, NULL);
812
813                 return synthetic_reply_method_return(m, "b", r >= 0);
814
815         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReleaseName")) {
816                 const char *name;
817
818                 r = sd_bus_message_read(m, "s", &name);
819                 if (r < 0)
820                         return synthetic_reply_method_errno(m, r, NULL);
821
822                 if (!service_name_is_valid(name))
823                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
824
825                 r = sd_bus_release_name(a, name);
826                 if (r < 0) {
827                         if (r == -ESRCH)
828                                 return synthetic_reply_method_return(m, "u", BUS_NAME_NON_EXISTENT);
829                         if (r == -EADDRINUSE)
830                                 return synthetic_reply_method_return(m, "u", BUS_NAME_NOT_OWNER);
831
832                         return synthetic_reply_method_errno(m, r, NULL);
833                 }
834
835                 hashmap_remove(names_hash, name);
836
837                 return synthetic_reply_method_return(m, "u", BUS_NAME_RELEASED);
838
839         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ReloadConfig")) {
840                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
841
842                 r = sd_bus_error_setf(&error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m));
843
844                 return synthetic_reply_method_errno(m, r, &error);
845
846         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "RequestName")) {
847                 const char *name;
848                 uint32_t flags, param;
849                 bool in_queue;
850
851                 r = sd_bus_message_read(m, "su", &name, &flags);
852                 if (r < 0)
853                         return synthetic_reply_method_errno(m, r, NULL);
854
855                 if (policy && !policy_check_own(policy, ucred, name))
856                         return synthetic_reply_method_errno(m, -EPERM, NULL);
857
858                 if (!service_name_is_valid(name))
859                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
860                 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
861                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
862
863                 param = 0;
864                 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
865                         param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
866                 if (flags & BUS_NAME_REPLACE_EXISTING)
867                         param |= SD_BUS_NAME_REPLACE_EXISTING;
868                 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
869                         param |= SD_BUS_NAME_QUEUE;
870
871                 r = sd_bus_request_name(a, name, param);
872                 if (r < 0) {
873                         if (r == -EEXIST)
874                                 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
875                         if (r == -EALREADY)
876                                 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
877                         return synthetic_reply_method_errno(m, r, NULL);
878                 }
879
880                 in_queue = (r == 0);
881
882                 r = hashmap_put(names_hash, name, NULL);
883                 if (r < 0)
884                         return synthetic_reply_method_errno(m, r, NULL);
885
886                 if (in_queue)
887                         return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
888
889                 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
890
891         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
892                 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
893                 const char *name;
894                 uint32_t flags;
895
896                 r = sd_bus_message_read(m, "su", &name, &flags);
897                 if (r < 0)
898                         return synthetic_reply_method_errno(m, r, NULL);
899
900                 if (!service_name_is_valid(name))
901                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
902                 if (flags != 0)
903                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
904
905                 r = sd_bus_get_name_creds(a, name, 0, NULL);
906                 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
907                         return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
908                 if (r != -ESRCH)
909                         return synthetic_reply_method_errno(m, r, NULL);
910
911                 r = sd_bus_message_new_method_call(
912                                 a,
913                                 &msg,
914                                 name,
915                                 "/",
916                                 "org.freedesktop.DBus.Peer",
917                                 "Ping");
918                 if (r < 0)
919                         return synthetic_reply_method_errno(m, r, NULL);
920
921                 r = sd_bus_send(a, msg, NULL);
922                 if (r < 0)
923                         return synthetic_reply_method_errno(m, r, NULL);
924
925                 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
926
927         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
928                 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
929                 _cleanup_strv_free_ char **args = NULL;
930
931                 if (!peer_is_privileged(a, m))
932                         return synthetic_reply_method_errno(m, -EPERM, NULL);
933
934                 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
935                 if (r < 0)
936                         return synthetic_reply_method_errno(m, r, NULL);
937
938                 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
939                         _cleanup_free_ char *s = NULL;
940                         const char *key;
941                         const char *value;
942
943                         r = sd_bus_message_read(m, "ss", &key, &value);
944                         if (r < 0)
945                                 return synthetic_reply_method_errno(m, r, NULL);
946
947                         s = strjoin(key, "=", value, NULL);
948                         if (!s)
949                                 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
950
951                         r  = strv_extend(&args, s);
952                         if (r < 0)
953                                 return synthetic_reply_method_errno(m, r, NULL);
954
955                         r = sd_bus_message_exit_container(m);
956                         if (r < 0)
957                                 return synthetic_reply_method_errno(m, r, NULL);
958                 }
959
960                 r = sd_bus_message_exit_container(m);
961                 if (r < 0)
962                         return synthetic_reply_method_errno(m, r, NULL);
963
964                 if (!args)
965                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
966
967                 r = sd_bus_message_new_method_call(
968                                 a,
969                                 &msg,
970                                 "org.freedesktop.systemd1",
971                                 "/org/freedesktop/systemd1",
972                                 "org.freedesktop.systemd1.Manager",
973                                 "SetEnvironment");
974                 if (r < 0)
975                         return synthetic_reply_method_errno(m, r, NULL);
976
977                 r = sd_bus_message_append_strv(msg, args);
978                 if (r < 0)
979                         return synthetic_reply_method_errno(m, r, NULL);
980
981                 r = sd_bus_call(a, msg, 0, NULL, NULL);
982                 if (r < 0)
983                         return synthetic_reply_method_errno(m, r, NULL);
984
985                return synthetic_reply_method_return(m, NULL);
986
987         } else {
988                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
989
990                 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
991
992                 return synthetic_reply_method_errno(m, r, &error);
993         }
994 }
995
996 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, Policy *policy, const struct ucred *ucred, bool *got_hello) {
997         _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
998         bool is_hello;
999         int r;
1000
1001         assert(a);
1002         assert(b);
1003         assert(m);
1004         assert(got_hello);
1005
1006         /* As reaction to hello we need to respond with two messages:
1007          * the callback reply and the NameAcquired for the unique
1008          * name, since hello is otherwise obsolete on kdbus. */
1009
1010         is_hello =
1011                 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1012                 streq_ptr(m->destination, "org.freedesktop.DBus");
1013
1014         if (!is_hello) {
1015
1016                 if (*got_hello)
1017                         return 0;
1018
1019                 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1020                 return -EIO;
1021         }
1022
1023         if (*got_hello) {
1024                 log_error("Got duplicate hello, aborting.");
1025                 return -EIO;
1026         }
1027
1028         if (policy && !policy_check_hello(policy, ucred)) {
1029                 log_error("Policy denied HELLO");
1030                 return -EPERM;
1031         }
1032
1033         *got_hello = true;
1034
1035         if (!a->is_kernel)
1036                 return 0;
1037
1038         r = sd_bus_message_new_method_return(m, &n);
1039         if (r < 0) {
1040                 log_error("Failed to generate HELLO reply: %s", strerror(-r));
1041                 return r;
1042         }
1043
1044         r = sd_bus_message_append(n, "s", a->unique_name);
1045         if (r < 0) {
1046                 log_error("Failed to append unique name to HELLO reply: %s", strerror(-r));
1047                 return r;
1048         }
1049
1050         r = bus_message_append_sender(n, "org.freedesktop.DBus");
1051         if (r < 0) {
1052                 log_error("Failed to append sender to HELLO reply: %s", strerror(-r));
1053                 return r;
1054         }
1055
1056         r = bus_seal_synthetic_message(b, n);
1057         if (r < 0) {
1058                 log_error("Failed to seal HELLO reply: %s", strerror(-r));
1059                 return r;
1060         }
1061
1062         r = sd_bus_send(b, n, NULL);
1063         if (r < 0) {
1064                 log_error("Failed to send HELLO reply: %s", strerror(-r));
1065                 return r;
1066         }
1067
1068         n = sd_bus_message_unref(n);
1069         r = sd_bus_message_new_signal(
1070                         b,
1071                         &n,
1072                         "/org/freedesktop/DBus",
1073                         "org.freedesktop.DBus",
1074                         "NameAcquired");
1075         if (r < 0) {
1076                 log_error("Failed to allocate initial NameAcquired message: %s", strerror(-r));
1077                 return r;
1078         }
1079
1080         r = sd_bus_message_append(n, "s", a->unique_name);
1081         if (r < 0) {
1082                 log_error("Failed to append unique name to NameAcquired message: %s", strerror(-r));
1083                 return r;
1084         }
1085
1086         r = bus_message_append_sender(n, "org.freedesktop.DBus");
1087         if (r < 0) {
1088                 log_error("Failed to append sender to NameAcquired message: %s", strerror(-r));
1089                 return r;
1090         }
1091
1092         r = bus_seal_synthetic_message(b, n);
1093         if (r < 0) {
1094                 log_error("Failed to seal NameAcquired message: %s", strerror(-r));
1095                 return r;
1096         }
1097
1098         r = sd_bus_send(b, n, NULL);
1099         if (r < 0) {
1100                 log_error("Failed to send NameAcquired message: %s", strerror(-r));
1101                 return r;
1102         }
1103
1104         return 1;
1105 }
1106
1107 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1108         char **well_known = NULL;
1109         sd_bus_creds *c;
1110         int r;
1111
1112         assert(a);
1113         assert(m);
1114
1115         if (!a->is_kernel)
1116                 return 0;
1117
1118         /* We will change the sender of messages from the bus driver
1119          * so that they originate from the bus driver. This is a
1120          * speciality originating from dbus1, where the bus driver did
1121          * not have a unique id, but only the well-known name. */
1122
1123         c = sd_bus_message_get_creds(m);
1124         if (!c)
1125                 return 0;
1126
1127         r = sd_bus_creds_get_well_known_names(c, &well_known);
1128         if (r < 0)
1129                 return r;
1130
1131         if (strv_contains(well_known, "org.freedesktop.DBus"))
1132                 m->sender = "org.freedesktop.DBus";
1133
1134         return 0;
1135 }
1136
1137 int main(int argc, char *argv[]) {
1138
1139         _cleanup_bus_creds_unref_ sd_bus_creds *bus_creds = NULL;
1140         _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1141         sd_id128_t server_id;
1142         int r, in_fd, out_fd;
1143         bool got_hello = false;
1144         bool is_unix;
1145         struct ucred ucred = {};
1146         _cleanup_free_ char *peersec = NULL;
1147         Policy policy = {};
1148
1149         log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1150         log_parse_environment();
1151         log_open();
1152
1153         r = parse_argv(argc, argv);
1154         if (r <= 0)
1155                 goto finish;
1156
1157         r = policy_load(&policy, arg_configuration);
1158         if (r < 0) {
1159                 log_error("Failed to load policy: %s", strerror(-r));
1160                 goto finish;
1161         }
1162
1163         /* policy_dump(&policy); */
1164
1165         r = sd_listen_fds(0);
1166         if (r == 0) {
1167                 in_fd = STDIN_FILENO;
1168                 out_fd = STDOUT_FILENO;
1169         } else if (r == 1) {
1170                 in_fd = SD_LISTEN_FDS_START;
1171                 out_fd = SD_LISTEN_FDS_START;
1172         } else {
1173                 log_error("Illegal number of file descriptors passed");
1174                 goto finish;
1175         }
1176
1177         is_unix =
1178                 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1179                 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1180
1181         if (is_unix) {
1182                 (void) getpeercred(in_fd, &ucred);
1183                 (void) getpeersec(in_fd, &peersec);
1184         }
1185
1186         if (arg_drop_privileges) {
1187                 const char *user = "systemd-bus-proxy";
1188                 uid_t uid;
1189                 gid_t gid;
1190
1191                 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1192                 if (r < 0) {
1193                         log_error("Cannot resolve user name %s: %s", user, strerror(-r));
1194                         goto finish;
1195                 }
1196
1197                 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1198                 if (r < 0)
1199                         goto finish;
1200         }
1201
1202         names_hash = hashmap_new(&string_hash_ops);
1203         if (!names_hash) {
1204                 log_oom();
1205                 goto finish;
1206         }
1207
1208         r = sd_bus_new(&a);
1209         if (r < 0) {
1210                 log_error("Failed to allocate bus: %s", strerror(-r));
1211                 goto finish;
1212         }
1213
1214         r = sd_bus_set_description(a, "sd-proxy");
1215         if (r < 0) {
1216                 log_error("Failed to set bus name: %s", strerror(-r));
1217                 goto finish;
1218         }
1219
1220         r = sd_bus_set_address(a, arg_address);
1221         if (r < 0) {
1222                 log_error("Failed to set address to connect to: %s", strerror(-r));
1223                 goto finish;
1224         }
1225
1226         r = sd_bus_negotiate_fds(a, is_unix);
1227         if (r < 0) {
1228                 log_error("Failed to set FD negotiation: %s", strerror(-r));
1229                 goto finish;
1230         }
1231
1232         if (ucred.pid > 0) {
1233                 a->fake_creds.pid = ucred.pid;
1234                 a->fake_creds.uid = ucred.uid;
1235                 a->fake_creds.gid = ucred.gid;
1236                 a->fake_creds_valid = true;
1237         }
1238
1239         if (peersec) {
1240                 a->fake_label = peersec;
1241                 peersec = NULL;
1242         }
1243
1244         a->manual_peer_interface = true;
1245
1246         r = sd_bus_start(a);
1247         if (r < 0) {
1248                 log_error("Failed to start bus client: %s", strerror(-r));
1249                 goto finish;
1250         }
1251
1252         r = sd_bus_get_owner_id(a, &server_id);
1253         if (r < 0) {
1254                 log_error("Failed to get server ID: %s", strerror(-r));
1255                 goto finish;
1256         }
1257
1258         r = sd_bus_get_owner_creds(a, SD_BUS_CREDS_UID, &bus_creds);
1259         if (r < 0) {
1260                 log_error("Failed to get bus creds: %s", strerror(-r));
1261                 goto finish;
1262         }
1263
1264         r = sd_bus_new(&b);
1265         if (r < 0) {
1266                 log_error("Failed to allocate bus: %s", strerror(-r));
1267                 goto finish;
1268         }
1269
1270         r = sd_bus_set_fd(b, in_fd, out_fd);
1271         if (r < 0) {
1272                 log_error("Failed to set fds: %s", strerror(-r));
1273                 goto finish;
1274         }
1275
1276         r = sd_bus_set_server(b, 1, server_id);
1277         if (r < 0) {
1278                 log_error("Failed to set server mode: %s", strerror(-r));
1279                 goto finish;
1280         }
1281
1282         r = sd_bus_negotiate_fds(b, is_unix);
1283         if (r < 0) {
1284                 log_error("Failed to set FD negotiation: %s", strerror(-r));
1285                 goto finish;
1286         }
1287
1288         r = sd_bus_set_anonymous(b, true);
1289         if (r < 0) {
1290                 log_error("Failed to set anonymous authentication: %s", strerror(-r));
1291                 goto finish;
1292         }
1293
1294         b->manual_peer_interface = true;
1295
1296         r = sd_bus_start(b);
1297         if (r < 0) {
1298                 log_error("Failed to start bus client: %s", strerror(-r));
1299                 goto finish;
1300         }
1301
1302         r = rename_service(a, b);
1303         if (r < 0)
1304                 log_debug("Failed to rename process: %s", strerror(-r));
1305
1306         if (a->is_kernel) {
1307                 _cleanup_free_ char *match = NULL;
1308                 const char *unique;
1309
1310                 r = sd_bus_get_unique_name(a, &unique);
1311                 if (r < 0) {
1312                         log_error("Failed to get unique name: %s", strerror(-r));
1313                         goto finish;
1314                 }
1315
1316                 match = strjoin("type='signal',"
1317                                 "sender='org.freedesktop.DBus',"
1318                                 "path='/org/freedesktop/DBus',"
1319                                 "interface='org.freedesktop.DBus',"
1320                                 "member='NameOwnerChanged',"
1321                                 "arg1='",
1322                                 unique,
1323                                 "'",
1324                                 NULL);
1325                 if (!match) {
1326                         log_oom();
1327                         goto finish;
1328                 }
1329
1330                 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1331                 if (r < 0) {
1332                         log_error("Failed to add match for NameLost: %s", strerror(-r));
1333                         goto finish;
1334                 }
1335
1336                 free(match);
1337                 match = strjoin("type='signal',"
1338                                 "sender='org.freedesktop.DBus',"
1339                                 "path='/org/freedesktop/DBus',"
1340                                 "interface='org.freedesktop.DBus',"
1341                                 "member='NameOwnerChanged',"
1342                                 "arg2='",
1343                                 unique,
1344                                 "'",
1345                                 NULL);
1346                 if (!match) {
1347                         log_oom();
1348                         goto finish;
1349                 }
1350
1351                 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1352                 if (r < 0) {
1353                         log_error("Failed to add match for NameAcquired: %s", strerror(-r));
1354                         goto finish;
1355                 }
1356         }
1357
1358         for (;;) {
1359                 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1360                 int events_a, events_b, fd;
1361                 uint64_t timeout_a, timeout_b, t;
1362                 struct timespec _ts, *ts;
1363                 struct pollfd *pollfd;
1364                 int k;
1365
1366                 if (got_hello) {
1367                         r = sd_bus_process(a, &m);
1368                         if (r < 0) {
1369                                 /* treat 'connection reset by peer' as clean exit condition */
1370                                 if (r == -ECONNRESET)
1371                                         r = 0;
1372                                 else
1373                                         log_error("Failed to process bus a: %s", strerror(-r));
1374
1375                                 goto finish;
1376                         }
1377
1378                         if (m) {
1379                                 /* We officially got EOF, let's quit */
1380                                 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1381                                         r = 0;
1382                                         goto finish;
1383                                 }
1384
1385                                 k = synthesize_name_acquired(a, b, m);
1386                                 if (k < 0) {
1387                                         r = k;
1388                                         log_error("Failed to synthesize message: %s", strerror(-r));
1389                                         goto finish;
1390                                 }
1391
1392                                 patch_sender(a, m);
1393
1394                                 k = sd_bus_send(b, m, NULL);
1395                                 if (k < 0) {
1396                                         if (k == -ECONNRESET)
1397                                                 r = 0;
1398                                         else {
1399                                                 r = k;
1400                                                 log_error("Failed to send message: %s", strerror(-r));
1401                                         }
1402
1403                                         goto finish;
1404                                 }
1405                         }
1406
1407                         if (r > 0)
1408                                 continue;
1409                 }
1410
1411                 r = sd_bus_process(b, &m);
1412                 if (r < 0) {
1413                         /* treat 'connection reset by peer' as clean exit condition */
1414                         if (r == -ECONNRESET)
1415                                 r = 0;
1416                         else
1417                                 log_error("Failed to process bus b: %s", strerror(-r));
1418
1419                         goto finish;
1420                 }
1421
1422                 if (m) {
1423                         Policy *p = NULL;
1424                         uid_t uid;
1425
1426                         assert_se(sd_bus_creds_get_uid(bus_creds, &uid) == 0);
1427
1428                         if (uid == 0 || uid != ucred.uid)
1429                                 p = &policy;
1430
1431                         /* We officially got EOF, let's quit */
1432                         if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1433                                 r = 0;
1434                                 goto finish;
1435                         }
1436
1437                         k = process_hello(a, b, m, p, &ucred, &got_hello);
1438                         if (k < 0) {
1439                                 r = k;
1440                                 log_error("Failed to process HELLO: %s", strerror(-r));
1441                                 goto finish;
1442                         }
1443
1444                         if (k > 0)
1445                                 r = k;
1446                         else {
1447                                 k = process_driver(a, b, m, p, &ucred);
1448                                 if (k < 0) {
1449                                         r = k;
1450                                         log_error("Failed to process driver calls: %s", strerror(-r));
1451                                         goto finish;
1452                                 }
1453
1454                                 if (k > 0)
1455                                         r = k;
1456                                 else {
1457                                         k = process_policy(a, b, m, &policy, &ucred);
1458                                         if (k < 0) {
1459                                                 r = k;
1460                                                 log_error("Failed to process policy: %s", strerror(-r));
1461                                                 goto finish;
1462                                         }
1463
1464                                         k = sd_bus_send(a, m, NULL);
1465                                         if (k < 0) {
1466                                                 if (k == -ECONNRESET)
1467                                                         r = 0;
1468                                                 else {
1469
1470                                                 k = process_policy(a, b, m, p, &ucred);
1471                                                 if (k < 0) {
1472                                                         r = k;
1473                                                         log_error("Failed to send message: %s", strerror(-r));
1474                                                 }
1475
1476                                                 goto finish;
1477                                         }
1478                                 }
1479                         }
1480                 }
1481
1482                 if (r > 0)
1483                         continue;
1484
1485                 fd = sd_bus_get_fd(a);
1486                 if (fd < 0) {
1487                         log_error("Failed to get fd: %s", strerror(-r));
1488                         goto finish;
1489                 }
1490
1491                 events_a = sd_bus_get_events(a);
1492                 if (events_a < 0) {
1493                         log_error("Failed to get events mask: %s", strerror(-r));
1494                         goto finish;
1495                 }
1496
1497                 r = sd_bus_get_timeout(a, &timeout_a);
1498                 if (r < 0) {
1499                         log_error("Failed to get timeout: %s", strerror(-r));
1500                         goto finish;
1501                 }
1502
1503                 events_b = sd_bus_get_events(b);
1504                 if (events_b < 0) {
1505                         log_error("Failed to get events mask: %s", strerror(-r));
1506                         goto finish;
1507                 }
1508
1509                 r = sd_bus_get_timeout(b, &timeout_b);
1510                 if (r < 0) {
1511                         log_error("Failed to get timeout: %s", strerror(-r));
1512                         goto finish;
1513                 }
1514
1515                 t = timeout_a;
1516                 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1517                         t = timeout_b;
1518
1519                 if (t == (uint64_t) -1)
1520                         ts = NULL;
1521                 else {
1522                         usec_t nw;
1523
1524                         nw = now(CLOCK_MONOTONIC);
1525                         if (t > nw)
1526                                 t -= nw;
1527                         else
1528                                 t = 0;
1529
1530                         ts = timespec_store(&_ts, t);
1531                 }
1532
1533                 pollfd = (struct pollfd[3]) {
1534                         {.fd = fd,     .events = events_a,           },
1535                         {.fd = in_fd,  .events = events_b & POLLIN,  },
1536                         {.fd = out_fd, .events = events_b & POLLOUT, }
1537                 };
1538
1539                 r = ppoll(pollfd, 3, ts, NULL);
1540                 if (r < 0) {
1541                         log_error("ppoll() failed: %m");
1542                         goto finish;
1543                 }
1544         }
1545
1546 finish:
1547         sd_notify(false,
1548                   "STOPPING=1\n"
1549                   "STATUS=Shutting down.");
1550
1551         policy_free(&policy);
1552         strv_free(arg_configuration);
1553         hashmap_free(names_hash);
1554         free(arg_address);
1555
1556         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1557 }