diff options
Diffstat (limited to 'meta-security')
17 files changed, 75 insertions, 6279 deletions
diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0001-Fix-memleak-in-GetConnectionCredentials-handler.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0001-Fix-memleak-in-GetConnectionCredentials-handler.patch deleted file mode 100644 index 271ac48a1..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0001-Fix-memleak-in-GetConnectionCredentials-handler.patch +++ /dev/null @@ -1,32 +0,0 @@ -From eacdc525a1f7bfc534e248a5a946c08b6f4aab35 Mon Sep 17 00:00:00 2001 -From: Jacek Bukarewicz <j.bukarewicz@samsung.com> -Date: Wed, 17 Jun 2015 18:53:41 +0100 -Subject: [PATCH 1/8] Fix memleak in GetConnectionCredentials handler - -Reply message was not unreferenced when GetConnectionCredentials -handler was successful. - -Signed-off-by: Jacek Bukarewicz <j.bukarewicz@samsung.com> -[smcv: changed bus_message_unref() to dbus_message_unref()] -Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> -Bug: https://bugs.freedesktop.org/show_bug.cgi?id=91008 ---- - bus/driver.c | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/bus/driver.c b/bus/driver.c -index f5d3ebe..888c7ca 100644 ---- a/bus/driver.c -+++ b/bus/driver.c -@@ -1613,6 +1613,8 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, - goto oom; - } - -+ dbus_message_unref (reply); -+ - return TRUE; - - oom: --- -2.1.4 - diff --git a/meta-security/recipes-core/dbus-cynara/dbus/0001-Integration-of-Cynara-asynchronous-security-checks.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0001-Integration-of-Cynara-asynchronous-security-checks.patch index 6a7e8a39d..6a7e8a39d 100644 --- a/meta-security/recipes-core/dbus-cynara/dbus/0001-Integration-of-Cynara-asynchronous-security-checks.patch +++ b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0001-Integration-of-Cynara-asynchronous-security-checks.patch diff --git a/meta-security/recipes-core/dbus-cynara/dbus/0002-Disable-message-dispatching-when-send-rule-result-is.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0002-Disable-message-dispatching-when-send-rule-result-is.patch index b1c3f3fdc..b1c3f3fdc 100644 --- a/meta-security/recipes-core/dbus-cynara/dbus/0002-Disable-message-dispatching-when-send-rule-result-is.patch +++ b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0002-Disable-message-dispatching-when-send-rule-result-is.patch diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0002-New-a-sv-helper-for-using-byte-arrays-as-the-variant.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0002-New-a-sv-helper-for-using-byte-arrays-as-the-variant.patch deleted file mode 100644 index 64c8b9b50..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0002-New-a-sv-helper-for-using-byte-arrays-as-the-variant.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 25cb15916402c55112cae2be0954d24afe74e2f2 Mon Sep 17 00:00:00 2001 -From: Tyler Hicks <tyhicks@canonical.com> -Date: Thu, 13 Mar 2014 17:37:38 -0500 -Subject: [PATCH 2/8] New a{sv} helper for using byte arrays as the variant - -Create a new helper for using a byte array as the value in the mapping -from string to variant. - -Bug: https://bugs.freedesktop.org/show_bug.cgi?id=75113 -Bug: https://bugs.freedesktop.org/show_bug.cgi?id=89041 -Signed-off-by: Tyler Hicks <tyhicks@canonical.com> -Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> -Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk> ---- - dbus/dbus-asv-util.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ - dbus/dbus-asv-util.h | 4 ++++ - 2 files changed, 58 insertions(+) - -diff --git a/dbus/dbus-asv-util.c b/dbus/dbus-asv-util.c -index 583e41f..d3ac5e9 100644 ---- a/dbus/dbus-asv-util.c -+++ b/dbus/dbus-asv-util.c -@@ -258,3 +258,57 @@ _dbus_asv_add_string (DBusMessageIter *arr_iter, - - return TRUE; - } -+ -+/** -+ * Create a new entry in an a{sv} (map from string to variant) -+ * with a byte array value. -+ * -+ * If this function fails, the a{sv} must be abandoned, for instance -+ * with _dbus_asv_abandon(). -+ * -+ * @param arr_iter the iterator which is appending to the array -+ * @param key a UTF-8 key for the map -+ * @param value the value -+ * @param n_elements the number of elements to append -+ * @returns #TRUE on success, or #FALSE if not enough memory -+ */ -+dbus_bool_t -+_dbus_asv_add_byte_array (DBusMessageIter *arr_iter, -+ const char *key, -+ const void *value, -+ int n_elements) -+{ -+ DBusMessageIter entry_iter; -+ DBusMessageIter var_iter; -+ DBusMessageIter byte_array_iter; -+ -+ if (!_dbus_asv_open_entry (arr_iter, &entry_iter, key, "ay", &var_iter)) -+ return FALSE; -+ -+ if (!dbus_message_iter_open_container (&var_iter, DBUS_TYPE_ARRAY, -+ DBUS_TYPE_BYTE_AS_STRING, -+ &byte_array_iter)) -+ { -+ _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter); -+ return FALSE; -+ } -+ -+ if (!dbus_message_iter_append_fixed_array (&byte_array_iter, DBUS_TYPE_BYTE, -+ &value, n_elements)) -+ { -+ dbus_message_iter_abandon_container (&var_iter, &byte_array_iter); -+ _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter); -+ return FALSE; -+ } -+ -+ if (!dbus_message_iter_close_container (&var_iter, &byte_array_iter)) -+ { -+ _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter); -+ return FALSE; -+ } -+ -+ if (!_dbus_asv_close_entry (arr_iter, &entry_iter, &var_iter)) -+ return FALSE; -+ -+ return TRUE; -+} -diff --git a/dbus/dbus-asv-util.h b/dbus/dbus-asv-util.h -index 0337260..277ab80 100644 ---- a/dbus/dbus-asv-util.h -+++ b/dbus/dbus-asv-util.h -@@ -42,5 +42,9 @@ dbus_bool_t _dbus_asv_add_uint32 (DBusMessageIter *arr_iter, - dbus_bool_t _dbus_asv_add_string (DBusMessageIter *arr_iter, - const char *key, - const char *value); -+dbus_bool_t _dbus_asv_add_byte_array (DBusMessageIter *arr_iter, -+ const char *key, -+ const void *value, -+ int n_elements); - - #endif --- -2.1.4 - diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch deleted file mode 100644 index fcb85504d..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch +++ /dev/null @@ -1,515 +0,0 @@ -From 9da49d4eb6982c659fec988231baef8cd1b05be2 Mon Sep 17 00:00:00 2001 -From: Simon McVittie <simon.mcvittie@collabora.co.uk> -Date: Wed, 11 Feb 2015 13:19:15 +0000 -Subject: [PATCH 3/8] Add LSM-agnostic support for LinuxSecurityLabel - credential - -Bug: https://bugs.freedesktop.org/show_bug.cgi?id=89041 -Change-Id: I70512843d1a7661c87461b1b6d86fbfbda934ad5 -Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk> -Acked-by: Stephen Smalley <sds@tycho.nsa.gov> (for SELinux) -Acked-by: John Johansen <john.johansen@canonical.com> (for AppArmor) -Acked-by: Casey Schaufler <casey@schaufler-ca.com> (for Smack) -Tested-by: Tyler Hicks <tyhicks@canonical.com> ---- - bus/driver.c | 19 ++++++++ - dbus/dbus-auth.c | 11 +++-- - dbus/dbus-connection-internal.h | 3 ++ - dbus/dbus-connection.c | 26 ++++++++++ - dbus/dbus-credentials.c | 68 ++++++++++++++++++++++++++ - dbus/dbus-credentials.h | 4 ++ - dbus/dbus-sysdeps-unix.c | 105 ++++++++++++++++++++++++++++++++++++++++ - dbus/dbus-transport.c | 27 +++++++++++ - dbus/dbus-transport.h | 3 ++ - 9 files changed, 262 insertions(+), 4 deletions(-) - -diff --git a/bus/driver.c b/bus/driver.c -index 888c7ca..11706f8 100644 ---- a/bus/driver.c -+++ b/bus/driver.c -@@ -34,6 +34,7 @@ - #include "utils.h" - - #include <dbus/dbus-asv-util.h> -+#include <dbus/dbus-connection-internal.h> - #include <dbus/dbus-string.h> - #include <dbus/dbus-internals.h> - #include <dbus/dbus-message.h> -@@ -1567,6 +1568,7 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, - DBusMessageIter reply_iter; - DBusMessageIter array_iter; - unsigned long ulong_val; -+ char *s; - const char *service; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); -@@ -1601,6 +1603,23 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, - goto oom; - } - -+ if (_dbus_connection_get_linux_security_label (conn, &s)) -+ { -+ if (s == NULL) -+ goto oom; -+ -+ /* use the GVariant bytestring convention for strings of unknown -+ * encoding: include the \0 in the payload, for zero-copy reading */ -+ if (!_dbus_asv_add_byte_array (&array_iter, "LinuxSecurityLabel", -+ s, strlen (s) + 1)) -+ { -+ dbus_free (s); -+ goto oom; -+ } -+ -+ dbus_free (s); -+ } -+ - if (!_dbus_asv_close (&reply_iter, &array_iter)) - goto oom; - -diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c -index 6a07665..aee877d 100644 ---- a/dbus/dbus-auth.c -+++ b/dbus/dbus-auth.c -@@ -1102,20 +1102,23 @@ handle_server_data_external_mech (DBusAuth *auth, - auth->desired_identity)) - return FALSE; - -- /* also copy process ID from the socket credentials -+ /* also copy misc process info from the socket credentials - */ - if (!_dbus_credentials_add_credential (auth->authorized_identity, - 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 (!_dbus_credentials_add_credential (auth->authorized_identity, -+ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL, -+ auth->credentials)) -+ return FALSE; -+ - if (!send_ok (auth)) - return FALSE; - -diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h -index 2897404..64ef336 100644 ---- a/dbus/dbus-connection-internal.h -+++ b/dbus/dbus-connection-internal.h -@@ -107,6 +107,9 @@ void _dbus_connection_set_pending_fds_function (DBusConnectio - DBusPendingFdsChangeFunction callback, - void *data); - -+dbus_bool_t _dbus_connection_get_linux_security_label (DBusConnection *connection, -+ char **label_p); -+ - /* if DBUS_ENABLE_STATS */ - void _dbus_connection_get_stats (DBusConnection *connection, - dbus_uint32_t *in_messages, -diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c -index b574207..8952b75 100644 ---- a/dbus/dbus-connection.c -+++ b/dbus/dbus-connection.c -@@ -5322,6 +5322,32 @@ dbus_connection_set_unix_user_function (DBusConnection *connection, - (* old_free_function) (old_data); - } - -+/* Same calling convention as dbus_connection_get_windows_user */ -+dbus_bool_t -+_dbus_connection_get_linux_security_label (DBusConnection *connection, -+ char **label_p) -+{ -+ dbus_bool_t result; -+ -+ _dbus_assert (connection != NULL); -+ _dbus_assert (label_p != NULL); -+ -+ CONNECTION_LOCK (connection); -+ -+ if (!_dbus_transport_try_to_authenticate (connection->transport)) -+ result = FALSE; -+ else -+ result = _dbus_transport_get_linux_security_label (connection->transport, -+ label_p); -+#ifndef __linux__ -+ _dbus_assert (!result); -+#endif -+ -+ CONNECTION_UNLOCK (connection); -+ -+ return result; -+} -+ - /** - * Gets the Windows user SID of the connection if known. Returns - * #TRUE if the ID is filled in. Always returns #FALSE on non-Windows -diff --git a/dbus/dbus-credentials.c b/dbus/dbus-credentials.c -index 7325125..151bb00 100644 ---- a/dbus/dbus-credentials.c -+++ b/dbus/dbus-credentials.c -@@ -50,6 +50,7 @@ struct DBusCredentials { - dbus_uid_t unix_uid; - dbus_pid_t pid; - char *windows_sid; -+ char *linux_security_label; - void *adt_audit_data; - dbus_int32_t adt_audit_data_size; - }; -@@ -79,6 +80,7 @@ _dbus_credentials_new (void) - creds->unix_uid = DBUS_UID_UNSET; - creds->pid = DBUS_PID_UNSET; - creds->windows_sid = NULL; -+ creds->linux_security_label = NULL; - creds->adt_audit_data = NULL; - creds->adt_audit_data_size = 0; - -@@ -133,6 +135,7 @@ _dbus_credentials_unref (DBusCredentials *credentials) - if (credentials->refcount == 0) - { - dbus_free (credentials->windows_sid); -+ dbus_free (credentials->linux_security_label); - dbus_free (credentials->adt_audit_data); - dbus_free (credentials); - } -@@ -193,6 +196,30 @@ _dbus_credentials_add_windows_sid (DBusCredentials *credentials, - } - - /** -+ * Add a Linux security label, as used by LSMs such as SELinux, Smack and -+ * AppArmor, to the credentials. -+ * -+ * @param credentials the object -+ * @param label the label -+ * @returns #FALSE if no memory -+ */ -+dbus_bool_t -+_dbus_credentials_add_linux_security_label (DBusCredentials *credentials, -+ const char *label) -+{ -+ char *copy; -+ -+ copy = _dbus_strdup (label); -+ if (copy == NULL) -+ return FALSE; -+ -+ dbus_free (credentials->linux_security_label); -+ credentials->linux_security_label = copy; -+ -+ return TRUE; -+} -+ -+/** - * Add ADT audit data to the credentials. - * - * @param credentials the object -@@ -236,6 +263,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_LINUX_SECURITY_LABEL: -+ return credentials->linux_security_label != NULL; - case DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID: - return credentials->adt_audit_data != NULL; - } -@@ -284,6 +313,19 @@ _dbus_credentials_get_windows_sid (DBusCredentials *credentials) - } - - /** -+ * Gets the Linux security label (as used by LSMs) from the credentials, -+ * or #NULL if the credentials object doesn't contain a security label. -+ * -+ * @param credentials the object -+ * @returns the security label -+ */ -+const char * -+_dbus_credentials_get_linux_security_label (DBusCredentials *credentials) -+{ -+ return credentials->linux_security_label; -+} -+ -+/** - * Gets the ADT audit data in the credentials, or #NULL if - * the credentials object doesn't contain ADT audit data. - * -@@ -329,6 +371,10 @@ _dbus_credentials_are_superset (DBusCredentials *credentials, - (possible_subset->windows_sid == NULL || - (credentials->windows_sid && strcmp (possible_subset->windows_sid, - credentials->windows_sid) == 0)) && -+ (possible_subset->linux_security_label == NULL || -+ (credentials->linux_security_label != NULL && -+ strcmp (possible_subset->linux_security_label, -+ credentials->linux_security_label) == 0)) && - (possible_subset->adt_audit_data == NULL || - (credentials->adt_audit_data && memcmp (possible_subset->adt_audit_data, - credentials->adt_audit_data, -@@ -348,6 +394,7 @@ _dbus_credentials_are_empty (DBusCredentials *credentials) - credentials->pid == DBUS_PID_UNSET && - credentials->unix_uid == DBUS_UID_UNSET && - credentials->windows_sid == NULL && -+ credentials->linux_security_label == NULL && - credentials->adt_audit_data == NULL; - } - -@@ -388,6 +435,9 @@ _dbus_credentials_add_credentials (DBusCredentials *credentials, - DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, - other_credentials) && - _dbus_credentials_add_credential (credentials, -+ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL, -+ other_credentials) && -+ _dbus_credentials_add_credential (credentials, - DBUS_CREDENTIAL_WINDOWS_SID, - other_credentials); - } -@@ -427,6 +477,13 @@ _dbus_credentials_add_credential (DBusCredentials *credentials, - if (!_dbus_credentials_add_windows_sid (credentials, other_credentials->windows_sid)) - return FALSE; - } -+ else if (which == DBUS_CREDENTIAL_LINUX_SECURITY_LABEL && -+ other_credentials->linux_security_label != NULL) -+ { -+ if (!_dbus_credentials_add_linux_security_label (credentials, -+ other_credentials->linux_security_label)) -+ return FALSE; -+ } - else if (which == DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID && - other_credentials->adt_audit_data != NULL) - { -@@ -449,6 +506,8 @@ _dbus_credentials_clear (DBusCredentials *credentials) - credentials->unix_uid = DBUS_UID_UNSET; - dbus_free (credentials->windows_sid); - credentials->windows_sid = NULL; -+ dbus_free (credentials->linux_security_label); -+ credentials->linux_security_label = NULL; - dbus_free (credentials->adt_audit_data); - credentials->adt_audit_data = NULL; - credentials->adt_audit_data_size = 0; -@@ -540,6 +599,15 @@ _dbus_credentials_to_string_append (DBusCredentials *credentials, - else - join = FALSE; - -+ if (credentials->linux_security_label != NULL) -+ { -+ if (!_dbus_string_append_printf (string, "%slsm='%s'", -+ join ? " " : "", -+ credentials->linux_security_label)) -+ goto oom; -+ join = TRUE; -+ } -+ - return TRUE; - oom: - return FALSE; -diff --git a/dbus/dbus-credentials.h b/dbus/dbus-credentials.h -index abcc4bb..ab74eac 100644 ---- a/dbus/dbus-credentials.h -+++ b/dbus/dbus-credentials.h -@@ -34,6 +34,7 @@ typedef enum { - DBUS_CREDENTIAL_UNIX_PROCESS_ID, - DBUS_CREDENTIAL_UNIX_USER_ID, - DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, -+ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL, - DBUS_CREDENTIAL_WINDOWS_SID - } DBusCredentialType; - -@@ -47,6 +48,8 @@ dbus_bool_t _dbus_credentials_add_unix_uid (DBusCredentials - dbus_uid_t uid); - dbus_bool_t _dbus_credentials_add_windows_sid (DBusCredentials *credentials, - const char *windows_sid); -+dbus_bool_t _dbus_credentials_add_linux_security_label (DBusCredentials *credentials, -+ const char *label); - dbus_bool_t _dbus_credentials_add_adt_audit_data (DBusCredentials *credentials, - void *audit_data, - dbus_int32_t size); -@@ -55,6 +58,7 @@ dbus_bool_t _dbus_credentials_include (DBusCredentials - dbus_pid_t _dbus_credentials_get_pid (DBusCredentials *credentials); - dbus_uid_t _dbus_credentials_get_unix_uid (DBusCredentials *credentials); - const char* _dbus_credentials_get_windows_sid (DBusCredentials *credentials); -+const char * _dbus_credentials_get_linux_security_label (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, -diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c -index fe891ab..61af423 100644 ---- a/dbus/dbus-sysdeps-unix.c -+++ b/dbus/dbus-sysdeps-unix.c -@@ -1639,6 +1639,105 @@ write_credentials_byte (int server_fd, - } - } - -+/* return FALSE on OOM, TRUE otherwise, even if no credentials were found */ -+static dbus_bool_t -+add_linux_security_label_to_credentials (int client_fd, -+ DBusCredentials *credentials) -+{ -+#if defined(__linux__) && defined(SO_PEERSEC) -+ DBusString buf; -+ socklen_t len = 1024; -+ dbus_bool_t oom = FALSE; -+ -+ if (!_dbus_string_init_preallocated (&buf, len) || -+ !_dbus_string_set_length (&buf, len)) -+ return FALSE; -+ -+ while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC, -+ _dbus_string_get_data (&buf), &len) < 0) -+ { -+ int e = errno; -+ -+ _dbus_verbose ("getsockopt failed with %s, len now %lu\n", -+ _dbus_strerror (e), (unsigned long) len); -+ -+ if (e != ERANGE || len <= _dbus_string_get_length (&buf)) -+ { -+ _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n", -+ _dbus_strerror (e)); -+ goto out; -+ } -+ -+ /* If not enough space, len is updated to be enough. -+ * Try again with a large enough buffer. */ -+ if (!_dbus_string_set_length (&buf, len)) -+ { -+ oom = TRUE; -+ goto out; -+ } -+ -+ _dbus_verbose ("will try again with %lu\n", (unsigned long) len); -+ } -+ -+ if (len <= 0) -+ { -+ _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n", -+ (unsigned long) len); -+ goto out; -+ } -+ -+ if (len > _dbus_string_get_length (&buf)) -+ { -+ _dbus_verbose ("%lu > %d", (unsigned long) len, -+ _dbus_string_get_length (&buf)); -+ _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed"); -+ } -+ -+ if (_dbus_string_get_byte (&buf, len - 1) == 0) -+ { -+ /* the kernel included the trailing \0 in its count, -+ * but DBusString always has an extra \0 after the data anyway */ -+ _dbus_verbose ("subtracting trailing \\0\n"); -+ len--; -+ } -+ -+ if (!_dbus_string_set_length (&buf, len)) -+ { -+ _dbus_assert_not_reached ("shortening string should not lead to OOM"); -+ oom = TRUE; -+ goto out; -+ } -+ -+ if (strlen (_dbus_string_get_const_data (&buf)) != len) -+ { -+ /* LSM people on the linux-security-module@ mailing list say this -+ * should never happen: the label should be a bytestring with -+ * an optional trailing \0 */ -+ _dbus_verbose ("security label from kernel had an embedded \\0, " -+ "ignoring it\n"); -+ goto out; -+ } -+ -+ _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n", -+ (unsigned long) len, -+ _dbus_string_get_const_data (&buf)); -+ -+ if (!_dbus_credentials_add_linux_security_label (credentials, -+ _dbus_string_get_const_data (&buf))) -+ { -+ oom = TRUE; -+ goto out; -+ } -+ -+out: -+ _dbus_string_free (&buf); -+ return !oom; -+#else -+ /* no error */ -+ return TRUE; -+#endif -+} -+ - /** - * Reads a single byte which must be nul (an error occurs otherwise), - * and reads unix credentials if available. Clears the credentials -@@ -1922,6 +2021,12 @@ _dbus_read_credentials_socket (int client_fd, - } - } - -+ if (!add_linux_security_label_to_credentials (client_fd, credentials)) -+ { -+ _DBUS_SET_OOM (error); -+ return FALSE; -+ } -+ - return TRUE; - } - -diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c -index e9dcc56..a43e7bb 100644 ---- a/dbus/dbus-transport.c -+++ b/dbus/dbus-transport.c -@@ -1425,6 +1425,33 @@ _dbus_transport_set_unix_user_function (DBusTransport *transport, - transport->free_unix_user_data = free_data_function; - } - -+dbus_bool_t -+_dbus_transport_get_linux_security_label (DBusTransport *transport, -+ char **label_p) -+{ -+ DBusCredentials *auth_identity; -+ -+ *label_p = NULL; -+ -+ if (!transport->authenticated) -+ return FALSE; -+ -+ auth_identity = _dbus_auth_get_identity (transport->auth); -+ -+ if (_dbus_credentials_include (auth_identity, -+ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL)) -+ { -+ /* If no memory, we are supposed to return TRUE and set NULL */ -+ *label_p = _dbus_strdup (_dbus_credentials_get_linux_security_label (auth_identity)); -+ -+ return TRUE; -+ } -+ else -+ { -+ return FALSE; -+ } -+} -+ - /** - * See dbus_connection_get_windows_user(). - * -diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h -index 39c74c4..843f231 100644 ---- a/dbus/dbus-transport.h -+++ b/dbus/dbus-transport.h -@@ -87,6 +87,9 @@ void _dbus_transport_set_unix_user_function (DBusTransport - DBusFreeFunction *old_free_data_function); - dbus_bool_t _dbus_transport_get_windows_user (DBusTransport *transport, - char **windows_sid_p); -+dbus_bool_t _dbus_transport_get_linux_security_label (DBusTransport *transport, -+ char **label_p); -+ - void _dbus_transport_set_windows_user_function (DBusTransport *transport, - DBusAllowWindowsUserFunction function, - void *data, --- -2.1.4 - diff --git a/meta-security/recipes-core/dbus-cynara/dbus/0003-Handle-unavailability-of-policy-results-for-broadcas.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Handle-unavailability-of-policy-results-for-broadcas.patch index b797064ec..b797064ec 100644 --- a/meta-security/recipes-core/dbus-cynara/dbus/0003-Handle-unavailability-of-policy-results-for-broadcas.patch +++ b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0003-Handle-unavailability-of-policy-results-for-broadcas.patch diff --git a/meta-security/recipes-core/dbus-cynara/dbus/0004-Add-own-rule-result-unavailability-handling.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0004-Add-own-rule-result-unavailability-handling.patch index 1086f5b12..1086f5b12 100644 --- a/meta-security/recipes-core/dbus-cynara/dbus/0004-Add-own-rule-result-unavailability-handling.patch +++ b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0004-Add-own-rule-result-unavailability-handling.patch diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0004-Integration-of-Cynara-asynchronous-security-checks.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0004-Integration-of-Cynara-asynchronous-security-checks.patch deleted file mode 100644 index 70d5fc9d7..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0004-Integration-of-Cynara-asynchronous-security-checks.patch +++ /dev/null @@ -1,2253 +0,0 @@ -From 4dcfb02f17247ff9de966b62182cd2e08f301238 Mon Sep 17 00:00:00 2001 -From: Jacek Bukarewicz <j.bukarewicz@samsung.com> -Date: Thu, 27 Nov 2014 18:11:05 +0100 -Subject: [PATCH 4/8] Integration of Cynara asynchronous security checks - -This commit introduces basic framework for asynchronous policy -checks and Cynara integration code. Functions for checking security -policy can now return third value - BUS_RESULT_LATER denoting check -result unavailability. Whenever policy checker cannot decide on the -result of the check it is supposed to allocate DeferredMessage structure -that will be passed to the upper layers which can decide what should be -done in such situation. -Proper handling of such case will be implemented in subsequent commits. -Currently such return value results in message denial. - -Change-Id: I9bcbce34577e5dc2a3cecf6233a0a2b0e43e1108 ---- - bus/Makefile.am | 6 + - bus/bus.c | 134 +++++--- - bus/bus.h | 58 ++-- - bus/check.c | 215 ++++++++++++ - bus/check.h | 68 ++++ - bus/config-parser-common.c | 6 + - bus/config-parser-common.h | 1 + - bus/config-parser.c | 71 +++- - bus/connection.c | 56 ++- - bus/connection.h | 5 + - bus/cynara.c | 374 +++++++++++++++++++++ - bus/cynara.h | 37 ++ - bus/dispatch.c | 51 ++- - bus/policy.c | 193 +++++++---- - bus/policy.h | 51 ++- - configure.ac | 13 + - test/Makefile.am | 1 + - test/data/invalid-config-files/badcheck-1.conf | 9 + - test/data/invalid-config-files/badcheck-2.conf | 9 + - test/data/valid-config-files/check-1.conf | 9 + - .../valid-config-files/debug-check-some.conf.in | 18 + - 22 files changed, 1211 insertions(+), 180 deletions(-) - create mode 100644 bus/check.c - create mode 100644 bus/check.h - create mode 100644 bus/cynara.c - create mode 100644 bus/cynara.h - create mode 100644 test/data/invalid-config-files/badcheck-1.conf - create mode 100644 test/data/invalid-config-files/badcheck-2.conf - create mode 100644 test/data/valid-config-files/check-1.conf - create mode 100644 test/data/valid-config-files/debug-check-some.conf.in - -diff --git a/bus/Makefile.am b/bus/Makefile.am -index f335e30..b057d6b 100644 ---- a/bus/Makefile.am -+++ b/bus/Makefile.am -@@ -7,6 +7,7 @@ DBUS_BUS_LIBS = \ - $(THREAD_LIBS) \ - $(ADT_LIBS) \ - $(NETWORK_libs) \ -+ $(CYNARA_LIBS) \ - $(NULL) - - DBUS_LAUNCHER_LIBS = \ -@@ -21,6 +22,7 @@ AM_CPPFLAGS = \ - -DDBUS_SYSTEM_CONFIG_FILE=\""$(configdir)/system.conf"\" \ - -DDBUS_COMPILATION \ - -DDBUS_STATIC_BUILD \ -+ $(CYNARA_CFLAGS) \ - $(NULL) - - # if assertions are enabled, improve backtraces -@@ -60,12 +62,16 @@ BUS_SOURCES= \ - activation-exit-codes.h \ - bus.c \ - bus.h \ -+ check.c \ -+ check.h \ - config-parser.c \ - config-parser.h \ - config-parser-common.c \ - config-parser-common.h \ - connection.c \ - connection.h \ -+ cynara.c \ -+ cynara.h \ - desktop-file.c \ - desktop-file.h \ - $(DIR_WATCH_SOURCE) \ -diff --git a/bus/bus.c b/bus/bus.c -index f0d980e..ac9ea8d 100644 ---- a/bus/bus.c -+++ b/bus/bus.c -@@ -35,6 +35,7 @@ - #include "signals.h" - #include "selinux.h" - #include "dir-watch.h" -+#include "check.h" - #include <dbus/dbus-list.h> - #include <dbus/dbus-hash.h> - #include <dbus/dbus-credentials.h> -@@ -63,6 +64,7 @@ struct BusContext - BusRegistry *registry; - BusPolicy *policy; - BusMatchmaker *matchmaker; -+ BusCheck *check; - BusLimits limits; - DBusRLimit *initial_fd_limit; - unsigned int fork : 1; -@@ -962,6 +964,10 @@ bus_context_new (const DBusString *config_file, - #endif - } - -+ context->check = bus_check_new(context, error); -+ if (context->check == NULL) -+ goto failed; -+ - dbus_server_free_data_slot (&server_data_slot); - - return context; -@@ -1086,6 +1092,12 @@ bus_context_unref (BusContext *context) - - bus_context_shutdown (context); - -+ if (context->check) -+ { -+ bus_check_unref(context->check); -+ context->check = NULL; -+ } -+ - if (context->connections) - { - bus_connections_unref (context->connections); -@@ -1215,6 +1227,12 @@ bus_context_get_loop (BusContext *context) - return context->loop; - } - -+BusCheck* -+bus_context_get_check (BusContext *context) -+{ -+ return context->check; -+} -+ - dbus_bool_t - bus_context_allow_unix_user (BusContext *context, - unsigned long uid) -@@ -1386,6 +1404,7 @@ complain_about_message (BusContext *context, - DBusConnection *proposed_recipient, - dbus_bool_t requested_reply, - dbus_bool_t log, -+ const char *privilege, - DBusError *error) - { - DBusError stack_error = DBUS_ERROR_INIT; -@@ -1415,7 +1434,8 @@ complain_about_message (BusContext *context, - dbus_set_error (&stack_error, error_name, - "%s, %d matched rules; type=\"%s\", sender=\"%s\" (%s) " - "interface=\"%s\" member=\"%s\" error name=\"%s\" " -- "requested_reply=\"%d\" destination=\"%s\" (%s)", -+ "requested_reply=\"%d\" destination=\"%s\" (%s) " -+ "privilege=\"%s\"", - complaint, - matched_rules, - dbus_message_type_to_string (dbus_message_get_type (message)), -@@ -1426,7 +1446,8 @@ complain_about_message (BusContext *context, - nonnull (dbus_message_get_error_name (message), "(unset)"), - requested_reply, - nonnull (dbus_message_get_destination (message), DBUS_SERVICE_DBUS), -- proposed_recipient_loginfo); -+ proposed_recipient_loginfo, -+ nonnull (privilege, "(n/a)")); - - /* If we hit OOM while setting the error, this will syslog "out of memory" - * which is itself an indication that something is seriously wrong */ -@@ -1450,14 +1471,15 @@ complain_about_message (BusContext *context, - * NULL for addressed_recipient may mean the bus driver, or may mean - * no destination was specified in the message (e.g. a signal). - */ --dbus_bool_t --bus_context_check_security_policy (BusContext *context, -- BusTransaction *transaction, -- DBusConnection *sender, -- DBusConnection *addressed_recipient, -- DBusConnection *proposed_recipient, -- DBusMessage *message, -- DBusError *error) -+BusResult -+bus_context_check_security_policy (BusContext *context, -+ BusTransaction *transaction, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ DBusMessage *message, -+ DBusError *error, -+ BusDeferredMessage **deferred_message) - { - const char *dest; - BusClientPolicy *sender_policy; -@@ -1466,6 +1488,7 @@ bus_context_check_security_policy (BusContext *context, - dbus_bool_t log; - int type; - dbus_bool_t requested_reply; -+ const char *privilege; - - type = dbus_message_get_type (message); - dest = dbus_message_get_destination (message); -@@ -1493,7 +1516,7 @@ bus_context_check_security_policy (BusContext *context, - dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, - "Message bus will not accept messages of unknown type\n"); - -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - requested_reply = FALSE; -@@ -1517,11 +1540,11 @@ bus_context_check_security_policy (BusContext *context, - complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, - "An SELinux policy prevents this sender from sending this " - "message to this recipient", -- 0, message, sender, proposed_recipient, FALSE, FALSE, error); -+ 0, message, sender, proposed_recipient, FALSE, FALSE, NULL, error); - _dbus_verbose ("SELinux security check denying send to service\n"); - } - -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - if (bus_connection_is_active (sender)) -@@ -1547,7 +1570,7 @@ bus_context_check_security_policy (BusContext *context, - if (dbus_error_is_set (&error2)) - { - dbus_move_error (&error2, error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - } - } -@@ -1564,7 +1587,7 @@ bus_context_check_security_policy (BusContext *context, - { - _dbus_verbose ("security check allowing %s message\n", - "Hello"); -- return TRUE; -+ return BUS_RESULT_TRUE; - } - else - { -@@ -1575,7 +1598,7 @@ bus_context_check_security_policy (BusContext *context, - "Client tried to send a message other than %s without being registered", - "Hello"); - -- return FALSE; -+ return BUS_RESULT_FALSE; - } - } - } -@@ -1624,20 +1647,29 @@ bus_context_check_security_policy (BusContext *context, - (proposed_recipient == NULL && recipient_policy == NULL)); - - log = FALSE; -- if (sender_policy && -- !bus_client_policy_check_can_send (sender_policy, -- context->registry, -- requested_reply, -- proposed_recipient, -- message, &toggles, &log)) -- { -- complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, -- "Rejected send message", toggles, -- message, sender, proposed_recipient, requested_reply, -- (addressed_recipient == proposed_recipient), error); -- _dbus_verbose ("security policy disallowing message due to sender policy\n"); -- return FALSE; -- } -+ if (sender_policy) -+ { -+ BusResult res = bus_client_policy_check_can_send (sender, -+ sender_policy, -+ context->registry, -+ requested_reply, -+ addressed_recipient, -+ proposed_recipient, -+ message, &toggles, &log, &privilege, -+ deferred_message); -+ if (res == BUS_RESULT_FALSE) -+ { -+ complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, -+ "Rejected send message", toggles, -+ message, sender, proposed_recipient, requested_reply, -+ (addressed_recipient == proposed_recipient), privilege, -+ error); -+ _dbus_verbose ("security policy disallowing message due to sender policy\n"); -+ return BUS_RESULT_FALSE; -+ } -+ else if (res == BUS_RESULT_LATER) -+ return BUS_RESULT_LATER; -+ } - - if (log) - { -@@ -1646,23 +1678,29 @@ bus_context_check_security_policy (BusContext *context, - complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, - "Would reject message", toggles, - message, sender, proposed_recipient, requested_reply, -- TRUE, NULL); -+ TRUE, privilege, NULL); - } - -- if (recipient_policy && -- !bus_client_policy_check_can_receive (recipient_policy, -- context->registry, -- requested_reply, -- sender, -- addressed_recipient, proposed_recipient, -- message, &toggles)) -+ if (recipient_policy) - { -- complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, -- "Rejected receive message", toggles, -- message, sender, proposed_recipient, requested_reply, -- (addressed_recipient == proposed_recipient), error); -- _dbus_verbose ("security policy disallowing message due to recipient policy\n"); -- return FALSE; -+ BusResult res; -+ res = bus_client_policy_check_can_receive (recipient_policy, -+ context->registry, -+ requested_reply, -+ sender, -+ addressed_recipient, proposed_recipient, -+ message, &toggles, &privilege, deferred_message); -+ if (res == BUS_RESULT_FALSE) -+ { -+ complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected receive message", -+ toggles, message, sender, proposed_recipient, requested_reply, -+ (addressed_recipient == proposed_recipient), privilege, error); -+ _dbus_verbose( -+ "security policy disallowing message due to recipient policy\n"); -+ return BUS_RESULT_FALSE; -+ } -+ else if (res == BUS_RESULT_LATER) -+ return BUS_RESULT_LATER; - } - - /* See if limits on size have been exceeded */ -@@ -1672,10 +1710,10 @@ bus_context_check_security_policy (BusContext *context, - { - complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED, - "Rejected: destination has a full message queue", -- 0, message, sender, proposed_recipient, requested_reply, TRUE, -+ 0, message, sender, proposed_recipient, requested_reply, TRUE, NULL, - error); - _dbus_verbose ("security policy disallowing message due to full message queue\n"); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - /* Record that we will allow a reply here in the future (don't -@@ -1692,11 +1730,11 @@ bus_context_check_security_policy (BusContext *context, - message, error)) - { - _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n"); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - _dbus_verbose ("security policy allowing message\n"); -- return TRUE; -+ return BUS_RESULT_TRUE; - } - - void -diff --git a/bus/bus.h b/bus/bus.h -index dac6ea5..78084dd 100644 ---- a/bus/bus.h -+++ b/bus/bus.h -@@ -30,19 +30,35 @@ - #include <dbus/dbus-pipe.h> - #include <dbus/dbus-sysdeps.h> - --typedef struct BusActivation BusActivation; --typedef struct BusConnections BusConnections; --typedef struct BusContext BusContext; --typedef struct BusPolicy BusPolicy; --typedef struct BusClientPolicy BusClientPolicy; --typedef struct BusPolicyRule BusPolicyRule; --typedef struct BusRegistry BusRegistry; --typedef struct BusSELinuxID BusSELinuxID; --typedef struct BusService BusService; --typedef struct BusOwner BusOwner; --typedef struct BusTransaction BusTransaction; --typedef struct BusMatchmaker BusMatchmaker; --typedef struct BusMatchRule BusMatchRule; -+typedef struct BusActivation BusActivation; -+typedef struct BusConnections BusConnections; -+typedef struct BusContext BusContext; -+typedef struct BusPolicy BusPolicy; -+typedef struct BusClientPolicy BusClientPolicy; -+typedef struct BusPolicyRule BusPolicyRule; -+typedef struct BusRegistry BusRegistry; -+typedef struct BusSELinuxID BusSELinuxID; -+typedef struct BusService BusService; -+typedef struct BusOwner BusOwner; -+typedef struct BusTransaction BusTransaction; -+typedef struct BusMatchmaker BusMatchmaker; -+typedef struct BusMatchRule BusMatchRule; -+typedef struct BusCheck BusCheck; -+typedef struct BusDeferredMessage BusDeferredMessage; -+typedef struct BusCynara BusCynara; -+ -+/** -+ * BusResult is defined as a pointer to a dummy structure to allow detection of type mismatches. -+ * The disadvantage of such solution is that now BusResult variables cannot be used in switch -+ * statement. -+ * Additionally, BUS_RESULT_TRUE is defined as 0 instead of 1 to help detect type mismatches -+ * at runtime. -+ */ -+typedef const struct BusResultStruct { int dummy; } *BusResult; -+ -+static const BusResult BUS_RESULT_TRUE = (BusResult)0x0; -+static const BusResult BUS_RESULT_FALSE = (BusResult)0x1; -+static const BusResult BUS_RESULT_LATER = (BusResult)0x2; - - typedef struct - { -@@ -96,6 +112,7 @@ BusConnections* bus_context_get_connections (BusContext - BusActivation* bus_context_get_activation (BusContext *context); - BusMatchmaker* bus_context_get_matchmaker (BusContext *context); - DBusLoop* bus_context_get_loop (BusContext *context); -+BusCheck * bus_context_get_check (BusContext *context); - dbus_bool_t bus_context_allow_unix_user (BusContext *context, - unsigned long uid); - dbus_bool_t bus_context_allow_windows_user (BusContext *context, -@@ -121,13 +138,14 @@ void bus_context_log (BusContext - DBusSystemLogSeverity severity, - const char *msg, - ...); --dbus_bool_t bus_context_check_security_policy (BusContext *context, -- BusTransaction *transaction, -- DBusConnection *sender, -- DBusConnection *addressed_recipient, -- DBusConnection *proposed_recipient, -- DBusMessage *message, -- DBusError *error); - void bus_context_check_all_watches (BusContext *context); -+BusResult bus_context_check_security_policy (BusContext *context, -+ BusTransaction *transaction, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ DBusMessage *message, -+ DBusError *error, -+ BusDeferredMessage **deferred_message); - - #endif /* BUS_BUS_H */ -diff --git a/bus/check.c b/bus/check.c -new file mode 100644 -index 0000000..d2f418a ---- /dev/null -+++ b/bus/check.c -@@ -0,0 +1,215 @@ -+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -+/* check.c Bus security policy runtime check -+ * -+ * Copyright (C) 2014 Intel, Inc. -+ * Copyright (c) 2014 Samsung Electronics, Ltd. -+ * -+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ */ -+ -+#include <config.h> -+#include "check.h" -+#include "connection.h" -+#include "dispatch.h" -+#include "cynara.h" -+#include "utils.h" -+#include <dbus/dbus-connection-internal.h> -+#include <dbus/dbus-message-internal.h> -+#include <dbus/dbus-internals.h> -+ -+ -+typedef struct BusCheck -+{ -+ int refcount; -+ -+ BusContext *context; -+ BusCynara *cynara; -+} BusCheck; -+ -+typedef struct BusDeferredMessage -+{ -+ int refcount; -+ -+ DBusMessage *message; -+ DBusConnection *sender; -+ DBusConnection *proposed_recipient; -+ DBusConnection *addressed_recipient; -+ dbus_bool_t full_dispatch; -+ BusDeferredMessageStatus status; -+ BusResult response; -+ BusCheckResponseFunc response_callback; -+} BusDeferredMessage; -+ -+BusCheck * -+bus_check_new (BusContext *context, DBusError *error) -+{ -+ BusCheck *check; -+ -+ check = dbus_new(BusCheck, 1); -+ if (check == NULL) -+ { -+ BUS_SET_OOM(error); -+ return NULL; -+ } -+ -+ check->refcount = 1; -+ check->context = context; -+ check->cynara = bus_cynara_new(check, error); -+ if (dbus_error_is_set(error)) -+ { -+ dbus_free(check); -+ return NULL; -+ } -+ -+ return check; -+} -+ -+BusCheck * -+bus_check_ref (BusCheck *check) -+{ -+ _dbus_assert (check->refcount > 0); -+ check->refcount += 1; -+ -+ return check; -+} -+ -+void -+bus_check_unref (BusCheck *check) -+{ -+ _dbus_assert (check->refcount > 0); -+ -+ check->refcount -= 1; -+ -+ if (check->refcount == 0) -+ { -+ bus_cynara_unref(check->cynara); -+ dbus_free(check); -+ } -+} -+ -+BusContext * -+bus_check_get_context (BusCheck *check) -+{ -+ return check->context; -+} -+ -+BusCynara * -+bus_check_get_cynara (BusCheck *check) -+{ -+ return check->cynara; -+} -+ -+BusResult -+bus_check_privilege (BusCheck *check, -+ DBusMessage *message, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ const char *privilege, -+ BusDeferredMessageStatus check_type, -+ BusDeferredMessage **deferred_message) -+{ -+ BusResult result = BUS_RESULT_FALSE; -+ BusCynara *cynara; -+ DBusConnection *connection; -+ -+ connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender; -+ -+ if (!dbus_connection_get_is_connected(connection)) -+ { -+ return BUS_RESULT_FALSE; -+ } -+ -+ /* ask policy checkers */ -+#ifdef DBUS_ENABLE_CYNARA -+ cynara = bus_check_get_cynara(check); -+ result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient, -+ proposed_recipient, privilege, check_type, deferred_message); -+#endif -+ -+ if (result == BUS_RESULT_LATER && deferred_message != NULL) -+ { -+ (*deferred_message)->status |= check_type; -+ } -+ return result; -+} -+ -+BusDeferredMessage *bus_deferred_message_new (DBusMessage *message, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ BusResult response) -+{ -+ BusDeferredMessage *deferred_message; -+ -+ deferred_message = dbus_new(BusDeferredMessage, 1); -+ if (deferred_message == NULL) -+ { -+ return NULL; -+ } -+ -+ deferred_message->refcount = 1; -+ deferred_message->sender = sender != NULL ? dbus_connection_ref(sender) : NULL; -+ deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL; -+ deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL; -+ deferred_message->message = dbus_message_ref(message); -+ deferred_message->response = response; -+ deferred_message->status = 0; -+ deferred_message->full_dispatch = FALSE; -+ deferred_message->response_callback = NULL; -+ -+ return deferred_message; -+} -+ -+BusDeferredMessage * -+bus_deferred_message_ref (BusDeferredMessage *deferred_message) -+{ -+ _dbus_assert (deferred_message->refcount > 0); -+ deferred_message->refcount += 1; -+ return deferred_message; -+} -+ -+void -+bus_deferred_message_unref (BusDeferredMessage *deferred_message) -+{ -+ _dbus_assert (deferred_message->refcount > 0); -+ -+ deferred_message->refcount -= 1; -+ -+ if (deferred_message->refcount == 0) -+ { -+ dbus_message_unref(deferred_message->message); -+ if (deferred_message->sender != NULL) -+ dbus_connection_unref(deferred_message->sender); -+ if (deferred_message->addressed_recipient != NULL) -+ dbus_connection_unref(deferred_message->addressed_recipient); -+ if (deferred_message->proposed_recipient != NULL) -+ dbus_connection_unref(deferred_message->proposed_recipient); -+ dbus_free(deferred_message); -+ } -+} -+ -+void -+bus_deferred_message_response_received (BusDeferredMessage *deferred_message, -+ BusResult result) -+{ -+ if (deferred_message->response_callback != NULL) -+ { -+ deferred_message->response_callback(deferred_message, result); -+ } -+} -diff --git a/bus/check.h b/bus/check.h -new file mode 100644 -index 0000000..c3fcaf9 ---- /dev/null -+++ b/bus/check.h -@@ -0,0 +1,68 @@ -+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -+/* check.h Bus security policy runtime check -+ * -+ * Copyright (C) 2014 Intel, Inc. -+ * Copyright (c) 2014 Samsung Electronics, Ltd. -+ * -+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ */ -+ -+#ifndef BUS_CHECK_H -+#define BUS_CHECK_H -+ -+#include "bus.h" -+#include "policy.h" -+ -+ -+typedef void (*BusCheckResponseFunc) (BusDeferredMessage *message, -+ BusResult result); -+ -+typedef enum { -+ BUS_DEFERRED_MESSAGE_CHECK_SEND = 1 << 0, -+ BUS_DEFERRED_MESSAGE_CHECK_RECEIVE = 1 << 1, -+ BUS_DEFERRED_MESSAGE_CHECK_OWN = 1 << 2, -+} BusDeferredMessageStatus; -+ -+ -+BusCheck *bus_check_new (BusContext *context, -+ DBusError *error); -+BusCheck *bus_check_ref (BusCheck *check); -+void bus_check_unref (BusCheck *check); -+ -+BusContext *bus_check_get_context (BusCheck *check); -+BusCynara *bus_check_get_cynara (BusCheck *check); -+BusResult bus_check_privilege (BusCheck *check, -+ DBusMessage *message, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ const char *privilege, -+ BusDeferredMessageStatus check_type, -+ BusDeferredMessage **deferred_message); -+ -+BusDeferredMessage *bus_deferred_message_new (DBusMessage *message, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ BusResult response); -+ -+BusDeferredMessage *bus_deferred_message_ref (BusDeferredMessage *deferred_message); -+void bus_deferred_message_unref (BusDeferredMessage *deferred_message); -+void bus_deferred_message_response_received (BusDeferredMessage *deferred_message, -+ BusResult result); -+#endif /* BUS_CHECK_H */ -diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c -index c522ff4..1cfe4c8 100644 ---- a/bus/config-parser-common.c -+++ b/bus/config-parser-common.c -@@ -75,6 +75,10 @@ bus_config_parser_element_name_to_type (const char *name) - { - return ELEMENT_DENY; - } -+ else if (strcmp (name, "check") == 0) -+ { -+ return ELEMENT_CHECK; -+ } - else if (strcmp (name, "servicehelper") == 0) - { - return ELEMENT_SERVICEHELPER; -@@ -155,6 +159,8 @@ bus_config_parser_element_type_to_name (ElementType type) - return "allow"; - case ELEMENT_DENY: - return "deny"; -+ case ELEMENT_CHECK: -+ return "check"; - case ELEMENT_FORK: - return "fork"; - case ELEMENT_PIDFILE: -diff --git a/bus/config-parser-common.h b/bus/config-parser-common.h -index 186bf4c..bff6fdb 100644 ---- a/bus/config-parser-common.h -+++ b/bus/config-parser-common.h -@@ -36,6 +36,7 @@ typedef enum - ELEMENT_LIMIT, - ELEMENT_ALLOW, - ELEMENT_DENY, -+ ELEMENT_CHECK, - ELEMENT_FORK, - ELEMENT_PIDFILE, - ELEMENT_SERVICEDIR, -diff --git a/bus/config-parser.c b/bus/config-parser.c -index ee2d4e7..73c9e6f 100644 ---- a/bus/config-parser.c -+++ b/bus/config-parser.c -@@ -1150,7 +1150,7 @@ append_rule_from_element (BusConfigParser *parser, - const char *element_name, - const char **attribute_names, - const char **attribute_values, -- dbus_bool_t allow, -+ BusPolicyRuleAccess access, - DBusError *error) - { - const char *log; -@@ -1173,6 +1173,7 @@ append_rule_from_element (BusConfigParser *parser, - const char *own_prefix; - const char *user; - const char *group; -+ const char *privilege; - - BusPolicyRule *rule; - -@@ -1200,6 +1201,7 @@ append_rule_from_element (BusConfigParser *parser, - "user", &user, - "group", &group, - "log", &log, -+ "privilege", &privilege, - NULL)) - return FALSE; - -@@ -1208,6 +1210,7 @@ append_rule_from_element (BusConfigParser *parser, - receive_interface || receive_member || receive_error || receive_sender || - receive_type || receive_path || eavesdrop || - send_requested_reply || receive_requested_reply || -+ privilege || - own || own_prefix || user || group)) - { - dbus_set_error (error, DBUS_ERROR_FAILED, -@@ -1224,7 +1227,30 @@ append_rule_from_element (BusConfigParser *parser, - element_name); - return FALSE; - } -- -+ -+ if (access == BUS_POLICY_RULE_ACCESS_CHECK) -+ { -+ if (privilege == NULL || !*privilege) -+ { -+ dbus_set_error (error, DBUS_ERROR_FAILED, -+ "On element <%s>, you must specify the privilege to be checked.", -+ element_name); -+ return FALSE; -+ } -+ } -+ else -+ { -+ if (privilege != NULL && *privilege) -+ { -+ dbus_set_error (error, DBUS_ERROR_FAILED, -+ "On element <%s>, privilege %s is used outside of a check rule.", -+ element_name, privilege); -+ return FALSE; -+ } -+ else -+ privilege = NULL; /* replace (potentially) empty string with NULL pointer, it wouldn't be used anyway */ -+ } -+ - /* Allowed combinations of elements are: - * - * base, must be all send or all receive: -@@ -1398,7 +1424,7 @@ append_rule_from_element (BusConfigParser *parser, - return FALSE; - } - -- rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); -+ rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, access); - if (rule == NULL) - goto nomem; - -@@ -1480,7 +1506,7 @@ append_rule_from_element (BusConfigParser *parser, - return FALSE; - } - -- rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); -+ rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, access); - if (rule == NULL) - goto nomem; - -@@ -1510,7 +1536,7 @@ append_rule_from_element (BusConfigParser *parser, - } - else if (own || own_prefix) - { -- rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow); -+ rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, access); - if (rule == NULL) - goto nomem; - -@@ -1536,7 +1562,7 @@ append_rule_from_element (BusConfigParser *parser, - { - if (IS_WILDCARD (user)) - { -- rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); -+ rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access); - if (rule == NULL) - goto nomem; - -@@ -1551,7 +1577,7 @@ append_rule_from_element (BusConfigParser *parser, - - if (_dbus_parse_unix_user_from_config (&username, &uid)) - { -- rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); -+ rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access); - if (rule == NULL) - goto nomem; - -@@ -1568,7 +1594,7 @@ append_rule_from_element (BusConfigParser *parser, - { - if (IS_WILDCARD (group)) - { -- rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); -+ rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access); - if (rule == NULL) - goto nomem; - -@@ -1583,7 +1609,7 @@ append_rule_from_element (BusConfigParser *parser, - - if (_dbus_parse_unix_group_from_config (&groupname, &gid)) - { -- rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); -+ rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access); - if (rule == NULL) - goto nomem; - -@@ -1607,6 +1633,10 @@ append_rule_from_element (BusConfigParser *parser, - _dbus_assert (pe != NULL); - _dbus_assert (pe->type == ELEMENT_POLICY); - -+ rule->privilege = _dbus_strdup (privilege); -+ if (privilege && !rule->privilege) -+ goto nomem; -+ - switch (pe->d.policy.type) - { - case POLICY_IGNORED: -@@ -1681,7 +1711,7 @@ start_policy_child (BusConfigParser *parser, - { - if (!append_rule_from_element (parser, element_name, - attribute_names, attribute_values, -- TRUE, error)) -+ BUS_POLICY_RULE_ACCESS_ALLOW, error)) - return FALSE; - - if (push_element (parser, ELEMENT_ALLOW) == NULL) -@@ -1696,7 +1726,7 @@ start_policy_child (BusConfigParser *parser, - { - if (!append_rule_from_element (parser, element_name, - attribute_names, attribute_values, -- FALSE, error)) -+ BUS_POLICY_RULE_ACCESS_DENY, error)) - return FALSE; - - if (push_element (parser, ELEMENT_DENY) == NULL) -@@ -1707,6 +1737,21 @@ start_policy_child (BusConfigParser *parser, - - return TRUE; - } -+ else if (strcmp (element_name, "check") == 0) -+ { -+ if (!append_rule_from_element (parser, element_name, -+ attribute_names, attribute_values, -+ BUS_POLICY_RULE_ACCESS_CHECK, error)) -+ return FALSE; -+ -+ if (push_element (parser, ELEMENT_CHECK) == NULL) -+ { -+ BUS_SET_OOM (error); -+ return FALSE; -+ } -+ -+ return TRUE; -+ } - else - { - dbus_set_error (error, DBUS_ERROR_FAILED, -@@ -2066,6 +2111,7 @@ bus_config_parser_end_element (BusConfigParser *parser, - case ELEMENT_POLICY: - case ELEMENT_ALLOW: - case ELEMENT_DENY: -+ case ELEMENT_CHECK: - case ELEMENT_FORK: - case ELEMENT_SYSLOG: - case ELEMENT_KEEP_UMASK: -@@ -2365,6 +2411,7 @@ bus_config_parser_content (BusConfigParser *parser, - case ELEMENT_POLICY: - case ELEMENT_ALLOW: - case ELEMENT_DENY: -+ case ELEMENT_CHECK: - case ELEMENT_FORK: - case ELEMENT_SYSLOG: - case ELEMENT_KEEP_UMASK: -@@ -2829,6 +2876,8 @@ do_load (const DBusString *full_path, - dbus_error_init (&error); - - parser = bus_config_load (full_path, TRUE, NULL, &error); -+ if (dbus_error_is_set (&error)) -+ _dbus_verbose ("Failed to load file: %s\n", error.message); - if (parser == NULL) - { - _DBUS_ASSERT_ERROR_IS_SET (&error); -diff --git a/bus/connection.c b/bus/connection.c -index 7107434..a6d87e5 100644 ---- a/bus/connection.c -+++ b/bus/connection.c -@@ -34,6 +34,10 @@ - #include <dbus/dbus-hash.h> - #include <dbus/dbus-timeout.h> - #include <dbus/dbus-connection-internal.h> -+#ifdef DBUS_ENABLE_CYNARA -+#include <stdlib.h> -+#include <cynara-session.h> -+#endif - - /* Trim executed commands to this length; we want to keep logs readable */ - #define MAX_LOG_COMMAND_LEN 50 -@@ -105,6 +109,9 @@ typedef struct - #endif - int n_pending_unix_fds; - DBusTimeout *pending_unix_fds_timeout; -+#ifdef DBUS_ENABLE_CYNARA -+ char *cynara_session_id; -+#endif - } BusConnectionData; - - static dbus_bool_t bus_pending_reply_expired (BusExpireList *list, -@@ -118,8 +125,8 @@ static dbus_bool_t expire_incomplete_timeout (void *data); - - #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot)) - --static DBusLoop* --connection_get_loop (DBusConnection *connection) -+DBusLoop* -+bus_connection_get_loop (DBusConnection *connection) - { - BusConnectionData *d; - -@@ -331,7 +338,7 @@ add_connection_watch (DBusWatch *watch, - { - DBusConnection *connection = data; - -- return _dbus_loop_add_watch (connection_get_loop (connection), watch); -+ return _dbus_loop_add_watch (bus_connection_get_loop (connection), watch); - } - - static void -@@ -340,7 +347,7 @@ remove_connection_watch (DBusWatch *watch, - { - DBusConnection *connection = data; - -- _dbus_loop_remove_watch (connection_get_loop (connection), watch); -+ _dbus_loop_remove_watch (bus_connection_get_loop (connection), watch); - } - - static void -@@ -349,7 +356,7 @@ toggle_connection_watch (DBusWatch *watch, - { - DBusConnection *connection = data; - -- _dbus_loop_toggle_watch (connection_get_loop (connection), watch); -+ _dbus_loop_toggle_watch (bus_connection_get_loop (connection), watch); - } - - static dbus_bool_t -@@ -358,7 +365,7 @@ add_connection_timeout (DBusTimeout *timeout, - { - DBusConnection *connection = data; - -- return _dbus_loop_add_timeout (connection_get_loop (connection), timeout); -+ return _dbus_loop_add_timeout (bus_connection_get_loop (connection), timeout); - } - - static void -@@ -367,7 +374,7 @@ remove_connection_timeout (DBusTimeout *timeout, - { - DBusConnection *connection = data; - -- _dbus_loop_remove_timeout (connection_get_loop (connection), timeout); -+ _dbus_loop_remove_timeout (bus_connection_get_loop (connection), timeout); - } - - static void -@@ -425,6 +432,10 @@ free_connection_data (void *data) - - dbus_free (d->name); - -+#ifdef DBUS_ENABLE_CYNARA -+ free (d->cynara_session_id); -+#endif -+ - dbus_free (d); - } - -@@ -984,6 +995,22 @@ bus_connection_get_policy (DBusConnection *connection) - return d->policy; - } - -+#ifdef DBUS_ENABLE_CYNARA -+const char *bus_connection_get_cynara_session_id (DBusConnection *connection) -+{ -+ BusConnectionData *d = BUS_CONNECTION_DATA (connection); -+ _dbus_assert (d != NULL); -+ -+ if (d->cynara_session_id == NULL) -+ { -+ unsigned long pid; -+ if (dbus_connection_get_unix_process_id(connection, &pid)) -+ d->cynara_session_id = cynara_session_from_pid(pid); -+ } -+ return d->cynara_session_id; -+} -+#endif -+ - static dbus_bool_t - foreach_active (BusConnections *connections, - BusConnectionForeachFunction function, -@@ -2104,6 +2131,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction, - DBusConnection *connection, - DBusMessage *message) - { -+ BusResult res; - /* We have to set the sender to the driver, and have - * to check security policy since it was not done in - * dispatch.c -@@ -2132,10 +2160,18 @@ bus_transaction_send_from_driver (BusTransaction *transaction, - /* If security policy doesn't allow the message, we silently - * eat it; the driver doesn't care about getting a reply. - */ -- if (!bus_context_check_security_policy (bus_transaction_get_context (transaction), -- transaction, -- NULL, connection, connection, message, NULL)) -+ res = bus_context_check_security_policy (bus_transaction_get_context (transaction), -+ transaction, -+ NULL, connection, connection, message, NULL, -+ NULL); -+ -+ if (res == BUS_RESULT_FALSE) - return TRUE; -+ else if (res == BUS_RESULT_LATER) -+ { -+ _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n"); -+ return TRUE; -+ } - - return bus_transaction_send (transaction, connection, message); - } -diff --git a/bus/connection.h b/bus/connection.h -index 6fbcd38..7433746 100644 ---- a/bus/connection.h -+++ b/bus/connection.h -@@ -31,6 +31,7 @@ - typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection, - void *data); - -+DBusLoop* bus_connection_get_loop (DBusConnection *connection); - - BusConnections* bus_connections_new (BusContext *context); - BusConnections* bus_connections_ref (BusConnections *connections); -@@ -116,6 +117,10 @@ dbus_bool_t bus_connection_get_unix_groups (DBusConnection *connecti - DBusError *error); - BusClientPolicy* bus_connection_get_policy (DBusConnection *connection); - -+#ifdef DBUS_ENABLE_CYNARA -+const char *bus_connection_get_cynara_session_id (DBusConnection *connection); -+#endif -+ - /* transaction API so we can send or not send a block of messages as a whole */ - - typedef void (* BusTransactionCancelFunction) (void *data); -diff --git a/bus/cynara.c b/bus/cynara.c -new file mode 100644 -index 0000000..57a4c45 ---- /dev/null -+++ b/bus/cynara.c -@@ -0,0 +1,374 @@ -+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -+/* cynara.c Cynara runtime privilege checking -+ * -+ * Copyright (c) 2014 Samsung Electronics, Ltd. -+ * -+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ */ -+ -+#include <config.h> -+#include "cynara.h" -+#include "check.h" -+#include "utils.h" -+ -+#include <stdio.h> -+ -+#include <dbus/dbus.h> -+#include <dbus/dbus-watch.h> -+#include <dbus/dbus-connection-internal.h> -+#include <bus/connection.h> -+#ifdef DBUS_ENABLE_CYNARA -+#include <cynara-client-async.h> -+#endif -+ -+ -+#ifdef DBUS_ENABLE_CYNARA -+typedef struct BusCynara -+{ -+ int refcount; -+ -+ BusContext *context; -+ BusCheck *check; -+ cynara_async *cynara; -+ DBusWatch *cynara_watch; -+} BusCynara; -+ -+#define USE_CYNARA_CACHE 1 -+#ifdef USE_CYNARA_CACHE -+#define CYNARA_CACHE_SIZE 1000 -+#endif -+ -+static dbus_bool_t bus_cynara_watch_callback(DBusWatch *watch, -+ unsigned int flags, -+ void *data); -+ -+static void status_callback(int old_fd, -+ int new_fd, -+ cynara_async_status status, -+ void *user_status_data); -+static void bus_cynara_check_response_callback (cynara_check_id check_id, -+ cynara_async_call_cause cause, -+ int response, -+ void *user_response_data); -+#endif -+ -+ -+BusCynara * -+bus_cynara_new(BusCheck *check, DBusError *error) -+{ -+#ifdef DBUS_ENABLE_CYNARA -+ BusContext *context; -+ BusCynara *cynara; -+ cynara_async_configuration *conf = NULL; -+ int ret; -+ -+ cynara = dbus_new(BusCynara, 1); -+ if (cynara == NULL) -+ { -+ BUS_SET_OOM(error); -+ return NULL; -+ } -+ -+ context = bus_check_get_context(check); -+ -+ cynara->refcount = 1; -+ cynara->check = check; -+ cynara->context = context; -+ cynara->cynara_watch = NULL; -+ -+ ret = cynara_async_configuration_create(&conf); -+ if (ret != CYNARA_API_SUCCESS) -+ { -+ dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to create Cynara configuration"); -+ goto out; -+ } -+ -+#ifdef CYNARA_CACHE_SIZE -+ ret = cynara_async_configuration_set_cache_size(conf, CYNARA_CACHE_SIZE); -+ if (ret != CYNARA_API_SUCCESS) -+ { -+ dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to Cynara cache size"); -+ goto out; -+ } -+#endif -+ -+ ret = cynara_async_initialize(&cynara->cynara, conf, &status_callback, cynara); -+ if (ret != CYNARA_API_SUCCESS) -+ { -+ dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to initialize Cynara client"); -+ goto out; -+ } -+ -+out: -+ cynara_async_configuration_destroy(conf); -+ if (ret != CYNARA_API_SUCCESS) -+ { -+ dbus_free(cynara); -+ return NULL; -+ } -+ -+ return cynara; -+#else -+ return NULL; -+#endif -+} -+ -+BusCynara * -+bus_cynara_ref (BusCynara *cynara) -+{ -+#ifdef DBUS_ENABLE_CYNARA -+ _dbus_assert (cynara->refcount > 0); -+ cynara->refcount += 1; -+ -+ return cynara; -+#else -+ return NULL; -+#endif -+} -+ -+void -+bus_cynara_unref (BusCynara *cynara) -+{ -+#ifdef DBUS_ENABLE_CYNARA -+ _dbus_assert (cynara->refcount > 0); -+ -+ cynara->refcount -= 1; -+ -+ if (cynara->refcount == 0) -+ { -+ cynara_async_finish(cynara->cynara); -+ dbus_free(cynara); -+ } -+#endif -+} -+ -+BusResult -+bus_cynara_check_privilege (BusCynara *cynara, -+ DBusMessage *message, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ const char *privilege, -+ BusDeferredMessageStatus check_type, -+ BusDeferredMessage **deferred_message_param) -+{ -+#ifdef DBUS_ENABLE_CYNARA -+ int result; -+ unsigned long uid; -+ char *label; -+ const char *session_id; -+ char user[32]; -+ cynara_check_id check_id; -+ DBusConnection *connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender; -+ BusDeferredMessage *deferred_message; -+ BusResult ret; -+ -+ _dbus_assert(connection != NULL); -+ -+ if (dbus_connection_get_unix_user(connection, &uid) == FALSE) -+ return BUS_RESULT_FALSE; -+ -+ if (_dbus_connection_get_linux_security_label(connection, &label) == FALSE || label == NULL) -+ { -+ _dbus_warn("Failed to obtain security label for connection\n"); -+ return BUS_RESULT_FALSE; -+ } -+ -+ session_id = bus_connection_get_cynara_session_id (connection); -+ if (session_id == NULL) -+ { -+ ret = BUS_RESULT_FALSE; -+ goto out; -+ } -+ -+ snprintf(user, sizeof(user), "%lu", uid); -+ -+#if USE_CYNARA_CACHE -+ result = cynara_async_check_cache(cynara->cynara, label, session_id, user, privilege); -+#else -+ result = CYNARA_API_CACHE_MISS; -+#endif -+ -+ switch (result) -+ { -+ case CYNARA_API_ACCESS_ALLOWED: -+ _dbus_verbose("Cynara: got ALLOWED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n", -+ label, session_id, user, privilege); -+ ret = BUS_RESULT_TRUE; -+ break; -+ -+ case CYNARA_API_ACCESS_DENIED: -+ _dbus_verbose("Cynara: got DENIED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n", -+ label, session_id, user, privilege); -+ ret = BUS_RESULT_FALSE; -+ break; -+ -+ case CYNARA_API_CACHE_MISS: -+ deferred_message = bus_deferred_message_new(message, sender, addressed_recipient, -+ proposed_recipient, BUS_RESULT_LATER); -+ if (deferred_message == NULL) -+ { -+ _dbus_verbose("Failed to allocate memory for deferred message\n"); -+ ret = BUS_RESULT_FALSE; -+ goto out; -+ } -+ -+ /* callback is supposed to unref deferred_message*/ -+ result = cynara_async_create_request(cynara->cynara, label, session_id, user, privilege, &check_id, -+ &bus_cynara_check_response_callback, deferred_message); -+ if (result == CYNARA_API_SUCCESS) -+ { -+ _dbus_verbose("Created Cynara request: client=%s session_id=%s user=%s privilege=%s check_id=%u " -+ "deferred_message=%p\n", label, session_id, user, privilege, (unsigned int)check_id, deferred_message); -+ if (deferred_message_param != NULL) -+ *deferred_message_param = deferred_message; -+ ret = BUS_RESULT_LATER; -+ } -+ else -+ { -+ _dbus_verbose("Error on cynara request create: %i\n", result); -+ bus_deferred_message_unref(deferred_message); -+ ret = BUS_RESULT_FALSE; -+ } -+ break; -+ default: -+ _dbus_verbose("Error when accessing Cynara cache: %i\n", result); -+ ret = BUS_RESULT_FALSE; -+ } -+out: -+ dbus_free(label); -+ return ret; -+ -+#else -+ return BUS_RESULT_FALSE; -+#endif -+} -+ -+ -+ -+#ifdef DBUS_ENABLE_CYNARA -+static void -+status_callback(int old_fd, int new_fd, cynara_async_status status, -+ void *user_status_data) -+{ -+ BusCynara *cynara = (BusCynara *)user_status_data; -+ DBusLoop *loop = bus_context_get_loop(cynara->context); -+ -+ if (cynara->cynara_watch != NULL) -+ { -+ _dbus_loop_remove_watch(loop, cynara->cynara_watch); -+ _dbus_watch_invalidate(cynara->cynara_watch); -+ _dbus_watch_unref(cynara->cynara_watch); -+ cynara->cynara_watch = NULL; -+ } -+ -+ if (new_fd != -1) -+ { -+ unsigned int flags; -+ DBusWatch *watch; -+ -+ switch (status) -+ { -+ case CYNARA_STATUS_FOR_READ: -+ flags = DBUS_WATCH_READABLE; -+ break; -+ case CYNARA_STATUS_FOR_RW: -+ flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE; -+ break; -+ default: -+ /* Cynara passed unknown status - warn and add RW watch */ -+ _dbus_verbose("Cynara passed unknown status value: 0x%08X\n", (unsigned int)status); -+ flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE; -+ break; -+ } -+ -+ watch = _dbus_watch_new(new_fd, flags, TRUE, &bus_cynara_watch_callback, cynara, NULL); -+ if (watch != NULL) -+ { -+ if (_dbus_loop_add_watch(loop, watch) == TRUE) -+ { -+ cynara->cynara_watch = watch; -+ return; -+ } -+ -+ _dbus_watch_invalidate(watch); -+ _dbus_watch_unref(watch); -+ } -+ -+ /* It seems like not much can be done at this point. Cynara events won't be processed -+ * until next Cynara function call triggering status callback */ -+ _dbus_verbose("Failed to add dbus watch\n"); -+ } -+} -+ -+static dbus_bool_t -+bus_cynara_watch_callback(DBusWatch *watch, -+ unsigned int flags, -+ void *data) -+{ -+ BusCynara *cynara = (BusCynara *)data; -+ int result = cynara_async_process(cynara->cynara); -+ if (result != CYNARA_API_SUCCESS) -+ _dbus_verbose("cynara_async_process returned %d\n", result); -+ -+ return result != CYNARA_API_OUT_OF_MEMORY ? TRUE : FALSE; -+} -+ -+static inline const char * -+call_cause_to_string(cynara_async_call_cause cause) -+{ -+ switch (cause) -+ { -+ case CYNARA_CALL_CAUSE_ANSWER: -+ return "ANSWER"; -+ case CYNARA_CALL_CAUSE_CANCEL: -+ return "CANCEL"; -+ case CYNARA_CALL_CAUSE_FINISH: -+ return "FINSIH"; -+ case CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE: -+ return "SERVICE NOT AVAILABLE"; -+ default: -+ return "INVALID"; -+ } -+} -+ -+static void -+bus_cynara_check_response_callback (cynara_check_id check_id, -+ cynara_async_call_cause cause, -+ int response, -+ void *user_response_data) -+{ -+ BusDeferredMessage *deferred_message = user_response_data; -+ BusResult result; -+ -+ _dbus_verbose("Cynara callback: check_id=%u, cause=%s response=%i response_data=%p\n", -+ (unsigned int)check_id, call_cause_to_string(cause), response, user_response_data); -+ -+ if (deferred_message == NULL) -+ return; -+ -+ if (cause == CYNARA_CALL_CAUSE_ANSWER && response == CYNARA_API_ACCESS_ALLOWED) -+ result = BUS_RESULT_TRUE; -+ else -+ result = BUS_RESULT_FALSE; -+ -+ bus_deferred_message_response_received(deferred_message, result); -+ bus_deferred_message_unref(deferred_message); -+} -+ -+#endif /* DBUS_ENABLE_CYNARA */ -diff --git a/bus/cynara.h b/bus/cynara.h -new file mode 100644 -index 0000000..c4728bb ---- /dev/null -+++ b/bus/cynara.h -@@ -0,0 +1,37 @@ -+/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ -+/* cynara.h Cynara runtime privilege checking -+ * -+ * Copyright (c) 2014 Samsung Electronics, Ltd. -+ * -+ * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA -+ * -+ */ -+ -+#include "bus.h" -+#include "check.h" -+ -+BusCynara *bus_cynara_new (BusCheck *check, DBusError *error); -+BusCynara *bus_cynara_ref (BusCynara *cynara); -+void bus_cynara_unref (BusCynara *cynara); -+BusResult bus_cynara_check_privilege (BusCynara *cynara, -+ DBusMessage *message, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ const char *privilege, -+ BusDeferredMessageStatus check_type, -+ BusDeferredMessage **deferred_message); -diff --git a/bus/dispatch.c b/bus/dispatch.c -index 7a61953..ce4076d 100644 ---- a/bus/dispatch.c -+++ b/bus/dispatch.c -@@ -25,6 +25,7 @@ - - #include <config.h> - #include "dispatch.h" -+#include "check.h" - #include "connection.h" - #include "driver.h" - #include "services.h" -@@ -56,13 +57,14 @@ send_one_message (DBusConnection *connection, - BusTransaction *transaction, - DBusError *error) - { -- if (!bus_context_check_security_policy (context, transaction, -- sender, -- addressed_recipient, -- connection, -- message, -- NULL)) -- return TRUE; /* silently don't send it */ -+ BusDeferredMessage *deferred_message; -+ BusResult result; -+ -+ result = bus_context_check_security_policy (context, transaction, sender, addressed_recipient, -+ connection, message, NULL, &deferred_message); -+ -+ if (result != BUS_RESULT_TRUE) -+ return TRUE; /* silently don't send it */ - - if (dbus_message_contains_unix_fds(message) && - !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD)) -@@ -92,6 +94,7 @@ bus_dispatch_matches (BusTransaction *transaction, - BusMatchmaker *matchmaker; - DBusList *link; - BusContext *context; -+ BusDeferredMessage *deferred_message; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - -@@ -107,11 +110,21 @@ bus_dispatch_matches (BusTransaction *transaction, - /* First, send the message to the addressed_recipient, if there is one. */ - if (addressed_recipient != NULL) - { -- if (!bus_context_check_security_policy (context, transaction, -- sender, addressed_recipient, -- addressed_recipient, -- message, error)) -+ BusResult res; -+ res = bus_context_check_security_policy (context, transaction, -+ sender, addressed_recipient, -+ addressed_recipient, -+ message, error, -+ &deferred_message); -+ if (res == BUS_RESULT_FALSE) - return FALSE; -+ else if (res == BUS_RESULT_LATER) -+ { -+ dbus_set_error (error, -+ DBUS_ERROR_ACCESS_DENIED, -+ "Rejecting message because time is needed to check security policy"); -+ return FALSE; -+ } - - if (dbus_message_contains_unix_fds (message) && - !dbus_connection_can_send_type (addressed_recipient, -@@ -273,12 +286,24 @@ bus_dispatch (DBusConnection *connection, - if (service_name && - strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */ - { -- if (!bus_context_check_security_policy (context, transaction, -- connection, NULL, NULL, message, &error)) -+ BusDeferredMessage *deferred_message; -+ BusResult res; -+ res = bus_context_check_security_policy (context, transaction, -+ connection, NULL, NULL, message, &error, -+ &deferred_message); -+ if (res == BUS_RESULT_FALSE) - { - _dbus_verbose ("Security policy rejected message\n"); - goto out; - } -+ else if (res == BUS_RESULT_LATER) -+ { -+ dbus_set_error (&error, -+ DBUS_ERROR_ACCESS_DENIED, -+ "Rejecting message because time is needed to check security policy"); -+ _dbus_verbose ("Security policy needs time to check policy. Dropping message\n"); -+ goto out; -+ } - - _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS); - if (!bus_driver_handle_message (connection, transaction, message, &error)) -diff --git a/bus/policy.c b/bus/policy.c -index 082f385..ec888df 100644 ---- a/bus/policy.c -+++ b/bus/policy.c -@@ -22,6 +22,7 @@ - */ - - #include <config.h> -+#include "check.h" - #include "policy.h" - #include "services.h" - #include "test.h" -@@ -32,7 +33,7 @@ - - BusPolicyRule* - bus_policy_rule_new (BusPolicyRuleType type, -- dbus_bool_t allow) -+ BusPolicyRuleAccess access) - { - BusPolicyRule *rule; - -@@ -42,7 +43,7 @@ bus_policy_rule_new (BusPolicyRuleType type, - - rule->type = type; - rule->refcount = 1; -- rule->allow = allow; -+ rule->access = access; - - switch (rule->type) - { -@@ -54,18 +55,19 @@ bus_policy_rule_new (BusPolicyRuleType type, - break; - case BUS_POLICY_RULE_SEND: - rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID; -- - /* allow rules default to TRUE (only requested replies allowed) -+ * check rules default to TRUE (only requested replies are checked) - * deny rules default to FALSE (only unrequested replies denied) - */ -- rule->d.send.requested_reply = rule->allow; -+ rule->d.send.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY; - break; - case BUS_POLICY_RULE_RECEIVE: - rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID; - /* allow rules default to TRUE (only requested replies allowed) -+ * check rules default to TRUE (only requested replies are checked) - * deny rules default to FALSE (only unrequested replies denied) - */ -- rule->d.receive.requested_reply = rule->allow; -+ rule->d.receive.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY; - break; - case BUS_POLICY_RULE_OWN: - break; -@@ -117,7 +119,8 @@ bus_policy_rule_unref (BusPolicyRule *rule) - case BUS_POLICY_RULE_GROUP: - break; - } -- -+ -+ dbus_free (rule->privilege); - dbus_free (rule); - } - } -@@ -427,7 +430,10 @@ list_allows_user (dbus_bool_t def, - else - continue; - -- allowed = rule->allow; -+ /* We don't intend to support <check user="..." /> and <check group="..." /> -+ rules. They are treated like deny. -+ */ -+ allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW; - } - - return allowed; -@@ -862,18 +868,23 @@ bus_client_policy_append_rule (BusClientPolicy *policy, - return TRUE; - } - --dbus_bool_t --bus_client_policy_check_can_send (BusClientPolicy *policy, -- BusRegistry *registry, -- dbus_bool_t requested_reply, -- DBusConnection *receiver, -- DBusMessage *message, -- dbus_int32_t *toggles, -- dbus_bool_t *log) -+BusResult -+bus_client_policy_check_can_send (DBusConnection *sender, -+ BusClientPolicy *policy, -+ BusRegistry *registry, -+ dbus_bool_t requested_reply, -+ DBusConnection *addressed_recipient, -+ DBusConnection *receiver, -+ DBusMessage *message, -+ dbus_int32_t *toggles, -+ dbus_bool_t *log, -+ const char **privilege_param, -+ BusDeferredMessage **deferred_message) - { - DBusList *link; -- dbus_bool_t allowed; -- -+ BusResult result; -+ const char *privilege; -+ - /* policy->rules is in the order the rules appeared - * in the config file, i.e. last rule that applies wins - */ -@@ -881,7 +892,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, - _dbus_verbose (" (policy) checking send rules\n"); - *toggles = 0; - -- allowed = FALSE; -+ result = BUS_RESULT_FALSE; - link = _dbus_list_get_first_link (&policy->rules); - while (link != NULL) - { -@@ -912,13 +923,14 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, - /* If it's a reply, the requested_reply flag kicks in */ - if (dbus_message_get_reply_serial (message) != 0) - { -- /* for allow, requested_reply=true means the rule applies -- * only when reply was requested. requested_reply=false means -- * always allow. -+ /* for allow or check requested_reply=true means the rule applies -+ * only when reply was requested. requested_reply=false means the -+ * rule always applies - */ -- if (!requested_reply && rule->allow && rule->d.send.requested_reply && !rule->d.send.eavesdrop) -+ if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop) - { -- _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n"); -+ _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n", -+ rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check"); - continue; - } - -@@ -926,7 +938,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, - * when the reply was not requested. requested_reply=true means the - * rule always applies. - */ -- if (requested_reply && !rule->allow && !rule->d.send.requested_reply) -+ if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.send.requested_reply) - { - _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n"); - continue; -@@ -949,13 +961,15 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, - /* The interface is optional in messages. For allow rules, if the message - * has no interface we want to skip the rule (and thus not allow); - * for deny rules, if the message has no interface we want to use the -- * rule (and thus deny). -+ * rule (and thus deny). Check rules are meant to be used like allow -+ * rules (they can grant access, but not remove it), so we treat it like -+ * allow here. - */ - dbus_bool_t no_interface; - - no_interface = dbus_message_get_interface (message) == NULL; - -- if ((no_interface && rule->allow) || -+ if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) || - (!no_interface && - strcmp (dbus_message_get_interface (message), - rule->d.send.interface) != 0)) -@@ -1029,33 +1043,63 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, - } - - /* Use this rule */ -- allowed = rule->allow; -+ switch (rule->access) -+ { -+ case BUS_POLICY_RULE_ACCESS_ALLOW: -+ result = BUS_RESULT_TRUE; -+ break; -+ case BUS_POLICY_RULE_ACCESS_DENY: -+ result = BUS_RESULT_FALSE; -+ break; -+ case BUS_POLICY_RULE_ACCESS_CHECK: -+ result = BUS_RESULT_LATER; -+ privilege = rule->privilege; -+ break; -+ } -+ - *log = rule->d.send.log; - (*toggles)++; - -- _dbus_verbose (" (policy) used rule, allow now = %d\n", -- allowed); -+ _dbus_verbose (" (policy) used rule, result now = %d\n", -+ result); - } - -- return allowed; -+ if (result == BUS_RESULT_LATER) -+ { -+ BusContext *context = bus_connection_get_context(sender); -+ BusCheck *check = bus_context_get_check(context); -+ -+ result = bus_check_privilege(check, message, sender, addressed_recipient, receiver, -+ privilege, BUS_DEFERRED_MESSAGE_CHECK_SEND, deferred_message); -+ } -+ else -+ privilege = NULL; -+ -+ if (privilege_param != NULL) -+ *privilege_param = privilege; -+ -+ return result; - } - - /* See docs on what the args mean on bus_context_check_security_policy() - * comment - */ --dbus_bool_t --bus_client_policy_check_can_receive (BusClientPolicy *policy, -- BusRegistry *registry, -- dbus_bool_t requested_reply, -- DBusConnection *sender, -- DBusConnection *addressed_recipient, -- DBusConnection *proposed_recipient, -- DBusMessage *message, -- dbus_int32_t *toggles) -+BusResult -+bus_client_policy_check_can_receive (BusClientPolicy *policy, -+ BusRegistry *registry, -+ dbus_bool_t requested_reply, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ DBusMessage *message, -+ dbus_int32_t *toggles, -+ const char **privilege_param, -+ BusDeferredMessage **deferred_message) - { - DBusList *link; -- dbus_bool_t allowed; - dbus_bool_t eavesdropping; -+ BusResult result; -+ const char *privilege; - - eavesdropping = - addressed_recipient != proposed_recipient && -@@ -1068,7 +1112,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, - _dbus_verbose (" (policy) checking receive rules, eavesdropping = %d\n", eavesdropping); - *toggles = 0; - -- allowed = FALSE; -+ result = BUS_RESULT_FALSE; - link = _dbus_list_get_first_link (&policy->rules); - while (link != NULL) - { -@@ -1091,19 +1135,21 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, - } - } - -- /* for allow, eavesdrop=false means the rule doesn't apply when -- * eavesdropping. eavesdrop=true means always allow. -+ -+ /* for allow or check, eavesdrop=false means the rule doesn't apply when -+ * eavesdropping. eavesdrop=true means the rule always applies - */ -- if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop) -+ if (eavesdropping && rule->access != BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.eavesdrop) - { -- _dbus_verbose (" (policy) skipping allow rule since it doesn't apply to eavesdropping\n"); -+ _dbus_verbose (" (policy) skipping %s rule since it doesn't apply to eavesdropping\n", -+ rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check"); - continue; - } - - /* for deny, eavesdrop=true means the rule applies only when - * eavesdropping; eavesdrop=false means always deny. - */ -- if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop) -+ if (!eavesdropping && rule->access == BUS_POLICY_RULE_ACCESS_DENY && rule->d.receive.eavesdrop) - { - _dbus_verbose (" (policy) skipping deny rule since it only applies to eavesdropping\n"); - continue; -@@ -1112,13 +1158,14 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, - /* If it's a reply, the requested_reply flag kicks in */ - if (dbus_message_get_reply_serial (message) != 0) - { -- /* for allow, requested_reply=true means the rule applies -- * only when reply was requested. requested_reply=false means -- * always allow. -+ /* for allow or check requested_reply=true means the rule applies -+ * only when reply was requested. requested_reply=false means the -+ * rule always applies - */ -- if (!requested_reply && rule->allow && rule->d.receive.requested_reply && !rule->d.receive.eavesdrop) -+ if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop) - { -- _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n"); -+ _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n", -+ rule->access == BUS_POLICY_RULE_ACCESS_DENY ? "allow" : "deny"); - continue; - } - -@@ -1126,7 +1173,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, - * when the reply was not requested. requested_reply=true means the - * rule always applies. - */ -- if (requested_reply && !rule->allow && !rule->d.receive.requested_reply) -+ if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.requested_reply) - { - _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n"); - continue; -@@ -1149,13 +1196,13 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, - /* The interface is optional in messages. For allow rules, if the message - * has no interface we want to skip the rule (and thus not allow); - * for deny rules, if the message has no interface we want to use the -- * rule (and thus deny). -+ * rule (and thus deny). Check rules are treated like allow rules. - */ - dbus_bool_t no_interface; - - no_interface = dbus_message_get_interface (message) == NULL; - -- if ((no_interface && rule->allow) || -+ if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) || - (!no_interface && - strcmp (dbus_message_get_interface (message), - rule->d.receive.interface) != 0)) -@@ -1230,14 +1277,42 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, - } - - /* Use this rule */ -- allowed = rule->allow; -+ switch (rule->access) -+ { -+ case BUS_POLICY_RULE_ACCESS_ALLOW: -+ result = BUS_RESULT_TRUE; -+ break; -+ case BUS_POLICY_RULE_ACCESS_DENY: -+ result = BUS_RESULT_FALSE; -+ break; -+ case BUS_POLICY_RULE_ACCESS_CHECK: -+ result = BUS_RESULT_LATER; -+ privilege = rule->privilege; -+ break; -+ } -+ - (*toggles)++; - -- _dbus_verbose (" (policy) used rule, allow now = %d\n", -- allowed); -+ _dbus_verbose (" (policy) used rule, result now = %d\n", -+ result); - } - -- return allowed; -+ -+ if (result == BUS_RESULT_LATER) -+ { -+ BusContext *context = bus_connection_get_context(proposed_recipient); -+ BusCheck *check = bus_context_get_check(context); -+ -+ result = bus_check_privilege(check, message, sender, addressed_recipient, proposed_recipient, -+ privilege, BUS_DEFERRED_MESSAGE_CHECK_RECEIVE, deferred_message); -+ } -+ else -+ privilege = NULL; -+ -+ if (privilege_param != NULL) -+ *privilege_param = privilege; -+ -+ return result; - } - - -@@ -1289,7 +1364,7 @@ bus_rules_check_can_own (DBusList *rules, - } - - /* Use this rule */ -- allowed = rule->allow; -+ allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW; - } - - return allowed; -diff --git a/bus/policy.h b/bus/policy.h -index d1d3e72..e9f193a 100644 ---- a/bus/policy.h -+++ b/bus/policy.h -@@ -39,6 +39,14 @@ typedef enum - BUS_POLICY_RULE_GROUP - } BusPolicyRuleType; - -+typedef enum -+{ -+ BUS_POLICY_RULE_ACCESS_DENY, -+ BUS_POLICY_RULE_ACCESS_ALLOW, -+ /** runtime check resulting in allow or deny */ -+ BUS_POLICY_RULE_ACCESS_CHECK -+} BusPolicyRuleAccess; -+ - /** determines whether the rule affects a connection, or some global item */ - #define BUS_POLICY_RULE_IS_PER_CLIENT(rule) (!((rule)->type == BUS_POLICY_RULE_USER || \ - (rule)->type == BUS_POLICY_RULE_GROUP)) -@@ -49,8 +57,9 @@ struct BusPolicyRule - - BusPolicyRuleType type; - -- unsigned int allow : 1; /**< #TRUE if this allows, #FALSE if it denies */ -- -+ unsigned int access : 2; /**< BusPolicyRuleAccess */ -+ char *privilege; /**< for BUS_POLICY_RULE_ACCESS_CHECK */ -+ - union - { - struct -@@ -106,7 +115,7 @@ struct BusPolicyRule - }; - - BusPolicyRule* bus_policy_rule_new (BusPolicyRuleType type, -- dbus_bool_t allow); -+ BusPolicyRuleAccess access); - BusPolicyRule* bus_policy_rule_ref (BusPolicyRule *rule); - void bus_policy_rule_unref (BusPolicyRule *rule); - -@@ -140,21 +149,27 @@ dbus_bool_t bus_policy_merge (BusPolicy *policy, - BusClientPolicy* bus_client_policy_new (void); - BusClientPolicy* bus_client_policy_ref (BusClientPolicy *policy); - void bus_client_policy_unref (BusClientPolicy *policy); --dbus_bool_t bus_client_policy_check_can_send (BusClientPolicy *policy, -- BusRegistry *registry, -- dbus_bool_t requested_reply, -- DBusConnection *receiver, -- DBusMessage *message, -- dbus_int32_t *toggles, -- dbus_bool_t *log); --dbus_bool_t bus_client_policy_check_can_receive (BusClientPolicy *policy, -- BusRegistry *registry, -- dbus_bool_t requested_reply, -- DBusConnection *sender, -- DBusConnection *addressed_recipient, -- DBusConnection *proposed_recipient, -- DBusMessage *message, -- dbus_int32_t *toggles); -+BusResult bus_client_policy_check_can_send (DBusConnection *sender, -+ BusClientPolicy *policy, -+ BusRegistry *registry, -+ dbus_bool_t requested_reply, -+ DBusConnection *addressed_recipient, -+ DBusConnection *receiver, -+ DBusMessage *message, -+ dbus_int32_t *toggles, -+ dbus_bool_t *log, -+ const char **privilege_param, -+ BusDeferredMessage **deferred_message); -+BusResult bus_client_policy_check_can_receive (BusClientPolicy *policy, -+ BusRegistry *registry, -+ dbus_bool_t requested_reply, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusConnection *proposed_recipient, -+ DBusMessage *message, -+ dbus_int32_t *toggles, -+ const char **privilege_param, -+ BusDeferredMessage **deferred_message); - dbus_bool_t bus_client_policy_check_can_own (BusClientPolicy *policy, - const DBusString *service_name); - dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy, -diff --git a/configure.ac b/configure.ac -index eb803af..b131f30 100644 ---- a/configure.ac -+++ b/configure.ac -@@ -1748,6 +1748,18 @@ if test "x$enable_stats" = xyes; then - [Define to enable bus daemon usage statistics]) - fi - -+#enable cynara integration -+AC_ARG_ENABLE([cynara], [AS_HELP_STRING([--enable-cynara], [enable Cynara integration])], [], [enable_cynara=no]) -+if test "x$enable_cynara" = xyes; then -+ PKG_CHECK_MODULES([CYNARA], [cynara-client-async >= 0.6.0 cynara-session >= 0.6.0], -+ [AC_DEFINE([DBUS_ENABLE_CYNARA], [1], [Define to enable Cynara privilege checks in dbus-daemon])], -+ [AC_MSG_ERROR([libcynara-client-async and cynara-session are required to enable Cynara integration])]) -+fi -+ -+AC_SUBST([CYNARA_CFLAGS]) -+AC_SUBST([CYNARA_LIBS]) -+ -+ - AC_CONFIG_FILES([ - Doxyfile - dbus/versioninfo.rc -@@ -1778,6 +1790,7 @@ dbus-1.pc - dbus-1-uninstalled.pc - test/data/valid-config-files/debug-allow-all.conf - test/data/valid-config-files/debug-allow-all-sha1.conf -+test/data/valid-config-files/debug-check-some.conf - test/data/valid-config-files/incoming-limit.conf - test/data/valid-config-files-system/debug-allow-all-pass.conf - test/data/valid-config-files-system/debug-allow-all-fail.conf -diff --git a/test/Makefile.am b/test/Makefile.am -index e0ed3c8..ab63edc 100644 ---- a/test/Makefile.am -+++ b/test/Makefile.am -@@ -254,6 +254,7 @@ in_data = \ - data/valid-config-files-system/debug-allow-all-pass.conf.in \ - data/valid-config-files/debug-allow-all-sha1.conf.in \ - data/valid-config-files/debug-allow-all.conf.in \ -+ data/valid-config-files/debug-check-some.conf.in \ - data/valid-config-files/incoming-limit.conf.in \ - data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in \ - data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.in \ -diff --git a/test/data/invalid-config-files/badcheck-1.conf b/test/data/invalid-config-files/badcheck-1.conf -new file mode 100644 -index 0000000..fad9f50 ---- /dev/null -+++ b/test/data/invalid-config-files/badcheck-1.conf -@@ -0,0 +1,9 @@ -+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" -+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> -+<busconfig> -+ <user>mybususer</user> -+ <listen>unix:path=/foo/bar</listen> -+ <policy context="default"> -+ <allow privilege="foo" send_destination="*"/> <!-- extra privilege="foo" --> -+ </policy> -+</busconfig> -diff --git a/test/data/invalid-config-files/badcheck-2.conf b/test/data/invalid-config-files/badcheck-2.conf -new file mode 100644 -index 0000000..63c7ef2 ---- /dev/null -+++ b/test/data/invalid-config-files/badcheck-2.conf -@@ -0,0 +1,9 @@ -+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" -+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> -+<busconfig> -+ <user>mybususer</user> -+ <listen>unix:path=/foo/bar</listen> -+ <policy context="default"> -+ <check send_destination="*"/> <!-- missing privilege="foo" --> -+ </policy> -+</busconfig> -diff --git a/test/data/valid-config-files/check-1.conf b/test/data/valid-config-files/check-1.conf -new file mode 100644 -index 0000000..ad71473 ---- /dev/null -+++ b/test/data/valid-config-files/check-1.conf -@@ -0,0 +1,9 @@ -+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" -+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> -+<busconfig> -+ <user>mybususer</user> -+ <listen>unix:path=/foo/bar</listen> -+ <policy context="default"> -+ <check privilege="foo" send_destination="*"/> -+ </policy> -+</busconfig> -diff --git a/test/data/valid-config-files/debug-check-some.conf.in b/test/data/valid-config-files/debug-check-some.conf.in -new file mode 100644 -index 0000000..47ee854 ---- /dev/null -+++ b/test/data/valid-config-files/debug-check-some.conf.in -@@ -0,0 +1,18 @@ -+<!-- Bus that listens on a debug pipe and doesn't create any restrictions --> -+ -+<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" -+ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> -+<busconfig> -+ <listen>debug-pipe:name=test-server</listen> -+ <listen>@TEST_LISTEN@</listen> -+ <servicedir>@DBUS_TEST_DATA@/valid-service-files</servicedir> -+ <policy context="default"> -+ <allow send_interface="*"/> -+ <allow receive_interface="*"/> -+ <allow own="*"/> -+ <allow user="*"/> -+ -+ <deny send_interface="org.freedesktop.TestSuite" send_member="Echo"/> -+ <check privilege="foo" send_interface="org.freedesktop.TestSuite" send_member="Echo"/> -+ </policy> -+</busconfig> --- -2.1.4 - diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0005-Disable-message-dispatching-when-send-rule-result-is.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0005-Disable-message-dispatching-when-send-rule-result-is.patch deleted file mode 100644 index ca787149e..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0005-Disable-message-dispatching-when-send-rule-result-is.patch +++ /dev/null @@ -1,941 +0,0 @@ -From b1b87ad9f20b2052c28431b48e81073078a745ce Mon Sep 17 00:00:00 2001 -From: Jacek Bukarewicz <j.bukarewicz@samsung.com> -Date: Fri, 28 Nov 2014 12:07:39 +0100 -Subject: [PATCH 5/8] Disable message dispatching when send rule result is not - known - -When unicast message is sent to addressed recipient and policy result -is not available message dispatch from the sender is disabled. -This also means that any further messages from the given connection are -put into the incoming queue without being processed. If response is received -message dispatching is resumed. This time answer is attached to the message -which is now processed synchronously. -Receive rule result unavailability is not yet handled - such messages are -rejected. Also, if message is sent to non-addressed recipient and policy result -is unknown, message is silently dropped. - -Change-Id: I57eccbf973525fd51369c7d4e58908292f44da80 ---- - bus/activation.c | 79 +++++++++++++++-- - bus/check.c | 109 ++++++++++++++++++++++-- - bus/check.h | 10 +++ - bus/cynara.c | 1 - - bus/dispatch.c | 183 ++++++++++++++++++++++++++++++++++++---- - bus/dispatch.h | 2 +- - bus/driver.c | 13 ++- - dbus/dbus-connection-internal.h | 9 ++ - dbus/dbus-connection.c | 125 +++++++++++++++++++++++++-- - dbus/dbus-list.c | 29 +++++++ - dbus/dbus-list.h | 2 + - dbus/dbus-shared.h | 3 +- - 12 files changed, 522 insertions(+), 43 deletions(-) - -diff --git a/bus/activation.c b/bus/activation.c -index ecd19bb..8c43941 100644 ---- a/bus/activation.c -+++ b/bus/activation.c -@@ -31,6 +31,7 @@ - #include "services.h" - #include "test.h" - #include "utils.h" -+#include <dbus/dbus-connection-internal.h> - #include <dbus/dbus-internals.h> - #include <dbus/dbus-hash.h> - #include <dbus/dbus-list.h> -@@ -91,6 +92,8 @@ struct BusPendingActivationEntry - DBusConnection *connection; - - dbus_bool_t auto_activation; -+ -+ dbus_bool_t is_put_back; - }; - - typedef struct -@@ -1180,20 +1183,23 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation - BusPendingActivationEntry *entry = link->data; - DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link); - -- if (entry->auto_activation && (entry->connection == NULL || dbus_connection_get_is_connected (entry->connection))) -+ if (entry->auto_activation && !entry->is_put_back && -+ (entry->connection == NULL || dbus_connection_get_is_connected (entry->connection))) - { - DBusConnection *addressed_recipient; - DBusError error; -+ BusResult res; - - dbus_error_init (&error); - - addressed_recipient = bus_service_get_primary_owners_connection (service); - - /* Resume dispatching where we left off in bus_dispatch() */ -- if (!bus_dispatch_matches (transaction, -- entry->connection, -- addressed_recipient, -- entry->activation_message, &error)) -+ res = bus_dispatch_matches (transaction, -+ entry->connection, -+ addressed_recipient, -+ entry->activation_message, &error); -+ if (res == BUS_RESULT_FALSE) - { - /* If permission is denied, we just want to return the error - * to the original method invoker; in particular, we don't -@@ -1205,9 +1211,40 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation - bus_connection_send_oom_error (entry->connection, - entry->activation_message); - } -+ } -+ else if (res == BUS_RESULT_LATER) -+ { -+ DBusList *putback_message_link = link; -+ DBusMessage *last_inserted_message = NULL; -+ -+ /* NULL entry->connection implies sending pending ActivationRequest message to systemd */ -+ if (entry->connection == NULL) -+ { -+ _dbus_assert_not_reached ("bus_dispatch_matches returned BUS_RESULT_LATER unexpectedly when sender is NULL"); -+ link = next; -+ continue; -+ } - -- link = next; -- continue; -+ /** -+ * Getting here means that policy check result is not yet available and dispatching -+ * messages from entry->connection has been disabled. -+ * Let's put back all messages for the given connection in the incoming queue and mark -+ * this entry as put back so they are not handled twice. -+ */ -+ while (putback_message_link != NULL) -+ { -+ BusPendingActivationEntry *putback_message = putback_message_link->data; -+ if (putback_message->connection == entry->connection) -+ { -+ if (!_dbus_connection_putback_message (putback_message->connection, last_inserted_message, -+ putback_message->activation_message, &error)) -+ goto error; -+ last_inserted_message = putback_message->activation_message; -+ putback_message->is_put_back = TRUE; -+ } -+ -+ putback_message_link = _dbus_list_get_next_link(&pending_activation->entries, putback_message_link); -+ } - } - } - -@@ -1225,6 +1262,19 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation - return TRUE; - - error: -+ /* remove all messages that have been put to connections' incoming queues */ -+ link = _dbus_list_get_first_link (&pending_activation->entries); -+ while (link != NULL) -+ { -+ BusPendingActivationEntry *entry = link->data; -+ if (entry->is_put_back) -+ { -+ _dbus_connection_remove_message(entry->connection, entry->activation_message); -+ entry->is_put_back = FALSE; -+ } -+ link = _dbus_list_get_next_link(&pending_activation->entries, link); -+ } -+ - return FALSE; - } - -@@ -2009,13 +2059,24 @@ bus_activation_activate_service (BusActivation *activation, - - if (service != NULL) - { -+ BusResult res; - bus_context_log (activation->context, - DBUS_SYSTEM_LOG_INFO, "Activating via systemd: service name='%s' unit='%s'", - service_name, - entry->systemd_service); - /* Wonderful, systemd is connected, let's just send the msg */ -- retval = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service), -- message, error); -+ res = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service), -+ message, error); -+ -+ if (res == BUS_RESULT_TRUE) -+ retval = TRUE; -+ else if (res == BUS_RESULT_FALSE) -+ retval = FALSE; -+ else if (res == BUS_RESULT_LATER) -+ { -+ _dbus_verbose("Unexpectedly need time to check message from bus driver to systemd - dropping the message.\n"); -+ retval = FALSE; -+ } - } - else - { -diff --git a/bus/check.c b/bus/check.c -index d2f418a..cd6a74b 100644 ---- a/bus/check.c -+++ b/bus/check.c -@@ -55,6 +55,8 @@ typedef struct BusDeferredMessage - BusCheckResponseFunc response_callback; - } BusDeferredMessage; - -+static dbus_int32_t deferred_message_data_slot = -1; -+ - BusCheck * - bus_check_new (BusContext *context, DBusError *error) - { -@@ -67,11 +69,19 @@ bus_check_new (BusContext *context, DBusError *error) - return NULL; - } - -+ if (!dbus_message_allocate_data_slot(&deferred_message_data_slot)) -+ { -+ dbus_free(check); -+ BUS_SET_OOM(error); -+ return NULL; -+ } -+ - check->refcount = 1; - check->context = context; - check->cynara = bus_cynara_new(check, error); - if (dbus_error_is_set(error)) - { -+ dbus_message_free_data_slot(&deferred_message_data_slot); - dbus_free(check); - return NULL; - } -@@ -98,6 +108,7 @@ bus_check_unref (BusCheck *check) - if (check->refcount == 0) - { - bus_cynara_unref(check->cynara); -+ dbus_message_free_data_slot(&deferred_message_data_slot); - dbus_free(check); - } - } -@@ -114,6 +125,45 @@ bus_check_get_cynara (BusCheck *check) - return check->cynara; - } - -+static void -+bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message, -+ BusResult result) -+{ -+ _dbus_verbose("bus_check_enable_dispatch_callback called deferred_message=%p\n", deferred_message); -+ -+ deferred_message->response = result; -+ _dbus_connection_enable_dispatch(deferred_message->sender); -+} -+ -+static void -+deferred_message_free_function(void *data) -+{ -+ BusDeferredMessage *deferred_message = (BusDeferredMessage *)data; -+ bus_deferred_message_unref(deferred_message); -+} -+ -+void -+bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message) -+{ -+ _dbus_assert(deferred_message != NULL); -+ _dbus_assert(deferred_message->sender != NULL); -+ -+ if (dbus_message_get_data(deferred_message->message, deferred_message_data_slot) == NULL) -+ { -+ if (dbus_message_set_data(deferred_message->message, deferred_message_data_slot, deferred_message, -+ deferred_message_free_function)) -+ bus_deferred_message_ref(deferred_message); -+ } -+ -+ _dbus_connection_disable_dispatch(deferred_message->sender); -+ deferred_message->response_callback = bus_check_enable_dispatch_callback; -+} -+ -+#ifdef DBUS_ENABLE_EMBEDDED_TESTS -+dbus_bool_t (*bus_check_test_override) (DBusConnection *connection, -+ const char *privilege); -+#endif -+ - BusResult - bus_check_privilege (BusCheck *check, - DBusMessage *message, -@@ -124,6 +174,7 @@ bus_check_privilege (BusCheck *check, - BusDeferredMessageStatus check_type, - BusDeferredMessage **deferred_message) - { -+ BusDeferredMessage *previous_deferred_message; - BusResult result = BUS_RESULT_FALSE; - BusCynara *cynara; - DBusConnection *connection; -@@ -135,16 +186,54 @@ bus_check_privilege (BusCheck *check, - return BUS_RESULT_FALSE; - } - -- /* ask policy checkers */ --#ifdef DBUS_ENABLE_CYNARA -- cynara = bus_check_get_cynara(check); -- result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient, -- proposed_recipient, privilege, check_type, deferred_message); -+#ifdef DBUS_ENABLE_EMBEDDED_TESTS -+ if (bus_check_test_override) -+ return bus_check_test_override (connection, privilege); - #endif - -- if (result == BUS_RESULT_LATER && deferred_message != NULL) -+ previous_deferred_message = dbus_message_get_data(message, deferred_message_data_slot); -+ /* check if message blocked at sender's queue is being processed */ -+ if (previous_deferred_message != NULL) -+ { -+ if ((check_type & BUS_DEFERRED_MESSAGE_CHECK_SEND) && -+ !(previous_deferred_message->status & BUS_DEFERRED_MESSAGE_CHECK_SEND)) -+ { -+ /** -+ * Message has been deferred due to receive or own rule which means that sending this message -+ * is allowed - it must have been checked previously. -+ * This might happen when client calls RequestName method which depending on security -+ * policy might result in both "can_send" and "can_own" Cynara checks. -+ */ -+ result = BUS_RESULT_TRUE; -+ } -+ else -+ { -+ result = previous_deferred_message->response; -+ if (result == BUS_RESULT_LATER) -+ { -+ /* result is still not known - reuse deferred message object */ -+ if (deferred_message != NULL) -+ *deferred_message = previous_deferred_message; -+ } -+ else -+ { -+ /* result is available - we can remove deferred message from the processed message */ -+ dbus_message_set_data(message, deferred_message_data_slot, NULL, NULL); -+ } -+ } -+ } -+ else - { -- (*deferred_message)->status |= check_type; -+ /* ask policy checkers */ -+#ifdef DBUS_ENABLE_CYNARA -+ cynara = bus_check_get_cynara(check); -+ result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient, -+ proposed_recipient, privilege, check_type, deferred_message); -+#endif -+ if (result == BUS_RESULT_LATER && deferred_message != NULL) -+ { -+ (*deferred_message)->status |= check_type; -+ } - } - return result; - } -@@ -204,6 +293,12 @@ bus_deferred_message_unref (BusDeferredMessage *deferred_message) - } - } - -+BusDeferredMessageStatus -+bus_deferred_message_get_status (BusDeferredMessage *deferred_message) -+{ -+ return deferred_message->status; -+} -+ - void - bus_deferred_message_response_received (BusDeferredMessage *deferred_message, - BusResult result) -diff --git a/bus/check.h b/bus/check.h -index c3fcaf9..f381789 100644 ---- a/bus/check.h -+++ b/bus/check.h -@@ -55,6 +55,7 @@ BusResult bus_check_privilege (BusCheck *check, - BusDeferredMessageStatus check_type, - BusDeferredMessage **deferred_message); - -+ - BusDeferredMessage *bus_deferred_message_new (DBusMessage *message, - DBusConnection *sender, - DBusConnection *addressed_recipient, -@@ -65,4 +66,13 @@ BusDeferredMessage *bus_deferred_message_ref (BusDeferredMessage - void bus_deferred_message_unref (BusDeferredMessage *deferred_message); - void bus_deferred_message_response_received (BusDeferredMessage *deferred_message, - BusResult result); -+void bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message); -+ -+BusDeferredMessageStatus bus_deferred_message_get_status (BusDeferredMessage *deferred_message); -+ -+#ifdef DBUS_ENABLE_EMBEDDED_TESTS -+extern dbus_bool_t (*bus_check_test_override) (DBusConnection *connection, -+ const char *privilege); -+#endif -+ - #endif /* BUS_CHECK_H */ -diff --git a/bus/cynara.c b/bus/cynara.c -index 57a4c45..77aed62 100644 ---- a/bus/cynara.c -+++ b/bus/cynara.c -@@ -36,7 +36,6 @@ - #include <cynara-client-async.h> - #endif - -- - #ifdef DBUS_ENABLE_CYNARA - typedef struct BusCynara - { -diff --git a/bus/dispatch.c b/bus/dispatch.c -index ce4076d..6b0eadc 100644 ---- a/bus/dispatch.c -+++ b/bus/dispatch.c -@@ -81,7 +81,7 @@ send_one_message (DBusConnection *connection, - return TRUE; - } - --dbus_bool_t -+BusResult - bus_dispatch_matches (BusTransaction *transaction, - DBusConnection *sender, - DBusConnection *addressed_recipient, -@@ -117,13 +117,29 @@ bus_dispatch_matches (BusTransaction *transaction, - message, error, - &deferred_message); - if (res == BUS_RESULT_FALSE) -- return FALSE; -+ return BUS_RESULT_FALSE; - else if (res == BUS_RESULT_LATER) - { -- dbus_set_error (error, -- DBUS_ERROR_ACCESS_DENIED, -- "Rejecting message because time is needed to check security policy"); -- return FALSE; -+ BusDeferredMessageStatus status; -+ status = bus_deferred_message_get_status(deferred_message); -+ -+ if (status & BUS_DEFERRED_MESSAGE_CHECK_SEND) -+ { -+ /* send rule result not available - disable dispatching messages from the sender */ -+ bus_deferred_message_disable_sender(deferred_message); -+ return BUS_RESULT_LATER; -+ } -+ else if (status & BUS_DEFERRED_MESSAGE_CHECK_RECEIVE) -+ { -+ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, -+ "Rejecting message because time is needed to check security policy"); -+ return BUS_RESULT_FALSE; -+ } -+ else -+ { -+ _dbus_verbose("deferred message has no status field set to send or receive unexpectedly\n"); -+ return BUS_RESULT_FALSE; -+ } - } - - if (dbus_message_contains_unix_fds (message) && -@@ -134,14 +150,14 @@ bus_dispatch_matches (BusTransaction *transaction, - DBUS_ERROR_NOT_SUPPORTED, - "Tried to send message with Unix file descriptors" - "to a client that doesn't support that."); -- return FALSE; -- } -+ return BUS_RESULT_FALSE; -+ } - - /* Dispatch the message */ - if (!bus_transaction_send (transaction, addressed_recipient, message)) - { - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - } - -@@ -156,7 +172,7 @@ bus_dispatch_matches (BusTransaction *transaction, - &recipients)) - { - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - link = _dbus_list_get_first_link (&recipients); -@@ -178,10 +194,10 @@ bus_dispatch_matches (BusTransaction *transaction, - if (dbus_error_is_set (&tmp_error)) - { - dbus_move_error (&tmp_error, error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - else -- return TRUE; -+ return BUS_RESULT_TRUE; - } - - static DBusHandlerResult -@@ -298,10 +314,12 @@ bus_dispatch (DBusConnection *connection, - } - else if (res == BUS_RESULT_LATER) - { -- dbus_set_error (&error, -- DBUS_ERROR_ACCESS_DENIED, -- "Rejecting message because time is needed to check security policy"); -- _dbus_verbose ("Security policy needs time to check policy. Dropping message\n"); -+ /* Disable dispatching messages from the sender, -+ * roll back and dispatch the message once the policy result is available */ -+ bus_deferred_message_disable_sender(deferred_message); -+ bus_transaction_cancel_and_free (transaction); -+ transaction = NULL; -+ result = DBUS_HANDLER_RESULT_LATER; - goto out; - } - -@@ -366,8 +384,14 @@ bus_dispatch (DBusConnection *connection, - * addressed_recipient == NULL), and match it against other connections' - * match rules. - */ -- if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error)) -- goto out; -+ if (BUS_RESULT_LATER == bus_dispatch_matches (transaction, connection, addressed_recipient, -+ message, &error)) -+ { -+ /* Roll back and dispatch the message once the policy result is available */ -+ bus_transaction_cancel_and_free (transaction); -+ transaction = NULL; -+ result = DBUS_HANDLER_RESULT_LATER; -+ } - - out: - if (dbus_error_is_set (&error)) -@@ -4714,9 +4738,132 @@ bus_dispatch_test_conf_fail (const DBusString *test_data_dir, - return TRUE; - } - -+typedef struct { -+ DBusTimeout *timeout; -+ DBusConnection *connection; -+ dbus_bool_t timedout; -+ int check_counter; -+} BusTestCheckData; -+ -+static BusTestCheckData *cdata; -+ -+static dbus_bool_t -+bus_dispatch_test_check_timeout (void *data) -+{ -+ _dbus_verbose ("timeout triggered - pretend that privilege check result is available\n"); -+ -+ /* should only happen once during the test */ -+ _dbus_assert (!cdata->timedout); -+ cdata->timedout = TRUE; -+ _dbus_connection_enable_dispatch (cdata->connection); -+ -+ /* don't call this again */ -+ _dbus_loop_remove_timeout (bus_connection_get_loop (cdata->connection), -+ cdata->timeout); -+ dbus_connection_unref (cdata->connection); -+ cdata->connection = NULL; -+ return TRUE; -+} -+ -+static dbus_bool_t -+bus_dispatch_test_check_override (DBusConnection *connection, -+ const char *privilege) -+{ -+ _dbus_verbose ("overriding privilege check %s #%d\n", privilege, cdata->check_counter); -+ cdata->check_counter++; -+ if (!cdata->timedout) -+ { -+ dbus_bool_t added; -+ -+ /* Should be the first privilege check for the "Echo" method. */ -+ _dbus_assert (cdata->check_counter == 1); -+ cdata->timeout = _dbus_timeout_new (1, bus_dispatch_test_check_timeout, -+ NULL, NULL); -+ _dbus_assert (cdata->timeout); -+ added = _dbus_loop_add_timeout (bus_connection_get_loop (connection), -+ cdata->timeout); -+ _dbus_assert (added); -+ cdata->connection = connection; -+ dbus_connection_ref (connection); -+ _dbus_connection_disable_dispatch (connection); -+ return BUS_RESULT_LATER; -+ } -+ else -+ { -+ /* Should only be checked one more time, and this time succeeds. */ -+ _dbus_assert (cdata->check_counter == 2); -+ return BUS_RESULT_TRUE; -+ } -+} -+ -+static dbus_bool_t -+bus_dispatch_test_check (const DBusString *test_data_dir) -+{ -+ const char *filename = "valid-config-files/debug-check-some.conf"; -+ BusContext *context; -+ DBusConnection *foo; -+ DBusError error; -+ dbus_bool_t result = TRUE; -+ BusTestCheckData data; -+ -+ /* save the config name for the activation helper */ -+ if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename)) -+ _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG"); -+ -+ dbus_error_init (&error); -+ -+ context = bus_context_new_test (test_data_dir, filename); -+ if (context == NULL) -+ return FALSE; -+ -+ foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); -+ if (foo == NULL) -+ _dbus_assert_not_reached ("could not alloc connection"); -+ -+ if (!bus_setup_debug_client (foo)) -+ _dbus_assert_not_reached ("could not set up connection"); -+ -+ spin_connection_until_authenticated (context, foo); -+ -+ if (!check_hello_message (context, foo)) -+ _dbus_assert_not_reached ("hello message failed"); -+ -+ if (!check_double_hello_message (context, foo)) -+ _dbus_assert_not_reached ("double hello message failed"); -+ -+ if (!check_add_match_all (context, foo)) -+ _dbus_assert_not_reached ("AddMatch message failed"); -+ -+ /* -+ * Cause bus_check_send_privilege() to return BUS_RESULT_LATER in the -+ * first call, then BUS_RESULT_TRUE. -+ */ -+ cdata = &data; -+ memset (cdata, 0, sizeof(*cdata)); -+ bus_check_test_override = bus_dispatch_test_check_override; -+ -+ result = check_existent_service_auto_start (context, foo); -+ -+ _dbus_assert (cdata->check_counter == 2); -+ _dbus_assert (cdata->timedout); -+ _dbus_assert (cdata->timeout); -+ _dbus_assert (!cdata->connection); -+ _dbus_timeout_unref (cdata->timeout); -+ -+ kill_client_connection_unchecked (foo); -+ -+ bus_context_unref (context); -+ -+ return result; -+} -+ - dbus_bool_t - bus_dispatch_test (const DBusString *test_data_dir) - { -+ _dbus_verbose ("<check> tests\n"); -+ if (!bus_dispatch_test_check (test_data_dir)) -+ return FALSE; -+ - /* run normal activation tests */ - _dbus_verbose ("Normal activation tests\n"); - if (!bus_dispatch_test_conf (test_data_dir, -diff --git a/bus/dispatch.h b/bus/dispatch.h -index fb5ba7a..afba6a2 100644 ---- a/bus/dispatch.h -+++ b/bus/dispatch.h -@@ -29,7 +29,7 @@ - - dbus_bool_t bus_dispatch_add_connection (DBusConnection *connection); - void bus_dispatch_remove_connection (DBusConnection *connection); --dbus_bool_t bus_dispatch_matches (BusTransaction *transaction, -+BusResult bus_dispatch_matches (BusTransaction *transaction, - DBusConnection *sender, - DBusConnection *recipient, - DBusMessage *message, -diff --git a/bus/driver.c b/bus/driver.c -index 11706f8..4dbce3d 100644 ---- a/bus/driver.c -+++ b/bus/driver.c -@@ -97,6 +97,7 @@ bus_driver_send_service_owner_changed (const char *service_name, - { - DBusMessage *message; - dbus_bool_t retval; -+ BusResult res; - const char *null_service; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); -@@ -129,7 +130,17 @@ bus_driver_send_service_owner_changed (const char *service_name, - - _dbus_assert (dbus_message_has_signature (message, "sss")); - -- retval = bus_dispatch_matches (transaction, NULL, NULL, message, error); -+ res = bus_dispatch_matches (transaction, NULL, NULL, message, error); -+ if (res == BUS_RESULT_TRUE) -+ retval = TRUE; -+ else if (res == BUS_RESULT_FALSE) -+ retval = FALSE; -+ else if (res == BUS_RESULT_LATER) -+ { -+ /* should never happen */ -+ _dbus_assert_not_reached ("bus_dispatch_matches returned BUS_RESULT_LATER unexpectedly"); -+ retval = FALSE; -+ } - dbus_message_unref (message); - - return retval; -diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h -index 64ef336..4fcd118 100644 ---- a/dbus/dbus-connection-internal.h -+++ b/dbus/dbus-connection-internal.h -@@ -109,6 +109,15 @@ void _dbus_connection_set_pending_fds_function (DBusConnectio - - dbus_bool_t _dbus_connection_get_linux_security_label (DBusConnection *connection, - char **label_p); -+void _dbus_connection_enable_dispatch (DBusConnection *connection); -+void _dbus_connection_disable_dispatch (DBusConnection *connection); -+dbus_bool_t _dbus_connection_putback_message (DBusConnection *connection, -+ DBusMessage *after_message, -+ DBusMessage *message, -+ DBusError *error); -+ -+dbus_bool_t _dbus_connection_remove_message (DBusConnection *connection, -+ DBusMessage *message); - - /* if DBUS_ENABLE_STATS */ - void _dbus_connection_get_stats (DBusConnection *connection, -diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c -index 8952b75..5d8d943 100644 ---- a/dbus/dbus-connection.c -+++ b/dbus/dbus-connection.c -@@ -311,7 +311,8 @@ struct DBusConnection - */ - dbus_bool_t dispatch_acquired; /**< Someone has dispatch path (can drain incoming queue) */ - dbus_bool_t io_path_acquired; /**< Someone has transport io path (can use the transport to read/write messages) */ -- -+ -+ unsigned int dispatch_disabled : 1; /**< if true, then dispatching incoming messages is stopped until enabled again */ - unsigned int shareable : 1; /**< #TRUE if libdbus owns a reference to the connection and can return it from dbus_connection_open() more than once */ - - unsigned int exit_on_disconnect : 1; /**< If #TRUE, exit after handling disconnect signal */ -@@ -439,6 +440,39 @@ _dbus_connection_wakeup_mainloop (DBusConnection *connection) - (*connection->wakeup_main_function) (connection->wakeup_main_data); - } - -+static void -+_dbus_connection_set_dispatch(DBusConnection *connection, -+ dbus_bool_t disabled) -+{ -+ CONNECTION_LOCK (connection); -+ if (connection->dispatch_disabled != disabled) -+ { -+ DBusDispatchStatus status; -+ -+ connection->dispatch_disabled = disabled; -+ status = _dbus_connection_get_dispatch_status_unlocked (connection); -+ _dbus_connection_update_dispatch_status_and_unlock (connection, status); -+ } -+ else -+ { -+ CONNECTION_UNLOCK (connection); -+ } -+} -+ -+ -+void -+_dbus_connection_enable_dispatch (DBusConnection *connection) -+{ -+ _dbus_connection_set_dispatch (connection, FALSE); -+} -+ -+void -+ _dbus_connection_disable_dispatch (DBusConnection *connection) -+{ -+ _dbus_connection_set_dispatch (connection, TRUE); -+} -+ -+ - #ifdef DBUS_ENABLE_EMBEDDED_TESTS - /** - * Gets the locks so we can examine them -@@ -4068,6 +4102,82 @@ _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, - "_dbus_connection_putback_message_link_unlocked"); - } - -+dbus_bool_t -+_dbus_connection_putback_message (DBusConnection *connection, -+ DBusMessage *after_message, -+ DBusMessage *message, -+ DBusError *error) -+{ -+ DBusDispatchStatus status; -+ DBusList *message_link = _dbus_list_alloc_link (message); -+ DBusList *after_link; -+ if (message_link == NULL) -+ { -+ _DBUS_SET_OOM (error); -+ return FALSE; -+ } -+ dbus_message_ref (message); -+ -+ CONNECTION_LOCK (connection); -+ _dbus_connection_acquire_dispatch (connection); -+ HAVE_LOCK_CHECK (connection); -+ -+ after_link = _dbus_list_find_first(&connection->incoming_messages, after_message); -+ _dbus_list_insert_after_link (&connection->incoming_messages, after_link, message_link); -+ connection->n_incoming += 1; -+ -+ _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n", -+ message_link->data, -+ dbus_message_type_to_string (dbus_message_get_type (message_link->data)), -+ dbus_message_get_interface (message_link->data) ? -+ dbus_message_get_interface (message_link->data) : -+ "no interface", -+ dbus_message_get_member (message_link->data) ? -+ dbus_message_get_member (message_link->data) : -+ "no member", -+ dbus_message_get_signature (message_link->data), -+ connection, connection->n_incoming); -+ -+ _dbus_message_trace_ref (message_link->data, -1, -1, -+ "_dbus_connection_putback_message"); -+ -+ _dbus_connection_release_dispatch (connection); -+ -+ status = _dbus_connection_get_dispatch_status_unlocked (connection); -+ _dbus_connection_update_dispatch_status_and_unlock (connection, status); -+ -+ return TRUE; -+} -+ -+dbus_bool_t -+_dbus_connection_remove_message (DBusConnection *connection, -+ DBusMessage *message) -+{ -+ DBusDispatchStatus status; -+ dbus_bool_t removed; -+ -+ CONNECTION_LOCK (connection); -+ _dbus_connection_acquire_dispatch (connection); -+ HAVE_LOCK_CHECK (connection); -+ -+ removed = _dbus_list_remove(&connection->incoming_messages, message); -+ -+ if (removed) -+ { -+ connection->n_incoming -= 1; -+ dbus_message_unref(message); -+ _dbus_verbose ("Message %p removed from incoming queue\n", message); -+ } -+ else -+ _dbus_verbose ("Message %p not found in the incoming queue\n", message); -+ -+ _dbus_connection_release_dispatch (connection); -+ -+ status = _dbus_connection_get_dispatch_status_unlocked (connection); -+ _dbus_connection_update_dispatch_status_and_unlock (connection, status); -+ return removed; -+} -+ - /** - * Returns the first-received message from the incoming message queue, - * removing it from the queue. The caller owns a reference to the -@@ -4251,8 +4361,9 @@ static DBusDispatchStatus - _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) - { - HAVE_LOCK_CHECK (connection); -- -- if (connection->n_incoming > 0) -+ if (connection->dispatch_disabled && dbus_connection_get_is_connected(connection)) -+ return DBUS_DISPATCH_COMPLETE; -+ else if (connection->n_incoming > 0) - return DBUS_DISPATCH_DATA_REMAINS; - else if (!_dbus_transport_queue_messages (connection->transport)) - return DBUS_DISPATCH_NEED_MEMORY; -@@ -4689,6 +4800,8 @@ dbus_connection_dispatch (DBusConnection *connection) - - CONNECTION_LOCK (connection); - -+ if (result == DBUS_HANDLER_RESULT_LATER) -+ goto out; - if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) - { - _dbus_verbose ("No memory\n"); -@@ -4811,9 +4924,11 @@ dbus_connection_dispatch (DBusConnection *connection) - connection); - - out: -- if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) -+ if (result == DBUS_HANDLER_RESULT_LATER || -+ result == DBUS_HANDLER_RESULT_NEED_MEMORY) - { -- _dbus_verbose ("out of memory\n"); -+ if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) -+ _dbus_verbose ("out of memory\n"); - - /* Put message back, and we'll start over. - * Yes this means handlers must be idempotent if they -diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c -index c4c1856..f84918b 100644 ---- a/dbus/dbus-list.c -+++ b/dbus/dbus-list.c -@@ -459,6 +459,35 @@ _dbus_list_remove_last (DBusList **list, - } - - /** -+ * Finds a value in the list. Returns the first link -+ * with value equal to the given data pointer. -+ * This is a linear-time operation. -+ * Returns #NULL if no value found that matches. -+ * -+ * @param list address of the list head. -+ * @param data the value to find. -+ * @returns the link if found -+ */ -+DBusList* -+_dbus_list_find_first (DBusList **list, -+ void *data) -+{ -+ DBusList *link; -+ -+ link = _dbus_list_get_first_link (list); -+ -+ while (link != NULL) -+ { -+ if (link->data == data) -+ return link; -+ -+ link = _dbus_list_get_next_link (list, link); -+ } -+ -+ return NULL; -+} -+ -+/** - * Finds a value in the list. Returns the last link - * with value equal to the given data pointer. - * This is a linear-time operation. -diff --git a/dbus/dbus-list.h b/dbus/dbus-list.h -index 910d738..abe8331 100644 ---- a/dbus/dbus-list.h -+++ b/dbus/dbus-list.h -@@ -59,6 +59,8 @@ dbus_bool_t _dbus_list_remove_last (DBusList **list, - void *data); - void _dbus_list_remove_link (DBusList **list, - DBusList *link); -+DBusList* _dbus_list_find_first (DBusList **list, -+ void *data); - DBusList* _dbus_list_find_last (DBusList **list, - void *data); - void _dbus_list_clear (DBusList **list); -diff --git a/dbus/dbus-shared.h b/dbus/dbus-shared.h -index 6a57670..5371d88 100644 ---- a/dbus/dbus-shared.h -+++ b/dbus/dbus-shared.h -@@ -67,7 +67,8 @@ typedef enum - { - DBUS_HANDLER_RESULT_HANDLED, /**< Message has had its effect - no need to run more handlers. */ - DBUS_HANDLER_RESULT_NOT_YET_HANDLED, /**< Message has not had any effect - see if other handlers want it. */ -- DBUS_HANDLER_RESULT_NEED_MEMORY /**< Need more memory in order to return #DBUS_HANDLER_RESULT_HANDLED or #DBUS_HANDLER_RESULT_NOT_YET_HANDLED. Please try again later with more memory. */ -+ DBUS_HANDLER_RESULT_NEED_MEMORY, /**< Need more memory in order to return #DBUS_HANDLER_RESULT_HANDLED or #DBUS_HANDLER_RESULT_NOT_YET_HANDLED. Please try again later with more memory. */ -+ DBUS_HANDLER_RESULT_LATER /**< Message dispatch deferred due to pending policy check */ - } DBusHandlerResult; - - /* Bus names */ --- -2.1.4 - diff --git a/meta-security/recipes-core/dbus-cynara/dbus/0005-Perform-Cynara-runtime-policy-checks-by-default.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0005-Perform-Cynara-runtime-policy-checks-by-default.patch index d30b2dbf8..d30b2dbf8 100644 --- a/meta-security/recipes-core/dbus-cynara/dbus/0005-Perform-Cynara-runtime-policy-checks-by-default.patch +++ b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0005-Perform-Cynara-runtime-policy-checks-by-default.patch diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0006-Handle-unavailability-of-policy-results-for-broadcas.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0006-Handle-unavailability-of-policy-results-for-broadcas.patch deleted file mode 100644 index 66f4e14e5..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0006-Handle-unavailability-of-policy-results-for-broadcas.patch +++ /dev/null @@ -1,1071 +0,0 @@ -From 1e231194610892dd4360224998d91336097b05a1 Mon Sep 17 00:00:00 2001 -From: Jacek Bukarewicz <j.bukarewicz@samsung.com> -Date: Fri, 28 Nov 2014 12:39:33 +0100 -Subject: [PATCH 6/8] Handle unavailability of policy results for broadcasts - and receive rules - -When message is sent to the addressed recipient and receive rule -result is unavailable we don't want to block the sender -as it most likely will be the privileged service, so instead we queue -it at the recipient. Any further messages sent to it will be queued to -maintain message order. Once the answer from Cynara arrives messages are -dispatched from the recipient queue. In such case full dispatch is -performed - messages are sent to addressed recipient and other -interested connections. -Messages sent to non-addressed recipients (eavesdroppers or broadcast -message recipients) are handled in a similar way. The difference is -that it is not full dispatch meaning message is sent to a single recipient. - -Change-Id: Iecd5395f75a4c7811fa97247a37d8fc4d42e8814 ---- - bus/activation.c | 4 +- - bus/bus.c | 50 +++++++-- - bus/bus.h | 19 ++++ - bus/check.c | 307 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ - bus/check.h | 25 +++++ - bus/connection.c | 166 ++++++++++++++++++++++++++++-- - bus/connection.h | 19 +++- - bus/dispatch.c | 122 ++++++++++++++++++---- - bus/dispatch.h | 11 +- - bus/driver.c | 2 +- - bus/policy.c | 6 ++ - 11 files changed, 685 insertions(+), 46 deletions(-) - -diff --git a/bus/activation.c b/bus/activation.c -index 8c43941..308bf41 100644 ---- a/bus/activation.c -+++ b/bus/activation.c -@@ -1198,7 +1198,7 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation - res = bus_dispatch_matches (transaction, - entry->connection, - addressed_recipient, -- entry->activation_message, &error); -+ entry->activation_message, NULL, &error); - if (res == BUS_RESULT_FALSE) - { - /* If permission is denied, we just want to return the error -@@ -2066,7 +2066,7 @@ bus_activation_activate_service (BusActivation *activation, - entry->systemd_service); - /* Wonderful, systemd is connected, let's just send the msg */ - res = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service), -- message, error); -+ message, NULL, error); - - if (res == BUS_RESULT_TRUE) - retval = TRUE; -diff --git a/bus/bus.c b/bus/bus.c -index ac9ea8d..b478b8e 100644 ---- a/bus/bus.c -+++ b/bus/bus.c -@@ -1704,17 +1704,9 @@ bus_context_check_security_policy (BusContext *context, - } - - /* See if limits on size have been exceeded */ -- if (proposed_recipient && -- ((dbus_connection_get_outgoing_size (proposed_recipient) > context->limits.max_outgoing_bytes) || -- (dbus_connection_get_outgoing_unix_fds (proposed_recipient) > context->limits.max_outgoing_unix_fds))) -- { -- complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED, -- "Rejected: destination has a full message queue", -- 0, message, sender, proposed_recipient, requested_reply, TRUE, NULL, -- error); -- _dbus_verbose ("security policy disallowing message due to full message queue\n"); -+ if (!bus_context_check_recipient_message_limits(context, proposed_recipient, sender, message, -+ requested_reply, error)) - return BUS_RESULT_FALSE; -- } - - /* Record that we will allow a reply here in the future (don't - * bother if the recipient is the bus or this is an eavesdropping -@@ -1769,3 +1761,41 @@ bus_context_check_all_watches (BusContext *context) - _dbus_server_toggle_all_watches (server, enabled); - } - } -+ -+void -+bus_context_complain_about_message (BusContext *context, -+ const char *error_name, -+ const char *complaint, -+ int matched_rules, -+ DBusMessage *message, -+ DBusConnection *sender, -+ DBusConnection *proposed_recipient, -+ dbus_bool_t requested_reply, -+ dbus_bool_t log, -+ const char *privilege, -+ DBusError *error) -+{ -+ complain_about_message(context, error_name, complaint, matched_rules, message, sender, -+ proposed_recipient, requested_reply, log, privilege, error); -+} -+ -+dbus_bool_t bus_context_check_recipient_message_limits (BusContext *context, -+ DBusConnection *recipient, -+ DBusConnection *sender, -+ DBusMessage *message, -+ dbus_bool_t requested_reply, -+ DBusError *error) -+{ -+ if (recipient && -+ ((dbus_connection_get_outgoing_size (recipient) > context->limits.max_outgoing_bytes) || -+ (dbus_connection_get_outgoing_unix_fds (recipient) > context->limits.max_outgoing_unix_fds))) -+ { -+ complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED, -+ "Rejected: destination has a full message queue", -+ 0, message, sender, recipient, requested_reply, TRUE, NULL, -+ error); -+ _dbus_verbose ("security policy disallowing message due to full message queue\n"); -+ return FALSE; -+ } -+ return TRUE; -+} -diff --git a/bus/bus.h b/bus/bus.h -index 78084dd..27a5e49 100644 ---- a/bus/bus.h -+++ b/bus/bus.h -@@ -148,4 +148,23 @@ BusResult bus_context_check_security_policy (BusContext - DBusError *error, - BusDeferredMessage **deferred_message); - -+dbus_bool_t bus_context_check_recipient_message_limits (BusContext *context, -+ DBusConnection *recipient, -+ DBusConnection *sender, -+ DBusMessage *message, -+ dbus_bool_t requested_reply, -+ DBusError *error); -+void bus_context_complain_about_message (BusContext *context, -+ const char *error_name, -+ const char *complaint, -+ int matched_rules, -+ DBusMessage *message, -+ DBusConnection *sender, -+ DBusConnection *proposed_recipient, -+ dbus_bool_t requested_reply, -+ dbus_bool_t log, -+ const char *privilege, -+ DBusError *error); -+ -+ - #endif /* BUS_BUS_H */ -diff --git a/bus/check.c b/bus/check.c -index cd6a74b..733763a 100644 ---- a/bus/check.c -+++ b/bus/check.c -@@ -49,6 +49,9 @@ typedef struct BusDeferredMessage - DBusConnection *sender; - DBusConnection *proposed_recipient; - DBusConnection *addressed_recipient; -+ dbus_bool_t requested_reply; -+ int matched_rules; -+ const char *privilege; - dbus_bool_t full_dispatch; - BusDeferredMessageStatus status; - BusResult response; -@@ -136,6 +139,89 @@ bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message, - } - - static void -+bus_check_queued_message_reply_callback (BusDeferredMessage *deferred_message, -+ BusResult result) -+{ -+ int status; -+ -+ _dbus_verbose("bus_check_queued_message_reply_callback called message=%p\n", deferred_message); -+ -+ if (!bus_connection_is_active(deferred_message->proposed_recipient)) -+ return; -+ -+ status = deferred_message->status; -+ -+ deferred_message->status = 0; /* mark message as not waiting for response */ -+ deferred_message->response = result; -+ -+ /* -+ * If send rule allows us to send message we still need to check receive rules. -+ */ -+ if ((status & BUS_DEFERRED_MESSAGE_CHECK_SEND) && (result == BUS_RESULT_TRUE)) -+ { -+ int toggles; -+ BusContext *context; -+ BusRegistry *registry; -+ BusClientPolicy *recipient_policy; -+ BusDeferredMessage *deferred_message_receive; -+ -+ context = bus_connection_get_context(deferred_message->proposed_recipient); -+ registry = bus_context_get_registry(context); -+ recipient_policy = bus_connection_get_policy(deferred_message->proposed_recipient); -+ -+ deferred_message->response = bus_client_policy_check_can_receive(recipient_policy, registry, -+ deferred_message->requested_reply, deferred_message->sender, -+ deferred_message->addressed_recipient, deferred_message->proposed_recipient, deferred_message->message, -+ &toggles, NULL, &deferred_message_receive); -+ if (deferred_message->response == BUS_RESULT_LATER) -+ { -+ /* replace deferred message associated with send check with the one associated with -+ * receive check */ -+ if (!bus_deferred_message_replace(deferred_message, deferred_message_receive)) -+ { -+ /* failed to replace deferred message (due to oom). Set it to rejected */ -+ deferred_message->response = BUS_RESULT_FALSE; -+ } -+ } -+ } -+ -+ bus_connection_dispatch_deferred(deferred_message->proposed_recipient); -+} -+ -+static void -+queue_deferred_message_cancel_transaction_hook (void *data) -+{ -+ BusDeferredMessage *deferred_message = (BusDeferredMessage *)data; -+ bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message); -+} -+ -+ -+dbus_bool_t -+bus_deferred_message_queue_at_recipient (BusDeferredMessage *deferred_message, -+ BusTransaction *transaction, -+ dbus_bool_t full_dispatch, -+ dbus_bool_t prepend) -+{ -+ _dbus_assert(deferred_message != NULL); -+ _dbus_assert(deferred_message->proposed_recipient != NULL); -+ -+ if (!bus_connection_queue_deferred_message(deferred_message->proposed_recipient, -+ deferred_message, prepend)) -+ return FALSE; -+ -+ if (!bus_transaction_add_cancel_hook(transaction, queue_deferred_message_cancel_transaction_hook, -+ deferred_message, NULL)) -+ { -+ bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message); -+ return FALSE; -+ } -+ deferred_message->response_callback = bus_check_queued_message_reply_callback; -+ deferred_message->full_dispatch = full_dispatch; -+ -+ return TRUE; -+} -+ -+static void - deferred_message_free_function(void *data) - { - BusDeferredMessage *deferred_message = (BusDeferredMessage *)data; -@@ -159,6 +245,20 @@ bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message) - deferred_message->response_callback = bus_check_enable_dispatch_callback; - } - -+void -+bus_deferred_message_set_policy_check_info (BusDeferredMessage *deferred_message, -+ dbus_bool_t requested_reply, -+ int matched_rules, -+ const char *privilege) -+{ -+ _dbus_assert(deferred_message != NULL); -+ -+ deferred_message->requested_reply = requested_reply; -+ deferred_message->matched_rules = matched_rules; -+ deferred_message->privilege = privilege; -+} -+ -+ - #ifdef DBUS_ENABLE_EMBEDDED_TESTS - dbus_bool_t (*bus_check_test_override) (DBusConnection *connection, - const char *privilege); -@@ -257,6 +357,9 @@ BusDeferredMessage *bus_deferred_message_new (DBusMessage *message, - deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL; - deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL; - deferred_message->message = dbus_message_ref(message); -+ deferred_message->requested_reply = FALSE; -+ deferred_message->matched_rules = 0; -+ deferred_message->privilege = NULL; - deferred_message->response = response; - deferred_message->status = 0; - deferred_message->full_dispatch = FALSE; -@@ -293,12 +396,215 @@ bus_deferred_message_unref (BusDeferredMessage *deferred_message) - } - } - -+dbus_bool_t -+bus_deferred_message_check_message_limits (BusDeferredMessage *deferred_message, DBusError *error) -+{ -+ BusContext *context = bus_connection_get_context(deferred_message->proposed_recipient); -+ -+ return bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient, -+ deferred_message->sender, deferred_message->message, deferred_message->requested_reply, -+ error); -+} -+ -+dbus_bool_t -+bus_deferred_message_expect_method_reply(BusDeferredMessage *deferred_message, BusTransaction *transaction, DBusError *error) -+{ -+ int type = dbus_message_get_type(deferred_message->message); -+ if (type == DBUS_MESSAGE_TYPE_METHOD_CALL && -+ deferred_message->sender && -+ deferred_message->addressed_recipient && -+ deferred_message->addressed_recipient == deferred_message->proposed_recipient && /* not eavesdropping */ -+ !bus_connections_expect_reply (bus_connection_get_connections (deferred_message->sender), -+ transaction, -+ deferred_message->sender, deferred_message->addressed_recipient, -+ deferred_message->message, error)) -+ { -+ _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n"); -+ return FALSE; -+ } -+ return TRUE; -+} -+ -+void -+bus_deferred_message_create_error(BusDeferredMessage *deferred_message, -+ const char *error_message, DBusError *error) -+{ -+ BusContext *context; -+ _dbus_assert (deferred_message->status == 0 && deferred_message->response == BUS_RESULT_FALSE); -+ -+ if (deferred_message->sender == NULL) -+ return; /* error won't be sent to bus driver anyway */ -+ -+ context = bus_connection_get_context(deferred_message->sender); -+ bus_context_complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected message", -+ deferred_message->matched_rules, deferred_message->message, deferred_message->sender, -+ deferred_message->proposed_recipient, deferred_message->requested_reply, FALSE, -+ deferred_message->privilege, error); -+} -+ -+BusResult -+bus_deferred_message_dispatch (BusDeferredMessage *deferred_message) -+{ -+ BusContext *context = bus_connection_get_context (deferred_message->proposed_recipient); -+ BusTransaction *transaction = bus_transaction_new (context); -+ BusResult result = BUS_RESULT_TRUE; -+ DBusError error; -+ -+ if (transaction == NULL) -+ { -+ return BUS_RESULT_FALSE; -+ } -+ -+ dbus_error_init(&error); -+ -+ if (!deferred_message->full_dispatch) -+ { -+ result = deferred_message->response; -+ if (result == BUS_RESULT_TRUE) -+ { -+ if (!bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient, -+ deferred_message->sender, deferred_message->message, deferred_message->requested_reply, &error)) -+ result = BUS_RESULT_FALSE; -+ } -+ else if (result == BUS_RESULT_LATER) -+ { -+ BusDeferredMessage *deferred_message2; -+ result = bus_context_check_security_policy (context, transaction, -+ deferred_message->sender, -+ deferred_message->addressed_recipient, -+ deferred_message->proposed_recipient, -+ deferred_message->message, NULL, -+ &deferred_message2); -+ -+ if (result == BUS_RESULT_LATER) -+ { -+ /* prepend at recipient */ -+ if (!bus_deferred_message_queue_at_recipient(deferred_message2, transaction, -+ FALSE, TRUE)) -+ result = BUS_RESULT_FALSE; -+ } -+ } -+ -+ /* silently drop messages on access denial */ -+ if (result == BUS_RESULT_TRUE) -+ { -+ if (!bus_transaction_send (transaction, deferred_message->proposed_recipient, deferred_message->message, TRUE)) -+ result = BUS_RESULT_FALSE; -+ } -+ -+ bus_transaction_execute_and_free(transaction); -+ -+ goto out; -+ } -+ -+ /* do not attempt to send message if sender has disconnected */ -+ if (deferred_message->sender != NULL && !bus_connection_is_active(deferred_message->sender)) -+ { -+ bus_transaction_cancel_and_free(transaction); -+ result = BUS_RESULT_FALSE; -+ goto out; -+ } -+ -+ result = bus_dispatch_matches(transaction, deferred_message->sender, -+ deferred_message->addressed_recipient, deferred_message->message, deferred_message, &error); -+ -+ if (result == BUS_RESULT_LATER) -+ { -+ /* Message deferring was already done in bus_dispatch_matches */ -+ bus_transaction_cancel_and_free(transaction); -+ goto out; -+ } -+ -+ /* this part is a copy & paste from bus_dispatch function. Probably can be moved to a function */ -+ if (dbus_error_is_set (&error)) -+ { -+ if (!dbus_connection_get_is_connected (deferred_message->sender)) -+ { -+ /* If we disconnected it, we won't bother to send it any error -+ * messages. -+ */ -+ _dbus_verbose ("Not sending error to connection we disconnected\n"); -+ } -+ else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) -+ { -+ bus_connection_send_oom_error (deferred_message->sender, deferred_message->message); -+ -+ /* cancel transaction due to OOM */ -+ if (transaction != NULL) -+ { -+ bus_transaction_cancel_and_free (transaction); -+ transaction = NULL; -+ } -+ } -+ else -+ { -+ /* Try to send the real error, if no mem to do that, send -+ * the OOM error -+ */ -+ _dbus_assert (transaction != NULL); -+ if (!bus_transaction_send_error_reply (transaction, deferred_message->sender, -+ &error, deferred_message->message)) -+ { -+ bus_connection_send_oom_error (deferred_message->sender, deferred_message->message); -+ -+ /* cancel transaction due to OOM */ -+ if (transaction != NULL) -+ { -+ bus_transaction_cancel_and_free (transaction); -+ transaction = NULL; -+ } -+ } -+ } -+ } -+ -+ if (transaction != NULL) -+ { -+ bus_transaction_execute_and_free (transaction); -+ } -+ -+out: -+ dbus_error_free(&error); -+ -+ return result; -+} -+ -+dbus_bool_t -+bus_deferred_message_replace (BusDeferredMessage *old_message, BusDeferredMessage *new_message) -+{ -+ if (bus_connection_replace_deferred_message(old_message->proposed_recipient, -+ old_message, new_message)) -+ { -+ new_message->response_callback = old_message->response_callback; -+ new_message->full_dispatch = old_message->full_dispatch; -+ return TRUE; -+ } -+ return FALSE; -+} -+ -+dbus_bool_t -+bus_deferred_message_waits_for_check(BusDeferredMessage *deferred_message) -+{ -+ return deferred_message->status != 0; -+} -+ -+DBusConnection * -+bus_deferred_message_get_recipient(BusDeferredMessage *deferred_message) -+{ -+ return deferred_message->proposed_recipient; -+} -+ - BusDeferredMessageStatus - bus_deferred_message_get_status (BusDeferredMessage *deferred_message) - { - return deferred_message->status; - } - -+BusResult -+bus_deferred_message_get_response (BusDeferredMessage *deferred_message) -+{ -+ return deferred_message->response; -+} -+ - void - bus_deferred_message_response_received (BusDeferredMessage *deferred_message, - BusResult result) -@@ -308,3 +614,4 @@ bus_deferred_message_response_received (BusDeferredMessage *deferred_message, - deferred_message->response_callback(deferred_message, result); - } - } -+ -diff --git a/bus/check.h b/bus/check.h -index f381789..3c6b2a1 100644 ---- a/bus/check.h -+++ b/bus/check.h -@@ -64,12 +64,37 @@ BusDeferredMessage *bus_deferred_message_new (DBusMessage *messag - - BusDeferredMessage *bus_deferred_message_ref (BusDeferredMessage *deferred_message); - void bus_deferred_message_unref (BusDeferredMessage *deferred_message); -+BusResult bus_deferred_message_dispatch (BusDeferredMessage *deferred_message); -+dbus_bool_t bus_deferred_message_waits_for_check (BusDeferredMessage *deferred_message); -+DBusConnection *bus_deferred_message_get_recipient (BusDeferredMessage *deferred_message); - void bus_deferred_message_response_received (BusDeferredMessage *deferred_message, - BusResult result); -+dbus_bool_t bus_deferred_message_queue_at_recipient (BusDeferredMessage *deferred_message, -+ BusTransaction *transaction, -+ dbus_bool_t full_dispatch, -+ dbus_bool_t prepend); -+dbus_bool_t bus_deferred_message_replace (BusDeferredMessage *old_message, -+ BusDeferredMessage *new_message); - void bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message); -+BusResult bus_deferred_message_get_response (BusDeferredMessage *deferred_message); - - BusDeferredMessageStatus bus_deferred_message_get_status (BusDeferredMessage *deferred_message); - -+ -+dbus_bool_t bus_deferred_message_expect_method_reply (BusDeferredMessage *deferred_message, -+ BusTransaction *transaction, -+ DBusError *error); -+void bus_deferred_message_create_error (BusDeferredMessage *deferred_message, -+ const char *error_message, -+ DBusError *error); -+void bus_deferred_message_set_policy_check_info (BusDeferredMessage *deferred_message, -+ dbus_bool_t requested_reply, -+ int matched_rules, -+ const char *privilege); -+dbus_bool_t bus_deferred_message_check_message_limits (BusDeferredMessage *deferred_message, -+ DBusError *error); -+ -+ - #ifdef DBUS_ENABLE_EMBEDDED_TESTS - extern dbus_bool_t (*bus_check_test_override) (DBusConnection *connection, - const char *privilege); -diff --git a/bus/connection.c b/bus/connection.c -index a6d87e5..d2ebe82 100644 ---- a/bus/connection.c -+++ b/bus/connection.c -@@ -30,10 +30,12 @@ - #include "signals.h" - #include "expirelist.h" - #include "selinux.h" -+#include "check.h" - #include <dbus/dbus-list.h> - #include <dbus/dbus-hash.h> - #include <dbus/dbus-timeout.h> - #include <dbus/dbus-connection-internal.h> -+#include <dbus/dbus-message-internal.h> - #ifdef DBUS_ENABLE_CYNARA - #include <stdlib.h> - #include <cynara-session.h> -@@ -95,6 +97,7 @@ typedef struct - DBusMessage *oom_message; - DBusPreallocatedSend *oom_preallocated; - BusClientPolicy *policy; -+ DBusList *deferred_messages; /**< Queue of messages deferred due to pending policy check */ - - char *cached_loginfo_string; - BusSELinuxID *selinux_id; -@@ -256,6 +259,8 @@ bus_connection_disconnected (DBusConnection *connection) - bus_transaction_execute_and_free (transaction); - } - -+ bus_connection_clear_deferred_messages(connection); -+ - bus_dispatch_remove_connection (connection); - - /* no more watching */ -@@ -2132,6 +2137,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction, - DBusMessage *message) - { - BusResult res; -+ BusDeferredMessage *deferred_message; - /* We have to set the sender to the driver, and have - * to check security policy since it was not done in - * dispatch.c -@@ -2163,23 +2169,25 @@ bus_transaction_send_from_driver (BusTransaction *transaction, - res = bus_context_check_security_policy (bus_transaction_get_context (transaction), - transaction, - NULL, connection, connection, message, NULL, -- NULL); -+ &deferred_message); - - if (res == BUS_RESULT_FALSE) - return TRUE; - else if (res == BUS_RESULT_LATER) - { -- _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n"); -- return TRUE; -+ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, FALSE, FALSE)) -+ return FALSE; -+ return TRUE; /* pretend to have sent it */ - } - -- return bus_transaction_send (transaction, connection, message); -+ return bus_transaction_send (transaction, connection, message, FALSE); - } - - dbus_bool_t - bus_transaction_send (BusTransaction *transaction, - DBusConnection *connection, -- DBusMessage *message) -+ DBusMessage *message, -+ dbus_bool_t deferred_dispatch) - { - MessageToSend *to_send; - BusConnectionData *d; -@@ -2205,7 +2213,28 @@ bus_transaction_send (BusTransaction *transaction, - - d = BUS_CONNECTION_DATA (connection); - _dbus_assert (d != NULL); -- -+ -+ if (!deferred_dispatch && d->deferred_messages != NULL) -+ { -+ BusDeferredMessage *deferred_message; -+ dbus_bool_t success; -+ /* sender and addressed recipient are not required at this point as we only need to send message -+ * to a single recipient without performing policy check. */ -+ deferred_message = bus_deferred_message_new (message, -+ NULL, -+ NULL, -+ connection, -+ BUS_RESULT_TRUE); -+ if (deferred_message == NULL) -+ return FALSE; -+ -+ success = bus_deferred_message_queue_at_recipient(deferred_message, transaction, -+ FALSE, FALSE); -+ bus_deferred_message_unref(deferred_message); -+ -+ return success; -+ } -+ - to_send = dbus_new (MessageToSend, 1); - if (to_send == NULL) - { -@@ -2457,6 +2486,131 @@ bus_transaction_add_cancel_hook (BusTransaction *transaction, - return TRUE; - } - -+void -+bus_connection_dispatch_deferred (DBusConnection *connection) -+{ -+ BusDeferredMessage *message; -+ -+ _dbus_return_if_fail (connection != NULL); -+ -+ while ((message = bus_connection_pop_deferred_message(connection)) != NULL) -+ { -+ bus_deferred_message_dispatch(message); -+ bus_deferred_message_unref(message); -+ } -+} -+ -+dbus_bool_t -+bus_connection_has_deferred_messages (DBusConnection *connection) -+{ -+ BusConnectionData *d = BUS_CONNECTION_DATA(connection); -+ return d->deferred_messages != NULL ? TRUE : FALSE; -+} -+ -+dbus_bool_t -+bus_connection_queue_deferred_message (DBusConnection *connection, -+ BusDeferredMessage *message, -+ dbus_bool_t prepend) -+{ -+ BusConnectionData *d = BUS_CONNECTION_DATA(connection); -+ dbus_bool_t success; -+ if (prepend) -+ success = _dbus_list_prepend(&d->deferred_messages, message); -+ else -+ success = _dbus_list_append(&d->deferred_messages, message); -+ -+ if (success) -+ { -+ bus_deferred_message_ref(message); -+ return TRUE; -+ } -+ -+ return FALSE; -+} -+ -+dbus_bool_t -+bus_connection_replace_deferred_message (DBusConnection *connection, -+ BusDeferredMessage *oldMessage, -+ BusDeferredMessage *newMessage) -+{ -+ DBusList *link; -+ BusConnectionData *d = BUS_CONNECTION_DATA(connection); -+ -+ link = _dbus_list_find_first(&d->deferred_messages, oldMessage); -+ if (link == NULL) -+ return FALSE; -+ -+ if (!_dbus_list_insert_after(&d->deferred_messages, link, newMessage)) -+ return FALSE; -+ -+ bus_deferred_message_ref(newMessage); -+ _dbus_list_remove_link(&d->deferred_messages, link); -+ bus_deferred_message_unref(oldMessage); -+ return TRUE; -+} -+ -+BusDeferredMessage * -+bus_connection_pop_deferred_message (DBusConnection *connection) -+{ -+ DBusList *link; -+ BusDeferredMessage *message; -+ BusConnectionData *d = BUS_CONNECTION_DATA(connection); -+ -+ link =_dbus_list_get_first_link(&d->deferred_messages); -+ if (link != NULL) -+ { -+ message = link->data; -+ if (!bus_deferred_message_waits_for_check(message)) -+ { -+ _dbus_list_remove_link(&d->deferred_messages, link); -+ return message; -+ } -+ } -+ -+ return NULL; -+} -+ -+dbus_bool_t -+bus_connection_putback_deferred_message (DBusConnection *connection, BusDeferredMessage *message) -+{ -+ BusConnectionData *d = BUS_CONNECTION_DATA(connection); -+ if (_dbus_list_prepend(&d->deferred_messages, message)) -+ { -+ return TRUE; -+ } -+ return FALSE; -+} -+ -+void -+bus_connection_clear_deferred_messages (DBusConnection *connection) -+{ -+ BusConnectionData *d = BUS_CONNECTION_DATA(connection); -+ DBusList *link; -+ DBusList *next; -+ BusDeferredMessage *message; -+ -+ link =_dbus_list_get_first_link(&d->deferred_messages); -+ while (link != NULL) -+ { -+ next = _dbus_list_get_next_link (&d->deferred_messages, link); -+ message = link->data; -+ -+ bus_deferred_message_unref(message); -+ _dbus_list_remove_link(&d->deferred_messages, link); -+ -+ link = next; -+ } -+} -+ -+void -+bus_connection_remove_deferred_message (DBusConnection *connection, -+ BusDeferredMessage *message) -+{ -+ BusConnectionData *d = BUS_CONNECTION_DATA(connection); -+ if (_dbus_list_remove(&d->deferred_messages, message)) -+ bus_deferred_message_unref(message); -+} -+ - int - bus_connections_get_n_active (BusConnections *connections) - { -diff --git a/bus/connection.h b/bus/connection.h -index 7433746..8d49b25 100644 ---- a/bus/connection.h -+++ b/bus/connection.h -@@ -82,6 +82,22 @@ dbus_bool_t bus_connection_preallocate_oom_error (DBusConnection *connection); - void bus_connection_send_oom_error (DBusConnection *connection, - DBusMessage *in_reply_to); - -+dbus_bool_t bus_connection_has_deferred_messages (DBusConnection *connection); -+dbus_bool_t bus_connection_queue_deferred_message (DBusConnection *connection, -+ BusDeferredMessage *message, -+ dbus_bool_t prepend); -+BusDeferredMessage *bus_connection_pop_deferred_message (DBusConnection *connection); -+dbus_bool_t bus_connection_putback_deferred_message (DBusConnection *connection, -+ BusDeferredMessage *message); -+void bus_connection_remove_deferred_message (DBusConnection *connection, -+ BusDeferredMessage *message); -+dbus_bool_t bus_connection_replace_deferred_message (DBusConnection *connection, -+ BusDeferredMessage *oldMessage, -+ BusDeferredMessage *newMessage); -+void bus_connection_dispatch_deferred (DBusConnection *connection); -+void bus_connection_clear_deferred_messages (DBusConnection *connection); -+ -+ - /* called by signals.c */ - dbus_bool_t bus_connection_add_match_rule (DBusConnection *connection, - BusMatchRule *rule); -@@ -129,7 +145,8 @@ BusTransaction* bus_transaction_new (BusContext * - BusContext* bus_transaction_get_context (BusTransaction *transaction); - dbus_bool_t bus_transaction_send (BusTransaction *transaction, - DBusConnection *connection, -- DBusMessage *message); -+ DBusMessage *message, -+ dbus_bool_t deferred_dispatch); - dbus_bool_t bus_transaction_send_from_driver (BusTransaction *transaction, - DBusConnection *connection, - DBusMessage *message); -diff --git a/bus/dispatch.c b/bus/dispatch.c -index 6b0eadc..9972e76 100644 ---- a/bus/dispatch.c -+++ b/bus/dispatch.c -@@ -33,8 +33,10 @@ - #include "utils.h" - #include "bus.h" - #include "signals.h" -+#include "dispatch.h" - #include "test.h" - #include <dbus/dbus-internals.h> -+#include <dbus/dbus-connection-internal.h> - #include <dbus/dbus-misc.h> - #include <string.h> - -@@ -63,16 +65,26 @@ send_one_message (DBusConnection *connection, - result = bus_context_check_security_policy (context, transaction, sender, addressed_recipient, - connection, message, NULL, &deferred_message); - -- if (result != BUS_RESULT_TRUE) -+ if (result == BUS_RESULT_FALSE) - return TRUE; /* silently don't send it */ - - if (dbus_message_contains_unix_fds(message) && - !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD)) - return TRUE; /* silently don't send it */ - -+ if (result == BUS_RESULT_LATER) -+ { -+ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, FALSE, FALSE)) -+ { -+ BUS_SET_OOM (error); -+ return FALSE; -+ } -+ return TRUE; /* pretend to have sent it */ -+ } -+ - if (!bus_transaction_send (transaction, - connection, -- message)) -+ message, FALSE)) - { - BUS_SET_OOM (error); - return FALSE; -@@ -82,11 +94,12 @@ send_one_message (DBusConnection *connection, - } - - BusResult --bus_dispatch_matches (BusTransaction *transaction, -- DBusConnection *sender, -- DBusConnection *addressed_recipient, -- DBusMessage *message, -- DBusError *error) -+bus_dispatch_matches (BusTransaction *transaction, -+ DBusConnection *sender, -+ DBusConnection *addressed_recipient, -+ DBusMessage *message, -+ BusDeferredMessage *dispatched_deferred_message, -+ DBusError *error) - { - DBusError tmp_error; - BusConnections *connections; -@@ -110,17 +123,78 @@ bus_dispatch_matches (BusTransaction *transaction, - /* First, send the message to the addressed_recipient, if there is one. */ - if (addressed_recipient != NULL) - { -- BusResult res; -- res = bus_context_check_security_policy (context, transaction, -- sender, addressed_recipient, -- addressed_recipient, -- message, error, -- &deferred_message); -- if (res == BUS_RESULT_FALSE) -+ BusResult result; -+ /* To maintain message order message needs to be appended at the recipient if there are already -+ * deferred messages and we are not doing deferred dispatch -+ */ -+ if (dispatched_deferred_message == NULL && bus_connection_has_deferred_messages(addressed_recipient)) -+ { -+ deferred_message = bus_deferred_message_new(message, sender, -+ addressed_recipient, addressed_recipient, BUS_RESULT_LATER); -+ -+ if (deferred_message == NULL) -+ { -+ BUS_SET_OOM(error); -+ return BUS_RESULT_FALSE; -+ } -+ -+ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, TRUE, FALSE)) -+ { -+ bus_deferred_message_unref(deferred_message); -+ BUS_SET_OOM(error); -+ return BUS_RESULT_FALSE; -+ } -+ -+ bus_deferred_message_unref(deferred_message); -+ return BUS_RESULT_TRUE; /* pretend to have sent it */ -+ } -+ -+ if (dispatched_deferred_message != NULL) -+ { -+ result = bus_deferred_message_get_response(dispatched_deferred_message); -+ if (result == BUS_RESULT_TRUE) -+ { -+ /* if we know the result of policy check we still need to check if message limits -+ * are not exceeded. It is also required to add entry in expected replies list if -+ * this is a method call -+ */ -+ if (!bus_deferred_message_check_message_limits(dispatched_deferred_message, error)) -+ return BUS_RESULT_FALSE; -+ -+ if (!bus_deferred_message_expect_method_reply(dispatched_deferred_message, transaction, error)) -+ return BUS_RESULT_FALSE; -+ } -+ else if (result == BUS_RESULT_FALSE) -+ { -+ bus_deferred_message_create_error(dispatched_deferred_message, "Rejected message", error); -+ return BUS_RESULT_FALSE; -+ } -+ } -+ else -+ result = BUS_RESULT_LATER; -+ -+ if (result == BUS_RESULT_LATER) -+ result = bus_context_check_security_policy(context, transaction, -+ sender, addressed_recipient, addressed_recipient, message, error, -+ &deferred_message); -+ -+ if (result == BUS_RESULT_FALSE) - return BUS_RESULT_FALSE; -- else if (res == BUS_RESULT_LATER) -+ else if (result == BUS_RESULT_LATER) - { - BusDeferredMessageStatus status; -+ -+ if (dispatched_deferred_message != NULL) -+ { -+ /* for deferred dispatch prepend message at the recipient */ -+ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, TRUE, TRUE)) -+ { -+ BUS_SET_OOM(error); -+ return BUS_RESULT_FALSE; -+ } -+ return BUS_RESULT_TRUE; /* pretend to have sent it */ -+ } -+ - status = bus_deferred_message_get_status(deferred_message); - - if (status & BUS_DEFERRED_MESSAGE_CHECK_SEND) -@@ -131,13 +205,18 @@ bus_dispatch_matches (BusTransaction *transaction, - } - else if (status & BUS_DEFERRED_MESSAGE_CHECK_RECEIVE) - { -- dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, -- "Rejecting message because time is needed to check security policy"); -- return BUS_RESULT_FALSE; -+ /* receive rule result not available - queue message at the recipient */ -+ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, TRUE, FALSE)) -+ { -+ BUS_SET_OOM(error); -+ return BUS_RESULT_FALSE; -+ } -+ -+ return BUS_RESULT_TRUE; /* pretend to have sent it */ - } - else - { -- _dbus_verbose("deferred message has no status field set to send or receive unexpectedly\n"); -+ _dbus_verbose("deferred message has no status field set unexpectedly\n"); - return BUS_RESULT_FALSE; - } - } -@@ -154,7 +233,8 @@ bus_dispatch_matches (BusTransaction *transaction, - } - - /* Dispatch the message */ -- if (!bus_transaction_send (transaction, addressed_recipient, message)) -+ if (!bus_transaction_send(transaction, addressed_recipient, message, -+ dispatched_deferred_message != NULL ? TRUE : FALSE)) - { - BUS_SET_OOM (error); - return BUS_RESULT_FALSE; -@@ -385,7 +465,7 @@ bus_dispatch (DBusConnection *connection, - * match rules. - */ - if (BUS_RESULT_LATER == bus_dispatch_matches (transaction, connection, addressed_recipient, -- message, &error)) -+ message, NULL, &error)) - { - /* Roll back and dispatch the message once the policy result is available */ - bus_transaction_cancel_and_free (transaction); -diff --git a/bus/dispatch.h b/bus/dispatch.h -index afba6a2..f6102e8 100644 ---- a/bus/dispatch.h -+++ b/bus/dispatch.h -@@ -29,10 +29,11 @@ - - dbus_bool_t bus_dispatch_add_connection (DBusConnection *connection); - void bus_dispatch_remove_connection (DBusConnection *connection); --BusResult bus_dispatch_matches (BusTransaction *transaction, -- DBusConnection *sender, -- DBusConnection *recipient, -- DBusMessage *message, -- DBusError *error); -+BusResult bus_dispatch_matches (BusTransaction *transaction, -+ DBusConnection *sender, -+ DBusConnection *recipient, -+ DBusMessage *message, -+ BusDeferredMessage *dispatched_deferred_message, -+ DBusError *error); - - #endif /* BUS_DISPATCH_H */ -diff --git a/bus/driver.c b/bus/driver.c -index 4dbce3d..2fb1385 100644 ---- a/bus/driver.c -+++ b/bus/driver.c -@@ -130,7 +130,7 @@ bus_driver_send_service_owner_changed (const char *service_name, - - _dbus_assert (dbus_message_has_signature (message, "sss")); - -- res = bus_dispatch_matches (transaction, NULL, NULL, message, error); -+ res = bus_dispatch_matches (transaction, NULL, NULL, message, NULL, error); - if (res == BUS_RESULT_TRUE) - retval = TRUE; - else if (res == BUS_RESULT_FALSE) -diff --git a/bus/policy.c b/bus/policy.c -index ec888df..448147f 100644 ---- a/bus/policy.c -+++ b/bus/policy.c -@@ -1071,6 +1071,9 @@ bus_client_policy_check_can_send (DBusConnection *sender, - - result = bus_check_privilege(check, message, sender, addressed_recipient, receiver, - privilege, BUS_DEFERRED_MESSAGE_CHECK_SEND, deferred_message); -+ if (result == BUS_RESULT_LATER && deferred_message != NULL) -+ bus_deferred_message_set_policy_check_info(*deferred_message, requested_reply, -+ *toggles, privilege); - } - else - privilege = NULL; -@@ -1305,6 +1308,9 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, - - result = bus_check_privilege(check, message, sender, addressed_recipient, proposed_recipient, - privilege, BUS_DEFERRED_MESSAGE_CHECK_RECEIVE, deferred_message); -+ if (result == BUS_RESULT_LATER && deferred_message != NULL) -+ bus_deferred_message_set_policy_check_info(*deferred_message, requested_reply, -+ *toggles, privilege); - } - else - privilege = NULL; --- -2.1.4 - diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0007-Add-own-rule-result-unavailability-handling.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0007-Add-own-rule-result-unavailability-handling.patch deleted file mode 100644 index e1b1e62f1..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0007-Add-own-rule-result-unavailability-handling.patch +++ /dev/null @@ -1,1142 +0,0 @@ -From 35ef89cd6777ea2430077fc621d21bd01df92349 Mon Sep 17 00:00:00 2001 -From: Jacek Bukarewicz <j.bukarewicz@samsung.com> -Date: Thu, 27 Nov 2014 11:26:21 +0100 -Subject: [PATCH 7/8] Add own rule result unavailability handling - -Own rule result unavailability is handled like send rules - dispatching -messages from the sender is blocked and resumed when result becomes -available. - -Handler of "RequestName" method needs to return BUS_RESULT_LATER when -policy result is not known therefore its return type is modified. -Since bus message handlers are put into function pointer array other -message handler function singatures are also affected. - -Change-Id: I4c2cbd4585e41fccd8a30f825a8f0d342ab56755 ---- - bus/dispatch.c | 11 ++- - bus/driver.c | 227 ++++++++++++++++++++++++++++++--------------------------- - bus/driver.h | 2 +- - bus/policy.c | 51 ++++++++++--- - bus/policy.h | 6 +- - bus/services.c | 26 +++++-- - bus/services.h | 3 +- - bus/stats.c | 16 ++-- - 8 files changed, 204 insertions(+), 138 deletions(-) - -diff --git a/bus/dispatch.c b/bus/dispatch.c -index 9972e76..d3b970f 100644 ---- a/bus/dispatch.c -+++ b/bus/dispatch.c -@@ -404,8 +404,17 @@ bus_dispatch (DBusConnection *connection, - } - - _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS); -- if (!bus_driver_handle_message (connection, transaction, message, &error)) -+ res = bus_driver_handle_message (connection, transaction, message, &error); -+ if (res == BUS_RESULT_FALSE) - goto out; -+ else if (res == BUS_RESULT_LATER) -+ { -+ /* connection has been disabled in message handler */ -+ bus_transaction_cancel_and_free (transaction); -+ transaction = NULL; -+ result = DBUS_HANDLER_RESULT_LATER; -+ goto out; -+ } - } - else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */ - { -diff --git a/bus/driver.c b/bus/driver.c -index 2fb1385..9708f49 100644 ---- a/bus/driver.c -+++ b/bus/driver.c -@@ -297,7 +297,7 @@ create_unique_client_name (BusRegistry *registry, - return TRUE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_hello (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -305,7 +305,7 @@ bus_driver_handle_hello (DBusConnection *connection, - { - DBusString unique_name; - BusService *service; -- dbus_bool_t retval; -+ BusResult retval; - BusRegistry *registry; - BusConnections *connections; - -@@ -316,7 +316,7 @@ bus_driver_handle_hello (DBusConnection *connection, - /* We already handled an Hello message for this connection. */ - dbus_set_error (error, DBUS_ERROR_FAILED, - "Already handled an Hello message"); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - /* Note that when these limits are exceeded we don't disconnect the -@@ -330,16 +330,16 @@ bus_driver_handle_hello (DBusConnection *connection, - error)) - { - _DBUS_ASSERT_ERROR_IS_SET (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - if (!_dbus_string_init (&unique_name)) - { - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - -- retval = FALSE; -+ retval = BUS_RESULT_FALSE; - - registry = bus_connection_get_registry (connection); - -@@ -372,7 +372,7 @@ bus_driver_handle_hello (DBusConnection *connection, - goto out_0; - - _dbus_assert (bus_connection_is_active (connection)); -- retval = TRUE; -+ retval = BUS_RESULT_TRUE; - - out_0: - _dbus_string_free (&unique_name); -@@ -424,7 +424,7 @@ bus_driver_send_welcome_message (DBusConnection *connection, - } - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_list_services (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -446,14 +446,14 @@ bus_driver_handle_list_services (DBusConnection *connection, - if (reply == NULL) - { - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - if (!bus_registry_list_services (registry, &services, &len)) - { - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - dbus_message_iter_init_append (reply, &iter); -@@ -465,7 +465,7 @@ bus_driver_handle_list_services (DBusConnection *connection, - dbus_free_string_array (services); - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - { -@@ -477,7 +477,7 @@ bus_driver_handle_list_services (DBusConnection *connection, - dbus_free_string_array (services); - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - } - -@@ -490,7 +490,7 @@ bus_driver_handle_list_services (DBusConnection *connection, - dbus_free_string_array (services); - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - ++i; - } -@@ -501,23 +501,23 @@ bus_driver_handle_list_services (DBusConnection *connection, - { - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - if (!bus_transaction_send_from_driver (transaction, connection, reply)) - { - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - else - { - dbus_message_unref (reply); -- return TRUE; -+ return BUS_RESULT_TRUE; - } - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_list_activatable_services (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -539,14 +539,14 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, - if (reply == NULL) - { - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - if (!bus_activation_list_services (activation, &services, &len)) - { - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - dbus_message_iter_init_append (reply, &iter); -@@ -558,7 +558,7 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, - dbus_free_string_array (services); - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - { -@@ -570,7 +570,7 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, - dbus_free_string_array (services); - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - } - -@@ -583,7 +583,7 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, - dbus_free_string_array (services); - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - ++i; - } -@@ -594,23 +594,23 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, - { - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - if (!bus_transaction_send_from_driver (transaction, connection, reply)) - { - dbus_message_unref (reply); - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - else - { - dbus_message_unref (reply); -- return TRUE; -+ return BUS_RESULT_TRUE; - } - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_acquire_service (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -621,7 +621,8 @@ bus_driver_handle_acquire_service (DBusConnection *connection, - const char *name; - dbus_uint32_t service_reply; - dbus_uint32_t flags; -- dbus_bool_t retval; -+ BusResult retval; -+ BusResult res; - BusRegistry *registry; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); -@@ -632,20 +633,24 @@ bus_driver_handle_acquire_service (DBusConnection *connection, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_UINT32, &flags, - DBUS_TYPE_INVALID)) -- return FALSE; -+ return BUS_RESULT_FALSE; - - _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags); - -- retval = FALSE; -+ retval = BUS_RESULT_FALSE; - reply = NULL; - - _dbus_string_init_const (&service_name, name); - -- if (!bus_registry_acquire_service (registry, connection, -- &service_name, flags, -- &service_reply, transaction, -- error)) -- goto out; -+ res = bus_registry_acquire_service (registry, connection, message, -+ &service_name, flags, -+ &service_reply, transaction, -+ error); -+ if (res != BUS_RESULT_TRUE) -+ { -+ retval = res; -+ goto out; -+ } - - reply = dbus_message_new_method_return (message); - if (reply == NULL) -@@ -666,7 +671,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection, - goto out; - } - -- retval = TRUE; -+ retval = BUS_RESULT_TRUE; - - out: - if (reply) -@@ -674,7 +679,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection, - return retval; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_release_service (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -684,7 +689,7 @@ bus_driver_handle_release_service (DBusConnection *connection, - DBusString service_name; - const char *name; - dbus_uint32_t service_reply; -- dbus_bool_t retval; -+ BusResult retval; - BusRegistry *registry; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); -@@ -694,11 +699,11 @@ bus_driver_handle_release_service (DBusConnection *connection, - if (!dbus_message_get_args (message, error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) -- return FALSE; -+ return BUS_RESULT_FALSE; - - _dbus_verbose ("Trying to release name %s\n", name); - -- retval = FALSE; -+ retval = BUS_RESULT_FALSE; - reply = NULL; - - _dbus_string_init_const (&service_name, name); -@@ -727,7 +732,7 @@ bus_driver_handle_release_service (DBusConnection *connection, - goto out; - } - -- retval = TRUE; -+ retval = BUS_RESULT_TRUE; - - out: - if (reply) -@@ -735,7 +740,7 @@ bus_driver_handle_release_service (DBusConnection *connection, - return retval; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_service_exists (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -746,7 +751,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, - BusService *service; - dbus_bool_t service_exists; - const char *name; -- dbus_bool_t retval; -+ BusResult retval; - BusRegistry *registry; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); -@@ -756,9 +761,9 @@ bus_driver_handle_service_exists (DBusConnection *connection, - if (!dbus_message_get_args (message, error, - DBUS_TYPE_STRING, &name, - DBUS_TYPE_INVALID)) -- return FALSE; -+ return BUS_RESULT_FALSE; - -- retval = FALSE; -+ retval = BUS_RESULT_FALSE; - - if (strcmp (name, DBUS_SERVICE_DBUS) == 0) - { -@@ -792,7 +797,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, - goto out; - } - -- retval = TRUE; -+ retval = BUS_RESULT_TRUE; - - out: - if (reply) -@@ -801,7 +806,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, - return retval; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_activate_service (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -809,7 +814,7 @@ bus_driver_handle_activate_service (DBusConnection *connection, - { - dbus_uint32_t flags; - const char *name; -- dbus_bool_t retval; -+ BusResult retval; - BusActivation *activation; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); -@@ -823,10 +828,10 @@ bus_driver_handle_activate_service (DBusConnection *connection, - { - _DBUS_ASSERT_ERROR_IS_SET (error); - _dbus_verbose ("No memory to get arguments to StartServiceByName\n"); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - -- retval = FALSE; -+ retval = BUS_RESULT_FALSE; - - if (!bus_activation_activate_service (activation, connection, transaction, FALSE, - message, name, error)) -@@ -836,7 +841,7 @@ bus_driver_handle_activate_service (DBusConnection *connection, - goto out; - } - -- retval = TRUE; -+ retval = BUS_RESULT_TRUE; - - out: - return retval; -@@ -872,13 +877,13 @@ send_ack_reply (DBusConnection *connection, - return TRUE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_update_activation_environment (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, - DBusError *error) - { -- dbus_bool_t retval; -+ BusResult retval; - BusActivation *activation; - DBusMessageIter iter; - DBusMessageIter dict_iter; -@@ -939,7 +944,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, - - dbus_message_iter_recurse (&iter, &dict_iter); - -- retval = FALSE; -+ retval = BUS_RESULT_FALSE; - - /* Then loop through the sent dictionary, add the location of - * the environment keys and values to lists. The result will -@@ -1026,7 +1031,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, - message, error)) - goto out; - -- retval = TRUE; -+ retval = BUS_RESULT_TRUE; - - out: - _dbus_list_clear (&keys); -@@ -1034,7 +1039,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, - return retval; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_add_match (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1093,16 +1098,16 @@ bus_driver_handle_add_match (DBusConnection *connection, - - bus_match_rule_unref (rule); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - failed: - _DBUS_ASSERT_ERROR_IS_SET (error); - if (rule) - bus_match_rule_unref (rule); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_remove_match (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1146,16 +1151,16 @@ bus_driver_handle_remove_match (DBusConnection *connection, - - bus_match_rule_unref (rule); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - failed: - _DBUS_ASSERT_ERROR_IS_SET (error); - if (rule) - bus_match_rule_unref (rule); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_get_service_owner (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1225,7 +1230,7 @@ bus_driver_handle_get_service_owner (DBusConnection *connection, - - dbus_message_unref (reply); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - BUS_SET_OOM (error); -@@ -1234,10 +1239,10 @@ bus_driver_handle_get_service_owner (DBusConnection *connection, - _DBUS_ASSERT_ERROR_IS_SET (error); - if (reply) - dbus_message_unref (reply); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_list_queued_owners (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1328,7 +1333,7 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection, - - dbus_message_unref (reply); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - BUS_SET_OOM (error); -@@ -1341,10 +1346,10 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection, - if (base_names) - _dbus_list_clear (&base_names); - -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_get_connection_unix_user (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1389,7 +1394,7 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection, - - dbus_message_unref (reply); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - BUS_SET_OOM (error); -@@ -1398,10 +1403,10 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection, - _DBUS_ASSERT_ERROR_IS_SET (error); - if (reply) - dbus_message_unref (reply); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1446,7 +1451,7 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, - - dbus_message_unref (reply); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - BUS_SET_OOM (error); -@@ -1455,10 +1460,10 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, - _DBUS_ASSERT_ERROR_IS_SET (error); - if (reply) - dbus_message_unref (reply); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1502,7 +1507,7 @@ bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, - - dbus_message_unref (reply); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - BUS_SET_OOM (error); -@@ -1511,10 +1516,10 @@ bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, - _DBUS_ASSERT_ERROR_IS_SET (error); - if (reply) - dbus_message_unref (reply); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1556,7 +1561,7 @@ bus_driver_handle_get_connection_selinux_security_context (DBusConnection *conne - - dbus_message_unref (reply); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - BUS_SET_OOM (error); -@@ -1565,10 +1570,10 @@ bus_driver_handle_get_connection_selinux_security_context (DBusConnection *conne - _DBUS_ASSERT_ERROR_IS_SET (error); - if (reply) - dbus_message_unref (reply); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_get_connection_credentials (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1645,7 +1650,7 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, - - dbus_message_unref (reply); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - BUS_SET_OOM (error); -@@ -1659,10 +1664,10 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, - dbus_message_unref (reply); - } - -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_reload_config (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1687,7 +1692,7 @@ bus_driver_handle_reload_config (DBusConnection *connection, - goto oom; - - dbus_message_unref (reply); -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - BUS_SET_OOM (error); -@@ -1696,10 +1701,10 @@ bus_driver_handle_reload_config (DBusConnection *connection, - _DBUS_ASSERT_ERROR_IS_SET (error); - if (reply) - dbus_message_unref (reply); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_get_id (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1715,7 +1720,7 @@ bus_driver_handle_get_id (DBusConnection *connection, - if (!_dbus_string_init (&uuid)) - { - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - reply = NULL; -@@ -1741,7 +1746,7 @@ bus_driver_handle_get_id (DBusConnection *connection, - - _dbus_string_free (&uuid); - dbus_message_unref (reply); -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - _DBUS_ASSERT_ERROR_IS_CLEAR (error); -@@ -1751,7 +1756,7 @@ bus_driver_handle_get_id (DBusConnection *connection, - if (reply) - dbus_message_unref (reply); - _dbus_string_free (&uuid); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - typedef struct -@@ -1759,10 +1764,10 @@ typedef struct - const char *name; - const char *in_args; - const char *out_args; -- dbus_bool_t (* handler) (DBusConnection *connection, -- BusTransaction *transaction, -- DBusMessage *message, -- DBusError *error); -+ BusResult (* handler) (DBusConnection *connection, -+ BusTransaction *transaction, -+ DBusMessage *message, -+ DBusError *error); - } MessageHandler; - - /* For speed it might be useful to sort this in order of -@@ -1847,7 +1852,7 @@ static const MessageHandler dbus_message_handlers[] = { - { NULL, NULL, NULL, NULL } - }; - --static dbus_bool_t bus_driver_handle_introspect (DBusConnection *, -+static BusResult bus_driver_handle_introspect (DBusConnection *, - BusTransaction *, DBusMessage *, DBusError *); - - static const MessageHandler introspectable_message_handlers[] = { -@@ -1973,7 +1978,7 @@ bus_driver_generate_introspect_string (DBusString *xml) - return TRUE; - } - --static dbus_bool_t -+static BusResult - bus_driver_handle_introspect (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -1993,13 +1998,13 @@ bus_driver_handle_introspect (DBusConnection *connection, - DBUS_TYPE_INVALID)) - { - _DBUS_ASSERT_ERROR_IS_SET (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - if (!_dbus_string_init (&xml)) - { - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - if (!bus_driver_generate_introspect_string (&xml)) -@@ -2022,7 +2027,7 @@ bus_driver_handle_introspect (DBusConnection *connection, - dbus_message_unref (reply); - _dbus_string_free (&xml); - -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - BUS_SET_OOM (error); -@@ -2032,7 +2037,7 @@ bus_driver_handle_introspect (DBusConnection *connection, - - _dbus_string_free (&xml); - -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - /* -@@ -2067,7 +2072,7 @@ bus_driver_check_message_is_for_us (DBusMessage *message, - return TRUE; - } - --dbus_bool_t -+BusResult - bus_driver_handle_message (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -2077,6 +2082,7 @@ bus_driver_handle_message (DBusConnection *connection, - const InterfaceHandler *ih; - const MessageHandler *mh; - dbus_bool_t found_interface = FALSE; -+ BusResult res; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - -@@ -2085,13 +2091,13 @@ bus_driver_handle_message (DBusConnection *connection, - BusContext *context; - - context = bus_connection_get_context (connection); -- return dbus_activation_systemd_failure(bus_context_get_activation(context), message); -+ return dbus_activation_systemd_failure(bus_context_get_activation(context), message) == TRUE ? BUS_RESULT_TRUE : BUS_RESULT_FALSE; - } - - if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL) - { - _dbus_verbose ("Driver got a non-method-call message, ignoring\n"); -- return TRUE; /* we just ignore this */ -+ return BUS_RESULT_TRUE; /* we just ignore this */ - } - - /* may be NULL, which means "any interface will do" */ -@@ -2133,20 +2139,27 @@ bus_driver_handle_message (DBusConnection *connection, - name, dbus_message_get_signature (message), - mh->in_args); - _DBUS_ASSERT_ERROR_IS_SET (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - -- if ((* mh->handler) (connection, transaction, message, error)) -+ res = (* mh->handler) (connection, transaction, message, error); -+ if (res == BUS_RESULT_TRUE) - { - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - _dbus_verbose ("Driver handler succeeded\n"); -- return TRUE; -+ return BUS_RESULT_TRUE; - } -- else -+ else if (res == BUS_RESULT_FALSE) - { - _DBUS_ASSERT_ERROR_IS_SET (error); - _dbus_verbose ("Driver handler returned failure\n"); -- return FALSE; -+ return BUS_RESULT_FALSE; -+ } -+ else if (res == BUS_RESULT_LATER) -+ { -+ _DBUS_ASSERT_ERROR_IS_CLEAR (error); -+ _dbus_verbose ("Driver handler delayed message processing due to policy check\n"); -+ return BUS_RESULT_LATER; - } - } - } -@@ -2158,7 +2171,7 @@ bus_driver_handle_message (DBusConnection *connection, - "%s does not understand message %s", - DBUS_SERVICE_DBUS, name); - -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - void -diff --git a/bus/driver.h b/bus/driver.h -index 201709c..3ff4ff1 100644 ---- a/bus/driver.h -+++ b/bus/driver.h -@@ -28,7 +28,7 @@ - #include "connection.h" - - void bus_driver_remove_connection (DBusConnection *connection); --dbus_bool_t bus_driver_handle_message (DBusConnection *connection, -+BusResult bus_driver_handle_message (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, - DBusError *error); -diff --git a/bus/policy.c b/bus/policy.c -index 448147f..3672ff9 100644 ---- a/bus/policy.c -+++ b/bus/policy.c -@@ -1323,18 +1323,21 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, - - - --static dbus_bool_t -+static BusResult - bus_rules_check_can_own (DBusList *rules, -- const DBusString *service_name) -+ const DBusString *service_name, -+ DBusConnection *connection, -+ DBusMessage *message) - { - DBusList *link; -- dbus_bool_t allowed; -+ BusResult result; -+ const char *privilege; - - /* rules is in the order the rules appeared - * in the config file, i.e. last rule that applies wins - */ - -- allowed = FALSE; -+ result = BUS_RESULT_FALSE; - link = _dbus_list_get_first_link (&rules); - while (link != NULL) - { -@@ -1370,17 +1373,45 @@ bus_rules_check_can_own (DBusList *rules, - } - - /* Use this rule */ -- allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW; -+ switch (rule->access) -+ { -+ case BUS_POLICY_RULE_ACCESS_ALLOW: -+ result = BUS_RESULT_TRUE; -+ break; -+ case BUS_POLICY_RULE_ACCESS_DENY: -+ result = BUS_RESULT_FALSE; -+ break; -+ case BUS_POLICY_RULE_ACCESS_CHECK: -+ result = BUS_RESULT_LATER; -+ privilege = rule->privilege; -+ break; -+ } - } - -- return allowed; -+ if (result == BUS_RESULT_LATER) -+ { -+ BusContext *context = bus_connection_get_context(connection); -+ BusCheck *check = bus_context_get_check(context); -+ BusDeferredMessage *deferred_message; -+ -+ result = bus_check_privilege(check, message, connection, NULL, NULL, -+ privilege, BUS_DEFERRED_MESSAGE_CHECK_OWN, &deferred_message); -+ if (result == BUS_RESULT_LATER) -+ { -+ bus_deferred_message_disable_sender(deferred_message); -+ } -+ } -+ -+ return result; - } - --dbus_bool_t -+BusResult - bus_client_policy_check_can_own (BusClientPolicy *policy, -- const DBusString *service_name) -+ const DBusString *service_name, -+ DBusConnection *connection, -+ DBusMessage *message) - { -- return bus_rules_check_can_own (policy->rules, service_name); -+ return bus_rules_check_can_own (policy->rules, service_name, connection, message); - } - - #ifdef DBUS_ENABLE_EMBEDDED_TESTS -@@ -1388,7 +1419,7 @@ dbus_bool_t - bus_policy_check_can_own (BusPolicy *policy, - const DBusString *service_name) - { -- return bus_rules_check_can_own (policy->default_rules, service_name); -+ return bus_rules_check_can_own (policy->default_rules, service_name, NULL, NULL); - } - #endif /* DBUS_ENABLE_EMBEDDED_TESTS */ - -diff --git a/bus/policy.h b/bus/policy.h -index e9f193a..1f23431 100644 ---- a/bus/policy.h -+++ b/bus/policy.h -@@ -170,8 +170,10 @@ BusResult bus_client_policy_check_can_receive (BusClientPolicy *polic - dbus_int32_t *toggles, - const char **privilege_param, - BusDeferredMessage **deferred_message); --dbus_bool_t bus_client_policy_check_can_own (BusClientPolicy *policy, -- const DBusString *service_name); -+BusResult bus_client_policy_check_can_own (BusClientPolicy *policy, -+ const DBusString *service_name, -+ DBusConnection *connection, -+ DBusMessage *message); - dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy, - BusPolicyRule *rule); - void bus_client_policy_optimize (BusClientPolicy *policy); -diff --git a/bus/services.c b/bus/services.c -index 584485b..f25fdf3 100644 ---- a/bus/services.c -+++ b/bus/services.c -@@ -374,24 +374,26 @@ bus_registry_list_services (BusRegistry *registry, - return FALSE; - } - --dbus_bool_t -+BusResult - bus_registry_acquire_service (BusRegistry *registry, - DBusConnection *connection, -+ DBusMessage *message, - const DBusString *service_name, - dbus_uint32_t flags, - dbus_uint32_t *result, - BusTransaction *transaction, - DBusError *error) - { -- dbus_bool_t retval; -+ BusResult retval; - DBusConnection *old_owner_conn; - BusClientPolicy *policy; - BusService *service; - BusActivation *activation; - BusSELinuxID *sid; - BusOwner *primary_owner; -+ BusResult res; - -- retval = FALSE; -+ retval = BUS_RESULT_FALSE; - - if (!_dbus_validate_bus_name (service_name, 0, - _dbus_string_get_length (service_name))) -@@ -459,7 +461,8 @@ bus_registry_acquire_service (BusRegistry *registry, - goto out; - } - -- if (!bus_client_policy_check_can_own (policy, service_name)) -+ res = bus_client_policy_check_can_own (policy, service_name, connection, message); -+ if (res == BUS_RESULT_FALSE) - { - dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, - "Connection \"%s\" is not allowed to own the service \"%s\" due " -@@ -470,6 +473,11 @@ bus_registry_acquire_service (BusRegistry *registry, - _dbus_string_get_const_data (service_name)); - goto out; - } -+ else if (res == BUS_RESULT_LATER) -+ { -+ retval = BUS_RESULT_LATER; -+ goto out; -+ } - - if (bus_connection_get_n_services_owned (connection) >= - bus_context_get_max_services_per_connection (registry->context)) -@@ -586,11 +594,13 @@ bus_registry_acquire_service (BusRegistry *registry, - } - - activation = bus_context_get_activation (registry->context); -- retval = bus_activation_send_pending_auto_activation_messages (activation, -+ -+ if (bus_activation_send_pending_auto_activation_messages (activation, - service, -- transaction); -- if (!retval) -- BUS_SET_OOM (error); -+ transaction)) -+ retval = BUS_RESULT_TRUE; -+ else -+ BUS_SET_OOM (error); - - out: - return retval; -diff --git a/bus/services.h b/bus/services.h -index 056dd9f..3df3dd7 100644 ---- a/bus/services.h -+++ b/bus/services.h -@@ -50,8 +50,9 @@ void bus_registry_foreach (BusRegistry *registry - dbus_bool_t bus_registry_list_services (BusRegistry *registry, - char ***listp, - int *array_len); --dbus_bool_t bus_registry_acquire_service (BusRegistry *registry, -+BusResult bus_registry_acquire_service (BusRegistry *registry, - DBusConnection *connection, -+ DBusMessage *message, - const DBusString *service_name, - dbus_uint32_t flags, - dbus_uint32_t *result, -diff --git a/bus/stats.c b/bus/stats.c -index 20321e5..61dc428 100644 ---- a/bus/stats.c -+++ b/bus/stats.c -@@ -35,7 +35,7 @@ - - #ifdef DBUS_ENABLE_STATS - --dbus_bool_t -+BusResult - bus_stats_handle_get_stats (DBusConnection *connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -106,17 +106,17 @@ bus_stats_handle_get_stats (DBusConnection *connection, - goto oom; - - dbus_message_unref (reply); -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - if (reply != NULL) - dbus_message_unref (reply); - - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - --dbus_bool_t -+BusResult - bus_stats_handle_get_connection_stats (DBusConnection *caller_connection, - BusTransaction *transaction, - DBusMessage *message, -@@ -143,7 +143,7 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection, - if (! dbus_message_get_args (message, error, - DBUS_TYPE_STRING, &bus_name, - DBUS_TYPE_INVALID)) -- return FALSE; -+ return BUS_RESULT_FALSE; - - _dbus_string_init_const (&bus_name_str, bus_name); - service = bus_registry_lookup (registry, &bus_name_str); -@@ -152,7 +152,7 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection, - { - dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER, - "Bus name '%s' has no owner", bus_name); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - stats_connection = bus_service_get_primary_owners_connection (service); -@@ -214,14 +214,14 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection, - goto oom; - - dbus_message_unref (reply); -- return TRUE; -+ return BUS_RESULT_TRUE; - - oom: - if (reply != NULL) - dbus_message_unref (reply); - - BUS_SET_OOM (error); -- return FALSE; -+ return BUS_RESULT_FALSE; - } - - #endif --- -2.1.4 - diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0008-Add-GetConnectionSmackContext-D-Bus-daemon-method.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/0008-Add-GetConnectionSmackContext-D-Bus-daemon-method.patch deleted file mode 100644 index 43a1ef658..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus-cynara/0008-Add-GetConnectionSmackContext-D-Bus-daemon-method.patch +++ /dev/null @@ -1,99 +0,0 @@ -From 6c9997fb1cdff4281166e8c2fb8276018b1025dd Mon Sep 17 00:00:00 2001 -From: Jacek Bukarewicz <j.bukarewicz@samsung.com> -Date: Mon, 15 Jun 2015 11:46:47 +0200 -Subject: [PATCH 8/8] Add "GetConnectionSmackContext" D-Bus daemon method - -This method is used to obtain smack label of given D-Bus client. -Note that it is deprecated and is included only for compatilibity with -existing D-Bus users. GetConnectionCredentials should be used to obtain -client's credentials. - -Change-Id: Idf9648032ca5cbd9605ffab055e6384baa4eb9b4 ---- - bus/driver.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 63 insertions(+) - -diff --git a/bus/driver.c b/bus/driver.c -index 9708f49..4e76224 100644 ---- a/bus/driver.c -+++ b/bus/driver.c -@@ -1759,6 +1759,65 @@ bus_driver_handle_get_id (DBusConnection *connection, - return BUS_RESULT_FALSE; - } - -+static BusResult -+bus_driver_handle_get_connection_smack_context (DBusConnection *connection, -+ BusTransaction *transaction, -+ DBusMessage *message, -+ DBusError *error) -+{ -+ DBusConnection *conn; -+ DBusMessage *reply = NULL; -+ char *label = NULL; -+ const char *service; -+ -+ _DBUS_ASSERT_ERROR_IS_CLEAR (error); -+ -+ conn = bus_driver_get_conn_helper (connection, message, "credentials", -+ &service, error); -+ if (conn == NULL) -+ goto err; -+ -+ reply = dbus_message_new_method_return (message); -+ if (reply == NULL) -+ goto oom; -+ -+ if (!_dbus_connection_get_linux_security_label (conn, &label)) -+ { -+ dbus_set_error (error, DBUS_ERROR_FAILED, -+ "Failed to get smack label of connection", -+ conn); -+ goto err; -+ } -+ -+ if (label == NULL) -+ goto oom; -+ -+ if (!dbus_message_append_args (reply, -+ DBUS_TYPE_STRING, &label, -+ DBUS_TYPE_INVALID)) -+ goto oom; -+ -+ if (!bus_transaction_send_from_driver (transaction, connection, reply)) -+ goto oom; -+ -+ dbus_message_unref (reply); -+ dbus_free(label); -+ -+ return BUS_RESULT_TRUE; -+ -+oom: -+ BUS_SET_OOM (error); -+ -+err: -+ if (reply != NULL) -+ dbus_message_unref (reply); -+ -+ dbus_free(label); -+ -+ return BUS_RESULT_FALSE; -+} -+ -+ - typedef struct - { - const char *name; -@@ -1849,6 +1908,10 @@ static const MessageHandler dbus_message_handlers[] = { - bus_driver_handle_get_id }, - { "GetConnectionCredentials", "s", "a{sv}", - bus_driver_handle_get_connection_credentials }, -+ { "GetConnectionSmackContext", /* deprecated - you should use GetConnectionCredentials instead */ -+ DBUS_TYPE_STRING_AS_STRING, -+ DBUS_TYPE_STRING_AS_STRING, -+ bus_driver_handle_get_connection_smack_context }, - { NULL, NULL, NULL, NULL } - }; - --- -2.1.4 - diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara/Perform-Cynara-runtime-policy-checks-by-default.patch b/meta-security/recipes-core/dbus-cynara/dbus-cynara/Perform-Cynara-runtime-policy-checks-by-default.patch deleted file mode 100644 index e573fb3b3..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus-cynara/Perform-Cynara-runtime-policy-checks-by-default.patch +++ /dev/null @@ -1,116 +0,0 @@ -From e8610297cf7031e94eb314a2e8c11246f4405403 Mon Sep 17 00:00:00 2001 -From: Jacek Bukarewicz <j.bukarewicz@samsung.com> -Date: Tue, 23 Jun 2015 11:08:48 +0200 -Subject: [PATCH] Perform Cynara runtime policy checks by default - -This change introduces http://tizen.org/privilege/internal/dbus privilege -which is supposed to be available only to trusted system resources. -Checks for this privilege are used in place of certain allow rules to -make security policy more strict. - -For system bus sending and receiving signals now requires -http://tizen.org/privilege/internal/dbus privilege. Requesting name -ownership and sending methods is still denied by default. - -For session bus http://tizen.org/privilege/internal/dbus privilege -is now required for requesting name, calling methods, sending and receiving -signals. - -Services are supposed to override these default settings to implement their -own security policy. - -Change-Id: Ifb4a160bf6e0638404e0295a2e4fa3077efd881c -Signed-off-by: Jacek Bukarewicz <j.bukarewicz@samsung.com> ---- - bus/session.conf.in | 32 ++++++++++++++++++++++++++------ - bus/system.conf.in | 22 ++++++++++++++++------ - 2 files changed, 42 insertions(+), 12 deletions(-) - -diff --git a/bus/session.conf.in b/bus/session.conf.in -index 74d9d1f..fa5c232 100644 ---- a/bus/session.conf.in -+++ b/bus/session.conf.in -@@ -17,12 +17,32 @@ - <standard_session_servicedirs /> - - <policy context="default"> -- <!-- Allow everything to be sent --> -- <allow send_destination="*" eavesdrop="true"/> -- <!-- Allow everything to be received --> -- <allow eavesdrop="true"/> -- <!-- Allow anyone to own anything --> -- <allow own="*"/> -+ <!-- By default clients require internal/dbus privilege to communicate -+ with D-Bus services and to claim name ownership. This is internal privilege that -+ is only accessible to trusted system services --> -+ <check own="*" privilege="http://tizen.org/privilege/internal/dbus" /> -+ <check send_type="method_call" privilege="http://tizen.org/privilege/internal/dbus" /> -+ <check send_type="signal" privilege="http://tizen.org/privilege/internal/dbus" /> -+ <check receive_type="signal" privilege="http://tizen.org/privilege/internal/dbus" /> -+ -+ <!-- Reply messages (method returns, errors) are allowed -+ by default --> -+ <allow send_requested_reply="true" send_type="method_return"/> -+ <allow send_requested_reply="true" send_type="error"/> -+ -+ <!-- All messages but signals may be received by default --> -+ <allow receive_type="method_call"/> -+ <allow receive_type="method_return"/> -+ <allow receive_type="error"/> -+ -+ <!-- Allow anyone to talk to the message bus --> -+ <allow send_destination="org.freedesktop.DBus"/> -+ <allow receive_sender="org.freedesktop.DBus"/> -+ -+ <!-- But disallow some specific bus services --> -+ <deny send_destination="org.freedesktop.DBus" -+ send_interface="org.freedesktop.DBus" -+ send_member="UpdateActivationEnvironment"/> - </policy> - - <!-- Config files are placed here that among other things, -diff --git a/bus/system.conf.in b/bus/system.conf.in -index 92f4cc4..dd16947 100644 ---- a/bus/system.conf.in -+++ b/bus/system.conf.in -@@ -50,21 +50,31 @@ - <deny own="*"/> - <deny send_type="method_call"/> - -- <!-- Signals and reply messages (method returns, errors) are allowed -+ <!-- By default clients require internal/dbus privilege to send and receive signaks. -+ This is internal privilege that is only accessible to trusted system services --> -+ <check send_type="signal" privilege="http://tizen.org/privilege/internal/dbus" /> -+ <check receive_type="signal" privilege="http://tizen.org/privilege/internal/dbus" /> -+ -+ <!-- Reply messages (method returns, errors) are allowed - by default --> -- <allow send_type="signal"/> - <allow send_requested_reply="true" send_type="method_return"/> - <allow send_requested_reply="true" send_type="error"/> - -- <!-- All messages may be received by default --> -+ <!-- All messages but signals may be received by default --> - <allow receive_type="method_call"/> - <allow receive_type="method_return"/> - <allow receive_type="error"/> -- <allow receive_type="signal"/> - -- <!-- Allow anyone to talk to the message bus --> -+ <!-- If there is a need specific bus services could be protected by Cynara as well. -+ However, this can lead to deadlock during the boot process when such check is made and -+ Cynara is not yet activated (systemd calls protected method synchronously, -+ dbus daemon tries to consult Cynara, Cynara waits for systemd activation). -+ Therefore it is advised to allow root processes to use bus services. -+ Currently anyone is allowed to talk to the message bus --> - <allow send_destination="org.freedesktop.DBus"/> -- <!-- But disallow some specific bus services --> -+ <allow receive_sender="org.freedesktop.DBus"/> -+ -+ <!-- Disallow some specific bus services --> - <deny send_destination="org.freedesktop.DBus" - send_interface="org.freedesktop.DBus" - send_member="UpdateActivationEnvironment"/> --- -2.1.4 - diff --git a/meta-security/recipes-core/dbus-cynara/dbus-cynara_1.10.20.bb b/meta-security/recipes-core/dbus-cynara/dbus-cynara_1.10.20.bb new file mode 100644 index 000000000..c46298e53 --- /dev/null +++ b/meta-security/recipes-core/dbus-cynara/dbus-cynara_1.10.20.bb @@ -0,0 +1,39 @@ +require ${COREBASE}/meta/recipes-core/dbus/dbus_1.10.20.bb + +FILESEXTRAPATHS_prepend := "${COREBASE}/meta/recipes-core/dbus/dbus:${THISDIR}/dbus-cynara:" +S = "${WORKDIR}/dbus-${PV}" + +SRC_URI_append = "\ + file://0001-Integration-of-Cynara-asynchronous-security-checks.patch \ + file://0002-Disable-message-dispatching-when-send-rule-result-is.patch \ + file://0003-Handle-unavailability-of-policy-results-for-broadcas.patch \ + file://0004-Add-own-rule-result-unavailability-handling.patch \ + file://0005-Perform-Cynara-runtime-policy-checks-by-default.patch \ +" + +DEPENDS += "cynara smack" +EXTRA_OECONF += "--enable-cynara --disable-selinux" + +inherit distro_features_check +REQUIRED_DISTRO_FEATURES += "smack" + +# Only the main package gets created here, everything else remains in the +# normal dbus recipe. +do_install_append () { + for i in ${@' '.join([d.getVar('D', True) + x for x in (' '.join([d.getVar('FILES_${PN}-' + p, True) or '' for p in ['lib', 'dev', 'staticdev', 'doc', 'locale', 'ptest']])).split()])}; do + rm -rf $i + done + + # Try to remove empty directories, starting with the + # longest path (= deepest directory) first. + # Find needs a valid current directory. Somehow the directory + # we get called in is gone by the time that we get invoked. + ( cd ${D} + for i in `find . -type d | sort -r`; do + rmdir $i || true + done + ) +} + +# Avoid warning about dbus and dbus-cynara providing dbus-x11. +RPROVIDES_${PN}_remove = "${OLDPKGNAME}" diff --git a/meta-security/recipes-core/dbus-cynara/dbus_%.bbappend b/meta-security/recipes-core/dbus-cynara/dbus_%.bbappend new file mode 100644 index 000000000..78df8ec3c --- /dev/null +++ b/meta-security/recipes-core/dbus-cynara/dbus_%.bbappend @@ -0,0 +1,36 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/dbus-cynara:" +SRC_URI_append = "\ + file://0001-Integration-of-Cynara-asynchronous-security-checks.patch \ + file://0002-Disable-message-dispatching-when-send-rule-result-is.patch \ + file://0003-Handle-unavailability-of-policy-results-for-broadcas.patch \ + file://0004-Add-own-rule-result-unavailability-handling.patch \ + file://0005-Perform-Cynara-runtime-policy-checks-by-default.patch \ +" + +# Optionally, compilation of the main package with the daemon gets moved into +# dbus-cynara. That is necessary to break a dependency cycle once the +# daemon gets compiled with Cynara support (dbus -> cynara -> systemd +# -> dbus). +do_install_append_class-target () { + if ${@bb.utils.contains('DISTRO_FEATURES', 'dbus-cynara', 'true', 'false', d)}; then + for i in ${@' '.join([d.getVar('D', True) + x for x in (d.getVar('FILES_${PN}', True) or '').split()])}; do + rm -rf $i + done + + # Try to remove empty directories, starting with the + # longest path (= deepest directory) first. + # Find needs a valid current directory. Somehow the directory + # we get called in is gone by the time that we get invoked. + ( cd ${D} + for i in `find . -type d | sort -r`; do + rmdir $i || true + done + ) + fi +} + +# The main package will be empty, but we want to have it created +# anyway because of the dependencies on it. Installing it will pull in +# the replacement dbus-cynara package. +ALLOW_EMPTY_${PN}_class-target = "1" +RDEPENDS_${PN}_append_class-target = "${@bb.utils.contains('DISTRO_FEATURES', 'dbus-cynara', ' dbus-cynara', '', d)}" diff --git a/meta-security/recipes-core/dbus-cynara/dbus_1.10.20.bbappend b/meta-security/recipes-core/dbus-cynara/dbus_1.10.20.bbappend deleted file mode 100644 index 34064bab2..000000000 --- a/meta-security/recipes-core/dbus-cynara/dbus_1.10.20.bbappend +++ /dev/null @@ -1,13 +0,0 @@ -FILESEXTRAPATHS_append := ":${THISDIR}/${PN}" - -SRC_URI_append = "\ - file://0001-Integration-of-Cynara-asynchronous-security-checks.patch \ - file://0002-Disable-message-dispatching-when-send-rule-result-is.patch \ - file://0003-Handle-unavailability-of-policy-results-for-broadcas.patch \ - file://0004-Add-own-rule-result-unavailability-handling.patch \ - file://0005-Perform-Cynara-runtime-policy-checks-by-default.patch \ -" - -DEPENDS_append_class-target = " cynara" -EXTRA_OECONF_append_class-target = " --disable-selinux --enable-cynara" - |