diff options
-rw-r--r-- | HACKING | 7 | ||||
-rw-r--r-- | bus/driver.c | 79 | ||||
-rw-r--r-- | configure.in | 26 | ||||
-rw-r--r-- | dbus/dbus-auth.c | 7 | ||||
-rw-r--r-- | dbus/dbus-bus.c | 2 | ||||
-rw-r--r-- | dbus/dbus-connection.c | 56 | ||||
-rw-r--r-- | dbus/dbus-connection.h | 3 | ||||
-rw-r--r-- | dbus/dbus-credentials.c | 79 | ||||
-rw-r--r-- | dbus/dbus-credentials.h | 3 | ||||
-rw-r--r-- | dbus/dbus-protocol.h | 2 | ||||
-rw-r--r-- | dbus/dbus-sysdeps-unix.c | 52 | ||||
-rw-r--r-- | dbus/dbus-transport.c | 34 | ||||
-rw-r--r-- | dbus/dbus-transport.h | 3 | ||||
-rw-r--r-- | dbus/dbus-userdb-util.c | 2 | ||||
-rw-r--r-- | dbus/dbus-userdb.c | 2 | ||||
-rw-r--r-- | test/Makefile.am | 26 | ||||
-rw-r--r-- | test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service.in | 4 | ||||
-rw-r--r-- | test/name-test/Makefile.am | 26 | ||||
-rwxr-xr-x | test/name-test/run-test.sh | 11 | ||||
-rw-r--r-- | test/name-test/test-privserver-client.c | 116 | ||||
-rw-r--r-- | test/name-test/test-privserver.c | 118 | ||||
-rw-r--r-- | test/name-test/test-shutdown.c | 67 | ||||
-rw-r--r-- | test/test-utils.c | 154 | ||||
-rw-r--r-- | test/test-utils.h | 6 |
24 files changed, 851 insertions, 34 deletions
@@ -193,6 +193,11 @@ test/break-loader A test that tries to break the message loader by passing it randomly created invalid messages. +test/name-test/* +This is a suite of programs which are run with a temporary session bus. +If your test involves multiple processes communicating, your best bet +is to add a test in here. + "make check" runs all the deterministic test programs (i.e. not break-loader). "make check-coverage" is available if you configure with --enable-gcov and @@ -221,7 +226,7 @@ rules are: - regardless of reviews, to commit a patch: - make check must pass - the test suite must be extended to cover the new code - as much as reasonably feasible + as much as reasonably feasible (see Tests above) - the patch has to follow the portability, security, and style guidelines - the patch should as much as reasonable do one thing, diff --git a/bus/driver.c b/bus/driver.c index 25196265..bdf5afbe 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -1273,6 +1273,81 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, } static dbus_bool_t +bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error) +{ + const char *service; + DBusString str; + BusRegistry *registry; + BusService *serv; + DBusConnection *conn; + DBusMessage *reply; + char *data = NULL; + dbus_uint32_t data_size; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + + registry = bus_connection_get_registry (connection); + + service = NULL; + reply = NULL; + + if (! dbus_message_get_args (message, error, + DBUS_TYPE_STRING, &service, + DBUS_TYPE_INVALID)) + goto failed; + + _dbus_verbose ("asked for audit session data for connection %s\n", service); + + _dbus_string_init_const (&str, service); + serv = bus_registry_lookup (registry, &str); + if (serv == NULL) + { + dbus_set_error (error, + DBUS_ERROR_NAME_HAS_NO_OWNER, + "Could not get audit session data for name '%s': no such name", service); + goto failed; + } + + conn = bus_service_get_primary_owners_connection (serv); + + reply = dbus_message_new_method_return (message); + if (reply == NULL) + goto oom; + + if (!dbus_connection_get_adt_audit_session_data (conn, &data, &data_size) || data == NULL) + { + dbus_set_error (error, + DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN, + "Could not determine audit session data for '%s'", service); + goto failed; + } + + if (! dbus_message_append_args (reply, + DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE, &data, data_size, + DBUS_TYPE_INVALID)) + goto oom; + + if (! bus_transaction_send_from_driver (transaction, connection, reply)) + goto oom; + + dbus_message_unref (reply); + + return TRUE; + + oom: + BUS_SET_OOM (error); + + failed: + _DBUS_ASSERT_ERROR_IS_SET (error); + if (reply) + dbus_message_unref (reply); + return FALSE; +} + +static dbus_bool_t bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection, BusTransaction *transaction, DBusMessage *message, @@ -1503,6 +1578,10 @@ struct DBUS_TYPE_STRING_AS_STRING, DBUS_TYPE_UINT32_AS_STRING, bus_driver_handle_get_connection_unix_process_id }, + { "GetAdtAuditSessionData", + DBUS_TYPE_STRING_AS_STRING, + DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, + bus_driver_handle_get_adt_audit_session_data }, { "GetConnectionSELinuxSecurityContext", DBUS_TYPE_STRING_AS_STRING, DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING, diff --git a/configure.in b/configure.in index d3ca0172..b8338405 100644 --- a/configure.in +++ b/configure.in @@ -2,8 +2,8 @@ dnl -*- mode: m4 -*- AC_PREREQ(2.52) m4_define([dbus_major_version], [1]) -m4_define([dbus_minor_version], [2]) -m4_define([dbus_micro_version], [2]) +m4_define([dbus_minor_version], [3]) +m4_define([dbus_micro_version], [0]) m4_define([dbus_version], [dbus_major_version.dbus_minor_version.dbus_micro_version]) AC_INIT(dbus, [dbus_version]) @@ -1028,6 +1028,24 @@ if test x$have_libaudit = xyes ; then AC_DEFINE(HAVE_LIBAUDIT,1,[audit daemon SELinux support]) fi +# Check for ADT API +AC_MSG_CHECKING(for ADT API) +AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ +#include <bsm/adt.h> +adt_user_context = ADT_USER; +]], [[]])], [ check_adt_audit=yes ], [ check_adt_audit=no ]) + +if test ${check_adt_audit} = yes +then + AC_DEFINE([HAVE_ADT], [], [Adt audit API]) + ADT_LIBS="-lbsm" + LIBS="-lbsm $LIBS" + AC_MSG_RESULT(yes) +else + AC_MSG_RESULT(no) +fi + + #### Set up final flags DBUS_CLIENT_CFLAGS= DBUS_CLIENT_LIBS="$THREAD_LIBS" @@ -1035,7 +1053,7 @@ AC_SUBST(DBUS_CLIENT_CFLAGS) AC_SUBST(DBUS_CLIENT_LIBS) DBUS_BUS_CFLAGS="$XML_CFLAGS" -DBUS_BUS_LIBS="$XML_LIBS $SELINUX_LIBS $INTLLIBS $THREAD_LIBS" +DBUS_BUS_LIBS="$XML_LIBS $SELINUX_LIBS $INTLLIBS $THREAD_LIBS $ADT_LIBS" AC_SUBST(DBUS_BUS_CFLAGS) AC_SUBST(DBUS_BUS_LIBS) @@ -1275,6 +1293,7 @@ TEST_PATH(SHELL_SERVICE_BINARY, test-shell-service) TEST_PATH(EXIT_BINARY, test-exit) TEST_PATH(SEGFAULT_BINARY, test-segfault) TEST_PATH(SLEEP_FOREVER_BINARY, test-sleep-forever) +TEST_PATH(PRIVSERVER_BINARY, name-test/test-privserver) AC_DEFINE_UNQUOTED(TEST_BUS_BINARY, "$DBUS_PWD/bus/dbus-daemon", [Full path to the daemon in the builddir]) @@ -1347,6 +1366,7 @@ test/data/valid-config-files/debug-allow-all.conf test/data/valid-config-files/debug-allow-all-sha1.conf test/data/valid-config-files-system/debug-allow-all-pass.conf test/data/valid-config-files-system/debug-allow-all-fail.conf +test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service test/data/valid-service-files/org.freedesktop.DBus.TestSuiteEchoService.service test/data/valid-service-files/org.freedesktop.DBus.TestSuiteSegfaultService.service test/data/valid-service-files/org.freedesktop.DBus.TestSuiteShellEchoServiceSuccess.service diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c index 7e424aff..ec7cf312 100644 --- a/dbus/dbus-auth.c +++ b/dbus/dbus-auth.c @@ -1094,6 +1094,13 @@ handle_server_data_external_mech (DBusAuth *auth, DBUS_CREDENTIAL_UNIX_PROCESS_ID, auth->credentials)) return FALSE; + + /* also copy audit data from the socket credentials + */ + if (!_dbus_credentials_add_credential (auth->authorized_identity, + DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, + auth->credentials)) + return FALSE; if (!send_ok (auth)) return FALSE; diff --git a/dbus/dbus-bus.c b/dbus/dbus-bus.c index e159dae7..f97cce68 100644 --- a/dbus/dbus-bus.c +++ b/dbus/dbus-bus.c @@ -124,6 +124,8 @@ addresses_shutdown_func (void *data) } activation_bus_type = DBUS_BUS_STARTER; + + initialized = FALSE; } static dbus_bool_t diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 2e291eee..a960a991 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -1678,21 +1678,26 @@ connection_forget_shared_unlocked (DBusConnection *connection) if (!connection->shareable) return; + _DBUS_LOCK (shared_connections); + if (connection->server_guid != NULL) { _dbus_verbose ("dropping connection to %s out of the shared table\n", connection->server_guid); - _DBUS_LOCK (shared_connections); - if (!_dbus_hash_table_remove_string (shared_connections, connection->server_guid)) _dbus_assert_not_reached ("connection was not in the shared table"); dbus_free (connection->server_guid); connection->server_guid = NULL; - _DBUS_UNLOCK (shared_connections); } + else + { + _dbus_list_remove (&shared_connections_no_guid, connection); + } + + _DBUS_UNLOCK (shared_connections); /* remove our reference held on all shareable connections */ _dbus_connection_unref_unlocked (connection); @@ -3411,9 +3416,13 @@ _dbus_connection_read_write_dispatch (DBusConnection *connection, dbus_bool_t dispatch) { DBusDispatchStatus dstatus; - dbus_bool_t no_progress_possible; dbus_bool_t progress_possible; - + + /* Need to grab a ref here in case we're a private connection and + * the user drops the last ref in a handler we call; see bug + * https://bugs.freedesktop.org/show_bug.cgi?id=15635 + */ + dbus_connection_ref (connection); dstatus = dbus_connection_get_dispatch_status (connection); if (dispatch && dstatus == DBUS_DISPATCH_DATA_REMAINS) @@ -3454,6 +3463,9 @@ _dbus_connection_read_write_dispatch (DBusConnection *connection, progress_possible = _dbus_connection_get_is_connected_unlocked (connection); CONNECTION_UNLOCK (connection); + + dbus_connection_unref (connection); + return progress_possible; /* TRUE if we can make more progress */ } @@ -4973,6 +4985,40 @@ dbus_connection_get_unix_process_id (DBusConnection *connection, } /** + * Gets the ADT audit data of the connection if any. + * Returns #TRUE if the structure pointer is returned. + * Always returns #FALSE prior to authenticating the + * connection. + * + * @param connection the connection + * @param data return location for audit data + * @returns #TRUE if audit data is filled in with a valid ucred pointer + */ +dbus_bool_t +dbus_connection_get_adt_audit_session_data (DBusConnection *connection, + void **data, + dbus_int32_t *data_size) +{ + dbus_bool_t result; + + _dbus_return_val_if_fail (connection != NULL, FALSE); + _dbus_return_val_if_fail (data != NULL, FALSE); + _dbus_return_val_if_fail (data_size != NULL, FALSE); + + CONNECTION_LOCK (connection); + + if (!_dbus_transport_get_is_authenticated (connection->transport)) + result = FALSE; + else + result = _dbus_transport_get_adt_audit_session_data (connection->transport, + data, + data_size); + CONNECTION_UNLOCK (connection); + + return result; +} + +/** * Sets a predicate function used to determine whether a given user ID * is allowed to connect. When an incoming connection has * authenticated with a particular user ID, this function is called; diff --git a/dbus/dbus-connection.h b/dbus/dbus-connection.h index 5d7e493b..b8fd35fb 100644 --- a/dbus/dbus-connection.h +++ b/dbus/dbus-connection.h @@ -231,6 +231,9 @@ dbus_bool_t dbus_connection_get_unix_user (DBusConnection unsigned long *uid); dbus_bool_t dbus_connection_get_unix_process_id (DBusConnection *connection, unsigned long *pid); +dbus_bool_t dbus_connection_get_adt_audit_session_data (DBusConnection *connection, + void **data, + dbus_int32_t *data_size); void dbus_connection_set_unix_user_function (DBusConnection *connection, DBusAllowUnixUserFunction function, void *data, diff --git a/dbus/dbus-credentials.c b/dbus/dbus-credentials.c index 790ca06b..f21ecb27 100644 --- a/dbus/dbus-credentials.c +++ b/dbus/dbus-credentials.c @@ -50,6 +50,8 @@ struct DBusCredentials { dbus_uid_t unix_uid; dbus_pid_t unix_pid; char *windows_sid; + void *adt_audit_data; + dbus_int32_t adt_audit_data_size; }; /** @} */ @@ -77,6 +79,8 @@ _dbus_credentials_new (void) creds->unix_uid = DBUS_UID_UNSET; creds->unix_pid = DBUS_PID_UNSET; creds->windows_sid = NULL; + creds->adt_audit_data = NULL; + creds->adt_audit_data_size = 0; return creds; } @@ -129,6 +133,7 @@ _dbus_credentials_unref (DBusCredentials *credentials) if (credentials->refcount == 0) { dbus_free (credentials->windows_sid); + dbus_free (credentials->adt_audit_data); dbus_free (credentials); } } @@ -188,6 +193,31 @@ _dbus_credentials_add_windows_sid (DBusCredentials *credentials, } /** + * Add ADT audit data to the credentials. + * + * @param credentials the object + * @param audit_data the audit data + * @param size the length of audit data + * @returns #FALSE if no memory + */ +dbus_bool_t +_dbus_credentials_add_adt_audit_data (DBusCredentials *credentials, + void *audit_data, + dbus_int32_t size) +{ + void *copy; + copy = _dbus_memdup (audit_data, size); + if (copy == NULL) + return FALSE; + + dbus_free (credentials->adt_audit_data); + credentials->adt_audit_data = copy; + credentials->adt_audit_data_size = size; + + return TRUE; +} + +/** * Checks whether the given credential is present. * * @param credentials the object @@ -206,6 +236,8 @@ _dbus_credentials_include (DBusCredentials *credentials, return credentials->unix_uid != DBUS_UID_UNSET; case DBUS_CREDENTIAL_WINDOWS_SID: return credentials->windows_sid != NULL; + case DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID: + return credentials->adt_audit_data != NULL; } _dbus_assert_not_reached ("Unknown credential enum value"); @@ -252,6 +284,32 @@ _dbus_credentials_get_windows_sid (DBusCredentials *credentials) } /** + * Gets the ADT audit data in the credentials, or #NULL if + * the credentials object doesn't contain ADT audit data. + * + * @param credentials the object + * @returns Solaris ADT audit data + */ +void * +_dbus_credentials_get_adt_audit_data (DBusCredentials *credentials) +{ + return credentials->adt_audit_data; +} + +/** + * Gets the ADT audit data size in the credentials, or 0 if + * the credentials object doesn't contain ADT audit data. + * + * @param credentials the object + * @returns Solaris ADT audit data size + */ +dbus_int32_t +_dbus_credentials_get_adt_audit_data_size (DBusCredentials *credentials) +{ + return credentials->adt_audit_data_size; +} + +/** * Checks whether the first credentials object contains * all the credentials found in the second credentials object. * @@ -270,7 +328,11 @@ _dbus_credentials_are_superset (DBusCredentials *credentials, possible_subset->unix_uid == credentials->unix_uid) && (possible_subset->windows_sid == NULL || (credentials->windows_sid && strcmp (possible_subset->windows_sid, - credentials->windows_sid) == 0)); + credentials->windows_sid) == 0)) && + (possible_subset->adt_audit_data == NULL || + (credentials->adt_audit_data && memcmp (possible_subset->adt_audit_data, + credentials->adt_audit_data, + credentials->adt_audit_data_size) == 0)); } /** @@ -285,7 +347,8 @@ _dbus_credentials_are_empty (DBusCredentials *credentials) return credentials->unix_pid == DBUS_PID_UNSET && credentials->unix_uid == DBUS_UID_UNSET && - credentials->windows_sid == NULL; + credentials->windows_sid == NULL && + credentials->adt_audit_data == NULL; } /** @@ -322,6 +385,9 @@ _dbus_credentials_add_credentials (DBusCredentials *credentials, DBUS_CREDENTIAL_UNIX_USER_ID, other_credentials) && _dbus_credentials_add_credential (credentials, + DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, + other_credentials) && + _dbus_credentials_add_credential (credentials, DBUS_CREDENTIAL_WINDOWS_SID, other_credentials); } @@ -360,6 +426,12 @@ _dbus_credentials_add_credential (DBusCredentials *credentials, { if (!_dbus_credentials_add_windows_sid (credentials, other_credentials->windows_sid)) return FALSE; + } + else if (which == DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID && + other_credentials->adt_audit_data != NULL) + { + if (!_dbus_credentials_add_adt_audit_data (credentials, other_credentials->adt_audit_data, other_credentials->adt_audit_data_size)) + return FALSE; } return TRUE; @@ -377,6 +449,9 @@ _dbus_credentials_clear (DBusCredentials *credentials) credentials->unix_uid = DBUS_UID_UNSET; dbus_free (credentials->windows_sid); credentials->windows_sid = NULL; + dbus_free (credentials->adt_audit_data); + credentials->adt_audit_data = NULL; + credentials->adt_audit_data_size = 0; } /** diff --git a/dbus/dbus-credentials.h b/dbus/dbus-credentials.h index b8d7dd7a..d4c8d160 100644 --- a/dbus/dbus-credentials.h +++ b/dbus/dbus-credentials.h @@ -33,6 +33,7 @@ DBUS_BEGIN_DECLS typedef enum { DBUS_CREDENTIAL_UNIX_PROCESS_ID, DBUS_CREDENTIAL_UNIX_USER_ID, + DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, DBUS_CREDENTIAL_WINDOWS_SID } DBusCredentialType; @@ -51,6 +52,8 @@ dbus_bool_t _dbus_credentials_include (DBusCredentials 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); +void * _dbus_credentials_get_adt_audit_data (DBusCredentials *credentials); +dbus_int32_t _dbus_credentials_get_adt_audit_data_size (DBusCredentials *credentials); dbus_bool_t _dbus_credentials_are_superset (DBusCredentials *credentials, DBusCredentials *possible_subset); dbus_bool_t _dbus_credentials_are_empty (DBusCredentials *credentials); diff --git a/dbus/dbus-protocol.h b/dbus/dbus-protocol.h index 58677dcf..814deae0 100644 --- a/dbus/dbus-protocol.h +++ b/dbus/dbus-protocol.h @@ -411,6 +411,8 @@ extern "C" { #define DBUS_ERROR_INVALID_FILE_CONTENT "org.freedesktop.DBus.Error.InvalidFileContent" /** Asked for SELinux security context and it wasn't available. */ #define DBUS_ERROR_SELINUX_SECURITY_CONTEXT_UNKNOWN "org.freedesktop.DBus.Error.SELinuxSecurityContextUnknown" +/** Asked for ADT audit data and it wasn't available. */ +#define DBUS_ERROR_ADT_AUDIT_DATA_UNKNOWN "org.freedesktop.DBus.Error.AdtAuditDataUnknown" /** There's already an object with the requested object path. */ #define DBUS_ERROR_OBJECT_PATH_IN_USE "org.freedesktop.DBus.Error.ObjectPathInUse" diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c index 19858dd3..64d925d9 100644 --- a/dbus/dbus-sysdeps-unix.c +++ b/dbus/dbus-sysdeps-unix.c @@ -71,6 +71,10 @@ #include <ucred.h> #endif +#ifdef HAVE_ADT +#include <bsm/adt.h> +#endif + #ifndef O_BINARY #define O_BINARY 0 #endif @@ -1260,6 +1264,37 @@ _dbus_read_credentials_socket (int client_fd, { pid_read = ucred_getpid (ucred); uid_read = ucred_geteuid (ucred); +#ifdef HAVE_ADT + /* generate audit session data based on socket ucred */ + adt_session_data_t *adth = NULL; + adt_export_data_t *data = NULL; + size_t size = 0; + if (adt_start_session (&adth, NULL, 0) || (adth == NULL)) + { + _dbus_verbose ("Failed to adt_start_session(): %s\n", _dbus_strerror (errno)); + } + else + { + if (adt_set_from_ucred (adth, ucred, ADT_NEW)) + { + _dbus_verbose ("Failed to adt_set_from_ucred(): %s\n", _dbus_strerror (errno)); + } + else + { + size = adt_export_session_data (adth, &data); + if (size <= 0) + { + _dbus_verbose ("Failed to adt_export_session_data(): %s\n", _dbus_strerror (errno)); + } + else + { + _dbus_credentials_add_adt_audit_data (credentials, data, size); + free (data); + } + } + (void) adt_end_session (adth); + } +#endif /* HAVE_ADT */ } else { @@ -2848,7 +2883,10 @@ _dbus_get_autolaunch_address (DBusString *address, if (pid == 0) { /* child process */ - int fd = open ("/dev/null", O_RDWR); + int maxfds; + int fd; + + fd = open ("/dev/null", O_RDWR); if (fd == -1) /* huh?! can't open /dev/null? */ _exit (1); @@ -2869,9 +2907,15 @@ _dbus_get_autolaunch_address (DBusString *address, if (dup2 (errors_pipe[WRITE_END], 2) == -1) _exit (1); - close (fd); - close (address_pipe[WRITE_END]); - close (errors_pipe[WRITE_END]); + maxfds = sysconf (_SC_OPEN_MAX); + /* Pick something reasonable if for some reason sysconf + * says unlimited. + */ + if (maxfds < 0) + maxfds = 1024; + /* close all inherited fds */ + for (i = 3; i < maxfds; i++) + close (i); execv (DBUS_BINDIR "/dbus-launch", argv); diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index 1e1fc97d..90291980 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -1262,6 +1262,40 @@ _dbus_transport_get_unix_process_id (DBusTransport *transport, } /** + * See dbus_connection_get_adt_audit_session_data(). + * + * @param transport the transport + * @param data return location for the ADT audit data + * @param data_size return length of audit data + * @returns #TRUE if audit data is filled in with a valid ucred + */ +dbus_bool_t +_dbus_transport_get_adt_audit_session_data (DBusTransport *transport, + void **data, + int *data_size) +{ + DBusCredentials *auth_identity; + + *data = NULL; + *data_size = 0; + + if (!transport->authenticated) + return FALSE; + + auth_identity = _dbus_auth_get_identity (transport->auth); + + if (_dbus_credentials_include (auth_identity, + DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID)) + { + *data = (void *) _dbus_credentials_get_adt_audit_data (auth_identity); + *data_size = _dbus_credentials_get_adt_audit_data_size (auth_identity); + return TRUE; + } + else + return FALSE; +} + +/** * See dbus_connection_set_unix_user_function(). * * @param transport the transport diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h index 9a9e5532..691763ca 100644 --- a/dbus/dbus-transport.h +++ b/dbus/dbus-transport.h @@ -64,6 +64,9 @@ dbus_bool_t _dbus_transport_get_unix_user (DBusTransport unsigned long *uid); dbus_bool_t _dbus_transport_get_unix_process_id (DBusTransport *transport, unsigned long *pid); +dbus_bool_t _dbus_transport_get_adt_audit_session_data (DBusTransport *transport, + void **data, + int *data_size); void _dbus_transport_set_unix_user_function (DBusTransport *transport, DBusAllowUnixUserFunction function, void *data, diff --git a/dbus/dbus-userdb-util.c b/dbus/dbus-userdb-util.c index 30d50832..d03a7c78 100644 --- a/dbus/dbus-userdb-util.c +++ b/dbus/dbus-userdb-util.c @@ -223,7 +223,7 @@ _dbus_user_database_lookup_group (DBusUserDatabase *db, gid = n; } -#ifdef DBUS_ENABLE_USER_CACHE +#ifdef DBUS_ENABLE_USERDB_CACHE if (gid != DBUS_GID_UNSET) info = _dbus_hash_table_lookup_ulong (db->groups, gid); else diff --git a/dbus/dbus-userdb.c b/dbus/dbus-userdb.c index 0e430b2b..03d263f4 100644 --- a/dbus/dbus-userdb.c +++ b/dbus/dbus-userdb.c @@ -143,7 +143,7 @@ _dbus_user_database_lookup (DBusUserDatabase *db, uid = n; } -#ifdef DBUS_ENABLE_USER_CACHE +#ifdef DBUS_ENABLE_USERDB_CACHE if (uid != DBUS_UID_UNSET) info = _dbus_hash_table_lookup_ulong (db->users, uid); else diff --git a/test/Makefile.am b/test/Makefile.am index 56ab66fc..a7f05970 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,10 +1,14 @@ ## the "name-test" subdir in fact contains a bunch of tests now that need a temporary bus ## to be running to do stuff with. The directory should be renamed. -SUBDIRS=name-test +## We want to build the current directory first to pick up the testutils lib +SUBDIRS= . name-test DIST_SUBDIRS=name-test INCLUDES=-I$(top_srcdir) $(DBUS_TEST_CFLAGS) +libdbus_testutils_la_SOURCES = test-utils.h test-utils.c + +noinst_LTLIBRARIES = libdbus-testutils.la if DBUS_BUILD_TESTS ## break-loader removed for now @@ -28,22 +32,16 @@ endif noinst_PROGRAMS= $(TEST_BINARIES) $(GCOV_BINARIES) test_service_SOURCES= \ - test-service.c \ - test-utils.c \ - test-utils.h + test-service.c test_names_SOURCES= \ - test-names.c \ - test-utils.c \ - test-utils.h + test-names.c ##break_loader_SOURCES= \ ## break-loader.c test_shell_service_SOURCES = \ - test-shell-service.c \ - test-utils.c \ - test-utils.h + test-shell-service.c shell_test_SOURCES= \ shell-test.c @@ -65,15 +63,15 @@ decode_gcov_SOURCES= \ TEST_LIBS=$(DBUS_TEST_LIBS) $(top_builddir)/dbus/libdbus-convenience.la -test_service_LDADD=$(TEST_LIBS) +test_service_LDADD=$(TEST_LIBS) libdbus-testutils.la test_service_LDFLAGS=@R_DYNAMIC_LDFLAG@ -test_names_LDADD=$(TEST_LIBS) +test_names_LDADD=$(TEST_LIBS) libdbus-testutils.la test_names_LDFLAGS=@R_DYNAMIC_LDFLAG@ ## break_loader_LDADD= $(TEST_LIBS) ## break_loader_LDFLAGS=@R_DYNAMIC_LDFLAG@ -test_shell_service_LDADD=$(TEST_LIBS) +test_shell_service_LDADD=$(TEST_LIBS) libdbus-testutils.la test_shell_service_LDFLAGS=@R_DYNAMIC_LDFLAG@ -shell_test_LDADD=$(TEST_LIBS) +shell_test_LDADD=$(TEST_LIBS) libdbus-testutils.la shell_test_LDFLAGS=@R_DYNAMIC_LDFLAG@ spawn_test_LDADD=$(TEST_LIBS) spawn_test_LDFLAGS=@R_DYNAMIC_LDFLAG@ diff --git a/test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service.in b/test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service.in new file mode 100644 index 00000000..2cbdaa8b --- /dev/null +++ b/test/data/valid-service-files/org.freedesktop.DBus.TestSuite.PrivServer.service.in @@ -0,0 +1,4 @@ +[D-BUS Service] +Name=org.freedesktop.DBus.TestSuite.PrivServer +Exec=@TEST_PRIVSERVER_BINARY@ + diff --git a/test/name-test/Makefile.am b/test/name-test/Makefile.am index fbc80c42..17e05bec 100644 --- a/test/name-test/Makefile.am +++ b/test/name-test/Makefile.am @@ -1,4 +1,4 @@ -INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) -DDBUS_COMPILATION +INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_GLIB_CFLAGS) $(DBUS_TEST_CFLAGS) -DDBUS_COMPILATION ## note that TESTS has special meaning (stuff to use in make check) ## so if adding tests not to be run in make check, don't add them to @@ -16,7 +16,7 @@ if DBUS_BUILD_TESTS ## we use noinst_PROGRAMS not check_PROGRAMS for TESTS so that we ## build even when not doing "make check" -noinst_PROGRAMS=test-names test-pending-call-dispatch test-threads-init test-ids +noinst_PROGRAMS=test-names test-pending-call-dispatch test-threads-init test-ids test-shutdown test-privserver test-privserver-client test_names_SOURCES= \ test-names.c @@ -42,5 +42,25 @@ test_ids_SOURCES = \ test_ids_LDADD=$(top_builddir)/dbus/libdbus-convenience.la $(DBUS_TEST_LIBS) test_ids_LDFLAGS=@R_DYNAMIC_LDFLAG@ -endif +test_shutdown_SOURCES = \ + test-shutdown.c + +test_shutdown_CFLAGS= +test_shutdown_LDADD=$(top_builddir)/dbus/libdbus-convenience.la ../libdbus-testutils.la $(DBUS_TEST_LIBS) +test_shutdown_LDFLAGS=@R_DYNAMIC_LDFLAG@ + +test_privserver_SOURCES = \ + test-privserver.c + +test_privserver_CFLAGS= +test_privserver_LDADD=$(top_builddir)/dbus/libdbus-convenience.la ../libdbus-testutils.la $(DBUS_TEST_LIBS) +test_privserver_LDFLAGS=@R_DYNAMIC_LDFLAG@ +test_privserver_client_SOURCES = \ + test-privserver-client.c + +test_privserver_client_CFLAGS= +test_privserver_client_LDADD=$(top_builddir)/dbus/libdbus-convenience.la ../libdbus-testutils.la $(DBUS_TEST_LIBS) +test_privserver_client_LDFLAGS=@R_DYNAMIC_LDFLAG@ + +endif diff --git a/test/name-test/run-test.sh b/test/name-test/run-test.sh index 5d9c584a..3699bc9a 100755 --- a/test/name-test/run-test.sh +++ b/test/name-test/run-test.sh @@ -25,6 +25,11 @@ if test -z "$DBUS_TEST_NAME_IN_RUN_TEST"; then export DBUS_TEST_NAME_IN_RUN_TEST exec $DBUS_TOP_SRCDIR/tools/run-with-tmp-session-bus.sh $SCRIPTNAME $MODE fi + +if test -n "$DBUS_TEST_MONITOR"; then + dbus-monitor --session & +fi + echo "running test-ids" ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-ids || die "test-ids failed" @@ -36,3 +41,9 @@ ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name- echo "running test-threads-init" ${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-threads-init || die "test-threads-init failed" + +echo "running test-privserver-client" +${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-privserver-client || die "test-privserver-client failed" + +echo "running test-shutdown" +${DBUS_TOP_BUILDDIR}/libtool --mode=execute $DEBUG $DBUS_TOP_BUILDDIR/test/name-test/test-shutdown || die "test-shutdown failed" diff --git a/test/name-test/test-privserver-client.c b/test/name-test/test-privserver-client.c new file mode 100644 index 00000000..239b7bdf --- /dev/null +++ b/test/name-test/test-privserver-client.c @@ -0,0 +1,116 @@ +#include "../test-utils.h" + +static void +die (const char *message, ...) +{ + va_list args; + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + exit (1); +} + +static DBusHandlerResult +filter_private_message (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + if (dbus_message_is_signal (message, + DBUS_INTERFACE_LOCAL, + "Disconnected")) + { + DBusLoop *loop = user_data; + _dbus_loop_quit (loop); + return DBUS_HANDLER_RESULT_HANDLED; + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +static void +open_shutdown_private_connection (dbus_bool_t use_guid) +{ + DBusError error; + DBusLoop *loop; + DBusConnection *session; + DBusMessage *msg; + DBusMessage *reply; + DBusConnection *privconn; + char *addr; + char *comma; + + dbus_error_init (&error); + + loop = _dbus_loop_new (); + + session = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (!session) + die ("couldn't access session bus\n"); + dbus_connection_set_exit_on_disconnect (session, FALSE); + msg = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuite.TestServer", + "/", + "org.freedesktop.DBus.TestSuite.TestServer", + "GetPrivateAddress"); + if (!(reply = dbus_connection_send_with_reply_and_block (session, msg, -1, &error))) + die ("couldn't send message: %s\n", error.message); + dbus_message_unref (msg); + if (!dbus_message_get_args (reply, &error, DBUS_TYPE_STRING, &addr, DBUS_TYPE_INVALID)) + die ("couldn't parse message replym\n"); + printf ("got private temp address %s\n", addr); + addr = strdup (addr); + if (!use_guid) + { + char *comma = strrchr (addr, ','); + if (comma) + *comma = '\0'; + } + privconn = dbus_connection_open (addr, &error); + free (addr); + if (!privconn) + die ("couldn't connect to server direct connection: %s\n", error.message); + dbus_message_unref (reply); + + dbus_connection_set_exit_on_disconnect (privconn, FALSE); + dbus_connection_add_filter (privconn, filter_private_message, loop, NULL); + test_connection_setup (loop, privconn); + + msg = dbus_message_new_method_call ("org.freedesktop.DBus.TestSuite.TestServer", + "/", + "org.freedesktop.DBus.TestSuite.TestServer", + "Quit"); + if (!dbus_connection_send (session, msg, NULL)) + die ("couldn't send Quit message\n"); + dbus_message_unref (msg); + + _dbus_loop_run (loop); + + test_connection_shutdown (loop, session); + dbus_connection_unref (session); + + test_connection_shutdown (loop, privconn); + dbus_connection_remove_filter (privconn, filter_private_message, loop); + dbus_connection_unref (privconn); + + _dbus_loop_unref (loop); +} + +int +main (int argc, char *argv[]) +{ + open_shutdown_private_connection (TRUE); + + dbus_shutdown (); + + open_shutdown_private_connection (TRUE); + + dbus_shutdown (); + + open_shutdown_private_connection (FALSE); + + dbus_shutdown (); + + open_shutdown_private_connection (FALSE); + + dbus_shutdown (); + + return 0; +} diff --git a/test/name-test/test-privserver.c b/test/name-test/test-privserver.c new file mode 100644 index 00000000..8a6efc4e --- /dev/null +++ b/test/name-test/test-privserver.c @@ -0,0 +1,118 @@ +#include "../test-utils.h" + +static void +die (const char *message, ...) +{ + va_list args; + va_start (args, message); + vfprintf (stderr, message, args); + va_end (args); + exit (1); +} + +typedef struct TestServiceData TestServiceData; + +struct TestServiceData +{ + DBusLoop *loop; + char *private_addr; +}; + +static void +new_connection_callback (DBusServer *server, + DBusConnection *new_connection, + void *data) +{ + TestServiceData *testdata = data; + + if (!test_connection_setup (testdata->loop, new_connection)) + dbus_connection_close (new_connection); +} + +static DBusHandlerResult +filter_session_message (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + TestServiceData *testdata = user_data; + + if (dbus_message_is_method_call (message, + "org.freedesktop.DBus.TestSuite.TestServer", + "GetPrivateAddress")) + { + DBusMessage *reply; + reply = dbus_message_new_method_return (message); + dbus_message_append_args (reply, DBUS_TYPE_STRING, + &(testdata->private_addr), DBUS_TYPE_INVALID); + dbus_connection_send (connection, reply, NULL); + dbus_message_unref (reply); + return DBUS_HANDLER_RESULT_HANDLED; + } + else if (dbus_message_is_method_call (message, + "org.freedesktop.DBus.TestSuite.TestServer", + "Quit")) + { + fprintf (stderr, "server exiting loop\n"); + _dbus_loop_quit (testdata->loop); + return DBUS_HANDLER_RESULT_HANDLED; + } + return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; +} + +int +main (int argc, char *argv[]) +{ + DBusServer *server; + DBusError error; + DBusLoop *loop; + DBusConnection *session; + TestServiceData *testdata; + + dbus_error_init (&error); + + loop = _dbus_loop_new (); + + testdata = dbus_new (TestServiceData, 1); + testdata->loop = loop; + + session = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (!session) + die ("couldn't access session bus"); + + test_connection_setup (loop, session); + + dbus_bus_request_name (session, "org.freedesktop.DBus.TestSuite.TestServer", 0, &error); + if (dbus_error_is_set (&error)) + die ("couldn't request name: %s", error.message); + + if (!dbus_connection_add_filter (session, filter_session_message, testdata, NULL)) + die ("couldn't add filter"); + + server = dbus_server_listen ("unix:tmpdir=/tmp", &error); + if (!server) + die (error.message); + testdata->private_addr = dbus_server_get_address (server); + printf ("test server listening on %s\n", testdata->private_addr); + + dbus_server_set_new_connection_function (server, new_connection_callback, + testdata, NULL); + + if (!test_server_setup (loop, server)) + die ("server setup failed"); + + fprintf (stderr, "server running mainloop\n"); + _dbus_loop_run (loop); + fprintf (stderr, "server mainloop quit\n"); + + test_server_shutdown (loop, server); + + test_connection_shutdown (loop, session); + + dbus_connection_unref (session); + + _dbus_loop_unref (loop); + + dbus_free (testdata); + + return 0; +} diff --git a/test/name-test/test-shutdown.c b/test/name-test/test-shutdown.c new file mode 100644 index 00000000..c50ef4b6 --- /dev/null +++ b/test/name-test/test-shutdown.c @@ -0,0 +1,67 @@ + +#include "../test-utils.h" + +static DBusLoop *loop; + +static void +die (const char *message) +{ + fprintf (stderr, "*** test-shutdown: %s", message); + exit (1); +} + +static void +open_destroy_shared_session_bus_connection () +{ + DBusError error; + DBusConnection *connection; + char *session_addr_no_guid; + char *comma; + + dbus_error_init (&error); + + session_addr_no_guid = strdup (getenv ("DBUS_SESSION_BUS_ADDRESS")); + comma = strchr (session_addr_no_guid, ','); + if (comma == NULL) + die ("Couldn't find GUID in session bus address"); + *comma = '\0'; + + connection = dbus_connection_open (session_addr_no_guid, &error); + free (session_addr_no_guid); + if (connection == NULL) + die ("Failed to open connection to temp session bus\n"); + + loop = _dbus_loop_new (); + if (loop == NULL) + die ("No memory\n"); + + if (!test_connection_setup (loop, connection)) + die ("No memory\n"); + + test_connection_shutdown (loop, connection); + + _dbus_loop_unref (loop); + + dbus_connection_unref (connection); +} + +int +main (int argc, + char **argv) +{ + open_destroy_shared_session_bus_connection (); + + dbus_shutdown (); + + open_destroy_shared_session_bus_connection (); + + dbus_shutdown (); + + open_destroy_shared_session_bus_connection (); + + dbus_shutdown (); + + _dbus_verbose ("*** Test shutdown exiting\n"); + + return 0; +} diff --git a/test/test-utils.c b/test/test-utils.c index 9665eda3..d875cc95 100644 --- a/test/test-utils.c +++ b/test/test-utils.c @@ -187,3 +187,157 @@ test_connection_shutdown (DBusLoop *loop, dbus_connection_set_dispatch_status_function (connection, NULL, NULL, NULL); } + +typedef struct +{ + DBusLoop *loop; + DBusServer *server; +} ServerData; + +static void +serverdata_free (void *data) +{ + ServerData *sd = data; + + dbus_server_unref (sd->server); + _dbus_loop_unref (sd->loop); + + dbus_free (sd); +} + +static ServerData* +serverdata_new (DBusLoop *loop, + DBusServer *server) +{ + ServerData *sd; + + sd = dbus_new0 (ServerData, 1); + if (sd == NULL) + return NULL; + + sd->loop = loop; + sd->server = server; + + dbus_server_ref (sd->server); + _dbus_loop_ref (sd->loop); + + return sd; +} + +static dbus_bool_t +server_watch_callback (DBusWatch *watch, + unsigned int condition, + void *data) +{ + /* FIXME this can be done in dbus-mainloop.c + * if the code in activation.c for the babysitter + * watch handler is fixed. + */ + + return dbus_watch_handle (watch, condition); +} + +static dbus_bool_t +add_server_watch (DBusWatch *watch, + void *data) +{ + ServerData *context = data; + + return _dbus_loop_add_watch (context->loop, + watch, server_watch_callback, context, + NULL); +} + +static void +remove_server_watch (DBusWatch *watch, + void *data) +{ + ServerData *context = data; + + _dbus_loop_remove_watch (context->loop, + watch, server_watch_callback, context); +} + +static void +server_timeout_callback (DBusTimeout *timeout, + void *data) +{ + /* can return FALSE on OOM but we just let it fire again later */ + dbus_timeout_handle (timeout); +} + +static dbus_bool_t +add_server_timeout (DBusTimeout *timeout, + void *data) +{ + ServerData *context = data; + + return _dbus_loop_add_timeout (context->loop, + timeout, server_timeout_callback, context, NULL); +} + +static void +remove_server_timeout (DBusTimeout *timeout, + void *data) +{ + ServerData *context = data; + + _dbus_loop_remove_timeout (context->loop, + timeout, server_timeout_callback, context); +} + +dbus_bool_t +test_server_setup (DBusLoop *loop, + DBusServer *server) +{ + ServerData *sd; + + sd = serverdata_new (loop, server); + if (sd == NULL) + goto nomem; + + if (!dbus_server_set_watch_functions (server, + add_server_watch, + remove_server_watch, + NULL, + sd, + serverdata_free)) + { + return FALSE; + } + + if (!dbus_server_set_timeout_functions (server, + add_server_timeout, + remove_server_timeout, + NULL, + sd, serverdata_free)) + { + return FALSE; + } + return TRUE; + + nomem: + if (sd) + serverdata_free (sd); + + test_server_shutdown (loop, server); + + return FALSE; +} + +void +test_server_shutdown (DBusLoop *loop, + DBusServer *server) +{ + if (!dbus_server_set_watch_functions (server, + NULL, NULL, NULL, + NULL, + NULL)) + _dbus_assert_not_reached ("setting watch functions to NULL failed"); + + if (!dbus_server_set_timeout_functions (server, + NULL, NULL, NULL, + NULL, + NULL)) + _dbus_assert_not_reached ("setting timeout functions to NULL failed"); +} diff --git a/test/test-utils.h b/test/test-utils.h index f00a7181..90d87767 100644 --- a/test/test-utils.h +++ b/test/test-utils.h @@ -1,7 +1,9 @@ #ifndef TEST_UTILS_H #define TEST_UTILS_H #include <config.h> +#ifndef DBUS_COMPILATION #define DBUS_COMPILATION /* Cheat and use private stuff */ +#endif #include <dbus/dbus.h> #include <stdio.h> #include <stdlib.h> @@ -16,5 +18,9 @@ void test_connection_shutdown (DBusLoop *loop, void test_connection_dispatch_all_messages (DBusConnection *connection); dbus_bool_t test_connection_dispatch_one_message (DBusConnection *connection); +dbus_bool_t test_server_setup (DBusLoop *loop, + DBusServer *server); +void test_server_shutdown (DBusLoop *loop, + DBusServer *server); #endif |