chiark / gitweb /
b6933417a1519dda59c422cde602410021f6343f
[elogind.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 #include "driver.h"
52 #include "synthesize.h"
53
54 static char *arg_address = NULL;
55 static char *arg_command_line_buffer = NULL;
56 static bool arg_drop_privileges = false;
57 static char **arg_configuration = NULL;
58
59 static int help(void) {
60
61         printf("%s [OPTIONS...]\n\n"
62                "Connect STDIO or a socket to a given bus address.\n\n"
63                "  -h --help               Show this help\n"
64                "     --version            Show package version\n"
65                "     --drop-privileges    Drop privileges\n"
66                "     --configuration=PATH Configuration file or directory\n"
67                "     --machine=MACHINE    Connect to specified machine\n"
68                "     --address=ADDRESS    Connect to the bus specified by ADDRESS\n"
69                "                          (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
70                program_invocation_short_name);
71
72         return 0;
73 }
74
75 static int parse_argv(int argc, char *argv[]) {
76
77         enum {
78                 ARG_VERSION = 0x100,
79                 ARG_ADDRESS,
80                 ARG_DROP_PRIVILEGES,
81                 ARG_CONFIGURATION,
82                 ARG_MACHINE,
83         };
84
85         static const struct option options[] = {
86                 { "help",            no_argument,       NULL, 'h'                 },
87                 { "version",         no_argument,       NULL, ARG_VERSION         },
88                 { "address",         required_argument, NULL, ARG_ADDRESS         },
89                 { "drop-privileges", no_argument,       NULL, ARG_DROP_PRIVILEGES },
90                 { "configuration",   required_argument, NULL, ARG_CONFIGURATION   },
91                 { "machine",         required_argument, NULL, ARG_MACHINE         },
92                 {},
93         };
94
95         int c, r;
96
97         assert(argc >= 0);
98         assert(argv);
99
100         while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
101
102                 switch (c) {
103
104                 case 'h':
105                         help();
106                         return 0;
107
108                 case ARG_VERSION:
109                         puts(PACKAGE_STRING);
110                         puts(SYSTEMD_FEATURES);
111                         return 0;
112
113                 case ARG_ADDRESS: {
114                         char *a;
115
116                         a = strdup(optarg);
117                         if (!a)
118                                 return log_oom();
119
120                         free(arg_address);
121                         arg_address = a;
122                         break;
123                 }
124
125                 case ARG_DROP_PRIVILEGES:
126                         arg_drop_privileges = true;
127                         break;
128
129                 case ARG_CONFIGURATION:
130                         r = strv_extend(&arg_configuration, optarg);
131                         if (r < 0)
132                                 return log_oom();
133                         break;
134
135                 case ARG_MACHINE: {
136                         _cleanup_free_ char *e = NULL;
137                         char *a;
138
139                         e = bus_address_escape(optarg);
140                         if (!e)
141                                 return log_oom();
142
143 #ifdef ENABLE_KDBUS
144                         a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
145 #else
146                         a = strjoin("x-machine-unix:machine=", e, NULL);
147 #endif
148                         if (!a)
149                                 return log_oom();
150
151                         free(arg_address);
152                         arg_address = a;
153
154                         break;
155                 }
156
157                 case '?':
158                         return -EINVAL;
159
160                 default:
161                         assert_not_reached("Unhandled option");
162                 }
163
164         /* If the first command line argument is only "x" characters
165          * we'll write who we are talking to into it, so that "ps" is
166          * explanatory */
167         arg_command_line_buffer = argv[optind];
168         if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
169                 log_error("Too many arguments");
170                 return -EINVAL;
171         }
172
173         if (!arg_address) {
174                 arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
175                 if (!arg_address)
176                         return log_oom();
177         }
178
179         return 1;
180 }
181
182 static int rename_service(sd_bus *a, sd_bus *b) {
183         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
184         _cleanup_free_ char *p = NULL, *name = NULL;
185         const char *comm;
186         char **cmdline;
187         uid_t uid;
188         pid_t pid;
189         int r;
190
191         assert(a);
192         assert(b);
193
194         r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds);
195         if (r < 0)
196                 return r;
197
198         r = sd_bus_creds_get_uid(creds, &uid);
199         if (r < 0)
200                 return r;
201
202         r = sd_bus_creds_get_pid(creds, &pid);
203         if (r < 0)
204                 return r;
205
206         r = sd_bus_creds_get_cmdline(creds, &cmdline);
207         if (r < 0)
208                 return r;
209
210         r = sd_bus_creds_get_comm(creds, &comm);
211         if (r < 0)
212                 return r;
213
214         name = uid_to_name(uid);
215         if (!name)
216                 return -ENOMEM;
217
218         p = strv_join(cmdline, " ");
219         if (!p)
220                 return -ENOMEM;
221
222         /* The status string gets the full command line ... */
223         sd_notifyf(false,
224                    "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
225                    pid, p,
226                    uid, name);
227
228         /* ... and the argv line only the short comm */
229         if (arg_command_line_buffer) {
230                 size_t m, w;
231
232                 m = strlen(arg_command_line_buffer);
233                 w = snprintf(arg_command_line_buffer, m,
234                              "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
235                              pid, comm,
236                              uid, name);
237
238                 if (m > w)
239                         memzero(arg_command_line_buffer + w, m - w);
240         }
241
242         log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
243                   pid, p,
244                   uid, name,
245                   a->unique_name);
246
247         return 0;
248 }
249
250 static int handle_policy_error(sd_bus_message *m, int r) {
251         if (r == -ESRCH || r == -ENXIO)
252                 return synthetic_reply_method_errorf(m, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", m->destination);
253
254         return r;
255 }
256
257 static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *policy, const struct ucred *our_ucred, Set *owned_names) {
258         int r;
259
260         assert(from);
261         assert(to);
262         assert(m);
263
264         if (!policy)
265                 return 0;
266
267         /*
268          * dbus-1 distinguishes expected and non-expected replies by tracking
269          * method-calls and timeouts. By default, DENY rules are *NEVER* applied
270          * on expected replies, unless explicitly specified. But we dont track
271          * method-calls, thus, we cannot know whether a reply is expected.
272          * Fortunately, the kdbus forbids non-expected replies, so we can safely
273          * ignore any policy on those and let the kernel deal with it.
274          *
275          * TODO: To be correct, we should only ignore policy-tags that are
276          * applied on non-expected replies. However, so far we don't parse those
277          * tags so we let everything pass. I haven't seen a DENY policy tag on
278          * expected-replies, ever, so don't bother..
279          */
280         if (m->reply_cookie > 0)
281                 return 0;
282
283         if (from->is_kernel) {
284                 uid_t sender_uid = UID_INVALID;
285                 gid_t sender_gid = GID_INVALID;
286                 char **sender_names = NULL;
287                 bool granted = false;
288
289                 /* Driver messages are always OK */
290                 if (streq_ptr(m->sender, "org.freedesktop.DBus"))
291                         return 0;
292
293                 /* The message came from the kernel, and is sent to our legacy client. */
294                 sd_bus_creds_get_well_known_names(&m->creds, &sender_names);
295
296                 (void) sd_bus_creds_get_uid(&m->creds, &sender_uid);
297                 (void) sd_bus_creds_get_gid(&m->creds, &sender_gid);
298
299                 if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) {
300                         _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL;
301
302                         /* If the message came from another legacy
303                          * client, then the message creds will be
304                          * missing, simply because on legacy clients
305                          * per-message creds were unknown. In this
306                          * case, query the creds of the peer
307                          * instead. */
308
309                         r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_UID|SD_BUS_CREDS_GID, true, &sender_creds);
310                         if (r < 0)
311                                 return handle_policy_error(m, r);
312
313                         (void) sd_bus_creds_get_uid(sender_creds, &sender_uid);
314                         (void) sd_bus_creds_get_gid(sender_creds, &sender_gid);
315                 }
316
317                 /* First check whether the sender can send the message to our name */
318                 if (set_isempty(owned_names)) {
319                         if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member, false))
320                                 granted = true;
321                 } else {
322                         Iterator i;
323                         char *n;
324
325                         SET_FOREACH(n, owned_names, i)
326                                 if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, n, m->path, m->interface, m->member, false)) {
327                                         granted = true;
328                                         break;
329                                 }
330                 }
331
332                 if (granted) {
333                         /* Then check whether us (the recipient) can receive from the sender's name */
334                         if (strv_isempty(sender_names)) {
335                                 if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member, false))
336                                         return 0;
337                         } else {
338                                 char **n;
339
340                                 STRV_FOREACH(n, sender_names) {
341                                         if (policy_check_recv(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member, false))
342                                                 return 0;
343                                 }
344                         }
345                 }
346
347                 /* Return an error back to the caller */
348                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
349                         return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML receiver policy.");
350
351                 /* Return 1, indicating that the message shall not be processed any further */
352                 return 1;
353         }
354
355         if (to->is_kernel) {
356                 _cleanup_bus_creds_unref_ sd_bus_creds *destination_creds = NULL;
357                 uid_t destination_uid = UID_INVALID;
358                 gid_t destination_gid = GID_INVALID;
359                 const char *destination_unique = NULL;
360                 char **destination_names = NULL;
361                 bool granted = false;
362
363                 /* Driver messages are always OK */
364                 if (streq_ptr(m->destination, "org.freedesktop.DBus"))
365                         return 0;
366
367                 /* The message came from the legacy client, and is sent to kdbus. */
368                 if (m->destination) {
369                         r = bus_get_name_creds_kdbus(to, m->destination,
370                                                      SD_BUS_CREDS_WELL_KNOWN_NAMES|SD_BUS_CREDS_UNIQUE_NAME|
371                                                      SD_BUS_CREDS_UID|SD_BUS_CREDS_GID|SD_BUS_CREDS_PID,
372                                                      true, &destination_creds);
373                         if (r < 0)
374                                 return handle_policy_error(m, r);
375
376                         r = sd_bus_creds_get_unique_name(destination_creds, &destination_unique);
377                         if (r < 0)
378                                 return handle_policy_error(m, r);
379
380                         sd_bus_creds_get_well_known_names(destination_creds, &destination_names);
381
382                         (void) sd_bus_creds_get_uid(destination_creds, &destination_uid);
383                         (void) sd_bus_creds_get_gid(destination_creds, &destination_gid);
384                 }
385
386                 /* First check if we (the sender) can send to this name */
387                 if (strv_isempty(destination_names)) {
388                         if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, NULL, m->path, m->interface, m->member, true))
389                                 granted = true;
390                 } else {
391                         char **n;
392
393                         STRV_FOREACH(n, destination_names) {
394                                 if (policy_check_send(policy, our_ucred->uid, our_ucred->gid, m->header->type, *n, m->path, m->interface, m->member, true)) {
395
396                                         /* If we made a receiver decision,
397                                            then remember which name's policy
398                                            we used, and to which unique ID it
399                                            mapped when we made the
400                                            decision. Then, let's pass this to
401                                            the kernel when sending the
402                                            message, so that it refuses the
403                                            operation should the name and
404                                            unique ID not map to each other
405                                            anymore. */
406
407                                         r = free_and_strdup(&m->destination_ptr, *n);
408                                         if (r < 0)
409                                                 return r;
410
411                                         r = bus_kernel_parse_unique_name(destination_unique, &m->verify_destination_id);
412                                         if (r < 0)
413                                                 break;
414
415                                         granted = true;
416                                         break;
417                                 }
418                         }
419                 }
420
421                 /* Then check if the recipient can receive from our name */
422                 if (granted) {
423                         if (sd_bus_message_is_signal(m, NULL, NULL)) {
424                                 /* If we forward a signal from dbus-1 to kdbus,
425                                  * we have no idea who the recipient is.
426                                  * Therefore, we cannot apply any dbus-1
427                                  * receiver policies that match on receiver
428                                  * credentials. We know sd-bus always sets
429                                  * KDBUS_MSG_SIGNAL, so the kernel applies
430                                  * receiver policies to the message. Therefore,
431                                  * skip policy checks in this case. */
432                                 return 0;
433                         } else if (set_isempty(owned_names)) {
434                                 if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, NULL, m->path, m->interface, m->member, true))
435                                         return 0;
436                         } else {
437                                 Iterator i;
438                                 char *n;
439
440                                 SET_FOREACH(n, owned_names, i)
441                                         if (policy_check_recv(policy, destination_uid, destination_gid, m->header->type, n, m->path, m->interface, m->member, true))
442                                                 return 0;
443                         }
444                 }
445
446                 /* Return an error back to the caller */
447                 if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
448                         return synthetic_reply_method_errorf(m, SD_BUS_ERROR_ACCESS_DENIED, "Access prohibited by XML sender policy.");
449
450                 /* Return 1, indicating that the message shall not be processed any further */
451                 return 1;
452         }
453
454         return 0;
455 }
456
457 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
458         _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
459         bool is_hello;
460         int r;
461
462         assert(a);
463         assert(b);
464         assert(m);
465         assert(got_hello);
466
467         /* As reaction to hello we need to respond with two messages:
468          * the callback reply and the NameAcquired for the unique
469          * name, since hello is otherwise obsolete on kdbus. */
470
471         is_hello =
472                 sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "Hello") &&
473                 streq_ptr(m->destination, "org.freedesktop.DBus");
474
475         if (!is_hello) {
476
477                 if (*got_hello)
478                         return 0;
479
480                 log_error("First packet isn't hello (it's %s.%s), aborting.", m->interface, m->member);
481                 return -EIO;
482         }
483
484         if (*got_hello) {
485                 log_error("Got duplicate hello, aborting.");
486                 return -EIO;
487         }
488
489         *got_hello = true;
490
491         if (!a->is_kernel)
492                 return 0;
493
494         r = sd_bus_message_new_method_return(m, &n);
495         if (r < 0)
496                 return log_error_errno(r, "Failed to generate HELLO reply: %m");
497
498         r = sd_bus_message_append(n, "s", a->unique_name);
499         if (r < 0)
500                 return log_error_errno(r, "Failed to append unique name to HELLO reply: %m");
501
502         r = bus_message_append_sender(n, "org.freedesktop.DBus");
503         if (r < 0)
504                 return log_error_errno(r, "Failed to append sender to HELLO reply: %m");
505
506         r = bus_seal_synthetic_message(b, n);
507         if (r < 0)
508                 return log_error_errno(r, "Failed to seal HELLO reply: %m");
509
510         r = sd_bus_send(b, n, NULL);
511         if (r < 0)
512                 return log_error_errno(r, "Failed to send HELLO reply: %m");
513
514         n = sd_bus_message_unref(n);
515         r = sd_bus_message_new_signal(
516                         b,
517                         &n,
518                         "/org/freedesktop/DBus",
519                         "org.freedesktop.DBus",
520                         "NameAcquired");
521         if (r < 0)
522                 return log_error_errno(r, "Failed to allocate initial NameAcquired message: %m");
523
524         r = sd_bus_message_append(n, "s", a->unique_name);
525         if (r < 0)
526                 return log_error_errno(r, "Failed to append unique name to NameAcquired message: %m");
527
528         r = bus_message_append_sender(n, "org.freedesktop.DBus");
529         if (r < 0)
530                 return log_error_errno(r, "Failed to append sender to NameAcquired message: %m");
531
532         r = bus_seal_synthetic_message(b, n);
533         if (r < 0)
534                 return log_error_errno(r, "Failed to seal NameAcquired message: %m");
535
536         r = sd_bus_send(b, n, NULL);
537         if (r < 0)
538                 return log_error_errno(r, "Failed to send NameAcquired message: %m");
539
540         return 1;
541 }
542
543 static int patch_sender(sd_bus *a, sd_bus_message *m) {
544         char **well_known = NULL;
545         sd_bus_creds *c;
546         int r;
547
548         assert(a);
549         assert(m);
550
551         if (!a->is_kernel)
552                 return 0;
553
554         /* We will change the sender of messages from the bus driver
555          * so that they originate from the bus driver. This is a
556          * speciality originating from dbus1, where the bus driver did
557          * not have a unique id, but only the well-known name. */
558
559         c = sd_bus_message_get_creds(m);
560         if (!c)
561                 return 0;
562
563         r = sd_bus_creds_get_well_known_names(c, &well_known);
564         if (r < 0)
565                 return r;
566
567         if (strv_contains(well_known, "org.freedesktop.DBus"))
568                 m->sender = "org.freedesktop.DBus";
569
570         return 0;
571 }
572
573 static int bus_new_destination(sd_bus **out, struct ucred *ucred, const char *peersec, bool negotiate_fds) {
574         _cleanup_bus_close_unref_ sd_bus *a = NULL;
575         int r;
576
577         r = sd_bus_new(&a);
578         if (r < 0)
579                 return log_error_errno(r, "Failed to allocate bus: %m");
580
581         r = sd_bus_set_description(a, "sd-proxy");
582         if (r < 0)
583                 return log_error_errno(r, "Failed to set bus name: %m");
584
585         r = sd_bus_set_address(a, arg_address);
586         if (r < 0)
587                 return log_error_errno(r, "Failed to set address to connect to: %m");
588
589         r = sd_bus_negotiate_fds(a, negotiate_fds);
590         if (r < 0)
591                 return log_error_errno(r, "Failed to set FD negotiation: %m");
592
593         r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
594         if (r < 0)
595                 return log_error_errno(r, "Failed to set credential negotiation: %m");
596
597         if (ucred->pid > 0) {
598                 a->fake_pids.pid = ucred->pid;
599                 a->fake_pids_valid = true;
600
601                 a->fake_creds.uid = ucred->uid;
602                 a->fake_creds.euid = UID_INVALID;
603                 a->fake_creds.suid = UID_INVALID;
604                 a->fake_creds.fsuid = UID_INVALID;
605                 a->fake_creds.gid = ucred->gid;
606                 a->fake_creds.egid = GID_INVALID;
607                 a->fake_creds.sgid = GID_INVALID;
608                 a->fake_creds.fsgid = GID_INVALID;
609                 a->fake_creds_valid = true;
610         }
611
612         if (peersec) {
613                 a->fake_label = strdup(peersec);
614                 if (!a->fake_label)
615                         return log_oom();
616         }
617
618         a->manual_peer_interface = true;
619
620         r = sd_bus_start(a);
621         if (r < 0)
622                 return log_error_errno(r, "Failed to start bus client: %m");
623
624         *out = a;
625         a = NULL;
626         return 0;
627 }
628
629 static int bus_new_local(sd_bus **out, sd_bus *dest, int in_fd, int out_fd, bool negotiate_fds) {
630         _cleanup_bus_close_unref_ sd_bus *b = NULL;
631         sd_id128_t server_id;
632         int r;
633
634         r = sd_bus_new(&b);
635         if (r < 0)
636                 return log_error_errno(r, "Failed to allocate bus: %m");
637
638         r = sd_bus_set_fd(b, in_fd, out_fd);
639         if (r < 0)
640                 return log_error_errno(r, "Failed to set fds: %m");
641
642         r = sd_bus_get_bus_id(dest, &server_id);
643         if (r < 0)
644                 return log_error_errno(r, "Failed to get server ID: %m");
645
646         r = sd_bus_set_server(b, 1, server_id);
647         if (r < 0)
648                 return log_error_errno(r, "Failed to set server mode: %m");
649
650         r = sd_bus_negotiate_fds(b, negotiate_fds);
651         if (r < 0)
652                 return log_error_errno(r, "Failed to set FD negotiation: %m");
653
654         r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT);
655         if (r < 0)
656                 return log_error_errno(r, "Failed to set credential negotiation: %m");
657
658         r = sd_bus_set_anonymous(b, true);
659         if (r < 0)
660                 return log_error_errno(r, "Failed to set anonymous authentication: %m");
661
662         b->manual_peer_interface = true;
663
664         r = sd_bus_start(b);
665         if (r < 0)
666                 return log_error_errno(r, "Failed to start bus client: %m");
667
668         *out = b;
669         b = NULL;
670         return 0;
671 }
672
673 static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) {
674 #ifdef HAVE_SMACK
675         int r = 0, k;
676
677         if (!mac_smack_use())
678                 return 0;
679
680         if (new_label && its_pid > 0)
681                 r = mac_smack_apply_pid(its_pid, new_label);
682
683         k = drop_capability(CAP_MAC_ADMIN);
684         return r < 0 ? r : k;
685 #else
686         return 0;
687 #endif
688 }
689
690
691 int main(int argc, char *argv[]) {
692
693         _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL;
694         int r, in_fd, out_fd;
695         bool got_hello = false;
696         bool is_unix;
697         struct ucred ucred = {};
698         _cleanup_free_ char *peersec = NULL;
699         Policy policy_buffer = {}, *policy = NULL;
700         _cleanup_set_free_free_ Set *owned_names = NULL;
701         uid_t original_uid;
702
703         log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
704         log_parse_environment();
705         log_open();
706
707         r = parse_argv(argc, argv);
708         if (r <= 0)
709                 goto finish;
710
711         r = sd_listen_fds(0);
712         if (r == 0) {
713                 in_fd = STDIN_FILENO;
714                 out_fd = STDOUT_FILENO;
715         } else if (r == 1) {
716                 in_fd = SD_LISTEN_FDS_START;
717                 out_fd = SD_LISTEN_FDS_START;
718         } else {
719                 log_error("Illegal number of file descriptors passed");
720                 goto finish;
721         }
722
723         original_uid = getuid();
724
725         is_unix =
726                 sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 &&
727                 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
728
729         if (is_unix) {
730                 (void) getpeercred(in_fd, &ucred);
731                 (void) getpeersec(in_fd, &peersec);
732
733                 r = mac_smack_apply_label_and_drop_cap_mac_admin(getpid(), peersec);
734                 if (r < 0)
735                         log_warning_errno(r, "Failed to set SMACK label (%s) and drop CAP_MAC_ADMIN: %m", peersec);
736         }
737
738         if (arg_drop_privileges) {
739                 const char *user = "systemd-bus-proxy";
740                 uid_t uid;
741                 gid_t gid;
742
743                 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
744                 if (r < 0) {
745                         log_error_errno(r, "Cannot resolve user name %s: %m", user);
746                         goto finish;
747                 }
748
749                 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
750                 if (r < 0)
751                         goto finish;
752         }
753
754         owned_names = set_new(&string_hash_ops);
755         if (!owned_names) {
756                 log_oom();
757                 goto finish;
758         }
759
760         r = bus_new_destination(&a, &ucred, peersec, is_unix);
761         if (r < 0)
762                 goto finish;
763
764         if (a->is_kernel) {
765                 if (!arg_configuration) {
766                         const char *scope;
767
768                         r = sd_bus_get_scope(a, &scope);
769                         if (r < 0) {
770                                 log_error_errno(r, "Couldn't determine bus scope: %m");
771                                 goto finish;
772                         }
773
774                         if (streq(scope, "system"))
775                                 arg_configuration = strv_new(
776                                                 "/etc/dbus-1/system.conf",
777                                                 "/etc/dbus-1/system.d/",
778                                                 "/etc/dbus-1/system-local.conf",
779                                                 NULL);
780                         else if (streq(scope, "user"))
781                                 arg_configuration = strv_new(
782                                                 "/etc/dbus-1/session.conf",
783                                                 "/etc/dbus-1/session.d/",
784                                                 "/etc/dbus-1/session-local.conf",
785                                                 NULL);
786                         else {
787                                 log_error("Unknown scope %s, don't know which policy to load. Refusing.", scope);
788                                 goto finish;
789                         }
790
791                         if (!arg_configuration) {
792                                 r = log_oom();
793                                 goto finish;
794                         }
795                 }
796
797                 r = policy_load(&policy_buffer, arg_configuration);
798                 if (r < 0) {
799                         log_error_errno(r, "Failed to load policy: %m");
800                         goto finish;
801                 }
802
803                 policy = &policy_buffer;
804                 /* policy_dump(policy); */
805
806                 if (ucred.uid == original_uid)
807                         log_debug("Permitting access, since bus owner matches bus client.");
808                 else if (policy_check_hello(policy, ucred.uid, ucred.gid))
809                         log_debug("Permitting access due to XML policy.");
810                 else {
811                         r = log_error_errno(EPERM, "Policy denied connection.");
812                         goto finish;
813                 }
814         }
815
816         r = bus_new_local(&b, a, in_fd, out_fd, is_unix);
817         if (r < 0)
818                 goto finish;
819
820         r = rename_service(a, b);
821         if (r < 0)
822                 log_debug_errno(r, "Failed to rename process: %m");
823
824         if (a->is_kernel) {
825                 _cleanup_free_ char *match = NULL;
826                 const char *unique;
827
828                 r = sd_bus_get_unique_name(a, &unique);
829                 if (r < 0) {
830                         log_error_errno(r, "Failed to get unique name: %m");
831                         goto finish;
832                 }
833
834                 match = strjoin("type='signal',"
835                                 "sender='org.freedesktop.DBus',"
836                                 "path='/org/freedesktop/DBus',"
837                                 "interface='org.freedesktop.DBus',"
838                                 "member='NameOwnerChanged',"
839                                 "arg1='",
840                                 unique,
841                                 "'",
842                                 NULL);
843                 if (!match) {
844                         log_oom();
845                         goto finish;
846                 }
847
848                 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
849                 if (r < 0) {
850                         log_error_errno(r, "Failed to add match for NameLost: %m");
851                         goto finish;
852                 }
853
854                 free(match);
855                 match = strjoin("type='signal',"
856                                 "sender='org.freedesktop.DBus',"
857                                 "path='/org/freedesktop/DBus',"
858                                 "interface='org.freedesktop.DBus',"
859                                 "member='NameOwnerChanged',"
860                                 "arg2='",
861                                 unique,
862                                 "'",
863                                 NULL);
864                 if (!match) {
865                         log_oom();
866                         goto finish;
867                 }
868
869                 r = sd_bus_add_match(a, NULL, match, NULL, NULL);
870                 if (r < 0) {
871                         log_error_errno(r, "Failed to add match for NameAcquired: %m");
872                         goto finish;
873                 }
874         }
875
876         for (;;) {
877                 _cleanup_bus_message_unref_ sd_bus_message *m = NULL;
878                 int events_a, events_b, fd;
879                 uint64_t timeout_a, timeout_b, t;
880                 struct timespec _ts, *ts;
881                 struct pollfd *pollfd;
882                 int k;
883
884                 if (got_hello) {
885                         /* Read messages from bus, to pass them on to our client */
886
887                         r = sd_bus_process(a, &m);
888                         if (r < 0) {
889                                 /* treat 'connection reset by peer' as clean exit condition */
890                                 if (r == -ECONNRESET)
891                                         r = 0;
892                                 else
893                                         log_error_errno(r, "Failed to process bus a: %m");
894
895                                 goto finish;
896                         }
897
898                         if (m) {
899                                 bool processed = false;
900
901                                 /* We officially got EOF, let's quit */
902                                 if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
903                                         r = 0;
904                                         goto finish;
905                                 }
906
907                                 k = synthesize_name_acquired(a, b, m);
908                                 if (k < 0) {
909                                         r = k;
910                                         log_error_errno(r, "Failed to synthesize message: %m");
911                                         goto finish;
912                                 }
913
914                                 patch_sender(a, m);
915
916                                 if (policy) {
917                                         k = process_policy(a, b, m, policy, &ucred, owned_names);
918                                         if (k < 0) {
919                                                 r = k;
920                                                 log_error_errno(r, "Failed to process policy: %m");
921                                                 goto finish;
922                                         } else if (k > 0) {
923                                                 r = 1;
924                                                 processed = true;
925                                         }
926                                 }
927
928                                 if (!processed) {
929                                         k = sd_bus_send(b, m, NULL);
930                                         if (k < 0) {
931                                                 if (k == -ECONNRESET) {
932                                                         r = 0;
933                                                         goto finish;
934                                                 } else if (k == -EPERM && m->reply_cookie > 0) {
935                                                         /* If the peer tries to send a reply and it is rejected with EPERM
936                                                          * by the kernel, we ignore the error. This catches cases where the
937                                                          * original method-call didn't had EXPECT_REPLY set, but the proxy-peer
938                                                          * still sends a reply. This is allowed in dbus1, but not in kdbus. We
939                                                          * don't want to track reply-windows in the proxy, so we simply ignore
940                                                          * EPERM for all replies. The only downside is, that callers are no
941                                                          * longer notified if their replies are dropped. However, this is
942                                                          * equivalent to the caller's timeout to expire, so this should be
943                                                          * acceptable. Nobody sane sends replies without a matching method-call,
944                                                          * so nobody should care. */
945                                                         r = 1;
946                                                 } else {
947                                                         r = k;
948                                                         log_error_errno(r, "Failed to send message to client: %m");
949                                                         goto finish;
950                                                 }
951                                         } else
952                                                 r = 1;
953                                 }
954                         }
955
956                         if (r > 0)
957                                 continue;
958                 }
959
960                 /* Read messages from our client, to pass them on to the bus */
961                 r = sd_bus_process(b, &m);
962                 if (r < 0) {
963                         /* treat 'connection reset by peer' as clean exit condition */
964                         if (r == -ECONNRESET)
965                                 r = 0;
966                         else
967                                 log_error_errno(r, "Failed to process bus b: %m");
968
969                         goto finish;
970                 }
971
972                 if (m) {
973                         bool processed = false;
974
975                         /* We officially got EOF, let's quit */
976                         if (sd_bus_message_is_signal(m, "org.freedesktop.DBus.Local", "Disconnected")) {
977                                 r = 0;
978                                 goto finish;
979                         }
980
981                         k = process_hello(a, b, m, &got_hello);
982                         if (k < 0) {
983                                 r = k;
984                                 log_error_errno(r, "Failed to process HELLO: %m");
985                                 goto finish;
986                         } else if (k > 0) {
987                                 processed = true;
988                                 r = 1;
989                         }
990
991                         if (!processed) {
992                                 k = bus_proxy_process_driver(a, b, m, policy, &ucred, owned_names);
993                                 if (k < 0) {
994                                         r = k;
995                                         log_error_errno(r, "Failed to process driver calls: %m");
996                                         goto finish;
997                                 } else if (k > 0) {
998                                         processed = true;
999                                         r = 1;
1000                                 }
1001
1002                                 if (!processed) {
1003
1004                                         for (;;) {
1005                                                 if (policy) {
1006                                                         k = process_policy(b, a, m, policy, &ucred, owned_names);
1007                                                         if (k < 0) {
1008                                                                 r = k;
1009                                                                 log_error_errno(r, "Failed to process policy: %m");
1010                                                                 goto finish;
1011                                                         } else if (k > 0) {
1012                                                                 processed = true;
1013                                                                 r = 1;
1014                                                                 break;
1015                                                         }
1016                                                 }
1017
1018                                                 k = sd_bus_send(a, m, NULL);
1019                                                 if (k < 0) {
1020                                                         if (k == -EREMCHG) {
1021                                                                 /* The name database changed since the policy check, hence let's check again */
1022                                                                 continue;
1023                                                         } else if (k == -ECONNRESET) {
1024                                                                 r = 0;
1025                                                                 goto finish;
1026                                                         } else if (k == -EPERM && m->reply_cookie > 0) {
1027                                                                 /* see above why EPERM is ignored for replies */
1028                                                                 r = 1;
1029                                                         } else {
1030                                                                 r = k;
1031                                                                 log_error_errno(r, "Failed to send message to bus: %m");
1032                                                                 goto finish;
1033                                                         }
1034                                                 } else
1035                                                         r = 1;
1036
1037                                                 break;
1038                                         }
1039                                 }
1040                         }
1041                 }
1042
1043                 if (r > 0)
1044                         continue;
1045
1046                 fd = sd_bus_get_fd(a);
1047                 if (fd < 0) {
1048                         log_error_errno(r, "Failed to get fd: %m");
1049                         goto finish;
1050                 }
1051
1052                 events_a = sd_bus_get_events(a);
1053                 if (events_a < 0) {
1054                         log_error_errno(r, "Failed to get events mask: %m");
1055                         goto finish;
1056                 }
1057
1058                 r = sd_bus_get_timeout(a, &timeout_a);
1059                 if (r < 0) {
1060                         log_error_errno(r, "Failed to get timeout: %m");
1061                         goto finish;
1062                 }
1063
1064                 events_b = sd_bus_get_events(b);
1065                 if (events_b < 0) {
1066                         log_error_errno(r, "Failed to get events mask: %m");
1067                         goto finish;
1068                 }
1069
1070                 r = sd_bus_get_timeout(b, &timeout_b);
1071                 if (r < 0) {
1072                         log_error_errno(r, "Failed to get timeout: %m");
1073                         goto finish;
1074                 }
1075
1076                 t = timeout_a;
1077                 if (t == (uint64_t) -1 || (timeout_b != (uint64_t) -1 && timeout_b < timeout_a))
1078                         t = timeout_b;
1079
1080                 if (t == (uint64_t) -1)
1081                         ts = NULL;
1082                 else {
1083                         usec_t nw;
1084
1085                         nw = now(CLOCK_MONOTONIC);
1086                         if (t > nw)
1087                                 t -= nw;
1088                         else
1089                                 t = 0;
1090
1091                         ts = timespec_store(&_ts, t);
1092                 }
1093
1094                 pollfd = (struct pollfd[3]) {
1095                         {.fd = fd,     .events = events_a,           },
1096                         {.fd = in_fd,  .events = events_b & POLLIN,  },
1097                         {.fd = out_fd, .events = events_b & POLLOUT, }
1098                 };
1099
1100                 r = ppoll(pollfd, 3, ts, NULL);
1101                 if (r < 0) {
1102                         log_error_errno(errno, "ppoll() failed: %m");
1103                         goto finish;
1104                 }
1105         }
1106
1107 finish:
1108         sd_notify(false,
1109                   "STOPPING=1\n"
1110                   "STATUS=Shutting down.");
1111
1112         policy_free(&policy_buffer);
1113         strv_free(arg_configuration);
1114         free(arg_address);
1115
1116         return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
1117 }