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