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