}
}
+/*
+ * Parse an attribute named name, whose content is content, or NULL if
+ * missing. It is meant to be a (long) integer between min and max inclusive.
+ * If it is missing, use def as the default value (which does not
+ * necessarily need to be between min and max).
+ */
+static dbus_bool_t
+parse_int_attribute (const char *name,
+ const char *content,
+ long min,
+ long max,
+ long def,
+ long *value,
+ DBusError *error)
+{
+ DBusString parse_string;
+
+ *value = def;
+
+ if (content == NULL)
+ return TRUE;
+
+ _dbus_string_init_const (&parse_string, content);
+
+ if (!_dbus_string_parse_int (&parse_string, 0, value, NULL) ||
+ *value < min || *value > max)
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "Bad value \"%s\" for %s attribute, must be an "
+ "integer in range %ld to %ld inclusive",
+ content, name, min, max);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
static dbus_bool_t
append_rule_from_element (BusConfigParser *parser,
const char *element_name,
/* Group: message-matching modifiers that can go on send_ or receive_ */
const char *eavesdrop;
+ const char *max_fds_attr;
+ long max_fds = DBUS_MAXIMUM_MESSAGE_UNIX_FDS;
+ const char *min_fds_attr;
+ long min_fds = 0;
/* TRUE if any message-matching modifier is present */
dbus_bool_t any_message_attribute;
"receive_path", &receive_path,
"receive_type", &receive_type,
"eavesdrop", &eavesdrop,
+ "max_fds", &max_fds_attr,
+ "min_fds", &min_fds_attr,
"send_requested_reply", &send_requested_reply,
"receive_requested_reply", &receive_requested_reply,
"own", &own,
(!any_send_attribute && eavesdrop != NULL));
any_message_attribute = (any_send_attribute ||
any_receive_attribute ||
- eavesdrop != NULL);
+ eavesdrop != NULL ||
+ max_fds_attr != NULL ||
+ min_fds_attr != NULL);
if (!(any_send_attribute ||
any_receive_attribute ||
"send_requested_reply", send_requested_reply);
return FALSE;
}
-
+
+ /* Matching only messages with DBUS_MAXIMUM_MESSAGE_UNIX_FDS or fewer
+ * fds is the same as matching all messages, so we always set a maximum,
+ * but perhaps an unrealistically high one. */
+ if (!parse_int_attribute ("max_fds", max_fds_attr,
+ 0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS,
+ DBUS_MAXIMUM_MESSAGE_UNIX_FDS, &max_fds,
+ error) ||
+ !parse_int_attribute ("min_fds", min_fds_attr,
+ 0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS, 0, &min_fds,
+ error))
+ return FALSE;
+
rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow);
if (rule == NULL)
goto nomem;
rule->d.send.member = _dbus_strdup (send_member);
rule->d.send.error = _dbus_strdup (send_error);
rule->d.send.destination = _dbus_strdup (send_destination);
+ rule->d.send.max_fds = max_fds;
+ rule->d.send.min_fds = min_fds;
+
if (send_path && rule->d.send.path == NULL)
goto nomem;
if (send_interface && rule->d.send.interface == NULL)
"receive_requested_reply", receive_requested_reply);
return FALSE;
}
-
+
+ if (!parse_int_attribute ("max_fds", max_fds_attr,
+ 0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS,
+ DBUS_MAXIMUM_MESSAGE_UNIX_FDS, &max_fds,
+ error) ||
+ !parse_int_attribute ("min_fds", min_fds_attr,
+ 0, DBUS_MAXIMUM_MESSAGE_UNIX_FDS, 0, &min_fds,
+ error))
+ return FALSE;
+
rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow);
if (rule == NULL)
goto nomem;
rule->d.receive.member = _dbus_strdup (receive_member);
rule->d.receive.error = _dbus_strdup (receive_error);
rule->d.receive.origin = _dbus_strdup (receive_sender);
+ rule->d.receive.max_fds = max_fds;
+ rule->d.receive.min_fds = min_fds;
if (receive_path && rule->d.receive.path == NULL)
goto nomem;
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-internals.h>
+#include <dbus/dbus-message-internal.h>
BusPolicyRule*
bus_policy_rule_new (BusPolicyRuleType type,
}
}
+ 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 (message);
+
+ if (n_fds < rule->d.send.min_fds || n_fds > rule->d.send.max_fds)
+ {
+ _dbus_verbose (" (policy) skipping rule because message has %u fds "
+ "and that is outside range [%u,%u]",
+ n_fds, rule->d.send.min_fds, rule->d.send.max_fds);
+ continue;
+ }
+ }
+
/* Use this rule */
allowed = rule->allow;
*log = rule->d.send.log;
}
}
}
-
+
+ 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 (message);
+
+ if (n_fds < rule->d.receive.min_fds || n_fds > rule->d.receive.max_fds)
+ {
+ _dbus_verbose (" (policy) skipping rule because message has %u fds "
+ "and that is outside range [%u,%u]",
+ n_fds, rule->d.receive.min_fds,
+ rule->d.receive.max_fds);
+ continue;
+ }
+ }
+
/* Use this rule */
allowed = rule->allow;
(*toggles)++;
recipient, and any broadcast message).
</para>
+<para>
+ The <literal>eavesdrop</literal>, <literal>min_fds</literal> and
+ <literal>max_fds</literal> attributes are modifiers that can be applied
+ to either <literal>send_</literal>* or <literal>receive_</literal>*
+ rules, and are documented below.
+</para>
+
<para>send_destination and receive_sender rules mean that messages may not be
sent to or received from the *owner* of the given name, not that
they may not be sent *to that name*. That is, if a connection
requested. [send|receive]_requested_reply="true" indicates that the rule applies
always, regardless of pending reply state.</para>
+<para>
+ The <literal>min_fds</literal> and <literal>max_fds</literal> attributes
+ modify either <literal>send_</literal>* or <literal>receive_</literal>*
+ rules. A rule with the <literal>min_fds</literal> attribute only matches
+ messages if they have at least that many Unix file descriptors attached.
+ Conversely, a rule with the <literal>max_fds</literal> attribute only
+ matches messages if they have no more than that many file descriptors
+ attached. In practice, rules with these attributes will most commonly
+ take the form
+ <literal><allow send_destination="…" max_fds="0"/></literal>,
+ <literal><deny send_destination="…" min_fds="1"/></literal> or
+ <literal><deny receive_sender="*" min_fds="1"/></literal>.
+</para>
<para>
Rules with the <literal>user</literal> or <literal>group</literal>