2003-04-01 Havoc Pennington <hp@redhat.com>
authorHavoc Pennington <hp@redhat.com>
Wed, 2 Apr 2003 00:29:33 +0000 (00:29 +0000)
committerHavoc Pennington <hp@redhat.com>
Wed, 2 Apr 2003 00:29:33 +0000 (00:29 +0000)
* bus/config-parser.c, bus/bus.c: implement <servicedir> and
<includedir> (at least mostly)

* dbus/dbus-sysdeps.c (_dbus_change_identity): set the group ID
first, then the user ID

ChangeLog
bus/activation.c
bus/activation.h
bus/bus.c
bus/config-parser.c
bus/config-parser.h
dbus/dbus-keyring.c
dbus/dbus-sysdeps.c
test/data/valid-config-files/basic.conf

index 602341a..ba9cb71 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,11 @@
+2003-04-01  Havoc Pennington  <hp@redhat.com>
+
+       * bus/config-parser.c, bus/bus.c: implement <servicedir> and
+       <includedir> (at least mostly)
+
+       * dbus/dbus-sysdeps.c (_dbus_change_identity): set the group ID
+       first, then the user ID
+
 2003-04-01  Havoc Pennington  <hp@pobox.com>
 
        * dbus/dbus-server.c (dbus_server_set_auth_mechanisms): new
index fe069c7..7f3693a 100644 (file)
@@ -316,12 +316,12 @@ load_directory (BusActivation *activation,
 BusActivation*
 bus_activation_new (BusContext        *context,
                    const DBusString  *address,
-                    const char       **directories,
+                    DBusList         **directories,
                     DBusError         *error)
 {
-  int i;
   BusActivation *activation;
-
+  DBusList *link;
+  
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
   activation = dbus_new0 (BusActivation, 1);
@@ -358,12 +358,12 @@ bus_activation_new (BusContext        *context,
     }
   
   /* Load service files */
-  i = 0;
-  while (directories[i] != NULL)
+  link = _dbus_list_get_first_link (directories);
+  while (link != NULL)
     {
-      if (!load_directory (activation, directories[i], error))
+      if (!load_directory (activation, link->data, error))
         goto failed;
-      ++i;
+      link = _dbus_list_get_next_link (directories, link);
     }
 
   return activation;
index fd3a72c..0e9e6ea 100644 (file)
 #define BUS_ACTIVATION_H
 
 #include <dbus/dbus.h>
+#include <dbus/dbus-list.h>
 #include "bus.h"
 
 BusActivation* bus_activation_new              (BusContext        *context,
                                                 const DBusString  *address,
-                                                const char       **paths,
+                                                DBusList         **directories,
                                                 DBusError         *error);
 void           bus_activation_ref              (BusActivation     *activation);
 void           bus_activation_unref            (BusActivation     *activation);
index 1ca4feb..82452d0 100644 (file)
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -187,7 +187,6 @@ bus_context_new (const DBusString *config_file,
   DBusList **addresses;
   BusConfigParser *parser;
   DBusString full_address;
-  const char *service_dirs[] = { NULL, NULL };
   const char *user;
   char **auth_mechanisms;
   DBusList **auth_mechanisms_list;
@@ -336,7 +335,8 @@ bus_context_new (const DBusString *config_file,
   /* Create activation subsystem */
   
   context->activation = bus_activation_new (context, &full_address,
-                                            service_dirs, error);
+                                            bus_config_parser_get_service_dirs (parser),
+                                            error);
   if (context->activation == NULL)
     {
       _DBUS_ASSERT_ERROR_IS_SET (error);
index dc3cb4d..77b68ca 100644 (file)
@@ -38,7 +38,9 @@ typedef enum
   ELEMENT_LIMIT,
   ELEMENT_ALLOW,
   ELEMENT_DENY,
-  ELEMENT_FORK
+  ELEMENT_FORK,
+  ELEMENT_SERVICEDIR,
+  ELEMENT_INCLUDEDIR
 } ElementType;
 
 typedef struct
@@ -87,6 +89,8 @@ struct BusConfigParser
   DBusList *listen_on; /**< List of addresses to listen to */
 
   DBusList *mechanisms; /**< Auth mechanisms */
+
+  DBusList *service_dirs; /**< Directories to look for services in */
   
   unsigned int fork : 1; /**< TRUE to fork into daemon mode */
 };
@@ -118,6 +122,10 @@ element_type_to_name (ElementType type)
       return "deny";
     case ELEMENT_FORK:
       return "fork";
+    case ELEMENT_SERVICEDIR:
+      return "servicedir";
+    case ELEMENT_INCLUDEDIR:
+      return "includedir";
     }
 
   _dbus_assert_not_reached ("bad element type");
@@ -210,6 +218,9 @@ merge_included (BusConfigParser *parser,
 
   while ((link = _dbus_list_pop_first_link (&included->mechanisms)))
     _dbus_list_append_link (&parser->mechanisms, link);
+
+  while ((link = _dbus_list_pop_first_link (&included->service_dirs)))
+    _dbus_list_append_link (&parser->service_dirs, link);
   
   return TRUE;
 }
@@ -256,6 +267,12 @@ bus_config_parser_unref (BusConfigParser *parser)
 
       _dbus_list_clear (&parser->listen_on);
 
+      _dbus_list_foreach (&parser->service_dirs,
+                          (DBusForeachFunction) dbus_free,
+                          NULL);
+
+      _dbus_list_clear (&parser->service_dirs);
+      
       dbus_free (parser);
     }
 }
@@ -463,6 +480,32 @@ start_busconfig_child (BusConfigParser   *parser,
 
       return TRUE;
     }
+  else if (strcmp (element_name, "includedir") == 0)
+    {
+      if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
+  else if (strcmp (element_name, "servicedir") == 0)
+    {
+      if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error))
+        return FALSE;
+
+      if (push_element (parser, ELEMENT_SERVICEDIR) == NULL)
+        {
+          dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+          return FALSE;
+        }
+
+      return TRUE;
+    }
   else if (strcmp (element_name, "include") == 0)
     {
       Element *e;
@@ -681,6 +724,8 @@ bus_config_parser_end_element (BusConfigParser   *parser,
     case ELEMENT_USER:
     case ELEMENT_LISTEN:
     case ELEMENT_AUTH:
+    case ELEMENT_SERVICEDIR:
+    case ELEMENT_INCLUDEDIR:
       if (!e->had_content)
         {
           dbus_set_error (error, DBUS_ERROR_FAILED,
@@ -714,6 +759,112 @@ all_whitespace (const DBusString *str)
   return i == _dbus_string_get_length (str);
 }
 
+static dbus_bool_t
+include_file (BusConfigParser   *parser,
+              const DBusString  *filename,
+              dbus_bool_t        ignore_missing,
+              DBusError         *error)
+{
+  /* FIXME good test case for this would load each config file in the
+   * test suite both alone, and as an include, and check
+   * that the result is the same
+   */
+  BusConfigParser *included;
+  DBusError tmp_error;
+        
+  dbus_error_init (&tmp_error);
+  included = bus_config_load (filename, &tmp_error);
+  if (included == NULL)
+    {
+      _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
+
+      if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) &&
+          ignore_missing)
+        {
+          dbus_error_free (&tmp_error);
+          return TRUE;
+        }
+      else
+        {
+          dbus_move_error (&tmp_error, error);
+          return FALSE;
+        }
+    }
+  else
+    {
+      _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
+
+      if (!merge_included (parser, included, error))
+        {
+          bus_config_parser_unref (included);
+          return FALSE;
+        }
+
+      bus_config_parser_unref (included);
+      return TRUE;
+    }
+}
+
+static dbus_bool_t
+include_dir (BusConfigParser   *parser,
+             const DBusString  *dirname,
+             DBusError         *error)
+{
+  DBusString filename;
+  dbus_bool_t retval;
+  DBusError tmp_error;
+  DBusDirIter *dir;
+  
+  if (!_dbus_string_init (&filename))
+    {
+      dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL);
+      return FALSE;
+    }
+
+  retval = FALSE;
+  
+  dir = _dbus_directory_open (dirname, error);
+    
+  /* FIXME this is just so the tests pass for now, it needs to come out
+   * once I implement make-dirname-relative-to-currently-parsed-files-dir
+   */
+  if (dir == NULL)
+    {
+      if (error)
+        dbus_error_free (error);
+      _dbus_string_free (&filename);
+      return TRUE;
+    }
+
+  if (dir == NULL)
+    goto failed;
+  
+  while (_dbus_directory_get_next_file (dir, &filename, &tmp_error))
+    {
+      if (_dbus_string_ends_with_c_str (&filename, ".conf"))
+        {
+          if (!include_file (parser, &filename, TRUE, error))
+            goto failed;
+        }
+    }
+
+  if (dbus_error_is_set (&tmp_error))
+    {
+      dbus_move_error (&tmp_error, error);
+      goto failed;
+    }
+  
+  retval = TRUE;
+  
+ failed:
+  _dbus_string_free (&filename);
+  
+  if (dir)
+    _dbus_directory_close (dir);
+
+  return retval;
+}
+
 dbus_bool_t
 bus_config_parser_content (BusConfigParser   *parser,
                            const DBusString  *content,
@@ -770,45 +921,23 @@ bus_config_parser_content (BusConfigParser   *parser,
 
     case ELEMENT_INCLUDE:
       {
-        /* FIXME good test case for this would load each config file in the
-         * test suite both alone, and as an include, and check
-         * that the result is the same
-         */
-        BusConfigParser *included;
-        DBusError tmp_error;
-
         e->had_content = TRUE;
-        
-        dbus_error_init (&tmp_error);
-        included = bus_config_load (content, &tmp_error);
-        if (included == NULL)
-          {
-            _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
-            if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) &&
-                e->d.include.ignore_missing)
-              {
-                dbus_error_free (&tmp_error);
-                return TRUE;
-              }
-            else
-              {
-                dbus_move_error (&tmp_error, error);
-                return FALSE;
-              }
-          }
-        else
-          {
-            _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
 
-            if (!merge_included (parser, included, error))
-              return FALSE;
-
-            bus_config_parser_unref (included);
-            return TRUE;
-          }
+        if (!include_file (parser, content,
+                           e->d.include.ignore_missing, error))
+          return FALSE;
       }
       break;
 
+    case ELEMENT_INCLUDEDIR:
+      {
+        e->had_content = TRUE;
+        
+        if (!include_dir (parser, content, error))
+          return FALSE;
+      }
+      break;
+      
     case ELEMENT_USER:
       {
         char *s;
@@ -858,6 +987,24 @@ bus_config_parser_content (BusConfigParser   *parser,
           }
       }
       break;
+
+    case ELEMENT_SERVICEDIR:
+      {
+        char *s;
+
+        e->had_content = TRUE;
+        
+        if (!_dbus_string_copy_data (content, &s))
+          goto nomem;
+
+        if (!_dbus_list_append (&parser->service_dirs,
+                                s))
+          {
+            dbus_free (s);
+            goto nomem;
+          }
+      }
+      break;
     }
 
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
@@ -911,6 +1058,12 @@ bus_config_parser_get_mechanisms (BusConfigParser *parser)
   return &parser->mechanisms;
 }
 
+DBusList**
+bus_config_parser_get_service_dirs (BusConfigParser *parser)
+{
+  return &parser->service_dirs;
+}
+
 dbus_bool_t
 bus_config_parser_get_fork (BusConfigParser   *parser)
 {
index 101b4c6..d06cde0 100644 (file)
@@ -55,10 +55,11 @@ dbus_bool_t      bus_config_parser_finished      (BusConfigParser   *parser,
                                                   DBusError         *error);
 
 /* Functions for extracting the parse results */
-const char*      bus_config_parser_get_user       (BusConfigParser   *parser);
-DBusList**       bus_config_parser_get_addresses  (BusConfigParser   *parser);
-DBusList**       bus_config_parser_get_mechanisms (BusConfigParser   *parser);
-dbus_bool_t      bus_config_parser_get_fork       (BusConfigParser   *parser);
+const char* bus_config_parser_get_user         (BusConfigParser *parser);
+DBusList**  bus_config_parser_get_addresses    (BusConfigParser *parser);
+DBusList**  bus_config_parser_get_mechanisms   (BusConfigParser *parser);
+dbus_bool_t bus_config_parser_get_fork         (BusConfigParser *parser);
+DBusList**  bus_config_parser_get_service_dirs (BusConfigParser *parser);
 
 /* Loader functions (backended off one of the XML parsers).  Returns a
  * finished ConfigParser.
index d63bc3e..b920340 100644 (file)
  * file in the user's homedir. However they are transient (only used
  * by a single server instance for a fixed period of time, then
  * discarded). Also, the keys are not sent over the wire.
+ *
+ * @todo there's a memory leak on some codepath in here, I saw it once
+ * when running make check - probably some specific initial cookies
+ * present in the cookie file, then depending on what we do with them.
  */
 
 /**
index 71863ef..8aa9181 100644 (file)
@@ -3185,18 +3185,21 @@ _dbus_change_identity  (unsigned long  uid,
                         unsigned long  gid,
                         DBusError     *error)
 {
-  if (setuid (uid) < 0)
+  /* Set GID first, or the setuid may remove our permission
+   * to change the GID
+   */
+  if (setgid (gid) < 0)
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to set UID to %lu: %s", uid,
+                      "Failed to set GID to %lu: %s", gid,
                       _dbus_strerror (errno));
       return FALSE;
     }
-
-  if (setgid (gid) < 0)
+  
+  if (setuid (uid) < 0)
     {
       dbus_set_error (error, _dbus_error_from_errno (errno),
-                      "Failed to set GID to %lu: %s", gid,
+                      "Failed to set UID to %lu: %s", uid,
                       _dbus_strerror (errno));
       return FALSE;
     }
index 222122c..d109d71 100644 (file)
@@ -4,6 +4,8 @@
   <user>mybususer</user>
   <listen>unix:path=/foo/bar</listen>
   <listen>tcp:port=1234</listen>
+  <includedir>basic.d</includedir>
+  <servicedir>/usr/share/foo</servicedir>
   <include ignore_missing="yes">nonexistent.conf</include>
   <policy context="default">
     <allow user="*"/>