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