00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include "config-parser.h"
00024 #include "test.h"
00025 #include "utils.h"
00026 #include "policy.h"
00027 #include <dbus/dbus-list.h>
00028 #include <dbus/dbus-internals.h>
00029 #include <string.h>
00030
00031 typedef enum
00032 {
00033 ELEMENT_NONE,
00034 ELEMENT_BUSCONFIG,
00035 ELEMENT_INCLUDE,
00036 ELEMENT_USER,
00037 ELEMENT_LISTEN,
00038 ELEMENT_AUTH,
00039 ELEMENT_POLICY,
00040 ELEMENT_LIMIT,
00041 ELEMENT_ALLOW,
00042 ELEMENT_DENY,
00043 ELEMENT_FORK,
00044 ELEMENT_PIDFILE,
00045 ELEMENT_SERVICEDIR,
00046 ELEMENT_INCLUDEDIR,
00047 ELEMENT_TYPE
00048 } ElementType;
00049
00050 typedef enum
00051 {
00052
00053 POLICY_IGNORED,
00054
00055
00056 POLICY_DEFAULT,
00057 POLICY_MANDATORY,
00058 POLICY_USER,
00059 POLICY_GROUP
00060 } PolicyType;
00061
00062 typedef struct
00063 {
00064 ElementType type;
00065
00066 unsigned int had_content : 1;
00067
00068 union
00069 {
00070 struct
00071 {
00072 unsigned int ignore_missing : 1;
00073 } include;
00074
00075 struct
00076 {
00077 PolicyType type;
00078 unsigned long gid_or_uid;
00079 } policy;
00080
00081 struct
00082 {
00083 char *name;
00084 long value;
00085 } limit;
00086
00087 } d;
00088
00089 } Element;
00090
00091 struct BusConfigParser
00092 {
00093 int refcount;
00094
00095 DBusString basedir;
00097 DBusList *stack;
00099 char *user;
00101 char *bus_type;
00103 DBusList *listen_on;
00105 DBusList *mechanisms;
00107 DBusList *service_dirs;
00109 BusPolicy *policy;
00111 BusLimits limits;
00113 char *pidfile;
00115 unsigned int fork : 1;
00117 unsigned int is_toplevel : 1;
00118 };
00119
00120 static const char*
00121 element_type_to_name (ElementType type)
00122 {
00123 switch (type)
00124 {
00125 case ELEMENT_NONE:
00126 return NULL;
00127 case ELEMENT_BUSCONFIG:
00128 return "busconfig";
00129 case ELEMENT_INCLUDE:
00130 return "include";
00131 case ELEMENT_USER:
00132 return "user";
00133 case ELEMENT_LISTEN:
00134 return "listen";
00135 case ELEMENT_AUTH:
00136 return "auth";
00137 case ELEMENT_POLICY:
00138 return "policy";
00139 case ELEMENT_LIMIT:
00140 return "limit";
00141 case ELEMENT_ALLOW:
00142 return "allow";
00143 case ELEMENT_DENY:
00144 return "deny";
00145 case ELEMENT_FORK:
00146 return "fork";
00147 case ELEMENT_PIDFILE:
00148 return "pidfile";
00149 case ELEMENT_SERVICEDIR:
00150 return "servicedir";
00151 case ELEMENT_INCLUDEDIR:
00152 return "includedir";
00153 case ELEMENT_TYPE:
00154 return "type";
00155 }
00156
00157 _dbus_assert_not_reached ("bad element type");
00158
00159 return NULL;
00160 }
00161
00162 static Element*
00163 push_element (BusConfigParser *parser,
00164 ElementType type)
00165 {
00166 Element *e;
00167
00168 _dbus_assert (type != ELEMENT_NONE);
00169
00170 e = dbus_new0 (Element, 1);
00171 if (e == NULL)
00172 return NULL;
00173
00174 if (!_dbus_list_append (&parser->stack, e))
00175 {
00176 dbus_free (e);
00177 return NULL;
00178 }
00179
00180 e->type = type;
00181
00182 return e;
00183 }
00184
00185 static void
00186 element_free (Element *e)
00187 {
00188 if (e->type == ELEMENT_LIMIT)
00189 dbus_free (e->d.limit.name);
00190
00191 dbus_free (e);
00192 }
00193
00194 static void
00195 pop_element (BusConfigParser *parser)
00196 {
00197 Element *e;
00198
00199 e = _dbus_list_pop_last (&parser->stack);
00200
00201 element_free (e);
00202 }
00203
00204 static Element*
00205 peek_element (BusConfigParser *parser)
00206 {
00207 Element *e;
00208
00209 e = _dbus_list_get_last (&parser->stack);
00210
00211 return e;
00212 }
00213
00214 static ElementType
00215 top_element_type (BusConfigParser *parser)
00216 {
00217 Element *e;
00218
00219 e = _dbus_list_get_last (&parser->stack);
00220
00221 if (e)
00222 return e->type;
00223 else
00224 return ELEMENT_NONE;
00225 }
00226
00227 static dbus_bool_t
00228 merge_included (BusConfigParser *parser,
00229 BusConfigParser *included,
00230 DBusError *error)
00231 {
00232 DBusList *link;
00233
00234 if (!bus_policy_merge (parser->policy,
00235 included->policy))
00236 {
00237 BUS_SET_OOM (error);
00238 return FALSE;
00239 }
00240
00241 if (included->user != NULL)
00242 {
00243 dbus_free (parser->user);
00244 parser->user = included->user;
00245 included->user = NULL;
00246 }
00247
00248 if (included->bus_type != NULL)
00249 {
00250 dbus_free (parser->bus_type);
00251 parser->bus_type = included->bus_type;
00252 included->bus_type = NULL;
00253 }
00254
00255 if (included->fork)
00256 parser->fork = TRUE;
00257
00258 if (included->pidfile != NULL)
00259 {
00260 dbus_free (parser->pidfile);
00261 parser->pidfile = included->pidfile;
00262 included->pidfile = NULL;
00263 }
00264
00265 while ((link = _dbus_list_pop_first_link (&included->listen_on)))
00266 _dbus_list_append_link (&parser->listen_on, link);
00267
00268 while ((link = _dbus_list_pop_first_link (&included->mechanisms)))
00269 _dbus_list_append_link (&parser->mechanisms, link);
00270
00271 while ((link = _dbus_list_pop_first_link (&included->service_dirs)))
00272 _dbus_list_append_link (&parser->service_dirs, link);
00273
00274 return TRUE;
00275 }
00276
00277 BusConfigParser*
00278 bus_config_parser_new (const DBusString *basedir,
00279 dbus_bool_t is_toplevel)
00280 {
00281 BusConfigParser *parser;
00282
00283 parser = dbus_new0 (BusConfigParser, 1);
00284 if (parser == NULL)
00285 return NULL;
00286
00287 parser->is_toplevel = !!is_toplevel;
00288
00289 if (!_dbus_string_init (&parser->basedir))
00290 {
00291 dbus_free (parser);
00292 return NULL;
00293 }
00294
00295 if (((parser->policy = bus_policy_new ()) == NULL) ||
00296 !_dbus_string_copy (basedir, 0, &parser->basedir, 0))
00297 {
00298 if (parser->policy)
00299 bus_policy_unref (parser->policy);
00300
00301 _dbus_string_free (&parser->basedir);
00302 dbus_free (parser);
00303 return NULL;
00304 }
00305
00306
00307 parser->limits.max_incoming_bytes = _DBUS_ONE_MEGABYTE * 63;
00308 parser->limits.max_outgoing_bytes = _DBUS_ONE_MEGABYTE * 63;
00309 parser->limits.max_message_size = _DBUS_ONE_MEGABYTE * 32;
00310
00311
00312
00313
00314
00315 parser->limits.activation_timeout = 25000;
00316
00317
00318
00319
00320
00321 parser->limits.auth_timeout = 30000;
00322
00323 parser->limits.max_incomplete_connections = 32;
00324 parser->limits.max_connections_per_user = 128;
00325
00326
00327
00328
00329
00330 parser->limits.max_completed_connections = 1024;
00331
00332 parser->limits.max_pending_activations = 256;
00333 parser->limits.max_services_per_connection = 256;
00334
00335 parser->refcount = 1;
00336
00337 return parser;
00338 }
00339
00340 void
00341 bus_config_parser_ref (BusConfigParser *parser)
00342 {
00343 _dbus_assert (parser->refcount > 0);
00344
00345 parser->refcount += 1;
00346 }
00347
00348 void
00349 bus_config_parser_unref (BusConfigParser *parser)
00350 {
00351 _dbus_assert (parser->refcount > 0);
00352
00353 parser->refcount -= 1;
00354
00355 if (parser->refcount == 0)
00356 {
00357 while (parser->stack != NULL)
00358 pop_element (parser);
00359
00360 dbus_free (parser->user);
00361 dbus_free (parser->bus_type);
00362 dbus_free (parser->pidfile);
00363
00364 _dbus_list_foreach (&parser->listen_on,
00365 (DBusForeachFunction) dbus_free,
00366 NULL);
00367
00368 _dbus_list_clear (&parser->listen_on);
00369
00370 _dbus_list_foreach (&parser->service_dirs,
00371 (DBusForeachFunction) dbus_free,
00372 NULL);
00373
00374 _dbus_list_clear (&parser->service_dirs);
00375
00376 _dbus_list_foreach (&parser->mechanisms,
00377 (DBusForeachFunction) dbus_free,
00378 NULL);
00379
00380 _dbus_list_clear (&parser->mechanisms);
00381
00382 _dbus_string_free (&parser->basedir);
00383
00384 if (parser->policy)
00385 bus_policy_unref (parser->policy);
00386
00387 dbus_free (parser);
00388 }
00389 }
00390
00391 dbus_bool_t
00392 bus_config_parser_check_doctype (BusConfigParser *parser,
00393 const char *doctype,
00394 DBusError *error)
00395 {
00396 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
00397
00398 if (strcmp (doctype, "busconfig") != 0)
00399 {
00400 dbus_set_error (error,
00401 DBUS_ERROR_FAILED,
00402 "Configuration file has the wrong document type %s",
00403 doctype);
00404 return FALSE;
00405 }
00406 else
00407 return TRUE;
00408 }
00409
00410 typedef struct
00411 {
00412 const char *name;
00413 const char **retloc;
00414 } LocateAttr;
00415
00416 static dbus_bool_t
00417 locate_attributes (BusConfigParser *parser,
00418 const char *element_name,
00419 const char **attribute_names,
00420 const char **attribute_values,
00421 DBusError *error,
00422 const char *first_attribute_name,
00423 const char **first_attribute_retloc,
00424 ...)
00425 {
00426 va_list args;
00427 const char *name;
00428 const char **retloc;
00429 int n_attrs;
00430 #define MAX_ATTRS 24
00431 LocateAttr attrs[MAX_ATTRS];
00432 dbus_bool_t retval;
00433 int i;
00434
00435 _dbus_assert (first_attribute_name != NULL);
00436 _dbus_assert (first_attribute_retloc != NULL);
00437
00438 retval = TRUE;
00439
00440 n_attrs = 1;
00441 attrs[0].name = first_attribute_name;
00442 attrs[0].retloc = first_attribute_retloc;
00443 *first_attribute_retloc = NULL;
00444
00445 va_start (args, first_attribute_retloc);
00446
00447 name = va_arg (args, const char*);
00448 retloc = va_arg (args, const char**);
00449
00450 while (name != NULL)
00451 {
00452 _dbus_assert (retloc != NULL);
00453 _dbus_assert (n_attrs < MAX_ATTRS);
00454
00455 attrs[n_attrs].name = name;
00456 attrs[n_attrs].retloc = retloc;
00457 n_attrs += 1;
00458 *retloc = NULL;
00459
00460 name = va_arg (args, const char*);
00461 retloc = va_arg (args, const char**);
00462 }
00463
00464 va_end (args);
00465
00466 if (!retval)
00467 return retval;
00468
00469 i = 0;
00470 while (attribute_names[i])
00471 {
00472 int j;
00473 dbus_bool_t found;
00474
00475 found = FALSE;
00476 j = 0;
00477 while (j < n_attrs)
00478 {
00479 if (strcmp (attrs[j].name, attribute_names[i]) == 0)
00480 {
00481 retloc = attrs[j].retloc;
00482
00483 if (*retloc != NULL)
00484 {
00485 dbus_set_error (error, DBUS_ERROR_FAILED,
00486 "Attribute \"%s\" repeated twice on the same <%s> element",
00487 attrs[j].name, element_name);
00488 retval = FALSE;
00489 goto out;
00490 }
00491
00492 *retloc = attribute_values[i];
00493 found = TRUE;
00494 }
00495
00496 ++j;
00497 }
00498
00499 if (!found)
00500 {
00501 dbus_set_error (error, DBUS_ERROR_FAILED,
00502 "Attribute \"%s\" is invalid on <%s> element in this context",
00503 attribute_names[i], element_name);
00504 retval = FALSE;
00505 goto out;
00506 }
00507
00508 ++i;
00509 }
00510
00511 out:
00512 return retval;
00513 }
00514
00515 static dbus_bool_t
00516 check_no_attributes (BusConfigParser *parser,
00517 const char *element_name,
00518 const char **attribute_names,
00519 const char **attribute_values,
00520 DBusError *error)
00521 {
00522 if (attribute_names[0] != NULL)
00523 {
00524 dbus_set_error (error, DBUS_ERROR_FAILED,
00525 "Attribute \"%s\" is invalid on <%s> element in this context",
00526 attribute_names[0], element_name);
00527 return FALSE;
00528 }
00529
00530 return TRUE;
00531 }
00532
00533 static dbus_bool_t
00534 start_busconfig_child (BusConfigParser *parser,
00535 const char *element_name,
00536 const char **attribute_names,
00537 const char **attribute_values,
00538 DBusError *error)
00539 {
00540 if (strcmp (element_name, "user") == 0)
00541 {
00542 if (!check_no_attributes (parser, "user", attribute_names, attribute_values, error))
00543 return FALSE;
00544
00545 if (push_element (parser, ELEMENT_USER) == NULL)
00546 {
00547 BUS_SET_OOM (error);
00548 return FALSE;
00549 }
00550
00551 return TRUE;
00552 }
00553 else if (strcmp (element_name, "type") == 0)
00554 {
00555 if (!check_no_attributes (parser, "type", attribute_names, attribute_values, error))
00556 return FALSE;
00557
00558 if (push_element (parser, ELEMENT_TYPE) == NULL)
00559 {
00560 BUS_SET_OOM (error);
00561 return FALSE;
00562 }
00563
00564 return TRUE;
00565 }
00566 else if (strcmp (element_name, "fork") == 0)
00567 {
00568 if (!check_no_attributes (parser, "fork", attribute_names, attribute_values, error))
00569 return FALSE;
00570
00571 if (push_element (parser, ELEMENT_FORK) == NULL)
00572 {
00573 BUS_SET_OOM (error);
00574 return FALSE;
00575 }
00576
00577 parser->fork = TRUE;
00578
00579 return TRUE;
00580 }
00581 else if (strcmp (element_name, "pidfile") == 0)
00582 {
00583 if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
00584 return FALSE;
00585
00586 if (push_element (parser, ELEMENT_PIDFILE) == NULL)
00587 {
00588 BUS_SET_OOM (error);
00589 return FALSE;
00590 }
00591
00592 return TRUE;
00593 }
00594 else if (strcmp (element_name, "listen") == 0)
00595 {
00596 if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
00597 return FALSE;
00598
00599 if (push_element (parser, ELEMENT_LISTEN) == NULL)
00600 {
00601 BUS_SET_OOM (error);
00602 return FALSE;
00603 }
00604
00605 return TRUE;
00606 }
00607 else if (strcmp (element_name, "auth") == 0)
00608 {
00609 if (!check_no_attributes (parser, "auth", attribute_names, attribute_values, error))
00610 return FALSE;
00611
00612 if (push_element (parser, ELEMENT_AUTH) == NULL)
00613 {
00614 BUS_SET_OOM (error);
00615 return FALSE;
00616 }
00617
00618 return TRUE;
00619 }
00620 else if (strcmp (element_name, "includedir") == 0)
00621 {
00622 if (!check_no_attributes (parser, "includedir", attribute_names, attribute_values, error))
00623 return FALSE;
00624
00625 if (push_element (parser, ELEMENT_INCLUDEDIR) == NULL)
00626 {
00627 BUS_SET_OOM (error);
00628 return FALSE;
00629 }
00630
00631 return TRUE;
00632 }
00633 else if (strcmp (element_name, "servicedir") == 0)
00634 {
00635 if (!check_no_attributes (parser, "servicedir", attribute_names, attribute_values, error))
00636 return FALSE;
00637
00638 if (push_element (parser, ELEMENT_SERVICEDIR) == NULL)
00639 {
00640 BUS_SET_OOM (error);
00641 return FALSE;
00642 }
00643
00644 return TRUE;
00645 }
00646 else if (strcmp (element_name, "include") == 0)
00647 {
00648 Element *e;
00649 const char *ignore_missing;
00650
00651 if ((e = push_element (parser, ELEMENT_INCLUDE)) == NULL)
00652 {
00653 BUS_SET_OOM (error);
00654 return FALSE;
00655 }
00656
00657 e->d.include.ignore_missing = FALSE;
00658
00659 if (!locate_attributes (parser, "include",
00660 attribute_names,
00661 attribute_values,
00662 error,
00663 "ignore_missing", &ignore_missing,
00664 NULL))
00665 return FALSE;
00666
00667 if (ignore_missing != NULL)
00668 {
00669 if (strcmp (ignore_missing, "yes") == 0)
00670 e->d.include.ignore_missing = TRUE;
00671 else if (strcmp (ignore_missing, "no") == 0)
00672 e->d.include.ignore_missing = FALSE;
00673 else
00674 {
00675 dbus_set_error (error, DBUS_ERROR_FAILED,
00676 "ignore_missing attribute must have value \"yes\" or \"no\"");
00677 return FALSE;
00678 }
00679 }
00680
00681 return TRUE;
00682 }
00683 else if (strcmp (element_name, "policy") == 0)
00684 {
00685 Element *e;
00686 const char *context;
00687 const char *user;
00688 const char *group;
00689
00690 if ((e = push_element (parser, ELEMENT_POLICY)) == NULL)
00691 {
00692 BUS_SET_OOM (error);
00693 return FALSE;
00694 }
00695
00696 e->d.policy.type = POLICY_IGNORED;
00697
00698 if (!locate_attributes (parser, "policy",
00699 attribute_names,
00700 attribute_values,
00701 error,
00702 "context", &context,
00703 "user", &user,
00704 "group", &group,
00705 NULL))
00706 return FALSE;
00707
00708 if (((context && user) ||
00709 (context && group)) ||
00710 (user && group) ||
00711 !(context || user || group))
00712 {
00713 dbus_set_error (error, DBUS_ERROR_FAILED,
00714 "<policy> element must have exactly one of (context|user|group) attributes");
00715 return FALSE;
00716 }
00717
00718 if (context != NULL)
00719 {
00720 if (strcmp (context, "default") == 0)
00721 {
00722 e->d.policy.type = POLICY_DEFAULT;
00723 }
00724 else if (strcmp (context, "mandatory") == 0)
00725 {
00726 e->d.policy.type = POLICY_MANDATORY;
00727 }
00728 else
00729 {
00730 dbus_set_error (error, DBUS_ERROR_FAILED,
00731 "context attribute on <policy> must have the value \"default\" or \"mandatory\", not \"%s\"",
00732 context);
00733 return FALSE;
00734 }
00735 }
00736 else if (user != NULL)
00737 {
00738 DBusString username;
00739 _dbus_string_init_const (&username, user);
00740
00741 if (_dbus_get_user_id (&username,
00742 &e->d.policy.gid_or_uid))
00743 e->d.policy.type = POLICY_USER;
00744 else
00745 _dbus_warn ("Unknown username \"%s\" in message bus configuration file\n",
00746 user);
00747 }
00748 else if (group != NULL)
00749 {
00750 DBusString group_name;
00751 _dbus_string_init_const (&group_name, group);
00752
00753 if (_dbus_get_group_id (&group_name,
00754 &e->d.policy.gid_or_uid))
00755 e->d.policy.type = POLICY_GROUP;
00756 else
00757 _dbus_warn ("Unknown group \"%s\" in message bus configuration file\n",
00758 group);
00759 }
00760 else
00761 {
00762 _dbus_assert_not_reached ("all <policy> attributes null and we didn't set error");
00763 }
00764
00765 return TRUE;
00766 }
00767 else if (strcmp (element_name, "limit") == 0)
00768 {
00769 Element *e;
00770 const char *name;
00771
00772 if ((e = push_element (parser, ELEMENT_LIMIT)) == NULL)
00773 {
00774 BUS_SET_OOM (error);
00775 return FALSE;
00776 }
00777
00778 if (!locate_attributes (parser, "limit",
00779 attribute_names,
00780 attribute_values,
00781 error,
00782 "name", &name,
00783 NULL))
00784 return FALSE;
00785
00786 if (name == NULL)
00787 {
00788 dbus_set_error (error, DBUS_ERROR_FAILED,
00789 "<limit> element must have a \"name\" attribute");
00790 return FALSE;
00791 }
00792
00793 e->d.limit.name = _dbus_strdup (name);
00794 if (e->d.limit.name == NULL)
00795 {
00796 BUS_SET_OOM (error);
00797 return FALSE;
00798 }
00799
00800 return TRUE;
00801 }
00802 else
00803 {
00804 dbus_set_error (error, DBUS_ERROR_FAILED,
00805 "Element <%s> not allowed inside <%s> in configuration file",
00806 element_name, "busconfig");
00807 return FALSE;
00808 }
00809 }
00810
00811 static dbus_bool_t
00812 append_rule_from_element (BusConfigParser *parser,
00813 const char *element_name,
00814 const char **attribute_names,
00815 const char **attribute_values,
00816 dbus_bool_t allow,
00817 DBusError *error)
00818 {
00819 const char *send;
00820 const char *receive;
00821 const char *own;
00822 const char *send_to;
00823 const char *receive_from;
00824 const char *user;
00825 const char *group;
00826 BusPolicyRule *rule;
00827
00828 if (!locate_attributes (parser, element_name,
00829 attribute_names,
00830 attribute_values,
00831 error,
00832 "send", &send,
00833 "receive", &receive,
00834 "own", &own,
00835 "send_to", &send_to,
00836 "receive_from", &receive_from,
00837 "user", &user,
00838 "group", &group,
00839 NULL))
00840 return FALSE;
00841
00842 if (!(send || receive || own || send_to || receive_from ||
00843 user || group))
00844 {
00845 dbus_set_error (error, DBUS_ERROR_FAILED,
00846 "Element <%s> must have one or more attributes",
00847 element_name);
00848 return FALSE;
00849 }
00850
00851 if (((send && own) ||
00852 (send && receive) ||
00853 (send && receive_from) ||
00854 (send && user) ||
00855 (send && group)) ||
00856
00857 ((receive && own) ||
00858 (receive && send_to) ||
00859 (receive && user) ||
00860 (receive && group)) ||
00861
00862 ((own && send_to) ||
00863 (own && receive_from) ||
00864 (own && user) ||
00865 (own && group)) ||
00866
00867 ((send_to && receive_from) ||
00868 (send_to && user) ||
00869 (send_to && group)) ||
00870
00871 ((receive_from && user) ||
00872 (receive_from && group)) ||
00873
00874 (user && group))
00875 {
00876 dbus_set_error (error, DBUS_ERROR_FAILED,
00877 "Invalid combination of attributes on element <%s>, "
00878 "only send/send_to or receive/receive_from may be paired",
00879 element_name);
00880 return FALSE;
00881 }
00882
00883 rule = NULL;
00884
00885
00886
00887
00888 #define IS_WILDCARD(str) ((str) && ((str)[0]) == '*' && ((str)[1]) == '\0')
00889
00890 if (send || send_to)
00891 {
00892 rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow);
00893 if (rule == NULL)
00894 goto nomem;
00895
00896 if (IS_WILDCARD (send))
00897 send = NULL;
00898 if (IS_WILDCARD (send_to))
00899 send_to = NULL;
00900
00901 rule->d.send.message_name = _dbus_strdup (send);
00902 rule->d.send.destination = _dbus_strdup (send_to);
00903 if (send && rule->d.send.message_name == NULL)
00904 goto nomem;
00905 if (send_to && rule->d.send.destination == NULL)
00906 goto nomem;
00907 }
00908 else if (receive || receive_from)
00909 {
00910 rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow);
00911 if (rule == NULL)
00912 goto nomem;
00913
00914 if (IS_WILDCARD (receive))
00915 receive = NULL;
00916
00917 if (IS_WILDCARD (receive_from))
00918 receive_from = NULL;
00919
00920 rule->d.receive.message_name = _dbus_strdup (receive);
00921 rule->d.receive.origin = _dbus_strdup (receive_from);
00922 if (receive && rule->d.receive.message_name == NULL)
00923 goto nomem;
00924 if (receive_from && rule->d.receive.origin == NULL)
00925 goto nomem;
00926 }
00927 else if (own)
00928 {
00929 rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow);
00930 if (rule == NULL)
00931 goto nomem;
00932
00933 if (IS_WILDCARD (own))
00934 own = NULL;
00935
00936 rule->d.own.service_name = _dbus_strdup (own);
00937 if (own && rule->d.own.service_name == NULL)
00938 goto nomem;
00939 }
00940 else if (user)
00941 {
00942 if (IS_WILDCARD (user))
00943 {
00944 rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
00945 if (rule == NULL)
00946 goto nomem;
00947
00948 rule->d.user.uid = DBUS_UID_UNSET;
00949 }
00950 else
00951 {
00952 DBusString username;
00953 dbus_uid_t uid;
00954
00955 _dbus_string_init_const (&username, user);
00956
00957 if (_dbus_get_user_id (&username, &uid))
00958 {
00959 rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
00960 if (rule == NULL)
00961 goto nomem;
00962
00963 rule->d.user.uid = uid;
00964 }
00965 else
00966 {
00967 _dbus_warn ("Unknown username \"%s\" on element <%s>\n",
00968 user, element_name);
00969 }
00970 }
00971 }
00972 else if (group)
00973 {
00974 if (IS_WILDCARD (group))
00975 {
00976 rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
00977 if (rule == NULL)
00978 goto nomem;
00979
00980 rule->d.group.gid = DBUS_GID_UNSET;
00981 }
00982 else
00983 {
00984 DBusString groupname;
00985 dbus_gid_t gid;
00986
00987 _dbus_string_init_const (&groupname, group);
00988
00989 if (_dbus_get_user_id (&groupname, &gid))
00990 {
00991 rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
00992 if (rule == NULL)
00993 goto nomem;
00994
00995 rule->d.group.gid = gid;
00996 }
00997 else
00998 {
00999 _dbus_warn ("Unknown group \"%s\" on element <%s>\n",
01000 group, element_name);
01001 }
01002 }
01003 }
01004 else
01005 _dbus_assert_not_reached ("Did not handle some combination of attributes on <allow> or <deny>");
01006
01007 if (rule != NULL)
01008 {
01009 Element *pe;
01010
01011 pe = peek_element (parser);
01012 _dbus_assert (pe != NULL);
01013 _dbus_assert (pe->type == ELEMENT_POLICY);
01014
01015 switch (pe->d.policy.type)
01016 {
01017 case POLICY_IGNORED:
01018
01019 break;
01020
01021 case POLICY_DEFAULT:
01022 if (!bus_policy_append_default_rule (parser->policy, rule))
01023 goto nomem;
01024 break;
01025 case POLICY_MANDATORY:
01026 if (!bus_policy_append_mandatory_rule (parser->policy, rule))
01027 goto nomem;
01028 break;
01029 case POLICY_USER:
01030 if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
01031 {
01032 dbus_set_error (error, DBUS_ERROR_FAILED,
01033 "<%s> rule cannot be per-user because it has bus-global semantics",
01034 element_name);
01035 goto failed;
01036 }
01037
01038 if (!bus_policy_append_user_rule (parser->policy, pe->d.policy.gid_or_uid,
01039 rule))
01040 goto nomem;
01041 break;
01042 case POLICY_GROUP:
01043 if (!BUS_POLICY_RULE_IS_PER_CLIENT (rule))
01044 {
01045 dbus_set_error (error, DBUS_ERROR_FAILED,
01046 "<%s> rule cannot be per-group because it has bus-global semantics",
01047 element_name);
01048 goto failed;
01049 }
01050
01051 if (!bus_policy_append_group_rule (parser->policy, pe->d.policy.gid_or_uid,
01052 rule))
01053 goto nomem;
01054 break;
01055 }
01056
01057 bus_policy_rule_unref (rule);
01058 rule = NULL;
01059 }
01060
01061 return TRUE;
01062
01063 nomem:
01064 BUS_SET_OOM (error);
01065 failed:
01066 if (rule)
01067 bus_policy_rule_unref (rule);
01068 return FALSE;
01069 }
01070
01071 static dbus_bool_t
01072 start_policy_child (BusConfigParser *parser,
01073 const char *element_name,
01074 const char **attribute_names,
01075 const char **attribute_values,
01076 DBusError *error)
01077 {
01078 if (strcmp (element_name, "allow") == 0)
01079 {
01080 if (!append_rule_from_element (parser, element_name,
01081 attribute_names, attribute_values,
01082 TRUE, error))
01083 return FALSE;
01084
01085 if (push_element (parser, ELEMENT_ALLOW) == NULL)
01086 {
01087 BUS_SET_OOM (error);
01088 return FALSE;
01089 }
01090
01091 return TRUE;
01092 }
01093 else if (strcmp (element_name, "deny") == 0)
01094 {
01095 if (!append_rule_from_element (parser, element_name,
01096 attribute_names, attribute_values,
01097 FALSE, error))
01098 return FALSE;
01099
01100 if (push_element (parser, ELEMENT_DENY) == NULL)
01101 {
01102 BUS_SET_OOM (error);
01103 return FALSE;
01104 }
01105
01106 return TRUE;
01107 }
01108 else
01109 {
01110 dbus_set_error (error, DBUS_ERROR_FAILED,
01111 "Element <%s> not allowed inside <%s> in configuration file",
01112 element_name, "policy");
01113 return FALSE;
01114 }
01115 }
01116
01117 dbus_bool_t
01118 bus_config_parser_start_element (BusConfigParser *parser,
01119 const char *element_name,
01120 const char **attribute_names,
01121 const char **attribute_values,
01122 DBusError *error)
01123 {
01124 ElementType t;
01125
01126 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01127
01128
01129
01130 t = top_element_type (parser);
01131
01132 if (t == ELEMENT_NONE)
01133 {
01134 if (strcmp (element_name, "busconfig") == 0)
01135 {
01136 if (!check_no_attributes (parser, "busconfig", attribute_names, attribute_values, error))
01137 return FALSE;
01138
01139 if (push_element (parser, ELEMENT_BUSCONFIG) == NULL)
01140 {
01141 BUS_SET_OOM (error);
01142 return FALSE;
01143 }
01144
01145 return TRUE;
01146 }
01147 else
01148 {
01149 dbus_set_error (error, DBUS_ERROR_FAILED,
01150 "Unknown element <%s> at root of configuration file",
01151 element_name);
01152 return FALSE;
01153 }
01154 }
01155 else if (t == ELEMENT_BUSCONFIG)
01156 {
01157 return start_busconfig_child (parser, element_name,
01158 attribute_names, attribute_values,
01159 error);
01160 }
01161 else if (t == ELEMENT_POLICY)
01162 {
01163 return start_policy_child (parser, element_name,
01164 attribute_names, attribute_values,
01165 error);
01166 }
01167 else
01168 {
01169 dbus_set_error (error, DBUS_ERROR_FAILED,
01170 "Element <%s> is not allowed in this context",
01171 element_name);
01172 return FALSE;
01173 }
01174 }
01175
01176 static dbus_bool_t
01177 set_limit (BusConfigParser *parser,
01178 const char *name,
01179 long value,
01180 DBusError *error)
01181 {
01182 dbus_bool_t must_be_positive;
01183 dbus_bool_t must_be_int;
01184
01185 must_be_int = FALSE;
01186 must_be_positive = FALSE;
01187
01188 if (strcmp (name, "max_incoming_bytes") == 0)
01189 {
01190 must_be_positive = TRUE;
01191 parser->limits.max_incoming_bytes = value;
01192 }
01193 else if (strcmp (name, "max_outgoing_bytes") == 0)
01194 {
01195 must_be_positive = TRUE;
01196 parser->limits.max_outgoing_bytes = value;
01197 }
01198 else if (strcmp (name, "max_message_size") == 0)
01199 {
01200 must_be_positive = TRUE;
01201 parser->limits.max_message_size = value;
01202 }
01203 else if (strcmp (name, "activation_timeout") == 0)
01204 {
01205 must_be_positive = TRUE;
01206 must_be_int = TRUE;
01207 parser->limits.activation_timeout = value;
01208 }
01209 else if (strcmp (name, "auth_timeout") == 0)
01210 {
01211 must_be_positive = TRUE;
01212 must_be_int = TRUE;
01213 parser->limits.auth_timeout = value;
01214 }
01215 else if (strcmp (name, "max_completed_connections") == 0)
01216 {
01217 must_be_positive = TRUE;
01218 must_be_int = TRUE;
01219 parser->limits.max_completed_connections = value;
01220 }
01221 else if (strcmp (name, "max_incomplete_connections") == 0)
01222 {
01223 must_be_positive = TRUE;
01224 must_be_int = TRUE;
01225 parser->limits.max_incomplete_connections = value;
01226 }
01227 else if (strcmp (name, "max_connections_per_user") == 0)
01228 {
01229 must_be_positive = TRUE;
01230 must_be_int = TRUE;
01231 parser->limits.max_connections_per_user = value;
01232 }
01233 else if (strcmp (name, "max_pending_activations") == 0)
01234 {
01235 must_be_positive = TRUE;
01236 must_be_int = TRUE;
01237 parser->limits.max_pending_activations = value;
01238 }
01239 else if (strcmp (name, "max_services_per_connection") == 0)
01240 {
01241 must_be_positive = TRUE;
01242 must_be_int = TRUE;
01243 parser->limits.max_services_per_connection = value;
01244 }
01245 else
01246 {
01247 dbus_set_error (error, DBUS_ERROR_FAILED,
01248 "There is no limit called \"%s\"\n",
01249 name);
01250 return FALSE;
01251 }
01252
01253 if (must_be_positive && value < 0)
01254 {
01255 dbus_set_error (error, DBUS_ERROR_FAILED,
01256 "<limit name=\"%s\"> must be a positive number\n",
01257 name);
01258 return FALSE;
01259 }
01260
01261 if (must_be_int &&
01262 (value < _DBUS_INT_MIN || value > _DBUS_INT_MAX))
01263 {
01264 dbus_set_error (error, DBUS_ERROR_FAILED,
01265 "<limit name=\"%s\"> value is too large\n",
01266 name);
01267 return FALSE;
01268 }
01269
01270 return TRUE;
01271 }
01272
01273 dbus_bool_t
01274 bus_config_parser_end_element (BusConfigParser *parser,
01275 const char *element_name,
01276 DBusError *error)
01277 {
01278 ElementType t;
01279 const char *n;
01280 Element *e;
01281
01282 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01283
01284
01285
01286 t = top_element_type (parser);
01287
01288 if (t == ELEMENT_NONE)
01289 {
01290
01291
01292
01293 dbus_set_error (error, DBUS_ERROR_FAILED,
01294 "XML parser ended element with no element on the stack");
01295 return FALSE;
01296 }
01297
01298 n = element_type_to_name (t);
01299 _dbus_assert (n != NULL);
01300 if (strcmp (n, element_name) != 0)
01301 {
01302
01303
01304
01305 dbus_set_error (error, DBUS_ERROR_FAILED,
01306 "XML element <%s> ended but topmost element on the stack was <%s>",
01307 element_name, n);
01308 return FALSE;
01309 }
01310
01311 e = peek_element (parser);
01312 _dbus_assert (e != NULL);
01313
01314 switch (e->type)
01315 {
01316 case ELEMENT_NONE:
01317 _dbus_assert_not_reached ("element in stack has no type");
01318 break;
01319
01320 case ELEMENT_INCLUDE:
01321 case ELEMENT_USER:
01322 case ELEMENT_TYPE:
01323 case ELEMENT_LISTEN:
01324 case ELEMENT_PIDFILE:
01325 case ELEMENT_AUTH:
01326 case ELEMENT_SERVICEDIR:
01327 case ELEMENT_INCLUDEDIR:
01328 case ELEMENT_LIMIT:
01329 if (!e->had_content)
01330 {
01331 dbus_set_error (error, DBUS_ERROR_FAILED,
01332 "XML element <%s> was expected to have content inside it",
01333 element_type_to_name (e->type));
01334 return FALSE;
01335 }
01336
01337 if (e->type == ELEMENT_LIMIT)
01338 {
01339 if (!set_limit (parser, e->d.limit.name, e->d.limit.value,
01340 error))
01341 return FALSE;
01342 }
01343 break;
01344
01345 case ELEMENT_BUSCONFIG:
01346 case ELEMENT_POLICY:
01347 case ELEMENT_ALLOW:
01348 case ELEMENT_DENY:
01349 case ELEMENT_FORK:
01350 break;
01351 }
01352
01353 pop_element (parser);
01354
01355 return TRUE;
01356 }
01357
01358 static dbus_bool_t
01359 all_whitespace (const DBusString *str)
01360 {
01361 int i;
01362
01363 _dbus_string_skip_white (str, 0, &i);
01364
01365 return i == _dbus_string_get_length (str);
01366 }
01367
01368 static dbus_bool_t
01369 make_full_path (const DBusString *basedir,
01370 const DBusString *filename,
01371 DBusString *full_path)
01372 {
01373 if (_dbus_path_is_absolute (filename))
01374 {
01375 return _dbus_string_copy (filename, 0, full_path, 0);
01376 }
01377 else
01378 {
01379 if (!_dbus_string_copy (basedir, 0, full_path, 0))
01380 return FALSE;
01381
01382 if (!_dbus_concat_dir_and_file (full_path, filename))
01383 return FALSE;
01384
01385 return TRUE;
01386 }
01387 }
01388
01389 static dbus_bool_t
01390 include_file (BusConfigParser *parser,
01391 const DBusString *filename,
01392 dbus_bool_t ignore_missing,
01393 DBusError *error)
01394 {
01395
01396
01397
01398
01399 BusConfigParser *included;
01400 DBusError tmp_error;
01401
01402 dbus_error_init (&tmp_error);
01403 included = bus_config_load (filename, FALSE, &tmp_error);
01404 if (included == NULL)
01405 {
01406 _DBUS_ASSERT_ERROR_IS_SET (&tmp_error);
01407
01408 if (dbus_error_has_name (&tmp_error, DBUS_ERROR_FILE_NOT_FOUND) &&
01409 ignore_missing)
01410 {
01411 dbus_error_free (&tmp_error);
01412 return TRUE;
01413 }
01414 else
01415 {
01416 dbus_move_error (&tmp_error, error);
01417 return FALSE;
01418 }
01419 }
01420 else
01421 {
01422 _DBUS_ASSERT_ERROR_IS_CLEAR (&tmp_error);
01423
01424 if (!merge_included (parser, included, error))
01425 {
01426 bus_config_parser_unref (included);
01427 return FALSE;
01428 }
01429
01430 bus_config_parser_unref (included);
01431 return TRUE;
01432 }
01433 }
01434
01435 static dbus_bool_t
01436 include_dir (BusConfigParser *parser,
01437 const DBusString *dirname,
01438 DBusError *error)
01439 {
01440 DBusString filename;
01441 dbus_bool_t retval;
01442 DBusError tmp_error;
01443 DBusDirIter *dir;
01444
01445 if (!_dbus_string_init (&filename))
01446 {
01447 BUS_SET_OOM (error);
01448 return FALSE;
01449 }
01450
01451 retval = FALSE;
01452
01453 dir = _dbus_directory_open (dirname, error);
01454
01455 if (dir == NULL)
01456 goto failed;
01457
01458 dbus_error_init (&tmp_error);
01459 while (_dbus_directory_get_next_file (dir, &filename, &tmp_error))
01460 {
01461 DBusString full_path;
01462
01463 if (!_dbus_string_init (&full_path))
01464 {
01465 BUS_SET_OOM (error);
01466 goto failed;
01467 }
01468
01469 if (!_dbus_string_copy (dirname, 0, &full_path, 0))
01470 {
01471 BUS_SET_OOM (error);
01472 _dbus_string_free (&full_path);
01473 goto failed;
01474 }
01475
01476 if (!_dbus_concat_dir_and_file (&full_path, &filename))
01477 {
01478 BUS_SET_OOM (error);
01479 _dbus_string_free (&full_path);
01480 goto failed;
01481 }
01482
01483 if (_dbus_string_ends_with_c_str (&full_path, ".conf"))
01484 {
01485 if (!include_file (parser, &full_path, TRUE, error))
01486 {
01487 _dbus_string_free (&full_path);
01488 goto failed;
01489 }
01490 }
01491
01492 _dbus_string_free (&full_path);
01493 }
01494
01495 if (dbus_error_is_set (&tmp_error))
01496 {
01497 dbus_move_error (&tmp_error, error);
01498 goto failed;
01499 }
01500
01501 retval = TRUE;
01502
01503 failed:
01504 _dbus_string_free (&filename);
01505
01506 if (dir)
01507 _dbus_directory_close (dir);
01508
01509 return retval;
01510 }
01511
01512 dbus_bool_t
01513 bus_config_parser_content (BusConfigParser *parser,
01514 const DBusString *content,
01515 DBusError *error)
01516 {
01517 Element *e;
01518
01519 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01520
01521 #if 0
01522 {
01523 const char *c_str;
01524
01525 _dbus_string_get_const_data (content, &c_str);
01526
01527 printf ("CONTENT %d bytes: %s\n", _dbus_string_get_length (content), c_str);
01528 }
01529 #endif
01530
01531 e = peek_element (parser);
01532 if (e == NULL)
01533 {
01534 dbus_set_error (error, DBUS_ERROR_FAILED,
01535 "Text content outside of any XML element in configuration file");
01536 return FALSE;
01537 }
01538 else if (e->had_content)
01539 {
01540 _dbus_assert_not_reached ("Element had multiple content blocks");
01541 return FALSE;
01542 }
01543
01544 switch (top_element_type (parser))
01545 {
01546 case ELEMENT_NONE:
01547 _dbus_assert_not_reached ("element at top of stack has no type");
01548 return FALSE;
01549
01550 case ELEMENT_BUSCONFIG:
01551 case ELEMENT_POLICY:
01552 case ELEMENT_ALLOW:
01553 case ELEMENT_DENY:
01554 case ELEMENT_FORK:
01555 if (all_whitespace (content))
01556 return TRUE;
01557 else
01558 {
01559 dbus_set_error (error, DBUS_ERROR_FAILED,
01560 "No text content expected inside XML element %s in configuration file",
01561 element_type_to_name (top_element_type (parser)));
01562 return FALSE;
01563 }
01564
01565 case ELEMENT_PIDFILE:
01566 {
01567 char *s;
01568
01569 e->had_content = TRUE;
01570
01571 if (!_dbus_string_copy_data (content, &s))
01572 goto nomem;
01573
01574 dbus_free (parser->pidfile);
01575 parser->pidfile = s;
01576 }
01577 break;
01578
01579 case ELEMENT_INCLUDE:
01580 {
01581 DBusString full_path;
01582
01583 e->had_content = TRUE;
01584
01585 if (!_dbus_string_init (&full_path))
01586 goto nomem;
01587
01588 if (!make_full_path (&parser->basedir, content, &full_path))
01589 {
01590 _dbus_string_free (&full_path);
01591 goto nomem;
01592 }
01593
01594 if (!include_file (parser, &full_path,
01595 e->d.include.ignore_missing, error))
01596 {
01597 _dbus_string_free (&full_path);
01598 return FALSE;
01599 }
01600
01601 _dbus_string_free (&full_path);
01602 }
01603 break;
01604
01605 case ELEMENT_INCLUDEDIR:
01606 {
01607 DBusString full_path;
01608
01609 e->had_content = TRUE;
01610
01611 if (!_dbus_string_init (&full_path))
01612 goto nomem;
01613
01614 if (!make_full_path (&parser->basedir, content, &full_path))
01615 {
01616 _dbus_string_free (&full_path);
01617 goto nomem;
01618 }
01619
01620 if (!include_dir (parser, &full_path, error))
01621 {
01622 _dbus_string_free (&full_path);
01623 return FALSE;
01624 }
01625
01626 _dbus_string_free (&full_path);
01627 }
01628 break;
01629
01630 case ELEMENT_USER:
01631 {
01632 char *s;
01633
01634 e->had_content = TRUE;
01635
01636 if (!_dbus_string_copy_data (content, &s))
01637 goto nomem;
01638
01639 dbus_free (parser->user);
01640 parser->user = s;
01641 }
01642 break;
01643
01644 case ELEMENT_TYPE:
01645 {
01646 char *s;
01647
01648 e->had_content = TRUE;
01649
01650 if (!_dbus_string_copy_data (content, &s))
01651 goto nomem;
01652
01653 dbus_free (parser->bus_type);
01654 parser->bus_type = s;
01655 }
01656 break;
01657
01658 case ELEMENT_LISTEN:
01659 {
01660 char *s;
01661
01662 e->had_content = TRUE;
01663
01664 if (!_dbus_string_copy_data (content, &s))
01665 goto nomem;
01666
01667 if (!_dbus_list_append (&parser->listen_on,
01668 s))
01669 {
01670 dbus_free (s);
01671 goto nomem;
01672 }
01673 }
01674 break;
01675
01676 case ELEMENT_AUTH:
01677 {
01678 char *s;
01679
01680 e->had_content = TRUE;
01681
01682 if (!_dbus_string_copy_data (content, &s))
01683 goto nomem;
01684
01685 if (!_dbus_list_append (&parser->mechanisms,
01686 s))
01687 {
01688 dbus_free (s);
01689 goto nomem;
01690 }
01691 }
01692 break;
01693
01694 case ELEMENT_SERVICEDIR:
01695 {
01696 char *s;
01697 DBusString full_path;
01698
01699 e->had_content = TRUE;
01700
01701 if (!_dbus_string_init (&full_path))
01702 goto nomem;
01703
01704 if (!make_full_path (&parser->basedir, content, &full_path))
01705 {
01706 _dbus_string_free (&full_path);
01707 goto nomem;
01708 }
01709
01710 if (!_dbus_string_copy_data (&full_path, &s))
01711 {
01712 _dbus_string_free (&full_path);
01713 goto nomem;
01714 }
01715
01716 if (!_dbus_list_append (&parser->service_dirs, s))
01717 {
01718 _dbus_string_free (&full_path);
01719 dbus_free (s);
01720 goto nomem;
01721 }
01722
01723 _dbus_string_free (&full_path);
01724 }
01725 break;
01726
01727 case ELEMENT_LIMIT:
01728 {
01729 long val;
01730
01731 e->had_content = TRUE;
01732
01733 val = 0;
01734 if (!_dbus_string_parse_int (content, 0, &val, NULL))
01735 {
01736 dbus_set_error (error, DBUS_ERROR_FAILED,
01737 "<limit name=\"%s\"> element has invalid value (could not parse as integer)",
01738 e->d.limit.name);
01739 return FALSE;
01740 }
01741
01742 e->d.limit.value = val;
01743
01744 _dbus_verbose ("Loaded value %ld for limit %s\n",
01745 e->d.limit.value,
01746 e->d.limit.name);
01747 }
01748 break;
01749 }
01750
01751 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01752 return TRUE;
01753
01754 nomem:
01755 BUS_SET_OOM (error);
01756 return FALSE;
01757 }
01758
01759 dbus_bool_t
01760 bus_config_parser_finished (BusConfigParser *parser,
01761 DBusError *error)
01762 {
01763 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
01764
01765 if (parser->stack != NULL)
01766 {
01767 dbus_set_error (error, DBUS_ERROR_FAILED,
01768 "Element <%s> was not closed in configuration file",
01769 element_type_to_name (top_element_type (parser)));
01770
01771 return FALSE;
01772 }
01773
01774 if (parser->is_toplevel && parser->listen_on == NULL)
01775 {
01776 dbus_set_error (error, DBUS_ERROR_FAILED,
01777 "Configuration file needs one or more <listen> elements giving addresses");
01778 return FALSE;
01779 }
01780
01781 return TRUE;
01782 }
01783
01784 const char*
01785 bus_config_parser_get_user (BusConfigParser *parser)
01786 {
01787 return parser->user;
01788 }
01789
01790 const char*
01791 bus_config_parser_get_type (BusConfigParser *parser)
01792 {
01793 return parser->bus_type;
01794 }
01795
01796 DBusList**
01797 bus_config_parser_get_addresses (BusConfigParser *parser)
01798 {
01799 return &parser->listen_on;
01800 }
01801
01802 DBusList**
01803 bus_config_parser_get_mechanisms (BusConfigParser *parser)
01804 {
01805 return &parser->mechanisms;
01806 }
01807
01808 DBusList**
01809 bus_config_parser_get_service_dirs (BusConfigParser *parser)
01810 {
01811 return &parser->service_dirs;
01812 }
01813
01814 dbus_bool_t
01815 bus_config_parser_get_fork (BusConfigParser *parser)
01816 {
01817 return parser->fork;
01818 }
01819
01820 const char *
01821 bus_config_parser_get_pidfile (BusConfigParser *parser)
01822 {
01823 return parser->pidfile;
01824 }
01825
01826 BusPolicy*
01827 bus_config_parser_steal_policy (BusConfigParser *parser)
01828 {
01829 BusPolicy *policy;
01830
01831 _dbus_assert (parser->policy != NULL);
01832
01833 policy = parser->policy;
01834
01835 parser->policy = NULL;
01836
01837 return policy;
01838 }
01839
01840
01841 void
01842 bus_config_parser_get_limits (BusConfigParser *parser,
01843 BusLimits *limits)
01844 {
01845 *limits = parser->limits;
01846 }
01847
01848 #ifdef DBUS_BUILD_TESTS
01849 #include <stdio.h>
01850
01851 typedef enum
01852 {
01853 VALID,
01854 INVALID,
01855 UNKNOWN
01856 } Validity;
01857
01858 static dbus_bool_t
01859 do_load (const DBusString *full_path,
01860 Validity validity,
01861 dbus_bool_t oom_possible)
01862 {
01863 BusConfigParser *parser;
01864 DBusError error;
01865
01866 dbus_error_init (&error);
01867
01868 parser = bus_config_load (full_path, TRUE, &error);
01869 if (parser == NULL)
01870 {
01871 _DBUS_ASSERT_ERROR_IS_SET (&error);
01872
01873 if (oom_possible &&
01874 dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY))
01875 {
01876 _dbus_verbose ("Failed to load valid file due to OOM\n");
01877 dbus_error_free (&error);
01878 return TRUE;
01879 }
01880 else if (validity == VALID)
01881 {
01882 _dbus_warn ("Failed to load valid file but still had memory: %s\n",
01883 error.message);
01884
01885 dbus_error_free (&error);
01886 return FALSE;
01887 }
01888 else
01889 {
01890 dbus_error_free (&error);
01891 return TRUE;
01892 }
01893 }
01894 else
01895 {
01896 _DBUS_ASSERT_ERROR_IS_CLEAR (&error);
01897
01898 bus_config_parser_unref (parser);
01899
01900 if (validity == INVALID)
01901 {
01902 _dbus_warn ("Accepted invalid file\n");
01903 return FALSE;
01904 }
01905
01906 return TRUE;
01907 }
01908 }
01909
01910 typedef struct
01911 {
01912 const DBusString *full_path;
01913 Validity validity;
01914 } LoaderOomData;
01915
01916 static dbus_bool_t
01917 check_loader_oom_func (void *data)
01918 {
01919 LoaderOomData *d = data;
01920
01921 return do_load (d->full_path, d->validity, TRUE);
01922 }
01923
01924 static dbus_bool_t
01925 process_test_subdir (const DBusString *test_base_dir,
01926 const char *subdir,
01927 Validity validity)
01928 {
01929 DBusString test_directory;
01930 DBusString filename;
01931 DBusDirIter *dir;
01932 dbus_bool_t retval;
01933 DBusError error;
01934
01935 retval = FALSE;
01936 dir = NULL;
01937
01938 if (!_dbus_string_init (&test_directory))
01939 _dbus_assert_not_reached ("didn't allocate test_directory\n");
01940
01941 _dbus_string_init_const (&filename, subdir);
01942
01943 if (!_dbus_string_copy (test_base_dir, 0,
01944 &test_directory, 0))
01945 _dbus_assert_not_reached ("couldn't copy test_base_dir to test_directory");
01946
01947 if (!_dbus_concat_dir_and_file (&test_directory, &filename))
01948 _dbus_assert_not_reached ("couldn't allocate full path");
01949
01950 _dbus_string_free (&filename);
01951 if (!_dbus_string_init (&filename))
01952 _dbus_assert_not_reached ("didn't allocate filename string\n");
01953
01954 dbus_error_init (&error);
01955 dir = _dbus_directory_open (&test_directory, &error);
01956 if (dir == NULL)
01957 {
01958 _dbus_warn ("Could not open %s: %s\n",
01959 _dbus_string_get_const_data (&test_directory),
01960 error.message);
01961 dbus_error_free (&error);
01962 goto failed;
01963 }
01964
01965 printf ("Testing:\n");
01966
01967 next:
01968 while (_dbus_directory_get_next_file (dir, &filename, &error))
01969 {
01970 DBusString full_path;
01971 LoaderOomData d;
01972
01973 if (!_dbus_string_init (&full_path))
01974 _dbus_assert_not_reached ("couldn't init string");
01975
01976 if (!_dbus_string_copy (&test_directory, 0, &full_path, 0))
01977 _dbus_assert_not_reached ("couldn't copy dir to full_path");
01978
01979 if (!_dbus_concat_dir_and_file (&full_path, &filename))
01980 _dbus_assert_not_reached ("couldn't concat file to dir");
01981
01982 if (!_dbus_string_ends_with_c_str (&full_path, ".conf"))
01983 {
01984 _dbus_verbose ("Skipping non-.conf file %s\n",
01985 _dbus_string_get_const_data (&filename));
01986 _dbus_string_free (&full_path);
01987 goto next;
01988 }
01989
01990 printf (" %s\n", _dbus_string_get_const_data (&filename));
01991
01992 _dbus_verbose (" expecting %s\n",
01993 validity == VALID ? "valid" :
01994 (validity == INVALID ? "invalid" :
01995 (validity == UNKNOWN ? "unknown" : "???")));
01996
01997 d.full_path = &full_path;
01998 d.validity = validity;
01999 if (!_dbus_test_oom_handling ("config-loader", check_loader_oom_func, &d))
02000 _dbus_assert_not_reached ("test failed");
02001
02002 _dbus_string_free (&full_path);
02003 }
02004
02005 if (dbus_error_is_set (&error))
02006 {
02007 _dbus_warn ("Could not get next file in %s: %s\n",
02008 _dbus_string_get_const_data (&test_directory),
02009 error.message);
02010 dbus_error_free (&error);
02011 goto failed;
02012 }
02013
02014 retval = TRUE;
02015
02016 failed:
02017
02018 if (dir)
02019 _dbus_directory_close (dir);
02020 _dbus_string_free (&test_directory);
02021 _dbus_string_free (&filename);
02022
02023 return retval;
02024 }
02025
02026 dbus_bool_t
02027 bus_config_parser_test (const DBusString *test_data_dir)
02028 {
02029 if (test_data_dir == NULL ||
02030 _dbus_string_get_length (test_data_dir) == 0)
02031 {
02032 printf ("No test data\n");
02033 return TRUE;
02034 }
02035
02036 if (!process_test_subdir (test_data_dir, "valid-config-files", VALID))
02037 return FALSE;
02038
02039 return TRUE;
02040 }
02041
02042 #endif
02043