diff options
-rw-r--r-- | ChangeLog | 13 | ||||
-rw-r--r-- | bus/config-parser.c | 119 | ||||
-rw-r--r-- | bus/dbus-daemon-1.1.in | 61 | ||||
-rw-r--r-- | bus/policy.c | 50 | ||||
-rw-r--r-- | bus/policy.h | 6 | ||||
-rw-r--r-- | doc/dbus-specification.sgml | 53 | ||||
-rw-r--r-- | test/data/valid-config-files/many-rules.conf | 57 |
7 files changed, 309 insertions, 50 deletions
@@ -1,5 +1,18 @@ 2003-09-06 Havoc Pennington <hp@pobox.com> + * doc/dbus-specification.sgml: partial updates + + * bus/dbus-daemon-1.1.in: fix the config file docs for the + zillionth time; hopefully I edited the right file this time. + + * bus/config-parser.c (append_rule_from_element): support + send_type, send_path, receive_type, receive_path + + * bus/policy.c: add message type and path to the list of things + that can be "firewalled" + +2003-09-06 Havoc Pennington <hp@pobox.com> + * dbus/dbus-connection.c (dbus_connection_register_fallback): add this (dbus_connection_register_object_path): make this not handle messages to paths below the given path diff --git a/bus/config-parser.c b/bus/config-parser.c index 471c67d8..2a7d0752 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -808,6 +808,21 @@ start_busconfig_child (BusConfigParser *parser, } } +static int +message_type_from_string (const char *type_str) +{ + if (strcmp (type_str, "method_call") == 0) + return DBUS_MESSAGE_TYPE_METHOD_CALL; + if (strcmp (type_str, "method_return") == 0) + return DBUS_MESSAGE_TYPE_METHOD_RETURN; + else if (strcmp (type_str, "signal") == 0) + return DBUS_MESSAGE_TYPE_SIGNAL; + else if (strcmp (type_str, "error") == 0) + return DBUS_MESSAGE_TYPE_ERROR; + else + return DBUS_MESSAGE_TYPE_INVALID; +} + static dbus_bool_t append_rule_from_element (BusConfigParser *parser, const char *element_name, @@ -820,10 +835,14 @@ append_rule_from_element (BusConfigParser *parser, const char *send_member; const char *send_error; const char *send_service; + const char *send_path; + const char *send_type; const char *receive_interface; const char *receive_member; const char *receive_error; const char *receive_service; + const char *receive_path; + const char *receive_type; const char *own; const char *user; const char *group; @@ -837,10 +856,14 @@ append_rule_from_element (BusConfigParser *parser, "send_member", &send_member, "send_error", &send_error, "send_service", &send_service, + "send_path", &send_path, + "send_type", &send_type, "receive_interface", &receive_interface, "receive_member", &receive_member, "receive_error", &receive_error, "receive_service", &receive_service, + "receive_path", &receive_path, + "receive_type", &receive_type, "own", &own, "user", &user, "group", &group, @@ -848,7 +871,9 @@ append_rule_from_element (BusConfigParser *parser, return FALSE; if (!(send_interface || send_member || send_error || send_service || + send_type || send_path || receive_interface || receive_member || receive_error || receive_service || + receive_type || receive_path || own || user || group)) { dbus_set_error (error, DBUS_ERROR_FAILED, @@ -857,11 +882,11 @@ append_rule_from_element (BusConfigParser *parser, return FALSE; } - if ((send_member && send_interface == NULL) || - (receive_member && receive_interface == NULL)) + if ((send_member && (send_interface == NULL && send_path == NULL)) || + (receive_member && (receive_interface == NULL && receive_path == NULL))) { dbus_set_error (error, DBUS_ERROR_FAILED, - "On element <%s>, if you specify a member you must specify an interface", + "On element <%s>, if you specify a member you must specify an interface or a path. Keep in mind that not all messages have an interface field.", element_name); return FALSE; } @@ -869,12 +894,13 @@ append_rule_from_element (BusConfigParser *parser, /* Allowed combinations of elements are: * * base, must be all send or all receive: + * nothing * interface * interface + member * error * - * base send_ can combine with send_service, - * base receive_ with receive_service + * base send_ can combine with send_service, send_path, send_type + * base receive_ with receive_service, receive_path, receive_type * * user, group, own must occur alone */ @@ -913,6 +939,22 @@ append_rule_from_element (BusConfigParser *parser, (send_service && user) || (send_service && group)) || + ((send_type && receive_interface) || + (send_type && receive_member) || + (send_type && receive_error) || + (send_type && receive_service) || + (send_type && own) || + (send_type && user) || + (send_type && group)) || + + ((send_path && receive_interface) || + (send_path && receive_member) || + (send_path && receive_error) || + (send_path && receive_service) || + (send_path && own) || + (send_path && user) || + (send_path && group)) || + ((receive_interface && receive_error) || (receive_interface && own) || (receive_interface && user) || @@ -938,7 +980,7 @@ append_rule_from_element (BusConfigParser *parser, element_name); return FALSE; } - + rule = NULL; /* In BusPolicyRule, NULL represents wildcard. @@ -946,11 +988,10 @@ append_rule_from_element (BusConfigParser *parser, */ #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0') - if (send_interface || send_member || send_error || send_service) + if (send_interface || send_member || send_error || send_service || + send_path || send_type) { - rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); - if (rule == NULL) - goto nomem; + int message_type; if (IS_WILDCARD (send_interface)) send_interface = NULL; @@ -960,11 +1001,36 @@ append_rule_from_element (BusConfigParser *parser, send_error = NULL; if (IS_WILDCARD (send_service)) send_service = NULL; + if (IS_WILDCARD (send_path)) + send_path = NULL; + if (IS_WILDCARD (send_type)) + send_type = NULL; + + message_type = DBUS_MESSAGE_TYPE_INVALID; + if (send_type != NULL) + { + message_type = message_type_from_string (send_type); + if (message_type == DBUS_MESSAGE_TYPE_INVALID) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Bad message type \"%s\"", + send_type); + return FALSE; + } + } + rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); + if (rule == NULL) + goto nomem; + + rule->d.send.message_type = message_type; + rule->d.send.path = _dbus_strdup (send_path); 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_service); + if (send_path && rule->d.send.path == NULL) + goto nomem; if (send_interface && rule->d.send.interface == NULL) goto nomem; if (send_member && rule->d.send.member == NULL) @@ -974,11 +1040,10 @@ append_rule_from_element (BusConfigParser *parser, if (send_service && rule->d.send.destination == NULL) goto nomem; } - else if (receive_interface || receive_member || receive_error || receive_service) + else if (receive_interface || receive_member || receive_error || receive_service || + receive_path || receive_type) { - rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); - if (rule == NULL) - goto nomem; + int message_type; if (IS_WILDCARD (receive_interface)) receive_interface = NULL; @@ -988,11 +1053,37 @@ append_rule_from_element (BusConfigParser *parser, receive_error = NULL; if (IS_WILDCARD (receive_service)) receive_service = NULL; + if (IS_WILDCARD (receive_path)) + receive_path = NULL; + if (IS_WILDCARD (receive_type)) + receive_type = NULL; + + + message_type = DBUS_MESSAGE_TYPE_INVALID; + if (receive_type != NULL) + { + message_type = message_type_from_string (receive_type); + if (message_type == DBUS_MESSAGE_TYPE_INVALID) + { + dbus_set_error (error, DBUS_ERROR_FAILED, + "Bad message type \"%s\"", + receive_type); + return FALSE; + } + } + + rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); + if (rule == NULL) + goto nomem; + rule->d.receive.message_type = message_type; + rule->d.receive.path = _dbus_strdup (receive_path); rule->d.receive.interface = _dbus_strdup (receive_interface); rule->d.receive.member = _dbus_strdup (receive_member); rule->d.receive.error = _dbus_strdup (receive_error); rule->d.receive.origin = _dbus_strdup (receive_service); + if (receive_path && rule->d.receive.path == NULL) + goto nomem; if (receive_interface && rule->d.receive.interface == NULL) goto nomem; if (receive_member && rule->d.receive.member == NULL) diff --git a/bus/dbus-daemon-1.1.in b/bus/dbus-daemon-1.1.in index 73a88c90..ec915edd 100644 --- a/bus/dbus-daemon-1.1.in +++ b/bus/dbus-daemon-1.1.in @@ -333,11 +333,22 @@ in the config file. A <deny> element appears below a <policy> element and prohibits some action. The possible attributes of a <deny> element are: .nf - send="messagename" + send_interface="interface_name" + send_member="method_or_signal_name" + send_error="error_name" + send_service="service_name" + send_type="method_call|method_return|signal|error" + send_path="/path/name" + + receive_interface="interface_name" + receive_member="method_or_signal_name" + receive_error="error_name" + receive_service="service_name" + receive_type="method_call|method_return|signal|error" + receive_path="/path/name" + receive="messagename" own="servicename" - send_to="servicename" - receive_from="servicename" user="username" group="groupname" .fi @@ -345,11 +356,11 @@ some action. The possible attributes of a <deny> element are: .PP Examples: .nf - <deny send="org.freedesktop.System.Reboot"/> - <deny receive="org.freedesktop.System.Reboot"/> + <deny send_interface="org.freedesktop.System" send_member="Reboot"/> + <deny receive_interface="org.freedesktop.System" receive_member="Reboot"/> <deny own="org.freedesktop.System"/> - <deny send_to="org.freedesktop.System"/> - <deny receive_from="org.freedesktop.System"/> + <deny send_service="org.freedesktop.System"/> + <deny receive_service="org.freedesktop.System"/> <deny user="john"/> <deny group="enemies"/> .fi @@ -360,18 +371,22 @@ particular action. If it matches, the action is denied (unless later rules in the config file allow it). .PP -send_to and receive_from mean that messages may not be sent to or -received from the *owner* of the given service, not that they may not -be sent *to that service name*. That is, if a connection owns services -A, B, C, and sending to A is denied, sending to B or C will not work -either. +send_service and receive_service rules mean that messages may not be +sent to or received from the *owner* of the given service, not that +they may not be sent *to that service name*. That is, if a connection +owns services A, B, C, and sending to A is denied, sending to B or C +will not work either. + +.PP +The other send_* and receive_* attributes are purely textual/by-value +matches against the given field in the message header. .PP user and group denials mean that the given user or group may not connect to the message bus. .PP -For "servicename" or "messagename" or "username" or "groupname" +For "service_name", "username", "groupname", etc. the character "*" can be substituted, meaning "any." Complex globs like "foo.bar.*" aren't allowed for now because they'd be work to implement and maybe encourage sloppy security anyway. @@ -382,11 +397,21 @@ for a user or group; user/group denials can only be inside context="default" or context="mandatory" policies. .PP -A single <deny> rule may specify both send and send_to, OR both -receive and receive_from. In this case, the denial applies only if -both attributes match the message being denied. -e.g. <deny send="foo.bar" send_to="foo.blah"/> would deny -messages of the given name AND to the given service. +A single <deny> rule may specify combinations of attributes such as +send_service and send_interface and send_type. In this case, the +denial applies only if both attributes match the message being denied. +e.g. <deny send_interface="foo.bar" send_service="foo.blah"/> would +deny messages of the given interface AND to the given service. +To get an OR effect you specify multiple <deny> rules. + +.PP +You can't include both send_ and receive_ attributes on the same +rule, since "whether the message can be sent" and "whether it can be +received" are evaluated separately. + +.PP +Be careful with send_interface/receive_interface, because the +interface field in messages is optional. .TP .I "<allow>" diff --git a/bus/policy.c b/bus/policy.c index f7978c05..21d0b02e 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -52,7 +52,11 @@ bus_policy_rule_new (BusPolicyRuleType type, rule->d.group.gid = DBUS_GID_UNSET; break; case BUS_POLICY_RULE_SEND: + rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID; + break; case BUS_POLICY_RULE_RECEIVE: + rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID; + break; case BUS_POLICY_RULE_OWN: break; } @@ -80,12 +84,14 @@ bus_policy_rule_unref (BusPolicyRule *rule) switch (rule->type) { case BUS_POLICY_RULE_SEND: + dbus_free (rule->d.send.path); dbus_free (rule->d.send.interface); dbus_free (rule->d.send.member); dbus_free (rule->d.send.error); dbus_free (rule->d.send.destination); break; case BUS_POLICY_RULE_RECEIVE: + dbus_free (rule->d.receive.path); dbus_free (rule->d.receive.interface); dbus_free (rule->d.receive.member); dbus_free (rule->d.receive.error); @@ -717,6 +723,8 @@ bus_client_policy_optimize (BusClientPolicy *policy) { case BUS_POLICY_RULE_SEND: remove_preceding = + rule->d.send.message_type == DBUS_MESSAGE_TYPE_INVALID && + rule->d.send.path == NULL && rule->d.send.interface == NULL && rule->d.send.member == NULL && rule->d.send.error == NULL && @@ -724,6 +732,8 @@ bus_client_policy_optimize (BusClientPolicy *policy) break; case BUS_POLICY_RULE_RECEIVE: remove_preceding = + rule->d.receive.message_type == DBUS_MESSAGE_TYPE_INVALID && + rule->d.receive.path == NULL && rule->d.receive.interface == NULL && rule->d.receive.member == NULL && rule->d.receive.error == NULL && @@ -799,6 +809,26 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, continue; } + if (rule->d.send.message_type != DBUS_MESSAGE_TYPE_INVALID) + { + if (dbus_message_get_type (message) != rule->d.send.message_type) + { + _dbus_verbose (" (policy) skipping rule for different message type\n"); + continue; + } + } + + if (rule->d.send.path != NULL) + { + if (dbus_message_get_path (message) != NULL && + strcmp (dbus_message_get_path (message), + rule->d.send.path) != 0) + { + _dbus_verbose (" (policy) skipping rule for different path\n"); + continue; + } + } + if (rule->d.send.interface != NULL) { if (dbus_message_get_interface (message) != NULL && @@ -911,6 +941,26 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, _dbus_verbose (" (policy) skipping non-receive rule\n"); continue; } + + if (rule->d.receive.message_type != DBUS_MESSAGE_TYPE_INVALID) + { + if (dbus_message_get_type (message) != rule->d.receive.message_type) + { + _dbus_verbose (" (policy) skipping rule for different message type\n"); + continue; + } + } + + if (rule->d.receive.path != NULL) + { + if (dbus_message_get_path (message) != NULL && + strcmp (dbus_message_get_path (message), + rule->d.receive.path) != 0) + { + _dbus_verbose (" (policy) skipping rule for different path\n"); + continue; + } + } if (rule->d.receive.interface != NULL) { diff --git a/bus/policy.h b/bus/policy.h index 2aa69aaf..5824816c 100644 --- a/bus/policy.h +++ b/bus/policy.h @@ -54,7 +54,10 @@ struct BusPolicyRule { struct { + /* message type can be DBUS_MESSAGE_TYPE_INVALID meaning "any" */ + int message_type; /* any of these can be NULL meaning "any" */ + char *path; char *interface; char *member; char *error; @@ -63,7 +66,10 @@ struct BusPolicyRule struct { + /* message type can be DBUS_MESSAGE_TYPE_INVALID meaning "any" */ + int message_type; /* any of these can be NULL meaning "any" */ + char *path; char *interface; char *member; char *error; diff --git a/doc/dbus-specification.sgml b/doc/dbus-specification.sgml index 031bb329..7800165b 100644 --- a/doc/dbus-specification.sgml +++ b/doc/dbus-specification.sgml @@ -3,8 +3,8 @@ <article id="index"> <artheader> <title>D-BUS Specification</title> - <releaseinfo>Version 0.7</releaseinfo> - <date>26 March 2003</date> + <releaseinfo>Version 0.8</releaseinfo> + <date>06 September 2003</date> <authorgroup> <author> <firstname>Havoc</firstname> @@ -65,10 +65,10 @@ <para> D-BUS is <emphasis>easy to use</emphasis> because it works in terms of <firstterm>messages</firstterm> rather than byte streams, and - does not require users to understand any complex concepts such as a - new type system or elaborate APIs. Libraries implementing D-BUS - may choose to abstract messages as "method calls" (see - <xref linkend="message-conventions-method">). + automatically handles a lot of the hard IPC issues. Also, the D-BUS + library is designed to be wrapped in a way that lets users use their + framework's existing object/type system, rather than learning a new + one specifically for IPC. </para> </listitem> </itemizedlist> @@ -83,11 +83,10 @@ forwards messages among them. </para> <para> - Things that D-BUS can be used for is for example notification of - system changes (notification of when a camera is plugged in to a - computer, or a new version of some software has been installed), - or desktop interoperablity, for example a file monitoring - service or a configuration service. + Uses of D-BUS include notification of system changes (notification of when + a camera is plugged in to a computer, or a new version of some software + has been installed), or desktop interoperablity, for example a file + monitoring service or a configuration service. </para> </sect1> @@ -279,9 +278,27 @@ </thead> <tbody> <row> - <entry>name</entry> + <entry>path</entry> <entry>STRING</entry> - <entry>The name of the message, such as org.freedesktop.Peer.Ping</entry> + <entry>The object to send the message to; objects are identified by + a path, "/foo/bar"</entry> + </row> + <row> + <entry>ifce</entry> + <entry>STRING</entry> + <entry>The interface to invoke a method call on, or + that a signal is emitted from. e.g. "org.freedesktop.Introspectable"</entry> + </row> + <row> + <entry>mebr</entry> + <entry>STRING</entry> + <entry>The member, either the method name or signal name. + e.g. "Frobate"</entry> + </row> + <row> + <entry>ernm</entry> + <entry>STRING</entry> + <entry>The name of the error that occurred, for errors</entry> </row> <row> <entry>rply</entry> @@ -298,10 +315,10 @@ <xref linkend="message-bus">.</entry> </row> <row> - <entry>sndr</entry> + <entry>sdrs</entry> <entry>STRING</entry> - <entry>The name of the base service that sent this message. - The message bus fills in this field; the field is + <entry>Sender service. The name of the base service that sent + this message. The message bus fills in this field; the field is only meaningful in combination with the message bus.</entry> </row> </tbody> @@ -480,9 +497,9 @@ <sect2 id="message-protocol-names"> <title>Valid names</title> <para> - Messages and services have names with type STRING, meaning that + Services have names with type STRING, meaning that they must be valid UTF-8. However, there are also some - additional restrictions that apply to message and service names + additional restrictions that apply to service names specifically: <itemizedlist> <listitem><para>They must contain at least one '.' (period) character</para></listitem> diff --git a/test/data/valid-config-files/many-rules.conf b/test/data/valid-config-files/many-rules.conf new file mode 100644 index 00000000..57ea5ec9 --- /dev/null +++ b/test/data/valid-config-files/many-rules.conf @@ -0,0 +1,57 @@ +<!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> + <listen>tcp:port=1234</listen> + <includedir>basic.d</includedir> + <servicedir>/usr/share/foo</servicedir> + <include ignore_missing="yes">nonexistent.conf</include> + <policy context="default"> + <allow user="*"/> + <deny send_interface="org.freedesktop.System" send_member="Reboot"/> + <deny receive_interface="org.freedesktop.System" receive_member="Reboot"/> + <deny send_path="/foo/bar/SystemObjectThing" send_member="Reboot"/> + <deny own="org.freedesktop.System"/> + <deny send_service="org.freedesktop.System"/> + <deny receive_service="org.freedesktop.System"/> + <deny user="root"/> + <deny group="root"/> + <allow send_type="error"/> + <allow send_type="method_call"/> + <allow send_type="method_return"/> + <allow send_type="signal"/> + <deny send_service="org.freedesktop.Bar" send_interface="org.freedesktop.Foo"/> + <deny send_service="org.freedesktop.Bar" send_interface="org.freedesktop.Foo" send_type="method_call"/> + </policy> + + <policy context="mandatory"> + <allow user="*"/> + <deny send_interface="org.freedesktop.System" send_member="Reboot"/> + <deny receive_interface="org.freedesktop.System" receive_member="Reboot"/> + <deny send_path="/foo/bar/SystemObjectThing" send_member="Reboot"/> + <deny own="org.freedesktop.System"/> + <deny send_service="org.freedesktop.System"/> + <deny receive_service="org.freedesktop.System"/> + <deny user="root"/> + <deny group="root"/> + <allow send_type="error"/> + <allow send_type="method_call"/> + <allow send_type="method_return"/> + <allow send_type="signal"/> + <deny send_service="org.freedesktop.Bar" send_interface="org.freedesktop.Foo"/> + <deny send_service="org.freedesktop.Bar" send_interface="org.freedesktop.Foo" send_type="method_call"/> + </policy> + + <limit name="max_incoming_bytes">5000</limit> + <limit name="max_outgoing_bytes">5000</limit> + <limit name="max_message_size">300</limit> + <limit name="activation_timeout">5000</limit> + <limit name="auth_timeout">6000</limit> + <limit name="max_completed_connections">50</limit> + <limit name="max_incomplete_connections">80</limit> + <limit name="max_connections_per_user">64</limit> + <limit name="max_pending_activations">64</limit> + <limit name="max_services_per_connection">256</limit> + +</busconfig> |