1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* config-parser.c XML-library-agnostic configuration file parser
4 * Copyright (C) 2003 Red Hat, Inc.
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 #include "config-parser.h"
27 #include <dbus/dbus-list.h>
28 #include <dbus/dbus-internals.h>
52 /* we ignore policies for unknown groups/users */
66 unsigned int had_content : 1;
72 unsigned int ignore_missing : 1;
78 unsigned long gid_or_uid;
91 struct BusConfigParser
95 DBusString basedir; /**< Directory we resolve paths relative to */
97 DBusList *stack; /**< stack of Element */
99 char *user; /**< user to run as */
101 char *bus_type; /**< Message bus type */
103 DBusList *listen_on; /**< List of addresses to listen to */
105 DBusList *mechanisms; /**< Auth mechanisms */
107 DBusList *service_dirs; /**< Directories to look for services in */
109 BusPolicy *policy; /**< Security policy */
111 BusLimits limits; /**< Limits */
113 unsigned int fork : 1; /**< TRUE to fork into daemon mode */
119 element_type_to_name (ElementType type)
125 case ELEMENT_BUSCONFIG:
127 case ELEMENT_INCLUDE:
145 case ELEMENT_PIDFILE:
147 case ELEMENT_SERVICEDIR:
149 case ELEMENT_INCLUDEDIR:
155 _dbus_assert_not_reached ("bad element type");
161 push_element (BusConfigParser *parser,
166 _dbus_assert (type != ELEMENT_NONE);
168 e = dbus_new0 (Element, 1);
172 if (!_dbus_list_append (&parser->stack, e))
184 element_free (Element *e)
186 if (e->type == ELEMENT_LIMIT)
187 dbus_free (e->d.limit.name);
193 pop_element (BusConfigParser *parser)
197 e = _dbus_list_pop_last (&parser->stack);
203 peek_element (BusConfigParser *parser)
207 e = _dbus_list_get_last (&parser->stack);
213 top_element_type (BusConfigParser *parser)
217 e = _dbus_list_get_last (&parser->stack);
226 merge_included (BusConfigParser *parser,
227 BusConfigParser *included,
232 if (included->user != NULL)
234 dbus_free (parser->user);
235 parser->user = included->user;
236 included->user = NULL;
239 if (included->bus_type != NULL)
241 dbus_free (parser->bus_type);
242 parser->bus_type = included->bus_type;
243 included->bus_type = NULL;
249 if (included->pidfile != NULL)
251 dbus_free (parser->pidfile);
252 parser->pidfile = included->pidfile;
253 included->pidfile = NULL;
256 while ((link = _dbus_list_pop_first_link (&included->listen_on)))
257 _dbus_list_append_link (&parser->listen_on, link);
259 while ((link = _dbus_list_pop_first_link (&included->mechanisms)))
260 _dbus_list_append_link (&parser->mechanisms, link);
262 while ((link = _dbus_list_pop_first_link (&included->service_dirs)))
263 _dbus_list_append_link (&parser->service_dirs, link);
269 bus_config_parser_new (const DBusString *basedir)
271 BusConfigParser *parser;
273 parser = dbus_new0 (BusConfigParser, 1);
277 if (!_dbus_string_init (&parser->basedir))
283 if (((parser->policy = bus_policy_new ()) == NULL) ||
284 !_dbus_string_copy (basedir, 0, &parser->basedir, 0))
287 bus_policy_unref (parser->policy);
289 _dbus_string_free (&parser->basedir);
294 /* Make up some numbers! woot! */
295 parser->limits.max_incoming_bytes = _DBUS_ONE_MEGABYTE * 63;
296 parser->limits.max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 63;
297 parser->limits.max_message_size = _DBUS_ONE_MEGABYTE * 32;
299 #ifdef DBUS_BUILD_TESTS
300 parser->limits.activation_timeout = 6000; /* 6 seconds */
302 parser->limits.activation_timeout = 15000; /* 15 seconds */
305 /* Making this long risks making a DOS attack easier, but too short
306 * and legitimate auth will fail. If interactive auth (ask user for
307 * password) is allowed, then potentially it has to be quite long.
309 parser->limits.auth_timeout = 30000; /* 30 seconds */
311 parser->limits.max_incomplete_connections = 32;
312 parser->limits.max_connections_per_user = 128;
314 /* Note that max_completed_connections / max_connections_per_user
315 * is the number of users that would have to work together to
316 * DOS all the other users.
318 parser->limits.max_completed_connections = 1024;
320 parser->limits.max_pending_activations = 256;
321 parser->limits.max_services_per_connection = 256;
323 parser->refcount = 1;
329 bus_config_parser_ref (BusConfigParser *parser)
331 _dbus_assert (parser->refcount > 0);
333 parser->refcount += 1;
337 bus_config_parser_unref (BusConfigParser *parser)
339 _dbus_assert (parser->refcount > 0);
341 parser->refcount -= 1;
343 if (parser->refcount == 0)
345 while (parser->stack != NULL)
346 pop_element (parser);
348 dbus_free (parser->user);
349 dbus_free (parser->bus_type);
350 dbus_free (parser->pidfile);
352 _dbus_list_foreach (&parser->listen_on,
353 (DBusForeachFunction) dbus_free,
356 _dbus_list_clear (&parser->listen_on);
358 _dbus_list_foreach (&parser->service_dirs,
359 (DBusForeachFunction) dbus_free,
362 _dbus_list_clear (&parser->service_dirs);
364 _dbus_list_foreach (&parser->mechanisms,
365 (DBusForeachFunction) dbus_free,
368 _dbus_list_clear (&parser->mechanisms);
370 _dbus_string_free (&parser->basedir);
373 bus_policy_unref (parser->policy);
380 bus_config_parser_check_doctype (BusConfigParser *parser,
384 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
386 if (strcmp (doctype, "busconfig") != 0)
388 dbus_set_error (error,
390 "Configuration file has the wrong document type %s",
405 locate_attributes (BusConfigParser *parser,
406 const char *element_name,
407 const char **attribute_names,
408 const char **attribute_values,
410 const char *first_attribute_name,
411 const char **first_attribute_retloc,
419 LocateAttr attrs[MAX_ATTRS];
423 _dbus_assert (first_attribute_name != NULL);
424 _dbus_assert (first_attribute_retloc != NULL);
429 attrs[0].name = first_attribute_name;
430 attrs[0].retloc = first_attribute_retloc;
431 *first_attribute_retloc = NULL;
433 va_start (args, first_attribute_retloc);
435 name = va_arg (args, const char*);
436 retloc = va_arg (args, const char**);
440 _dbus_assert (retloc != NULL);
441 _dbus_assert (n_attrs < MAX_ATTRS);
443 attrs[n_attrs].name = name;
444 attrs[n_attrs].retloc = retloc;
448 name = va_arg (args, const char*);
449 retloc = va_arg (args, const char**);
458 while (attribute_names[i])
467 if (strcmp (attrs[j].name, attribute_names[i]) == 0)
469 retloc = attrs[j].retloc;
473 dbus_set_error (error, DBUS_ERROR_FAILED,
474 "Attribute \"%s\" repeated twice on the same <%s> element",
475 attrs[j].name, element_name);
480 *retloc = attribute_values[i];
489 dbus_set_error (error, DBUS_ERROR_FAILED,
490 "Attribute \"%s\" is invalid on <%s> element in this context",
491 attribute_names[i], element_name);
504 check_no_attributes (BusConfigParser *parser,
505 const char *element_name,
506 const char **attribute_names,
507 const char **attribute_values,
510 if (attribute_names[0] != NULL)
512 dbus_set_error (error, DBUS_ERROR_FAILED,
513 "Attribute \"%s\" is invalid on <%s> element in this context",
514 attribute_names[0], element_name);
522 start_busconfig_child (BusConfigParser *parser,
523 const char *element_name,
524 const char **attribute_names,
525 const char **attribute_values,
528 if (strcmp (element_name, "user") == 0)
530 if (!check_no_attributes (parser, "user", attribute_names, attribute_values, error))
533 if (push_element (parser, ELEMENT_USER) == NULL)
541 else if (strcmp (element_name, "type") == 0)
543 if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
546 if (push_element (parser, ELEMENT_TYPE) == NULL)
554 else if (strcmp (element_name, "fork") == 0)
556 if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
559 if (push_element (parser, ELEMENT_FORK) == NULL)
569 else if (strcmp (element_name, "pidfile") == 0)
571 if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
574 if (push_element (parser, ELEMENT_PIDFILE) == NULL)
582 else if (strcmp (element_name, "listen") == 0)
584 if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
587 if (push_element (parser, ELEMENT_LISTEN) == NULL)
595 else if (strcmp (element_name, "auth") == 0)
597 if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
600 if (push_element (parser, ELEMENT_AUTH) == NULL)
608 else if (strcmp (element_name, "includedir") == 0)
610 if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error))
613 if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL)
621 else if (strcmp (element_name, "servicedir") == 0)
623 if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error))
626 if (push_element (parser, ELEMENT_SERVICEDIR) == NULL)
634 else if (strcmp (element_name, "include") == 0)
637 const char *ignore_missing;
639 if ((e = push_element (parser, ELEMENT_INCLUDE)) == NULL)
645 e->d.include.ignore_missing = FALSE;
647 if (!locate_attributes (parser, "include",
651 "ignore_missing", &ignore_missing,
655 if (ignore_missing != NULL)
657 if (strcmp (ignore_missing, "yes") == 0)
658 e->d.include.ignore_missing = TRUE;
659 else if (strcmp (ignore_missing, "no") == 0)
660 e->d.include.ignore_missing = FALSE;
663 dbus_set_error (error, DBUS_ERROR_FAILED,
664 "ignore_missing attribute must have value \"yes\" or \"no\"");
671 else if (strcmp (element_name, "policy") == 0)
678 if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
684 e->d.policy.type = POLICY_IGNORED;
686 if (!locate_attributes (parser, "policy",
696 if (((context && user) ||
697 (context && group)) ||
699 !(context || user || group))
701 dbus_set_error (error, DBUS_ERROR_FAILED,
702 "<policy> element must have exactly one of (context|user|group) attributes");
708 if (strcmp (context, "default") == 0)
710 e->d.policy.type = POLICY_DEFAULT;
712 else if (strcmp (context, "mandatory") == 0)
714 e->d.policy.type = POLICY_MANDATORY;
718 dbus_set_error (error, DBUS_ERROR_FAILED,
719 "context attribute on <policy> must have the value \"default\" or \"mandatory\", not \"%s\"",
724 else if (user != NULL)
727 _dbus_string_init_const (&username, user);
729 if (_dbus_get_user_id (&username,
730 &e->d.policy.gid_or_uid))
731 e->d.policy.type = POLICY_USER;
733 _dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
736 else if (group != NULL)
738 DBusString group_name;
739 _dbus_string_init_const (&group_name, group);
741 if (_dbus_get_group_id (&group_name,
742 &e->d.policy.gid_or_uid))
743 e->d.policy.type = POLICY_GROUP;
745 _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
750 _dbus_assert_not_reached ("all <policy> attributes null and we didn't set error");
755 else if (strcmp (element_name, "limit") == 0)
760 if ((e = push_element (parser, ELEMENT_LIMIT)) == NULL)
766 if (!locate_attributes (parser, "limit",
776 dbus_set_error (error, DBUS_ERROR_FAILED,
777 "<limit> element must have a \"name\" attribute");
781 e->d.limit.name = _dbus_strdup (name);
782 if (e->d.limit.name == NULL)
792 dbus_set_error (error, DBUS_ERROR_FAILED,
793 "Element <%s> not allowed inside <%s> in configuration file",
794 element_name, "busconfig");
800 append_rule_from_element (BusConfigParser *parser,
801 const char *element_name,
802 const char **attribute_names,
803 const char **attribute_values,
811 const char *receive_from;
816 if (!locate_attributes (parser, element_name,
824 "receive_from", &receive_from,
830 if (!(send || receive || own || send_to || receive_from ||
833 dbus_set_error (error, DBUS_ERROR_FAILED,
834 "Element <%s> must have one or more attributes",
839 if (((send && own) ||
841 (send && receive_from) ||
846 (receive && send_to) ||
848 (receive && group)) ||
851 (own && receive_from) ||
855 ((send_to && receive_from) ||
857 (send_to && group)) ||
859 ((receive_from && user) ||
860 (receive_from && group)) ||
864 dbus_set_error (error, DBUS_ERROR_FAILED,
865 "Invalid combination of attributes on element <%s>, "
866 "only send/send_to or receive/receive_from may be paired",
873 /* In BusPolicyRule, NULL represents wildcard.
874 * In the config file, '*' represents it.
876 #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
880 rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow);
884 if (IS_WILDCARD (send))
886 if (IS_WILDCARD (send_to))
889 rule->d.send.message_name = _dbus_strdup (send);
890 rule->d.send.destination = _dbus_strdup (send_to);
891 if (send && rule->d.send.message_name == NULL)
893 if (send_to && rule->d.send.destination == NULL)
896 else if (receive || receive_from)
898 rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow);
902 if (IS_WILDCARD (receive))
905 if (IS_WILDCARD (receive_from))
908 rule->d.receive.message_name = _dbus_strdup (receive);
909 rule->d.receive.origin = _dbus_strdup (receive_from);
910 if (receive && rule->d.receive.message_name == NULL)
912 if (receive_from && rule->d.receive.origin == NULL)
917 rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow);
921 if (IS_WILDCARD (own))
924 rule->d.own.service_name = _dbus_strdup (own);
925 if (own && rule->d.own.service_name == NULL)
930 if (IS_WILDCARD (user))
932 rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
936 rule->d.user.uid = DBUS_UID_UNSET;
943 _dbus_string_init_const (&username, user);
945 if (_dbus_get_user_id (&username, &uid))
947 rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
951 rule->d.user.uid = uid;
955 _dbus_warn ("Unknown username \"%s\" on element <%s>\n",
962 if (IS_WILDCARD (group))
964 rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
968 rule->d.group.gid = DBUS_GID_UNSET;
972 DBusString groupname;
975 _dbus_string_init_const (&groupname, group);
977 if (_dbus_get_user_id (&groupname, &gid))
979 rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
983 rule->d.group.gid = gid;
987 _dbus_warn ("Unknown group \"%s\" on element <%s>\n",
988 group, element_name);
993 _dbus_assert_not_reached ("Did not handle some combination of attributes on <allow> or <deny>");
999 pe = peek_element (parser);
1000 _dbus_assert (pe != NULL);
1001 _dbus_assert (pe->type == ELEMENT_POLICY);
1003 switch (pe->d.policy.type)
1005 case POLICY_IGNORED:
1006 /* drop the rule on the floor */
1009 case POLICY_DEFAULT:
1010 if (!bus_policy_append_default_rule (parser->policy, rule))
1013 case POLICY_MANDATORY:
1014 if (!bus_policy_append_mandatory_rule (parser->policy, rule))
1018 if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1020 dbus_set_error (error, DBUS_ERROR_FAILED,
1021 "<%s> rule cannot be per-user because it has bus-global semantics",
1026 if (!bus_policy_append_user_rule (parser->policy, pe->d.policy.gid_or_uid,
1031 if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1033 dbus_set_error (error, DBUS_ERROR_FAILED,
1034 "<%s> rule cannot be per-group because it has bus-global semantics",
1039 if (!bus_policy_append_group_rule (parser->policy, pe->d.policy.gid_or_uid,
1045 bus_policy_rule_unref (rule);
1052 BUS_SET_OOM (error);
1055 bus_policy_rule_unref (rule);
1060 start_policy_child (BusConfigParser *parser,
1061 const char *element_name,
1062 const char **attribute_names,
1063 const char **attribute_values,
1066 if (strcmp (element_name, "allow") == 0)
1068 if (!append_rule_from_element (parser, element_name,
1069 attribute_names, attribute_values,
1073 if (push_element (parser, ELEMENT_ALLOW) == NULL)
1075 BUS_SET_OOM (error);
1081 else if (strcmp (element_name, "deny") == 0)
1083 if (!append_rule_from_element (parser, element_name,
1084 attribute_names, attribute_values,
1088 if (push_element (parser, ELEMENT_DENY) == NULL)
1090 BUS_SET_OOM (error);
1098 dbus_set_error (error, DBUS_ERROR_FAILED,
1099 "Element <%s> not allowed inside <%s> in configuration file",
1100 element_name, "policy");
1106 bus_config_parser_start_element (BusConfigParser *parser,
1107 const char *element_name,
1108 const char **attribute_names,
1109 const char **attribute_values,
1114 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1116 /* printf ("START: %s\n", element_name); */
1118 t = top_element_type (parser);
1120 if (t == ELEMENT_NONE)
1122 if (strcmp (element_name, "busconfig") == 0)
1124 if (!check_no_attributes (parser, "busconfig", attribute_names, attribute_values, error))
1127 if (push_element (parser, ELEMENT_BUSCONFIG) == NULL)
1129 BUS_SET_OOM (error);
1137 dbus_set_error (error, DBUS_ERROR_FAILED,
1138 "Unknown element <%s> at root of configuration file",
1143 else if (t == ELEMENT_BUSCONFIG)
1145 return start_busconfig_child (parser, element_name,
1146 attribute_names, attribute_values,
1149 else if (t == ELEMENT_POLICY)
1151 return start_policy_child (parser, element_name,
1152 attribute_names, attribute_values,
1157 dbus_set_error (error, DBUS_ERROR_FAILED,
1158 "Element <%s> is not allowed in this context",
1165 set_limit (BusConfigParser *parser,
1170 dbus_bool_t must_be_positive;
1171 dbus_bool_t must_be_int;
1173 must_be_int = FALSE;
1174 must_be_positive = FALSE;
1176 if (strcmp (name, "max_incoming_bytes") == 0)
1178 must_be_positive = TRUE;
1179 parser->limits.max_incoming_bytes = value;
1181 else if (strcmp (name, "max_outgoing_bytes") == 0)
1183 must_be_positive = TRUE;
1184 parser->limits.max_outgoing_bytes = value;
1186 else if (strcmp (name, "max_message_size") == 0)
1188 must_be_positive = TRUE;
1189 parser->limits.max_message_size = value;
1191 else if (strcmp (name, "activation_timeout") == 0)
1193 must_be_positive = TRUE;
1195 parser->limits.activation_timeout = value;
1197 else if (strcmp (name, "auth_timeout") == 0)
1199 must_be_positive = TRUE;
1201 parser->limits.auth_timeout = value;
1203 else if (strcmp (name, "max_completed_connections") == 0)
1205 must_be_positive = TRUE;
1207 parser->limits.max_completed_connections = value;
1209 else if (strcmp (name, "max_incomplete_connections") == 0)
1211 must_be_positive = TRUE;
1213 parser->limits.max_incomplete_connections = value;
1215 else if (strcmp (name, "max_connections_per_user") == 0)
1217 must_be_positive = TRUE;
1219 parser->limits.max_connections_per_user = value;
1221 else if (strcmp (name, "max_pending_activations") == 0)
1223 must_be_positive = TRUE;
1225 parser->limits.max_pending_activations = value;
1227 else if (strcmp (name, "max_services_per_connection") == 0)
1229 must_be_positive = TRUE;
1231 parser->limits.max_services_per_connection = value;
1235 dbus_set_error (error, DBUS_ERROR_FAILED,
1236 "There is no limit called \"%s\"\n",
1241 if (must_be_positive && value < 0)
1243 dbus_set_error (error, DBUS_ERROR_FAILED,
1244 "<limit name=\"%s\"> must be a positive number\n",
1250 (value < _DBUS_INT_MIN || value > _DBUS_INT_MAX))
1252 dbus_set_error (error, DBUS_ERROR_FAILED,
1253 "<limit name=\"%s\"> value is too large\n",
1262 bus_config_parser_end_element (BusConfigParser *parser,
1263 const char *element_name,
1270 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1272 /* printf ("END: %s\n", element_name); */
1274 t = top_element_type (parser);
1276 if (t == ELEMENT_NONE)
1278 /* should probably be an assertion failure but
1279 * being paranoid about XML parsers
1281 dbus_set_error (error, DBUS_ERROR_FAILED,
1282 "XML parser ended element with no element on the stack");
1286 n = element_type_to_name (t);
1287 _dbus_assert (n != NULL);
1288 if (strcmp (n, element_name) != 0)
1290 /* should probably be an assertion failure but
1291 * being paranoid about XML parsers
1293 dbus_set_error (error, DBUS_ERROR_FAILED,
1294 "XML element <%s> ended but topmost element on the stack was <%s>",
1299 e = peek_element (parser);
1300 _dbus_assert (e != NULL);
1305 _dbus_assert_not_reached ("element in stack has no type");
1308 case ELEMENT_INCLUDE:
1311 case ELEMENT_LISTEN:
1312 case ELEMENT_PIDFILE:
1314 case ELEMENT_SERVICEDIR:
1315 case ELEMENT_INCLUDEDIR:
1317 if (!e->had_content)
1319 dbus_set_error (error, DBUS_ERROR_FAILED,
1320 "XML element <%s> was expected to have content inside it",
1321 element_type_to_name (e->type));
1325 if (e->type == ELEMENT_LIMIT)
1327 if (!set_limit (parser, e->d.limit.name, e->d.limit.value,
1333 case ELEMENT_BUSCONFIG:
1334 case ELEMENT_POLICY:
1341 pop_element (parser);
1347 all_whitespace (const DBusString *str)
1351 _dbus_string_skip_white (str, 0, &i);
1353 return i == _dbus_string_get_length (str);
1357 make_full_path (const DBusString *basedir,
1358 const DBusString *filename,
1359 DBusString *full_path)
1361 if (_dbus_path_is_absolute (filename))
1363 return _dbus_string_copy (filename, 0, full_path, 0);
1367 if (!_dbus_string_copy (basedir, 0, full_path, 0))
1370 if (!_dbus_concat_dir_and_file (full_path, filename))
1378 include_file (BusConfigParser *parser,
1379 const DBusString *filename,
1380 dbus_bool_t ignore_missing,
1383 /* FIXME good test case for this would load each config file in the
1384 * test suite both alone, and as an include, and check
1385 * that the result is the same
1387 BusConfigParser *included;
1388 DBusError tmp_error;
1390 dbus_error_init (&tmp_error);
1391 included = bus_config_load (filename, &tmp_error);
1392 if (included == NULL)
1394 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
1396 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) &&
1399 dbus_error_free (&tmp_error);
1404 dbus_move_error (&tmp_error, error);
1410 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
1412 if (!merge_included (parser, included, error))
1414 bus_config_parser_unref (included);
1418 bus_config_parser_unref (included);
1424 include_dir (BusConfigParser *parser,
1425 const DBusString *dirname,
1428 DBusString filename;
1430 DBusError tmp_error;
1433 if (!_dbus_string_init (&filename))
1435 BUS_SET_OOM (error);
1441 dir = _dbus_directory_open (dirname, error);
1446 dbus_error_init (&tmp_error);
1447 while (_dbus_directory_get_next_file (dir, &filename, &tmp_error))
1449 DBusString full_path;
1451 if (!_dbus_string_init (&full_path))
1453 BUS_SET_OOM (error);
1457 if (!_dbus_string_copy (dirname, 0, &full_path, 0))
1459 BUS_SET_OOM (error);
1460 _dbus_string_free (&full_path);
1464 if (!_dbus_concat_dir_and_file (&full_path, &filename))
1466 BUS_SET_OOM (error);
1467 _dbus_string_free (&full_path);
1471 if (_dbus_string_ends_with_c_str (&full_path, ".conf"))
1473 if (!include_file (parser, &full_path, TRUE, error))
1475 _dbus_string_free (&full_path);
1480 _dbus_string_free (&full_path);
1483 if (dbus_error_is_set (&tmp_error))
1485 dbus_move_error (&tmp_error, error);
1492 _dbus_string_free (&filename);
1495 _dbus_directory_close (dir);
1501 bus_config_parser_content (BusConfigParser *parser,
1502 const DBusString *content,
1507 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1513 _dbus_string_get_const_data (content, &c_str);
1515 printf ("CONTENT %d bytes: %s\n", _dbus_string_get_length (content), c_str);
1519 e = peek_element (parser);
1522 dbus_set_error (error, DBUS_ERROR_FAILED,
1523 "Text content outside of any XML element in configuration file");
1526 else if (e->had_content)
1528 _dbus_assert_not_reached ("Element had multiple content blocks");
1532 switch (top_element_type (parser))
1535 _dbus_assert_not_reached ("element at top of stack has no type");
1538 case ELEMENT_BUSCONFIG:
1539 case ELEMENT_POLICY:
1543 if (all_whitespace (content))
1547 dbus_set_error (error, DBUS_ERROR_FAILED,
1548 "No text content expected inside XML element %s in configuration file",
1549 element_type_to_name (top_element_type (parser)));
1553 case ELEMENT_PIDFILE:
1557 e->had_content = TRUE;
1559 if (!_dbus_string_copy_data (content, &s))
1562 dbus_free (parser->pidfile);
1563 parser->pidfile = s;
1567 case ELEMENT_INCLUDE:
1569 DBusString full_path;
1571 e->had_content = TRUE;
1573 if (!_dbus_string_init (&full_path))
1576 if (!make_full_path (&parser->basedir, content, &full_path))
1578 _dbus_string_free (&full_path);
1582 if (!include_file (parser, &full_path,
1583 e->d.include.ignore_missing, error))
1585 _dbus_string_free (&full_path);
1589 _dbus_string_free (&full_path);
1593 case ELEMENT_INCLUDEDIR:
1595 DBusString full_path;
1597 e->had_content = TRUE;
1599 if (!_dbus_string_init (&full_path))
1602 if (!make_full_path (&parser->basedir, content, &full_path))
1604 _dbus_string_free (&full_path);
1608 if (!include_dir (parser, &full_path, error))
1610 _dbus_string_free (&full_path);
1614 _dbus_string_free (&full_path);
1622 e->had_content = TRUE;
1624 if (!_dbus_string_copy_data (content, &s))
1627 dbus_free (parser->user);
1636 e->had_content = TRUE;
1638 if (!_dbus_string_copy_data (content, &s))
1641 dbus_free (parser->bus_type);
1642 parser->bus_type = s;
1646 case ELEMENT_LISTEN:
1650 e->had_content = TRUE;
1652 if (!_dbus_string_copy_data (content, &s))
1655 if (!_dbus_list_append (&parser->listen_on,
1668 e->had_content = TRUE;
1670 if (!_dbus_string_copy_data (content, &s))
1673 if (!_dbus_list_append (&parser->mechanisms,
1682 case ELEMENT_SERVICEDIR:
1685 DBusString full_path;
1687 e->had_content = TRUE;
1689 if (!_dbus_string_init (&full_path))
1692 if (!make_full_path (&parser->basedir, content, &full_path))
1694 _dbus_string_free (&full_path);
1698 if (!_dbus_string_copy_data (&full_path, &s))
1700 _dbus_string_free (&full_path);
1704 if (!_dbus_list_append (&parser->service_dirs, s))
1706 _dbus_string_free (&full_path);
1711 _dbus_string_free (&full_path);
1719 e->had_content = TRUE;
1722 if (!_dbus_string_parse_int (content, 0, &val, NULL))
1724 dbus_set_error (error, DBUS_ERROR_FAILED,
1725 "<limit name=\"%s\"> element has invalid value (could not parse as integer)",
1730 e->d.limit.value = val;
1732 _dbus_verbose ("Loaded value %ld for limit %s\n",
1739 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1743 BUS_SET_OOM (error);
1748 bus_config_parser_finished (BusConfigParser *parser,
1751 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1753 if (parser->stack != NULL)
1755 dbus_set_error (error, DBUS_ERROR_FAILED,
1756 "Element <%s> was not closed in configuration file",
1757 element_type_to_name (top_element_type (parser)));
1762 if (parser->listen_on == NULL)
1764 dbus_set_error (error, DBUS_ERROR_FAILED,
1765 "Configuration file needs one or more <listen> elements giving addresses");
1773 bus_config_parser_get_user (BusConfigParser *parser)
1775 return parser->user;
1779 bus_config_parser_get_type (BusConfigParser *parser)
1781 return parser->bus_type;
1785 bus_config_parser_get_addresses (BusConfigParser *parser)
1787 return &parser->listen_on;
1791 bus_config_parser_get_mechanisms (BusConfigParser *parser)
1793 return &parser->mechanisms;
1797 bus_config_parser_get_service_dirs (BusConfigParser *parser)
1799 return &parser->service_dirs;
1803 bus_config_parser_get_fork (BusConfigParser *parser)
1805 return parser->fork;
1809 bus_config_parser_get_pidfile (BusConfigParser *parser)
1811 return parser->pidfile;
1815 bus_config_parser_steal_policy (BusConfigParser *parser)
1819 _dbus_assert (parser->policy != NULL); /* can only steal the policy 1 time */
1821 policy = parser->policy;
1823 parser->policy = NULL;
1828 /* Overwrite any limits that were set in the configuration file */
1830 bus_config_parser_get_limits (BusConfigParser *parser,
1833 *limits = parser->limits;
1836 #ifdef DBUS_BUILD_TESTS
1847 do_load (const DBusString *full_path,
1849 dbus_bool_t oom_possible)
1851 BusConfigParser *parser;
1854 dbus_error_init (&error);
1856 parser = bus_config_load (full_path, &error);
1859 _DBUS_ASSERT_ERROR_IS_SET (&error);
1862 dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
1864 _dbus_verbose ("Failed to load valid file due to OOM\n");
1865 dbus_error_free (&error);
1868 else if (validity == VALID)
1870 _dbus_warn ("Failed to load valid file but still had memory: %s\n",
1873 dbus_error_free (&error);
1878 dbus_error_free (&error);
1884 _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
1886 bus_config_parser_unref (parser);
1888 if (validity == INVALID)
1890 _dbus_warn ("Accepted invalid file\n");
1900 const DBusString *full_path;
1905 check_loader_oom_func (void *data)
1907 LoaderOomData *d = data;
1909 return do_load (d->full_path, d->validity, TRUE);
1913 process_test_subdir (const DBusString *test_base_dir,
1917 DBusString test_directory;
1918 DBusString filename;
1926 if (!_dbus_string_init (&test_directory))
1927 _dbus_assert_not_reached ("didn't allocate test_directory\n");
1929 _dbus_string_init_const (&filename, subdir);
1931 if (!_dbus_string_copy (test_base_dir, 0,
1932 &test_directory, 0))
1933 _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
1935 if (!_dbus_concat_dir_and_file (&test_directory, &filename))
1936 _dbus_assert_not_reached ("couldn't allocate full path");
1938 _dbus_string_free (&filename);
1939 if (!_dbus_string_init (&filename))
1940 _dbus_assert_not_reached ("didn't allocate filename string\n");
1942 dbus_error_init (&error);
1943 dir = _dbus_directory_open (&test_directory, &error);
1946 _dbus_warn ("Could not open %s: %s\n",
1947 _dbus_string_get_const_data (&test_directory),
1949 dbus_error_free (&error);
1953 printf ("Testing:\n");
1956 while (_dbus_directory_get_next_file (dir, &filename, &error))
1958 DBusString full_path;
1961 if (!_dbus_string_init (&full_path))
1962 _dbus_assert_not_reached ("couldn't init string");
1964 if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
1965 _dbus_assert_not_reached ("couldn't copy dir to full_path");
1967 if (!_dbus_concat_dir_and_file (&full_path, &filename))
1968 _dbus_assert_not_reached ("couldn't concat file to dir");
1970 if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
1972 _dbus_verbose ("Skipping non-.conf file %s\n",
1973 _dbus_string_get_const_data (&filename));
1974 _dbus_string_free (&full_path);
1978 printf (" %s\n", _dbus_string_get_const_data (&filename));
1980 _dbus_verbose (" expecting %s\n",
1981 validity == VALID ? "valid" :
1982 (validity == INVALID ? "invalid" :
1983 (validity == UNKNOWN ? "unknown" : "???")));
1985 d.full_path = &full_path;
1986 d.validity = validity;
1987 if (!_dbus_test_oom_handling ("config-loader", check_loader_oom_func, &d))
1988 _dbus_assert_not_reached ("test failed");
1990 _dbus_string_free (&full_path);
1993 if (dbus_error_is_set (&error))
1995 _dbus_warn ("Could not get next file in %s: %s\n",
1996 _dbus_string_get_const_data (&test_directory),
1998 dbus_error_free (&error);
2007 _dbus_directory_close (dir);
2008 _dbus_string_free (&test_directory);
2009 _dbus_string_free (&filename);
2015 bus_config_parser_test (const DBusString *test_data_dir)
2017 if (test_data_dir == NULL ||
2018 _dbus_string_get_length (test_data_dir) == 0)
2020 printf ("No test data\n");
2024 if (!process_test_subdir (test_data_dir, "valid-config-files", VALID))
2030 #endif /* DBUS_BUILD_TESTS */