dbus_bool_t requested_reply;
const char *privilege;
char *out_rule = NULL;
+ BusResult can_send_result;
type = dbus_message_get_type (message);
src = dbus_message_get_sender (message);
log = FALSE;
if (sender_policy) {
- switch (bus_client_policy_check_can_send (sender,
- sender_policy,
- context->registry,
- requested_reply,
- addressed_recipient,
- proposed_recipient,
- message, &toggles, &log, &privilege,
- deferred_message, &out_rule))
+ can_send_result = bus_client_policy_check_can_send (sender,
+ sender_policy,
+ context->registry,
+ requested_reply,
+ addressed_recipient,
+ proposed_recipient,
+ message, &toggles, &log, &privilege,
+ deferred_message, &out_rule);
+ if (can_send_result == BUS_RESULT_FALSE)
{
- case BUS_RESULT_TRUE:
- break;
- case BUS_RESULT_FALSE:
complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
"Rejected send message", toggles,
message, sender, proposed_recipient, requested_reply,
if (out_rule)
free (out_rule);
return BUS_RESULT_FALSE;
- break;
- case BUS_RESULT_LATER:
- return BUS_RESULT_LATER;
- break;
}
}
"security policy disallowing message due to recipient policy\n");
if (out_rule)
free (out_rule);
+ if (deferred_message && *deferred_message)
+ bus_deferred_message_set_response (*deferred_message, BUS_RESULT_FALSE);
return BUS_RESULT_FALSE;
case BUS_RESULT_LATER:
return BUS_RESULT_LATER;
}
}
+ if (can_send_result == BUS_RESULT_LATER)
+ return BUS_RESULT_LATER;
+
/* See if limits on size have been exceeded */
if (!bus_context_check_recipient_message_limits(context, proposed_recipient, sender, message,
requested_reply, error))
static void
bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message,
+ BusDeferredMessageStatus check_type,
BusResult result)
{
_dbus_verbose("bus_check_enable_dispatch_callback called deferred_message=%p\n", deferred_message);
static void
bus_check_queued_message_reply_callback (BusDeferredMessage *deferred_message,
+ BusDeferredMessageStatus check_type,
BusResult result)
{
- int status;
-
_dbus_verbose("bus_check_queued_message_reply_callback called message=%p\n", deferred_message);
if (!(dbus_connection_get_is_connected(deferred_message->proposed_recipient)
&& bus_connection_is_active(deferred_message->proposed_recipient)))
return;
- status = deferred_message->status;
-
- deferred_message->status = 0; /* mark message as not waiting for response */
- deferred_message->response = result;
+ deferred_message->status &= ~check_type; /* mark message as not waiting for response of this type*/
+ if (deferred_message->response != BUS_RESULT_FALSE)
+ deferred_message->response = result;
- /*
- * If send rule allows us to send message we still need to check receive rules.
- */
- if ((status & BUS_DEFERRED_MESSAGE_CHECK_SEND) && (result == BUS_RESULT_TRUE))
- {
- int toggles;
- BusContext *context;
- BusRegistry *registry;
- BusClientPolicy *recipient_policy;
- BusDeferredMessage *deferred_message_receive = NULL;
-
- context = bus_connection_get_context(deferred_message->proposed_recipient);
- registry = bus_context_get_registry(context);
- recipient_policy = bus_connection_get_policy(deferred_message->proposed_recipient);
-
- deferred_message->response = bus_client_policy_check_can_receive(recipient_policy, registry,
- deferred_message->requested_reply, deferred_message->sender,
- deferred_message->addressed_recipient, deferred_message->proposed_recipient, deferred_message->message,
- &toggles, NULL, &deferred_message_receive, NULL);
- if (deferred_message->response == BUS_RESULT_LATER)
- {
- /* replace deferred message associated with send check with the one associated with
- * receive check */
- if (!bus_deferred_message_replace(deferred_message, deferred_message_receive))
- {
- /* failed to replace deferred message (due to oom). Set it to rejected */
- deferred_message->response = BUS_RESULT_FALSE;
- }
- }
- }
+ _dbus_assert (deferred_message->response != BUS_RESULT_LATER || deferred_message->status != 0);
- bus_connection_dispatch_deferred(deferred_message->proposed_recipient);
+ if (!deferred_message->status)
+ bus_connection_dispatch_deferred(deferred_message->proposed_recipient);
}
static void
int type = dbus_message_get_type(deferred_message->message);
if (type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
deferred_message->sender &&
+ dbus_connection_get_is_connected(deferred_message->sender) &&
+ bus_connection_is_active(deferred_message->sender) &&
deferred_message->addressed_recipient &&
deferred_message->addressed_recipient == deferred_message->proposed_recipient && /* not eavesdropping */
!bus_connections_expect_reply (bus_connection_get_connections (deferred_message->sender),
goto out;
}
- /* do not attempt to send message if sender has disconnected */
- if (deferred_message->sender != NULL && !(dbus_connection_get_is_connected(deferred_message->sender) && bus_connection_is_active(deferred_message->sender)))
- {
- bus_transaction_cancel_and_free(transaction);
- result = BUS_RESULT_FALSE;
- goto out;
- }
-
result = bus_dispatch_matches(transaction, deferred_message->sender,
deferred_message->addressed_recipient, deferred_message->message, deferred_message, &error);
}
dbus_bool_t
-bus_deferred_message_replace (BusDeferredMessage *old_message, BusDeferredMessage *new_message)
-{
- if (bus_connection_replace_deferred_message(old_message->proposed_recipient,
- old_message, new_message))
- {
- new_message->response_callback = old_message->response_callback;
- new_message->full_dispatch = old_message->full_dispatch;
- return TRUE;
- }
- return FALSE;
-}
-
-dbus_bool_t
bus_deferred_message_waits_for_check(BusDeferredMessage *deferred_message)
{
return deferred_message->status != 0;
}
void
+bus_deferred_message_set_response (BusDeferredMessage *deferred_message, BusResult response)
+{
+ return deferred_message->response = response;
+}
+
+void
bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
+ BusDeferredMessageStatus check_type,
BusResult result)
{
if (deferred_message->response_callback != NULL)
{
- deferred_message->response_callback(deferred_message, result);
+ deferred_message->response_callback(deferred_message, check_type, result);
}
}
#include "policy.h"
-typedef void (*BusCheckResponseFunc) (BusDeferredMessage *message,
- BusResult result);
-
typedef enum {
BUS_DEFERRED_MESSAGE_CHECK_SEND = 1 << 0,
BUS_DEFERRED_MESSAGE_CHECK_RECEIVE = 1 << 1,
BUS_DEFERRED_MESSAGE_CHECK_OWN = 1 << 2,
} BusDeferredMessageStatus;
+typedef void (*BusCheckResponseFunc) (BusDeferredMessage *message,
+ BusDeferredMessageStatus check_type,
+ BusResult result);
BusCheck *bus_check_new (BusContext *context,
DBusError *error);
dbus_bool_t bus_deferred_message_waits_for_check (BusDeferredMessage *deferred_message);
DBusConnection *bus_deferred_message_get_recipient (BusDeferredMessage *deferred_message);
void bus_deferred_message_response_received (BusDeferredMessage *deferred_message,
+ BusDeferredMessageStatus check_type,
BusResult result);
dbus_bool_t bus_deferred_message_queue_at_recipient (BusDeferredMessage *deferred_message,
BusTransaction *transaction,
dbus_bool_t full_dispatch,
dbus_bool_t prepend);
-dbus_bool_t bus_deferred_message_replace (BusDeferredMessage *old_message,
- BusDeferredMessage *new_message);
void bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message);
BusResult bus_deferred_message_get_response (BusDeferredMessage *deferred_message);
+void bus_deferred_message_set_response (BusDeferredMessage *deferred_message,
+ BusResult response);
BusDeferredMessageStatus bus_deferred_message_get_status (BusDeferredMessage *deferred_message);
return FALSE;
}
-dbus_bool_t
-bus_connection_replace_deferred_message (DBusConnection *connection,
- BusDeferredMessage *oldMessage,
- BusDeferredMessage *newMessage)
-{
- DBusList *link;
- BusConnectionData *d = BUS_CONNECTION_DATA(connection);
-
- _dbus_assert (d != NULL);
-
- link = _dbus_list_find_first(&d->deferred_messages, oldMessage);
- if (link == NULL)
- return FALSE;
-
- if (!_dbus_list_insert_after(&d->deferred_messages, link, newMessage))
- return FALSE;
-
- bus_deferred_message_ref(newMessage);
- _dbus_list_remove_link(&d->deferred_messages, link);
- bus_deferred_message_unref(oldMessage);
- return TRUE;
-}
-
BusDeferredMessage *
bus_connection_pop_deferred_message (DBusConnection *connection)
{
BusDeferredMessage *message);
void bus_connection_remove_deferred_message (DBusConnection *connection,
BusDeferredMessage *message);
-dbus_bool_t bus_connection_replace_deferred_message (DBusConnection *connection,
- BusDeferredMessage *oldMessage,
- BusDeferredMessage *newMessage);
void bus_connection_dispatch_deferred (DBusConnection *connection);
void bus_connection_clear_deferred_messages (DBusConnection *connection);
DBusWatch *cynara_watch;
} BusCynara;
+typedef struct BusCynaraCheckData
+{
+ BusDeferredMessage *deferred_message;
+ BusDeferredMessageStatus check_type;
+} BusCynaraCheckData;
+
static dbus_bool_t bus_cynara_watch_callback(DBusWatch *watch,
unsigned int flags,
void *data);
void *user_response_data);
#endif
+static BusCynaraCheckData *
+bus_cynara_check_data_new(BusDeferredMessage *deferred_message, BusDeferredMessageStatus check_type)
+{
+ BusCynaraCheckData *data;
+
+ data = dbus_new(BusCynaraCheckData, 1);
+ if (data == NULL)
+ return NULL;
+
+ data->deferred_message = deferred_message;
+ data->check_type = check_type;
+
+ return data;
+}
BusCynara *
bus_cynara_new(BusCheck *check, DBusError *error)
char user[32];
cynara_check_id check_id;
DBusConnection *connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender;
- BusDeferredMessage *deferred_message;
+ BusDeferredMessage *deferred_message = NULL;
BusResult return_result;
+ BusCynaraCheckData *callback_data;
_dbus_assert(connection != NULL);
bus_deferred_message_ref(deferred_message);
}
- /* callback is supposed to unref deferred_message*/
+ callback_data = bus_cynara_check_data_new(deferred_message, check_type);
+ if (callback_data == NULL)
+ {
+ _dbus_verbose("Failed to allocate memory for deferred message callback data\n");
+ return_result = BUS_RESULT_FALSE;
+ }
+
+ /* callback is supposed to unref deferred_message and free callback_data */
result = cynara_async_create_request(cynara->cynara, label, session_id, user, privilege, &check_id,
- &bus_cynara_check_response_callback, deferred_message);
+ &bus_cynara_check_response_callback, callback_data);
if (result == CYNARA_API_SUCCESS)
{
_dbus_verbose("Created Cynara request: client=%s session_id=%s user=%s privilege=%s check_id=%u "
int response,
void *user_response_data)
{
- BusDeferredMessage *deferred_message = user_response_data;
+ BusCynaraCheckData *check_data = user_response_data;
+ BusDeferredMessage *deferred_message;
BusResult result;
+ BusDeferredMessageStatus check_type;
_dbus_verbose("Cynara callback: check_id=%u, cause=%s response=%i response_data=%p\n",
(unsigned int)check_id, call_cause_to_string(cause), response, user_response_data);
+ if (check_data == NULL)
+ return;
+
+ deferred_message = check_data->deferred_message;
+ check_type = check_data->check_type;
+
+ dbus_free(check_data);
+
if (deferred_message == NULL)
return;
else
result = BUS_RESULT_FALSE;
- bus_deferred_message_response_received(deferred_message, result);
+ bus_deferred_message_response_received(deferred_message, check_type, result);
bus_deferred_message_unref(deferred_message);
}
* or for signals with no particular recipient
*/
- _dbus_assert (sender == NULL || bus_connection_is_active (sender));
+ /*
+ * With deferred messages, dispatch may happen when there is no sender anymore.
+ * Policy rules involving the sender should be checked before, anyway.
+ */
+/* _dbus_assert (sender == NULL || bus_connection_is_active (sender)); */
_dbus_assert (dbus_message_get_sender (message) != NULL);
context = bus_transaction_get_context (transaction);
*/
if (dispatched_deferred_message == NULL && bus_connection_has_deferred_messages(addressed_recipient))
{
- deferred_message = bus_deferred_message_new(message, sender,
- addressed_recipient, addressed_recipient, BUS_RESULT_LATER);
+ result = bus_context_check_security_policy(context, transaction,
+ sender, addressed_recipient, addressed_recipient, message, NULL, error,
+ &deferred_message);
+
+ if (deferred_message == NULL)
+ deferred_message = bus_deferred_message_new(message, sender,
+ addressed_recipient, addressed_recipient, result);
+ else
+ bus_deferred_message_ref(deferred_message);
if (deferred_message == NULL)
{