D-Bus 1.6.12
|
00001 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ 00002 /* dbus-userdb-util.c Would be in dbus-userdb.c, but not used in libdbus 00003 * 00004 * Copyright (C) 2003, 2004, 2005 Red Hat, Inc. 00005 * 00006 * Licensed under the Academic Free License version 2.1 00007 * 00008 * This program is free software; you can redistribute it and/or modify 00009 * it under the terms of the GNU General Public License as published by 00010 * the Free Software Foundation; either version 2 of the License, or 00011 * (at your option) any later version. 00012 * 00013 * This program is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 * GNU General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU General Public License 00019 * along with this program; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00021 * 00022 */ 00023 #include <config.h> 00024 #define DBUS_USERDB_INCLUDES_PRIVATE 1 00025 #include "dbus-userdb.h" 00026 #include "dbus-test.h" 00027 #include "dbus-internals.h" 00028 #include "dbus-protocol.h" 00029 #include <string.h> 00030 00031 #if HAVE_SYSTEMD 00032 #include <systemd/sd-daemon.h> 00033 #include <systemd/sd-login.h> 00034 #endif 00035 00048 dbus_bool_t 00049 _dbus_is_console_user (dbus_uid_t uid, 00050 DBusError *error) 00051 { 00052 00053 DBusUserDatabase *db; 00054 const DBusUserInfo *info; 00055 dbus_bool_t result = FALSE; 00056 00057 #ifdef HAVE_SYSTEMD 00058 if (sd_booted () > 0) 00059 { 00060 int r; 00061 00062 /* Check whether this user is logged in on at least one physical 00063 seat */ 00064 r = sd_uid_get_seats (uid, 0, NULL); 00065 if (r < 0) 00066 { 00067 dbus_set_error (error, _dbus_error_from_errno (-r), 00068 "Failed to determine seats of user \"" DBUS_UID_FORMAT "\": %s", 00069 uid, 00070 _dbus_strerror (-r)); 00071 return FALSE; 00072 } 00073 00074 return (r > 0); 00075 } 00076 #endif 00077 00078 #ifdef HAVE_CONSOLE_OWNER_FILE 00079 00080 DBusString f; 00081 DBusStat st; 00082 00083 if (!_dbus_string_init (&f)) 00084 { 00085 _DBUS_SET_OOM (error); 00086 return FALSE; 00087 } 00088 00089 if (!_dbus_string_append(&f, DBUS_CONSOLE_OWNER_FILE)) 00090 { 00091 _dbus_string_free(&f); 00092 _DBUS_SET_OOM (error); 00093 return FALSE; 00094 } 00095 00096 if (_dbus_stat(&f, &st, NULL) && (st.uid == uid)) 00097 { 00098 _dbus_string_free(&f); 00099 return TRUE; 00100 } 00101 00102 _dbus_string_free(&f); 00103 00104 #endif /* HAVE_CONSOLE_OWNER_FILE */ 00105 00106 _dbus_user_database_lock_system (); 00107 00108 db = _dbus_user_database_get_system (); 00109 if (db == NULL) 00110 { 00111 dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get system database."); 00112 _dbus_user_database_unlock_system (); 00113 return FALSE; 00114 } 00115 00116 /* TPTD: this should be cache-safe, we've locked the DB and 00117 _dbus_user_at_console doesn't pass it on. */ 00118 info = _dbus_user_database_lookup (db, uid, NULL, error); 00119 00120 if (info == NULL) 00121 { 00122 _dbus_user_database_unlock_system (); 00123 return FALSE; 00124 } 00125 00126 result = _dbus_user_at_console (info->username, error); 00127 00128 _dbus_user_database_unlock_system (); 00129 00130 return result; 00131 } 00132 00140 dbus_bool_t 00141 _dbus_get_user_id (const DBusString *username, 00142 dbus_uid_t *uid) 00143 { 00144 return _dbus_get_user_id_and_primary_group (username, uid, NULL); 00145 } 00146 00154 dbus_bool_t 00155 _dbus_get_group_id (const DBusString *groupname, 00156 dbus_gid_t *gid) 00157 { 00158 DBusUserDatabase *db; 00159 const DBusGroupInfo *info; 00160 _dbus_user_database_lock_system (); 00161 00162 db = _dbus_user_database_get_system (); 00163 if (db == NULL) 00164 { 00165 _dbus_user_database_unlock_system (); 00166 return FALSE; 00167 } 00168 00169 if (!_dbus_user_database_get_groupname (db, groupname, 00170 &info, NULL)) 00171 { 00172 _dbus_user_database_unlock_system (); 00173 return FALSE; 00174 } 00175 00176 *gid = info->gid; 00177 00178 _dbus_user_database_unlock_system (); 00179 return TRUE; 00180 } 00181 00190 dbus_bool_t 00191 _dbus_get_user_id_and_primary_group (const DBusString *username, 00192 dbus_uid_t *uid_p, 00193 dbus_gid_t *gid_p) 00194 { 00195 DBusUserDatabase *db; 00196 const DBusUserInfo *info; 00197 _dbus_user_database_lock_system (); 00198 00199 db = _dbus_user_database_get_system (); 00200 if (db == NULL) 00201 { 00202 _dbus_user_database_unlock_system (); 00203 return FALSE; 00204 } 00205 00206 if (!_dbus_user_database_get_username (db, username, 00207 &info, NULL)) 00208 { 00209 _dbus_user_database_unlock_system (); 00210 return FALSE; 00211 } 00212 00213 if (uid_p) 00214 *uid_p = info->uid; 00215 if (gid_p) 00216 *gid_p = info->primary_gid; 00217 00218 _dbus_user_database_unlock_system (); 00219 return TRUE; 00220 } 00221 00234 DBusGroupInfo* 00235 _dbus_user_database_lookup_group (DBusUserDatabase *db, 00236 dbus_gid_t gid, 00237 const DBusString *groupname, 00238 DBusError *error) 00239 { 00240 DBusGroupInfo *info; 00241 00242 _DBUS_ASSERT_ERROR_IS_CLEAR (error); 00243 00244 /* See if the group is really a number */ 00245 if (gid == DBUS_UID_UNSET) 00246 { 00247 unsigned long n; 00248 00249 if (_dbus_is_a_number (groupname, &n)) 00250 gid = n; 00251 } 00252 00253 #ifdef DBUS_ENABLE_USERDB_CACHE 00254 if (gid != DBUS_GID_UNSET) 00255 info = _dbus_hash_table_lookup_uintptr (db->groups, gid); 00256 else 00257 info = _dbus_hash_table_lookup_string (db->groups_by_name, 00258 _dbus_string_get_const_data (groupname)); 00259 if (info) 00260 { 00261 _dbus_verbose ("Using cache for GID "DBUS_GID_FORMAT" information\n", 00262 info->gid); 00263 return info; 00264 } 00265 else 00266 #else 00267 if (1) 00268 #endif 00269 { 00270 if (gid != DBUS_GID_UNSET) 00271 _dbus_verbose ("No cache for GID "DBUS_GID_FORMAT"\n", 00272 gid); 00273 else 00274 _dbus_verbose ("No cache for groupname \"%s\"\n", 00275 _dbus_string_get_const_data (groupname)); 00276 00277 info = dbus_new0 (DBusGroupInfo, 1); 00278 if (info == NULL) 00279 { 00280 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00281 return NULL; 00282 } 00283 00284 if (gid != DBUS_GID_UNSET) 00285 { 00286 if (!_dbus_group_info_fill_gid (info, gid, error)) 00287 { 00288 _DBUS_ASSERT_ERROR_IS_SET (error); 00289 _dbus_group_info_free_allocated (info); 00290 return NULL; 00291 } 00292 } 00293 else 00294 { 00295 if (!_dbus_group_info_fill (info, groupname, error)) 00296 { 00297 _DBUS_ASSERT_ERROR_IS_SET (error); 00298 _dbus_group_info_free_allocated (info); 00299 return NULL; 00300 } 00301 } 00302 00303 /* don't use these past here */ 00304 gid = DBUS_GID_UNSET; 00305 groupname = NULL; 00306 00307 if (!_dbus_hash_table_insert_uintptr (db->groups, info->gid, info)) 00308 { 00309 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00310 _dbus_group_info_free_allocated (info); 00311 return NULL; 00312 } 00313 00314 00315 if (!_dbus_hash_table_insert_string (db->groups_by_name, 00316 info->groupname, 00317 info)) 00318 { 00319 _dbus_hash_table_remove_uintptr (db->groups, info->gid); 00320 dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); 00321 return NULL; 00322 } 00323 00324 return info; 00325 } 00326 } 00327 00328 00339 dbus_bool_t 00340 _dbus_user_database_get_groupname (DBusUserDatabase *db, 00341 const DBusString *groupname, 00342 const DBusGroupInfo **info, 00343 DBusError *error) 00344 { 00345 *info = _dbus_user_database_lookup_group (db, DBUS_GID_UNSET, groupname, error); 00346 return *info != NULL; 00347 } 00348 00359 dbus_bool_t 00360 _dbus_user_database_get_gid (DBusUserDatabase *db, 00361 dbus_gid_t gid, 00362 const DBusGroupInfo **info, 00363 DBusError *error) 00364 { 00365 *info = _dbus_user_database_lookup_group (db, gid, NULL, error); 00366 return *info != NULL; 00367 } 00368 00369 00380 dbus_bool_t 00381 _dbus_groups_from_uid (dbus_uid_t uid, 00382 dbus_gid_t **group_ids, 00383 int *n_group_ids) 00384 { 00385 DBusUserDatabase *db; 00386 const DBusUserInfo *info; 00387 *group_ids = NULL; 00388 *n_group_ids = 0; 00389 00390 _dbus_user_database_lock_system (); 00391 00392 db = _dbus_user_database_get_system (); 00393 if (db == NULL) 00394 { 00395 _dbus_user_database_unlock_system (); 00396 return FALSE; 00397 } 00398 00399 if (!_dbus_user_database_get_uid (db, uid, 00400 &info, NULL)) 00401 { 00402 _dbus_user_database_unlock_system (); 00403 return FALSE; 00404 } 00405 00406 _dbus_assert (info->uid == uid); 00407 00408 if (info->n_group_ids > 0) 00409 { 00410 *group_ids = dbus_new (dbus_gid_t, info->n_group_ids); 00411 if (*group_ids == NULL) 00412 { 00413 _dbus_user_database_unlock_system (); 00414 return FALSE; 00415 } 00416 00417 *n_group_ids = info->n_group_ids; 00418 00419 memcpy (*group_ids, info->group_ids, info->n_group_ids * sizeof (dbus_gid_t)); 00420 } 00421 00422 _dbus_user_database_unlock_system (); 00423 return TRUE; 00424 } 00427 #ifdef DBUS_BUILD_TESTS 00428 #include <stdio.h> 00429 00435 dbus_bool_t 00436 _dbus_userdb_test (const char *test_data_dir) 00437 { 00438 const DBusString *username; 00439 const DBusString *homedir; 00440 dbus_uid_t uid; 00441 unsigned long *group_ids; 00442 int n_group_ids, i; 00443 DBusError error; 00444 00445 if (!_dbus_username_from_current_process (&username)) 00446 _dbus_assert_not_reached ("didn't get username"); 00447 00448 if (!_dbus_homedir_from_current_process (&homedir)) 00449 _dbus_assert_not_reached ("didn't get homedir"); 00450 00451 if (!_dbus_get_user_id (username, &uid)) 00452 _dbus_assert_not_reached ("didn't get uid"); 00453 00454 if (!_dbus_groups_from_uid (uid, &group_ids, &n_group_ids)) 00455 _dbus_assert_not_reached ("didn't get groups"); 00456 00457 printf (" Current user: %s homedir: %s gids:", 00458 _dbus_string_get_const_data (username), 00459 _dbus_string_get_const_data (homedir)); 00460 00461 for (i=0; i<n_group_ids; i++) 00462 printf(" %ld", group_ids[i]); 00463 00464 printf ("\n"); 00465 00466 dbus_error_init (&error); 00467 printf ("Is Console user: %i\n", 00468 _dbus_is_console_user (uid, &error)); 00469 printf ("Invocation was OK: %s\n", error.message ? error.message : "yes"); 00470 dbus_error_free (&error); 00471 printf ("Is Console user 4711: %i\n", 00472 _dbus_is_console_user (4711, &error)); 00473 printf ("Invocation was OK: %s\n", error.message ? error.message : "yes"); 00474 dbus_error_free (&error); 00475 00476 dbus_free (group_ids); 00477 00478 return TRUE; 00479 } 00480 #endif /* DBUS_BUILD_TESTS */