2003-09-21 Havoc Pennington <hp@pobox.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->refcount = 1;
341
342   return parser;
343 }
344
345 void
346 bus_config_parser_ref (BusConfigParser *parser)
347 {
348   _dbus_assert (parser->refcount > 0);
349
350   parser->refcount += 1;
351 }
352
353 void
354 bus_config_parser_unref (BusConfigParser *parser)
355 {
356   _dbus_assert (parser->refcount > 0);
357
358   parser->refcount -= 1;
359
360   if (parser->refcount == 0)
361     {
362       while (parser->stack != NULL)
363         pop_element (parser);
364
365       dbus_free (parser->user);
366       dbus_free (parser->bus_type);
367       dbus_free (parser->pidfile);
368       
369       _dbus_list_foreach (&parser->listen_on,
370                           (DBusForeachFunction) dbus_free,
371                           NULL);
372
373       _dbus_list_clear (&parser->listen_on);
374
375       _dbus_list_foreach (&parser->service_dirs,
376                           (DBusForeachFunction) dbus_free,
377                           NULL);
378
379       _dbus_list_clear (&parser->service_dirs);
380
381       _dbus_list_foreach (&parser->mechanisms,
382                           (DBusForeachFunction) dbus_free,
383                           NULL);
384
385       _dbus_list_clear (&parser->mechanisms);
386       
387       _dbus_string_free (&parser->basedir);
388
389       if (parser->policy)
390         bus_policy_unref (parser->policy);
391       
392       dbus_free (parser);
393     }
394 }
395
396 dbus_bool_t
397 bus_config_parser_check_doctype (BusConfigParser   *parser,
398                                  const char        *doctype,
399                                  DBusError         *error)
400 {
401   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
402
403   if (strcmp (doctype, "busconfig") != 0)
404     {
405       dbus_set_error (error,
406                       DBUS_ERROR_FAILED,
407                       "Configuration file has the wrong document type %s",
408                       doctype);
409       return FALSE;
410     }
411   else
412     return TRUE;
413 }
414
415 typedef struct
416 {
417   const char  *name;
418   const char **retloc;
419 } LocateAttr;
420
421 static dbus_bool_t
422 locate_attributes (BusConfigParser  *parser,
423                    const char       *element_name,
424                    const char      **attribute_names,
425                    const char      **attribute_values,
426                    DBusError        *error,
427                    const char       *first_attribute_name,
428                    const char      **first_attribute_retloc,
429                    ...)
430 {
431   va_list args;
432   const char *name;
433   const char **retloc;
434   int n_attrs;
435 #define MAX_ATTRS 24
436   LocateAttr attrs[MAX_ATTRS];
437   dbus_bool_t retval;
438   int i;
439
440   _dbus_assert (first_attribute_name != NULL);
441   _dbus_assert (first_attribute_retloc != NULL);
442
443   retval = TRUE;
444
445   n_attrs = 1;
446   attrs[0].name = first_attribute_name;
447   attrs[0].retloc = first_attribute_retloc;
448   *first_attribute_retloc = NULL;
449
450   va_start (args, first_attribute_retloc);
451
452   name = va_arg (args, const char*);
453   retloc = va_arg (args, const char**);
454
455   while (name != NULL)
456     {
457       _dbus_assert (retloc != NULL);
458       _dbus_assert (n_attrs < MAX_ATTRS);
459
460       attrs[n_attrs].name = name;
461       attrs[n_attrs].retloc = retloc;
462       n_attrs += 1;
463       *retloc = NULL;
464
465       name = va_arg (args, const char*);
466       retloc = va_arg (args, const char**);
467     }
468
469   va_end (args);
470
471   if (!retval)
472     return retval;
473
474   i = 0;
475   while (attribute_names[i])
476     {
477       int j;
478       dbus_bool_t found;
479       
480       found = FALSE;
481       j = 0;
482       while (j < n_attrs)
483         {
484           if (strcmp (attrs[j].name, attribute_names[i]) == 0)
485             {
486               retloc = attrs[j].retloc;
487
488               if (*retloc != NULL)
489                 {
490                   dbus_set_error (error, DBUS_ERROR_FAILED,
491                                   "Attribute \"%s\" repeated twice on the same <%s> element",
492                                   attrs[j].name, element_name);
493                   retval = FALSE;
494                   goto out;
495                 }
496
497               *retloc = attribute_values[i];
498               found = TRUE;
499             }
500
501           ++j;
502         }
503
504       if (!found)
505         {
506           dbus_set_error (error, DBUS_ERROR_FAILED,
507                           "Attribute \"%s\" is invalid on <%s> element in this context",
508                           attribute_names[i], element_name);
509           retval = FALSE;
510           goto out;
511         }
512
513       ++i;
514     }
515
516  out:
517   return retval;
518 }
519
520 static dbus_bool_t
521 check_no_attributes (BusConfigParser  *parser,
522                      const char       *element_name,
523                      const char      **attribute_names,
524                      const char      **attribute_values,
525                      DBusError        *error)
526 {
527   if (attribute_names[0] != NULL)
528     {
529       dbus_set_error (error, DBUS_ERROR_FAILED,
530                       "Attribute \"%s\" is invalid on <%s> element in this context",
531                       attribute_names[0], element_name);
532       return FALSE;
533     }
534
535   return TRUE;
536 }
537
538 static dbus_bool_t
539 start_busconfig_child (BusConfigParser   *parser,
540                        const char        *element_name,
541                        const char       **attribute_names,
542                        const char       **attribute_values,
543                        DBusError         *error)
544 {
545   if (strcmp (element_name, "user") == 0)
546     {
547       if (!check_no_attributes (parser, "user", attribute_names, attribute_values, error))
548         return FALSE;
549
550       if (push_element (parser, ELEMENT_USER) == NULL)
551         {
552           BUS_SET_OOM (error);
553           return FALSE;
554         }
555
556       return TRUE;
557     }
558   else if (strcmp (element_name, "type") == 0)
559     {
560       if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
561         return FALSE;
562
563       if (push_element (parser, ELEMENT_TYPE) == NULL)
564         {
565           BUS_SET_OOM (error);
566           return FALSE;
567         }
568
569       return TRUE;
570     }
571   else if (strcmp (element_name, "fork") == 0)
572     {
573       if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
574         return FALSE;
575
576       if (push_element (parser, ELEMENT_FORK) == NULL)
577         {
578           BUS_SET_OOM (error);
579           return FALSE;
580         }
581
582       parser->fork = TRUE;
583       
584       return TRUE;
585     }
586   else if (strcmp (element_name, "pidfile") == 0)
587     {
588       if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
589         return FALSE;
590
591       if (push_element (parser, ELEMENT_PIDFILE) == NULL)
592         {
593           BUS_SET_OOM (error);
594           return FALSE;
595         }
596
597       return TRUE;
598     }
599   else if (strcmp (element_name, "listen") == 0)
600     {
601       if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
602         return FALSE;
603
604       if (push_element (parser, ELEMENT_LISTEN) == NULL)
605         {
606           BUS_SET_OOM (error);
607           return FALSE;
608         }
609
610       return TRUE;
611     }
612   else if (strcmp (element_name, "auth") == 0)
613     {
614       if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
615         return FALSE;
616
617       if (push_element (parser, ELEMENT_AUTH) == NULL)
618         {
619           BUS_SET_OOM (error);
620           return FALSE;
621         }
622
623       return TRUE;
624     }
625   else if (strcmp (element_name, "includedir") == 0)
626     {
627       if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error))
628         return FALSE;
629
630       if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL)
631         {
632           BUS_SET_OOM (error);
633           return FALSE;
634         }
635
636       return TRUE;
637     }
638   else if (strcmp (element_name, "servicedir") == 0)
639     {
640       if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error))
641         return FALSE;
642
643       if (push_element (parser, ELEMENT_SERVICEDIR) == NULL)
644         {
645           BUS_SET_OOM (error);
646           return FALSE;
647         }
648
649       return TRUE;
650     }
651   else if (strcmp (element_name, "include") == 0)
652     {
653       Element *e;
654       const char *ignore_missing;
655
656       if ((e = push_element (parser, ELEMENT_INCLUDE)) == NULL)
657         {
658           BUS_SET_OOM (error);
659           return FALSE;
660         }
661
662       e->d.include.ignore_missing = FALSE;
663
664       if (!locate_attributes (parser, "include",
665                               attribute_names,
666                               attribute_values,
667                               error,
668                               "ignore_missing", &ignore_missing,
669                               NULL))
670         return FALSE;
671
672       if (ignore_missing != NULL)
673         {
674           if (strcmp (ignore_missing, "yes") == 0)
675             e->d.include.ignore_missing = TRUE;
676           else if (strcmp (ignore_missing, "no") == 0)
677             e->d.include.ignore_missing = FALSE;
678           else
679             {
680               dbus_set_error (error, DBUS_ERROR_FAILED,
681                               "ignore_missing attribute must have value \"yes\" or \"no\"");
682               return FALSE;
683             }
684         }
685
686       return TRUE;
687     }
688   else if (strcmp (element_name, "policy") == 0)
689     {
690       Element *e;
691       const char *context;
692       const char *user;
693       const char *group;
694
695       if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
696         {
697           BUS_SET_OOM (error);
698           return FALSE;
699         }
700
701       e->d.policy.type = POLICY_IGNORED;
702       
703       if (!locate_attributes (parser, "policy",
704                               attribute_names,
705                               attribute_values,
706                               error,
707                               "context", &context,
708                               "user", &user,
709                               "group", &group,
710                               NULL))
711         return FALSE;
712
713       if (((context && user) ||
714            (context && group)) ||
715           (user && group) ||
716           !(context || user || group))
717         {
718           dbus_set_error (error, DBUS_ERROR_FAILED,
719                           "<policy> element must have exactly one of (context|user|group) attributes");
720           return FALSE;
721         }
722
723       if (context != NULL)
724         {
725           if (strcmp (context, "default") == 0)
726             {
727               e->d.policy.type = POLICY_DEFAULT;
728             }
729           else if (strcmp (context, "mandatory") == 0)
730             {
731               e->d.policy.type = POLICY_MANDATORY;
732             }
733           else
734             {
735               dbus_set_error (error, DBUS_ERROR_FAILED,
736                               "context attribute on <policy> must have the value \"default\" or \"mandatory\", not \"%s\"",
737                               context);
738               return FALSE;
739             }
740         }
741       else if (user != NULL)
742         {
743           DBusString username;
744           _dbus_string_init_const (&username, user);
745
746           if (_dbus_get_user_id (&username,
747                                  &e->d.policy.gid_or_uid))
748             e->d.policy.type = POLICY_USER;
749           else
750             _dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
751                         user);
752         }
753       else if (group != NULL)
754         {
755           DBusString group_name;
756           _dbus_string_init_const (&group_name, group);
757
758           if (_dbus_get_group_id (&group_name,
759                                   &e->d.policy.gid_or_uid))
760             e->d.policy.type = POLICY_GROUP;
761           else
762             _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
763                         group);          
764         }
765       else
766         {
767           _dbus_assert_not_reached ("all <policy> attributes null and we didn't set error");
768         }
769       
770       return TRUE;
771     }
772   else if (strcmp (element_name, "limit") == 0)
773     {
774       Element *e;
775       const char *name;
776
777       if ((e = push_element (parser, ELEMENT_LIMIT)) == NULL)
778         {
779           BUS_SET_OOM (error);
780           return FALSE;
781         }
782       
783       if (!locate_attributes (parser, "limit",
784                               attribute_names,
785                               attribute_values,
786                               error,
787                               "name", &name,
788                               NULL))
789         return FALSE;
790
791       if (name == NULL)
792         {
793           dbus_set_error (error, DBUS_ERROR_FAILED,
794                           "<limit> element must have a \"name\" attribute");
795           return FALSE;
796         }
797
798       e->d.limit.name = _dbus_strdup (name);
799       if (e->d.limit.name == NULL)
800         {
801           BUS_SET_OOM (error);
802           return FALSE;
803         }
804
805       return TRUE;
806     }
807   else
808     {
809       dbus_set_error (error, DBUS_ERROR_FAILED,
810                       "Element <%s> not allowed inside <%s> in configuration file",
811                       element_name, "busconfig");
812       return FALSE;
813     }
814 }
815
816 static int
817 message_type_from_string (const char *type_str)
818 {
819   if (strcmp (type_str, "method_call") == 0)
820     return DBUS_MESSAGE_TYPE_METHOD_CALL;
821   if (strcmp (type_str, "method_return") == 0)
822     return DBUS_MESSAGE_TYPE_METHOD_RETURN;
823   else if (strcmp (type_str, "signal") == 0)
824     return DBUS_MESSAGE_TYPE_SIGNAL;
825   else if (strcmp (type_str, "error") == 0)
826     return DBUS_MESSAGE_TYPE_ERROR;
827   else
828     return DBUS_MESSAGE_TYPE_INVALID;
829 }
830
831 static dbus_bool_t
832 append_rule_from_element (BusConfigParser   *parser,
833                           const char        *element_name,
834                           const char       **attribute_names,
835                           const char       **attribute_values,
836                           dbus_bool_t        allow,
837                           DBusError         *error)
838 {
839   const char *send_interface;
840   const char *send_member;
841   const char *send_error;
842   const char *send_destination;
843   const char *send_path;
844   const char *send_type;
845   const char *receive_interface;
846   const char *receive_member;
847   const char *receive_error;
848   const char *receive_sender;
849   const char *receive_path;
850   const char *receive_type;
851   const char *eavesdrop;
852   const char *own;
853   const char *user;
854   const char *group;
855   BusPolicyRule *rule;
856   
857   if (!locate_attributes (parser, element_name,
858                           attribute_names,
859                           attribute_values,
860                           error,
861                           "send_interface", &send_interface,
862                           "send_member", &send_member,
863                           "send_error", &send_error,
864                           "send_destination", &send_destination,
865                           "send_path", &send_path,
866                           "send_type", &send_type,
867                           "receive_interface", &receive_interface,
868                           "receive_member", &receive_member,
869                           "receive_error", &receive_error,
870                           "receive_sender", &receive_sender,
871                           "receive_path", &receive_path,
872                           "receive_type", &receive_type,
873                           "eavesdrop", &eavesdrop,
874                           "own", &own,
875                           "user", &user,
876                           "group", &group,
877                           NULL))
878     return FALSE;
879
880   if (!(send_interface || send_member || send_error || send_destination ||
881         send_type || send_path ||
882         receive_interface || receive_member || receive_error || receive_sender ||
883         receive_type || receive_path || eavesdrop ||
884         own || user || group))
885     {
886       dbus_set_error (error, DBUS_ERROR_FAILED,
887                       "Element <%s> must have one or more attributes",
888                       element_name);
889       return FALSE;
890     }
891
892   if ((send_member && (send_interface == NULL && send_path == NULL)) ||
893       (receive_member && (receive_interface == NULL && receive_path == NULL)))
894     {
895       dbus_set_error (error, DBUS_ERROR_FAILED,
896                       "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.",
897                       element_name);
898       return FALSE;
899     }
900   
901   /* Allowed combinations of elements are:
902    *
903    *   base, must be all send or all receive:
904    *     nothing
905    *     interface
906    *     interface + member
907    *     error
908    * 
909    *   base send_ can combine with send_destination, send_path, send_type
910    *   base receive_ with receive_sender, receive_path, receive_type, eavesdrop
911    *
912    *   user, group, own must occur alone
913    *
914    * Pretty sure the below stuff is broken, FIXME think about it more.
915    */
916
917   if (((send_interface && send_error) ||
918        (send_interface && receive_interface) ||
919        (send_interface && receive_member) ||
920        (send_interface && receive_error) ||
921        (send_interface && receive_sender) ||
922        (send_interface && eavesdrop) ||
923        (send_interface && own) ||
924        (send_interface && user) ||
925        (send_interface && group)) ||
926
927       ((send_member && send_error) ||
928        (send_member && receive_interface) ||
929        (send_member && receive_member) ||
930        (send_member && receive_error) ||
931        (send_member && receive_sender) ||
932        (send_member && eavesdrop) ||
933        (send_member && own) ||
934        (send_member && user) ||
935        (send_member && group)) ||
936       
937       ((send_error && receive_interface) ||
938        (send_error && receive_member) ||
939        (send_error && receive_error) ||
940        (send_error && receive_sender) ||
941        (send_error && eavesdrop) ||
942        (send_error && own) ||
943        (send_error && user) ||
944        (send_error && group)) ||
945
946       ((send_destination && receive_interface) ||
947        (send_destination && receive_member) ||
948        (send_destination && receive_error) ||
949        (send_destination && receive_sender) ||
950        (send_destination && eavesdrop) ||
951        (send_destination && own) ||
952        (send_destination && user) ||
953        (send_destination && group)) ||
954
955       ((send_type && receive_interface) ||
956        (send_type && receive_member) ||
957        (send_type && receive_error) ||
958        (send_type && receive_sender) ||
959        (send_type && eavesdrop) ||
960        (send_type && own) ||
961        (send_type && user) ||
962        (send_type && group)) ||
963
964       ((send_path && receive_interface) ||
965        (send_path && receive_member) ||
966        (send_path && receive_error) ||
967        (send_path && receive_sender) ||
968        (send_path && eavesdrop) ||
969        (send_path && own) ||
970        (send_path && user) ||
971        (send_path && group)) ||
972       
973       ((receive_interface && receive_error) ||
974        (receive_interface && own) ||
975        (receive_interface && user) ||
976        (receive_interface && group)) ||
977
978       ((receive_member && receive_error) ||
979        (receive_member && own) ||
980        (receive_member && user) ||
981        (receive_member && group)) ||
982       
983       ((receive_error && own) ||
984        (receive_error && user) ||
985        (receive_error && group)) ||
986
987       ((eavesdrop && own) ||
988        (eavesdrop && user) ||
989        (eavesdrop && group)) ||
990       
991       ((own && user) ||
992        (own && group)) ||
993
994       ((user && group)))
995     {
996       dbus_set_error (error, DBUS_ERROR_FAILED,
997                       "Invalid combination of attributes on element <%s>",
998                       element_name);
999       return FALSE;
1000     }
1001   
1002   rule = NULL;
1003
1004   /* In BusPolicyRule, NULL represents wildcard.
1005    * In the config file, '*' represents it.
1006    */
1007 #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
1008
1009   if (send_interface || send_member || send_error || send_destination ||
1010       send_path || send_type)
1011     {
1012       int message_type;
1013       
1014       if (IS_WILDCARD (send_interface))
1015         send_interface = NULL;
1016       if (IS_WILDCARD (send_member))
1017         send_member = NULL;
1018       if (IS_WILDCARD (send_error))
1019         send_error = NULL;
1020       if (IS_WILDCARD (send_destination))
1021         send_destination = NULL;
1022       if (IS_WILDCARD (send_path))
1023         send_path = NULL;
1024       if (IS_WILDCARD (send_type))
1025         send_type = NULL;
1026
1027       message_type = DBUS_MESSAGE_TYPE_INVALID;
1028       if (send_type != NULL)
1029         {
1030           message_type = message_type_from_string (send_type);
1031           if (message_type == DBUS_MESSAGE_TYPE_INVALID)
1032             {
1033               dbus_set_error (error, DBUS_ERROR_FAILED,
1034                               "Bad message type \"%s\"",
1035                               send_type);
1036               return FALSE;
1037             }
1038         }
1039       
1040       rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); 
1041       if (rule == NULL)
1042         goto nomem;
1043       
1044       rule->d.send.message_type = message_type;
1045       rule->d.send.path = _dbus_strdup (send_path);
1046       rule->d.send.interface = _dbus_strdup (send_interface);
1047       rule->d.send.member = _dbus_strdup (send_member);
1048       rule->d.send.error = _dbus_strdup (send_error);
1049       rule->d.send.destination = _dbus_strdup (send_destination);
1050       if (send_path && rule->d.send.path == NULL)
1051         goto nomem;
1052       if (send_interface && rule->d.send.interface == NULL)
1053         goto nomem;
1054       if (send_member && rule->d.send.member == NULL)
1055         goto nomem;
1056       if (send_error && rule->d.send.error == NULL)
1057         goto nomem;
1058       if (send_destination && rule->d.send.destination == NULL)
1059         goto nomem;
1060     }
1061   else if (receive_interface || receive_member || receive_error || receive_sender ||
1062            receive_path || receive_type || eavesdrop)
1063     {
1064       int message_type;
1065       
1066       if (IS_WILDCARD (receive_interface))
1067         receive_interface = NULL;
1068       if (IS_WILDCARD (receive_member))
1069         receive_member = NULL;
1070       if (IS_WILDCARD (receive_error))
1071         receive_error = NULL;
1072       if (IS_WILDCARD (receive_sender))
1073         receive_sender = NULL;
1074       if (IS_WILDCARD (receive_path))
1075         receive_path = NULL;
1076       if (IS_WILDCARD (receive_type))
1077         receive_type = NULL;
1078
1079       message_type = DBUS_MESSAGE_TYPE_INVALID;
1080       if (receive_type != NULL)
1081         {
1082           message_type = message_type_from_string (receive_type);
1083           if (message_type == DBUS_MESSAGE_TYPE_INVALID)
1084             {
1085               dbus_set_error (error, DBUS_ERROR_FAILED,
1086                               "Bad message type \"%s\"",
1087                               receive_type);
1088               return FALSE;
1089             }
1090         }
1091
1092
1093       if (eavesdrop &&
1094           !(strcmp (eavesdrop, "true") == 0 ||
1095             strcmp (eavesdrop, "false") == 0))
1096         {
1097           dbus_set_error (error, DBUS_ERROR_FAILED,
1098                           "Bad value \"%s\" for eavesdrop attribute, must be true or false",
1099                           eavesdrop);
1100           return FALSE;
1101         }
1102       
1103       rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); 
1104       if (rule == NULL)
1105         goto nomem;
1106
1107       if (eavesdrop)
1108         rule->d.receive.eavesdrop = (strcmp (eavesdrop, "true") == 0);
1109       
1110       rule->d.receive.message_type = message_type;
1111       rule->d.receive.path = _dbus_strdup (receive_path);
1112       rule->d.receive.interface = _dbus_strdup (receive_interface);
1113       rule->d.receive.member = _dbus_strdup (receive_member);
1114       rule->d.receive.error = _dbus_strdup (receive_error);
1115       rule->d.receive.origin = _dbus_strdup (receive_sender);
1116       if (receive_path && rule->d.receive.path == NULL)
1117         goto nomem;
1118       if (receive_interface && rule->d.receive.interface == NULL)
1119         goto nomem;
1120       if (receive_member && rule->d.receive.member == NULL)
1121         goto nomem;
1122       if (receive_error && rule->d.receive.error == NULL)
1123         goto nomem;
1124       if (receive_sender && rule->d.receive.origin == NULL)
1125         goto nomem;
1126     }
1127   else if (own)
1128     {
1129       rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow); 
1130       if (rule == NULL)
1131         goto nomem;
1132
1133       if (IS_WILDCARD (own))
1134         own = NULL;
1135       
1136       rule->d.own.service_name = _dbus_strdup (own);
1137       if (own && rule->d.own.service_name == NULL)
1138         goto nomem;
1139     }
1140   else if (user)
1141     {      
1142       if (IS_WILDCARD (user))
1143         {
1144           rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); 
1145           if (rule == NULL)
1146             goto nomem;
1147
1148           rule->d.user.uid = DBUS_UID_UNSET;
1149         }
1150       else
1151         {
1152           DBusString username;
1153           dbus_uid_t uid;
1154           
1155           _dbus_string_init_const (&username, user);
1156       
1157           if (_dbus_get_user_id (&username, &uid))
1158             {
1159               rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); 
1160               if (rule == NULL)
1161                 goto nomem;
1162
1163               rule->d.user.uid = uid;
1164             }
1165           else
1166             {
1167               _dbus_warn ("Unknown username \"%s\" on element <%s>\n",
1168                           user, element_name);
1169             }
1170         }
1171     }
1172   else if (group)
1173     {
1174       if (IS_WILDCARD (group))
1175         {
1176           rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); 
1177           if (rule == NULL)
1178             goto nomem;
1179
1180           rule->d.group.gid = DBUS_GID_UNSET;
1181         }
1182       else
1183         {
1184           DBusString groupname;
1185           dbus_gid_t gid;
1186           
1187           _dbus_string_init_const (&groupname, group);
1188           
1189           if (_dbus_get_user_id (&groupname, &gid))
1190             {
1191               rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); 
1192               if (rule == NULL)
1193                 goto nomem;
1194
1195               rule->d.group.gid = gid;
1196             }
1197           else
1198             {
1199               _dbus_warn ("Unknown group \"%s\" on element <%s>\n",
1200                           group, element_name);
1201             }
1202         }
1203     }
1204   else
1205     _dbus_assert_not_reached ("Did not handle some combination of attributes on <allow> or <deny>");
1206
1207   if (rule != NULL)
1208     {
1209       Element *pe;
1210       
1211       pe = peek_element (parser);      
1212       _dbus_assert (pe != NULL);
1213       _dbus_assert (pe->type == ELEMENT_POLICY);
1214
1215       switch (pe->d.policy.type)
1216         {
1217         case POLICY_IGNORED:
1218           /* drop the rule on the floor */
1219           break;
1220           
1221         case POLICY_DEFAULT:
1222           if (!bus_policy_append_default_rule (parser->policy, rule))
1223             goto nomem;
1224           break;
1225         case POLICY_MANDATORY:
1226           if (!bus_policy_append_mandatory_rule (parser->policy, rule))
1227             goto nomem;
1228           break;
1229         case POLICY_USER:
1230           if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1231             {
1232               dbus_set_error (error, DBUS_ERROR_FAILED,
1233                               "<%s> rule cannot be per-user because it has bus-global semantics",
1234                               element_name);
1235               goto failed;
1236             }
1237           
1238           if (!bus_policy_append_user_rule (parser->policy, pe->d.policy.gid_or_uid,
1239                                             rule))
1240             goto nomem;
1241           break;
1242         case POLICY_GROUP:
1243           if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
1244             {
1245               dbus_set_error (error, DBUS_ERROR_FAILED,
1246                               "<%s> rule cannot be per-group because it has bus-global semantics",
1247                               element_name);
1248               goto failed;
1249             }
1250           
1251           if (!bus_policy_append_group_rule (parser->policy, pe->d.policy.gid_or_uid,
1252                                              rule))
1253             goto nomem;
1254           break;
1255         }
1256       
1257       bus_policy_rule_unref (rule);
1258       rule = NULL;
1259     }
1260   
1261   return TRUE;
1262
1263  nomem:
1264   BUS_SET_OOM (error);
1265  failed:
1266   if (rule)
1267     bus_policy_rule_unref (rule);
1268   return FALSE;
1269 }
1270
1271 static dbus_bool_t
1272 start_policy_child (BusConfigParser   *parser,
1273                     const char        *element_name,
1274                     const char       **attribute_names,
1275                     const char       **attribute_values,
1276                     DBusError         *error)
1277 {
1278   if (strcmp (element_name, "allow") == 0)
1279     {
1280       if (!append_rule_from_element (parser, element_name,
1281                                      attribute_names, attribute_values,
1282                                      TRUE, error))
1283         return FALSE;
1284       
1285       if (push_element (parser, ELEMENT_ALLOW) == NULL)
1286         {
1287           BUS_SET_OOM (error);
1288           return FALSE;
1289         }
1290       
1291       return TRUE;
1292     }
1293   else if (strcmp (element_name, "deny") == 0)
1294     {
1295       if (!append_rule_from_element (parser, element_name,
1296                                      attribute_names, attribute_values,
1297                                      FALSE, error))
1298         return FALSE;
1299       
1300       if (push_element (parser, ELEMENT_DENY) == NULL)
1301         {
1302           BUS_SET_OOM (error);
1303           return FALSE;
1304         }
1305       
1306       return TRUE;
1307     }
1308   else
1309     {
1310       dbus_set_error (error, DBUS_ERROR_FAILED,
1311                       "Element <%s> not allowed inside <%s> in configuration file",
1312                       element_name, "policy");
1313       return FALSE;
1314     }
1315 }
1316
1317 dbus_bool_t
1318 bus_config_parser_start_element (BusConfigParser   *parser,
1319                                  const char        *element_name,
1320                                  const char       **attribute_names,
1321                                  const char       **attribute_values,
1322                                  DBusError         *error)
1323 {
1324   ElementType t;
1325
1326   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1327
1328   /* printf ("START: %s\n", element_name); */
1329   
1330   t = top_element_type (parser);
1331
1332   if (t == ELEMENT_NONE)
1333     {
1334       if (strcmp (element_name, "busconfig") == 0)
1335         {
1336           if (!check_no_attributes (parser, "busconfig", attribute_names, attribute_values, error))
1337             return FALSE;
1338           
1339           if (push_element (parser, ELEMENT_BUSCONFIG) == NULL)
1340             {
1341               BUS_SET_OOM (error);
1342               return FALSE;
1343             }
1344
1345           return TRUE;
1346         }
1347       else
1348         {
1349           dbus_set_error (error, DBUS_ERROR_FAILED,
1350                           "Unknown element <%s> at root of configuration file",
1351                           element_name);
1352           return FALSE;
1353         }
1354     }
1355   else if (t == ELEMENT_BUSCONFIG)
1356     {
1357       return start_busconfig_child (parser, element_name,
1358                                     attribute_names, attribute_values,
1359                                     error);
1360     }
1361   else if (t == ELEMENT_POLICY)
1362     {
1363       return start_policy_child (parser, element_name,
1364                                  attribute_names, attribute_values,
1365                                  error);
1366     }
1367   else
1368     {
1369       dbus_set_error (error, DBUS_ERROR_FAILED,
1370                       "Element <%s> is not allowed in this context",
1371                       element_name);
1372       return FALSE;
1373     }  
1374 }
1375
1376 static dbus_bool_t
1377 set_limit (BusConfigParser *parser,
1378            const char      *name,
1379            long             value,
1380            DBusError       *error)
1381 {
1382   dbus_bool_t must_be_positive;
1383   dbus_bool_t must_be_int;
1384
1385   must_be_int = FALSE;
1386   must_be_positive = FALSE;
1387   
1388   if (strcmp (name, "max_incoming_bytes") == 0)
1389     {
1390       must_be_positive = TRUE;
1391       parser->limits.max_incoming_bytes = value;
1392     }
1393   else if (strcmp (name, "max_outgoing_bytes") == 0)
1394     {
1395       must_be_positive = TRUE;
1396       parser->limits.max_outgoing_bytes = value;
1397     }
1398   else if (strcmp (name, "max_message_size") == 0)
1399     {
1400       must_be_positive = TRUE;
1401       parser->limits.max_message_size = value;
1402     }
1403   else if (strcmp (name, "activation_timeout") == 0)
1404     {
1405       must_be_positive = TRUE;
1406       must_be_int = TRUE;
1407       parser->limits.activation_timeout = value;
1408     }
1409   else if (strcmp (name, "auth_timeout") == 0)
1410     {
1411       must_be_positive = TRUE;
1412       must_be_int = TRUE;
1413       parser->limits.auth_timeout = value;
1414     }
1415   else if (strcmp (name, "max_completed_connections") == 0)
1416     {
1417       must_be_positive = TRUE;
1418       must_be_int = TRUE;
1419       parser->limits.max_completed_connections = value;
1420     }
1421   else if (strcmp (name, "max_incomplete_connections") == 0)
1422     {
1423       must_be_positive = TRUE;
1424       must_be_int = TRUE;
1425       parser->limits.max_incomplete_connections = value;
1426     }
1427   else if (strcmp (name, "max_connections_per_user") == 0)
1428     {
1429       must_be_positive = TRUE;
1430       must_be_int = TRUE;
1431       parser->limits.max_connections_per_user = value;
1432     }
1433   else if (strcmp (name, "max_pending_activations") == 0)
1434     {
1435       must_be_positive = TRUE;
1436       must_be_int = TRUE;
1437       parser->limits.max_pending_activations = value;
1438     }
1439   else if (strcmp (name, "max_services_per_connection") == 0)
1440     {
1441       must_be_positive = TRUE;
1442       must_be_int = TRUE;
1443       parser->limits.max_services_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