1 From ea4b650366261e4257e4b0fb95e7f48e30ef36f0 Mon Sep 17 00:00:00 2001
2 From: Jacek Bukarewicz <j.bukarewicz@samsung.com>
3 Date: Thu, 27 Nov 2014 18:11:05 +0100
4 Subject: [PATCH 1/8] Integration of Cynara asynchronous security checks
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 This commit introduces basic framework for asynchronous policy
10 checks and Cynara integration code. Functions for checking security
11 policy can now return third value - BUS_RESULT_LATER denoting check
12 result unavailability. Whenever policy checker cannot decide on the
13 result of the check it is supposed to allocate DeferredMessage structure
14 that will be passed to the upper layers which can decide what should be
15 done in such situation.
16 Proper handling of such case will be implemented in subsequent commits.
17 Currently such return value results in message denial.
19 Cherry picked from 4dcfb02f17247ff9de966b62182cd2e08f301238
22 Updated for dbus 1.10.20 by Scott Murray and José Bollo
23 Updated for dbus 1.12.16 by José Bollo
25 Change-Id: I9bcbce34577e5dc2a3cecf6233a0a2b0e43e1108
26 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
27 Signed-off-by: Scott Murray <scott.murray@konsulko.com>
30 bus/activation.c | 5 +-
31 bus/bus.c | 124 ++++--
33 bus/check.c | 217 ++++++++++
35 bus/config-parser-common.c | 6 +
36 bus/config-parser-common.h | 1 +
37 bus/config-parser-trivial.c | 2 +
38 bus/config-parser.c | 72 +++-
39 bus/connection.c | 57 ++-
40 bus/connection.h | 4 +
41 bus/cynara.c | 374 ++++++++++++++++++
43 bus/dispatch.c | 46 ++-
45 bus/policy.c | 195 ++++++---
48 test/Makefile.am | 1 +
49 .../data/invalid-config-files/badcheck-1.conf | 9 +
50 .../data/invalid-config-files/badcheck-2.conf | 9 +
51 test/data/valid-config-files/check-1.conf | 9 +
52 .../debug-check-some.conf.in | 18 +
53 24 files changed, 1181 insertions(+), 144 deletions(-)
54 create mode 100644 bus/check.c
55 create mode 100644 bus/check.h
56 create mode 100644 bus/cynara.c
57 create mode 100644 bus/cynara.h
58 create mode 100644 test/data/invalid-config-files/badcheck-1.conf
59 create mode 100644 test/data/invalid-config-files/badcheck-2.conf
60 create mode 100644 test/data/valid-config-files/check-1.conf
61 create mode 100644 test/data/valid-config-files/debug-check-some.conf.in
63 diff --git a/bus/Makefile.am b/bus/Makefile.am
64 index c917063..2a8a72c 100644
67 @@ -13,6 +13,7 @@ DBUS_BUS_LIBS = \
74 DBUS_LAUNCHER_LIBS = \
75 @@ -30,6 +31,7 @@ AM_CPPFLAGS = \
77 -DDBUS_SYSTEM_CONFIG_FILE=\""$(dbusdatadir)/system.conf"\" \
82 # if assertions are enabled, improve backtraces
83 @@ -90,6 +92,8 @@ BUS_SOURCES= \
89 config-loader-expat.c \
92 @@ -97,6 +101,8 @@ BUS_SOURCES= \
93 config-parser-common.h \
100 $(DIR_WATCH_SOURCE) \
101 diff --git a/bus/activation.c b/bus/activation.c
102 index 99404b9..f9c6c62 100644
103 --- a/bus/activation.c
104 +++ b/bus/activation.c
105 @@ -1789,14 +1789,15 @@ bus_activation_activate_service (BusActivation *activation,
107 if (auto_activation &&
109 - !bus_context_check_security_policy (activation->context,
110 + BUS_RESULT_TRUE != bus_context_check_security_policy (activation->context,
112 connection, /* sender */
113 NULL, /* addressed recipient */
114 NULL, /* proposed recipient */
121 _DBUS_ASSERT_ERROR_IS_SET (error);
122 _dbus_verbose ("activation not authorized: %s: %s\n",
123 diff --git a/bus/bus.c b/bus/bus.c
124 index 2ad8e78..6fc45d0 100644
128 #include "apparmor.h"
130 #include "dir-watch.h"
132 #include <dbus/dbus-auth.h>
133 #include <dbus/dbus-list.h>
134 #include <dbus/dbus-hash.h>
135 @@ -67,6 +68,7 @@ struct BusContext
136 BusRegistry *registry;
138 BusMatchmaker *matchmaker;
141 DBusRLimit *initial_fd_limit;
142 unsigned int fork : 1;
143 @@ -1003,6 +1005,10 @@ bus_context_new (const DBusString *config_file,
147 + context->check = bus_check_new(context, error);
148 + if (context->check == NULL)
151 dbus_server_free_data_slot (&server_data_slot);
154 @@ -1127,6 +1133,12 @@ bus_context_unref (BusContext *context)
156 bus_context_shutdown (context);
158 + if (context->check)
160 + bus_check_unref(context->check);
161 + context->check = NULL;
164 if (context->connections)
166 bus_connections_unref (context->connections);
167 @@ -1256,6 +1268,12 @@ bus_context_get_loop (BusContext *context)
168 return context->loop;
172 +bus_context_get_check (BusContext *context)
174 + return context->check;
178 bus_context_allow_unix_user (BusContext *context,
180 @@ -1451,6 +1469,7 @@ complain_about_message (BusContext *context,
181 DBusConnection *proposed_recipient,
182 dbus_bool_t requested_reply,
184 + const char *privilege,
187 DBusError stack_error = DBUS_ERROR_INIT;
188 @@ -1480,7 +1499,8 @@ complain_about_message (BusContext *context,
189 dbus_set_error (&stack_error, error_name,
190 "%s, %d matched rules; type=\"%s\", sender=\"%s\" (%s) "
191 "interface=\"%s\" member=\"%s\" error name=\"%s\" "
192 - "requested_reply=\"%d\" destination=\"%s\" (%s)",
193 + "requested_reply=\"%d\" destination=\"%s\" (%s) "
194 + "privilege=\"%s\"",
197 dbus_message_type_to_string (dbus_message_get_type (message)),
198 @@ -1491,7 +1511,8 @@ complain_about_message (BusContext *context,
199 nonnull (dbus_message_get_error_name (message), "(unset)"),
201 nonnull (dbus_message_get_destination (message), DBUS_SERVICE_DBUS),
202 - proposed_recipient_loginfo);
203 + proposed_recipient_loginfo,
204 + nonnull (privilege, "(n/a)"));
206 /* If we hit OOM while setting the error, this will syslog "out of memory"
207 * which is itself an indication that something is seriously wrong */
208 @@ -1519,7 +1540,7 @@ complain_about_message (BusContext *context,
209 * NULL for addressed_recipient may mean the bus driver, or may mean
210 * no destination was specified in the message (e.g. a signal).
214 bus_context_check_security_policy (BusContext *context,
215 BusTransaction *transaction,
216 DBusConnection *sender,
217 @@ -1527,7 +1548,8 @@ bus_context_check_security_policy (BusContext *context,
218 DBusConnection *proposed_recipient,
219 DBusMessage *message,
220 BusActivationEntry *activation_entry,
223 + BusDeferredMessage **deferred_message)
225 const char *src, *dest;
226 BusClientPolicy *sender_policy;
227 @@ -1536,6 +1558,7 @@ bus_context_check_security_policy (BusContext *context,
230 dbus_bool_t requested_reply;
231 + const char *privilege;
233 type = dbus_message_get_type (message);
234 src = dbus_message_get_sender (message);
235 @@ -1565,7 +1588,7 @@ bus_context_check_security_policy (BusContext *context,
236 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
237 "Message bus will not accept messages of unknown type\n");
240 + return BUS_RESULT_FALSE;
243 requested_reply = FALSE;
244 @@ -1595,7 +1618,7 @@ bus_context_check_security_policy (BusContext *context,
245 if (dbus_error_is_set (&error2))
247 dbus_move_error (&error2, error);
249 + return BUS_RESULT_FALSE;
253 @@ -1624,11 +1647,11 @@ bus_context_check_security_policy (BusContext *context,
254 complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
255 "An SELinux policy prevents this sender from sending this "
256 "message to this recipient",
257 - 0, message, sender, proposed_recipient, FALSE, FALSE, error);
258 + 0, message, sender, proposed_recipient, FALSE, FALSE, NULL, error);
259 _dbus_verbose ("SELinux security check denying send to service\n");
263 + return BUS_RESULT_FALSE;
266 /* next verify AppArmor access controls. If allowed then
267 @@ -1646,7 +1669,7 @@ bus_context_check_security_policy (BusContext *context,
268 src ? src : DBUS_SERVICE_DBUS,
272 + return BUS_RESULT_FALSE;
274 if (!bus_connection_is_active (sender))
276 @@ -1660,7 +1683,7 @@ bus_context_check_security_policy (BusContext *context,
278 _dbus_verbose ("security check allowing %s message\n",
281 + return BUS_RESULT_TRUE;
285 @@ -1671,7 +1694,7 @@ bus_context_check_security_policy (BusContext *context,
286 "Client tried to send a message other than %s without being registered",
290 + return BUS_RESULT_FALSE;
294 @@ -1720,20 +1743,29 @@ bus_context_check_security_policy (BusContext *context,
295 (proposed_recipient == NULL && recipient_policy == NULL));
298 - if (sender_policy &&
299 - !bus_client_policy_check_can_send (sender_policy,
302 - proposed_recipient,
303 - message, &toggles, &log))
305 - complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
306 - "Rejected send message", toggles,
307 - message, sender, proposed_recipient, requested_reply,
308 - (addressed_recipient == proposed_recipient), error);
309 - _dbus_verbose ("security policy disallowing message due to sender policy\n");
314 + BusResult res = bus_client_policy_check_can_send (sender,
318 + addressed_recipient,
319 + proposed_recipient,
320 + message, &toggles, &log, &privilege,
322 + if (res == BUS_RESULT_FALSE)
324 + complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
325 + "Rejected send message", toggles,
326 + message, sender, proposed_recipient, requested_reply,
327 + (addressed_recipient == proposed_recipient), privilege,
329 + _dbus_verbose ("security policy disallowing message due to sender policy\n");
330 + return BUS_RESULT_FALSE;
332 + else if (res == BUS_RESULT_LATER)
333 + return BUS_RESULT_LATER;
338 @@ -1742,23 +1774,29 @@ bus_context_check_security_policy (BusContext *context,
339 complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
340 "Would reject message", toggles,
341 message, sender, proposed_recipient, requested_reply,
343 + TRUE, privilege, NULL);
346 - if (recipient_policy &&
347 - !bus_client_policy_check_can_receive (recipient_policy,
351 - addressed_recipient, proposed_recipient,
352 - message, &toggles))
353 + if (recipient_policy)
355 - complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
356 - "Rejected receive message", toggles,
357 - message, sender, proposed_recipient, requested_reply,
358 - (addressed_recipient == proposed_recipient), error);
359 - _dbus_verbose ("security policy disallowing message due to recipient policy\n");
362 + res = bus_client_policy_check_can_receive (recipient_policy,
366 + addressed_recipient, proposed_recipient,
367 + message, &toggles, &privilege, deferred_message);
368 + if (res == BUS_RESULT_FALSE)
370 + complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected receive message",
371 + toggles, message, sender, proposed_recipient, requested_reply,
372 + (addressed_recipient == proposed_recipient), privilege, error);
374 + "security policy disallowing message due to recipient policy\n");
375 + return BUS_RESULT_FALSE;
377 + else if (res == BUS_RESULT_LATER)
378 + return BUS_RESULT_LATER;
381 /* See if limits on size have been exceeded */
382 @@ -1768,10 +1806,10 @@ bus_context_check_security_policy (BusContext *context,
384 complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED,
385 "Rejected: destination has a full message queue",
386 - 0, message, sender, proposed_recipient, requested_reply, TRUE,
387 + 0, message, sender, proposed_recipient, requested_reply, TRUE, NULL,
389 _dbus_verbose ("security policy disallowing message due to full message queue\n");
391 + return BUS_RESULT_FALSE;
394 /* Record that we will allow a reply here in the future (don't
395 @@ -1792,11 +1830,11 @@ bus_context_check_security_policy (BusContext *context,
398 _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
400 + return BUS_RESULT_FALSE;
403 _dbus_verbose ("security policy allowing message\n");
405 + return BUS_RESULT_TRUE;
409 diff --git a/bus/bus.h b/bus/bus.h
410 index 2e0de82..82c32c8 100644
413 @@ -45,6 +45,22 @@ typedef struct BusTransaction BusTransaction;
414 typedef struct BusMatchmaker BusMatchmaker;
415 typedef struct BusMatchRule BusMatchRule;
416 typedef struct BusActivationEntry BusActivationEntry;
417 +typedef struct BusCheck BusCheck;
418 +typedef struct BusDeferredMessage BusDeferredMessage;
419 +typedef struct BusCynara BusCynara;
422 + * BusResult is defined as a pointer to a dummy structure to allow detection of type mismatches.
423 + * The disadvantage of such solution is that now BusResult variables cannot be used in switch
425 + * Additionally, BUS_RESULT_TRUE is defined as 0 instead of 1 to help detect type mismatches
428 +typedef const struct BusResultStruct { int dummy; } *BusResult;
430 +static const BusResult BUS_RESULT_TRUE = (BusResult)0x0;
431 +static const BusResult BUS_RESULT_FALSE = (BusResult)0x1;
432 +static const BusResult BUS_RESULT_LATER = (BusResult)0x2;
436 @@ -101,6 +117,7 @@ BusConnections* bus_context_get_connections (BusContext
437 BusActivation* bus_context_get_activation (BusContext *context);
438 BusMatchmaker* bus_context_get_matchmaker (BusContext *context);
439 DBusLoop* bus_context_get_loop (BusContext *context);
440 +BusCheck * bus_context_get_check (BusContext *context);
441 dbus_bool_t bus_context_allow_unix_user (BusContext *context,
443 dbus_bool_t bus_context_allow_windows_user (BusContext *context,
444 @@ -136,14 +153,15 @@ void bus_context_log_and_set_error (BusContext
447 ...) _DBUS_GNUC_PRINTF (5, 6);
448 -dbus_bool_t bus_context_check_security_policy (BusContext *context,
449 +BusResult bus_context_check_security_policy (BusContext *context,
450 BusTransaction *transaction,
451 DBusConnection *sender,
452 DBusConnection *addressed_recipient,
453 DBusConnection *proposed_recipient,
454 DBusMessage *message,
455 BusActivationEntry *activation_entry,
458 + BusDeferredMessage **deferred_message);
459 void bus_context_check_all_watches (BusContext *context);
461 #endif /* BUS_BUS_H */
462 diff --git a/bus/check.c b/bus/check.c
464 index 0000000..5b72d31
468 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
469 +/* check.c Bus security policy runtime check
471 + * Copyright (C) 2014 Intel, Inc.
472 + * Copyright (c) 2014 Samsung Electronics, Ltd.
474 + * Licensed under the Academic Free License version 2.1
476 + * This program is free software; you can redistribute it and/or modify
477 + * it under the terms of the GNU General Public License as published by
478 + * the Free Software Foundation; either version 2 of the License, or
479 + * (at your option) any later version.
481 + * This program is distributed in the hope that it will be useful,
482 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
483 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
484 + * GNU General Public License for more details.
486 + * You should have received a copy of the GNU General Public License
487 + * along with this program; if not, write to the Free Software
488 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
494 +#include "connection.h"
495 +#include "dispatch.h"
498 +#include <dbus/dbus-connection-internal.h>
499 +#include <dbus/dbus-message-internal.h>
500 +#include <dbus/dbus-internals.h>
503 +typedef struct BusCheck
507 + BusContext *context;
511 +typedef struct BusDeferredMessage
515 + DBusMessage *message;
516 + DBusConnection *sender;
517 + DBusConnection *proposed_recipient;
518 + DBusConnection *addressed_recipient;
519 + dbus_bool_t full_dispatch;
520 + BusDeferredMessageStatus status;
521 + BusResult response;
522 + BusCheckResponseFunc response_callback;
523 +} BusDeferredMessage;
526 +bus_check_new (BusContext *context, DBusError *error)
530 + check = dbus_new(BusCheck, 1);
533 + BUS_SET_OOM(error);
537 + check->refcount = 1;
538 + check->context = context;
539 + check->cynara = bus_cynara_new(check, error);
540 + if (dbus_error_is_set(error))
550 +bus_check_ref (BusCheck *check)
552 + _dbus_assert (check->refcount > 0);
553 + check->refcount += 1;
559 +bus_check_unref (BusCheck *check)
561 + _dbus_assert (check->refcount > 0);
563 + check->refcount -= 1;
565 + if (check->refcount == 0)
567 + bus_cynara_unref(check->cynara);
573 +bus_check_get_context (BusCheck *check)
575 + return check->context;
579 +bus_check_get_cynara (BusCheck *check)
581 + return check->cynara;
585 +bus_check_privilege (BusCheck *check,
586 + DBusMessage *message,
587 + DBusConnection *sender,
588 + DBusConnection *addressed_recipient,
589 + DBusConnection *proposed_recipient,
590 + const char *privilege,
591 + BusDeferredMessageStatus check_type,
592 + BusDeferredMessage **deferred_message)
594 + BusResult result = BUS_RESULT_FALSE;
595 +#ifdef DBUS_ENABLE_CYNARA
598 + DBusConnection *connection;
600 + connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
602 + if (!dbus_connection_get_is_connected(connection))
604 + return BUS_RESULT_FALSE;
607 + /* ask policy checkers */
608 +#ifdef DBUS_ENABLE_CYNARA
609 + cynara = bus_check_get_cynara(check);
610 + result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient,
611 + proposed_recipient, privilege, check_type, deferred_message);
614 + if (result == BUS_RESULT_LATER && deferred_message != NULL)
616 + (*deferred_message)->status |= check_type;
621 +BusDeferredMessage *bus_deferred_message_new (DBusMessage *message,
622 + DBusConnection *sender,
623 + DBusConnection *addressed_recipient,
624 + DBusConnection *proposed_recipient,
625 + BusResult response)
627 + BusDeferredMessage *deferred_message;
629 + deferred_message = dbus_new(BusDeferredMessage, 1);
630 + if (deferred_message == NULL)
635 + deferred_message->refcount = 1;
636 + deferred_message->sender = sender != NULL ? dbus_connection_ref(sender) : NULL;
637 + deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL;
638 + deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL;
639 + deferred_message->message = dbus_message_ref(message);
640 + deferred_message->response = response;
641 + deferred_message->status = 0;
642 + deferred_message->full_dispatch = FALSE;
643 + deferred_message->response_callback = NULL;
645 + return deferred_message;
648 +BusDeferredMessage *
649 +bus_deferred_message_ref (BusDeferredMessage *deferred_message)
651 + _dbus_assert (deferred_message->refcount > 0);
652 + deferred_message->refcount += 1;
653 + return deferred_message;
657 +bus_deferred_message_unref (BusDeferredMessage *deferred_message)
659 + _dbus_assert (deferred_message->refcount > 0);
661 + deferred_message->refcount -= 1;
663 + if (deferred_message->refcount == 0)
665 + dbus_message_unref(deferred_message->message);
666 + if (deferred_message->sender != NULL)
667 + dbus_connection_unref(deferred_message->sender);
668 + if (deferred_message->addressed_recipient != NULL)
669 + dbus_connection_unref(deferred_message->addressed_recipient);
670 + if (deferred_message->proposed_recipient != NULL)
671 + dbus_connection_unref(deferred_message->proposed_recipient);
672 + dbus_free(deferred_message);
677 +bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
680 + if (deferred_message->response_callback != NULL)
682 + deferred_message->response_callback(deferred_message, result);
685 diff --git a/bus/check.h b/bus/check.h
687 index 0000000..c3fcaf9
691 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
692 +/* check.h Bus security policy runtime check
694 + * Copyright (C) 2014 Intel, Inc.
695 + * Copyright (c) 2014 Samsung Electronics, Ltd.
697 + * Licensed under the Academic Free License version 2.1
699 + * This program is free software; you can redistribute it and/or modify
700 + * it under the terms of the GNU General Public License as published by
701 + * the Free Software Foundation; either version 2 of the License, or
702 + * (at your option) any later version.
704 + * This program is distributed in the hope that it will be useful,
705 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
706 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
707 + * GNU General Public License for more details.
709 + * You should have received a copy of the GNU General Public License
710 + * along with this program; if not, write to the Free Software
711 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
722 +typedef void (*BusCheckResponseFunc) (BusDeferredMessage *message,
726 + BUS_DEFERRED_MESSAGE_CHECK_SEND = 1 << 0,
727 + BUS_DEFERRED_MESSAGE_CHECK_RECEIVE = 1 << 1,
728 + BUS_DEFERRED_MESSAGE_CHECK_OWN = 1 << 2,
729 +} BusDeferredMessageStatus;
732 +BusCheck *bus_check_new (BusContext *context,
734 +BusCheck *bus_check_ref (BusCheck *check);
735 +void bus_check_unref (BusCheck *check);
737 +BusContext *bus_check_get_context (BusCheck *check);
738 +BusCynara *bus_check_get_cynara (BusCheck *check);
739 +BusResult bus_check_privilege (BusCheck *check,
740 + DBusMessage *message,
741 + DBusConnection *sender,
742 + DBusConnection *addressed_recipient,
743 + DBusConnection *proposed_recipient,
744 + const char *privilege,
745 + BusDeferredMessageStatus check_type,
746 + BusDeferredMessage **deferred_message);
748 +BusDeferredMessage *bus_deferred_message_new (DBusMessage *message,
749 + DBusConnection *sender,
750 + DBusConnection *addressed_recipient,
751 + DBusConnection *proposed_recipient,
752 + BusResult response);
754 +BusDeferredMessage *bus_deferred_message_ref (BusDeferredMessage *deferred_message);
755 +void bus_deferred_message_unref (BusDeferredMessage *deferred_message);
756 +void bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
758 +#endif /* BUS_CHECK_H */
759 diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c
760 index c1c4191..e2f253d 100644
761 --- a/bus/config-parser-common.c
762 +++ b/bus/config-parser-common.c
763 @@ -75,6 +75,10 @@ bus_config_parser_element_name_to_type (const char *name)
767 + else if (strcmp (name, "check") == 0)
769 + return ELEMENT_CHECK;
771 else if (strcmp (name, "servicehelper") == 0)
773 return ELEMENT_SERVICEHELPER;
774 @@ -159,6 +163,8 @@ bus_config_parser_element_type_to_name (ElementType type)
778 + case ELEMENT_CHECK:
782 case ELEMENT_PIDFILE:
783 diff --git a/bus/config-parser-common.h b/bus/config-parser-common.h
784 index 382a014..9e026d1 100644
785 --- a/bus/config-parser-common.h
786 +++ b/bus/config-parser-common.h
787 @@ -36,6 +36,7 @@ typedef enum
795 diff --git a/bus/config-parser-trivial.c b/bus/config-parser-trivial.c
796 index dd65c6d..23dedb4 100644
797 --- a/bus/config-parser-trivial.c
798 +++ b/bus/config-parser-trivial.c
799 @@ -194,6 +194,7 @@ bus_config_parser_start_element (BusConfigParser *parser,
803 + case ELEMENT_CHECK:
806 case ELEMENT_PIDFILE:
807 @@ -316,6 +317,7 @@ bus_config_parser_content (BusConfigParser *parser,
811 + case ELEMENT_CHECK:
814 case ELEMENT_PIDFILE:
815 diff --git a/bus/config-parser.c b/bus/config-parser.c
816 index be27d38..7f91469 100644
817 --- a/bus/config-parser.c
818 +++ b/bus/config-parser.c
819 @@ -1318,7 +1318,7 @@ append_rule_from_element (BusConfigParser *parser,
820 const char *element_name,
821 const char **attribute_names,
822 const char **attribute_values,
824 + BusPolicyRuleAccess access,
828 @@ -1360,6 +1360,7 @@ append_rule_from_element (BusConfigParser *parser,
829 const char *own_prefix;
832 + const char *privilege;
836 @@ -1390,6 +1391,7 @@ append_rule_from_element (BusConfigParser *parser,
840 + "privilege", &privilege,
844 @@ -1422,6 +1424,7 @@ append_rule_from_element (BusConfigParser *parser,
846 if (!(any_send_attribute ||
847 any_receive_attribute ||
849 own || own_prefix || user || group))
851 dbus_set_error (error, DBUS_ERROR_FAILED,
852 @@ -1438,7 +1441,30 @@ append_rule_from_element (BusConfigParser *parser,
858 + if (access == BUS_POLICY_RULE_ACCESS_CHECK)
860 + if (privilege == NULL || !*privilege)
862 + dbus_set_error (error, DBUS_ERROR_FAILED,
863 + "On element <%s>, you must specify the privilege to be checked.",
870 + if (privilege != NULL && *privilege)
872 + dbus_set_error (error, DBUS_ERROR_FAILED,
873 + "On element <%s>, privilege %s is used outside of a check rule.",
874 + element_name, privilege);
878 + privilege = NULL; /* replace (potentially) empty string with NULL pointer, it wouldn't be used anyway */
881 /* Allowed combinations of elements are:
883 * base, must be all send or all receive:
884 @@ -1589,7 +1615,7 @@ append_rule_from_element (BusConfigParser *parser,
888 - rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow);
889 + rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, access);
893 @@ -1694,7 +1720,7 @@ append_rule_from_element (BusConfigParser *parser,
897 - rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow);
898 + rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, access);
902 @@ -1726,7 +1752,7 @@ append_rule_from_element (BusConfigParser *parser,
904 else if (own || own_prefix)
906 - rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow);
907 + rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, access);
911 @@ -1752,7 +1778,7 @@ append_rule_from_element (BusConfigParser *parser,
913 if (IS_WILDCARD (user))
915 - rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
916 + rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access);
920 @@ -1767,7 +1793,7 @@ append_rule_from_element (BusConfigParser *parser,
922 if (_dbus_parse_unix_user_from_config (&username, &uid))
924 - rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
925 + rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access);
929 @@ -1784,7 +1810,7 @@ append_rule_from_element (BusConfigParser *parser,
931 if (IS_WILDCARD (group))
933 - rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
934 + rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access);
938 @@ -1799,7 +1825,7 @@ append_rule_from_element (BusConfigParser *parser,
940 if (_dbus_parse_unix_group_from_config (&groupname, &gid))
942 - rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
943 + rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access);
947 @@ -1823,6 +1849,10 @@ append_rule_from_element (BusConfigParser *parser,
948 _dbus_assert (pe != NULL);
949 _dbus_assert (pe->type == ELEMENT_POLICY);
951 + rule->privilege = _dbus_strdup (privilege);
952 + if (privilege && !rule->privilege)
955 switch (pe->d.policy.type)
958 @@ -1898,7 +1928,7 @@ start_policy_child (BusConfigParser *parser,
960 if (!append_rule_from_element (parser, element_name,
961 attribute_names, attribute_values,
963 + BUS_POLICY_RULE_ACCESS_ALLOW, error))
966 if (push_element (parser, ELEMENT_ALLOW) == NULL)
967 @@ -1913,7 +1943,7 @@ start_policy_child (BusConfigParser *parser,
969 if (!append_rule_from_element (parser, element_name,
970 attribute_names, attribute_values,
972 + BUS_POLICY_RULE_ACCESS_DENY, error))
975 if (push_element (parser, ELEMENT_DENY) == NULL)
976 @@ -1922,6 +1952,21 @@ start_policy_child (BusConfigParser *parser,
982 + else if (strcmp (element_name, "check") == 0)
984 + if (!append_rule_from_element (parser, element_name,
985 + attribute_names, attribute_values,
986 + BUS_POLICY_RULE_ACCESS_CHECK, error))
989 + if (push_element (parser, ELEMENT_CHECK) == NULL)
991 + BUS_SET_OOM (error);
998 @@ -2284,6 +2329,7 @@ bus_config_parser_end_element (BusConfigParser *parser,
1002 + case ELEMENT_CHECK:
1004 case ELEMENT_SYSLOG:
1005 case ELEMENT_KEEP_UMASK:
1006 @@ -2600,6 +2646,7 @@ bus_config_parser_content (BusConfigParser *parser,
1007 case ELEMENT_POLICY:
1010 + case ELEMENT_CHECK:
1012 case ELEMENT_SYSLOG:
1013 case ELEMENT_KEEP_UMASK:
1014 @@ -3127,6 +3174,8 @@ do_load (const DBusString *full_path,
1015 dbus_error_init (&error);
1017 parser = bus_config_load (full_path, TRUE, NULL, &error);
1018 + if (dbus_error_is_set (&error))
1019 + _dbus_verbose ("Failed to load file: %s\n", error.message);
1022 _DBUS_ASSERT_ERROR_IS_SET (&error);
1023 @@ -3359,6 +3408,7 @@ elements_equal (const Element *a,
1024 case ELEMENT_LISTEN:
1027 + case ELEMENT_CHECK:
1030 case ELEMENT_PIDFILE:
1031 diff --git a/bus/connection.c b/bus/connection.c
1032 index 53605fa..b348d42 100644
1033 --- a/bus/connection.c
1034 +++ b/bus/connection.c
1036 #include <dbus/dbus-timeout.h>
1037 #include <dbus/dbus-connection-internal.h>
1038 #include <dbus/dbus-internals.h>
1039 +#ifdef DBUS_ENABLE_CYNARA
1040 +#include <stdlib.h>
1041 +#include <cynara-session.h>
1044 /* Trim executed commands to this length; we want to keep logs readable */
1045 #define MAX_LOG_COMMAND_LEN 50
1046 @@ -116,6 +120,9 @@ typedef struct
1048 /** non-NULL if and only if this is a monitor */
1049 DBusList *link_in_monitors;
1050 +#ifdef DBUS_ENABLE_CYNARA
1051 + char *cynara_session_id;
1053 } BusConnectionData;
1055 static dbus_bool_t bus_pending_reply_expired (BusExpireList *list,
1056 @@ -129,8 +136,8 @@ static dbus_bool_t expire_incomplete_timeout (void *data);
1058 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
1061 -connection_get_loop (DBusConnection *connection)
1063 +bus_connection_get_loop (DBusConnection *connection)
1065 BusConnectionData *d;
1067 @@ -354,7 +361,7 @@ add_connection_watch (DBusWatch *watch,
1069 DBusConnection *connection = data;
1071 - return _dbus_loop_add_watch (connection_get_loop (connection), watch);
1072 + return _dbus_loop_add_watch (bus_connection_get_loop (connection), watch);
1076 @@ -363,7 +370,7 @@ remove_connection_watch (DBusWatch *watch,
1078 DBusConnection *connection = data;
1080 - _dbus_loop_remove_watch (connection_get_loop (connection), watch);
1081 + _dbus_loop_remove_watch (bus_connection_get_loop (connection), watch);
1085 @@ -372,7 +379,7 @@ toggle_connection_watch (DBusWatch *watch,
1087 DBusConnection *connection = data;
1089 - _dbus_loop_toggle_watch (connection_get_loop (connection), watch);
1090 + _dbus_loop_toggle_watch (bus_connection_get_loop (connection), watch);
1094 @@ -381,7 +388,7 @@ add_connection_timeout (DBusTimeout *timeout,
1096 DBusConnection *connection = data;
1098 - return _dbus_loop_add_timeout (connection_get_loop (connection), timeout);
1099 + return _dbus_loop_add_timeout (bus_connection_get_loop (connection), timeout);
1103 @@ -390,7 +397,7 @@ remove_connection_timeout (DBusTimeout *timeout,
1105 DBusConnection *connection = data;
1107 - _dbus_loop_remove_timeout (connection_get_loop (connection), timeout);
1108 + _dbus_loop_remove_timeout (bus_connection_get_loop (connection), timeout);
1112 @@ -448,6 +455,10 @@ free_connection_data (void *data)
1114 dbus_free (d->name);
1116 +#ifdef DBUS_ENABLE_CYNARA
1117 + free (d->cynara_session_id);
1123 @@ -1078,6 +1089,22 @@ bus_connection_get_policy (DBusConnection *connection)
1127 +#ifdef DBUS_ENABLE_CYNARA
1128 +const char *bus_connection_get_cynara_session_id (DBusConnection *connection)
1130 + BusConnectionData *d = BUS_CONNECTION_DATA (connection);
1131 + _dbus_assert (d != NULL);
1133 + if (d->cynara_session_id == NULL)
1135 + unsigned long pid;
1136 + if (dbus_connection_get_unix_process_id(connection, &pid))
1137 + d->cynara_session_id = cynara_session_from_pid(pid);
1139 + return d->cynara_session_id;
1144 foreach_active (BusConnections *connections,
1145 BusConnectionForeachFunction function,
1146 @@ -2333,6 +2360,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
1147 DBusMessage *message)
1149 DBusError error = DBUS_ERROR_INIT;
1152 /* We have to set the sender to the driver, and have
1153 * to check security policy since it was not done in
1154 @@ -2370,10 +2398,11 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
1155 * if we're actively capturing messages, it's nice to log that we
1156 * tried to send it and did not allow ourselves to do so.
1158 - if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
1160 - NULL, connection, connection,
1161 - message, NULL, &error))
1162 + res = bus_context_check_security_policy (bus_transaction_get_context (transaction),
1164 + NULL, connection, connection, message, NULL,
1166 + if (res == BUS_RESULT_FALSE)
1168 if (!bus_transaction_capture_error_reply (transaction, connection,
1170 @@ -2388,6 +2417,12 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
1171 dbus_error_free (&error);
1174 + else if (res == BUS_RESULT_LATER)
1176 + _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n");
1177 + dbus_error_free (&error);
1181 return bus_transaction_send (transaction, connection, message);
1183 diff --git a/bus/connection.h b/bus/connection.h
1184 index 9e253ae..71078ea 100644
1185 --- a/bus/connection.h
1186 +++ b/bus/connection.h
1188 typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection,
1191 +DBusLoop* bus_connection_get_loop (DBusConnection *connection);
1193 BusConnections* bus_connections_new (BusContext *context);
1194 BusConnections* bus_connections_ref (BusConnections *connections);
1195 @@ -124,6 +125,9 @@ dbus_bool_t bus_connection_be_monitor (DBusConnection *connection,
1196 BusTransaction *transaction,
1199 +#ifdef DBUS_ENABLE_CYNARA
1200 +const char *bus_connection_get_cynara_session_id (DBusConnection *connection);
1203 /* transaction API so we can send or not send a block of messages as a whole */
1205 diff --git a/bus/cynara.c b/bus/cynara.c
1206 new file mode 100644
1207 index 0000000..57a4c45
1211 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1212 +/* cynara.c Cynara runtime privilege checking
1214 + * Copyright (c) 2014 Samsung Electronics, Ltd.
1216 + * Licensed under the Academic Free License version 2.1
1218 + * This program is free software; you can redistribute it and/or modify
1219 + * it under the terms of the GNU General Public License as published by
1220 + * the Free Software Foundation; either version 2 of the License, or
1221 + * (at your option) any later version.
1223 + * This program is distributed in the hope that it will be useful,
1224 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1225 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1226 + * GNU General Public License for more details.
1228 + * You should have received a copy of the GNU General Public License
1229 + * along with this program; if not, write to the Free Software
1230 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1234 +#include <config.h>
1235 +#include "cynara.h"
1241 +#include <dbus/dbus.h>
1242 +#include <dbus/dbus-watch.h>
1243 +#include <dbus/dbus-connection-internal.h>
1244 +#include <bus/connection.h>
1245 +#ifdef DBUS_ENABLE_CYNARA
1246 +#include <cynara-client-async.h>
1250 +#ifdef DBUS_ENABLE_CYNARA
1251 +typedef struct BusCynara
1255 + BusContext *context;
1257 + cynara_async *cynara;
1258 + DBusWatch *cynara_watch;
1261 +#define USE_CYNARA_CACHE 1
1262 +#ifdef USE_CYNARA_CACHE
1263 +#define CYNARA_CACHE_SIZE 1000
1266 +static dbus_bool_t bus_cynara_watch_callback(DBusWatch *watch,
1267 + unsigned int flags,
1270 +static void status_callback(int old_fd,
1272 + cynara_async_status status,
1273 + void *user_status_data);
1274 +static void bus_cynara_check_response_callback (cynara_check_id check_id,
1275 + cynara_async_call_cause cause,
1277 + void *user_response_data);
1282 +bus_cynara_new(BusCheck *check, DBusError *error)
1284 +#ifdef DBUS_ENABLE_CYNARA
1285 + BusContext *context;
1286 + BusCynara *cynara;
1287 + cynara_async_configuration *conf = NULL;
1290 + cynara = dbus_new(BusCynara, 1);
1291 + if (cynara == NULL)
1293 + BUS_SET_OOM(error);
1297 + context = bus_check_get_context(check);
1299 + cynara->refcount = 1;
1300 + cynara->check = check;
1301 + cynara->context = context;
1302 + cynara->cynara_watch = NULL;
1304 + ret = cynara_async_configuration_create(&conf);
1305 + if (ret != CYNARA_API_SUCCESS)
1307 + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to create Cynara configuration");
1311 +#ifdef CYNARA_CACHE_SIZE
1312 + ret = cynara_async_configuration_set_cache_size(conf, CYNARA_CACHE_SIZE);
1313 + if (ret != CYNARA_API_SUCCESS)
1315 + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to Cynara cache size");
1320 + ret = cynara_async_initialize(&cynara->cynara, conf, &status_callback, cynara);
1321 + if (ret != CYNARA_API_SUCCESS)
1323 + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to initialize Cynara client");
1328 + cynara_async_configuration_destroy(conf);
1329 + if (ret != CYNARA_API_SUCCESS)
1331 + dbus_free(cynara);
1342 +bus_cynara_ref (BusCynara *cynara)
1344 +#ifdef DBUS_ENABLE_CYNARA
1345 + _dbus_assert (cynara->refcount > 0);
1346 + cynara->refcount += 1;
1355 +bus_cynara_unref (BusCynara *cynara)
1357 +#ifdef DBUS_ENABLE_CYNARA
1358 + _dbus_assert (cynara->refcount > 0);
1360 + cynara->refcount -= 1;
1362 + if (cynara->refcount == 0)
1364 + cynara_async_finish(cynara->cynara);
1365 + dbus_free(cynara);
1371 +bus_cynara_check_privilege (BusCynara *cynara,
1372 + DBusMessage *message,
1373 + DBusConnection *sender,
1374 + DBusConnection *addressed_recipient,
1375 + DBusConnection *proposed_recipient,
1376 + const char *privilege,
1377 + BusDeferredMessageStatus check_type,
1378 + BusDeferredMessage **deferred_message_param)
1380 +#ifdef DBUS_ENABLE_CYNARA
1382 + unsigned long uid;
1384 + const char *session_id;
1386 + cynara_check_id check_id;
1387 + DBusConnection *connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
1388 + BusDeferredMessage *deferred_message;
1391 + _dbus_assert(connection != NULL);
1393 + if (dbus_connection_get_unix_user(connection, &uid) == FALSE)
1394 + return BUS_RESULT_FALSE;
1396 + if (_dbus_connection_get_linux_security_label(connection, &label) == FALSE || label == NULL)
1398 + _dbus_warn("Failed to obtain security label for connection\n");
1399 + return BUS_RESULT_FALSE;
1402 + session_id = bus_connection_get_cynara_session_id (connection);
1403 + if (session_id == NULL)
1405 + ret = BUS_RESULT_FALSE;
1409 + snprintf(user, sizeof(user), "%lu", uid);
1411 +#if USE_CYNARA_CACHE
1412 + result = cynara_async_check_cache(cynara->cynara, label, session_id, user, privilege);
1414 + result = CYNARA_API_CACHE_MISS;
1419 + case CYNARA_API_ACCESS_ALLOWED:
1420 + _dbus_verbose("Cynara: got ALLOWED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n",
1421 + label, session_id, user, privilege);
1422 + ret = BUS_RESULT_TRUE;
1425 + case CYNARA_API_ACCESS_DENIED:
1426 + _dbus_verbose("Cynara: got DENIED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n",
1427 + label, session_id, user, privilege);
1428 + ret = BUS_RESULT_FALSE;
1431 + case CYNARA_API_CACHE_MISS:
1432 + deferred_message = bus_deferred_message_new(message, sender, addressed_recipient,
1433 + proposed_recipient, BUS_RESULT_LATER);
1434 + if (deferred_message == NULL)
1436 + _dbus_verbose("Failed to allocate memory for deferred message\n");
1437 + ret = BUS_RESULT_FALSE;
1441 + /* callback is supposed to unref deferred_message*/
1442 + result = cynara_async_create_request(cynara->cynara, label, session_id, user, privilege, &check_id,
1443 + &bus_cynara_check_response_callback, deferred_message);
1444 + if (result == CYNARA_API_SUCCESS)
1446 + _dbus_verbose("Created Cynara request: client=%s session_id=%s user=%s privilege=%s check_id=%u "
1447 + "deferred_message=%p\n", label, session_id, user, privilege, (unsigned int)check_id, deferred_message);
1448 + if (deferred_message_param != NULL)
1449 + *deferred_message_param = deferred_message;
1450 + ret = BUS_RESULT_LATER;
1454 + _dbus_verbose("Error on cynara request create: %i\n", result);
1455 + bus_deferred_message_unref(deferred_message);
1456 + ret = BUS_RESULT_FALSE;
1460 + _dbus_verbose("Error when accessing Cynara cache: %i\n", result);
1461 + ret = BUS_RESULT_FALSE;
1468 + return BUS_RESULT_FALSE;
1474 +#ifdef DBUS_ENABLE_CYNARA
1476 +status_callback(int old_fd, int new_fd, cynara_async_status status,
1477 + void *user_status_data)
1479 + BusCynara *cynara = (BusCynara *)user_status_data;
1480 + DBusLoop *loop = bus_context_get_loop(cynara->context);
1482 + if (cynara->cynara_watch != NULL)
1484 + _dbus_loop_remove_watch(loop, cynara->cynara_watch);
1485 + _dbus_watch_invalidate(cynara->cynara_watch);
1486 + _dbus_watch_unref(cynara->cynara_watch);
1487 + cynara->cynara_watch = NULL;
1492 + unsigned int flags;
1497 + case CYNARA_STATUS_FOR_READ:
1498 + flags = DBUS_WATCH_READABLE;
1500 + case CYNARA_STATUS_FOR_RW:
1501 + flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE;
1504 + /* Cynara passed unknown status - warn and add RW watch */
1505 + _dbus_verbose("Cynara passed unknown status value: 0x%08X\n", (unsigned int)status);
1506 + flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE;
1510 + watch = _dbus_watch_new(new_fd, flags, TRUE, &bus_cynara_watch_callback, cynara, NULL);
1511 + if (watch != NULL)
1513 + if (_dbus_loop_add_watch(loop, watch) == TRUE)
1515 + cynara->cynara_watch = watch;
1519 + _dbus_watch_invalidate(watch);
1520 + _dbus_watch_unref(watch);
1523 + /* It seems like not much can be done at this point. Cynara events won't be processed
1524 + * until next Cynara function call triggering status callback */
1525 + _dbus_verbose("Failed to add dbus watch\n");
1530 +bus_cynara_watch_callback(DBusWatch *watch,
1531 + unsigned int flags,
1534 + BusCynara *cynara = (BusCynara *)data;
1535 + int result = cynara_async_process(cynara->cynara);
1536 + if (result != CYNARA_API_SUCCESS)
1537 + _dbus_verbose("cynara_async_process returned %d\n", result);
1539 + return result != CYNARA_API_OUT_OF_MEMORY ? TRUE : FALSE;
1542 +static inline const char *
1543 +call_cause_to_string(cynara_async_call_cause cause)
1547 + case CYNARA_CALL_CAUSE_ANSWER:
1549 + case CYNARA_CALL_CAUSE_CANCEL:
1551 + case CYNARA_CALL_CAUSE_FINISH:
1553 + case CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE:
1554 + return "SERVICE NOT AVAILABLE";
1561 +bus_cynara_check_response_callback (cynara_check_id check_id,
1562 + cynara_async_call_cause cause,
1564 + void *user_response_data)
1566 + BusDeferredMessage *deferred_message = user_response_data;
1569 + _dbus_verbose("Cynara callback: check_id=%u, cause=%s response=%i response_data=%p\n",
1570 + (unsigned int)check_id, call_cause_to_string(cause), response, user_response_data);
1572 + if (deferred_message == NULL)
1575 + if (cause == CYNARA_CALL_CAUSE_ANSWER && response == CYNARA_API_ACCESS_ALLOWED)
1576 + result = BUS_RESULT_TRUE;
1578 + result = BUS_RESULT_FALSE;
1580 + bus_deferred_message_response_received(deferred_message, result);
1581 + bus_deferred_message_unref(deferred_message);
1584 +#endif /* DBUS_ENABLE_CYNARA */
1585 diff --git a/bus/cynara.h b/bus/cynara.h
1586 new file mode 100644
1587 index 0000000..c4728bb
1591 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1592 +/* cynara.h Cynara runtime privilege checking
1594 + * Copyright (c) 2014 Samsung Electronics, Ltd.
1596 + * Licensed under the Academic Free License version 2.1
1598 + * This program is free software; you can redistribute it and/or modify
1599 + * it under the terms of the GNU General Public License as published by
1600 + * the Free Software Foundation; either version 2 of the License, or
1601 + * (at your option) any later version.
1603 + * This program is distributed in the hope that it will be useful,
1604 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1605 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1606 + * GNU General Public License for more details.
1608 + * You should have received a copy of the GNU General Public License
1609 + * along with this program; if not, write to the Free Software
1610 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1617 +BusCynara *bus_cynara_new (BusCheck *check, DBusError *error);
1618 +BusCynara *bus_cynara_ref (BusCynara *cynara);
1619 +void bus_cynara_unref (BusCynara *cynara);
1620 +BusResult bus_cynara_check_privilege (BusCynara *cynara,
1621 + DBusMessage *message,
1622 + DBusConnection *sender,
1623 + DBusConnection *addressed_recipient,
1624 + DBusConnection *proposed_recipient,
1625 + const char *privilege,
1626 + BusDeferredMessageStatus check_type,
1627 + BusDeferredMessage **deferred_message);
1628 diff --git a/bus/dispatch.c b/bus/dispatch.c
1629 index 19228be..d3867f7 100644
1630 --- a/bus/dispatch.c
1631 +++ b/bus/dispatch.c
1635 #include "dispatch.h"
1637 #include "connection.h"
1639 #include "services.h"
1640 @@ -64,14 +65,18 @@ send_one_message (DBusConnection *connection,
1643 DBusError stack_error = DBUS_ERROR_INIT;
1644 + BusDeferredMessage *deferred_message;
1647 - if (!bus_context_check_security_policy (context, transaction,
1648 + result = bus_context_check_security_policy (context, transaction,
1650 addressed_recipient,
1656 + &deferred_message);
1657 + if (result != BUS_RESULT_TRUE)
1659 if (!bus_transaction_capture_error_reply (transaction, sender,
1660 &stack_error, message))
1661 @@ -130,6 +135,8 @@ bus_dispatch_matches (BusTransaction *transaction,
1662 BusMatchmaker *matchmaker;
1664 BusContext *context;
1665 + BusDeferredMessage *deferred_message;
1668 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1670 @@ -145,11 +152,20 @@ bus_dispatch_matches (BusTransaction *transaction,
1671 /* First, send the message to the addressed_recipient, if there is one. */
1672 if (addressed_recipient != NULL)
1674 - if (!bus_context_check_security_policy (context, transaction,
1675 - sender, addressed_recipient,
1676 - addressed_recipient,
1677 - message, NULL, error))
1678 + res = bus_context_check_security_policy (context, transaction,
1679 + sender, addressed_recipient,
1680 + addressed_recipient,
1681 + message, NULL, error,
1682 + &deferred_message);
1683 + if (res == BUS_RESULT_FALSE)
1685 + else if (res == BUS_RESULT_LATER)
1687 + dbus_set_error (error,
1688 + DBUS_ERROR_ACCESS_DENIED,
1689 + "Rejecting message because time is needed to check security policy");
1693 if (dbus_message_contains_unix_fds (message) &&
1694 !dbus_connection_can_send_type (addressed_recipient,
1695 @@ -374,19 +390,31 @@ bus_dispatch (DBusConnection *connection,
1697 strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
1699 + BusDeferredMessage *deferred_message;
1702 if (!bus_transaction_capture (transaction, connection, NULL, message))
1704 BUS_SET_OOM (&error);
1708 - if (!bus_context_check_security_policy (context, transaction,
1709 - connection, NULL, NULL, message,
1711 + res = bus_context_check_security_policy (context, transaction,
1712 + connection, NULL, NULL, message, NULL,
1713 + &error, &deferred_message);
1714 + if (res == BUS_RESULT_FALSE)
1716 _dbus_verbose ("Security policy rejected message\n");
1719 + else if (res == BUS_RESULT_LATER)
1721 + dbus_set_error (&error,
1722 + DBUS_ERROR_ACCESS_DENIED,
1723 + "Rejecting message because time is needed to check security policy");
1724 + _dbus_verbose ("Security policy needs time to check policy. Dropping message\n");
1728 _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
1729 if (!bus_driver_handle_message (connection, transaction, message, &error))
1730 diff --git a/bus/driver.h b/bus/driver.h
1731 index ac1289d..a7297ad 100644
1734 @@ -66,5 +66,7 @@ dbus_bool_t bus_driver_send_ack_reply (DBusConnection *connection,
1735 BusTransaction *transaction,
1736 DBusMessage *message,
1738 +dbus_bool_t bus_driver_check_message_is_for_us (DBusMessage *message,
1739 + DBusError *error);
1741 #endif /* BUS_DRIVER_H */
1742 diff --git a/bus/policy.c b/bus/policy.c
1743 index a37be80..7de92c6 100644
1752 #include "services.h"
1757 bus_policy_rule_new (BusPolicyRuleType type,
1758 - dbus_bool_t allow)
1759 + BusPolicyRuleAccess access)
1761 BusPolicyRule *rule;
1763 @@ -43,7 +44,7 @@ bus_policy_rule_new (BusPolicyRuleType type,
1767 - rule->allow = allow;
1768 + rule->access = access;
1772 @@ -55,18 +56,19 @@ bus_policy_rule_new (BusPolicyRuleType type,
1774 case BUS_POLICY_RULE_SEND:
1775 rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID;
1777 /* allow rules default to TRUE (only requested replies allowed)
1778 + * check rules default to TRUE (only requested replies are checked)
1779 * deny rules default to FALSE (only unrequested replies denied)
1781 - rule->d.send.requested_reply = rule->allow;
1782 + rule->d.send.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY;
1784 case BUS_POLICY_RULE_RECEIVE:
1785 rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID;
1786 /* allow rules default to TRUE (only requested replies allowed)
1787 + * check rules default to TRUE (only requested replies are checked)
1788 * deny rules default to FALSE (only unrequested replies denied)
1790 - rule->d.receive.requested_reply = rule->allow;
1791 + rule->d.receive.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY;
1793 case BUS_POLICY_RULE_OWN:
1795 @@ -122,7 +124,8 @@ bus_policy_rule_unref (BusPolicyRule *rule)
1797 _dbus_assert_not_reached ("invalid rule");
1801 + dbus_free (rule->privilege);
1805 @@ -435,7 +438,10 @@ list_allows_user (dbus_bool_t def,
1809 - allowed = rule->allow;
1810 + /* We don't intend to support <check user="..." /> and <check group="..." />
1811 + rules. They are treated like deny.
1813 + allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW;
1817 @@ -873,18 +879,23 @@ bus_client_policy_append_rule (BusClientPolicy *policy,
1822 -bus_client_policy_check_can_send (BusClientPolicy *policy,
1823 - BusRegistry *registry,
1824 - dbus_bool_t requested_reply,
1825 - DBusConnection *receiver,
1826 - DBusMessage *message,
1827 - dbus_int32_t *toggles,
1830 +bus_client_policy_check_can_send (DBusConnection *sender,
1831 + BusClientPolicy *policy,
1832 + BusRegistry *registry,
1833 + dbus_bool_t requested_reply,
1834 + DBusConnection *addressed_recipient,
1835 + DBusConnection *receiver,
1836 + DBusMessage *message,
1837 + dbus_int32_t *toggles,
1839 + const char **privilege_param,
1840 + BusDeferredMessage **deferred_message)
1843 - dbus_bool_t allowed;
1846 + const char *privilege;
1848 /* policy->rules is in the order the rules appeared
1849 * in the config file, i.e. last rule that applies wins
1851 @@ -892,7 +903,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1852 _dbus_verbose (" (policy) checking send rules\n");
1856 + result = BUS_RESULT_FALSE;
1857 link = _dbus_list_get_first_link (&policy->rules);
1858 while (link != NULL)
1860 @@ -923,13 +934,14 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1861 /* If it's a reply, the requested_reply flag kicks in */
1862 if (dbus_message_get_reply_serial (message) != 0)
1864 - /* for allow, requested_reply=true means the rule applies
1865 - * only when reply was requested. requested_reply=false means
1867 + /* for allow or check requested_reply=true means the rule applies
1868 + * only when reply was requested. requested_reply=false means the
1869 + * rule always applies
1871 - if (!requested_reply && rule->allow && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
1872 + if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
1874 - _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
1875 + _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n",
1876 + rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check");
1880 @@ -937,7 +949,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1881 * when the reply was not requested. requested_reply=true means the
1882 * rule always applies.
1884 - if (requested_reply && !rule->allow && !rule->d.send.requested_reply)
1885 + if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.send.requested_reply)
1887 _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n");
1889 @@ -960,13 +972,15 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1890 /* The interface is optional in messages. For allow rules, if the message
1891 * has no interface we want to skip the rule (and thus not allow);
1892 * for deny rules, if the message has no interface we want to use the
1893 - * rule (and thus deny).
1894 + * rule (and thus deny). Check rules are meant to be used like allow
1895 + * rules (they can grant access, but not remove it), so we treat it like
1898 dbus_bool_t no_interface;
1900 no_interface = dbus_message_get_interface (message) == NULL;
1902 - if ((no_interface && rule->allow) ||
1903 + if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) ||
1905 strcmp (dbus_message_get_interface (message),
1906 rule->d.send.interface) != 0))
1907 @@ -1079,33 +1093,64 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1911 - allowed = rule->allow;
1912 + switch (rule->access)
1914 + case BUS_POLICY_RULE_ACCESS_ALLOW:
1915 + result = BUS_RESULT_TRUE;
1917 + case BUS_POLICY_RULE_ACCESS_DENY:
1919 + result = BUS_RESULT_FALSE;
1921 + case BUS_POLICY_RULE_ACCESS_CHECK:
1922 + result = BUS_RESULT_LATER;
1923 + privilege = rule->privilege;
1927 *log = rule->d.send.log;
1930 - _dbus_verbose (" (policy) used rule, allow now = %d\n",
1932 + _dbus_verbose (" (policy) used rule, result now = %d\n",
1933 + (int)(intptr_t)result);
1937 + if (result == BUS_RESULT_LATER)
1939 + BusContext *context = bus_connection_get_context(sender);
1940 + BusCheck *check = bus_context_get_check(context);
1942 + result = bus_check_privilege(check, message, sender, addressed_recipient, receiver,
1943 + privilege, BUS_DEFERRED_MESSAGE_CHECK_SEND, deferred_message);
1948 + if (privilege_param != NULL)
1949 + *privilege_param = privilege;
1954 /* See docs on what the args mean on bus_context_check_security_policy()
1958 -bus_client_policy_check_can_receive (BusClientPolicy *policy,
1959 - BusRegistry *registry,
1960 - dbus_bool_t requested_reply,
1961 - DBusConnection *sender,
1962 - DBusConnection *addressed_recipient,
1963 - DBusConnection *proposed_recipient,
1964 - DBusMessage *message,
1965 - dbus_int32_t *toggles)
1967 +bus_client_policy_check_can_receive (BusClientPolicy *policy,
1968 + BusRegistry *registry,
1969 + dbus_bool_t requested_reply,
1970 + DBusConnection *sender,
1971 + DBusConnection *addressed_recipient,
1972 + DBusConnection *proposed_recipient,
1973 + DBusMessage *message,
1974 + dbus_int32_t *toggles,
1975 + const char **privilege_param,
1976 + BusDeferredMessage **deferred_message)
1979 - dbus_bool_t allowed;
1980 dbus_bool_t eavesdropping;
1982 + const char *privilege;
1985 addressed_recipient != proposed_recipient &&
1986 @@ -1118,7 +1163,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1987 _dbus_verbose (" (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
1991 + result = BUS_RESULT_FALSE;
1992 link = _dbus_list_get_first_link (&policy->rules);
1993 while (link != NULL)
1995 @@ -1141,19 +1186,21 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1999 - /* for allow, eavesdrop=false means the rule doesn't apply when
2000 - * eavesdropping. eavesdrop=true means always allow.
2002 + /* for allow or check, eavesdrop=false means the rule doesn't apply when
2003 + * eavesdropping. eavesdrop=true means the rule always applies
2005 - if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop)
2006 + if (eavesdropping && rule->access != BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.eavesdrop)
2008 - _dbus_verbose (" (policy) skipping allow rule since it doesn't apply to eavesdropping\n");
2009 + _dbus_verbose (" (policy) skipping %s rule since it doesn't apply to eavesdropping\n",
2010 + rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check");
2014 /* for deny, eavesdrop=true means the rule applies only when
2015 * eavesdropping; eavesdrop=false means always deny.
2017 - if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop)
2018 + if (!eavesdropping && rule->access == BUS_POLICY_RULE_ACCESS_DENY && rule->d.receive.eavesdrop)
2020 _dbus_verbose (" (policy) skipping deny rule since it only applies to eavesdropping\n");
2022 @@ -1162,13 +1209,14 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
2023 /* If it's a reply, the requested_reply flag kicks in */
2024 if (dbus_message_get_reply_serial (message) != 0)
2026 - /* for allow, requested_reply=true means the rule applies
2027 - * only when reply was requested. requested_reply=false means
2029 + /* for allow or check requested_reply=true means the rule applies
2030 + * only when reply was requested. requested_reply=false means the
2031 + * rule always applies
2033 - if (!requested_reply && rule->allow && rule->d.receive.requested_reply && !rule->d.receive.eavesdrop)
2034 + if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
2036 - _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
2037 + _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n",
2038 + rule->access == BUS_POLICY_RULE_ACCESS_DENY ? "allow" : "deny");
2042 @@ -1176,7 +1224,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
2043 * when the reply was not requested. requested_reply=true means the
2044 * rule always applies.
2046 - if (requested_reply && !rule->allow && !rule->d.receive.requested_reply)
2047 + if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.requested_reply)
2049 _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n");
2051 @@ -1199,13 +1247,13 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
2052 /* The interface is optional in messages. For allow rules, if the message
2053 * has no interface we want to skip the rule (and thus not allow);
2054 * for deny rules, if the message has no interface we want to use the
2055 - * rule (and thus deny).
2056 + * rule (and thus deny). Check rules are treated like allow rules.
2058 dbus_bool_t no_interface;
2060 no_interface = dbus_message_get_interface (message) == NULL;
2062 - if ((no_interface && rule->allow) ||
2063 + if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) ||
2065 strcmp (dbus_message_get_interface (message),
2066 rule->d.receive.interface) != 0))
2067 @@ -1295,14 +1343,43 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
2071 - allowed = rule->allow;
2072 + switch (rule->access)
2074 + case BUS_POLICY_RULE_ACCESS_ALLOW:
2075 + result = BUS_RESULT_TRUE;
2077 + case BUS_POLICY_RULE_ACCESS_DENY:
2079 + result = BUS_RESULT_FALSE;
2081 + case BUS_POLICY_RULE_ACCESS_CHECK:
2082 + result = BUS_RESULT_LATER;
2083 + privilege = rule->privilege;
2089 - _dbus_verbose (" (policy) used rule, allow now = %d\n",
2091 + _dbus_verbose (" (policy) used rule, result now = %d\n",
2092 + (int)(intptr_t)result);
2097 + if (result == BUS_RESULT_LATER)
2099 + BusContext *context = bus_connection_get_context(proposed_recipient);
2100 + BusCheck *check = bus_context_get_check(context);
2102 + result = bus_check_privilege(check, message, sender, addressed_recipient, proposed_recipient,
2103 + privilege, BUS_DEFERRED_MESSAGE_CHECK_RECEIVE, deferred_message);
2108 + if (privilege_param != NULL)
2109 + *privilege_param = privilege;
2115 @@ -1354,7 +1431,7 @@ bus_rules_check_can_own (DBusList *rules,
2119 - allowed = rule->allow;
2120 + allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW;
2124 diff --git a/bus/policy.h b/bus/policy.h
2125 index ec43ffa..f839d23 100644
2128 @@ -46,6 +46,14 @@ typedef enum
2129 BUS_POLICY_TRISTATE_TRUE
2130 } BusPolicyTristate;
2134 + BUS_POLICY_RULE_ACCESS_DENY,
2135 + BUS_POLICY_RULE_ACCESS_ALLOW,
2136 + /** runtime check resulting in allow or deny */
2137 + BUS_POLICY_RULE_ACCESS_CHECK
2138 +} BusPolicyRuleAccess;
2140 /** determines whether the rule affects a connection, or some global item */
2141 #define BUS_POLICY_RULE_IS_PER_CLIENT(rule) (!((rule)->type == BUS_POLICY_RULE_USER || \
2142 (rule)->type == BUS_POLICY_RULE_GROUP))
2143 @@ -56,8 +64,9 @@ struct BusPolicyRule
2145 BusPolicyRuleType type;
2147 - unsigned int allow : 1; /**< #TRUE if this allows, #FALSE if it denies */
2149 + unsigned int access : 2; /**< BusPolicyRuleAccess */
2150 + char *privilege; /**< for BUS_POLICY_RULE_ACCESS_CHECK */
2155 @@ -118,7 +127,7 @@ struct BusPolicyRule
2158 BusPolicyRule* bus_policy_rule_new (BusPolicyRuleType type,
2159 - dbus_bool_t allow);
2160 + BusPolicyRuleAccess access);
2161 BusPolicyRule* bus_policy_rule_ref (BusPolicyRule *rule);
2162 void bus_policy_rule_unref (BusPolicyRule *rule);
2164 @@ -152,21 +161,27 @@ dbus_bool_t bus_policy_merge (BusPolicy *policy,
2165 BusClientPolicy* bus_client_policy_new (void);
2166 BusClientPolicy* bus_client_policy_ref (BusClientPolicy *policy);
2167 void bus_client_policy_unref (BusClientPolicy *policy);
2168 -dbus_bool_t bus_client_policy_check_can_send (BusClientPolicy *policy,
2169 +BusResult bus_client_policy_check_can_send (DBusConnection *sender,
2170 + BusClientPolicy *policy,
2171 BusRegistry *registry,
2172 dbus_bool_t requested_reply,
2173 + DBusConnection *addressed_recipient,
2174 DBusConnection *receiver,
2175 DBusMessage *message,
2176 dbus_int32_t *toggles,
2177 - dbus_bool_t *log);
2178 -dbus_bool_t bus_client_policy_check_can_receive (BusClientPolicy *policy,
2180 + const char **privilege_param,
2181 + BusDeferredMessage **deferred_message);
2182 +BusResult bus_client_policy_check_can_receive (BusClientPolicy *policy,
2183 BusRegistry *registry,
2184 dbus_bool_t requested_reply,
2185 DBusConnection *sender,
2186 DBusConnection *addressed_recipient,
2187 DBusConnection *proposed_recipient,
2188 DBusMessage *message,
2189 - dbus_int32_t *toggles);
2190 + dbus_int32_t *toggles,
2191 + const char **privilege_param,
2192 + BusDeferredMessage **deferred_message);
2193 dbus_bool_t bus_client_policy_check_can_own (BusClientPolicy *policy,
2194 const DBusString *service_name);
2195 dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy,
2196 diff --git a/configure.ac b/configure.ac
2197 index d1e3a29..11b5ffd 100644
2200 @@ -1742,6 +1742,17 @@ AC_ARG_ENABLE([user-session],
2201 AM_CONDITIONAL([DBUS_ENABLE_USER_SESSION],
2202 [test "x$enable_user_session" = xyes])
2204 +#enable cynara integration
2205 +AC_ARG_ENABLE([cynara], [AS_HELP_STRING([--enable-cynara], [enable Cynara integration])], [], [enable_cynara=no])
2206 +if test "x$enable_cynara" = xyes; then
2207 + PKG_CHECK_MODULES([CYNARA], [cynara-client-async >= 0.6.0 cynara-session >= 0.6.0],
2208 + [AC_DEFINE([DBUS_ENABLE_CYNARA], [1], [Define to enable Cynara privilege checks in dbus-daemon])],
2209 + [AC_MSG_ERROR([libcynara-client-async and cynara-session are required to enable Cynara integration])])
2212 +AC_SUBST([CYNARA_CFLAGS])
2213 +AC_SUBST([CYNARA_LIBS])
2218 @@ -1824,6 +1835,7 @@ echo "
2219 Building bus stats API: ${enable_stats}
2220 Building SELinux support: ${have_selinux}
2221 Building AppArmor support: ${have_apparmor}
2222 + Building Cynara support: ${enable_cynara}
2223 Building inotify support: ${have_inotify}
2224 Building kqueue support: ${have_kqueue}
2225 Building systemd support: ${have_systemd}
2226 diff --git a/test/Makefile.am b/test/Makefile.am
2227 index af1e13b..e6f50e1 100644
2228 --- a/test/Makefile.am
2229 +++ b/test/Makefile.am
2230 @@ -439,6 +439,7 @@ in_data = \
2231 data/valid-config-files/debug-allow-all.conf.in \
2232 data/valid-config-files/finite-timeout.conf.in \
2233 data/valid-config-files/forbidding.conf.in \
2234 + data/valid-config-files/debug-check-some.conf.in \
2235 data/valid-config-files/incoming-limit.conf.in \
2236 data/valid-config-files/max-completed-connections.conf.in \
2237 data/valid-config-files/max-connections-per-user.conf.in \
2238 diff --git a/test/data/invalid-config-files/badcheck-1.conf b/test/data/invalid-config-files/badcheck-1.conf
2239 new file mode 100644
2240 index 0000000..fad9f50
2242 +++ b/test/data/invalid-config-files/badcheck-1.conf
2244 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2245 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2247 + <user>mybususer</user>
2248 + <listen>unix:path=/foo/bar</listen>
2249 + <policy context="default">
2250 + <allow privilege="foo" send_destination="*"/> <!-- extra privilege="foo" -->
2253 diff --git a/test/data/invalid-config-files/badcheck-2.conf b/test/data/invalid-config-files/badcheck-2.conf
2254 new file mode 100644
2255 index 0000000..63c7ef2
2257 +++ b/test/data/invalid-config-files/badcheck-2.conf
2259 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2260 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2262 + <user>mybususer</user>
2263 + <listen>unix:path=/foo/bar</listen>
2264 + <policy context="default">
2265 + <check send_destination="*"/> <!-- missing privilege="foo" -->
2268 diff --git a/test/data/valid-config-files/check-1.conf b/test/data/valid-config-files/check-1.conf
2269 new file mode 100644
2270 index 0000000..ad71473
2272 +++ b/test/data/valid-config-files/check-1.conf
2274 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2275 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2277 + <user>mybususer</user>
2278 + <listen>unix:path=/foo/bar</listen>
2279 + <policy context="default">
2280 + <check privilege="foo" send_destination="*"/>
2283 diff --git a/test/data/valid-config-files/debug-check-some.conf.in b/test/data/valid-config-files/debug-check-some.conf.in
2284 new file mode 100644
2285 index 0000000..47ee854
2287 +++ b/test/data/valid-config-files/debug-check-some.conf.in
2289 +<!-- Bus that listens on a debug pipe and doesn't create any restrictions -->
2291 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2292 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2294 + <listen>debug-pipe:name=test-server</listen>
2295 + <listen>@TEST_LISTEN@</listen>
2296 + <servicedir>@DBUS_TEST_DATA@/valid-service-files</servicedir>
2297 + <policy context="default">
2298 + <allow send_interface="*"/>
2299 + <allow receive_interface="*"/>
2303 + <deny send_interface="org.freedesktop.TestSuite" send_member="Echo"/>
2304 + <check privilege="foo" send_interface="org.freedesktop.TestSuite" send_member="Echo"/>