From 7be5fd95cdccdca28937804f32ca8b1308887d09 Mon Sep 17 00:00:00 2001 From: Havoc Pennington Date: Sat, 9 Jun 2007 23:41:33 +0000 Subject: 2007-06-09 Havoc Pennington * bus/policy.c (bus_policy_create_client_policy): gracefully continue if the connection has no unix user - just don't apply any unix user dependent rules. * bus/config-parser.c: remove dbus-userdb.h usage * bus/bus.c: remove dbus-userdb.h usage * dbus/dbus-transport.c (_dbus_transport_get_is_authenticated): support Windows user function; also, fix the logic for checking auth as root in the default auth code (broken in the previous commit) * dbus/dbus-connection.c (dbus_connection_set_windows_user_function): new function (dbus_connection_get_windows_user): new function --- dbus/dbus-connection.c | 141 +++++++++++++++--- dbus/dbus-connection.h | 24 ++- dbus/dbus-sysdeps-unix.c | 13 ++ dbus/dbus-sysdeps-unix.h | 2 - dbus/dbus-sysdeps-util-unix.c | 92 ++++++++++++ dbus/dbus-sysdeps.h | 20 +++ dbus/dbus-test.c | 4 +- dbus/dbus-transport-protected.h | 5 + dbus/dbus-transport.c | 319 +++++++++++++++++++++++++++++----------- dbus/dbus-transport.h | 8 + 10 files changed, 513 insertions(+), 115 deletions(-) (limited to 'dbus') diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 5dc463a4..1cd3d05d 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -4763,8 +4763,10 @@ dbus_connection_get_socket(DBusConnection *connection, /** * Gets the UNIX user ID of the connection if known. Returns #TRUE if - * the uid is filled in. Always returns #FALSE on non-UNIX platforms. - * Always returns #FALSE prior to authenticating the connection. + * the uid is filled in. Always returns #FALSE on non-UNIX platforms + * for now, though in theory someone could hook Windows to NIS or + * something. Always returns #FALSE prior to authenticating the + * connection. * * The UID is only read by servers from clients; clients can't usually * get the UID of servers, because servers do not authenticate to @@ -4789,14 +4791,6 @@ dbus_connection_get_unix_user (DBusConnection *connection, _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (uid != NULL, FALSE); - -#ifdef DBUS_WIN - /* FIXME this should be done at a lower level, but it's kind of hard, - * just want to be sure we don't ship with this API returning - * some weird internal fake uid for 1.0 - */ - return FALSE; -#endif CONNECTION_LOCK (connection); @@ -4805,6 +4799,11 @@ dbus_connection_get_unix_user (DBusConnection *connection, else result = _dbus_transport_get_unix_user (connection->transport, uid); + +#ifdef DBUS_WIN + _dbus_assert (!result); +#endif + CONNECTION_UNLOCK (connection); return result; @@ -4812,7 +4811,7 @@ dbus_connection_get_unix_user (DBusConnection *connection, /** * Gets the process ID of the connection if any. - * Returns #TRUE if the uid is filled in. + * Returns #TRUE if the pid is filled in. * Always returns #FALSE prior to authenticating the * connection. * @@ -4828,14 +4827,6 @@ dbus_connection_get_unix_process_id (DBusConnection *connection, _dbus_return_val_if_fail (connection != NULL, FALSE); _dbus_return_val_if_fail (pid != NULL, FALSE); - -#ifdef DBUS_WIN - /* FIXME this should be done at a lower level, but it's kind of hard, - * just want to be sure we don't ship with this API returning - * some weird internal fake uid for 1.0 - */ - return FALSE; -#endif CONNECTION_LOCK (connection); @@ -4844,6 +4835,10 @@ dbus_connection_get_unix_process_id (DBusConnection *connection, else result = _dbus_transport_get_unix_process_id (connection->transport, pid); +#ifdef DBUS_WIN + _dbus_assert (!result); +#endif + CONNECTION_UNLOCK (connection); return result; @@ -4858,14 +4853,13 @@ dbus_connection_get_unix_process_id (DBusConnection *connection, * * If the function is set to #NULL (as it is by default), then * only the same UID as the server process will be allowed to - * connect. + * connect. Also, root is always allowed to connect. * * On Windows, the function will be set and its free_data_function will * be invoked when the connection is freed or a new function is set. * However, the function will never be called, because there are - * no UNIX user ids to pass to it. - * - * @todo add a Windows API analogous to dbus_connection_set_unix_user_function() + * no UNIX user ids to pass to it, or at least none of the existing + * auth protocols would allow authenticating as a UNIX user on Windows. * * @param connection the connection * @param function the predicate @@ -4890,7 +4884,106 @@ dbus_connection_set_unix_user_function (DBusConnection *connection, CONNECTION_UNLOCK (connection); if (old_free_function != NULL) - (* old_free_function) (old_data); + (* old_free_function) (old_data); +} + +/** + * Gets the Windows user SID of the connection if known. Returns + * #TRUE if the ID is filled in. Always returns #FALSE on non-Windows + * platforms for now, though in theory someone could hook UNIX to + * Active Directory or something. Always returns #FALSE prior to + * authenticating the connection. + * + * The user is only read by servers from clients; clients can't usually + * get the user of servers, because servers do not authenticate to + * clients. The returned user is the user the connection authenticated + * as. + * + * The message bus is a server and the apps connecting to the bus + * are clients. + * + * The returned user string has to be freed with dbus_free(). + * + * The return value indicates whether the user SID is available; + * if it's available but we don't have the memory to copy it, + * then the return value is #TRUE and #NULL is given as the SID. + * + * @todo We would like to be able to say "You can ask the bus to tell + * you the user of another connection though if you like; this is done + * with dbus_bus_get_windows_user()." But this has to be implemented + * in bus/driver.c and dbus/dbus-bus.c, and is pointless anyway + * since on Windows we only use the session bus for now. + * + * @param connection the connection + * @param windows_sid_p return location for an allocated copy of the user ID, or #NULL if no memory + * @returns #TRUE if user is available (returned value may be #NULL anyway if no memory) + */ +dbus_bool_t +dbus_connection_get_windows_user (DBusConnection *connection, + char **windows_sid_p) +{ + dbus_bool_t result; + + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (windows_sid_p != NULL, FALSE); + + CONNECTION_LOCK (connection); + + if (!_dbus_transport_get_is_authenticated (connection->transport)) + result = FALSE; + else + result = _dbus_transport_get_windows_user (connection->transport, + windows_sid_p); + +#ifdef DBUS_UNIX + _dbus_assert (!result); +#endif + + CONNECTION_UNLOCK (connection); + + return result; +} + +/** + * Sets a predicate function used to determine whether a given user ID + * is allowed to connect. When an incoming connection has + * authenticated with a particular user ID, this function is called; + * if it returns #TRUE, the connection is allowed to proceed, + * otherwise the connection is disconnected. + * + * If the function is set to #NULL (as it is by default), then + * only the same user owning the server process will be allowed to + * connect. + * + * On UNIX, the function will be set and its free_data_function will + * be invoked when the connection is freed or a new function is set. + * However, the function will never be called, because there is no + * way right now to authenticate as a Windows user on UNIX. + * + * @param connection the connection + * @param function the predicate + * @param data data to pass to the predicate + * @param free_data_function function to free the data + */ +void +dbus_connection_set_windows_user_function (DBusConnection *connection, + DBusAllowWindowsUserFunction function, + void *data, + DBusFreeFunction free_data_function) +{ + void *old_data = NULL; + DBusFreeFunction old_free_function = NULL; + + _dbus_return_if_fail (connection != NULL); + + CONNECTION_LOCK (connection); + _dbus_transport_set_windows_user_function (connection->transport, + function, data, free_data_function, + &old_data, &old_free_function); + CONNECTION_UNLOCK (connection); + + if (old_free_function != NULL) + (* old_free_function) (old_data); } /** diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index 819e96c8..2b673fda 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -132,14 +132,28 @@ typedef void (* DBusDispatchStatusFunction) (DBusConnection *connection, * to do. Set with dbus_connection_set_wakeup_main_function(). */ typedef void (* DBusWakeupMainFunction) (void *data); + /** - * Called during authentication on UNIX systems to check whether the given - * user ID is allowed to connect. Never called on Windows. Set with + * Called during authentication to check whether the given UNIX user + * ID is allowed to connect, if the client tried to auth as a UNIX + * user ID. Normally on Windows this would never happen. Set with * dbus_connection_set_unix_user_function(). */ typedef dbus_bool_t (* DBusAllowUnixUserFunction) (DBusConnection *connection, unsigned long uid, void *data); + +/** + * Called during authentication to check whether the given Windows user + * ID is allowed to connect, if the client tried to auth as a Windows + * user ID. Normally on UNIX this would never happen. Set with + * dbus_connection_set_windows_user_function(). + */ +typedef dbus_bool_t (* DBusAllowWindowsUserFunction) (DBusConnection *connection, + const char *user_sid, + void *data); + + /** * Called when a pending call now has a reply available. Set with * dbus_pending_call_set_notify(). @@ -219,6 +233,12 @@ void dbus_connection_set_unix_user_function (DBusConnection DBusAllowUnixUserFunction function, void *data, DBusFreeFunction free_data_function); +dbus_bool_t dbus_connection_get_windows_user (DBusConnection *connection, + char **windows_sid_p); +void dbus_connection_set_windows_user_function (DBusConnection *connection, + DBusAllowWindowsUserFunction function, + void *data, + DBusFreeFunction free_data_function); void dbus_connection_set_route_peer_messages (DBusConnection *connection, dbus_bool_t value); diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 135f7c9f..f1c133fd 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -2916,4 +2916,17 @@ _dbus_get_standard_session_servicedirs (DBusList **dirs) return FALSE; } +/** + * Called when the bus daemon is signaled to reload its configuration; any + * caches should be nuked. Of course any caches that need explicit reload + * are probably broken, but c'est la vie. + * + * + */ +void +_dbus_flush_caches (void) +{ + _dbus_user_database_flush_system (); +} + /* tests in dbus-sysdeps-util.c */ diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h index 58fce9ce..0e8bdbb3 100644 --- a/dbus/dbus-sysdeps-unix.h +++ b/dbus/dbus-sysdeps-unix.h @@ -120,8 +120,6 @@ dbus_bool_t _dbus_group_info_fill_gid (DBusGroupInfo *info, DBusError *error); void _dbus_group_info_free (DBusGroupInfo *info); - -dbus_pid_t _dbus_getpid (void); dbus_uid_t _dbus_getuid (void); dbus_gid_t _dbus_getgid (void); diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c index 9963432b..339b8f96 100644 --- a/dbus/dbus-sysdeps-util-unix.c +++ b/dbus/dbus-sysdeps-util-unix.c @@ -780,6 +780,98 @@ _dbus_group_info_fill_gid (DBusGroupInfo *info, return fill_group_info (info, gid, NULL, error); } +/** + * Parse a UNIX user from the bus config file. On Windows, this should + * simply always fail (just return #FALSE). + * + * @param username the username text + * @param uid_p place to return the uid + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_parse_unix_user_from_config (const DBusString *username, + dbus_uid_t *uid_p) +{ + return _dbus_get_user_id (username, uid_p); + +} + +/** + * Parse a UNIX group from the bus config file. On Windows, this should + * simply always fail (just return #FALSE). + * + * @param groupname the groupname text + * @param gid_p place to return the gid + * @returns #TRUE on success + */ +dbus_bool_t +_dbus_parse_unix_group_from_config (const DBusString *groupname, + dbus_gid_t *gid_p) +{ + return _dbus_get_group_id (groupname, gid_p); +} + +/** + * Gets all groups corresponding to the given UNIX user ID. On UNIX, + * just calls _dbus_groups_from_uid(). On Windows, should always + * fail since we don't know any UNIX groups. + * + * @param uid the UID + * @param group_ids return location for array of group IDs + * @param n_group_ids return location for length of returned array + * @returns #TRUE if the UID existed and we got some credentials + */ +dbus_bool_t +_dbus_unix_groups_from_uid (dbus_uid_t uid, + dbus_gid_t **group_ids, + int *n_group_ids) +{ + return _dbus_groups_from_uid (uid, group_ids, n_group_ids); +} + +/** + * Checks to see if the UNIX user ID is at the console. + * Should always fail on Windows (set the error to + * #DBUS_ERROR_NOT_SUPPORTED). + * + * @param uid UID of person to check + * @param error return location for errors + * @returns #TRUE if the UID is the same as the console user and there are no errors + */ +dbus_bool_t +_dbus_unix_user_is_at_console (dbus_uid_t uid, + DBusError *error) +{ + return _dbus_is_console_user (uid, error); + +} + +/** + * Checks to see if the UNIX user ID matches the UID of + * the process. Should always return #FALSE on Windows. + * + * @param uid the UNIX user ID + * @returns #TRUE if this uid owns the process. + */ +dbus_bool_t +_dbus_unix_user_is_process_owner (dbus_uid_t uid) +{ + return uid == _dbus_getuid (); +} + +/** + * Checks to see if the Windows user SID matches the owner of + * the process. Should always return #FALSE on UNIX. + * + * @param windows_sid the Windows user SID + * @returns #TRUE if this user owns the process. + */ +dbus_bool_t +_dbus_windows_user_is_process_owner (const char *windows_sid) +{ + return FALSE; +} + /** @} */ /* End of DBusInternalsUtils functions */ /** diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index f83c17ca..87bfc8fa 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -173,6 +173,18 @@ dbus_bool_t _dbus_append_desired_identity (DBusString *str); dbus_bool_t _dbus_homedir_from_current_process (const DBusString **homedir); dbus_bool_t _dbus_homedir_from_username (const DBusString *username, DBusString *homedir); +dbus_bool_t _dbus_parse_unix_user_from_config (const DBusString *username, + dbus_uid_t *uid_p); +dbus_bool_t _dbus_parse_unix_group_from_config (const DBusString *groupname, + dbus_gid_t *gid_p); +dbus_bool_t _dbus_unix_groups_from_uid (dbus_uid_t uid, + dbus_gid_t **group_ids, + int *n_group_ids); +dbus_bool_t _dbus_unix_user_is_at_console (dbus_uid_t uid, + DBusError *error); +dbus_bool_t _dbus_unix_user_is_process_owner (dbus_uid_t uid); +dbus_bool_t _dbus_windows_user_is_process_owner (const char *windows_sid); + /** Opaque type representing an atomically-modifiable integer * that can be used from multiple threads. @@ -420,6 +432,14 @@ dbus_bool_t _dbus_split_paths_and_append (DBusString *dirs, unsigned long _dbus_pid_for_log (void); +/* FIXME move back to dbus-sysdeps-unix.h probably - + * the PID file handling just needs a little more abstraction + * in the bus daemon first. + */ +dbus_pid_t _dbus_getpid (void); + +void _dbus_flush_caches (void); + /** @} */ DBUS_END_DECLS diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c index a1df3604..818c4ed0 100644 --- a/dbus/dbus-test.c +++ b/dbus/dbus-test.c @@ -161,8 +161,10 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir, const char *speci #endif run_data_test ("credentials", specific_test, _dbus_credentials_test, test_data_dir); - + +#ifdef DBUS_UNIX run_data_test ("userdb", specific_test, _dbus_userdb_test, test_data_dir); +#endif run_test ("keyring", specific_test, _dbus_keyring_test); diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index bfdff0e2..6d3f1f3c 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -104,6 +104,11 @@ struct DBusTransport void *unix_user_data; /**< Data for unix_user_function */ DBusFreeFunction free_unix_user_data; /**< Function to free unix_user_data */ + + DBusAllowWindowsUserFunction windows_user_function; /**< Function for checking whether a user is authorized. */ + void *windows_user_data; /**< Data for windows_user_function */ + + DBusFreeFunction free_windows_user_data; /**< Function to free windows_user_data */ unsigned int disconnected : 1; /**< #TRUE if we are disconnected. */ unsigned int authenticated : 1; /**< Cache of auth state; use _dbus_transport_get_is_authenticated() to query value */ diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index e922eb5d..029cc6cf 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -167,6 +167,10 @@ _dbus_transport_init_base (DBusTransport *transport, transport->unix_user_data = NULL; transport->free_unix_user_data = NULL; + transport->windows_user_function = NULL; + transport->windows_user_data = NULL; + transport->free_windows_user_data = NULL; + transport->expected_guid = NULL; /* Try to default to something that won't totally hose the system, @@ -202,6 +206,9 @@ _dbus_transport_finalize_base (DBusTransport *transport) if (transport->free_unix_user_data != NULL) (* transport->free_unix_user_data) (transport->unix_user_data); + + if (transport->free_windows_user_data != NULL) + (* transport->free_windows_user_data) (transport->windows_user_data); _dbus_message_loader_unref (transport->loader); _dbus_auth_unref (transport->auth); @@ -491,12 +498,157 @@ _dbus_transport_get_is_connected (DBusTransport *transport) return !transport->disconnected; } +static dbus_bool_t +auth_via_unix_user_function (DBusTransport *transport) +{ + DBusCredentials *auth_identity; + dbus_bool_t allow; + DBusConnection *connection; + DBusAllowUnixUserFunction unix_user_function; + void *unix_user_data; + dbus_uid_t uid; + + /* Dropping the lock here probably isn't that safe. */ + + auth_identity = _dbus_auth_get_identity (transport->auth); + _dbus_assert (auth_identity != NULL); + + connection = transport->connection; + unix_user_function = transport->unix_user_function; + unix_user_data = transport->unix_user_data; + uid = _dbus_credentials_get_unix_uid (auth_identity), + + _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME); + _dbus_connection_unlock (connection); + + allow = (* unix_user_function) (connection, + uid, + unix_user_data); + + _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME); + _dbus_connection_lock (connection); + + if (allow) + { + _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); + } + else + { + _dbus_verbose ("Client UID "DBUS_UID_FORMAT + " was rejected, disconnecting\n", + _dbus_credentials_get_unix_uid (auth_identity)); + _dbus_transport_disconnect (transport); + } + + return allow; +} + +static dbus_bool_t +auth_via_windows_user_function (DBusTransport *transport) +{ + DBusCredentials *auth_identity; + dbus_bool_t allow; + DBusConnection *connection; + DBusAllowWindowsUserFunction windows_user_function; + void *windows_user_data; + char *windows_sid; + + /* Dropping the lock here probably isn't that safe. */ + + auth_identity = _dbus_auth_get_identity (transport->auth); + _dbus_assert (auth_identity != NULL); + + connection = transport->connection; + windows_user_function = transport->windows_user_function; + windows_user_data = transport->unix_user_data; + windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); + + if (windows_sid == NULL) + { + /* OOM */ + return FALSE; + } + + _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME); + _dbus_connection_unlock (connection); + + allow = (* windows_user_function) (connection, + windows_sid, + windows_user_data); + + _dbus_verbose ("lock %s post windows user function\n", _DBUS_FUNCTION_NAME); + _dbus_connection_lock (connection); + + if (allow) + { + _dbus_verbose ("Client SID '%s' authorized\n", windows_sid); + } + else + { + _dbus_verbose ("Client SID '%s' was rejected, disconnecting\n", + _dbus_credentials_get_windows_sid (auth_identity)); + _dbus_transport_disconnect (transport); + } + + return allow; +} + +static dbus_bool_t +auth_via_default_rules (DBusTransport *transport) +{ + DBusCredentials *auth_identity; + DBusCredentials *our_identity; + dbus_bool_t allow; + + auth_identity = _dbus_auth_get_identity (transport->auth); + _dbus_assert (auth_identity != NULL); + + /* By default, connection is allowed if the client is + * 1) root or 2) has the same UID as us + */ + + our_identity = _dbus_credentials_new_from_current_process (); + if (our_identity == NULL) + { + /* OOM */ + return FALSE; + } + + if (_dbus_credentials_get_unix_uid (auth_identity) == 0 || + _dbus_credentials_same_user (our_identity, + auth_identity)) + { + /* FIXME the verbose spam here is unix-specific */ + _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT + " matching our UID "DBUS_UID_FORMAT"\n", + _dbus_credentials_get_unix_uid(auth_identity), + _dbus_credentials_get_unix_uid(our_identity)); + /* We have authenticated! */ + allow = TRUE; + } + else + { + /* FIXME the verbose spam here is unix-specific */ + _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT + " but our UID is "DBUS_UID_FORMAT", disconnecting\n", + _dbus_credentials_get_unix_uid(our_identity), + _dbus_credentials_get_unix_uid(our_identity)); + _dbus_transport_disconnect (transport); + allow = FALSE; + } + + _dbus_credentials_unref (our_identity); + + return allow; +} + + /** * Returns #TRUE if we have been authenticated. Will return #TRUE * even if the transport is disconnected. * * @todo we drop connection->mutex when calling the unix_user_function, - * which may not be safe really. + * and windows_user_function, which may not be safe really. * * @param transport the transport * @returns whether we're authenticated @@ -532,6 +684,8 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) } } + /* If we're the client, verify the GUID + */ if (maybe_authenticated && !transport->is_server) { const char *server_guid; @@ -560,106 +714,40 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) } } } - - /* If we've authenticated as some identity, check that the auth - * identity is the same as our own identity. In the future, we - * may have API allowing applications to specify how this is - * done, for example they may allow connection as any identity, - * but then impose restrictions on certain identities. - * Or they may give certain identities extra privileges. + + /* If we're the server, see if we want to allow this identity to proceed. */ - if (maybe_authenticated && transport->is_server) { + dbus_bool_t allow; DBusCredentials *auth_identity; - + auth_identity = _dbus_auth_get_identity (transport->auth); _dbus_assert (auth_identity != NULL); - - /* If we have a UNIX user and a unix user function, delegate - * deciding whether auth credentials are good enough to the app; - * otherwise, use our default decision process. + + /* If we have an auth'd user and a user function, delegate + * deciding whether auth credentials are good enough to the + * app; otherwise, use our default decision process. */ if (transport->unix_user_function != NULL && _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID)) { - dbus_bool_t allow; - DBusConnection *connection; - DBusAllowUnixUserFunction unix_user_function; - void *unix_user_data; - dbus_uid_t uid; - - /* Dropping the lock here probably isn't that safe. */ - - connection = transport->connection; - unix_user_function = transport->unix_user_function; - unix_user_data = transport->unix_user_data; - uid = _dbus_credentials_get_unix_uid (auth_identity), - - _dbus_verbose ("unlock %s\n", _DBUS_FUNCTION_NAME); - _dbus_connection_unlock (connection); - - allow = (* unix_user_function) (connection, - uid, - unix_user_data); - - _dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME); - _dbus_connection_lock (connection); - - if (allow) - { - _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid); - } - else - { - _dbus_verbose ("Client UID "DBUS_UID_FORMAT - " was rejected, disconnecting\n", - _dbus_credentials_get_unix_uid (auth_identity)); - _dbus_transport_disconnect (transport); - _dbus_connection_unref_unlocked (connection); - return FALSE; - } + allow = auth_via_unix_user_function (transport); } + else if (transport->windows_user_function != NULL && + _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID)) + { + allow = auth_via_windows_user_function (transport); + } else { - DBusCredentials *our_identity; - - /* By default, connection is allowed if the client is - * 1) root or 2) has the same UID as us - */ - - our_identity = _dbus_credentials_new_from_current_process (); - if (our_identity == NULL) - { - /* OOM */ - _dbus_connection_unref_unlocked (transport->connection); - return FALSE; - } - - if (_dbus_credentials_get_unix_uid (auth_identity) == 0 || - !_dbus_credentials_same_user (our_identity, - auth_identity)) - { - /* FIXME the verbose spam here is unix-specific */ - _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT - " but our UID is "DBUS_UID_FORMAT", disconnecting\n", - _dbus_credentials_get_unix_uid(our_identity), - _dbus_credentials_get_unix_uid(our_identity)); - _dbus_transport_disconnect (transport); - _dbus_connection_unref_unlocked (transport->connection); - return FALSE; - } - else - { - /* FIXME the verbose spam here is unix-specific */ - _dbus_verbose ("Client authorized as UID "DBUS_UID_FORMAT - " matching our UID "DBUS_UID_FORMAT"\n", - _dbus_credentials_get_unix_uid(auth_identity), - _dbus_credentials_get_unix_uid(our_identity)); - } + allow = auth_via_default_rules (transport); } + + if (!allow) + maybe_authenticated = FALSE; } - + transport->authenticated = maybe_authenticated; _dbus_connection_unref_unlocked (transport->connection); @@ -1136,6 +1224,65 @@ _dbus_transport_set_unix_user_function (DBusTransport *transport, transport->free_unix_user_data = free_data_function; } +/** + * See dbus_connection_get_windows_user(). + * + * @param transport the transport + * @param windows_sid_p return location for the user ID + * @returns #TRUE if user is available; the returned value may still be #NULL if no memory to copy it + */ +dbus_bool_t +_dbus_transport_get_windows_user (DBusTransport *transport, + char **windows_sid_p) +{ + DBusCredentials *auth_identity; + + *windows_sid_p = NULL; + + if (!transport->authenticated) + return FALSE; + + auth_identity = _dbus_auth_get_identity (transport->auth); + + if (_dbus_credentials_include (auth_identity, + DBUS_CREDENTIAL_WINDOWS_SID)) + { + /* If no memory, we are supposed to return TRUE and set NULL */ + *windows_sid_p = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity)); + + return TRUE; + } + else + return FALSE; +} + +/** + * See dbus_connection_set_windows_user_function(). + * + * @param transport the transport + * @param function the predicate + * @param data data to pass to the predicate + * @param free_data_function function to free the data + * @param old_data the old user data to be freed + * @param old_free_data_function old free data function to free it with + */ + +void +_dbus_transport_set_windows_user_function (DBusTransport *transport, + DBusAllowWindowsUserFunction function, + void *data, + DBusFreeFunction free_data_function, + void **old_data, + DBusFreeFunction *old_free_data_function) +{ + *old_data = transport->windows_user_data; + *old_free_data_function = transport->free_windows_user_data; + + transport->windows_user_function = function; + transport->windows_user_data = data; + transport->free_windows_user_data = free_data_function; +} + /** * Sets the SASL authentication mechanisms supported by this transport. * diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index 4784e462..9e952a1e 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -68,6 +68,14 @@ void _dbus_transport_set_unix_user_function (DBusTransport DBusFreeFunction free_data_function, void **old_data, DBusFreeFunction *old_free_data_function); +dbus_bool_t _dbus_transport_get_windows_user (DBusTransport *transport, + char **windows_sid_p); +void _dbus_transport_set_windows_user_function (DBusTransport *transport, + DBusAllowWindowsUserFunction function, + void *data, + DBusFreeFunction free_data_function, + void **old_data, + DBusFreeFunction *old_free_data_function); dbus_bool_t _dbus_transport_set_auth_mechanisms (DBusTransport *transport, const char **mechanisms); -- cgit