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