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