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