1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
9 Copyright 2014 David Herrmann
11 systemd is free software; you can redistribute it and/or modify it
12 under the terms of the GNU Lesser General Public License as published by
13 the Free Software Foundation; either version 2.1 of the License, or
14 (at your option) any later version.
16 systemd is distributed in the hope that it will be useful, but
17 WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public License
22 along with systemd; If not, see <http://www.gnu.org/licenses/>.
25 #include <sys/socket.h>
27 #include <sys/types.h>
38 #include "socket-util.h"
39 #include "sd-daemon.h"
41 #include "bus-internal.h"
42 #include "bus-message.h"
47 #include "capability.h"
48 #include "bus-control.h"
49 #include "smack-util.h"
51 #include "bus-xml-policy.h"
54 #include "synthesize.h"
56 static int proxy_create_dest(Proxy *p, const char *dest, const char *local_sec, bool negotiate_fds) {
57 _cleanup_bus_close_unref_ sd_bus *b = NULL;
62 return log_error_errno(r, "Failed to allocate bus: %m");
64 r = sd_bus_set_description(b, "sd-proxy");
66 return log_error_errno(r, "Failed to set bus name: %m");
68 r = sd_bus_set_address(b, dest);
70 return log_error_errno(r, "Failed to set address to connect to: %m");
72 r = sd_bus_negotiate_fds(b, negotiate_fds);
74 return log_error_errno(r, "Failed to set FD negotiation: %m");
76 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
78 return log_error_errno(r, "Failed to set credential negotiation: %m");
80 if (p->local_creds.pid > 0) {
81 b->fake_pids.pid = p->local_creds.pid;
82 b->fake_pids_valid = true;
84 b->fake_creds.uid = p->local_creds.uid;
85 b->fake_creds.euid = UID_INVALID;
86 b->fake_creds.suid = UID_INVALID;
87 b->fake_creds.fsuid = UID_INVALID;
88 b->fake_creds.gid = p->local_creds.gid;
89 b->fake_creds.egid = GID_INVALID;
90 b->fake_creds.sgid = GID_INVALID;
91 b->fake_creds.fsgid = GID_INVALID;
92 b->fake_creds_valid = true;
96 b->fake_label = strdup(local_sec);
101 b->manual_peer_interface = true;
105 return log_error_errno(r, "Failed to start bus client: %m");
112 static int proxy_create_local(Proxy *p, int in_fd, int out_fd, bool negotiate_fds) {
113 _cleanup_bus_close_unref_ sd_bus *b = NULL;
114 sd_id128_t server_id;
119 return log_error_errno(r, "Failed to allocate bus: %m");
121 r = sd_bus_set_fd(b, in_fd, out_fd);
123 return log_error_errno(r, "Failed to set fds: %m");
125 r = sd_bus_get_bus_id(p->dest_bus, &server_id);
127 return log_error_errno(r, "Failed to get server ID: %m");
129 r = sd_bus_set_server(b, 1, server_id);
131 return log_error_errno(r, "Failed to set server mode: %m");
133 r = sd_bus_negotiate_fds(b, negotiate_fds);
135 return log_error_errno(r, "Failed to set FD negotiation: %m");
137 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
139 return log_error_errno(r, "Failed to set credential negotiation: %m");
141 r = sd_bus_set_anonymous(b, true);
143 return log_error_errno(r, "Failed to set anonymous authentication: %m");
145 b->manual_peer_interface = true;
149 return log_error_errno(r, "Failed to start bus client: %m");
156 static int proxy_prepare_matches(Proxy *p) {
157 _cleanup_free_ char *match = NULL;
161 if (!p->dest_bus->is_kernel)
164 r = sd_bus_get_unique_name(p->dest_bus, &unique);
166 return log_error_errno(r, "Failed to get unique name: %m");
168 match = strjoin("type='signal',"
169 "sender='org.freedesktop.DBus',"
170 "path='/org/freedesktop/DBus',"
171 "interface='org.freedesktop.DBus',"
172 "member='NameOwnerChanged',"
180 r = sd_bus_add_match(p->dest_bus, NULL, match, NULL, NULL);
182 return log_error_errno(r, "Failed to add match for NameLost: %m");
185 match = strjoin("type='signal',"
186 "sender='org.freedesktop.DBus',"
187 "path='/org/freedesktop/DBus',"
188 "interface='org.freedesktop.DBus',"
189 "member='NameOwnerChanged',"
197 r = sd_bus_add_match(p->dest_bus, NULL, match, NULL, NULL);
199 return log_error_errno(r, "Failed to add match for NameAcquired: %m");
204 int proxy_new(Proxy **out, int in_fd, int out_fd, const char *dest) {
205 _cleanup_(proxy_freep) Proxy *p = NULL;
206 _cleanup_free_ char *local_sec = NULL;
215 p->local_out = out_fd;
217 p->owned_names = set_new(&string_hash_ops);
221 is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
222 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
225 (void) getpeercred(in_fd, &p->local_creds);
226 (void) getpeersec(in_fd, &local_sec);
229 r = proxy_create_dest(p, dest, local_sec, is_unix);
233 r = proxy_create_local(p, in_fd, out_fd, is_unix);
237 r = proxy_prepare_matches(p);
246 Proxy *proxy_free(Proxy *p) {
250 sd_bus_close_unrefp(&p->local_bus);
251 sd_bus_close_unrefp(&p->dest_bus);
252 set_free_free(p->owned_names);
258 int proxy_load_policy(Proxy *p, char **configuration) {
259 _cleanup_strv_free_ char **strv = NULL;
264 /* no need to load legacy policy if destination is not kdbus */
265 if (!p->dest_bus->is_kernel)
268 if (!configuration) {
271 r = sd_bus_get_scope(p->dest_bus, &scope);
273 return log_error_errno(r, "Couldn't determine bus scope: %m");
275 if (streq(scope, "system"))
276 strv = strv_new("/etc/dbus-1/system.conf",
277 "/etc/dbus-1/system.d/",
278 "/etc/dbus-1/system-local.conf",
280 else if (streq(scope, "user"))
281 strv = strv_new("/etc/dbus-1/session.conf",
282 "/etc/dbus-1/session.d/",
283 "/etc/dbus-1/session-local.conf",
286 return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
291 configuration = strv;
294 r = policy_load(&p->policy_buffer, configuration);
296 return log_error_errno(r, "Failed to load policy: %m");
298 p->policy = &p->policy_buffer;
299 /* policy_dump(p->policy); */
304 int proxy_hello_policy(Proxy *p, uid_t original_uid) {
310 if (p->local_creds.uid == original_uid)
311 log_debug("Permitting access, since bus owner matches bus client.");
312 else if (policy_check_hello(p->policy, p->local_creds.uid, p->local_creds.gid))
313 log_debug("Permitting access due to XML policy.");
315 return log_error_errno(EPERM, "Policy denied connection.");
320 static int proxy_wait(Proxy *p) {
321 uint64_t timeout_dest, timeout_local, t;
322 int events_dest, events_local, fd;
323 struct timespec _ts, *ts;
324 struct pollfd *pollfd;
329 fd = sd_bus_get_fd(p->dest_bus);
331 return log_error_errno(fd, "Failed to get fd: %m");
333 events_dest = sd_bus_get_events(p->dest_bus);
335 return log_error_errno(events_dest, "Failed to get events mask: %m");
337 r = sd_bus_get_timeout(p->dest_bus, &timeout_dest);
339 return log_error_errno(r, "Failed to get timeout: %m");
341 events_local = sd_bus_get_events(p->local_bus);
342 if (events_local < 0)
343 return log_error_errno(events_local, "Failed to get events mask: %m");
345 r = sd_bus_get_timeout(p->local_bus, &timeout_local);
347 return log_error_errno(r, "Failed to get timeout: %m");
350 if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_dest))
353 if (t == (uint64_t) -1)
358 nw = now(CLOCK_MONOTONIC);
364 ts = timespec_store(&_ts, t);
367 pollfd = (struct pollfd[3]) {
368 { .fd = fd, .events = events_dest, },
369 { .fd = p->local_in, .events = events_local & POLLIN, },
370 { .fd = p->local_out, .events = events_local & POLLOUT, },
373 r = ppoll(pollfd, 3, ts, NULL);
375 return log_error_errno(errno, "ppoll() failed: %m");
380 static int handle_policy_error(sd_bus_message *m, int r) {
381 if (r == -ESRCH || r == -ENXIO)
382 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
387 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
398 * dbus-1 distinguishes expected and non-expected replies by tracking
399 * method-calls and timeouts. By default, DENY rules are *NEVER* applied
400 * on expected replies, unless explicitly specified. But we dont track
401 * method-calls, thus, we cannot know whether a reply is expected.
402 * Fortunately, the kdbus forbids non-expected replies, so we can safely
403 * ignore any policy on those and let the kernel deal with it.
405 * TODO: To be correct, we should only ignore policy-tags that are
406 * applied on non-expected replies. However, so far we don't parse those
407 * tags so we let everything pass. I haven't seen a DENY policy tag on
408 * expected-replies, ever, so don't bother..
410 if (m->reply_cookie > 0)
413 if (from->is_kernel) {
414 uid_t sender_uid = UID_INVALID;
415 gid_t sender_gid = GID_INVALID;
416 char **sender_names = NULL;
417 bool granted = false;
419 /* Driver messages are always OK */
420 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
423 /* The message came from the kernel, and is sent to our legacy client. */
424 sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
426 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
427 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
429 if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
430 _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL;
432 /* If the message came from another legacy
433 * client, then the message creds will be
434 * missing, simply because on legacy clients
435 * per-message creds were unknown. In this
436 * case, query the creds of the peer
439 r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_UID|SD_BUS_CREDS_GID, true, &sender_creds);
441 return handle_policy_error(m, r);
443 (void) sd_bus_creds_get_uid(sender_creds, &sender_uid);
444 (void) sd_bus_creds_get_gid(sender_creds, &sender_gid);
447 /* First check whether the sender can send the message to our name */
448 if (set_isempty(owned_names)) {
449 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member, false))
455 SET_FOREACH(n, owned_names, i)
456 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member, false)) {
463 /* Then check whether us (the recipient) can receive from the sender's name */
464 if (strv_isempty(sender_names)) {
465 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member, false))
470 STRV_FOREACH(n, sender_names) {
471 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member, false))
477 /* Return an error back to the caller */
478 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
479 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
481 /* Return 1, indicating that the message shall not be processed any further */
486 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
487 uid_t destination_uid = UID_INVALID;
488 gid_t destination_gid = GID_INVALID;
489 const char *destination_unique = NULL;
490 char **destination_names = NULL;
491 bool granted = false;
493 /* Driver messages are always OK */
494 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
497 /* The message came from the legacy client, and is sent to kdbus. */
498 if (m->destination) {
499 r = bus_get_name_creds_kdbus(to, m->destination,
500 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
501 SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
502 true, &destination_creds);
504 return handle_policy_error(m, r);
506 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
508 return handle_policy_error(m, r);
510 sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
512 (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
513 (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
516 /* First check if we (the sender) can send to this name */
517 if (strv_isempty(destination_names)) {
518 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member, true))
523 STRV_FOREACH(n, destination_names) {
524 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member, true)) {
526 /* If we made a receiver decision,
527 then remember which name's policy
528 we used, and to which unique ID it
529 mapped when we made the
530 decision. Then, let's pass this to
531 the kernel when sending the
532 message, so that it refuses the
533 operation should the name and
534 unique ID not map to each other
537 r = free_and_strdup(&m->destination_ptr, *n);
541 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
551 /* Then check if the recipient can receive from our name */
553 if (sd_bus_message_is_signal(m, NULL, NULL)) {
554 /* If we forward a signal from dbus-1 to kdbus,
555 * we have no idea who the recipient is.
556 * Therefore, we cannot apply any dbus-1
557 * receiver policies that match on receiver
558 * credentials. We know sd-bus always sets
559 * KDBUS_MSG_SIGNAL, so the kernel applies
560 * receiver policies to the message. Therefore,
561 * skip policy checks in this case. */
563 } else if (set_isempty(owned_names)) {
564 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member, true))
570 SET_FOREACH(n, owned_names, i)
571 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member, true))
576 /* Return an error back to the caller */
577 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
578 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
580 /* Return 1, indicating that the message shall not be processed any further */
587 static int process_hello(Proxy *p, sd_bus_message *m) {
588 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
595 /* As reaction to hello we need to respond with two messages:
596 * the callback reply and the NameAcquired for the unique
597 * name, since hello is otherwise obsolete on kdbus. */
600 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
601 streq_ptr(m->destination, "org.freedesktop.DBus");
607 return log_error_errno(-EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
611 return log_error_errno(-EIO, "Got duplicate hello, aborting.");
615 if (!p->dest_bus->is_kernel)
618 r = sd_bus_message_new_method_return(m, &n);
620 return log_error_errno(r, "Failed to generate HELLO reply: %m");
622 r = sd_bus_message_append(n, "s", p->dest_bus->unique_name);
624 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
626 r = bus_message_append_sender(n, "org.freedesktop.DBus");
628 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
630 r = bus_seal_synthetic_message(p->local_bus, n);
632 return log_error_errno(r, "Failed to seal HELLO reply: %m");
634 r = sd_bus_send(p->local_bus, n, NULL);
636 return log_error_errno(r, "Failed to send HELLO reply: %m");
638 n = sd_bus_message_unref(n);
639 r = sd_bus_message_new_signal(
642 "/org/freedesktop/DBus",
643 "org.freedesktop.DBus",
646 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
648 r = sd_bus_message_append(n, "s", p->dest_bus->unique_name);
650 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
652 r = bus_message_append_sender(n, "org.freedesktop.DBus");
654 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
656 r = bus_seal_synthetic_message(p->local_bus, n);
658 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
660 r = sd_bus_send(p->local_bus, n, NULL);
662 return log_error_errno(r, "Failed to send NameAcquired message: %m");
667 static int patch_sender(sd_bus *a, sd_bus_message *m) {
668 char **well_known = NULL;
678 /* We will change the sender of messages from the bus driver
679 * so that they originate from the bus driver. This is a
680 * speciality originating from dbus1, where the bus driver did
681 * not have a unique id, but only the well-known name. */
683 c = sd_bus_message_get_creds(m);
687 r = sd_bus_creds_get_well_known_names(c, &well_known);
691 if (strv_contains(well_known, "org.freedesktop.DBus"))
692 m->sender = "org.freedesktop.DBus";
697 static int proxy_process_dest_to_local(Proxy *p) {
698 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
703 r = sd_bus_process(p->dest_bus, &m);
705 /* treat 'connection reset by peer' as clean exit condition */
706 if (r != -ECONNRESET)
707 log_error_errno(r, "Failed to process destination bus: %m");
716 /* We officially got EOF, let's quit */
717 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
720 r = synthesize_name_acquired(p->dest_bus, p->local_bus, m);
722 return log_error_errno(r, "Failed to synthesize message: %m");
724 patch_sender(p->dest_bus, m);
727 r = process_policy(p->dest_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
729 return log_error_errno(r, "Failed to process policy: %m");
734 r = sd_bus_send(p->local_bus, m, NULL);
736 if (r == -EPERM && m->reply_cookie > 0) {
737 /* If the peer tries to send a reply and it is rejected with EPERM
738 * by the kernel, we ignore the error. This catches cases where the
739 * original method-call didn't had EXPECT_REPLY set, but the proxy-peer
740 * still sends a reply. This is allowed in dbus1, but not in kdbus. We
741 * don't want to track reply-windows in the proxy, so we simply ignore
742 * EPERM for all replies. The only downside is, that callers are no
743 * longer notified if their replies are dropped. However, this is
744 * equivalent to the caller's timeout to expire, so this should be
745 * acceptable. Nobody sane sends replies without a matching method-call,
746 * so nobody should care. */
749 if (r != -ECONNRESET)
750 log_error_errno(r, "Failed to send message to client: %m");
758 static int proxy_process_local_to_dest(Proxy *p) {
759 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
764 r = sd_bus_process(p->local_bus, &m);
766 /* treat 'connection reset by peer' as clean exit condition */
767 if (r != -ECONNRESET)
768 log_error_errno(r, "Failed to process local bus: %m");
777 /* We officially got EOF, let's quit */
778 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
781 r = process_hello(p, m);
783 return log_error_errno(r, "Failed to process HELLO: %m");
787 r = bus_proxy_process_driver(p->dest_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
789 return log_error_errno(r, "Failed to process driver calls: %m");
795 r = process_policy(p->local_bus, p->dest_bus, m, p->policy, &p->local_creds, p->owned_names);
797 return log_error_errno(r, "Failed to process policy: %m");
802 r = sd_bus_send(p->dest_bus, m, NULL);
805 /* The name database changed since the policy check, hence let's check again */
807 } else if (r == -EPERM && m->reply_cookie > 0) {
808 /* see above why EPERM is ignored for replies */
811 if (r != -ECONNRESET)
812 log_error_errno(r, "Failed to send message to bus: %m");
823 int proxy_run(Proxy *p) {
832 /* Read messages from bus, to pass them on to our client */
833 r = proxy_process_dest_to_local(p);
834 if (r == -ECONNRESET)
842 /* Read messages from our client, to pass them on to the bus */
843 r = proxy_process_local_to_dest(p);
844 if (r == -ECONNRESET)