summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJan Alexander Steffens (heftig) <jan.steffens@gmail.com>2015-11-14 16:32:43 +0100
committerSimon McVittie <simon.mcvittie@collabora.co.uk>2015-11-17 18:21:44 +0000
commitcc37dc857fcd7a5afb57ba6e7c2002acc73a0b5d (patch)
tree33519a6e78bb6a36ad8dbfcd320ea2b558d71cd8
parent6e63e23983c3a0ef0fcd1c6f6f1c3a081ac5d5f6 (diff)
downloaddbus-cc37dc857fcd7a5afb57ba6e7c2002acc73a0b5d.tar.gz
bus-driver: Support returning org.freedesktop.DBus UID and PID
Attempting to call SetEnvironment on systemd causes it to inquire about the caller's connection UID and PID. If this check fails, the call is rejected. Bug: https://bugs.freedesktop.org/show_bug.cgi?id=92857 Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> [smcv: go back to DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN as the error code for failure to determine the pid]
-rw-r--r--bus/driver.c170
-rw-r--r--dbus/dbus-sysdeps-unix.h1
-rw-r--r--dbus/dbus-sysdeps-win.c9
-rw-r--r--dbus/dbus-sysdeps.h3
4 files changed, 127 insertions, 56 deletions
diff --git a/bus/driver.c b/bus/driver.c
index 3234250f..01fd340f 100644
--- a/bus/driver.c
+++ b/bus/driver.c
@@ -43,6 +43,13 @@
#include <dbus/dbus-marshal-validate.h>
#include <string.h>
+typedef enum
+{
+ BUS_DRIVER_FOUND_SELF,
+ BUS_DRIVER_FOUND_PEER,
+ BUS_DRIVER_FOUND_ERROR,
+} BusDriverFound;
+
static inline const char *
nonnull (const char *maybe_null,
const char *if_null)
@@ -68,11 +75,12 @@ bus_driver_get_owner_of_name (DBusConnection *connection,
return bus_service_get_primary_owners_connection (serv);
}
-static DBusConnection *
+static BusDriverFound
bus_driver_get_conn_helper (DBusConnection *connection,
DBusMessage *message,
const char *what_we_want,
const char **name_p,
+ DBusConnection **peer_conn_p,
DBusError *error)
{
DBusConnection *conn;
@@ -81,11 +89,17 @@ bus_driver_get_conn_helper (DBusConnection *connection,
if (!dbus_message_get_args (message, error,
DBUS_TYPE_STRING, &name,
DBUS_TYPE_INVALID))
- return NULL;
+ return BUS_DRIVER_FOUND_ERROR;
_dbus_assert (name != NULL);
_dbus_verbose ("asked for %s of connection %s\n", what_we_want, name);
+ if (name_p != NULL)
+ *name_p = name;
+
+ if (strcmp (name, DBUS_SERVICE_DBUS) == 0)
+ return BUS_DRIVER_FOUND_SELF;
+
conn = bus_driver_get_owner_of_name (connection, name);
if (conn == NULL)
@@ -93,13 +107,13 @@ bus_driver_get_conn_helper (DBusConnection *connection,
dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
"Could not get %s of name '%s': no such name",
what_we_want, name);
- return NULL;
+ return BUS_DRIVER_FOUND_ERROR;
}
- if (name_p != NULL)
- *name_p = name;
+ if (peer_conn_p != NULL)
+ *peer_conn_p = conn;
- return conn;
+ return BUS_DRIVER_FOUND_PEER;
}
/*
@@ -1602,25 +1616,31 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
{
DBusConnection *conn;
DBusMessage *reply;
- unsigned long uid;
+ dbus_uid_t uid;
dbus_uint32_t uid32;
const char *service;
+ BusDriverFound found;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
reply = NULL;
- conn = bus_driver_get_conn_helper (connection, message, "UID", &service,
- error);
-
- if (conn == NULL)
- goto failed;
-
- reply = dbus_message_new_method_return (message);
- if (reply == NULL)
- goto oom;
+ found = bus_driver_get_conn_helper (connection, message, "UID", &service,
+ &conn, error);
+ switch (found)
+ {
+ case BUS_DRIVER_FOUND_SELF:
+ uid = _dbus_getuid ();
+ break;
+ case BUS_DRIVER_FOUND_PEER:
+ if (!dbus_connection_get_unix_user (conn, &uid))
+ uid = DBUS_UID_UNSET;
+ break;
+ case BUS_DRIVER_FOUND_ERROR:
+ goto failed;
+ }
- if (!dbus_connection_get_unix_user (conn, &uid))
+ if (uid == DBUS_UID_UNSET)
{
dbus_set_error (error,
DBUS_ERROR_FAILED,
@@ -1628,6 +1648,10 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection,
goto failed;
}
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ goto oom;
+
uid32 = uid;
if (! dbus_message_append_args (reply,
DBUS_TYPE_UINT32, &uid32,
@@ -1659,25 +1683,31 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
{
DBusConnection *conn;
DBusMessage *reply;
- unsigned long pid;
+ dbus_pid_t pid;
dbus_uint32_t pid32;
const char *service;
+ BusDriverFound found;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
reply = NULL;
- conn = bus_driver_get_conn_helper (connection, message, "PID", &service,
- error);
-
- if (conn == NULL)
- goto failed;
-
- reply = dbus_message_new_method_return (message);
- if (reply == NULL)
- goto oom;
+ found = bus_driver_get_conn_helper (connection, message, "PID", &service,
+ &conn, error);
+ switch (found)
+ {
+ case BUS_DRIVER_FOUND_SELF:
+ pid = _dbus_getpid ();
+ break;
+ case BUS_DRIVER_FOUND_PEER:
+ if (!dbus_connection_get_unix_process_id (conn, &pid))
+ pid = DBUS_PID_UNSET;
+ break;
+ case BUS_DRIVER_FOUND_ERROR:
+ goto failed;
+ }
- if (!dbus_connection_get_unix_process_id (conn, &pid))
+ if (pid == DBUS_PID_UNSET)
{
dbus_set_error (error,
DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN,
@@ -1685,6 +1715,10 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection,
goto failed;
}
+ reply = dbus_message_new_method_return (message);
+ if (reply == NULL)
+ goto oom;
+
pid32 = pid;
if (! dbus_message_append_args (reply,
DBUS_TYPE_UINT32, &pid32,
@@ -1719,22 +1753,29 @@ bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection,
void *data = NULL;
dbus_uint32_t data_size;
const char *service;
+ BusDriverFound found;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
reply = NULL;
- conn = bus_driver_get_conn_helper (connection, message,
- "audit session data", &service, error);
+ found = bus_driver_get_conn_helper (connection, message, "audit session data",
+ &service, &conn, error);
- if (conn == NULL)
+ if (found == BUS_DRIVER_FOUND_ERROR)
goto failed;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
goto oom;
- if (!dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) || data == NULL)
+ /* We don't know how to find "ADT audit session data" for the bus daemon
+ * itself. Is that even meaningful?
+ * FIXME: Implement this or briefly note it makes no sense.
+ */
+ if (found != BUS_DRIVER_FOUND_PEER ||
+ !dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) ||
+ data == NULL)
{
dbus_set_error (error,
DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN,
@@ -1774,22 +1815,28 @@ bus_driver_handle_get_connection_selinux_security_context (DBusConnection *conne
DBusMessage *reply;
BusSELinuxID *context;
const char *service;
+ BusDriverFound found;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
reply = NULL;
- conn = bus_driver_get_conn_helper (connection, message, "security context",
- &service, error);
+ found = bus_driver_get_conn_helper (connection, message, "security context",
+ &service, &conn, error);
- if (conn == NULL)
+ if (found == BUS_DRIVER_FOUND_ERROR)
goto failed;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
goto oom;
- context = bus_connection_get_selinux_id (conn);
+ /* FIXME: Obtain the SELinux security context for the bus daemon itself */
+ if (found == BUS_DRIVER_FOUND_PEER)
+ context = bus_connection_get_selinux_id (conn);
+ else
+ context = NULL;
+
if (!context)
{
dbus_set_error (error,
@@ -1828,19 +1875,34 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection,
DBusMessage *reply;
DBusMessageIter reply_iter;
DBusMessageIter array_iter;
- unsigned long ulong_val;
+ unsigned long ulong_uid, ulong_pid;
char *s;
const char *service;
+ BusDriverFound found;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
reply = NULL;
- conn = bus_driver_get_conn_helper (connection, message, "credentials",
- &service, error);
+ found = bus_driver_get_conn_helper (connection, message, "credentials",
+ &service, &conn, error);
- if (conn == NULL)
- goto failed;
+ switch (found)
+ {
+ case BUS_DRIVER_FOUND_SELF:
+ ulong_pid = _dbus_getpid ();
+ ulong_uid = _dbus_getuid ();
+ break;
+
+ case BUS_DRIVER_FOUND_PEER:
+ if (!dbus_connection_get_unix_process_id (conn, &ulong_pid))
+ ulong_pid = DBUS_PID_UNSET;
+ if (!dbus_connection_get_unix_user (conn, &ulong_uid))
+ ulong_uid = DBUS_UID_UNSET;
+ break;
+ case BUS_DRIVER_FOUND_ERROR:
+ goto failed;
+ }
reply = _dbus_asv_new_method_return (message, &reply_iter, &array_iter);
if (reply == NULL)
@@ -1848,23 +1910,19 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection,
/* we can't represent > 32-bit pids; if your system needs them, please
* add ProcessID64 to the spec or something */
- if (dbus_connection_get_unix_process_id (conn, &ulong_val) &&
- ulong_val <= _DBUS_UINT32_MAX)
- {
- if (!_dbus_asv_add_uint32 (&array_iter, "ProcessID", ulong_val))
- goto oom;
- }
+ if (ulong_pid <= _DBUS_UINT32_MAX && ulong_pid != DBUS_PID_UNSET &&
+ !_dbus_asv_add_uint32 (&array_iter, "ProcessID", ulong_pid))
+ goto oom;
/* we can't represent > 32-bit uids; if your system needs them, please
* add UnixUserID64 to the spec or something */
- if (dbus_connection_get_unix_user (conn, &ulong_val) &&
- ulong_val <= _DBUS_UINT32_MAX)
- {
- if (!_dbus_asv_add_uint32 (&array_iter, "UnixUserID", ulong_val))
- goto oom;
- }
+ if (ulong_uid <= _DBUS_UINT32_MAX && ulong_uid != DBUS_UID_UNSET &&
+ !_dbus_asv_add_uint32 (&array_iter, "UnixUserID", ulong_uid))
+ goto oom;
- if (dbus_connection_get_windows_user (conn, &s))
+ /* FIXME: Obtain the Windows user of the bus daemon itself */
+ if (found == BUS_DRIVER_FOUND_PEER &&
+ dbus_connection_get_windows_user (conn, &s))
{
DBusString str;
dbus_bool_t result;
@@ -1886,7 +1944,9 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection,
dbus_free (s);
}
- if (_dbus_connection_get_linux_security_label (conn, &s))
+ /* FIXME: Obtain the security label for the bus daemon itself */
+ if (found == BUS_DRIVER_FOUND_PEER &&
+ _dbus_connection_get_linux_security_label (conn, &s))
{
if (s == NULL)
goto oom;
diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h
index 0932129f..72f3ecf5 100644
--- a/dbus/dbus-sysdeps-unix.h
+++ b/dbus/dbus-sysdeps-unix.h
@@ -138,7 +138,6 @@ dbus_bool_t _dbus_group_info_fill_gid (DBusGroupInfo *info,
DBusError *error);
void _dbus_group_info_free (DBusGroupInfo *info);
-dbus_uid_t _dbus_getuid (void);
DBUS_PRIVATE_EXPORT
dbus_uid_t _dbus_geteuid (void);
diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
index fb14e409..fb195801 100644
--- a/dbus/dbus-sysdeps-win.c
+++ b/dbus/dbus-sysdeps-win.c
@@ -2138,6 +2138,15 @@ _dbus_getpid (void)
return GetCurrentProcessId ();
}
+/** Gets our Unix UID
+ * @returns on Windows, just DBUS_UID_UNSET
+ */
+dbus_uid_t
+_dbus_getuid (void)
+{
+ return DBUS_UID_UNSET;
+}
+
/** nanoseconds in a second */
#define NANOSECONDS_PER_SECOND 1000000000
/** microseconds in a second */
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index 79a6cc7c..2f493b09 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -641,6 +641,9 @@ unsigned long _dbus_pid_for_log (void);
DBUS_PRIVATE_EXPORT
dbus_pid_t _dbus_getpid (void);
+DBUS_PRIVATE_EXPORT
+dbus_uid_t _dbus_getuid (void);
+
dbus_bool_t _dbus_change_to_daemon_user (const char *user,
DBusError *error);