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