summaryrefslogtreecommitdiffstats
path: root/bus/config-parser.c
diff options
context:
space:
mode:
authorRichard Hughes <richard@hughsie.com>2007-07-24 11:58:08 +0000
committerRichard Hughes <richard@hughsie.com>2007-07-24 11:58:08 +0000
commit0cb8dd64a94fd3b57b37a68a6611a125689bf5df (patch)
treefbfe6c4538cee81a88d8bd6cbff06a1c59b7ab25 /bus/config-parser.c
parentd6fddc64b5ed5ddd7b087679b4bd4b8d79e2fe69 (diff)
2007-07-24 Richard Hughes <richard@hughsie.com>
* bus/Makefile.am: * bus/config-parser.c: (bus_config_parser_unref), (start_busconfig_child), (bus_config_parser_end_element), (servicehelper_path), (bus_config_parser_content), (bus_config_parser_finished), (bus_config_parser_get_servicehelper), (test_default_session_servicedirs), (test_default_system_servicedirs), (bus_config_parser_test): * bus/config-parser.h: Make the config-parser code use the common config code. Also add the session and systemdirs stuff, and make the config parser aware of the servicehelper field.
Diffstat (limited to 'bus/config-parser.c')
-rw-r--r--bus/config-parser.c364
1 files changed, 268 insertions, 96 deletions
diff --git a/bus/config-parser.c b/bus/config-parser.c
index 3c2389c7..43e516e3 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -20,6 +20,7 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
+#include "config-parser-common.h"
#include "config-parser.h"
#include "test.h"
#include "utils.h"
@@ -31,28 +32,6 @@
typedef enum
{
- ELEMENT_NONE,
- ELEMENT_BUSCONFIG,
- ELEMENT_INCLUDE,
- ELEMENT_USER,
- ELEMENT_LISTEN,
- ELEMENT_AUTH,
- ELEMENT_POLICY,
- ELEMENT_LIMIT,
- ELEMENT_ALLOW,
- ELEMENT_DENY,
- ELEMENT_FORK,
- ELEMENT_PIDFILE,
- ELEMENT_SERVICEDIR,
- ELEMENT_INCLUDEDIR,
- ELEMENT_TYPE,
- ELEMENT_SELINUX,
- ELEMENT_ASSOCIATE,
- ELEMENT_STANDARD_SESSION_SERVICEDIRS
-} ElementType;
-
-typedef enum
-{
/* we ignore policies for unknown groups/users */
POLICY_IGNORED,
@@ -108,13 +87,15 @@ struct BusConfigParser
char *user; /**< user to run as */
+ char *servicehelper; /**< location of the setuid helper */
+
char *bus_type; /**< Message bus type */
DBusList *listen_on; /**< List of addresses to listen to */
DBusList *mechanisms; /**< Auth mechanisms */
- DBusList *service_dirs; /**< Directories to look for services in */
+ DBusList *service_dirs; /**< Directories to look for session services in */
DBusList *conf_dirs; /**< Directories to look for policy configuration in */
@@ -133,54 +114,6 @@ struct BusConfigParser
unsigned int is_toplevel : 1; /**< FALSE if we are a sub-config-file inside another one */
};
-static const char*
-element_type_to_name (ElementType type)
-{
- switch (type)
- {
- case ELEMENT_NONE:
- return NULL;
- case ELEMENT_BUSCONFIG:
- return "busconfig";
- case ELEMENT_INCLUDE:
- return "include";
- case ELEMENT_USER:
- return "user";
- case ELEMENT_LISTEN:
- return "listen";
- case ELEMENT_AUTH:
- return "auth";
- case ELEMENT_POLICY:
- return "policy";
- case ELEMENT_LIMIT:
- return "limit";
- case ELEMENT_ALLOW:
- return "allow";
- case ELEMENT_DENY:
- return "deny";
- case ELEMENT_FORK:
- return "fork";
- case ELEMENT_PIDFILE:
- return "pidfile";
- case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
- return "standard_session_servicedirs";
- case ELEMENT_SERVICEDIR:
- return "servicedir";
- case ELEMENT_INCLUDEDIR:
- return "includedir";
- case ELEMENT_TYPE:
- return "type";
- case ELEMENT_SELINUX:
- return "selinux";
- case ELEMENT_ASSOCIATE:
- return "associate";
- }
-
- _dbus_assert_not_reached ("bad element type");
-
- return NULL;
-}
-
static Element*
push_element (BusConfigParser *parser,
ElementType type)
@@ -534,6 +467,7 @@ bus_config_parser_unref (BusConfigParser *parser)
pop_element (parser);
dbus_free (parser->user);
+ dbus_free (parser->servicehelper);
dbus_free (parser->bus_type);
dbus_free (parser->pidfile);
@@ -722,7 +656,11 @@ start_busconfig_child (BusConfigParser *parser,
const char **attribute_values,
DBusError *error)
{
- if (strcmp (element_name, "user") == 0)
+ ElementType element_type;
+
+ element_type = bus_config_parser_element_name_to_type (element_name);
+
+ if (element_type == ELEMENT_USER)
{
if (!check_no_attributes (parser, "user", attribute_names, attribute_values, error))
return FALSE;
@@ -735,7 +673,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "type") == 0)
+ else if (element_type == ELEMENT_TYPE)
{
if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
return FALSE;
@@ -748,7 +686,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "fork") == 0)
+ else if (element_type == ELEMENT_FORK)
{
if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
return FALSE;
@@ -763,7 +701,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "pidfile") == 0)
+ else if (element_type == ELEMENT_PIDFILE)
{
if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
return FALSE;
@@ -776,7 +714,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "listen") == 0)
+ else if (element_type == ELEMENT_LISTEN)
{
if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
return FALSE;
@@ -789,7 +727,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "auth") == 0)
+ else if (element_type == ELEMENT_AUTH)
{
if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
return FALSE;
@@ -802,7 +740,20 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "includedir") == 0)
+ else if (element_type == ELEMENT_SERVICEHELPER)
+ {
+ if (!check_no_attributes (parser, "servicehelper", attribute_names, attribute_values, error))
+ return FALSE;
+
+ if (push_element (parser, ELEMENT_SERVICEHELPER) == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
+ else if (element_type == ELEMENT_INCLUDEDIR)
{
if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error))
return FALSE;
@@ -815,7 +766,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "standard_session_servicedirs") == 0)
+ else if (element_type == ELEMENT_STANDARD_SESSION_SERVICEDIRS)
{
DBusList *link;
DBusList *dirs;
@@ -841,7 +792,33 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "servicedir") == 0)
+ else if (element_type == ELEMENT_STANDARD_SYSTEM_SERVICEDIRS)
+ {
+ DBusList *link;
+ DBusList *dirs;
+ dirs = NULL;
+
+ if (!check_no_attributes (parser, "standard_system_servicedirs", attribute_names, attribute_values, error))
+ return FALSE;
+
+ if (push_element (parser, ELEMENT_STANDARD_SYSTEM_SERVICEDIRS) == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ if (!_dbus_get_standard_system_servicedirs (&dirs))
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ while ((link = _dbus_list_pop_first_link (&dirs)))
+ service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
+
+ return TRUE;
+ }
+ else if (element_type == ELEMENT_SERVICEDIR)
{
if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error))
return FALSE;
@@ -854,7 +831,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "include") == 0)
+ else if (element_type == ELEMENT_INCLUDE)
{
Element *e;
const char *if_selinux_enabled;
@@ -927,7 +904,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "policy") == 0)
+ else if (element_type == ELEMENT_POLICY)
{
Element *e;
const char *context;
@@ -1034,7 +1011,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "limit") == 0)
+ else if (element_type == ELEMENT_LIMIT)
{
Element *e;
const char *name;
@@ -1069,7 +1046,7 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
- else if (strcmp (element_name, "selinux") == 0)
+ else if (element_type == ELEMENT_SELINUX)
{
if (!check_no_attributes (parser, "selinux", attribute_names, attribute_values, error))
return FALSE;
@@ -1920,7 +1897,7 @@ bus_config_parser_end_element (BusConfigParser *parser,
return FALSE;
}
- n = element_type_to_name (t);
+ n = bus_config_parser_element_type_to_name (t);
_dbus_assert (n != NULL);
if (strcmp (n, element_name) != 0)
{
@@ -1949,13 +1926,14 @@ bus_config_parser_end_element (BusConfigParser *parser,
case ELEMENT_PIDFILE:
case ELEMENT_AUTH:
case ELEMENT_SERVICEDIR:
+ case ELEMENT_SERVICEHELPER:
case ELEMENT_INCLUDEDIR:
case ELEMENT_LIMIT:
if (!e->had_content)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"XML element <%s> was expected to have content inside it",
- element_type_to_name (e->type));
+ bus_config_parser_element_type_to_name (e->type));
return FALSE;
}
@@ -1975,6 +1953,7 @@ bus_config_parser_end_element (BusConfigParser *parser,
case ELEMENT_SELINUX:
case ELEMENT_ASSOCIATE:
case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
+ case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS:
break;
}
@@ -2088,6 +2067,40 @@ include_file (BusConfigParser *parser,
}
static dbus_bool_t
+servicehelper_path (BusConfigParser *parser,
+ const DBusString *filename,
+ DBusError *error)
+{
+ const char *filename_str;
+ char *servicehelper;
+ filename_str = _dbus_string_get_const_data (filename);
+
+ /* check if helper exists... */
+ if (!_dbus_file_exists (filename_str))
+ {
+ dbus_set_error (error, DBUS_ERROR_FILE_NOT_FOUND,
+ "setuid helper '%s'not found", filename_str);
+ return FALSE;
+ }
+
+ /* copy to avoid overwriting with NULL on OOM */
+ servicehelper = _dbus_strdup (filename_str);
+
+ /* check for OOM */
+ if (servicehelper == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ /* save the latest servicehelper only if not OOM */
+ dbus_free (parser->servicehelper);
+ parser->servicehelper = servicehelper;
+
+ return TRUE;
+}
+
+static dbus_bool_t
include_dir (BusConfigParser *parser,
const DBusString *dirname,
DBusError *error)
@@ -2223,6 +2236,7 @@ bus_config_parser_content (BusConfigParser *parser,
case ELEMENT_DENY:
case ELEMENT_FORK:
case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
+ case ELEMENT_STANDARD_SYSTEM_SERVICEDIRS:
case ELEMENT_SELINUX:
case ELEMENT_ASSOCIATE:
if (all_whitespace (content))
@@ -2231,7 +2245,7 @@ bus_config_parser_content (BusConfigParser *parser,
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"No text content expected inside XML element %s in configuration file",
- element_type_to_name (top_element_type (parser)));
+ bus_config_parser_element_type_to_name (top_element_type (parser)));
return FALSE;
}
@@ -2296,6 +2310,31 @@ bus_config_parser_content (BusConfigParser *parser,
}
break;
+ case ELEMENT_SERVICEHELPER:
+ {
+ DBusString full_path;
+
+ e->had_content = TRUE;
+
+ if (!_dbus_string_init (&full_path))
+ goto nomem;
+
+ if (!make_full_path (&parser->basedir, content, &full_path))
+ {
+ _dbus_string_free (&full_path);
+ goto nomem;
+ }
+
+ if (!servicehelper_path (parser, &full_path, error))
+ {
+ _dbus_string_free (&full_path);
+ return FALSE;
+ }
+
+ _dbus_string_free (&full_path);
+ }
+ break;
+
case ELEMENT_INCLUDEDIR:
{
DBusString full_path;
@@ -2407,6 +2446,7 @@ bus_config_parser_content (BusConfigParser *parser,
goto nomem;
}
+ /* _only_ extra session directories can be specified */
if (!service_dirs_append_unique_or_free (&parser->service_dirs, s))
{
_dbus_string_free (&full_path);
@@ -2460,7 +2500,7 @@ bus_config_parser_finished (BusConfigParser *parser,
{
dbus_set_error (error, DBUS_ERROR_FAILED,
"Element <%s> was not closed in configuration file",
- element_type_to_name (top_element_type (parser)));
+ bus_config_parser_element_type_to_name (top_element_type (parser)));
return FALSE;
}
@@ -2523,6 +2563,12 @@ bus_config_parser_get_pidfile (BusConfigParser *parser)
return parser->pidfile;
}
+const char *
+bus_config_parser_get_servicehelper (BusConfigParser *parser)
+{
+ return parser->servicehelper;
+}
+
BusPolicy*
bus_config_parser_steal_policy (BusConfigParser *parser)
{
@@ -3082,7 +3128,7 @@ process_test_equiv_subdir (const DBusString *test_base_dir,
}
-static const char *test_service_dir_matches[] =
+static const char *test_session_service_dir_matches[] =
{
#ifdef DBUS_UNIX
"/testusr/testlocal/testshare/dbus-1/services",
@@ -3124,7 +3170,7 @@ test_default_session_servicedirs (void)
_dbus_string_free (&progs);
return FALSE;
}
- test_service_dir_matches[1] = _dbus_string_get_const_data(&progs);
+ test_session_service_dir_matches[1] = _dbus_string_get_const_data(&progs);
}
#endif
dirs = NULL;
@@ -3168,7 +3214,7 @@ test_default_session_servicedirs (void)
while ((link = _dbus_list_pop_first_link (&dirs)))
{
printf (" test service dir: %s\n", (char *)link->data);
- if (test_service_dir_matches[i] == NULL)
+ if (test_session_service_dir_matches[i] == NULL)
{
printf ("more directories parsed than in match set\n");
dbus_free (link->data);
@@ -3177,12 +3223,12 @@ test_default_session_servicedirs (void)
return FALSE;
}
- if (strcmp (test_service_dir_matches[i],
+ if (strcmp (test_session_service_dir_matches[i],
(char *)link->data) != 0)
{
printf ("%s directory does not match %s in the match set\n",
(char *)link->data,
- test_service_dir_matches[i]);
+ test_session_service_dir_matches[i]);
dbus_free (link->data);
_dbus_list_free_link (link);
_dbus_string_free (&progs);
@@ -3195,10 +3241,10 @@ test_default_session_servicedirs (void)
_dbus_list_free_link (link);
}
- if (test_service_dir_matches[i] != NULL)
+ if (test_session_service_dir_matches[i] != NULL)
{
printf ("extra data %s in the match set was not matched\n",
- test_service_dir_matches[i]);
+ test_session_service_dir_matches[i]);
_dbus_string_free (&progs);
return FALSE;
@@ -3207,7 +3253,130 @@ test_default_session_servicedirs (void)
_dbus_string_free (&progs);
return TRUE;
}
-
+
+static const char *test_system_service_dir_matches[] =
+ {
+#ifdef DBUS_UNIX
+ "/testusr/testlocal/testshare/dbus-1/system-services",
+ "/testusr/testshare/dbus-1/system-services",
+#endif
+ DBUS_DATADIR"/dbus-1/system-services",
+ NULL
+ };
+
+static dbus_bool_t
+test_default_system_servicedirs (void)
+{
+ DBusList *dirs;
+ DBusList *link;
+ DBusString progs;
+ const char *common_progs;
+ int i;
+
+ /* 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
+ if (common_progs)
+ {
+ if (!_dbus_string_append (&progs, common_progs))
+ {
+ _dbus_string_free (&progs);
+ return FALSE;
+ }
+
+ if (!_dbus_string_append (&progs, "/dbus-1/system-services"))
+ {
+ _dbus_string_free (&progs);
+ return FALSE;
+ }
+ test_system_service_dir_matches[1] = _dbus_string_get_const_data(&progs);
+ }
+#endif
+ dirs = NULL;
+
+ printf ("Testing retrieving the default system service directories\n");
+ if (!_dbus_get_standard_system_servicedirs (&dirs))
+ _dbus_assert_not_reached ("couldn't get stardard dirs");
+
+ /* make sure our defaults end with share/dbus-1/system-service */
+ while ((link = _dbus_list_pop_first_link (&dirs)))
+ {
+ DBusString path;
+
+ printf (" default service dir: %s\n", (char *)link->data);
+ _dbus_string_init_const (&path, (char *)link->data);
+ if (!_dbus_string_ends_with_c_str (&path, "dbus-1/system-services"))
+ {
+ printf ("error with default system service directories\n");
+ dbus_free (link->data);
+ _dbus_list_free_link (link);
+ _dbus_string_free (&progs);
+ return FALSE;
+ }
+
+ dbus_free (link->data);
+ _dbus_list_free_link (link);
+ }
+
+#ifdef DBUS_UNIX
+ 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:"))
+ _dbus_assert_not_reached ("couldn't setenv XDG_DATA_DIRS");
+#endif
+ if (!_dbus_get_standard_system_servicedirs (&dirs))
+ _dbus_assert_not_reached ("couldn't get stardard dirs");
+
+ /* make sure we read and parse the env variable correctly */
+ i = 0;
+ while ((link = _dbus_list_pop_first_link (&dirs)))
+ {
+ printf (" test service dir: %s\n", (char *)link->data);
+ if (test_system_service_dir_matches[i] == NULL)
+ {
+ printf ("more directories parsed than in match set\n");
+ dbus_free (link->data);
+ _dbus_list_free_link (link);
+ _dbus_string_free (&progs);
+ return FALSE;
+ }
+
+ if (strcmp (test_system_service_dir_matches[i],
+ (char *)link->data) != 0)
+ {
+ printf ("%s directory does not match %s in the match set\n",
+ (char *)link->data,
+ test_system_service_dir_matches[i]);
+ dbus_free (link->data);
+ _dbus_list_free_link (link);
+ _dbus_string_free (&progs);
+ return FALSE;
+ }
+
+ ++i;
+
+ dbus_free (link->data);
+ _dbus_list_free_link (link);
+ }
+
+ if (test_system_service_dir_matches[i] != NULL)
+ {
+ printf ("extra data %s in the match set was not matched\n",
+ test_system_service_dir_matches[i]);
+
+ _dbus_string_free (&progs);
+ return FALSE;
+ }
+
+ _dbus_string_free (&progs);
+ return TRUE;
+}
+
dbus_bool_t
bus_config_parser_test (const DBusString *test_data_dir)
{
@@ -3221,6 +3390,9 @@ bus_config_parser_test (const DBusString *test_data_dir)
if (!test_default_session_servicedirs())
return FALSE;
+ if (!test_default_system_servicedirs())
+ return FALSE;
+
if (!process_test_valid_subdir (test_data_dir, "valid-config-files", VALID))
return FALSE;