diff options
author | Adrian Szyndela <adrian.s@samsung.com> | 2018-11-28 15:15:16 +0100 |
---|---|---|
committer | Adrian Szyndela <adrian.s@samsung.com> | 2019-04-26 13:29:42 +0200 |
commit | 055ff9e64a65931cbd2b94f24ea46bf3750d0b8e (patch) | |
tree | 3c29341596c34215ef6af254ce98f21e0f50d83a /bus | |
parent | 3486e0f48dfadf1b175e3796f0a65c0da231889b (diff) | |
download | dbus-055ff9e64a65931cbd2b94f24ea46bf3750d0b8e.tar.gz |
dbus-daemon: add send_destination_prefix support
This extends dbus-daemon with support for send_destination_prefix
attribute in XML policies.
It allows having policy rules for sending to bus names generated
within namespaces defined by a prefix. The similar behaviour can be
emulated by owning an additional name, not used for addressing messages,
as described in
https://lists.freedesktop.org/archives/dbus/2017-May/017188.html
However, introducing send_destination_prefix creates possibility
of communicating intentions in a more direct way, which is easier
to understand.
Signed-off-by: Adrian Szyndela <adrian.s@samsung.com>
Change-Id: I0016ad93f1c16b7742fef5f45ebaf01b55694d3c
Diffstat (limited to 'bus')
-rw-r--r-- | bus/config-parser.c | 29 | ||||
-rw-r--r-- | bus/connection.c | 40 | ||||
-rw-r--r-- | bus/connection.h | 4 | ||||
-rw-r--r-- | bus/policy.c | 43 | ||||
-rw-r--r-- | bus/policy.h | 1 |
5 files changed, 111 insertions, 6 deletions
diff --git a/bus/config-parser.c b/bus/config-parser.c index 4e62c342..a47b8a58 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -1298,6 +1298,7 @@ append_rule_from_element (BusConfigParser *parser, const char *send_member; const char *send_error; const char *send_destination; + const char *send_destination_prefix; const char *send_path; const char *send_type; const char *send_requested_reply; @@ -1341,6 +1342,7 @@ append_rule_from_element (BusConfigParser *parser, "send_member", &send_member, "send_error", &send_error, "send_destination", &send_destination, + "send_destination_prefix", &send_destination_prefix, "send_path", &send_path, "send_type", &send_type, "send_broadcast", &send_broadcast, @@ -1364,6 +1366,7 @@ append_rule_from_element (BusConfigParser *parser, return FALSE; any_send_attribute = (send_destination != NULL || + send_destination_prefix != NULL || send_broadcast != NULL || send_path != NULL || send_type != NULL || @@ -1417,7 +1420,8 @@ append_rule_from_element (BusConfigParser *parser, * interface + member * error * - * base send_ can combine with send_destination, send_path, send_type, send_requested_reply, send_broadcast, eavesdrop + * base send_ can combine with send_destination, send_destination_prefix, send_path, send_type, send_requested_reply, send_broadcast, eavesdrop + * send_destination must not occur with send_destination_prefix * base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop * * user, group, own, own_prefix must occur alone @@ -1456,6 +1460,16 @@ append_rule_from_element (BusConfigParser *parser, return FALSE; } + if ((send_destination != NULL) + (send_destination_prefix != NULL) > 1) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Invalid combination of attributes on element <%s>: " + "send_destination cannot be combined with " + "send_destination_prefix", + element_name); + return FALSE; + } + if ((receive_member != NULL || receive_interface != NULL) && receive_error != NULL) { @@ -1589,7 +1603,16 @@ append_rule_from_element (BusConfigParser *parser, rule->d.send.interface = _dbus_strdup (send_interface); rule->d.send.member = _dbus_strdup (send_member); rule->d.send.error = _dbus_strdup (send_error); - rule->d.send.destination = _dbus_strdup (send_destination); + if (send_destination) + { + rule->d.send.destination = _dbus_strdup (send_destination); + rule->d.send.destination_is_prefix = 0; + } + else if (send_destination_prefix) + { + rule->d.send.destination = _dbus_strdup (send_destination_prefix); + rule->d.send.destination_is_prefix = 1; + } rule->d.send.max_fds = max_fds; rule->d.send.min_fds = min_fds; @@ -1601,7 +1624,7 @@ append_rule_from_element (BusConfigParser *parser, goto nomem; if (send_error && rule->d.send.error == NULL) goto nomem; - if (send_destination && rule->d.send.destination == NULL) + if ((send_destination || send_destination_prefix) && rule->d.send.destination == NULL) goto nomem; } else if (any_receive_attribute) diff --git a/bus/connection.c b/bus/connection.c index 3af980d0..5943841d 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -1446,6 +1446,46 @@ bus_connection_get_n_match_rules (DBusConnection *connection) return d->n_match_rules; } +/** + * Checks whether the connection owns any name with a given prefix, + * regardless of whether the type of ownership is primary or queued. + * + * @note A name matches to a prefix if it is equal to the prefix, + * or if it starts with the prefix followed by a dot. This is the same + * rule as the 'own_prefix' checking rule. + * + * @param connection the connection + * @param name_prefix the prefix + * @returns #TRUE if the connection owns at least one name with the prefix, + * regardless of the type of ownership + */ +dbus_bool_t +bus_connection_is_name_owner_by_prefix (DBusConnection *connection, + const char *name_prefix) +{ + BusConnectionData *d; + DBusList *link; + + d = BUS_CONNECTION_DATA (connection); + _dbus_assert (d != NULL); + + link = _dbus_list_get_first_link (&d->services_owned); + while (link != NULL) + { + BusService *service = link->data; + DBusString str; + + _dbus_string_init_const (&str, bus_service_get_name (service)); + + if (_dbus_string_starts_with_words_c_str (&str, name_prefix, '.')) + return TRUE; + + link = _dbus_list_get_next_link (&d->services_owned, link); + } + + return FALSE; +} + void bus_connection_add_owned_service_link (DBusConnection *connection, DBusList *link) diff --git a/bus/connection.h b/bus/connection.h index 949a2231..912638c0 100644 --- a/bus/connection.h +++ b/bus/connection.h @@ -82,6 +82,10 @@ void bus_connection_send_oom_error (DBusConnection *connection, void bus_connection_request_headers (DBusConnection *connection, BusExtraHeaders headers); +/* called by policy.c */ +dbus_bool_t bus_connection_is_name_owner_by_prefix (DBusConnection *connection, + const char *name_prefix); + /* called by signals.c */ dbus_bool_t bus_connection_add_match_rule (DBusConnection *connection, BusMatchRule *rule); diff --git a/bus/policy.c b/bus/policy.c index 11d21bf0..feb1156e 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -1018,7 +1018,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, } } - if (rule->d.send.destination != NULL) + if (rule->d.send.destination != NULL && !rule->d.send.destination_is_prefix) { /* receiver can be NULL for messages that are sent to the * message bus itself, we check the strings in that case as @@ -1044,9 +1044,9 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, { DBusString str; BusService *service; - + _dbus_string_init_const (&str, rule->d.send.destination); - + service = bus_registry_lookup (registry, &str); if (service == NULL) { @@ -1064,6 +1064,43 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, } } + if (rule->d.send.destination != NULL && rule->d.send.destination_is_prefix) + { + /* receiver can be NULL - the same as in !send.destination_is_prefix */ + if (receiver == NULL) + { + const char *destination = dbus_message_get_destination (message); + DBusString dest_name; + + if (destination == NULL) + { + _dbus_verbose (" (policy) skipping rule because message has no dest\n"); + continue; + } + + _dbus_string_init_const (&dest_name, destination); + + if (!_dbus_string_starts_with_words_c_str (&dest_name, + rule->d.send.destination, + '.')) + { + _dbus_verbose (" (policy) skipping rule because message dest doesn't start with %s\n", + rule->d.send.destination); + continue; + } + } + else + { + if (!bus_connection_is_name_owner_by_prefix (receiver, + rule->d.send.destination)) + { + _dbus_verbose (" (policy) skipping rule because no dest with prefix %s is owned by receiver\n", + rule->d.send.destination); + continue; + } + } + } + if (rule->d.send.min_fds > 0 || rule->d.send.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS) { diff --git a/bus/policy.h b/bus/policy.h index 308eaf86..df59d090 100644 --- a/bus/policy.h +++ b/bus/policy.h @@ -76,6 +76,7 @@ struct BusPolicyRule unsigned int requested_reply : 1; unsigned int log : 1; unsigned int broadcast : 2; /**< really a BusPolicyTristate */ + unsigned int destination_is_prefix : 1; } send; struct |