chiark / gitweb /
bus-proxy: fix sd_bus_reply_*() usage
[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_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 (policy && !policy_check_own(policy, ucred->uid, ucred->gid, name))
833                         return synthetic_reply_method_errno(m, -EPERM, NULL);
834
835                 if ((flags & ~(BUS_NAME_ALLOW_REPLACEMENT|BUS_NAME_REPLACE_EXISTING|BUS_NAME_DO_NOT_QUEUE)) != 0)
836                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
837
838                 param = 0;
839                 if (flags & BUS_NAME_ALLOW_REPLACEMENT)
840                         param |= SD_BUS_NAME_ALLOW_REPLACEMENT;
841                 if (flags & BUS_NAME_REPLACE_EXISTING)
842                         param |= SD_BUS_NAME_REPLACE_EXISTING;
843                 if (!(flags & BUS_NAME_DO_NOT_QUEUE))
844                         param |= SD_BUS_NAME_QUEUE;
845
846                 r = set_put_strdup(owned_names, name);
847                 if (r < 0)
848                         return synthetic_reply_method_errno(m, r, NULL);
849
850                 r = sd_bus_request_name(a, name, param);
851                 if (r < 0) {
852                         if (r == -EALREADY)
853                                 return synthetic_reply_method_return(m, "u", BUS_NAME_ALREADY_OWNER);
854
855                         set_remove(owned_names, (char*) name);
856
857                         if (r == -EEXIST)
858                                 return synthetic_reply_method_return(m, "u", BUS_NAME_EXISTS);
859                         return synthetic_reply_method_errno(m, r, NULL);
860                 }
861
862                 in_queue = (r == 0);
863
864                 if (in_queue)
865                         return synthetic_reply_method_return(m, "u", BUS_NAME_IN_QUEUE);
866
867                 return synthetic_reply_method_return(m, "u", BUS_NAME_PRIMARY_OWNER);
868
869         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "StartServiceByName")) {
870                 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
871                 const char *name;
872                 uint32_t flags;
873
874                 if (!sd_bus_message_has_signature(m, "su"))
875                         return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
876
877                 r = sd_bus_message_read(m, "su", &name, &flags);
878                 if (r < 0)
879                         return synthetic_reply_method_errno(m, r, NULL);
880
881                 if (flags != 0)
882                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
883
884                 r = sd_bus_get_name_creds(a, name, 0, NULL);
885                 if (r >= 0 || streq(name, "org.freedesktop.DBus"))
886                         return synthetic_reply_method_return(m, "u", BUS_START_REPLY_ALREADY_RUNNING);
887                 if (r != -ESRCH)
888                         return synthetic_reply_method_errno(m, r, NULL);
889
890                 r = sd_bus_message_new_method_call(
891                                 a,
892                                 &msg,
893                                 name,
894                                 "/",
895                                 "org.freedesktop.DBus.Peer",
896                                 "Ping");
897                 if (r < 0)
898                         return synthetic_reply_method_errno(m, r, NULL);
899
900                 r = sd_bus_send(a, msg, NULL);
901                 if (r < 0)
902                         return synthetic_reply_method_errno(m, r, NULL);
903
904                 return synthetic_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS);
905
906         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "UpdateActivationEnvironment")) {
907                 _cleanup_bus_message_unref_ sd_bus_message *msg = NULL;
908                 _cleanup_strv_free_ char **args = NULL;
909
910                 if (!sd_bus_message_has_signature(m, "a{ss}"))
911                         return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
912
913                 r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}");
914                 if (r < 0)
915                         return synthetic_reply_method_errno(m, r, NULL);
916
917                 while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) {
918                         _cleanup_free_ char *s = NULL;
919                         const char *key;
920                         const char *value;
921
922                         r = sd_bus_message_read(m, "ss", &key, &value);
923                         if (r < 0)
924                                 return synthetic_reply_method_errno(m, r, NULL);
925
926                         s = strjoin(key, "=", value, NULL);
927                         if (!s)
928                                 return synthetic_reply_method_errno(m, -ENOMEM, NULL);
929
930                         r  = strv_extend(&args, s);
931                         if (r < 0)
932                                 return synthetic_reply_method_errno(m, r, NULL);
933
934                         r = sd_bus_message_exit_container(m);
935                         if (r < 0)
936                                 return synthetic_reply_method_errno(m, r, NULL);
937                 }
938
939                 r = sd_bus_message_exit_container(m);
940                 if (r < 0)
941                         return synthetic_reply_method_errno(m, r, NULL);
942
943                 if (!args)
944                         return synthetic_reply_method_errno(m, -EINVAL, NULL);
945
946                 r = sd_bus_message_new_method_call(
947                                 a,
948                                 &msg,
949                                 "org.freedesktop.systemd1",
950                                 "/org/freedesktop/systemd1",
951                                 "org.freedesktop.systemd1.Manager",
952                                 "SetEnvironment");
953                 if (r < 0)
954                         return synthetic_reply_method_errno(m, r, NULL);
955
956                 r = sd_bus_message_append_strv(msg, args);
957                 if (r < 0)
958                         return synthetic_reply_method_errno(m, r, NULL);
959
960                 r = sd_bus_call(a, msg, 0, NULL, NULL);
961                 if (r < 0)
962                         return synthetic_reply_method_errno(m, r, NULL);
963
964                return synthetic_reply_method_return(m, NULL);
965
966         } else {
967                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
968
969                 r = sd_bus_error_setf(&error, SD_BUS_ERROR_UNKNOWN_METHOD, "Unknown method '%s'.", m->member);
970
971                 return synthetic_reply_method_errno(m, r, &error);
972         }
973 }
974
975 static int handle_policy_error(sd_bus_message *m, int r) {
976         if (r == -ESRCH || r == -ENXIO)
977                 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
978
979         return r;
980 }
981
982 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
983         int r;
984
985         assert(from);
986         assert(to);
987         assert(m);
988
989         if (!policy)
990                 return 0;
991
992         if (from->is_kernel) {
993                 uid_t sender_uid = UID_INVALID;
994                 gid_t sender_gid = GID_INVALID;
995                 char **sender_names = NULL;
996                 bool granted = false;
997
998                 /* Driver messages are always OK */
999                 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
1000                         return 0;
1001
1002                 /* The message came from the kernel, and is sent to our legacy client. */
1003                 sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
1004
1005                 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
1006                 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
1007
1008                 /* First check whether the sender can send the message to our name */
1009                 if (set_isempty(owned_names)) {
1010                         if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member))
1011                                 granted = true;
1012                 } else {
1013                         Iterator i;
1014                         char *n;
1015
1016                         SET_FOREACH(n, owned_names, i)
1017                                 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member)) {
1018                                         granted = true;
1019                                         break;
1020                                 }
1021                 }
1022
1023                 if (granted) {
1024                         /* Then check whether us (the recipient) can recieve from the sender's name */
1025                         if (strv_isempty(sender_names)) {
1026                                 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1027                                         return 0;
1028                         } else {
1029                                 char **n;
1030
1031                                 STRV_FOREACH(n, sender_names) {
1032                                         if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member))
1033                                                 return 0;
1034                                 }
1035                         }
1036                 }
1037
1038                 /* Return an error back to the caller */
1039                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1040                         return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
1041
1042                 /* Return 1, indicating that the message shall not be processed any further */
1043                 return 1;
1044         }
1045
1046         if (to->is_kernel) {
1047                 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
1048                 uid_t destination_uid = UID_INVALID;
1049                 gid_t destination_gid = GID_INVALID;
1050                 const char *destination_unique = NULL;
1051                 char **destination_names = NULL;
1052                 bool granted = false;
1053
1054                 /* Driver messages are always OK */
1055                 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
1056                         return 0;
1057
1058                 /* The message came from the legacy client, and is sent to kdbus. */
1059                 if (m->destination) {
1060                         r = bus_get_name_creds_kdbus(to, m->destination,
1061                                                      SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
1062                                                      SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
1063                                                      true, &destination_creds);
1064                         if (r < 0)
1065                                 return handle_policy_error(m, r);
1066
1067                         r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
1068                         if (r < 0)
1069                                 return handle_policy_error(m, r);
1070
1071                         sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
1072
1073                         (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
1074                         (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
1075                 }
1076
1077                 /* First check if we (the sender) can send to this name */
1078                 if (strv_isempty(destination_names)) {
1079                         if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member))
1080                                 granted = true;
1081                 } else {
1082                         char **n;
1083
1084                         STRV_FOREACH(n, destination_names) {
1085                                 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member)) {
1086
1087                                         /* If we made a receiver decision,
1088                                            then remember which name's policy
1089                                            we used, and to which unique ID it
1090                                            mapped when we made the
1091                                            decision. Then, let's pass this to
1092                                            the kernel when sending the
1093                                            message, so that it refuses the
1094                                            operation should the name and
1095                                            unique ID not map to each other
1096                                            anymore. */
1097
1098                                         r = free_and_strdup(&m->destination_ptr, *n);
1099                                         if (r < 0)
1100                                                 return r;
1101
1102                                         r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
1103                                         if (r < 0)
1104                                                 break;
1105
1106                                         granted = true;
1107                                         break;
1108                                 }
1109                         }
1110                 }
1111
1112                 /* Then check if the recipient can receive from our name */
1113                 if (granted) {
1114                         if (set_isempty(owned_names)) {
1115                                 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member))
1116                                         return 0;
1117                         } else {
1118                                 Iterator i;
1119                                 char *n;
1120
1121                                 SET_FOREACH(n, owned_names, i)
1122                                         if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member))
1123                                                 return 0;
1124                         }
1125                 }
1126
1127                 /* Return an error back to the caller */
1128                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
1129                         return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
1130
1131                 /* Return 1, indicating that the message shall not be processed any further */
1132                 return 1;
1133         }
1134
1135         return 0;
1136 }
1137
1138 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
1139         _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
1140         bool is_hello;
1141         int r;
1142
1143         assert(a);
1144         assert(b);
1145         assert(m);
1146         assert(got_hello);
1147
1148         /* As reaction to hello we need to respond with two messages:
1149          * the callback reply and the NameAcquired for the unique
1150          * name, since hello is otherwise obsolete on kdbus. */
1151
1152         is_hello =
1153                 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
1154                 streq_ptr(m->destination, "org.freedesktop.DBus");
1155
1156         if (!is_hello) {
1157
1158                 if (*got_hello)
1159                         return 0;
1160
1161                 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
1162                 return -EIO;
1163         }
1164
1165         if (*got_hello) {
1166                 log_error("Got duplicate hello, aborting.");
1167                 return -EIO;
1168         }
1169
1170         *got_hello = true;
1171
1172         if (!a->is_kernel)
1173                 return 0;
1174
1175         r = sd_bus_message_new_method_return(m, &n);
1176         if (r < 0)
1177                 return log_error_errno(r, "Failed to generate HELLO reply: %m");
1178
1179         r = sd_bus_message_append(n, "s", a->unique_name);
1180         if (r < 0)
1181                 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
1182
1183         r = bus_message_append_sender(n, "org.freedesktop.DBus");
1184         if (r < 0)
1185                 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
1186
1187         r = bus_seal_synthetic_message(b, n);
1188         if (r < 0)
1189                 return log_error_errno(r, "Failed to seal HELLO reply: %m");
1190
1191         r = sd_bus_send(b, n, NULL);
1192         if (r < 0)
1193                 return log_error_errno(r, "Failed to send HELLO reply: %m");
1194
1195         n = sd_bus_message_unref(n);
1196         r = sd_bus_message_new_signal(
1197                         b,
1198                         &n,
1199                         "/org/freedesktop/DBus",
1200                         "org.freedesktop.DBus",
1201                         "NameAcquired");
1202         if (r < 0)
1203                 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
1204
1205         r = sd_bus_message_append(n, "s", a->unique_name);
1206         if (r < 0)
1207                 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
1208
1209         r = bus_message_append_sender(n, "org.freedesktop.DBus");
1210         if (r < 0)
1211                 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
1212
1213         r = bus_seal_synthetic_message(b, n);
1214         if (r < 0)
1215                 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
1216
1217         r = sd_bus_send(b, n, NULL);
1218         if (r < 0)
1219                 return log_error_errno(r, "Failed to send NameAcquired message: %m");
1220
1221         return 1;
1222 }
1223
1224 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1225         char **well_known = NULL;
1226         sd_bus_creds *c;
1227         int r;
1228
1229         assert(a);
1230         assert(m);
1231
1232         if (!a->is_kernel)
1233                 return 0;
1234
1235         /* We will change the sender of messages from the bus driver
1236          * so that they originate from the bus driver. This is a
1237          * speciality originating from dbus1, where the bus driver did
1238          * not have a unique id, but only the well-known name. */
1239
1240         c = sd_bus_message_get_creds(m);
1241         if (!c)
1242                 return 0;
1243
1244         r = sd_bus_creds_get_well_known_names(c, &well_known);
1245         if (r < 0)
1246                 return r;
1247
1248         if (strv_contains(well_known, "org.freedesktop.DBus"))
1249                 m->sender = "org.freedesktop.DBus";
1250
1251         return 0;
1252 }
1253
1254 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
1255 #ifdef HAVE_SMACK
1256         int r = 0, k;
1257
1258         if (!mac_smack_use())
1259                 return 0;
1260
1261         if (new_label && its_pid > 0)
1262                 r = mac_smack_apply_pid(its_pid, new_label);
1263
1264         k = drop_capability(CAP_MAC_ADMIN);
1265         return r < 0 ? r : k;
1266 #else
1267         return 0;
1268 #endif
1269 }
1270
1271 int main(int argc, char *argv[]) {
1272
1273         _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1274         sd_id128_t server_id;
1275         int r, in_fd, out_fd;
1276         bool got_hello = false;
1277         bool is_unix;
1278         struct ucred ucred = {};
1279         _cleanup_free_ char *peersec = NULL;
1280         Policy policy_buffer = {}, *policy = NULL;
1281         _cleanup_set_free_free_ Set *owned_names = NULL;
1282
1283         log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1284         log_parse_environment();
1285         log_open();
1286
1287         r = parse_argv(argc, argv);
1288         if (r <= 0)
1289                 goto finish;
1290
1291         r = sd_listen_fds(0);
1292         if (r == 0) {
1293                 in_fd = STDIN_FILENO;
1294                 out_fd = STDOUT_FILENO;
1295         } else if (r == 1) {
1296                 in_fd = SD_LISTEN_FDS_START;
1297                 out_fd = SD_LISTEN_FDS_START;
1298         } else {
1299                 log_error("Illegal number of file descriptors passed");
1300                 goto finish;
1301         }
1302
1303         is_unix =
1304                 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1305                 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1306
1307         if (is_unix) {
1308                 (void) getpeercred(in_fd, &ucred);
1309                 (void) getpeersec(in_fd, &peersec);
1310
1311                 r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
1312                 if (r < 0)
1313                         log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
1314         }
1315
1316         if (arg_drop_privileges) {
1317                 const char *user = "systemd-bus-proxy";
1318                 uid_t uid;
1319                 gid_t gid;
1320
1321                 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1322                 if (r < 0) {
1323                         log_error_errno(r, "Cannot resolve user name %s: %m", user);
1324                         goto finish;
1325                 }
1326
1327                 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1328                 if (r < 0)
1329                         goto finish;
1330         }
1331
1332         owned_names = set_new(&string_hash_ops);
1333         if (!owned_names) {
1334                 log_oom();
1335                 goto finish;
1336         }
1337
1338         r = sd_bus_new(&a);
1339         if (r < 0) {
1340                 log_error_errno(r, "Failed to allocate bus: %m");
1341                 goto finish;
1342         }
1343
1344         r = sd_bus_set_description(a, "sd-proxy");
1345         if (r < 0) {
1346                 log_error_errno(r, "Failed to set bus name: %m");
1347                 goto finish;
1348         }
1349
1350         r = sd_bus_set_address(a, arg_address);
1351         if (r < 0) {
1352                 log_error_errno(r, "Failed to set address to connect to: %m");
1353                 goto finish;
1354         }
1355
1356         r = sd_bus_negotiate_fds(a, is_unix);
1357         if (r < 0) {
1358                 log_error_errno(r, "Failed to set FD negotiation: %m");
1359                 goto finish;
1360         }
1361
1362         r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1363         if (r < 0) {
1364                 log_error_errno(r, "Failed to set credential negotiation: %m");
1365                 goto finish;
1366         }
1367
1368         if (ucred.pid > 0) {
1369                 a->fake_pids.pid = ucred.pid;
1370                 a->fake_pids_valid = true;
1371
1372                 a->fake_creds.uid = ucred.uid;
1373                 a->fake_creds.euid = UID_INVALID;
1374                 a->fake_creds.suid = UID_INVALID;
1375                 a->fake_creds.fsuid = UID_INVALID;
1376                 a->fake_creds.gid = ucred.gid;
1377                 a->fake_creds.egid = GID_INVALID;
1378                 a->fake_creds.sgid = GID_INVALID;
1379                 a->fake_creds.fsgid = GID_INVALID;
1380                 a->fake_creds_valid = true;
1381         }
1382
1383         if (peersec) {
1384                 a->fake_label = peersec;
1385                 peersec = NULL;
1386         }
1387
1388         a->manual_peer_interface = true;
1389
1390         r = sd_bus_start(a);
1391         if (r < 0) {
1392                 log_error_errno(r, "Failed to start bus client: %m");
1393                 goto finish;
1394         }
1395
1396         r = sd_bus_get_bus_id(a, &server_id);
1397         if (r < 0) {
1398                 log_error_errno(r, "Failed to get server ID: %m");
1399                 goto finish;
1400         }
1401
1402         if (a->is_kernel) {
1403                 if (!arg_configuration) {
1404                         const char *scope;
1405
1406                         r = sd_bus_get_scope(a, &scope);
1407                         if (r < 0) {
1408                                 log_error_errno(r, "Couldn't determine bus scope: %m");
1409                                 goto finish;
1410                         }
1411
1412                         if (streq(scope, "system"))
1413                                 arg_configuration = strv_new(
1414                                                 "/etc/dbus-1/system.conf",
1415                                                 "/etc/dbus-1/system.d/",
1416                                                 "/etc/dbus-1/system-local.conf",
1417                                                 NULL);
1418                         else if (streq(scope, "user"))
1419                                 arg_configuration = strv_new(
1420                                                 "/etc/dbus-1/session.conf",
1421                                                 "/etc/dbus-1/session.d/",
1422                                                 "/etc/dbus-1/session-local.conf",
1423                                                 NULL);
1424                         else {
1425                                 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
1426                                 goto finish;
1427                         }
1428
1429                         if (!arg_configuration) {
1430                                 r = log_oom();
1431                                 goto finish;
1432                         }
1433                 }
1434
1435                 r = policy_load(&policy_buffer, arg_configuration);
1436                 if (r < 0) {
1437                         log_error_errno(r, "Failed to load policy: %m");
1438                         goto finish;
1439                 }
1440
1441                 policy = &policy_buffer;
1442                 /* policy_dump(policy); */
1443
1444                 if (!policy_check_hello(policy, ucred.uid, ucred.gid)) {
1445                         r = log_error_errno(EPERM, "Policy denied connection.");
1446                         goto finish;
1447                 }
1448         }
1449
1450         r = sd_bus_new(&b);
1451         if (r < 0) {
1452                 log_error_errno(r, "Failed to allocate bus: %m");
1453                 goto finish;
1454         }
1455
1456         r = sd_bus_set_fd(b, in_fd, out_fd);
1457         if (r < 0) {
1458                 log_error_errno(r, "Failed to set fds: %m");
1459                 goto finish;
1460         }
1461
1462         r = sd_bus_set_server(b, 1, server_id);
1463         if (r < 0) {
1464                 log_error_errno(r, "Failed to set server mode: %m");
1465                 goto finish;
1466         }
1467
1468         r = sd_bus_negotiate_fds(b, is_unix);
1469         if (r < 0) {
1470                 log_error_errno(r, "Failed to set FD negotiation: %m");
1471                 goto finish;
1472         }
1473
1474         r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1475         if (r < 0) {
1476                 log_error_errno(r, "Failed to set credential negotiation: %m");
1477                 goto finish;
1478         }
1479
1480         r = sd_bus_set_anonymous(b, true);
1481         if (r < 0) {
1482                 log_error_errno(r, "Failed to set anonymous authentication: %m");
1483                 goto finish;
1484         }
1485
1486         b->manual_peer_interface = true;
1487
1488         r = sd_bus_start(b);
1489         if (r < 0) {
1490                 log_error_errno(r, "Failed to start bus client: %m");
1491                 goto finish;
1492         }
1493
1494         r = rename_service(a, b);
1495         if (r < 0)
1496                 log_debug_errno(r, "Failed to rename process: %m");
1497
1498         if (a->is_kernel) {
1499                 _cleanup_free_ char *match = NULL;
1500                 const char *unique;
1501
1502                 r = sd_bus_get_unique_name(a, &unique);
1503                 if (r < 0) {
1504                         log_error_errno(r, "Failed to get unique name: %m");
1505                         goto finish;
1506                 }
1507
1508                 match = strjoin("type='signal',"
1509                                 "sender='org.freedesktop.DBus',"
1510                                 "path='/org/freedesktop/DBus',"
1511                                 "interface='org.freedesktop.DBus',"
1512                                 "member='NameOwnerChanged',"
1513                                 "arg1='",
1514                                 unique,
1515                                 "'",
1516                                 NULL);
1517                 if (!match) {
1518                         log_oom();
1519                         goto finish;
1520                 }
1521
1522                 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1523                 if (r < 0) {
1524                         log_error_errno(r, "Failed to add match for NameLost: %m");
1525                         goto finish;
1526                 }
1527
1528                 free(match);
1529                 match = strjoin("type='signal',"
1530                                 "sender='org.freedesktop.DBus',"
1531                                 "path='/org/freedesktop/DBus',"
1532                                 "interface='org.freedesktop.DBus',"
1533                                 "member='NameOwnerChanged',"
1534                                 "arg2='",
1535                                 unique,
1536                                 "'",
1537                                 NULL);
1538                 if (!match) {
1539                         log_oom();
1540                         goto finish;
1541                 }
1542
1543                 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1544                 if (r < 0) {
1545                         log_error_errno(r, "Failed to add match for NameAcquired: %m");
1546                         goto finish;
1547                 }
1548         }
1549
1550         for (;;) {
1551                 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1552                 int events_a, events_b, fd;
1553                 uint64_t timeout_a, timeout_b, t;
1554                 struct timespec _ts, *ts;
1555                 struct pollfd *pollfd;
1556                 int k;
1557
1558                 if (got_hello) {
1559                         /* Read messages from bus, to pass them on to our client */
1560
1561                         r = sd_bus_process(a, &m);
1562                         if (r < 0) {
1563                                 /* treat 'connection reset by peer' as clean exit condition */
1564                                 if (r == -ECONNRESET)
1565                                         r = 0;
1566                                 else
1567                                         log_error_errno(r, "Failed to process bus a: %m");
1568
1569                                 goto finish;
1570                         }
1571
1572                         if (m) {
1573                                 bool processed = false;
1574
1575                                 /* We officially got EOF, let's quit */
1576                                 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1577                                         r = 0;
1578                                         goto finish;
1579                                 }
1580
1581                                 k = synthesize_name_acquired(a, b, m);
1582                                 if (k < 0) {
1583                                         r = k;
1584                                         log_error_errno(r, "Failed to synthesize message: %m");
1585                                         goto finish;
1586                                 }
1587
1588                                 patch_sender(a, m);
1589
1590                                 if (policy) {
1591                                         k = process_policy(a, b, m, policy, &ucred, owned_names);
1592                                         if (k < 0) {
1593                                                 r = k;
1594                                                 log_error_errno(r, "Failed to process policy: %m");
1595                                                 goto finish;
1596                                         } else if (k > 0) {
1597                                                 r = 1;
1598                                                 processed = true;
1599                                         }
1600                                 }
1601
1602                                 if (!processed) {
1603                                         k = sd_bus_send(b, m, NULL);
1604                                         if (k < 0) {
1605                                                 if (k == -ECONNRESET)
1606                                                         r = 0;
1607                                                 else {
1608                                                         r = k;
1609                                                         log_error_errno(r, "Failed to send message to client: %m");
1610                                                 }
1611
1612                                                 goto finish;
1613                                         } else
1614                                                 r = 1;
1615                                 }
1616                         }
1617
1618                         if (r > 0)
1619                                 continue;
1620                 }
1621
1622                 /* Read messages from our client, to pass them on to the bus */
1623                 r = sd_bus_process(b, &m);
1624                 if (r < 0) {
1625                         /* treat 'connection reset by peer' as clean exit condition */
1626                         if (r == -ECONNRESET)
1627                                 r = 0;
1628                         else
1629                                 log_error_errno(r, "Failed to process bus b: %m");
1630
1631                         goto finish;
1632                 }
1633
1634                 if (m) {
1635                         bool processed = false;
1636
1637                         /* We officially got EOF, let's quit */
1638                         if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1639                                 r = 0;
1640                                 goto finish;
1641                         }
1642
1643                         k = process_hello(a, b, m, &got_hello);
1644                         if (k < 0) {
1645                                 r = k;
1646                                 log_error_errno(r, "Failed to process HELLO: %m");
1647                                 goto finish;
1648                         } else if (k > 0) {
1649                                 processed = true;
1650                                 r = 1;
1651                         }
1652
1653                         if (!processed) {
1654                                 k = process_driver(a, b, m, policy, &ucred, owned_names);
1655                                 if (k < 0) {
1656                                         r = k;
1657                                         log_error_errno(r, "Failed to process driver calls: %m");
1658                                         goto finish;
1659                                 } else if (k > 0) {
1660                                         processed = true;
1661                                         r = 1;
1662                                 }
1663
1664                                 if (!processed) {
1665
1666                                         for (;;) {
1667                                                 if (policy) {
1668                                                         k = process_policy(b, a, m, policy, &ucred, owned_names);
1669                                                         if (k < 0) {
1670                                                                 r = k;
1671                                                                 log_error_errno(r, "Failed to process policy: %m");
1672                                                                 goto finish;
1673                                                         } else if (k > 0) {
1674                                                                 processed = true;
1675                                                                 r = 1;
1676                                                                 break;
1677                                                         }
1678                                                 }
1679
1680                                                 k = sd_bus_send(a, m, NULL);
1681                                                 if (k < 0) {
1682                                                         if (k == -EREMCHG)
1683                                                                 /* The name database changed since the policy check, hence let's check again */
1684                                                                 continue;
1685                                                         else if (k == -ECONNRESET)
1686                                                                 r = 0;
1687                                                         else {
1688                                                                 r = k;
1689                                                                 log_error_errno(r, "Failed to send message to bus: %m");
1690                                                         }
1691
1692                                                         goto finish;
1693                                                 } else
1694                                                         r = 1;
1695
1696                                                 break;
1697                                         }
1698                                 }
1699                         }
1700                 }
1701
1702                 if (r > 0)
1703                         continue;
1704
1705                 fd = sd_bus_get_fd(a);
1706                 if (fd < 0) {
1707                         log_error_errno(r, "Failed to get fd: %m");
1708                         goto finish;
1709                 }
1710
1711                 events_a = sd_bus_get_events(a);
1712                 if (events_a < 0) {
1713                         log_error_errno(r, "Failed to get events mask: %m");
1714                         goto finish;
1715                 }
1716
1717                 r = sd_bus_get_timeout(a, &timeout_a);
1718                 if (r < 0) {
1719                         log_error_errno(r, "Failed to get timeout: %m");
1720                         goto finish;
1721                 }
1722
1723                 events_b = sd_bus_get_events(b);
1724                 if (events_b < 0) {
1725                         log_error_errno(r, "Failed to get events mask: %m");
1726                         goto finish;
1727                 }
1728
1729                 r = sd_bus_get_timeout(b, &timeout_b);
1730                 if (r < 0) {
1731                         log_error_errno(r, "Failed to get timeout: %m");
1732                         goto finish;
1733                 }
1734
1735                 t = timeout_a;
1736                 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1737                         t = timeout_b;
1738
1739                 if (t == (uint64_t) -1)
1740                         ts = NULL;
1741                 else {
1742                         usec_t nw;
1743
1744                         nw = now(CLOCK_MONOTONIC);
1745                         if (t > nw)
1746                                 t -= nw;
1747                         else
1748                                 t = 0;
1749
1750                         ts = timespec_store(&_ts, t);
1751                 }
1752
1753                 pollfd = (struct pollfd[3]) {
1754                         {.fd = fd,     .events = events_a,           },
1755                         {.fd = in_fd,  .events = events_b & POLLIN,  },
1756                         {.fd = out_fd, .events = events_b & POLLOUT, }
1757                 };
1758
1759                 r = ppoll(pollfd, 3, ts, NULL);
1760                 if (r < 0) {
1761                         log_error_errno(errno, "ppoll() failed: %m");
1762                         goto finish;
1763                 }
1764         }
1765
1766 finish:
1767         sd_notify(false,
1768                   "STOPPING=1\n"
1769                   "STATUS=Shutting down.");
1770
1771         policy_free(&policy_buffer);
1772         strv_free(arg_configuration);
1773         free(arg_address);
1774
1775         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1776 }