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