2003-04-13 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Mon, 14 Apr 2003 02:29:21 +0000 (02:29 +0000)
committerHavoc Pennington <hp@redhat.com>
Mon, 14 Apr 2003 02:29:21 +0000 (02:29 +0000)
* dbus/dbus-mainloop.c: fix some reentrancy issues by refcounting
callbacks

* test/data/valid-config-files/debug-allow-all.conf.in: allow all
users

* dbus/dbus-transport.c (_dbus_transport_get_dispatch_status):
fix to only recover unused bytes if we're already authenticated
(_dbus_transport_get_is_authenticated): fix to still mark us
authenticated if there are unused bytes.

* bus/dispatch.c: implement security policy checking

* bus/connection.c (bus_transaction_send_from_driver): new

* bus/bus.c (bus_context_check_security_policy): new

* bus/dispatch.c (send_service_nonexistent_error): delete this,
now we just set the DBusError and it gets converted to an error
reply.

* bus/connection.c (allow_user_function): enable code using actual
data from the config file

* bus/policy.c (list_allows_user): handle wildcard rules for
user/group connection perms

23 files changed:
ChangeLog
bus/activation.c
bus/bus.c
bus/bus.h
bus/config-parser.c
bus/connection.c
bus/connection.h
bus/dispatch.c
bus/dispatch.h
bus/driver.c
bus/policy.c
bus/policy.h
bus/session.conf.in
bus/system.conf.in
dbus/dbus-connection.c
dbus/dbus-mainloop.c
dbus/dbus-message.c
dbus/dbus-sysdeps.c
dbus/dbus-sysdeps.h
dbus/dbus-transport-protected.h
dbus/dbus-transport.c
doc/TODO
test/data/valid-config-files/debug-allow-all.conf.in

index 1cb38e2..0d03e46 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,34 @@
 2003-04-13  Havoc Pennington  <hp@pobox.com>
 
+       * dbus/dbus-mainloop.c: fix some reentrancy issues by refcounting 
+       callbacks
+
+       * test/data/valid-config-files/debug-allow-all.conf.in: allow all
+       users
+
+       * dbus/dbus-transport.c (_dbus_transport_get_dispatch_status):
+       fix to only recover unused bytes if we're already authenticated
+       (_dbus_transport_get_is_authenticated): fix to still mark us 
+       authenticated if there are unused bytes.
+
+       * bus/dispatch.c: implement security policy checking
+       
+       * bus/connection.c (bus_transaction_send_from_driver): new
+
+       * bus/bus.c (bus_context_check_security_policy): new
+
+       * bus/dispatch.c (send_service_nonexistent_error): delete this,
+       now we just set the DBusError and it gets converted to an error
+       reply.
+
+       * bus/connection.c (allow_user_function): enable code using actual
+       data from the config file
+
+       * bus/policy.c (list_allows_user): handle wildcard rules for
+       user/group connection perms
+
+2003-04-13  Havoc Pennington  <hp@pobox.com>
+
        * bus/config-parser.c: Load up the BusPolicy and BusPolicyRules
        
        * dbus/dbus-sysdeps.c (_dbus_get_user_id): new function
index 1a448a7..0a70d6b 100644 (file)
@@ -582,8 +582,7 @@ bus_activation_service_created (BusActivation  *activation,
              goto error;
            }
 
-         if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
-              !dbus_message_append_args (message,
+         if (!dbus_message_append_args (message,
                                         DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ACTIVATED,
                                         0))
            {
@@ -592,7 +591,7 @@ bus_activation_service_created (BusActivation  *activation,
              goto error;
            }
           
-         if (!bus_transaction_send_message (transaction, entry->connection, message))
+         if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
            {
              dbus_message_unref (message);
              BUS_SET_OOM (error);
@@ -654,14 +653,8 @@ try_send_activation_failure (BusPendingActivation *pending_activation,
                                                   how->message);
          if (!message)
             goto error;
-
-         if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
-            {
-             dbus_message_unref (message);
-             goto error;
-           }
           
-         if (!bus_transaction_send_message (transaction, entry->connection, message))
+         if (!bus_transaction_send_from_driver (transaction, entry->connection, message))
            {
              dbus_message_unref (message);
              goto error;
@@ -861,8 +854,7 @@ bus_activation_activate_service (BusActivation  *activation,
          return FALSE;
        }
 
-      if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) ||
-          !dbus_message_append_args (message,
+      if (!dbus_message_append_args (message,
                                     DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE, 
                                     0))
        {
@@ -872,7 +864,7 @@ bus_activation_activate_service (BusActivation  *activation,
          return FALSE;
        }
 
-      retval = bus_transaction_send_message (transaction, connection, message);
+      retval = bus_transaction_send_from_driver (transaction, connection, message);
       dbus_message_unref (message);
       if (!retval)
         {
index 31b43f2..7b7ea6f 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -796,3 +796,66 @@ bus_context_get_activation_timeout (BusContext *context)
   
   return context->activation_timeout;
 }
+
+dbus_bool_t
+bus_context_check_security_policy (BusContext     *context,
+                                   DBusConnection *sender,
+                                   DBusConnection *recipient,
+                                   DBusMessage    *message,
+                                   DBusError      *error)
+{
+  BusClientPolicy *sender_policy;
+  BusClientPolicy *recipient_policy;
+
+  /* NULL sender/receiver means the bus driver */
+  
+  if (sender != NULL)
+    {
+      _dbus_assert (dbus_connection_get_is_authenticated (sender));
+      sender_policy = bus_connection_get_policy (sender);
+    }
+  else
+    sender_policy = NULL;
+
+  if (recipient != NULL)
+    {
+      _dbus_assert (dbus_connection_get_is_authenticated (recipient));
+      recipient_policy = bus_connection_get_policy (recipient);
+    }
+  else
+    recipient_policy = NULL;
+
+  if (sender_policy &&
+      !bus_client_policy_check_can_send (sender_policy,
+                                         context->registry, recipient,
+                                         message))
+    {
+      const char *dest = dbus_message_get_service (message);
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "A security policy in place prevents this sender "
+                      "from sending this message to this recipient, "
+                      "see message bus configuration file (rejected message "
+                      "had name \"%s\" destination \"%s\")",
+                      dbus_message_get_name (message),
+                      dest ? dest : DBUS_SERVICE_DBUS);
+      return FALSE;
+    }
+
+  if (recipient_policy &&
+      !bus_client_policy_check_can_receive (recipient_policy,
+                                            context->registry, sender,
+                                            message))
+    {
+      const char *dest = dbus_message_get_service (message);
+      dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
+                      "A security policy in place prevents this recipient "
+                      "from receiving this message from this sender, "
+                      "see message bus configuration file (rejected message "
+                      "had name \"%s\" destination \"%s\")",
+                      dbus_message_get_name (message),
+                      dest ? dest : DBUS_SERVICE_DBUS);
+      return FALSE;
+    }
+
+  return TRUE;
+}
index 754fab0..885182c 100644 (file)
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -57,6 +57,11 @@ dbus_bool_t      bus_context_allow_user             (BusContext       *context,
 BusClientPolicy* bus_context_create_client_policy   (BusContext       *context,
                                                      DBusConnection   *connection);
 int              bus_context_get_activation_timeout (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 85c367b..bf959ae 100644 (file)
@@ -859,7 +859,7 @@ append_rule_from_element (BusConfigParser   *parser,
           if (rule == NULL)
             goto nomem;
 
-          /* FIXME the wildcard needs storing in the rule somehow */
+          rule->d.user.uid = DBUS_UID_UNSET;
         }
       else
         {
@@ -873,10 +873,7 @@ append_rule_from_element (BusConfigParser   *parser,
               rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); 
               if (rule == NULL)
                 goto nomem;
-              
-              rule->d.user.user = _dbus_strdup (user);
-              if (rule->d.user.user == NULL)
-                goto nomem;
+
               rule->d.user.uid = uid;
             }
           else
@@ -894,7 +891,7 @@ append_rule_from_element (BusConfigParser   *parser,
           if (rule == NULL)
             goto nomem;
 
-          /* FIXME the wildcard needs storing in the rule somehow */
+          rule->d.group.gid = DBUS_GID_UNSET;
         }
       else
         {
@@ -908,10 +905,7 @@ append_rule_from_element (BusConfigParser   *parser,
               rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); 
               if (rule == NULL)
                 goto nomem;
-              
-              rule->d.group.group = _dbus_strdup (group);
-              if (rule->d.group.group == NULL)
-                goto nomem;
+
               rule->d.group.gid = gid;
             }
           else
index 21c8f1a..4c48fbd 100644 (file)
@@ -283,8 +283,6 @@ allow_user_function (DBusConnection *connection,
   d = BUS_CONNECTION_DATA (connection);
 
   _dbus_assert (d != NULL);
-
-  return TRUE; /* FIXME - this is just until we can parse a config file */
   
   return bus_context_allow_user (d->connections->context, uid);
 }
@@ -504,7 +502,7 @@ bus_connection_get_groups  (DBusConnection       *connection,
       
       if (dbus_connection_get_unix_user (connection, &uid))
         {
-          if (!_dbus_get_groups (uid, &d->group_ids, &d->n_group_ids))
+          if (!_dbus_get_groups (uid, &d->group_ids, &d->n_group_ids, NULL))
             {
               _dbus_verbose ("Did not get any groups for UID %lu\n",
                              uid);
@@ -924,9 +922,34 @@ bus_transaction_get_connections (BusTransaction  *transaction)
 }
 
 dbus_bool_t
-bus_transaction_send_message (BusTransaction *transaction,
-                              DBusConnection *connection,
-                              DBusMessage    *message)
+bus_transaction_send_from_driver (BusTransaction *transaction,
+                                  DBusConnection *connection,
+                                  DBusMessage    *message)
+{
+  /* We have to set the sender to the driver, and have
+   * to check security policy since it was not done in
+   * dispatch.c
+   */
+  _dbus_verbose ("Sending %s from driver\n",
+                 dbus_message_get_name (message));
+  
+  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
+    return FALSE;
+
+  /* If security policy doesn't allow the message, we silently
+   * 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))
+    return TRUE;
+
+  return bus_transaction_send (transaction, connection, message);
+}
+
+dbus_bool_t
+bus_transaction_send (BusTransaction *transaction,
+                      DBusConnection *connection,
+                      DBusMessage    *message)
 {
   MessageToSend *to_send;
   BusConnectionData *d;
@@ -934,7 +957,7 @@ bus_transaction_send_message (BusTransaction *transaction,
 
   _dbus_verbose ("  trying to add %s %s to transaction%s\n",
                  dbus_message_get_is_error (message) ? "error" :
-                 dbus_message_get_reply_serial (message) != 0 ? "reply" :
+                 dbus_message_get_reply_serial (message) != -1 ? "reply" :
                  "message",
                  dbus_message_get_name (message),
                  dbus_connection_get_is_connected (connection) ?
@@ -1152,8 +1175,7 @@ bus_transaction_send_error_reply (BusTransaction  *transaction,
   if (reply == NULL)
     return FALSE;
 
-  if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS) ||
-      !bus_transaction_send_message (transaction, connection, reply))
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
     {
       dbus_message_unref (reply);
       return FALSE;
index 4962211..ead4767 100644 (file)
@@ -84,7 +84,10 @@ typedef void (* BusTransactionCancelFunction) (void *data);
 BusTransaction* bus_transaction_new              (BusContext                   *context);
 BusContext*     bus_transaction_get_context      (BusTransaction               *transaction);
 BusConnections* bus_transaction_get_connections  (BusTransaction               *transaction);
-dbus_bool_t     bus_transaction_send_message     (BusTransaction               *transaction,
+dbus_bool_t     bus_transaction_send             (BusTransaction               *transaction,
+                                                  DBusConnection               *connection,
+                                                  DBusMessage                  *message);
+dbus_bool_t     bus_transaction_send_from_driver (BusTransaction               *transaction,
                                                   DBusConnection               *connection,
                                                   DBusMessage                  *message);
 dbus_bool_t     bus_transaction_send_error_reply (BusTransaction               *transaction,
index 4131754..3ce7731 100644 (file)
@@ -37,6 +37,8 @@ static int message_handler_slot_refcount;
 
 typedef struct
 {
+  BusContext     *context;
+  DBusConnection *sender;
   DBusMessage    *message;
   BusTransaction *transaction;
   DBusError      *error;
@@ -50,9 +52,16 @@ send_one_message (DBusConnection *connection, void *data)
   if (!bus_connection_is_active (connection))
     return TRUE;
 
-  if (!bus_transaction_send_message (d->transaction,
-                                     connection,
-                                     d->message))
+  if (!bus_context_check_security_policy (d->context,
+                                          d->sender,
+                                          connection,
+                                          d->message,
+                                          NULL))
+    return TRUE; /* silently don't send it */
+  
+  if (!bus_transaction_send (d->transaction,
+                             connection,
+                             d->message))
     {
       BUS_SET_OOM (d->error);
       return FALSE;
@@ -63,6 +72,7 @@ send_one_message (DBusConnection *connection, void *data)
 
 dbus_bool_t
 bus_dispatch_broadcast_message (BusTransaction *transaction,
+                                DBusConnection *sender,
                                 DBusMessage    *message,
                                 DBusError      *error)
 {
@@ -77,6 +87,8 @@ bus_dispatch_broadcast_message (BusTransaction *transaction,
   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;
@@ -92,70 +104,6 @@ bus_dispatch_broadcast_message (BusTransaction *transaction,
     return TRUE;
 }
 
-static dbus_bool_t
-send_service_nonexistent_error (BusTransaction *transaction,
-                                DBusConnection *connection,
-                                const char     *service_name,
-                                DBusMessage    *in_reply_to,
-                                DBusError      *error)
-{
-  DBusMessage *error_reply;
-  DBusString error_message;
-  const char *error_str;
-
-  _DBUS_ASSERT_ERROR_IS_CLEAR (error);
-  
-  /* Trying to send a message to a non-existant service,
-   * bounce back an error message.
-   */
-         
-  if (!_dbus_string_init (&error_message))
-    {
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-
-  if (!_dbus_string_append (&error_message, "Service \"") ||
-      !_dbus_string_append (&error_message, service_name) ||
-      !_dbus_string_append (&error_message, "\" does not exist"))
-    {
-      _dbus_string_free (&error_message);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-              
-  error_str = _dbus_string_get_const_data (&error_message);
-  error_reply = dbus_message_new_error_reply (in_reply_to,
-                                              DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
-                                              error_str);
-
-  _dbus_string_free (&error_message);
-              
-  if (error_reply == NULL)
-    {
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-
-  if (!dbus_message_set_sender (error_reply, DBUS_SERVICE_DBUS))
-    {
-      dbus_message_unref (error_reply);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }      
-  
-  if (!bus_transaction_send_message (transaction, connection, error_reply))
-    {
-      dbus_message_unref (error_reply);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-              
-  dbus_message_unref (error_reply);
-
-  return TRUE;
-}
-
 static void
 bus_dispatch (DBusConnection *connection,
               DBusMessage    *message)
@@ -188,9 +136,10 @@ bus_dispatch (DBusConnection *connection,
   _dbus_verbose ("DISPATCH: %s to %s\n",
                  message_name, service_name ? service_name : "peer");
   
-  /* 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 ping. Handle these
-   * immediately, especially disconnection messages.
+  /* 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
+   * ping. Handle these immediately, especially disconnection
+   * messages. There are no security policy checks on these.
    */
   if (service_name == NULL)
     {      
@@ -235,6 +184,10 @@ bus_dispatch (DBusConnection *connection,
 
   if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
     {
+      if (!bus_context_check_security_policy (context,
+                                              connection, NULL, message, &error))
+        goto out;
+      
       if (!bus_driver_handle_message (connection, transaction, message, &error))
        goto out;
     }
@@ -249,7 +202,7 @@ bus_dispatch (DBusConnection *connection,
    */
   else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */
     {
-      if (!bus_dispatch_broadcast_message (transaction, message, &error))
+      if (!bus_dispatch_broadcast_message (transaction, connection, message, &error))
         goto out;
     }
   else  /* route to named service */
@@ -265,19 +218,25 @@ bus_dispatch (DBusConnection *connection,
 
       if (service == NULL)
         {
-          if (!send_service_nonexistent_error (transaction, connection,
-                                               service_name,
-                                               message, &error))
-            goto out;
+          dbus_set_error (&error,
+                          DBUS_ERROR_SERVICE_DOES_NOT_EXIST,
+                          "Service \"%s\" does not exist",
+                          service_name);
+          goto out;
         }
       else
         {
-          _dbus_assert (bus_service_get_primary_owner (service) != NULL);
-      
+          DBusConnection *recipient;
+          
+          recipient = bus_service_get_primary_owner (service);
+          _dbus_assert (recipient != NULL);
+          
+          if (!bus_context_check_security_policy (context,
+                                                  connection, recipient, message, &error))
+            goto out;
+          
           /* Dispatch the message */
-          if (!bus_transaction_send_message (transaction,
-                                             bus_service_get_primary_owner (service),
-                                             message))
+          if (!bus_transaction_send (transaction, recipient, message))
             {
               BUS_SET_OOM (&error);
               goto out;
@@ -316,7 +275,7 @@ bus_dispatch (DBusConnection *connection,
                                                  &error, message))
             {
               bus_connection_send_oom_error (connection, message);
-
+              
               /* cancel transaction due to OOM */
               if (transaction != NULL)
                 {
@@ -608,8 +567,9 @@ kill_client_connection_unchecked (DBusConnection *connection)
   /* dispatching disconnect handler will unref once */
   if (bus_connection_dispatch_one_message (connection))
     _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register");
-  dbus_connection_unref (connection);
+
   _dbus_assert (!bus_test_client_listed (connection));
+  dbus_connection_unref (connection);
 }
 
 typedef struct
@@ -740,10 +700,12 @@ check_hello_message (BusContext     *context,
   DBusError error;
   char *name;
   char *acquired;
-  
+
+  retval = FALSE;
   dbus_error_init (&error);
   name = NULL;
   acquired = NULL;
+  message = NULL;
   
   message = dbus_message_new (DBUS_SERVICE_DBUS,
                              DBUS_MESSAGE_HELLO);
@@ -760,15 +722,22 @@ check_hello_message (BusContext     *context,
   dbus_message_unref (message);
   message = NULL;
 
-  bus_test_run_everything (context);
+  /* 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;
     }
-  
-  retval = FALSE;
+
+  dbus_connection_unref (connection);
   
   message = pop_message_waiting_for_memory (connection);
   if (message == NULL)
@@ -1390,7 +1359,10 @@ check_send_exit_to_service (BusContext     *context,
   message = dbus_connection_borrow_message (connection);
   got_error = message != NULL && dbus_message_get_is_error (message);
   if (message)
-    dbus_connection_return_message (connection, message);
+    {
+      dbus_connection_return_message (connection, message);
+      message = NULL;
+    }
           
   if (!got_error)
     {
@@ -1944,6 +1916,12 @@ bus_dispatch_test (const DBusString *test_data_dir)
   if (!check_hello_message (context, baz))
     _dbus_assert_not_reached ("hello message failed");
 
+  if (!check_no_leftovers (context))
+    {
+      _dbus_warn ("Messages were left over after setting up initial connections");
+      _dbus_assert_not_reached ("initial connection setup failed");
+    }
+  
   check1_try_iterations (context, "create_and_hello",
                          check_hello_connection);
   
index c24170d..18f7452 100644 (file)
@@ -30,6 +30,7 @@
 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,
+                                            DBusConnection *sender,
                                             DBusMessage    *message,
                                             DBusError      *error);
 
index f89b70a..c7d66d5 100644 (file)
@@ -67,7 +67,7 @@ bus_driver_send_service_deleted (const char     *service_name,
       return FALSE;
     }
 
-  retval = bus_dispatch_broadcast_message (transaction, message, error);
+  retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
   dbus_message_unref (message);
 
   return retval;
@@ -107,7 +107,7 @@ bus_driver_send_service_created (const char     *service_name,
       return FALSE;
     }
   
-  retval = bus_dispatch_broadcast_message (transaction, message, error);
+  retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
   dbus_message_unref (message);
 
   return retval;
@@ -131,13 +131,6 @@ bus_driver_send_service_lost (DBusConnection *connection,
       return FALSE;
     }
   
-  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
-    {
-      dbus_message_unref (message);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-  
   if (!dbus_message_append_args (message,
                                  DBUS_TYPE_STRING, service_name,
                                  0))
@@ -147,7 +140,7 @@ bus_driver_send_service_lost (DBusConnection *connection,
       return FALSE;
     }
 
-  if (!bus_transaction_send_message (transaction, connection, message))
+  if (!bus_transaction_send_from_driver (transaction, connection, message))
     {
       dbus_message_unref (message);
       BUS_SET_OOM (error);
@@ -178,13 +171,6 @@ bus_driver_send_service_acquired (DBusConnection *connection,
       return FALSE;
     }
   
-  if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS))
-    {
-      dbus_message_unref (message);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-  
   if (!dbus_message_append_args (message,
                                  DBUS_TYPE_STRING, service_name,
                                  0))
@@ -194,7 +180,7 @@ bus_driver_send_service_acquired (DBusConnection *connection,
       return FALSE;
     }
 
-  if (!bus_transaction_send_message (transaction, connection, message))
+  if (!bus_transaction_send_from_driver (transaction, connection, message))
     {
       dbus_message_unref (message);
       BUS_SET_OOM (error);
@@ -347,13 +333,6 @@ bus_driver_send_welcome_message (DBusConnection *connection,
       return FALSE;
     }
   
-  if (!dbus_message_set_sender (welcome, DBUS_SERVICE_DBUS))
-    {
-      dbus_message_unref (welcome);
-      BUS_SET_OOM (error);
-      return FALSE;
-    }
-  
   if (!dbus_message_append_args (welcome,
                                  DBUS_TYPE_STRING, name,
                                  NULL))
@@ -363,7 +342,7 @@ bus_driver_send_welcome_message (DBusConnection *connection,
       return FALSE;
     }
 
-  if (!bus_transaction_send_message (transaction, connection, welcome))
+  if (!bus_transaction_send_from_driver (transaction, connection, welcome))
     {
       dbus_message_unref (welcome);
       BUS_SET_OOM (error);
@@ -417,7 +396,7 @@ bus_driver_handle_list_services (DBusConnection *connection,
 
   dbus_free_string_array (services);
   
-  if (!bus_transaction_send_message (transaction, connection, reply))
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
     {
       dbus_message_unref (reply);
       BUS_SET_OOM (error);
@@ -474,19 +453,13 @@ bus_driver_handle_acquire_service (DBusConnection *connection,
       goto out;
     }
 
-  if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
-    {
-      BUS_SET_OOM (error);
-      goto out;
-    }
-
   if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, service_reply, DBUS_TYPE_INVALID))
     {
       BUS_SET_OOM (error);
       goto out;
     }
 
-  if (!bus_transaction_send_message (transaction, connection, reply))
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
     {
       BUS_SET_OOM (error);
       goto out;
@@ -534,12 +507,6 @@ bus_driver_handle_service_exists (DBusConnection *connection,
       BUS_SET_OOM (error);
       goto out;
     }
-  
-  if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS))
-    {
-      BUS_SET_OOM (error);
-      goto out;
-    }
 
   if (!dbus_message_append_args (reply,
                                  DBUS_TYPE_UINT32, service != NULL,
@@ -549,7 +516,7 @@ bus_driver_handle_service_exists (DBusConnection *connection,
       goto out;
     }
 
-  if (!bus_transaction_send_message (transaction, connection, reply))
+  if (!bus_transaction_send_from_driver (transaction, connection, reply))
     {
       BUS_SET_OOM (error);
       goto out;
@@ -653,6 +620,12 @@ bus_driver_handle_message (DBusConnection *connection,
       return FALSE;
     }
 
+  if (dbus_message_get_reply_serial (message) != -1)
+    {
+      _dbus_verbose ("Client sent a reply to the bus driver, ignoring it\n");
+      return TRUE;
+    }
+  
   i = 0;
   while (i < _DBUS_N_ELEMENTS (message_handlers))
     {
index 81894b8..ad0cfae 100644 (file)
@@ -73,7 +73,7 @@ bus_policy_rule_unref (BusPolicyRule *rule)
   _dbus_assert (rule->refcount > 0);
 
   rule->refcount -= 1;
-
+  
   if (rule->refcount == 0)
     {
       switch (rule->type)
@@ -90,10 +90,8 @@ bus_policy_rule_unref (BusPolicyRule *rule)
           dbus_free (rule->d.own.service_name);
           break;
         case BUS_POLICY_RULE_USER:
-          dbus_free (rule->d.user.user);
           break;
         case BUS_POLICY_RULE_GROUP:
-          dbus_free (rule->d.group.group);
           break;
         }
       
@@ -239,7 +237,6 @@ bus_policy_create_client_policy (BusPolicy      *policy,
 {
   BusClientPolicy *client;
   unsigned long uid;
-  DBusList **list;
 
   _dbus_assert (dbus_connection_get_is_authenticated (connection));
   
@@ -266,6 +263,8 @@ bus_policy_create_client_policy (BusPolicy      *policy,
       i = 0;
       while (i < n_groups)
         {
+          DBusList **list;
+          
           list = _dbus_hash_table_lookup_ulong (policy->rules_by_gid,
                                                 groups[i]);
           
@@ -282,12 +281,20 @@ bus_policy_create_client_policy (BusPolicy      *policy,
   if (!dbus_connection_get_unix_user (connection, &uid))
     goto failed;
 
-  list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid,
-                                        uid);
+  if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0)
+    {
+      DBusList **list;
+      
+      list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid,
+                                            uid);
+
+      if (list != NULL)
+        {
+          if (!add_list_to_client (list, client))
+            goto failed;
+        }
+    }
 
-  if (!add_list_to_client (list, client))
-    goto failed;
-  
   if (!add_list_to_client (&policy->mandatory_rules,
                            client))
     goto failed;
@@ -310,9 +317,6 @@ list_allows_user (dbus_bool_t           def,
 {
   DBusList *link;
   dbus_bool_t allowed;
-
-  /* FIXME there's currently no handling of wildcard user/group rules.
-   */
   
   allowed = def;
 
@@ -324,23 +328,36 @@ list_allows_user (dbus_bool_t           def,
       
       if (rule->type == BUS_POLICY_RULE_USER)
         {
-          if (rule->d.user.uid != uid)
+          _dbus_verbose ("List %p user rule uid="DBUS_UID_FORMAT"\n",
+                         list, rule->d.user.uid);
+          
+          if (rule->d.user.uid == DBUS_UID_UNSET)
+            ; /* '*' wildcard */
+          else if (rule->d.user.uid != uid)
             continue;
         }
       else if (rule->type == BUS_POLICY_RULE_GROUP)
         {
-          int i;
-
-          i = 0;
-          while (i < n_group_ids)
+          _dbus_verbose ("List %p group rule uid="DBUS_UID_FORMAT"\n",
+                         list, rule->d.user.uid);
+          
+          if (rule->d.group.gid == DBUS_GID_UNSET)
+            ;  /* '*' wildcard */
+          else
             {
-              if (rule->d.group.gid == group_ids[i])
-                break;
-              ++i;
+              int i;
+              
+              i = 0;
+              while (i < n_group_ids)
+                {
+                  if (rule->d.group.gid == group_ids[i])
+                    break;
+                  ++i;
+                }
+              
+              if (i == n_group_ids)
+                continue;
             }
-
-          if (i == n_group_ids)
-            continue;
         }
       else
         continue;
@@ -360,7 +377,7 @@ bus_policy_allow_user (BusPolicy    *policy,
   int n_group_ids;
 
   /* On OOM or error we always reject the user */
-  if (!_dbus_get_groups (uid, &group_ids, &n_group_ids))
+  if (!_dbus_get_groups (uid, &group_ids, &n_group_ids, NULL))
     {
       _dbus_verbose ("Did not get any groups for UID %lu\n",
                      uid);
@@ -381,6 +398,8 @@ bus_policy_allow_user (BusPolicy    *policy,
 
   dbus_free (group_ids);
 
+  _dbus_verbose ("UID %lu allowed = %d\n", uid, allowed);
+  
   return allowed;
 }
 
@@ -536,15 +555,18 @@ remove_rules_by_type_up_to (BusClientPolicy   *policy,
 {
   DBusList *link;
 
-  link = _dbus_list_get_first (&policy->rules);
+  link = _dbus_list_get_first_link (&policy->rules);
   while (link != up_to)
     {
       BusPolicyRule *rule = link->data;
       DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
 
-      bus_policy_rule_unref (rule);
-      _dbus_list_remove_link (&policy->rules, link);
-
+      if (rule->type == type)
+        {
+          _dbus_list_remove_link (&policy->rules, link);
+          bus_policy_rule_unref (rule);
+        }
+      
       link = next;
     }
 }
@@ -571,14 +593,19 @@ bus_client_policy_optimize (BusClientPolicy *policy)
   _dbus_verbose ("Optimizing policy with %d rules\n",
                  _dbus_list_get_length (&policy->rules));
   
-  link = _dbus_list_get_first (&policy->rules);
+  link = _dbus_list_get_first_link (&policy->rules);
   while (link != NULL)
     {
-      BusPolicyRule *rule = link->data;
-      DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
+      BusPolicyRule *rule;
+      DBusList *next;
       dbus_bool_t remove_preceding;
 
+      next = _dbus_list_get_next_link (&policy->rules, link);
+      rule = link->data;
+      
       remove_preceding = FALSE;
+
+      _dbus_assert (rule != NULL);
       
       switch (rule->type)
         {
@@ -601,7 +628,7 @@ bus_client_policy_optimize (BusClientPolicy *policy)
           _dbus_assert_not_reached ("invalid rule");
           break;
         }
-                
+
       if (remove_preceding)
         remove_rules_by_type_up_to (policy, rule->type,
                                     link);
@@ -617,6 +644,9 @@ dbus_bool_t
 bus_client_policy_append_rule (BusClientPolicy *policy,
                                BusPolicyRule   *rule)
 {
+  _dbus_verbose ("Appending rule %p with type %d to policy %p\n",
+                 rule, rule->type, policy);
+  
   if (!_dbus_list_append (&policy->rules, rule))
     return FALSE;
 
@@ -639,7 +669,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
    */
 
   allowed = FALSE;
-  link = _dbus_list_get_first (&policy->rules);
+  link = _dbus_list_get_first_link (&policy->rules);
   while (link != NULL)
     {
       BusPolicyRule *rule = link->data;
@@ -711,7 +741,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
    */
 
   allowed = FALSE;
-  link = _dbus_list_get_first (&policy->rules);
+  link = _dbus_list_get_first_link (&policy->rules);
   while (link != NULL)
     {
       BusPolicyRule *rule = link->data;
@@ -783,7 +813,7 @@ bus_client_policy_check_can_own (BusClientPolicy  *policy,
    */
 
   allowed = FALSE;
-  link = _dbus_list_get_first (&policy->rules);
+  link = _dbus_list_get_first_link (&policy->rules);
   while (link != NULL)
     {
       BusPolicyRule *rule = link->data;
index 986cfe0..53e30e7 100644 (file)
@@ -74,13 +74,13 @@ struct BusPolicyRule
 
     struct
     {
-      char *user;
+      /* can be DBUS_UID_UNSET meaning "any" */
       dbus_uid_t uid;
     } user;
 
     struct
     {
-      char *group;
+      /* can be DBUS_GID_UNSET meaning "any" */
       dbus_gid_t gid;
     } group;
     
index d430d99..4feca23 100644 (file)
@@ -15,6 +15,7 @@
     <allow send="*"/>
     <allow receive="*"/>
     <allow own="*"/>
+    <allow user="*"/>  
   </policy>
 
   <!-- This is included last so local configuration can override what's 
index 0e57057..e65c4af 100644 (file)
@@ -34,6 +34,8 @@
     <deny send="*"/>
     <deny receive="*"/>
     <deny own="*"/>
+    <!-- But allow all users to connect -->
+    <allow user="*"/>
   </policy>
 
   <!-- This is included last so local configuration can override what's 
index 9595f48..94fe075 100644 (file)
@@ -2082,8 +2082,8 @@ dbus_connection_dispatch (DBusConnection *connection)
         }
     }
 
-  _dbus_verbose ("  done dispatching %p (%s)\n", message,
-                 dbus_message_get_name (message));
+  _dbus_verbose ("  done dispatching %p (%s) on connection %p\n", message,
+                 dbus_message_get_name (message), connection);
   
  out:
   _dbus_connection_release_dispatch (connection);
index bf01108..3c810f2 100644 (file)
@@ -47,6 +47,7 @@ typedef enum
 
 typedef struct
 {
+  int refcount;
   CallbackType type;
   void *data;
   DBusFreeFunction free_data_func;
@@ -74,10 +75,10 @@ typedef struct
 #define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback)
 
 static WatchCallback*
-watch_callback_new (DBusWatch        *watch,
+watch_callback_new (DBusWatch         *watch,
                     DBusWatchFunction  function,
-                    void             *data,
-                    DBusFreeFunction  free_data_func)
+                    void              *data,
+                    DBusFreeFunction   free_data_func)
 {
   WatchCallback *cb;
 
@@ -88,18 +89,19 @@ watch_callback_new (DBusWatch        *watch,
   cb->watch = watch;
   cb->function = function;
   cb->last_iteration_oom = FALSE;
+  cb->callback.refcount = 1;
   cb->callback.type = CALLBACK_WATCH;
   cb->callback.data = data;
   cb->callback.free_data_func = free_data_func;
-
+  
   return cb;
 }
 
 static TimeoutCallback*
-timeout_callback_new (DBusTimeout        *timeout,
+timeout_callback_new (DBusTimeout         *timeout,
                       DBusTimeoutFunction  function,
-                      void               *data,
-                      DBusFreeFunction    free_data_func)
+                      void                *data,
+                      DBusFreeFunction     free_data_func)
 {
   TimeoutCallback *cb;
 
@@ -111,6 +113,7 @@ timeout_callback_new (DBusTimeout        *timeout,
   cb->function = function;
   _dbus_get_current_time (&cb->last_tv_sec,
                           &cb->last_tv_usec);
+  cb->callback.refcount = 1;    
   cb->callback.type = CALLBACK_TIMEOUT;
   cb->callback.data = data;
   cb->callback.free_data_func = free_data_func;
@@ -119,12 +122,27 @@ timeout_callback_new (DBusTimeout        *timeout,
 }
 
 static void
-callback_free (Callback *cb)
+callback_ref (Callback *cb)
+{
+  _dbus_assert (cb->refcount > 0);
+  
+  cb->refcount += 1;
+}
+
+static void
+callback_unref (Callback *cb)
 {
-  if (cb->free_data_func)
-    (* cb->free_data_func) (cb->data);
+  _dbus_assert (cb->refcount > 0);
+
+  cb->refcount -= 1;
 
-  dbus_free (cb);
+  if (cb->refcount == 0)
+    {
+      if (cb->free_data_func)
+        (* cb->free_data_func) (cb->data);
+      
+      dbus_free (cb);
+    }
 }
 
 static dbus_bool_t
@@ -165,7 +183,7 @@ remove_callback (DBusLoop  *loop,
       break;
     }
   
-  callback_free (cb);
+  callback_unref (cb);
   _dbus_list_remove_link (&loop->callbacks, link);
   loop->callback_list_serial += 1;
 }
@@ -229,7 +247,7 @@ _dbus_loop_add_watch (DBusLoop          *loop,
   if (!add_callback (loop, (Callback*) wcb))
     {
       wcb->callback.free_data_func = NULL; /* don't want to have this side effect */
-      callback_free ((Callback*) wcb);
+      callback_unref ((Callback*) wcb);
       return FALSE;
     }
   
@@ -283,7 +301,7 @@ _dbus_loop_add_timeout (DBusLoop            *loop,
   if (!add_callback (loop, (Callback*) tcb))
     {
       tcb->callback.free_data_func = NULL; /* don't want to have this side effect */
-      callback_free ((Callback*) tcb);
+      callback_unref ((Callback*) tcb);
       return FALSE;
     }
   
@@ -490,6 +508,7 @@ _dbus_loop_iterate (DBusLoop     *loop,
       
   fds = NULL;
   watches_for_fds = NULL;
+  n_fds = 0;
   oom_watch_pending = FALSE;
   orig_depth = loop->depth;
   
@@ -578,6 +597,8 @@ _dbus_loop_iterate (DBusLoop     *loop,
               else if (dbus_watch_get_enabled (wcb->watch))
                 {
                   watches_for_fds[i] = wcb;
+
+                  callback_ref (cb);
                   
                   flags = dbus_watch_get_flags (wcb->watch);
                   
@@ -726,7 +747,7 @@ _dbus_loop_iterate (DBusLoop     *loop,
               unsigned int condition;
                   
               wcb = watches_for_fds[i];
-                  
+              
               condition = 0;
               if (fds[i].revents & _DBUS_POLLIN)
                 condition |= DBUS_WATCH_READABLE;
@@ -765,8 +786,18 @@ _dbus_loop_iterate (DBusLoop     *loop,
  next_iteration:
   if (fds && fds != static_fds)
     dbus_free (fds);
-  if (watches_for_fds && watches_for_fds != static_watches_for_fds)
-    dbus_free (watches_for_fds);
+  if (watches_for_fds)
+    {
+      i = 0;
+      while (i < n_fds)
+        {
+          callback_unref (&watches_for_fds[i]->callback);
+          ++i;
+        }
+      
+      if (watches_for_fds != static_watches_for_fds)
+        dbus_free (watches_for_fds);
+    }
   
   if (_dbus_loop_dispatch (loop))
     retval = TRUE;
index 0044913..5e6a2c6 100644 (file)
@@ -585,7 +585,7 @@ _dbus_message_set_serial (DBusMessage  *message,
  */
 dbus_bool_t
 dbus_message_set_reply_serial (DBusMessage  *message,
-                                dbus_int32_t  reply_serial)
+                               dbus_int32_t  reply_serial)
 {
   _dbus_assert (!message->locked);
 
index f706d08..0877a29 100644 (file)
@@ -1315,7 +1315,8 @@ static dbus_bool_t
 store_user_info (struct passwd    *p,
                  DBusCredentials  *credentials,
                  DBusString       *homedir,
-                 DBusString       *username_out)
+                 DBusString       *username_out,
+                 DBusError        *error)
 {
   int old_homedir_len;
   
@@ -1332,7 +1333,7 @@ store_user_info (struct passwd    *p,
       
       if (!_dbus_string_append (homedir, p->pw_dir))
         {
-          _dbus_verbose ("No memory to get homedir\n");
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
           return FALSE;
         }
     }
@@ -1342,7 +1343,7 @@ store_user_info (struct passwd    *p,
     {
       if (homedir)
         _dbus_string_set_length (homedir, old_homedir_len);
-      _dbus_verbose ("No memory to get username\n");
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
       return FALSE;
     }
       
@@ -1363,6 +1364,7 @@ store_user_info (struct passwd    *p,
  * @param credentials to fill in or #NULL
  * @param homedir string to append homedir to or #NULL
  * @param username_out string to append username to or #NULL
+ * @param error return location for reason for failure
  *
  * @returns #TRUE on success
  */
@@ -1371,7 +1373,8 @@ get_user_info (const DBusString *username,
                dbus_uid_t        uid,
                DBusCredentials  *credentials,
                DBusString       *homedir,
-               DBusString       *username_out)
+               DBusString       *username_out,
+               DBusError        *error)
 {
   const char *username_c_str;
       
@@ -1417,10 +1420,13 @@ get_user_info (const DBusString *username,
     if (result == 0 && p == &p_str)
       {
         return store_user_info (p, credentials, homedir,
-                                username_out);
+                                username_out, error);
       }
     else
       {
+        dbus_set_error (error, DBUS_ERROR_FAILED,
+                        "User \"%s\" unknown or no memory to allocate password entry\n",
+                        username_c_str);
         _dbus_verbose ("User %s unknown\n", username_c_str);
         return FALSE;
       }
@@ -1438,10 +1444,13 @@ get_user_info (const DBusString *username,
     if (p != NULL)
       {
         return store_user_info (p, credentials, homedir,
-                                username_out);
+                                username_out, error);
       }
     else
       {
+        dbus_set_error (error, DBUS_ERROR_FAILED,
+                        "User \"%s\" unknown or no memory to allocate password entry\n",
+                        username_c_str);
         _dbus_verbose ("User %s unknown\n", username_c_str);
         return FALSE;
       }
@@ -1474,7 +1483,7 @@ dbus_bool_t
 _dbus_credentials_from_username (const DBusString *username,
                                  DBusCredentials  *credentials)
 {
-  return get_user_info (username, -1, credentials, NULL, NULL);
+  return get_user_info (username, -1, credentials, NULL, NULL, NULL);
 }
 
 /**
@@ -1512,7 +1521,7 @@ dbus_bool_t
 _dbus_credentials_from_user_id (unsigned long     user_id,
                                 DBusCredentials  *credentials)
 {
-  return get_user_info (NULL, user_id, credentials, NULL, NULL);
+  return get_user_info (NULL, user_id, credentials, NULL, NULL, NULL);
 }
 
 _DBUS_DEFINE_GLOBAL_LOCK (user_info);
@@ -1570,7 +1579,7 @@ _dbus_user_info_from_current_process (const DBusString      **username,
       _dbus_credentials_clear (&u.creds);
 
       if (!get_user_info (NULL, getuid (),
-                          &u.creds, &u.dir, &u.name))
+                          &u.creds, &u.dir, &u.name, NULL))
         goto fail_init;
       
       if (!_dbus_register_shutdown_func (shutdown_user_info,
@@ -1611,7 +1620,7 @@ dbus_bool_t
 _dbus_homedir_from_username (const DBusString *username,
                              DBusString       *homedir)
 {
-  return get_user_info (username, -1, NULL, homedir, NULL);
+  return get_user_info (username, -1, NULL, homedir, NULL, NULL);
 }
 
 /**
@@ -1773,21 +1782,20 @@ _dbus_get_group_id (const DBusString *group_name,
 /**
  * Gets all groups for a particular user. Returns #FALSE
  * if no memory, or user isn't known, but always initializes
- * group_ids to a NULL array.
- *
- * @todo failing to distinguish "out of memory" from
- * "unknown user" is kind of bogus and would probably
- * result in a failure in a comprehensive test suite.
+ * group_ids to a NULL array. Sets error to the reason
+ * for returning #FALSE.
  *
  * @param uid the user ID
  * @param group_ids return location for array of group IDs
  * @param n_group_ids return location for length of returned array
+ * @param error return location for error
  * @returns #TRUE on success
  */
 dbus_bool_t
 _dbus_get_groups (unsigned long   uid,
                   unsigned long **group_ids,
-                  int            *n_group_ids)
+                  int            *n_group_ids,
+                  DBusError      *error)
 {
   DBusCredentials creds;
   DBusString username;
@@ -1800,10 +1808,13 @@ _dbus_get_groups (unsigned long   uid,
   retval = FALSE;
 
   if (!_dbus_string_init (&username))
-    return FALSE;
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
 
   if (!get_user_info (NULL, uid, &creds,
-                      NULL, &username) ||
+                      NULL, &username, error) ||
       creds.gid == DBUS_GID_UNSET)
     goto out;
 
@@ -1818,7 +1829,10 @@ _dbus_get_groups (unsigned long   uid,
     buf_count = 17;
     buf = dbus_new (gid_t, buf_count);
     if (buf == NULL)
-      goto out;
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto out;
+      }
     
     if (getgrouplist (username_c,
                       creds.gid,
@@ -1827,6 +1841,7 @@ _dbus_get_groups (unsigned long   uid,
         gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0]));
         if (new == NULL)
           {
+            dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
             dbus_free (buf);
             goto out;
           }
@@ -1839,6 +1854,7 @@ _dbus_get_groups (unsigned long   uid,
     *group_ids = dbus_new (unsigned long, buf_count);
     if (*group_ids == NULL)
       {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
         dbus_free (buf);
         goto out;
       }
@@ -1855,19 +1871,28 @@ _dbus_get_groups (unsigned long   uid,
     /* We just get the one group ID */
     *group_ids = dbus_new (unsigned long, 1);
     if (*group_ids == NULL)
-      goto out;
+      {
+        dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+        goto out;
+      }
 
     *n_group_ids = 1;
 
     (*group_ids)[0] = creds.gid;
   }
 #endif /* HAVE_GETGROUPLIST */
+  
+  retval = TRUE;
+  
+ out:
+  _dbus_string_free (&username);
 
-    retval = TRUE;
-    
-  out:
-    _dbus_string_free (&username);
-    return retval;
+  if (retval)
+    _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+  else
+    _DBUS_ASSERT_ERROR_IS_SET (error);
+  
+  return retval;
 }
 
 /**
index 4edfe94..27f27b5 100644 (file)
@@ -148,7 +148,8 @@ dbus_bool_t _dbus_get_group_id (const DBusString  *group_name,
                                 dbus_gid_t        *gid);
 dbus_bool_t _dbus_get_groups   (dbus_uid_t         uid,
                                 dbus_gid_t       **group_ids,
-                                int               *n_group_ids);
+                                int               *n_group_ids,
+                                DBusError         *error);
 
 unsigned long _dbus_getpid (void);
 
index 052c15f..1c5b420 100644 (file)
@@ -100,6 +100,7 @@ struct DBusTransport
   unsigned int send_credentials_pending : 1;  /**< #TRUE if we need to send credentials */
   unsigned int receive_credentials_pending : 1; /**< #TRUE if we need to receive credentials */
   unsigned int is_server : 1;                 /**< #TRUE if on the server side */
+  unsigned int unused_bytes_recovered : 1;    /**< #TRUE if we've recovered unused bytes from auth */
 };
 
 dbus_bool_t _dbus_transport_init_base     (DBusTransport             *transport,
index f9b3d8a..e726de2 100644 (file)
@@ -459,9 +459,21 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport)
       
       maybe_authenticated =
         (!(transport->send_credentials_pending ||
-           transport->receive_credentials_pending)) &&
-        _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_AUTHENTICATED;
+           transport->receive_credentials_pending));
 
+      if (maybe_authenticated)
+        {
+          switch (_dbus_auth_do_work (transport->auth))
+            {
+            case DBUS_AUTH_STATE_AUTHENTICATED:
+            case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES:
+              /* leave as maybe_authenticated */
+              break;
+            default:
+              maybe_authenticated = FALSE;
+            }
+        }
+      
       /* If we've authenticated as some identity, check that the auth
        * identity is the same as our own identity.  In the future, we
        * may have API allowing applications to specify how this is
@@ -768,18 +780,18 @@ _dbus_transport_get_dispatch_status (DBusTransport *transport)
 
   if (!_dbus_transport_get_is_authenticated (transport))
     {
-      switch (_dbus_auth_do_work (transport->auth))
-        {
-        case DBUS_AUTH_STATE_WAITING_FOR_MEMORY:
-          return DBUS_DISPATCH_NEED_MEMORY;
-        case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES:
-          if (!recover_unused_bytes (transport))
-            return DBUS_DISPATCH_NEED_MEMORY;
-          break;
-        default:
-          break;
-        }
+      if (_dbus_auth_do_work (transport->auth) ==
+          DBUS_AUTH_STATE_WAITING_FOR_MEMORY)
+        return DBUS_DISPATCH_NEED_MEMORY;
+      else
+        return DBUS_DISPATCH_COMPLETE;
     }
+
+  if (!transport->unused_bytes_recovered &&
+      !recover_unused_bytes (transport))
+    return DBUS_DISPATCH_NEED_MEMORY;
+
+  transport->unused_bytes_recovered = TRUE;
   
   if (!_dbus_message_loader_queue_messages (transport->loader))
     return DBUS_DISPATCH_NEED_MEMORY;
index e1d2152..2f1e787 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
@@ -82,3 +82,7 @@
    after the message bus has processed your message but before the service has replied, 
    it would be nice if the message bus sent you an error reply.
 
+ - We have a limit on the number of messages a connection can send, but 
+   not on how many can be buffered for a given connection.
+
+ - make client serial and reply serial unsigned and add dbus_message_get_is_reply()
index c430898..0dd8ed4 100644 (file)
@@ -10,5 +10,6 @@
     <allow send="*"/>
     <allow receive="*"/>
     <allow own="*"/>
+    <allow user="*"/>
   </policy>
 </busconfig>