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