DBusUserInfo* _dbus_user_database_lookup (DBusUserDatabase *db, dbus_uid_t uid, const DBusString *username, DBusError *error) { DBusUserInfo *info; _DBUS_ASSERT_ERROR_IS_CLEAR (error); _dbus_assert (uid != DBUS_UID_UNSET || username != NULL); /* See if the username is really a number */ if (uid == DBUS_UID_UNSET) { unsigned long n; if (_dbus_is_a_number (username, &n)) uid = n; } if (uid != DBUS_UID_UNSET) info = _dbus_hash_table_lookup_ulong (db->users, uid); else info = _dbus_hash_table_lookup_string (db->users_by_name, _dbus_string_get_const_data (username)); if (info) { _dbus_verbose ("Using cache for UID "DBUS_UID_FORMAT" information\n", info->uid); return info; } else { if (uid != DBUS_UID_UNSET) _dbus_verbose ("No cache for UID "DBUS_UID_FORMAT"\n", uid); else _dbus_verbose ("No cache for user \"%s\"\n", _dbus_string_get_const_data (username)); info = dbus_new0 (DBusUserInfo, 1); if (info == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } if (uid != DBUS_UID_UNSET) { if (!_dbus_user_info_fill_uid (info, uid, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); _dbus_user_info_free_allocated (info); return NULL; } } else { if (!_dbus_user_info_fill (info, username, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); _dbus_user_info_free_allocated (info); return NULL; } } /* be sure we don't use these after here */ uid = DBUS_UID_UNSET; username = NULL; /* insert into hash */ if (!_dbus_hash_table_insert_ulong (db->users, info->uid, info)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); _dbus_user_info_free_allocated (info); return NULL; } if (!_dbus_hash_table_insert_string (db->users_by_name, info->username, info)) { _dbus_hash_table_remove_ulong (db->users, info->uid); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } return info; } }
/** * Looks up a gid or group name in the user database. Only one of * name or GID can be provided. There are wrapper functions for this * that are better to use, this one does no locking or anything on the * database and otherwise sort of sucks. * * @param db the database * @param gid the group ID or #DBUS_GID_UNSET * @param groupname group name or #NULL * @param error error to fill in * @returns the entry in the database */ DBusGroupInfo* _dbus_user_database_lookup_group (DBusUserDatabase *db, dbus_gid_t gid, const DBusString *groupname, DBusError *error) { DBusGroupInfo *info; _DBUS_ASSERT_ERROR_IS_CLEAR (error); /* See if the group is really a number */ if (gid == DBUS_UID_UNSET) { unsigned long n; if (_dbus_is_a_number (groupname, &n)) gid = n; } #ifdef DBUS_ENABLE_USERDB_CACHE if (gid != DBUS_GID_UNSET) info = _dbus_hash_table_lookup_ulong (db->groups, gid); else info = _dbus_hash_table_lookup_string (db->groups_by_name, _dbus_string_get_const_data (groupname)); if (info) { _dbus_verbose ("Using cache for GID "DBUS_GID_FORMAT" information\n", info->gid); return info; } else #else if (1) #endif { if (gid != DBUS_GID_UNSET) _dbus_verbose ("No cache for GID "DBUS_GID_FORMAT"\n", gid); else _dbus_verbose ("No cache for groupname \"%s\"\n", _dbus_string_get_const_data (groupname)); info = dbus_new0 (DBusGroupInfo, 1); if (info == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } if (gid != DBUS_GID_UNSET) { if (!_dbus_group_info_fill_gid (info, gid, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); _dbus_group_info_free_allocated (info); return NULL; } } else { if (!_dbus_group_info_fill (info, groupname, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); _dbus_group_info_free_allocated (info); return NULL; } } /* don't use these past here */ gid = DBUS_GID_UNSET; groupname = NULL; if (!_dbus_hash_table_insert_ulong (db->groups, info->gid, info)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); _dbus_group_info_free_allocated (info); return NULL; } if (!_dbus_hash_table_insert_string (db->groups_by_name, info->groupname, info)) { _dbus_hash_table_remove_ulong (db->groups, info->gid); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } return info; } }
BusClientPolicy* bus_policy_create_client_policy (BusPolicy *policy, DBusConnection *connection, DBusError *error) { BusClientPolicy *client; dbus_uid_t uid; dbus_bool_t at_console; _dbus_assert (dbus_connection_get_is_authenticated (connection)); _DBUS_ASSERT_ERROR_IS_CLEAR (error); client = bus_client_policy_new (); if (client == NULL) goto nomem; if (!add_list_to_client (&policy->default_rules, client)) goto nomem; /* we avoid the overhead of looking up user's groups * if we don't have any group rules anyway */ if (_dbus_hash_table_get_n_entries (policy->rules_by_gid) > 0) { unsigned long *groups; int n_groups; int i; if (!bus_connection_get_groups (connection, &groups, &n_groups, error)) goto failed; i = 0; while (i < n_groups) { DBusList **list; list = _dbus_hash_table_lookup_ulong (policy->rules_by_gid, groups[i]); if (list != NULL) { if (!add_list_to_client (list, client)) { dbus_free (groups); goto nomem; } } ++i; } dbus_free (groups); } if (!dbus_connection_get_unix_user (connection, &uid)) { dbus_set_error (error, DBUS_ERROR_FAILED, "No user ID known for connection, cannot determine security policy\n"); goto failed; } if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0) { DBusList **list; list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid, uid); if (list != NULL) { if (!add_list_to_client (list, client)) goto nomem; } } /* Add console rules */ at_console = _dbus_is_console_user (uid, error); if (at_console) { if (!add_list_to_client (&policy->at_console_true_rules, client)) goto nomem; } else if (dbus_error_is_set (error) == TRUE) { goto failed; } else if (!add_list_to_client (&policy->at_console_false_rules, client)) { goto nomem; } if (!add_list_to_client (&policy->mandatory_rules, client)) goto nomem; bus_client_policy_optimize (client); return client; nomem: BUS_SET_OOM (error); failed: _DBUS_ASSERT_ERROR_IS_SET (error); if (client) bus_client_policy_unref (client); return NULL; }