chiark / gitweb /
use memzero(foo, length); for all memset(foo, 0, length); calls
[elogind.git] / src / bus-proxyd / bus-proxyd.c
index b87dffe0e8b77202d4858feda63e8f3b6858b63e..5869d79c52e4e79011cae65a689a85e7c05e0efe 100644 (file)
 #include "bus-util.h"
 #include "build.h"
 #include "strv.h"
+#include "def.h"
 
-#define UNIX_BUS_PATH "unix:path=/run/dbus/system_bus_socket"
-#define KERNEL_BUS_PATH "kernel:path=/dev/kdbus/0-system/bus"
-
-#ifdef ENABLE_KDBUS
-#  define DEFAULT_BUS_PATH KERNEL_BUS_PATH ";" UNIX_BUS_PATH
-#else
-#  define DEFAULT_BUS_PATH UNIX_BUS_PATH
-#endif
-
-static const char *arg_address = DEFAULT_BUS_PATH;
+static const char *arg_address = DEFAULT_SYSTEM_BUS_PATH;
 static char *arg_command_line_buffer = NULL;
 
 static int help(void) {
@@ -60,7 +52,7 @@ static int help(void) {
                "  -h --help              Show this help\n"
                "     --version           Show package version\n"
                "     --address=ADDRESS   Connect to the bus specified by ADDRESS\n"
-               "                         (default: " DEFAULT_BUS_PATH ")\n",
+               "                         (default: " DEFAULT_SYSTEM_BUS_PATH ")\n",
                program_invocation_short_name);
 
         return 0;
@@ -123,7 +115,7 @@ static int parse_argv(int argc, char *argv[]) {
         return 1;
 }
 
-static int rename_service(sd_bus *b) {
+static int rename_service(sd_bus *a, sd_bus *b) {
         _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
         _cleanup_free_ char *p = NULL, *name = NULL;
         const char *comm;
@@ -132,6 +124,7 @@ static int rename_service(sd_bus *b) {
         pid_t pid;
         int r;
 
+        assert(a);
         assert(b);
 
         r = sd_bus_get_peer_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds);
@@ -164,9 +157,9 @@ static int rename_service(sd_bus *b) {
 
         /* The status string gets the full command line ... */
         sd_notifyf(false,
-                   "STATUS=Processing requests from client PID %lu (%s); UID %lu (%s)",
-                   (unsigned long) pid, p,
-                   (unsigned long) uid, name);
+                   "STATUS=Processing requests from client PID "PID_FMT" (%s); UID "UID_FMT" (%s)",
+                   pid, p,
+                   uid, name);
 
         /* ... and the argv line only the short comm */
         if (arg_command_line_buffer) {
@@ -174,14 +167,19 @@ static int rename_service(sd_bus *b) {
 
                 m = strlen(arg_command_line_buffer);
                 w = snprintf(arg_command_line_buffer, m,
-                             "[PID %lu/%s; UID %lu/%s]",
-                             (unsigned long) pid, comm,
-                             (unsigned long) uid, name);
+                             "[PID "PID_FMT"/%s; UID "UID_FMT"/%s]",
+                             pid, comm,
+                             uid, name);
 
                 if (m > w)
-                        memset(arg_command_line_buffer + w, 0, m - w);
+                        memzero(arg_command_line_buffer + w, m - w);
         }
 
+        log_debug("Running on behalf of PID "PID_FMT" (%s), UID "UID_FMT" (%s), %s",
+                  pid, p,
+                  uid, name,
+                  a->unique_name);
+                ;
         return 0;
 }
 
@@ -252,6 +250,45 @@ static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) {
         return sd_bus_send(b, n, NULL);
 }
 
+static int process_policy(sd_bus *a, sd_bus *b, sd_bus_message *m) {
+        _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
+        int r;
+
+        assert(a);
+        assert(b);
+        assert(m);
+
+        if (!sd_bus_message_is_method_call(m, "org.freedesktop.DBus.Properties", "GetAll"))
+                return 0;
+
+        if (!streq_ptr(m->path, "/org/gnome/DisplayManager/Slave"))
+                return 0;
+
+        r = sd_bus_message_new_method_errorf(m, &n, SD_BUS_ERROR_ACCESS_DENIED, "gdm, you are stupid");
+        if (r < 0)
+                return r;
+
+        r = bus_message_append_sender(n, "org.freedesktop.DBus");
+        if (r < 0) {
+                log_error("Failed to append sender to gdm reply: %s", strerror(-r));
+                return r;
+        }
+
+        r = bus_seal_synthetic_message(b, n);
+        if (r < 0) {
+                log_error("Failed to seal gdm reply: %s", strerror(-r));
+                return r;
+        }
+
+        r = sd_bus_send(b, n, NULL);
+        if (r < 0) {
+                log_error("Failed to send gdm reply: %s", strerror(-r));
+                return r;
+        }
+
+        return 1;
+}
+
 static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hello) {
         _cleanup_bus_message_unref_ sd_bus_message *n = NULL;
         bool is_hello;
@@ -358,37 +395,33 @@ static int process_hello(sd_bus *a, sd_bus *b, sd_bus_message *m, bool *got_hell
         return 1;
 }
 
-static int getpeersec(int fd, char **ret) {
-        socklen_t n = 64;
-        char *s;
+static int patch_sender(sd_bus *a, sd_bus_message *m) {
+        char **well_known = NULL;
+        sd_bus_creds *c;
         int r;
 
-        assert(fd >= 0);
-        assert(ret);
+        assert(a);
+        assert(m);
 
-        s = new0(char, n);
-        if (!s)
-                return -ENOMEM;
+        if (!a->is_kernel)
+                return 0;
 
-        r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
-        if (r < 0) {
-                free(s);
+        /* We will change the sender of messages from the bus driver
+         * so that they originate from the bus driver. This is a
+         * speciality originating from dbus1, where the bus driver did
+         * not have a unique id, but only the well-known name. */
 
-                if (errno != ERANGE)
-                        return r;
+        c = sd_bus_message_get_creds(m);
+        if (!c)
+                return 0;
 
-                s = new0(char, n);
-                if (!s)
-                        return -ENOMEM;
+        r = sd_bus_creds_get_well_known_names(c, &well_known);
+        if (r < 0)
+                return r;
 
-                r = getsockopt(fd, SOL_SOCKET, SO_PEERSEC, s, &n);
-                if (r < 0) {
-                        free(s);
-                        return r;
-                }
-        }
+        if (strv_contains(well_known, "org.freedesktop.DBus"))
+                m->sender = "org.freedesktop.DBus";
 
-        *ret = s;
         return 0;
 }
 
@@ -418,7 +451,7 @@ int main(int argc, char *argv[]) {
                 in_fd = SD_LISTEN_FDS_START;
                 out_fd = SD_LISTEN_FDS_START;
         } else {
-                log_error("Illegal number of file descriptors passed\n");
+                log_error("Illegal number of file descriptors passed");
                 goto finish;
         }
 
@@ -427,16 +460,7 @@ int main(int argc, char *argv[]) {
                 sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0;
 
         if (is_unix) {
-                socklen_t l = sizeof(ucred);
-
-                r = getsockopt(in_fd, SOL_SOCKET, SO_PEERCRED, &ucred, &l);
-                if (r < 0) {
-                        r = -errno;
-                        goto finish;
-                }
-
-                assert(l == sizeof(ucred));
-
+                getpeercred(in_fd, &ucred);
                 getpeersec(in_fd, &peersec);
         }
 
@@ -446,6 +470,12 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        r = sd_bus_set_name(a, "sd-proxy");
+        if (r < 0) {
+                log_error("Failed to set bus name: %s", strerror(-r));
+                goto finish;
+        }
+
         r = sd_bus_set_address(a, arg_address);
         if (r < 0) {
                 log_error("Failed to set address to connect to: %s", strerror(-r));
@@ -470,6 +500,8 @@ int main(int argc, char *argv[]) {
                 peersec = NULL;
         }
 
+        a->manual_peer_interface = true;
+
         r = sd_bus_start(a);
         if (r < 0) {
                 log_error("Failed to start bus client: %s", strerror(-r));
@@ -512,13 +544,15 @@ int main(int argc, char *argv[]) {
                 goto finish;
         }
 
+        b->manual_peer_interface = true;
+
         r = sd_bus_start(b);
         if (r < 0) {
                 log_error("Failed to start bus client: %s", strerror(-r));
                 goto finish;
         }
 
-        r = rename_service(b);
+        r = rename_service(a, b);
         if (r < 0)
                 log_debug("Failed to rename process: %s", strerror(-r));
 
@@ -608,10 +642,17 @@ int main(int argc, char *argv[]) {
                                         goto finish;
                                 }
 
+                                patch_sender(a, m);
+
                                 k = sd_bus_send(b, m, NULL);
                                 if (k < 0) {
-                                        r = k;
-                                        log_error("Failed to send message: %s", strerror(-r));
+                                        if (k == -ECONNRESET)
+                                                r = 0;
+                                        else {
+                                                r = k;
+                                                log_error("Failed to send message: %s", strerror(-r));
+                                        }
+
                                         goto finish;
                                 }
                         }
@@ -641,16 +682,29 @@ int main(int argc, char *argv[]) {
                         k = process_hello(a, b, m, &got_hello);
                         if (k < 0) {
                                 r = k;
+                                log_error("Failed to process HELLO: %s", strerror(-r));
                                 goto finish;
                         }
 
                         if (k > 0)
                                 r = k;
                         else {
-                                k = sd_bus_send(a, m, NULL);
+                                k = process_policy(a, b, m);
                                 if (k < 0) {
                                         r = k;
-                                        log_error("Failed to send message: %s", strerror(-r));
+                                        log_error("Failed to process policy: %s", strerror(-r));
+                                        goto finish;
+                                }
+
+                                k = sd_bus_send(a, m, NULL);
+                                if (k < 0) {
+                                        if (r == -ECONNRESET)
+                                                r = 0;
+                                        else {
+                                                r = k;
+                                                log_error("Failed to send message: %s", strerror(-r));
+                                        }
+
                                         goto finish;
                                 }
                         }