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