[daemon-fix] Fixed sending daemon match rules for kdbus broadcasts
[platform/upstream/dbus.git] / bus / config-parser.c
index 34d8684..12a2d2e 100644 (file)
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  *
  */
+
+#include <config.h>
 #include "config-parser-common.h"
 #include "config-parser.h"
 #include "test.h"
@@ -28,6 +30,8 @@
 #include "selinux.h"
 #include <dbus/dbus-list.h>
 #include <dbus/dbus-internals.h>
+#include <dbus/dbus-misc.h>
+#include <dbus/dbus-sysdeps.h>
 #include <string.h>
 
 typedef enum
@@ -111,9 +115,8 @@ struct BusConfigParser
 
   unsigned int fork : 1; /**< TRUE to fork into daemon mode */
 
-  unsigned int keep_umask : 1; /**< TRUE to keep original umask when forking */
-
   unsigned int syslog : 1; /**< TRUE to enable syslog */
+  unsigned int keep_umask : 1; /**< TRUE to keep original umask when forking */
 
   unsigned int is_toplevel : 1; /**< FALSE if we are a sub-config-file inside another one */
 
@@ -321,7 +324,14 @@ merge_included (BusConfigParser *parser,
       parser->pidfile = included->pidfile;
       included->pidfile = NULL;
     }
-  
+
+  if (included->servicehelper != NULL)
+    {
+      dbus_free (parser->servicehelper);
+      parser->servicehelper = included->servicehelper;
+      included->servicehelper = NULL;
+    }
+
   while ((link = _dbus_list_pop_first_link (&included->listen_on)))
     _dbus_list_append_link (&parser->listen_on, link);
 
@@ -405,6 +415,15 @@ bus_config_parser_new (const DBusString      *basedir,
       parser->limits.max_incoming_bytes = _DBUS_ONE_MEGABYTE * 127;
       parser->limits.max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 127;
       parser->limits.max_message_size = _DBUS_ONE_MEGABYTE * 32;
+
+      /* We set relatively conservative values here since due to the
+      way SCM_RIGHTS works we need to preallocate an array for the
+      maximum number of file descriptors we can receive. Picking a
+      high value here thus translates directly to more memory
+      allocation. */
+      parser->limits.max_incoming_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS*4;
+      parser->limits.max_outgoing_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS*4;
+      parser->limits.max_message_unix_fds = DBUS_DEFAULT_MESSAGE_UNIX_FDS;
       
       /* Making this long means the user has to wait longer for an error
        * message if something screws up, but making it too short means
@@ -440,7 +459,7 @@ bus_config_parser_new (const DBusString      *basedir,
        */
       parser->limits.max_match_rules_per_connection = 512;
       
-      parser->limits.reply_timeout = 5 * 60 * 1000; /* 5 minutes */
+      parser->limits.reply_timeout = -1; /* never */
 
       /* this is effectively a limit on message queue size for messages
        * that require a reply
@@ -679,12 +698,12 @@ start_busconfig_child (BusConfigParser   *parser,
 
       return TRUE;
     }
-  else if (element_type == ELEMENT_TYPE)
+  else if (element_type == ELEMENT_CONFIGTYPE)
     {
       if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
         return FALSE;
 
-      if (push_element (parser, ELEMENT_TYPE) == NULL)
+      if (push_element (parser, ELEMENT_CONFIGTYPE) == NULL)
         {
           BUS_SET_OOM (error);
           return FALSE;
@@ -707,33 +726,33 @@ start_busconfig_child (BusConfigParser   *parser,
       
       return TRUE;
     }
-  else if (element_type == ELEMENT_KEEP_UMASK)
+  else if (element_type == ELEMENT_SYSLOG)
     {
-      if (!check_no_attributes (parser, "keep_umask", attribute_names, attribute_values, error))
+      if (!check_no_attributes (parser, "syslog", attribute_names, attribute_values, error))
         return FALSE;
 
-      if (push_element (parser, ELEMENT_KEEP_UMASK) == NULL)
+      if (push_element (parser, ELEMENT_SYSLOG) == NULL)
         {
           BUS_SET_OOM (error);
           return FALSE;
         }
-
-      parser->keep_umask = TRUE;
+      
+      parser->syslog = TRUE;
       
       return TRUE;
     }
-  else if (element_type == ELEMENT_SYSLOG)
+  else if (element_type == ELEMENT_KEEP_UMASK)
     {
-      if (!check_no_attributes (parser, "syslog", attribute_names, attribute_values, error))
+      if (!check_no_attributes (parser, "keep_umask", attribute_names, attribute_values, error))
         return FALSE;
 
-      if (push_element (parser, ELEMENT_SYSLOG) == NULL)
+      if (push_element (parser, ELEMENT_KEEP_UMASK) == NULL)
         {
           BUS_SET_OOM (error);
           return FALSE;
         }
 
-      parser->syslog = TRUE;
+      parser->keep_umask = TRUE;
       
       return TRUE;
     }
@@ -1143,6 +1162,7 @@ append_rule_from_element (BusConfigParser   *parser,
   const char *send_requested_reply;
   const char *receive_requested_reply;
   const char *own;
+  const char *own_prefix;
   const char *user;
   const char *group;
 
@@ -1168,6 +1188,7 @@ append_rule_from_element (BusConfigParser   *parser,
                           "send_requested_reply", &send_requested_reply,
                           "receive_requested_reply", &receive_requested_reply,
                           "own", &own,
+                          "own_prefix", &own_prefix,
                           "user", &user,
                           "group", &group,
                           "log", &log,
@@ -1179,7 +1200,7 @@ append_rule_from_element (BusConfigParser   *parser,
         receive_interface || receive_member || receive_error || receive_sender ||
         receive_type || receive_path || eavesdrop ||
         send_requested_reply || receive_requested_reply ||
-        own || user || group))
+        own || own_prefix || user || group))
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
                       "Element <%s> must have one or more attributes",
@@ -1207,102 +1228,103 @@ append_rule_from_element (BusConfigParser   *parser,
    *   base send_ can combine with send_destination, send_path, send_type, send_requested_reply
    *   base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop
    *
-   *   user, group, own must occur alone
+   *   user, group, own, own_prefix must occur alone
    *
    * Pretty sure the below stuff is broken, FIXME think about it more.
    */
 
-  if (((send_interface && send_error) ||
-       (send_interface && receive_interface) ||
-       (send_interface && receive_member) ||
-       (send_interface && receive_error) ||
-       (send_interface && receive_sender) ||
-       (send_interface && receive_requested_reply) ||
-       (send_interface && own) ||
-       (send_interface && user) ||
-       (send_interface && group)) ||
-
-      ((send_member && send_error) ||
-       (send_member && receive_interface) ||
-       (send_member && receive_member) ||
-       (send_member && receive_error) ||
-       (send_member && receive_sender) ||
-       (send_member && receive_requested_reply) ||
-       (send_member && own) ||
-       (send_member && user) ||
-       (send_member && group)) ||
-      
-      ((send_error && receive_interface) ||
-       (send_error && receive_member) ||
-       (send_error && receive_error) ||
-       (send_error && receive_sender) ||
-       (send_error && receive_requested_reply) ||
-       (send_error && own) ||
-       (send_error && user) ||
-       (send_error && group)) ||
-
-      ((send_destination && receive_interface) ||
-       (send_destination && receive_member) ||
-       (send_destination && receive_error) ||
-       (send_destination && receive_sender) ||
-       (send_destination && receive_requested_reply) ||
-       (send_destination && own) ||
-       (send_destination && user) ||
-       (send_destination && group)) ||
-
-      ((send_type && receive_interface) ||
-       (send_type && receive_member) ||
-       (send_type && receive_error) ||
-       (send_type && receive_sender) ||
-       (send_type && receive_requested_reply) ||
-       (send_type && own) ||
-       (send_type && user) ||
-       (send_type && group)) ||
-
-      ((send_path && receive_interface) ||
-       (send_path && receive_member) ||
-       (send_path && receive_error) ||
-       (send_path && receive_sender) ||
-       (send_path && receive_requested_reply) ||
-       (send_path && own) ||
-       (send_path && user) ||
-       (send_path && group)) ||
-
-      ((send_requested_reply && receive_interface) ||
-       (send_requested_reply && receive_member) ||
-       (send_requested_reply && receive_error) ||
-       (send_requested_reply && receive_sender) ||
-       (send_requested_reply && receive_requested_reply) ||
-       (send_requested_reply && own) ||
-       (send_requested_reply && user) ||
-       (send_requested_reply && group)) ||
-      
-      ((receive_interface && receive_error) ||
-       (receive_interface && own) ||
-       (receive_interface && user) ||
-       (receive_interface && group)) ||
-
-      ((receive_member && receive_error) ||
-       (receive_member && own) ||
-       (receive_member && user) ||
-       (receive_member && group)) ||
-      
-      ((receive_error && own) ||
-       (receive_error && user) ||
-       (receive_error && group)) ||
-
-      ((eavesdrop && own) ||
-       (eavesdrop && user) ||
-       (eavesdrop && group)) ||
-
-      ((receive_requested_reply && own) ||
-       (receive_requested_reply && user) ||
-       (receive_requested_reply && group)) ||
-      
-      ((own && user) ||
-       (own && group)) ||
-
-      ((user && group)))
+  if ((send_interface && (send_error ||
+                          receive_interface ||
+                          receive_member ||
+                          receive_error ||
+                          receive_sender ||
+                          receive_requested_reply ||
+                          own || own_prefix ||
+                          user ||
+                          group)) ||
+
+      (send_member && (send_error ||
+                       receive_interface ||
+                       receive_member ||
+                       receive_error ||
+                       receive_sender ||
+                       receive_requested_reply ||
+                       own || own_prefix ||
+                       user ||
+                       group)) ||
+
+      (send_error && (receive_interface ||
+                      receive_member ||
+                      receive_error ||
+                      receive_sender ||
+                      receive_requested_reply ||
+                      own || own_prefix ||
+                      user ||
+                      group)) ||
+
+      (send_destination && (receive_interface ||
+                            receive_member ||
+                            receive_error ||
+                            receive_sender ||
+                            receive_requested_reply ||
+                            own || own_prefix ||
+                            user ||
+                            group)) ||
+
+      (send_type && (receive_interface ||
+                     receive_member ||
+                     receive_error ||
+                     receive_sender ||
+                     receive_requested_reply ||
+                     own || own_prefix ||
+                     user ||
+                     group)) ||
+
+      (send_path && (receive_interface ||
+                     receive_member ||
+                     receive_error ||
+                     receive_sender ||
+                     receive_requested_reply ||
+                     own || own_prefix ||
+                     user ||
+                     group)) ||
+
+      (send_requested_reply && (receive_interface ||
+                                receive_member ||
+                                receive_error ||
+                                receive_sender ||
+                                receive_requested_reply ||
+                                own || own_prefix ||
+                                user ||
+                                group)) ||
+
+      (receive_interface && (receive_error ||
+                             own || own_prefix ||
+                             user ||
+                             group)) ||
+
+      (receive_member && (receive_error ||
+                          own || own_prefix ||
+                          user ||
+                          group)) ||
+
+      (receive_error && (own || own_prefix ||
+                         user ||
+                         group)) ||
+
+      (eavesdrop && (own || own_prefix ||
+                     user ||
+                     group)) ||
+
+      (receive_requested_reply && (own || own_prefix ||
+                                   user ||
+                                   group)) ||
+
+      (own && (own_prefix || user || group)) ||
+
+      (own_prefix && (own || user || group)) ||
+
+      (user && group))
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
                       "Invalid combination of attributes on element <%s>",
@@ -1478,18 +1500,29 @@ append_rule_from_element (BusConfigParser   *parser,
       if (receive_sender && rule->d.receive.origin == NULL)
         goto nomem;
     }
-  else if (own)
+  else if (own || own_prefix)
     {
       rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow); 
       if (rule == NULL)
         goto nomem;
 
-      if (IS_WILDCARD (own))
-        own = NULL;
+      if (own)
+        {
+          if (IS_WILDCARD (own))
+            own = NULL;
       
-      rule->d.own.service_name = _dbus_strdup (own);
-      if (own && rule->d.own.service_name == NULL)
-        goto nomem;
+          rule->d.own.prefix = 0;
+          rule->d.own.service_name = _dbus_strdup (own);
+          if (own && rule->d.own.service_name == NULL)
+            goto nomem;
+        }
+      else
+        {
+          rule->d.own.prefix = 1;
+          rule->d.own.service_name = _dbus_strdup (own_prefix);
+          if (rule->d.own.service_name == NULL)
+            goto nomem;
+        }
     }
   else if (user)
     {      
@@ -1829,16 +1862,31 @@ set_limit (BusConfigParser *parser,
       must_be_positive = TRUE;
       parser->limits.max_incoming_bytes = value;
     }
+  else if (strcmp (name, "max_incoming_unix_fds") == 0)
+    {
+      must_be_positive = TRUE;
+      parser->limits.max_incoming_unix_fds = value;
+    }
   else if (strcmp (name, "max_outgoing_bytes") == 0)
     {
       must_be_positive = TRUE;
       parser->limits.max_outgoing_bytes = value;
     }
+  else if (strcmp (name, "max_outgoing_unix_fds") == 0)
+    {
+      must_be_positive = TRUE;
+      parser->limits.max_outgoing_unix_fds = value;
+    }
   else if (strcmp (name, "max_message_size") == 0)
     {
       must_be_positive = TRUE;
       parser->limits.max_message_size = value;
     }
+  else if (strcmp (name, "max_message_unix_fds") == 0)
+    {
+      must_be_positive = TRUE;
+      parser->limits.max_message_unix_fds = value;
+    }
   else if (strcmp (name, "service_start_timeout") == 0)
     {
       must_be_positive = TRUE;
@@ -1976,7 +2024,7 @@ bus_config_parser_end_element (BusConfigParser   *parser,
 
     case ELEMENT_INCLUDE:
     case ELEMENT_USER:
-    case ELEMENT_TYPE:
+    case ELEMENT_CONFIGTYPE:
     case ELEMENT_LISTEN:
     case ELEMENT_PIDFILE:
     case ELEMENT_AUTH:
@@ -2005,8 +2053,8 @@ bus_config_parser_end_element (BusConfigParser   *parser,
     case ELEMENT_ALLOW:
     case ELEMENT_DENY:
     case ELEMENT_FORK:
-    case ELEMENT_KEEP_UMASK:
     case ELEMENT_SYSLOG:
+    case ELEMENT_KEEP_UMASK:
     case ELEMENT_SELINUX:
     case ELEMENT_ASSOCIATE:
     case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
@@ -2211,8 +2259,19 @@ include_dir (BusConfigParser   *parser,
         {
           if (!include_file (parser, &full_path, TRUE, error))
             {
-              _dbus_string_free (&full_path);
-              goto failed;
+              if (dbus_error_is_set (error))
+                {
+                  /* We log to syslog unconditionally here, because this is
+                   * the configuration parser, so we don't yet know whether
+                   * this bus is going to want to write to syslog! (There's
+                   * also some layer inversion going on, if we want to use
+                   * the bus context.) */
+                  _dbus_system_log (DBUS_SYSTEM_LOG_INFO,
+                                    "Encountered error '%s' while parsing '%s'\n",
+                                    error->message,
+                                    _dbus_string_get_const_data (&full_path));
+                  dbus_error_free (error);
+                }
             }
         }
 
@@ -2293,8 +2352,8 @@ bus_config_parser_content (BusConfigParser   *parser,
     case ELEMENT_ALLOW:
     case ELEMENT_DENY:
     case ELEMENT_FORK:
-    case ELEMENT_KEEP_UMASK:
     case ELEMENT_SYSLOG:
+    case ELEMENT_KEEP_UMASK:
     case ELEMENT_STANDARD_SESSION_SERVICEDIRS:    
     case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS:    
     case ELEMENT_ALLOW_ANONYMOUS:
@@ -2435,7 +2494,7 @@ bus_config_parser_content (BusConfigParser   *parser,
       }
       break;
 
-    case ELEMENT_TYPE:
+    case ELEMENT_CONFIGTYPE:
       {
         char *s;
 
@@ -2619,15 +2678,15 @@ bus_config_parser_get_fork (BusConfigParser   *parser)
 }
 
 dbus_bool_t
-bus_config_parser_get_keep_umask (BusConfigParser   *parser)
+bus_config_parser_get_syslog (BusConfigParser   *parser)
 {
-  return parser->keep_umask;
+  return parser->syslog;
 }
 
 dbus_bool_t
-bus_config_parser_get_syslog (BusConfigParser   *parser)
+bus_config_parser_get_keep_umask (BusConfigParser   *parser)
 {
-  return parser->syslog;
+  return parser->keep_umask;
 }
 
 dbus_bool_t
@@ -2684,7 +2743,7 @@ bus_config_parser_steal_service_context_table (BusConfigParser *parser)
   return table;
 }
 
-#ifdef DBUS_BUILD_TESTS
+#ifdef DBUS_ENABLE_EMBEDDED_TESTS
 #include <stdio.h>
 
 typedef enum
@@ -2695,9 +2754,60 @@ typedef enum
 } Validity;
 
 static dbus_bool_t
+do_check_own_rules (BusPolicy  *policy)
+{
+  const struct {
+    char *name;
+    dbus_bool_t allowed;
+  } checks[] = {
+    {"org.freedesktop", FALSE},
+    {"org.freedesktop.ManySystem", FALSE},
+    {"org.freedesktop.ManySystems", TRUE},
+    {"org.freedesktop.ManySystems.foo", TRUE},
+    {"org.freedesktop.ManySystems.foo.bar", TRUE},
+    {"org.freedesktop.ManySystems2", FALSE},
+    {"org.freedesktop.ManySystems2.foo", FALSE},
+    {"org.freedesktop.ManySystems2.foo.bar", FALSE},
+    {NULL, FALSE}
+  };
+  int i = 0;
+
+  while (checks[i].name)
+    {
+      DBusString service_name;
+      dbus_bool_t ret;
+
+      if (!_dbus_string_init (&service_name))
+        _dbus_assert_not_reached ("couldn't init string");
+      if (!_dbus_string_append (&service_name, checks[i].name))
+        _dbus_assert_not_reached ("couldn't append string");
+
+      ret = bus_policy_check_can_own (policy, &service_name);
+      printf ("        Check name %s: %s\n", checks[i].name,
+              ret ? "allowed" : "not allowed");
+      if (checks[i].allowed && !ret)
+        {
+          _dbus_warn ("Cannot own %s\n", checks[i].name);
+          return FALSE;
+        }
+      if (!checks[i].allowed && ret)
+        {
+          _dbus_warn ("Can own %s\n", checks[i].name);
+          return FALSE;
+        }
+      _dbus_string_free (&service_name);
+
+      i++;
+    }
+
+  return TRUE;
+}
+
+static dbus_bool_t
 do_load (const DBusString *full_path,
          Validity          validity,
-         dbus_bool_t       oom_possible)
+         dbus_bool_t       oom_possible,
+         dbus_bool_t       check_own_rules)
 {
   BusConfigParser *parser;
   DBusError error;
@@ -2734,6 +2844,11 @@ do_load (const DBusString *full_path,
     {
       _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
 
+      if (check_own_rules && do_check_own_rules (parser->policy) == FALSE)
+        {
+          return FALSE;
+        }
+
       bus_config_parser_unref (parser);
 
       if (validity == INVALID)
@@ -2750,6 +2865,7 @@ typedef struct
 {
   const DBusString *full_path;
   Validity          validity;
+  dbus_bool_t       check_own_rules;
 } LoaderOomData;
 
 static dbus_bool_t
@@ -2757,7 +2873,7 @@ check_loader_oom_func (void *data)
 {
   LoaderOomData *d = data;
 
-  return do_load (d->full_path, d->validity, TRUE);
+  return do_load (d->full_path, d->validity, TRUE, d->check_own_rules);
 }
 
 static dbus_bool_t
@@ -2840,6 +2956,8 @@ process_test_valid_subdir (const DBusString *test_base_dir,
 
       d.full_path = &full_path;
       d.validity = validity;
+      d.check_own_rules = _dbus_string_ends_with_c_str (&full_path,
+          "check-own-rules.conf");
 
       /* FIXME hackaround for an expat problem, see
        * https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=124747
@@ -2980,8 +3098,11 @@ limits_equal (const BusLimits *a,
 {
   return
     (a->max_incoming_bytes == b->max_incoming_bytes
+     || a->max_incoming_unix_fds == b->max_incoming_unix_fds
      || a->max_outgoing_bytes == b->max_outgoing_bytes
+     || a->max_outgoing_unix_fds == b->max_outgoing_unix_fds
      || a->max_message_size == b->max_message_size
+     || a->max_message_unix_fds == b->max_message_unix_fds
      || a->activation_timeout == b->activation_timeout
      || a->auth_timeout == b->auth_timeout
      || a->max_completed_connections == b->max_completed_connections
@@ -3213,12 +3334,15 @@ process_test_equiv_subdir (const DBusString *test_base_dir,
 static const char *test_session_service_dir_matches[] = 
         {
 #ifdef DBUS_UNIX
+         "/testhome/foo/.testlocal/testshare/dbus-1/services",
          "/testusr/testlocal/testshare/dbus-1/services",
          "/testusr/testshare/dbus-1/services",
-#endif
          DBUS_DATADIR"/dbus-1/services",
-#ifdef DBUS_UNIX
-         "/testhome/foo/.testlocal/testshare/dbus-1/services",
+#endif
+/* will be filled in test_default_session_servicedirs() */
+#ifdef DBUS_WIN
+         NULL,
+         NULL,
 #endif
          NULL
         };
@@ -3229,16 +3353,28 @@ test_default_session_servicedirs (void)
   DBusList *dirs;
   DBusList *link;
   DBusString progs;
-  const char *common_progs;
   int i;
 
+#ifdef DBUS_WIN
+  const char *common_progs;
+  char buffer[1024];
+
+  if (_dbus_get_install_root(buffer, sizeof(buffer)))
+    {
+      strcat(buffer,DBUS_DATADIR);
+      strcat(buffer,"/dbus-1/services");
+      test_session_service_dir_matches[0] = buffer;
+    }
+#endif
+
   /* On Unix we don't actually use this variable, but it's easier to handle the
    * deallocation if we always allocate it, whether needed or not */
   if (!_dbus_string_init (&progs))
     _dbus_assert_not_reached ("OOM allocating progs");
 
-  common_progs = _dbus_getenv ("CommonProgramFiles");
 #ifndef DBUS_UNIX
+  common_progs = _dbus_getenv ("CommonProgramFiles");
+
   if (common_progs) 
     {
       if (!_dbus_string_append (&progs, common_progs)) 
@@ -3282,10 +3418,10 @@ test_default_session_servicedirs (void)
     }
 
 #ifdef DBUS_UNIX
-  if (!_dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare"))
+  if (!dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare"))
     _dbus_assert_not_reached ("couldn't setenv XDG_DATA_HOME");
 
-  if (!_dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:"))
+  if (!dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:"))
     _dbus_assert_not_reached ("couldn't setenv XDG_DATA_DIRS");
 #endif
   if (!_dbus_get_standard_session_servicedirs (&dirs))
@@ -3339,10 +3475,17 @@ test_default_session_servicedirs (void)
 static const char *test_system_service_dir_matches[] = 
         {
 #ifdef DBUS_UNIX
-         "/testusr/testlocal/testshare/dbus-1/system-services",
-         "/testusr/testshare/dbus-1/system-services",
+         "/usr/local/share/dbus-1/system-services",
+         "/usr/share/dbus-1/system-services",
 #endif
          DBUS_DATADIR"/dbus-1/system-services",
+#ifdef DBUS_UNIX
+         "/lib/dbus-1/system-services",
+#endif
+
+#ifdef DBUS_WIN
+         NULL,
+#endif
          NULL
         };
 
@@ -3352,7 +3495,9 @@ test_default_system_servicedirs (void)
   DBusList *dirs;
   DBusList *link;
   DBusString progs;
+#ifndef DBUS_UNIX
   const char *common_progs;
+#endif
   int i;
 
   /* On Unix we don't actually use this variable, but it's easier to handle the
@@ -3360,8 +3505,9 @@ test_default_system_servicedirs (void)
   if (!_dbus_string_init (&progs))
     _dbus_assert_not_reached ("OOM allocating progs");
 
-  common_progs = _dbus_getenv ("CommonProgramFiles");
 #ifndef DBUS_UNIX
+  common_progs = _dbus_getenv ("CommonProgramFiles");
+
   if (common_progs) 
     {
       if (!_dbus_string_append (&progs, common_progs)) 
@@ -3405,10 +3551,10 @@ test_default_system_servicedirs (void)
     }
 
 #ifdef DBUS_UNIX
-  if (!_dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare"))
+  if (!dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare"))
     _dbus_assert_not_reached ("couldn't setenv XDG_DATA_HOME");
 
-  if (!_dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:"))
+  if (!dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:"))
     _dbus_assert_not_reached ("couldn't setenv XDG_DATA_DIRS");
 #endif
   if (!_dbus_get_standard_system_servicedirs (&dirs))
@@ -3472,8 +3618,12 @@ bus_config_parser_test (const DBusString *test_data_dir)
   if (!test_default_session_servicedirs())
     return FALSE;
 
+#ifdef DBUS_WIN
+  printf("default system service dir skipped\n");
+#else
   if (!test_default_system_servicedirs())
     return FALSE;
+#endif
 
   if (!process_test_valid_subdir (test_data_dir, "valid-config-files", VALID))
     return FALSE;
@@ -3487,5 +3637,5 @@ bus_config_parser_test (const DBusString *test_data_dir)
   return TRUE;
 }
 
-#endif /* DBUS_BUILD_TESTS */
+#endif /* DBUS_ENABLE_EMBEDDED_TESTS */