1 From 4dcfb02f17247ff9de966b62182cd2e08f301238 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 4/8] Integration of Cynara asynchronous security checks
6 This commit introduces basic framework for asynchronous policy
7 checks and Cynara integration code. Functions for checking security
8 policy can now return third value - BUS_RESULT_LATER denoting check
9 result unavailability. Whenever policy checker cannot decide on the
10 result of the check it is supposed to allocate DeferredMessage structure
11 that will be passed to the upper layers which can decide what should be
12 done in such situation.
13 Proper handling of such case will be implemented in subsequent commits.
14 Currently such return value results in message denial.
16 Change-Id: I9bcbce34577e5dc2a3cecf6233a0a2b0e43e1108
19 bus/bus.c | 134 +++++---
21 bus/check.c | 215 ++++++++++++
23 bus/config-parser-common.c | 6 +
24 bus/config-parser-common.h | 1 +
25 bus/config-parser.c | 71 +++-
26 bus/connection.c | 56 ++-
27 bus/connection.h | 5 +
28 bus/cynara.c | 374 +++++++++++++++++++++
30 bus/dispatch.c | 51 ++-
31 bus/policy.c | 193 +++++++----
34 test/Makefile.am | 1 +
35 test/data/invalid-config-files/badcheck-1.conf | 9 +
36 test/data/invalid-config-files/badcheck-2.conf | 9 +
37 test/data/valid-config-files/check-1.conf | 9 +
38 .../valid-config-files/debug-check-some.conf.in | 18 +
39 22 files changed, 1211 insertions(+), 180 deletions(-)
40 create mode 100644 bus/check.c
41 create mode 100644 bus/check.h
42 create mode 100644 bus/cynara.c
43 create mode 100644 bus/cynara.h
44 create mode 100644 test/data/invalid-config-files/badcheck-1.conf
45 create mode 100644 test/data/invalid-config-files/badcheck-2.conf
46 create mode 100644 test/data/valid-config-files/check-1.conf
47 create mode 100644 test/data/valid-config-files/debug-check-some.conf.in
49 diff --git a/bus/Makefile.am b/bus/Makefile.am
50 index f335e30..b057d6b 100644
53 @@ -7,6 +7,7 @@ DBUS_BUS_LIBS = \
60 DBUS_LAUNCHER_LIBS = \
61 @@ -21,6 +22,7 @@ AM_CPPFLAGS = \
62 -DDBUS_SYSTEM_CONFIG_FILE=\""$(configdir)/system.conf"\" \
68 # if assertions are enabled, improve backtraces
69 @@ -60,12 +62,16 @@ BUS_SOURCES= \
70 activation-exit-codes.h \
77 config-parser-common.c \
78 config-parser-common.h \
86 diff --git a/bus/bus.c b/bus/bus.c
87 index f0d980e..ac9ea8d 100644
93 #include "dir-watch.h"
95 #include <dbus/dbus-list.h>
96 #include <dbus/dbus-hash.h>
97 #include <dbus/dbus-credentials.h>
98 @@ -63,6 +64,7 @@ struct BusContext
99 BusRegistry *registry;
101 BusMatchmaker *matchmaker;
104 DBusRLimit *initial_fd_limit;
105 unsigned int fork : 1;
106 @@ -962,6 +964,10 @@ bus_context_new (const DBusString *config_file,
110 + context->check = bus_check_new(context, error);
111 + if (context->check == NULL)
114 dbus_server_free_data_slot (&server_data_slot);
117 @@ -1086,6 +1092,12 @@ bus_context_unref (BusContext *context)
119 bus_context_shutdown (context);
121 + if (context->check)
123 + bus_check_unref(context->check);
124 + context->check = NULL;
127 if (context->connections)
129 bus_connections_unref (context->connections);
130 @@ -1215,6 +1227,12 @@ bus_context_get_loop (BusContext *context)
131 return context->loop;
135 +bus_context_get_check (BusContext *context)
137 + return context->check;
141 bus_context_allow_unix_user (BusContext *context,
143 @@ -1386,6 +1404,7 @@ complain_about_message (BusContext *context,
144 DBusConnection *proposed_recipient,
145 dbus_bool_t requested_reply,
147 + const char *privilege,
150 DBusError stack_error = DBUS_ERROR_INIT;
151 @@ -1415,7 +1434,8 @@ complain_about_message (BusContext *context,
152 dbus_set_error (&stack_error, error_name,
153 "%s, %d matched rules; type=\"%s\", sender=\"%s\" (%s) "
154 "interface=\"%s\" member=\"%s\" error name=\"%s\" "
155 - "requested_reply=\"%d\" destination=\"%s\" (%s)",
156 + "requested_reply=\"%d\" destination=\"%s\" (%s) "
157 + "privilege=\"%s\"",
160 dbus_message_type_to_string (dbus_message_get_type (message)),
161 @@ -1426,7 +1446,8 @@ complain_about_message (BusContext *context,
162 nonnull (dbus_message_get_error_name (message), "(unset)"),
164 nonnull (dbus_message_get_destination (message), DBUS_SERVICE_DBUS),
165 - proposed_recipient_loginfo);
166 + proposed_recipient_loginfo,
167 + nonnull (privilege, "(n/a)"));
169 /* If we hit OOM while setting the error, this will syslog "out of memory"
170 * which is itself an indication that something is seriously wrong */
171 @@ -1450,14 +1471,15 @@ complain_about_message (BusContext *context,
172 * NULL for addressed_recipient may mean the bus driver, or may mean
173 * no destination was specified in the message (e.g. a signal).
176 -bus_context_check_security_policy (BusContext *context,
177 - BusTransaction *transaction,
178 - DBusConnection *sender,
179 - DBusConnection *addressed_recipient,
180 - DBusConnection *proposed_recipient,
181 - DBusMessage *message,
184 +bus_context_check_security_policy (BusContext *context,
185 + BusTransaction *transaction,
186 + DBusConnection *sender,
187 + DBusConnection *addressed_recipient,
188 + DBusConnection *proposed_recipient,
189 + DBusMessage *message,
191 + BusDeferredMessage **deferred_message)
194 BusClientPolicy *sender_policy;
195 @@ -1466,6 +1488,7 @@ bus_context_check_security_policy (BusContext *context,
198 dbus_bool_t requested_reply;
199 + const char *privilege;
201 type = dbus_message_get_type (message);
202 dest = dbus_message_get_destination (message);
203 @@ -1493,7 +1516,7 @@ bus_context_check_security_policy (BusContext *context,
204 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
205 "Message bus will not accept messages of unknown type\n");
208 + return BUS_RESULT_FALSE;
211 requested_reply = FALSE;
212 @@ -1517,11 +1540,11 @@ bus_context_check_security_policy (BusContext *context,
213 complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
214 "An SELinux policy prevents this sender from sending this "
215 "message to this recipient",
216 - 0, message, sender, proposed_recipient, FALSE, FALSE, error);
217 + 0, message, sender, proposed_recipient, FALSE, FALSE, NULL, error);
218 _dbus_verbose ("SELinux security check denying send to service\n");
222 + return BUS_RESULT_FALSE;
225 if (bus_connection_is_active (sender))
226 @@ -1547,7 +1570,7 @@ bus_context_check_security_policy (BusContext *context,
227 if (dbus_error_is_set (&error2))
229 dbus_move_error (&error2, error);
231 + return BUS_RESULT_FALSE;
235 @@ -1564,7 +1587,7 @@ bus_context_check_security_policy (BusContext *context,
237 _dbus_verbose ("security check allowing %s message\n",
240 + return BUS_RESULT_TRUE;
244 @@ -1575,7 +1598,7 @@ bus_context_check_security_policy (BusContext *context,
245 "Client tried to send a message other than %s without being registered",
249 + return BUS_RESULT_FALSE;
253 @@ -1624,20 +1647,29 @@ bus_context_check_security_policy (BusContext *context,
254 (proposed_recipient == NULL && recipient_policy == NULL));
257 - if (sender_policy &&
258 - !bus_client_policy_check_can_send (sender_policy,
261 - proposed_recipient,
262 - message, &toggles, &log))
264 - complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
265 - "Rejected send message", toggles,
266 - message, sender, proposed_recipient, requested_reply,
267 - (addressed_recipient == proposed_recipient), error);
268 - _dbus_verbose ("security policy disallowing message due to sender policy\n");
273 + BusResult res = bus_client_policy_check_can_send (sender,
277 + addressed_recipient,
278 + proposed_recipient,
279 + message, &toggles, &log, &privilege,
281 + if (res == BUS_RESULT_FALSE)
283 + complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
284 + "Rejected send message", toggles,
285 + message, sender, proposed_recipient, requested_reply,
286 + (addressed_recipient == proposed_recipient), privilege,
288 + _dbus_verbose ("security policy disallowing message due to sender policy\n");
289 + return BUS_RESULT_FALSE;
291 + else if (res == BUS_RESULT_LATER)
292 + return BUS_RESULT_LATER;
297 @@ -1646,23 +1678,29 @@ bus_context_check_security_policy (BusContext *context,
298 complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
299 "Would reject message", toggles,
300 message, sender, proposed_recipient, requested_reply,
302 + TRUE, privilege, NULL);
305 - if (recipient_policy &&
306 - !bus_client_policy_check_can_receive (recipient_policy,
310 - addressed_recipient, proposed_recipient,
311 - message, &toggles))
312 + if (recipient_policy)
314 - complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
315 - "Rejected receive message", toggles,
316 - message, sender, proposed_recipient, requested_reply,
317 - (addressed_recipient == proposed_recipient), error);
318 - _dbus_verbose ("security policy disallowing message due to recipient policy\n");
321 + res = bus_client_policy_check_can_receive (recipient_policy,
325 + addressed_recipient, proposed_recipient,
326 + message, &toggles, &privilege, deferred_message);
327 + if (res == BUS_RESULT_FALSE)
329 + complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected receive message",
330 + toggles, message, sender, proposed_recipient, requested_reply,
331 + (addressed_recipient == proposed_recipient), privilege, error);
333 + "security policy disallowing message due to recipient policy\n");
334 + return BUS_RESULT_FALSE;
336 + else if (res == BUS_RESULT_LATER)
337 + return BUS_RESULT_LATER;
340 /* See if limits on size have been exceeded */
341 @@ -1672,10 +1710,10 @@ bus_context_check_security_policy (BusContext *context,
343 complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED,
344 "Rejected: destination has a full message queue",
345 - 0, message, sender, proposed_recipient, requested_reply, TRUE,
346 + 0, message, sender, proposed_recipient, requested_reply, TRUE, NULL,
348 _dbus_verbose ("security policy disallowing message due to full message queue\n");
350 + return BUS_RESULT_FALSE;
353 /* Record that we will allow a reply here in the future (don't
354 @@ -1692,11 +1730,11 @@ bus_context_check_security_policy (BusContext *context,
357 _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
359 + return BUS_RESULT_FALSE;
362 _dbus_verbose ("security policy allowing message\n");
364 + return BUS_RESULT_TRUE;
368 diff --git a/bus/bus.h b/bus/bus.h
369 index dac6ea5..78084dd 100644
373 #include <dbus/dbus-pipe.h>
374 #include <dbus/dbus-sysdeps.h>
376 -typedef struct BusActivation BusActivation;
377 -typedef struct BusConnections BusConnections;
378 -typedef struct BusContext BusContext;
379 -typedef struct BusPolicy BusPolicy;
380 -typedef struct BusClientPolicy BusClientPolicy;
381 -typedef struct BusPolicyRule BusPolicyRule;
382 -typedef struct BusRegistry BusRegistry;
383 -typedef struct BusSELinuxID BusSELinuxID;
384 -typedef struct BusService BusService;
385 -typedef struct BusOwner BusOwner;
386 -typedef struct BusTransaction BusTransaction;
387 -typedef struct BusMatchmaker BusMatchmaker;
388 -typedef struct BusMatchRule BusMatchRule;
389 +typedef struct BusActivation BusActivation;
390 +typedef struct BusConnections BusConnections;
391 +typedef struct BusContext BusContext;
392 +typedef struct BusPolicy BusPolicy;
393 +typedef struct BusClientPolicy BusClientPolicy;
394 +typedef struct BusPolicyRule BusPolicyRule;
395 +typedef struct BusRegistry BusRegistry;
396 +typedef struct BusSELinuxID BusSELinuxID;
397 +typedef struct BusService BusService;
398 +typedef struct BusOwner BusOwner;
399 +typedef struct BusTransaction BusTransaction;
400 +typedef struct BusMatchmaker BusMatchmaker;
401 +typedef struct BusMatchRule BusMatchRule;
402 +typedef struct BusCheck BusCheck;
403 +typedef struct BusDeferredMessage BusDeferredMessage;
404 +typedef struct BusCynara BusCynara;
407 + * BusResult is defined as a pointer to a dummy structure to allow detection of type mismatches.
408 + * The disadvantage of such solution is that now BusResult variables cannot be used in switch
410 + * Additionally, BUS_RESULT_TRUE is defined as 0 instead of 1 to help detect type mismatches
413 +typedef const struct BusResultStruct { int dummy; } *BusResult;
415 +static const BusResult BUS_RESULT_TRUE = (BusResult)0x0;
416 +static const BusResult BUS_RESULT_FALSE = (BusResult)0x1;
417 +static const BusResult BUS_RESULT_LATER = (BusResult)0x2;
421 @@ -96,6 +112,7 @@ BusConnections* bus_context_get_connections (BusContext
422 BusActivation* bus_context_get_activation (BusContext *context);
423 BusMatchmaker* bus_context_get_matchmaker (BusContext *context);
424 DBusLoop* bus_context_get_loop (BusContext *context);
425 +BusCheck * bus_context_get_check (BusContext *context);
426 dbus_bool_t bus_context_allow_unix_user (BusContext *context,
428 dbus_bool_t bus_context_allow_windows_user (BusContext *context,
429 @@ -121,13 +138,14 @@ void bus_context_log (BusContext
430 DBusSystemLogSeverity severity,
433 -dbus_bool_t bus_context_check_security_policy (BusContext *context,
434 - BusTransaction *transaction,
435 - DBusConnection *sender,
436 - DBusConnection *addressed_recipient,
437 - DBusConnection *proposed_recipient,
438 - DBusMessage *message,
440 void bus_context_check_all_watches (BusContext *context);
441 +BusResult bus_context_check_security_policy (BusContext *context,
442 + BusTransaction *transaction,
443 + DBusConnection *sender,
444 + DBusConnection *addressed_recipient,
445 + DBusConnection *proposed_recipient,
446 + DBusMessage *message,
448 + BusDeferredMessage **deferred_message);
450 #endif /* BUS_BUS_H */
451 diff --git a/bus/check.c b/bus/check.c
453 index 0000000..d2f418a
457 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
458 +/* check.c Bus security policy runtime check
460 + * Copyright (C) 2014 Intel, Inc.
461 + * Copyright (c) 2014 Samsung Electronics, Ltd.
463 + * Licensed under the Academic Free License version 2.1
465 + * This program is free software; you can redistribute it and/or modify
466 + * it under the terms of the GNU General Public License as published by
467 + * the Free Software Foundation; either version 2 of the License, or
468 + * (at your option) any later version.
470 + * This program is distributed in the hope that it will be useful,
471 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
472 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
473 + * GNU General Public License for more details.
475 + * You should have received a copy of the GNU General Public License
476 + * along with this program; if not, write to the Free Software
477 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
483 +#include "connection.h"
484 +#include "dispatch.h"
487 +#include <dbus/dbus-connection-internal.h>
488 +#include <dbus/dbus-message-internal.h>
489 +#include <dbus/dbus-internals.h>
492 +typedef struct BusCheck
496 + BusContext *context;
500 +typedef struct BusDeferredMessage
504 + DBusMessage *message;
505 + DBusConnection *sender;
506 + DBusConnection *proposed_recipient;
507 + DBusConnection *addressed_recipient;
508 + dbus_bool_t full_dispatch;
509 + BusDeferredMessageStatus status;
510 + BusResult response;
511 + BusCheckResponseFunc response_callback;
512 +} BusDeferredMessage;
515 +bus_check_new (BusContext *context, DBusError *error)
519 + check = dbus_new(BusCheck, 1);
522 + BUS_SET_OOM(error);
526 + check->refcount = 1;
527 + check->context = context;
528 + check->cynara = bus_cynara_new(check, error);
529 + if (dbus_error_is_set(error))
539 +bus_check_ref (BusCheck *check)
541 + _dbus_assert (check->refcount > 0);
542 + check->refcount += 1;
548 +bus_check_unref (BusCheck *check)
550 + _dbus_assert (check->refcount > 0);
552 + check->refcount -= 1;
554 + if (check->refcount == 0)
556 + bus_cynara_unref(check->cynara);
562 +bus_check_get_context (BusCheck *check)
564 + return check->context;
568 +bus_check_get_cynara (BusCheck *check)
570 + return check->cynara;
574 +bus_check_privilege (BusCheck *check,
575 + DBusMessage *message,
576 + DBusConnection *sender,
577 + DBusConnection *addressed_recipient,
578 + DBusConnection *proposed_recipient,
579 + const char *privilege,
580 + BusDeferredMessageStatus check_type,
581 + BusDeferredMessage **deferred_message)
583 + BusResult result = BUS_RESULT_FALSE;
585 + DBusConnection *connection;
587 + connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
589 + if (!dbus_connection_get_is_connected(connection))
591 + return BUS_RESULT_FALSE;
594 + /* ask policy checkers */
595 +#ifdef DBUS_ENABLE_CYNARA
596 + cynara = bus_check_get_cynara(check);
597 + result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient,
598 + proposed_recipient, privilege, check_type, deferred_message);
601 + if (result == BUS_RESULT_LATER && deferred_message != NULL)
603 + (*deferred_message)->status |= check_type;
608 +BusDeferredMessage *bus_deferred_message_new (DBusMessage *message,
609 + DBusConnection *sender,
610 + DBusConnection *addressed_recipient,
611 + DBusConnection *proposed_recipient,
612 + BusResult response)
614 + BusDeferredMessage *deferred_message;
616 + deferred_message = dbus_new(BusDeferredMessage, 1);
617 + if (deferred_message == NULL)
622 + deferred_message->refcount = 1;
623 + deferred_message->sender = sender != NULL ? dbus_connection_ref(sender) : NULL;
624 + deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL;
625 + deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL;
626 + deferred_message->message = dbus_message_ref(message);
627 + deferred_message->response = response;
628 + deferred_message->status = 0;
629 + deferred_message->full_dispatch = FALSE;
630 + deferred_message->response_callback = NULL;
632 + return deferred_message;
635 +BusDeferredMessage *
636 +bus_deferred_message_ref (BusDeferredMessage *deferred_message)
638 + _dbus_assert (deferred_message->refcount > 0);
639 + deferred_message->refcount += 1;
640 + return deferred_message;
644 +bus_deferred_message_unref (BusDeferredMessage *deferred_message)
646 + _dbus_assert (deferred_message->refcount > 0);
648 + deferred_message->refcount -= 1;
650 + if (deferred_message->refcount == 0)
652 + dbus_message_unref(deferred_message->message);
653 + if (deferred_message->sender != NULL)
654 + dbus_connection_unref(deferred_message->sender);
655 + if (deferred_message->addressed_recipient != NULL)
656 + dbus_connection_unref(deferred_message->addressed_recipient);
657 + if (deferred_message->proposed_recipient != NULL)
658 + dbus_connection_unref(deferred_message->proposed_recipient);
659 + dbus_free(deferred_message);
664 +bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
667 + if (deferred_message->response_callback != NULL)
669 + deferred_message->response_callback(deferred_message, result);
672 diff --git a/bus/check.h b/bus/check.h
674 index 0000000..c3fcaf9
678 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
679 +/* check.h Bus security policy runtime check
681 + * Copyright (C) 2014 Intel, Inc.
682 + * Copyright (c) 2014 Samsung Electronics, Ltd.
684 + * Licensed under the Academic Free License version 2.1
686 + * This program is free software; you can redistribute it and/or modify
687 + * it under the terms of the GNU General Public License as published by
688 + * the Free Software Foundation; either version 2 of the License, or
689 + * (at your option) any later version.
691 + * This program is distributed in the hope that it will be useful,
692 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
693 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
694 + * GNU General Public License for more details.
696 + * You should have received a copy of the GNU General Public License
697 + * along with this program; if not, write to the Free Software
698 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
709 +typedef void (*BusCheckResponseFunc) (BusDeferredMessage *message,
713 + BUS_DEFERRED_MESSAGE_CHECK_SEND = 1 << 0,
714 + BUS_DEFERRED_MESSAGE_CHECK_RECEIVE = 1 << 1,
715 + BUS_DEFERRED_MESSAGE_CHECK_OWN = 1 << 2,
716 +} BusDeferredMessageStatus;
719 +BusCheck *bus_check_new (BusContext *context,
721 +BusCheck *bus_check_ref (BusCheck *check);
722 +void bus_check_unref (BusCheck *check);
724 +BusContext *bus_check_get_context (BusCheck *check);
725 +BusCynara *bus_check_get_cynara (BusCheck *check);
726 +BusResult bus_check_privilege (BusCheck *check,
727 + DBusMessage *message,
728 + DBusConnection *sender,
729 + DBusConnection *addressed_recipient,
730 + DBusConnection *proposed_recipient,
731 + const char *privilege,
732 + BusDeferredMessageStatus check_type,
733 + BusDeferredMessage **deferred_message);
735 +BusDeferredMessage *bus_deferred_message_new (DBusMessage *message,
736 + DBusConnection *sender,
737 + DBusConnection *addressed_recipient,
738 + DBusConnection *proposed_recipient,
739 + BusResult response);
741 +BusDeferredMessage *bus_deferred_message_ref (BusDeferredMessage *deferred_message);
742 +void bus_deferred_message_unref (BusDeferredMessage *deferred_message);
743 +void bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
745 +#endif /* BUS_CHECK_H */
746 diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c
747 index c522ff4..1cfe4c8 100644
748 --- a/bus/config-parser-common.c
749 +++ b/bus/config-parser-common.c
750 @@ -75,6 +75,10 @@ bus_config_parser_element_name_to_type (const char *name)
754 + else if (strcmp (name, "check") == 0)
756 + return ELEMENT_CHECK;
758 else if (strcmp (name, "servicehelper") == 0)
760 return ELEMENT_SERVICEHELPER;
761 @@ -155,6 +159,8 @@ bus_config_parser_element_type_to_name (ElementType type)
765 + case ELEMENT_CHECK:
769 case ELEMENT_PIDFILE:
770 diff --git a/bus/config-parser-common.h b/bus/config-parser-common.h
771 index 186bf4c..bff6fdb 100644
772 --- a/bus/config-parser-common.h
773 +++ b/bus/config-parser-common.h
774 @@ -36,6 +36,7 @@ typedef enum
782 diff --git a/bus/config-parser.c b/bus/config-parser.c
783 index ee2d4e7..73c9e6f 100644
784 --- a/bus/config-parser.c
785 +++ b/bus/config-parser.c
786 @@ -1150,7 +1150,7 @@ append_rule_from_element (BusConfigParser *parser,
787 const char *element_name,
788 const char **attribute_names,
789 const char **attribute_values,
791 + BusPolicyRuleAccess access,
795 @@ -1173,6 +1173,7 @@ append_rule_from_element (BusConfigParser *parser,
796 const char *own_prefix;
799 + const char *privilege;
803 @@ -1200,6 +1201,7 @@ append_rule_from_element (BusConfigParser *parser,
807 + "privilege", &privilege,
811 @@ -1208,6 +1210,7 @@ append_rule_from_element (BusConfigParser *parser,
812 receive_interface || receive_member || receive_error || receive_sender ||
813 receive_type || receive_path || eavesdrop ||
814 send_requested_reply || receive_requested_reply ||
816 own || own_prefix || user || group))
818 dbus_set_error (error, DBUS_ERROR_FAILED,
819 @@ -1224,7 +1227,30 @@ append_rule_from_element (BusConfigParser *parser,
825 + if (access == BUS_POLICY_RULE_ACCESS_CHECK)
827 + if (privilege == NULL || !*privilege)
829 + dbus_set_error (error, DBUS_ERROR_FAILED,
830 + "On element <%s>, you must specify the privilege to be checked.",
837 + if (privilege != NULL && *privilege)
839 + dbus_set_error (error, DBUS_ERROR_FAILED,
840 + "On element <%s>, privilege %s is used outside of a check rule.",
841 + element_name, privilege);
845 + privilege = NULL; /* replace (potentially) empty string with NULL pointer, it wouldn't be used anyway */
848 /* Allowed combinations of elements are:
850 * base, must be all send or all receive:
851 @@ -1398,7 +1424,7 @@ append_rule_from_element (BusConfigParser *parser,
855 - rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow);
856 + rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, access);
860 @@ -1480,7 +1506,7 @@ append_rule_from_element (BusConfigParser *parser,
864 - rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow);
865 + rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, access);
869 @@ -1510,7 +1536,7 @@ append_rule_from_element (BusConfigParser *parser,
871 else if (own || own_prefix)
873 - rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow);
874 + rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, access);
878 @@ -1536,7 +1562,7 @@ append_rule_from_element (BusConfigParser *parser,
880 if (IS_WILDCARD (user))
882 - rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
883 + rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access);
887 @@ -1551,7 +1577,7 @@ append_rule_from_element (BusConfigParser *parser,
889 if (_dbus_parse_unix_user_from_config (&username, &uid))
891 - rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
892 + rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access);
896 @@ -1568,7 +1594,7 @@ append_rule_from_element (BusConfigParser *parser,
898 if (IS_WILDCARD (group))
900 - rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
901 + rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access);
905 @@ -1583,7 +1609,7 @@ append_rule_from_element (BusConfigParser *parser,
907 if (_dbus_parse_unix_group_from_config (&groupname, &gid))
909 - rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
910 + rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access);
914 @@ -1607,6 +1633,10 @@ append_rule_from_element (BusConfigParser *parser,
915 _dbus_assert (pe != NULL);
916 _dbus_assert (pe->type == ELEMENT_POLICY);
918 + rule->privilege = _dbus_strdup (privilege);
919 + if (privilege && !rule->privilege)
922 switch (pe->d.policy.type)
925 @@ -1681,7 +1711,7 @@ start_policy_child (BusConfigParser *parser,
927 if (!append_rule_from_element (parser, element_name,
928 attribute_names, attribute_values,
930 + BUS_POLICY_RULE_ACCESS_ALLOW, error))
933 if (push_element (parser, ELEMENT_ALLOW) == NULL)
934 @@ -1696,7 +1726,7 @@ start_policy_child (BusConfigParser *parser,
936 if (!append_rule_from_element (parser, element_name,
937 attribute_names, attribute_values,
939 + BUS_POLICY_RULE_ACCESS_DENY, error))
942 if (push_element (parser, ELEMENT_DENY) == NULL)
943 @@ -1707,6 +1737,21 @@ start_policy_child (BusConfigParser *parser,
947 + else if (strcmp (element_name, "check") == 0)
949 + if (!append_rule_from_element (parser, element_name,
950 + attribute_names, attribute_values,
951 + BUS_POLICY_RULE_ACCESS_CHECK, error))
954 + if (push_element (parser, ELEMENT_CHECK) == NULL)
956 + BUS_SET_OOM (error);
964 dbus_set_error (error, DBUS_ERROR_FAILED,
965 @@ -2066,6 +2111,7 @@ bus_config_parser_end_element (BusConfigParser *parser,
969 + case ELEMENT_CHECK:
972 case ELEMENT_KEEP_UMASK:
973 @@ -2365,6 +2411,7 @@ bus_config_parser_content (BusConfigParser *parser,
977 + case ELEMENT_CHECK:
980 case ELEMENT_KEEP_UMASK:
981 @@ -2829,6 +2876,8 @@ do_load (const DBusString *full_path,
982 dbus_error_init (&error);
984 parser = bus_config_load (full_path, TRUE, NULL, &error);
985 + if (dbus_error_is_set (&error))
986 + _dbus_verbose ("Failed to load file: %s\n", error.message);
989 _DBUS_ASSERT_ERROR_IS_SET (&error);
990 diff --git a/bus/connection.c b/bus/connection.c
991 index 7107434..a6d87e5 100644
992 --- a/bus/connection.c
993 +++ b/bus/connection.c
995 #include <dbus/dbus-hash.h>
996 #include <dbus/dbus-timeout.h>
997 #include <dbus/dbus-connection-internal.h>
998 +#ifdef DBUS_ENABLE_CYNARA
1000 +#include <cynara-session.h>
1003 /* Trim executed commands to this length; we want to keep logs readable */
1004 #define MAX_LOG_COMMAND_LEN 50
1005 @@ -105,6 +109,9 @@ typedef struct
1007 int n_pending_unix_fds;
1008 DBusTimeout *pending_unix_fds_timeout;
1009 +#ifdef DBUS_ENABLE_CYNARA
1010 + char *cynara_session_id;
1012 } BusConnectionData;
1014 static dbus_bool_t bus_pending_reply_expired (BusExpireList *list,
1015 @@ -118,8 +125,8 @@ static dbus_bool_t expire_incomplete_timeout (void *data);
1017 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
1020 -connection_get_loop (DBusConnection *connection)
1022 +bus_connection_get_loop (DBusConnection *connection)
1024 BusConnectionData *d;
1026 @@ -331,7 +338,7 @@ add_connection_watch (DBusWatch *watch,
1028 DBusConnection *connection = data;
1030 - return _dbus_loop_add_watch (connection_get_loop (connection), watch);
1031 + return _dbus_loop_add_watch (bus_connection_get_loop (connection), watch);
1035 @@ -340,7 +347,7 @@ remove_connection_watch (DBusWatch *watch,
1037 DBusConnection *connection = data;
1039 - _dbus_loop_remove_watch (connection_get_loop (connection), watch);
1040 + _dbus_loop_remove_watch (bus_connection_get_loop (connection), watch);
1044 @@ -349,7 +356,7 @@ toggle_connection_watch (DBusWatch *watch,
1046 DBusConnection *connection = data;
1048 - _dbus_loop_toggle_watch (connection_get_loop (connection), watch);
1049 + _dbus_loop_toggle_watch (bus_connection_get_loop (connection), watch);
1053 @@ -358,7 +365,7 @@ add_connection_timeout (DBusTimeout *timeout,
1055 DBusConnection *connection = data;
1057 - return _dbus_loop_add_timeout (connection_get_loop (connection), timeout);
1058 + return _dbus_loop_add_timeout (bus_connection_get_loop (connection), timeout);
1062 @@ -367,7 +374,7 @@ remove_connection_timeout (DBusTimeout *timeout,
1064 DBusConnection *connection = data;
1066 - _dbus_loop_remove_timeout (connection_get_loop (connection), timeout);
1067 + _dbus_loop_remove_timeout (bus_connection_get_loop (connection), timeout);
1071 @@ -425,6 +432,10 @@ free_connection_data (void *data)
1073 dbus_free (d->name);
1075 +#ifdef DBUS_ENABLE_CYNARA
1076 + free (d->cynara_session_id);
1082 @@ -984,6 +995,22 @@ bus_connection_get_policy (DBusConnection *connection)
1086 +#ifdef DBUS_ENABLE_CYNARA
1087 +const char *bus_connection_get_cynara_session_id (DBusConnection *connection)
1089 + BusConnectionData *d = BUS_CONNECTION_DATA (connection);
1090 + _dbus_assert (d != NULL);
1092 + if (d->cynara_session_id == NULL)
1094 + unsigned long pid;
1095 + if (dbus_connection_get_unix_process_id(connection, &pid))
1096 + d->cynara_session_id = cynara_session_from_pid(pid);
1098 + return d->cynara_session_id;
1103 foreach_active (BusConnections *connections,
1104 BusConnectionForeachFunction function,
1105 @@ -2104,6 +2131,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
1106 DBusConnection *connection,
1107 DBusMessage *message)
1110 /* We have to set the sender to the driver, and have
1111 * to check security policy since it was not done in
1113 @@ -2132,10 +2160,18 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
1114 /* If security policy doesn't allow the message, we silently
1115 * eat it; the driver doesn't care about getting a reply.
1117 - if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
1119 - NULL, connection, connection, message, NULL))
1120 + res = bus_context_check_security_policy (bus_transaction_get_context (transaction),
1122 + NULL, connection, connection, message, NULL,
1125 + if (res == BUS_RESULT_FALSE)
1127 + else if (res == BUS_RESULT_LATER)
1129 + _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n");
1133 return bus_transaction_send (transaction, connection, message);
1135 diff --git a/bus/connection.h b/bus/connection.h
1136 index 6fbcd38..7433746 100644
1137 --- a/bus/connection.h
1138 +++ b/bus/connection.h
1140 typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection,
1143 +DBusLoop* bus_connection_get_loop (DBusConnection *connection);
1145 BusConnections* bus_connections_new (BusContext *context);
1146 BusConnections* bus_connections_ref (BusConnections *connections);
1147 @@ -116,6 +117,10 @@ dbus_bool_t bus_connection_get_unix_groups (DBusConnection *connecti
1149 BusClientPolicy* bus_connection_get_policy (DBusConnection *connection);
1151 +#ifdef DBUS_ENABLE_CYNARA
1152 +const char *bus_connection_get_cynara_session_id (DBusConnection *connection);
1155 /* transaction API so we can send or not send a block of messages as a whole */
1157 typedef void (* BusTransactionCancelFunction) (void *data);
1158 diff --git a/bus/cynara.c b/bus/cynara.c
1159 new file mode 100644
1160 index 0000000..57a4c45
1164 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1165 +/* cynara.c Cynara runtime privilege checking
1167 + * Copyright (c) 2014 Samsung Electronics, Ltd.
1169 + * Licensed under the Academic Free License version 2.1
1171 + * This program is free software; you can redistribute it and/or modify
1172 + * it under the terms of the GNU General Public License as published by
1173 + * the Free Software Foundation; either version 2 of the License, or
1174 + * (at your option) any later version.
1176 + * This program is distributed in the hope that it will be useful,
1177 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1178 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1179 + * GNU General Public License for more details.
1181 + * You should have received a copy of the GNU General Public License
1182 + * along with this program; if not, write to the Free Software
1183 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1187 +#include <config.h>
1188 +#include "cynara.h"
1194 +#include <dbus/dbus.h>
1195 +#include <dbus/dbus-watch.h>
1196 +#include <dbus/dbus-connection-internal.h>
1197 +#include <bus/connection.h>
1198 +#ifdef DBUS_ENABLE_CYNARA
1199 +#include <cynara-client-async.h>
1203 +#ifdef DBUS_ENABLE_CYNARA
1204 +typedef struct BusCynara
1208 + BusContext *context;
1210 + cynara_async *cynara;
1211 + DBusWatch *cynara_watch;
1214 +#define USE_CYNARA_CACHE 1
1215 +#ifdef USE_CYNARA_CACHE
1216 +#define CYNARA_CACHE_SIZE 1000
1219 +static dbus_bool_t bus_cynara_watch_callback(DBusWatch *watch,
1220 + unsigned int flags,
1223 +static void status_callback(int old_fd,
1225 + cynara_async_status status,
1226 + void *user_status_data);
1227 +static void bus_cynara_check_response_callback (cynara_check_id check_id,
1228 + cynara_async_call_cause cause,
1230 + void *user_response_data);
1235 +bus_cynara_new(BusCheck *check, DBusError *error)
1237 +#ifdef DBUS_ENABLE_CYNARA
1238 + BusContext *context;
1239 + BusCynara *cynara;
1240 + cynara_async_configuration *conf = NULL;
1243 + cynara = dbus_new(BusCynara, 1);
1244 + if (cynara == NULL)
1246 + BUS_SET_OOM(error);
1250 + context = bus_check_get_context(check);
1252 + cynara->refcount = 1;
1253 + cynara->check = check;
1254 + cynara->context = context;
1255 + cynara->cynara_watch = NULL;
1257 + ret = cynara_async_configuration_create(&conf);
1258 + if (ret != CYNARA_API_SUCCESS)
1260 + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to create Cynara configuration");
1264 +#ifdef CYNARA_CACHE_SIZE
1265 + ret = cynara_async_configuration_set_cache_size(conf, CYNARA_CACHE_SIZE);
1266 + if (ret != CYNARA_API_SUCCESS)
1268 + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to Cynara cache size");
1273 + ret = cynara_async_initialize(&cynara->cynara, conf, &status_callback, cynara);
1274 + if (ret != CYNARA_API_SUCCESS)
1276 + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to initialize Cynara client");
1281 + cynara_async_configuration_destroy(conf);
1282 + if (ret != CYNARA_API_SUCCESS)
1284 + dbus_free(cynara);
1295 +bus_cynara_ref (BusCynara *cynara)
1297 +#ifdef DBUS_ENABLE_CYNARA
1298 + _dbus_assert (cynara->refcount > 0);
1299 + cynara->refcount += 1;
1308 +bus_cynara_unref (BusCynara *cynara)
1310 +#ifdef DBUS_ENABLE_CYNARA
1311 + _dbus_assert (cynara->refcount > 0);
1313 + cynara->refcount -= 1;
1315 + if (cynara->refcount == 0)
1317 + cynara_async_finish(cynara->cynara);
1318 + dbus_free(cynara);
1324 +bus_cynara_check_privilege (BusCynara *cynara,
1325 + DBusMessage *message,
1326 + DBusConnection *sender,
1327 + DBusConnection *addressed_recipient,
1328 + DBusConnection *proposed_recipient,
1329 + const char *privilege,
1330 + BusDeferredMessageStatus check_type,
1331 + BusDeferredMessage **deferred_message_param)
1333 +#ifdef DBUS_ENABLE_CYNARA
1335 + unsigned long uid;
1337 + const char *session_id;
1339 + cynara_check_id check_id;
1340 + DBusConnection *connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
1341 + BusDeferredMessage *deferred_message;
1344 + _dbus_assert(connection != NULL);
1346 + if (dbus_connection_get_unix_user(connection, &uid) == FALSE)
1347 + return BUS_RESULT_FALSE;
1349 + if (_dbus_connection_get_linux_security_label(connection, &label) == FALSE || label == NULL)
1351 + _dbus_warn("Failed to obtain security label for connection\n");
1352 + return BUS_RESULT_FALSE;
1355 + session_id = bus_connection_get_cynara_session_id (connection);
1356 + if (session_id == NULL)
1358 + ret = BUS_RESULT_FALSE;
1362 + snprintf(user, sizeof(user), "%lu", uid);
1364 +#if USE_CYNARA_CACHE
1365 + result = cynara_async_check_cache(cynara->cynara, label, session_id, user, privilege);
1367 + result = CYNARA_API_CACHE_MISS;
1372 + case CYNARA_API_ACCESS_ALLOWED:
1373 + _dbus_verbose("Cynara: got ALLOWED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n",
1374 + label, session_id, user, privilege);
1375 + ret = BUS_RESULT_TRUE;
1378 + case CYNARA_API_ACCESS_DENIED:
1379 + _dbus_verbose("Cynara: got DENIED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n",
1380 + label, session_id, user, privilege);
1381 + ret = BUS_RESULT_FALSE;
1384 + case CYNARA_API_CACHE_MISS:
1385 + deferred_message = bus_deferred_message_new(message, sender, addressed_recipient,
1386 + proposed_recipient, BUS_RESULT_LATER);
1387 + if (deferred_message == NULL)
1389 + _dbus_verbose("Failed to allocate memory for deferred message\n");
1390 + ret = BUS_RESULT_FALSE;
1394 + /* callback is supposed to unref deferred_message*/
1395 + result = cynara_async_create_request(cynara->cynara, label, session_id, user, privilege, &check_id,
1396 + &bus_cynara_check_response_callback, deferred_message);
1397 + if (result == CYNARA_API_SUCCESS)
1399 + _dbus_verbose("Created Cynara request: client=%s session_id=%s user=%s privilege=%s check_id=%u "
1400 + "deferred_message=%p\n", label, session_id, user, privilege, (unsigned int)check_id, deferred_message);
1401 + if (deferred_message_param != NULL)
1402 + *deferred_message_param = deferred_message;
1403 + ret = BUS_RESULT_LATER;
1407 + _dbus_verbose("Error on cynara request create: %i\n", result);
1408 + bus_deferred_message_unref(deferred_message);
1409 + ret = BUS_RESULT_FALSE;
1413 + _dbus_verbose("Error when accessing Cynara cache: %i\n", result);
1414 + ret = BUS_RESULT_FALSE;
1421 + return BUS_RESULT_FALSE;
1427 +#ifdef DBUS_ENABLE_CYNARA
1429 +status_callback(int old_fd, int new_fd, cynara_async_status status,
1430 + void *user_status_data)
1432 + BusCynara *cynara = (BusCynara *)user_status_data;
1433 + DBusLoop *loop = bus_context_get_loop(cynara->context);
1435 + if (cynara->cynara_watch != NULL)
1437 + _dbus_loop_remove_watch(loop, cynara->cynara_watch);
1438 + _dbus_watch_invalidate(cynara->cynara_watch);
1439 + _dbus_watch_unref(cynara->cynara_watch);
1440 + cynara->cynara_watch = NULL;
1445 + unsigned int flags;
1450 + case CYNARA_STATUS_FOR_READ:
1451 + flags = DBUS_WATCH_READABLE;
1453 + case CYNARA_STATUS_FOR_RW:
1454 + flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE;
1457 + /* Cynara passed unknown status - warn and add RW watch */
1458 + _dbus_verbose("Cynara passed unknown status value: 0x%08X\n", (unsigned int)status);
1459 + flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE;
1463 + watch = _dbus_watch_new(new_fd, flags, TRUE, &bus_cynara_watch_callback, cynara, NULL);
1464 + if (watch != NULL)
1466 + if (_dbus_loop_add_watch(loop, watch) == TRUE)
1468 + cynara->cynara_watch = watch;
1472 + _dbus_watch_invalidate(watch);
1473 + _dbus_watch_unref(watch);
1476 + /* It seems like not much can be done at this point. Cynara events won't be processed
1477 + * until next Cynara function call triggering status callback */
1478 + _dbus_verbose("Failed to add dbus watch\n");
1483 +bus_cynara_watch_callback(DBusWatch *watch,
1484 + unsigned int flags,
1487 + BusCynara *cynara = (BusCynara *)data;
1488 + int result = cynara_async_process(cynara->cynara);
1489 + if (result != CYNARA_API_SUCCESS)
1490 + _dbus_verbose("cynara_async_process returned %d\n", result);
1492 + return result != CYNARA_API_OUT_OF_MEMORY ? TRUE : FALSE;
1495 +static inline const char *
1496 +call_cause_to_string(cynara_async_call_cause cause)
1500 + case CYNARA_CALL_CAUSE_ANSWER:
1502 + case CYNARA_CALL_CAUSE_CANCEL:
1504 + case CYNARA_CALL_CAUSE_FINISH:
1506 + case CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE:
1507 + return "SERVICE NOT AVAILABLE";
1514 +bus_cynara_check_response_callback (cynara_check_id check_id,
1515 + cynara_async_call_cause cause,
1517 + void *user_response_data)
1519 + BusDeferredMessage *deferred_message = user_response_data;
1522 + _dbus_verbose("Cynara callback: check_id=%u, cause=%s response=%i response_data=%p\n",
1523 + (unsigned int)check_id, call_cause_to_string(cause), response, user_response_data);
1525 + if (deferred_message == NULL)
1528 + if (cause == CYNARA_CALL_CAUSE_ANSWER && response == CYNARA_API_ACCESS_ALLOWED)
1529 + result = BUS_RESULT_TRUE;
1531 + result = BUS_RESULT_FALSE;
1533 + bus_deferred_message_response_received(deferred_message, result);
1534 + bus_deferred_message_unref(deferred_message);
1537 +#endif /* DBUS_ENABLE_CYNARA */
1538 diff --git a/bus/cynara.h b/bus/cynara.h
1539 new file mode 100644
1540 index 0000000..c4728bb
1544 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1545 +/* cynara.h Cynara runtime privilege checking
1547 + * Copyright (c) 2014 Samsung Electronics, Ltd.
1549 + * Licensed under the Academic Free License version 2.1
1551 + * This program is free software; you can redistribute it and/or modify
1552 + * it under the terms of the GNU General Public License as published by
1553 + * the Free Software Foundation; either version 2 of the License, or
1554 + * (at your option) any later version.
1556 + * This program is distributed in the hope that it will be useful,
1557 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1558 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1559 + * GNU General Public License for more details.
1561 + * You should have received a copy of the GNU General Public License
1562 + * along with this program; if not, write to the Free Software
1563 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1570 +BusCynara *bus_cynara_new (BusCheck *check, DBusError *error);
1571 +BusCynara *bus_cynara_ref (BusCynara *cynara);
1572 +void bus_cynara_unref (BusCynara *cynara);
1573 +BusResult bus_cynara_check_privilege (BusCynara *cynara,
1574 + DBusMessage *message,
1575 + DBusConnection *sender,
1576 + DBusConnection *addressed_recipient,
1577 + DBusConnection *proposed_recipient,
1578 + const char *privilege,
1579 + BusDeferredMessageStatus check_type,
1580 + BusDeferredMessage **deferred_message);
1581 diff --git a/bus/dispatch.c b/bus/dispatch.c
1582 index 7a61953..ce4076d 100644
1583 --- a/bus/dispatch.c
1584 +++ b/bus/dispatch.c
1588 #include "dispatch.h"
1590 #include "connection.h"
1592 #include "services.h"
1593 @@ -56,13 +57,14 @@ send_one_message (DBusConnection *connection,
1594 BusTransaction *transaction,
1597 - if (!bus_context_check_security_policy (context, transaction,
1599 - addressed_recipient,
1603 - return TRUE; /* silently don't send it */
1604 + BusDeferredMessage *deferred_message;
1607 + result = bus_context_check_security_policy (context, transaction, sender, addressed_recipient,
1608 + connection, message, NULL, &deferred_message);
1610 + if (result != BUS_RESULT_TRUE)
1611 + return TRUE; /* silently don't send it */
1613 if (dbus_message_contains_unix_fds(message) &&
1614 !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD))
1615 @@ -92,6 +94,7 @@ bus_dispatch_matches (BusTransaction *transaction,
1616 BusMatchmaker *matchmaker;
1618 BusContext *context;
1619 + BusDeferredMessage *deferred_message;
1621 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1623 @@ -107,11 +110,21 @@ bus_dispatch_matches (BusTransaction *transaction,
1624 /* First, send the message to the addressed_recipient, if there is one. */
1625 if (addressed_recipient != NULL)
1627 - if (!bus_context_check_security_policy (context, transaction,
1628 - sender, addressed_recipient,
1629 - addressed_recipient,
1632 + res = bus_context_check_security_policy (context, transaction,
1633 + sender, addressed_recipient,
1634 + addressed_recipient,
1636 + &deferred_message);
1637 + if (res == BUS_RESULT_FALSE)
1639 + else if (res == BUS_RESULT_LATER)
1641 + dbus_set_error (error,
1642 + DBUS_ERROR_ACCESS_DENIED,
1643 + "Rejecting message because time is needed to check security policy");
1647 if (dbus_message_contains_unix_fds (message) &&
1648 !dbus_connection_can_send_type (addressed_recipient,
1649 @@ -273,12 +286,24 @@ bus_dispatch (DBusConnection *connection,
1651 strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
1653 - if (!bus_context_check_security_policy (context, transaction,
1654 - connection, NULL, NULL, message, &error))
1655 + BusDeferredMessage *deferred_message;
1657 + res = bus_context_check_security_policy (context, transaction,
1658 + connection, NULL, NULL, message, &error,
1659 + &deferred_message);
1660 + if (res == BUS_RESULT_FALSE)
1662 _dbus_verbose ("Security policy rejected message\n");
1665 + else if (res == BUS_RESULT_LATER)
1667 + dbus_set_error (&error,
1668 + DBUS_ERROR_ACCESS_DENIED,
1669 + "Rejecting message because time is needed to check security policy");
1670 + _dbus_verbose ("Security policy needs time to check policy. Dropping message\n");
1674 _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
1675 if (!bus_driver_handle_message (connection, transaction, message, &error))
1676 diff --git a/bus/policy.c b/bus/policy.c
1677 index 082f385..ec888df 100644
1686 #include "services.h"
1691 bus_policy_rule_new (BusPolicyRuleType type,
1692 - dbus_bool_t allow)
1693 + BusPolicyRuleAccess access)
1695 BusPolicyRule *rule;
1697 @@ -42,7 +43,7 @@ bus_policy_rule_new (BusPolicyRuleType type,
1701 - rule->allow = allow;
1702 + rule->access = access;
1706 @@ -54,18 +55,19 @@ bus_policy_rule_new (BusPolicyRuleType type,
1708 case BUS_POLICY_RULE_SEND:
1709 rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID;
1711 /* allow rules default to TRUE (only requested replies allowed)
1712 + * check rules default to TRUE (only requested replies are checked)
1713 * deny rules default to FALSE (only unrequested replies denied)
1715 - rule->d.send.requested_reply = rule->allow;
1716 + rule->d.send.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY;
1718 case BUS_POLICY_RULE_RECEIVE:
1719 rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID;
1720 /* allow rules default to TRUE (only requested replies allowed)
1721 + * check rules default to TRUE (only requested replies are checked)
1722 * deny rules default to FALSE (only unrequested replies denied)
1724 - rule->d.receive.requested_reply = rule->allow;
1725 + rule->d.receive.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY;
1727 case BUS_POLICY_RULE_OWN:
1729 @@ -117,7 +119,8 @@ bus_policy_rule_unref (BusPolicyRule *rule)
1730 case BUS_POLICY_RULE_GROUP:
1735 + dbus_free (rule->privilege);
1739 @@ -427,7 +430,10 @@ list_allows_user (dbus_bool_t def,
1743 - allowed = rule->allow;
1744 + /* We don't intend to support <check user="..." /> and <check group="..." />
1745 + rules. They are treated like deny.
1747 + allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW;
1751 @@ -862,18 +868,23 @@ bus_client_policy_append_rule (BusClientPolicy *policy,
1756 -bus_client_policy_check_can_send (BusClientPolicy *policy,
1757 - BusRegistry *registry,
1758 - dbus_bool_t requested_reply,
1759 - DBusConnection *receiver,
1760 - DBusMessage *message,
1761 - dbus_int32_t *toggles,
1764 +bus_client_policy_check_can_send (DBusConnection *sender,
1765 + BusClientPolicy *policy,
1766 + BusRegistry *registry,
1767 + dbus_bool_t requested_reply,
1768 + DBusConnection *addressed_recipient,
1769 + DBusConnection *receiver,
1770 + DBusMessage *message,
1771 + dbus_int32_t *toggles,
1773 + const char **privilege_param,
1774 + BusDeferredMessage **deferred_message)
1777 - dbus_bool_t allowed;
1780 + const char *privilege;
1782 /* policy->rules is in the order the rules appeared
1783 * in the config file, i.e. last rule that applies wins
1785 @@ -881,7 +892,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1786 _dbus_verbose (" (policy) checking send rules\n");
1790 + result = BUS_RESULT_FALSE;
1791 link = _dbus_list_get_first_link (&policy->rules);
1792 while (link != NULL)
1794 @@ -912,13 +923,14 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1795 /* If it's a reply, the requested_reply flag kicks in */
1796 if (dbus_message_get_reply_serial (message) != 0)
1798 - /* for allow, requested_reply=true means the rule applies
1799 - * only when reply was requested. requested_reply=false means
1801 + /* for allow or check requested_reply=true means the rule applies
1802 + * only when reply was requested. requested_reply=false means the
1803 + * rule always applies
1805 - if (!requested_reply && rule->allow && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
1806 + if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
1808 - _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
1809 + _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n",
1810 + rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check");
1814 @@ -926,7 +938,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1815 * when the reply was not requested. requested_reply=true means the
1816 * rule always applies.
1818 - if (requested_reply && !rule->allow && !rule->d.send.requested_reply)
1819 + if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.send.requested_reply)
1821 _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n");
1823 @@ -949,13 +961,15 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1824 /* The interface is optional in messages. For allow rules, if the message
1825 * has no interface we want to skip the rule (and thus not allow);
1826 * for deny rules, if the message has no interface we want to use the
1827 - * rule (and thus deny).
1828 + * rule (and thus deny). Check rules are meant to be used like allow
1829 + * rules (they can grant access, but not remove it), so we treat it like
1832 dbus_bool_t no_interface;
1834 no_interface = dbus_message_get_interface (message) == NULL;
1836 - if ((no_interface && rule->allow) ||
1837 + if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) ||
1839 strcmp (dbus_message_get_interface (message),
1840 rule->d.send.interface) != 0))
1841 @@ -1029,33 +1043,63 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1845 - allowed = rule->allow;
1846 + switch (rule->access)
1848 + case BUS_POLICY_RULE_ACCESS_ALLOW:
1849 + result = BUS_RESULT_TRUE;
1851 + case BUS_POLICY_RULE_ACCESS_DENY:
1852 + result = BUS_RESULT_FALSE;
1854 + case BUS_POLICY_RULE_ACCESS_CHECK:
1855 + result = BUS_RESULT_LATER;
1856 + privilege = rule->privilege;
1860 *log = rule->d.send.log;
1863 - _dbus_verbose (" (policy) used rule, allow now = %d\n",
1865 + _dbus_verbose (" (policy) used rule, result now = %d\n",
1870 + if (result == BUS_RESULT_LATER)
1872 + BusContext *context = bus_connection_get_context(sender);
1873 + BusCheck *check = bus_context_get_check(context);
1875 + result = bus_check_privilege(check, message, sender, addressed_recipient, receiver,
1876 + privilege, BUS_DEFERRED_MESSAGE_CHECK_SEND, deferred_message);
1881 + if (privilege_param != NULL)
1882 + *privilege_param = privilege;
1887 /* See docs on what the args mean on bus_context_check_security_policy()
1891 -bus_client_policy_check_can_receive (BusClientPolicy *policy,
1892 - BusRegistry *registry,
1893 - dbus_bool_t requested_reply,
1894 - DBusConnection *sender,
1895 - DBusConnection *addressed_recipient,
1896 - DBusConnection *proposed_recipient,
1897 - DBusMessage *message,
1898 - dbus_int32_t *toggles)
1900 +bus_client_policy_check_can_receive (BusClientPolicy *policy,
1901 + BusRegistry *registry,
1902 + dbus_bool_t requested_reply,
1903 + DBusConnection *sender,
1904 + DBusConnection *addressed_recipient,
1905 + DBusConnection *proposed_recipient,
1906 + DBusMessage *message,
1907 + dbus_int32_t *toggles,
1908 + const char **privilege_param,
1909 + BusDeferredMessage **deferred_message)
1912 - dbus_bool_t allowed;
1913 dbus_bool_t eavesdropping;
1915 + const char *privilege;
1918 addressed_recipient != proposed_recipient &&
1919 @@ -1068,7 +1112,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1920 _dbus_verbose (" (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
1924 + result = BUS_RESULT_FALSE;
1925 link = _dbus_list_get_first_link (&policy->rules);
1926 while (link != NULL)
1928 @@ -1091,19 +1135,21 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1932 - /* for allow, eavesdrop=false means the rule doesn't apply when
1933 - * eavesdropping. eavesdrop=true means always allow.
1935 + /* for allow or check, eavesdrop=false means the rule doesn't apply when
1936 + * eavesdropping. eavesdrop=true means the rule always applies
1938 - if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop)
1939 + if (eavesdropping && rule->access != BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.eavesdrop)
1941 - _dbus_verbose (" (policy) skipping allow rule since it doesn't apply to eavesdropping\n");
1942 + _dbus_verbose (" (policy) skipping %s rule since it doesn't apply to eavesdropping\n",
1943 + rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check");
1947 /* for deny, eavesdrop=true means the rule applies only when
1948 * eavesdropping; eavesdrop=false means always deny.
1950 - if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop)
1951 + if (!eavesdropping && rule->access == BUS_POLICY_RULE_ACCESS_DENY && rule->d.receive.eavesdrop)
1953 _dbus_verbose (" (policy) skipping deny rule since it only applies to eavesdropping\n");
1955 @@ -1112,13 +1158,14 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1956 /* If it's a reply, the requested_reply flag kicks in */
1957 if (dbus_message_get_reply_serial (message) != 0)
1959 - /* for allow, requested_reply=true means the rule applies
1960 - * only when reply was requested. requested_reply=false means
1962 + /* for allow or check requested_reply=true means the rule applies
1963 + * only when reply was requested. requested_reply=false means the
1964 + * rule always applies
1966 - if (!requested_reply && rule->allow && rule->d.receive.requested_reply && !rule->d.receive.eavesdrop)
1967 + if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
1969 - _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
1970 + _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n",
1971 + rule->access == BUS_POLICY_RULE_ACCESS_DENY ? "allow" : "deny");
1975 @@ -1126,7 +1173,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1976 * when the reply was not requested. requested_reply=true means the
1977 * rule always applies.
1979 - if (requested_reply && !rule->allow && !rule->d.receive.requested_reply)
1980 + if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.requested_reply)
1982 _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n");
1984 @@ -1149,13 +1196,13 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1985 /* The interface is optional in messages. For allow rules, if the message
1986 * has no interface we want to skip the rule (and thus not allow);
1987 * for deny rules, if the message has no interface we want to use the
1988 - * rule (and thus deny).
1989 + * rule (and thus deny). Check rules are treated like allow rules.
1991 dbus_bool_t no_interface;
1993 no_interface = dbus_message_get_interface (message) == NULL;
1995 - if ((no_interface && rule->allow) ||
1996 + if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) ||
1998 strcmp (dbus_message_get_interface (message),
1999 rule->d.receive.interface) != 0))
2000 @@ -1230,14 +1277,42 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
2004 - allowed = rule->allow;
2005 + switch (rule->access)
2007 + case BUS_POLICY_RULE_ACCESS_ALLOW:
2008 + result = BUS_RESULT_TRUE;
2010 + case BUS_POLICY_RULE_ACCESS_DENY:
2011 + result = BUS_RESULT_FALSE;
2013 + case BUS_POLICY_RULE_ACCESS_CHECK:
2014 + result = BUS_RESULT_LATER;
2015 + privilege = rule->privilege;
2021 - _dbus_verbose (" (policy) used rule, allow now = %d\n",
2023 + _dbus_verbose (" (policy) used rule, result now = %d\n",
2029 + if (result == BUS_RESULT_LATER)
2031 + BusContext *context = bus_connection_get_context(proposed_recipient);
2032 + BusCheck *check = bus_context_get_check(context);
2034 + result = bus_check_privilege(check, message, sender, addressed_recipient, proposed_recipient,
2035 + privilege, BUS_DEFERRED_MESSAGE_CHECK_RECEIVE, deferred_message);
2040 + if (privilege_param != NULL)
2041 + *privilege_param = privilege;
2047 @@ -1289,7 +1364,7 @@ bus_rules_check_can_own (DBusList *rules,
2051 - allowed = rule->allow;
2052 + allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW;
2056 diff --git a/bus/policy.h b/bus/policy.h
2057 index d1d3e72..e9f193a 100644
2060 @@ -39,6 +39,14 @@ typedef enum
2061 BUS_POLICY_RULE_GROUP
2062 } BusPolicyRuleType;
2066 + BUS_POLICY_RULE_ACCESS_DENY,
2067 + BUS_POLICY_RULE_ACCESS_ALLOW,
2068 + /** runtime check resulting in allow or deny */
2069 + BUS_POLICY_RULE_ACCESS_CHECK
2070 +} BusPolicyRuleAccess;
2072 /** determines whether the rule affects a connection, or some global item */
2073 #define BUS_POLICY_RULE_IS_PER_CLIENT(rule) (!((rule)->type == BUS_POLICY_RULE_USER || \
2074 (rule)->type == BUS_POLICY_RULE_GROUP))
2075 @@ -49,8 +57,9 @@ struct BusPolicyRule
2077 BusPolicyRuleType type;
2079 - unsigned int allow : 1; /**< #TRUE if this allows, #FALSE if it denies */
2081 + unsigned int access : 2; /**< BusPolicyRuleAccess */
2082 + char *privilege; /**< for BUS_POLICY_RULE_ACCESS_CHECK */
2087 @@ -106,7 +115,7 @@ struct BusPolicyRule
2090 BusPolicyRule* bus_policy_rule_new (BusPolicyRuleType type,
2091 - dbus_bool_t allow);
2092 + BusPolicyRuleAccess access);
2093 BusPolicyRule* bus_policy_rule_ref (BusPolicyRule *rule);
2094 void bus_policy_rule_unref (BusPolicyRule *rule);
2096 @@ -140,21 +149,27 @@ dbus_bool_t bus_policy_merge (BusPolicy *policy,
2097 BusClientPolicy* bus_client_policy_new (void);
2098 BusClientPolicy* bus_client_policy_ref (BusClientPolicy *policy);
2099 void bus_client_policy_unref (BusClientPolicy *policy);
2100 -dbus_bool_t bus_client_policy_check_can_send (BusClientPolicy *policy,
2101 - BusRegistry *registry,
2102 - dbus_bool_t requested_reply,
2103 - DBusConnection *receiver,
2104 - DBusMessage *message,
2105 - dbus_int32_t *toggles,
2106 - dbus_bool_t *log);
2107 -dbus_bool_t bus_client_policy_check_can_receive (BusClientPolicy *policy,
2108 - BusRegistry *registry,
2109 - dbus_bool_t requested_reply,
2110 - DBusConnection *sender,
2111 - DBusConnection *addressed_recipient,
2112 - DBusConnection *proposed_recipient,
2113 - DBusMessage *message,
2114 - dbus_int32_t *toggles);
2115 +BusResult bus_client_policy_check_can_send (DBusConnection *sender,
2116 + BusClientPolicy *policy,
2117 + BusRegistry *registry,
2118 + dbus_bool_t requested_reply,
2119 + DBusConnection *addressed_recipient,
2120 + DBusConnection *receiver,
2121 + DBusMessage *message,
2122 + dbus_int32_t *toggles,
2124 + const char **privilege_param,
2125 + BusDeferredMessage **deferred_message);
2126 +BusResult bus_client_policy_check_can_receive (BusClientPolicy *policy,
2127 + BusRegistry *registry,
2128 + dbus_bool_t requested_reply,
2129 + DBusConnection *sender,
2130 + DBusConnection *addressed_recipient,
2131 + DBusConnection *proposed_recipient,
2132 + DBusMessage *message,
2133 + dbus_int32_t *toggles,
2134 + const char **privilege_param,
2135 + BusDeferredMessage **deferred_message);
2136 dbus_bool_t bus_client_policy_check_can_own (BusClientPolicy *policy,
2137 const DBusString *service_name);
2138 dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy,
2139 diff --git a/configure.ac b/configure.ac
2140 index eb803af..b131f30 100644
2143 @@ -1748,6 +1748,18 @@ if test "x$enable_stats" = xyes; then
2144 [Define to enable bus daemon usage statistics])
2147 +#enable cynara integration
2148 +AC_ARG_ENABLE([cynara], [AS_HELP_STRING([--enable-cynara], [enable Cynara integration])], [], [enable_cynara=no])
2149 +if test "x$enable_cynara" = xyes; then
2150 + PKG_CHECK_MODULES([CYNARA], [cynara-client-async >= 0.6.0 cynara-session >= 0.6.0],
2151 + [AC_DEFINE([DBUS_ENABLE_CYNARA], [1], [Define to enable Cynara privilege checks in dbus-daemon])],
2152 + [AC_MSG_ERROR([libcynara-client-async and cynara-session are required to enable Cynara integration])])
2155 +AC_SUBST([CYNARA_CFLAGS])
2156 +AC_SUBST([CYNARA_LIBS])
2162 @@ -1778,6 +1790,7 @@ dbus-1.pc
2163 dbus-1-uninstalled.pc
2164 test/data/valid-config-files/debug-allow-all.conf
2165 test/data/valid-config-files/debug-allow-all-sha1.conf
2166 +test/data/valid-config-files/debug-check-some.conf
2167 test/data/valid-config-files/incoming-limit.conf
2168 test/data/valid-config-files-system/debug-allow-all-pass.conf
2169 test/data/valid-config-files-system/debug-allow-all-fail.conf
2170 diff --git a/test/Makefile.am b/test/Makefile.am
2171 index e0ed3c8..ab63edc 100644
2172 --- a/test/Makefile.am
2173 +++ b/test/Makefile.am
2174 @@ -254,6 +254,7 @@ in_data = \
2175 data/valid-config-files-system/debug-allow-all-pass.conf.in \
2176 data/valid-config-files/debug-allow-all-sha1.conf.in \
2177 data/valid-config-files/debug-allow-all.conf.in \
2178 + data/valid-config-files/debug-check-some.conf.in \
2179 data/valid-config-files/incoming-limit.conf.in \
2180 data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in \
2181 data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.in \
2182 diff --git a/test/data/invalid-config-files/badcheck-1.conf b/test/data/invalid-config-files/badcheck-1.conf
2183 new file mode 100644
2184 index 0000000..fad9f50
2186 +++ b/test/data/invalid-config-files/badcheck-1.conf
2188 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2189 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2191 + <user>mybususer</user>
2192 + <listen>unix:path=/foo/bar</listen>
2193 + <policy context="default">
2194 + <allow privilege="foo" send_destination="*"/> <!-- extra privilege="foo" -->
2197 diff --git a/test/data/invalid-config-files/badcheck-2.conf b/test/data/invalid-config-files/badcheck-2.conf
2198 new file mode 100644
2199 index 0000000..63c7ef2
2201 +++ b/test/data/invalid-config-files/badcheck-2.conf
2203 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2204 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2206 + <user>mybususer</user>
2207 + <listen>unix:path=/foo/bar</listen>
2208 + <policy context="default">
2209 + <check send_destination="*"/> <!-- missing privilege="foo" -->
2212 diff --git a/test/data/valid-config-files/check-1.conf b/test/data/valid-config-files/check-1.conf
2213 new file mode 100644
2214 index 0000000..ad71473
2216 +++ b/test/data/valid-config-files/check-1.conf
2218 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2219 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2221 + <user>mybususer</user>
2222 + <listen>unix:path=/foo/bar</listen>
2223 + <policy context="default">
2224 + <check privilege="foo" send_destination="*"/>
2227 diff --git a/test/data/valid-config-files/debug-check-some.conf.in b/test/data/valid-config-files/debug-check-some.conf.in
2228 new file mode 100644
2229 index 0000000..47ee854
2231 +++ b/test/data/valid-config-files/debug-check-some.conf.in
2233 +<!-- Bus that listens on a debug pipe and doesn't create any restrictions -->
2235 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2236 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2238 + <listen>debug-pipe:name=test-server</listen>
2239 + <listen>@TEST_LISTEN@</listen>
2240 + <servicedir>@DBUS_TEST_DATA@/valid-service-files</servicedir>
2241 + <policy context="default">
2242 + <allow send_interface="*"/>
2243 + <allow receive_interface="*"/>
2247 + <deny send_interface="org.freedesktop.TestSuite" send_member="Echo"/>
2248 + <check privilege="foo" send_interface="org.freedesktop.TestSuite" send_member="Echo"/>