summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Szyndela <adrian.s@samsung.com>2020-05-20 15:01:22 +0200
committerAdrian Szyndela <adrian.s@samsung.com>2020-06-01 11:59:55 +0200
commit22eb17b827ad3de1b2d53e5ca17675edabf44a75 (patch)
treec2555aa7ac31db17a7c3cd1a0c81311050c1ba33
parentbf80b7127be0a70640cfb4cf14a1f53daf212997 (diff)
downloaddbus-22eb17b827ad3de1b2d53e5ca17675edabf44a75.tar.gz
dbus-22eb17b827ad3de1b2d53e5ca17675edabf44a75.tar.bz2
dbus-22eb17b827ad3de1b2d53e5ca17675edabf44a75.zip
bus/policy: generalized policy checking process
Change-Id: I573ddbc7e64bef38ed7517644bd842728e14679b
-rw-r--r--bus/policy.c270
1 files changed, 135 insertions, 135 deletions
diff --git a/bus/policy.c b/bus/policy.c
index 6eb52f25..272adcfb 100644
--- a/bus/policy.c
+++ b/bus/policy.c
@@ -868,18 +868,30 @@ bus_policy_rule_to_string (BusPolicyRule *rule,
return TRUE;
}
-struct MatchSendRuleParams {
- BusRegistry *registry;
- dbus_bool_t requested_reply;
- DBusConnection *receiver;
- DBusMessage *message;
-};
+typedef struct RuleParams {
+ enum {PARAM_SR, PARAM_OWN} type;
+ union {
+ struct {
+ BusRegistry *registry;
+ dbus_bool_t requested_reply;
+ DBusConnection *peer;
+ DBusMessage *message;
+ dbus_bool_t eavesdropping;
+ } sr;
+ const DBusString *name;
+ } u;
+} RuleParams;
+
+typedef dbus_bool_t (*CheckRuleFunc) (const BusPolicyRule *,
+ const RuleParams *,
+ BusResult *,
+ const char **);
static dbus_bool_t
-check_send_rule (const BusPolicyRule *rule,
- const struct MatchSendRuleParams *match_params,
- BusResult *result,
- const char **privilege)
+check_send_rule (const BusPolicyRule *rule,
+ const RuleParams *match_params,
+ BusResult *result,
+ const char **privilege)
{
/* Rule is skipped if it specifies a different
* message name from the message, or a different
@@ -893,7 +905,7 @@ check_send_rule (const BusPolicyRule *rule,
if (rule->d.send.message_type != DBUS_MESSAGE_TYPE_INVALID)
{
- if (dbus_message_get_type (match_params->message) != rule->d.send.message_type)
+ if (dbus_message_get_type (match_params->u.sr.message) != rule->d.send.message_type)
{
_dbus_verbose (" (policy) skipping rule for different message type\n");
return FALSE;
@@ -901,13 +913,13 @@ check_send_rule (const BusPolicyRule *rule,
}
/* If it's a reply, the requested_reply flag kicks in */
- if (dbus_message_get_reply_serial (match_params->message) != 0)
+ if (dbus_message_get_reply_serial (match_params->u.sr.message) != 0)
{
/* 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 (!match_params->requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
+ if (!match_params->u.sr.requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
{
_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");
@@ -918,7 +930,7 @@ check_send_rule (const BusPolicyRule *rule,
* when the reply was not requested. requested_reply=true means the
* rule always applies.
*/
- if (match_params->requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.send.requested_reply)
+ if (match_params->u.sr.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");
return FALSE;
@@ -927,8 +939,8 @@ check_send_rule (const BusPolicyRule *rule,
if (rule->d.send.path != NULL)
{
- if (dbus_message_get_path (match_params->message) != NULL &&
- strcmp (dbus_message_get_path (match_params->message),
+ if (dbus_message_get_path (match_params->u.sr.message) != NULL &&
+ strcmp (dbus_message_get_path (match_params->u.sr.message),
rule->d.send.path) != 0)
{
_dbus_verbose (" (policy) skipping rule for different path\n");
@@ -947,11 +959,11 @@ check_send_rule (const BusPolicyRule *rule,
*/
dbus_bool_t no_interface;
- no_interface = dbus_message_get_interface (match_params->message) == NULL;
-
+ no_interface = dbus_message_get_interface (match_params->u.sr.message) == NULL;
+
if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) ||
(!no_interface &&
- strcmp (dbus_message_get_interface (match_params->message),
+ strcmp (dbus_message_get_interface (match_params->u.sr.message),
rule->d.send.interface) != 0))
{
_dbus_verbose (" (policy) skipping rule for different interface\n");
@@ -961,8 +973,8 @@ check_send_rule (const BusPolicyRule *rule,
if (rule->d.send.member != NULL)
{
- if (dbus_message_get_member (match_params->message) != NULL &&
- strcmp (dbus_message_get_member (match_params->message),
+ if (dbus_message_get_member (match_params->u.sr.message) != NULL &&
+ strcmp (dbus_message_get_member (match_params->u.sr.message),
rule->d.send.member) != 0)
{
_dbus_verbose (" (policy) skipping rule for different member\n");
@@ -972,8 +984,8 @@ check_send_rule (const BusPolicyRule *rule,
if (rule->d.send.error != NULL)
{
- if (dbus_message_get_error_name (match_params->message) != NULL &&
- strcmp (dbus_message_get_error_name (match_params->message),
+ if (dbus_message_get_error_name (match_params->u.sr.message) != NULL &&
+ strcmp (dbus_message_get_error_name (match_params->u.sr.message),
rule->d.send.error) != 0)
{
_dbus_verbose (" (policy) skipping rule for different error name\n");
@@ -983,8 +995,8 @@ check_send_rule (const BusPolicyRule *rule,
if (rule->d.send.broadcast != BUS_POLICY_TRISTATE_ANY)
{
- if (dbus_message_get_destination (match_params->message) == NULL &&
- dbus_message_get_type (match_params->message) == DBUS_MESSAGE_TYPE_SIGNAL)
+ if (dbus_message_get_destination (match_params->u.sr.message) == NULL &&
+ dbus_message_get_type (match_params->u.sr.message) == DBUS_MESSAGE_TYPE_SIGNAL)
{
/* it's a broadcast */
if (rule->d.send.broadcast == BUS_POLICY_TRISTATE_FALSE)
@@ -1015,9 +1027,9 @@ check_send_rule (const BusPolicyRule *rule,
* on the assumption that the activated service will have the
* requested name and no others.
*/
- if (match_params->receiver == NULL)
+ if (match_params->u.sr.peer == NULL)
{
- if (!dbus_message_has_destination (match_params->message,
+ if (!dbus_message_has_destination (match_params->u.sr.message,
rule->d.send.destination))
{
_dbus_verbose (" (policy) skipping rule because message dest is not %s\n",
@@ -1032,7 +1044,7 @@ check_send_rule (const BusPolicyRule *rule,
_dbus_string_init_const (&str, rule->d.send.destination);
- service = bus_registry_lookup (match_params->registry, &str);
+ service = bus_registry_lookup (match_params->u.sr.registry, &str);
if (service == NULL)
{
_dbus_verbose (" (policy) skipping rule because dest %s doesn't exist\n",
@@ -1040,7 +1052,7 @@ check_send_rule (const BusPolicyRule *rule,
return FALSE;
}
- if (!bus_service_has_owner (service, match_params->receiver))
+ if (!bus_service_has_owner (service, match_params->u.sr.peer))
{
_dbus_verbose (" (policy) skipping rule because dest %s isn't owned by receiver\n",
rule->d.send.destination);
@@ -1051,9 +1063,9 @@ check_send_rule (const BusPolicyRule *rule,
else if (rule->d.send.destination_prefix)
{
/* receiver can be NULL - the same as in !send.destination_prefix */
- if (match_params->receiver == NULL)
+ if (match_params->u.sr.peer == NULL)
{
- const char *destination = dbus_message_get_destination (match_params->message);
+ const char *destination = dbus_message_get_destination (match_params->u.sr.message);
DBusString dest_name;
if (destination == NULL)
@@ -1075,7 +1087,7 @@ check_send_rule (const BusPolicyRule *rule,
}
else
{
- if (!bus_connection_is_service_owner_by_prefix (match_params->receiver,
+ if (!bus_connection_is_service_owner_by_prefix (match_params->u.sr.peer,
rule->d.send.destination))
{
_dbus_verbose (" (policy) skipping rule because no dest with prefix %s is owned by receiver\n",
@@ -1089,7 +1101,7 @@ check_send_rule (const BusPolicyRule *rule,
if (rule->d.send.min_fds > 0 ||
rule->d.send.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
{
- unsigned int n_fds = _dbus_message_get_n_unix_fds (match_params->message);
+ unsigned int n_fds = _dbus_message_get_n_unix_fds (match_params->u.sr.message);
if (n_fds < rule->d.send.min_fds || n_fds > rule->d.send.max_fds)
{
@@ -1120,6 +1132,40 @@ check_send_rule (const BusPolicyRule *rule,
return TRUE;
}
+static void
+check_rules_list (const DBusList *rules,
+ CheckRuleFunc check_func,
+ const RuleParams *params,
+ dbus_int32_t *toggles,
+ dbus_bool_t *log,
+ BusResult *result,
+ const char **privilege,
+ BusPolicyRule **matched_rule)
+{
+ const DBusList *link;
+
+ link = _dbus_list_get_first_link ((DBusList **)&rules);
+ while (link != NULL)
+ {
+ const BusPolicyRule *rule = link->data;
+
+ link = _dbus_list_get_next_link ((DBusList **)&rules, link);
+
+ if (check_func (rule, params, result, privilege))
+ {
+ if (log)
+ *log = rule->d.send.log;
+ if (toggles)
+ (*toggles)++;
+ if (matched_rule)
+ *matched_rule = (BusPolicyRule *)rule;
+
+ _dbus_verbose (" (policy) used rule, result now = %d\n",
+ result);
+ }
+ }
+}
+
BusResult
bus_client_policy_check_can_send (DBusConnection *sender,
BusClientPolicy *policy,
@@ -1134,16 +1180,16 @@ bus_client_policy_check_can_send (DBusConnection *sender,
BusDeferredMessage **deferred_message,
char **out_rule)
{
- DBusList *link;
BusResult result;
const char *privilege;
BusPolicyRule *matched_rule = NULL;
- struct MatchSendRuleParams params;
+ struct RuleParams params;
- params.registry = registry;
- params.requested_reply = requested_reply;
- params.receiver = receiver;
- params.message = message;
+ params.type = PARAM_SR;
+ params.u.sr.registry = registry;
+ params.u.sr.requested_reply = requested_reply;
+ params.u.sr.peer = receiver;
+ params.u.sr.message = message;
/* policy->rules is in the order the rules appeared
* in the config file, i.e. last rule that applies wins
@@ -1153,23 +1199,9 @@ bus_client_policy_check_can_send (DBusConnection *sender,
*toggles = 0;
result = BUS_RESULT_FALSE;
- link = _dbus_list_get_first_link (&policy->rules);
- while (link != NULL)
- {
- const BusPolicyRule *rule = link->data;
-
- link = _dbus_list_get_next_link (&policy->rules, link);
- if (check_send_rule (rule, &params, &result, &privilege))
- {
- *log = rule->d.send.log;
- (*toggles)++;
- matched_rule = (BusPolicyRule *)rule;
-
- _dbus_verbose (" (policy) used rule, result now = %d\n",
- result);
- }
- }
+ check_rules_list (policy->rules, check_send_rule, &params,
+ toggles, log, &result, &privilege, &matched_rule);
if (result == BUS_RESULT_LATER)
{
@@ -1197,19 +1229,11 @@ bus_client_policy_check_can_send (DBusConnection *sender,
return result;
}
-struct MatchReceiveRuleParams {
- BusRegistry *registry;
- dbus_bool_t requested_reply;
- DBusConnection *sender;
- DBusMessage *message;
- dbus_bool_t eavesdropping;
-};
-
static dbus_bool_t
-check_receive_rule (const BusPolicyRule *rule,
- const struct MatchReceiveRuleParams *match_params,
- BusResult *result,
- const char **privilege)
+check_receive_rule (const BusPolicyRule *rule,
+ const RuleParams *match_params,
+ BusResult *result,
+ const char **privilege)
{
if (rule->type != BUS_POLICY_RULE_RECEIVE)
{
@@ -1219,7 +1243,7 @@ check_receive_rule (const BusPolicyRule *rule,
if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID)
{
- if (dbus_message_get_type (match_params->message) != rule->d.receive.message_type)
+ if (dbus_message_get_type (match_params->u.sr.message) != rule->d.receive.message_type)
{
_dbus_verbose (" (policy) skipping rule for different message type\n");
return FALSE;
@@ -1230,7 +1254,7 @@ check_receive_rule (const BusPolicyRule *rule,
/* for allow or check, eavesdrop=false means the rule doesn't apply when
* eavesdropping. eavesdrop=true means the rule always applies
*/
- if (match_params->eavesdropping && rule->access != BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.eavesdrop)
+ if (match_params->u.sr.eavesdropping && rule->access != BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.eavesdrop)
{
_dbus_verbose (" (policy) skipping %s rule since it doesn't apply to eavesdropping\n",
rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check");
@@ -1240,20 +1264,20 @@ check_receive_rule (const BusPolicyRule *rule,
/* for deny, eavesdrop=true means the rule applies only when
* eavesdropping; eavesdrop=false means always deny.
*/
- if (!match_params->eavesdropping && rule->access == BUS_POLICY_RULE_ACCESS_DENY && rule->d.receive.eavesdrop)
+ if (!match_params->u.sr.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");
return FALSE;
}
/* If it's a reply, the requested_reply flag kicks in */
- if (dbus_message_get_reply_serial (match_params->message) != 0)
+ if (dbus_message_get_reply_serial (match_params->u.sr.message) != 0)
{
/* 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 (!match_params->requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
+ if (!match_params->u.sr.requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
{
_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");
@@ -1264,7 +1288,7 @@ check_receive_rule (const BusPolicyRule *rule,
* when the reply was not requested. requested_reply=true means the
* rule always applies.
*/
- if (match_params->requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.requested_reply)
+ if (match_params->u.sr.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");
return FALSE;
@@ -1273,8 +1297,8 @@ check_receive_rule (const BusPolicyRule *rule,
if (rule->d.receive.path != NULL)
{
- if (dbus_message_get_path (match_params->message) != NULL &&
- strcmp (dbus_message_get_path (match_params->message),
+ if (dbus_message_get_path (match_params->u.sr.message) != NULL &&
+ strcmp (dbus_message_get_path (match_params->u.sr.message),
rule->d.receive.path) != 0)
{
_dbus_verbose (" (policy) skipping rule for different path\n");
@@ -1291,11 +1315,11 @@ check_receive_rule (const BusPolicyRule *rule,
*/
dbus_bool_t no_interface;
- no_interface = dbus_message_get_interface (match_params->message) == NULL;
+ no_interface = dbus_message_get_interface (match_params->u.sr.message) == NULL;
if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) ||
(!no_interface &&
- strcmp (dbus_message_get_interface (match_params->message),
+ strcmp (dbus_message_get_interface (match_params->u.sr.message),
rule->d.receive.interface) != 0))
{
_dbus_verbose (" (policy) skipping rule for different interface\n");
@@ -1305,8 +1329,8 @@ check_receive_rule (const BusPolicyRule *rule,
if (rule->d.receive.member != NULL)
{
- if (dbus_message_get_member (match_params->message) != NULL &&
- strcmp (dbus_message_get_member (match_params->message),
+ if (dbus_message_get_member (match_params->u.sr.message) != NULL &&
+ strcmp (dbus_message_get_member (match_params->u.sr.message),
rule->d.receive.member) != 0)
{
_dbus_verbose (" (policy) skipping rule for different member\n");
@@ -1316,8 +1340,8 @@ check_receive_rule (const BusPolicyRule *rule,
if (rule->d.receive.error != NULL)
{
- if (dbus_message_get_error_name (match_params->message) != NULL &&
- strcmp (dbus_message_get_error_name (match_params->message),
+ if (dbus_message_get_error_name (match_params->u.sr.message) != NULL &&
+ strcmp (dbus_message_get_error_name (match_params->u.sr.message),
rule->d.receive.error) != 0)
{
_dbus_verbose (" (policy) skipping rule for different error name\n");
@@ -1332,9 +1356,9 @@ check_receive_rule (const BusPolicyRule *rule,
* built-in services don't have a DBusConnection but will
* still set the sender on their messages.
*/
- if (match_params->sender == NULL)
+ if (match_params->u.sr.peer == NULL)
{
- if (!dbus_message_has_sender (match_params->message,
+ if (!dbus_message_has_sender (match_params->u.sr.message,
rule->d.receive.origin))
{
_dbus_verbose (" (policy) skipping rule because message sender is not %s\n",
@@ -1349,7 +1373,7 @@ check_receive_rule (const BusPolicyRule *rule,
_dbus_string_init_const (&str, rule->d.receive.origin);
- service = bus_registry_lookup (match_params->registry, &str);
+ service = bus_registry_lookup (match_params->u.sr.registry, &str);
if (service == NULL)
{
@@ -1358,7 +1382,7 @@ check_receive_rule (const BusPolicyRule *rule,
return FALSE;
}
- if (!bus_service_has_owner (service, match_params->sender))
+ if (!bus_service_has_owner (service, match_params->u.sr.peer))
{
_dbus_verbose (" (policy) skipping rule because origin %s isn't owned by sender\n",
rule->d.receive.origin);
@@ -1370,7 +1394,7 @@ check_receive_rule (const BusPolicyRule *rule,
if (rule->d.receive.min_fds > 0 ||
rule->d.receive.max_fds < DBUS_MAXIMUM_MESSAGE_UNIX_FDS)
{
- unsigned int n_fds = _dbus_message_get_n_unix_fds (match_params->message);
+ unsigned int n_fds = _dbus_message_get_n_unix_fds (match_params->u.sr.message);
if (n_fds < rule->d.receive.min_fds || n_fds > rule->d.receive.max_fds)
{
@@ -1418,19 +1442,19 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
BusDeferredMessage **deferred_message,
char **out_rule)
{
- DBusList *link;
BusResult result;
const char *privilege;
BusPolicyRule *matched_rule = NULL;
- struct MatchReceiveRuleParams params;
-
- params.eavesdropping =
+ struct RuleParams params;
+
+ params.type = PARAM_SR;
+ params.u.sr.registry = registry;
+ params.u.sr.requested_reply = requested_reply;
+ params.u.sr.peer = sender;
+ params.u.sr.message = message;
+ params.u.sr.eavesdropping =
addressed_recipient != proposed_recipient &&
dbus_message_get_destination (message) != NULL;
- params.registry = registry;
- params.requested_reply = requested_reply;
- params.sender = sender;
- params.message = message;
/* policy->rules is in the order the rules appeared
* in the config file, i.e. last rule that applies wins
@@ -1440,23 +1464,9 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
*toggles = 0;
result = BUS_RESULT_FALSE;
- link = _dbus_list_get_first_link (&policy->rules);
- while (link != NULL)
- {
- const BusPolicyRule *rule = link->data;
-
- link = _dbus_list_get_next_link (&policy->rules, link);
-
- if (check_receive_rule (rule, &params, &result, &privilege))
- {
- (*toggles)++;
- matched_rule = (BusPolicyRule *)rule;
-
- _dbus_verbose (" (policy) used rule, result now = %d\n",
- result);
- }
- }
+ check_rules_list (policy->rules, check_receive_rule, &params,
+ toggles, NULL, &result, &privilege, &matched_rule);
if (result == BUS_RESULT_LATER)
{
@@ -1486,10 +1496,12 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
static dbus_bool_t
check_own_rule (const BusPolicyRule *rule,
- const DBusString *service_name,
+ const RuleParams *params,
BusResult *result,
const char **privilege)
{
+ const DBusString *service_name = params->u.name;
+
/* Rule is skipped if it specifies a different service name from
* the desired one.
*/
@@ -1531,30 +1543,27 @@ check_own_rule (const BusPolicyRule *rule,
return TRUE;
}
-static BusResult
-bus_rules_check_can_own (DBusList *rules,
- const DBusString *service_name,
- DBusConnection *connection,
- DBusMessage *message)
+BusResult
+bus_client_policy_check_can_own (BusClientPolicy *policy,
+ const DBusString *service_name,
+ DBusConnection *connection,
+ DBusMessage *message)
{
- DBusList *link;
BusResult result;
const char *privilege;
+ RuleParams params;
+
+ params.type = PARAM_OWN;
+ params.u.name = service_name;
- /* rules is in the order the rules appeared
+ /* policy->rules is in the order the rules appeared
* in the config file, i.e. last rule that applies wins
*/
result = BUS_RESULT_FALSE;
- link = _dbus_list_get_first_link (&rules);
- while (link != NULL)
- {
- const BusPolicyRule *rule = link->data;
- link = _dbus_list_get_next_link (&rules, link);
-
- check_own_rule (rule, service_name, &result, &privilege);
- }
+ check_rules_list (policy->rules, check_own_rule, &params,
+ NULL, NULL, &result, &privilege, NULL);
if (result == BUS_RESULT_LATER)
{
@@ -1573,15 +1582,6 @@ bus_rules_check_can_own (DBusList *rules,
return result;
}
-BusResult
-bus_client_policy_check_can_own (BusClientPolicy *policy,
- const DBusString *service_name,
- DBusConnection *connection,
- DBusMessage *message)
-{
- return bus_rules_check_can_own (policy->rules, service_name, connection, message);
-}
-
#ifdef DBUS_ENABLE_EMBEDDED_TESTS
dbus_bool_t
bus_policy_check_can_own (BusPolicy *policy,