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