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