1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* config-parser.c XML-library-agnostic configuration file parser
3 *
4 * Copyright (C) 2003, 2004 Red Hat, Inc.
5 *
6 * Licensed under the Academic Free License version 2.1
7 *
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.
12 *
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.
17 *
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
21 *
22 */
23 #include "config-parser.h"
24 #include "test.h"
25 #include "utils.h"
26 #include "policy.h"
27 #include "selinux.h"
28 #include <dbus/dbus-list.h>
29 #include <dbus/dbus-internals.h>
30 #include <string.h>
31
32 typedef enum
33 {
34 ELEMENT_NONE,
35 ELEMENT_BUSCONFIG,
36 ELEMENT_INCLUDE,
37 ELEMENT_USER,
38 ELEMENT_LISTEN,
39 ELEMENT_AUTH,
40 ELEMENT_POLICY,
41 ELEMENT_LIMIT,
42 ELEMENT_ALLOW,
43 ELEMENT_DENY,
44 ELEMENT_FORK,
45 ELEMENT_PIDFILE,
46 ELEMENT_SERVICEDIR,
47 ELEMENT_INCLUDEDIR,
48 ELEMENT_TYPE,
49 ELEMENT_SELINUX,
50 ELEMENT_ASSOCIATE,
51 ELEMENT_STANDARD_SESSION_SERVICEDIRS
52 } ElementType;
53
54 typedef enum
55 {
56 /* we ignore policies for unknown groups/users */
57 POLICY_IGNORED,
58
59 /* non-ignored */
60 POLICY_DEFAULT,
61 POLICY_MANDATORY,
62 POLICY_USER,
63 POLICY_GROUP,
64 POLICY_CONSOLE
65 } PolicyType;
66
67 typedef struct
68 {
69 ElementType type;
70
71 unsigned int had_content : 1;
72
73 union
74 {
75 struct
76 {
77 unsigned int ignore_missing : 1;
78 unsigned int if_selinux_enabled : 1;
79 unsigned int selinux_root_relative : 1;
80 } include;
81
82 struct
83 {
84 PolicyType type;
85 unsigned long gid_uid_or_at_console;
86 } policy;
87
88 struct
89 {
90 char *name;
91 long value;
92 } limit;
93
94 } d;
95
96 } Element;
97
98 /**
99 * Parser for bus configuration file.
100 */
101 struct BusConfigParser
102 {
103 int refcount; /**< Reference count */
104
105 DBusString basedir; /**< Directory we resolve paths relative to */
106
107 DBusList *stack; /**< stack of Element */
108
109 char *user; /**< user to run as */
110
111 char *bus_type; /**< Message bus type */
112
113 DBusList *listen_on; /**< List of addresses to listen to */
114
115 DBusList *mechanisms; /**< Auth mechanisms */
116
117 DBusList *service_dirs; /**< Directories to look for services in */
118
119 DBusList *conf_dirs; /**< Directories to look for policy configuration in */
120
121 BusPolicy *policy; /**< Security policy */
122
123 BusLimits limits; /**< Limits */
124
125 char *pidfile; /**< PID file */
126
127 DBusList *included_files; /**< Included files stack */
128
129 DBusHashTable *service_context_table; /**< Map service names to SELinux contexts */
130
131 unsigned int fork : 1; /**< TRUE to fork into daemon mode */
132
133 unsigned int is_toplevel : 1; /**< FALSE if we are a sub-config-file inside another one */
134 };
135
136 static const char*
element_type_to_name(ElementType type)137 element_type_to_name (ElementType type)
138 {
139 switch (type)
140 {
141 case ELEMENT_NONE:
142 return NULL;
143 case ELEMENT_BUSCONFIG:
144 return "busconfig";
145 case ELEMENT_INCLUDE:
146 return "include";
147 case ELEMENT_USER:
148 return "user";
149 case ELEMENT_LISTEN:
150 return "listen";
151 case ELEMENT_AUTH:
152 return "auth";
153 case ELEMENT_POLICY:
154 return "policy";
155 case ELEMENT_LIMIT:
156 return "limit";
157 case ELEMENT_ALLOW:
158 return "allow";
159 case ELEMENT_DENY:
160 return "deny";
161 case ELEMENT_FORK:
162 return "fork";
163 case ELEMENT_PIDFILE:
164 return "pidfile";
165 case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
166 return "standard_session_servicedirs";
167 case ELEMENT_SERVICEDIR:
168 return "servicedir";
169 case ELEMENT_INCLUDEDIR:
170 return "includedir";
171 case ELEMENT_TYPE:
172 return "type";
173 case ELEMENT_SELINUX:
174 return "selinux";
175 case ELEMENT_ASSOCIATE:
176 return "associate";
177 }
178
179 _dbus_assert_not_reached ("bad element type");
180
181 return NULL;
182 }
183
184 static Element*
push_element(BusConfigParser * parser,ElementType type)185 push_element (BusConfigParser *parser,
186 ElementType type)
187 {
188 Element *e;
189
190 _dbus_assert (type != ELEMENT_NONE);
191
192 e = dbus_new0 (Element, 1);
193 if (e == NULL)
194 return NULL;
195
196 if (!_dbus_list_append (&parser->stack, e))
197 {
198 dbus_free (e);
199 return NULL;
200 }
201
202 e->type = type;
203
204 return e;
205 }
206
207 static void
element_free(Element * e)208 element_free (Element *e)
209 {
210 if (e->type == ELEMENT_LIMIT)
211 dbus_free (e->d.limit.name);
212
213 dbus_free (e);
214 }
215
216 static void
pop_element(BusConfigParser * parser)217 pop_element (BusConfigParser *parser)
218 {
219 Element *e;
220
221 e = _dbus_list_pop_last (&parser->stack);
222
223 element_free (e);
224 }
225
226 static Element*
peek_element(BusConfigParser * parser)227 peek_element (BusConfigParser *parser)
228 {
229 Element *e;
230
231 e = _dbus_list_get_last (&parser->stack);
232
233 return e;
234 }
235
236 static ElementType
top_element_type(BusConfigParser * parser)237 top_element_type (BusConfigParser *parser)
238 {
239 Element *e;
240
241 e = _dbus_list_get_last (&parser->stack);
242
243 if (e)
244 return e->type;
245 else
246 return ELEMENT_NONE;
247 }
248
249 static dbus_bool_t
merge_service_context_hash(DBusHashTable * dest,DBusHashTable * from)250 merge_service_context_hash (DBusHashTable *dest,
251 DBusHashTable *from)
252 {
253 DBusHashIter iter;
254 char *service_copy;
255 char *context_copy;
256
257 service_copy = NULL;
258 context_copy = NULL;
259
260 _dbus_hash_iter_init (from, &iter);
261 while (_dbus_hash_iter_next (&iter))
262 {
263 const char *service = _dbus_hash_iter_get_string_key (&iter);
264 const char *context = _dbus_hash_iter_get_value (&iter);
265
266 service_copy = _dbus_strdup (service);
267 if (service_copy == NULL)
268 goto fail;
269 context_copy = _dbus_strdup (context);
270 if (context_copy == NULL)
271 goto fail;
272
273 if (!_dbus_hash_table_insert_string (dest, service_copy, context_copy))
274 goto fail;
275
276 service_copy = NULL;
277 context_copy = NULL;
278 }
279
280 return TRUE;
281
282 fail:
283 if (service_copy)
284 dbus_free (service_copy);
285
286 if (context_copy)
287 dbus_free (context_copy);
288
289 return FALSE;
290 }
291
292 static dbus_bool_t
service_dirs_find_dir(DBusList ** service_dirs,const char * dir)293 service_dirs_find_dir (DBusList **service_dirs,
294 const char *dir)
295 {
296 DBusList *link;
297
298 _dbus_assert (dir != NULL);
299
300 for (link = *service_dirs; link; link = _dbus_list_get_next_link(service_dirs, link))
301 {
302 const char *link_dir;
303
304 link_dir = (const char *)link->data;
305 if (strcmp (dir, link_dir) == 0)
306 return TRUE;
307 }
308
309 return FALSE;
310 }
311
312 static dbus_bool_t
service_dirs_append_unique_or_free(DBusList ** service_dirs,char * dir)313 service_dirs_append_unique_or_free (DBusList **service_dirs,
314 char *dir)
315 {
316 if (!service_dirs_find_dir (service_dirs, dir))
317 return _dbus_list_append (service_dirs, dir);
318
319 dbus_free (dir);
320 return TRUE;
321 }
322
323 static void
service_dirs_append_link_unique_or_free(DBusList ** service_dirs,DBusList * dir_link)324 service_dirs_append_link_unique_or_free (DBusList **service_dirs,
325 DBusList *dir_link)
326 {
327 if (!service_dirs_find_dir (service_dirs, dir_link->data))
328 {
329 _dbus_list_append_link (service_dirs, dir_link);
330 }
331 else
332 {
333 dbus_free (dir_link->data);
334 _dbus_list_free_link (dir_link);
335 }
336 }
337
338 static dbus_bool_t
merge_included(BusConfigParser * parser,BusConfigParser * included,DBusError * error)339 merge_included (BusConfigParser *parser,
340 BusConfigParser *included,
341 DBusError *error)
342 {
343 DBusList *link;
344
345 if (!bus_policy_merge (parser->policy,
346 included->policy))
347 {
348 BUS_SET_OOM (error);
349 return FALSE;
350 }
351
352 if (!merge_service_context_hash (parser->service_context_table,
353 included->service_context_table))
354 {
355 BUS_SET_OOM (error);
356 return FALSE;
357 }
358
359 if (included->user != NULL)
360 {
361 dbus_free (parser->user);
362 parser->user = included->user;
363 included->user = NULL;
364 }
365
366 if (included->bus_type != NULL)
367 {
368 dbus_free (parser->bus_type);
369 parser->bus_type = included->bus_type;
370 included->bus_type = NULL;
371 }
372
373 if (included->fork)
374 parser->fork = TRUE;
375
376 if (included->pidfile != NULL)
377 {
378 dbus_free (parser->pidfile);
379 parser->pidfile = included->pidfile;
380 included->pidfile = NULL;
381 }
382
383 while ((link = _dbus_list_pop_first_link (&included->listen_on)))
384 _dbus_list_append_link (&parser->listen_on, link);
385
386 while ((link = _dbus_list_pop_first_link (&included->mechanisms)))
387 _dbus_list_append_link (&parser->mechanisms, link);
388
389 while ((link = _dbus_list_pop_first_link (&included->service_dirs)))
390 service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
391
392 while ((link = _dbus_list_pop_first_link (&included->conf_dirs)))
393 _dbus_list_append_link (&parser->conf_dirs, link);
394
395 return TRUE;
396 }
397
398 static dbus_bool_t
seen_include(BusConfigParser * parser,const DBusString * file)399 seen_include (BusConfigParser *parser,
400 const DBusString *file)
401 {
402 DBusList *iter;
403
404 iter = parser->included_files;
405 while (iter != NULL)
406 {
407 if (! strcmp (_dbus_string_get_const_data (file), iter->data))
408 return TRUE;
409
410 iter = _dbus_list_get_next_link (&parser->included_files, iter);
411 }
412
413 return FALSE;
414 }
415
416 BusConfigParser*
bus_config_parser_new(const DBusString * basedir,dbus_bool_t is_toplevel,const BusConfigParser * parent)417 bus_config_parser_new (const DBusString *basedir,
418 dbus_bool_t is_toplevel,
419 const BusConfigParser *parent)
420 {
421 BusConfigParser *parser;
422
423 parser = dbus_new0 (BusConfigParser, 1);
424 if (parser == NULL)
425 return NULL;
426
427 parser->is_toplevel = !!is_toplevel;
428
429 if (!_dbus_string_init (&parser->basedir))
430 {
431 dbus_free (parser);
432 return NULL;
433 }
434
435 if (((parser->policy = bus_policy_new ()) == NULL) ||
436 !_dbus_string_copy (basedir, 0, &parser->basedir, 0) ||
437 ((parser->service_context_table = _dbus_hash_table_new (DBUS_HASH_STRING,
438 dbus_free,
439 dbus_free)) == NULL))
440 {
441 if (parser->policy)
442 bus_policy_unref (parser->policy);
443
444 _dbus_string_free (&parser->basedir);
445
446 dbus_free (parser);
447 return NULL;
448 }
449
450 if (parent != NULL)
451 {
452 /* Initialize the parser's limits from the parent. */
453 parser->limits = parent->limits;
454
455 /* Use the parent's list of included_files to avoid
456 circular inclusions. */
457 parser->included_files = parent->included_files;
458 }
459 else
460 {
461
462 /* Make up some numbers! woot! */
463 parser->limits.max_incoming_bytes = _DBUS_ONE_MEGABYTE * 63;
464 parser->limits.max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 63;
465 parser->limits.max_message_size = _DBUS_ONE_MEGABYTE * 32;
466
467 /* Making this long means the user has to wait longer for an error
468 * message if something screws up, but making it too short means
469 * they might see a false failure.
470 */
471 parser->limits.activation_timeout = 25000; /* 25 seconds */
472
473 /* Making this long risks making a DOS attack easier, but too short
474 * and legitimate auth will fail. If interactive auth (ask user for
475 * password) is allowed, then potentially it has to be quite long.
476 */
477 parser->limits.auth_timeout = 30000; /* 30 seconds */
478
479 parser->limits.max_incomplete_connections = 32;
480 parser->limits.max_connections_per_user = 128;
481
482 /* Note that max_completed_connections / max_connections_per_user
483 * is the number of users that would have to work together to
484 * DOS all the other users.
485 */
486 parser->limits.max_completed_connections = 1024;
487
488 parser->limits.max_pending_activations = 256;
489 parser->limits.max_services_per_connection = 256;
490
491 parser->limits.max_match_rules_per_connection = 512;
492
493 parser->limits.reply_timeout = 5 * 60 * 1000; /* 5 minutes */
494 parser->limits.max_replies_per_connection = 32;
495 }
496
497 parser->refcount = 1;
498
499 return parser;
500 }
501
502 BusConfigParser *
bus_config_parser_ref(BusConfigParser * parser)503 bus_config_parser_ref (BusConfigParser *parser)
504 {
505 _dbus_assert (parser->refcount > 0);
506
507 parser->refcount += 1;
508
509 return parser;
510 }
511
512 void
bus_config_parser_unref(BusConfigParser * parser)513 bus_config_parser_unref (BusConfigParser *parser)
514 {
515 _dbus_assert (parser->refcount > 0);
516
517 parser->refcount -= 1;
518
519 if (parser->refcount == 0)
520 {
521 while (parser->stack != NULL)
522 pop_element (parser);
523
524 dbus_free (parser->user);
525 dbus_free (parser->bus_type);
526 dbus_free (parser->pidfile);
527
528 _dbus_list_foreach (&parser->listen_on,
529 (DBusForeachFunction) dbus_free,
530 NULL);
531
532 _dbus_list_clear (&parser->listen_on);
533
534 _dbus_list_foreach (&parser->service_dirs,
535 (DBusForeachFunction) dbus_free,
536 NULL);
537
538 _dbus_list_clear (&parser->service_dirs);
539
540 _dbus_list_foreach (&parser->conf_dirs,
541 (DBusForeachFunction) dbus_free,
542 NULL);
543
544 _dbus_list_clear (&parser->conf_dirs);
545
546 _dbus_list_foreach (&parser->mechanisms,
547 (DBusForeachFunction) dbus_free,
548 NULL);
549
550 _dbus_list_clear (&parser->mechanisms);
551
552 _dbus_string_free (&parser->basedir);
553
554 if (parser->policy)
555 bus_policy_unref (parser->policy);
556
557 if (parser->service_context_table)
558 _dbus_hash_table_unref (parser->service_context_table);
559
560 dbus_free (parser);
561 }
562 }
563
564 dbus_bool_t
bus_config_parser_check_doctype(BusConfigParser * parser,const char * doctype,DBusError * error)565 bus_config_parser_check_doctype (BusConfigParser *parser,
566 const char *doctype,
567 DBusError *error)
568 {
569 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
570
571 if (strcmp (doctype, "busconfig") != 0)
572 {
573 dbus_set_error (error,
574 DBUS_ERROR_FAILED,
575 "Configuration file has the wrong document type %s",
576 doctype);
577 return FALSE;
578 }
579 else
580 return TRUE;
581 }
582
583 typedef struct
584 {
585 const char *name;
586 const char **retloc;
587 } LocateAttr;
588
589 static dbus_bool_t
locate_attributes(BusConfigParser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,DBusError * error,const char * first_attribute_name,const char ** first_attribute_retloc,...)590 locate_attributes (BusConfigParser *parser,
591 const char *element_name,
592 const char **attribute_names,
593 const char **attribute_values,
594 DBusError *error,
595 const char *first_attribute_name,
596 const char **first_attribute_retloc,
597 ...)
598 {
599 va_list args;
600 const char *name;
601 const char **retloc;
602 int n_attrs;
603 #define MAX_ATTRS 24
604 LocateAttr attrs[MAX_ATTRS];
605 dbus_bool_t retval;
606 int i;
607
608 _dbus_assert (first_attribute_name != NULL);
609 _dbus_assert (first_attribute_retloc != NULL);
610
611 retval = TRUE;
612
613 n_attrs = 1;
614 attrs[0].name = first_attribute_name;
615 attrs[0].retloc = first_attribute_retloc;
616 *first_attribute_retloc = NULL;
617
618 va_start (args, first_attribute_retloc);
619
620 name = va_arg (args, const char*);
621 retloc = va_arg (args, const char**);
622
623 while (name != NULL)
624 {
625 _dbus_assert (retloc != NULL);
626 _dbus_assert (n_attrs < MAX_ATTRS);
627
628 attrs[n_attrs].name = name;
629 attrs[n_attrs].retloc = retloc;
630 n_attrs += 1;
631 *retloc = NULL;
632
633 name = va_arg (args, const char*);
634 retloc = va_arg (args, const char**);
635 }
636
637 va_end (args);
638
639 if (!retval)
640 return retval;
641
642 i = 0;
643 while (attribute_names[i])
644 {
645 int j;
646 dbus_bool_t found;
647
648 found = FALSE;
649 j = 0;
650 while (j < n_attrs)
651 {
652 if (strcmp (attrs[j].name, attribute_names[i]) == 0)
653 {
654 retloc = attrs[j].retloc;
655
656 if (*retloc != NULL)
657 {
658 dbus_set_error (error, DBUS_ERROR_FAILED,
659 "Attribute \"%s\" repeated twice on the same <%s> element",
660 attrs[j].name, element_name);
661 retval = FALSE;
662 goto out;
663 }
664
665 *retloc = attribute_values[i];
666 found = TRUE;
667 }
668
669 ++j;
670 }
671
672 if (!found)
673 {
674 dbus_set_error (error, DBUS_ERROR_FAILED,
675 "Attribute \"%s\" is invalid on <%s> element in this context",
676 attribute_names[i], element_name);
677 retval = FALSE;
678 goto out;
679 }
680
681 ++i;
682 }
683
684 out:
685 return retval;
686 }
687
688 static dbus_bool_t
check_no_attributes(BusConfigParser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,DBusError * error)689 check_no_attributes (BusConfigParser *parser,
690 const char *element_name,
691 const char **attribute_names,
692 const char **attribute_values,
693 DBusError *error)
694 {
695 if (attribute_names[0] != NULL)
696 {
697 dbus_set_error (error, DBUS_ERROR_FAILED,
698 "Attribute \"%s\" is invalid on <%s> element in this context",
699 attribute_names[0], element_name);
700 return FALSE;
701 }
702
703 return TRUE;
704 }
705
706 static dbus_bool_t
start_busconfig_child(BusConfigParser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,DBusError * error)707 start_busconfig_child (BusConfigParser *parser,
708 const char *element_name,
709 const char **attribute_names,
710 const char **attribute_values,
711 DBusError *error)
712 {
713 if (strcmp (element_name, "user") == 0)
714 {
715 if (!check_no_attributes (parser, "user", attribute_names, attribute_values, error))
716 return FALSE;
717
718 if (push_element (parser, ELEMENT_USER) == NULL)
719 {
720 BUS_SET_OOM (error);
721 return FALSE;
722 }
723
724 return TRUE;
725 }
726 else if (strcmp (element_name, "type") == 0)
727 {
728 if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
729 return FALSE;
730
731 if (push_element (parser, ELEMENT_TYPE) == NULL)
732 {
733 BUS_SET_OOM (error);
734 return FALSE;
735 }
736
737 return TRUE;
738 }
739 else if (strcmp (element_name, "fork") == 0)
740 {
741 if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
742 return FALSE;
743
744 if (push_element (parser, ELEMENT_FORK) == NULL)
745 {
746 BUS_SET_OOM (error);
747 return FALSE;
748 }
749
750 parser->fork = TRUE;
751
752 return TRUE;
753 }
754 else if (strcmp (element_name, "pidfile") == 0)
755 {
756 if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
757 return FALSE;
758
759 if (push_element (parser, ELEMENT_PIDFILE) == NULL)
760 {
761 BUS_SET_OOM (error);
762 return FALSE;
763 }
764
765 return TRUE;
766 }
767 else if (strcmp (element_name, "listen") == 0)
768 {
769 if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
770 return FALSE;
771
772 if (push_element (parser, ELEMENT_LISTEN) == NULL)
773 {
774 BUS_SET_OOM (error);
775 return FALSE;
776 }
777
778 return TRUE;
779 }
780 else if (strcmp (element_name, "auth") == 0)
781 {
782 if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
783 return FALSE;
784
785 if (push_element (parser, ELEMENT_AUTH) == NULL)
786 {
787 BUS_SET_OOM (error);
788 return FALSE;
789 }
790
791 return TRUE;
792 }
793 else if (strcmp (element_name, "includedir") == 0)
794 {
795 if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error))
796 return FALSE;
797
798 if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL)
799 {
800 BUS_SET_OOM (error);
801 return FALSE;
802 }
803
804 return TRUE;
805 }
806 else if (strcmp (element_name, "standard_session_servicedirs") == 0)
807 {
808 DBusList *link;
809 DBusList *dirs;
810 dirs = NULL;
811
812 if (!check_no_attributes (parser, "standard_session_servicedirs", attribute_names, attribute_values, error))
813 return FALSE;
814
815 if (push_element (parser, ELEMENT_STANDARD_SESSION_SERVICEDIRS) == NULL)
816 {
817 BUS_SET_OOM (error);
818 return FALSE;
819 }
820
821 if (!_dbus_get_standard_session_servicedirs (&dirs))
822 {
823 BUS_SET_OOM (error);
824 return FALSE;
825 }
826
827 while ((link = _dbus_list_pop_first_link (&dirs)))
828 service_dirs_append_link_unique_or_free (&parser->service_dirs, link);
829
830 return TRUE;
831 }
832 else if (strcmp (element_name, "servicedir") == 0)
833 {
834 if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error))
835 return FALSE;
836
837 if (push_element (parser, ELEMENT_SERVICEDIR) == NULL)
838 {
839 BUS_SET_OOM (error);
840 return FALSE;
841 }
842
843 return TRUE;
844 }
845 else if (strcmp (element_name, "include") == 0)
846 {
847 Element *e;
848 const char *if_selinux_enabled;
849 const char *ignore_missing;
850 const char *selinux_root_relative;
851
852 if ((e = push_element (parser, ELEMENT_INCLUDE)) == NULL)
853 {
854 BUS_SET_OOM (error);
855 return FALSE;
856 }
857
858 e->d.include.ignore_missing = FALSE;
859 e->d.include.if_selinux_enabled = FALSE;
860 e->d.include.selinux_root_relative = FALSE;
861
862 if (!locate_attributes (parser, "include",
863 attribute_names,
864 attribute_values,
865 error,
866 "ignore_missing", &ignore_missing,
867 "if_selinux_enabled", &if_selinux_enabled,
868 "selinux_root_relative", &selinux_root_relative,
869 NULL))
870 return FALSE;
871
872 if (ignore_missing != NULL)
873 {
874 if (strcmp (ignore_missing, "yes") == 0)
875 e->d.include.ignore_missing = TRUE;
876 else if (strcmp (ignore_missing, "no") == 0)
877 e->d.include.ignore_missing = FALSE;
878 else
879 {
880 dbus_set_error (error, DBUS_ERROR_FAILED,
881 "ignore_missing attribute must have value \"yes\" or \"no\"");
882 return FALSE;
883 }
884 }
885
886 if (if_selinux_enabled != NULL)
887 {
888 if (strcmp (if_selinux_enabled, "yes") == 0)
889 e->d.include.if_selinux_enabled = TRUE;
890 else if (strcmp (if_selinux_enabled, "no") == 0)
891 e->d.include.if_selinux_enabled = FALSE;
892 else
893 {
894 dbus_set_error (error, DBUS_ERROR_FAILED,
895 "if_selinux_enabled attribute must have value"
896 " \"yes\" or \"no\"");
897 return FALSE;
898 }
899 }
900
901 if (selinux_root_relative != NULL)
902 {
903 if (strcmp (selinux_root_relative, "yes") == 0)
904 e->d.include.selinux_root_relative = TRUE;
905 else if (strcmp (selinux_root_relative, "no") == 0)
906 e->d.include.selinux_root_relative = FALSE;
907 else
908 {
909 dbus_set_error (error, DBUS_ERROR_FAILED,
910 "selinux_root_relative attribute must have value"
911 " \"yes\" or \"no\"");
912 return FALSE;
913 }
914 }
915
916 return TRUE;
917 }
918 else if (strcmp (element_name, "policy") == 0)
919 {
920 Element *e;
921 const char *context;
922 const char *user;
923 const char *group;
924 const char *at_console;
925
926 if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
927 {
928 BUS_SET_OOM (error);
929 return FALSE;
930 }
931
932 e->d.policy.type = POLICY_IGNORED;
933
934 if (!locate_attributes (parser, "policy",
935 attribute_names,
936 attribute_values,
937 error,
938 "context", &context,
939 "user", &user,
940 "group", &group,
941 "at_console", &at_console,
942 NULL))
943 return FALSE;
944
945 if (((context && user) ||
946 (context && group) ||
947 (context && at_console)) ||
948 ((user && group) ||
949 (user && at_console)) ||
950 (group && at_console) ||
951 !(context || user || group || at_console))
952 {
953 dbus_set_error (error, DBUS_ERROR_FAILED,
954 "<policy> element must have exactly one of (context|user|group|at_console) attributes");
955 return FALSE;
956 }
957
958 if (context != NULL)
959 {
960 if (strcmp (context, "default") == 0)
961 {
962 e->d.policy.type = POLICY_DEFAULT;
963 }
964 else if (strcmp (context, "mandatory") == 0)
965 {
966 e->d.policy.type = POLICY_MANDATORY;
967 }
968 else
969 {
970 dbus_set_error (error, DBUS_ERROR_FAILED,
971 "context attribute on <policy> must have the value \"default\" or \"mandatory\", not \"%s\"",
972 context);
973 return FALSE;
974 }
975 }
976 else if (user != NULL)
977 {
978 DBusString username;
979 _dbus_string_init_const (&username, user);
980
981 if (_dbus_get_user_id (&username,
982 &e->d.policy.gid_uid_or_at_console))
983 e->d.policy.type = POLICY_USER;
984 else
985 _dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
986 user);
987 }
988 else if (group != NULL)
989 {
990 DBusString group_name;
991 _dbus_string_init_const (&group_name, group);
992
993 if (_dbus_get_group_id (&group_name,
994 &e->d.policy.gid_uid_or_at_console))
995 e->d.policy.type = POLICY_GROUP;
996 else
997 _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
998 group);
999 }
1000 else if (at_console != NULL)
1001 {
1002 dbus_bool_t t;
1003 t = (strcmp (at_console, "true") == 0);
1004 if (t || strcmp (at_console, "false") == 0)
1005 {
1006 e->d.policy.gid_uid_or_at_console = t;
1007 e->d.policy.type = POLICY_CONSOLE;
1008 }
1009 else
1010 {
1011 dbus_set_error (error, DBUS_ERROR_FAILED,
1012 "Unknown value \"%s\" for at_console in message bus configuration file",
1013 at_console);
1014
1015 return FALSE;
1016 }
1017 }
1018 else
1019 {
1020 _dbus_assert_not_reached ("all <policy> attributes null and we didn't set error");
1021 }
1022
1023 return TRUE;
1024 }
1025 else if (strcmp (element_name, "limit") == 0)
1026 {
1027 Element *e;
1028 const char *name;
1029
1030 if ((e = push_element (parser, ELEMENT_LIMIT)) == NULL)
1031 {
1032 BUS_SET_OOM (error);
1033 return FALSE;
1034 }
1035
1036 if (!locate_attributes (parser, "limit",
1037 attribute_names,
1038 attribute_values,
1039 error,
1040 "name", &name,
1041 NULL))
1042 return FALSE;
1043
1044 if (name == NULL)
1045 {
1046 dbus_set_error (error, DBUS_ERROR_FAILED,
1047 "<limit> element must have a \"name\" attribute");
1048 return FALSE;
1049 }
1050
1051 e->d.limit.name = _dbus_strdup (name);
1052 if (e->d.limit.name == NULL)
1053 {
1054 BUS_SET_OOM (error);
1055 return FALSE;
1056 }
1057
1058 return TRUE;
1059 }
1060 else if (strcmp (element_name, "selinux") == 0)
1061 {
1062 if (!check_no_attributes (parser, "selinux", attribute_names, attribute_values, error))
1063 return FALSE;
1064
1065 if (push_element (parser, ELEMENT_SELINUX) == NULL)
1066 {
1067 BUS_SET_OOM (error);
1068 return FALSE;
1069 }
1070
1071 return TRUE;
1072 }
1073 else
1074 {
1075 dbus_set_error (error, DBUS_ERROR_FAILED,
1076 "Element <%s> not allowed inside <%s> in configuration file",
1077 element_name, "busconfig");
1078 return FALSE;
1079 }
1080 }
1081
1082 static dbus_bool_t
append_rule_from_element(BusConfigParser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,dbus_bool_t allow,DBusError * error)1083 append_rule_from_element (BusConfigParser *parser,
1084 const char *element_name,
1085 const char **attribute_names,
1086 const char **attribute_values,
1087 dbus_bool_t allow,
1088 DBusError *error)
1089 {
1090 const char *send_interface;
1091 const char *send_member;
1092 const char *send_error;
1093 const char *send_destination;
1094 const char *send_path;
1095 const char *send_type;
1096 const char *receive_interface;
1097 const char *receive_member;
1098 const char *receive_error;
1099 const char *receive_sender;
1100 const char *receive_path;
1101 const char *receive_type;
1102 const char *eavesdrop;
1103 const char *send_requested_reply;
1104 const char *receive_requested_reply;
1105 const char *own;
1106 const char *user;
1107 const char *group;
1108
1109 BusPolicyRule *rule;
1110
1111 if (!locate_attributes (parser, element_name,
1112 attribute_names,
1113 attribute_values,
1114 error,
1115 "send_interface", &send_interface,
1116 "send_member", &send_member,
1117 "send_error", &send_error,
1118 "send_destination", &send_destination,
1119 "send_path", &send_path,
1120 "send_type", &send_type,
1121 "receive_interface", &receive_interface,
1122 "receive_member", &receive_member,
1123 "receive_error", &receive_error,
1124 "receive_sender", &receive_sender,
1125 "receive_path", &receive_path,
1126 "receive_type", &receive_type,
1127 "eavesdrop", &eavesdrop,
1128 "send_requested_reply", &send_requested_reply,
1129 "receive_requested_reply", &receive_requested_reply,
1130 "own", &own,
1131 "user", &user,
1132 "group", &group,
1133 NULL))
1134 return FALSE;
1135
1136 if (!(send_interface || send_member || send_error || send_destination ||
1137 send_type || send_path ||
1138 receive_interface || receive_member || receive_error || receive_sender ||
1139 receive_type || receive_path || eavesdrop ||
1140 send_requested_reply || receive_requested_reply ||
1141 own || user || group))
1142 {
1143 dbus_set_error (error, DBUS_ERROR_FAILED,
1144 "Element <%s> must have one or more attributes",
1145 element_name);
1146 return FALSE;
1147 }
1148
1149 if ((send_member && (send_interface == NULL && send_path == NULL)) ||
1150 (receive_member && (receive_interface == NULL && receive_path == NULL)))
1151 {
1152 dbus_set_error (error, DBUS_ERROR_FAILED,
1153 "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.",
1154 element_name);
1155 return FALSE;
1156 }
1157
1158 /* Allowed combinations of elements are:
1159 *
1160 * base, must be all send or all receive:
1161 * nothing
1162 * interface
1163 * interface + member
1164 * error
1165 *
1166 * base send_ can combine with send_destination, send_path, send_type, send_requested_reply
1167 * base receive_ with receive_sender, receive_path, receive_type, receive_requested_reply, eavesdrop
1168 *
1169 * user, group, own must occur alone
1170 *
1171 * Pretty sure the below stuff is broken, FIXME think about it more.
1172 */
1173
1174 if (((send_interface && send_error) ||
1175 (send_interface && receive_interface) ||
1176 (send_interface && receive_member) ||
1177 (send_interface && receive_error) ||
1178 (send_interface && receive_sender) ||
1179 (send_interface && eavesdrop) ||
1180 (send_interface && receive_requested_reply) ||
1181 (send_interface && own) ||
1182 (send_interface && user) ||
1183 (send_interface && group)) ||
1184
1185 ((send_member && send_error) ||
1186 (send_member && receive_interface) ||
1187 (send_member && receive_member) ||
1188 (send_member && receive_error) ||
1189 (send_member && receive_sender) ||
1190 (send_member && eavesdrop) ||
1191 (send_member && receive_requested_reply) ||
1192 (send_member && own) ||
1193 (send_member && user) ||
1194 (send_member && group)) ||
1195
1196 ((send_error && receive_interface) ||
1197 (send_error && receive_member) ||
1198 (send_error && receive_error) ||
1199 (send_error && receive_sender) ||
1200 (send_error && eavesdrop) ||
1201 (send_error && receive_requested_reply) ||
1202 (send_error && own) ||
1203 (send_error && user) ||
1204 (send_error && group)) ||
1205
1206 ((send_destination && receive_interface) ||
1207 (send_destination && receive_member) ||
1208 (send_destination && receive_error) ||
1209 (send_destination && receive_sender) ||
1210 (send_destination && eavesdrop) ||
1211 (send_destination && receive_requested_reply) ||
1212 (send_destination && own) ||
1213 (send_destination && user) ||
1214 (send_destination && group)) ||
1215
1216 ((send_type && receive_interface) ||
1217 (send_type && receive_member) ||
1218 (send_type && receive_error) ||
1219 (send_type && receive_sender) ||
1220 (send_type && eavesdrop) ||
1221 (send_type && receive_requested_reply) ||
1222 (send_type && own) ||
1223 (send_type && user) ||
1224 (send_type && group)) ||
1225
1226 ((send_path && receive_interface) ||
1227 (send_path && receive_member) ||
1228 (send_path && receive_error) ||
1229 (send_path && receive_sender) ||
1230 (send_path && eavesdrop) ||
1231 (send_path && receive_requested_reply) ||
1232 (send_path && own) ||
1233 (send_path && user) ||
1234 (send_path && group)) ||
1235
1236 ((send_requested_reply && receive_interface) ||
1237 (send_requested_reply && receive_member) ||
1238 (send_requested_reply && receive_error) ||
1239 (send_requested_reply && receive_sender) ||
1240 (send_requested_reply && eavesdrop) ||
1241 (send_requested_reply && receive_requested_reply) ||
1242 (send_requested_reply && own) ||
1243 (send_requested_reply && user) ||
1244 (send_requested_reply && group)) ||
1245
1246 ((receive_interface && receive_error) ||
1247 (receive_interface && own) ||
1248 (receive_interface && user) ||
1249 (receive_interface && group)) ||
1250
1251 ((receive_member && receive_error) ||
1252 (receive_member && own) ||
1253 (receive_member && user) ||
1254 (receive_member && group)) ||
1255
1256 ((receive_error && own) ||
1257 (receive_error && user) ||
1258 (receive_error && group)) ||
1259
1260 ((eavesdrop && own) ||
1261 (eavesdrop && user) ||
1262 (eavesdrop && group)) ||
1263
1264 ((receive_requested_reply && own) ||
1265 (receive_requested_reply && user) ||
1266 (receive_requested_reply && group)) ||
1267
1268 ((own && user) ||
1269 (own && group)) ||
1270
1271 ((user && group)))
1272 {
1273 dbus_set_error (error, DBUS_ERROR_FAILED,
1274 "Invalid combination of attributes on element <%s>",
1275 element_name);
1276 return FALSE;
1277 }
1278
1279 rule = NULL;
1280
1281 /* In BusPolicyRule, NULL represents wildcard.
1282 * In the config file, '*' represents it.
1283 */
1284 #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
1285
1286 if (send_interface || send_member || send_error || send_destination ||
1287 send_path || send_type || send_requested_reply)
1288 {
1289 int message_type;
1290
1291 if (IS_WILDCARD (send_interface))
1292 send_interface = NULL;
1293 if (IS_WILDCARD (send_member))
1294 send_member = NULL;
1295 if (IS_WILDCARD (send_error))
1296 send_error = NULL;
1297 if (IS_WILDCARD (send_destination))
1298 send_destination = NULL;
1299 if (IS_WILDCARD (send_path))
1300 send_path = NULL;
1301 if (IS_WILDCARD (send_type))
1302 send_type = NULL;
1303
1304 message_type = DBUS_MESSAGE_TYPE_INVALID;
1305 if (send_type != NULL)
1306 {
1307 message_type = dbus_message_type_from_string (send_type);
1308 if (message_type == DBUS_MESSAGE_TYPE_INVALID)
1309 {
1310 dbus_set_error (error, DBUS_ERROR_FAILED,
1311 "Bad message type \"%s\"",
1312 send_type);
1313 return FALSE;
1314 }
1315 }
1316
1317 if (send_requested_reply &&
1318 !(strcmp (send_requested_reply, "true") == 0 ||
1319 strcmp (send_requested_reply, "false") == 0))
1320 {
1321 dbus_set_error (error, DBUS_ERROR_FAILED,
1322 "Bad value \"%s\" for %s attribute, must be true or false",
1323 "send_requested_reply", send_requested_reply);
1324 return FALSE;
1325 }
1326
1327 rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow);
1328 if (rule == NULL)
1329 goto nomem;
1330
1331 if (send_requested_reply)
1332 rule->d.send.requested_reply = (strcmp (send_requested_reply, "true") == 0);
1333
1334 rule->d.send.message_type = message_type;
1335 rule->d.send.path = _dbus_strdup (send_path);
1336 rule->d.send.interface = _dbus_strdup (send_interface);
1337 rule->d.send.member = _dbus_strdup (send_member);
1338 rule->d.send.error = _dbus_strdup (send_error);
1339 rule->d.send.destination = _dbus_strdup (send_destination);
1340 if (send_path && rule->d.send.path == NULL)
1341 goto nomem;
1342 if (send_interface && rule->d.send.interface == NULL)
1343 goto nomem;
1344 if (send_member && rule->d.send.member == NULL)
1345 goto nomem;
1346 if (send_error && rule->d.send.error == NULL)
1347 goto nomem;
1348 if (send_destination && rule->d.send.destination == NULL)
1349 goto nomem;
1350 }
1351 else if (receive_interface || receive_member || receive_error || receive_sender ||
1352 receive_path || receive_type || eavesdrop || receive_requested_reply)
1353 {
1354 int message_type;
1355
1356 if (IS_WILDCARD (receive_interface))
1357 receive_interface = NULL;
1358 if (IS_WILDCARD (receive_member))
1359 receive_member = NULL;
1360 if (IS_WILDCARD (receive_error))
1361 receive_error = NULL;
1362 if (IS_WILDCARD (receive_sender))
1363 receive_sender = NULL;
1364 if (IS_WILDCARD (receive_path))
1365 receive_path = NULL;
1366 if (IS_WILDCARD (receive_type))
1367 receive_type = NULL;
1368
1369 message_type = DBUS_MESSAGE_TYPE_INVALID;
1370 if (receive_type != NULL)
1371 {
1372 message_type = dbus_message_type_from_string (receive_type);
1373 if (message_type == DBUS_MESSAGE_TYPE_INVALID)
1374 {
1375 dbus_set_error (error, DBUS_ERROR_FAILED,
1376 "Bad message type \"%s\"",
1377 receive_type);
1378 return FALSE;
1379 }
1380 }
1381
1382
1383 if (eavesdrop &&
1384 !(strcmp (eavesdrop, "true") == 0 ||
1385 strcmp (eavesdrop, "false") == 0))
1386 {
1387 dbus_set_error (error, DBUS_ERROR_FAILED,
1388 "Bad value \"%s\" for %s attribute, must be true or false",
1389 "eavesdrop", eavesdrop);
1390 return FALSE;
1391 }
1392
1393 if (receive_requested_reply &&
1394 !(strcmp (receive_requested_reply, "true") == 0 ||
1395 strcmp (receive_requested_reply, "false") == 0))
1396 {
1397 dbus_set_error (error, DBUS_ERROR_FAILED,
1398 "Bad value \"%s\" for %s attribute, must be true or false",
1399 "receive_requested_reply", receive_requested_reply);
1400 return FALSE;
1401 }
1402
1403 rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow);
1404 if (rule == NULL)
1405 goto nomem;
1406
1407 if (eavesdrop)
1408 rule->d.receive.eavesdrop = (strcmp (eavesdrop, "true") == 0);
1409
1410 if (receive_requested_reply)
1411 rule->d.receive.requested_reply = (strcmp (receive_requested_reply, "true") == 0);
1412
1413 rule->d.receive.message_type = message_type;
1414 rule->d.receive.path = _dbus_strdup (receive_path);
1415 rule->d.receive.interface = _dbus_strdup (receive_interface);
1416 rule->d.receive.member = _dbus_strdup (receive_member);
1417 rule->d.receive.error = _dbus_strdup (receive_error);
1418 rule->d.receive.origin = _dbus_strdup (receive_sender);
1419
1420 if (receive_path && rule->d.receive.path == NULL)
1421 goto nomem;
1422 if (receive_interface && rule->d.receive.interface == NULL)
1423 goto nomem;
1424 if (receive_member && rule->d.receive.member == NULL)
1425 goto nomem;
1426 if (receive_error && rule->d.receive.error == NULL)
1427 goto nomem;
1428 if (receive_sender && rule->d.receive.origin == NULL)
1429 goto nomem;
1430 }
1431 else if (own)
1432 {
1433 rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow);
1434 if (rule == NULL)
1435 goto nomem;
1436
1437 if (IS_WILDCARD (own))
1438 own = NULL;
1439
1440 rule->d.own.service_name = _dbus_strdup (own);
1441 if (own && rule->d.own.service_name == NULL)
1442 goto nomem;
1443 }
1444 else if (user)
1445 {
1446 if (IS_WILDCARD (user))
1447 {
1448 rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
1449 if (rule == NULL)
1450 goto nomem;
1451
1452 rule->d.user.uid = DBUS_UID_UNSET;
1453 }
1454 else
1455 {
1456 DBusString username;
1457 dbus_uid_t uid;
1458
1459 _dbus_string_init_const (&username, user);
1460
1461 if (_dbus_get_user_id (&username, &uid))
1462 {
1463 rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
1464 if (rule == NULL)
1465 goto nomem;
1466
1467 rule->d.user.uid = uid;
1468 }
1469 else
1470 {
1471 _dbus_warn ("Unknown username \"%s\" on element <%s>\n",
1472 user, element_name);
1473 }
1474 }
1475 }
1476 else if (group)
1477 {
1478 if (IS_WILDCARD (group))
1479 {
1480 rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
1481 if (rule == NULL)
1482 goto nomem;
1483
1484 rule->d.group.gid = DBUS_GID_UNSET;
1485 }
1486 else
1487 {
1488 DBusString groupname;
1489 dbus_gid_t gid;
1490
1491 _dbus_string_init_const (&groupname, group);
1492
1493 if (_dbus_get_user_id (&groupname, &gid))
1494 {
1495 rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
1496 if (rule == NULL)
1497 goto nomem;
1498
1499 rule->d.group.gid = gid;
1500 }
1501 else
1502 {
1503 _dbus_warn ("Unknown group \"%s\" on element <%s>\n",
1504 group, element_name);
1505 }
1506 }
1507 }
1508 else
1509 _dbus_assert_not_reached ("Did not handle some combination of attributes on <allow> or <deny>");
1510
1511 if (rule != NULL)
1512 {
1513 Element *pe;
1514
1515 pe = peek_element (parser);
1516 _dbus_assert (pe != NULL);
1517 _dbus_assert (pe->type == ELEMENT_POLICY);
1518
1519 switch (pe->d.policy.type)
1520 {
1521 case POLICY_IGNORED:
1522 /* drop the rule on the floor */
1523 break;
1524
1525 case POLICY_DEFAULT:
1526 if (!bus_policy_append_default_rule (parser->policy, rule))
1527 goto nomem;
1528 break;
1529 case POLICY_MANDATORY:
1530 if (!bus_policy_append_mandatory_rule (parser->policy, rule))
1531 goto nomem;
1532 break;
1533 case POLICY_USER:
1534 if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1535 {
1536 dbus_set_error (error, DBUS_ERROR_FAILED,
1537 "<%s> rule cannot be per-user because it has bus-global semantics",
1538 element_name);
1539 goto failed;
1540 }
1541
1542 if (!bus_policy_append_user_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
1543 rule))
1544 goto nomem;
1545 break;
1546 case POLICY_GROUP:
1547 if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1548 {
1549 dbus_set_error (error, DBUS_ERROR_FAILED,
1550 "<%s> rule cannot be per-group because it has bus-global semantics",
1551 element_name);
1552 goto failed;
1553 }
1554
1555 if (!bus_policy_append_group_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
1556 rule))
1557 goto nomem;
1558 break;
1559
1560
1561 case POLICY_CONSOLE:
1562 if (!bus_policy_append_console_rule (parser->policy, pe->d.policy.gid_uid_or_at_console,
1563 rule))
1564 goto nomem;
1565 break;
1566 }
1567
1568 bus_policy_rule_unref (rule);
1569 rule = NULL;
1570 }
1571
1572 return TRUE;
1573
1574 nomem:
1575 BUS_SET_OOM (error);
1576 failed:
1577 if (rule)
1578 bus_policy_rule_unref (rule);
1579 return FALSE;
1580 }
1581
1582 static dbus_bool_t
start_policy_child(BusConfigParser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,DBusError * error)1583 start_policy_child (BusConfigParser *parser,
1584 const char *element_name,
1585 const char **attribute_names,
1586 const char **attribute_values,
1587 DBusError *error)
1588 {
1589 if (strcmp (element_name, "allow") == 0)
1590 {
1591 if (!append_rule_from_element (parser, element_name,
1592 attribute_names, attribute_values,
1593 TRUE, error))
1594 return FALSE;
1595
1596 if (push_element (parser, ELEMENT_ALLOW) == NULL)
1597 {
1598 BUS_SET_OOM (error);
1599 return FALSE;
1600 }
1601
1602 return TRUE;
1603 }
1604 else if (strcmp (element_name, "deny") == 0)
1605 {
1606 if (!append_rule_from_element (parser, element_name,
1607 attribute_names, attribute_values,
1608 FALSE, error))
1609 return FALSE;
1610
1611 if (push_element (parser, ELEMENT_DENY) == NULL)
1612 {
1613 BUS_SET_OOM (error);
1614 return FALSE;
1615 }
1616
1617 return TRUE;
1618 }
1619 else
1620 {
1621 dbus_set_error (error, DBUS_ERROR_FAILED,
1622 "Element <%s> not allowed inside <%s> in configuration file",
1623 element_name, "policy");
1624 return FALSE;
1625 }
1626 }
1627
1628 static dbus_bool_t
start_selinux_child(BusConfigParser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,DBusError * error)1629 start_selinux_child (BusConfigParser *parser,
1630 const char *element_name,
1631 const char **attribute_names,
1632 const char **attribute_values,
1633 DBusError *error)
1634 {
1635 char *own_copy;
1636 char *context_copy;
1637
1638 own_copy = NULL;
1639 context_copy = NULL;
1640
1641 if (strcmp (element_name, "associate") == 0)
1642 {
1643 const char *own;
1644 const char *context;
1645
1646 if (!locate_attributes (parser, "associate",
1647 attribute_names,
1648 attribute_values,
1649 error,
1650 "own", &own,
1651 "context", &context,
1652 NULL))
1653 return FALSE;
1654
1655 if (push_element (parser, ELEMENT_ASSOCIATE) == NULL)
1656 {
1657 BUS_SET_OOM (error);
1658 return FALSE;
1659 }
1660
1661 if (own == NULL || context == NULL)
1662 {
1663 dbus_set_error (error, DBUS_ERROR_FAILED,
1664 "Element <associate> must have attributes own=\"<servicename>\" and context=\"<selinux context>\"");
1665 return FALSE;
1666 }
1667
1668 own_copy = _dbus_strdup (own);
1669 if (own_copy == NULL)
1670 goto oom;
1671 context_copy = _dbus_strdup (context);
1672 if (context_copy == NULL)
1673 goto oom;
1674
1675 if (!_dbus_hash_table_insert_string (parser->service_context_table,
1676 own_copy, context_copy))
1677 goto oom;
1678
1679 return TRUE;
1680 }
1681 else
1682 {
1683 dbus_set_error (error, DBUS_ERROR_FAILED,
1684 "Element <%s> not allowed inside <%s> in configuration file",
1685 element_name, "selinux");
1686 return FALSE;
1687 }
1688
1689 oom:
1690 if (own_copy)
1691 dbus_free (own_copy);
1692
1693 if (context_copy)
1694 dbus_free (context_copy);
1695
1696 BUS_SET_OOM (error);
1697 return FALSE;
1698 }
1699
1700 dbus_bool_t
bus_config_parser_start_element(BusConfigParser * parser,const char * element_name,const char ** attribute_names,const char ** attribute_values,DBusError * error)1701 bus_config_parser_start_element (BusConfigParser *parser,
1702 const char *element_name,
1703 const char **attribute_names,
1704 const char **attribute_values,
1705 DBusError *error)
1706 {
1707 ElementType t;
1708
1709 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1710
1711 /* printf ("START: %s\n", element_name); */
1712
1713 t = top_element_type (parser);
1714
1715 if (t == ELEMENT_NONE)
1716 {
1717 if (strcmp (element_name, "busconfig") == 0)
1718 {
1719 if (!check_no_attributes (parser, "busconfig", attribute_names, attribute_values, error))
1720 return FALSE;
1721
1722 if (push_element (parser, ELEMENT_BUSCONFIG) == NULL)
1723 {
1724 BUS_SET_OOM (error);
1725 return FALSE;
1726 }
1727
1728 return TRUE;
1729 }
1730 else
1731 {
1732 dbus_set_error (error, DBUS_ERROR_FAILED,
1733 "Unknown element <%s> at root of configuration file",
1734 element_name);
1735 return FALSE;
1736 }
1737 }
1738 else if (t == ELEMENT_BUSCONFIG)
1739 {
1740 return start_busconfig_child (parser, element_name,
1741 attribute_names, attribute_values,
1742 error);
1743 }
1744 else if (t == ELEMENT_POLICY)
1745 {
1746 return start_policy_child (parser, element_name,
1747 attribute_names, attribute_values,
1748 error);
1749 }
1750 else if (t == ELEMENT_SELINUX)
1751 {
1752 return start_selinux_child (parser, element_name,
1753 attribute_names, attribute_values,
1754 error);
1755 }
1756 else
1757 {
1758 dbus_set_error (error, DBUS_ERROR_FAILED,
1759 "Element <%s> is not allowed in this context",
1760 element_name);
1761 return FALSE;
1762 }
1763 }
1764
1765 static dbus_bool_t
set_limit(BusConfigParser * parser,const char * name,long value,DBusError * error)1766 set_limit (BusConfigParser *parser,
1767 const char *name,
1768 long value,
1769 DBusError *error)
1770 {
1771 dbus_bool_t must_be_positive;
1772 dbus_bool_t must_be_int;
1773
1774 must_be_int = FALSE;
1775 must_be_positive = FALSE;
1776
1777 if (strcmp (name, "max_incoming_bytes") == 0)
1778 {
1779 must_be_positive = TRUE;
1780 parser->limits.max_incoming_bytes = value;
1781 }
1782 else if (strcmp (name, "max_outgoing_bytes") == 0)
1783 {
1784 must_be_positive = TRUE;
1785 parser->limits.max_outgoing_bytes = value;
1786 }
1787 else if (strcmp (name, "max_message_size") == 0)
1788 {
1789 must_be_positive = TRUE;
1790 parser->limits.max_message_size = value;
1791 }
1792 else if (strcmp (name, "service_start_timeout") == 0)
1793 {
1794 must_be_positive = TRUE;
1795 must_be_int = TRUE;
1796 parser->limits.activation_timeout = value;
1797 }
1798 else if (strcmp (name, "auth_timeout") == 0)
1799 {
1800 must_be_positive = TRUE;
1801 must_be_int = TRUE;
1802 parser->limits.auth_timeout = value;
1803 }
1804 else if (strcmp (name, "reply_timeout") == 0)
1805 {
1806 must_be_positive = TRUE;
1807 must_be_int = TRUE;
1808 parser->limits.reply_timeout = value;
1809 }
1810 else if (strcmp (name, "max_completed_connections") == 0)
1811 {
1812 must_be_positive = TRUE;
1813 must_be_int = TRUE;
1814 parser->limits.max_completed_connections = value;
1815 }
1816 else if (strcmp (name, "max_incomplete_connections") == 0)
1817 {
1818 must_be_positive = TRUE;
1819 must_be_int = TRUE;
1820 parser->limits.max_incomplete_connections = value;
1821 }
1822 else if (strcmp (name, "max_connections_per_user") == 0)
1823 {
1824 must_be_positive = TRUE;
1825 must_be_int = TRUE;
1826 parser->limits.max_connections_per_user = value;
1827 }
1828 else if (strcmp (name, "max_pending_service_starts") == 0)
1829 {
1830 must_be_positive = TRUE;
1831 must_be_int = TRUE;
1832 parser->limits.max_pending_activations = value;
1833 }
1834 else if (strcmp (name, "max_names_per_connection") == 0)
1835 {
1836 must_be_positive = TRUE;
1837 must_be_int = TRUE;
1838 parser->limits.max_services_per_connection = value;
1839 }
1840 else if (strcmp (name, "max_match_rules_per_connection") == 0)
1841 {
1842 must_be_positive = TRUE;
1843 must_be_int = TRUE;
1844 parser->limits.max_match_rules_per_connection = value;
1845 }
1846 else if (strcmp (name, "max_replies_per_connection") == 0)
1847 {
1848 must_be_positive = TRUE;
1849 must_be_int = TRUE;
1850 parser->limits.max_replies_per_connection = value;
1851 }
1852 else
1853 {
1854 dbus_set_error (error, DBUS_ERROR_FAILED,
1855 "There is no limit called \"%s\"\n",
1856 name);
1857 return FALSE;
1858 }
1859
1860 if (must_be_positive && value < 0)
1861 {
1862 dbus_set_error (error, DBUS_ERROR_FAILED,
1863 "<limit name=\"%s\"> must be a positive number\n",
1864 name);
1865 return FALSE;
1866 }
1867
1868 if (must_be_int &&
1869 (value < _DBUS_INT_MIN || value > _DBUS_INT_MAX))
1870 {
1871 dbus_set_error (error, DBUS_ERROR_FAILED,
1872 "<limit name=\"%s\"> value is too large\n",
1873 name);
1874 return FALSE;
1875 }
1876
1877 return TRUE;
1878 }
1879
1880 dbus_bool_t
bus_config_parser_end_element(BusConfigParser * parser,const char * element_name,DBusError * error)1881 bus_config_parser_end_element (BusConfigParser *parser,
1882 const char *element_name,
1883 DBusError *error)
1884 {
1885 ElementType t;
1886 const char *n;
1887 Element *e;
1888
1889 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1890
1891 /* printf ("END: %s\n", element_name); */
1892
1893 t = top_element_type (parser);
1894
1895 if (t == ELEMENT_NONE)
1896 {
1897 /* should probably be an assertion failure but
1898 * being paranoid about XML parsers
1899 */
1900 dbus_set_error (error, DBUS_ERROR_FAILED,
1901 "XML parser ended element with no element on the stack");
1902 return FALSE;
1903 }
1904
1905 n = element_type_to_name (t);
1906 _dbus_assert (n != NULL);
1907 if (strcmp (n, element_name) != 0)
1908 {
1909 /* should probably be an assertion failure but
1910 * being paranoid about XML parsers
1911 */
1912 dbus_set_error (error, DBUS_ERROR_FAILED,
1913 "XML element <%s> ended but topmost element on the stack was <%s>",
1914 element_name, n);
1915 return FALSE;
1916 }
1917
1918 e = peek_element (parser);
1919 _dbus_assert (e != NULL);
1920
1921 switch (e->type)
1922 {
1923 case ELEMENT_NONE:
1924 _dbus_assert_not_reached ("element in stack has no type");
1925 break;
1926
1927 case ELEMENT_INCLUDE:
1928 case ELEMENT_USER:
1929 case ELEMENT_TYPE:
1930 case ELEMENT_LISTEN:
1931 case ELEMENT_PIDFILE:
1932 case ELEMENT_AUTH:
1933 case ELEMENT_SERVICEDIR:
1934 case ELEMENT_INCLUDEDIR:
1935 case ELEMENT_LIMIT:
1936 if (!e->had_content)
1937 {
1938 dbus_set_error (error, DBUS_ERROR_FAILED,
1939 "XML element <%s> was expected to have content inside it",
1940 element_type_to_name (e->type));
1941 return FALSE;
1942 }
1943
1944 if (e->type == ELEMENT_LIMIT)
1945 {
1946 if (!set_limit (parser, e->d.limit.name, e->d.limit.value,
1947 error))
1948 return FALSE;
1949 }
1950 break;
1951
1952 case ELEMENT_BUSCONFIG:
1953 case ELEMENT_POLICY:
1954 case ELEMENT_ALLOW:
1955 case ELEMENT_DENY:
1956 case ELEMENT_FORK:
1957 case ELEMENT_SELINUX:
1958 case ELEMENT_ASSOCIATE:
1959 case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
1960 break;
1961 }
1962
1963 pop_element (parser);
1964
1965 return TRUE;
1966 }
1967
1968 static dbus_bool_t
all_whitespace(const DBusString * str)1969 all_whitespace (const DBusString *str)
1970 {
1971 int i;
1972
1973 _dbus_string_skip_white (str, 0, &i);
1974
1975 return i == _dbus_string_get_length (str);
1976 }
1977
1978 static dbus_bool_t
make_full_path(const DBusString * basedir,const DBusString * filename,DBusString * full_path)1979 make_full_path (const DBusString *basedir,
1980 const DBusString *filename,
1981 DBusString *full_path)
1982 {
1983 if (_dbus_path_is_absolute (filename))
1984 {
1985 return _dbus_string_copy (filename, 0, full_path, 0);
1986 }
1987 else
1988 {
1989 if (!_dbus_string_copy (basedir, 0, full_path, 0))
1990 return FALSE;
1991
1992 if (!_dbus_concat_dir_and_file (full_path, filename))
1993 return FALSE;
1994
1995 return TRUE;
1996 }
1997 }
1998
1999 static dbus_bool_t
include_file(BusConfigParser * parser,const DBusString * filename,dbus_bool_t ignore_missing,DBusError * error)2000 include_file (BusConfigParser *parser,
2001 const DBusString *filename,
2002 dbus_bool_t ignore_missing,
2003 DBusError *error)
2004 {
2005 /* FIXME good test case for this would load each config file in the
2006 * test suite both alone, and as an include, and check
2007 * that the result is the same
2008 */
2009 BusConfigParser *included;
2010 const char *filename_str;
2011 DBusError tmp_error;
2012
2013 dbus_error_init (&tmp_error);
2014
2015 filename_str = _dbus_string_get_const_data (filename);
2016
2017 /* Check to make sure this file hasn't already been included. */
2018 if (seen_include (parser, filename))
2019 {
2020 dbus_set_error (error, DBUS_ERROR_FAILED,
2021 "Circular inclusion of file '%s'",
2022 filename_str);
2023 return FALSE;
2024 }
2025
2026 if (! _dbus_list_append (&parser->included_files, (void *) filename_str))
2027 {
2028 BUS_SET_OOM (error);
2029 return FALSE;
2030 }
2031
2032 /* Since parser is passed in as the parent, included
2033 inherits parser's limits. */
2034 included = bus_config_load (filename, FALSE, parser, &tmp_error);
2035
2036 _dbus_list_pop_last (&parser->included_files);
2037
2038 if (included == NULL)
2039 {
2040 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
2041
2042 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) &&
2043 ignore_missing)
2044 {
2045 dbus_error_free (&tmp_error);
2046 return TRUE;
2047 }
2048 else
2049 {
2050 dbus_move_error (&tmp_error, error);
2051 return FALSE;
2052 }
2053 }
2054 else
2055 {
2056 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
2057
2058 if (!merge_included (parser, included, error))
2059 {
2060 bus_config_parser_unref (included);
2061 return FALSE;
2062 }
2063
2064 /* Copy included's limits back to parser. */
2065 parser->limits = included->limits;
2066
2067 bus_config_parser_unref (included);
2068 return TRUE;
2069 }
2070 }
2071
2072 static dbus_bool_t
include_dir(BusConfigParser * parser,const DBusString * dirname,DBusError * error)2073 include_dir (BusConfigParser *parser,
2074 const DBusString *dirname,
2075 DBusError *error)
2076 {
2077 DBusString filename;
2078 dbus_bool_t retval;
2079 DBusError tmp_error;
2080 DBusDirIter *dir;
2081 char *s;
2082
2083 if (!_dbus_string_init (&filename))
2084 {
2085 BUS_SET_OOM (error);
2086 return FALSE;
2087 }
2088
2089 retval = FALSE;
2090
2091 dir = _dbus_directory_open (dirname, error);
2092
2093 if (dir == NULL)
2094 goto failed;
2095
2096 dbus_error_init (&tmp_error);
2097 while (_dbus_directory_get_next_file (dir, &filename, &tmp_error))
2098 {
2099 DBusString full_path;
2100
2101 if (!_dbus_string_init (&full_path))
2102 {
2103 BUS_SET_OOM (error);
2104 goto failed;
2105 }
2106
2107 if (!_dbus_string_copy (dirname, 0, &full_path, 0))
2108 {
2109 BUS_SET_OOM (error);
2110 _dbus_string_free (&full_path);
2111 goto failed;
2112 }
2113
2114 if (!_dbus_concat_dir_and_file (&full_path, &filename))
2115 {
2116 BUS_SET_OOM (error);
2117 _dbus_string_free (&full_path);
2118 goto failed;
2119 }
2120
2121 if (_dbus_string_ends_with_c_str (&full_path, ".conf"))
2122 {
2123 if (!include_file (parser, &full_path, TRUE, error))
2124 {
2125 _dbus_string_free (&full_path);
2126 goto failed;
2127 }
2128 }
2129
2130 _dbus_string_free (&full_path);
2131 }
2132
2133 if (dbus_error_is_set (&tmp_error))
2134 {
2135 dbus_move_error (&tmp_error, error);
2136 goto failed;
2137 }
2138
2139
2140 if (!_dbus_string_copy_data (dirname, &s))
2141 {
2142 BUS_SET_OOM (error);
2143 goto failed;
2144 }
2145
2146 if (!_dbus_list_append (&parser->conf_dirs, s))
2147 {
2148 dbus_free (s);
2149 BUS_SET_OOM (error);
2150 goto failed;
2151 }
2152
2153 retval = TRUE;
2154
2155 failed:
2156 _dbus_string_free (&filename);
2157
2158 if (dir)
2159 _dbus_directory_close (dir);
2160
2161 return retval;
2162 }
2163
2164 dbus_bool_t
bus_config_parser_content(BusConfigParser * parser,const DBusString * content,DBusError * error)2165 bus_config_parser_content (BusConfigParser *parser,
2166 const DBusString *content,
2167 DBusError *error)
2168 {
2169 Element *e;
2170
2171 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2172
2173 #if 0
2174 {
2175 const char *c_str;
2176
2177 _dbus_string_get_const_data (content, &c_str);
2178
2179 printf ("CONTENT %d bytes: %s\n", _dbus_string_get_length (content), c_str);
2180 }
2181 #endif
2182
2183 e = peek_element (parser);
2184 if (e == NULL)
2185 {
2186 dbus_set_error (error, DBUS_ERROR_FAILED,
2187 "Text content outside of any XML element in configuration file");
2188 return FALSE;
2189 }
2190 else if (e->had_content)
2191 {
2192 _dbus_assert_not_reached ("Element had multiple content blocks");
2193 return FALSE;
2194 }
2195
2196 switch (top_element_type (parser))
2197 {
2198 case ELEMENT_NONE:
2199 _dbus_assert_not_reached ("element at top of stack has no type");
2200 return FALSE;
2201
2202 case ELEMENT_BUSCONFIG:
2203 case ELEMENT_POLICY:
2204 case ELEMENT_ALLOW:
2205 case ELEMENT_DENY:
2206 case ELEMENT_FORK:
2207 case ELEMENT_STANDARD_SESSION_SERVICEDIRS:
2208 case ELEMENT_SELINUX:
2209 case ELEMENT_ASSOCIATE:
2210 if (all_whitespace (content))
2211 return TRUE;
2212 else
2213 {
2214 dbus_set_error (error, DBUS_ERROR_FAILED,
2215 "No text content expected inside XML element %s in configuration file",
2216 element_type_to_name (top_element_type (parser)));
2217 return FALSE;
2218 }
2219
2220 case ELEMENT_PIDFILE:
2221 {
2222 char *s;
2223
2224 e->had_content = TRUE;
2225
2226 if (!_dbus_string_copy_data (content, &s))
2227 goto nomem;
2228
2229 dbus_free (parser->pidfile);
2230 parser->pidfile = s;
2231 }
2232 break;
2233
2234 case ELEMENT_INCLUDE:
2235 {
2236 DBusString full_path, selinux_policy_root;
2237
2238 e->had_content = TRUE;
2239
2240 if (e->d.include.if_selinux_enabled
2241 && !bus_selinux_enabled ())
2242 break;
2243
2244 if (!_dbus_string_init (&full_path))
2245 goto nomem;
2246
2247 if (e->d.include.selinux_root_relative)
2248 {
2249 if (!bus_selinux_get_policy_root ())
2250 {
2251 dbus_set_error (error, DBUS_ERROR_FAILED,
2252 "Could not determine SELinux policy root for relative inclusion");
2253 _dbus_string_free (&full_path);
2254 return FALSE;
2255 }
2256 _dbus_string_init_const (&selinux_policy_root,
2257 bus_selinux_get_policy_root ());
2258 if (!make_full_path (&selinux_policy_root, content, &full_path))
2259 {
2260 _dbus_string_free (&full_path);
2261 goto nomem;
2262 }
2263 }
2264 else if (!make_full_path (&parser->basedir, content, &full_path))
2265 {
2266 _dbus_string_free (&full_path);
2267 goto nomem;
2268 }
2269
2270 if (!include_file (parser, &full_path,
2271 e->d.include.ignore_missing, error))
2272 {
2273 _dbus_string_free (&full_path);
2274 return FALSE;
2275 }
2276
2277 _dbus_string_free (&full_path);
2278 }
2279 break;
2280
2281 case ELEMENT_INCLUDEDIR:
2282 {
2283 DBusString full_path;
2284
2285 e->had_content = TRUE;
2286
2287 if (!_dbus_string_init (&full_path))
2288 goto nomem;
2289
2290 if (!make_full_path (&parser->basedir, content, &full_path))
2291 {
2292 _dbus_string_free (&full_path);
2293 goto nomem;
2294 }
2295
2296 if (!include_dir (parser, &full_path, error))
2297 {
2298 _dbus_string_free (&full_path);
2299 return FALSE;
2300 }
2301
2302 _dbus_string_free (&full_path);
2303 }
2304 break;
2305
2306 case ELEMENT_USER:
2307 {
2308 char *s;
2309
2310 e->had_content = TRUE;
2311
2312 if (!_dbus_string_copy_data (content, &s))
2313 goto nomem;
2314
2315 dbus_free (parser->user);
2316 parser->user = s;
2317 }
2318 break;
2319
2320 case ELEMENT_TYPE:
2321 {
2322 char *s;
2323
2324 e->had_content = TRUE;
2325
2326 if (!_dbus_string_copy_data (content, &s))
2327 goto nomem;
2328
2329 dbus_free (parser->bus_type);
2330 parser->bus_type = s;
2331 }
2332 break;
2333
2334 case ELEMENT_LISTEN:
2335 {
2336 char *s;
2337
2338 e->had_content = TRUE;
2339
2340 if (!_dbus_string_copy_data (content, &s))
2341 goto nomem;
2342
2343 if (!_dbus_list_append (&parser->listen_on,
2344 s))
2345 {
2346 dbus_free (s);
2347 goto nomem;
2348 }
2349 }
2350 break;
2351
2352 case ELEMENT_AUTH:
2353 {
2354 char *s;
2355
2356 e->had_content = TRUE;
2357
2358 if (!_dbus_string_copy_data (content, &s))
2359 goto nomem;
2360
2361 if (!_dbus_list_append (&parser->mechanisms,
2362 s))
2363 {
2364 dbus_free (s);
2365 goto nomem;
2366 }
2367 }
2368 break;
2369
2370 case ELEMENT_SERVICEDIR:
2371 {
2372 char *s;
2373 DBusString full_path;
2374
2375 e->had_content = TRUE;
2376
2377 if (!_dbus_string_init (&full_path))
2378 goto nomem;
2379
2380 if (!make_full_path (&parser->basedir, content, &full_path))
2381 {
2382 _dbus_string_free (&full_path);
2383 goto nomem;
2384 }
2385
2386 if (!_dbus_string_copy_data (&full_path, &s))
2387 {
2388 _dbus_string_free (&full_path);
2389 goto nomem;
2390 }
2391
2392 if (!service_dirs_append_unique_or_free (&parser->service_dirs, s))
2393 {
2394 _dbus_string_free (&full_path);
2395 dbus_free (s);
2396 goto nomem;
2397 }
2398
2399 _dbus_string_free (&full_path);
2400 }
2401 break;
2402
2403 case ELEMENT_LIMIT:
2404 {
2405 long val;
2406
2407 e->had_content = TRUE;
2408
2409 val = 0;
2410 if (!_dbus_string_parse_int (content, 0, &val, NULL))
2411 {
2412 dbus_set_error (error, DBUS_ERROR_FAILED,
2413 "<limit name=\"%s\"> element has invalid value (could not parse as integer)",
2414 e->d.limit.name);
2415 return FALSE;
2416 }
2417
2418 e->d.limit.value = val;
2419
2420 _dbus_verbose ("Loaded value %ld for limit %s\n",
2421 e->d.limit.value,
2422 e->d.limit.name);
2423 }
2424 break;
2425 }
2426
2427 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2428 return TRUE;
2429
2430 nomem:
2431 BUS_SET_OOM (error);
2432 return FALSE;
2433 }
2434
2435 dbus_bool_t
bus_config_parser_finished(BusConfigParser * parser,DBusError * error)2436 bus_config_parser_finished (BusConfigParser *parser,
2437 DBusError *error)
2438 {
2439 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
2440
2441 if (parser->stack != NULL)
2442 {
2443 dbus_set_error (error, DBUS_ERROR_FAILED,
2444 "Element <%s> was not closed in configuration file",
2445 element_type_to_name (top_element_type (parser)));
2446
2447 return FALSE;
2448 }
2449
2450 if (parser->is_toplevel && parser->listen_on == NULL)
2451 {
2452 dbus_set_error (error, DBUS_ERROR_FAILED,
2453 "Configuration file needs one or more <listen> elements giving addresses");
2454 return FALSE;
2455 }
2456
2457 return TRUE;
2458 }
2459
2460 const char*
bus_config_parser_get_user(BusConfigParser * parser)2461 bus_config_parser_get_user (BusConfigParser *parser)
2462 {
2463 return parser->user;
2464 }
2465
2466 const char*
bus_config_parser_get_type(BusConfigParser * parser)2467 bus_config_parser_get_type (BusConfigParser *parser)
2468 {
2469 return parser->bus_type;
2470 }
2471
2472 DBusList**
bus_config_parser_get_addresses(BusConfigParser * parser)2473 bus_config_parser_get_addresses (BusConfigParser *parser)
2474 {
2475 return &parser->listen_on;
2476 }
2477
2478 DBusList**
bus_config_parser_get_mechanisms(BusConfigParser * parser)2479 bus_config_parser_get_mechanisms (BusConfigParser *parser)
2480 {
2481 return &parser->mechanisms;
2482 }
2483
2484 DBusList**
bus_config_parser_get_service_dirs(BusConfigParser * parser)2485 bus_config_parser_get_service_dirs (BusConfigParser *parser)
2486 {
2487 return &parser->service_dirs;
2488 }
2489
2490 DBusList**
bus_config_parser_get_conf_dirs(BusConfigParser * parser)2491 bus_config_parser_get_conf_dirs (BusConfigParser *parser)
2492 {
2493 return &parser->conf_dirs;
2494 }
2495
2496 dbus_bool_t
bus_config_parser_get_fork(BusConfigParser * parser)2497 bus_config_parser_get_fork (BusConfigParser *parser)
2498 {
2499 return parser->fork;
2500 }
2501
2502 const char *
bus_config_parser_get_pidfile(BusConfigParser * parser)2503 bus_config_parser_get_pidfile (BusConfigParser *parser)
2504 {
2505 return parser->pidfile;
2506 }
2507
2508 BusPolicy*
bus_config_parser_steal_policy(BusConfigParser * parser)2509 bus_config_parser_steal_policy (BusConfigParser *parser)
2510 {
2511 BusPolicy *policy;
2512
2513 _dbus_assert (parser->policy != NULL); /* can only steal the policy 1 time */
2514
2515 policy = parser->policy;
2516
2517 parser->policy = NULL;
2518
2519 return policy;
2520 }
2521
2522 /* Overwrite any limits that were set in the configuration file */
2523 void
bus_config_parser_get_limits(BusConfigParser * parser,BusLimits * limits)2524 bus_config_parser_get_limits (BusConfigParser *parser,
2525 BusLimits *limits)
2526 {
2527 *limits = parser->limits;
2528 }
2529
2530 DBusHashTable*
bus_config_parser_steal_service_context_table(BusConfigParser * parser)2531 bus_config_parser_steal_service_context_table (BusConfigParser *parser)
2532 {
2533 DBusHashTable *table;
2534
2535 _dbus_assert (parser->service_context_table != NULL); /* can only steal once */
2536
2537 table = parser->service_context_table;
2538
2539 parser->service_context_table = NULL;
2540
2541 return table;
2542 }
2543
2544 #ifdef DBUS_BUILD_TESTS
2545 #include <stdio.h>
2546
2547 typedef enum
2548 {
2549 VALID,
2550 INVALID,
2551 UNKNOWN
2552 } Validity;
2553
2554 static dbus_bool_t
do_load(const DBusString * full_path,Validity validity,dbus_bool_t oom_possible)2555 do_load (const DBusString *full_path,
2556 Validity validity,
2557 dbus_bool_t oom_possible)
2558 {
2559 BusConfigParser *parser;
2560 DBusError error;
2561
2562 dbus_error_init (&error);
2563
2564 parser = bus_config_load (full_path, TRUE, NULL, &error);
2565 if (parser == NULL)
2566 {
2567 _DBUS_ASSERT_ERROR_IS_SET (&error);
2568
2569 if (oom_possible &&
2570 dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2571 {
2572 _dbus_verbose ("Failed to load valid file due to OOM\n");
2573 dbus_error_free (&error);
2574 return TRUE;
2575 }
2576 else if (validity == VALID)
2577 {
2578 _dbus_warn ("Failed to load valid file but still had memory: %s\n",
2579 error.message);
2580
2581 dbus_error_free (&error);
2582 return FALSE;
2583 }
2584 else
2585 {
2586 dbus_error_free (&error);
2587 return TRUE;
2588 }
2589 }
2590 else
2591 {
2592 _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
2593
2594 bus_config_parser_unref (parser);
2595
2596 if (validity == INVALID)
2597 {
2598 _dbus_warn ("Accepted invalid file\n");
2599 return FALSE;
2600 }
2601
2602 return TRUE;
2603 }
2604 }
2605
2606 typedef struct
2607 {
2608 const DBusString *full_path;
2609 Validity validity;
2610 } LoaderOomData;
2611
2612 static dbus_bool_t
check_loader_oom_func(void * data)2613 check_loader_oom_func (void *data)
2614 {
2615 LoaderOomData *d = data;
2616
2617 return do_load (d->full_path, d->validity, TRUE);
2618 }
2619
2620 static dbus_bool_t
process_test_valid_subdir(const DBusString * test_base_dir,const char * subdir,Validity validity)2621 process_test_valid_subdir (const DBusString *test_base_dir,
2622 const char *subdir,
2623 Validity validity)
2624 {
2625 DBusString test_directory;
2626 DBusString filename;
2627 DBusDirIter *dir;
2628 dbus_bool_t retval;
2629 DBusError error;
2630
2631 retval = FALSE;
2632 dir = NULL;
2633
2634 if (!_dbus_string_init (&test_directory))
2635 _dbus_assert_not_reached ("didn't allocate test_directory\n");
2636
2637 _dbus_string_init_const (&filename, subdir);
2638
2639 if (!_dbus_string_copy (test_base_dir, 0,
2640 &test_directory, 0))
2641 _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
2642
2643 if (!_dbus_concat_dir_and_file (&test_directory, &filename))
2644 _dbus_assert_not_reached ("couldn't allocate full path");
2645
2646 _dbus_string_free (&filename);
2647 if (!_dbus_string_init (&filename))
2648 _dbus_assert_not_reached ("didn't allocate filename string\n");
2649
2650 dbus_error_init (&error);
2651 dir = _dbus_directory_open (&test_directory, &error);
2652 if (dir == NULL)
2653 {
2654 _dbus_warn ("Could not open %s: %s\n",
2655 _dbus_string_get_const_data (&test_directory),
2656 error.message);
2657 dbus_error_free (&error);
2658 goto failed;
2659 }
2660
2661 if (validity == VALID)
2662 printf ("Testing valid files:\n");
2663 else if (validity == INVALID)
2664 printf ("Testing invalid files:\n");
2665 else
2666 printf ("Testing unknown files:\n");
2667
2668 next:
2669 while (_dbus_directory_get_next_file (dir, &filename, &error))
2670 {
2671 DBusString full_path;
2672 LoaderOomData d;
2673
2674 if (!_dbus_string_init (&full_path))
2675 _dbus_assert_not_reached ("couldn't init string");
2676
2677 if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
2678 _dbus_assert_not_reached ("couldn't copy dir to full_path");
2679
2680 if (!_dbus_concat_dir_and_file (&full_path, &filename))
2681 _dbus_assert_not_reached ("couldn't concat file to dir");
2682
2683 if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
2684 {
2685 _dbus_verbose ("Skipping non-.conf file %s\n",
2686 _dbus_string_get_const_data (&filename));
2687 _dbus_string_free (&full_path);
2688 goto next;
2689 }
2690
2691 printf (" %s\n", _dbus_string_get_const_data (&filename));
2692
2693 _dbus_verbose (" expecting %s\n",
2694 validity == VALID ? "valid" :
2695 (validity == INVALID ? "invalid" :
2696 (validity == UNKNOWN ? "unknown" : "???")));
2697
2698 d.full_path = &full_path;
2699 d.validity = validity;
2700
2701 /* FIXME hackaround for an expat problem, see
2702 * https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=124747
2703 * http://freedesktop.org/pipermail/dbus/2004-May/001153.html
2704 */
2705 /* if (!_dbus_test_oom_handling ("config-loader", check_loader_oom_func, &d)) */
2706 if (!check_loader_oom_func (&d))
2707 _dbus_assert_not_reached ("test failed");
2708
2709 _dbus_string_free (&full_path);
2710 }
2711
2712 if (dbus_error_is_set (&error))
2713 {
2714 _dbus_warn ("Could not get next file in %s: %s\n",
2715 _dbus_string_get_const_data (&test_directory),
2716 error.message);
2717 dbus_error_free (&error);
2718 goto failed;
2719 }
2720
2721 retval = TRUE;
2722
2723 failed:
2724
2725 if (dir)
2726 _dbus_directory_close (dir);
2727 _dbus_string_free (&test_directory);
2728 _dbus_string_free (&filename);
2729
2730 return retval;
2731 }
2732
2733 static dbus_bool_t
bools_equal(dbus_bool_t a,dbus_bool_t b)2734 bools_equal (dbus_bool_t a,
2735 dbus_bool_t b)
2736 {
2737 return a ? b : !b;
2738 }
2739
2740 static dbus_bool_t
strings_equal_or_both_null(const char * a,const char * b)2741 strings_equal_or_both_null (const char *a,
2742 const char *b)
2743 {
2744 if (a == NULL || b == NULL)
2745 return a == b;
2746 else
2747 return !strcmp (a, b);
2748 }
2749
2750 static dbus_bool_t
elements_equal(const Element * a,const Element * b)2751 elements_equal (const Element *a,
2752 const Element *b)
2753 {
2754 if (a->type != b->type)
2755 return FALSE;
2756
2757 if (!bools_equal (a->had_content, b->had_content))
2758 return FALSE;
2759
2760 switch (a->type)
2761 {
2762
2763 case ELEMENT_INCLUDE:
2764 if (!bools_equal (a->d.include.ignore_missing,
2765 b->d.include.ignore_missing))
2766 return FALSE;
2767 break;
2768
2769 case ELEMENT_POLICY:
2770 if (a->d.policy.type != b->d.policy.type)
2771 return FALSE;
2772 if (a->d.policy.gid_uid_or_at_console != b->d.policy.gid_uid_or_at_console)
2773 return FALSE;
2774 break;
2775
2776 case ELEMENT_LIMIT:
2777 if (strcmp (a->d.limit.name, b->d.limit.name))
2778 return FALSE;
2779 if (a->d.limit.value != b->d.limit.value)
2780 return FALSE;
2781 break;
2782
2783 default:
2784 /* do nothing */
2785 break;
2786 }
2787
2788 return TRUE;
2789
2790 }
2791
2792 static dbus_bool_t
lists_of_elements_equal(DBusList * a,DBusList * b)2793 lists_of_elements_equal (DBusList *a,
2794 DBusList *b)
2795 {
2796 DBusList *ia;
2797 DBusList *ib;
2798
2799 ia = a;
2800 ib = b;
2801
2802 while (ia != NULL && ib != NULL)
2803 {
2804 if (elements_equal (ia->data, ib->data))
2805 return FALSE;
2806 ia = _dbus_list_get_next_link (&a, ia);
2807 ib = _dbus_list_get_next_link (&b, ib);
2808 }
2809
2810 return ia == NULL && ib == NULL;
2811 }
2812
2813 static dbus_bool_t
lists_of_c_strings_equal(DBusList * a,DBusList * b)2814 lists_of_c_strings_equal (DBusList *a,
2815 DBusList *b)
2816 {
2817 DBusList *ia;
2818 DBusList *ib;
2819
2820 ia = a;
2821 ib = b;
2822
2823 while (ia != NULL && ib != NULL)
2824 {
2825 if (strcmp (ia->data, ib->data))
2826 return FALSE;
2827 ia = _dbus_list_get_next_link (&a, ia);
2828 ib = _dbus_list_get_next_link (&b, ib);
2829 }
2830
2831 return ia == NULL && ib == NULL;
2832 }
2833
2834 static dbus_bool_t
limits_equal(const BusLimits * a,const BusLimits * b)2835 limits_equal (const BusLimits *a,
2836 const BusLimits *b)
2837 {
2838 return
2839 (a->max_incoming_bytes == b->max_incoming_bytes
2840 || a->max_outgoing_bytes == b->max_outgoing_bytes
2841 || a->max_message_size == b->max_message_size
2842 || a->activation_timeout == b->activation_timeout
2843 || a->auth_timeout == b->auth_timeout
2844 || a->max_completed_connections == b->max_completed_connections
2845 || a->max_incomplete_connections == b->max_incomplete_connections
2846 || a->max_connections_per_user == b->max_connections_per_user
2847 || a->max_pending_activations == b->max_pending_activations
2848 || a->max_services_per_connection == b->max_services_per_connection
2849 || a->max_match_rules_per_connection == b->max_match_rules_per_connection
2850 || a->max_replies_per_connection == b->max_replies_per_connection
2851 || a->reply_timeout == b->reply_timeout);
2852 }
2853
2854 static dbus_bool_t
config_parsers_equal(const BusConfigParser * a,const BusConfigParser * b)2855 config_parsers_equal (const BusConfigParser *a,
2856 const BusConfigParser *b)
2857 {
2858 if (!_dbus_string_equal (&a->basedir, &b->basedir))
2859 return FALSE;
2860
2861 if (!lists_of_elements_equal (a->stack, b->stack))
2862 return FALSE;
2863
2864 if (!strings_equal_or_both_null (a->user, b->user))
2865 return FALSE;
2866
2867 if (!lists_of_c_strings_equal (a->listen_on, b->listen_on))
2868 return FALSE;
2869
2870 if (!lists_of_c_strings_equal (a->mechanisms, b->mechanisms))
2871 return FALSE;
2872
2873 if (!lists_of_c_strings_equal (a->service_dirs, b->service_dirs))
2874 return FALSE;
2875
2876 /* FIXME: compare policy */
2877
2878 /* FIXME: compare service selinux ID table */
2879
2880 if (! limits_equal (&a->limits, &b->limits))
2881 return FALSE;
2882
2883 if (!strings_equal_or_both_null (a->pidfile, b->pidfile))
2884 return FALSE;
2885
2886 if (! bools_equal (a->fork, b->fork))
2887 return FALSE;
2888
2889 if (! bools_equal (a->is_toplevel, b->is_toplevel))
2890 return FALSE;
2891
2892 return TRUE;
2893 }
2894
2895 static dbus_bool_t
all_are_equiv(const DBusString * target_directory)2896 all_are_equiv (const DBusString *target_directory)
2897 {
2898 DBusString filename;
2899 DBusDirIter *dir;
2900 BusConfigParser *first_parser;
2901 BusConfigParser *parser;
2902 DBusError error;
2903 dbus_bool_t equal;
2904 dbus_bool_t retval;
2905
2906 dir = NULL;
2907 first_parser = NULL;
2908 parser = NULL;
2909 retval = FALSE;
2910
2911 if (!_dbus_string_init (&filename))
2912 _dbus_assert_not_reached ("didn't allocate filename string");
2913
2914 dbus_error_init (&error);
2915 dir = _dbus_directory_open (target_directory, &error);
2916 if (dir == NULL)
2917 {
2918 _dbus_warn ("Could not open %s: %s\n",
2919 _dbus_string_get_const_data (target_directory),
2920 error.message);
2921 dbus_error_free (&error);
2922 goto finished;
2923 }
2924
2925 printf ("Comparing equivalent files:\n");
2926
2927 next:
2928 while (_dbus_directory_get_next_file (dir, &filename, &error))
2929 {
2930 DBusString full_path;
2931
2932 if (!_dbus_string_init (&full_path))
2933 _dbus_assert_not_reached ("couldn't init string");
2934
2935 if (!_dbus_string_copy (target_directory, 0, &full_path, 0))
2936 _dbus_assert_not_reached ("couldn't copy dir to full_path");
2937
2938 if (!_dbus_concat_dir_and_file (&full_path, &filename))
2939 _dbus_assert_not_reached ("couldn't concat file to dir");
2940
2941 if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
2942 {
2943 _dbus_verbose ("Skipping non-.conf file %s\n",
2944 _dbus_string_get_const_data (&filename));
2945 _dbus_string_free (&full_path);
2946 goto next;
2947 }
2948
2949 printf (" %s\n", _dbus_string_get_const_data (&filename));
2950
2951 parser = bus_config_load (&full_path, TRUE, NULL, &error);
2952
2953 if (parser == NULL)
2954 {
2955 _dbus_warn ("Could not load file %s: %s\n",
2956 _dbus_string_get_const_data (&full_path),
2957 error.message);
2958 _dbus_string_free (&full_path);
2959 dbus_error_free (&error);
2960 goto finished;
2961 }
2962 else if (first_parser == NULL)
2963 {
2964 _dbus_string_free (&full_path);
2965 first_parser = parser;
2966 }
2967 else
2968 {
2969 _dbus_string_free (&full_path);
2970 equal = config_parsers_equal (first_parser, parser);
2971 bus_config_parser_unref (parser);
2972 if (! equal)
2973 goto finished;
2974 }
2975 }
2976
2977 retval = TRUE;
2978
2979 finished:
2980 _dbus_string_free (&filename);
2981 if (first_parser)
2982 bus_config_parser_unref (first_parser);
2983 if (dir)
2984 _dbus_directory_close (dir);
2985
2986 return retval;
2987
2988 }
2989
2990 static dbus_bool_t
process_test_equiv_subdir(const DBusString * test_base_dir,const char * subdir)2991 process_test_equiv_subdir (const DBusString *test_base_dir,
2992 const char *subdir)
2993 {
2994 DBusString test_directory;
2995 DBusString filename;
2996 DBusDirIter *dir;
2997 DBusError error;
2998 dbus_bool_t equal;
2999 dbus_bool_t retval;
3000
3001 dir = NULL;
3002 retval = FALSE;
3003
3004 if (!_dbus_string_init (&test_directory))
3005 _dbus_assert_not_reached ("didn't allocate test_directory");
3006
3007 _dbus_string_init_const (&filename, subdir);
3008
3009 if (!_dbus_string_copy (test_base_dir, 0,
3010 &test_directory, 0))
3011 _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
3012
3013 if (!_dbus_concat_dir_and_file (&test_directory, &filename))
3014 _dbus_assert_not_reached ("couldn't allocate full path");
3015
3016 _dbus_string_free (&filename);
3017 if (!_dbus_string_init (&filename))
3018 _dbus_assert_not_reached ("didn't allocate filename string");
3019
3020 dbus_error_init (&error);
3021 dir = _dbus_directory_open (&test_directory, &error);
3022 if (dir == NULL)
3023 {
3024 _dbus_warn ("Could not open %s: %s\n",
3025 _dbus_string_get_const_data (&test_directory),
3026 error.message);
3027 dbus_error_free (&error);
3028 goto finished;
3029 }
3030
3031 while (_dbus_directory_get_next_file (dir, &filename, &error))
3032 {
3033 DBusString full_path;
3034
3035 /* Skip CVS's magic directories! */
3036 if (_dbus_string_equal_c_str (&filename, "CVS"))
3037 continue;
3038
3039 if (!_dbus_string_init (&full_path))
3040 _dbus_assert_not_reached ("couldn't init string");
3041
3042 if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
3043 _dbus_assert_not_reached ("couldn't copy dir to full_path");
3044
3045 if (!_dbus_concat_dir_and_file (&full_path, &filename))
3046 _dbus_assert_not_reached ("couldn't concat file to dir");
3047
3048 equal = all_are_equiv (&full_path);
3049 _dbus_string_free (&full_path);
3050
3051 if (!equal)
3052 goto finished;
3053 }
3054
3055 retval = TRUE;
3056
3057 finished:
3058 _dbus_string_free (&test_directory);
3059 _dbus_string_free (&filename);
3060 if (dir)
3061 _dbus_directory_close (dir);
3062
3063 return retval;
3064
3065 }
3066
3067 static const char *test_service_dir_matches[] =
3068 {
3069 "/testusr/testlocal/testshare/dbus-1/services",
3070 "/testusr/testshare/dbus-1/services",
3071 DBUS_DATADIR"/dbus-1/services",
3072 "/testhome/foo/.testlocal/testshare/dbus-1/services",
3073 NULL
3074 };
3075
3076 static dbus_bool_t
test_default_session_servicedirs(void)3077 test_default_session_servicedirs (void)
3078 {
3079 DBusList *dirs;
3080 DBusList *link;
3081 int i;
3082
3083 dirs = NULL;
3084
3085 printf ("Testing retriving the default session service directories\n");
3086 if (!_dbus_get_standard_session_servicedirs (&dirs))
3087 _dbus_assert_not_reached ("couldn't get stardard dirs");
3088
3089 /* make sure our defaults end with share/dbus-1/service */
3090 while ((link = _dbus_list_pop_first_link (&dirs)))
3091 {
3092 DBusString path;
3093
3094 printf (" default service dir: %s\n", (char *)link->data);
3095 _dbus_string_init_const (&path, (char *)link->data);
3096 if (!_dbus_string_ends_with_c_str (&path, "share/dbus-1/services"))
3097 {
3098 printf ("error with default session service directories\n");
3099 return FALSE;
3100 }
3101
3102 dbus_free (link->data);
3103 _dbus_list_free_link (link);
3104 }
3105
3106 if (!_dbus_setenv ("XDG_DATA_HOME", "/testhome/foo/.testlocal/testshare"))
3107 _dbus_assert_not_reached ("couldn't setenv XDG_DATA_HOME");
3108
3109 if (!_dbus_setenv ("XDG_DATA_DIRS", ":/testusr/testlocal/testshare: :/testusr/testshare:"))
3110 _dbus_assert_not_reached ("couldn't setenv XDG_DATA_DIRS");
3111
3112 if (!_dbus_get_standard_session_servicedirs (&dirs))
3113 _dbus_assert_not_reached ("couldn't get stardard dirs");
3114
3115 /* make sure we read and parse the env variable correctly */
3116 i = 0;
3117 while ((link = _dbus_list_pop_first_link (&dirs)))
3118 {
3119 printf (" test service dir: %s\n", (char *)link->data);
3120 if (test_service_dir_matches[i] == NULL)
3121 {
3122 printf ("more directories parsed than in match set\n");
3123 return FALSE;
3124 }
3125
3126 if (strcmp (test_service_dir_matches[i],
3127 (char *)link->data) != 0)
3128 {
3129 printf ("%s directory does not match %s in the match set\n",
3130 (char *)link->data,
3131 test_service_dir_matches[i]);
3132 return FALSE;
3133 }
3134
3135 ++i;
3136
3137 dbus_free (link->data);
3138 _dbus_list_free_link (link);
3139 }
3140
3141 if (test_service_dir_matches[i] != NULL)
3142 {
3143 printf ("extra data %s in the match set was not matched\n",
3144 test_service_dir_matches[i]);
3145
3146 return FALSE;
3147 }
3148
3149 return TRUE;
3150 }
3151
3152 dbus_bool_t
bus_config_parser_test(const DBusString * test_data_dir)3153 bus_config_parser_test (const DBusString *test_data_dir)
3154 {
3155 if (test_data_dir == NULL ||
3156 _dbus_string_get_length (test_data_dir) == 0)
3157 {
3158 printf ("No test data\n");
3159 return TRUE;
3160 }
3161
3162 if (!test_default_session_servicedirs())
3163 return FALSE;
3164
3165 if (!process_test_valid_subdir (test_data_dir, "valid-config-files", VALID))
3166 return FALSE;
3167
3168 if (!process_test_valid_subdir (test_data_dir, "invalid-config-files", INVALID))
3169 return FALSE;
3170
3171 if (!process_test_equiv_subdir (test_data_dir, "equiv-config-files"))
3172 return FALSE;
3173
3174 return TRUE;
3175 }
3176
3177 #endif /* DBUS_BUILD_TESTS */
3178
3179