2003-09-21 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Sun, 21 Sep 2003 19:53:56 +0000 (19:53 +0000)
committerHavoc Pennington <hp@redhat.com>
Sun, 21 Sep 2003 19:53:56 +0000 (19:53 +0000)
Get matching rules mostly working in the bus; only actually
parsing the rule text remains. However, the client side of
"signal connections" hasn't been started, this patch is only the
bus side.

* dbus/dispatch.c: fix for the matching rules changes

* bus/driver.c (bus_driver_handle_remove_match)
(bus_driver_handle_add_match): send an ack reply from these
method calls

* glib/dbus-gproxy.c (dbus_gproxy_begin_call): fix order of
arguments, reported by Seth Nickell

* bus/config-parser.c (append_rule_from_element): support
eavesdrop=true|false attribute on policies so match rules
can be prevented from snooping on the system bus.

* bus/dbus-daemon-1.1.in: consistently use terminology "sender"
and "destination" in attribute names; fix some docs bugs;
add eavesdrop=true|false attribute

* bus/driver.c (bus_driver_handle_add_match)
(bus_driver_handle_remove_match): handle AddMatch, RemoveMatch
messages

* dbus/dbus-protocol.h (DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST): get
rid of broadcast service concept, signals are just always broadcast

* bus/signals.c, bus/dispatch.c, bus/connection.c, bus/bus.c:
mostly implement matching rules stuff (currently only exposed as signal
connections)

28 files changed:
ChangeLog
bus/Makefile.am
bus/bus.c
bus/bus.h
bus/config-parser.c
bus/connection.c
bus/connection.h
bus/dbus-daemon-1.1.in
bus/dispatch.c
bus/dispatch.h
bus/driver.c
bus/policy.c
bus/policy.h
bus/session.conf.in
bus/signals.c [new file with mode: 0644]
bus/signals.h [new file with mode: 0644]
bus/system.conf.in
bus/test-main.c
bus/test.h
dbus/dbus-errors.h
dbus/dbus-mainloop.c
dbus/dbus-protocol.h
dbus/dbus-transport.c
doc/TODO
glib/dbus-gproxy.c
test/data/valid-config-files/many-rules.conf
test/data/valid-config-files/system.d/test.conf
tools/dbus-send.c

index 64d29e8..68dfde4 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,38 @@
+2003-09-21  Havoc Pennington  <hp@pobox.com>
+
+       Get matching rules mostly working in the bus; only actually
+       parsing the rule text remains. However, the client side of
+       "signal connections" hasn't been started, this patch is only the
+       bus side.
+       
+       * dbus/dispatch.c: fix for the matching rules changes
+       
+       * bus/driver.c (bus_driver_handle_remove_match)
+       (bus_driver_handle_add_match): send an ack reply from these
+       method calls
+
+       * glib/dbus-gproxy.c (dbus_gproxy_begin_call): fix order of
+       arguments, reported by Seth Nickell
+
+       * bus/config-parser.c (append_rule_from_element): support
+       eavesdrop=true|false attribute on policies so match rules 
+       can be prevented from snooping on the system bus.
+
+       * bus/dbus-daemon-1.1.in: consistently use terminology "sender"
+       and "destination" in attribute names; fix some docs bugs; 
+       add eavesdrop=true|false attribute
+
+       * bus/driver.c (bus_driver_handle_add_match)
+       (bus_driver_handle_remove_match): handle AddMatch, RemoveMatch
+       messages
+
+       * dbus/dbus-protocol.h (DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST): get
+       rid of broadcast service concept, signals are just always broadcast
+
+       * bus/signals.c, bus/dispatch.c, bus/connection.c, bus/bus.c:
+       mostly implement matching rules stuff (currently only exposed as signal
+       connections)
+
 2003-09-21  Mark McLoughlin  <mark@skynet.ie>
 
        * doc/dbus-specification.sgml: Change the header field name
index 2773507..bc72880 100644 (file)
@@ -44,6 +44,8 @@ BUS_SOURCES=                                  \
        policy.h                                \
        services.c                              \
        services.h                              \
+       signals.c                               \
+       signals.h                               \
        test.c                                  \
        test.h                                  \
        utils.c                                 \
index 1b461fe..4087334 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -28,6 +28,7 @@
 #include "utils.h"
 #include "policy.h"
 #include "config-parser.h"
+#include "signals.h"
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-hash.h>
 #include <dbus/dbus-internals.h>
@@ -44,6 +45,7 @@ struct BusContext
   BusActivation *activation;
   BusRegistry *registry;
   BusPolicy *policy;
+  BusMatchmaker *matchmaker;
   DBusUserDatabase *user_database;
   BusLimits limits;
 };
@@ -505,6 +507,13 @@ bus_context_new (const DBusString *config_file,
       goto failed;
     }
 
+  context->matchmaker = bus_matchmaker_new ();
+  if (context->matchmaker == NULL)
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+  
   context->policy = bus_config_parser_steal_policy (parser);
   _dbus_assert (context->policy != NULL);
   
@@ -715,6 +724,12 @@ bus_context_unref (BusContext *context)
           _dbus_loop_unref (context->loop);
           context->loop = NULL;
         }
+
+      if (context->matchmaker)
+        {
+          bus_matchmaker_unref (context->matchmaker);
+          context->matchmaker = NULL;
+        }
       
       dbus_free (context->type);
       dbus_free (context->address);
@@ -771,6 +786,12 @@ bus_context_get_activation (BusContext  *context)
   return context->activation;
 }
 
+BusMatchmaker*
+bus_context_get_matchmaker (BusContext  *context)
+{
+  return context->matchmaker;
+}
+
 DBusLoop*
 bus_context_get_loop (BusContext *context)
 {
@@ -845,18 +866,33 @@ bus_context_get_max_services_per_connection (BusContext *context)
   return context->limits.max_services_per_connection;
 }
 
+int
+bus_context_get_max_match_rules_per_connection (BusContext *context)
+{
+  return context->limits.max_match_rules_per_connection;
+}
+
 dbus_bool_t
 bus_context_check_security_policy (BusContext     *context,
                                    DBusConnection *sender,
-                                   DBusConnection *recipient,
+                                   DBusConnection *addressed_recipient,
+                                   DBusConnection *proposed_recipient,
                                    DBusMessage    *message,
                                    DBusError      *error)
 {
   BusClientPolicy *sender_policy;
   BusClientPolicy *recipient_policy;
 
-  /* NULL sender/receiver means the bus driver */
+  /* NULL sender, proposed_recipient means the bus driver.  NULL
+   * addressed_recipient means the message didn't specify an explicit
+   * target. If proposed_recipient is NULL, then addressed_recipient
+   * is also NULL but is implicitly the bus driver.
+   */
 
+  _dbus_assert (proposed_recipient == NULL ||
+                (dbus_message_get_destination (message) == NULL ||
+                 addressed_recipient != NULL));
+  
   if (sender != NULL)
     {
       if (bus_connection_is_active (sender))
@@ -869,7 +905,7 @@ bus_context_check_security_policy (BusContext     *context,
           /* Policy for inactive connections is that they can only send
            * the hello message to the bus driver
            */
-          if (recipient == NULL &&
+          if (proposed_recipient == NULL &&
               dbus_message_is_method_call (message,
                                            DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
                                            "Hello"))
@@ -897,15 +933,15 @@ bus_context_check_security_policy (BusContext     *context,
   _dbus_assert ((sender != NULL && sender_policy != NULL) ||
                 (sender == NULL && sender_policy == NULL));
   
-  if (recipient != NULL)
+  if (proposed_recipient != NULL)
     {
       /* only the bus driver can send to an inactive recipient (as it
        * owns no services, so other apps can't address it). Inactive
        * recipients can receive any message.
        */
-      if (bus_connection_is_active (recipient))
+      if (bus_connection_is_active (proposed_recipient))
         {
-          recipient_policy = bus_connection_get_policy (recipient);
+          recipient_policy = bus_connection_get_policy (proposed_recipient);
           _dbus_assert (recipient_policy != NULL);
         }
       else if (sender == NULL)
@@ -922,13 +958,13 @@ bus_context_check_security_policy (BusContext     *context,
   else
     recipient_policy = NULL;
   
-  _dbus_assert ((recipient != NULL && recipient_policy != NULL) ||
-                (recipient != NULL && sender == NULL && recipient_policy == NULL) ||
-                (recipient == NULL && recipient_policy == NULL));
+  _dbus_assert ((proposed_recipient != NULL && recipient_policy != NULL) ||
+                (proposed_recipient != NULL && sender == NULL && recipient_policy == NULL) ||
+                (proposed_recipient == NULL && recipient_policy == NULL));
   
   if (sender_policy &&
       !bus_client_policy_check_can_send (sender_policy,
-                                         context->registry, recipient,
+                                         context->registry, proposed_recipient,
                                          message))
     {
       const char *dest = dbus_message_get_destination (message);
@@ -951,6 +987,7 @@ bus_context_check_security_policy (BusContext     *context,
   if (recipient_policy &&
       !bus_client_policy_check_can_receive (recipient_policy,
                                             context->registry, sender,
+                                            addressed_recipient, proposed_recipient,
                                             message))
     {
       const char *dest = dbus_message_get_destination (message);
@@ -971,14 +1008,16 @@ bus_context_check_security_policy (BusContext     *context,
     }
 
   /* See if limits on size have been exceeded */
-  if (recipient &&
-      dbus_connection_get_outgoing_size (recipient) >
+  if (proposed_recipient &&
+      dbus_connection_get_outgoing_size (proposed_recipient) >
       context->limits.max_outgoing_bytes)
     {
       const char *dest = dbus_message_get_destination (message);
       dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
                       "The destination service \"%s\" has a full message queue",
-                      dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
+                      dest ? dest : (proposed_recipient ?
+                                     bus_connection_get_name (proposed_recipient) : 
+                                     DBUS_SERVICE_ORG_FREEDESKTOP_DBUS));
       _dbus_verbose ("security policy disallowing message due to full message queue\n");
       return FALSE;
     }
index 8f32d7a..5809321 100644 (file)
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -40,7 +40,8 @@ typedef struct BusPolicyRule    BusPolicyRule;
 typedef struct BusRegistry      BusRegistry;
 typedef struct BusService       BusService;
 typedef struct BusTransaction   BusTransaction;
-
+typedef struct BusMatchmaker    BusMatchmaker;
+typedef struct BusMatchRule     BusMatchRule;
 
 typedef struct
 {
@@ -54,40 +55,44 @@ typedef struct
   int max_connections_per_user;     /**< Max number of connections auth'd as same user */
   int max_pending_activations;      /**< Max number of pending activations for the entire bus */
   int max_services_per_connection;  /**< Max number of owned services for a single connection */
+  int max_match_rules_per_connection; /**< Max number of match rules for a single connection */
 } BusLimits;
 
-BusContext*       bus_context_new                             (const DBusString *config_file,
-                                                               dbus_bool_t       force_fork,
-                                                               int               print_addr_fd,
-                                                               int               print_pid_fd,
-                                                               DBusError        *error);
-void              bus_context_shutdown                        (BusContext       *context);
-void              bus_context_ref                             (BusContext       *context);
-void              bus_context_unref                           (BusContext       *context);
-const char*       bus_context_get_type                        (BusContext       *context);
-const char*       bus_context_get_address                     (BusContext       *context);
-BusRegistry*      bus_context_get_registry                    (BusContext       *context);
-BusConnections*   bus_context_get_connections                 (BusContext       *context);
-BusActivation*    bus_context_get_activation                  (BusContext       *context);
-DBusLoop*         bus_context_get_loop                        (BusContext       *context);
-DBusUserDatabase* bus_context_get_user_database               (BusContext       *context);
-dbus_bool_t       bus_context_allow_user                      (BusContext       *context,
-                                                               unsigned long     uid);
-BusClientPolicy*  bus_context_create_client_policy            (BusContext       *context,
-                                                               DBusConnection   *connection,
-                                                               DBusError        *error);
+BusContext*       bus_context_new                                (const DBusString *config_file,
+                                                                  dbus_bool_t       force_fork,
+                                                                  int               print_addr_fd,
+                                                                  int               print_pid_fd,
+                                                                  DBusError        *error);
+void              bus_context_shutdown                           (BusContext       *context);
+void              bus_context_ref                                (BusContext       *context);
+void              bus_context_unref                              (BusContext       *context);
+const char*       bus_context_get_type                           (BusContext       *context);
+const char*       bus_context_get_address                        (BusContext       *context);
+BusRegistry*      bus_context_get_registry                       (BusContext       *context);
+BusConnections*   bus_context_get_connections                    (BusContext       *context);
+BusActivation*    bus_context_get_activation                     (BusContext       *context);
+BusMatchmaker*    bus_context_get_matchmaker                     (BusContext       *context);
+DBusLoop*         bus_context_get_loop                           (BusContext       *context);
+DBusUserDatabase* bus_context_get_user_database                  (BusContext       *context);
+dbus_bool_t       bus_context_allow_user                         (BusContext       *context,
+                                                                  unsigned long     uid);
+BusClientPolicy*  bus_context_create_client_policy               (BusContext       *context,
+                                                                  DBusConnection   *connection,
+                                                                  DBusError        *error);
+int               bus_context_get_activation_timeout             (BusContext       *context);
+int               bus_context_get_auth_timeout                   (BusContext       *context);
+int               bus_context_get_max_completed_connections      (BusContext       *context);
+int               bus_context_get_max_incomplete_connections     (BusContext       *context);
+int               bus_context_get_max_connections_per_user       (BusContext       *context);
+int               bus_context_get_max_pending_activations        (BusContext       *context);
+int               bus_context_get_max_services_per_connection    (BusContext       *context);
+int               bus_context_get_max_match_rules_per_connection (BusContext       *context);
+dbus_bool_t       bus_context_check_security_policy              (BusContext       *context,
+                                                                  DBusConnection   *sender,
+                                                                  DBusConnection   *addressed_recipient,
+                                                                  DBusConnection   *proposed_recipient,
+                                                                  DBusMessage      *message,
+                                                                  DBusError        *error);
 
-int               bus_context_get_activation_timeout          (BusContext       *context);
-int               bus_context_get_auth_timeout                (BusContext       *context);
-int               bus_context_get_max_completed_connections   (BusContext       *context);
-int               bus_context_get_max_incomplete_connections  (BusContext       *context);
-int               bus_context_get_max_connections_per_user    (BusContext       *context);
-int               bus_context_get_max_pending_activations     (BusContext       *context);
-int               bus_context_get_max_services_per_connection (BusContext       *context);
-dbus_bool_t       bus_context_check_security_policy           (BusContext       *context,
-                                                               DBusConnection   *sender,
-                                                               DBusConnection   *recipient,
-                                                               DBusMessage      *message,
-                                                               DBusError        *error);
 
 #endif /* BUS_BUS_H */
index cbc239f..7b9b962 100644 (file)
@@ -334,6 +334,8 @@ bus_config_parser_new (const DBusString *basedir,
 
   parser->limits.max_pending_activations = 256;
   parser->limits.max_services_per_connection = 256;
+
+  parser->limits.max_match_rules_per_connection = 128;
   
   parser->refcount = 1;
 
@@ -837,15 +839,16 @@ append_rule_from_element (BusConfigParser   *parser,
   const char *send_interface;
   const char *send_member;
   const char *send_error;
-  const char *send_service;
+  const char *send_destination;
   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_sender;
   const char *receive_path;
   const char *receive_type;
+  const char *eavesdrop;
   const char *own;
   const char *user;
   const char *group;
@@ -858,25 +861,26 @@ append_rule_from_element (BusConfigParser   *parser,
                           "send_interface", &send_interface,
                           "send_member", &send_member,
                           "send_error", &send_error,
-                          "send_service", &send_service,
+                          "send_destination", &send_destination,
                           "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_sender", &receive_sender,
                           "receive_path", &receive_path,
                           "receive_type", &receive_type,
+                          "eavesdrop", &eavesdrop,
                           "own", &own,
                           "user", &user,
                           "group", &group,
                           NULL))
     return FALSE;
 
-  if (!(send_interface || send_member || send_error || send_service ||
+  if (!(send_interface || send_member || send_error || send_destination ||
         send_type || send_path ||
-        receive_interface || receive_member || receive_error || receive_service ||
-        receive_type || receive_path ||
+        receive_interface || receive_member || receive_error || receive_sender ||
+        receive_type || receive_path || eavesdrop ||
         own || user || group))
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
@@ -902,17 +906,20 @@ append_rule_from_element (BusConfigParser   *parser,
    *     interface + member
    *     error
    * 
-   *   base send_ can combine with send_service, send_path, send_type
-   *   base receive_ with receive_service, receive_path, receive_type
+   *   base send_ can combine with send_destination, send_path, send_type
+   *   base receive_ with receive_sender, receive_path, receive_type, eavesdrop
    *
    *   user, group, own must occur alone
+   *
+   * Pretty sure the below stuff is broken, FIXME think about it more.
    */
 
   if (((send_interface && send_error) ||
        (send_interface && receive_interface) ||
        (send_interface && receive_member) ||
        (send_interface && receive_error) ||
-       (send_interface && receive_service) ||
+       (send_interface && receive_sender) ||
+       (send_interface && eavesdrop) ||
        (send_interface && own) ||
        (send_interface && user) ||
        (send_interface && group)) ||
@@ -921,7 +928,8 @@ append_rule_from_element (BusConfigParser   *parser,
        (send_member && receive_interface) ||
        (send_member && receive_member) ||
        (send_member && receive_error) ||
-       (send_member && receive_service) ||
+       (send_member && receive_sender) ||
+       (send_member && eavesdrop) ||
        (send_member && own) ||
        (send_member && user) ||
        (send_member && group)) ||
@@ -929,23 +937,26 @@ append_rule_from_element (BusConfigParser   *parser,
       ((send_error && receive_interface) ||
        (send_error && receive_member) ||
        (send_error && receive_error) ||
-       (send_error && receive_service) ||
+       (send_error && receive_sender) ||
+       (send_error && eavesdrop) ||
        (send_error && own) ||
        (send_error && user) ||
        (send_error && group)) ||
 
-      ((send_service && receive_interface) ||
-       (send_service && receive_member) ||
-       (send_service && receive_error) ||
-       (send_service && receive_service) ||
-       (send_service && own) ||
-       (send_service && user) ||
-       (send_service && group)) ||
+      ((send_destination && receive_interface) ||
+       (send_destination && receive_member) ||
+       (send_destination && receive_error) ||
+       (send_destination && receive_sender) ||
+       (send_destination && eavesdrop) ||
+       (send_destination && own) ||
+       (send_destination && user) ||
+       (send_destination && group)) ||
 
       ((send_type && receive_interface) ||
        (send_type && receive_member) ||
        (send_type && receive_error) ||
-       (send_type && receive_service) ||
+       (send_type && receive_sender) ||
+       (send_type && eavesdrop) ||
        (send_type && own) ||
        (send_type && user) ||
        (send_type && group)) ||
@@ -953,7 +964,8 @@ append_rule_from_element (BusConfigParser   *parser,
       ((send_path && receive_interface) ||
        (send_path && receive_member) ||
        (send_path && receive_error) ||
-       (send_path && receive_service) ||
+       (send_path && receive_sender) ||
+       (send_path && eavesdrop) ||
        (send_path && own) ||
        (send_path && user) ||
        (send_path && group)) ||
@@ -967,19 +979,22 @@ append_rule_from_element (BusConfigParser   *parser,
        (receive_member && own) ||
        (receive_member && user) ||
        (receive_member && group)) ||
-
+      
       ((receive_error && own) ||
        (receive_error && user) ||
        (receive_error && group)) ||
 
+      ((eavesdrop && own) ||
+       (eavesdrop && user) ||
+       (eavesdrop && group)) ||
+      
       ((own && user) ||
        (own && group)) ||
 
       ((user && group)))
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
-                      "Invalid combination of attributes on element <%s>, "
-                      "only send_foo/send_service or receive_foo/receive_service may be paired",
+                      "Invalid combination of attributes on element <%s>",
                       element_name);
       return FALSE;
     }
@@ -991,7 +1006,7 @@ 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_destination ||
       send_path || send_type)
     {
       int message_type;
@@ -1002,8 +1017,8 @@ append_rule_from_element (BusConfigParser   *parser,
         send_member = NULL;
       if (IS_WILDCARD (send_error))
         send_error = NULL;
-      if (IS_WILDCARD (send_service))
-        send_service = NULL;
+      if (IS_WILDCARD (send_destination))
+        send_destination = NULL;
       if (IS_WILDCARD (send_path))
         send_path = NULL;
       if (IS_WILDCARD (send_type))
@@ -1025,13 +1040,13 @@ append_rule_from_element (BusConfigParser   *parser,
       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);
+      rule->d.send.destination = _dbus_strdup (send_destination);
       if (send_path && rule->d.send.path == NULL)
         goto nomem;
       if (send_interface && rule->d.send.interface == NULL)
@@ -1040,11 +1055,11 @@ append_rule_from_element (BusConfigParser   *parser,
         goto nomem;
       if (send_error && rule->d.send.error == NULL)
         goto nomem;
-      if (send_service && rule->d.send.destination == NULL)
+      if (send_destination && rule->d.send.destination == NULL)
         goto nomem;
     }
-  else if (receive_interface || receive_member || receive_error || receive_service ||
-           receive_path || receive_type)
+  else if (receive_interface || receive_member || receive_error || receive_sender ||
+           receive_path || receive_type || eavesdrop)
     {
       int message_type;
       
@@ -1054,14 +1069,13 @@ append_rule_from_element (BusConfigParser   *parser,
         receive_member = NULL;
       if (IS_WILDCARD (receive_error))
         receive_error = NULL;
-      if (IS_WILDCARD (receive_service))
-        receive_service = NULL;
+      if (IS_WILDCARD (receive_sender))
+        receive_sender = 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)
         {
@@ -1074,17 +1088,31 @@ append_rule_from_element (BusConfigParser   *parser,
               return FALSE;
             }
         }
+
+
+      if (eavesdrop &&
+          !(strcmp (eavesdrop, "true") == 0 ||
+            strcmp (eavesdrop, "false") == 0))
+        {
+          dbus_set_error (error, DBUS_ERROR_FAILED,
+                          "Bad value \"%s\" for eavesdrop attribute, must be true or false",
+                          eavesdrop);
+          return FALSE;
+        }
       
       rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); 
       if (rule == NULL)
         goto nomem;
 
+      if (eavesdrop)
+        rule->d.receive.eavesdrop = (strcmp (eavesdrop, "true") == 0);
+      
       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);
+      rule->d.receive.origin = _dbus_strdup (receive_sender);
       if (receive_path && rule->d.receive.path == NULL)
         goto nomem;
       if (receive_interface && rule->d.receive.interface == NULL)
@@ -1093,7 +1121,7 @@ append_rule_from_element (BusConfigParser   *parser,
         goto nomem;
       if (receive_error && rule->d.receive.error == NULL)
         goto nomem;
-      if (receive_service && rule->d.receive.origin == NULL)
+      if (receive_sender && rule->d.receive.origin == NULL)
         goto nomem;
     }
   else if (own)
index f6ce4a2..a824576 100644 (file)
@@ -25,6 +25,7 @@
 #include "policy.h"
 #include "services.h"
 #include "utils.h"
+#include "signals.h"
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-hash.h>
 #include <dbus/dbus-timeout.h>
@@ -41,6 +42,7 @@ struct BusConnections
   BusContext *context;
   DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */
   DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */
+  int stamp;            /**< Incrementing number */
 };
 
 static dbus_int32_t connection_data_slot = -1;
@@ -52,6 +54,8 @@ typedef struct
   DBusConnection *connection;
   DBusList *services_owned;
   int n_services_owned;
+  DBusList *match_rules;
+  int n_match_rules;
   char *name;
   DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
   DBusMessage *oom_message;
@@ -60,6 +64,7 @@ typedef struct
 
   long connection_tv_sec;  /**< Time when we connected (seconds component) */
   long connection_tv_usec; /**< Time when we connected (microsec component) */
+  int stamp;               /**< connections->stamp last time we were traversed */
 } BusConnectionData;
 
 static dbus_bool_t expire_incomplete_timeout (void *data);
@@ -140,12 +145,20 @@ bus_connection_disconnected (DBusConnection *connection)
 {
   BusConnectionData *d;
   BusService *service;
-
+  BusMatchmaker *matchmaker;
+  
   d = BUS_CONNECTION_DATA (connection);
   _dbus_assert (d != NULL);
 
   _dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
                  d->name ? d->name : "(inactive)");
+
+  /* Delete our match rules */
+  if (d->n_match_rules > 0)
+    {
+      matchmaker = bus_context_get_matchmaker (d->connections->context);
+      bus_matchmaker_disconnected (matchmaker, connection);
+    }
   
   /* Drop any service ownership. FIXME Unfortunately, this requires
    * memory allocation and there doesn't seem to be a good way to
@@ -881,6 +894,40 @@ bus_connections_get_context (BusConnections *connections)
   return connections->context;
 }
 
+/*
+ * This is used to avoid covering the same connection twice when
+ * traversing connections. Note that it assumes we will
+ * bus_connection_mark_stamp() each connection at least once per
+ * INT_MAX increments of the global stamp, or wraparound would break
+ * things.
+ */
+void
+bus_connections_increment_stamp (BusConnections *connections)
+{
+  connections->stamp += 1;
+}
+
+/* Mark connection with current stamp, return TRUE if it
+ * didn't already have that stamp
+ */
+dbus_bool_t
+bus_connection_mark_stamp (DBusConnection *connection)
+{
+  BusConnectionData *d;
+  
+  d = BUS_CONNECTION_DATA (connection);
+  
+  _dbus_assert (d != NULL);
+
+  if (d->stamp == d->connections->stamp)
+    return FALSE;
+  else
+    {
+      d->stamp = d->connections->stamp;
+      return TRUE;
+    }
+}
+
 BusContext*
 bus_connection_get_context (DBusConnection *connection)
 {
@@ -929,6 +976,18 @@ bus_connection_get_activation (DBusConnection *connection)
   return bus_context_get_activation (d->connections->context);
 }
 
+BusMatchmaker*
+bus_connection_get_matchmaker (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+
+  _dbus_assert (d != NULL);
+
+  return bus_context_get_matchmaker (d->connections->context);
+}
+
 /**
  * Checks whether the connection is registered with the message bus.
  *
@@ -1025,6 +1084,62 @@ bus_connection_send_oom_error (DBusConnection *connection,
 }
 
 void
+bus_connection_add_match_rule_link (DBusConnection *connection,
+                                    DBusList       *link)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  _dbus_list_append_link (&d->match_rules, link);
+
+  d->n_match_rules += 1;
+}
+
+dbus_bool_t
+bus_connection_add_match_rule (DBusConnection *connection,
+                               BusMatchRule   *rule)
+{
+    DBusList *link;
+
+  link = _dbus_list_alloc_link (rule);
+
+  if (link == NULL)
+    return FALSE;
+
+  bus_connection_add_match_rule_link (connection, link);
+
+  return TRUE;
+}
+
+void
+bus_connection_remove_match_rule (DBusConnection *connection,
+                                  BusMatchRule   *rule)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+
+  _dbus_list_remove_last (&d->match_rules, rule);
+
+  d->n_match_rules -= 1;
+  _dbus_assert (d->n_match_rules >= 0);
+}
+
+int
+bus_connection_get_n_match_rules (DBusConnection *connection)
+{
+  BusConnectionData *d;
+
+  d = BUS_CONNECTION_DATA (connection);
+  _dbus_assert (d != NULL);
+  
+  return d->n_match_rules;
+}
+
+void
 bus_connection_add_owned_service_link (DBusConnection *connection,
                                        DBusList       *link)
 {
@@ -1092,6 +1207,8 @@ bus_connection_complete (DBusConnection   *connection,
   _dbus_assert (d != NULL);
   _dbus_assert (d->name == NULL);
   _dbus_assert (d->policy == NULL);
+
+  _dbus_assert (!bus_connection_is_active (connection));
   
   if (!_dbus_string_copy_data (name, &d->name))
     {
@@ -1147,6 +1264,8 @@ bus_connection_complete (DBusConnection   *connection,
 
   /* See if we can remove the timeout */
   bus_connections_expire_incomplete (d->connections);
+
+  _dbus_assert (bus_connection_is_active (connection));
   
   return TRUE;
 }
@@ -1327,7 +1446,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
    * eat it; the driver doesn't care about getting a reply.
    */
   if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
-                                          NULL, connection, message, NULL))
+                                          NULL, connection, connection, message, NULL))
     return TRUE;
 
   return bus_transaction_send (transaction, connection, message);
index 92c9326..d9fd727 100644 (file)
@@ -44,16 +44,18 @@ void            bus_connections_foreach_active    (BusConnections
                                                    BusConnectionForeachFunction  function,
                                                    void                         *data);
 BusContext*     bus_connections_get_context       (BusConnections               *connections);
+void            bus_connections_increment_stamp   (BusConnections               *connections);
 BusContext*     bus_connection_get_context        (DBusConnection               *connection);
 BusConnections* bus_connection_get_connections    (DBusConnection               *connection);
 BusRegistry*    bus_connection_get_registry       (DBusConnection               *connection);
 BusActivation*  bus_connection_get_activation     (DBusConnection               *connection);
+BusMatchmaker*  bus_connection_get_matchmaker     (DBusConnection               *connection);
 dbus_bool_t     bus_connections_check_limits      (BusConnections               *connections,
                                                    DBusConnection               *requesting_completion,
                                                    DBusError                    *error);
 void            bus_connections_expire_incomplete (BusConnections               *connections);
 
-
+dbus_bool_t     bus_connection_mark_stamp         (DBusConnection               *connection);
 
 dbus_bool_t bus_connection_is_active (DBusConnection *connection);
 const char *bus_connection_get_name  (DBusConnection *connection);
@@ -62,6 +64,15 @@ dbus_bool_t bus_connection_preallocate_oom_error (DBusConnection *connection);
 void        bus_connection_send_oom_error        (DBusConnection *connection,
                                                   DBusMessage    *in_reply_to);
 
+/* called by signals.c */
+dbus_bool_t bus_connection_add_match_rule      (DBusConnection *connection,
+                                                BusMatchRule   *rule);
+void        bus_connection_add_match_rule_link (DBusConnection *connection,
+                                                DBusList       *link);
+void        bus_connection_remove_match_rule   (DBusConnection *connection,
+                                                BusMatchRule   *rule);
+int         bus_connection_get_n_match_rules   (DBusConnection *connection);
+
 
 /* called by services.c */
 dbus_bool_t bus_connection_add_owned_service      (DBusConnection *connection,
index ec915ed..b272a62 100644 (file)
@@ -328,26 +328,32 @@ in the config file.
 
 .TP
 .I "<deny>"
+.I "<allow>"
+
+.PP
+A <deny> element appears below a <policy> element and prohibits some
+action. The <allow> element makes an exception to previous <deny>
+statements, and works just like <deny> but with the inverse meaning.
 
 .PP
-A <deny> element appears below a <policy> element and prohibits 
-some action. The possible attributes of a <deny> element are:
+The possible attributes of these elements are:
 .nf
    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_destination="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_sender="service_name" 
+   receive_type="method_call" | "method_return" | "signal" | "error"
    receive_path="/path/name"
+   
+   eavesdrop="true" | "false"
 
-   receive="messagename"
    own="servicename"
    user="username"
    group="groupname"
@@ -359,8 +365,8 @@ Examples:
    <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_service="org.freedesktop.System"/>
-   <deny receive_service="org.freedesktop.System"/>
+   <deny send_destination="org.freedesktop.System"/>
+   <deny receive_sender="org.freedesktop.System"/>
    <deny user="john"/>
    <deny group="enemies"/>
 .fi
@@ -371,7 +377,7 @@ particular action. If it matches, the action is denied (unless later
 rules in the config file allow it).
 
 .PP
-send_service and receive_service rules mean that messages may not be
+send_destination and receive_sender 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
@@ -382,6 +388,22 @@ The other send_* and receive_* attributes are purely textual/by-value
 matches against the given field in the message header.
 
 .PP
+"Eavesdropping" occurs when an application receives a message that
+was explicitly addressed to a service the application does not own.
+Eavesdropping thus only applies to messages that are addressed to
+services (i.e. it does not apply to signals).
+
+.PP
+For <allow>, eavesdrop="true" indicates that the rule matches even 
+when eavesdropping. eavesdrop="false" is the default and means that 
+the rule only allows messages to go to their specified recipient.
+For <deny>, eavesdrop="true" indicates that the rule matches 
+only when eavesdropping. eavesdrop="false" is the default for <deny>
+also, but here it means that the rule applies always, even when 
+not eavesdropping. The eavesdrop attribute can only be combined with
+receive rules (with receive_* attributes).
+
+.PP
 user and group denials mean that the given user or group may 
 not connect to the message bus.
 
@@ -413,13 +435,6 @@ received" are evaluated separately.
 Be careful with send_interface/receive_interface, because the 
 interface field in messages is optional.
 
-.TP
-.I "<allow>"
-
-.PP
-Makes an exception to previous <deny> statements. Works 
-just like <deny> but with the inverse meaning.
-
 .SH AUTHOR
 See http://www.freedesktop.org/software/dbus/doc/AUTHORS
 
index 7bdda0d..606c68e 100644 (file)
 #include "services.h"
 #include "utils.h"
 #include "bus.h"
+#include "signals.h"
 #include "test.h"
 #include <dbus/dbus-internals.h>
 #include <string.h>
 
-typedef struct
-{
-  BusContext     *context;
-  DBusConnection *sender;
-  DBusMessage    *message;
-  BusTransaction *transaction;
-  DBusError      *error;
-} SendMessageData;
-
 static dbus_bool_t
-send_one_message (DBusConnection *connection, void *data)
+send_one_message (DBusConnection *connection,
+                  BusContext     *context,
+                  DBusConnection *sender,
+                  DBusConnection *addressed_recipient,
+                  DBusMessage    *message,
+                  BusTransaction *transaction,
+                  DBusError      *error)
 {
-  SendMessageData *d = data;
-
-  if (!bus_context_check_security_policy (d->context,
-                                          d->sender,
+  if (!bus_context_check_security_policy (context,
+                                          sender,
+                                          addressed_recipient,
                                           connection,
-                                          d->message,
+                                          message,
                                           NULL))
     return TRUE; /* silently don't send it */
   
-  if (!bus_transaction_send (d->transaction,
+  if (!bus_transaction_send (transaction,
                              connection,
-                             d->message))
+                             message))
     {
-      BUS_SET_OOM (d->error);
+      BUS_SET_OOM (error);
       return FALSE;
     }
 
@@ -65,30 +62,60 @@ send_one_message (DBusConnection *connection, void *data)
 }
 
 dbus_bool_t
-bus_dispatch_broadcast_message (BusTransaction *transaction,
-                                DBusConnection *sender,
-                                DBusMessage    *message,
-                                DBusError      *error)
+bus_dispatch_matches (BusTransaction *transaction,
+                      DBusConnection *sender,
+                      DBusConnection *addressed_recipient,
+                      DBusMessage    *message,
+                      DBusError      *error)
 {
   DBusError tmp_error;
-  SendMessageData d;
   BusConnections *connections;
+  DBusList *recipients;
+  BusMatchmaker *matchmaker;
+  DBusList *link;
+  BusContext *context;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
+
+  /* sender and recipient can both be NULL for the bus driver,
+   * or for signals with no particular recipient
+   */
+
+  _dbus_assert (sender == NULL || bus_connection_is_active (sender));
   _dbus_assert (dbus_message_get_sender (message) != NULL);
 
   connections = bus_transaction_get_connections (transaction);
   
   dbus_error_init (&tmp_error);
-  d.sender = sender;
-  d.context = bus_transaction_get_context (transaction);
-  d.message = message;
-  d.transaction = transaction;
-  d.error = &tmp_error;
-  
-  bus_connections_foreach_active (connections, send_one_message, &d);
+  context = bus_transaction_get_context (transaction);
+  matchmaker = bus_context_get_matchmaker (context);
+
+  recipients = NULL;
+  if (!bus_matchmaker_get_recipients (matchmaker,
+                                      bus_context_get_connections (context),
+                                      sender, addressed_recipient, message,
+                                      &recipients))
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  link = _dbus_list_get_first_link (&recipients);
+  while (link != NULL)
+    {
+      DBusConnection *dest;
+
+      dest = link->data;
+
+      if (!send_one_message (dest, context, sender, addressed_recipient,
+                             message, transaction, &tmp_error))
+        break;
+
+      link = _dbus_list_get_next_link (&recipients, link);
+    }
 
+  _dbus_list_clear (&recipients);
+  
   if (dbus_error_is_set (&tmp_error))
     {
       dbus_move_error (&tmp_error, error);
@@ -107,10 +134,12 @@ bus_dispatch (DBusConnection *connection,
   BusTransaction *transaction;
   BusContext *context;
   DBusHandlerResult result;
-
+  DBusConnection *addressed_recipient;
+  
   result = DBUS_HANDLER_RESULT_HANDLED;
   
   transaction = NULL;
+  addressed_recipient = NULL;
   dbus_error_init (&error);
   
   context = bus_connection_get_context (connection);
@@ -143,26 +172,31 @@ bus_dispatch (DBusConnection *connection,
   }
 #endif /* DBUS_ENABLE_VERBOSE_MODE */
   
-  /* If service_name is NULL, this is a message to the bus daemon, not
-   * intended to actually go "on the bus"; e.g. a peer-to-peer
+  /* If service_name is NULL, if it's a signal we send it to all
+   * connections with a match rule. If it's not a signal, it goes to
+   * the bus daemon but doesn't go "on the bus"; e.g. a peer-to-peer
    * ping. Handle these immediately, especially disconnection
    * messages. There are no security policy checks on these.
    */
   if (service_name == NULL)
-    {      
+    {
       if (dbus_message_is_signal (message,
                                   DBUS_INTERFACE_ORG_FREEDESKTOP_LOCAL,
                                   "Disconnected"))
-        bus_connection_disconnected (connection);
+        {
+          bus_connection_disconnected (connection);
+          goto out;
+        }
 
-      /* DBusConnection also handles some of these automatically, we leave
-       * it to do so.
-       */
-      result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-      goto out;
+      if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_SIGNAL)
+        {
+          /* DBusConnection also handles some of these automatically, we leave
+           * it to do so.
+           */
+          result = DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
+          goto out;
+        }
     }
-
-  _dbus_assert (service_name != NULL); /* this message is intended for bus routing */
   
   /* Create our transaction */
   transaction = bus_transaction_new (context);
@@ -191,11 +225,12 @@ bus_dispatch (DBusConnection *connection,
        */
       service_name = dbus_message_get_destination (message);
     }
-
-  if (strcmp (service_name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0) /* to bus driver */
+  
+  if (service_name &&
+      strcmp (service_name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0) /* to bus driver */
     {
       if (!bus_context_check_security_policy (context,
-                                              connection, NULL, message, &error))
+                                              connection, NULL, NULL, message, &error))
         {
           _dbus_verbose ("Security policy rejected message\n");
           goto out;
@@ -209,22 +244,16 @@ bus_dispatch (DBusConnection *connection,
     {
       _dbus_verbose ("Received message from non-registered client. Disconnecting.\n");
       dbus_connection_disconnect (connection);
+      goto out;
     }
-  /* FIXME what if we un-special-case this service and just have a flag
-   * on services that all service owners will get messages to it, not just
-   * the primary owner.
-   */
-  else if (strcmp (service_name, DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST) == 0) /* spam! */
-    {
-      if (!bus_dispatch_broadcast_message (transaction, connection, message, &error))
-        goto out;
-    }
-  else  /* route to named service */
+  else if (service_name != NULL) /* route to named service */
     {
       DBusString service_string;
       BusService *service;
       BusRegistry *registry;
 
+      _dbus_assert (service_name != NULL);
+      
       registry = bus_connection_get_registry (connection);
       
       _dbus_string_init_const (&service_string, service_name);
@@ -239,24 +268,30 @@ bus_dispatch (DBusConnection *connection,
           goto out;
         }
       else
-        {
-          DBusConnection *recipient;
-          
-          recipient = bus_service_get_primary_owner (service);
-          _dbus_assert (recipient != NULL);
+        {          
+          addressed_recipient = bus_service_get_primary_owner (service);
+          _dbus_assert (addressed_recipient != NULL);
           
           if (!bus_context_check_security_policy (context,
-                                                  connection, recipient, message, &error))
+                                                  connection, addressed_recipient,
+                                                  addressed_recipient,
+                                                  message, &error))
             goto out;
           
           /* Dispatch the message */
-          if (!bus_transaction_send (transaction, recipient, message))
+          if (!bus_transaction_send (transaction, addressed_recipient, message))
             {
               BUS_SET_OOM (&error);
               goto out;
             }
         }
     }
+
+  /* Now match the messages against any match rules, which will send
+   * out signals and such. addressed_recipient may == NULL.
+   */
+  if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error))
+    goto out;
   
  out:
   if (dbus_error_is_set (&error))
@@ -673,7 +708,7 @@ check_hello_message (BusContext     *context,
                      DBusConnection *connection)
 {
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   DBusError error;
   char *name;
@@ -684,6 +719,8 @@ check_hello_message (BusContext     *context,
   name = NULL;
   acquired = NULL;
   message = NULL;
+
+  _dbus_verbose ("check_hello_message for %p\n", connection);
   
   message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
                                           DBUS_PATH_ORG_FREEDESKTOP_DBUS,
@@ -791,7 +828,7 @@ check_hello_message (BusContext     *context,
       while (!dbus_bus_set_base_service (connection, name))
         _dbus_wait_for_memory ();
       
-      scd.skip_connection = NULL;
+      scd.skip_connection = connection; /* we haven't done AddMatch so won't get it ourselves */
       scd.failed = FALSE;
       scd.expected_service_name = name;
       bus_test_clients_foreach (check_service_created_foreach,
@@ -861,6 +898,126 @@ check_hello_message (BusContext     *context,
  * but the correct thing may include OOM errors.
  */
 static dbus_bool_t
+check_add_match_all (BusContext     *context,
+                     DBusConnection *connection)
+{
+  DBusMessage *message;
+  dbus_bool_t retval;
+  dbus_uint32_t serial;
+  DBusError error;
+
+  retval = FALSE;
+  dbus_error_init (&error);
+  message = NULL;
+
+  _dbus_verbose ("check_add_match_all for %p\n", connection);
+  
+  message = dbus_message_new_method_call (DBUS_SERVICE_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_PATH_ORG_FREEDESKTOP_DBUS,
+                                          DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
+                                          "AddMatch");
+
+  if (message == NULL)
+    return TRUE;
+
+  if (!dbus_message_append_args (message, DBUS_TYPE_STRING, "", /* FIXME */
+                                 DBUS_TYPE_INVALID))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+  
+  if (!dbus_connection_send (connection, message, &serial))
+    {
+      dbus_message_unref (message);
+      return TRUE;
+    }
+
+  dbus_message_unref (message);
+  message = NULL;
+
+  /* send our message */
+  bus_test_run_clients_loop (TRUE);
+
+  dbus_connection_ref (connection); /* because we may get disconnected */
+  block_connection_until_message_from_bus (context, connection);
+
+  if (!dbus_connection_get_is_connected (connection))
+    {
+      _dbus_verbose ("connection was disconnected\n");
+      
+      dbus_connection_unref (connection);
+      
+      return TRUE;
+    }
+
+  dbus_connection_unref (connection);
+  
+  message = pop_message_waiting_for_memory (connection);
+  if (message == NULL)
+    {
+      _dbus_warn ("Did not receive a reply to %s %d on %p\n",
+                  "AddMatch", serial, connection);
+      goto out;
+    }
+
+  verbose_message_received (connection, message);
+
+  if (!dbus_message_has_sender (message, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS))
+    {
+      _dbus_warn ("Message has wrong sender %s\n",
+                  dbus_message_get_sender (message) ?
+                  dbus_message_get_sender (message) : "(none)");
+      goto out;
+    }
+  
+  if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_ERROR)
+    {
+      if (dbus_message_is_error (message,
+                                 DBUS_ERROR_NO_MEMORY))
+        {
+          ; /* good, this is a valid response */
+        }
+      else
+        {
+          warn_unexpected (connection, message, "not this error");
+
+          goto out;
+        }
+    }
+  else
+    {
+      if (dbus_message_get_type (message) == DBUS_MESSAGE_TYPE_METHOD_RETURN)
+        {
+          ; /* good, expected */
+          _dbus_assert (dbus_message_get_reply_serial (message) == serial);
+        }
+      else
+        {
+          warn_unexpected (connection, message, "method return for AddMatch");
+
+          goto out;
+        }
+    }
+
+  if (!check_no_leftovers (context))
+    goto out;
+  
+  retval = TRUE;
+  
+ out:
+  dbus_error_free (&error);
+  
+  if (message)
+    dbus_message_unref (message);
+  
+  return retval;
+}
+
+/* returns TRUE if the correct thing happens,
+ * but the correct thing may include OOM errors.
+ */
+static dbus_bool_t
 check_hello_connection (BusContext *context)
 {
   DBusConnection *connection;
@@ -885,7 +1042,7 @@ check_hello_connection (BusContext *context)
 
   if (!check_hello_message (context, connection))
     return FALSE;
-
+  
   if (dbus_bus_get_base_service (connection) == NULL)
     {
       /* We didn't successfully register, so we can't
@@ -895,6 +1052,9 @@ check_hello_connection (BusContext *context)
     }
   else
     {
+      if (!check_add_match_all (context, connection))
+        return FALSE;
+      
       kill_client_connection (context, connection);
     }
 
@@ -911,7 +1071,7 @@ check_nonexistent_service_activation (BusContext     *context,
                                       DBusConnection *connection)
 {
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   DBusError error;
   
@@ -1293,7 +1453,7 @@ check_send_exit_to_service (BusContext     *context,
 {
   dbus_bool_t got_error;
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   
   _dbus_verbose ("Sending exit message to the test service\n");
@@ -1462,7 +1622,7 @@ check_existent_service_activation (BusContext     *context,
                                    DBusConnection *connection)
 {
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   DBusError error;
   char *base_service;
@@ -1676,7 +1836,7 @@ check_segfault_service_activation (BusContext     *context,
                                    DBusConnection *connection)
 {
   DBusMessage *message;
-  dbus_int32_t serial;
+  dbus_uint32_t serial;
   dbus_bool_t retval;
   DBusError error;
   
@@ -1877,6 +2037,9 @@ bus_dispatch_test (const DBusString *test_data_dir)
 
   if (!check_hello_message (context, foo))
     _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_add_match_all (context, foo))
+    _dbus_assert_not_reached ("AddMatch message failed");
   
   bar = dbus_connection_open ("debug-pipe:name=test-server", &error);
   if (bar == NULL)
@@ -1887,6 +2050,9 @@ bus_dispatch_test (const DBusString *test_data_dir)
 
   if (!check_hello_message (context, bar))
     _dbus_assert_not_reached ("hello message failed");
+
+  if (!check_add_match_all (context, bar))
+    _dbus_assert_not_reached ("AddMatch message failed");
   
   baz = dbus_connection_open ("debug-pipe:name=test-server", &error);
   if (baz == NULL)
@@ -1898,6 +2064,9 @@ bus_dispatch_test (const DBusString *test_data_dir)
   if (!check_hello_message (context, baz))
     _dbus_assert_not_reached ("hello message failed");
 
+  if (!check_add_match_all (context, baz))
+    _dbus_assert_not_reached ("AddMatch message failed");
+  
   if (!check_no_leftovers (context))
     {
       _dbus_warn ("Messages were left over after setting up initial connections");
@@ -1954,6 +2123,9 @@ bus_dispatch_sha1_test (const DBusString *test_data_dir)
   if (!check_hello_message (context, foo))
     _dbus_assert_not_reached ("hello message failed");
 
+  if (!check_add_match_all (context, foo))
+    _dbus_assert_not_reached ("addmatch message failed");
+  
   if (!check_no_leftovers (context))
     {
       _dbus_warn ("Messages were left over after setting up initial SHA-1 connection\n");
index 18f7452..d8107b1 100644 (file)
@@ -29,8 +29,9 @@
 
 dbus_bool_t bus_dispatch_add_connection    (DBusConnection *connection);
 void        bus_dispatch_remove_connection (DBusConnection *connection);
-dbus_bool_t bus_dispatch_broadcast_message (BusTransaction *transaction,
+dbus_bool_t bus_dispatch_matches           (BusTransaction *transaction,
                                             DBusConnection *sender,
+                                            DBusConnection *recipient,
                                             DBusMessage    *message,
                                             DBusError      *error);
 
index 61bfe1c..791fcd6 100644 (file)
@@ -27,6 +27,7 @@
 #include "driver.h"
 #include "dispatch.h"
 #include "services.h"
+#include "signals.h"
 #include "utils.h"
 #include <dbus/dbus-string.h>
 #include <dbus/dbus-internals.h>
@@ -69,7 +70,7 @@ bus_driver_send_service_deleted (const char     *service_name,
       return FALSE;
     }
 
-  retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
+  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
   dbus_message_unref (message);
 
   return retval;
@@ -111,7 +112,7 @@ bus_driver_send_service_created (const char     *service_name,
       return FALSE;
     }
   
-  retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
+  retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
   dbus_message_unref (message);
 
   return retval;
@@ -331,6 +332,7 @@ bus_driver_handle_hello (DBusConnection *connection,
   
   bus_service_set_prohibit_replacement (service, TRUE);
 
+  _dbus_assert (bus_connection_is_active (connection));
   retval = TRUE;
   
  out_0:
@@ -600,6 +602,160 @@ bus_driver_handle_activate_service (DBusConnection *connection,
   return retval;
 }
 
+static dbus_bool_t
+send_ack_reply (DBusConnection *connection,
+                BusTransaction *transaction,
+                DBusMessage    *message,
+                DBusError      *error)
+{
+  DBusMessage *reply;
+
+  reply = dbus_message_new_method_return (message);
+  if (reply == NULL)
+    {
+      BUS_SET_OOM (error);
+      return FALSE;
+    }
+
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
+    {
+      BUS_SET_OOM (error);
+      dbus_message_unref (reply);
+      return FALSE;
+    }
+
+  dbus_message_unref (reply);
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+bus_driver_handle_add_match (DBusConnection *connection,
+                             BusTransaction *transaction,
+                             DBusMessage    *message,
+                             DBusError      *error)
+{
+  BusMatchRule *rule;
+  char *text;
+  DBusString str;
+  BusMatchmaker *matchmaker;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  text = NULL;
+  rule = NULL;
+
+  if (bus_connection_get_n_match_rules (connection) >=
+      bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "Connection \"%s\" is not allowed to add more match rules "
+                      "(increase limits in configuration file if required)",
+                      bus_connection_is_active (connection) ?
+                      bus_connection_get_name (connection) :
+                      "(inactive)");
+      goto failed;
+    }
+  
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &text,
+                              DBUS_TYPE_INVALID))
+    {
+      _dbus_verbose ("No memory to get arguments to AddMatch\n");
+      goto failed;
+    }
+
+  _dbus_string_init_const (&str, text);
+
+  rule = bus_match_rule_parse (connection, &str, error);
+  if (rule == NULL)
+    goto failed;
+
+  matchmaker = bus_connection_get_matchmaker (connection);
+
+  if (!bus_matchmaker_add_rule (matchmaker, rule))
+    {
+      BUS_SET_OOM (error);
+      goto failed;
+    }
+
+  if (!send_ack_reply (connection, transaction,
+                       message, error))
+    {
+      bus_matchmaker_remove_rule (matchmaker, rule);
+      goto failed;
+    }
+  
+  bus_match_rule_unref (rule);
+  dbus_free (text);
+  
+  return TRUE;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (rule)
+    bus_match_rule_unref (rule);
+  if (text)
+    dbus_free (text);
+  return FALSE;
+}
+
+static dbus_bool_t
+bus_driver_handle_remove_match (DBusConnection *connection,
+                                BusTransaction *transaction,
+                                DBusMessage    *message,
+                                DBusError      *error)
+{
+  BusMatchRule *rule;
+  char *text;
+  DBusString str;
+  BusMatchmaker *matchmaker;
+  
+  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  text = NULL;
+  rule = NULL;
+  
+  if (!dbus_message_get_args (message, error,
+                              DBUS_TYPE_STRING, &text,
+                              DBUS_TYPE_INVALID))
+    {
+      _dbus_verbose ("No memory to get arguments to RemoveMatch\n");
+      goto failed;
+    }
+
+  _dbus_string_init_const (&str, text);
+
+  rule = bus_match_rule_parse (connection, &str, error);
+  if (rule == NULL)
+    goto failed;
+
+  /* Send the ack before we remove the rule, since the ack is undone
+   * on transaction cancel, but rule removal isn't.
+   */
+  if (!send_ack_reply (connection, transaction,
+                       message, error))
+    goto failed;
+  
+  matchmaker = bus_connection_get_matchmaker (connection);
+
+  if (!bus_matchmaker_remove_rule_by_value (matchmaker, rule, error))
+    goto failed;
+
+  bus_match_rule_unref (rule);
+  dbus_free (text);
+  
+  return TRUE;
+
+ failed:
+  _DBUS_ASSERT_ERROR_IS_SET (error);
+  if (rule)
+    bus_match_rule_unref (rule);
+  if (text)
+    dbus_free (text);
+  return FALSE;
+}
+
 /* For speed it might be useful to sort this in order of
  * frequency of use (but doesn't matter with only a few items
  * anyhow)
@@ -616,7 +772,9 @@ struct
   { "ActivateService", bus_driver_handle_activate_service },
   { "Hello", bus_driver_handle_hello },
   { "ServiceExists", bus_driver_handle_service_exists },
-  { "ListServices", bus_driver_handle_list_services }
+  { "ListServices", bus_driver_handle_list_services },
+  { "AddMatch", bus_driver_handle_add_match },
+  { "RemoveMatch", bus_driver_handle_remove_match }
 };
 
 dbus_bool_t
index 21d0b02..2d462fb 100644 (file)
@@ -917,16 +917,33 @@ dbus_bool_t
 bus_client_policy_check_can_receive (BusClientPolicy *policy,
                                      BusRegistry     *registry,
                                      DBusConnection  *sender,
+                                     DBusConnection  *addressed_recipient,
+                                     DBusConnection  *proposed_recipient,
                                      DBusMessage     *message)
 {
   DBusList *link;
   dbus_bool_t allowed;
+  dbus_bool_t eavesdropping;
+  
+  /* NULL sender, proposed_recipient means the bus driver.  NULL
+   * addressed_recipient means the message didn't specify an explicit
+   * target. If proposed_recipient is NULL, then addressed_recipient
+   * is also NULL but is implicitly the bus driver.
+   */
+
+  _dbus_assert (proposed_recipient == NULL ||
+                (dbus_message_get_destination (message) == NULL ||
+                 addressed_recipient != NULL));
+  
+  eavesdropping =
+    (proposed_recipient == NULL || /* explicitly to bus driver */
+     (addressed_recipient && addressed_recipient != proposed_recipient)); /* explicitly to a different recipient */
   
   /* policy->rules is in the order the rules appeared
    * in the config file, i.e. last rule that applies wins
    */
 
-  _dbus_verbose ("  (policy) checking receive rules\n");
+  _dbus_verbose ("  (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
   
   allowed = FALSE;
   link = _dbus_list_get_first_link (&policy->rules);
@@ -950,6 +967,24 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
               continue;
             }
         }
+
+      /* for allow, eavesdrop=false means the rule doesn't apply when
+       * eavesdropping. eavesdrop=true means always allow.
+       */
+      if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop)
+        {
+          _dbus_verbose ("  (policy) skipping allow rule since it doesn't apply to eavesdropping\n");
+          continue;
+        }
+
+      /* for deny, eavesdrop=true means the rule applies only when
+       * eavesdropping; eavesdrop=false means always deny.
+       */
+      if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop)
+        {
+          _dbus_verbose ("  (policy) skipping deny rule since it only applies to eavesdropping\n");
+          continue;
+        }
       
       if (rule->d.receive.path != NULL)
         {
@@ -1036,7 +1071,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
                 }
             }
         }
-
+      
       /* Use this rule */
       allowed = rule->allow;
 
index 5824816..63981cc 100644 (file)
@@ -74,6 +74,7 @@ struct BusPolicyRule
       char *member;
       char *error;
       char *origin;
+      unsigned int eavesdrop : 1;
     } receive;
 
     struct
@@ -134,6 +135,8 @@ dbus_bool_t      bus_client_policy_check_can_send    (BusClientPolicy  *policy,
 dbus_bool_t      bus_client_policy_check_can_receive (BusClientPolicy  *policy,
                                                       BusRegistry      *registry,
                                                       DBusConnection   *sender,
+                                                      DBusConnection   *addressed_recipient,
+                                                      DBusConnection   *proposed_recipient,
                                                       DBusMessage      *message);
 dbus_bool_t      bus_client_policy_check_can_own     (BusClientPolicy  *policy,
                                                       DBusConnection   *connection,
index 09dd250..4594568 100644 (file)
 
   <policy context="default">
     <!-- Allow everything -->
-    <allow send_interface="*"/>
-    <allow receive_interface="*"/>
+    <allow eavesdrop="true"/>
     <allow own="*"/>
-    <allow user="*"/>  
+    <allow user="*"/>
   </policy>
 
   <!-- This is included last so local configuration can override what's 
diff --git a/bus/signals.c b/bus/signals.c
new file mode 100644 (file)
index 0000000..db7b066
--- /dev/null
@@ -0,0 +1,774 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* signals.c  Bus signal connection implementation
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 1.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+#include "signals.h"
+#include "services.h"
+#include "utils.h"
+
+struct BusMatchRule
+{
+  int refcount;       /**< reference count */
+
+  DBusConnection *matches_go_to; /**< Owner of the rule */
+
+  unsigned int flags; /**< BusMatchFlags */
+
+  int   message_type;
+  char *interface;
+  char *member;
+  char *sender;
+  char *destination;
+  char *path;
+};
+
+BusMatchRule*
+bus_match_rule_new (DBusConnection *matches_go_to)
+{
+  BusMatchRule *rule;
+
+  rule = dbus_new0 (BusMatchRule, 1);
+  if (rule == NULL)
+    return NULL;
+
+  rule->refcount = 1;
+  rule->matches_go_to = matches_go_to;
+
+  return rule;
+}
+
+void
+bus_match_rule_ref (BusMatchRule *rule)
+{
+  _dbus_assert (rule->refcount > 0);
+
+  rule->refcount += 1;
+}
+
+void
+bus_match_rule_unref (BusMatchRule *rule)
+{
+  _dbus_assert (rule->refcount > 0);
+
+  rule->refcount -= 1;
+  if (rule->refcount == 0)
+    {
+      dbus_free (rule->interface);
+      dbus_free (rule->member);
+      dbus_free (rule->sender);
+      dbus_free (rule->destination);
+      dbus_free (rule->path);
+      dbus_free (rule);
+    }
+}
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+static char*
+match_rule_to_string (BusMatchRule *rule)
+{
+  DBusString str;
+  char *ret;
+  
+  if (!_dbus_string_init (&str))
+    {
+      char *s;
+      while ((s = _dbus_strdup ("nomem")) == NULL)
+        ; /* only OK for debug spew... */
+      return s;
+    }
+  
+  if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
+    {
+      /* FIXME make type readable */
+      if (!_dbus_string_append_printf (&str, "type='%d'", rule->message_type))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_INTERFACE)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "interface='%s'", rule->interface))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_MEMBER)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "member='%s'", rule->member))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_PATH)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "path='%s'", rule->path))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_SENDER)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "sender='%s'", rule->sender))
+        goto nomem;
+    }
+
+  if (rule->flags & BUS_MATCH_DESTINATION)
+    {
+      if (_dbus_string_get_length (&str) > 0)
+        {
+          if (!_dbus_string_append (&str, ","))
+            goto nomem;
+        }
+      
+      if (!_dbus_string_append_printf (&str, "destination='%s'", rule->destination))
+        goto nomem;
+    }
+  
+  if (!_dbus_string_steal_data (&str, &ret))
+    goto nomem;
+
+  _dbus_string_free (&str);
+  return ret;
+  
+ nomem:
+  _dbus_string_free (&str);
+  {
+    char *s;
+    while ((s = _dbus_strdup ("nomem")) == NULL)
+      ;  /* only OK for debug spew... */
+    return s;
+  }
+}
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+
+dbus_bool_t
+bus_match_rule_set_message_type (BusMatchRule *rule,
+                                 int           type)
+{
+  rule->flags |= BUS_MATCH_MESSAGE_TYPE;
+
+  rule->message_type = type;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_interface (BusMatchRule *rule,
+                              const char   *interface)
+{
+  char *new;
+
+  _dbus_assert (interface != NULL);
+
+  new = _dbus_strdup (interface);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_INTERFACE;
+  dbus_free (rule->interface);
+  rule->interface = new;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_member (BusMatchRule *rule,
+                           const char   *member)
+{
+  char *new;
+
+  _dbus_assert (member != NULL);
+
+  new = _dbus_strdup (member);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_MEMBER;
+  dbus_free (rule->member);
+  rule->member = new;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_sender (BusMatchRule *rule,
+                           const char   *sender)
+{
+  char *new;
+
+  _dbus_assert (sender != NULL);
+
+  new = _dbus_strdup (sender);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_SENDER;
+  dbus_free (rule->sender);
+  rule->sender = new;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_destination (BusMatchRule *rule,
+                                const char   *destination)
+{
+  char *new;
+
+  _dbus_assert (destination != NULL);
+
+  new = _dbus_strdup (destination);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_DESTINATION;
+  dbus_free (rule->destination);
+  rule->destination = new;
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_match_rule_set_path (BusMatchRule *rule,
+                         const char   *path)
+{
+  char *new;
+
+  _dbus_assert (path != NULL);
+
+  new = _dbus_strdup (path);
+  if (new == NULL)
+    return FALSE;
+
+  rule->flags |= BUS_MATCH_PATH;
+  dbus_free (rule->path);
+  rule->path = new;
+
+  return TRUE;
+}
+
+/*
+ * The format is comma-separated with strings quoted with single quotes
+ * as for the shell (to escape a literal single quote, use '\'').
+ *
+ * type='signal',sender='org.freedesktop.DBus',interface='org.freedesktop.DBus',member='Foo',
+ * path='/bar/foo',destination=':452345-34'
+ *
+ */
+BusMatchRule*
+bus_match_rule_parse (DBusConnection   *matches_go_to,
+                      const DBusString *rule_text,
+                      DBusError        *error)
+{
+  BusMatchRule *rule;
+
+  rule = bus_match_rule_new (matches_go_to);
+  if (rule == NULL)
+    goto oom;
+
+  /* FIXME implement for real */
+  
+  if (!bus_match_rule_set_message_type (rule,
+                                        DBUS_MESSAGE_TYPE_SIGNAL))
+    goto oom;
+  
+  return rule;
+  
+ oom:
+  if (rule)
+    bus_match_rule_unref (rule);
+  BUS_SET_OOM (error);
+  return NULL;
+}
+
+struct BusMatchmaker
+{
+  int refcount;
+
+  DBusList *all_rules;
+};
+
+BusMatchmaker*
+bus_matchmaker_new (void)
+{
+  BusMatchmaker *matchmaker;
+
+  matchmaker = dbus_new0 (BusMatchmaker, 1);
+  if (matchmaker == NULL)
+    return NULL;
+
+  matchmaker->refcount = 1;
+  
+  return matchmaker;
+}
+
+void
+bus_matchmaker_ref (BusMatchmaker *matchmaker)
+{
+  _dbus_assert (matchmaker->refcount > 0);
+
+  matchmaker->refcount += 1;
+}
+
+void
+bus_matchmaker_unref (BusMatchmaker *matchmaker)
+{
+  _dbus_assert (matchmaker->refcount > 0);
+
+  matchmaker->refcount -= 1;
+  if (matchmaker->refcount == 0)
+    {
+      while (matchmaker->all_rules != NULL)
+        {
+          BusMatchRule *rule;
+
+          rule = matchmaker->all_rules->data;
+          bus_match_rule_unref (rule);
+          _dbus_list_remove_link (&matchmaker->all_rules,
+                                  matchmaker->all_rules);
+        }
+
+      dbus_free (matchmaker);
+    }
+}
+
+/* The rule can't be modified after it's added. */
+dbus_bool_t
+bus_matchmaker_add_rule (BusMatchmaker   *matchmaker,
+                         BusMatchRule    *rule)
+{
+  _dbus_assert (bus_connection_is_active (rule->matches_go_to));
+
+  if (!_dbus_list_append (&matchmaker->all_rules, rule))
+    return FALSE;
+
+  if (!bus_connection_add_match_rule (rule->matches_go_to, rule))
+    {
+      _dbus_list_remove_last (&matchmaker->all_rules, rule);
+      return FALSE;
+    }
+  
+  bus_match_rule_ref (rule);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  {
+    char *s = match_rule_to_string (rule);
+
+    _dbus_verbose ("Added match rule %s to connection %p\n",
+                   s, rule->matches_go_to);
+    dbus_free (s);
+  }
+#endif
+  
+  return TRUE;
+}
+
+static dbus_bool_t
+match_rule_equal (BusMatchRule *a,
+                  BusMatchRule *b)
+{
+  if (a->flags != b->flags)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_MESSAGE_TYPE) &&
+      a->message_type != b->message_type)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_MEMBER) &&
+      strcmp (a->member, b->member) != 0)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_PATH) &&
+      strcmp (a->path, b->path) != 0)
+    return FALSE;
+  
+  if ((a->flags & BUS_MATCH_INTERFACE) &&
+      strcmp (a->interface, b->interface) != 0)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_SENDER) &&
+      strcmp (a->sender, b->sender) != 0)
+    return FALSE;
+
+  if ((a->flags & BUS_MATCH_DESTINATION) &&
+      strcmp (a->destination, b->destination) != 0)
+    return FALSE;
+
+  return TRUE;
+}
+
+static void
+bus_matchmaker_remove_rule_link (BusMatchmaker   *matchmaker,
+                                 DBusList        *link)
+{
+  BusMatchRule *rule = link->data;
+  
+  bus_connection_remove_match_rule (rule->matches_go_to, rule);
+  _dbus_list_remove_link (&matchmaker->all_rules, link);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  {
+    char *s = match_rule_to_string (rule);
+
+    _dbus_verbose ("Removed match rule %s for connection %p\n",
+                   s, rule->matches_go_to);
+    dbus_free (s);
+  }
+#endif
+  
+  bus_match_rule_unref (rule);  
+}
+
+void
+bus_matchmaker_remove_rule (BusMatchmaker   *matchmaker,
+                            BusMatchRule    *rule)
+{
+  bus_connection_remove_match_rule (rule->matches_go_to, rule);
+  _dbus_list_remove (&matchmaker->all_rules, rule);
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+  {
+    char *s = match_rule_to_string (rule);
+
+    _dbus_verbose ("Removed match rule %s for connection %p\n",
+                   s, rule->matches_go_to);
+    dbus_free (s);
+  }
+#endif
+  
+  bus_match_rule_unref (rule);
+}
+
+/* Remove a single rule which is equal to the given rule by value */
+dbus_bool_t
+bus_matchmaker_remove_rule_by_value (BusMatchmaker   *matchmaker,
+                                     BusMatchRule    *value,
+                                     DBusError       *error)
+{
+  /* FIXME this is an unoptimized linear scan */
+
+  DBusList *link;
+
+  /* we traverse backward because bus_connection_remove_match_rule()
+   * removes the most-recently-added rule
+   */
+  link = _dbus_list_get_last_link (&matchmaker->all_rules);
+  while (link != NULL)
+    {
+      BusMatchRule *rule;
+      DBusList *prev;
+
+      rule = link->data;
+      prev = _dbus_list_get_prev_link (&matchmaker->all_rules, link);
+
+      if (match_rule_equal (rule, value))
+        {
+          bus_matchmaker_remove_rule_link (matchmaker, link);
+          break;
+        }
+
+      link = prev;
+    }
+
+  if (link == NULL)
+    {
+      dbus_set_error (error, DBUS_ERROR_MATCH_RULE_NOT_FOUND,
+                      "The given match rule wasn't found and can't be removed");
+      return FALSE;
+    }
+
+  return TRUE;
+}
+
+void
+bus_matchmaker_disconnected (BusMatchmaker   *matchmaker,
+                             DBusConnection  *disconnected)
+{
+  DBusList *link;
+
+  /* FIXME
+   *
+   * This scans all match rules on the bus. We could avoid that
+   * for the rules belonging to the connection, since we keep
+   * a list of those; but for the rules that just refer to
+   * the connection we'd need to do something more elaborate.
+   * 
+   */
+  
+  _dbus_assert (bus_connection_is_active (disconnected));
+
+  link = _dbus_list_get_first_link (&matchmaker->all_rules);
+  while (link != NULL)
+    {
+      BusMatchRule *rule;
+      DBusList *next;
+
+      rule = link->data;
+      next = _dbus_list_get_next_link (&matchmaker->all_rules, link);
+
+      if (rule->matches_go_to == disconnected)
+        {
+          bus_matchmaker_remove_rule_link (matchmaker, link);
+        }
+      else if (((rule->flags & BUS_MATCH_SENDER) && *rule->sender == ':') ||
+               ((rule->flags & BUS_MATCH_DESTINATION) && *rule->destination == ':'))
+        {
+          /* The rule matches to/from a base service, see if it's the
+           * one being disconnected, since we know this service name
+           * will never be recycled.
+           */
+          const char *name;
+
+          name = bus_connection_get_name (disconnected);
+          _dbus_assert (name != NULL); /* because we're an active connection */
+
+          if (((rule->flags & BUS_MATCH_SENDER) &&
+               strcmp (rule->sender, name) == 0) ||
+              ((rule->flags & BUS_MATCH_DESTINATION) &&
+               strcmp (rule->destination, name) == 0))
+            {
+              bus_matchmaker_remove_rule_link (matchmaker, link);
+            }
+        }
+
+      link = next;
+    }
+}
+
+static dbus_bool_t
+connection_is_primary_owner (DBusConnection *connection,
+                             const char     *service_name)
+{
+  BusService *service;
+  DBusString str;
+  BusRegistry *registry;
+
+  registry = bus_connection_get_registry (connection);
+
+  _dbus_string_init_const (&str, service_name);
+  service = bus_registry_lookup (registry, &str);
+
+  if (service == NULL)
+    return FALSE; /* Service doesn't exist so connection can't own it. */
+
+  return bus_service_get_primary_owner (service) == connection;
+}
+
+static dbus_bool_t
+match_rule_matches (BusMatchRule    *rule,
+                    BusConnections  *connections,
+                    DBusConnection  *sender,
+                    DBusConnection  *addressed_recipient,
+                    DBusMessage     *message)
+{
+  /* All features of the match rule are AND'd together,
+   * so FALSE if any of them don't match.
+   */
+
+  if (rule->flags & BUS_MATCH_MESSAGE_TYPE)
+    {
+      _dbus_assert (rule->message_type != DBUS_MESSAGE_TYPE_INVALID);
+
+      if (rule->message_type != dbus_message_get_type (message))
+        return FALSE;
+    }
+
+  if (rule->flags & BUS_MATCH_INTERFACE)
+    {
+      const char *iface;
+
+      _dbus_assert (rule->interface != NULL);
+
+      iface = dbus_message_get_interface (message);
+      if (iface == NULL)
+        return FALSE;
+
+      if (strcmp (iface, rule->interface) != 0)
+        return FALSE;
+    }
+
+  if (rule->flags & BUS_MATCH_MEMBER)
+    {
+      const char *member;
+
+      _dbus_assert (rule->member != NULL);
+
+      member = dbus_message_get_member (message);
+      if (member == NULL)
+        return FALSE;
+
+      if (strcmp (member, rule->member) != 0)
+        return FALSE;
+    }
+
+  if (rule->flags & BUS_MATCH_SENDER)
+    {
+      _dbus_assert (rule->sender != NULL);
+
+      if (!connection_is_primary_owner (sender, rule->sender))
+        return FALSE;
+    }
+
+  if (rule->flags & BUS_MATCH_DESTINATION)
+    {
+      const char *destination;
+
+      _dbus_assert (rule->destination != NULL);
+
+      if (addressed_recipient == NULL)
+        return FALSE;
+
+      destination = dbus_message_get_destination (message);
+      if (destination == NULL)
+        return FALSE;
+
+      if (!connection_is_primary_owner (addressed_recipient, rule->destination))
+        return FALSE;
+    }
+
+  if (rule->flags & BUS_MATCH_PATH)
+    {
+      const char *path;
+
+      _dbus_assert (rule->path != NULL);
+
+      path = dbus_message_get_path (message);
+      if (path == NULL)
+        return FALSE;
+
+      if (strcmp (path, rule->path) != 0)
+        return FALSE;
+    }
+
+  return TRUE;
+}
+
+dbus_bool_t
+bus_matchmaker_get_recipients (BusMatchmaker   *matchmaker,
+                               BusConnections  *connections,
+                               DBusConnection  *sender,
+                               DBusConnection  *addressed_recipient,
+                               DBusMessage     *message,
+                               DBusList       **recipients_p)
+{
+  /* FIXME for now this is a wholly unoptimized linear search */
+
+  DBusList *link;
+
+  _dbus_assert (*recipients_p == NULL);
+
+  /* This avoids sending same message to the same connection twice.
+   * Purpose of the stamp instead of a bool is to avoid iterating over
+   * all connections resetting the bool each time.
+   */
+  bus_connections_increment_stamp (connections);
+
+  /* addressed_recipient is already receiving the message, don't add to list.
+   * NULL addressed_recipient means either bus driver, or this is a signal
+   * and thus lacks a specific addressed_recipient.
+   */
+  if (addressed_recipient != NULL)
+    bus_connection_mark_stamp (addressed_recipient);
+
+  link = _dbus_list_get_first_link (&matchmaker->all_rules);
+  while (link != NULL)
+    {
+      BusMatchRule *rule;
+
+      rule = link->data;
+
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+      {
+        char *s = match_rule_to_string (rule);
+        
+        _dbus_verbose ("Checking whether message matches rule %s for connection %p\n",
+                       s, rule->matches_go_to);
+        dbus_free (s);
+      }
+#endif
+      
+      if (match_rule_matches (rule, connections,
+                              sender, addressed_recipient, message))
+        {
+          _dbus_verbose ("Rule matched\n");
+          
+          /* Append to the list if we haven't already */
+          if (bus_connection_mark_stamp (rule->matches_go_to))
+            {
+              if (!_dbus_list_append (recipients_p, rule->matches_go_to))
+                goto nomem;
+            }
+#ifdef DBUS_ENABLE_VERBOSE_MODE
+          else
+            {
+              _dbus_verbose ("Connection already receiving this message, so not adding again\n");
+            }
+#endif /* DBUS_ENABLE_VERBOSE_MODE */
+        }
+
+      link = _dbus_list_get_next_link (&matchmaker->all_rules, link);
+    }
+
+  return TRUE;
+
+ nomem:
+  _dbus_list_clear (recipients_p);
+  return FALSE;
+}
+
+#ifdef DBUS_BUILD_TESTS
+#include "test.h"
+
+dbus_bool_t
+bus_signals_test (const DBusString *test_data_dir)
+{
+  BusMatchmaker *matchmaker;
+
+  matchmaker = bus_matchmaker_new ();
+  bus_matchmaker_ref (matchmaker);
+  bus_matchmaker_unref (matchmaker);
+  bus_matchmaker_unref (matchmaker);
+  
+  return TRUE;
+}
+
+#endif /* DBUS_BUILD_TESTS */
+
diff --git a/bus/signals.h b/bus/signals.h
new file mode 100644 (file)
index 0000000..fab018a
--- /dev/null
@@ -0,0 +1,83 @@
+/* -*- mode: C; c-file-style: "gnu" -*- */
+/* signals.h  Bus signal connection implementation
+ *
+ * Copyright (C) 2003  Red Hat, Inc.
+ *
+ * Licensed under the Academic Free License version 1.2
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#ifndef BUS_SIGNALS_H
+#define BUS_SIGNALS_H
+
+#include <dbus/dbus.h>
+#include <dbus/dbus-string.h>
+#include <dbus/dbus-sysdeps.h>
+#include "connection.h"
+
+typedef enum
+{
+  BUS_MATCH_MESSAGE_TYPE = 1 << 0,
+  BUS_MATCH_INTERFACE    = 1 << 1,
+  BUS_MATCH_MEMBER       = 1 << 2,
+  BUS_MATCH_SENDER       = 1 << 3,
+  BUS_MATCH_DESTINATION  = 1 << 4,
+  BUS_MATCH_PATH         = 1 << 5
+} BusMatchFlags;
+
+BusMatchRule* bus_match_rule_new   (DBusConnection *matches_go_to);
+void          bus_match_rule_ref   (BusMatchRule   *rule);
+void          bus_match_rule_unref (BusMatchRule   *rule);
+
+dbus_bool_t bus_match_rule_set_message_type (BusMatchRule *rule,
+                                             int           type);
+dbus_bool_t bus_match_rule_set_interface    (BusMatchRule *rule,
+                                             const char   *interface);
+dbus_bool_t bus_match_rule_set_member       (BusMatchRule *rule,
+                                             const char   *member);
+dbus_bool_t bus_match_rule_set_sender       (BusMatchRule *rule,
+                                             const char   *sender);
+dbus_bool_t bus_match_rule_set_destination  (BusMatchRule *rule,
+                                             const char   *destination);
+dbus_bool_t bus_match_rule_set_path         (BusMatchRule *rule,
+                                             const char   *path);
+
+BusMatchRule* bus_match_rule_parse (DBusConnection   *matches_go_to,
+                                    const DBusString *rule_text,
+                                    DBusError        *error);
+
+BusMatchmaker* bus_matchmaker_new   (void);
+void           bus_matchmaker_ref   (BusMatchmaker *matchmaker);
+void           bus_matchmaker_unref (BusMatchmaker *matchmaker);
+
+dbus_bool_t bus_matchmaker_add_rule             (BusMatchmaker   *matchmaker,
+                                                 BusMatchRule    *rule);
+dbus_bool_t bus_matchmaker_remove_rule_by_value (BusMatchmaker   *matchmaker,
+                                                 BusMatchRule    *value,
+                                                 DBusError       *error);
+void        bus_matchmaker_remove_rule          (BusMatchmaker   *matchmaker,
+                                                 BusMatchRule    *rule);
+void        bus_matchmaker_disconnected         (BusMatchmaker   *matchmaker,
+                                                 DBusConnection  *disconnected);
+dbus_bool_t bus_matchmaker_get_recipients       (BusMatchmaker   *matchmaker,
+                                                 BusConnections  *connections,
+                                                 DBusConnection  *sender,
+                                                 DBusConnection  *addressed_recipient,
+                                                 DBusMessage     *message,
+                                                 DBusList       **recipients_p);
+
+#endif /* BUS_SIGNALS_H */
index 96513a7..122ea1b 100644 (file)
@@ -42,8 +42,8 @@
     <!-- Allow anyone to talk to the message bus -->
     <!-- FIXME I think currently these allow rules are always implicit 
          even if they aren't in here -->
-    <allow send_service="org.freedesktop.DBus"/>
-    <allow receive_service="org.freedesktop.DBus"/>
+    <allow send_destination="org.freedesktop.DBus"/>
+    <allow receive_sender="org.freedesktop.DBus"/>
   </policy>
 
   <!-- Config files are placed here that among other things, punch 
index c433075..3f280d4 100644 (file)
@@ -89,6 +89,12 @@ main (int argc, char **argv)
 
   check_memleaks (argv[0]);
 
+  printf ("%s: Running signals test\n", argv[0]);
+  if (!bus_signals_test (&test_data_dir))
+    die ("signals");
+
+  check_memleaks (argv[0]);
+  
   printf ("%s: Running SHA1 connection test\n", argv[0]);
   if (!bus_dispatch_sha1_test (&test_data_dir))
     die ("sha1");
index 36a69e6..fc972fe 100644 (file)
@@ -36,6 +36,7 @@ dbus_bool_t bus_dispatch_test         (const DBusString             *test_data_d
 dbus_bool_t bus_dispatch_sha1_test    (const DBusString             *test_data_dir);
 dbus_bool_t bus_policy_test           (const DBusString             *test_data_dir);
 dbus_bool_t bus_config_parser_test    (const DBusString             *test_data_dir);
+dbus_bool_t bus_signals_test          (const DBusString             *test_data_dir);
 dbus_bool_t bus_setup_debug_client    (DBusConnection               *connection);
 void        bus_test_clients_foreach  (BusConnectionForeachFunction  function,
                                        void                         *data);
index ad4801c..f229188 100644 (file)
@@ -53,13 +53,8 @@ struct DBusError
 };
 
 #define DBUS_ERROR_FAILED                     "org.freedesktop.DBus.Error.Failed"
-#define DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND "org.freedesktop.DBus.Activate.ServiceNotFound"
-#define DBUS_ERROR_SPAWN_EXEC_FAILED          "org.freedesktop.DBus.Error.Spawn.ExecFailed"
-#define DBUS_ERROR_SPAWN_FORK_FAILED          "org.freedesktop.DBus.Error.Spawn.ForkFailed"
-#define DBUS_ERROR_SPAWN_CHILD_EXITED         "org.freedesktop.DBus.Error.Spawn.ChildExited"
-#define DBUS_ERROR_SPAWN_CHILD_SIGNALED       "org.freedesktop.DBus.Error.Spawn.ChildSignaled"
-#define DBUS_ERROR_SPAWN_FAILED               "org.freedesktop.DBus.Error.Spawn.Failed"
 #define DBUS_ERROR_NO_MEMORY                  "org.freedesktop.DBus.Error.NoMemory"
+#define DBUS_ERROR_ACTIVATE_SERVICE_NOT_FOUND "org.freedesktop.DBus.Error.ServiceNotFound"
 #define DBUS_ERROR_SERVICE_DOES_NOT_EXIST     "org.freedesktop.DBus.Error.ServiceDoesNotExist"
 #define DBUS_ERROR_NO_REPLY                   "org.freedesktop.DBus.Error.NoReply"
 #define DBUS_ERROR_IO_ERROR                   "org.freedesktop.DBus.Error.IOError"
@@ -77,6 +72,12 @@ struct DBusError
 #define DBUS_ERROR_FILE_NOT_FOUND             "org.freedesktop.DBus.Error.FileNotFound"
 #define DBUS_ERROR_UNKNOWN_METHOD             "org.freedesktop.DBus.Error.UnknownMethod"
 #define DBUS_ERROR_TIMED_OUT                  "org.freedesktop.DBus.Error.TimedOut"
+#define DBUS_ERROR_MATCH_RULE_NOT_FOUND       "org.freedesktop.DBus.Error.MatchRuleNotFound"
+#define DBUS_ERROR_SPAWN_EXEC_FAILED          "org.freedesktop.DBus.Error.Spawn.ExecFailed"
+#define DBUS_ERROR_SPAWN_FORK_FAILED          "org.freedesktop.DBus.Error.Spawn.ForkFailed"
+#define DBUS_ERROR_SPAWN_CHILD_EXITED         "org.freedesktop.DBus.Error.Spawn.ChildExited"
+#define DBUS_ERROR_SPAWN_CHILD_SIGNALED       "org.freedesktop.DBus.Error.Spawn.ChildSignaled"
+#define DBUS_ERROR_SPAWN_FAILED               "org.freedesktop.DBus.Error.Spawn.Failed"
 
 void        dbus_error_init      (DBusError       *error);
 void        dbus_error_free      (DBusError       *error);
index f3b6827..6da5318 100644 (file)
@@ -28,7 +28,7 @@
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-sysdeps.h>
 
-#define MAINLOOP_SPEW 1
+#define MAINLOOP_SPEW 0
 
 struct DBusLoop
 {
index 329609d..a0cf54e 100644 (file)
@@ -84,7 +84,6 @@ extern "C" {
   
 /* Services */
 #define DBUS_SERVICE_ORG_FREEDESKTOP_DBUS      "org.freedesktop.DBus"
-#define DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST "org.freedesktop.Broadcast"
 
 /* Paths */
 #define DBUS_PATH_ORG_FREEDESKTOP_DBUS  "/org/freedesktop/DBus"
index 59ec6ea..4625cf2 100644 (file)
@@ -813,7 +813,9 @@ _dbus_transport_queue_messages (DBusTransport *transport)
 {
   DBusDispatchStatus status;
 
+#if 0
   _dbus_verbose ("_dbus_transport_queue_messages()\n");
+#endif
   
   /* Queue any messages */
   while ((status = _dbus_transport_get_dispatch_status (transport)) == DBUS_DISPATCH_DATA_REMAINS)
index caa8856..8186233 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
  - the invalid messages in the test suite are all useless because 
    they are invalid for the wrong reasons due to protocol changes
 
- - Nuke the org.freedesktop.Broadcast service; instead, 
-   just broadcast messages of type signal
-
  - I don't want to introduce DBusObject, but refcounting and object
    data could still be factored out into an internal "base class" 
    perhaps.
 
+ - modify the auth protocol to also support other initial-handshake
+   type of information
+
+ - document the auth protocol as a set of states and transitions, and
+   then reimplement it in those terms
+
  - Header fields names are required to be aligned on a 4 byte boundary
    at the moment. No alignment should be neccessary.
index 59d86a3..b77e7d3 100644 (file)
@@ -188,8 +188,8 @@ dbus_gproxy_begin_call (DBusGProxy *proxy,
   LOCK_PROXY (proxy);
 
   message = dbus_message_new_method_call (proxy->service,
-                                          proxy->interface,
                                           proxy->path,
+                                          proxy->interface,
                                           method);
   if (message == NULL)
     goto oom;
index 57ea5ec..f68430e 100644 (file)
     <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 send_destination="org.freedesktop.System"/>
+    <deny receive_sender="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"/>
+    <deny send_destination="org.freedesktop.Bar" send_interface="org.freedesktop.Foo"/>
+    <deny send_destination="org.freedesktop.Bar" send_interface="org.freedesktop.Foo" send_type="method_call"/>
   </policy>
 
   <policy context="mandatory">
     <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 send_destination="org.freedesktop.System"/>
+    <deny receive_sender="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"/>
+    <deny send_destination="org.freedesktop.Bar" send_interface="org.freedesktop.Foo"/>
+    <deny send_destination="org.freedesktop.Bar" send_interface="org.freedesktop.Foo" send_type="method_call"/>
   </policy>
 
   <limit name="max_incoming_bytes">5000</limit>   
index 10a7984..5b60a1f 100644 (file)
@@ -15,6 +15,6 @@
   <!-- Allow any connection to receive the message, but 
        only if the message is sent by the owner of FooService -->
   <policy context="default">
-    <allow receive_interface="org.foo.FooBroadcastInterface" receive_service="org.foo.FooService"/>
+    <allow receive_interface="org.foo.FooBroadcastInterface" receive_sender="org.foo.FooService"/>
   </policy>
 </busconfig>
index 67abe06..06a87ad 100644 (file)
@@ -44,7 +44,7 @@ main (int argc, char *argv[])
   DBusMessageIter iter;
   int i;
   DBusBusType type = DBUS_BUS_SESSION;
-  const char *dest = DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST;
+  const char *dest = NULL;
   const char *name = NULL;
   const char *path = NULL;
   int message_type = DBUS_MESSAGE_TYPE_SIGNAL;