From c788f01375b2d7a9e2ccfd118e63b933c4842ea7 Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Sat, 14 Nov 2015 16:32:43 +0100 Subject: [PATCH 4/4] 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 --- bus/driver.c | 174 +++++++++++++++++++++++++++++++---------------- dbus/dbus-sysdeps-unix.h | 1 - dbus/dbus-sysdeps-win.c | 9 +++ dbus/dbus-sysdeps.h | 3 + 4 files changed, 129 insertions(+), 58 deletions(-) diff --git a/bus/driver.c b/bus/driver.c index 8d78c67..c671964 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -43,6 +43,13 @@ #include #include +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; } /* @@ -1614,25 +1628,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); + 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 (conn == NULL) - goto failed; - - reply = dbus_message_new_method_return (message); - if (reply == NULL) - goto oom; - - if (!dbus_connection_get_unix_user (conn, &uid)) + if (uid == DBUS_UID_UNSET) { dbus_set_error (error, DBUS_ERROR_FAILED, @@ -1640,6 +1660,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, @@ -1671,32 +1695,42 @@ 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); + 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 (conn == NULL) - goto failed; + if (pid == DBUS_PID_UNSET) + { + dbus_set_error (error, + DBUS_ERROR_FAILED, + "Could not determine PID for '%s'", service); + goto failed; + } reply = dbus_message_new_method_return (message); if (reply == NULL) goto oom; - if (!dbus_connection_get_unix_process_id (conn, &pid)) - { - dbus_set_error (error, - DBUS_ERROR_UNIX_PROCESS_ID_UNKNOWN, - "Could not determine PID for '%s'", service); - goto failed; - } - pid32 = pid; if (! dbus_message_append_args (reply, DBUS_TYPE_UINT32, &pid32, @@ -1731,22 +1765,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, @@ -1786,22 +1827,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, @@ -1840,19 +1887,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) @@ -1860,23 +1922,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; @@ -1898,7 +1956,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 0932129..72f3ecf 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 c7587db..ee212fc 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 bd0356e..c788252 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); -- 2.6.2