diff options
Diffstat (limited to 'dbus')
-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 |
12 files changed, 232 insertions, 13 deletions
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 |