1 From 8f69153081140fa4c347ab1729c348ec77b309ec 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/5] 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.
24 Change-Id: I9bcbce34577e5dc2a3cecf6233a0a2b0e43e1108
25 Signed-off-by: José Bollo <jose.bollo@iot.bzh>
26 Signed-off-by: Scott Murray <scott.murray@konsulko.com>
28 diff --git a/bus/Makefile.am b/bus/Makefile.am
29 index 9ae3071..46afb31 100644
32 @@ -13,6 +13,7 @@ DBUS_BUS_LIBS = \
39 DBUS_LAUNCHER_LIBS = \
40 @@ -30,6 +31,7 @@ AM_CPPFLAGS = \
42 -DDBUS_SYSTEM_CONFIG_FILE=\""$(dbusdatadir)/system.conf"\" \
47 # if assertions are enabled, improve backtraces
48 @@ -90,6 +92,8 @@ BUS_SOURCES= \
54 config-loader-expat.c \
57 @@ -97,6 +101,8 @@ BUS_SOURCES= \
58 config-parser-common.h \
66 diff --git a/bus/activation.c b/bus/activation.c
67 index 6f009f5..451179d 100644
68 --- a/bus/activation.c
69 +++ b/bus/activation.c
70 @@ -1795,7 +1795,8 @@ bus_activation_activate_service (BusActivation *activation,
71 NULL, /* proposed recipient */
78 _DBUS_ASSERT_ERROR_IS_SET (error);
79 _dbus_verbose ("activation not authorized: %s: %s\n",
80 diff --git a/bus/bus.c b/bus/bus.c
81 index 30ce4e1..237efe3 100644
87 #include "dir-watch.h"
89 #include <dbus/dbus-auth.h>
90 #include <dbus/dbus-list.h>
91 #include <dbus/dbus-hash.h>
92 @@ -67,6 +68,7 @@ struct BusContext
93 BusRegistry *registry;
95 BusMatchmaker *matchmaker;
98 DBusRLimit *initial_fd_limit;
99 unsigned int fork : 1;
100 @@ -1003,6 +1005,10 @@ bus_context_new (const DBusString *config_file,
104 + context->check = bus_check_new(context, error);
105 + if (context->check == NULL)
108 dbus_server_free_data_slot (&server_data_slot);
111 @@ -1127,6 +1133,12 @@ bus_context_unref (BusContext *context)
113 bus_context_shutdown (context);
115 + if (context->check)
117 + bus_check_unref(context->check);
118 + context->check = NULL;
121 if (context->connections)
123 bus_connections_unref (context->connections);
124 @@ -1256,6 +1268,12 @@ bus_context_get_loop (BusContext *context)
125 return context->loop;
129 +bus_context_get_check (BusContext *context)
131 + return context->check;
135 bus_context_allow_unix_user (BusContext *context,
137 @@ -1451,6 +1469,7 @@ complain_about_message (BusContext *context,
138 DBusConnection *proposed_recipient,
139 dbus_bool_t requested_reply,
141 + const char *privilege,
144 DBusError stack_error = DBUS_ERROR_INIT;
145 @@ -1480,7 +1499,8 @@ complain_about_message (BusContext *context,
146 dbus_set_error (&stack_error, error_name,
147 "%s, %d matched rules; type=\"%s\", sender=\"%s\" (%s) "
148 "interface=\"%s\" member=\"%s\" error name=\"%s\" "
149 - "requested_reply=\"%d\" destination=\"%s\" (%s)",
150 + "requested_reply=\"%d\" destination=\"%s\" (%s) "
151 + "privilege=\"%s\"",
154 dbus_message_type_to_string (dbus_message_get_type (message)),
155 @@ -1491,7 +1511,8 @@ complain_about_message (BusContext *context,
156 nonnull (dbus_message_get_error_name (message), "(unset)"),
158 nonnull (dbus_message_get_destination (message), DBUS_SERVICE_DBUS),
159 - proposed_recipient_loginfo);
160 + proposed_recipient_loginfo,
161 + nonnull (privilege, "(n/a)"));
163 /* If we hit OOM while setting the error, this will syslog "out of memory"
164 * which is itself an indication that something is seriously wrong */
165 @@ -1519,7 +1540,7 @@ complain_about_message (BusContext *context,
166 * NULL for addressed_recipient may mean the bus driver, or may mean
167 * no destination was specified in the message (e.g. a signal).
171 bus_context_check_security_policy (BusContext *context,
172 BusTransaction *transaction,
173 DBusConnection *sender,
174 @@ -1527,7 +1548,8 @@ bus_context_check_security_policy (BusContext *context,
175 DBusConnection *proposed_recipient,
176 DBusMessage *message,
177 BusActivationEntry *activation_entry,
180 + BusDeferredMessage **deferred_message)
182 const char *src, *dest;
183 BusClientPolicy *sender_policy;
184 @@ -1536,6 +1558,7 @@ bus_context_check_security_policy (BusContext *context,
187 dbus_bool_t requested_reply;
188 + const char *privilege;
190 type = dbus_message_get_type (message);
191 src = dbus_message_get_sender (message);
192 @@ -1565,7 +1588,7 @@ bus_context_check_security_policy (BusContext *context,
193 dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
194 "Message bus will not accept messages of unknown type\n");
197 + return BUS_RESULT_FALSE;
200 requested_reply = FALSE;
201 @@ -1595,7 +1618,7 @@ bus_context_check_security_policy (BusContext *context,
202 if (dbus_error_is_set (&error2))
204 dbus_move_error (&error2, error);
206 + return BUS_RESULT_FALSE;
210 @@ -1624,11 +1647,11 @@ bus_context_check_security_policy (BusContext *context,
211 complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
212 "An SELinux policy prevents this sender from sending this "
213 "message to this recipient",
214 - 0, message, sender, proposed_recipient, FALSE, FALSE, error);
215 + 0, message, sender, proposed_recipient, FALSE, FALSE, NULL, error);
216 _dbus_verbose ("SELinux security check denying send to service\n");
220 + return BUS_RESULT_FALSE;
223 /* next verify AppArmor access controls. If allowed then
224 @@ -1646,7 +1669,7 @@ bus_context_check_security_policy (BusContext *context,
225 src ? src : DBUS_SERVICE_DBUS,
229 + return BUS_RESULT_FALSE;
231 if (!bus_connection_is_active (sender))
233 @@ -1660,7 +1683,7 @@ bus_context_check_security_policy (BusContext *context,
235 _dbus_verbose ("security check allowing %s message\n",
238 + return BUS_RESULT_TRUE;
242 @@ -1671,7 +1694,7 @@ bus_context_check_security_policy (BusContext *context,
243 "Client tried to send a message other than %s without being registered",
247 + return BUS_RESULT_FALSE;
251 @@ -1720,20 +1743,29 @@ bus_context_check_security_policy (BusContext *context,
252 (proposed_recipient == NULL && recipient_policy == NULL));
255 - if (sender_policy &&
256 - !bus_client_policy_check_can_send (sender_policy,
259 - proposed_recipient,
260 - message, &toggles, &log))
262 - complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
263 - "Rejected send message", toggles,
264 - message, sender, proposed_recipient, requested_reply,
265 - (addressed_recipient == proposed_recipient), error);
266 - _dbus_verbose ("security policy disallowing message due to sender policy\n");
271 + BusResult res = bus_client_policy_check_can_send (sender,
275 + addressed_recipient,
276 + proposed_recipient,
277 + message, &toggles, &log, &privilege,
279 + if (res == BUS_RESULT_FALSE)
281 + complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
282 + "Rejected send message", toggles,
283 + message, sender, proposed_recipient, requested_reply,
284 + (addressed_recipient == proposed_recipient), privilege,
286 + _dbus_verbose ("security policy disallowing message due to sender policy\n");
287 + return BUS_RESULT_FALSE;
289 + else if (res == BUS_RESULT_LATER)
290 + return BUS_RESULT_LATER;
295 @@ -1742,23 +1774,29 @@ bus_context_check_security_policy (BusContext *context,
296 complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
297 "Would reject message", toggles,
298 message, sender, proposed_recipient, requested_reply,
300 + TRUE, privilege, NULL);
303 - if (recipient_policy &&
304 - !bus_client_policy_check_can_receive (recipient_policy,
308 - addressed_recipient, proposed_recipient,
309 - message, &toggles))
310 + if (recipient_policy)
312 - complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
313 - "Rejected receive message", toggles,
314 - message, sender, proposed_recipient, requested_reply,
315 - (addressed_recipient == proposed_recipient), error);
316 - _dbus_verbose ("security policy disallowing message due to recipient policy\n");
319 + res = bus_client_policy_check_can_receive (recipient_policy,
323 + addressed_recipient, proposed_recipient,
324 + message, &toggles, &privilege, deferred_message);
325 + if (res == BUS_RESULT_FALSE)
327 + complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected receive message",
328 + toggles, message, sender, proposed_recipient, requested_reply,
329 + (addressed_recipient == proposed_recipient), privilege, error);
331 + "security policy disallowing message due to recipient policy\n");
332 + return BUS_RESULT_FALSE;
334 + else if (res == BUS_RESULT_LATER)
335 + return BUS_RESULT_LATER;
338 /* See if limits on size have been exceeded */
339 @@ -1768,10 +1806,10 @@ bus_context_check_security_policy (BusContext *context,
341 complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED,
342 "Rejected: destination has a full message queue",
343 - 0, message, sender, proposed_recipient, requested_reply, TRUE,
344 + 0, message, sender, proposed_recipient, requested_reply, TRUE, NULL,
346 _dbus_verbose ("security policy disallowing message due to full message queue\n");
348 + return BUS_RESULT_FALSE;
351 /* Record that we will allow a reply here in the future (don't
352 @@ -1792,11 +1830,11 @@ bus_context_check_security_policy (BusContext *context,
355 _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
357 + return BUS_RESULT_FALSE;
360 _dbus_verbose ("security policy allowing message\n");
362 + return BUS_RESULT_TRUE;
366 diff --git a/bus/bus.h b/bus/bus.h
367 index 2e0de82..82c32c8 100644
370 @@ -45,6 +45,22 @@ typedef struct BusTransaction BusTransaction;
371 typedef struct BusMatchmaker BusMatchmaker;
372 typedef struct BusMatchRule BusMatchRule;
373 typedef struct BusActivationEntry BusActivationEntry;
374 +typedef struct BusCheck BusCheck;
375 +typedef struct BusDeferredMessage BusDeferredMessage;
376 +typedef struct BusCynara BusCynara;
379 + * BusResult is defined as a pointer to a dummy structure to allow detection of type mismatches.
380 + * The disadvantage of such solution is that now BusResult variables cannot be used in switch
382 + * Additionally, BUS_RESULT_TRUE is defined as 0 instead of 1 to help detect type mismatches
385 +typedef const struct BusResultStruct { int dummy; } *BusResult;
387 +static const BusResult BUS_RESULT_TRUE = (BusResult)0x0;
388 +static const BusResult BUS_RESULT_FALSE = (BusResult)0x1;
389 +static const BusResult BUS_RESULT_LATER = (BusResult)0x2;
393 @@ -101,6 +117,7 @@ BusConnections* bus_context_get_connections (BusContext
394 BusActivation* bus_context_get_activation (BusContext *context);
395 BusMatchmaker* bus_context_get_matchmaker (BusContext *context);
396 DBusLoop* bus_context_get_loop (BusContext *context);
397 +BusCheck * bus_context_get_check (BusContext *context);
398 dbus_bool_t bus_context_allow_unix_user (BusContext *context,
400 dbus_bool_t bus_context_allow_windows_user (BusContext *context,
401 @@ -136,14 +153,15 @@ void bus_context_log_and_set_error (BusContext
404 ...) _DBUS_GNUC_PRINTF (5, 6);
405 -dbus_bool_t bus_context_check_security_policy (BusContext *context,
406 +BusResult bus_context_check_security_policy (BusContext *context,
407 BusTransaction *transaction,
408 DBusConnection *sender,
409 DBusConnection *addressed_recipient,
410 DBusConnection *proposed_recipient,
411 DBusMessage *message,
412 BusActivationEntry *activation_entry,
415 + BusDeferredMessage **deferred_message);
416 void bus_context_check_all_watches (BusContext *context);
418 #endif /* BUS_BUS_H */
419 diff --git a/bus/check.c b/bus/check.c
421 index 0000000..5b72d31
425 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
426 +/* check.c Bus security policy runtime check
428 + * Copyright (C) 2014 Intel, Inc.
429 + * Copyright (c) 2014 Samsung Electronics, Ltd.
431 + * Licensed under the Academic Free License version 2.1
433 + * This program is free software; you can redistribute it and/or modify
434 + * it under the terms of the GNU General Public License as published by
435 + * the Free Software Foundation; either version 2 of the License, or
436 + * (at your option) any later version.
438 + * This program is distributed in the hope that it will be useful,
439 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
440 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
441 + * GNU General Public License for more details.
443 + * You should have received a copy of the GNU General Public License
444 + * along with this program; if not, write to the Free Software
445 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
451 +#include "connection.h"
452 +#include "dispatch.h"
455 +#include <dbus/dbus-connection-internal.h>
456 +#include <dbus/dbus-message-internal.h>
457 +#include <dbus/dbus-internals.h>
460 +typedef struct BusCheck
464 + BusContext *context;
468 +typedef struct BusDeferredMessage
472 + DBusMessage *message;
473 + DBusConnection *sender;
474 + DBusConnection *proposed_recipient;
475 + DBusConnection *addressed_recipient;
476 + dbus_bool_t full_dispatch;
477 + BusDeferredMessageStatus status;
478 + BusResult response;
479 + BusCheckResponseFunc response_callback;
480 +} BusDeferredMessage;
483 +bus_check_new (BusContext *context, DBusError *error)
487 + check = dbus_new(BusCheck, 1);
490 + BUS_SET_OOM(error);
494 + check->refcount = 1;
495 + check->context = context;
496 + check->cynara = bus_cynara_new(check, error);
497 + if (dbus_error_is_set(error))
507 +bus_check_ref (BusCheck *check)
509 + _dbus_assert (check->refcount > 0);
510 + check->refcount += 1;
516 +bus_check_unref (BusCheck *check)
518 + _dbus_assert (check->refcount > 0);
520 + check->refcount -= 1;
522 + if (check->refcount == 0)
524 + bus_cynara_unref(check->cynara);
530 +bus_check_get_context (BusCheck *check)
532 + return check->context;
536 +bus_check_get_cynara (BusCheck *check)
538 + return check->cynara;
542 +bus_check_privilege (BusCheck *check,
543 + DBusMessage *message,
544 + DBusConnection *sender,
545 + DBusConnection *addressed_recipient,
546 + DBusConnection *proposed_recipient,
547 + const char *privilege,
548 + BusDeferredMessageStatus check_type,
549 + BusDeferredMessage **deferred_message)
551 + BusResult result = BUS_RESULT_FALSE;
552 +#ifdef DBUS_ENABLE_CYNARA
555 + DBusConnection *connection;
557 + connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
559 + if (!dbus_connection_get_is_connected(connection))
561 + return BUS_RESULT_FALSE;
564 + /* ask policy checkers */
565 +#ifdef DBUS_ENABLE_CYNARA
566 + cynara = bus_check_get_cynara(check);
567 + result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient,
568 + proposed_recipient, privilege, check_type, deferred_message);
571 + if (result == BUS_RESULT_LATER && deferred_message != NULL)
573 + (*deferred_message)->status |= check_type;
578 +BusDeferredMessage *bus_deferred_message_new (DBusMessage *message,
579 + DBusConnection *sender,
580 + DBusConnection *addressed_recipient,
581 + DBusConnection *proposed_recipient,
582 + BusResult response)
584 + BusDeferredMessage *deferred_message;
586 + deferred_message = dbus_new(BusDeferredMessage, 1);
587 + if (deferred_message == NULL)
592 + deferred_message->refcount = 1;
593 + deferred_message->sender = sender != NULL ? dbus_connection_ref(sender) : NULL;
594 + deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL;
595 + deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL;
596 + deferred_message->message = dbus_message_ref(message);
597 + deferred_message->response = response;
598 + deferred_message->status = 0;
599 + deferred_message->full_dispatch = FALSE;
600 + deferred_message->response_callback = NULL;
602 + return deferred_message;
605 +BusDeferredMessage *
606 +bus_deferred_message_ref (BusDeferredMessage *deferred_message)
608 + _dbus_assert (deferred_message->refcount > 0);
609 + deferred_message->refcount += 1;
610 + return deferred_message;
614 +bus_deferred_message_unref (BusDeferredMessage *deferred_message)
616 + _dbus_assert (deferred_message->refcount > 0);
618 + deferred_message->refcount -= 1;
620 + if (deferred_message->refcount == 0)
622 + dbus_message_unref(deferred_message->message);
623 + if (deferred_message->sender != NULL)
624 + dbus_connection_unref(deferred_message->sender);
625 + if (deferred_message->addressed_recipient != NULL)
626 + dbus_connection_unref(deferred_message->addressed_recipient);
627 + if (deferred_message->proposed_recipient != NULL)
628 + dbus_connection_unref(deferred_message->proposed_recipient);
629 + dbus_free(deferred_message);
634 +bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
637 + if (deferred_message->response_callback != NULL)
639 + deferred_message->response_callback(deferred_message, result);
642 diff --git a/bus/check.h b/bus/check.h
644 index 0000000..c3fcaf9
648 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
649 +/* check.h Bus security policy runtime check
651 + * Copyright (C) 2014 Intel, Inc.
652 + * Copyright (c) 2014 Samsung Electronics, Ltd.
654 + * Licensed under the Academic Free License version 2.1
656 + * This program is free software; you can redistribute it and/or modify
657 + * it under the terms of the GNU General Public License as published by
658 + * the Free Software Foundation; either version 2 of the License, or
659 + * (at your option) any later version.
661 + * This program is distributed in the hope that it will be useful,
662 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
663 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
664 + * GNU General Public License for more details.
666 + * You should have received a copy of the GNU General Public License
667 + * along with this program; if not, write to the Free Software
668 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
679 +typedef void (*BusCheckResponseFunc) (BusDeferredMessage *message,
683 + BUS_DEFERRED_MESSAGE_CHECK_SEND = 1 << 0,
684 + BUS_DEFERRED_MESSAGE_CHECK_RECEIVE = 1 << 1,
685 + BUS_DEFERRED_MESSAGE_CHECK_OWN = 1 << 2,
686 +} BusDeferredMessageStatus;
689 +BusCheck *bus_check_new (BusContext *context,
691 +BusCheck *bus_check_ref (BusCheck *check);
692 +void bus_check_unref (BusCheck *check);
694 +BusContext *bus_check_get_context (BusCheck *check);
695 +BusCynara *bus_check_get_cynara (BusCheck *check);
696 +BusResult bus_check_privilege (BusCheck *check,
697 + DBusMessage *message,
698 + DBusConnection *sender,
699 + DBusConnection *addressed_recipient,
700 + DBusConnection *proposed_recipient,
701 + const char *privilege,
702 + BusDeferredMessageStatus check_type,
703 + BusDeferredMessage **deferred_message);
705 +BusDeferredMessage *bus_deferred_message_new (DBusMessage *message,
706 + DBusConnection *sender,
707 + DBusConnection *addressed_recipient,
708 + DBusConnection *proposed_recipient,
709 + BusResult response);
711 +BusDeferredMessage *bus_deferred_message_ref (BusDeferredMessage *deferred_message);
712 +void bus_deferred_message_unref (BusDeferredMessage *deferred_message);
713 +void bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
715 +#endif /* BUS_CHECK_H */
716 diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c
717 index c1c4191..e2f253d 100644
718 --- a/bus/config-parser-common.c
719 +++ b/bus/config-parser-common.c
720 @@ -75,6 +75,10 @@ bus_config_parser_element_name_to_type (const char *name)
724 + else if (strcmp (name, "check") == 0)
726 + return ELEMENT_CHECK;
728 else if (strcmp (name, "servicehelper") == 0)
730 return ELEMENT_SERVICEHELPER;
731 @@ -159,6 +163,8 @@ bus_config_parser_element_type_to_name (ElementType type)
735 + case ELEMENT_CHECK:
739 case ELEMENT_PIDFILE:
740 diff --git a/bus/config-parser-common.h b/bus/config-parser-common.h
741 index 382a014..9e026d1 100644
742 --- a/bus/config-parser-common.h
743 +++ b/bus/config-parser-common.h
744 @@ -36,6 +36,7 @@ typedef enum
752 diff --git a/bus/config-parser.c b/bus/config-parser.c
753 index be27d38..b54b0e4 100644
754 --- a/bus/config-parser.c
755 +++ b/bus/config-parser.c
756 @@ -1318,7 +1318,7 @@ append_rule_from_element (BusConfigParser *parser,
757 const char *element_name,
758 const char **attribute_names,
759 const char **attribute_values,
761 + BusPolicyRuleAccess access,
765 @@ -1360,6 +1360,7 @@ append_rule_from_element (BusConfigParser *parser,
766 const char *own_prefix;
769 + const char *privilege;
773 @@ -1390,6 +1391,7 @@ append_rule_from_element (BusConfigParser *parser,
777 + "privilege", &privilege,
781 @@ -1422,6 +1424,7 @@ append_rule_from_element (BusConfigParser *parser,
783 if (!(any_send_attribute ||
784 any_receive_attribute ||
786 own || own_prefix || user || group))
788 dbus_set_error (error, DBUS_ERROR_FAILED,
789 @@ -1438,7 +1441,30 @@ append_rule_from_element (BusConfigParser *parser,
795 + if (access == BUS_POLICY_RULE_ACCESS_CHECK)
797 + if (privilege == NULL || !*privilege)
799 + dbus_set_error (error, DBUS_ERROR_FAILED,
800 + "On element <%s>, you must specify the privilege to be checked.",
807 + if (privilege != NULL && *privilege)
809 + dbus_set_error (error, DBUS_ERROR_FAILED,
810 + "On element <%s>, privilege %s is used outside of a check rule.",
811 + element_name, privilege);
815 + privilege = NULL; /* replace (potentially) empty string with NULL pointer, it wouldn't be used anyway */
818 /* Allowed combinations of elements are:
820 * base, must be all send or all receive:
821 @@ -1589,7 +1615,7 @@ append_rule_from_element (BusConfigParser *parser,
825 - rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow);
826 + rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, access);
830 @@ -1694,7 +1720,7 @@ append_rule_from_element (BusConfigParser *parser,
834 - rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow);
835 + rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, access);
839 @@ -1726,7 +1752,7 @@ append_rule_from_element (BusConfigParser *parser,
841 else if (own || own_prefix)
843 - rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow);
844 + rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, access);
848 @@ -1752,7 +1778,7 @@ append_rule_from_element (BusConfigParser *parser,
850 if (IS_WILDCARD (user))
852 - rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
853 + rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access);
857 @@ -1767,7 +1793,7 @@ append_rule_from_element (BusConfigParser *parser,
859 if (_dbus_parse_unix_user_from_config (&username, &uid))
861 - rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow);
862 + rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access);
866 @@ -1784,7 +1810,7 @@ append_rule_from_element (BusConfigParser *parser,
868 if (IS_WILDCARD (group))
870 - rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
871 + rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access);
875 @@ -1799,7 +1825,7 @@ append_rule_from_element (BusConfigParser *parser,
877 if (_dbus_parse_unix_group_from_config (&groupname, &gid))
879 - rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow);
880 + rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access);
884 @@ -1823,6 +1849,10 @@ append_rule_from_element (BusConfigParser *parser,
885 _dbus_assert (pe != NULL);
886 _dbus_assert (pe->type == ELEMENT_POLICY);
888 + rule->privilege = _dbus_strdup (privilege);
889 + if (privilege && !rule->privilege)
892 switch (pe->d.policy.type)
895 @@ -1898,7 +1928,7 @@ start_policy_child (BusConfigParser *parser,
897 if (!append_rule_from_element (parser, element_name,
898 attribute_names, attribute_values,
900 + BUS_POLICY_RULE_ACCESS_ALLOW, error))
903 if (push_element (parser, ELEMENT_ALLOW) == NULL)
904 @@ -1913,7 +1943,7 @@ start_policy_child (BusConfigParser *parser,
906 if (!append_rule_from_element (parser, element_name,
907 attribute_names, attribute_values,
909 + BUS_POLICY_RULE_ACCESS_DENY, error))
912 if (push_element (parser, ELEMENT_DENY) == NULL)
913 @@ -1922,6 +1952,21 @@ start_policy_child (BusConfigParser *parser,
919 + else if (strcmp (element_name, "check") == 0)
921 + if (!append_rule_from_element (parser, element_name,
922 + attribute_names, attribute_values,
923 + BUS_POLICY_RULE_ACCESS_CHECK, error))
926 + if (push_element (parser, ELEMENT_CHECK) == NULL)
928 + BUS_SET_OOM (error);
935 @@ -2284,6 +2329,7 @@ bus_config_parser_end_element (BusConfigParser *parser,
939 + case ELEMENT_CHECK:
942 case ELEMENT_KEEP_UMASK:
943 @@ -2600,6 +2646,7 @@ bus_config_parser_content (BusConfigParser *parser,
947 + case ELEMENT_CHECK:
950 case ELEMENT_KEEP_UMASK:
951 @@ -3127,6 +3174,8 @@ do_load (const DBusString *full_path,
952 dbus_error_init (&error);
954 parser = bus_config_load (full_path, TRUE, NULL, &error);
955 + if (dbus_error_is_set (&error))
956 + _dbus_verbose ("Failed to load file: %s\n", error.message);
959 _DBUS_ASSERT_ERROR_IS_SET (&error);
960 diff --git a/bus/connection.c b/bus/connection.c
961 index 53605fa..deebde3 100644
962 --- a/bus/connection.c
963 +++ b/bus/connection.c
965 #include <dbus/dbus-timeout.h>
966 #include <dbus/dbus-connection-internal.h>
967 #include <dbus/dbus-internals.h>
968 +#ifdef DBUS_ENABLE_CYNARA
970 +#include <cynara-session.h>
973 /* Trim executed commands to this length; we want to keep logs readable */
974 #define MAX_LOG_COMMAND_LEN 50
975 @@ -116,6 +120,9 @@ typedef struct
977 /** non-NULL if and only if this is a monitor */
978 DBusList *link_in_monitors;
979 +#ifdef DBUS_ENABLE_CYNARA
980 + char *cynara_session_id;
984 static dbus_bool_t bus_pending_reply_expired (BusExpireList *list,
985 @@ -129,8 +136,8 @@ static dbus_bool_t expire_incomplete_timeout (void *data);
987 #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot))
990 -connection_get_loop (DBusConnection *connection)
992 +bus_connection_get_loop (DBusConnection *connection)
994 BusConnectionData *d;
996 @@ -354,7 +361,7 @@ add_connection_watch (DBusWatch *watch,
998 DBusConnection *connection = data;
1000 - return _dbus_loop_add_watch (connection_get_loop (connection), watch);
1001 + return _dbus_loop_add_watch (bus_connection_get_loop (connection), watch);
1005 @@ -363,7 +370,7 @@ remove_connection_watch (DBusWatch *watch,
1007 DBusConnection *connection = data;
1009 - _dbus_loop_remove_watch (connection_get_loop (connection), watch);
1010 + _dbus_loop_remove_watch (bus_connection_get_loop (connection), watch);
1014 @@ -372,7 +379,7 @@ toggle_connection_watch (DBusWatch *watch,
1016 DBusConnection *connection = data;
1018 - _dbus_loop_toggle_watch (connection_get_loop (connection), watch);
1019 + _dbus_loop_toggle_watch (bus_connection_get_loop (connection), watch);
1023 @@ -381,7 +388,7 @@ add_connection_timeout (DBusTimeout *timeout,
1025 DBusConnection *connection = data;
1027 - return _dbus_loop_add_timeout (connection_get_loop (connection), timeout);
1028 + return _dbus_loop_add_timeout (bus_connection_get_loop (connection), timeout);
1032 @@ -390,7 +397,7 @@ remove_connection_timeout (DBusTimeout *timeout,
1034 DBusConnection *connection = data;
1036 - _dbus_loop_remove_timeout (connection_get_loop (connection), timeout);
1037 + _dbus_loop_remove_timeout (bus_connection_get_loop (connection), timeout);
1041 @@ -448,6 +455,10 @@ free_connection_data (void *data)
1043 dbus_free (d->name);
1045 +#ifdef DBUS_ENABLE_CYNARA
1046 + free (d->cynara_session_id);
1052 @@ -1078,6 +1089,22 @@ bus_connection_get_policy (DBusConnection *connection)
1056 +#ifdef DBUS_ENABLE_CYNARA
1057 +const char *bus_connection_get_cynara_session_id (DBusConnection *connection)
1059 + BusConnectionData *d = BUS_CONNECTION_DATA (connection);
1060 + _dbus_assert (d != NULL);
1062 + if (d->cynara_session_id == NULL)
1064 + unsigned long pid;
1065 + if (dbus_connection_get_unix_process_id(connection, &pid))
1066 + d->cynara_session_id = cynara_session_from_pid(pid);
1068 + return d->cynara_session_id;
1073 foreach_active (BusConnections *connections,
1074 BusConnectionForeachFunction function,
1075 @@ -2333,6 +2360,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
1076 DBusMessage *message)
1078 DBusError error = DBUS_ERROR_INIT;
1081 /* We have to set the sender to the driver, and have
1082 * to check security policy since it was not done in
1083 @@ -2370,10 +2398,12 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
1084 * if we're actively capturing messages, it's nice to log that we
1085 * tried to send it and did not allow ourselves to do so.
1087 - if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
1089 - NULL, connection, connection,
1090 - message, NULL, &error))
1091 + res = bus_context_check_security_policy (bus_transaction_get_context (transaction),
1093 + NULL, connection, connection,
1094 + message, NULL, &error,
1096 + if (res == BUS_RESULT_FALSE)
1098 if (!bus_transaction_capture_error_reply (transaction, connection,
1100 @@ -2388,6 +2418,12 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
1101 dbus_error_free (&error);
1104 + else if (res == BUS_RESULT_LATER)
1106 + _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n");
1107 + dbus_error_free (&error);
1111 return bus_transaction_send (transaction, connection, message);
1113 diff --git a/bus/connection.h b/bus/connection.h
1114 index 9e253ae..71078ea 100644
1115 --- a/bus/connection.h
1116 +++ b/bus/connection.h
1118 typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection,
1121 +DBusLoop* bus_connection_get_loop (DBusConnection *connection);
1123 BusConnections* bus_connections_new (BusContext *context);
1124 BusConnections* bus_connections_ref (BusConnections *connections);
1125 @@ -124,6 +125,9 @@ dbus_bool_t bus_connection_be_monitor (DBusConnection *connection,
1126 BusTransaction *transaction,
1129 +#ifdef DBUS_ENABLE_CYNARA
1130 +const char *bus_connection_get_cynara_session_id (DBusConnection *connection);
1133 /* transaction API so we can send or not send a block of messages as a whole */
1135 diff --git a/bus/cynara.c b/bus/cynara.c
1136 new file mode 100644
1137 index 0000000..57a4c45
1141 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1142 +/* cynara.c Cynara runtime privilege checking
1144 + * Copyright (c) 2014 Samsung Electronics, Ltd.
1146 + * Licensed under the Academic Free License version 2.1
1148 + * This program is free software; you can redistribute it and/or modify
1149 + * it under the terms of the GNU General Public License as published by
1150 + * the Free Software Foundation; either version 2 of the License, or
1151 + * (at your option) any later version.
1153 + * This program is distributed in the hope that it will be useful,
1154 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1155 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1156 + * GNU General Public License for more details.
1158 + * You should have received a copy of the GNU General Public License
1159 + * along with this program; if not, write to the Free Software
1160 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1164 +#include <config.h>
1165 +#include "cynara.h"
1171 +#include <dbus/dbus.h>
1172 +#include <dbus/dbus-watch.h>
1173 +#include <dbus/dbus-connection-internal.h>
1174 +#include <bus/connection.h>
1175 +#ifdef DBUS_ENABLE_CYNARA
1176 +#include <cynara-client-async.h>
1180 +#ifdef DBUS_ENABLE_CYNARA
1181 +typedef struct BusCynara
1185 + BusContext *context;
1187 + cynara_async *cynara;
1188 + DBusWatch *cynara_watch;
1191 +#define USE_CYNARA_CACHE 1
1192 +#ifdef USE_CYNARA_CACHE
1193 +#define CYNARA_CACHE_SIZE 1000
1196 +static dbus_bool_t bus_cynara_watch_callback(DBusWatch *watch,
1197 + unsigned int flags,
1200 +static void status_callback(int old_fd,
1202 + cynara_async_status status,
1203 + void *user_status_data);
1204 +static void bus_cynara_check_response_callback (cynara_check_id check_id,
1205 + cynara_async_call_cause cause,
1207 + void *user_response_data);
1212 +bus_cynara_new(BusCheck *check, DBusError *error)
1214 +#ifdef DBUS_ENABLE_CYNARA
1215 + BusContext *context;
1216 + BusCynara *cynara;
1217 + cynara_async_configuration *conf = NULL;
1220 + cynara = dbus_new(BusCynara, 1);
1221 + if (cynara == NULL)
1223 + BUS_SET_OOM(error);
1227 + context = bus_check_get_context(check);
1229 + cynara->refcount = 1;
1230 + cynara->check = check;
1231 + cynara->context = context;
1232 + cynara->cynara_watch = NULL;
1234 + ret = cynara_async_configuration_create(&conf);
1235 + if (ret != CYNARA_API_SUCCESS)
1237 + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to create Cynara configuration");
1241 +#ifdef CYNARA_CACHE_SIZE
1242 + ret = cynara_async_configuration_set_cache_size(conf, CYNARA_CACHE_SIZE);
1243 + if (ret != CYNARA_API_SUCCESS)
1245 + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to Cynara cache size");
1250 + ret = cynara_async_initialize(&cynara->cynara, conf, &status_callback, cynara);
1251 + if (ret != CYNARA_API_SUCCESS)
1253 + dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to initialize Cynara client");
1258 + cynara_async_configuration_destroy(conf);
1259 + if (ret != CYNARA_API_SUCCESS)
1261 + dbus_free(cynara);
1272 +bus_cynara_ref (BusCynara *cynara)
1274 +#ifdef DBUS_ENABLE_CYNARA
1275 + _dbus_assert (cynara->refcount > 0);
1276 + cynara->refcount += 1;
1285 +bus_cynara_unref (BusCynara *cynara)
1287 +#ifdef DBUS_ENABLE_CYNARA
1288 + _dbus_assert (cynara->refcount > 0);
1290 + cynara->refcount -= 1;
1292 + if (cynara->refcount == 0)
1294 + cynara_async_finish(cynara->cynara);
1295 + dbus_free(cynara);
1301 +bus_cynara_check_privilege (BusCynara *cynara,
1302 + DBusMessage *message,
1303 + DBusConnection *sender,
1304 + DBusConnection *addressed_recipient,
1305 + DBusConnection *proposed_recipient,
1306 + const char *privilege,
1307 + BusDeferredMessageStatus check_type,
1308 + BusDeferredMessage **deferred_message_param)
1310 +#ifdef DBUS_ENABLE_CYNARA
1312 + unsigned long uid;
1314 + const char *session_id;
1316 + cynara_check_id check_id;
1317 + DBusConnection *connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
1318 + BusDeferredMessage *deferred_message;
1321 + _dbus_assert(connection != NULL);
1323 + if (dbus_connection_get_unix_user(connection, &uid) == FALSE)
1324 + return BUS_RESULT_FALSE;
1326 + if (_dbus_connection_get_linux_security_label(connection, &label) == FALSE || label == NULL)
1328 + _dbus_warn("Failed to obtain security label for connection\n");
1329 + return BUS_RESULT_FALSE;
1332 + session_id = bus_connection_get_cynara_session_id (connection);
1333 + if (session_id == NULL)
1335 + ret = BUS_RESULT_FALSE;
1339 + snprintf(user, sizeof(user), "%lu", uid);
1341 +#if USE_CYNARA_CACHE
1342 + result = cynara_async_check_cache(cynara->cynara, label, session_id, user, privilege);
1344 + result = CYNARA_API_CACHE_MISS;
1349 + case CYNARA_API_ACCESS_ALLOWED:
1350 + _dbus_verbose("Cynara: got ALLOWED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n",
1351 + label, session_id, user, privilege);
1352 + ret = BUS_RESULT_TRUE;
1355 + case CYNARA_API_ACCESS_DENIED:
1356 + _dbus_verbose("Cynara: got DENIED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n",
1357 + label, session_id, user, privilege);
1358 + ret = BUS_RESULT_FALSE;
1361 + case CYNARA_API_CACHE_MISS:
1362 + deferred_message = bus_deferred_message_new(message, sender, addressed_recipient,
1363 + proposed_recipient, BUS_RESULT_LATER);
1364 + if (deferred_message == NULL)
1366 + _dbus_verbose("Failed to allocate memory for deferred message\n");
1367 + ret = BUS_RESULT_FALSE;
1371 + /* callback is supposed to unref deferred_message*/
1372 + result = cynara_async_create_request(cynara->cynara, label, session_id, user, privilege, &check_id,
1373 + &bus_cynara_check_response_callback, deferred_message);
1374 + if (result == CYNARA_API_SUCCESS)
1376 + _dbus_verbose("Created Cynara request: client=%s session_id=%s user=%s privilege=%s check_id=%u "
1377 + "deferred_message=%p\n", label, session_id, user, privilege, (unsigned int)check_id, deferred_message);
1378 + if (deferred_message_param != NULL)
1379 + *deferred_message_param = deferred_message;
1380 + ret = BUS_RESULT_LATER;
1384 + _dbus_verbose("Error on cynara request create: %i\n", result);
1385 + bus_deferred_message_unref(deferred_message);
1386 + ret = BUS_RESULT_FALSE;
1390 + _dbus_verbose("Error when accessing Cynara cache: %i\n", result);
1391 + ret = BUS_RESULT_FALSE;
1398 + return BUS_RESULT_FALSE;
1404 +#ifdef DBUS_ENABLE_CYNARA
1406 +status_callback(int old_fd, int new_fd, cynara_async_status status,
1407 + void *user_status_data)
1409 + BusCynara *cynara = (BusCynara *)user_status_data;
1410 + DBusLoop *loop = bus_context_get_loop(cynara->context);
1412 + if (cynara->cynara_watch != NULL)
1414 + _dbus_loop_remove_watch(loop, cynara->cynara_watch);
1415 + _dbus_watch_invalidate(cynara->cynara_watch);
1416 + _dbus_watch_unref(cynara->cynara_watch);
1417 + cynara->cynara_watch = NULL;
1422 + unsigned int flags;
1427 + case CYNARA_STATUS_FOR_READ:
1428 + flags = DBUS_WATCH_READABLE;
1430 + case CYNARA_STATUS_FOR_RW:
1431 + flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE;
1434 + /* Cynara passed unknown status - warn and add RW watch */
1435 + _dbus_verbose("Cynara passed unknown status value: 0x%08X\n", (unsigned int)status);
1436 + flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE;
1440 + watch = _dbus_watch_new(new_fd, flags, TRUE, &bus_cynara_watch_callback, cynara, NULL);
1441 + if (watch != NULL)
1443 + if (_dbus_loop_add_watch(loop, watch) == TRUE)
1445 + cynara->cynara_watch = watch;
1449 + _dbus_watch_invalidate(watch);
1450 + _dbus_watch_unref(watch);
1453 + /* It seems like not much can be done at this point. Cynara events won't be processed
1454 + * until next Cynara function call triggering status callback */
1455 + _dbus_verbose("Failed to add dbus watch\n");
1460 +bus_cynara_watch_callback(DBusWatch *watch,
1461 + unsigned int flags,
1464 + BusCynara *cynara = (BusCynara *)data;
1465 + int result = cynara_async_process(cynara->cynara);
1466 + if (result != CYNARA_API_SUCCESS)
1467 + _dbus_verbose("cynara_async_process returned %d\n", result);
1469 + return result != CYNARA_API_OUT_OF_MEMORY ? TRUE : FALSE;
1472 +static inline const char *
1473 +call_cause_to_string(cynara_async_call_cause cause)
1477 + case CYNARA_CALL_CAUSE_ANSWER:
1479 + case CYNARA_CALL_CAUSE_CANCEL:
1481 + case CYNARA_CALL_CAUSE_FINISH:
1483 + case CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE:
1484 + return "SERVICE NOT AVAILABLE";
1491 +bus_cynara_check_response_callback (cynara_check_id check_id,
1492 + cynara_async_call_cause cause,
1494 + void *user_response_data)
1496 + BusDeferredMessage *deferred_message = user_response_data;
1499 + _dbus_verbose("Cynara callback: check_id=%u, cause=%s response=%i response_data=%p\n",
1500 + (unsigned int)check_id, call_cause_to_string(cause), response, user_response_data);
1502 + if (deferred_message == NULL)
1505 + if (cause == CYNARA_CALL_CAUSE_ANSWER && response == CYNARA_API_ACCESS_ALLOWED)
1506 + result = BUS_RESULT_TRUE;
1508 + result = BUS_RESULT_FALSE;
1510 + bus_deferred_message_response_received(deferred_message, result);
1511 + bus_deferred_message_unref(deferred_message);
1514 +#endif /* DBUS_ENABLE_CYNARA */
1515 diff --git a/bus/cynara.h b/bus/cynara.h
1516 new file mode 100644
1517 index 0000000..c4728bb
1521 +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
1522 +/* cynara.h Cynara runtime privilege checking
1524 + * Copyright (c) 2014 Samsung Electronics, Ltd.
1526 + * Licensed under the Academic Free License version 2.1
1528 + * This program is free software; you can redistribute it and/or modify
1529 + * it under the terms of the GNU General Public License as published by
1530 + * the Free Software Foundation; either version 2 of the License, or
1531 + * (at your option) any later version.
1533 + * This program is distributed in the hope that it will be useful,
1534 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
1535 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
1536 + * GNU General Public License for more details.
1538 + * You should have received a copy of the GNU General Public License
1539 + * along with this program; if not, write to the Free Software
1540 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
1547 +BusCynara *bus_cynara_new (BusCheck *check, DBusError *error);
1548 +BusCynara *bus_cynara_ref (BusCynara *cynara);
1549 +void bus_cynara_unref (BusCynara *cynara);
1550 +BusResult bus_cynara_check_privilege (BusCynara *cynara,
1551 + DBusMessage *message,
1552 + DBusConnection *sender,
1553 + DBusConnection *addressed_recipient,
1554 + DBusConnection *proposed_recipient,
1555 + const char *privilege,
1556 + BusDeferredMessageStatus check_type,
1557 + BusDeferredMessage **deferred_message);
1558 diff --git a/bus/dispatch.c b/bus/dispatch.c
1559 index 19228be..7e51bc1 100644
1560 --- a/bus/dispatch.c
1561 +++ b/bus/dispatch.c
1565 #include "dispatch.h"
1567 #include "connection.h"
1569 #include "services.h"
1570 @@ -64,14 +65,18 @@ send_one_message (DBusConnection *connection,
1573 DBusError stack_error = DBUS_ERROR_INIT;
1574 + BusDeferredMessage *deferred_message;
1577 - if (!bus_context_check_security_policy (context, transaction,
1578 + result = bus_context_check_security_policy (context, transaction,
1580 addressed_recipient,
1586 + &deferred_message);
1587 + if (result != BUS_RESULT_TRUE)
1589 if (!bus_transaction_capture_error_reply (transaction, sender,
1590 &stack_error, message))
1591 @@ -130,6 +135,7 @@ bus_dispatch_matches (BusTransaction *transaction,
1592 BusMatchmaker *matchmaker;
1594 BusContext *context;
1595 + BusDeferredMessage *deferred_message;
1597 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
1599 @@ -145,11 +151,21 @@ bus_dispatch_matches (BusTransaction *transaction,
1600 /* First, send the message to the addressed_recipient, if there is one. */
1601 if (addressed_recipient != NULL)
1603 - if (!bus_context_check_security_policy (context, transaction,
1604 - sender, addressed_recipient,
1605 - addressed_recipient,
1606 - message, NULL, error))
1608 + res = bus_context_check_security_policy (context, transaction,
1609 + sender, addressed_recipient,
1610 + addressed_recipient,
1611 + message, NULL, error,
1612 + &deferred_message);
1613 + if (res == BUS_RESULT_FALSE)
1615 + else if (res == BUS_RESULT_LATER)
1617 + dbus_set_error (error,
1618 + DBUS_ERROR_ACCESS_DENIED,
1619 + "Rejecting message because time is needed to check security policy");
1623 if (dbus_message_contains_unix_fds (message) &&
1624 !dbus_connection_can_send_type (addressed_recipient,
1625 @@ -374,19 +390,32 @@ bus_dispatch (DBusConnection *connection,
1627 strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */
1629 + BusDeferredMessage *deferred_message;
1632 if (!bus_transaction_capture (transaction, connection, NULL, message))
1634 BUS_SET_OOM (&error);
1638 - if (!bus_context_check_security_policy (context, transaction,
1639 - connection, NULL, NULL, message,
1641 + res = bus_context_check_security_policy (context, transaction,
1642 + connection, NULL, NULL, message,
1644 + &deferred_message);
1645 + if (res == BUS_RESULT_FALSE)
1647 _dbus_verbose ("Security policy rejected message\n");
1650 + else if (res == BUS_RESULT_LATER)
1652 + dbus_set_error (&error,
1653 + DBUS_ERROR_ACCESS_DENIED,
1654 + "Rejecting message because time is needed to check security policy");
1655 + _dbus_verbose ("Security policy needs time to check policy. Dropping message\n");
1659 _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS);
1660 if (!bus_driver_handle_message (connection, transaction, message, &error))
1661 diff --git a/bus/policy.c b/bus/policy.c
1662 index a37be80..7ee1ce5 100644
1671 #include "services.h"
1676 bus_policy_rule_new (BusPolicyRuleType type,
1677 - dbus_bool_t allow)
1678 + BusPolicyRuleAccess access)
1680 BusPolicyRule *rule;
1682 @@ -43,7 +44,7 @@ bus_policy_rule_new (BusPolicyRuleType type,
1686 - rule->allow = allow;
1687 + rule->access = access;
1691 @@ -55,18 +56,19 @@ bus_policy_rule_new (BusPolicyRuleType type,
1693 case BUS_POLICY_RULE_SEND:
1694 rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID;
1696 /* allow rules default to TRUE (only requested replies allowed)
1697 + * check rules default to TRUE (only requested replies are checked)
1698 * deny rules default to FALSE (only unrequested replies denied)
1700 - rule->d.send.requested_reply = rule->allow;
1701 + rule->d.send.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY;
1703 case BUS_POLICY_RULE_RECEIVE:
1704 rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID;
1705 /* allow rules default to TRUE (only requested replies allowed)
1706 + * check rules default to TRUE (only requested replies are checked)
1707 * deny rules default to FALSE (only unrequested replies denied)
1709 - rule->d.receive.requested_reply = rule->allow;
1710 + rule->d.receive.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY;
1712 case BUS_POLICY_RULE_OWN:
1714 @@ -122,7 +124,8 @@ bus_policy_rule_unref (BusPolicyRule *rule)
1716 _dbus_assert_not_reached ("invalid rule");
1720 + dbus_free (rule->privilege);
1724 @@ -435,7 +438,10 @@ list_allows_user (dbus_bool_t def,
1728 - allowed = rule->allow;
1729 + /* We don't intend to support <check user="..." /> and <check group="..." />
1730 + rules. They are treated like deny.
1732 + allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW;
1736 @@ -873,18 +879,23 @@ bus_client_policy_append_rule (BusClientPolicy *policy,
1741 -bus_client_policy_check_can_send (BusClientPolicy *policy,
1742 - BusRegistry *registry,
1743 - dbus_bool_t requested_reply,
1744 - DBusConnection *receiver,
1745 - DBusMessage *message,
1746 - dbus_int32_t *toggles,
1749 +bus_client_policy_check_can_send (DBusConnection *sender,
1750 + BusClientPolicy *policy,
1751 + BusRegistry *registry,
1752 + dbus_bool_t requested_reply,
1753 + DBusConnection *addressed_recipient,
1754 + DBusConnection *receiver,
1755 + DBusMessage *message,
1756 + dbus_int32_t *toggles,
1758 + const char **privilege_param,
1759 + BusDeferredMessage **deferred_message)
1762 - dbus_bool_t allowed;
1765 + const char *privilege;
1767 /* policy->rules is in the order the rules appeared
1768 * in the config file, i.e. last rule that applies wins
1770 @@ -892,7 +903,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1771 _dbus_verbose (" (policy) checking send rules\n");
1775 + result = BUS_RESULT_FALSE;
1776 link = _dbus_list_get_first_link (&policy->rules);
1777 while (link != NULL)
1779 @@ -923,13 +934,14 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1780 /* If it's a reply, the requested_reply flag kicks in */
1781 if (dbus_message_get_reply_serial (message) != 0)
1783 - /* for allow, requested_reply=true means the rule applies
1784 - * only when reply was requested. requested_reply=false means
1786 + /* for allow or check requested_reply=true means the rule applies
1787 + * only when reply was requested. requested_reply=false means the
1788 + * rule always applies
1790 - if (!requested_reply && rule->allow && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
1791 + if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
1793 - _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
1794 + _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n",
1795 + rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check");
1799 @@ -937,7 +949,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1800 * when the reply was not requested. requested_reply=true means the
1801 * rule always applies.
1803 - if (requested_reply && !rule->allow && !rule->d.send.requested_reply)
1804 + if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.send.requested_reply)
1806 _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n");
1808 @@ -960,13 +972,15 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1809 /* The interface is optional in messages. For allow rules, if the message
1810 * has no interface we want to skip the rule (and thus not allow);
1811 * for deny rules, if the message has no interface we want to use the
1812 - * rule (and thus deny).
1813 + * rule (and thus deny). Check rules are meant to be used like allow
1814 + * rules (they can grant access, but not remove it), so we treat it like
1817 dbus_bool_t no_interface;
1819 no_interface = dbus_message_get_interface (message) == NULL;
1821 - if ((no_interface && rule->allow) ||
1822 + if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) ||
1824 strcmp (dbus_message_get_interface (message),
1825 rule->d.send.interface) != 0))
1826 @@ -1079,33 +1093,63 @@ bus_client_policy_check_can_send (BusClientPolicy *policy,
1830 - allowed = rule->allow;
1831 + switch (rule->access)
1833 + case BUS_POLICY_RULE_ACCESS_ALLOW:
1834 + result = BUS_RESULT_TRUE;
1836 + case BUS_POLICY_RULE_ACCESS_DENY:
1837 + result = BUS_RESULT_FALSE;
1839 + case BUS_POLICY_RULE_ACCESS_CHECK:
1840 + result = BUS_RESULT_LATER;
1841 + privilege = rule->privilege;
1845 *log = rule->d.send.log;
1848 - _dbus_verbose (" (policy) used rule, allow now = %d\n",
1850 + _dbus_verbose (" (policy) used rule, result now = %d\n",
1851 + (int)(intptr_t)result);
1855 + if (result == BUS_RESULT_LATER)
1857 + BusContext *context = bus_connection_get_context(sender);
1858 + BusCheck *check = bus_context_get_check(context);
1860 + result = bus_check_privilege(check, message, sender, addressed_recipient, receiver,
1861 + privilege, BUS_DEFERRED_MESSAGE_CHECK_SEND, deferred_message);
1866 + if (privilege_param != NULL)
1867 + *privilege_param = privilege;
1872 /* See docs on what the args mean on bus_context_check_security_policy()
1876 -bus_client_policy_check_can_receive (BusClientPolicy *policy,
1877 - BusRegistry *registry,
1878 - dbus_bool_t requested_reply,
1879 - DBusConnection *sender,
1880 - DBusConnection *addressed_recipient,
1881 - DBusConnection *proposed_recipient,
1882 - DBusMessage *message,
1883 - dbus_int32_t *toggles)
1885 +bus_client_policy_check_can_receive (BusClientPolicy *policy,
1886 + BusRegistry *registry,
1887 + dbus_bool_t requested_reply,
1888 + DBusConnection *sender,
1889 + DBusConnection *addressed_recipient,
1890 + DBusConnection *proposed_recipient,
1891 + DBusMessage *message,
1892 + dbus_int32_t *toggles,
1893 + const char **privilege_param,
1894 + BusDeferredMessage **deferred_message)
1897 - dbus_bool_t allowed;
1898 dbus_bool_t eavesdropping;
1900 + const char *privilege;
1903 addressed_recipient != proposed_recipient &&
1904 @@ -1118,7 +1162,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1905 _dbus_verbose (" (policy) checking receive rules, eavesdropping = %d\n", eavesdropping);
1909 + result = BUS_RESULT_FALSE;
1910 link = _dbus_list_get_first_link (&policy->rules);
1911 while (link != NULL)
1913 @@ -1141,19 +1185,21 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1917 - /* for allow, eavesdrop=false means the rule doesn't apply when
1918 - * eavesdropping. eavesdrop=true means always allow.
1920 + /* for allow or check, eavesdrop=false means the rule doesn't apply when
1921 + * eavesdropping. eavesdrop=true means the rule always applies
1923 - if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop)
1924 + if (eavesdropping && rule->access != BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.eavesdrop)
1926 - _dbus_verbose (" (policy) skipping allow rule since it doesn't apply to eavesdropping\n");
1927 + _dbus_verbose (" (policy) skipping %s rule since it doesn't apply to eavesdropping\n",
1928 + rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check");
1932 /* for deny, eavesdrop=true means the rule applies only when
1933 * eavesdropping; eavesdrop=false means always deny.
1935 - if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop)
1936 + if (!eavesdropping && rule->access == BUS_POLICY_RULE_ACCESS_DENY && rule->d.receive.eavesdrop)
1938 _dbus_verbose (" (policy) skipping deny rule since it only applies to eavesdropping\n");
1940 @@ -1162,13 +1208,14 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1941 /* If it's a reply, the requested_reply flag kicks in */
1942 if (dbus_message_get_reply_serial (message) != 0)
1944 - /* for allow, requested_reply=true means the rule applies
1945 - * only when reply was requested. requested_reply=false means
1947 + /* for allow or check requested_reply=true means the rule applies
1948 + * only when reply was requested. requested_reply=false means the
1949 + * rule always applies
1951 - if (!requested_reply && rule->allow && rule->d.receive.requested_reply && !rule->d.receive.eavesdrop)
1952 + if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop)
1954 - _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n");
1955 + _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n",
1956 + rule->access == BUS_POLICY_RULE_ACCESS_DENY ? "allow" : "deny");
1960 @@ -1176,7 +1223,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1961 * when the reply was not requested. requested_reply=true means the
1962 * rule always applies.
1964 - if (requested_reply && !rule->allow && !rule->d.receive.requested_reply)
1965 + if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.requested_reply)
1967 _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n");
1969 @@ -1199,13 +1246,13 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1970 /* The interface is optional in messages. For allow rules, if the message
1971 * has no interface we want to skip the rule (and thus not allow);
1972 * for deny rules, if the message has no interface we want to use the
1973 - * rule (and thus deny).
1974 + * rule (and thus deny). Check rules are treated like allow rules.
1976 dbus_bool_t no_interface;
1978 no_interface = dbus_message_get_interface (message) == NULL;
1980 - if ((no_interface && rule->allow) ||
1981 + if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) ||
1983 strcmp (dbus_message_get_interface (message),
1984 rule->d.receive.interface) != 0))
1985 @@ -1295,14 +1342,42 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy,
1989 - allowed = rule->allow;
1990 + switch (rule->access)
1992 + case BUS_POLICY_RULE_ACCESS_ALLOW:
1993 + result = BUS_RESULT_TRUE;
1995 + case BUS_POLICY_RULE_ACCESS_DENY:
1996 + result = BUS_RESULT_FALSE;
1998 + case BUS_POLICY_RULE_ACCESS_CHECK:
1999 + result = BUS_RESULT_LATER;
2000 + privilege = rule->privilege;
2006 - _dbus_verbose (" (policy) used rule, allow now = %d\n",
2008 + _dbus_verbose (" (policy) used rule, result now = %d\n",
2009 + (int)(intptr_t)result);
2014 + if (result == BUS_RESULT_LATER)
2016 + BusContext *context = bus_connection_get_context(proposed_recipient);
2017 + BusCheck *check = bus_context_get_check(context);
2019 + result = bus_check_privilege(check, message, sender, addressed_recipient, proposed_recipient,
2020 + privilege, BUS_DEFERRED_MESSAGE_CHECK_RECEIVE, deferred_message);
2025 + if (privilege_param != NULL)
2026 + *privilege_param = privilege;
2032 @@ -1354,7 +1429,7 @@ bus_rules_check_can_own (DBusList *rules,
2036 - allowed = rule->allow;
2037 + allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW;
2041 diff --git a/bus/policy.h b/bus/policy.h
2042 index ec43ffa..f306a3c 100644
2045 @@ -46,6 +46,14 @@ typedef enum
2046 BUS_POLICY_TRISTATE_TRUE
2047 } BusPolicyTristate;
2051 + BUS_POLICY_RULE_ACCESS_DENY,
2052 + BUS_POLICY_RULE_ACCESS_ALLOW,
2053 + /** runtime check resulting in allow or deny */
2054 + BUS_POLICY_RULE_ACCESS_CHECK
2055 +} BusPolicyRuleAccess;
2057 /** determines whether the rule affects a connection, or some global item */
2058 #define BUS_POLICY_RULE_IS_PER_CLIENT(rule) (!((rule)->type == BUS_POLICY_RULE_USER || \
2059 (rule)->type == BUS_POLICY_RULE_GROUP))
2060 @@ -56,8 +64,9 @@ struct BusPolicyRule
2062 BusPolicyRuleType type;
2064 - unsigned int allow : 1; /**< #TRUE if this allows, #FALSE if it denies */
2066 + unsigned int access : 2; /**< BusPolicyRuleAccess */
2067 + char *privilege; /**< for BUS_POLICY_RULE_ACCESS_CHECK */
2072 @@ -118,7 +127,7 @@ struct BusPolicyRule
2075 BusPolicyRule* bus_policy_rule_new (BusPolicyRuleType type,
2076 - dbus_bool_t allow);
2077 + BusPolicyRuleAccess access);
2078 BusPolicyRule* bus_policy_rule_ref (BusPolicyRule *rule);
2079 void bus_policy_rule_unref (BusPolicyRule *rule);
2081 @@ -152,21 +161,27 @@ dbus_bool_t bus_policy_merge (BusPolicy *policy,
2082 BusClientPolicy* bus_client_policy_new (void);
2083 BusClientPolicy* bus_client_policy_ref (BusClientPolicy *policy);
2084 void bus_client_policy_unref (BusClientPolicy *policy);
2085 -dbus_bool_t bus_client_policy_check_can_send (BusClientPolicy *policy,
2086 - BusRegistry *registry,
2087 - dbus_bool_t requested_reply,
2088 - DBusConnection *receiver,
2089 - DBusMessage *message,
2090 - dbus_int32_t *toggles,
2091 - dbus_bool_t *log);
2092 -dbus_bool_t bus_client_policy_check_can_receive (BusClientPolicy *policy,
2093 - BusRegistry *registry,
2094 - dbus_bool_t requested_reply,
2095 - DBusConnection *sender,
2096 - DBusConnection *addressed_recipient,
2097 - DBusConnection *proposed_recipient,
2098 - DBusMessage *message,
2099 - dbus_int32_t *toggles);
2100 +BusResult bus_client_policy_check_can_send (DBusConnection *sender,
2101 + BusClientPolicy *policy,
2102 + BusRegistry *registry,
2103 + dbus_bool_t requested_reply,
2104 + DBusConnection *addressed_recipient,
2105 + DBusConnection *receiver,
2106 + DBusMessage *message,
2107 + dbus_int32_t *toggles,
2109 + const char **privilege_param,
2110 + BusDeferredMessage **deferred_message);
2111 +BusResult bus_client_policy_check_can_receive (BusClientPolicy *policy,
2112 + BusRegistry *registry,
2113 + dbus_bool_t requested_reply,
2114 + DBusConnection *sender,
2115 + DBusConnection *addressed_recipient,
2116 + DBusConnection *proposed_recipient,
2117 + DBusMessage *message,
2118 + dbus_int32_t *toggles,
2119 + const char **privilege_param,
2120 + BusDeferredMessage **deferred_message);
2121 dbus_bool_t bus_client_policy_check_can_own (BusClientPolicy *policy,
2122 const DBusString *service_name);
2123 dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy,
2124 diff --git a/configure.ac b/configure.ac
2125 index 80671b2..d975b04 100644
2128 @@ -1761,6 +1761,17 @@ AC_ARG_ENABLE([user-session],
2129 AM_CONDITIONAL([DBUS_ENABLE_USER_SESSION],
2130 [test "x$enable_user_session" = xyes])
2132 +#enable cynara integration
2133 +AC_ARG_ENABLE([cynara], [AS_HELP_STRING([--enable-cynara], [enable Cynara integration])], [], [enable_cynara=no])
2134 +if test "x$enable_cynara" = xyes; then
2135 + PKG_CHECK_MODULES([CYNARA], [cynara-client-async >= 0.6.0 cynara-session >= 0.6.0],
2136 + [AC_DEFINE([DBUS_ENABLE_CYNARA], [1], [Define to enable Cynara privilege checks in dbus-daemon])],
2137 + [AC_MSG_ERROR([libcynara-client-async and cynara-session are required to enable Cynara integration])])
2140 +AC_SUBST([CYNARA_CFLAGS])
2141 +AC_SUBST([CYNARA_LIBS])
2146 @@ -1843,6 +1854,7 @@ echo "
2147 Building bus stats API: ${enable_stats}
2148 Building SELinux support: ${have_selinux}
2149 Building AppArmor support: ${have_apparmor}
2150 + Building Cynara support: ${enable_cynara}
2151 Building inotify support: ${have_inotify}
2152 Building kqueue support: ${have_kqueue}
2153 Building systemd support: ${have_systemd}
2154 diff --git a/test/Makefile.am b/test/Makefile.am
2155 index 6a6e1a3..ce84dbc 100644
2156 --- a/test/Makefile.am
2157 +++ b/test/Makefile.am
2158 @@ -439,6 +439,7 @@ in_data = \
2159 data/valid-config-files/debug-allow-all.conf.in \
2160 data/valid-config-files/finite-timeout.conf.in \
2161 data/valid-config-files/forbidding.conf.in \
2162 + data/valid-config-files/debug-check-some.conf.in \
2163 data/valid-config-files/incoming-limit.conf.in \
2164 data/valid-config-files/max-completed-connections.conf.in \
2165 data/valid-config-files/max-connections-per-user.conf.in \
2166 diff --git a/test/data/invalid-config-files/badcheck-1.conf b/test/data/invalid-config-files/badcheck-1.conf
2167 new file mode 100644
2168 index 0000000..fad9f50
2170 +++ b/test/data/invalid-config-files/badcheck-1.conf
2172 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2173 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2175 + <user>mybususer</user>
2176 + <listen>unix:path=/foo/bar</listen>
2177 + <policy context="default">
2178 + <allow privilege="foo" send_destination="*"/> <!-- extra privilege="foo" -->
2181 diff --git a/test/data/invalid-config-files/badcheck-2.conf b/test/data/invalid-config-files/badcheck-2.conf
2182 new file mode 100644
2183 index 0000000..63c7ef2
2185 +++ b/test/data/invalid-config-files/badcheck-2.conf
2187 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2188 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2190 + <user>mybususer</user>
2191 + <listen>unix:path=/foo/bar</listen>
2192 + <policy context="default">
2193 + <check send_destination="*"/> <!-- missing privilege="foo" -->
2196 diff --git a/test/data/valid-config-files/check-1.conf b/test/data/valid-config-files/check-1.conf
2197 new file mode 100644
2198 index 0000000..ad71473
2200 +++ b/test/data/valid-config-files/check-1.conf
2202 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2203 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2205 + <user>mybususer</user>
2206 + <listen>unix:path=/foo/bar</listen>
2207 + <policy context="default">
2208 + <check privilege="foo" send_destination="*"/>
2211 diff --git a/test/data/valid-config-files/debug-check-some.conf.in b/test/data/valid-config-files/debug-check-some.conf.in
2212 new file mode 100644
2213 index 0000000..47ee854
2215 +++ b/test/data/valid-config-files/debug-check-some.conf.in
2217 +<!-- Bus that listens on a debug pipe and doesn't create any restrictions -->
2219 +<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN"
2220 + "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd">
2222 + <listen>debug-pipe:name=test-server</listen>
2223 + <listen>@TEST_LISTEN@</listen>
2224 + <servicedir>@DBUS_TEST_DATA@/valid-service-files</servicedir>
2225 + <policy context="default">
2226 + <allow send_interface="*"/>
2227 + <allow receive_interface="*"/>
2231 + <deny send_interface="org.freedesktop.TestSuite" send_member="Echo"/>
2232 + <check privilege="foo" send_interface="org.freedesktop.TestSuite" send_member="Echo"/>