From ff1f5af5ff8eaaead1afa79b648fef281187ee81 Mon Sep 17 00:00:00 2001 From: "Jan Alexander Steffens (heftig)" Date: Sat, 7 Nov 2015 18:28:04 +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. --- bus/driver.c | 145 ++++++++++++++++++++++++++++++++--------------- dbus/dbus-sysdeps-unix.h | 1 - dbus/dbus-sysdeps-win.c | 9 +++ dbus/dbus-sysdeps.h | 3 + 4 files changed, 110 insertions(+), 48 deletions(-) diff --git a/bus/driver.c b/bus/driver.c index 056476c..a0a3787 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; } /* @@ -1588,25 +1602,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, @@ -1614,6 +1634,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, @@ -1645,32 +1669,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, @@ -1705,22 +1739,25 @@ 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) + 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, @@ -1760,22 +1797,27 @@ 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); + if (found == BUS_DRIVER_FOUND_PEER) + context = bus_connection_get_selinux_id (conn); + else + context = NULL; + if (!context) { dbus_set_error (error, @@ -1817,15 +1859,16 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, unsigned long ulong_val; 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) + if (found == BUS_DRIVER_FOUND_ERROR) goto failed; reply = _dbus_asv_new_method_return (message, &reply_iter, &array_iter); @@ -1834,8 +1877,11 @@ 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 ((found == BUS_DRIVER_FOUND_PEER && + dbus_connection_get_unix_process_id (conn, &ulong_val) && + ulong_val <= _DBUS_UINT32_MAX) || + (found == BUS_DRIVER_FOUND_SELF && + (ulong_val = _dbus_getpid ()) != DBUS_PID_UNSET)) { if (!_dbus_asv_add_uint32 (&array_iter, "ProcessID", ulong_val)) goto oom; @@ -1843,14 +1889,18 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, /* 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 ((found == BUS_DRIVER_FOUND_PEER && + dbus_connection_get_unix_user (conn, &ulong_val) && + ulong_val <= _DBUS_UINT32_MAX) || + (found == BUS_DRIVER_FOUND_SELF && + (ulong_val = _dbus_getuid ()) != DBUS_UID_UNSET)) { if (!_dbus_asv_add_uint32 (&array_iter, "UnixUserID", ulong_val)) goto oom; } - if (dbus_connection_get_windows_user (conn, &s)) + if (found == BUS_DRIVER_FOUND_PEER && + dbus_connection_get_windows_user (conn, &s)) { DBusString str; dbus_bool_t result; @@ -1872,7 +1922,8 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, dbus_free (s); } - if (_dbus_connection_get_linux_security_label (conn, &s)) + 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..aaa0257 100644 --- a/dbus/dbus-sysdeps-win.c +++ b/dbus/dbus-sysdeps-win.c @@ -2138,6 +2138,15 @@ _dbus_getpid (void) return GetCurrentProcessId (); } +/** Gets our UID + * @returns process UID + */ +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