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