summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2007-06-09 21:53:20 +0000
committerHavoc Pennington <hp@redhat.com>2007-06-09 21:53:20 +0000
commit23832672266bb4ff23b66247c0cfa1a2ed0cc97b (patch)
tree119e37411f14923780de3ca7a759707508f1ec63
parentb80a8fe6b364543aa4b32a02a5ad913faf97173b (diff)
2007-06-09 Havoc Pennington <hp@redhat.com>
* bus/dispatch.c (check_get_connection_unix_process_id): adapt since sysdeps-unix.h stuff isn't included anymore * bus/bus.c (bus_context_new): use more abstract functions to change user, so they can be no-ops on Windows * dbus/dbus-credentials.c, dbus/dbus-credentials.h, dbus/dbus-credentials-util.c: new files containing a fully opaque DBusCredentials data type to replace the old not opaque one. * configure.in (DBUS_UNIX): define DBUS_UNIX to match DBUS_WIN on windows * dbus/dbus-userdb.h: prohibit on Windows, next step is to clean up the uses of it in bus/*.c and factor out the parts of cookie auth that depend on it
-rw-r--r--ChangeLog19
-rw-r--r--bus/bus.c11
-rw-r--r--bus/dispatch.c6
-rw-r--r--bus/policy.c4
-rw-r--r--configure.in2
-rw-r--r--dbus/Makefile.am3
-rw-r--r--dbus/dbus-auth-script.c84
-rw-r--r--dbus/dbus-auth.c146
-rw-r--r--dbus/dbus-auth.h5
-rw-r--r--dbus/dbus-credentials-util.c202
-rw-r--r--dbus/dbus-credentials.c418
-rw-r--r--dbus/dbus-credentials.h71
-rw-r--r--dbus/dbus-internals.c10
-rw-r--r--dbus/dbus-keyring.c1
-rw-r--r--dbus/dbus-marshal-recursive-util.c2
-rw-r--r--dbus/dbus-spawn.c4
-rw-r--r--dbus/dbus-sysdeps-unix.c225
-rw-r--r--dbus/dbus-sysdeps-unix.h57
-rw-r--r--dbus/dbus-sysdeps-util-unix.c37
-rw-r--r--dbus/dbus-sysdeps-win.c1
-rw-r--r--dbus/dbus-sysdeps.c109
-rw-r--r--dbus/dbus-sysdeps.h98
-rw-r--r--dbus/dbus-test.c2
-rw-r--r--dbus/dbus-test.h1
-rw-r--r--dbus/dbus-transport-protected.h2
-rw-r--r--dbus/dbus-transport-socket.c31
-rw-r--r--dbus/dbus-transport.c99
-rw-r--r--dbus/dbus-userdb-util.c86
-rw-r--r--dbus/dbus-userdb.c42
-rw-r--r--dbus/dbus-userdb.h15
-rw-r--r--test/Makefile.am1
31 files changed, 1360 insertions, 434 deletions
diff --git a/ChangeLog b/ChangeLog
index 1423b0d7..4fe45e26 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,22 @@
+2007-06-09 Havoc Pennington <hp@redhat.com>
+
+ * bus/dispatch.c (check_get_connection_unix_process_id): adapt
+ since sysdeps-unix.h stuff isn't included anymore
+
+ * bus/bus.c (bus_context_new): use more abstract functions to
+ change user, so they can be no-ops on Windows
+
+ * dbus/dbus-credentials.c, dbus/dbus-credentials.h,
+ dbus/dbus-credentials-util.c: new files containing a fully opaque
+ DBusCredentials data type to replace the old not opaque one.
+
+ * configure.in (DBUS_UNIX): define DBUS_UNIX to match DBUS_WIN on
+ windows
+
+ * dbus/dbus-userdb.h: prohibit on Windows, next step is to clean
+ up the uses of it in bus/*.c and factor out the parts of
+ cookie auth that depend on it
+
2007-06-07 Havoc Pennington <hp@redhat.com>
* dbus/dbus-message.c: improve some docs related to reading values
diff --git a/bus/bus.c b/bus/bus.c
index fb9322a9..e1396f23 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -533,7 +533,6 @@ bus_context_new (const DBusString *config_file,
{
BusContext *context;
BusConfigParser *parser;
- DBusCredentials creds;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -660,13 +659,7 @@ bus_context_new (const DBusString *config_file,
/* check user before we fork */
if (context->user != NULL)
{
- DBusString u;
-
- _dbus_string_init_const (&u, context->user);
-
- if (!_dbus_credentials_from_username (&u, &creds) ||
- creds.uid < 0 ||
- creds.gid < 0)
+ if (!_dbus_verify_daemon_user (context->user))
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Could not get UID and GID for username \"%s\"",
@@ -769,7 +762,7 @@ bus_context_new (const DBusString *config_file,
*/
if (context->user != NULL)
{
- if (!_dbus_change_identity (creds.uid, creds.gid, error))
+ if (!_dbus_change_to_daemon_user (context->user, error))
{
_DBUS_ASSERT_ERROR_IS_SET (error);
goto failed;
diff --git a/bus/dispatch.c b/bus/dispatch.c
index f491ef44..ef75933f 100644
--- a/bus/dispatch.c
+++ b/bus/dispatch.c
@@ -399,6 +399,10 @@ bus_dispatch_remove_connection (DBusConnection *connection)
#ifdef DBUS_BUILD_TESTS
#include <stdio.h>
+#ifdef DBUS_UNIX
+#include <sys/types.h>
+#include <unistd.h>
+#endif
/* This is used to know whether we need to block in order to finish
* sending a message, or whether the initial dbus_connection_send()
@@ -1313,7 +1317,7 @@ check_get_connection_unix_process_id (BusContext *context,
* cause then we can test that the pid returned matches
* getppid()
*/
- if (pid != (dbus_uint32_t) _dbus_getpid ())
+ if (pid != (dbus_uint32_t) getpid ())
{
_dbus_assert (dbus_error_is_set (&error));
_dbus_warn ("Result from GetConnectionUnixProcessID is not our own pid\n");
diff --git a/bus/policy.c b/bus/policy.c
index 52ae72a4..7782563b 100644
--- a/bus/policy.c
+++ b/bus/policy.c
@@ -324,13 +324,9 @@ bus_policy_create_client_policy (BusPolicy *policy,
if (!dbus_connection_get_unix_user (connection, &uid))
{
-#ifdef DBUS_WIN_FIXME
- _dbus_verbose ("policy.c: dbus_connection_get_unix_user check disabled under windows\n");
-#else
dbus_set_error (error, DBUS_ERROR_FAILED,
"No user ID known for connection, cannot determine security policy\n");
goto failed;
-#endif
}
if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0)
diff --git a/configure.in b/configure.in
index 6cbcb9b3..4836342f 100644
--- a/configure.in
+++ b/configure.in
@@ -1169,6 +1169,8 @@ fi
AC_DEFINE_UNQUOTED(DBUS_SESSION_SOCKET_DIR, "$DBUS_SESSION_SOCKET_DIR", [Where per-session bus puts its sockets])
AC_SUBST(DBUS_SESSION_SOCKET_DIR)
+AC_DEFINE_UNQUOTED(DBUS_UNIX, "1", [Defined on UNIX and Linux systems and not on Windows])
+
AC_OUTPUT([
Doxyfile
dbus/dbus-arch-deps.h
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index 70d5b371..d27ca6f4 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -41,6 +41,8 @@ DBUS_LIB_SOURCES= \
dbus-bus.c \
dbus-connection.c \
dbus-connection-internal.h \
+ dbus-credentials.c \
+ dbus-credentials.h \
dbus-errors.c \
dbus-keyring.c \
dbus-keyring.h \
@@ -128,6 +130,7 @@ DBUS_SHARED_SOURCES= \
### to be unless they move to DBUS_SHARED_SOURCES later)
DBUS_UTIL_SOURCES= \
dbus-auth-util.c \
+ dbus-credentials-util.c \
dbus-mainloop.c \
dbus-mainloop.h \
dbus-marshal-byteswap-util.c \
diff --git a/dbus/dbus-auth-script.c b/dbus/dbus-auth-script.c
index 3cb86d0f..5aa17d4b 100644
--- a/dbus/dbus-auth-script.c
+++ b/dbus/dbus-auth-script.c
@@ -28,8 +28,8 @@
#include "dbus-auth.h"
#include "dbus-string.h"
#include "dbus-hash.h"
+#include "dbus-credentials.h"
#include "dbus-internals.h"
-#include "dbus-userdb.h"
/**
* @defgroup DBusAuthScript code for running unit test scripts for DBusAuth
@@ -209,6 +209,29 @@ split_string (DBusString *str)
return array;
}
+static void
+auth_set_unix_credentials(DBusAuth *auth,
+ dbus_uid_t uid,
+ dbus_pid_t pid)
+{
+ DBusCredentials *credentials;
+
+ credentials = _dbus_credentials_new ();
+ if (credentials == NULL)
+ {
+ _dbus_warn ("no memory\n");
+ return;
+ }
+ if (uid != DBUS_UID_UNSET)
+ _dbus_credentials_add_unix_uid (credentials, uid);
+ if (pid != DBUS_PID_UNSET)
+ _dbus_credentials_add_unix_pid (credentials, pid);
+
+ _dbus_auth_set_credentials (auth, credentials);
+
+ _dbus_credentials_unref (credentials);
+}
+
/**
* Runs an "auth script" which is a script for testing the
* authentication protocol. Scripts send and receive data, and then
@@ -303,7 +326,7 @@ _dbus_auth_script_run (const DBusString *filename)
else if (_dbus_string_starts_with_c_str (&line,
"CLIENT"))
{
- DBusCredentials creds;
+ DBusCredentials *creds;
if (auth != NULL)
{
@@ -321,14 +344,31 @@ _dbus_auth_script_run (const DBusString *filename)
/* test ref/unref */
_dbus_auth_ref (auth);
_dbus_auth_unref (auth);
+
+ creds = _dbus_credentials_new_from_current_process ();
+ if (creds == NULL)
+ {
+ _dbus_warn ("no memory for credentials\n");
+ _dbus_auth_unref (auth);
+ auth = NULL;
+ goto out;
+ }
+
+ if (!_dbus_auth_set_credentials (auth, creds))
+ {
+ _dbus_warn ("no memory for setting credentials\n");
+ _dbus_auth_unref (auth);
+ auth = NULL;
+ _dbus_credentials_unref (creds);
+ goto out;
+ }
- _dbus_credentials_from_current_process (&creds);
- _dbus_auth_set_credentials (auth, &creds);
+ _dbus_credentials_unref (creds);
}
else if (_dbus_string_starts_with_c_str (&line,
"SERVER"))
{
- DBusCredentials creds;
+ DBusCredentials *creds;
if (auth != NULL)
{
@@ -346,9 +386,27 @@ _dbus_auth_script_run (const DBusString *filename)
/* test ref/unref */
_dbus_auth_ref (auth);
_dbus_auth_unref (auth);
+
+ creds = _dbus_credentials_new_from_current_process ();
+ if (creds == NULL)
+ {
+ _dbus_warn ("no memory for credentials\n");
+ _dbus_auth_unref (auth);
+ auth = NULL;
+ goto out;
+ }
+
+ if (!_dbus_auth_set_credentials (auth, creds))
+ {
+ _dbus_warn ("no memory for setting credentials\n");
+ _dbus_auth_unref (auth);
+ auth = NULL;
+ _dbus_credentials_unref (creds);
+ goto out;
+ }
- _dbus_credentials_from_current_process (&creds);
- _dbus_auth_set_credentials (auth, &creds);
+ _dbus_credentials_unref (creds);
+
_dbus_auth_set_context (auth, &context);
}
else if (auth == NULL)
@@ -360,20 +418,17 @@ _dbus_auth_script_run (const DBusString *filename)
else if (_dbus_string_starts_with_c_str (&line,
"NO_CREDENTIALS"))
{
- DBusCredentials creds = { -1, -1, -1 };
- _dbus_auth_set_credentials (auth, &creds);
+ auth_set_unix_credentials (auth, DBUS_UID_UNSET, DBUS_PID_UNSET);
}
else if (_dbus_string_starts_with_c_str (&line,
"ROOT_CREDENTIALS"))
{
- DBusCredentials creds = { -1, 0, 0 };
- _dbus_auth_set_credentials (auth, &creds);
+ auth_set_unix_credentials (auth, 0, DBUS_PID_UNSET);
}
else if (_dbus_string_starts_with_c_str (&line,
"SILLY_CREDENTIALS"))
{
- DBusCredentials creds = { -1, 4312, 1232 };
- _dbus_auth_set_credentials (auth, &creds);
+ auth_set_unix_credentials (auth, 4312, DBUS_PID_UNSET);
}
else if (_dbus_string_starts_with_c_str (&line,
"ALLOWED_MECHS"))
@@ -432,8 +487,7 @@ _dbus_auth_script_run (const DBusString *filename)
goto out;
}
- if (!_dbus_string_append_uint (&username,
- _dbus_getuid ()))
+ if (!_dbus_append_desired_identity (&username))
{
_dbus_warn ("no memory for userid\n");
_dbus_string_free (&username);
diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c
index 7ece76e4..b1d57a49 100644
--- a/dbus/dbus-auth.c
+++ b/dbus/dbus-auth.c
@@ -27,7 +27,7 @@
#include "dbus-keyring.h"
#include "dbus-sha.h"
#include "dbus-protocol.h"
-#include "dbus-userdb.h"
+#include "dbus-credentials.h"
/**
* @defgroup DBusAuth Authentication
@@ -162,13 +162,12 @@ struct DBusAuth
* as.
*/
- DBusCredentials credentials; /**< Credentials read from socket,
- * fields may be -1
- */
+ DBusCredentials *credentials; /**< Credentials read from socket
+ */
- DBusCredentials authorized_identity; /**< Credentials that are authorized */
+ DBusCredentials *authorized_identity; /**< Credentials that are authorized */
- DBusCredentials desired_identity; /**< Identity client has requested */
+ DBusCredentials *desired_identity; /**< Identity client has requested */
DBusString context; /**< Cookie scope */
DBusKeyring *keyring; /**< Keyring for cookie mechanism. */
@@ -331,10 +330,6 @@ _dbus_auth_new (int size)
return NULL;
auth->refcount = 1;
-
- _dbus_credentials_clear (&auth->credentials);
- _dbus_credentials_clear (&auth->authorized_identity);
- _dbus_credentials_clear (&auth->desired_identity);
auth->keyring = NULL;
auth->cookie_id = -1;
@@ -365,9 +360,31 @@ _dbus_auth_new (int size)
/* default context if none is specified */
if (!_dbus_string_append (&auth->context, "org_freedesktop_general"))
goto enomem_5;
+
+ auth->credentials = _dbus_credentials_new ();
+ if (auth->credentials == NULL)
+ goto enomem_6;
+
+ auth->authorized_identity = _dbus_credentials_new ();
+ if (auth->authorized_identity == NULL)
+ goto enomem_7;
+
+ auth->desired_identity = _dbus_credentials_new ();
+ if (auth->desired_identity == NULL)
+ goto enomem_8;
return auth;
+#if 0
+ enomem_9:
+ _dbus_credentials_unref (auth->desired_identity);
+#endif
+ enomem_8:
+ _dbus_credentials_unref (auth->authorized_identity);
+ enomem_7:
+ _dbus_credentials_unref (auth->credentials);
+ enomem_6:
+ /* last alloc was an append to context, which is freed already below */ ;
enomem_5:
_dbus_string_free (&auth->challenge);
enomem_4:
@@ -390,8 +407,8 @@ shutdown_mech (DBusAuth *auth)
auth->already_asked_for_initial_response = FALSE;
_dbus_string_set_length (&auth->identity, 0);
- _dbus_credentials_clear (&auth->authorized_identity);
- _dbus_credentials_clear (&auth->desired_identity);
+ _dbus_credentials_clear (auth->authorized_identity);
+ _dbus_credentials_clear (auth->desired_identity);
if (auth->mech != NULL)
{
@@ -513,7 +530,7 @@ sha1_handle_first_client_response (DBusAuth *auth,
}
}
- if (!_dbus_credentials_from_username (data, &auth->desired_identity))
+ if (!_dbus_credentials_add_from_username (auth->desired_identity, data))
{
_dbus_verbose ("%s: Did not get a valid username from client\n",
DBUS_AUTH_NAME (auth));
@@ -706,14 +723,17 @@ sha1_handle_second_client_response (DBusAuth *auth,
retval = TRUE;
goto out_3;
}
-
+
+ if (!_dbus_credentials_add_credentials (auth->authorized_identity,
+ auth->desired_identity))
+ goto out_3;
+
if (!send_ok (auth))
goto out_3;
- _dbus_verbose ("%s: authenticated client with UID "DBUS_UID_FORMAT" using DBUS_COOKIE_SHA1\n",
- DBUS_AUTH_NAME (auth), auth->desired_identity.uid);
+ _dbus_verbose ("%s: authenticated client using DBUS_COOKIE_SHA1\n",
+ DBUS_AUTH_NAME (auth));
- auth->authorized_identity = auth->desired_identity;
retval = TRUE;
out_3:
@@ -966,7 +986,7 @@ static dbus_bool_t
handle_server_data_external_mech (DBusAuth *auth,
const DBusString *data)
{
- if (auth->credentials.uid == DBUS_UID_UNSET)
+ if (_dbus_credentials_are_empty (auth->credentials))
{
_dbus_verbose ("%s: no credentials, mechanism EXTERNAL can't authenticate\n",
DBUS_AUTH_NAME (auth));
@@ -1005,7 +1025,7 @@ handle_server_data_external_mech (DBusAuth *auth,
return FALSE;
}
- _dbus_credentials_clear (&auth->desired_identity);
+ _dbus_credentials_clear (auth->desired_identity);
/* If auth->identity is still empty here, then client
* responded with an empty string after we poked it for
@@ -1014,12 +1034,16 @@ handle_server_data_external_mech (DBusAuth *auth,
*/
if (_dbus_string_get_length (&auth->identity) == 0)
{
- auth->desired_identity.uid = auth->credentials.uid;
+ if (!_dbus_credentials_add_credentials (auth->desired_identity,
+ auth->credentials))
+ {
+ return FALSE; /* OOM */
+ }
}
else
{
- if (!_dbus_parse_uid (&auth->identity,
- &auth->desired_identity.uid))
+ if (!_dbus_credentials_parse_and_add_desired(auth->desired_identity,
+ &auth->identity))
{
_dbus_verbose ("%s: could not get credentials from uid string\n",
DBUS_AUTH_NAME (auth));
@@ -1027,7 +1051,7 @@ handle_server_data_external_mech (DBusAuth *auth,
}
}
- if (auth->desired_identity.uid == DBUS_UID_UNSET)
+ if (_dbus_credentials_are_empty(auth->desired_identity))
{
_dbus_verbose ("%s: desired user %s is no good\n",
DBUS_AUTH_NAME (auth),
@@ -1035,32 +1059,34 @@ handle_server_data_external_mech (DBusAuth *auth,
return send_rejected (auth);
}
- if (_dbus_credentials_match (&auth->desired_identity,
- &auth->credentials))
+ if (_dbus_credentials_are_superset (auth->credentials,
+ auth->desired_identity))
{
- /* client has authenticated */
+ /* client has authenticated */
+ if (!_dbus_credentials_add_credentials (auth->authorized_identity,
+ auth->desired_identity))
+ return FALSE;
+
+ /* also copy process ID from the socket credentials - FIXME this
+ * should be done even if auth EXTERNAL not used
+ */
+ if (!_dbus_credentials_add_credential (auth->authorized_identity,
+ DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+ auth->credentials))
+ return FALSE;
+
if (!send_ok (auth))
return FALSE;
- _dbus_verbose ("%s: authenticated client with UID "DBUS_UID_FORMAT
- " matching socket credentials UID "DBUS_UID_FORMAT"\n",
- DBUS_AUTH_NAME (auth),
- auth->desired_identity.uid,
- auth->credentials.uid);
+ _dbus_verbose ("%s: authenticated client based on socket credentials\n",
+ DBUS_AUTH_NAME (auth));
- auth->authorized_identity.pid = auth->credentials.pid;
- auth->authorized_identity.uid = auth->desired_identity.uid;
return TRUE;
}
else
{
- _dbus_verbose ("%s: credentials uid="DBUS_UID_FORMAT
- " gid="DBUS_GID_FORMAT
- " do not allow uid="DBUS_UID_FORMAT
- " gid="DBUS_GID_FORMAT"\n",
- DBUS_AUTH_NAME (auth),
- auth->credentials.uid, auth->credentials.gid,
- auth->desired_identity.uid, auth->desired_identity.gid);
+ _dbus_verbose ("%s: desired identity not found in socket credentials\n",
+ DBUS_AUTH_NAME (auth));
return send_rejected (auth);
}
}
@@ -1084,9 +1110,8 @@ handle_client_initial_response_external_mech (DBusAuth *auth,
if (!_dbus_string_init (&plaintext))
return FALSE;
-
- if (!_dbus_string_append_uint (&plaintext,
- _dbus_getuid ()))
+
+ if (!_dbus_append_desired_identity (&plaintext))
goto failed;
if (!_dbus_string_hex_encode (&plaintext, 0,
@@ -2105,6 +2130,10 @@ _dbus_auth_unref (DBusAuth *auth)
_dbus_string_free (&auth->outgoing);
dbus_free_string_array (auth->allowed_mechs);
+
+ _dbus_credentials_unref (auth->credentials);
+ _dbus_credentials_unref (auth->authorized_identity);
+ _dbus_credentials_unref (auth->desired_identity);
dbus_free (auth);
}
@@ -2435,29 +2464,42 @@ _dbus_auth_decode_data (DBusAuth *auth,
*
* @param auth the auth conversation
* @param credentials the credentials received
+ * @returns #FALSE on OOM
*/
-void
+dbus_bool_t
_dbus_auth_set_credentials (DBusAuth *auth,
- const DBusCredentials *credentials)
+ DBusCredentials *credentials)
{
- auth->credentials = *credentials;
+ _dbus_credentials_clear (auth->credentials);
+ return _dbus_credentials_add_credentials (auth->credentials,
+ credentials);
}
/**
* Gets the identity we authorized the client as. Apps may have
* different policies as to what identities they allow.
*
+ * Returned credentials are not a copy and should not be modified
+ *
* @param auth the auth conversation
- * @param credentials the credentials we've authorized
+ * @returns the credentials we've authorized BY REFERENCE do not modify
*/
-void
-_dbus_auth_get_identity (DBusAuth *auth,
- DBusCredentials *credentials)
+DBusCredentials*
+_dbus_auth_get_identity (DBusAuth *auth)
{
if (auth->state == &common_state_authenticated)
- *credentials = auth->authorized_identity;
+ {
+ return auth->authorized_identity;
+ }
else
- _dbus_credentials_clear (credentials);
+ {
+ /* FIXME instead of this, keep an empty credential around that
+ * doesn't require allocation or something
+ */
+ /* return empty credentials */
+ _dbus_assert (_dbus_credentials_are_empty (auth->authorized_identity));
+ return auth->authorized_identity;
+ }
}
/**
diff --git a/dbus/dbus-auth.h b/dbus/dbus-auth.h
index 9cff8b56..4b6b1065 100644
--- a/dbus/dbus-auth.h
+++ b/dbus/dbus-auth.h
@@ -68,10 +68,9 @@ dbus_bool_t _dbus_auth_needs_decoding (DBusAuth *auth);
dbus_bool_t _dbus_auth_decode_data (DBusAuth *auth,
const DBusString *encoded,
DBusString *plaintext);
-void _dbus_auth_set_credentials (DBusAuth *auth,
- const DBusCredentials *credentials);
-void _dbus_auth_get_identity (DBusAuth *auth,
+dbus_bool_t _dbus_auth_set_credentials (DBusAuth *auth,
DBusCredentials *credentials);
+DBusCredentials* _dbus_auth_get_identity (DBusAuth *auth);
dbus_bool_t _dbus_auth_set_context (DBusAuth *auth,
const DBusString *context);
const char* _dbus_auth_get_guid_from_server(DBusAuth *auth);
diff --git a/dbus/dbus-credentials-util.c b/dbus/dbus-credentials-util.c
new file mode 100644
index 00000000..9b81aca4
--- /dev/null
+++ b/dbus/dbus-credentials-util.c
@@ -0,0 +1,202 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-credentials-util.c Would be in dbus-credentials.c, but only used for tests/bus
+ *
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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
+ *
+ */
+#include "dbus-internals.h"
+#include "dbus-test.h"
+#include "dbus-credentials.h"
+
+/**
+ * @addtogroup DBusCredentials
+ * @{
+ */
+
+/** @} */
+
+#ifdef DBUS_BUILD_TESTS
+#include "dbus-test.h"
+#include <stdio.h>
+#include <string.h>
+
+static DBusCredentials*
+make_credentials(dbus_uid_t unix_uid,
+ dbus_pid_t unix_pid,
+ const char *windows_sid)
+{
+ DBusCredentials *credentials;
+
+ credentials = _dbus_credentials_new ();
+
+ if (unix_uid != DBUS_UID_UNSET)
+ {
+ if (!_dbus_credentials_add_unix_uid (credentials, unix_uid))
+ {
+ _dbus_credentials_unref (credentials);
+ return NULL;
+ }
+ }
+
+ if (unix_pid != DBUS_PID_UNSET)
+ {
+ if (!_dbus_credentials_add_unix_pid (credentials, unix_pid))
+ {
+ _dbus_credentials_unref (credentials);
+ return NULL;
+ }
+ }
+
+ if (windows_sid != NULL)
+ {
+ if (!_dbus_credentials_add_windows_sid (credentials, windows_sid))
+ {
+ _dbus_credentials_unref (credentials);
+ return NULL;
+ }
+ }
+
+ return credentials;
+}
+
+#define SAMPLE_SID "whatever a windows sid looks like"
+#define OTHER_SAMPLE_SID "whatever else"
+
+dbus_bool_t
+_dbus_credentials_test (const char *test_data_dir)
+{
+ DBusCredentials *creds;
+ DBusCredentials *creds2;
+
+ if (test_data_dir == NULL)
+ return TRUE;
+
+ creds = make_credentials (12, 511, SAMPLE_SID);
+ if (creds == NULL)
+ _dbus_assert_not_reached ("oom");
+
+ /* test refcounting */
+ _dbus_credentials_ref (creds);
+ _dbus_credentials_unref (creds);
+
+ _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_USER_ID));
+ _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_PROCESS_ID));
+ _dbus_assert (_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID));
+
+ _dbus_assert (_dbus_credentials_get_unix_uid (creds) == 12);
+ _dbus_assert (_dbus_credentials_get_unix_pid (creds) == 511);
+ _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds), SAMPLE_SID) == 0);
+
+ _dbus_assert (!_dbus_credentials_are_empty (creds));
+
+ /* Test copy */
+ creds2 = _dbus_credentials_copy (creds);
+ if (creds2 == NULL)
+ _dbus_assert_not_reached ("oom");
+
+ _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_UNIX_USER_ID));
+ _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_UNIX_PROCESS_ID));
+ _dbus_assert (_dbus_credentials_include (creds2, DBUS_CREDENTIAL_WINDOWS_SID));
+
+ _dbus_assert (_dbus_credentials_get_unix_uid (creds2) == 12);
+ _dbus_assert (_dbus_credentials_get_unix_pid (creds2) == 511);
+ _dbus_assert (strcmp (_dbus_credentials_get_windows_sid (creds2), SAMPLE_SID) == 0);
+
+ _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+
+ _dbus_credentials_unref (creds2);
+
+ /* Same user if both unix and windows are the same */
+ creds2 = make_credentials (12, DBUS_PID_UNSET, SAMPLE_SID);
+ if (creds2 == NULL)
+ _dbus_assert_not_reached ("oom");
+
+ _dbus_assert (_dbus_credentials_same_user (creds, creds2));
+
+ _dbus_credentials_unref (creds2);
+
+ /* Not the same user if Windows is missing */
+ creds2 = make_credentials (12, DBUS_PID_UNSET, NULL);
+ if (creds2 == NULL)
+ _dbus_assert_not_reached ("oom");
+
+ _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+ _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+
+ _dbus_credentials_unref (creds2);
+
+ /* Not the same user if Windows is different */
+ creds2 = make_credentials (12, DBUS_PID_UNSET, OTHER_SAMPLE_SID);
+ if (creds2 == NULL)
+ _dbus_assert_not_reached ("oom");
+
+ _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+ _dbus_assert (!_dbus_credentials_are_superset (creds, creds2));
+
+ _dbus_credentials_unref (creds2);
+
+ /* Not the same user if Unix is missing */
+ creds2 = make_credentials (DBUS_UID_UNSET, DBUS_PID_UNSET, SAMPLE_SID);
+ if (creds2 == NULL)
+ _dbus_assert_not_reached ("oom");
+
+ _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+ _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+
+ _dbus_credentials_unref (creds2);
+
+ /* Not the same user if Unix is different */
+ creds2 = make_credentials (15, DBUS_PID_UNSET, SAMPLE_SID);
+ if (creds2 == NULL)
+ _dbus_assert_not_reached ("oom");
+
+ _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+ _dbus_assert (!_dbus_credentials_are_superset (creds, creds2));
+
+ _dbus_credentials_unref (creds2);
+
+ /* Not the same user if both are missing */
+ creds2 = make_credentials (DBUS_UID_UNSET, DBUS_PID_UNSET, NULL);
+ if (creds2 == NULL)
+ _dbus_assert_not_reached ("oom");
+
+ _dbus_assert (!_dbus_credentials_same_user (creds, creds2));
+ _dbus_assert (_dbus_credentials_are_superset (creds, creds2));
+
+ _dbus_credentials_unref (creds2);
+
+ /* Clearing credentials works */
+ _dbus_credentials_clear (creds);
+
+ _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_USER_ID));
+ _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_UNIX_PROCESS_ID));
+ _dbus_assert (!_dbus_credentials_include (creds, DBUS_CREDENTIAL_WINDOWS_SID));
+
+ _dbus_assert (_dbus_credentials_get_unix_uid (creds) == DBUS_UID_UNSET);
+ _dbus_assert (_dbus_credentials_get_unix_pid (creds) == DBUS_PID_UNSET);
+ _dbus_assert (_dbus_credentials_get_windows_sid (creds) == NULL);
+
+ _dbus_assert (_dbus_credentials_are_empty (creds));
+
+ _dbus_credentials_unref (creds);
+
+ return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
diff --git a/dbus/dbus-credentials.c b/dbus/dbus-credentials.c
new file mode 100644
index 00000000..dde69281
--- /dev/null
+++ b/dbus/dbus-credentials.c
@@ -0,0 +1,418 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-credentials.c Credentials provable through authentication
+ *
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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
+ *
+ */
+#include <config.h>
+#include <string.h>
+#include "dbus-credentials.h"
+#include "dbus-internals.h"
+
+/**
+ * @defgroup DBusCredentials Credentials provable through authentication
+ * @ingroup DBusInternals
+ * @brief DBusCredentials object
+ *
+ * Credentials are what you have to prove you have in order to
+ * authenticate. The main credentials right now are a unix user
+ * account, a Windows user account, or a UNIX process ID.
+ */
+
+/**
+ * @defgroup DBusCredentialsInternals Credentials implementation details
+ * @ingroup DBusInternals
+ * @brief DBusCredentials implementation details
+ *
+ * Private details of credentials code.
+ *
+ * @{
+ */
+
+struct DBusCredentials {
+ int refcount;
+ dbus_uid_t unix_uid;
+ dbus_pid_t unix_pid;
+ char *windows_sid;
+};
+
+/** @} */
+
+/**
+ * @addtogroup DBusCredentials
+ * @{
+ */
+
+/**
+ * Creates a new credentials object.
+ *
+ * @returns the new object or #NULL if no memory
+ */
+DBusCredentials*
+_dbus_credentials_new (void)
+{
+ DBusCredentials *creds;
+
+ creds = dbus_new (DBusCredentials, 1);
+ if (creds == NULL)
+ return NULL;
+
+ creds->refcount = 1;
+ creds->unix_uid = DBUS_UID_UNSET;
+ creds->unix_pid = DBUS_PID_UNSET;
+ creds->windows_sid = NULL;
+
+ return creds;
+}
+
+/**
+ * Creates a new object with credentials (user ID and process ID) from the current process.
+ * @returns the new object or #NULL if no memory
+ */
+DBusCredentials*
+_dbus_credentials_new_from_current_process (void)
+{
+ DBusCredentials *creds;
+
+ creds = _dbus_credentials_new ();
+ if (creds == NULL)
+ return NULL;
+
+ if (!_dbus_credentials_add_from_current_process (creds))
+ {
+ _dbus_credentials_unref (creds);
+ return NULL;
+ }
+
+ return creds;
+}
+
+/**
+ * Increment refcount on credentials.
+ *
+ * @param credentials the object
+ */
+void
+_dbus_credentials_ref (DBusCredentials *credentials)
+{
+ _dbus_assert (credentials->refcount > 0);
+ credentials->refcount += 1;
+}
+
+/**
+ * Decrement refcount on credentials.
+ *
+ * @param credentials the object
+ */
+void
+_dbus_credentials_unref (DBusCredentials *credentials)
+{
+ _dbus_assert (credentials->refcount > 0);
+
+ credentials->refcount -= 1;
+ if (credentials->refcount == 0)
+ {
+ dbus_free (credentials->windows_sid);
+ dbus_free (credentials);
+ }
+}
+
+/**
+ * Add a UNIX process ID to the credentials.
+ *
+ * @param credentials the object
+ * @param pid the process ID
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_unix_pid (DBusCredentials *credentials,
+ dbus_pid_t pid)
+{
+ credentials->unix_pid = pid;
+ return TRUE;
+}
+
+/**
+ * Add a UNIX user ID to the credentials.
+ *
+ * @param credentials the object
+ * @param uid the user ID
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_unix_uid(DBusCredentials *credentials,
+ dbus_uid_t uid)
+{
+ credentials->unix_uid = uid;
+ return TRUE;
+
+}
+
+/**
+ * Add a Windows user SID to the credentials.
+ *
+ * @param credentials the object
+ * @param windows_sid the user SID
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_windows_sid (DBusCredentials *credentials,
+ const char *windows_sid)
+{
+ char *copy;
+
+ copy = _dbus_strdup (windows_sid);
+ if (copy == NULL)
+ return FALSE;
+
+ dbus_free (credentials->windows_sid);
+ credentials->windows_sid = copy;
+
+ return TRUE;
+}
+
+/**
+ * Checks whether the given credential is present.
+ *
+ * @param credentials the object
+ * @param type the credential to check for
+ * @returns #TRUE if the credential is present
+ */
+dbus_bool_t
+_dbus_credentials_include (DBusCredentials *credentials,
+ DBusCredentialType type)
+{
+ switch (type)
+ {
+ case DBUS_CREDENTIAL_UNIX_PROCESS_ID:
+ return credentials->unix_pid != DBUS_PID_UNSET;
+ case DBUS_CREDENTIAL_UNIX_USER_ID:
+ return credentials->unix_uid != DBUS_UID_UNSET;
+ case DBUS_CREDENTIAL_WINDOWS_SID:
+ return credentials->windows_sid != NULL;
+ }
+
+ _dbus_assert_not_reached ("Unknown credential enum value");
+ return FALSE;
+}
+
+/**
+ * Gets the UNIX process ID in the credentials, or #DBUS_PID_UNSET if
+ * the credentials object doesn't contain a process ID.
+ *
+ * @param credentials the object
+ * @returns UNIX process ID
+ */
+dbus_pid_t
+_dbus_credentials_get_unix_pid (DBusCredentials *credentials)
+{
+ return credentials->unix_pid;
+}
+
+/**
+ * Gets the UNIX user ID in the credentials, or #DBUS_UID_UNSET if
+ * the credentials object doesn't contain a user ID.
+ *
+ * @param credentials the object
+ * @returns UNIX user ID
+ */
+dbus_uid_t
+_dbus_credentials_get_unix_uid (DBusCredentials *credentials)
+{
+ return credentials->unix_uid;
+}
+
+/**
+ * Gets the Windows user SID in the credentials, or #NULL if
+ * the credentials object doesn't contain a Windows user SID.
+ *
+ * @param credentials the object
+ * @returns Windows user SID
+ */
+const char*
+_dbus_credentials_get_windows_sid (DBusCredentials *credentials)
+{
+ return credentials->windows_sid;
+}
+
+/**
+ * Checks whether the first credentials object contains
+ * all the credentials found in the second credentials object.
+ *
+ * @param credentials the object
+ * @param possible_subset see if credentials in here are also in the first arg
+ * @returns #TRUE if second arg is contained in first
+ */
+dbus_bool_t
+_dbus_credentials_are_superset (DBusCredentials *credentials,
+ DBusCredentials *possible_subset)
+{
+ return
+ (possible_subset->unix_pid == DBUS_PID_UNSET ||
+ possible_subset->unix_pid == credentials->unix_pid) &&
+ (possible_subset->unix_uid == DBUS_UID_UNSET ||
+ possible_subset->unix_uid == credentials->unix_uid) &&
+ (possible_subset->windows_sid == NULL ||
+ (credentials->windows_sid && strcmp (possible_subset->windows_sid,
+ credentials->windows_sid) == 0));
+}
+
+/**
+ * Checks whether a credentials object contains anything.
+ *
+ * @param credentials the object
+ * @returns #TRUE if there are no credentials in the object
+ */
+dbus_bool_t
+_dbus_credentials_are_empty (DBusCredentials *credentials)
+{
+ return
+ credentials->unix_pid == DBUS_PID_UNSET &&
+ credentials->unix_uid == DBUS_UID_UNSET &&
+ credentials->windows_sid == NULL;
+}
+
+/**
+ * Merge all credentials found in the second object into the first object,
+ * overwriting the first object if there are any overlaps.
+ *
+ * @param credentials the object
+ * @param other_credentials credentials to merge
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_credentials (DBusCredentials *credentials,
+ DBusCredentials *other_credentials)
+{
+ return
+ _dbus_credentials_add_credential (credentials,
+ DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+ other_credentials) &&
+ _dbus_credentials_add_credential (credentials,
+ DBUS_CREDENTIAL_UNIX_USER_ID,
+ other_credentials) &&
+ _dbus_credentials_add_credential (credentials,
+ DBUS_CREDENTIAL_WINDOWS_SID,
+ other_credentials);
+}
+
+/**
+ * Merge the given credential found in the second object into the first object,
+ * overwriting the first object's value for that credential.
+ *
+ * Does nothing if the second object does not contain the specified credential.
+ * i.e., will never delete a credential from the first object.
+ *
+ * @param credentials the object
+ * @param which the credential to overwrite
+ * @param other_credentials credentials to merge
+ * @returns #FALSE if no memory
+ */
+dbus_bool_t
+_dbus_credentials_add_credential (DBusCredentials *credentials,
+ DBusCredentialType which,
+ DBusCredentials *other_credentials)
+{
+ if (which == DBUS_CREDENTIAL_UNIX_PROCESS_ID &&
+ other_credentials->unix_pid != DBUS_PID_UNSET)
+ {
+ if (!_dbus_credentials_add_unix_pid (credentials, other_credentials->unix_pid))
+ return FALSE;
+ }
+ else if (which == DBUS_CREDENTIAL_UNIX_USER_ID &&
+ other_credentials->unix_uid != DBUS_UID_UNSET)
+ {
+ if (!_dbus_credentials_add_unix_uid (credentials, other_credentials->unix_uid))
+ return FALSE;
+ }
+ else if (which == DBUS_CREDENTIAL_WINDOWS_SID &&
+ other_credentials->windows_sid != NULL)
+ {
+ if (!_dbus_credentials_add_windows_sid (credentials, other_credentials->windows_sid))
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
+ * Clear all credentials in the object.
+ *
+ * @param credentials the object
+ */
+void
+_dbus_credentials_clear (DBusCredentials *credentials)
+{
+ credentials->unix_pid = DBUS_PID_UNSET;
+ credentials->unix_uid = DBUS_UID_UNSET;
+ dbus_free (credentials->windows_sid);
+ credentials->windows_sid = NULL;
+}
+
+/**
+ * Copy a credentials object.
+ *
+ * @param credentials the object
+ * @returns the copy or #NULL
+ */
+DBusCredentials*
+_dbus_credentials_copy (DBusCredentials *credentials)
+{
+ DBusCredentials *copy;
+
+ copy = _dbus_credentials_new ();
+ if (copy == NULL)
+ return NULL;
+
+ if (!_dbus_credentials_add_credentials (copy, credentials))
+ {
+ _dbus_credentials_unref (copy);
+ return NULL;
+ }
+
+ return copy;
+}
+
+/**
+ * Check whether the user-identifying credentials in two credentials
+ * objects are identical. Credentials that are not related to the
+ * user are ignored, but any kind of user ID credentials must be the
+ * same (UNIX user ID, Windows user SID, etc.) and present in both
+ * objects for the function to return #TRUE.
+ *
+ * @param credentials the object
+ * @param other_credentials credentials to compare
+ * @returns #TRUE if the two credentials refer to the same user
+ */
+dbus_bool_t
+_dbus_credentials_same_user (DBusCredentials *credentials,
+ DBusCredentials *other_credentials)
+{
+ /* both windows and unix user must be the same (though pretty much
+ * in all conceivable cases, one will be unset)
+ */
+ return credentials->unix_uid == other_credentials->unix_uid &&
+ ((!(credentials->windows_sid || other_credentials->windows_sid)) ||
+ (credentials->windows_sid && other_credentials->windows_sid &&
+ strcmp (credentials->windows_sid, other_credentials->windows_sid) == 0));
+}
+
+/** @} */
+
+/* tests in dbus-credentials-util.c */
diff --git a/dbus/dbus-credentials.h b/dbus/dbus-credentials.h
new file mode 100644
index 00000000..b47c9c47
--- /dev/null
+++ b/dbus/dbus-credentials.h
@@ -0,0 +1,71 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* dbus-credentials.h Credentials provable through authentication
+ *
+ * Copyright (C) 2007 Red Hat Inc.
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * 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
+ *
+ */
+#ifndef DBUS_CREDENTIALS_H
+#define DBUS_CREDENTIALS_H
+
+#include <dbus/dbus-macros.h>
+#include <dbus/dbus-errors.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+
+DBUS_BEGIN_DECLS
+
+typedef enum {
+ DBUS_CREDENTIAL_UNIX_PROCESS_ID,
+ DBUS_CREDENTIAL_UNIX_USER_ID,
+ DBUS_CREDENTIAL_WINDOWS_SID
+} DBusCredentialType;
+
+DBusCredentials* _dbus_credentials_new_from_current_process (void);
+DBusCredentials* _dbus_credentials_new (void);
+void _dbus_credentials_ref (DBusCredentials *credentials);
+void _dbus_credentials_unref (DBusCredentials *credentials);
+dbus_bool_t _dbus_credentials_add_unix_pid (DBusCredentials *credentials,
+ dbus_pid_t pid);
+dbus_bool_t _dbus_credentials_add_unix_uid (DBusCredentials *credentials,
+ dbus_uid_t uid);
+dbus_bool_t _dbus_credentials_add_windows_sid (DBusCredentials *credentials,
+ const char *windows_sid);
+dbus_bool_t _dbus_credentials_include (DBusCredentials *credentials,
+ DBusCredentialType type);
+dbus_pid_t _dbus_credentials_get_unix_pid (DBusCredentials *credentials);
+dbus_uid_t _dbus_credentials_get_unix_uid (DBusCredentials *credentials);
+const char* _dbus_credentials_get_windows_sid (DBusCredentials *credentials);
+dbus_bool_t _dbus_credentials_are_superset (DBusCredentials *credentials,
+ DBusCredentials *possible_subset);
+dbus_bool_t _dbus_credentials_are_empty (DBusCredentials *credentials);
+dbus_bool_t _dbus_credentials_add_credentials (DBusCredentials *credentials,
+ DBusCredentials *other_credentials);
+/* must silently allow 'which' to not exist */
+dbus_bool_t _dbus_credentials_add_credential (DBusCredentials *credentials,
+ DBusCredentialType which,
+ DBusCredentials *other_credentials);
+void _dbus_credentials_clear (DBusCredentials *credentials);
+DBusCredentials* _dbus_credentials_copy (DBusCredentials *credentials);
+dbus_bool_t _dbus_credentials_same_user (DBusCredentials *credentials,
+ DBusCredentials *other_credentials);
+
+
+DBUS_END_DECLS
+
+#endif /* DBUS_CREDENTIALS_H */
diff --git a/dbus/dbus-internals.c b/dbus/dbus-internals.c
index b0a0f023..86c13324 100644
--- a/dbus/dbus-internals.c
+++ b/dbus/dbus-internals.c
@@ -271,7 +271,7 @@ _dbus_warn_check_failed(const char *format,
if (!warn_initted)
init_warnings ();
- fprintf (stderr, "process %lu: ", _dbus_getpid ());
+ fprintf (stderr, "process %lu: ", _dbus_pid_for_log ());
va_start (args, format);
vfprintf (stderr, format, args);
@@ -349,9 +349,9 @@ _dbus_verbose_real (const char *format,
if (need_pid)
{
#if PTHREAD_IN_VERBOSE
- fprintf (stderr, "%lu: 0x%lx: ", _dbus_getpid (), pthread_self ());
+ fprintf (stderr, "%lu: 0x%lx: ", _dbus_pid_for_log (), pthread_self ());
#else
- fprintf (stderr, "%lu: ", _dbus_getpid ());
+ fprintf (stderr, "%lu: ", _dbus_pid_for_log ());
#endif
}
@@ -813,7 +813,7 @@ _dbus_real_assert (dbus_bool_t condition,
if (_DBUS_UNLIKELY (!condition))
{
_dbus_warn ("%lu: assertion failed \"%s\" file \"%s\" line %d function %s\n",
- _dbus_getpid (), condition_text, file, line, func);
+ _dbus_pid_for_log (), condition_text, file, line, func);
_dbus_abort ();
}
}
@@ -834,7 +834,7 @@ _dbus_real_assert_not_reached (const char *explanation,
int line)
{
_dbus_warn ("File \"%s\" line %d process %lu should not have been reached: %s\n",
- file, line, _dbus_getpid (), explanation);
+ file, line, _dbus_pid_for_log (), explanation);
_dbus_abort ();
}
#endif /* DBUS_DISABLE_ASSERT */
diff --git a/dbus/dbus-keyring.c b/dbus/dbus-keyring.c
index 018f45af..17c6b179 100644
--- a/dbus/dbus-keyring.c
+++ b/dbus/dbus-keyring.c
@@ -22,7 +22,6 @@
*/
#include "dbus-keyring.h"
-#include "dbus-userdb.h"
#include "dbus-protocol.h"
#include <dbus/dbus-string.h>
#include <dbus/dbus-list.h>
diff --git a/dbus/dbus-marshal-recursive-util.c b/dbus/dbus-marshal-recursive-util.c
index 3d4320d9..bd9949c0 100644
--- a/dbus/dbus-marshal-recursive-util.c
+++ b/dbus/dbus-marshal-recursive-util.c
@@ -986,7 +986,7 @@ node_read_value (TestTypeNode *node,
DBusTypeReader *reader,
int seed)
{
- DBusTypeReader restored;
+ /* DBusTypeReader restored; */
if (!(* node->klass->read_value) (node, reader, seed))
return FALSE;
diff --git a/dbus/dbus-spawn.c b/dbus/dbus-spawn.c
index 07535db9..c3be333c 100644
--- a/dbus/dbus-spawn.c
+++ b/dbus/dbus-spawn.c
@@ -22,7 +22,7 @@
*
*/
#include "dbus-spawn.h"
-#include "dbus-sysdeps.h"
+#include "dbus-sysdeps-unix.h"
#include "dbus-internals.h"
#include "dbus-test.h"
#include "dbus-protocol.h"
@@ -849,7 +849,7 @@ do_exec (int child_err_report_fd,
#endif
_dbus_verbose_reset ();
- _dbus_verbose ("Child process has PID %lu\n",
+ _dbus_verbose ("Child process has PID " DBUS_PID_FORMAT "\n",
_dbus_getpid ());
if (child_setup)
diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c
index 80732a79..135f7c9f 100644
--- a/dbus/dbus-sysdeps-unix.c
+++ b/dbus/dbus-sysdeps-unix.c
@@ -31,6 +31,7 @@
#include "dbus-string.h"
#include "dbus-userdb.h"
#include "dbus-list.h"
+#include "dbus-credentials.h"
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
@@ -85,6 +86,7 @@ _dbus_open_socket (int *fd_p,
*fd_p = socket (domain, type, protocol);
if (*fd_p >= 0)
{
+ _dbus_verbose ("socket fd %d opened\n", *fd_p);
return TRUE;
}
else
@@ -949,11 +951,14 @@ write_credentials_byte (int server_fd,
/**
* Reads a single byte which must be nul (an error occurs otherwise),
- * and reads unix credentials if available. Fills in pid/uid/gid with
- * -1 if no credentials are available. Return value indicates whether
- * a byte was read, not whether we got valid credentials. On some
- * systems, such as Linux, reading/writing the byte isn't actually
- * required, but we do it anyway just to avoid multiple codepaths.
+ * and reads unix credentials if available. Clears the credentials
+ * object, then adds pid/uid if available, so any previous credentials
+ * stored in the object are lost.
+ *
+ * Return value indicates whether a byte was read, not whether
+ * we got valid credentials. On some systems, such as Linux,
+ * reading/writing the byte isn't actually required, but we do it
+ * anyway just to avoid multiple codepaths.
*
* Fails if no byte is available, so you must select() first.
*
@@ -961,19 +966,24 @@ write_credentials_byte (int server_fd,
* use sendmsg()/recvmsg() to transmit credentials.
*
* @param client_fd the client file descriptor
- * @param credentials struct to fill with credentials of client
+ * @param credentials object to add client credentials to
* @param error location to store error code
* @returns #TRUE on success
*/
dbus_bool_t
-_dbus_read_credentials_unix_socket (int client_fd,
- DBusCredentials *credentials,
- DBusError *error)
+_dbus_read_credentials_socket (int client_fd,
+ DBusCredentials *credentials,
+ DBusError *error)
{
struct msghdr msg;
struct iovec iov;
char buf;
+ dbus_uid_t uid_read;
+ dbus_pid_t pid_read;
+ uid_read = DBUS_UID_UNSET;
+ pid_read = DBUS_PID_UNSET;
+
#ifdef HAVE_CMSGCRED
struct {
struct cmsghdr hdr;
@@ -993,9 +1003,9 @@ _dbus_read_credentials_unix_socket (int client_fd,
* we need these assertions to fail as soon as we're wrong about
* it so we can do the porting fixups
*/
- _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
- _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
- _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
+ _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
+ _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
+ _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
_dbus_credentials_clear (credentials);
@@ -1056,9 +1066,8 @@ _dbus_read_credentials_unix_socket (int client_fd,
if (getsockopt (client_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 &&
cr_len == sizeof (cr))
{
- credentials->pid = cr.pid;
- credentials->uid = cr.uid;
- credentials->gid = cr.gid;
+ pid_read = cr.pid;
+ uid_read = cr.uid;
}
else
{
@@ -1066,13 +1075,11 @@ _dbus_read_credentials_unix_socket (int client_fd,
cr_len, (int) sizeof (cr), _dbus_strerror (errno));
}
#elif defined(HAVE_CMSGCRED)
- credentials->pid = cmsg.cred.cmcred_pid;
- credentials->uid = cmsg.cred.cmcred_euid;
- credentials->gid = cmsg.cred.cmcred_groups[0];
+ pid_read = cmsg.cred.cmcred_pid;
+ uid_read = cmsg.cred.cmcred_euid;
#elif defined(LOCAL_CREDS)
- credentials->pid = DBUS_PID_UNSET;
- credentials->uid = cmsg.cred.sc_uid;
- credentials->gid = cmsg.cred.sc_gid;
+ pid_read = DBUS_PID_UNSET;
+ uid_read = cmsg.cred.sc_uid;
/* Since we have already got the credentials from this socket, we can
* disable its LOCAL_CREDS flag if it was ever set. */
_dbus_set_local_creds (client_fd, FALSE);
@@ -1081,8 +1088,7 @@ _dbus_read_credentials_unix_socket (int client_fd,
gid_t egid;
if (getpeereid (client_fd, &euid, &egid) == 0)
{
- credentials->uid = euid;
- credentials->gid = egid;
+ uid_read = euid;
}
else
{
@@ -1092,9 +1098,8 @@ _dbus_read_credentials_unix_socket (int client_fd,
ucred_t * ucred = NULL;
if (getpeerucred (client_fd, &ucred) == 0)
{
- credentials->pid = ucred_getpid (ucred);
- credentials->uid = ucred_geteuid (ucred);
- credentials->gid = ucred_getegid (ucred);
+ pid_read = ucred_getpid (ucred);
+ uid_read = ucred_geteuid (ucred);
}
else
{
@@ -1110,11 +1115,28 @@ _dbus_read_credentials_unix_socket (int client_fd,
_dbus_verbose ("Credentials:"
" pid "DBUS_PID_FORMAT
" uid "DBUS_UID_FORMAT
- " gid "DBUS_GID_FORMAT"\n",
- credentials->pid,
- credentials->uid,
- credentials->gid);
-
+ "\n",
+ pid_read,
+ uid_read);
+
+ if (pid_read != DBUS_PID_UNSET)
+ {
+ if (!_dbus_credentials_add_unix_pid (credentials, pid_read))
+ {
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+ }
+
+ if (uid_read != DBUS_UID_UNSET)
+ {
+ if (!_dbus_credentials_add_unix_uid (credentials, uid_read))
+ {
+ _DBUS_SET_OOM (error);
+ return FALSE;
+ }
+ }
+
return TRUE;
}
@@ -1136,8 +1158,8 @@ _dbus_read_credentials_unix_socket (int client_fd,
* @returns #TRUE if the byte was sent
*/
dbus_bool_t
-_dbus_send_credentials_unix_socket (int server_fd,
- DBusError *error)
+_dbus_send_credentials_socket (int server_fd,
+ DBusError *error)
{
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -1171,6 +1193,8 @@ _dbus_accept (int listen_fd)
if (errno == EINTR)
goto retry;
}
+
+ _dbus_verbose ("client fd %d accepted\n", client_fd);
return client_fd;
}
@@ -1446,31 +1470,77 @@ _dbus_user_info_fill_uid (DBusUserInfo *info,
}
/**
- * Gets the credentials of the current process.
+ * Adds the credentials of the current process to the
+ * passed-in credentials object.
*
- * @param credentials credentials to fill in.
+ * @param credentials credentials to add to
+ * @returns #FALSE if no memory; does not properly roll back on failure, so only some credentials may have been added
*/
-void
-_dbus_credentials_from_current_process (DBusCredentials *credentials)
+dbus_bool_t
+_dbus_credentials_add_from_current_process (DBusCredentials *credentials)
{
/* The POSIX spec certainly doesn't promise this, but
* we need these assertions to fail as soon as we're wrong about
* it so we can do the porting fixups
*/
- _dbus_assert (sizeof (pid_t) <= sizeof (credentials->pid));
- _dbus_assert (sizeof (uid_t) <= sizeof (credentials->uid));
- _dbus_assert (sizeof (gid_t) <= sizeof (credentials->gid));
-
- credentials->pid = getpid ();
- credentials->uid = getuid ();
- credentials->gid = getgid ();
+ _dbus_assert (sizeof (pid_t) <= sizeof (dbus_pid_t));
+ _dbus_assert (sizeof (uid_t) <= sizeof (dbus_uid_t));
+ _dbus_assert (sizeof (gid_t) <= sizeof (dbus_gid_t));
+
+ if (!_dbus_credentials_add_unix_pid(credentials, _dbus_getpid()))
+ return FALSE;
+ if (!_dbus_credentials_add_unix_uid(credentials, _dbus_getuid()))
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * Parses a desired identity provided from a client in the auth protocol.
+ * On UNIX this means parsing a UID.
+ *
+ * @todo this is broken because it treats OOM and parse error
+ * the same way. Needs a #DBusError.
+ *
+ * @param credentials the credentials to add what we parse to
+ * @param desired_identity the string to parse
+ * @returns #TRUE if we successfully parsed something
+ */
+dbus_bool_t
+_dbus_credentials_parse_and_add_desired (DBusCredentials *credentials,
+ const DBusString *desired_identity)
+{
+ dbus_uid_t uid;
+
+ if (!_dbus_parse_uid (desired_identity, &uid))
+ return FALSE;
+
+ if (!_dbus_credentials_add_unix_uid (credentials, uid))
+ return FALSE;
+
+ return TRUE;
+}
+
+/**
+ * Append to the string the identity we would like to have when we authenticate,
+ * on UNIX this is the current process UID and on Windows something else.
+ * No escaping is required, that is done in dbus-auth.c.
+ *
+ * @param str the string to append to
+ * @returns #FALSE on no memory
+ */
+dbus_bool_t
+_dbus_append_desired_identity (DBusString *str)
+{
+ return _dbus_string_append_uint (str,
+ _dbus_getuid ());
}
/**
* Gets our process ID
* @returns process ID
*/
-unsigned long
+dbus_pid_t
_dbus_getpid (void)
{
return getpid ();
@@ -1485,6 +1555,59 @@ _dbus_getuid (void)
return getuid ();
}
+/**
+ * The only reason this is separate from _dbus_getpid() is to allow it
+ * on Windows for logging but not for other purposes.
+ *
+ * @returns process ID to put in log messages
+ */
+unsigned long
+_dbus_pid_for_log (void)
+{
+ return getpid ();
+}
+
+/**
+ * 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_parse_uid (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;
+}
+
+
_DBUS_DEFINE_GLOBAL_LOCK (atomic);
#ifdef DBUS_USE_ATOMIC_INT_486
@@ -1717,6 +1840,8 @@ _dbus_file_get_contents (DBusString *str,
return FALSE;
}
+ _dbus_verbose ("file fd %d opened\n", fd);
+
if (fstat (fd, &sb) < 0)
{
dbus_set_error (error, _dbus_error_from_errno (errno),
@@ -1858,6 +1983,8 @@ _dbus_string_save_to_file (const DBusString *str,
goto out;
}
+ _dbus_verbose ("tmp file fd %d opened\n", fd);
+
need_unlink = TRUE;
total = 0;
@@ -1983,6 +2110,8 @@ _dbus_create_file_exclusively (const DBusString *filename,
return FALSE;
}
+ _dbus_verbose ("exclusive file fd %d opened\n", fd);
+
if (!_dbus_close (fd, NULL))
{
dbus_set_error (error,
@@ -2181,6 +2310,8 @@ _dbus_generate_random_bytes (DBusString *str,
if (fd < 0)
return _dbus_generate_pseudorandom_bytes (str, n_bytes);
+ _dbus_verbose ("/dev/urandom fd %d opened\n", fd);
+
if (_dbus_read (fd, str, n_bytes) != n_bytes)
{
_dbus_close (fd, NULL);
@@ -2571,6 +2702,8 @@ _dbus_get_autolaunch_address (DBusString *address,
/* huh?! can't open /dev/null? */
_exit (1);
+ _dbus_verbose ("/dev/null fd %d opened\n", fd);
+
/* set-up stdXXX */
close (address_pipe[READ_END]);
close (errors_pipe[READ_END]);
@@ -2757,7 +2890,7 @@ _dbus_get_standard_session_servicedirs (DBusList **dirs)
else
{
const DBusString *homedir;
- const DBusString local_share;
+ DBusString local_share;
if (!_dbus_homedir_from_current_process (&homedir))
goto oom;
diff --git a/dbus/dbus-sysdeps-unix.h b/dbus/dbus-sysdeps-unix.h
index f72493a7..58fce9ce 100644
--- a/dbus/dbus-sysdeps-unix.h
+++ b/dbus/dbus-sysdeps-unix.h
@@ -71,6 +71,63 @@ int _dbus_listen_unix_socket (const char *path,
dbus_bool_t abstract,
DBusError *error);
+dbus_bool_t _dbus_read_credentials (int client_fd,
+ DBusCredentials *credentials,
+ DBusError *error);
+dbus_bool_t _dbus_send_credentials (int server_fd,
+ DBusError *error);
+
+/** Information about a UNIX user */
+typedef struct DBusUserInfo DBusUserInfo;
+/** Information about a UNIX group */
+typedef struct DBusGroupInfo DBusGroupInfo;
+
+/**
+ * Information about a UNIX user
+ */
+struct DBusUserInfo
+{
+ dbus_uid_t uid; /**< UID */
+ dbus_gid_t primary_gid; /**< GID */
+ dbus_gid_t *group_ids; /**< Groups IDs, *including* above primary group */
+ int n_group_ids; /**< Size of group IDs array */
+ char *username; /**< Username */
+ char *homedir; /**< Home directory */
+};
+
+/**
+ * Information about a UNIX group
+ */
+struct DBusGroupInfo
+{
+ dbus_gid_t gid; /**< GID */
+ char *groupname; /**< Group name */
+};
+
+dbus_bool_t _dbus_user_info_fill (DBusUserInfo *info,
+ const DBusString *username,
+ DBusError *error);
+dbus_bool_t _dbus_user_info_fill_uid (DBusUserInfo *info,
+ dbus_uid_t uid,
+ DBusError *error);
+void _dbus_user_info_free (DBusUserInfo *info);
+
+dbus_bool_t _dbus_group_info_fill (DBusGroupInfo *info,
+ const DBusString *groupname,
+ DBusError *error);
+dbus_bool_t _dbus_group_info_fill_gid (DBusGroupInfo *info,
+ dbus_gid_t gid,
+ 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);
+
+dbus_bool_t _dbus_parse_uid (const DBusString *uid_str,
+ dbus_uid_t *uid);
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-sysdeps-util-unix.c b/dbus/dbus-sysdeps-util-unix.c
index 5ffc90d9..9963432b 100644
--- a/dbus/dbus-sysdeps-util-unix.c
+++ b/dbus/dbus-sysdeps-util-unix.c
@@ -243,20 +243,47 @@ _dbus_write_pid_file (const DBusString *filename,
return TRUE;
}
+/**
+ * Verify that after the fork we can successfully change to this user.
+ *
+ * @param user the username given in the daemon configuration
+ * @returns #TRUE if username is valid
+ */
+dbus_bool_t
+_dbus_verify_daemon_user (const char *user)
+{
+ DBusString u;
+
+ _dbus_string_init_const (&u, user);
+
+ return _dbus_get_user_id_and_primary_group (&u, NULL, NULL);
+}
/**
* Changes the user and group the bus is running as.
*
- * @param uid the new user ID
- * @param gid the new group ID
+ * @param user the user to become
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
-_dbus_change_identity (dbus_uid_t uid,
- dbus_gid_t gid,
- DBusError *error)
+_dbus_change_to_daemon_user (const char *user,
+ DBusError *error)
{
+ dbus_uid_t uid;
+ dbus_gid_t gid;
+ DBusString u;
+
+ _dbus_string_init_const (&u, user);
+
+ if (!_dbus_get_user_id_and_primary_group (&u, &uid, &gid))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "User '%s' does not appear to exist?",
+ user);
+ return FALSE;
+ }
+
/* setgroups() only works if we are a privileged process,
* so we don't return error on failure; the only possible
* failure is that we don't have perms to do it.
diff --git a/dbus/dbus-sysdeps-win.c b/dbus/dbus-sysdeps-win.c
index 3b9c8412..0f26ce71 100644
--- a/dbus/dbus-sysdeps-win.c
+++ b/dbus/dbus-sysdeps-win.c
@@ -42,7 +42,6 @@
#include "dbus-protocol.h"
#include "dbus-hash.h"
#include "dbus-sockets-win.h"
-#include "dbus-userdb.h"
#include "dbus-list.h"
#include <windows.h>
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 8ccdb3ff..cf689bc0 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -78,7 +78,7 @@ _dbus_abort (void)
if (s && *s)
{
/* don't use _dbus_warn here since it can _dbus_abort() */
- fprintf (stderr, " Process %lu sleeping for gdb attach\n", (unsigned long) _dbus_getpid());
+ fprintf (stderr, " Process %lu sleeping for gdb attach\n", _dbus_pid_for_log ());
_dbus_sleep_milliseconds (1000 * 180);
}
@@ -236,7 +236,8 @@ _dbus_pipe_invalidate (DBusPipe *pipe)
}
/**
- * split pathes into a list of char strings
+ * Split paths into a list of char strings
+ *
* @param dirs string with pathes
* @param suffix string concated to each path in dirs
* @param dir_list contains a list of splitted pathes
@@ -251,7 +252,7 @@ _dbus_split_paths_and_append (DBusString *dirs,
int i;
int len;
char *cpath;
- const DBusString file_suffix;
+ DBusString file_suffix;
start = 0;
i = 0;
@@ -770,68 +771,6 @@ _dbus_string_parse_double (const DBusString *str,
* @{
*/
-/**
- * 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);
-}
-
-/**
- * Sets fields in DBusCredentials to DBUS_PID_UNSET,
- * DBUS_UID_UNSET, DBUS_GID_UNSET.
- *
- * @param credentials the credentials object to fill in
- */
-void
-_dbus_credentials_clear (DBusCredentials *credentials)
-{
- credentials->pid = DBUS_PID_UNSET;
- credentials->uid = DBUS_UID_UNSET;
- credentials->gid = DBUS_GID_UNSET;
-}
-
-/**
- * Checks whether the provided_credentials are allowed to log in
- * as the expected_credentials.
- *
- * @param expected_credentials credentials we're trying to log in as
- * @param provided_credentials credentials we have
- * @returns #TRUE if we can log in
- */
-dbus_bool_t
-_dbus_credentials_match (const DBusCredentials *expected_credentials,
- const DBusCredentials *provided_credentials)
-{
- if (provided_credentials->uid == DBUS_UID_UNSET)
- return FALSE;
- else if (expected_credentials->uid == DBUS_UID_UNSET)
- return FALSE;
- else if (provided_credentials->uid == 0)
- return TRUE;
- else if (provided_credentials->uid == expected_credentials->uid)
- return TRUE;
- else
- return FALSE;
-}
-
void
_dbus_generate_pseudorandom_bytes_buffer (char *buffer,
int n_bytes)
@@ -929,46 +868,6 @@ _dbus_generate_random_ascii (DBusString *str,
}
/**
- * 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_parse_uid (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;
-}
-
-/**
* Converts a UNIX or Windows errno
* into a #DBusError name.
*
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index c89d35f0..f83c17ca 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -55,6 +55,9 @@ typedef struct DBusString DBusString;
/** An opaque list type */
typedef struct DBusList DBusList;
+/** Object that contains a list of credentials such as UNIX or Windows user ID */
+typedef struct DBusCredentials DBusCredentials;
+
/**
* @addtogroup DBusSysdeps
*
@@ -151,79 +154,25 @@ int _dbus_listen_tcp_socket (const char *host,
DBusError *error);
int _dbus_accept (int listen_fd);
-/**
- * Struct representing socket credentials
- */
-typedef struct
-{
- dbus_pid_t pid; /**< process ID or DBUS_PID_UNSET */
- dbus_uid_t uid; /**< user ID or DBUS_UID_UNSET */
- dbus_gid_t gid; /**< group ID or DBUS_GID_UNSET */
-} DBusCredentials;
-
-/* FIXME these read/send credentials should get moved to sysdeps-unix.h,
- * or renamed to reflect what they mean cross-platform
- */
-dbus_bool_t _dbus_read_credentials_unix_socket (int client_fd,
- DBusCredentials *credentials,
- DBusError *error);
-dbus_bool_t _dbus_send_credentials_unix_socket (int server_fd,
- DBusError *error);
-
-
-void _dbus_credentials_clear (DBusCredentials *credentials);
-void _dbus_credentials_from_current_process (DBusCredentials *credentials);
-dbus_bool_t _dbus_credentials_match (const DBusCredentials *expected_credentials,
- const DBusCredentials *provided_credentials);
-
-
-/** Information about a UNIX user */
-typedef struct DBusUserInfo DBusUserInfo;
-/** Information about a UNIX group */
-typedef struct DBusGroupInfo DBusGroupInfo;
-
-/**
- * Information about a UNIX user
- */
-struct DBusUserInfo
-{
- dbus_uid_t uid; /**< UID */
- dbus_gid_t primary_gid; /**< GID */
- dbus_gid_t *group_ids; /**< Groups IDs, *including* above primary group */
- int n_group_ids; /**< Size of group IDs array */
- char *username; /**< Username */
- char *homedir; /**< Home directory */
-};
-
-/**
- * Information about a UNIX group
- */
-struct DBusGroupInfo
-{
- dbus_gid_t gid; /**< GID */
- char *groupname; /**< Group name */
-};
-dbus_bool_t _dbus_user_info_fill (DBusUserInfo *info,
- const DBusString *username,
- DBusError *error);
-dbus_bool_t _dbus_user_info_fill_uid (DBusUserInfo *info,
- dbus_uid_t uid,
- DBusError *error);
-void _dbus_user_info_free (DBusUserInfo *info);
+dbus_bool_t _dbus_read_credentials_socket (int client_fd,
+ DBusCredentials *credentials,
+ DBusError *error);
+dbus_bool_t _dbus_send_credentials_socket (int server_fd,
+ DBusError *error);
-dbus_bool_t _dbus_group_info_fill (DBusGroupInfo *info,
- const DBusString *groupname,
- DBusError *error);
-dbus_bool_t _dbus_group_info_fill_gid (DBusGroupInfo *info,
- dbus_gid_t gid,
- DBusError *error);
-void _dbus_group_info_free (DBusGroupInfo *info);
+dbus_bool_t _dbus_credentials_add_from_username (DBusCredentials *credentials,
+ const DBusString *username);
+dbus_bool_t _dbus_credentials_add_from_current_process (DBusCredentials *credentials);
+dbus_bool_t _dbus_credentials_parse_and_add_desired (DBusCredentials *credentials,
+ const DBusString *desired_identity);
+dbus_bool_t _dbus_username_from_current_process (const DBusString **username);
+dbus_bool_t _dbus_append_desired_identity (DBusString *str);
-unsigned long _dbus_getpid (void);
-dbus_uid_t _dbus_getuid (void);
-dbus_gid_t _dbus_getgid (void);
+dbus_bool_t _dbus_homedir_from_current_process (const DBusString **homedir);
+dbus_bool_t _dbus_homedir_from_username (const DBusString *username,
+ DBusString *homedir);
/** Opaque type representing an atomically-modifiable integer
* that can be used from multiple threads.
@@ -398,9 +347,9 @@ dbus_bool_t _dbus_become_daemon (const DBusString *pidfile,
dbus_bool_t _dbus_write_pid_file (const DBusString *filename,
unsigned long pid,
DBusError *error);
-dbus_bool_t _dbus_change_identity (unsigned long uid,
- unsigned long gid,
- DBusError *error);
+dbus_bool_t _dbus_verify_daemon_user (const char *user);
+dbus_bool_t _dbus_change_to_daemon_user (const char *user,
+ DBusError *error);
/** A UNIX signal handler */
typedef void (* DBusSignalHandler) (int sig);
@@ -446,9 +395,6 @@ dbus_bool_t _dbus_user_at_console (const char *username,
_DBUS_BYTE_OF_PRIMITIVE (a, 6) == _DBUS_BYTE_OF_PRIMITIVE (b, 6) && \
_DBUS_BYTE_OF_PRIMITIVE (a, 7) == _DBUS_BYTE_OF_PRIMITIVE (b, 7))
-dbus_bool_t _dbus_parse_uid (const DBusString *uid_str,
- dbus_uid_t *uid);
-
dbus_bool_t _dbus_get_autolaunch_address (DBusString *address,
DBusError *error);
@@ -472,6 +418,8 @@ dbus_bool_t _dbus_split_paths_and_append (DBusString *dirs,
const char *suffix,
DBusList **dir_list);
+unsigned long _dbus_pid_for_log (void);
+
/** @} */
DBUS_END_DECLS
diff --git a/dbus/dbus-test.c b/dbus/dbus-test.c
index 07544622..a1df3604 100644
--- a/dbus/dbus-test.c
+++ b/dbus/dbus-test.c
@@ -160,6 +160,8 @@ dbus_internal_do_not_use_run_tests (const char *test_data_dir, const char *speci
run_data_test ("spawn", specific_test, _dbus_spawn_test, test_data_dir);
#endif
+ run_data_test ("credentials", specific_test, _dbus_credentials_test, test_data_dir);
+
run_data_test ("userdb", specific_test, _dbus_userdb_test, test_data_dir);
run_test ("keyring", specific_test, _dbus_keyring_test);
diff --git a/dbus/dbus-test.h b/dbus/dbus-test.h
index e7c55d92..8619ae73 100644
--- a/dbus/dbus-test.h
+++ b/dbus/dbus-test.h
@@ -54,6 +54,7 @@ dbus_bool_t _dbus_userdb_test (const char *test_data_dir);
dbus_bool_t _dbus_memory_test (void);
dbus_bool_t _dbus_object_tree_test (void);
dbus_bool_t _dbus_pending_call_test (const char *test_data_dir);
+dbus_bool_t _dbus_credentials_test (const char *test_data_dir);
void dbus_internal_do_not_use_run_tests (const char *test_data_dir,
const char *specific_test);
diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h
index 2b3a6c68..bfdff0e2 100644
--- a/dbus/dbus-transport-protected.h
+++ b/dbus/dbus-transport-protected.h
@@ -89,7 +89,7 @@ struct DBusTransport
DBusAuth *auth; /**< Authentication conversation */
- DBusCredentials credentials; /**< Credentials of other end */
+ DBusCredentials *credentials; /**< Credentials of other end read from the socket */
long max_live_messages_size; /**< Max total size of received messages. */
diff --git a/dbus/dbus-transport-socket.c b/dbus/dbus-transport-socket.c
index 76a6fcfb..3f8c94d5 100644
--- a/dbus/dbus-transport-socket.c
+++ b/dbus/dbus-transport-socket.c
@@ -26,6 +26,7 @@
#include "dbus-transport-socket.h"
#include "dbus-transport-protected.h"
#include "dbus-watch.h"
+#include "dbus-credentials.h"
/**
@@ -332,7 +333,8 @@ write_data_from_auth (DBusTransport *transport)
return FALSE;
}
-static void
+/* FALSE on OOM */
+static dbus_bool_t
exchange_credentials (DBusTransport *transport,
dbus_bool_t do_reading,
dbus_bool_t do_writing)
@@ -346,8 +348,8 @@ exchange_credentials (DBusTransport *transport,
dbus_error_init (&error);
if (do_writing && transport->send_credentials_pending)
{
- if (_dbus_send_credentials_unix_socket (socket_transport->fd,
- &error))
+ if (_dbus_send_credentials_socket (socket_transport->fd,
+ &error))
{
transport->send_credentials_pending = FALSE;
}
@@ -361,9 +363,10 @@ exchange_credentials (DBusTransport *transport,
if (do_reading && transport->receive_credentials_pending)
{
- if (_dbus_read_credentials_unix_socket (socket_transport->fd,
- &transport->credentials,
- &error))
+ /* FIXME this can fail due to IO error _or_ OOM, broken */
+ if (_dbus_read_credentials_socket (socket_transport->fd,
+ transport->credentials,
+ &error))
{
transport->receive_credentials_pending = FALSE;
}
@@ -378,9 +381,12 @@ exchange_credentials (DBusTransport *transport,
if (!(transport->send_credentials_pending ||
transport->receive_credentials_pending))
{
- _dbus_auth_set_credentials (transport->auth,
- &transport->credentials);
+ if (!_dbus_auth_set_credentials (transport->auth,
+ transport->credentials))
+ return FALSE;
}
+
+ return TRUE;
}
static dbus_bool_t
@@ -412,7 +418,12 @@ do_authentication (DBusTransport *transport,
while (!_dbus_transport_get_is_authenticated (transport) &&
_dbus_transport_get_is_connected (transport))
{
- exchange_credentials (transport, do_reading, do_writing);
+ if (!exchange_credentials (transport, do_reading, do_writing))
+ {
+ /* OOM */
+ oom = TRUE;
+ goto out;
+ }
if (transport->send_credentials_pending ||
transport->receive_credentials_pending)
@@ -1161,7 +1172,7 @@ _dbus_transport_new_for_socket (int fd,
NULL, NULL, NULL);
if (socket_transport->read_watch == NULL)
goto failed_3;
-
+
if (!_dbus_transport_init_base (&socket_transport->base,
&socket_vtable,
server_guid, address))
diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c
index d8d3bb29..e922eb5d 100644
--- a/dbus/dbus-transport.c
+++ b/dbus/dbus-transport.c
@@ -28,6 +28,7 @@
#include "dbus-watch.h"
#include "dbus-auth.h"
#include "dbus-address.h"
+#include "dbus-credentials.h"
#ifdef DBUS_BUILD_TESTS
#include "dbus-server-debug-pipe.h"
#endif
@@ -98,6 +99,7 @@ _dbus_transport_init_base (DBusTransport *transport,
DBusAuth *auth;
DBusCounter *counter;
char *address_copy;
+ DBusCredentials *creds;
loader = _dbus_message_loader_new ();
if (loader == NULL)
@@ -120,6 +122,15 @@ _dbus_transport_init_base (DBusTransport *transport,
_dbus_message_loader_unref (loader);
return FALSE;
}
+
+ creds = _dbus_credentials_new ();
+ if (creds == NULL)
+ {
+ _dbus_counter_unref (counter);
+ _dbus_auth_unref (auth);
+ _dbus_message_loader_unref (loader);
+ return FALSE;
+ }
if (server_guid)
{
@@ -132,6 +143,7 @@ _dbus_transport_init_base (DBusTransport *transport,
if (!_dbus_string_copy_data (address, &address_copy))
{
+ _dbus_credentials_unref (creds);
_dbus_counter_unref (counter);
_dbus_auth_unref (auth);
_dbus_message_loader_unref (loader);
@@ -161,11 +173,10 @@ _dbus_transport_init_base (DBusTransport *transport,
* but doesn't impose too much of a limitation.
*/
transport->max_live_messages_size = _DBUS_ONE_MEGABYTE * 63;
-
- transport->credentials.pid = -1;
- transport->credentials.uid = -1;
- transport->credentials.gid = -1;
+ /* credentials read from socket if any */
+ transport->credentials = creds;
+
_dbus_counter_set_notify (transport->live_messages_size,
transport->max_live_messages_size,
live_messages_size_notify,
@@ -199,6 +210,8 @@ _dbus_transport_finalize_base (DBusTransport *transport)
_dbus_counter_unref (transport->live_messages_size);
dbus_free (transport->address);
dbus_free (transport->expected_guid);
+ if (transport->credentials)
+ _dbus_credentials_unref (transport->credentials);
}
@@ -490,16 +503,7 @@ _dbus_transport_get_is_connected (DBusTransport *transport)
*/
dbus_bool_t
_dbus_transport_get_is_authenticated (DBusTransport *transport)
-{
- /* We don't want to run unix_user_function on Windows, but it
- * can exist, which allows application code to just unconditionally
- * set it and have it only be invoked when appropriate.
- */
- dbus_bool_t on_windows = FALSE;
-#ifdef DBUS_WIN
- on_windows = TRUE;
-#endif
-
+{
if (transport->authenticated)
return TRUE;
else
@@ -567,28 +571,36 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
if (maybe_authenticated && transport->is_server)
{
- DBusCredentials auth_identity;
+ DBusCredentials *auth_identity;
- _dbus_auth_get_identity (transport->auth, &auth_identity);
+ auth_identity = _dbus_auth_get_identity (transport->auth);
+ _dbus_assert (auth_identity != NULL);
- if (transport->unix_user_function != NULL && !on_windows)
+ /* 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 (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,
- auth_identity.uid,
+ uid,
unix_user_data);
_dbus_verbose ("lock %s post unix user function\n", _DBUS_FUNCTION_NAME);
@@ -596,13 +608,13 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
if (allow)
{
- _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", auth_identity.uid);
+ _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
}
else
{
_dbus_verbose ("Client UID "DBUS_UID_FORMAT
" was rejected, disconnecting\n",
- auth_identity.uid);
+ _dbus_credentials_get_unix_uid (auth_identity));
_dbus_transport_disconnect (transport);
_dbus_connection_unref_unlocked (connection);
return FALSE;
@@ -610,25 +622,40 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
}
else
{
- DBusCredentials our_identity;
+ DBusCredentials *our_identity;
+
+ /* By default, connection is allowed if the client is
+ * 1) root or 2) has the same UID as us
+ */
- _dbus_credentials_from_current_process (&our_identity);
+ our_identity = _dbus_credentials_new_from_current_process ();
+ if (our_identity == NULL)
+ {
+ /* OOM */
+ _dbus_connection_unref_unlocked (transport->connection);
+ return FALSE;
+ }
- if (!_dbus_credentials_match (&our_identity,
- &auth_identity))
+ 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",
- auth_identity.uid, our_identity.uid);
+ _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",
- auth_identity.uid, our_identity.uid);
+ _dbus_credentials_get_unix_uid(auth_identity),
+ _dbus_credentials_get_unix_uid(our_identity));
}
}
}
@@ -1028,7 +1055,7 @@ dbus_bool_t
_dbus_transport_get_unix_user (DBusTransport *transport,
unsigned long *uid)
{
- DBusCredentials auth_identity;
+ DBusCredentials *auth_identity;
*uid = _DBUS_INT32_MAX; /* better than some root or system user in
* case of bugs in the caller. Caller should
@@ -1038,11 +1065,12 @@ _dbus_transport_get_unix_user (DBusTransport *transport,
if (!transport->authenticated)
return FALSE;
- _dbus_auth_get_identity (transport->auth, &auth_identity);
+ auth_identity = _dbus_auth_get_identity (transport->auth);
- if (auth_identity.uid != DBUS_UID_UNSET)
+ if (_dbus_credentials_include (auth_identity,
+ DBUS_CREDENTIAL_UNIX_USER_ID))
{
- *uid = auth_identity.uid;
+ *uid = _dbus_credentials_get_unix_uid (auth_identity);
return TRUE;
}
else
@@ -1060,7 +1088,7 @@ dbus_bool_t
_dbus_transport_get_unix_process_id (DBusTransport *transport,
unsigned long *pid)
{
- DBusCredentials auth_identity;
+ DBusCredentials *auth_identity;
*pid = DBUS_PID_UNSET; /* Caller should never use this value on purpose,
* but we set it to a safe number, INT_MAX,
@@ -1070,11 +1098,12 @@ _dbus_transport_get_unix_process_id (DBusTransport *transport,
if (!transport->authenticated)
return FALSE;
- _dbus_auth_get_identity (transport->auth, &auth_identity);
+ auth_identity = _dbus_auth_get_identity (transport->auth);
- if (auth_identity.pid != DBUS_PID_UNSET)
+ if (_dbus_credentials_include (auth_identity,
+ DBUS_CREDENTIAL_UNIX_PROCESS_ID))
{
- *pid = auth_identity.pid;
+ *pid = _dbus_credentials_get_unix_pid (auth_identity);
return TRUE;
}
else
diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c
index 7b12de50..6e1653e6 100644
--- a/dbus/dbus-userdb-util.c
+++ b/dbus/dbus-userdb-util.c
@@ -103,20 +103,33 @@ _dbus_is_console_user (dbus_uid_t uid,
return result;
}
+/**
+ * Gets user ID given username
+ *
+ * @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)
+{
+ return _dbus_get_user_id_and_primary_group (username, uid, NULL);
+}
/**
- * Gets the credentials corresponding to the given UID.
+ * Gets group ID given groupname
*
- * @param uid the UID
- * @param credentials credentials to fill in
- * @returns #TRUE if the UID existed and we got some credentials
+ * @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_credentials_from_uid (dbus_uid_t uid,
- DBusCredentials *credentials)
+_dbus_get_group_id (const DBusString *groupname,
+ dbus_gid_t *gid)
{
DBusUserDatabase *db;
- const DBusUserInfo *info;
+ const DBusGroupInfo *info;
_dbus_user_database_lock_system ();
db = _dbus_user_database_get_system ();
@@ -126,61 +139,34 @@ _dbus_credentials_from_uid (dbus_uid_t uid,
return FALSE;
}
- if (!_dbus_user_database_get_uid (db, uid,
- &info, NULL))
+ if (!_dbus_user_database_get_groupname (db, groupname,
+ &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;
+ *gid = info->gid;
_dbus_user_database_unlock_system ();
return TRUE;
}
-
/**
- * Gets user ID given username
+ * Gets user ID and primary group given username
*
* @param username the username
- * @param uid return location for UID
- * @returns #TRUE if username existed and we got the UID
+ * @param uid_p return location for UID
+ * @param gid_p return location for GID
+ * @returns #TRUE if username existed and we got the UID and GID
*/
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;
-}
-
-/**
- * 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)
+_dbus_get_user_id_and_primary_group (const DBusString *username,
+ dbus_uid_t *uid_p,
+ dbus_gid_t *gid_p)
{
DBusUserDatabase *db;
- const DBusGroupInfo *info;
+ const DBusUserInfo *info;
_dbus_user_database_lock_system ();
db = _dbus_user_database_get_system ();
@@ -190,14 +176,17 @@ _dbus_get_group_id (const DBusString *groupname,
return FALSE;
}
- if (!_dbus_user_database_get_groupname (db, groupname,
- &info, NULL))
+ if (!_dbus_user_database_get_username (db, username,
+ &info, NULL))
{
_dbus_user_database_unlock_system ();
return FALSE;
}
- *gid = info->gid;
+ if (uid_p)
+ *uid_p = info->uid;
+ if (gid_p)
+ *gid_p = info->primary_gid;
_dbus_user_database_unlock_system ();
return TRUE;
@@ -434,7 +423,6 @@ _dbus_userdb_test (const char *test_data_dir)
if (!_dbus_get_user_id (username, &uid))
_dbus_assert_not_reached ("didn't get uid");
-
if (!_dbus_groups_from_uid (uid, &group_ids, &n_group_ids))
_dbus_assert_not_reached ("didn't get groups");
diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c
index 2aa395dc..c3ae8ef4 100644
--- a/dbus/dbus-userdb.c
+++ b/dbus/dbus-userdb.c
@@ -26,6 +26,7 @@
#include "dbus-test.h"
#include "dbus-internals.h"
#include "dbus-protocol.h"
+#include "dbus-credentials.h"
#include <string.h>
/**
@@ -66,6 +67,30 @@ _dbus_group_info_free_allocated (DBusGroupInfo *info)
}
/**
+ * 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
*
@@ -412,18 +437,19 @@ _dbus_homedir_from_username (const DBusString *username,
}
/**
- * Gets the credentials corresponding to the given username.
+ * Adds the credentials corresponding to the given username.
*
+ * @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_username (DBusCredentials *credentials,
+ const DBusString *username)
{
DBusUserDatabase *db;
const DBusUserInfo *info;
+
_dbus_user_database_lock_system ();
db = _dbus_user_database_get_system ();
@@ -440,9 +466,11 @@ _dbus_credentials_from_username (const DBusString *username,
return FALSE;
}
- credentials->pid = DBUS_PID_UNSET;
- credentials->uid = info->uid;
- credentials->gid = info->primary_gid;
+ if (!_dbus_credentials_add_unix_uid(credentials, info->uid))
+ {
+ _dbus_user_database_unlock_system ();
+ return FALSE;
+ }
_dbus_user_database_unlock_system ();
return TRUE;
diff --git a/dbus/dbus-userdb.h b/dbus/dbus-userdb.h
index 9e278544..4fae6f02 100644
--- a/dbus/dbus-userdb.h
+++ b/dbus/dbus-userdb.h
@@ -24,7 +24,11 @@
#ifndef DBUS_USERDB_H
#define DBUS_USERDB_H
-#include <dbus/dbus-sysdeps.h>
+#include <dbus/dbus-sysdeps-unix.h>
+
+#ifdef DBUS_WIN
+#error "Don't include this on Windows"
+#endif
DBUS_BEGIN_DECLS
@@ -86,16 +90,13 @@ void _dbus_user_database_lock_system (void);
void _dbus_user_database_unlock_system (void);
void _dbus_user_database_flush_system (void);
-dbus_bool_t _dbus_username_from_current_process (const DBusString **username);
-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_get_user_id (const DBusString *username,
dbus_uid_t *uid);
dbus_bool_t _dbus_get_group_id (const DBusString *group_name,
dbus_gid_t *gid);
-dbus_bool_t _dbus_credentials_from_username (const DBusString *username,
- DBusCredentials *credentials);
+dbus_bool_t _dbus_get_user_id_and_primary_group (const DBusString *username,
+ dbus_uid_t *uid_p,
+ dbus_gid_t *gid_p);
dbus_bool_t _dbus_credentials_from_uid (dbus_uid_t user_id,
DBusCredentials *credentials);
dbus_bool_t _dbus_groups_from_uid (dbus_uid_t uid,
diff --git a/test/Makefile.am b/test/Makefile.am
index ddb489d3..b3c9773b 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -88,6 +88,7 @@ TESTDIRS= \
data/sha-1 \
data/valid-config-files \
data/valid-config-files/basic.d \
+ data/valid-config-files/session.d \
data/valid-config-files/system.d \
data/valid-service-files \
data/invalid-config-files \