2003-04-19 Havoc Pennington <hp@pobox.com>
authorHavoc Pennington <hp@redhat.com>
Sat, 19 Apr 2003 16:16:24 +0000 (16:16 +0000)
committerHavoc Pennington <hp@redhat.com>
Sat, 19 Apr 2003 16:16:24 +0000 (16:16 +0000)
* bus/driver.c (bus_driver_handle_hello): check limits and
return an error if they are exceeded.

* bus/connection.c: maintain separate lists of active and inactive
connections, and a count of each. Maintain count of completed
connections per user. Implement code to check connection limits.

* dbus/dbus-list.c (_dbus_list_unlink): export

* bus/bus.c (bus_context_check_security_policy): enforce a maximum
number of bytes in the message queue for a connection

12 files changed:
ChangeLog
bus/bus.c
bus/bus.h
bus/connection.c
bus/connection.h
bus/dispatch.c
bus/driver.c
dbus/dbus-connection.h
dbus/dbus-list.c
dbus/dbus-list.h
dbus/dbus-sysdeps.c
doc/TODO

index 779138a..d9a2f6c 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,17 @@
+2003-04-19  Havoc Pennington  <hp@pobox.com>
+
+       * bus/driver.c (bus_driver_handle_hello): check limits and 
+       return an error if they are exceeded.
+
+       * bus/connection.c: maintain separate lists of active and inactive
+       connections, and a count of each. Maintain count of completed
+       connections per user. Implement code to check connection limits.
+
+       * dbus/dbus-list.c (_dbus_list_unlink): export
+
+       * bus/bus.c (bus_context_check_security_policy): enforce a maximum
+       number of bytes in the message queue for a connection
+
 2003-04-18  Havoc Pennington  <hp@pobox.com>
 
        * dbus/dbus-auth.c (record_mechanisms): memleak fixes
index 2b0f509..414f15e 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -45,8 +45,11 @@ struct BusContext
   BusRegistry *registry;
   BusPolicy *policy;
   DBusUserDatabase *user_database;
-  int activation_timeout;        /**< How long to wait for an activation to time out */
-  int auth_timeout;              /**< How long to wait for an authentication to time out */
+  long max_incoming_bytes;          /**< How many incoming messages for a connection */
+  long max_outgoing_bytes;          /**< How many outgoing bytes can be queued for a connection */
+  long max_message_size;            /**< Max size of a single message in bytes */
+  int activation_timeout;           /**< How long to wait for an activation to time out */
+  int auth_timeout;                 /**< How long to wait for an authentication to time out */
   int max_completed_connections;    /**< Max number of authorized connections */
   int max_incomplete_connections;   /**< Max number of incomplete connections */
   int max_connections_per_user;     /**< Max number of connections auth'd as same user */
@@ -210,6 +213,12 @@ new_connection_callback (DBusServer     *server,
        */
       dbus_connection_disconnect (new_connection);
     }
+
+  dbus_connection_set_max_received_size (new_connection,
+                                         context->max_incoming_bytes);
+
+  dbus_connection_set_max_message_size (new_connection,
+                                        context->max_message_size);
   
   /* on OOM, we won't have ref'd the connection so it will die. */
 }
@@ -353,6 +362,11 @@ bus_context_new (const DBusString *config_file,
    */
   if (!server_data_slot_ref ())
     _dbus_assert_not_reached ("second ref of server data slot failed");
+
+  /* Make up some numbers! woot! */
+  context->max_incoming_bytes = _DBUS_ONE_MEGABYTE * 63;  
+  context->max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 63;
+  context->max_message_size = _DBUS_ONE_MEGABYTE * 32;
   
 #ifdef DBUS_BUILD_TESTS
   context->activation_timeout = 6000;  /* 6 seconds */
@@ -375,7 +389,7 @@ bus_context_new (const DBusString *config_file,
    * DOS all the other users.
    */
   context->max_completed_connections = 1024;
-
+  
   context->user_database = _dbus_user_database_new ();
   if (context->user_database == NULL)
     {
@@ -818,6 +832,30 @@ bus_context_get_activation_timeout (BusContext *context)
   return context->activation_timeout;
 }
 
+int
+bus_context_get_auth_timeout (BusContext *context)
+{
+  return context->auth_timeout;
+}
+
+int
+bus_context_get_max_completed_connections (BusContext *context)
+{
+  return context->max_completed_connections;
+}
+
+int
+bus_context_get_max_incomplete_connections (BusContext *context)
+{
+  return context->max_incomplete_connections;
+}
+
+int
+bus_context_get_max_connections_per_user (BusContext *context)
+{
+  return context->max_connections_per_user;
+}
+
 dbus_bool_t
 bus_context_check_security_policy (BusContext     *context,
                                    DBusConnection *sender,
@@ -878,5 +916,17 @@ bus_context_check_security_policy (BusContext     *context,
       return FALSE;
     }
 
+  /* See if limits on size have been exceeded */
+  if (recipient &&
+      dbus_connection_get_outgoing_size (recipient) >
+      context->max_outgoing_bytes)
+    {
+      const char *dest = dbus_message_get_service (message);
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "The destination service \"%s\" has a full message queue",
+                      dest ? dest : DBUS_SERVICE_DBUS);
+      return FALSE;
+    }
+  
   return TRUE;
 }
index 7369d22..e4e6dab 100644 (file)
--- a/bus/bus.h
+++ b/bus/bus.h
@@ -41,29 +41,34 @@ typedef struct BusRegistry      BusRegistry;
 typedef struct BusService       BusService;
 typedef struct BusTransaction   BusTransaction;
 
-BusContext*       bus_context_new                    (const DBusString *config_file,
-                                                      int               print_addr_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);
-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);
+BusContext*       bus_context_new                            (const DBusString *config_file,
+                                                              int               print_addr_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);
+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);
+dbus_bool_t       bus_context_check_security_policy          (BusContext       *context,
+                                                              DBusConnection   *sender,
+                                                              DBusConnection   *recipient,
+                                                              DBusMessage      *message,
+                                                              DBusError        *error);
+
 
 
 #endif /* BUS_BUS_H */
index 71ab010..14081e2 100644 (file)
 #include "services.h"
 #include "utils.h"
 #include <dbus/dbus-list.h>
+#include <dbus/dbus-hash.h>
 
 static void bus_connection_remove_transactions (DBusConnection *connection);
 
 struct BusConnections
 {
   int refcount;
-  DBusList *list; /**< List of all the connections */
+  DBusList *completed;  /**< List of all completed connections */
+  int n_completed;      /**< Length of completed list */
+  DBusList *incomplete; /**< List of all not-yet-active connections */
+  int n_incomplete;     /**< Length of incomplete list */
   BusContext *context;
+  DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */
 };
 
 static int connection_data_slot = -1;
@@ -42,6 +47,7 @@ static int connection_data_slot_refcount = 0;
 typedef struct
 {
   BusConnections *connections;
+  DBusList *link_in_connection_list;
   DBusConnection *connection;
   DBusList *services_owned;
   char *name;
@@ -96,6 +102,65 @@ connection_get_loop (DBusConnection *connection)
   return bus_context_get_loop (d->connections->context);
 }
 
+
+static int
+get_connections_for_uid (BusConnections *connections,
+                         dbus_uid_t      uid)
+{
+  void *val;
+  int current_count;
+
+  /* val is NULL is 0 when it isn't in the hash yet */
+  
+  val = _dbus_hash_table_lookup_ulong (connections->completed_by_user,
+                                       uid);
+
+  current_count = _DBUS_POINTER_TO_INT (val);
+
+  return current_count;
+}
+
+static dbus_bool_t
+adjust_connections_for_uid (BusConnections *connections,
+                            dbus_uid_t      uid,
+                            int             adjustment)
+{
+  int current_count;
+
+  current_count = get_connections_for_uid (connections, uid);
+
+  _dbus_verbose ("Adjusting connection count for UID " DBUS_UID_FORMAT
+                 ": was %d adjustment %d making %d\n",
+                 uid, current_count, adjustment, current_count + adjustment);
+  
+  _dbus_assert (current_count >= 0);
+  
+  current_count += adjustment;
+
+  _dbus_assert (current_count >= 0);
+
+  if (current_count == 0)
+    {
+      _dbus_hash_table_remove_ulong (connections->completed_by_user, uid);
+      return TRUE;
+    }
+  else
+    {
+      dbus_bool_t retval;
+      
+      retval = _dbus_hash_table_insert_ulong (connections->completed_by_user,
+                                              uid, _DBUS_INT_TO_POINTER (current_count));
+
+      /* only positive adjustment can fail as otherwise
+       * a hash entry should already exist
+       */
+      _dbus_assert (adjustment > 0 ||
+                    (adjustment <= 0 && retval));
+
+      return retval;
+    }
+}
+
 void
 bus_connection_disconnected (DBusConnection *connection)
 {
@@ -180,8 +245,34 @@ bus_connection_disconnected (DBusConnection *connection)
   
   bus_connection_remove_transactions (connection);
 
-  _dbus_list_remove (&d->connections->list, connection);
+  if (d->link_in_connection_list != NULL)
+    {
+      if (d->name != NULL)
+        {
+          unsigned long uid;
+          
+          _dbus_list_remove_link (&d->connections->completed, d->link_in_connection_list);
+          d->link_in_connection_list = NULL;
+          d->connections->n_completed -= 1;
 
+          if (dbus_connection_get_unix_user (connection, &uid))
+            {
+              if (!adjust_connections_for_uid (d->connections,
+                                               uid, -1))
+                _dbus_assert_not_reached ("adjusting downward should never fail");
+            }
+        }
+      else
+        {
+          _dbus_list_remove_link (&d->connections->incomplete, d->link_in_connection_list);
+          d->link_in_connection_list = NULL;
+          d->connections->n_incomplete -= 1;
+        }
+      
+      _dbus_assert (d->connections->n_incomplete >= 0);
+      _dbus_assert (d->connections->n_completed >= 0);
+    }
+  
   /* frees "d" as side effect */
   dbus_connection_set_data (connection,
                             connection_data_slot,
@@ -323,6 +414,15 @@ bus_connections_new (BusContext *context)
       connection_data_slot_unref ();
       return NULL;
     }
+
+  connections->completed_by_user = _dbus_hash_table_new (DBUS_HASH_ULONG,
+                                                         NULL, NULL);
+  if (connections->completed_by_user == NULL)
+    {
+      dbus_free (connections);
+      connection_data_slot_unref ();
+      return NULL;
+    }
   
   connections->refcount = 1;
   connections->context = context;
@@ -344,19 +444,37 @@ bus_connections_unref (BusConnections *connections)
   connections->refcount -= 1;
   if (connections->refcount == 0)
     {
-      while (connections->list != NULL)
+      /* drop all incomplete */
+      while (connections->incomplete != NULL)
         {
           DBusConnection *connection;
 
-          connection = connections->list->data;
+          connection = connections->incomplete->data;
 
           dbus_connection_ref (connection);
           dbus_connection_disconnect (connection);
           bus_connection_disconnected (connection);
           dbus_connection_unref (connection);
         }
+
+      _dbus_assert (connections->n_incomplete == 0);
       
-      _dbus_list_clear (&connections->list);
+      /* drop all real connections */
+      while (connections->completed != NULL)
+        {
+          DBusConnection *connection;
+
+          connection = connections->completed->data;
+
+          dbus_connection_ref (connection);
+          dbus_connection_disconnect (connection);
+          bus_connection_disconnected (connection);
+          dbus_connection_unref (connection);          
+        }
+
+      _dbus_assert (connections->n_completed == 0);
+
+      _dbus_hash_table_unref (connections->completed_by_user);
       
       dbus_free (connections);
 
@@ -405,8 +523,7 @@ bus_connections_setup_connection (BusConnections *connections,
                                               NULL,
                                               connection, NULL))
     goto out;
-
-
+  
   dbus_connection_set_unix_user_function (connection,
                                           allow_user_function,
                                           NULL, NULL);
@@ -415,16 +532,14 @@ bus_connections_setup_connection (BusConnections *connections,
                                                 dispatch_status_function,
                                                 bus_context_get_loop (connections->context),
                                                 NULL);
+
+  d->link_in_connection_list = _dbus_list_alloc_link (connection);
+  if (d->link_in_connection_list == NULL)
+    goto out;
   
   /* Setup the connection with the dispatcher */
   if (!bus_dispatch_add_connection (connection))
     goto out;
-  
-  if (!_dbus_list_append (&connections->list, connection))
-    {
-      bus_dispatch_remove_connection (connection);
-      goto out;
-    }
 
   if (dbus_connection_get_dispatch_status (connection) != DBUS_DISPATCH_COMPLETE)
     {
@@ -434,13 +549,36 @@ bus_connections_setup_connection (BusConnections *connections,
           goto out;
         }
     }
+
+  _dbus_list_append_link (&connections->incomplete, d->link_in_connection_list);
+  connections->n_incomplete += 1;
   
   dbus_connection_ref (connection);
+
+  /* Note that we might disconnect ourselves here, but it only takes
+   * effect on return to the main loop.
+   */
+  if (connections->n_incomplete >
+      bus_context_get_max_incomplete_connections (connections->context))
+    {
+      _dbus_verbose ("Number of incomplete connections exceeds max, dropping oldest one\n");
+      
+      _dbus_assert (connections->incomplete != NULL);
+      /* Disconnect the oldest unauthenticated connection.  FIXME
+       * would it be more secure to drop a *random* connection?  This
+       * algorithm seems to mean that if someone can create new
+       * connections quickly enough, they can keep anyone else from
+       * completing authentication. But random may or may not really
+       * help with that, a more elaborate solution might be required.
+       */
+      dbus_connection_disconnect (connections->incomplete->data);
+    }
+  
   retval = TRUE;
 
  out:
   if (!retval)
-    {        
+    {      
       if (!dbus_connection_set_watch_functions (connection,
                                                 NULL, NULL, NULL,
                                                 connection,
@@ -463,6 +601,13 @@ bus_connections_setup_connection (BusConnections *connections,
                                      connection_data_slot,
                                      NULL, NULL))
         _dbus_assert_not_reached ("failed to set connection data to null");
+
+      if (d->link_in_connection_list != NULL)
+        {
+          _dbus_assert (d->link_in_connection_list->next == NULL);
+          _dbus_assert (d->link_in_connection_list->prev == NULL);
+          _dbus_list_free_link (d->link_in_connection_list);
+        }
     }
   
   return retval;
@@ -567,6 +712,67 @@ bus_connection_get_policy (DBusConnection *connection)
   return d->policy;
 }
 
+static dbus_bool_t
+foreach_active (BusConnections               *connections,
+                BusConnectionForeachFunction  function,
+                void                         *data)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (&connections->completed);
+  while (link != NULL)
+    {
+      DBusConnection *connection = link->data;
+      DBusList *next = _dbus_list_get_next_link (&connections->completed, link);
+
+      if (!(* function) (connection, data))
+        return FALSE;
+      
+      link = next;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
+foreach_inactive (BusConnections               *connections,
+                  BusConnectionForeachFunction  function,
+                  void                         *data)
+{
+  DBusList *link;
+  
+  link = _dbus_list_get_first_link (&connections->incomplete);
+  while (link != NULL)
+    {
+      DBusConnection *connection = link->data;
+      DBusList *next = _dbus_list_get_next_link (&connections->incomplete, link);
+
+      if (!(* function) (connection, data))
+        return FALSE;
+      
+      link = next;
+    }
+
+  return TRUE;
+}
+
+/**
+ * Calls function on each active connection; if the function returns
+ * #FALSE, stops iterating. Active connections are authenticated
+ * and have sent a Hello message.
+ *
+ * @param connections the connections object
+ * @param function the function
+ * @param data data to pass to it as a second arg
+ */
+void
+bus_connections_foreach_active (BusConnections               *connections,
+                                BusConnectionForeachFunction  function,
+                                void                         *data)
+{
+  foreach_active (connections, function, data);
+}
+
 /**
  * Calls function on each connection; if the function returns
  * #FALSE, stops iterating.
@@ -578,21 +784,12 @@ bus_connection_get_policy (DBusConnection *connection)
 void
 bus_connections_foreach (BusConnections               *connections,
                          BusConnectionForeachFunction  function,
-                       void                          *data)
+                         void                         *data)
 {
-  DBusList *link;
-  
-  link = _dbus_list_get_first_link (&connections->list);
-  while (link != NULL)
-    {
-      DBusConnection *connection = link->data;
-      DBusList *next = _dbus_list_get_next_link (&connections->list, link);
+  if (!foreach_active (connections, function, data))
+    return;
 
-      if (!(* function) (connection, data))
-        break;
-      
-      link = next;
-    }
+  foreach_inactive (connections, function, data);
 }
 
 BusContext*
@@ -789,17 +986,40 @@ bus_connection_set_name (DBusConnection   *connection,
                         const DBusString *name)
 {
   BusConnectionData *d;
+  unsigned long uid;
   
   d = BUS_CONNECTION_DATA (connection);
   _dbus_assert (d != NULL);
   _dbus_assert (d->name == NULL);
-
+  
   if (!_dbus_string_copy_data (name, &d->name))
     return FALSE;
 
   _dbus_assert (d->name != NULL);
   
   _dbus_verbose ("Name %s assigned to %p\n", d->name, connection);
+
+  if (dbus_connection_get_unix_user (connection, &uid))
+    {
+      if (!adjust_connections_for_uid (d->connections,
+                                       uid, 1))
+        {
+          dbus_free (d->name);
+          d->name = NULL;
+          return FALSE;
+        }
+    }
+  
+  /* Now the connection is active, move it between lists */
+  _dbus_list_unlink (&d->connections->incomplete,
+                     d->link_in_connection_list);
+  d->connections->n_incomplete -= 1;
+  _dbus_list_append_link (&d->connections->completed,
+                          d->link_in_connection_list);
+  d->connections->n_completed += 1;
+
+  _dbus_assert (d->connections->n_incomplete >= 0);
+  _dbus_assert (d->connections->n_completed > 0);
   
   return TRUE;
 }
@@ -815,6 +1035,47 @@ bus_connection_get_name (DBusConnection *connection)
   return d->name;
 }
 
+/**
+ * Check whether completing the passed-in connection would
+ * exceed limits, and if so set error and return #FALSE
+ */
+dbus_bool_t
+bus_connections_check_limits (BusConnections  *connections,
+                              DBusConnection  *requesting_completion,
+                              DBusError       *error)
+{
+  BusConnectionData *d;
+  unsigned long uid;
+  
+  d = BUS_CONNECTION_DATA (requesting_completion);
+  _dbus_assert (d != NULL);
+
+  _dbus_assert (d->name == NULL);
+
+  if (connections->n_completed >=
+      bus_context_get_max_completed_connections (connections->context))
+    {
+      dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                      "The maximum number of active connections has been reached");
+      return FALSE;
+    }
+  
+  if (dbus_connection_get_unix_user (requesting_completion, &uid))
+    {
+      if (get_connections_for_uid (connections, uid) >=
+          bus_context_get_max_connections_per_user (connections->context))
+        {
+          dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
+                          "The maximum number of active connections for UID %lu has been reached",
+                          uid);
+          return FALSE;
+        }
+    }
+  
+  return TRUE;
+}
+
+
 /*
  * Transactions
  *
index c429007..0d4d3a1 100644 (file)
@@ -40,12 +40,18 @@ dbus_bool_t     bus_connections_setup_connection (BusConnections               *
 void            bus_connections_foreach          (BusConnections               *connections,
                                                   BusConnectionForeachFunction  function,
                                                   void                         *data);
+void            bus_connections_foreach_active   (BusConnections               *connections,
+                                                  BusConnectionForeachFunction  function,
+                                                  void                         *data);
 BusContext*     bus_connections_get_context      (BusConnections               *connections);
-
-BusContext*     bus_connection_get_context       (DBusConnection               *connection); 
+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);
+dbus_bool_t     bus_connections_check_limits     (BusConnections               *connections,
+                                                  DBusConnection               *requesting_completion,
+                                                  DBusError                    *error);
+
 
 dbus_bool_t bus_connection_is_active (DBusConnection *connection);
 
index d1c19fd..c1e67d6 100644 (file)
@@ -48,9 +48,6 @@ static dbus_bool_t
 send_one_message (DBusConnection *connection, void *data)
 {
   SendMessageData *d = data;
-  
-  if (!bus_connection_is_active (connection))
-    return TRUE;
 
   if (!bus_context_check_security_policy (d->context,
                                           d->sender,
@@ -93,7 +90,7 @@ bus_dispatch_broadcast_message (BusTransaction *transaction,
   d.transaction = transaction;
   d.error = &tmp_error;
   
-  bus_connections_foreach (connections, send_one_message, &d);
+  bus_connections_foreach_active (connections, send_one_message, &d);
 
   if (dbus_error_is_set (&tmp_error))
     {
index c52020b..bc58f55 100644 (file)
@@ -262,8 +262,23 @@ bus_driver_handle_hello (DBusConnection *connection,
   BusService *service;
   dbus_bool_t retval;
   BusRegistry *registry;
+  BusConnections *connections;
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
+
+  /* Note that when these limits are exceeded we don't disconnect the
+   * connection; we just sort of leave it hanging there until it times
+   * out or disconnects itself or is dropped due to the max number of
+   * incomplete connections. It's even OK if the connection wants to
+   * retry the hello message, we support that.
+   */
+  connections = bus_connection_get_connections (connection);
+  if (!bus_connections_check_limits (connections, connection,
+                                     error))
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (error);
+      return FALSE;
+    }
   
   if (!_dbus_string_init (&unique_name))
     {
index 6e8a9f1..c2206cd 100644 (file)
@@ -183,11 +183,11 @@ void*       dbus_connection_get_data           (DBusConnection   *connection,
 
 void        dbus_connection_set_change_sigpipe (dbus_bool_t       will_modify_sigpipe); 
 
-void dbus_connection_set_max_message_size       (DBusConnection *connection,
-                                                 long            size);
-long dbus_connection_get_max_message_size       (DBusConnection *connection);
+void dbus_connection_set_max_message_size  (DBusConnection *connection,
+                                            long            size);
+long dbus_connection_get_max_message_size  (DBusConnection *connection);
 void dbus_connection_set_max_received_size (DBusConnection *connection,
-                                                 long            size);
+                                            long            size);
 long dbus_connection_get_max_received_size (DBusConnection *connection);
 long dbus_connection_get_outgoing_size     (DBusConnection *connection);
 
index 5f4c67c..235ed27 100644 (file)
@@ -470,7 +470,15 @@ _dbus_list_remove_last (DBusList **list,
   return FALSE;
 }
 
-static void
+/**
+ * Removes the given link from the list, but doesn't
+ * free it. _dbus_list_remove_link() both removes the
+ * link and also frees it.
+ *
+ * @param list the list
+ * @param link the link in the list
+ */
+void
 _dbus_list_unlink (DBusList **list,
                    DBusList  *link)
 {
@@ -487,6 +495,9 @@ _dbus_list_unlink (DBusList **list,
       if (*list == link)
         *list = link->next;
     }
+
+  link->next = NULL;
+  link->prev = NULL;
 }
 
 /**
index ad74dfd..f3b37ef 100644 (file)
@@ -74,6 +74,8 @@ dbus_bool_t _dbus_list_copy               (DBusList **list,
 int         _dbus_list_get_length         (DBusList **list);
 DBusList*   _dbus_list_alloc_link         (void      *data);
 void        _dbus_list_free_link          (DBusList  *link);
+void        _dbus_list_unlink             (DBusList **list,
+                                           DBusList  *link);
 void        _dbus_list_append_link        (DBusList **list,
                                            DBusList  *link);
 void        _dbus_list_prepend_link       (DBusList **list,
index 62aa0b4..7673085 100644 (file)
@@ -470,8 +470,8 @@ _dbus_listen_unix_socket (const char     *path,
    * But there doesn't seem to be a good way to do this.
    *
    * Just to be extra careful, I threw in the stat() - clearly
-   * the stat() can't *fix* any security issue, but it probably
-   * makes it harder to exploit.
+   * the stat() can't *fix* any security issue, but it at least
+   * avoids inadvertent/accidental data loss.
    */
   {
     struct stat sb;
index e6fe6bc..a02804a 100644 (file)
--- a/doc/TODO
+++ b/doc/TODO
 
  - Activation needs some careful additional thinking-through.
 
- - Recursive/composite/etc. types and associated API, see mailing list.
-
- - Configuration file (working on that now)
-
  - Property list feature on message bus (list of properties associated 
    with a connection). May also include message matching rules 
    that involve the properties of the source or destination
@@ -46,9 +42,6 @@
  - We might consider returning a "no such operation" error in dbus-connection.c 
    for unhandled messages.
 
- - Abstract the user database, so you can use something other than the system password 
-   database.
-
  - The convenience functions in dbus-bus.h should perhaps have
    the signatures that they would have if they were autogenerated
    stubs. e.g. the acquire service function. We should also evaluate 
@@ -60,9 +53,6 @@
    some basic spec'ing out of the GLib/Qt level stubs/skels stuff will be 
    needed to understand the right approach.
 
- - sync up DBusWatch and DBusTimeout so that handle_watch() is a method on DBusWatch 
-   similar to the way timeouts work
-
  - there are various bits of code to manage ref/unref of data slots, that should 
    be merged into a generic facility
 
@@ -85,7 +75,5 @@
  - 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()
-
  - other apps can send you a fake DBUS_MESSAGE_LOCAL_DISCONNECT; need to 
    check for that and disallow it.