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