chiark / gitweb /
sd-bus: add new call sd_bus_get_scope() for querying whether one is connected to...
[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_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_t) -1;
973                 gid_t sender_gid = (gid_t) -1;
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_t) -1;
1030                 gid_t destination_gid = (gid_t) -1;
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                 log_error_errno(r, "Failed to generate HELLO reply: %m");
1160                 return r;
1161         }
1162
1163         r = sd_bus_message_append(n, "s", a->unique_name);
1164         if (r < 0) {
1165                 log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
1166                 return r;
1167         }
1168
1169         r = bus_message_append_sender(n, "org.freedesktop.DBus");
1170         if (r < 0) {
1171                 log_error_errno(r, "Failed to append sender to HELLO reply: %m");
1172                 return r;
1173         }
1174
1175         r = bus_seal_synthetic_message(b, n);
1176         if (r < 0) {
1177                 log_error_errno(r, "Failed to seal HELLO reply: %m");
1178                 return r;
1179         }
1180
1181         r = sd_bus_send(b, n, NULL);
1182         if (r < 0) {
1183                 log_error_errno(r, "Failed to send HELLO reply: %m");
1184                 return r;
1185         }
1186
1187         n = sd_bus_message_unref(n);
1188         r = sd_bus_message_new_signal(
1189                         b,
1190                         &n,
1191                         "/org/freedesktop/DBus",
1192                         "org.freedesktop.DBus",
1193                         "NameAcquired");
1194         if (r < 0) {
1195                 log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
1196                 return r;
1197         }
1198
1199         r = sd_bus_message_append(n, "s", a->unique_name);
1200         if (r < 0) {
1201                 log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
1202                 return r;
1203         }
1204
1205         r = bus_message_append_sender(n, "org.freedesktop.DBus");
1206         if (r < 0) {
1207                 log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
1208                 return r;
1209         }
1210
1211         r = bus_seal_synthetic_message(b, n);
1212         if (r < 0) {
1213                 log_error_errno(r, "Failed to seal NameAcquired message: %m");
1214                 return r;
1215         }
1216
1217         r = sd_bus_send(b, n, NULL);
1218         if (r < 0) {
1219                 log_error_errno(r, "Failed to send NameAcquired message: %m");
1220                 return r;
1221         }
1222
1223         return 1;
1224 }
1225
1226 static int patch_sender(sd_bus *a, sd_bus_message *m) {
1227         char **well_known = NULL;
1228         sd_bus_creds *c;
1229         int r;
1230
1231         assert(a);
1232         assert(m);
1233
1234         if (!a->is_kernel)
1235                 return 0;
1236
1237         /* We will change the sender of messages from the bus driver
1238          * so that they originate from the bus driver. This is a
1239          * speciality originating from dbus1, where the bus driver did
1240          * not have a unique id, but only the well-known name. */
1241
1242         c = sd_bus_message_get_creds(m);
1243         if (!c)
1244                 return 0;
1245
1246         r = sd_bus_creds_get_well_known_names(c, &well_known);
1247         if (r < 0)
1248                 return r;
1249
1250         if (strv_contains(well_known, "org.freedesktop.DBus"))
1251                 m->sender = "org.freedesktop.DBus";
1252
1253         return 0;
1254 }
1255
1256 int main(int argc, char *argv[]) {
1257
1258         _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
1259         sd_id128_t server_id;
1260         int r, in_fd, out_fd;
1261         bool got_hello = false;
1262         bool is_unix;
1263         struct ucred ucred = {};
1264         _cleanup_free_ char *peersec = NULL;
1265         Policy policy_buffer = {}, *policy = NULL;
1266         _cleanup_set_free_free_ Set *owned_names = NULL;
1267
1268         log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
1269         log_parse_environment();
1270         log_open();
1271
1272         r = parse_argv(argc, argv);
1273         if (r <= 0)
1274                 goto finish;
1275
1276         r = sd_listen_fds(0);
1277         if (r == 0) {
1278                 in_fd = STDIN_FILENO;
1279                 out_fd = STDOUT_FILENO;
1280         } else if (r == 1) {
1281                 in_fd = SD_LISTEN_FDS_START;
1282                 out_fd = SD_LISTEN_FDS_START;
1283         } else {
1284                 log_error("Illegal number of file descriptors passed");
1285                 goto finish;
1286         }
1287
1288         is_unix =
1289                 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
1290                 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
1291
1292         if (is_unix) {
1293                 (void) getpeercred(in_fd, &ucred);
1294                 (void) getpeersec(in_fd, &peersec);
1295         }
1296
1297         if (arg_drop_privileges) {
1298                 const char *user = "systemd-bus-proxy";
1299                 uid_t uid;
1300                 gid_t gid;
1301
1302                 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
1303                 if (r < 0) {
1304                         log_error_errno(r, "Cannot resolve user name %s: %m", user);
1305                         goto finish;
1306                 }
1307
1308                 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
1309                 if (r < 0)
1310                         goto finish;
1311         }
1312
1313         owned_names = set_new(&string_hash_ops);
1314         if (!owned_names) {
1315                 log_oom();
1316                 goto finish;
1317         }
1318
1319         r = sd_bus_new(&a);
1320         if (r < 0) {
1321                 log_error_errno(r, "Failed to allocate bus: %m");
1322                 goto finish;
1323         }
1324
1325         r = sd_bus_set_description(a, "sd-proxy");
1326         if (r < 0) {
1327                 log_error_errno(r, "Failed to set bus name: %m");
1328                 goto finish;
1329         }
1330
1331         r = sd_bus_set_address(a, arg_address);
1332         if (r < 0) {
1333                 log_error_errno(r, "Failed to set address to connect to: %m");
1334                 goto finish;
1335         }
1336
1337         r = sd_bus_negotiate_fds(a, is_unix);
1338         if (r < 0) {
1339                 log_error_errno(r, "Failed to set FD negotiation: %m");
1340                 goto finish;
1341         }
1342
1343         r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1344         if (r < 0) {
1345                 log_error_errno(r, "Failed to set credential negotiation: %m");
1346                 goto finish;
1347         }
1348
1349         if (ucred.pid > 0) {
1350                 a->fake_pids.pid = ucred.pid;
1351                 a->fake_pids_valid = true;
1352
1353                 a->fake_creds.uid = ucred.uid;
1354                 a->fake_creds.euid = (uid_t) -1;
1355                 a->fake_creds.suid = (uid_t) -1;
1356                 a->fake_creds.fsuid = (uid_t) -1;
1357                 a->fake_creds.gid = ucred.gid;
1358                 a->fake_creds.egid = (gid_t) -1;
1359                 a->fake_creds.sgid = (gid_t) -1;
1360                 a->fake_creds.fsgid = (gid_t) -1;
1361                 a->fake_creds_valid = true;
1362         }
1363
1364         if (peersec) {
1365                 a->fake_label = peersec;
1366                 peersec = NULL;
1367         }
1368
1369         a->manual_peer_interface = true;
1370
1371         r = sd_bus_start(a);
1372         if (r < 0) {
1373                 log_error_errno(r, "Failed to start bus client: %m");
1374                 goto finish;
1375         }
1376
1377         r = sd_bus_get_owner_id(a, &server_id);
1378         if (r < 0) {
1379                 log_error_errno(r, "Failed to get server ID: %m");
1380                 goto finish;
1381         }
1382
1383         if (a->is_kernel) {
1384                 _cleanup_bus_creds_unref_ sd_bus_creds *bus_creds = NULL;
1385                 uid_t bus_uid;
1386
1387                 r = sd_bus_get_owner_creds(a, SD_BUS_CREDS_UID, &bus_creds);
1388                 if (r < 0) {
1389                         log_error_errno(r, "Failed to get bus creds: %m");
1390                         goto finish;
1391                 }
1392
1393                 r = sd_bus_creds_get_uid(bus_creds, &bus_uid);
1394                 if (r < 0) {
1395                         log_error_errno(r, "Failed to get bus owner UID: %m");
1396                         goto finish;
1397                 }
1398
1399                 if (bus_uid == 0) {
1400                         /* We only enforce the old XML policy on
1401                          * kernel busses owned by root users. */
1402
1403                         r = policy_load(&policy_buffer, arg_configuration);
1404                         if (r < 0) {
1405                                 log_error_errno(r, "Failed to load policy: %m");
1406                                 goto finish;
1407                         }
1408
1409                         if (!policy_check_hello(&policy_buffer, ucred.uid, ucred.gid)) {
1410                                 log_error("Policy denied connection");
1411                                 r = -EPERM;
1412                                 goto finish;
1413                         }
1414
1415                         policy_dump(&policy_buffer);
1416                         policy = &policy_buffer;
1417                 }
1418         }
1419
1420         r = sd_bus_new(&b);
1421         if (r < 0) {
1422                 log_error_errno(r, "Failed to allocate bus: %m");
1423                 goto finish;
1424         }
1425
1426         r = sd_bus_set_fd(b, in_fd, out_fd);
1427         if (r < 0) {
1428                 log_error_errno(r, "Failed to set fds: %m");
1429                 goto finish;
1430         }
1431
1432         r = sd_bus_set_server(b, 1, server_id);
1433         if (r < 0) {
1434                 log_error_errno(r, "Failed to set server mode: %m");
1435                 goto finish;
1436         }
1437
1438         r = sd_bus_negotiate_fds(b, is_unix);
1439         if (r < 0) {
1440                 log_error_errno(r, "Failed to set FD negotiation: %m");
1441                 goto finish;
1442         }
1443
1444         r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
1445         if (r < 0) {
1446                 log_error_errno(r, "Failed to set credential negotiation: %m");
1447                 goto finish;
1448         }
1449
1450         r = sd_bus_set_anonymous(b, true);
1451         if (r < 0) {
1452                 log_error_errno(r, "Failed to set anonymous authentication: %m");
1453                 goto finish;
1454         }
1455
1456         b->manual_peer_interface = true;
1457
1458         r = sd_bus_start(b);
1459         if (r < 0) {
1460                 log_error_errno(r, "Failed to start bus client: %m");
1461                 goto finish;
1462         }
1463
1464         r = rename_service(a, b);
1465         if (r < 0)
1466                 log_debug_errno(r, "Failed to rename process: %m");
1467
1468         if (a->is_kernel) {
1469                 _cleanup_free_ char *match = NULL;
1470                 const char *unique;
1471
1472                 r = sd_bus_get_unique_name(a, &unique);
1473                 if (r < 0) {
1474                         log_error_errno(r, "Failed to get unique name: %m");
1475                         goto finish;
1476                 }
1477
1478                 match = strjoin("type='signal',"
1479                                 "sender='org.freedesktop.DBus',"
1480                                 "path='/org/freedesktop/DBus',"
1481                                 "interface='org.freedesktop.DBus',"
1482                                 "member='NameOwnerChanged',"
1483                                 "arg1='",
1484                                 unique,
1485                                 "'",
1486                                 NULL);
1487                 if (!match) {
1488                         log_oom();
1489                         goto finish;
1490                 }
1491
1492                 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1493                 if (r < 0) {
1494                         log_error_errno(r, "Failed to add match for NameLost: %m");
1495                         goto finish;
1496                 }
1497
1498                 free(match);
1499                 match = strjoin("type='signal',"
1500                                 "sender='org.freedesktop.DBus',"
1501                                 "path='/org/freedesktop/DBus',"
1502                                 "interface='org.freedesktop.DBus',"
1503                                 "member='NameOwnerChanged',"
1504                                 "arg2='",
1505                                 unique,
1506                                 "'",
1507                                 NULL);
1508                 if (!match) {
1509                         log_oom();
1510                         goto finish;
1511                 }
1512
1513                 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
1514                 if (r < 0) {
1515                         log_error_errno(r, "Failed to add match for NameAcquired: %m");
1516                         goto finish;
1517                 }
1518         }
1519
1520         for (;;) {
1521                 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
1522                 int events_a, events_b, fd;
1523                 uint64_t timeout_a, timeout_b, t;
1524                 struct timespec _ts, *ts;
1525                 struct pollfd *pollfd;
1526                 int k;
1527
1528                 if (got_hello) {
1529                         /* Read messages from bus, to pass them on to our client */
1530
1531                         r = sd_bus_process(a, &m);
1532                         if (r < 0) {
1533                                 /* treat 'connection reset by peer' as clean exit condition */
1534                                 if (r == -ECONNRESET)
1535                                         r = 0;
1536                                 else
1537                                         log_error_errno(r, "Failed to process bus a: %m");
1538
1539                                 goto finish;
1540                         }
1541
1542                         if (m) {
1543                                 bool processed = false;
1544
1545                                 /* We officially got EOF, let's quit */
1546                                 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1547                                         r = 0;
1548                                         goto finish;
1549                                 }
1550
1551                                 k = synthesize_name_acquired(a, b, m);
1552                                 if (k < 0) {
1553                                         r = k;
1554                                         log_error_errno(r, "Failed to synthesize message: %m");
1555                                         goto finish;
1556                                 }
1557
1558                                 patch_sender(a, m);
1559
1560                                 if (policy) {
1561                                         k = process_policy(a, b, m, policy, &ucred, owned_names);
1562                                         if (k < 0) {
1563                                                 r = k;
1564                                                 log_error_errno(r, "Failed to process policy: %m");
1565                                                 goto finish;
1566                                         } else if (k > 0) {
1567                                                 r = 1;
1568                                                 processed = true;
1569                                         }
1570                                 }
1571
1572                                 if (!processed) {
1573                                         k = sd_bus_send(b, m, NULL);
1574                                         if (k < 0) {
1575                                                 if (k == -ECONNRESET)
1576                                                         r = 0;
1577                                                 else {
1578                                                         r = k;
1579                                                         log_error_errno(r, "Failed to send message to client: %m");
1580                                                 }
1581
1582                                                 goto finish;
1583                                         } else
1584                                                 r = 1;
1585                                 }
1586                         }
1587
1588                         if (r > 0)
1589                                 continue;
1590                 }
1591
1592                 /* Read messages from our client, to pass them on to the bus */
1593                 r = sd_bus_process(b, &m);
1594                 if (r < 0) {
1595                         /* treat 'connection reset by peer' as clean exit condition */
1596                         if (r == -ECONNRESET)
1597                                 r = 0;
1598                         else
1599                                 log_error_errno(r, "Failed to process bus b: %m");
1600
1601                         goto finish;
1602                 }
1603
1604                 if (m) {
1605                         bool processed = false;
1606
1607                         /* We officially got EOF, let's quit */
1608                         if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
1609                                 r = 0;
1610                                 goto finish;
1611                         }
1612
1613                         k = process_hello(a, b, m, &got_hello);
1614                         if (k < 0) {
1615                                 r = k;
1616                                 log_error_errno(r, "Failed to process HELLO: %m");
1617                                 goto finish;
1618                         } else if (k > 0) {
1619                                 processed = true;
1620                                 r = 1;
1621                         }
1622
1623                         if (!processed) {
1624                                 k = process_driver(a, b, m, policy, &ucred, owned_names);
1625                                 if (k < 0) {
1626                                         r = k;
1627                                         log_error_errno(r, "Failed to process driver calls: %m");
1628                                         goto finish;
1629                                 } else if (k > 0) {
1630                                         processed = true;
1631                                         r = 1;
1632                                 }
1633
1634                                 if (!processed) {
1635
1636                                         for (;;) {
1637                                                 if (policy) {
1638                                                         k = process_policy(b, a, m, policy, &ucred, owned_names);
1639                                                         if (k < 0) {
1640                                                                 r = k;
1641                                                                 log_error_errno(r, "Failed to process policy: %m");
1642                                                                 goto finish;
1643                                                         } else if (k > 0) {
1644                                                                 processed = true;
1645                                                                 r = 1;
1646                                                                 break;
1647                                                         }
1648                                                 }
1649
1650                                                 k = sd_bus_send(a, m, NULL);
1651                                                 if (k < 0) {
1652                                                         if (k == -EREMCHG)
1653                                                                 /* The name database changed since the policy check, hence let's check again */
1654                                                                 continue;
1655                                                         else if (k == -ECONNRESET)
1656                                                                 r = 0;
1657                                                         else {
1658                                                                 r = k;
1659                                                                 log_error_errno(r, "Failed to send message to bus: %m");
1660                                                         }
1661
1662                                                         goto finish;
1663                                                 } else
1664                                                         r = 1;
1665
1666                                                 break;
1667                                         }
1668                                 }
1669                         }
1670                 }
1671
1672                 if (r > 0)
1673                         continue;
1674
1675                 fd = sd_bus_get_fd(a);
1676                 if (fd < 0) {
1677                         log_error_errno(r, "Failed to get fd: %m");
1678                         goto finish;
1679                 }
1680
1681                 events_a = sd_bus_get_events(a);
1682                 if (events_a < 0) {
1683                         log_error_errno(r, "Failed to get events mask: %m");
1684                         goto finish;
1685                 }
1686
1687                 r = sd_bus_get_timeout(a, &timeout_a);
1688                 if (r < 0) {
1689                         log_error_errno(r, "Failed to get timeout: %m");
1690                         goto finish;
1691                 }
1692
1693                 events_b = sd_bus_get_events(b);
1694                 if (events_b < 0) {
1695                         log_error_errno(r, "Failed to get events mask: %m");
1696                         goto finish;
1697                 }
1698
1699                 r = sd_bus_get_timeout(b, &timeout_b);
1700                 if (r < 0) {
1701                         log_error_errno(r, "Failed to get timeout: %m");
1702                         goto finish;
1703                 }
1704
1705                 t = timeout_a;
1706                 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1707                         t = timeout_b;
1708
1709                 if (t == (uint64_t) -1)
1710                         ts = NULL;
1711                 else {
1712                         usec_t nw;
1713
1714                         nw = now(CLOCK_MONOTONIC);
1715                         if (t > nw)
1716                                 t -= nw;
1717                         else
1718                                 t = 0;
1719
1720                         ts = timespec_store(&_ts, t);
1721                 }
1722
1723                 pollfd = (struct pollfd[3]) {
1724                         {.fd = fd,     .events = events_a,           },
1725                         {.fd = in_fd,  .events = events_b & POLLIN,  },
1726                         {.fd = out_fd, .events = events_b & POLLOUT, }
1727                 };
1728
1729                 r = ppoll(pollfd, 3, ts, NULL);
1730                 if (r < 0) {
1731                         log_error("ppoll() failed: %m");
1732                         goto finish;
1733                 }
1734         }
1735
1736 finish:
1737         sd_notify(false,
1738                   "STOPPING=1\n"
1739                   "STATUS=Shutting down.");
1740
1741         policy_free(&policy_buffer);
1742         strv_free(arg_configuration);
1743         free(arg_address);
1744
1745         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1746 }