X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbus-proxyd%2Fbus-proxyd.c;h=1f17fe8c13b138bcf5a054bc02ef26a72356f3ac;hb=e05aa2e02ba35d8b3741dddb79af3c802308414b;hp=e095d61ffbd6a1dd8ce1b8c997b8324325fe22db;hpb=19befb2d5fc087f96e40ddc432b2cc9385666209;p=elogind.git diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index e095d61ff..1f17fe8c1 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -44,18 +44,25 @@ #include "build.h" #include "strv.h" #include "def.h" +#include "capability.h" +#include "bus-policy.h" -static const char *arg_address = DEFAULT_SYSTEM_BUS_PATH; +static char *arg_address = NULL; static char *arg_command_line_buffer = NULL; +static bool arg_drop_privileges = false; +static char **arg_configuration = NULL; static int help(void) { printf("%s [OPTIONS...]\n\n" "Connect STDIO or a socket to a given bus address.\n\n" - " -h --help Show this help\n" - " --version Show package version\n" - " --address=ADDRESS Connect to the bus specified by ADDRESS\n" - " (default: " DEFAULT_SYSTEM_BUS_PATH ")\n", + " -h --help Show this help\n" + " --version Show package version\n" + " --drop-privileges Drop privileges\n" + " --configuration=PATH Configuration file or directory\n" + " --machine=MACHINE Connect to specified machine\n" + " --address=ADDRESS Connect to the bus specified by ADDRESS\n" + " (default: " DEFAULT_SYSTEM_BUS_PATH ")\n", program_invocation_short_name); return 0; @@ -66,16 +73,22 @@ static int parse_argv(int argc, char *argv[]) { enum { ARG_VERSION = 0x100, ARG_ADDRESS, + ARG_DROP_PRIVILEGES, + ARG_CONFIGURATION, + ARG_MACHINE, }; static const struct option options[] = { - { "help", no_argument, NULL, 'h' }, - { "version", no_argument, NULL, ARG_VERSION }, - { "address", required_argument, NULL, ARG_ADDRESS }, - { NULL, 0, NULL, 0 } + { "help", no_argument, NULL, 'h' }, + { "version", no_argument, NULL, ARG_VERSION }, + { "address", required_argument, NULL, ARG_ADDRESS }, + { "drop-privileges", no_argument, NULL, ARG_DROP_PRIVILEGES }, + { "configuration", required_argument, NULL, ARG_CONFIGURATION }, + { "machine", required_argument, NULL, ARG_MACHINE }, + {}, }; - int c; + int c, r; assert(argc >= 0); assert(argv); @@ -93,9 +106,49 @@ static int parse_argv(int argc, char *argv[]) { puts(SYSTEMD_FEATURES); return 0; - case ARG_ADDRESS: - arg_address = optarg; + case ARG_ADDRESS: { + char *a; + + a = strdup(optarg); + if (!a) + return log_oom(); + + free(arg_address); + arg_address = a; + break; + } + + case ARG_DROP_PRIVILEGES: + arg_drop_privileges = true; + break; + + case ARG_CONFIGURATION: + r = strv_extend(&arg_configuration, optarg); + if (r < 0) + return log_oom(); + break; + + case ARG_MACHINE: { + _cleanup_free_ char *e = NULL; + char *a; + + e = bus_address_escape(optarg); + if (!e) + return log_oom(); + +#ifdef ENABLE_KDBUS + a = strjoin("x-container-kernel:machine=", e, ";x-container-unix:machine=", e, NULL); +#else + a = strjoin("x-container-unix:machine=", e, NULL); +#endif + if (!a) + return log_oom(); + + free(arg_address); + arg_address = a; + break; + } case '?': return -EINVAL; @@ -109,12 +162,17 @@ static int parse_argv(int argc, char *argv[]) { * we'll write who we are talking to into it, so that "ps" is * explanatory */ arg_command_line_buffer = argv[optind]; - if (argc > optind + 1 || - (arg_command_line_buffer && arg_command_line_buffer[strspn(arg_command_line_buffer, "x")] != 0)) { + if (argc > optind + 1 || (arg_command_line_buffer && !in_charset(arg_command_line_buffer, "x"))) { log_error("Too many arguments"); return -EINVAL; } + if (!arg_address) { + arg_address = strdup(DEFAULT_SYSTEM_BUS_PATH); + if (!arg_address) + return log_oom(); + } + return 1; } @@ -261,6 +319,9 @@ static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m) { assert(b); assert(m); + if (!a->is_kernel) + return 0; + if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "GetAll")) return 0; @@ -440,7 +501,6 @@ static int peer_is_privileged(sd_bus *bus, sd_bus_message *m) { return false; } - static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) { int r; @@ -448,6 +508,9 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) { assert(b); assert(m); + if (!a->is_kernel) + return 0; + if (!streq_ptr(sd_bus_message_get_destination(m), "org.freedesktop.DBus")) return 0; @@ -705,7 +768,7 @@ static int process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m) { if (r < 0) return synthetic_reply_method_errno(m, r, NULL); - if (err > 0) + if (err < 0) return synthetic_reply_method_errno(m, err, NULL); return synthetic_reply_return_strv(m, owners); @@ -1035,6 +1098,7 @@ int main(int argc, char *argv[]) { bool is_unix; struct ucred ucred = {}; _cleanup_free_ char *peersec = NULL; + Policy policy = {}; log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_parse_environment(); @@ -1044,6 +1108,14 @@ int main(int argc, char *argv[]) { if (r <= 0) goto finish; + r = policy_load(&policy, arg_configuration); + if (r < 0) { + log_error("Failed to load policy: %s", strerror(-r)); + goto finish; + } + + /* policy_dump(&policy); */ + r = sd_listen_fds(0); if (r == 0) { in_fd = STDIN_FILENO; @@ -1065,6 +1137,22 @@ int main(int argc, char *argv[]) { getpeersec(in_fd, &peersec); } + if (arg_drop_privileges) { + const char *user = "systemd-bus-proxy"; + uid_t uid; + gid_t gid; + + r = get_user_creds(&user, &uid, &gid, NULL, NULL); + if (r < 0) { + log_error("Cannot resolve user name %s: %s", user, strerror(-r)); + goto finish; + } + + r = drop_privileges(uid, gid, 1ULL << CAP_IPC_OWNER); + if (r < 0) + goto finish; + } + r = sd_bus_new(&a); if (r < 0) { log_error("Failed to allocate bus: %s", strerror(-r)); @@ -1309,7 +1397,7 @@ int main(int argc, char *argv[]) { else { k = sd_bus_send(a, m, NULL); if (k < 0) { - if (r == -ECONNRESET) + if (k == -ECONNRESET) r = 0; else { r = k; @@ -1389,6 +1477,12 @@ int main(int argc, char *argv[]) { finish: sd_bus_flush(a); sd_bus_flush(b); + sd_bus_close(a); + sd_bus_close(b); + + policy_free(&policy); + strv_free(arg_configuration); + free(arg_address); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; }