1 /*-*- Mode: C; c-basic-offset: 8; indent-tabs-mode: nil -*-*/
4 This file is part of systemd.
6 Copyright 2010 Lennart Poettering
7 Copyright 2013 Daniel Mack
8 Copyright 2014 Kay Sievers
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.
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.
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/>.
24 #include <sys/socket.h>
26 #include <sys/types.h>
37 #include "socket-util.h"
38 #include "sd-daemon.h"
40 #include "bus-internal.h"
41 #include "bus-message.h"
46 #include "capability.h"
47 #include "bus-control.h"
48 #include "smack-util.h"
50 #include "bus-xml-policy.h"
53 #include "synthesize.h"
55 static char *arg_address = NULL;
56 static char *arg_command_line_buffer = NULL;
57 static bool arg_drop_privileges = false;
58 static char **arg_configuration = NULL;
60 static int help(void) {
62 printf("%s [OPTIONS...]\n\n"
63 "Connect STDIO or a socket to a given bus address.\n\n"
64 " -h --help Show this help\n"
65 " --version Show package version\n"
66 " --drop-privileges Drop privileges\n"
67 " --configuration=PATH Configuration file or directory\n"
68 " --machine=MACHINE Connect to specified machine\n"
69 " --address=ADDRESS Connect to the bus specified by ADDRESS\n"
70 " (default: " DEFAULT_SYSTEM_BUS_ADDRESS ")\n",
71 program_invocation_short_name);
76 static int parse_argv(int argc, char *argv[]) {
86 static const struct option options[] = {
87 { "help", no_argument, NULL, 'h' },
88 { "version", no_argument, NULL, ARG_VERSION },
89 { "address", required_argument, NULL, ARG_ADDRESS },
90 { "drop-privileges", no_argument, NULL, ARG_DROP_PRIVILEGES },
91 { "configuration", required_argument, NULL, ARG_CONFIGURATION },
92 { "machine", required_argument, NULL, ARG_MACHINE },
101 while ((c = getopt_long(argc, argv, "h", options, NULL)) >= 0)
110 puts(PACKAGE_STRING);
111 puts(SYSTEMD_FEATURES);
126 case ARG_DROP_PRIVILEGES:
127 arg_drop_privileges = true;
130 case ARG_CONFIGURATION:
131 r = strv_extend(&arg_configuration, optarg);
137 _cleanup_free_ char *e = NULL;
140 e = bus_address_escape(optarg);
145 a = strjoin("x-machine-kernel:machine=", e, ";x-machine-unix:machine=", e, NULL);
147 a = strjoin("x-machine-unix:machine=", e, NULL);
162 assert_not_reached("Unhandled option");
165 /* If the first command line argument is only "x" characters
166 * we'll write who we are talking to into it, so that "ps" is
168 arg_command_line_buffer = argv[optind];
169 if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) {
170 log_error("Too many arguments");
175 arg_address = strdup(DEFAULT_SYSTEM_BUS_ADDRESS);
183 static int rename_service(sd_bus *a, sd_bus *b) {
184 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
185 _cleanup_free_ char *p = NULL, *name = NULL;
195 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);
199 r = sd_bus_creds_get_uid(creds, &uid);
203 r = sd_bus_creds_get_pid(creds, &pid);
207 r = sd_bus_creds_get_cmdline(creds, &cmdline);
211 r = sd_bus_creds_get_comm(creds, &comm);
215 name = uid_to_name(uid);
219 p = strv_join(cmdline, " ");
223 /* The status string gets the full command line ... */
225 "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
229 /* ... and the argv line only the short comm */
230 if (arg_command_line_buffer) {
233 m = strlen(arg_command_line_buffer);
234 w = snprintf(arg_command_line_buffer, m,
235 "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
240 memzero(arg_command_line_buffer + w, m - w);
243 log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
251 int main(int argc, char *argv[]) {
252 _cleanup_(proxy_freep) Proxy *p = NULL;
253 int r, in_fd, out_fd;
256 log_set_target(LOG_TARGET_JOURNAL_OR_KMSG);
257 log_parse_environment();
260 r = parse_argv(argc, argv);
264 r = sd_listen_fds(0);
266 in_fd = STDIN_FILENO;
267 out_fd = STDOUT_FILENO;
269 in_fd = SD_LISTEN_FDS_START;
270 out_fd = SD_LISTEN_FDS_START;
272 log_error("Illegal number of file descriptors passed");
276 original_uid = getuid();
278 if (arg_drop_privileges) {
279 const char *user = "systemd-bus-proxy";
283 r = get_user_creds(&user, &uid, &gid, NULL, NULL);
285 log_error_errno(r, "Cannot resolve user name %s: %m", user);
289 r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER);
294 r = proxy_new(&p, in_fd, out_fd, arg_address);
298 r = proxy_load_policy(p, arg_configuration);
302 r = proxy_hello_policy(p, original_uid);
306 r = rename_service(p->dest_bus, p->local_bus);
308 log_debug_errno(r, "Failed to rename process: %m");
315 "STATUS=Shutting down.");
317 strv_free(arg_configuration);
320 return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;