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