D-Bus  1.4.10
dbus-userdb-util.c
1 /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
2 /* dbus-userdb-util.c Would be in dbus-userdb.c, but not used in libdbus
3  *
4  * Copyright (C) 2003, 2004, 2005 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 2.1
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21  *
22  */
23 #include <config.h>
24 #define DBUS_USERDB_INCLUDES_PRIVATE 1
25 #include "dbus-userdb.h"
26 #include "dbus-test.h"
27 #include "dbus-internals.h"
28 #include "dbus-protocol.h"
29 #include <string.h>
30 
45  DBusError *error)
46 {
47 
48  DBusUserDatabase *db;
49  const DBusUserInfo *info;
50  dbus_bool_t result = FALSE;
51 
52 #ifdef HAVE_CONSOLE_OWNER_FILE
53 
54  DBusString f;
55  DBusStat st;
56 
57  if (!_dbus_string_init (&f))
58  {
59  _DBUS_SET_OOM (error);
60  return FALSE;
61  }
62 
63  if (!_dbus_string_append(&f, DBUS_CONSOLE_OWNER_FILE))
64  {
66  _DBUS_SET_OOM (error);
67  return FALSE;
68  }
69 
70  if (_dbus_stat(&f, &st, NULL) && (st.uid == uid))
71  {
73  return TRUE;
74  }
75 
77 
78 #endif /* HAVE_CONSOLE_OWNER_FILE */
79 
81 
83  if (db == NULL)
84  {
85  dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get system database.");
87  return FALSE;
88  }
89 
90  /* TPTD: this should be cache-safe, we've locked the DB and
91  _dbus_user_at_console doesn't pass it on. */
92  info = _dbus_user_database_lookup (db, uid, NULL, error);
93 
94  if (info == NULL)
95  {
97  return FALSE;
98  }
99 
100  result = _dbus_user_at_console (info->username, error);
101 
103 
104  return result;
105 }
106 
115 _dbus_get_user_id (const DBusString *username,
116  dbus_uid_t *uid)
117 {
118  return _dbus_get_user_id_and_primary_group (username, uid, NULL);
119 }
120 
129 _dbus_get_group_id (const DBusString *groupname,
130  dbus_gid_t *gid)
131 {
132  DBusUserDatabase *db;
133  const DBusGroupInfo *info;
135 
137  if (db == NULL)
138  {
140  return FALSE;
141  }
142 
143  if (!_dbus_user_database_get_groupname (db, groupname,
144  &info, NULL))
145  {
147  return FALSE;
148  }
149 
150  *gid = info->gid;
151 
153  return TRUE;
154 }
155 
166  dbus_uid_t *uid_p,
167  dbus_gid_t *gid_p)
168 {
169  DBusUserDatabase *db;
170  const DBusUserInfo *info;
172 
174  if (db == NULL)
175  {
177  return FALSE;
178  }
179 
180  if (!_dbus_user_database_get_username (db, username,
181  &info, NULL))
182  {
184  return FALSE;
185  }
186 
187  if (uid_p)
188  *uid_p = info->uid;
189  if (gid_p)
190  *gid_p = info->primary_gid;
191 
193  return TRUE;
194 }
195 
209 _dbus_user_database_lookup_group (DBusUserDatabase *db,
210  dbus_gid_t gid,
211  const DBusString *groupname,
212  DBusError *error)
213 {
214  DBusGroupInfo *info;
215 
216  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
217 
218  /* See if the group is really a number */
219  if (gid == DBUS_UID_UNSET)
220  {
221  unsigned long n;
222 
223  if (_dbus_is_a_number (groupname, &n))
224  gid = n;
225  }
226 
227 #ifdef DBUS_ENABLE_USERDB_CACHE
228  if (gid != DBUS_GID_UNSET)
229  info = _dbus_hash_table_lookup_uintptr (db->groups, gid);
230  else
231  info = _dbus_hash_table_lookup_string (db->groups_by_name,
232  _dbus_string_get_const_data (groupname));
233  if (info)
234  {
235  _dbus_verbose ("Using cache for GID "DBUS_GID_FORMAT" information\n",
236  info->gid);
237  return info;
238  }
239  else
240 #else
241  if (1)
242 #endif
243  {
244  if (gid != DBUS_GID_UNSET)
245  _dbus_verbose ("No cache for GID "DBUS_GID_FORMAT"\n",
246  gid);
247  else
248  _dbus_verbose ("No cache for groupname \"%s\"\n",
249  _dbus_string_get_const_data (groupname));
250 
251  info = dbus_new0 (DBusGroupInfo, 1);
252  if (info == NULL)
253  {
255  return NULL;
256  }
257 
258  if (gid != DBUS_GID_UNSET)
259  {
260  if (!_dbus_group_info_fill_gid (info, gid, error))
261  {
262  _DBUS_ASSERT_ERROR_IS_SET (error);
264  return NULL;
265  }
266  }
267  else
268  {
269  if (!_dbus_group_info_fill (info, groupname, error))
270  {
271  _DBUS_ASSERT_ERROR_IS_SET (error);
273  return NULL;
274  }
275  }
276 
277  /* don't use these past here */
278  gid = DBUS_GID_UNSET;
279  groupname = NULL;
280 
281  if (!_dbus_hash_table_insert_uintptr (db->groups, info->gid, info))
282  {
285  return NULL;
286  }
287 
288 
289  if (!_dbus_hash_table_insert_string (db->groups_by_name,
290  info->groupname,
291  info))
292  {
293  _dbus_hash_table_remove_uintptr (db->groups, info->gid);
295  return NULL;
296  }
297 
298  return info;
299  }
300 }
301 
302 
314 _dbus_user_database_get_groupname (DBusUserDatabase *db,
315  const DBusString *groupname,
316  const DBusGroupInfo **info,
317  DBusError *error)
318 {
319  *info = _dbus_user_database_lookup_group (db, DBUS_GID_UNSET, groupname, error);
320  return *info != NULL;
321 }
322 
334 _dbus_user_database_get_gid (DBusUserDatabase *db,
335  dbus_gid_t gid,
336  const DBusGroupInfo **info,
337  DBusError *error)
338 {
339  *info = _dbus_user_database_lookup_group (db, gid, NULL, error);
340  return *info != NULL;
341 }
342 
343 
356  dbus_gid_t **group_ids,
357  int *n_group_ids)
358 {
359  DBusUserDatabase *db;
360  const DBusUserInfo *info;
361  *group_ids = NULL;
362  *n_group_ids = 0;
363 
365 
367  if (db == NULL)
368  {
370  return FALSE;
371  }
372 
373  if (!_dbus_user_database_get_uid (db, uid,
374  &info, NULL))
375  {
377  return FALSE;
378  }
379 
380  _dbus_assert (info->uid == uid);
381 
382  if (info->n_group_ids > 0)
383  {
384  *group_ids = dbus_new (dbus_gid_t, info->n_group_ids);
385  if (*group_ids == NULL)
386  {
388  return FALSE;
389  }
390 
391  *n_group_ids = info->n_group_ids;
392 
393  memcpy (*group_ids, info->group_ids, info->n_group_ids * sizeof (dbus_gid_t));
394  }
395 
397  return TRUE;
398 }
401 #ifdef DBUS_BUILD_TESTS
402 #include <stdio.h>
403 
410 _dbus_userdb_test (const char *test_data_dir)
411 {
412  const DBusString *username;
413  const DBusString *homedir;
414  dbus_uid_t uid;
415  unsigned long *group_ids;
416  int n_group_ids, i;
417 
418  if (!_dbus_username_from_current_process (&username))
419  _dbus_assert_not_reached ("didn't get username");
420 
421  if (!_dbus_homedir_from_current_process (&homedir))
422  _dbus_assert_not_reached ("didn't get homedir");
423 
424  if (!_dbus_get_user_id (username, &uid))
425  _dbus_assert_not_reached ("didn't get uid");
426 
427  if (!_dbus_groups_from_uid (uid, &group_ids, &n_group_ids))
428  _dbus_assert_not_reached ("didn't get groups");
429 
430  printf (" Current user: %s homedir: %s gids:",
431  _dbus_string_get_const_data (username),
432  _dbus_string_get_const_data (homedir));
433 
434  for (i=0; i<n_group_ids; i++)
435  printf(" %ld", group_ids[i]);
436 
437  printf ("\n");
438 
439  dbus_free (group_ids);
440 
441  return TRUE;
442 }
443 #endif /* DBUS_BUILD_TESTS */