]> git.ipfire.org Git - thirdparty/systemd.git/blame - src/bus-proxyd/proxy.c
util-lib: split out allocation calls into alloc-util.[ch]
[thirdparty/systemd.git] / src / bus-proxyd / proxy.c
CommitLineData
c0395aeb
DH
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 Copyright 2014 David Herrmann
10
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.
15
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.
20
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/>.
23***/
24
c0395aeb 25#include <errno.h>
0a6f50c0 26#include <poll.h>
3ffd4af2
LP
27#include <string.h>
28#include <sys/socket.h>
29#include <sys/types.h>
c0395aeb 30
c0395aeb 31#include "sd-bus.h"
3ffd4af2
LP
32#include "sd-daemon.h"
33
b5efdb8a 34#include "alloc-util.h"
3ffd4af2 35#include "bus-control.h"
c0395aeb
DH
36#include "bus-internal.h"
37#include "bus-message.h"
38#include "bus-util.h"
c0395aeb
DH
39#include "bus-xml-policy.h"
40#include "driver.h"
3ffd4af2
LP
41#include "fd-util.h"
42#include "formats-util.h"
43#include "log.h"
c0395aeb 44#include "proxy.h"
3ffd4af2
LP
45#include "set.h"
46#include "strv.h"
c0395aeb 47#include "synthesize.h"
ee104e11 48#include "user-util.h"
3ffd4af2 49#include "util.h"
c0395aeb 50
d27efd93 51static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
03976f7b 52 _cleanup_bus_flush_close_unref_ sd_bus *b = NULL;
c0395aeb
DH
53 int r;
54
55 r = sd_bus_new(&b);
56 if (r < 0)
57 return log_error_errno(r, "Failed to allocate bus: %m");
58
59 r = sd_bus_set_description(b, "sd-proxy");
60 if (r < 0)
61 return log_error_errno(r, "Failed to set bus name: %m");
62
d27efd93 63 r = sd_bus_set_address(b, destination);
c0395aeb
DH
64 if (r < 0)
65 return log_error_errno(r, "Failed to set address to connect to: %m");
66
67 r = sd_bus_negotiate_fds(b, negotiate_fds);
68 if (r < 0)
69 return log_error_errno(r, "Failed to set FD negotiation: %m");
70
05bae4a6 71 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
c0395aeb
DH
72 if (r < 0)
73 return log_error_errno(r, "Failed to set credential negotiation: %m");
74
75 if (p->local_creds.pid > 0) {
76 b->fake_pids.pid = p->local_creds.pid;
77 b->fake_pids_valid = true;
78
d90c154e 79 b->fake_creds.uid = UID_INVALID;
e23f4bb5 80 b->fake_creds.euid = p->local_creds.uid;
d90c154e
DH
81 b->fake_creds.suid = UID_INVALID;
82 b->fake_creds.fsuid = UID_INVALID;
83 b->fake_creds.gid = GID_INVALID;
e23f4bb5 84 b->fake_creds.egid = p->local_creds.gid;
d90c154e
DH
85 b->fake_creds.sgid = GID_INVALID;
86 b->fake_creds.fsgid = GID_INVALID;
c0395aeb
DH
87 b->fake_creds_valid = true;
88 }
89
90 if (local_sec) {
91 b->fake_label = strdup(local_sec);
92 if (!b->fake_label)
93 return log_oom();
94 }
95
96 b->manual_peer_interface = true;
97
98 r = sd_bus_start(b);
99 if (r < 0)
100 return log_error_errno(r, "Failed to start bus client: %m");
101
d27efd93 102 p->destination_bus = b;
c0395aeb
DH
103 b = NULL;
104 return 0;
105}
106
1a37c975 107static int proxy_create_local(Proxy *p, bool negotiate_fds) {
c0395aeb 108 sd_id128_t server_id;
1a37c975 109 sd_bus *b;
c0395aeb
DH
110 int r;
111
112 r = sd_bus_new(&b);
113 if (r < 0)
114 return log_error_errno(r, "Failed to allocate bus: %m");
115
1a37c975
LP
116 r = sd_bus_set_fd(b, p->local_in, p->local_out);
117 if (r < 0) {
118 sd_bus_unref(b);
c0395aeb 119 return log_error_errno(r, "Failed to set fds: %m");
1a37c975
LP
120 }
121
122 /* The fds are now owned by the bus, and we indicate that by
123 * storing the bus object in the proxy object. */
124 p->local_bus = b;
c0395aeb 125
d27efd93 126 r = sd_bus_get_bus_id(p->destination_bus, &server_id);
c0395aeb
DH
127 if (r < 0)
128 return log_error_errno(r, "Failed to get server ID: %m");
129
130 r = sd_bus_set_server(b, 1, server_id);
131 if (r < 0)
132 return log_error_errno(r, "Failed to set server mode: %m");
133
134 r = sd_bus_negotiate_fds(b, negotiate_fds);
135 if (r < 0)
136 return log_error_errno(r, "Failed to set FD negotiation: %m");
137
05bae4a6 138 r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_EUID|SD_BUS_CREDS_PID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SELINUX_CONTEXT);
c0395aeb
DH
139 if (r < 0)
140 return log_error_errno(r, "Failed to set credential negotiation: %m");
141
142 r = sd_bus_set_anonymous(b, true);
143 if (r < 0)
144 return log_error_errno(r, "Failed to set anonymous authentication: %m");
145
146 b->manual_peer_interface = true;
147
148 r = sd_bus_start(b);
149 if (r < 0)
150 return log_error_errno(r, "Failed to start bus client: %m");
151
c0395aeb
DH
152 return 0;
153}
154
e23bc0e7
DH
155static int proxy_match_synthetic(sd_bus_message *m, void *userdata, sd_bus_error *error) {
156 Proxy *p = userdata;
157
158 p->synthetic_matched = true;
159 return 0; /* make sure to continue processing it in further handlers */
160}
161
619b80a1 162/*
e23bc0e7
DH
163 * We always need NameOwnerChanged so we can synthesize NameLost and
164 * NameAcquired. Furthermore, dbus-1 always passes unicast-signals through, so
165 * subscribe unconditionally.
619b80a1 166 */
c0395aeb
DH
167static int proxy_prepare_matches(Proxy *p) {
168 _cleanup_free_ char *match = NULL;
169 const char *unique;
170 int r;
171
d27efd93 172 if (!p->destination_bus->is_kernel)
c0395aeb
DH
173 return 0;
174
d27efd93 175 r = sd_bus_get_unique_name(p->destination_bus, &unique);
c0395aeb
DH
176 if (r < 0)
177 return log_error_errno(r, "Failed to get unique name: %m");
178
179 match = strjoin("type='signal',"
180 "sender='org.freedesktop.DBus',"
181 "path='/org/freedesktop/DBus',"
182 "interface='org.freedesktop.DBus',"
183 "member='NameOwnerChanged',"
184 "arg1='",
185 unique,
186 "'",
187 NULL);
188 if (!match)
189 return log_oom();
190
e23bc0e7 191 r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
c0395aeb
DH
192 if (r < 0)
193 return log_error_errno(r, "Failed to add match for NameLost: %m");
194
195 free(match);
196 match = strjoin("type='signal',"
197 "sender='org.freedesktop.DBus',"
198 "path='/org/freedesktop/DBus',"
199 "interface='org.freedesktop.DBus',"
200 "member='NameOwnerChanged',"
201 "arg2='",
202 unique,
203 "'",
204 NULL);
205 if (!match)
206 return log_oom();
207
e23bc0e7 208 r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
c0395aeb
DH
209 if (r < 0)
210 return log_error_errno(r, "Failed to add match for NameAcquired: %m");
211
de865432
KS
212 free(match);
213 match = strjoin("type='signal',"
214 "destination='",
215 unique,
216 "'",
217 NULL);
218 if (!match)
219 return log_oom();
220
e23bc0e7 221 r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
de865432 222 if (r < 0)
619b80a1
KS
223 log_error_errno(r, "Failed to add match for directed signals: %m");
224 /* FIXME: temporarily ignore error to support older kdbus versions */
de865432 225
c0395aeb
DH
226 return 0;
227}
228
d27efd93 229int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
c0395aeb
DH
230 _cleanup_(proxy_freep) Proxy *p = NULL;
231 _cleanup_free_ char *local_sec = NULL;
232 bool is_unix;
233 int r;
234
1a37c975
LP
235 /* This takes possession/destroys the file descriptors passed
236 * in even on failure. The caller should hence forget about
237 * the fds in all cases after calling this function and not
238 * close them. */
239
c0395aeb 240 p = new0(Proxy, 1);
1a37c975
LP
241 if (!p) {
242 safe_close(in_fd);
243 safe_close(out_fd);
c0395aeb 244 return log_oom();
1a37c975 245 }
c0395aeb
DH
246
247 p->local_in = in_fd;
248 p->local_out = out_fd;
249
250 p->owned_names = set_new(&string_hash_ops);
251 if (!p->owned_names)
252 return log_oom();
253
254 is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
255 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
256
257 if (is_unix) {
258 (void) getpeercred(in_fd, &p->local_creds);
259 (void) getpeersec(in_fd, &local_sec);
260 }
261
d27efd93 262 r = proxy_create_destination(p, destination, local_sec, is_unix);
c0395aeb
DH
263 if (r < 0)
264 return r;
265
1a37c975 266 r = proxy_create_local(p, is_unix);
c0395aeb
DH
267 if (r < 0)
268 return r;
269
270 r = proxy_prepare_matches(p);
271 if (r < 0)
272 return r;
273
274 *out = p;
275 p = NULL;
1a37c975 276
c0395aeb
DH
277 return 0;
278}
279
280Proxy *proxy_free(Proxy *p) {
11f254be
DH
281 ProxyActivation *activation;
282
c0395aeb
DH
283 if (!p)
284 return NULL;
285
11f254be
DH
286 while ((activation = p->activations)) {
287 LIST_REMOVE(activations_by_proxy, p->activations, activation);
288 sd_bus_message_unref(activation->request);
289 sd_bus_slot_unref(activation->slot);
290 free(activation);
291 }
292
1a37c975
LP
293 if (p->local_bus)
294 sd_bus_flush_close_unref(p->local_bus);
295 else {
296 safe_close(p->local_in);
297 if (p->local_out != p->local_in)
298 safe_close(p->local_out);
299 }
300
03976f7b 301 sd_bus_flush_close_unref(p->destination_bus);
c0395aeb
DH
302 set_free_free(p->owned_names);
303 free(p);
304
305 return NULL;
306}
307
c4bc1a84 308int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) {
c0395aeb 309 _cleanup_strv_free_ char **strv = NULL;
c4bc1a84 310 Policy *policy;
c0395aeb
DH
311 int r;
312
313 assert(p);
c4bc1a84 314 assert(sp);
c0395aeb
DH
315
316 /* no need to load legacy policy if destination is not kdbus */
d27efd93 317 if (!p->destination_bus->is_kernel)
c0395aeb
DH
318 return 0;
319
c4bc1a84
DH
320 p->policy = sp;
321
322 policy = shared_policy_acquire(sp);
323 if (policy) {
324 /* policy already pre-loaded */
325 shared_policy_release(sp, policy);
326 return 0;
327 }
328
c0395aeb
DH
329 if (!configuration) {
330 const char *scope;
331
d27efd93 332 r = sd_bus_get_scope(p->destination_bus, &scope);
c0395aeb
DH
333 if (r < 0)
334 return log_error_errno(r, "Couldn't determine bus scope: %m");
335
336 if (streq(scope, "system"))
97af81cf
LP
337 strv = strv_new("/usr/share/dbus-1/system.conf",
338 "/etc/dbus-1/system.conf",
339 "/usr/share/dbus-1/system.d/",
c0395aeb
DH
340 "/etc/dbus-1/system.d/",
341 "/etc/dbus-1/system-local.conf",
342 NULL);
343 else if (streq(scope, "user"))
97af81cf
LP
344 strv = strv_new("/usr/share/dbus-1/session.conf",
345 "/etc/dbus-1/session.conf",
346 "/usr/share/dbus-1/session.d/",
c0395aeb
DH
347 "/etc/dbus-1/session.d/",
348 "/etc/dbus-1/session-local.conf",
349 NULL);
350 else
351 return log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
352
353 if (!strv)
354 return log_oom();
355
356 configuration = strv;
357 }
358
c4bc1a84 359 return shared_policy_preload(sp, configuration);
c0395aeb
DH
360}
361
362int proxy_hello_policy(Proxy *p, uid_t original_uid) {
c4bc1a84
DH
363 Policy *policy;
364 int r = 0;
365
c0395aeb
DH
366 assert(p);
367
368 if (!p->policy)
369 return 0;
370
c4bc1a84
DH
371 policy = shared_policy_acquire(p->policy);
372
c0395aeb
DH
373 if (p->local_creds.uid == original_uid)
374 log_debug("Permitting access, since bus owner matches bus client.");
c4bc1a84 375 else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid))
c0395aeb
DH
376 log_debug("Permitting access due to XML policy.");
377 else
c4bc1a84 378 r = log_error_errno(EPERM, "Policy denied connection.");
c0395aeb 379
c4bc1a84
DH
380 shared_policy_release(p->policy, policy);
381
382 return r;
c0395aeb
DH
383}
384
385static int proxy_wait(Proxy *p) {
d27efd93
LP
386 uint64_t timeout_destination, timeout_local, t;
387 int events_destination, events_local, fd;
c0395aeb
DH
388 struct timespec _ts, *ts;
389 struct pollfd *pollfd;
390 int r;
391
392 assert(p);
393
d27efd93 394 fd = sd_bus_get_fd(p->destination_bus);
c0395aeb
DH
395 if (fd < 0)
396 return log_error_errno(fd, "Failed to get fd: %m");
397
d27efd93
LP
398 events_destination = sd_bus_get_events(p->destination_bus);
399 if (events_destination < 0)
400 return log_error_errno(events_destination, "Failed to get events mask: %m");
c0395aeb 401
d27efd93 402 r = sd_bus_get_timeout(p->destination_bus, &timeout_destination);
c0395aeb
DH
403 if (r < 0)
404 return log_error_errno(r, "Failed to get timeout: %m");
405
406 events_local = sd_bus_get_events(p->local_bus);
407 if (events_local < 0)
408 return log_error_errno(events_local, "Failed to get events mask: %m");
409
410 r = sd_bus_get_timeout(p->local_bus, &timeout_local);
411 if (r < 0)
412 return log_error_errno(r, "Failed to get timeout: %m");
413
d27efd93
LP
414 t = timeout_destination;
415 if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_destination))
c0395aeb
DH
416 t = timeout_local;
417
418 if (t == (uint64_t) -1)
419 ts = NULL;
420 else {
421 usec_t nw;
422
423 nw = now(CLOCK_MONOTONIC);
424 if (t > nw)
425 t -= nw;
426 else
427 t = 0;
428
429 ts = timespec_store(&_ts, t);
430 }
431
432 pollfd = (struct pollfd[3]) {
c74f883c 433 { .fd = fd, .events = events_destination, },
c0395aeb
DH
434 { .fd = p->local_in, .events = events_local & POLLIN, },
435 { .fd = p->local_out, .events = events_local & POLLOUT, },
436 };
437
438 r = ppoll(pollfd, 3, ts, NULL);
439 if (r < 0)
440 return log_error_errno(errno, "ppoll() failed: %m");
441
442 return 0;
443}
444
445static int handle_policy_error(sd_bus_message *m, int r) {
446 if (r == -ESRCH || r == -ENXIO)
447 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
448
449 return r;
450}
451
c4bc1a84 452static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
c0395aeb
DH
453 int r;
454
455 assert(from);
456 assert(to);
457 assert(m);
458
459 if (!policy)
460 return 0;
461
462 /*
463 * dbus-1 distinguishes expected and non-expected replies by tracking
464 * method-calls and timeouts. By default, DENY rules are *NEVER* applied
465 * on expected replies, unless explicitly specified. But we dont track
466 * method-calls, thus, we cannot know whether a reply is expected.
467 * Fortunately, the kdbus forbids non-expected replies, so we can safely
468 * ignore any policy on those and let the kernel deal with it.
469 *
470 * TODO: To be correct, we should only ignore policy-tags that are
471 * applied on non-expected replies. However, so far we don't parse those
472 * tags so we let everything pass. I haven't seen a DENY policy tag on
473 * expected-replies, ever, so don't bother..
474 */
475 if (m->reply_cookie > 0)
476 return 0;
477
478 if (from->is_kernel) {
479 uid_t sender_uid = UID_INVALID;
480 gid_t sender_gid = GID_INVALID;
481 char **sender_names = NULL;
c0395aeb
DH
482
483 /* Driver messages are always OK */
484 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
485 return 0;
486
487 /* The message came from the kernel, and is sent to our legacy client. */
1140e154 488 (void) sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
c0395aeb 489
05bae4a6
DH
490 (void) sd_bus_creds_get_euid(&m->creds, &sender_uid);
491 (void) sd_bus_creds_get_egid(&m->creds, &sender_gid);
c0395aeb
DH
492
493 if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
494 _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL;
495
496 /* If the message came from another legacy
497 * client, then the message creds will be
498 * missing, simply because on legacy clients
499 * per-message creds were unknown. In this
500 * case, query the creds of the peer
501 * instead. */
502
05bae4a6 503 r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds);
c0395aeb
DH
504 if (r < 0)
505 return handle_policy_error(m, r);
506
05bae4a6
DH
507 (void) sd_bus_creds_get_euid(sender_creds, &sender_uid);
508 (void) sd_bus_creds_get_egid(sender_creds, &sender_gid);
c0395aeb
DH
509 }
510
511 /* First check whether the sender can send the message to our name */
7447362c
DH
512 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, false, NULL) &&
513 policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, sender_names, m->path, m->interface, m->member, false))
514 return 0;
c0395aeb
DH
515
516 /* Return an error back to the caller */
517 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
518 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
519
520 /* Return 1, indicating that the message shall not be processed any further */
521 return 1;
522 }
523
524 if (to->is_kernel) {
525 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
526 uid_t destination_uid = UID_INVALID;
527 gid_t destination_gid = GID_INVALID;
528 const char *destination_unique = NULL;
529 char **destination_names = NULL;
7447362c 530 char *n;
c0395aeb
DH
531
532 /* Driver messages are always OK */
533 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
534 return 0;
535
536 /* The message came from the legacy client, and is sent to kdbus. */
537 if (m->destination) {
538 r = bus_get_name_creds_kdbus(to, m->destination,
539 SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
05bae4a6 540 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID,
c0395aeb
DH
541 true, &destination_creds);
542 if (r < 0)
543 return handle_policy_error(m, r);
544
545 r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
546 if (r < 0)
547 return handle_policy_error(m, r);
548
1140e154 549 (void) sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
c0395aeb 550
05bae4a6
DH
551 (void) sd_bus_creds_get_euid(destination_creds, &destination_uid);
552 (void) sd_bus_creds_get_egid(destination_creds, &destination_gid);
c0395aeb
DH
553 }
554
555 /* First check if we (the sender) can send to this name */
3723263f
DH
556 if (sd_bus_message_is_signal(m, NULL, NULL)) {
557 /* If we forward a signal from dbus-1 to kdbus, we have
558 * no idea who the recipient is. Therefore, we cannot
559 * apply any dbus-1 policies that match on receiver
560 * credentials. We know sd-bus always sets
561 * KDBUS_MSG_SIGNAL, so the kernel applies policies to
562 * the message. Therefore, skip policy checks in this
563 * case. */
564 return 0;
565 } else if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, destination_names, m->path, m->interface, m->member, true, &n)) {
7447362c
DH
566 if (n) {
567 /* If we made a receiver decision, then remember which
568 * name's policy we used, and to which unique ID it
569 * mapped when we made the decision. Then, let's pass
570 * this to the kernel when sending the message, so that
571 * it refuses the operation should the name and unique
572 * ID not map to each other anymore. */
573
574 r = free_and_strdup(&m->destination_ptr, n);
575 if (r < 0)
576 return r;
577
578 r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
579 if (r < 0)
580 return r;
c0395aeb 581 }
c0395aeb 582
3723263f 583 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true))
7447362c 584 return 0;
c0395aeb
DH
585 }
586
587 /* Return an error back to the caller */
588 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
589 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
590
591 /* Return 1, indicating that the message shall not be processed any further */
592 return 1;
593 }
594
595 return 0;
596}
597
c4bc1a84
DH
598static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, SharedPolicy *sp, const struct ucred *our_ucred, Set *owned_names) {
599 Policy *policy;
600 int r;
601
602 assert(sp);
603
604 policy = shared_policy_acquire(sp);
605 r = process_policy_unlocked(from, to, m, policy, our_ucred, owned_names);
606 shared_policy_release(sp, policy);
607
608 return r;
609}
610
c0395aeb
DH
611static int process_hello(Proxy *p, sd_bus_message *m) {
612 _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
613 bool is_hello;
614 int r;
615
616 assert(p);
617 assert(m);
618
619 /* As reaction to hello we need to respond with two messages:
620 * the callback reply and the NameAcquired for the unique
621 * name, since hello is otherwise obsolete on kdbus. */
622
623 is_hello =
624 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
625 streq_ptr(m->destination, "org.freedesktop.DBus");
626
627 if (!is_hello) {
628 if (p->got_hello)
629 return 0;
630
61adca52 631 return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
c0395aeb
DH
632 }
633
634 if (p->got_hello)
61adca52 635 return log_error_errno(EIO, "Got duplicate hello, aborting.");
c0395aeb
DH
636
637 p->got_hello = true;
638
d27efd93 639 if (!p->destination_bus->is_kernel)
c0395aeb
DH
640 return 0;
641
642 r = sd_bus_message_new_method_return(m, &n);
643 if (r < 0)
644 return log_error_errno(r, "Failed to generate HELLO reply: %m");
645
d27efd93 646 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
c0395aeb
DH
647 if (r < 0)
648 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
649
650 r = bus_message_append_sender(n, "org.freedesktop.DBus");
651 if (r < 0)
652 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
653
654 r = bus_seal_synthetic_message(p->local_bus, n);
655 if (r < 0)
656 return log_error_errno(r, "Failed to seal HELLO reply: %m");
657
658 r = sd_bus_send(p->local_bus, n, NULL);
659 if (r < 0)
660 return log_error_errno(r, "Failed to send HELLO reply: %m");
661
662 n = sd_bus_message_unref(n);
663 r = sd_bus_message_new_signal(
664 p->local_bus,
665 &n,
666 "/org/freedesktop/DBus",
667 "org.freedesktop.DBus",
668 "NameAcquired");
669 if (r < 0)
670 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
671
d27efd93 672 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
c0395aeb
DH
673 if (r < 0)
674 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
675
676 r = bus_message_append_sender(n, "org.freedesktop.DBus");
677 if (r < 0)
678 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
679
e3c57a86
DH
680 r = sd_bus_message_set_destination(n, p->destination_bus->unique_name);
681 if (r < 0)
682 return log_error_errno(r, "Failed to set destination for NameAcquired message: %m");
683
c0395aeb
DH
684 r = bus_seal_synthetic_message(p->local_bus, n);
685 if (r < 0)
686 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
687
688 r = sd_bus_send(p->local_bus, n, NULL);
689 if (r < 0)
690 return log_error_errno(r, "Failed to send NameAcquired message: %m");
691
692 return 1;
693}
694
695static int patch_sender(sd_bus *a, sd_bus_message *m) {
696 char **well_known = NULL;
697 sd_bus_creds *c;
698 int r;
699
700 assert(a);
701 assert(m);
702
703 if (!a->is_kernel)
704 return 0;
705
706 /* We will change the sender of messages from the bus driver
707 * so that they originate from the bus driver. This is a
708 * speciality originating from dbus1, where the bus driver did
709 * not have a unique id, but only the well-known name. */
710
711 c = sd_bus_message_get_creds(m);
712 if (!c)
713 return 0;
714
715 r = sd_bus_creds_get_well_known_names(c, &well_known);
716 if (r < 0)
717 return r;
718
719 if (strv_contains(well_known, "org.freedesktop.DBus"))
720 m->sender = "org.freedesktop.DBus";
721
722 return 0;
723}
724
d27efd93 725static int proxy_process_destination_to_local(Proxy *p) {
c0395aeb 726 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
e23bc0e7 727 bool matched, matched_synthetic;
c0395aeb
DH
728 int r;
729
730 assert(p);
731
e23bc0e7
DH
732 /*
733 * Usually, we would just take any message that the bus passes to us
734 * and forward it to the local connection. However, there are actually
735 * applications that fail if they receive broadcasts that they didn't
736 * subscribe to. Therefore, we actually emulate a real broadcast
737 * matching here, and discard any broadcasts that weren't matched. Our
738 * match-handlers remembers whether a message was matched by any rule,
739 * by marking it in @p->message_matched.
740 */
741
d27efd93 742 r = sd_bus_process(p->destination_bus, &m);
e23bc0e7
DH
743
744 matched = p->message_matched;
745 matched_synthetic = p->synthetic_matched;
746 p->message_matched = false;
747 p->synthetic_matched = false;
748
557b5d4a 749 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
418e4cb0 750 return r;
c0395aeb 751 if (r < 0) {
418e4cb0 752 log_error_errno(r, "Failed to process destination bus: %m");
c0395aeb
DH
753 return r;
754 }
c0395aeb
DH
755 if (r == 0)
756 return 0;
757 if (!m)
758 return 1;
759
760 /* We officially got EOF, let's quit */
761 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
762 return -ECONNRESET;
763
e23bc0e7 764 r = synthesize_name_acquired(p, p->destination_bus, p->local_bus, m);
c74f883c
LP
765 if (r == -ECONNRESET || r == -ENOTCONN)
766 return r;
c0395aeb
DH
767 if (r < 0)
768 return log_error_errno(r, "Failed to synthesize message: %m");
769
e23bc0e7
DH
770 /* discard broadcasts that were not matched by any MATCH rule */
771 if (!matched && !sd_bus_message_get_destination(m)) {
772 if (!matched_synthetic)
ad8373e9
DM
773 log_debug("Dropped unmatched broadcast: uid=" UID_FMT " gid=" GID_FMT " pid=" PID_FMT " message=%s path=%s interface=%s member=%s sender=%s destination=%s",
774 p->local_creds.uid, p->local_creds.gid, p->local_creds.pid, bus_message_type_to_string(m->header->type),
775 strna(m->path), strna(m->interface), strna(m->member), strna(m->sender), strna(m->destination));
e23bc0e7
DH
776 return 1;
777 }
778
d27efd93 779 patch_sender(p->destination_bus, m);
c0395aeb
DH
780
781 if (p->policy) {
d27efd93 782 r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
c74f883c
LP
783 if (r == -ECONNRESET || r == -ENOTCONN)
784 return r;
c0395aeb
DH
785 if (r < 0)
786 return log_error_errno(r, "Failed to process policy: %m");
418e4cb0 787 if (r > 0)
c0395aeb
DH
788 return 1;
789 }
790
791 r = sd_bus_send(p->local_bus, m, NULL);
792 if (r < 0) {
557b5d4a 793 if (r == -ECONNRESET || r == -ENOTCONN)
c0395aeb 794 return r;
5f6cb091
LP
795
796 /* If the peer tries to send a reply and it is
2c960818 797 * rejected with EBADSLT by the kernel, we ignore the
5f6cb091
LP
798 * error. This catches cases where the original
799 * method-call didn't had EXPECT_REPLY set, but the
800 * proxy-peer still sends a reply. This is allowed in
801 * dbus1, but not in kdbus. We don't want to track
802 * reply-windows in the proxy, so we simply ignore
2c960818 803 * EBADSLT for all replies. The only downside is, that
5f6cb091
LP
804 * callers are no longer notified if their replies are
805 * dropped. However, this is equivalent to the
806 * caller's timeout to expire, so this should be
807 * acceptable. Nobody sane sends replies without a
808 * matching method-call, so nobody should care. */
855fc974
KS
809
810 /* FIXME: remove -EPERM when kdbus is updated */
2c960818 811 if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
5f6cb091
LP
812 return 1;
813
814 /* Return the error to the client, if we can */
815 synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m");
ec2c7b56
DH
816 if (r == -ENOBUFS) {
817 /* if local dbus1 peer does not dispatch its queue, warn only once */
818 if (!p->queue_overflow)
819 log_error("Dropped messages due to queue overflow of local peer (pid: "PID_FMT" uid: "UID_FMT")", p->local_creds.pid, p->local_creds.uid);
820 p->queue_overflow = true;
821 } else
822 log_error_errno(r,
823 "Failed to forward message we got from destination: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m",
824 p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
825 strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
826
5f6cb091 827 return 1;
c0395aeb
DH
828 }
829
ec2c7b56 830 p->queue_overflow = false;
c0395aeb
DH
831 return 1;
832}
833
d27efd93 834static int proxy_process_local_to_destination(Proxy *p) {
c0395aeb
DH
835 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
836 int r;
837
838 assert(p);
839
840 r = sd_bus_process(p->local_bus, &m);
557b5d4a 841 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
418e4cb0 842 return r;
c0395aeb 843 if (r < 0) {
418e4cb0 844 log_error_errno(r, "Failed to process local bus: %m");
c0395aeb
DH
845 return r;
846 }
c0395aeb
DH
847 if (r == 0)
848 return 0;
849 if (!m)
850 return 1;
851
852 /* We officially got EOF, let's quit */
853 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected"))
854 return -ECONNRESET;
855
856 r = process_hello(p, m);
c74f883c
LP
857 if (r == -ECONNRESET || r == -ENOTCONN)
858 return r;
c0395aeb
DH
859 if (r < 0)
860 return log_error_errno(r, "Failed to process HELLO: %m");
418e4cb0 861 if (r > 0)
c0395aeb
DH
862 return 1;
863
e23bc0e7 864 r = bus_proxy_process_driver(p, p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
c74f883c
LP
865 if (r == -ECONNRESET || r == -ENOTCONN)
866 return r;
c0395aeb
DH
867 if (r < 0)
868 return log_error_errno(r, "Failed to process driver calls: %m");
418e4cb0 869 if (r > 0)
c0395aeb
DH
870 return 1;
871
872 for (;;) {
873 if (p->policy) {
d27efd93 874 r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names);
c74f883c
LP
875 if (r == -ECONNRESET || r == -ENOTCONN)
876 return r;
c0395aeb
DH
877 if (r < 0)
878 return log_error_errno(r, "Failed to process policy: %m");
c74f883c 879 if (r > 0)
c0395aeb
DH
880 return 1;
881 }
882
d27efd93 883 r = sd_bus_send(p->destination_bus, m, NULL);
c0395aeb 884 if (r < 0) {
557b5d4a 885 if (r == -ECONNRESET || r == -ENOTCONN)
5f6cb091
LP
886 return r;
887
888 /* The name database changed since the policy check, hence let's check again */
889 if (r == -EREMCHG)
c0395aeb 890 continue;
5f6cb091 891
2c960818
DH
892 /* see above why EBADSLT is ignored for replies */
893 if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
c0395aeb 894 return 1;
5f6cb091
LP
895
896 synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m");
e2856931
DH
897 log_error_errno(r,
898 "Failed to forward message we got from local: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m",
899 p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type),
900 strna(m->destination), strna(m->path), strna(m->interface), strna(m->member));
5f6cb091 901 return 1;
c0395aeb
DH
902 }
903
904 break;
905 }
906
907 return 1;
908}
909
e23bc0e7
DH
910int proxy_match(sd_bus_message *m, void *userdata, sd_bus_error *error) {
911 Proxy *p = userdata;
912
913 p->message_matched = true;
914 return 0; /* make sure to continue processing it in further handlers */
915}
916
c0395aeb
DH
917int proxy_run(Proxy *p) {
918 int r;
919
920 assert(p);
921
922 for (;;) {
923 bool busy = false;
924
925 if (p->got_hello) {
926 /* Read messages from bus, to pass them on to our client */
d27efd93 927 r = proxy_process_destination_to_local(p);
557b5d4a 928 if (r == -ECONNRESET || r == -ENOTCONN)
c0395aeb 929 return 0;
418e4cb0 930 if (r < 0)
c0395aeb 931 return r;
418e4cb0 932 if (r > 0)
c0395aeb
DH
933 busy = true;
934 }
935
936 /* Read messages from our client, to pass them on to the bus */
d27efd93 937 r = proxy_process_local_to_destination(p);
557b5d4a 938 if (r == -ECONNRESET || r == -ENOTCONN)
c0395aeb 939 return 0;
418e4cb0 940 if (r < 0)
c0395aeb 941 return r;
418e4cb0 942 if (r > 0)
c0395aeb
DH
943 busy = true;
944
945 if (!busy) {
946 r = proxy_wait(p);
c74f883c
LP
947 if (r == -ECONNRESET || r == -ENOTCONN)
948 return 0;
c0395aeb
DH
949 if (r < 0)
950 return r;
951 }
952 }
953
954 return 0;
955}