X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;ds=sidebyside;f=dbus%2Fdbus-userdb.c;h=b792cbe48b18f55f01c9cce63ff7b7e94d0a5f5d;hb=3ccb027c907f9ee2890028e83b60296204bbf478;hp=d8477cd2adbc6c224491703301d6d92a6c85773b;hpb=f14f2196cc129e4e17f993773d57000784958bcf;p=platform%2Fupstream%2Fdbus.git diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c index d8477cd..b792cbe 100644 --- a/dbus/dbus-userdb.c +++ b/dbus/dbus-userdb.c @@ -1,4 +1,4 @@ -/* -*- mode: C; c-file-style: "gnu" -*- */ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ /* dbus-userdb.c User database abstraction * * Copyright (C) 2003, 2004 Red Hat, Inc. @@ -17,35 +17,33 @@ * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA * */ +#include +#define DBUS_USERDB_INCLUDES_PRIVATE 1 #include "dbus-userdb.h" #include "dbus-hash.h" #include "dbus-test.h" #include "dbus-internals.h" #include "dbus-protocol.h" +#include "dbus-credentials.h" #include /** - * Internals of DBusUserDatabase + * @addtogroup DBusInternalsUtils + * @{ */ -struct DBusUserDatabase -{ - int refcount; /**< Reference count */ - - DBusHashTable *users; /**< Users in the database by UID */ - DBusHashTable *groups; /**< Groups in the database by GID */ - DBusHashTable *users_by_name; /**< Users in the database by name */ - DBusHashTable *groups_by_name; /**< Groups in the database by name */ - -}; -static void -free_user_info (void *data) +/** + * Frees the given #DBusUserInfo's members with _dbus_user_info_free() + * and also calls dbus_free() on the block itself + * + * @param info the info + */ +void +_dbus_user_info_free_allocated (DBusUserInfo *info) { - DBusUserInfo *info = data; - if (info == NULL) /* hash table will pass NULL */ return; @@ -53,11 +51,15 @@ free_user_info (void *data) dbus_free (info); } -static void -free_group_info (void *data) +/** + * Frees the given #DBusGroupInfo's members with _dbus_group_info_free() + * and also calls dbus_free() on the block itself + * + * @param info the info + */ +void +_dbus_group_info_free_allocated (DBusGroupInfo *info) { - DBusGroupInfo *info = data; - if (info == NULL) /* hash table will pass NULL */ return; @@ -65,7 +67,64 @@ free_group_info (void *data) dbus_free (info); } -static DBusUserInfo* +/** + * Frees the members of info + * (but not info itself) + * @param info the user info struct + */ +void +_dbus_user_info_free (DBusUserInfo *info) +{ + dbus_free (info->group_ids); + dbus_free (info->username); + dbus_free (info->homedir); +} + +/** + * Frees the members of info (but not info itself). + * + * @param info the group info + */ +void +_dbus_group_info_free (DBusGroupInfo *info) +{ + dbus_free (info->groupname); +} + +/** + * Checks if a given string is actually a number + * and converts it if it is + * + * @param str the string to check + * @param num the memory location of the unsigned long to fill in + * @returns TRUE if str is a number and num is filled in + */ +dbus_bool_t +_dbus_is_a_number (const DBusString *str, + unsigned long *num) +{ + int end; + + if (_dbus_string_parse_uint (str, 0, num, &end) && + end == _dbus_string_get_length (str)) + return TRUE; + else + return FALSE; +} + +/** + * Looks up a uid or username in the user database. Only one of name + * or UID 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 uid the user ID or #DBUS_UID_UNSET + * @param username username or #NULL + * @param error error to fill in + * @returns the entry in the database + */ +DBusUserInfo* _dbus_user_database_lookup (DBusUserDatabase *db, dbus_uid_t uid, const DBusString *username, @@ -75,22 +134,39 @@ _dbus_user_database_lookup (DBusUserDatabase *db, _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; + } + +#ifdef DBUS_ENABLE_USERDB_CACHE if (uid != DBUS_UID_UNSET) - info = _dbus_hash_table_lookup_ulong (db->users, uid); + info = _dbus_hash_table_lookup_uintptr (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", - uid); + info->uid); return info; } else +#else + if (1) +#endif { - _dbus_verbose ("No cache for UID "DBUS_UID_FORMAT"\n", - uid); + 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) @@ -104,7 +180,7 @@ _dbus_user_database_lookup (DBusUserDatabase *db, if (!_dbus_user_info_fill_uid (info, uid, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); - free_user_info (info); + _dbus_user_info_free_allocated (info); return NULL; } } @@ -113,7 +189,7 @@ _dbus_user_database_lookup (DBusUserDatabase *db, if (!_dbus_user_info_fill (info, username, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); - free_user_info (info); + _dbus_user_info_free_allocated (info); return NULL; } } @@ -123,10 +199,10 @@ _dbus_user_database_lookup (DBusUserDatabase *db, username = NULL; /* insert into hash */ - if (!_dbus_hash_table_insert_ulong (db->users, info->uid, info)) + if (!_dbus_hash_table_insert_uintptr (db->users, info->uid, info)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - free_user_info (info); + _dbus_user_info_free_allocated (info); return NULL; } @@ -134,7 +210,7 @@ _dbus_user_database_lookup (DBusUserDatabase *db, info->username, info)) { - _dbus_hash_table_remove_ulong (db->users, info->uid); + _dbus_hash_table_remove_uintptr (db->users, info->uid); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } @@ -143,68 +219,6 @@ _dbus_user_database_lookup (DBusUserDatabase *db, } } -static 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); - - 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", - gid); - return info; - } - else - { - _dbus_verbose ("No cache for GID "DBUS_GID_FORMAT"\n", - gid); - - info = dbus_new0 (DBusGroupInfo, 1); - if (info == NULL) - { - dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - return NULL; - } - - if (!_dbus_group_info_fill_gid (info, gid, error)) - { - _DBUS_ASSERT_ERROR_IS_SET (error); - free_group_info (info); - return NULL; - } - - if (!_dbus_hash_table_insert_ulong (db->groups, info->gid, info)) - { - dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - free_group_info (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; - } -} - -_DBUS_DEFINE_GLOBAL_LOCK(system_users); static dbus_bool_t database_locked = FALSE; static DBusUserDatabase *system_db = NULL; static DBusString process_username; @@ -213,7 +227,8 @@ static DBusString process_homedir; static void shutdown_system_db (void *data) { - _dbus_user_database_unref (system_db); + if (system_db != NULL) + _dbus_user_database_unref (system_db); system_db = NULL; _dbus_string_free (&process_username); _dbus_string_free (&process_homedir); @@ -226,15 +241,13 @@ init_system_db (void) if (system_db == NULL) { - DBusError error; + DBusError error = DBUS_ERROR_INIT; const DBusUserInfo *info; system_db = _dbus_user_database_new (); if (system_db == NULL) return FALSE; - dbus_error_init (&error); - if (!_dbus_user_database_get_uid (system_db, _dbus_getuid (), &info, @@ -291,18 +304,20 @@ init_system_db (void) } /** - * @addtogroup DBusInternalsUtils - * @{ - */ - -/** * Locks global system user database. */ -void +dbus_bool_t _dbus_user_database_lock_system (void) { - _DBUS_LOCK (system_users); - database_locked = TRUE; + if (_DBUS_LOCK (system_users)) + { + database_locked = TRUE; + return TRUE; + } + else + { + return FALSE; + } } /** @@ -332,6 +347,24 @@ _dbus_user_database_get_system (void) } /** + * Flushes the system global user database; + */ +void +_dbus_user_database_flush_system (void) +{ + if (!_dbus_user_database_lock_system ()) + { + /* nothing to flush */ + return; + } + + if (system_db != NULL) + _dbus_user_database_flush (system_db); + + _dbus_user_database_unlock_system (); +} + +/** * Gets username of user owning current process. The returned string * is valid until dbus_shutdown() is called. * @@ -341,7 +374,9 @@ _dbus_user_database_get_system (void) dbus_bool_t _dbus_username_from_current_process (const DBusString **username) { - _dbus_user_database_lock_system (); + if (!_dbus_user_database_lock_system ()) + return FALSE; + if (!init_system_db ()) { _dbus_user_database_unlock_system (); @@ -363,7 +398,9 @@ _dbus_username_from_current_process (const DBusString **username) dbus_bool_t _dbus_homedir_from_current_process (const DBusString **homedir) { - _dbus_user_database_lock_system (); + if (!_dbus_user_database_lock_system ()) + return FALSE; + if (!init_system_db ()) { _dbus_user_database_unlock_system (); @@ -376,100 +413,42 @@ _dbus_homedir_from_current_process (const DBusString **homedir) } /** - * Gets user ID given username + * Gets the home directory for the given user. * * @param username the username - * @param uid return location for UID - * @returns #TRUE if username existed and we got the UID - */ -dbus_bool_t -_dbus_get_user_id (const DBusString *username, - dbus_uid_t *uid) -{ - DBusCredentials creds; - - if (!_dbus_credentials_from_username (username, &creds)) - return FALSE; - - if (creds.uid == DBUS_UID_UNSET) - return FALSE; - - *uid = creds.uid; - - return TRUE; -} - -/** - * Checks to see if the UID sent in is the console user - * - * @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 + * @param homedir string to append home directory to + * @returns #TRUE if user existed and we appended their homedir */ dbus_bool_t -_dbus_is_console_user (dbus_uid_t uid, - DBusError *error) +_dbus_homedir_from_username (const DBusString *username, + DBusString *homedir) { - DBusUserDatabase *db; const DBusUserInfo *info; - dbus_bool_t result = FALSE; - _dbus_user_database_lock_system (); + /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) + return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) { - dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get system database."); _dbus_user_database_unlock_system (); return FALSE; } - info = _dbus_user_database_lookup (db, uid, NULL, error); - - if (info == NULL) - { - _dbus_user_database_unlock_system (); - return FALSE; - } - - result = _dbus_user_at_console (info->username, error); - - _dbus_user_database_unlock_system (); - - return result; -} - -/** - * Gets group ID given groupname - * - * @param groupname the groupname - * @param gid return location for GID - * @returns #TRUE if group name existed and we got the GID - */ -dbus_bool_t -_dbus_get_group_id (const DBusString *groupname, - dbus_gid_t *gid) -{ - DBusUserDatabase *db; - const DBusGroupInfo *info; - _dbus_user_database_lock_system (); - - db = _dbus_user_database_get_system (); - if (db == NULL) + if (!_dbus_user_database_get_username (db, username, + &info, NULL)) { _dbus_user_database_unlock_system (); return FALSE; } - if (!_dbus_user_database_get_groupname (db, groupname, - &info, NULL)) + if (!_dbus_string_append (homedir, info->homedir)) { _dbus_user_database_unlock_system (); return FALSE; } - - *gid = info->gid; _dbus_user_database_unlock_system (); return TRUE; @@ -478,17 +457,20 @@ _dbus_get_group_id (const DBusString *groupname, /** * Gets the home directory for the given user. * - * @param username the username + * @param uid the uid * @param homedir string to append home directory to * @returns #TRUE if user existed and we appended their homedir */ dbus_bool_t -_dbus_homedir_from_username (const DBusString *username, - DBusString *homedir) +_dbus_homedir_from_uid (dbus_uid_t uid, + DBusString *homedir) { DBusUserDatabase *db; const DBusUserInfo *info; - _dbus_user_database_lock_system (); + + /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) + return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) @@ -497,8 +479,8 @@ _dbus_homedir_from_username (const DBusString *username, return FALSE; } - if (!_dbus_user_database_get_username (db, username, - &info, NULL)) + if (!_dbus_user_database_get_uid (db, uid, + &info, NULL)) { _dbus_user_database_unlock_system (); return FALSE; @@ -515,59 +497,29 @@ _dbus_homedir_from_username (const DBusString *username, } /** - * Gets a UID from a UID string. - * - * @param uid_str the UID in string form - * @param uid UID to fill in - * @returns #TRUE if successfully filled in UID - */ -dbus_bool_t -_dbus_uid_from_string (const DBusString *uid_str, - dbus_uid_t *uid) -{ - int end; - long val; - - if (_dbus_string_get_length (uid_str) == 0) - { - _dbus_verbose ("UID string was zero length\n"); - return FALSE; - } - - val = -1; - end = 0; - if (!_dbus_string_parse_int (uid_str, 0, &val, - &end)) - { - _dbus_verbose ("could not parse string as a UID\n"); - return FALSE; - } - - if (end != _dbus_string_get_length (uid_str)) - { - _dbus_verbose ("string contained trailing stuff after UID\n"); - return FALSE; - } - - *uid = val; - - return TRUE; -} - -/** - * Gets the credentials corresponding to the given username. + * Adds the credentials corresponding to the given username. * + * Used among other purposes to parses a desired identity provided + * from a client in the auth protocol. On UNIX this means parsing a + * UID, on Windows probably parsing an SID string. + * + * @todo this is broken because it treats OOM and parse error + * the same way. Needs a #DBusError. + * + * @param credentials credentials to fill in * @param username the username - * @param credentials credentials to fill in * @returns #TRUE if the username existed and we got some credentials */ dbus_bool_t -_dbus_credentials_from_username (const DBusString *username, - DBusCredentials *credentials) +_dbus_credentials_add_from_user (DBusCredentials *credentials, + const DBusString *username) { DBusUserDatabase *db; const DBusUserInfo *info; - _dbus_user_database_lock_system (); + + /* FIXME: this can't distinguish ENOMEM from other errors */ + if (!_dbus_user_database_lock_system ()) + return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) @@ -583,48 +535,11 @@ _dbus_credentials_from_username (const DBusString *username, return FALSE; } - credentials->pid = DBUS_PID_UNSET; - credentials->uid = info->uid; - credentials->gid = info->primary_gid; - - _dbus_user_database_unlock_system (); - return TRUE; -} - -/** - * Gets the credentials corresponding to the given UID. - * - * @param uid the UID - * @param credentials credentials to fill in - * @returns #TRUE if the UID existed and we got some credentials - */ -dbus_bool_t -_dbus_credentials_from_uid (dbus_uid_t uid, - DBusCredentials *credentials) -{ - DBusUserDatabase *db; - const DBusUserInfo *info; - _dbus_user_database_lock_system (); - - db = _dbus_user_database_get_system (); - if (db == NULL) + if (!_dbus_credentials_add_unix_uid(credentials, info->uid)) { _dbus_user_database_unlock_system (); return FALSE; } - - if (!_dbus_user_database_get_uid (db, uid, - &info, NULL)) - { - _dbus_user_database_unlock_system (); - return FALSE; - } - - _dbus_assert (info->uid == uid); - - credentials->pid = DBUS_PID_UNSET; - credentials->uid = info->uid; - credentials->gid = info->primary_gid; _dbus_user_database_unlock_system (); return TRUE; @@ -646,14 +561,14 @@ _dbus_user_database_new (void) db->refcount = 1; - db->users = _dbus_hash_table_new (DBUS_HASH_ULONG, - NULL, free_user_info); + db->users = _dbus_hash_table_new (DBUS_HASH_UINTPTR, + NULL, (DBusFreeFunction) _dbus_user_info_free_allocated); if (db->users == NULL) goto failed; - db->groups = _dbus_hash_table_new (DBUS_HASH_ULONG, - NULL, free_group_info); + db->groups = _dbus_hash_table_new (DBUS_HASH_UINTPTR, + NULL, (DBusFreeFunction) _dbus_group_info_free_allocated); if (db->groups == NULL) goto failed; @@ -676,6 +591,19 @@ _dbus_user_database_new (void) } /** + * Flush all information out of the user database. + */ +void +_dbus_user_database_flush (DBusUserDatabase *db) +{ + _dbus_hash_table_remove_all(db->users_by_name); + _dbus_hash_table_remove_all(db->groups_by_name); + _dbus_hash_table_remove_all(db->users); + _dbus_hash_table_remove_all(db->groups); +} + +#ifdef DBUS_ENABLE_EMBEDDED_TESTS +/** * Increments refcount of user database. * @param db the database * @returns the database @@ -689,6 +617,7 @@ _dbus_user_database_ref (DBusUserDatabase *db) return db; } +#endif /* DBUS_ENABLE_EMBEDDED_TESTS */ /** * Decrements refcount of user database. @@ -719,57 +648,6 @@ _dbus_user_database_unref (DBusUserDatabase *db) } /** - * Gets all groups for a particular user. Returns #FALSE - * if no memory, or user isn't known, but always initializes - * group_ids to a NULL array. Sets error to the reason - * for returning #FALSE. - * - * @param db the user database object - * @param uid the user ID - * @param group_ids return location for array of group IDs - * @param n_group_ids return location for length of returned array - * @param error return location for error - * @returns #TRUE on success - */ -dbus_bool_t -_dbus_user_database_get_groups (DBusUserDatabase *db, - dbus_uid_t uid, - dbus_gid_t **group_ids, - int *n_group_ids, - DBusError *error) -{ - DBusUserInfo *info; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - - *group_ids = NULL; - *n_group_ids = 0; - - info = _dbus_user_database_lookup (db, uid, NULL, error); - if (info == NULL) - { - _DBUS_ASSERT_ERROR_IS_SET (error); - return FALSE; - } - - if (info->n_group_ids > 0) - { - *group_ids = dbus_new (dbus_gid_t, info->n_group_ids); - if (*group_ids == NULL) - { - dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); - return FALSE; - } - - *n_group_ids = info->n_group_ids; - - memcpy (*group_ids, info->group_ids, info->n_group_ids * sizeof (dbus_gid_t)); - } - - return TRUE; -} - -/** * Gets the user information for the given UID, * returned user info should not be freed. * @@ -790,26 +668,6 @@ _dbus_user_database_get_uid (DBusUserDatabase *db, } /** - * Gets the user information for the given GID, - * returned group info should not be freed. - * - * @param db user database - * @param gid the group ID - * @param info return location for const ref to group info - * @param error error location - * @returns #FALSE if error is set - */ -dbus_bool_t -_dbus_user_database_get_gid (DBusUserDatabase *db, - dbus_gid_t gid, - const DBusGroupInfo **info, - DBusError *error) -{ - *info = _dbus_user_database_lookup_group (db, gid, NULL, error); - return *info != NULL; -} - -/** * Gets the user information for the given username. * * @param db user database @@ -828,52 +686,6 @@ _dbus_user_database_get_username (DBusUserDatabase *db, return *info != NULL; } -/** - * Gets the user information for the given group name, - * returned group info should not be freed. - * - * @param db user database - * @param groupname the group name - * @param info return location for const ref to group info - * @param error error location - * @returns #FALSE if error is set - */ -dbus_bool_t -_dbus_user_database_get_groupname (DBusUserDatabase *db, - const DBusString *groupname, - const DBusGroupInfo **info, - DBusError *error) -{ - *info = _dbus_user_database_lookup_group (db, DBUS_GID_UNSET, groupname, error); - return *info != NULL; -} - /** @} */ -#ifdef DBUS_BUILD_TESTS -#include - -/** - * Unit test for dbus-userdb.c. - * - * @returns #TRUE on success. - */ -dbus_bool_t -_dbus_userdb_test (const char *test_data_dir) -{ - const DBusString *username; - const DBusString *homedir; - - if (!_dbus_username_from_current_process (&username)) - _dbus_assert_not_reached ("didn't get username"); - - if (!_dbus_homedir_from_current_process (&homedir)) - _dbus_assert_not_reached ("didn't get homedir"); - - printf (" Current user: %s homedir: %s\n", - _dbus_string_get_const_data (username), - _dbus_string_get_const_data (homedir)); - - return TRUE; -} -#endif /* DBUS_BUILD_TESTS */ +/* Tests in dbus-userdb-util.c */