1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* config-parser.c XML-library-agnostic configuration file parser
4 * Copyright (C) 2003, 2004 Red Hat, Inc.
6 * Licensed under the Academic Free License version 2.1
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"
28 #include <dbus/dbus-list.h>
29 #include <dbus/dbus-internals.h>
55 /* we ignore policies for unknown groups/users */
70 unsigned int had_content : 1;
76 unsigned int ignore_missing : 1;
77 unsigned int selinux_root_relative : 1;
83 unsigned long gid_uid_or_at_console;
97 * Parser for bus configuration file.
99 struct BusConfigParser
101 int refcount; /**< Reference count */
103 DBusString basedir; /**< Directory we resolve paths relative to */
105 DBusList *stack; /**< stack of Element */
107 char *user; /**< user to run as */
109 char *bus_type; /**< Message bus type */
111 DBusList *listen_on; /**< List of addresses to listen to */
113 DBusList *mechanisms; /**< Auth mechanisms */
115 DBusList *service_dirs; /**< Directories to look for services in */
117 BusPolicy *policy; /**< Security policy */
119 BusLimits limits; /**< Limits */
121 char *pidfile; /**< PID file */
123 DBusList *included_files; /**< Included files stack */
125 DBusHashTable *service_sid_table; /**< Map service names to SELinux contexts */
127 unsigned int fork : 1; /**< TRUE to fork into daemon mode */
129 unsigned int is_toplevel : 1; /**< FALSE if we are a sub-config-file inside another one */
133 element_type_to_name (ElementType type)
139 case ELEMENT_BUSCONFIG:
141 case ELEMENT_INCLUDE:
159 case ELEMENT_PIDFILE:
161 case ELEMENT_SERVICEDIR:
163 case ELEMENT_INCLUDEDIR:
167 case ELEMENT_SELINUX:
169 case ELEMENT_ASSOCIATE:
173 _dbus_assert_not_reached ("bad element type");
179 push_element (BusConfigParser *parser,
184 _dbus_assert (type != ELEMENT_NONE);
186 e = dbus_new0 (Element, 1);
190 if (!_dbus_list_append (&parser->stack, e))
202 element_free (Element *e)
204 if (e->type == ELEMENT_LIMIT)
205 dbus_free (e->d.limit.name);
211 pop_element (BusConfigParser *parser)
215 e = _dbus_list_pop_last (&parser->stack);
221 peek_element (BusConfigParser *parser)
225 e = _dbus_list_get_last (&parser->stack);
231 top_element_type (BusConfigParser *parser)
235 e = _dbus_list_get_last (&parser->stack);
244 merge_included (BusConfigParser *parser,
245 BusConfigParser *included,
249 DBusHashTable *table;
251 if (!bus_policy_merge (parser->policy,
258 table = bus_selinux_id_table_union (parser->service_sid_table,
259 included->service_sid_table);
266 _dbus_hash_table_unref (parser->service_sid_table);
267 parser->service_sid_table = table;
269 if (included->user != NULL)
271 dbus_free (parser->user);
272 parser->user = included->user;
273 included->user = NULL;
276 if (included->bus_type != NULL)
278 dbus_free (parser->bus_type);
279 parser->bus_type = included->bus_type;
280 included->bus_type = NULL;
286 if (included->pidfile != NULL)
288 dbus_free (parser->pidfile);
289 parser->pidfile = included->pidfile;
290 included->pidfile = NULL;
293 while ((link = _dbus_list_pop_first_link (&included->listen_on)))
294 _dbus_list_append_link (&parser->listen_on, link);
296 while ((link = _dbus_list_pop_first_link (&included->mechanisms)))
297 _dbus_list_append_link (&parser->mechanisms, link);
299 while ((link = _dbus_list_pop_first_link (&included->service_dirs)))
300 _dbus_list_append_link (&parser->service_dirs, link);
306 seen_include (BusConfigParser *parser,
307 const DBusString *file)
311 iter = parser->included_files;
314 if (! strcmp (_dbus_string_get_const_data (file), iter->data))
317 iter = _dbus_list_get_next_link (&parser->included_files, iter);
324 bus_config_parser_new (const DBusString *basedir,
325 dbus_bool_t is_toplevel,
326 const BusConfigParser *parent)
328 BusConfigParser *parser;
330 parser = dbus_new0 (BusConfigParser, 1);
334 parser->is_toplevel = !!is_toplevel;
336 if (!_dbus_string_init (&parser->basedir))
342 if (((parser->policy = bus_policy_new ()) == NULL) ||
343 !_dbus_string_copy (basedir, 0, &parser->basedir, 0) ||
344 ((parser->service_sid_table = bus_selinux_id_table_new ()) == NULL))
347 bus_policy_unref (parser->policy);
349 _dbus_string_free (&parser->basedir);
357 /* Initialize the parser's limits from the parent. */
358 parser->limits = parent->limits;
360 /* Use the parent's list of included_files to avoid
361 circular inclusions. */
362 parser->included_files = parent->included_files;
367 /* Make up some numbers! woot! */
368 parser->limits.max_incoming_bytes = _DBUS_ONE_MEGABYTE * 63;
369 parser->limits.max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 63;
370 parser->limits.max_message_size = _DBUS_ONE_MEGABYTE * 32;
372 /* Making this long means the user has to wait longer for an error
373 * message if something screws up, but making it too short means
374 * they might see a false failure.
376 parser->limits.activation_timeout = 25000; /* 25 seconds */
378 /* Making this long risks making a DOS attack easier, but too short
379 * and legitimate auth will fail. If interactive auth (ask user for
380 * password) is allowed, then potentially it has to be quite long.
382 parser->limits.auth_timeout = 30000; /* 30 seconds */
384 parser->limits.max_incomplete_connections = 32;
385 parser->limits.max_connections_per_user = 128;
387 /* Note that max_completed_connections / max_connections_per_user
388 * is the number of users that would have to work together to
389 * DOS all the other users.
391 parser->limits.max_completed_connections = 1024;
393 parser->limits.max_pending_activations = 256;
394 parser->limits.max_services_per_connection = 256;
396 parser->limits.max_match_rules_per_connection = 128;
398 parser->limits.reply_timeout = 5 * 60 * 1000; /* 5 minutes */
399 parser->limits.max_replies_per_connection = 32;
402 parser->refcount = 1;
408 bus_config_parser_ref (BusConfigParser *parser)
410 _dbus_assert (parser->refcount > 0);
412 parser->refcount += 1;
418 bus_config_parser_unref (BusConfigParser *parser)
420 _dbus_assert (parser->refcount > 0);
422 parser->refcount -= 1;
424 if (parser->refcount == 0)
426 while (parser->stack != NULL)
427 pop_element (parser);
429 dbus_free (parser->user);
430 dbus_free (parser->bus_type);
431 dbus_free (parser->pidfile);
433 _dbus_list_foreach (&parser->listen_on,
434 (DBusForeachFunction) dbus_free,
437 _dbus_list_clear (&parser->listen_on);
439 _dbus_list_foreach (&parser->service_dirs,
440 (DBusForeachFunction) dbus_free,
443 _dbus_list_clear (&parser->service_dirs);
445 _dbus_list_foreach (&parser->mechanisms,
446 (DBusForeachFunction) dbus_free,
449 _dbus_list_clear (&parser->mechanisms);
451 _dbus_string_free (&parser->basedir);
454 bus_policy_unref (parser->policy);
456 if (parser->service_sid_table)
457 _dbus_hash_table_unref (parser->service_sid_table);
464 bus_config_parser_check_doctype (BusConfigParser *parser,
468 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
470 if (strcmp (doctype, "busconfig") != 0)
472 dbus_set_error (error,
474 "Configuration file has the wrong document type %s",
489 locate_attributes (BusConfigParser *parser,
490 const char *element_name,
491 const char **attribute_names,
492 const char **attribute_values,
494 const char *first_attribute_name,
495 const char **first_attribute_retloc,
503 LocateAttr attrs[MAX_ATTRS];
507 _dbus_assert (first_attribute_name != NULL);
508 _dbus_assert (first_attribute_retloc != NULL);
513 attrs[0].name = first_attribute_name;
514 attrs[0].retloc = first_attribute_retloc;
515 *first_attribute_retloc = NULL;
517 va_start (args, first_attribute_retloc);
519 name = va_arg (args, const char*);
520 retloc = va_arg (args, const char**);
524 _dbus_assert (retloc != NULL);
525 _dbus_assert (n_attrs < MAX_ATTRS);
527 attrs[n_attrs].name = name;
528 attrs[n_attrs].retloc = retloc;
532 name = va_arg (args, const char*);
533 retloc = va_arg (args, const char**);
542 while (attribute_names[i])
551 if (strcmp (attrs[j].name, attribute_names[i]) == 0)
553 retloc = attrs[j].retloc;
557 dbus_set_error (error, DBUS_ERROR_FAILED,
558 "Attribute \"%s\" repeated twice on the same <%s> element",
559 attrs[j].name, element_name);
564 *retloc = attribute_values[i];
573 dbus_set_error (error, DBUS_ERROR_FAILED,
574 "Attribute \"%s\" is invalid on <%s> element in this context",
575 attribute_names[i], element_name);
588 check_no_attributes (BusConfigParser *parser,
589 const char *element_name,
590 const char **attribute_names,
591 const char **attribute_values,
594 if (attribute_names[0] != NULL)
596 dbus_set_error (error, DBUS_ERROR_FAILED,
597 "Attribute \"%s\" is invalid on <%s> element in this context",
598 attribute_names[0], element_name);
606 start_busconfig_child (BusConfigParser *parser,
607 const char *element_name,
608 const char **attribute_names,
609 const char **attribute_values,
612 if (strcmp (element_name, "user") == 0)
614 if (!check_no_attributes (parser, "user", attribute_names, attribute_values, error))
617 if (push_element (parser, ELEMENT_USER) == NULL)
625 else if (strcmp (element_name, "type") == 0)
627 if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
630 if (push_element (parser, ELEMENT_TYPE) == NULL)
638 else if (strcmp (element_name, "fork") == 0)
640 if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
643 if (push_element (parser, ELEMENT_FORK) == NULL)
653 else if (strcmp (element_name, "pidfile") == 0)
655 if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
658 if (push_element (parser, ELEMENT_PIDFILE) == NULL)
666 else if (strcmp (element_name, "listen") == 0)
668 if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
671 if (push_element (parser, ELEMENT_LISTEN) == NULL)
679 else if (strcmp (element_name, "auth") == 0)
681 if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
684 if (push_element (parser, ELEMENT_AUTH) == NULL)
692 else if (strcmp (element_name, "includedir") == 0)
694 if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error))
697 if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL)
705 else if (strcmp (element_name, "servicedir") == 0)
707 if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error))
710 if (push_element (parser, ELEMENT_SERVICEDIR) == NULL)
718 else if (strcmp (element_name, "include") == 0)
721 const char *ignore_missing;
722 const char *selinux_root_relative;
724 if ((e = push_element (parser, ELEMENT_INCLUDE)) == NULL)
730 e->d.include.ignore_missing = FALSE;
731 e->d.include.selinux_root_relative = FALSE;
733 if (!locate_attributes (parser, "include",
737 "ignore_missing", &ignore_missing,
738 "selinux_root_relative", &selinux_root_relative,
742 if (ignore_missing != NULL)
744 if (strcmp (ignore_missing, "yes") == 0)
745 e->d.include.ignore_missing = TRUE;
746 else if (strcmp (ignore_missing, "no") == 0)
747 e->d.include.ignore_missing = FALSE;
750 dbus_set_error (error, DBUS_ERROR_FAILED,
751 "ignore_missing attribute must have value \"yes\" or \"no\"");
756 if (selinux_root_relative != NULL)
758 if (strcmp (selinux_root_relative, "yes") == 0)
759 e->d.include.selinux_root_relative = TRUE;
760 else if (strcmp (selinux_root_relative, "no") == 0)
761 e->d.include.selinux_root_relative = FALSE;
764 dbus_set_error (error, DBUS_ERROR_FAILED,
765 "selinux_root_relative attribute must have value"
766 " \"yes\" or \"no\"");
773 else if (strcmp (element_name, "policy") == 0)
779 const char *at_console;
781 if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
787 e->d.policy.type = POLICY_IGNORED;
789 if (!locate_attributes (parser, "policy",
796 "at_console", &at_console,
800 if (((context && user) ||
801 (context && group) ||
802 (context && at_console)) ||
804 (user && at_console)) ||
805 (group && at_console) ||
806 !(context || user || group || at_console))
808 dbus_set_error (error, DBUS_ERROR_FAILED,
809 "<policy> element must have exactly one of (context|user|group|at_console) attributes");
815 if (strcmp (context, "default") == 0)
817 e->d.policy.type = POLICY_DEFAULT;
819 else if (strcmp (context, "mandatory") == 0)
821 e->d.policy.type = POLICY_MANDATORY;
825 dbus_set_error (error, DBUS_ERROR_FAILED,
826 "context attribute on <policy> must have the value \"default\" or \"mandatory\", not \"%s\"",
831 else if (user != NULL)
834 _dbus_string_init_const (&username, user);
836 if (_dbus_get_user_id (&username,
837 &e->d.policy.gid_uid_or_at_console))
838 e->d.policy.type = POLICY_USER;
840 _dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
843 else if (group != NULL)
845 DBusString group_name;
846 _dbus_string_init_const (&group_name, group);
848 if (_dbus_get_group_id (&group_name,
849 &e->d.policy.gid_uid_or_at_console))
850 e->d.policy.type = POLICY_GROUP;
852 _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
855 else if (at_console != NULL)
858 t = (strcmp (at_console, "true") == 0);
859 if (t || strcmp (at_console, "false") == 0)
861 e->d.policy.gid_uid_or_at_console = t;
862 e->d.policy.type = POLICY_CONSOLE;
866 dbus_set_error (error, DBUS_ERROR_FAILED,
867 "Unknown value \"%s\" for at_console in message bus configuration file",
875 _dbus_assert_not_reached ("all <policy> attributes null and we didn't set error");
880 else if (strcmp (element_name, "limit") == 0)
885 if ((e = push_element (parser, ELEMENT_LIMIT)) == NULL)
891 if (!locate_attributes (parser, "limit",
901 dbus_set_error (error, DBUS_ERROR_FAILED,
902 "<limit> element must have a \"name\" attribute");
906 e->d.limit.name = _dbus_strdup (name);
907 if (e->d.limit.name == NULL)
915 else if (strcmp (element_name, "selinux") == 0)
917 if (!check_no_attributes (parser, "selinux", attribute_names, attribute_values, error))
920 if (push_element (parser, ELEMENT_SELINUX) == NULL)
930 dbus_set_error (error, DBUS_ERROR_FAILED,
931 "Element <%s> not allowed inside <%s> in configuration file",
932 element_name, "busconfig");
938 append_rule_from_element (BusConfigParser *parser,
939 const char *element_name,
940 const char **attribute_names,
941 const char **attribute_values,
945 const char *send_interface;
946 const char *send_member;
947 const char *send_error;
948 const char *send_destination;
949 const char *send_path;
950 const char *send_type;
951 const char *receive_interface;
952 const char *receive_member;
953 const char *receive_error;
954 const char *receive_sender;
955 const char *receive_path;
956 const char *receive_type;
957 const char *eavesdrop;
958 const char *send_requested_reply;
959 const char *receive_requested_reply;
966 if (!locate_attributes (parser, element_name,
970 "send_interface", &send_interface,
971 "send_member", &send_member,
972 "send_error", &send_error,
973 "send_destination", &send_destination,
974 "send_path", &send_path,
975 "send_type", &send_type,
976 "receive_interface", &receive_interface,
977 "receive_member", &receive_member,
978 "receive_error", &receive_error,
979 "receive_sender", &receive_sender,
980 "receive_path", &receive_path,
981 "receive_type", &receive_type,
982 "eavesdrop", &eavesdrop,
983 "send_requested_reply", &send_requested_reply,
984 "receive_requested_reply", &receive_requested_reply,
991 if (!(send_interface || send_member || send_error || send_destination ||
992 send_type || send_path ||
993 receive_interface || receive_member || receive_error || receive_sender ||
994 receive_type || receive_path || eavesdrop ||
995 send_requested_reply || receive_requested_reply ||
996 own || user || group))
998 dbus_set_error (error, DBUS_ERROR_FAILED,
999 "Element <%s> must have one or more attributes",
1004 if ((send_member && (send_interface == NULL && send_path == NULL)) ||
1005 (receive_member && (receive_interface == NULL && receive_path == NULL)))
1007 dbus_set_error (error, DBUS_ERROR_FAILED,
1008 "On element <%s>, if you specify a member you must specify an interface or a path. Keep in mind that not all messages have an interface field.",
1013 /* Allowed combinations of elements are:
1015 * base, must be all send or all receive:
1018 * interface + member
1021 * base send_ can combine with send_destination, send_path, send_type, send_requested_reply
1022 * base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop
1024 * user, group, own must occur alone
1026 * Pretty sure the below stuff is broken, FIXME think about it more.
1029 if (((send_interface && send_error) ||
1030 (send_interface && receive_interface) ||
1031 (send_interface && receive_member) ||
1032 (send_interface && receive_error) ||
1033 (send_interface && receive_sender) ||
1034 (send_interface && eavesdrop) ||
1035 (send_interface && receive_requested_reply) ||
1036 (send_interface && own) ||
1037 (send_interface && user) ||
1038 (send_interface && group)) ||
1040 ((send_member && send_error) ||
1041 (send_member && receive_interface) ||
1042 (send_member && receive_member) ||
1043 (send_member && receive_error) ||
1044 (send_member && receive_sender) ||
1045 (send_member && eavesdrop) ||
1046 (send_member && receive_requested_reply) ||
1047 (send_member && own) ||
1048 (send_member && user) ||
1049 (send_member && group)) ||
1051 ((send_error && receive_interface) ||
1052 (send_error && receive_member) ||
1053 (send_error && receive_error) ||
1054 (send_error && receive_sender) ||
1055 (send_error && eavesdrop) ||
1056 (send_error && receive_requested_reply) ||
1057 (send_error && own) ||
1058 (send_error && user) ||
1059 (send_error && group)) ||
1061 ((send_destination && receive_interface) ||
1062 (send_destination && receive_member) ||
1063 (send_destination && receive_error) ||
1064 (send_destination && receive_sender) ||
1065 (send_destination && eavesdrop) ||
1066 (send_destination && receive_requested_reply) ||
1067 (send_destination && own) ||
1068 (send_destination && user) ||
1069 (send_destination && group)) ||
1071 ((send_type && receive_interface) ||
1072 (send_type && receive_member) ||
1073 (send_type && receive_error) ||
1074 (send_type && receive_sender) ||
1075 (send_type && eavesdrop) ||
1076 (send_type && receive_requested_reply) ||
1077 (send_type && own) ||
1078 (send_type && user) ||
1079 (send_type && group)) ||
1081 ((send_path && receive_interface) ||
1082 (send_path && receive_member) ||
1083 (send_path && receive_error) ||
1084 (send_path && receive_sender) ||
1085 (send_path && eavesdrop) ||
1086 (send_path && receive_requested_reply) ||
1087 (send_path && own) ||
1088 (send_path && user) ||
1089 (send_path && group)) ||
1091 ((send_requested_reply && receive_interface) ||
1092 (send_requested_reply && receive_member) ||
1093 (send_requested_reply && receive_error) ||
1094 (send_requested_reply && receive_sender) ||
1095 (send_requested_reply && eavesdrop) ||
1096 (send_requested_reply && receive_requested_reply) ||
1097 (send_requested_reply && own) ||
1098 (send_requested_reply && user) ||
1099 (send_requested_reply && group)) ||
1101 ((receive_interface && receive_error) ||
1102 (receive_interface && own) ||
1103 (receive_interface && user) ||
1104 (receive_interface && group)) ||
1106 ((receive_member && receive_error) ||
1107 (receive_member && own) ||
1108 (receive_member && user) ||
1109 (receive_member && group)) ||
1111 ((receive_error && own) ||
1112 (receive_error && user) ||
1113 (receive_error && group)) ||
1115 ((eavesdrop && own) ||
1116 (eavesdrop && user) ||
1117 (eavesdrop && group)) ||
1119 ((receive_requested_reply && own) ||
1120 (receive_requested_reply && user) ||
1121 (receive_requested_reply && group)) ||
1128 dbus_set_error (error, DBUS_ERROR_FAILED,
1129 "Invalid combination of attributes on element <%s>",
1136 /* In BusPolicyRule, NULL represents wildcard.
1137 * In the config file, '*' represents it.
1139 #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
1141 if (send_interface || send_member || send_error || send_destination ||
1142 send_path || send_type || send_requested_reply)
1146 if (IS_WILDCARD (send_interface))
1147 send_interface = NULL;
1148 if (IS_WILDCARD (send_member))
1150 if (IS_WILDCARD (send_error))
1152 if (IS_WILDCARD (send_destination))
1153 send_destination = NULL;
1154 if (IS_WILDCARD (send_path))
1156 if (IS_WILDCARD (send_type))
1159 message_type = DBUS_MESSAGE_TYPE_INVALID;
1160 if (send_type != NULL)
1162 message_type = dbus_message_type_from_string (send_type);
1163 if (message_type == DBUS_MESSAGE_TYPE_INVALID)
1165 dbus_set_error (error, DBUS_ERROR_FAILED,
1166 "Bad message type \"%s\"",
1172 if (send_requested_reply &&
1173 !(strcmp (send_requested_reply, "true") == 0 ||
1174 strcmp (send_requested_reply, "false") == 0))
1176 dbus_set_error (error, DBUS_ERROR_FAILED,
1177 "Bad value \"%s\" for %s attribute, must be true or false",
1178 "send_requested_reply", send_requested_reply);
1182 rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow);
1186 if (send_requested_reply)
1187 rule->d.send.requested_reply = (strcmp (send_requested_reply, "true") == 0);
1189 rule->d.send.message_type = message_type;
1190 rule->d.send.path = _dbus_strdup (send_path);
1191 rule->d.send.interface = _dbus_strdup (send_interface);
1192 rule->d.send.member = _dbus_strdup (send_member);
1193 rule->d.send.error = _dbus_strdup (send_error);
1194 rule->d.send.destination = _dbus_strdup (send_destination);
1195 if (send_path && rule->d.send.path == NULL)
1197 if (send_interface && rule->d.send.interface == NULL)
1199 if (send_member && rule->d.send.member == NULL)
1201 if (send_error && rule->d.send.error == NULL)
1203 if (send_destination && rule->d.send.destination == NULL)
1206 else if (receive_interface || receive_member || receive_error || receive_sender ||
1207 receive_path || receive_type || eavesdrop || receive_requested_reply)
1211 if (IS_WILDCARD (receive_interface))
1212 receive_interface = NULL;
1213 if (IS_WILDCARD (receive_member))
1214 receive_member = NULL;
1215 if (IS_WILDCARD (receive_error))
1216 receive_error = NULL;
1217 if (IS_WILDCARD (receive_sender))
1218 receive_sender = NULL;
1219 if (IS_WILDCARD (receive_path))
1220 receive_path = NULL;
1221 if (IS_WILDCARD (receive_type))
1222 receive_type = NULL;
1224 message_type = DBUS_MESSAGE_TYPE_INVALID;
1225 if (receive_type != NULL)
1227 message_type = dbus_message_type_from_string (receive_type);
1228 if (message_type == DBUS_MESSAGE_TYPE_INVALID)
1230 dbus_set_error (error, DBUS_ERROR_FAILED,
1231 "Bad message type \"%s\"",
1239 !(strcmp (eavesdrop, "true") == 0 ||
1240 strcmp (eavesdrop, "false") == 0))
1242 dbus_set_error (error, DBUS_ERROR_FAILED,
1243 "Bad value \"%s\" for %s attribute, must be true or false",
1244 "eavesdrop", eavesdrop);
1248 if (receive_requested_reply &&
1249 !(strcmp (receive_requested_reply, "true") == 0 ||
1250 strcmp (receive_requested_reply, "false") == 0))
1252 dbus_set_error (error, DBUS_ERROR_FAILED,
1253 "Bad value \"%s\" for %s attribute, must be true or false",
1254 "receive_requested_reply", receive_requested_reply);
1258 rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow);
1263 rule->d.receive.eavesdrop = (strcmp (eavesdrop, "true") == 0);
1265 if (receive_requested_reply)
1266 rule->d.receive.requested_reply = (strcmp (receive_requested_reply, "true") == 0);
1268 rule->d.receive.message_type = message_type;
1269 rule->d.receive.path = _dbus_strdup (receive_path);
1270 rule->d.receive.interface = _dbus_strdup (receive_interface);
1271 rule->d.receive.member = _dbus_strdup (receive_member);
1272 rule->d.receive.error = _dbus_strdup (receive_error);
1273 rule->d.receive.origin = _dbus_strdup (receive_sender);
1275 if (receive_path && rule->d.receive.path == NULL)
1277 if (receive_interface && rule->d.receive.interface == NULL)
1279 if (receive_member && rule->d.receive.member == NULL)
1281 if (receive_error && rule->d.receive.error == NULL)
1283 if (receive_sender && rule->d.receive.origin == NULL)
1288 rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow);
1292 if (IS_WILDCARD (own))
1295 rule->d.own.service_name = _dbus_strdup (own);
1296 if (own && rule->d.own.service_name == NULL)
1301 if (IS_WILDCARD (user))
1303 rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
1307 rule->d.user.uid = DBUS_UID_UNSET;
1311 DBusString username;
1314 _dbus_string_init_const (&username, user);
1316 if (_dbus_get_user_id (&username, &uid))
1318 rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
1322 rule->d.user.uid = uid;
1326 _dbus_warn ("Unknown username \"%s\" on element <%s>\n",
1327 user, element_name);
1333 if (IS_WILDCARD (group))
1335 rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
1339 rule->d.group.gid = DBUS_GID_UNSET;
1343 DBusString groupname;
1346 _dbus_string_init_const (&groupname, group);
1348 if (_dbus_get_user_id (&groupname, &gid))
1350 rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
1354 rule->d.group.gid = gid;
1358 _dbus_warn ("Unknown group \"%s\" on element <%s>\n",
1359 group, element_name);
1364 _dbus_assert_not_reached ("Did not handle some combination of attributes on <allow> or <deny>");
1370 pe = peek_element (parser);
1371 _dbus_assert (pe != NULL);
1372 _dbus_assert (pe->type == ELEMENT_POLICY);
1374 switch (pe->d.policy.type)
1376 case POLICY_IGNORED:
1377 /* drop the rule on the floor */
1380 case POLICY_DEFAULT:
1381 if (!bus_policy_append_default_rule (parser->policy, rule))
1384 case POLICY_MANDATORY:
1385 if (!bus_policy_append_mandatory_rule (parser->policy, rule))
1389 if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1391 dbus_set_error (error, DBUS_ERROR_FAILED,
1392 "<%s> rule cannot be per-user because it has bus-global semantics",
1397 if (!bus_policy_append_user_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
1402 if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1404 dbus_set_error (error, DBUS_ERROR_FAILED,
1405 "<%s> rule cannot be per-group because it has bus-global semantics",
1410 if (!bus_policy_append_group_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
1416 case POLICY_CONSOLE:
1417 if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
1423 bus_policy_rule_unref (rule);
1430 BUS_SET_OOM (error);
1433 bus_policy_rule_unref (rule);
1438 start_policy_child (BusConfigParser *parser,
1439 const char *element_name,
1440 const char **attribute_names,
1441 const char **attribute_values,
1444 if (strcmp (element_name, "allow") == 0)
1446 if (!append_rule_from_element (parser, element_name,
1447 attribute_names, attribute_values,
1451 if (push_element (parser, ELEMENT_ALLOW) == NULL)
1453 BUS_SET_OOM (error);
1459 else if (strcmp (element_name, "deny") == 0)
1461 if (!append_rule_from_element (parser, element_name,
1462 attribute_names, attribute_values,
1466 if (push_element (parser, ELEMENT_DENY) == NULL)
1468 BUS_SET_OOM (error);
1476 dbus_set_error (error, DBUS_ERROR_FAILED,
1477 "Element <%s> not allowed inside <%s> in configuration file",
1478 element_name, "policy");
1484 start_selinux_child (BusConfigParser *parser,
1485 const char *element_name,
1486 const char **attribute_names,
1487 const char **attribute_values,
1490 if (strcmp (element_name, "associate") == 0)
1493 const char *context;
1495 if (!locate_attributes (parser, "associate",
1500 "context", &context,
1504 if (push_element (parser, ELEMENT_ASSOCIATE) == NULL)
1506 BUS_SET_OOM (error);
1510 if (own == NULL || context == NULL)
1512 dbus_set_error (error, DBUS_ERROR_FAILED,
1513 "Element <associate> must have attributes own=\"<servicename>\" and context=\"<selinux context>\"");
1517 if (!bus_selinux_id_table_insert (parser->service_sid_table,
1520 BUS_SET_OOM (error);
1528 dbus_set_error (error, DBUS_ERROR_FAILED,
1529 "Element <%s> not allowed inside <%s> in configuration file",
1530 element_name, "selinux");
1536 bus_config_parser_start_element (BusConfigParser *parser,
1537 const char *element_name,
1538 const char **attribute_names,
1539 const char **attribute_values,
1544 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1546 /* printf ("START: %s\n", element_name); */
1548 t = top_element_type (parser);
1550 if (t == ELEMENT_NONE)
1552 if (strcmp (element_name, "busconfig") == 0)
1554 if (!check_no_attributes (parser, "busconfig", attribute_names, attribute_values, error))
1557 if (push_element (parser, ELEMENT_BUSCONFIG) == NULL)
1559 BUS_SET_OOM (error);
1567 dbus_set_error (error, DBUS_ERROR_FAILED,
1568 "Unknown element <%s> at root of configuration file",
1573 else if (t == ELEMENT_BUSCONFIG)
1575 return start_busconfig_child (parser, element_name,
1576 attribute_names, attribute_values,
1579 else if (t == ELEMENT_POLICY)
1581 return start_policy_child (parser, element_name,
1582 attribute_names, attribute_values,
1585 else if (t == ELEMENT_SELINUX)
1587 return start_selinux_child (parser, element_name,
1588 attribute_names, attribute_values,
1593 dbus_set_error (error, DBUS_ERROR_FAILED,
1594 "Element <%s> is not allowed in this context",
1601 set_limit (BusConfigParser *parser,
1606 dbus_bool_t must_be_positive;
1607 dbus_bool_t must_be_int;
1609 must_be_int = FALSE;
1610 must_be_positive = FALSE;
1612 if (strcmp (name, "max_incoming_bytes") == 0)
1614 must_be_positive = TRUE;
1615 parser->limits.max_incoming_bytes = value;
1617 else if (strcmp (name, "max_outgoing_bytes") == 0)
1619 must_be_positive = TRUE;
1620 parser->limits.max_outgoing_bytes = value;
1622 else if (strcmp (name, "max_message_size") == 0)
1624 must_be_positive = TRUE;
1625 parser->limits.max_message_size = value;
1627 else if (strcmp (name, "activation_timeout") == 0)
1629 must_be_positive = TRUE;
1631 parser->limits.activation_timeout = value;
1633 else if (strcmp (name, "auth_timeout") == 0)
1635 must_be_positive = TRUE;
1637 parser->limits.auth_timeout = value;
1639 else if (strcmp (name, "reply_timeout") == 0)
1641 must_be_positive = TRUE;
1643 parser->limits.reply_timeout = value;
1645 else if (strcmp (name, "max_completed_connections") == 0)
1647 must_be_positive = TRUE;
1649 parser->limits.max_completed_connections = value;
1651 else if (strcmp (name, "max_incomplete_connections") == 0)
1653 must_be_positive = TRUE;
1655 parser->limits.max_incomplete_connections = value;
1657 else if (strcmp (name, "max_connections_per_user") == 0)
1659 must_be_positive = TRUE;
1661 parser->limits.max_connections_per_user = value;
1663 else if (strcmp (name, "max_pending_activations") == 0)
1665 must_be_positive = TRUE;
1667 parser->limits.max_pending_activations = value;
1669 else if (strcmp (name, "max_services_per_connection") == 0)
1671 must_be_positive = TRUE;
1673 parser->limits.max_services_per_connection = value;
1675 else if (strcmp (name, "max_match_rules_per_connection") == 0)
1677 must_be_positive = TRUE;
1679 parser->limits.max_match_rules_per_connection = value;
1681 else if (strcmp (name, "max_replies_per_connection") == 0)
1683 must_be_positive = TRUE;
1685 parser->limits.max_replies_per_connection = value;
1689 dbus_set_error (error, DBUS_ERROR_FAILED,
1690 "There is no limit called \"%s\"\n",
1695 if (must_be_positive && value < 0)
1697 dbus_set_error (error, DBUS_ERROR_FAILED,
1698 "<limit name=\"%s\"> must be a positive number\n",
1704 (value < _DBUS_INT_MIN || value > _DBUS_INT_MAX))
1706 dbus_set_error (error, DBUS_ERROR_FAILED,
1707 "<limit name=\"%s\"> value is too large\n",
1716 bus_config_parser_end_element (BusConfigParser *parser,
1717 const char *element_name,
1724 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1726 /* printf ("END: %s\n", element_name); */
1728 t = top_element_type (parser);
1730 if (t == ELEMENT_NONE)
1732 /* should probably be an assertion failure but
1733 * being paranoid about XML parsers
1735 dbus_set_error (error, DBUS_ERROR_FAILED,
1736 "XML parser ended element with no element on the stack");
1740 n = element_type_to_name (t);
1741 _dbus_assert (n != NULL);
1742 if (strcmp (n, element_name) != 0)
1744 /* should probably be an assertion failure but
1745 * being paranoid about XML parsers
1747 dbus_set_error (error, DBUS_ERROR_FAILED,
1748 "XML element <%s> ended but topmost element on the stack was <%s>",
1753 e = peek_element (parser);
1754 _dbus_assert (e != NULL);
1759 _dbus_assert_not_reached ("element in stack has no type");
1762 case ELEMENT_INCLUDE:
1765 case ELEMENT_LISTEN:
1766 case ELEMENT_PIDFILE:
1768 case ELEMENT_SERVICEDIR:
1769 case ELEMENT_INCLUDEDIR:
1771 if (!e->had_content)
1773 dbus_set_error (error, DBUS_ERROR_FAILED,
1774 "XML element <%s> was expected to have content inside it",
1775 element_type_to_name (e->type));
1779 if (e->type == ELEMENT_LIMIT)
1781 if (!set_limit (parser, e->d.limit.name, e->d.limit.value,
1787 case ELEMENT_BUSCONFIG:
1788 case ELEMENT_POLICY:
1792 case ELEMENT_SELINUX:
1793 case ELEMENT_ASSOCIATE:
1797 pop_element (parser);
1803 all_whitespace (const DBusString *str)
1807 _dbus_string_skip_white (str, 0, &i);
1809 return i == _dbus_string_get_length (str);
1813 make_full_path (const DBusString *basedir,
1814 const DBusString *filename,
1815 DBusString *full_path)
1817 if (_dbus_path_is_absolute (filename))
1819 return _dbus_string_copy (filename, 0, full_path, 0);
1823 if (!_dbus_string_copy (basedir, 0, full_path, 0))
1826 if (!_dbus_concat_dir_and_file (full_path, filename))
1834 include_file (BusConfigParser *parser,
1835 const DBusString *filename,
1836 dbus_bool_t ignore_missing,
1839 /* FIXME good test case for this would load each config file in the
1840 * test suite both alone, and as an include, and check
1841 * that the result is the same
1843 BusConfigParser *included;
1844 const char *filename_str;
1845 DBusError tmp_error;
1847 dbus_error_init (&tmp_error);
1849 filename_str = _dbus_string_get_const_data (filename);
1851 /* Check to make sure this file hasn't already been included. */
1852 if (seen_include (parser, filename))
1854 dbus_set_error (error, DBUS_ERROR_FAILED,
1855 "Circular inclusion of file '%s'",
1860 if (! _dbus_list_append (&parser->included_files, (void *) filename_str))
1862 BUS_SET_OOM (error);
1866 /* Since parser is passed in as the parent, included
1867 inherits parser's limits. */
1868 included = bus_config_load (filename, FALSE, parser, &tmp_error);
1870 _dbus_list_pop_last (&parser->included_files);
1872 if (included == NULL)
1874 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
1876 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) &&
1879 dbus_error_free (&tmp_error);
1884 dbus_move_error (&tmp_error, error);
1890 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
1892 if (!merge_included (parser, included, error))
1894 bus_config_parser_unref (included);
1898 /* Copy included's limits back to parser. */
1899 parser->limits = included->limits;
1901 bus_config_parser_unref (included);
1907 include_dir (BusConfigParser *parser,
1908 const DBusString *dirname,
1911 DBusString filename;
1913 DBusError tmp_error;
1916 if (!_dbus_string_init (&filename))
1918 BUS_SET_OOM (error);
1924 dir = _dbus_directory_open (dirname, error);
1929 dbus_error_init (&tmp_error);
1930 while (_dbus_directory_get_next_file (dir, &filename, &tmp_error))
1932 DBusString full_path;
1934 if (!_dbus_string_init (&full_path))
1936 BUS_SET_OOM (error);
1940 if (!_dbus_string_copy (dirname, 0, &full_path, 0))
1942 BUS_SET_OOM (error);
1943 _dbus_string_free (&full_path);
1947 if (!_dbus_concat_dir_and_file (&full_path, &filename))
1949 BUS_SET_OOM (error);
1950 _dbus_string_free (&full_path);
1954 if (_dbus_string_ends_with_c_str (&full_path, ".conf"))
1956 if (!include_file (parser, &full_path, TRUE, error))
1958 _dbus_string_free (&full_path);
1963 _dbus_string_free (&full_path);
1966 if (dbus_error_is_set (&tmp_error))
1968 dbus_move_error (&tmp_error, error);
1975 _dbus_string_free (&filename);
1978 _dbus_directory_close (dir);
1984 bus_config_parser_content (BusConfigParser *parser,
1985 const DBusString *content,
1990 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1996 _dbus_string_get_const_data (content, &c_str);
1998 printf ("CONTENT %d bytes: %s\n", _dbus_string_get_length (content), c_str);
2002 e = peek_element (parser);
2005 dbus_set_error (error, DBUS_ERROR_FAILED,
2006 "Text content outside of any XML element in configuration file");
2009 else if (e->had_content)
2011 _dbus_assert_not_reached ("Element had multiple content blocks");
2015 switch (top_element_type (parser))
2018 _dbus_assert_not_reached ("element at top of stack has no type");
2021 case ELEMENT_BUSCONFIG:
2022 case ELEMENT_POLICY:
2026 case ELEMENT_SELINUX:
2027 case ELEMENT_ASSOCIATE:
2028 if (all_whitespace (content))
2032 dbus_set_error (error, DBUS_ERROR_FAILED,
2033 "No text content expected inside XML element %s in configuration file",
2034 element_type_to_name (top_element_type (parser)));
2038 case ELEMENT_PIDFILE:
2042 e->had_content = TRUE;
2044 if (!_dbus_string_copy_data (content, &s))
2047 dbus_free (parser->pidfile);
2048 parser->pidfile = s;
2052 case ELEMENT_INCLUDE:
2054 DBusString full_path, selinux_policy_root;
2056 e->had_content = TRUE;
2058 if (!_dbus_string_init (&full_path))
2061 if (e->d.include.selinux_root_relative)
2063 if (!bus_selinux_get_policy_root ())
2065 dbus_set_error (error, DBUS_ERROR_FAILED,
2066 "Could not determine SELinux policy root for relative inclusion");
2067 _dbus_string_free (&full_path);
2070 _dbus_string_init_const (&selinux_policy_root,
2071 bus_selinux_get_policy_root ());
2072 if (!make_full_path (&selinux_policy_root, content, &full_path))
2074 _dbus_string_free (&full_path);
2078 else if (!make_full_path (&parser->basedir, content, &full_path))
2080 _dbus_string_free (&full_path);
2084 if (!include_file (parser, &full_path,
2085 e->d.include.ignore_missing, error))
2087 _dbus_string_free (&full_path);
2091 _dbus_string_free (&full_path);
2095 case ELEMENT_INCLUDEDIR:
2097 DBusString full_path;
2099 e->had_content = TRUE;
2101 if (!_dbus_string_init (&full_path))
2104 if (!make_full_path (&parser->basedir, content, &full_path))
2106 _dbus_string_free (&full_path);
2110 if (!include_dir (parser, &full_path, error))
2112 _dbus_string_free (&full_path);
2116 _dbus_string_free (&full_path);
2124 e->had_content = TRUE;
2126 if (!_dbus_string_copy_data (content, &s))
2129 dbus_free (parser->user);
2138 e->had_content = TRUE;
2140 if (!_dbus_string_copy_data (content, &s))
2143 dbus_free (parser->bus_type);
2144 parser->bus_type = s;
2148 case ELEMENT_LISTEN:
2152 e->had_content = TRUE;
2154 if (!_dbus_string_copy_data (content, &s))
2157 if (!_dbus_list_append (&parser->listen_on,
2170 e->had_content = TRUE;
2172 if (!_dbus_string_copy_data (content, &s))
2175 if (!_dbus_list_append (&parser->mechanisms,
2184 case ELEMENT_SERVICEDIR:
2187 DBusString full_path;
2189 e->had_content = TRUE;
2191 if (!_dbus_string_init (&full_path))
2194 if (!make_full_path (&parser->basedir, content, &full_path))
2196 _dbus_string_free (&full_path);
2200 if (!_dbus_string_copy_data (&full_path, &s))
2202 _dbus_string_free (&full_path);
2206 if (!_dbus_list_append (&parser->service_dirs, s))
2208 _dbus_string_free (&full_path);
2213 _dbus_string_free (&full_path);
2221 e->had_content = TRUE;
2224 if (!_dbus_string_parse_int (content, 0, &val, NULL))
2226 dbus_set_error (error, DBUS_ERROR_FAILED,
2227 "<limit name=\"%s\"> element has invalid value (could not parse as integer)",
2232 e->d.limit.value = val;
2234 _dbus_verbose ("Loaded value %ld for limit %s\n",
2241 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2245 BUS_SET_OOM (error);
2250 bus_config_parser_finished (BusConfigParser *parser,
2253 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2255 if (parser->stack != NULL)
2257 dbus_set_error (error, DBUS_ERROR_FAILED,
2258 "Element <%s> was not closed in configuration file",
2259 element_type_to_name (top_element_type (parser)));
2264 if (parser->is_toplevel && parser->listen_on == NULL)
2266 dbus_set_error (error, DBUS_ERROR_FAILED,
2267 "Configuration file needs one or more <listen> elements giving addresses");
2275 bus_config_parser_get_user (BusConfigParser *parser)
2277 return parser->user;
2281 bus_config_parser_get_type (BusConfigParser *parser)
2283 return parser->bus_type;
2287 bus_config_parser_get_addresses (BusConfigParser *parser)
2289 return &parser->listen_on;
2293 bus_config_parser_get_mechanisms (BusConfigParser *parser)
2295 return &parser->mechanisms;
2299 bus_config_parser_get_service_dirs (BusConfigParser *parser)
2301 return &parser->service_dirs;
2305 bus_config_parser_get_fork (BusConfigParser *parser)
2307 return parser->fork;
2311 bus_config_parser_get_pidfile (BusConfigParser *parser)
2313 return parser->pidfile;
2317 bus_config_parser_steal_policy (BusConfigParser *parser)
2321 _dbus_assert (parser->policy != NULL); /* can only steal the policy 1 time */
2323 policy = parser->policy;
2325 parser->policy = NULL;
2330 /* Overwrite any limits that were set in the configuration file */
2332 bus_config_parser_get_limits (BusConfigParser *parser,
2335 *limits = parser->limits;
2339 bus_config_parser_steal_service_sid_table (BusConfigParser *parser)
2341 DBusHashTable *table;
2343 _dbus_assert (parser->service_sid_table != NULL); /* can only steal once */
2345 table = parser->service_sid_table;
2347 parser->service_sid_table = NULL;
2352 #ifdef DBUS_BUILD_TESTS
2363 do_load (const DBusString *full_path,
2365 dbus_bool_t oom_possible)
2367 BusConfigParser *parser;
2370 dbus_error_init (&error);
2372 parser = bus_config_load (full_path, TRUE, NULL, &error);
2375 _DBUS_ASSERT_ERROR_IS_SET (&error);
2378 dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2380 _dbus_verbose ("Failed to load valid file due to OOM\n");
2381 dbus_error_free (&error);
2384 else if (validity == VALID)
2386 _dbus_warn ("Failed to load valid file but still had memory: %s\n",
2389 dbus_error_free (&error);
2394 dbus_error_free (&error);
2400 _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
2402 bus_config_parser_unref (parser);
2404 if (validity == INVALID)
2406 _dbus_warn ("Accepted invalid file\n");
2416 const DBusString *full_path;
2421 check_loader_oom_func (void *data)
2423 LoaderOomData *d = data;
2425 return do_load (d->full_path, d->validity, TRUE);
2429 process_test_valid_subdir (const DBusString *test_base_dir,
2433 DBusString test_directory;
2434 DBusString filename;
2442 if (!_dbus_string_init (&test_directory))
2443 _dbus_assert_not_reached ("didn't allocate test_directory\n");
2445 _dbus_string_init_const (&filename, subdir);
2447 if (!_dbus_string_copy (test_base_dir, 0,
2448 &test_directory, 0))
2449 _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
2451 if (!_dbus_concat_dir_and_file (&test_directory, &filename))
2452 _dbus_assert_not_reached ("couldn't allocate full path");
2454 _dbus_string_free (&filename);
2455 if (!_dbus_string_init (&filename))
2456 _dbus_assert_not_reached ("didn't allocate filename string\n");
2458 dbus_error_init (&error);
2459 dir = _dbus_directory_open (&test_directory, &error);
2462 _dbus_warn ("Could not open %s: %s\n",
2463 _dbus_string_get_const_data (&test_directory),
2465 dbus_error_free (&error);
2469 if (validity == VALID)
2470 printf ("Testing valid files:\n");
2471 else if (validity == INVALID)
2472 printf ("Testing invalid files:\n");
2474 printf ("Testing unknown files:\n");
2477 while (_dbus_directory_get_next_file (dir, &filename, &error))
2479 DBusString full_path;
2482 if (!_dbus_string_init (&full_path))
2483 _dbus_assert_not_reached ("couldn't init string");
2485 if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
2486 _dbus_assert_not_reached ("couldn't copy dir to full_path");
2488 if (!_dbus_concat_dir_and_file (&full_path, &filename))
2489 _dbus_assert_not_reached ("couldn't concat file to dir");
2491 if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
2493 _dbus_verbose ("Skipping non-.conf file %s\n",
2494 _dbus_string_get_const_data (&filename));
2495 _dbus_string_free (&full_path);
2499 printf (" %s\n", _dbus_string_get_const_data (&filename));
2501 _dbus_verbose (" expecting %s\n",
2502 validity == VALID ? "valid" :
2503 (validity == INVALID ? "invalid" :
2504 (validity == UNKNOWN ? "unknown" : "???")));
2506 d.full_path = &full_path;
2507 d.validity = validity;
2509 /* FIXME hackaround for an expat problem, see
2510 * https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=124747
2511 * http://freedesktop.org/pipermail/dbus/2004-May/001153.html
2513 /* if (!_dbus_test_oom_handling ("config-loader", check_loader_oom_func, &d)) */
2514 if (!check_loader_oom_func (&d))
2515 _dbus_assert_not_reached ("test failed");
2517 _dbus_string_free (&full_path);
2520 if (dbus_error_is_set (&error))
2522 _dbus_warn ("Could not get next file in %s: %s\n",
2523 _dbus_string_get_const_data (&test_directory),
2525 dbus_error_free (&error);
2534 _dbus_directory_close (dir);
2535 _dbus_string_free (&test_directory);
2536 _dbus_string_free (&filename);
2542 bools_equal (dbus_bool_t a,
2549 strings_equal_or_both_null (const char *a,
2552 if (a == NULL || b == NULL)
2555 return !strcmp (a, b);
2559 elements_equal (const Element *a,
2562 if (a->type != b->type)
2565 if (!bools_equal (a->had_content, b->had_content))
2571 case ELEMENT_INCLUDE:
2572 if (!bools_equal (a->d.include.ignore_missing,
2573 b->d.include.ignore_missing))
2577 case ELEMENT_POLICY:
2578 if (a->d.policy.type != b->d.policy.type)
2580 if (a->d.policy.gid_uid_or_at_console != b->d.policy.gid_uid_or_at_console)
2585 if (strcmp (a->d.limit.name, b->d.limit.name))
2587 if (a->d.limit.value != b->d.limit.value)
2601 lists_of_elements_equal (DBusList *a,
2610 while (ia != NULL && ib != NULL)
2612 if (elements_equal (ia->data, ib->data))
2614 ia = _dbus_list_get_next_link (&a, ia);
2615 ib = _dbus_list_get_next_link (&b, ib);
2618 return ia == NULL && ib == NULL;
2622 lists_of_c_strings_equal (DBusList *a,
2631 while (ia != NULL && ib != NULL)
2633 if (strcmp (ia->data, ib->data))
2635 ia = _dbus_list_get_next_link (&a, ia);
2636 ib = _dbus_list_get_next_link (&b, ib);
2639 return ia == NULL && ib == NULL;
2643 limits_equal (const BusLimits *a,
2647 (a->max_incoming_bytes == b->max_incoming_bytes
2648 || a->max_outgoing_bytes == b->max_outgoing_bytes
2649 || a->max_message_size == b->max_message_size
2650 || a->activation_timeout == b->activation_timeout
2651 || a->auth_timeout == b->auth_timeout
2652 || a->max_completed_connections == b->max_completed_connections
2653 || a->max_incomplete_connections == b->max_incomplete_connections
2654 || a->max_connections_per_user == b->max_connections_per_user
2655 || a->max_pending_activations == b->max_pending_activations
2656 || a->max_services_per_connection == b->max_services_per_connection
2657 || a->max_match_rules_per_connection == b->max_match_rules_per_connection
2658 || a->max_replies_per_connection == b->max_replies_per_connection
2659 || a->reply_timeout == b->reply_timeout);
2663 config_parsers_equal (const BusConfigParser *a,
2664 const BusConfigParser *b)
2666 if (!_dbus_string_equal (&a->basedir, &b->basedir))
2669 if (!lists_of_elements_equal (a->stack, b->stack))
2672 if (!strings_equal_or_both_null (a->user, b->user))
2675 if (!lists_of_c_strings_equal (a->listen_on, b->listen_on))
2678 if (!lists_of_c_strings_equal (a->mechanisms, b->mechanisms))
2681 if (!lists_of_c_strings_equal (a->service_dirs, b->service_dirs))
2684 /* FIXME: compare policy */
2686 /* FIXME: compare service selinux ID table */
2688 if (! limits_equal (&a->limits, &b->limits))
2691 if (!strings_equal_or_both_null (a->pidfile, b->pidfile))
2694 if (! bools_equal (a->fork, b->fork))
2697 if (! bools_equal (a->is_toplevel, b->is_toplevel))
2704 all_are_equiv (const DBusString *target_directory)
2706 DBusString filename;
2708 BusConfigParser *first_parser;
2709 BusConfigParser *parser;
2715 first_parser = NULL;
2719 if (!_dbus_string_init (&filename))
2720 _dbus_assert_not_reached ("didn't allocate filename string");
2722 dbus_error_init (&error);
2723 dir = _dbus_directory_open (target_directory, &error);
2726 _dbus_warn ("Could not open %s: %s\n",
2727 _dbus_string_get_const_data (target_directory),
2729 dbus_error_free (&error);
2733 printf ("Comparing equivalent files:\n");
2736 while (_dbus_directory_get_next_file (dir, &filename, &error))
2738 DBusString full_path;
2740 if (!_dbus_string_init (&full_path))
2741 _dbus_assert_not_reached ("couldn't init string");
2743 if (!_dbus_string_copy (target_directory, 0, &full_path, 0))
2744 _dbus_assert_not_reached ("couldn't copy dir to full_path");
2746 if (!_dbus_concat_dir_and_file (&full_path, &filename))
2747 _dbus_assert_not_reached ("couldn't concat file to dir");
2749 if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
2751 _dbus_verbose ("Skipping non-.conf file %s\n",
2752 _dbus_string_get_const_data (&filename));
2753 _dbus_string_free (&full_path);
2757 printf (" %s\n", _dbus_string_get_const_data (&filename));
2759 parser = bus_config_load (&full_path, TRUE, NULL, &error);
2760 _dbus_string_free (&full_path);
2764 _dbus_warn ("Could not load file %s: %s\n",
2765 _dbus_string_get_const_data (&full_path),
2767 dbus_error_free (&error);
2770 else if (first_parser == NULL)
2772 first_parser = parser;
2776 equal = config_parsers_equal (first_parser, parser);
2777 bus_config_parser_unref (parser);
2787 _dbus_string_free (&filename);
2789 bus_config_parser_unref (first_parser);
2791 _dbus_directory_close (dir);
2798 process_test_equiv_subdir (const DBusString *test_base_dir,
2801 DBusString test_directory;
2802 DBusString filename;
2811 if (!_dbus_string_init (&test_directory))
2812 _dbus_assert_not_reached ("didn't allocate test_directory");
2814 _dbus_string_init_const (&filename, subdir);
2816 if (!_dbus_string_copy (test_base_dir, 0,
2817 &test_directory, 0))
2818 _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
2820 if (!_dbus_concat_dir_and_file (&test_directory, &filename))
2821 _dbus_assert_not_reached ("couldn't allocate full path");
2823 _dbus_string_free (&filename);
2824 if (!_dbus_string_init (&filename))
2825 _dbus_assert_not_reached ("didn't allocate filename string");
2827 dbus_error_init (&error);
2828 dir = _dbus_directory_open (&test_directory, &error);
2831 _dbus_warn ("Could not open %s: %s\n",
2832 _dbus_string_get_const_data (&test_directory),
2834 dbus_error_free (&error);
2838 while (_dbus_directory_get_next_file (dir, &filename, &error))
2840 DBusString full_path;
2842 /* Skip CVS's magic directories! */
2843 if (_dbus_string_equal_c_str (&filename, "CVS"))
2846 if (!_dbus_string_init (&full_path))
2847 _dbus_assert_not_reached ("couldn't init string");
2849 if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
2850 _dbus_assert_not_reached ("couldn't copy dir to full_path");
2852 if (!_dbus_concat_dir_and_file (&full_path, &filename))
2853 _dbus_assert_not_reached ("couldn't concat file to dir");
2855 equal = all_are_equiv (&full_path);
2856 _dbus_string_free (&full_path);
2865 _dbus_string_free (&test_directory);
2866 _dbus_string_free (&filename);
2868 _dbus_directory_close (dir);
2875 bus_config_parser_test (const DBusString *test_data_dir)
2877 if (test_data_dir == NULL ||
2878 _dbus_string_get_length (test_data_dir) == 0)
2880 printf ("No test data\n");
2884 if (!process_test_valid_subdir (test_data_dir, "valid-config-files", VALID))
2887 if (!process_test_valid_subdir (test_data_dir, "invalid-config-files", INVALID))
2890 if (!process_test_equiv_subdir (test_data_dir, "equiv-config-files"))
2896 #endif /* DBUS_BUILD_TESTS */