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