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