chiark / gitweb /
bus-proxy: add support for "GetConnectionCredentials" method
[elogind.git] / src / bus-proxyd / driver.c
index 6a72d181fe833398848a4f156bdd14b2f175cedd..e63a95d875a1b279963627cb67ef51734d9fb82d 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-#include <sys/types.h>
-#include <unistd.h>
 #include <string.h>
 #include <errno.h>
 #include <stddef.h>
 
-#include "log.h"
 #include "util.h"
 #include "sd-bus.h"
 #include "bus-internal.h"
 #include "bus-message.h"
 #include "bus-util.h"
-#include "build.h"
 #include "strv.h"
-#include "def.h"
-#include "capability.h"
-#include "bus-control.h"
 #include "set.h"
 #include "driver.h"
 #include "synthesize.h"
@@ -56,9 +49,6 @@ static int get_creds_by_name(sd_bus *bus, const char *name, uint64_t mask, sd_bu
         if (r < 0)
                 return r;
 
-        if ((c->mask & mask) != mask)
-                return -ENOTSUP;
-
         *_creds = c;
         c = NULL;
 
@@ -116,6 +106,10 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                         "  <method name=\"RemoveMatch\">\n"
                         "   <arg type=\"s\" direction=\"in\"/>\n"
                         "  </method>\n"
+                        "  <method name=\"GetConnectionCredentials\">\n"
+                        "   <arg type=\"s\" direction=\"in\"/>\n"
+                        "   <arg type=\"a{sv}\" direction=\"out\"/>\n"
+                        "  </method>\n"
                         "  <method name=\"GetConnectionSELinuxSecurityContext\">\n"
                         "   <arg type=\"s\" direction=\"in\"/>\n"
                         "   <arg type=\"ay\" direction=\"out\"/>\n"
@@ -219,6 +213,72 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
 
                 return synthetic_reply_method_return(m, NULL);
 
+        } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionCredentials")) {
+                _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
+                _cleanup_bus_message_unref_ sd_bus_message *reply = NULL;
+                _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
+
+                if (!sd_bus_message_has_signature(m, "s"))
+                        return synthetic_reply_method_error(m, &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_INVALID_ARGS, "Invalid parameters"));
+
+                r = get_creds_by_message(a, m, SD_BUS_CREDS_PID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SELINUX_CONTEXT, &creds, &error);
+                if (r < 0)
+                        return synthetic_reply_method_errno(m, r, &error);
+
+                r = sd_bus_message_new_method_return(m, &reply);
+                if (r < 0)
+                        return synthetic_reply_method_errno(m, r, NULL);
+
+                r = sd_bus_message_open_container(reply, 'a', "{sv}");
+                if (r < 0)
+                        return synthetic_reply_method_errno(m, r, NULL);
+
+                /* Due to i.e. namespace translations some data might be missing */
+
+                if (creds->mask & SD_BUS_CREDS_PID) {
+                        r = sd_bus_message_append(reply, "{sv}", "ProcessID", "u", (uint32_t) creds->pid);
+                        if (r < 0)
+                                return synthetic_reply_method_errno(m, r, NULL);
+                }
+
+                if (creds->mask & SD_BUS_CREDS_EUID) {
+                        r = sd_bus_message_append(reply, "{sv}", "UnixUserID", "u", (uint32_t) creds->euid);
+                        if (r < 0)
+                                return synthetic_reply_method_errno(m, r, NULL);
+                }
+
+                if (creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
+                        r = sd_bus_message_open_container(reply, 'e', "sv");
+                        if (r < 0)
+                                return synthetic_reply_method_errno(m, r, NULL);
+
+                        r = sd_bus_message_append(reply, "s", "LinuxSecurityLabel");
+                        if (r < 0)
+                                return synthetic_reply_method_errno(m, r, NULL);
+
+                        r = sd_bus_message_open_container(reply, 'v', "ay");
+                        if (r < 0)
+                                return synthetic_reply_method_errno(m, r, NULL);
+
+                        r = sd_bus_message_append_array(reply, 'y', creds->label, strlen(creds->label));
+                        if (r < 0)
+                                return synthetic_reply_method_errno(m, r, NULL);
+
+                        r = sd_bus_message_close_container(reply);
+                        if (r < 0)
+                                return synthetic_reply_method_errno(m, r, NULL);
+
+                        r = sd_bus_message_close_container(reply);
+                        if (r < 0)
+                                return synthetic_reply_method_errno(m, r, NULL);
+                }
+
+                r = sd_bus_message_close_container(reply);
+                if (r < 0)
+                        return synthetic_reply_method_errno(m, r, NULL);
+
+                return synthetic_driver_send(m->bus, reply);
+
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionSELinuxSecurityContext")) {
                 _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL;
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
@@ -230,6 +290,9 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                 if (r < 0)
                         return synthetic_reply_method_errno(m, r, &error);
 
+                if (!(creds->mask & SD_BUS_CREDS_SELINUX_CONTEXT))
+                        return synthetic_reply_method_errno(m, -ENOTSUP, NULL);
+
                 return synthetic_reply_method_return(m, "y", creds->label, strlen(creds->label));
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixProcessID")) {
@@ -243,6 +306,9 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                 if (r < 0)
                         return synthetic_reply_method_errno(m, r, &error);
 
+                if (!(creds->mask & SD_BUS_CREDS_PID))
+                        return synthetic_reply_method_errno(m, -ENOTSUP, NULL);
+
                 return synthetic_reply_method_return(m, "u", (uint32_t) creds->pid);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetConnectionUnixUser")) {
@@ -256,6 +322,9 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                 if (r < 0)
                         return synthetic_reply_method_errno(m, r, &error);
 
+                if (!(creds->mask & SD_BUS_CREDS_EUID))
+                        return synthetic_reply_method_errno(m, -ENOTSUP, NULL);
+
                 return synthetic_reply_method_return(m, "u", (uint32_t) creds->euid);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "GetId")) {
@@ -290,6 +359,9 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                 if (r < 0)
                         return synthetic_reply_method_errno(m, r, &error);
 
+                if (!(creds->mask & SD_BUS_CREDS_UNIQUE_NAME))
+                        return synthetic_reply_method_errno(m, -ENOTSUP, NULL);
+
                 return synthetic_reply_method_return(m, "s", creds->unique_name);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListActivatableNames")) {
@@ -305,7 +377,7 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                 /* Let's sort the names list to make it stable */
                 strv_sort(names);
 
-                return synthetic_reply_return_strv(m, names);
+                return synthetic_reply_method_return_strv(m, names);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListNames")) {
                 _cleanup_strv_free_ char **names = NULL;
@@ -324,12 +396,14 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                 /* Let's sort the names list to make it stable */
                 strv_sort(names);
 
-                return synthetic_reply_return_strv(m, names);
+                return synthetic_reply_method_return_strv(m, names);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "ListQueuedOwners")) {
-                struct kdbus_cmd_name_list cmd = {};
-                struct kdbus_name_list *name_list;
-                struct kdbus_name_info *name;
+                struct kdbus_cmd_list cmd = {
+                        .flags = KDBUS_LIST_QUEUED,
+                        .size = sizeof(cmd),
+                };
+                struct kdbus_info *name_list, *name;
                 _cleanup_strv_free_ char **owners = NULL;
                 _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL;
                 char *arg0;
@@ -350,14 +424,13 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                 if (r < 0)
                         return synthetic_reply_method_errno(m, r, NULL);
 
-                cmd.flags = KDBUS_NAME_LIST_QUEUED;
-                r = ioctl(a->input_fd, KDBUS_CMD_NAME_LIST, &cmd);
+                r = ioctl(a->input_fd, KDBUS_CMD_LIST, &cmd);
                 if (r < 0)
                         return synthetic_reply_method_errno(m, -errno, NULL);
 
-                name_list = (struct kdbus_name_list *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
+                name_list = (struct kdbus_info *) ((uint8_t *) a->kdbus_buffer + cmd.offset);
 
-                KDBUS_ITEM_FOREACH(name, name_list, names) {
+                KDBUS_FOREACH(name, name_list, cmd.list_size) {
                         const char *entry_name = NULL;
                         struct kdbus_item *item;
                         char *n;
@@ -369,7 +442,7 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                         if (!streq_ptr(entry_name, arg0))
                                 continue;
 
-                        if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) {
+                        if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) {
                                 err  = -ENOMEM;
                                 break;
                         }
@@ -388,7 +461,7 @@ int bus_proxy_process_driver(sd_bus *a, sd_bus *b, sd_bus_message *m, SharedPoli
                 if (err < 0)
                         return synthetic_reply_method_errno(m, err, NULL);
 
-                return synthetic_reply_return_strv(m, owners);
+                return synthetic_reply_method_return_strv(m, owners);
 
         } else if (sd_bus_message_is_method_call(m, "org.freedesktop.DBus", "NameHasOwner")) {
                 const char *name;