diff options
| author | Havoc Pennington <hp@redhat.com> | 2003-09-06 21:12:11 +0000 | 
|---|---|---|
| committer | Havoc Pennington <hp@redhat.com> | 2003-09-06 21:12:11 +0000 | 
| commit | 83e41dff82abe99e1a35e70ca0bb60672204ffcd (patch) | |
| tree | addc05c0961d5f908ee98f5bac859cdcf107b6ce | |
| parent | 666fe95480c14d7cbf5143b1a4e1bf0558403d4d (diff) | |
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"
| -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>  | 
