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