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