2003-10-14 Havoc Pennington <hp@redhat.com>
[platform/upstream/dbus.git] / bus / config-parser.c
1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* config-parser.c  XML-library-agnostic configuration file parser
3  *
4  * Copyright (C) 2003 Red Hat, Inc.
5  *
6  * Licensed under the Academic Free License version 1.2
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 <dbus/dbus-list.h>
28 #include <dbus/dbus-internals.h>
29 #include <string.h>
30
31 typedef enum
32 {
33   ELEMENT_NONE,
34   ELEMENT_BUSCONFIG,
35   ELEMENT_INCLUDE,
36   ELEMENT_USER,
37   ELEMENT_LISTEN,
38   ELEMENT_AUTH,
39   ELEMENT_POLICY,
40   ELEMENT_LIMIT,
41   ELEMENT_ALLOW,
42   ELEMENT_DENY,
43   ELEMENT_FORK,
44   ELEMENT_PIDFILE,
45   ELEMENT_SERVICEDIR,
46   ELEMENT_INCLUDEDIR,
47   ELEMENT_TYPE
48 } ElementType;
49
50 typedef enum
51 {
52   /* we ignore policies for unknown groups/users */
53   POLICY_IGNORED,
54
55   /* non-ignored */
56   POLICY_DEFAULT,
57   POLICY_MANDATORY,
58   POLICY_USER,
59   POLICY_GROUP
60 } PolicyType;
61
62 typedef struct
63 {
64   ElementType type;
65
66   unsigned int had_content : 1;
67
68   union
69   {
70     struct
71     {
72       unsigned int ignore_missing : 1;
73     } include;
74
75     struct
76     {
77       PolicyType type;
78       unsigned long gid_or_uid;      
79     } policy;
80
81     struct
82     {
83       char *name;
84       long value;
85     } limit;
86     
87   } d;
88
89 } Element;
90
91 /**
92  * Parser for bus configuration file. 
93  */
94 struct BusConfigParser
95 {
96   int refcount;        /**< Reference count */
97
98   DBusString basedir;  /**< Directory we resolve paths relative to */
99   
100   DBusList *stack;     /**< stack of Element */
101
102   char *user;          /**< user to run as */
103
104   char *bus_type;          /**< Message bus type */
105   
106   DBusList *listen_on; /**< List of addresses to listen to */
107
108   DBusList *mechanisms; /**< Auth mechanisms */
109
110   DBusList *service_dirs; /**< Directories to look for services in */
111
112   BusPolicy *policy;     /**< Security policy */
113
114   BusLimits limits;      /**< Limits */
115
116   char *pidfile;         /**< PID file */
117
118   unsigned int fork : 1; /**< TRUE to fork into daemon mode */
119
120   unsigned int is_toplevel : 1; /**< FALSE if we are a sub-config-file inside another one */
121 };
122
123 static const char*
124 element_type_to_name (ElementType type)
125 {
126   switch (type)
127     {
128     case ELEMENT_NONE:
129       return NULL;
130     case ELEMENT_BUSCONFIG:
131       return "busconfig";
132     case ELEMENT_INCLUDE:
133       return "include";
134     case ELEMENT_USER:
135       return "user";
136     case ELEMENT_LISTEN:
137       return "listen";
138     case ELEMENT_AUTH:
139       return "auth";
140     case ELEMENT_POLICY:
141       return "policy";
142     case ELEMENT_LIMIT:
143       return "limit";
144     case ELEMENT_ALLOW:
145       return "allow";
146     case ELEMENT_DENY:
147       return "deny";
148     case ELEMENT_FORK:
149       return "fork";
150     case ELEMENT_PIDFILE:
151       return "pidfile";
152     case ELEMENT_SERVICEDIR:
153       return "servicedir";
154     case ELEMENT_INCLUDEDIR:
155       return "includedir";
156     case ELEMENT_TYPE:
157       return "type";
158     }
159
160   _dbus_assert_not_reached ("bad element type");
161
162   return NULL;
163 }
164
165 static Element*
166 push_element (BusConfigParser *parser,
167               ElementType      type)
168 {
169   Element *e;
170
171   _dbus_assert (type != ELEMENT_NONE);
172   
173   e = dbus_new0 (Element, 1);
174   if (e == NULL)
175     return NULL;
176
177   if (!_dbus_list_append (&parser->stack, e))
178     {
179       dbus_free (e);
180       return NULL;
181     }
182   
183   e->type = type;
184
185   return e;
186 }
187
188 static void
189 element_free (Element *e)
190 {
191   if (e->type == ELEMENT_LIMIT)
192     dbus_free (e->d.limit.name);
193   
194   dbus_free (e);
195 }
196
197 static void
198 pop_element (BusConfigParser *parser)
199 {
200   Element *e;
201
202   e = _dbus_list_pop_last (&parser->stack);
203   
204   element_free (e);
205 }
206
207 static Element*
208 peek_element (BusConfigParser *parser)
209 {
210   Element *e;
211
212   e = _dbus_list_get_last (&parser->stack);
213
214   return e;
215 }
216
217 static ElementType
218 top_element_type (BusConfigParser *parser)
219 {
220   Element *e;
221
222   e = _dbus_list_get_last (&parser->stack);
223
224   if (e)
225     return e->type;
226   else
227     return ELEMENT_NONE;
228 }
229
230 static dbus_bool_t
231 merge_included (BusConfigParser *parser,
232                 BusConfigParser *included,
233                 DBusError       *error)
234 {
235   DBusList *link;
236
237   if (!bus_policy_merge (parser->policy,
238                          included->policy))
239     {
240       BUS_SET_OOM (error);
241       return FALSE;
242     }
243   
244   if (included->user != NULL)
245     {
246       dbus_free (parser->user);
247       parser->user = included->user;
248       included->user = NULL;
249     }
250
251   if (included->bus_type != NULL)
252     {
253       dbus_free (parser->bus_type);
254       parser->bus_type = included->bus_type;
255       included->bus_type = NULL;
256     }
257   
258   if (included->fork)
259     parser->fork = TRUE;
260
261   if (included->pidfile != NULL)
262     {
263       dbus_free (parser->pidfile);
264       parser->pidfile = included->pidfile;
265       included->pidfile = NULL;
266     }
267   
268   while ((link = _dbus_list_pop_first_link (&included->listen_on)))
269     _dbus_list_append_link (&parser->listen_on, link);
270
271   while ((link = _dbus_list_pop_first_link (&included->mechanisms)))
272     _dbus_list_append_link (&parser->mechanisms, link);
273
274   while ((link = _dbus_list_pop_first_link (&included->service_dirs)))
275     _dbus_list_append_link (&parser->service_dirs, link);
276   
277   return TRUE;
278 }
279
280 BusConfigParser*
281 bus_config_parser_new (const DBusString *basedir,
282                        dbus_bool_t       is_toplevel)
283 {
284   BusConfigParser *parser;
285
286   parser = dbus_new0 (BusConfigParser, 1);
287   if (parser == NULL)
288     return NULL;
289
290   parser->is_toplevel = !!is_toplevel;
291   
292   if (!_dbus_string_init (&parser->basedir))
293     {
294       dbus_free (parser);
295       return NULL;
296     }
297
298   if (((parser->policy = bus_policy_new ()) == NULL) ||
299       !_dbus_string_copy (basedir, 0, &parser->basedir, 0))
300     {
301       if (parser->policy)
302         bus_policy_unref (parser->policy);
303       
304       _dbus_string_free (&parser->basedir);
305       dbus_free (parser);
306       return NULL;
307     }
308
309   /* Make up some numbers! woot! */
310   parser->limits.max_incoming_bytes = _DBUS_ONE_MEGABYTE * 63;
311   parser->limits.max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 63;
312   parser->limits.max_message_size = _DBUS_ONE_MEGABYTE * 32;
313
314   /* Making this long means the user has to wait longer for an error
315    * message if something screws up, but making it too short means
316    * they might see a false failure.
317    */
318   parser->limits.activation_timeout = 25000; /* 25 seconds */
319
320   /* Making this long risks making a DOS attack easier, but too short
321    * and legitimate auth will fail.  If interactive auth (ask user for
322    * password) is allowed, then potentially it has to be quite long.
323    */
324   parser->limits.auth_timeout = 30000; /* 30 seconds */
325
326   parser->limits.max_incomplete_connections = 32;
327   parser->limits.max_connections_per_user = 128;
328
329   /* Note that max_completed_connections / max_connections_per_user
330    * is the number of users that would have to work together to
331    * DOS all the other users.
332    */
333   parser->limits.max_completed_connections = 1024;
334
335   parser->limits.max_pending_activations = 256;
336   parser->limits.max_services_per_connection = 256;
337
338   parser->limits.max_match_rules_per_connection = 128;
339
340   parser->limits.reply_timeout = 5 * 60 * 1000; /* 5 minutes */
341   parser->limits.max_replies_per_connection = 32;
342   
343   parser->refcount = 1;
344
345   return parser;
346 }
347
348 void
349 bus_config_parser_ref (BusConfigParser *parser)
350 {
351   _dbus_assert (parser->refcount > 0);
352
353   parser->refcount += 1;
354 }
355
356 void
357 bus_config_parser_unref (BusConfigParser *parser)
358 {
359   _dbus_assert (parser->refcount > 0);
360
361   parser->refcount -= 1;
362
363   if (parser->refcount == 0)
364     {
365       while (parser->stack != NULL)
366         pop_element (parser);
367
368       dbus_free (parser->user);
369       dbus_free (parser->bus_type);
370       dbus_free (parser->pidfile);
371       
372       _dbus_list_foreach (&parser->listen_on,
373                           (DBusForeachFunction) dbus_free,
374                           NULL);
375
376       _dbus_list_clear (&parser->listen_on);
377
378       _dbus_list_foreach (&parser->service_dirs,
379                           (DBusForeachFunction) dbus_free,
380                           NULL);
381
382       _dbus_list_clear (&parser->service_dirs);
383
384       _dbus_list_foreach (&parser->mechanisms,
385                           (DBusForeachFunction) dbus_free,
386                           NULL);
387
388       _dbus_list_clear (&parser->mechanisms);
389       
390       _dbus_string_free (&parser->basedir);
391
392       if (parser->policy)
393         bus_policy_unref (parser->policy);
394       
395       dbus_free (parser);
396     }
397 }
398
399 dbus_bool_t
400 bus_config_parser_check_doctype (BusConfigParser   *parser,
401                                  const char        *doctype,
402                                  DBusError         *error)
403 {
404   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
405
406   if (strcmp (doctype, "busconfig") != 0)
407     {
408       dbus_set_error (error,
409                       DBUS_ERROR_FAILED,
410                       "Configuration file has the wrong document type %s",
411                       doctype);
412       return FALSE;
413     }
414   else
415     return TRUE;
416 }
417
418 typedef struct
419 {
420   const char  *name;
421   const char **retloc;
422 } LocateAttr;
423
424 static dbus_bool_t
425 locate_attributes (BusConfigParser  *parser,
426                    const char       *element_name,
427                    const char      **attribute_names,
428                    const char      **attribute_values,
429                    DBusError        *error,
430                    const char       *first_attribute_name,
431                    const char      **first_attribute_retloc,
432                    ...)
433 {
434   va_list args;
435   const char *name;
436   const char **retloc;
437   int n_attrs;
438 #define MAX_ATTRS 24
439   LocateAttr attrs[MAX_ATTRS];
440   dbus_bool_t retval;
441   int i;
442
443   _dbus_assert (first_attribute_name != NULL);
444   _dbus_assert (first_attribute_retloc != NULL);
445
446   retval = TRUE;
447
448   n_attrs = 1;
449   attrs[0].name = first_attribute_name;
450   attrs[0].retloc = first_attribute_retloc;
451   *first_attribute_retloc = NULL;
452
453   va_start (args, first_attribute_retloc);
454
455   name = va_arg (args, const char*);
456   retloc = va_arg (args, const char**);
457
458   while (name != NULL)
459     {
460       _dbus_assert (retloc != NULL);
461       _dbus_assert (n_attrs < MAX_ATTRS);
462
463       attrs[n_attrs].name = name;
464       attrs[n_attrs].retloc = retloc;
465       n_attrs += 1;
466       *retloc = NULL;
467
468       name = va_arg (args, const char*);
469       retloc = va_arg (args, const char**);
470     }
471
472   va_end (args);
473
474   if (!retval)
475     return retval;
476
477   i = 0;
478   while (attribute_names[i])
479     {
480       int j;
481       dbus_bool_t found;
482       
483       found = FALSE;
484       j = 0;
485       while (j < n_attrs)
486         {
487           if (strcmp (attrs[j].name, attribute_names[i]) == 0)
488             {
489               retloc = attrs[j].retloc;
490
491               if (*retloc != NULL)
492                 {
493                   dbus_set_error (error, DBUS_ERROR_FAILED,
494                                   "Attribute \"%s\" repeated twice on the same <%s> element",
495                                   attrs[j].name, element_name);
496                   retval = FALSE;
497                   goto out;
498                 }
499
500               *retloc = attribute_values[i];
501               found = TRUE;
502             }
503
504           ++j;
505         }
506
507       if (!found)
508         {
509           dbus_set_error (error, DBUS_ERROR_FAILED,
510                           "Attribute \"%s\" is invalid on <%s> element in this context",
511                           attribute_names[i], element_name);
512           retval = FALSE;
513           goto out;
514         }
515
516       ++i;
517     }
518
519  out:
520   return retval;
521 }
522
523 static dbus_bool_t
524 check_no_attributes (BusConfigParser  *parser,
525                      const char       *element_name,
526                      const char      **attribute_names,
527                      const char      **attribute_values,
528                      DBusError        *error)
529 {
530   if (attribute_names[0] != NULL)
531     {
532       dbus_set_error (error, DBUS_ERROR_FAILED,
533                       "Attribute \"%s\" is invalid on <%s> element in this context",
534                       attribute_names[0], element_name);
535       return FALSE;
536     }
537
538   return TRUE;
539 }
540
541 static dbus_bool_t
542 start_busconfig_child (BusConfigParser   *parser,
543                        const char        *element_name,
544                        const char       **attribute_names,
545                        const char       **attribute_values,
546                        DBusError         *error)
547 {
548   if (strcmp (element_name, "user") == 0)
549     {
550       if (!check_no_attributes (parser, "user", attribute_names, attribute_values, error))
551         return FALSE;
552
553       if (push_element (parser, ELEMENT_USER) == NULL)
554         {
555           BUS_SET_OOM (error);
556           return FALSE;
557         }
558
559       return TRUE;
560     }
561   else if (strcmp (element_name, "type") == 0)
562     {
563       if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
564         return FALSE;
565
566       if (push_element (parser, ELEMENT_TYPE) == NULL)
567         {
568           BUS_SET_OOM (error);
569           return FALSE;
570         }
571
572       return TRUE;
573     }
574   else if (strcmp (element_name, "fork") == 0)
575     {
576       if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
577         return FALSE;
578
579       if (push_element (parser, ELEMENT_FORK) == NULL)
580         {
581           BUS_SET_OOM (error);
582           return FALSE;
583         }
584
585       parser->fork = TRUE;
586       
587       return TRUE;
588     }
589   else if (strcmp (element_name, "pidfile") == 0)
590     {
591       if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
592         return FALSE;
593
594       if (push_element (parser, ELEMENT_PIDFILE) == NULL)
595         {
596           BUS_SET_OOM (error);
597           return FALSE;
598         }
599
600       return TRUE;
601     }
602   else if (strcmp (element_name, "listen") == 0)
603     {
604       if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
605         return FALSE;
606
607       if (push_element (parser, ELEMENT_LISTEN) == NULL)
608         {
609           BUS_SET_OOM (error);
610           return FALSE;
611         }
612
613       return TRUE;
614     }
615   else if (strcmp (element_name, "auth") == 0)
616     {
617       if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
618         return FALSE;
619
620       if (push_element (parser, ELEMENT_AUTH) == NULL)
621         {
622           BUS_SET_OOM (error);
623           return FALSE;
624         }
625
626       return TRUE;
627     }
628   else if (strcmp (element_name, "includedir") == 0)
629     {
630       if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error))
631         return FALSE;
632
633       if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL)
634         {
635           BUS_SET_OOM (error);
636           return FALSE;
637         }
638
639       return TRUE;
640     }
641   else if (strcmp (element_name, "servicedir") == 0)
642     {
643       if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error))
644         return FALSE;
645
646       if (push_element (parser, ELEMENT_SERVICEDIR) == NULL)
647         {
648           BUS_SET_OOM (error);
649           return FALSE;
650         }
651
652       return TRUE;
653     }
654   else if (strcmp (element_name, "include") == 0)
655     {
656       Element *e;
657       const char *ignore_missing;
658
659       if ((e = push_element (parser, ELEMENT_INCLUDE)) == NULL)
660         {
661           BUS_SET_OOM (error);
662           return FALSE;
663         }
664
665       e->d.include.ignore_missing = FALSE;
666
667       if (!locate_attributes (parser, "include",
668                               attribute_names,
669                               attribute_values,
670                               error,
671                               "ignore_missing", &ignore_missing,
672                               NULL))
673         return FALSE;
674
675       if (ignore_missing != NULL)
676         {
677           if (strcmp (ignore_missing, "yes") == 0)
678             e->d.include.ignore_missing = TRUE;
679           else if (strcmp (ignore_missing, "no") == 0)
680             e->d.include.ignore_missing = FALSE;
681           else
682             {
683               dbus_set_error (error, DBUS_ERROR_FAILED,
684                               "ignore_missing attribute must have value \"yes\" or \"no\"");
685               return FALSE;
686             }
687         }
688
689       return TRUE;
690     }
691   else if (strcmp (element_name, "policy") == 0)
692     {
693       Element *e;
694       const char *context;
695       const char *user;
696       const char *group;
697
698       if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
699         {
700           BUS_SET_OOM (error);
701           return FALSE;
702         }
703
704       e->d.policy.type = POLICY_IGNORED;
705       
706       if (!locate_attributes (parser, "policy",
707                               attribute_names,
708                               attribute_values,
709                               error,
710                               "context", &context,
711                               "user", &user,
712                               "group", &group,
713                               NULL))
714         return FALSE;
715
716       if (((context && user) ||
717            (context && group)) ||
718           (user && group) ||
719           !(context || user || group))
720         {
721           dbus_set_error (error, DBUS_ERROR_FAILED,
722                           "<policy> element must have exactly one of (context|user|group) attributes");
723           return FALSE;
724         }
725
726       if (context != NULL)
727         {
728           if (strcmp (context, "default") == 0)
729             {
730               e->d.policy.type = POLICY_DEFAULT;
731             }
732           else if (strcmp (context, "mandatory") == 0)
733             {
734               e->d.policy.type = POLICY_MANDATORY;
735             }
736           else
737             {
738               dbus_set_error (error, DBUS_ERROR_FAILED,
739                               "context attribute on <policy> must have the value \"default\" or \"mandatory\", not \"%s\"",
740                               context);
741               return FALSE;
742             }
743         }
744       else if (user != NULL)
745         {
746           DBusString username;
747           _dbus_string_init_const (&username, user);
748
749           if (_dbus_get_user_id (&username,
750                                  &e->d.policy.gid_or_uid))
751             e->d.policy.type = POLICY_USER;
752           else
753             _dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
754                         user);
755         }
756       else if (group != NULL)
757         {
758           DBusString group_name;
759           _dbus_string_init_const (&group_name, group);
760
761           if (_dbus_get_group_id (&group_name,
762                                   &e->d.policy.gid_or_uid))
763             e->d.policy.type = POLICY_GROUP;
764           else
765             _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
766                         group);          
767         }
768       else
769         {
770           _dbus_assert_not_reached ("all <policy> attributes null and we didn't set error");
771         }
772       
773       return TRUE;
774     }
775   else if (strcmp (element_name, "limit") == 0)
776     {
777       Element *e;
778       const char *name;
779
780       if ((e = push_element (parser, ELEMENT_LIMIT)) == NULL)
781         {
782           BUS_SET_OOM (error);
783           return FALSE;
784         }
785       
786       if (!locate_attributes (parser, "limit",
787                               attribute_names,
788                               attribute_values,
789                               error,
790                               "name", &name,
791                               NULL))
792         return FALSE;
793
794       if (name == NULL)
795         {
796           dbus_set_error (error, DBUS_ERROR_FAILED,
797                           "<limit> element must have a \"name\" attribute");
798           return FALSE;
799         }
800
801       e->d.limit.name = _dbus_strdup (name);
802       if (e->d.limit.name == NULL)
803         {
804           BUS_SET_OOM (error);
805           return FALSE;
806         }
807
808       return TRUE;
809     }
810   else
811     {
812       dbus_set_error (error, DBUS_ERROR_FAILED,
813                       "Element <%s> not allowed inside <%s> in configuration file",
814                       element_name, "busconfig");
815       return FALSE;
816     }
817 }
818
819 static dbus_bool_t
820 append_rule_from_element (BusConfigParser   *parser,
821                           const char        *element_name,
822                           const char       **attribute_names,
823                           const char       **attribute_values,
824                           dbus_bool_t        allow,
825                           DBusError         *error)
826 {
827   const char *send_interface;
828   const char *send_member;
829   const char *send_error;
830   const char *send_destination;
831   const char *send_path;
832   const char *send_type;
833   const char *receive_interface;
834   const char *receive_member;
835   const char *receive_error;
836   const char *receive_sender;
837   const char *receive_path;
838   const char *receive_type;
839   const char *eavesdrop;
840   const char *own;
841   const char *user;
842   const char *group;
843   BusPolicyRule *rule;
844   
845   if (!locate_attributes (parser, element_name,
846                           attribute_names,
847                           attribute_values,
848                           error,
849                           "send_interface", &send_interface,
850                           "send_member", &send_member,
851                           "send_error", &send_error,
852                           "send_destination", &send_destination,
853                           "send_path", &send_path,
854                           "send_type", &send_type,
855                           "receive_interface", &receive_interface,
856                           "receive_member", &receive_member,
857                           "receive_error", &receive_error,
858                           "receive_sender", &receive_sender,
859                           "receive_path", &receive_path,
860                           "receive_type", &receive_type,
861                           "eavesdrop", &eavesdrop,
862                           "own", &own,
863                           "user", &user,
864                           "group", &group,
865                           NULL))
866     return FALSE;
867
868   if (!(send_interface || send_member || send_error || send_destination ||
869         send_type || send_path ||
870         receive_interface || receive_member || receive_error || receive_sender ||
871         receive_type || receive_path || eavesdrop ||
872         own || user || group))
873     {
874       dbus_set_error (error, DBUS_ERROR_FAILED,
875                       "Element <%s> must have one or more attributes",
876                       element_name);
877       return FALSE;
878     }
879
880   if ((send_member && (send_interface == NULL && send_path == NULL)) ||
881       (receive_member && (receive_interface == NULL && receive_path == NULL)))
882     {
883       dbus_set_error (error, DBUS_ERROR_FAILED,
884                       "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.",
885                       element_name);
886       return FALSE;
887     }
888   
889   /* Allowed combinations of elements are:
890    *
891    *   base, must be all send or all receive:
892    *     nothing
893    *     interface
894    *     interface + member
895    *     error
896    * 
897    *   base send_ can combine with send_destination, send_path, send_type
898    *   base receive_ with receive_sender, receive_path, receive_type, eavesdrop
899    *
900    *   user, group, own must occur alone
901    *
902    * Pretty sure the below stuff is broken, FIXME think about it more.
903    */
904
905   if (((send_interface && send_error) ||
906        (send_interface && receive_interface) ||
907        (send_interface && receive_member) ||
908        (send_interface && receive_error) ||
909        (send_interface && receive_sender) ||
910        (send_interface && eavesdrop) ||
911        (send_interface && own) ||
912        (send_interface && user) ||
913        (send_interface && group)) ||
914
915       ((send_member && send_error) ||
916        (send_member && receive_interface) ||
917        (send_member && receive_member) ||
918        (send_member && receive_error) ||
919        (send_member && receive_sender) ||
920        (send_member && eavesdrop) ||
921        (send_member && own) ||
922        (send_member && user) ||
923        (send_member && group)) ||
924       
925       ((send_error && receive_interface) ||
926        (send_error && receive_member) ||
927        (send_error && receive_error) ||
928        (send_error && receive_sender) ||
929        (send_error && eavesdrop) ||
930        (send_error && own) ||
931        (send_error && user) ||
932        (send_error && group)) ||
933
934       ((send_destination && receive_interface) ||
935        (send_destination && receive_member) ||
936        (send_destination && receive_error) ||
937        (send_destination && receive_sender) ||
938        (send_destination && eavesdrop) ||
939        (send_destination && own) ||
940        (send_destination && user) ||
941        (send_destination && group)) ||
942
943       ((send_type && receive_interface) ||
944        (send_type && receive_member) ||
945        (send_type && receive_error) ||
946        (send_type && receive_sender) ||
947        (send_type && eavesdrop) ||
948        (send_type && own) ||
949        (send_type && user) ||
950        (send_type && group)) ||
951
952       ((send_path && receive_interface) ||
953        (send_path && receive_member) ||
954        (send_path && receive_error) ||
955        (send_path && receive_sender) ||
956        (send_path && eavesdrop) ||
957        (send_path && own) ||
958        (send_path && user) ||
959        (send_path && group)) ||
960       
961       ((receive_interface && receive_error) ||
962        (receive_interface && own) ||
963        (receive_interface && user) ||
964        (receive_interface && group)) ||
965
966       ((receive_member && receive_error) ||
967        (receive_member && own) ||
968        (receive_member && user) ||
969        (receive_member && group)) ||
970       
971       ((receive_error && own) ||
972        (receive_error && user) ||
973        (receive_error && group)) ||
974
975       ((eavesdrop && own) ||
976        (eavesdrop && user) ||
977        (eavesdrop && group)) ||
978       
979       ((own && user) ||
980        (own && group)) ||
981
982       ((user && group)))
983     {
984       dbus_set_error (error, DBUS_ERROR_FAILED,
985                       "Invalid combination of attributes on element <%s>",
986                       element_name);
987       return FALSE;
988     }
989   
990   rule = NULL;
991
992   /* In BusPolicyRule, NULL represents wildcard.
993    * In the config file, '*' represents it.
994    */
995 #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
996
997   if (send_interface || send_member || send_error || send_destination ||
998       send_path || send_type)
999     {
1000       int message_type;
1001       
1002       if (IS_WILDCARD (send_interface))
1003         send_interface = NULL;
1004       if (IS_WILDCARD (send_member))
1005         send_member = NULL;
1006       if (IS_WILDCARD (send_error))
1007         send_error = NULL;
1008       if (IS_WILDCARD (send_destination))
1009         send_destination = NULL;
1010       if (IS_WILDCARD (send_path))
1011         send_path = NULL;
1012       if (IS_WILDCARD (send_type))
1013         send_type = NULL;
1014
1015       message_type = DBUS_MESSAGE_TYPE_INVALID;
1016       if (send_type != NULL)
1017         {
1018           message_type = dbus_message_type_from_string (send_type);
1019           if (message_type == DBUS_MESSAGE_TYPE_INVALID)
1020             {
1021               dbus_set_error (error, DBUS_ERROR_FAILED,
1022                               "Bad message type \"%s\"",
1023                               send_type);
1024               return FALSE;
1025             }
1026         }
1027       
1028       rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); 
1029       if (rule == NULL)
1030         goto nomem;
1031       
1032       rule->d.send.message_type = message_type;
1033       rule->d.send.path = _dbus_strdup (send_path);
1034       rule->d.send.interface = _dbus_strdup (send_interface);
1035       rule->d.send.member = _dbus_strdup (send_member);
1036       rule->d.send.error = _dbus_strdup (send_error);
1037       rule->d.send.destination = _dbus_strdup (send_destination);
1038       if (send_path && rule->d.send.path == NULL)
1039         goto nomem;
1040       if (send_interface && rule->d.send.interface == NULL)
1041         goto nomem;
1042       if (send_member && rule->d.send.member == NULL)
1043         goto nomem;
1044       if (send_error && rule->d.send.error == NULL)
1045         goto nomem;
1046       if (send_destination && rule->d.send.destination == NULL)
1047         goto nomem;
1048     }
1049   else if (receive_interface || receive_member || receive_error || receive_sender ||
1050            receive_path || receive_type || eavesdrop)
1051     {
1052       int message_type;
1053       
1054       if (IS_WILDCARD (receive_interface))
1055         receive_interface = NULL;
1056       if (IS_WILDCARD (receive_member))
1057         receive_member = NULL;
1058       if (IS_WILDCARD (receive_error))
1059         receive_error = NULL;
1060       if (IS_WILDCARD (receive_sender))
1061         receive_sender = NULL;
1062       if (IS_WILDCARD (receive_path))
1063         receive_path = NULL;
1064       if (IS_WILDCARD (receive_type))
1065         receive_type = NULL;
1066
1067       message_type = DBUS_MESSAGE_TYPE_INVALID;
1068       if (receive_type != NULL)
1069         {
1070           message_type = dbus_message_type_from_string (receive_type);
1071           if (message_type == DBUS_MESSAGE_TYPE_INVALID)
1072             {
1073               dbus_set_error (error, DBUS_ERROR_FAILED,
1074                               "Bad message type \"%s\"",
1075                               receive_type);
1076               return FALSE;
1077             }
1078         }
1079
1080
1081       if (eavesdrop &&
1082           !(strcmp (eavesdrop, "true") == 0 ||
1083             strcmp (eavesdrop, "false") == 0))
1084         {
1085           dbus_set_error (error, DBUS_ERROR_FAILED,
1086                           "Bad value \"%s\" for eavesdrop attribute, must be true or false",
1087                           eavesdrop);
1088           return FALSE;
1089         }
1090       
1091       rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); 
1092       if (rule == NULL)
1093         goto nomem;
1094
1095       if (eavesdrop)
1096         rule->d.receive.eavesdrop = (strcmp (eavesdrop, "true") == 0);
1097       
1098       rule->d.receive.message_type = message_type;
1099       rule->d.receive.path = _dbus_strdup (receive_path);
1100       rule->d.receive.interface = _dbus_strdup (receive_interface);
1101       rule->d.receive.member = _dbus_strdup (receive_member);
1102       rule->d.receive.error = _dbus_strdup (receive_error);
1103       rule->d.receive.origin = _dbus_strdup (receive_sender);
1104       if (receive_path && rule->d.receive.path == NULL)
1105         goto nomem;
1106       if (receive_interface && rule->d.receive.interface == NULL)
1107         goto nomem;
1108       if (receive_member && rule->d.receive.member == NULL)
1109         goto nomem;
1110       if (receive_error && rule->d.receive.error == NULL)
1111         goto nomem;
1112       if (receive_sender && rule->d.receive.origin == NULL)
1113         goto nomem;
1114     }
1115   else if (own)
1116     {
1117       rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow); 
1118       if (rule == NULL)
1119         goto nomem;
1120
1121       if (IS_WILDCARD (own))
1122         own = NULL;
1123       
1124       rule->d.own.service_name = _dbus_strdup (own);
1125       if (own && rule->d.own.service_name == NULL)
1126         goto nomem;
1127     }
1128   else if (user)
1129     {      
1130       if (IS_WILDCARD (user))
1131         {
1132           rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); 
1133           if (rule == NULL)
1134             goto nomem;
1135
1136           rule->d.user.uid = DBUS_UID_UNSET;
1137         }
1138       else
1139         {
1140           DBusString username;
1141           dbus_uid_t uid;
1142           
1143           _dbus_string_init_const (&username, user);
1144       
1145           if (_dbus_get_user_id (&username, &uid))
1146             {
1147               rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); 
1148               if (rule == NULL)
1149                 goto nomem;
1150
1151               rule->d.user.uid = uid;
1152             }
1153           else
1154             {
1155               _dbus_warn ("Unknown username \"%s\" on element <%s>\n",
1156                           user, element_name);
1157             }
1158         }
1159     }
1160   else if (group)
1161     {
1162       if (IS_WILDCARD (group))
1163         {
1164           rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); 
1165           if (rule == NULL)
1166             goto nomem;
1167
1168           rule->d.group.gid = DBUS_GID_UNSET;
1169         }
1170       else
1171         {
1172           DBusString groupname;
1173           dbus_gid_t gid;
1174           
1175           _dbus_string_init_const (&groupname, group);
1176           
1177           if (_dbus_get_user_id (&groupname, &gid))
1178             {
1179               rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); 
1180               if (rule == NULL)
1181                 goto nomem;
1182
1183               rule->d.group.gid = gid;
1184             }
1185           else
1186             {
1187               _dbus_warn ("Unknown group \"%s\" on element <%s>\n",
1188                           group, element_name);
1189             }
1190         }
1191     }
1192   else
1193     _dbus_assert_not_reached ("Did not handle some combination of attributes on <allow> or <deny>");
1194
1195   if (rule != NULL)
1196     {
1197       Element *pe;
1198       
1199       pe = peek_element (parser);      
1200       _dbus_assert (pe != NULL);
1201       _dbus_assert (pe->type == ELEMENT_POLICY);
1202
1203       switch (pe->d.policy.type)
1204         {
1205         case POLICY_IGNORED:
1206           /* drop the rule on the floor */
1207           break;
1208           
1209         case POLICY_DEFAULT:
1210           if (!bus_policy_append_default_rule (parser->policy, rule))
1211             goto nomem;
1212           break;
1213         case POLICY_MANDATORY:
1214           if (!bus_policy_append_mandatory_rule (parser->policy, rule))
1215             goto nomem;
1216           break;
1217         case POLICY_USER:
1218           if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1219             {
1220               dbus_set_error (error, DBUS_ERROR_FAILED,
1221                               "<%s> rule cannot be per-user because it has bus-global semantics",
1222                               element_name);
1223               goto failed;
1224             }
1225           
1226           if (!bus_policy_append_user_rule (parser->policy, pe->d.policy.gid_or_uid,
1227                                             rule))
1228             goto nomem;
1229           break;
1230         case POLICY_GROUP:
1231           if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1232             {
1233               dbus_set_error (error, DBUS_ERROR_FAILED,
1234                               "<%s> rule cannot be per-group because it has bus-global semantics",
1235                               element_name);
1236               goto failed;
1237             }
1238           
1239           if (!bus_policy_append_group_rule (parser->policy, pe->d.policy.gid_or_uid,
1240                                              rule))
1241             goto nomem;
1242           break;
1243         }
1244       
1245       bus_policy_rule_unref (rule);
1246       rule = NULL;
1247     }
1248   
1249   return TRUE;
1250
1251  nomem:
1252   BUS_SET_OOM (error);
1253  failed:
1254   if (rule)
1255     bus_policy_rule_unref (rule);
1256   return FALSE;
1257 }
1258
1259 static dbus_bool_t
1260 start_policy_child (BusConfigParser   *parser,
1261                     const char        *element_name,
1262                     const char       **attribute_names,
1263                     const char       **attribute_values,
1264                     DBusError         *error)
1265 {
1266   if (strcmp (element_name, "allow") == 0)
1267     {
1268       if (!append_rule_from_element (parser, element_name,
1269                                      attribute_names, attribute_values,
1270                                      TRUE, error))
1271         return FALSE;
1272       
1273       if (push_element (parser, ELEMENT_ALLOW) == NULL)
1274         {
1275           BUS_SET_OOM (error);
1276           return FALSE;
1277         }
1278       
1279       return TRUE;
1280     }
1281   else if (strcmp (element_name, "deny") == 0)
1282     {
1283       if (!append_rule_from_element (parser, element_name,
1284                                      attribute_names, attribute_values,
1285                                      FALSE, error))
1286         return FALSE;
1287       
1288       if (push_element (parser, ELEMENT_DENY) == NULL)
1289         {
1290           BUS_SET_OOM (error);
1291           return FALSE;
1292         }
1293       
1294       return TRUE;
1295     }
1296   else
1297     {
1298       dbus_set_error (error, DBUS_ERROR_FAILED,
1299                       "Element <%s> not allowed inside <%s> in configuration file",
1300                       element_name, "policy");
1301       return FALSE;
1302     }
1303 }
1304
1305 dbus_bool_t
1306 bus_config_parser_start_element (BusConfigParser   *parser,
1307                                  const char        *element_name,
1308                                  const char       **attribute_names,
1309                                  const char       **attribute_values,
1310                                  DBusError         *error)
1311 {
1312   ElementType t;
1313
1314   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1315
1316   /* printf ("START: %s\n", element_name); */
1317   
1318   t = top_element_type (parser);
1319
1320   if (t == ELEMENT_NONE)
1321     {
1322       if (strcmp (element_name, "busconfig") == 0)
1323         {
1324           if (!check_no_attributes (parser, "busconfig", attribute_names, attribute_values, error))
1325             return FALSE;
1326           
1327           if (push_element (parser, ELEMENT_BUSCONFIG) == NULL)
1328             {
1329               BUS_SET_OOM (error);
1330               return FALSE;
1331             }
1332
1333           return TRUE;
1334         }
1335       else
1336         {
1337           dbus_set_error (error, DBUS_ERROR_FAILED,
1338                           "Unknown element <%s> at root of configuration file",
1339                           element_name);
1340           return FALSE;
1341         }
1342     }
1343   else if (t == ELEMENT_BUSCONFIG)
1344     {
1345       return start_busconfig_child (parser, element_name,
1346                                     attribute_names, attribute_values,
1347                                     error);
1348     }
1349   else if (t == ELEMENT_POLICY)
1350     {
1351       return start_policy_child (parser, element_name,
1352                                  attribute_names, attribute_values,
1353                                  error);
1354     }
1355   else
1356     {
1357       dbus_set_error (error, DBUS_ERROR_FAILED,
1358                       "Element <%s> is not allowed in this context",
1359                       element_name);
1360       return FALSE;
1361     }  
1362 }
1363
1364 static dbus_bool_t
1365 set_limit (BusConfigParser *parser,
1366            const char      *name,
1367            long             value,
1368            DBusError       *error)
1369 {
1370   dbus_bool_t must_be_positive;
1371   dbus_bool_t must_be_int;
1372
1373   must_be_int = FALSE;
1374   must_be_positive = FALSE;
1375   
1376   if (strcmp (name, "max_incoming_bytes") == 0)
1377     {
1378       must_be_positive = TRUE;
1379       parser->limits.max_incoming_bytes = value;
1380     }
1381   else if (strcmp (name, "max_outgoing_bytes") == 0)
1382     {
1383       must_be_positive = TRUE;
1384       parser->limits.max_outgoing_bytes = value;
1385     }
1386   else if (strcmp (name, "max_message_size") == 0)
1387     {
1388       must_be_positive = TRUE;
1389       parser->limits.max_message_size = value;
1390     }
1391   else if (strcmp (name, "activation_timeout") == 0)
1392     {
1393       must_be_positive = TRUE;
1394       must_be_int = TRUE;
1395       parser->limits.activation_timeout = value;
1396     }
1397   else if (strcmp (name, "auth_timeout") == 0)
1398     {
1399       must_be_positive = TRUE;
1400       must_be_int = TRUE;
1401       parser->limits.auth_timeout = value;
1402     }
1403   else if (strcmp (name, "reply_timeout") == 0)
1404     {
1405       must_be_positive = TRUE;
1406       must_be_int = TRUE;
1407       parser->limits.reply_timeout = value;
1408     }
1409   else if (strcmp (name, "max_completed_connections") == 0)
1410     {
1411       must_be_positive = TRUE;
1412       must_be_int = TRUE;
1413       parser->limits.max_completed_connections = value;
1414     }
1415   else if (strcmp (name, "max_incomplete_connections") == 0)
1416     {
1417       must_be_positive = TRUE;
1418       must_be_int = TRUE;
1419       parser->limits.max_incomplete_connections = value;
1420     }
1421   else if (strcmp (name, "max_connections_per_user") == 0)
1422     {
1423       must_be_positive = TRUE;
1424       must_be_int = TRUE;
1425       parser->limits.max_connections_per_user = value;
1426     }
1427   else if (strcmp (name, "max_pending_activations") == 0)
1428     {
1429       must_be_positive = TRUE;
1430       must_be_int = TRUE;
1431       parser->limits.max_pending_activations = value;
1432     }
1433   else if (strcmp (name, "max_services_per_connection") == 0)
1434     {
1435       must_be_positive = TRUE;
1436       must_be_int = TRUE;
1437       parser->limits.max_services_per_connection = value;
1438     }
1439   else if (strcmp (name, "max_replies_per_connection") == 0)
1440     {
1441       must_be_positive = TRUE;
1442       must_be_int = TRUE;
1443       parser->limits.max_replies_per_connection = value;
1444     }
1445   else
1446     {
1447       dbus_set_error (error, DBUS_ERROR_FAILED,
1448                       "There is no limit called \"%s\"\n",
1449                       name);
1450       return FALSE;
1451     }
1452   
1453   if (must_be_positive && value < 0)
1454     {
1455       dbus_set_error (error, DBUS_ERROR_FAILED,
1456                       "<limit name=\"%s\"> must be a positive number\n",
1457                       name);
1458       return FALSE;
1459     }
1460
1461   if (must_be_int &&
1462       (value < _DBUS_INT_MIN || value > _DBUS_INT_MAX))
1463     {
1464       dbus_set_error (error, DBUS_ERROR_FAILED,
1465                       "<limit name=\"%s\"> value is too large\n",
1466                       name);
1467       return FALSE;
1468     }
1469
1470   return TRUE;  
1471 }
1472
1473 dbus_bool_t
1474 bus_config_parser_end_element (BusConfigParser   *parser,
1475                                const char        *element_name,
1476                                DBusError         *error)
1477 {
1478   ElementType t;
1479   const char *n;
1480   Element *e;
1481
1482   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1483
1484   /* printf ("END: %s\n", element_name); */
1485   
1486   t = top_element_type (parser);
1487
1488   if (t == ELEMENT_NONE)
1489     {
1490       /* should probably be an assertion failure but
1491        * being paranoid about XML parsers
1492        */
1493       dbus_set_error (error, DBUS_ERROR_FAILED,
1494                       "XML parser ended element with no element on the stack");
1495       return FALSE;
1496     }
1497
1498   n = element_type_to_name (t);
1499   _dbus_assert (n != NULL);
1500   if (strcmp (n, element_name) != 0)
1501     {
1502       /* should probably be an assertion failure but
1503        * being paranoid about XML parsers
1504        */
1505       dbus_set_error (error, DBUS_ERROR_FAILED,
1506                       "XML element <%s> ended but topmost element on the stack was <%s>",
1507                       element_name, n);
1508       return FALSE;
1509     }
1510
1511   e = peek_element (parser);
1512   _dbus_assert (e != NULL);
1513
1514   switch (e->type)
1515     {
1516     case ELEMENT_NONE:
1517       _dbus_assert_not_reached ("element in stack has no type");
1518       break;
1519
1520     case ELEMENT_INCLUDE:
1521     case ELEMENT_USER:
1522     case ELEMENT_TYPE:
1523     case ELEMENT_LISTEN:
1524     case ELEMENT_PIDFILE:
1525     case ELEMENT_AUTH:
1526     case ELEMENT_SERVICEDIR:
1527     case ELEMENT_INCLUDEDIR:
1528     case ELEMENT_LIMIT:
1529       if (!e->had_content)
1530         {
1531           dbus_set_error (error, DBUS_ERROR_FAILED,
1532                           "XML element <%s> was expected to have content inside it",
1533                           element_type_to_name (e->type));
1534           return FALSE;
1535         }
1536
1537       if (e->type == ELEMENT_LIMIT)
1538         {
1539           if (!set_limit (parser, e->d.limit.name, e->d.limit.value,
1540                           error))
1541             return FALSE;
1542         }
1543       break;
1544
1545     case ELEMENT_BUSCONFIG:
1546     case ELEMENT_POLICY:
1547     case ELEMENT_ALLOW:
1548     case ELEMENT_DENY:
1549     case ELEMENT_FORK:
1550       break;
1551     }
1552
1553   pop_element (parser);
1554
1555   return TRUE;
1556 }
1557
1558 static dbus_bool_t
1559 all_whitespace (const DBusString *str)
1560 {
1561   int i;
1562
1563   _dbus_string_skip_white (str, 0, &i);
1564
1565   return i == _dbus_string_get_length (str);
1566 }
1567
1568 static dbus_bool_t
1569 make_full_path (const DBusString *basedir,
1570                 const DBusString *filename,
1571                 DBusString       *full_path)
1572 {
1573   if (_dbus_path_is_absolute (filename))
1574     {
1575       return _dbus_string_copy (filename, 0, full_path, 0);
1576     }
1577   else
1578     {
1579       if (!_dbus_string_copy (basedir, 0, full_path, 0))
1580         return FALSE;
1581       
1582       if (!_dbus_concat_dir_and_file (full_path, filename))
1583         return FALSE;
1584
1585       return TRUE;
1586     }
1587 }
1588
1589 static dbus_bool_t
1590 include_file (BusConfigParser   *parser,
1591               const DBusString  *filename,
1592               dbus_bool_t        ignore_missing,
1593               DBusError         *error)
1594 {
1595   /* FIXME good test case for this would load each config file in the
1596    * test suite both alone, and as an include, and check
1597    * that the result is the same
1598    */
1599   BusConfigParser *included;
1600   DBusError tmp_error;
1601         
1602   dbus_error_init (&tmp_error);
1603   included = bus_config_load (filename, FALSE, &tmp_error);
1604   if (included == NULL)
1605     {
1606       _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
1607
1608       if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) &&
1609           ignore_missing)
1610         {
1611           dbus_error_free (&tmp_error);
1612           return TRUE;
1613         }
1614       else
1615         {
1616           dbus_move_error (&tmp_error, error);
1617           return FALSE;
1618         }
1619     }
1620   else
1621     {
1622       _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
1623
1624       if (!merge_included (parser, included, error))
1625         {
1626           bus_config_parser_unref (included);
1627           return FALSE;
1628         }
1629
1630       bus_config_parser_unref (included);
1631       return TRUE;
1632     }
1633 }
1634
1635 static dbus_bool_t
1636 include_dir (BusConfigParser   *parser,
1637              const DBusString  *dirname,
1638              DBusError         *error)
1639 {
1640   DBusString filename;
1641   dbus_bool_t retval;
1642   DBusError tmp_error;
1643   DBusDirIter *dir;
1644   
1645   if (!_dbus_string_init (&filename))
1646     {
1647       BUS_SET_OOM (error);
1648       return FALSE;
1649     }
1650
1651   retval = FALSE;
1652   
1653   dir = _dbus_directory_open (dirname, error);
1654
1655   if (dir == NULL)
1656     goto failed;
1657
1658   dbus_error_init (&tmp_error);
1659   while (_dbus_directory_get_next_file (dir, &filename, &tmp_error))
1660     {
1661       DBusString full_path;
1662
1663       if (!_dbus_string_init (&full_path))
1664         {
1665           BUS_SET_OOM (error);
1666           goto failed;
1667         }
1668
1669       if (!_dbus_string_copy (dirname, 0, &full_path, 0))
1670         {
1671           BUS_SET_OOM (error);
1672           _dbus_string_free (&full_path);
1673           goto failed;
1674         }      
1675
1676       if (!_dbus_concat_dir_and_file (&full_path, &filename))
1677         {
1678           BUS_SET_OOM (error);
1679           _dbus_string_free (&full_path);
1680           goto failed;
1681         }
1682       
1683       if (_dbus_string_ends_with_c_str (&full_path, ".conf"))
1684         {
1685           if (!include_file (parser, &full_path, TRUE, error))
1686             {
1687               _dbus_string_free (&full_path);
1688               goto failed;
1689             }
1690         }
1691
1692       _dbus_string_free (&full_path);
1693     }
1694
1695   if (dbus_error_is_set (&tmp_error))
1696     {
1697       dbus_move_error (&tmp_error, error);
1698       goto failed;
1699     }
1700   
1701   retval = TRUE;
1702   
1703  failed:
1704   _dbus_string_free (&filename);
1705   
1706   if (dir)
1707     _dbus_directory_close (dir);
1708
1709   return retval;
1710 }
1711
1712 dbus_bool_t
1713 bus_config_parser_content (BusConfigParser   *parser,
1714                            const DBusString  *content,
1715                            DBusError         *error)
1716 {
1717   Element *e;
1718
1719   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1720
1721 #if 0
1722   {
1723     const char *c_str;
1724     
1725     _dbus_string_get_const_data (content, &c_str);
1726
1727     printf ("CONTENT %d bytes: %s\n", _dbus_string_get_length (content), c_str);
1728   }
1729 #endif
1730   
1731   e = peek_element (parser);
1732   if (e == NULL)
1733     {
1734       dbus_set_error (error, DBUS_ERROR_FAILED,
1735                       "Text content outside of any XML element in configuration file");
1736       return FALSE;
1737     }
1738   else if (e->had_content)
1739     {
1740       _dbus_assert_not_reached ("Element had multiple content blocks");
1741       return FALSE;
1742     }
1743
1744   switch (top_element_type (parser))
1745     {
1746     case ELEMENT_NONE:
1747       _dbus_assert_not_reached ("element at top of stack has no type");
1748       return FALSE;
1749
1750     case ELEMENT_BUSCONFIG:
1751     case ELEMENT_POLICY:
1752     case ELEMENT_ALLOW:
1753     case ELEMENT_DENY:
1754     case ELEMENT_FORK:
1755       if (all_whitespace (content))
1756         return TRUE;
1757       else
1758         {
1759           dbus_set_error (error, DBUS_ERROR_FAILED,
1760                           "No text content expected inside XML element %s in configuration file",
1761                           element_type_to_name (top_element_type (parser)));
1762           return FALSE;
1763         }
1764
1765     case ELEMENT_PIDFILE:
1766       {
1767         char *s;
1768
1769         e->had_content = TRUE;
1770         
1771         if (!_dbus_string_copy_data (content, &s))
1772           goto nomem;
1773           
1774         dbus_free (parser->pidfile);
1775         parser->pidfile = s;
1776       }
1777       break;
1778
1779     case ELEMENT_INCLUDE:
1780       {
1781         DBusString full_path;
1782         
1783         e->had_content = TRUE;
1784
1785         if (!_dbus_string_init (&full_path))
1786           goto nomem;
1787         
1788         if (!make_full_path (&parser->basedir, content, &full_path))
1789           {
1790             _dbus_string_free (&full_path);
1791             goto nomem;
1792           }
1793         
1794         if (!include_file (parser, &full_path,
1795                            e->d.include.ignore_missing, error))
1796           {
1797             _dbus_string_free (&full_path);
1798             return FALSE;
1799           }
1800
1801         _dbus_string_free (&full_path);
1802       }
1803       break;
1804
1805     case ELEMENT_INCLUDEDIR:
1806       {
1807         DBusString full_path;
1808         
1809         e->had_content = TRUE;
1810
1811         if (!_dbus_string_init (&full_path))
1812           goto nomem;
1813         
1814         if (!make_full_path (&parser->basedir, content, &full_path))
1815           {
1816             _dbus_string_free (&full_path);
1817             goto nomem;
1818           }
1819         
1820         if (!include_dir (parser, &full_path, error))
1821           {
1822             _dbus_string_free (&full_path);
1823             return FALSE;
1824           }
1825
1826         _dbus_string_free (&full_path);
1827       }
1828       break;
1829       
1830     case ELEMENT_USER:
1831       {
1832         char *s;
1833
1834         e->had_content = TRUE;
1835         
1836         if (!_dbus_string_copy_data (content, &s))
1837           goto nomem;
1838           
1839         dbus_free (parser->user);
1840         parser->user = s;
1841       }
1842       break;
1843
1844     case ELEMENT_TYPE:
1845       {
1846         char *s;
1847
1848         e->had_content = TRUE;
1849
1850         if (!_dbus_string_copy_data (content, &s))
1851           goto nomem;
1852         
1853         dbus_free (parser->bus_type);
1854         parser->bus_type = s;
1855       }
1856       break;
1857       
1858     case ELEMENT_LISTEN:
1859       {
1860         char *s;
1861
1862         e->had_content = TRUE;
1863         
1864         if (!_dbus_string_copy_data (content, &s))
1865           goto nomem;
1866
1867         if (!_dbus_list_append (&parser->listen_on,
1868                                 s))
1869           {
1870             dbus_free (s);
1871             goto nomem;
1872           }
1873       }
1874       break;
1875
1876     case ELEMENT_AUTH:
1877       {
1878         char *s;
1879         
1880         e->had_content = TRUE;
1881
1882         if (!_dbus_string_copy_data (content, &s))
1883           goto nomem;
1884
1885         if (!_dbus_list_append (&parser->mechanisms,
1886                                 s))
1887           {
1888             dbus_free (s);
1889             goto nomem;
1890           }
1891       }
1892       break;
1893
1894     case ELEMENT_SERVICEDIR:
1895       {
1896         char *s;
1897         DBusString full_path;
1898         
1899         e->had_content = TRUE;
1900
1901         if (!_dbus_string_init (&full_path))
1902           goto nomem;
1903         
1904         if (!make_full_path (&parser->basedir, content, &full_path))
1905           {
1906             _dbus_string_free (&full_path);
1907             goto nomem;
1908           }
1909         
1910         if (!_dbus_string_copy_data (&full_path, &s))
1911           {
1912             _dbus_string_free (&full_path);
1913             goto nomem;
1914           }
1915
1916         if (!_dbus_list_append (&parser->service_dirs, s))
1917           {
1918             _dbus_string_free (&full_path);
1919             dbus_free (s);
1920             goto nomem;
1921           }
1922
1923         _dbus_string_free (&full_path);
1924       }
1925       break;
1926
1927     case ELEMENT_LIMIT:
1928       {
1929         long val;
1930
1931         e->had_content = TRUE;
1932
1933         val = 0;
1934         if (!_dbus_string_parse_int (content, 0, &val, NULL))
1935           {
1936             dbus_set_error (error, DBUS_ERROR_FAILED,
1937                             "<limit name=\"%s\"> element has invalid value (could not parse as integer)",
1938                             e->d.limit.name);
1939             return FALSE;
1940           }
1941
1942         e->d.limit.value = val;
1943
1944         _dbus_verbose ("Loaded value %ld for limit %s\n",
1945                        e->d.limit.value,
1946                        e->d.limit.name);
1947       }
1948       break;
1949     }
1950
1951   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1952   return TRUE;
1953
1954  nomem:
1955   BUS_SET_OOM (error);
1956   return FALSE;
1957 }
1958
1959 dbus_bool_t
1960 bus_config_parser_finished (BusConfigParser   *parser,
1961                             DBusError         *error)
1962 {
1963   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1964
1965   if (parser->stack != NULL)
1966     {
1967       dbus_set_error (error, DBUS_ERROR_FAILED,
1968                       "Element <%s> was not closed in configuration file",
1969                       element_type_to_name (top_element_type (parser)));
1970
1971       return FALSE;
1972     }
1973
1974   if (parser->is_toplevel && parser->listen_on == NULL)
1975     {
1976       dbus_set_error (error, DBUS_ERROR_FAILED,
1977                       "Configuration file needs one or more <listen> elements giving addresses"); 
1978       return FALSE;
1979     }
1980   
1981   return TRUE;
1982 }
1983
1984 const char*
1985 bus_config_parser_get_user (BusConfigParser *parser)
1986 {
1987   return parser->user;
1988 }
1989
1990 const char*
1991 bus_config_parser_get_type (BusConfigParser *parser)
1992 {
1993   return parser->bus_type;
1994 }
1995
1996 DBusList**
1997 bus_config_parser_get_addresses (BusConfigParser *parser)
1998 {
1999   return &parser->listen_on;
2000 }
2001
2002 DBusList**
2003 bus_config_parser_get_mechanisms (BusConfigParser *parser)
2004 {
2005   return &parser->mechanisms;
2006 }
2007
2008 DBusList**
2009 bus_config_parser_get_service_dirs (BusConfigParser *parser)
2010 {
2011   return &parser->service_dirs;
2012 }
2013
2014 dbus_bool_t
2015 bus_config_parser_get_fork (BusConfigParser   *parser)
2016 {
2017   return parser->fork;
2018 }
2019
2020 const char *
2021 bus_config_parser_get_pidfile (BusConfigParser   *parser)
2022 {
2023   return parser->pidfile;
2024 }
2025
2026 BusPolicy*
2027 bus_config_parser_steal_policy (BusConfigParser *parser)
2028 {
2029   BusPolicy *policy;
2030
2031   _dbus_assert (parser->policy != NULL); /* can only steal the policy 1 time */
2032   
2033   policy = parser->policy;
2034
2035   parser->policy = NULL;
2036
2037   return policy;
2038 }
2039
2040 /* Overwrite any limits that were set in the configuration file */
2041 void
2042 bus_config_parser_get_limits (BusConfigParser *parser,
2043                               BusLimits       *limits)
2044 {
2045   *limits = parser->limits;
2046 }
2047
2048 #ifdef DBUS_BUILD_TESTS
2049 #include <stdio.h>
2050
2051 typedef enum
2052 {
2053   VALID,
2054   INVALID,
2055   UNKNOWN
2056 } Validity;
2057
2058 static dbus_bool_t
2059 do_load (const DBusString *full_path,
2060          Validity          validity,
2061          dbus_bool_t       oom_possible)
2062 {
2063   BusConfigParser *parser;
2064   DBusError error;
2065
2066   dbus_error_init (&error);
2067
2068   parser = bus_config_load (full_path, TRUE, &error);
2069   if (parser == NULL)
2070     {
2071       _DBUS_ASSERT_ERROR_IS_SET (&error);
2072
2073       if (oom_possible &&
2074           dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
2075         {
2076           _dbus_verbose ("Failed to load valid file due to OOM\n");
2077           dbus_error_free (&error);
2078           return TRUE;
2079         }
2080       else if (validity == VALID)
2081         {
2082           _dbus_warn ("Failed to load valid file but still had memory: %s\n",
2083                       error.message);
2084
2085           dbus_error_free (&error);
2086           return FALSE;
2087         }
2088       else
2089         {
2090           dbus_error_free (&error);
2091           return TRUE;
2092         }
2093     }
2094   else
2095     {
2096       _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
2097
2098       bus_config_parser_unref (parser);
2099
2100       if (validity == INVALID)
2101         {
2102           _dbus_warn ("Accepted invalid file\n");
2103           return FALSE;
2104         }
2105
2106       return TRUE;
2107     }
2108 }
2109
2110 typedef struct
2111 {
2112   const DBusString *full_path;
2113   Validity          validity;
2114 } LoaderOomData;
2115
2116 static dbus_bool_t
2117 check_loader_oom_func (void *data)
2118 {
2119   LoaderOomData *d = data;
2120
2121   return do_load (d->full_path, d->validity, TRUE);
2122 }
2123
2124 static dbus_bool_t
2125 process_test_subdir (const DBusString *test_base_dir,
2126                      const char       *subdir,
2127                      Validity          validity)
2128 {
2129   DBusString test_directory;
2130   DBusString filename;
2131   DBusDirIter *dir;
2132   dbus_bool_t retval;
2133   DBusError error;
2134
2135   retval = FALSE;
2136   dir = NULL;
2137
2138   if (!_dbus_string_init (&test_directory))
2139     _dbus_assert_not_reached ("didn't allocate test_directory\n");
2140
2141   _dbus_string_init_const (&filename, subdir);
2142
2143   if (!_dbus_string_copy (test_base_dir, 0,
2144                           &test_directory, 0))
2145     _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
2146
2147   if (!_dbus_concat_dir_and_file (&test_directory, &filename))
2148     _dbus_assert_not_reached ("couldn't allocate full path");
2149
2150   _dbus_string_free (&filename);
2151   if (!_dbus_string_init (&filename))
2152     _dbus_assert_not_reached ("didn't allocate filename string\n");
2153
2154   dbus_error_init (&error);
2155   dir = _dbus_directory_open (&test_directory, &error);
2156   if (dir == NULL)
2157     {
2158       _dbus_warn ("Could not open %s: %s\n",
2159                   _dbus_string_get_const_data (&test_directory),
2160                   error.message);
2161       dbus_error_free (&error);
2162       goto failed;
2163     }
2164
2165   printf ("Testing:\n");
2166
2167  next:
2168   while (_dbus_directory_get_next_file (dir, &filename, &error))
2169     {
2170       DBusString full_path;
2171       LoaderOomData d;
2172
2173       if (!_dbus_string_init (&full_path))
2174         _dbus_assert_not_reached ("couldn't init string");
2175
2176       if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
2177         _dbus_assert_not_reached ("couldn't copy dir to full_path");
2178
2179       if (!_dbus_concat_dir_and_file (&full_path, &filename))
2180         _dbus_assert_not_reached ("couldn't concat file to dir");
2181
2182       if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
2183         {
2184           _dbus_verbose ("Skipping non-.conf file %s\n",
2185                          _dbus_string_get_const_data (&filename));
2186           _dbus_string_free (&full_path);
2187           goto next;
2188         }
2189
2190       printf ("    %s\n", _dbus_string_get_const_data (&filename));
2191
2192       _dbus_verbose (" expecting %s\n",
2193                      validity == VALID ? "valid" :
2194                      (validity == INVALID ? "invalid" :
2195                       (validity == UNKNOWN ? "unknown" : "???")));
2196
2197       d.full_path = &full_path;
2198       d.validity = validity;
2199       if (!_dbus_test_oom_handling ("config-loader", check_loader_oom_func, &d))
2200         _dbus_assert_not_reached ("test failed");
2201
2202       _dbus_string_free (&full_path);
2203     }
2204
2205   if (dbus_error_is_set (&error))
2206     {
2207       _dbus_warn ("Could not get next file in %s: %s\n",
2208                   _dbus_string_get_const_data (&test_directory),
2209                   error.message);
2210       dbus_error_free (&error);
2211       goto failed;
2212     }
2213
2214   retval = TRUE;
2215
2216  failed:
2217
2218   if (dir)
2219     _dbus_directory_close (dir);
2220   _dbus_string_free (&test_directory);
2221   _dbus_string_free (&filename);
2222
2223   return retval;
2224 }
2225
2226 dbus_bool_t
2227 bus_config_parser_test (const DBusString *test_data_dir)
2228 {
2229   if (test_data_dir == NULL ||
2230       _dbus_string_get_length (test_data_dir) == 0)
2231     {
2232       printf ("No test data\n");
2233       return TRUE;
2234     }
2235
2236   if (!process_test_subdir (test_data_dir, "valid-config-files", VALID))
2237     return FALSE;
2238
2239   return TRUE;
2240 }
2241
2242 #endif /* DBUS_BUILD_TESTS */
2243