]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/bus-proxyd/proxy.c
tty-ask-password: Split out password sending
[thirdparty/systemd.git] / src / bus-proxyd / proxy.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 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
25 #include <errno.h>
26 #include <poll.h>
27 #include <string.h>
28 #include <sys/socket.h>
29 #include <sys/types.h>
30
31 #include "sd-bus.h"
32 #include "sd-daemon.h"
33
34 #include "alloc-util.h"
35 #include "bus-control.h"
36 #include "bus-internal.h"
37 #include "bus-message.h"
38 #include "bus-util.h"
39 #include "bus-xml-policy.h"
40 #include "driver.h"
41 #include "fd-util.h"
42 #include "formats-util.h"
43 #include "log.h"
44 #include "proxy.h"
45 #include "set.h"
46 #include "strv.h"
47 #include "synthesize.h"
48 #include "user-util.h"
49 #include "util.h"
50
51 static int proxy_create_destination(Proxy *p, const char *destination, const char *local_sec, bool negotiate_fds) {
52 _cleanup_(sd_bus_flush_close_unrefp) sd_bus *b = NULL;
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
63 r = sd_bus_set_address(b, destination);
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
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);
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
79 b->fake_creds.uid = UID_INVALID;
80 b->fake_creds.euid = p->local_creds.uid;
81 b->fake_creds.suid = UID_INVALID;
82 b->fake_creds.fsuid = UID_INVALID;
83 b->fake_creds.gid = GID_INVALID;
84 b->fake_creds.egid = p->local_creds.gid;
85 b->fake_creds.sgid = GID_INVALID;
86 b->fake_creds.fsgid = GID_INVALID;
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
102 p->destination_bus = b;
103 b = NULL;
104 return 0;
105 }
106
107 static int proxy_create_local(Proxy *p, bool negotiate_fds) {
108 sd_id128_t server_id;
109 sd_bus *b;
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
116 r = sd_bus_set_fd(b, p->local_in, p->local_out);
117 if (r < 0) {
118 sd_bus_unref(b);
119 return log_error_errno(r, "Failed to set fds: %m");
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;
125
126 r = sd_bus_get_bus_id(p->destination_bus, &server_id);
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
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);
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
152 return 0;
153 }
154
155 static 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
162 /*
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.
166 */
167 static int proxy_prepare_matches(Proxy *p) {
168 _cleanup_free_ char *match = NULL;
169 const char *unique;
170 int r;
171
172 if (!p->destination_bus->is_kernel)
173 return 0;
174
175 r = sd_bus_get_unique_name(p->destination_bus, &unique);
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
191 r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
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
208 r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
209 if (r < 0)
210 return log_error_errno(r, "Failed to add match for NameAcquired: %m");
211
212 free(match);
213 match = strjoin("type='signal',"
214 "destination='",
215 unique,
216 "'",
217 NULL);
218 if (!match)
219 return log_oom();
220
221 r = sd_bus_add_match(p->destination_bus, NULL, match, proxy_match_synthetic, p);
222 if (r < 0)
223 log_error_errno(r, "Failed to add match for directed signals: %m");
224 /* FIXME: temporarily ignore error to support older kdbus versions */
225
226 return 0;
227 }
228
229 int proxy_new(Proxy **out, int in_fd, int out_fd, const char *destination) {
230 _cleanup_(proxy_freep) Proxy *p = NULL;
231 _cleanup_free_ char *local_sec = NULL;
232 bool is_unix;
233 int r;
234
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
240 p = new0(Proxy, 1);
241 if (!p) {
242 safe_close(in_fd);
243 safe_close(out_fd);
244 return log_oom();
245 }
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
262 r = proxy_create_destination(p, destination, local_sec, is_unix);
263 if (r < 0)
264 return r;
265
266 r = proxy_create_local(p, is_unix);
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;
276
277 return 0;
278 }
279
280 Proxy *proxy_free(Proxy *p) {
281 ProxyActivation *activation;
282
283 if (!p)
284 return NULL;
285
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
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
301 sd_bus_flush_close_unref(p->destination_bus);
302 set_free_free(p->owned_names);
303 free(p);
304
305 return NULL;
306 }
307
308 int proxy_set_policy(Proxy *p, SharedPolicy *sp, char **configuration) {
309 _cleanup_strv_free_ char **strv = NULL;
310 Policy *policy;
311 int r;
312
313 assert(p);
314 assert(sp);
315
316 /* no need to load legacy policy if destination is not kdbus */
317 if (!p->destination_bus->is_kernel)
318 return 0;
319
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
329 if (!configuration) {
330 const char *scope;
331
332 r = sd_bus_get_scope(p->destination_bus, &scope);
333 if (r < 0)
334 return log_error_errno(r, "Couldn't determine bus scope: %m");
335
336 if (streq(scope, "system"))
337 strv = strv_new("/usr/share/dbus-1/system.conf",
338 "/etc/dbus-1/system.conf",
339 "/usr/share/dbus-1/system.d/",
340 "/etc/dbus-1/system.d/",
341 "/etc/dbus-1/system-local.conf",
342 NULL);
343 else if (streq(scope, "user"))
344 strv = strv_new("/usr/share/dbus-1/session.conf",
345 "/etc/dbus-1/session.conf",
346 "/usr/share/dbus-1/session.d/",
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
359 return shared_policy_preload(sp, configuration);
360 }
361
362 int proxy_hello_policy(Proxy *p, uid_t original_uid) {
363 Policy *policy;
364 int r = 0;
365
366 assert(p);
367
368 if (!p->policy)
369 return 0;
370
371 policy = shared_policy_acquire(p->policy);
372
373 if (p->local_creds.uid == original_uid)
374 log_debug("Permitting access, since bus owner matches bus client.");
375 else if (policy_check_hello(policy, p->local_creds.uid, p->local_creds.gid))
376 log_debug("Permitting access due to XML policy.");
377 else
378 r = log_error_errno(EPERM, "Policy denied connection.");
379
380 shared_policy_release(p->policy, policy);
381
382 return r;
383 }
384
385 static int proxy_wait(Proxy *p) {
386 uint64_t timeout_destination, timeout_local, t;
387 int events_destination, events_local, fd;
388 struct timespec _ts, *ts;
389 struct pollfd *pollfd;
390 int r;
391
392 assert(p);
393
394 fd = sd_bus_get_fd(p->destination_bus);
395 if (fd < 0)
396 return log_error_errno(fd, "Failed to get fd: %m");
397
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");
401
402 r = sd_bus_get_timeout(p->destination_bus, &timeout_destination);
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
414 t = timeout_destination;
415 if (t == (uint64_t) -1 || (timeout_local != (uint64_t) -1 && timeout_local < timeout_destination))
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]) {
433 { .fd = fd, .events = events_destination, },
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
445 static 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
452 static int process_policy_unlocked(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
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;
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. */
488 (void) sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
489
490 (void) sd_bus_creds_get_euid(&m->creds, &sender_uid);
491 (void) sd_bus_creds_get_egid(&m->creds, &sender_gid);
492
493 if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
494 _cleanup_(sd_bus_creds_unrefp) 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
503 r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID, true, &sender_creds);
504 if (r < 0)
505 return handle_policy_error(m, r);
506
507 (void) sd_bus_creds_get_euid(sender_creds, &sender_uid);
508 (void) sd_bus_creds_get_egid(sender_creds, &sender_gid);
509 }
510
511 /* First check whether the sender can send the message to our name */
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;
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_(sd_bus_creds_unrefp) 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;
530 char *n;
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|
540 SD_BUS_CREDS_EUID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_PID,
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
549 (void) sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
550
551 (void) sd_bus_creds_get_euid(destination_creds, &destination_uid);
552 (void) sd_bus_creds_get_egid(destination_creds, &destination_gid);
553 }
554
555 /* First check if we (the sender) can send to this name */
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)) {
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;
581 }
582
583 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, owned_names, NULL, m->path, m->interface, m->member, true))
584 return 0;
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
598 static 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
611 static int process_hello(Proxy *p, sd_bus_message *m) {
612 _cleanup_(sd_bus_message_unrefp) 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
631 return log_error_errno(EIO, "First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
632 }
633
634 if (p->got_hello)
635 return log_error_errno(EIO, "Got duplicate hello, aborting.");
636
637 p->got_hello = true;
638
639 if (!p->destination_bus->is_kernel)
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
646 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
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
672 r = sd_bus_message_append(n, "s", p->destination_bus->unique_name);
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
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
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
695 static 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
725 static int proxy_process_destination_to_local(Proxy *p) {
726 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
727 bool matched, matched_synthetic;
728 int r;
729
730 assert(p);
731
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
742 r = sd_bus_process(p->destination_bus, &m);
743
744 matched = p->message_matched;
745 matched_synthetic = p->synthetic_matched;
746 p->message_matched = false;
747 p->synthetic_matched = false;
748
749 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
750 return r;
751 if (r < 0) {
752 log_error_errno(r, "Failed to process destination bus: %m");
753 return r;
754 }
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
764 r = synthesize_name_acquired(p, p->destination_bus, p->local_bus, m);
765 if (r == -ECONNRESET || r == -ENOTCONN)
766 return r;
767 if (r < 0)
768 return log_error_errno(r, "Failed to synthesize message: %m");
769
770 /* discard broadcasts that were not matched by any MATCH rule */
771 if (!matched && !sd_bus_message_get_destination(m)) {
772 if (!matched_synthetic)
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));
776 return 1;
777 }
778
779 patch_sender(p->destination_bus, m);
780
781 if (p->policy) {
782 r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
783 if (r == -ECONNRESET || r == -ENOTCONN)
784 return r;
785 if (r < 0)
786 return log_error_errno(r, "Failed to process policy: %m");
787 if (r > 0)
788 return 1;
789 }
790
791 r = sd_bus_send(p->local_bus, m, NULL);
792 if (r < 0) {
793 if (r == -ECONNRESET || r == -ENOTCONN)
794 return r;
795
796 /* If the peer tries to send a reply and it is
797 * rejected with EBADSLT by the kernel, we ignore the
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
803 * EBADSLT for all replies. The only downside is, that
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. */
809
810 /* FIXME: remove -EPERM when kdbus is updated */
811 if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
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");
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
827 return 1;
828 }
829
830 p->queue_overflow = false;
831 return 1;
832 }
833
834 static int proxy_process_local_to_destination(Proxy *p) {
835 _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
836 int r;
837
838 assert(p);
839
840 r = sd_bus_process(p->local_bus, &m);
841 if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */
842 return r;
843 if (r < 0) {
844 log_error_errno(r, "Failed to process local bus: %m");
845 return r;
846 }
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);
857 if (r == -ECONNRESET || r == -ENOTCONN)
858 return r;
859 if (r < 0)
860 return log_error_errno(r, "Failed to process HELLO: %m");
861 if (r > 0)
862 return 1;
863
864 r = bus_proxy_process_driver(p, p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names);
865 if (r == -ECONNRESET || r == -ENOTCONN)
866 return r;
867 if (r < 0)
868 return log_error_errno(r, "Failed to process driver calls: %m");
869 if (r > 0)
870 return 1;
871
872 for (;;) {
873 if (p->policy) {
874 r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names);
875 if (r == -ECONNRESET || r == -ENOTCONN)
876 return r;
877 if (r < 0)
878 return log_error_errno(r, "Failed to process policy: %m");
879 if (r > 0)
880 return 1;
881 }
882
883 r = sd_bus_send(p->destination_bus, m, NULL);
884 if (r < 0) {
885 if (r == -ECONNRESET || r == -ENOTCONN)
886 return r;
887
888 /* The name database changed since the policy check, hence let's check again */
889 if (r == -EREMCHG)
890 continue;
891
892 /* see above why EBADSLT is ignored for replies */
893 if ((r == -EPERM || r == -EBADSLT) && m->reply_cookie > 0)
894 return 1;
895
896 synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m");
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));
901 return 1;
902 }
903
904 break;
905 }
906
907 return 1;
908 }
909
910 int 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
917 int 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 */
927 r = proxy_process_destination_to_local(p);
928 if (r == -ECONNRESET || r == -ENOTCONN)
929 return 0;
930 if (r < 0)
931 return r;
932 if (r > 0)
933 busy = true;
934 }
935
936 /* Read messages from our client, to pass them on to the bus */
937 r = proxy_process_local_to_destination(p);
938 if (r == -ECONNRESET || r == -ENOTCONN)
939 return 0;
940 if (r < 0)
941 return r;
942 if (r > 0)
943 busy = true;
944
945 if (!busy) {
946 r = proxy_wait(p);
947 if (r == -ECONNRESET || r == -ENOTCONN)
948 return 0;
949 if (r < 0)
950 return r;
951 }
952 }
953
954 return 0;
955 }