? config.cache ? test/data/valid-config-files/session.d ? test/name-test/run-with-tmp-session-bus.conf Index: ChangeLog =================================================================== RCS file: /cvs/dbus/dbus/ChangeLog,v retrieving revision 1.1306 diff -u -p -r1.1306 ChangeLog --- ChangeLog 7 Jun 2007 16:40:30 -0000 1.1306 +++ ChangeLog 9 Jun 2007 21:50:51 -0000 @@ -1,3 +1,22 @@ +2007-06-09 Havoc Pennington + + * 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 * dbus/dbus-message.c: improve some docs related to reading values Index: configure.in =================================================================== RCS file: /cvs/dbus/dbus/configure.in,v retrieving revision 1.205 diff -u -p -r1.205 configure.in --- configure.in 25 May 2007 21:53:55 -0000 1.205 +++ configure.in 9 Jun 2007 21:50:52 -0000 @@ -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 Index: bus/bus.c =================================================================== RCS file: /cvs/dbus/dbus/bus/bus.c,v retrieving revision 1.77 diff -u -p -r1.77 bus.c --- bus/bus.c 12 Mar 2007 22:52:39 -0000 1.77 +++ bus/bus.c 9 Jun 2007 21:50:52 -0000 @@ -533,7 +533,6 @@ bus_context_new (const DBusString *confi { BusContext *context; BusConfigParser *parser; - DBusCredentials creds; _DBUS_ASSERT_ERROR_IS_CLEAR (error); @@ -660,13 +659,7 @@ bus_context_new (const DBusString *confi /* 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 *confi */ 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; Index: bus/dispatch.c =================================================================== RCS file: /cvs/dbus/dbus/bus/dispatch.c,v retrieving revision 1.79 diff -u -p -r1.79 dispatch.c --- bus/dispatch.c 8 Mar 2007 08:30:17 -0000 1.79 +++ bus/dispatch.c 9 Jun 2007 21:50:55 -0000 @@ -399,6 +399,10 @@ bus_dispatch_remove_connection (DBusConn #ifdef DBUS_BUILD_TESTS #include +#ifdef DBUS_UNIX +#include +#include +#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 (Bu * 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"); @@ -2812,7 +2816,7 @@ check_segfault_service_auto_start (BusCo return retval; } #endif - + #define TEST_ECHO_MESSAGE "Test echo message" #define TEST_RUN_HELLO_FROM_SELF_MESSAGE "Test sending message to self" Index: bus/policy.c =================================================================== RCS file: /cvs/dbus/dbus/bus/policy.c,v retrieving revision 1.27 diff -u -p -r1.27 policy.c --- bus/policy.c 27 May 2007 11:38:27 -0000 1.27 +++ bus/policy.c 9 Jun 2007 21:50:56 -0000 @@ -324,13 +324,9 @@ bus_policy_create_client_policy (BusPoli 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) Index: dbus/Makefile.am =================================================================== RCS file: /cvs/dbus/dbus/dbus/Makefile.am,v retrieving revision 1.89 diff -u -p -r1.89 Makefile.am --- dbus/Makefile.am 15 Nov 2006 03:07:59 -0000 1.89 +++ dbus/Makefile.am 9 Jun 2007 21:50:56 -0000 @@ -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 \ Index: dbus/dbus-auth-script.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-auth-script.c,v retrieving revision 1.18 diff -u -p -r1.18 dbus-auth-script.c --- dbus/dbus-auth-script.c 3 Aug 2006 20:34:36 -0000 1.18 +++ dbus/dbus-auth-script.c 9 Jun 2007 21:50:56 -0000 @@ -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 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 /* 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 /* 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 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 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); Index: dbus/dbus-auth.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-auth.c,v retrieving revision 1.48 diff -u -p -r1.48 dbus-auth.c --- dbus/dbus-auth.c 6 Sep 2006 00:14:06 -0000 1.48 +++ dbus/dbus-auth.c 9 Jun 2007 21:50:58 -0000 @@ -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 (DBusA } } - 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 (DBus 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 (DBusAu 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 (DBusAu */ 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 (DBusAu } } - 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 (DBusAu 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_ 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 * * @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; + } } /** Index: dbus/dbus-auth.h =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-auth.h,v retrieving revision 1.13 diff -u -p -r1.13 dbus-auth.h --- dbus/dbus-auth.h 5 May 2005 22:02:11 -0000 1.13 +++ dbus/dbus-auth.h 9 Jun 2007 21:50:58 -0000 @@ -68,10 +68,9 @@ dbus_bool_t _dbus_auth_needs_decoding 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); Index: dbus/dbus-credentials-util.c =================================================================== RCS file: dbus/dbus-credentials-util.c diff -N dbus/dbus-credentials-util.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dbus/dbus-credentials-util.c 9 Jun 2007 21:50:58 -0000 @@ -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 +#include + +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 */ Index: dbus/dbus-credentials.c =================================================================== RCS file: dbus/dbus-credentials.c diff -N dbus/dbus-credentials.c --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dbus/dbus-credentials.c 9 Jun 2007 21:50:58 -0000 @@ -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 +#include +#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 */ Index: dbus/dbus-credentials.h =================================================================== RCS file: dbus/dbus-credentials.h diff -N dbus/dbus-credentials.h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ dbus/dbus-credentials.h 9 Jun 2007 21:50:58 -0000 @@ -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 +#include +#include +#include + +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 */ Index: dbus/dbus-internals.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-internals.c,v retrieving revision 1.57 diff -u -p -r1.57 dbus-internals.c --- dbus/dbus-internals.c 27 May 2007 11:38:28 -0000 1.57 +++ dbus/dbus-internals.c 9 Jun 2007 21:50:59 -0000 @@ -271,7 +271,7 @@ _dbus_warn_check_failed(const char *form 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 conditio 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 cha 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 */ Index: dbus/dbus-keyring.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-keyring.c,v retrieving revision 1.33 diff -u -p -r1.33 dbus-keyring.c --- dbus/dbus-keyring.c 11 Sep 2006 17:41:21 -0000 1.33 +++ dbus/dbus-keyring.c 9 Jun 2007 21:50:59 -0000 @@ -22,7 +22,6 @@ */ #include "dbus-keyring.h" -#include "dbus-userdb.h" #include "dbus-protocol.h" #include #include Index: dbus/dbus-marshal-recursive-util.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-marshal-recursive-util.c,v retrieving revision 1.13 diff -u -p -r1.13 dbus-marshal-recursive-util.c --- dbus/dbus-marshal-recursive-util.c 20 Oct 2006 03:04:59 -0000 1.13 +++ dbus/dbus-marshal-recursive-util.c 9 Jun 2007 21:51:02 -0000 @@ -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; Index: dbus/dbus-spawn.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-spawn.c,v retrieving revision 1.25 diff -u -p -r1.25 dbus-spawn.c --- dbus/dbus-spawn.c 4 Mar 2007 19:14:03 -0000 1.25 +++ dbus/dbus-spawn.c 9 Jun 2007 21:51:02 -0000 @@ -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 #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) Index: dbus/dbus-sysdeps-unix.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps-unix.c,v retrieving revision 1.26 diff -u -p -r1.26 dbus-sysdeps-unix.c --- dbus/dbus-sysdeps-unix.c 27 Apr 2007 17:58:46 -0000 1.26 +++ dbus/dbus-sysdeps-unix.c 9 Jun 2007 21:51:04 -0000 @@ -31,6 +31,7 @@ #include "dbus-string.h" #include "dbus-userdb.h" #include "dbus-list.h" +#include "dbus-credentials.h" #include #include #include @@ -85,6 +86,7 @@ _dbus_open_socket (int *fd_ *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 /** * 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 * 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 * 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 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 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 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 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 _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 * @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 * } /** - * 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 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 DBusStr 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 DBu 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 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 /* 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 ( else { const DBusString *homedir; - const DBusString local_share; + DBusString local_share; if (!_dbus_homedir_from_current_process (&homedir)) goto oom; Index: dbus/dbus-sysdeps-unix.h =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps-unix.h,v retrieving revision 1.3 diff -u -p -r1.3 dbus-sysdeps-unix.h --- dbus/dbus-sysdeps-unix.h 21 Oct 2006 18:17:02 -0000 1.3 +++ dbus/dbus-sysdeps-unix.h 9 Jun 2007 21:51:04 -0000 @@ -71,6 +71,63 @@ int _dbus_listen_unix_socket (const cha 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 Index: dbus/dbus-sysdeps-util-unix.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps-util-unix.c,v retrieving revision 1.14 diff -u -p -r1.14 dbus-sysdeps-util-unix.c --- dbus/dbus-sysdeps-util-unix.c 12 Mar 2007 22:52:40 -0000 1.14 +++ dbus/dbus-sysdeps-util-unix.c 9 Jun 2007 21:51:05 -0000 @@ -243,20 +243,47 @@ _dbus_write_pid_file (const DBusString * 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. Index: dbus/dbus-sysdeps-win.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps-win.c,v retrieving revision 1.14 diff -u -p -r1.14 dbus-sysdeps-win.c --- dbus/dbus-sysdeps-win.c 24 May 2007 18:15:24 -0000 1.14 +++ dbus/dbus-sysdeps-win.c 9 Jun 2007 21:51:08 -0000 @@ -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 Index: dbus/dbus-sysdeps.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps.c,v retrieving revision 1.123 diff -u -p -r1.123 dbus-sysdeps.c --- dbus/dbus-sysdeps.c 19 May 2007 15:39:01 -0000 1.123 +++ dbus/dbus-sysdeps.c 9 Jun 2007 21:51:08 -0000 @@ -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 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 DBusStr * @{ */ -/** - * 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 } /** - * 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. * Index: dbus/dbus-sysdeps.h =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-sysdeps.h,v retrieving revision 1.73 diff -u -p -r1.73 dbus-sysdeps.h --- dbus/dbus-sysdeps.h 16 Mar 2007 21:56:33 -0000 1.73 +++ dbus/dbus-sysdeps.h 9 Jun 2007 21:51:09 -0000 @@ -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 cha 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_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); - - -unsigned long _dbus_getpid (void); -dbus_uid_t _dbus_getuid (void); -dbus_gid_t _dbus_getgid (void); +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_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); + +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 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 _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 const char *suffix, DBusList **dir_list); +unsigned long _dbus_pid_for_log (void); + /** @} */ DBUS_END_DECLS Index: dbus/dbus-test.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-test.c,v retrieving revision 1.45 diff -u -p -r1.45 dbus-test.c --- dbus/dbus-test.c 19 May 2007 18:15:56 -0000 1.45 +++ dbus/dbus-test.c 9 Jun 2007 21:51:09 -0000 @@ -160,6 +160,8 @@ dbus_internal_do_not_use_run_tests (cons 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); Index: dbus/dbus-test.h =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-test.h,v retrieving revision 1.33 diff -u -p -r1.33 dbus-test.h --- dbus/dbus-test.h 15 Nov 2006 03:07:59 -0000 1.33 +++ dbus/dbus-test.h 9 Jun 2007 21:51:09 -0000 @@ -54,6 +54,7 @@ dbus_bool_t _dbus_userdb_test 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); Index: dbus/dbus-transport-protected.h =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-transport-protected.h,v retrieving revision 1.20 diff -u -p -r1.20 dbus-transport-protected.h --- dbus/dbus-transport-protected.h 16 Sep 2006 19:24:08 -0000 1.20 +++ dbus/dbus-transport-protected.h 9 Jun 2007 21:51:09 -0000 @@ -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. */ Index: dbus/dbus-transport-socket.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-transport-socket.c,v retrieving revision 1.4 diff -u -p -r1.4 dbus-transport-socket.c --- dbus/dbus-transport-socket.c 20 Oct 2006 03:05:00 -0000 1.4 +++ dbus/dbus-transport-socket.c 9 Jun 2007 21:51:10 -0000 @@ -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 *tra 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 *tra 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 *tra 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 *tra 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 *transp 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 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)) Index: dbus/dbus-transport.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-transport.c,v retrieving revision 1.54 diff -u -p -r1.54 dbus-transport.c --- dbus/dbus-transport.c 17 Oct 2006 20:52:13 -0000 1.54 +++ dbus/dbus-transport.c 9 Jun 2007 21:51:10 -0000 @@ -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 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 _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 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 * 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 (DBusTrans _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 (DBusTr */ 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 (DB 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 (DB 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 (DB } 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 (DBusTrans 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 (DBu 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 Index: dbus/dbus-userdb-util.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-userdb-util.c,v retrieving revision 1.9 diff -u -p -r1.9 dbus-userdb-util.c --- dbus/dbus-userdb-util.c 12 Dec 2006 22:01:22 -0000 1.9 +++ dbus/dbus-userdb-util.c 9 Jun 2007 21:51:11 -0000 @@ -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 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 *g 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 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"); Index: dbus/dbus-userdb.c =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-userdb.c,v retrieving revision 1.22 diff -u -p -r1.22 dbus-userdb.c --- dbus/dbus-userdb.c 12 Dec 2006 22:01:22 -0000 1.22 +++ dbus/dbus-userdb.c 9 Jun 2007 21:51:11 -0000 @@ -26,6 +26,7 @@ #include "dbus-test.h" #include "dbus-internals.h" #include "dbus-protocol.h" +#include "dbus-credentials.h" #include /** @@ -66,6 +67,30 @@ _dbus_group_info_free_allocated (DBusGro } /** + * 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 DBusS } /** - * 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 D 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; Index: dbus/dbus-userdb.h =================================================================== RCS file: /cvs/dbus/dbus/dbus/dbus-userdb.h,v retrieving revision 1.12 diff -u -p -r1.12 dbus-userdb.h --- dbus/dbus-userdb.h 12 Dec 2006 21:24:07 -0000 1.12 +++ dbus/dbus-userdb.h 9 Jun 2007 21:51:11 -0000 @@ -24,7 +24,11 @@ #ifndef DBUS_USERDB_H #define DBUS_USERDB_H -#include +#include + +#ifdef DBUS_WIN +#error "Don't include this on Windows" +#endif DBUS_BEGIN_DECLS @@ -86,16 +90,13 @@ void _dbus_user_database_lo 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, Index: test/Makefile.am =================================================================== RCS file: /cvs/dbus/dbus/test/Makefile.am,v retrieving revision 1.44 diff -u -p -r1.44 Makefile.am --- test/Makefile.am 4 Mar 2007 18:53:29 -0000 1.44 +++ test/Makefile.am 9 Jun 2007 21:51:11 -0000 @@ -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 \