#include "apparmor.h"
#include "audit.h"
#include "dir-watch.h"
+#include "check.h"
#include <dbus/dbus-auth.h>
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
BusRegistry *registry;
BusPolicy *policy;
BusMatchmaker *matchmaker;
+ BusCheck *check;
BusLimits limits;
DBusRLimit *initial_fd_limit;
unsigned int fork : 1;
parser = NULL;
}
+ context->check = bus_check_new(context, error);
+ if (context->check == NULL)
+ goto failed;
+
dbus_server_free_data_slot (&server_data_slot);
return context;
bus_context_shutdown (context);
+ if (context->check)
+ {
+ bus_check_unref(context->check);
+ context->check = NULL;
+ }
+
if (context->connections)
{
bus_connections_unref (context->connections);
return context->loop;
}
+BusCheck*
+bus_context_get_check (BusContext *context)
+{
+ return context->check;
+}
+
dbus_bool_t
bus_context_allow_unix_user (BusContext *context,
unsigned long uid)
DBusConnection *proposed_recipient,
dbus_bool_t requested_reply,
dbus_bool_t log,
- DBusError *error)
+ const char *privilege,
+ DBusError *error,
+ const char *rule)
{
DBusError stack_error = DBUS_ERROR_INIT;
const char *sender_name;
dbus_set_error (&stack_error, error_name,
"%s, %d matched rules; type=\"%s\", sender=\"%s\" (%s) "
"interface=\"%s\" member=\"%s\" error name=\"%s\" "
- "requested_reply=\"%d\" destination=\"%s\" (%s)",
+ "requested_reply=\"%d\" destination=\"%s\" "
+ "privilege=\"%s\" (%s) "
+ "rule(%s)",
complaint,
matched_rules,
dbus_message_type_to_string (dbus_message_get_type (message)),
nonnull (dbus_message_get_error_name (message), "(unset)"),
requested_reply,
nonnull (dbus_message_get_destination (message), DBUS_SERVICE_DBUS),
- proposed_recipient_loginfo);
+ nonnull (privilege, "(n/a)"),
+ proposed_recipient_loginfo,
+ rule);
/* If we hit OOM while setting the error, this will syslog "out of memory"
* which is itself an indication that something is seriously wrong */
* NULL for addressed_recipient may mean the bus driver, or may mean
* no destination was specified in the message (e.g. a signal).
*/
-dbus_bool_t
-bus_context_check_security_policy (BusContext *context,
- BusTransaction *transaction,
- DBusConnection *sender,
- DBusConnection *addressed_recipient,
- DBusConnection *proposed_recipient,
- DBusMessage *message,
- BusActivationEntry *activation_entry,
- DBusError *error)
+BusResult
+bus_context_check_security_policy (BusContext *context,
+ BusTransaction *transaction,
+ DBusConnection *sender,
+ DBusConnection *addressed_recipient,
+ DBusConnection *proposed_recipient,
+ DBusMessage *message,
+ BusActivationEntry *activation_entry,
+ DBusError *error,
+ BusDeferredMessage **deferred_message)
{
const char *src, *dest;
BusClientPolicy *sender_policy;
dbus_bool_t log;
int type;
dbus_bool_t requested_reply;
+ const char *privilege;
+ char *out_rule = NULL;
+ BusResult can_send_result = BUS_RESULT_TRUE;
type = dbus_message_get_type (message);
src = dbus_message_get_sender (message);
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
"Message bus will not accept messages of unknown type\n");
- return FALSE;
+ return BUS_RESULT_FALSE;
}
requested_reply = FALSE;
if (dbus_error_is_set (&error2))
{
dbus_move_error (&error2, error);
- return FALSE;
+ return BUS_RESULT_FALSE;
}
}
}
complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
"An SELinux policy prevents this sender from sending this "
"message to this recipient",
- 0, message, sender, proposed_recipient, FALSE, FALSE, error);
+ 0, message, sender, proposed_recipient, FALSE, FALSE, NULL, error, NULL);
_dbus_verbose ("SELinux security check denying send to service\n");
}
{
_dbus_verbose ("security check allowing %s message\n",
"Hello");
- return TRUE;
+ return BUS_RESULT_TRUE;
}
else
{
"Client tried to send a message other than %s without being registered",
"Hello");
- return FALSE;
+ return BUS_RESULT_FALSE;
}
}
}
(proposed_recipient == NULL && recipient_policy == NULL));
log = FALSE;
- if (sender_policy &&
- !bus_client_policy_check_can_send (sender_policy,
- context->registry,
- requested_reply,
- proposed_recipient,
- message, &toggles, &log))
- {
- complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
- "Rejected send message", toggles,
- message, sender, proposed_recipient, requested_reply,
- (addressed_recipient == proposed_recipient), error);
- _dbus_verbose ("security policy disallowing message due to sender policy\n");
- return FALSE;
- }
+ if (sender_policy) {
+ 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)
+ {
+ complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
+ "Rejected send message", toggles,
+ message, sender, proposed_recipient, requested_reply,
+ (addressed_recipient == proposed_recipient) || (type == DBUS_MESSAGE_TYPE_SIGNAL),
+ privilege,
+ error, out_rule);
+ _dbus_verbose ("security policy disallowing message due to sender policy\n");
+ if (out_rule)
+ free (out_rule);
+ return BUS_RESULT_FALSE;
+ }
+ }
if (log)
{
complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
"Would reject message", toggles,
message, sender, proposed_recipient, requested_reply,
- TRUE, NULL);
+ TRUE, privilege, NULL, NULL);
}
- if (recipient_policy &&
- !bus_client_policy_check_can_receive (recipient_policy,
- context->registry,
- requested_reply,
- sender,
- addressed_recipient, proposed_recipient,
- message, &toggles))
- {
- complain_about_message (context, DBUS_ERROR_ACCESS_DENIED,
- "Rejected receive message", toggles,
- message, sender, proposed_recipient, requested_reply,
- (addressed_recipient == proposed_recipient), error);
- _dbus_verbose ("security policy disallowing message due to recipient policy\n");
- return FALSE;
- }
+ if (recipient_policy) {
+ switch (bus_client_policy_check_can_receive (recipient_policy,
+ context->registry,
+ requested_reply,
+ sender,
+ addressed_recipient, proposed_recipient,
+ message, &toggles, &privilege, deferred_message, &out_rule))
+ {
+ case BUS_RESULT_TRUE:
+ break;
+ case BUS_RESULT_FALSE:
+ complain_about_message(context, DBUS_ERROR_ACCESS_DENIED,
+ "Rejected receive message", toggles, message, sender,
+ proposed_recipient, requested_reply,
+ (addressed_recipient == proposed_recipient) || (type == DBUS_MESSAGE_TYPE_SIGNAL),
+ privilege, error, out_rule);
+ _dbus_verbose(
+ "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 (proposed_recipient &&
- ((dbus_connection_get_outgoing_size (proposed_recipient) > context->limits.max_outgoing_bytes) ||
- (dbus_connection_get_outgoing_unix_fds (proposed_recipient) > context->limits.max_outgoing_unix_fds)))
- {
- complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED,
- "Rejected: destination has a full message queue",
- 0, message, sender, proposed_recipient, requested_reply, TRUE,
- error);
- _dbus_verbose ("security policy disallowing message due to full message queue\n");
- return FALSE;
- }
+ if (!bus_context_check_recipient_message_limits(context, proposed_recipient, sender, message,
+ requested_reply, error))
+ return BUS_RESULT_FALSE;
/* Record that we will allow a reply here in the future (don't
* bother if the recipient is the bus or this is an eavesdropping
message, error))
{
_dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
- return FALSE;
+ return BUS_RESULT_FALSE;
}
_dbus_verbose ("security policy allowing message\n");
- return TRUE;
+ return BUS_RESULT_TRUE;
}
void
_dbus_server_toggle_all_watches (server, enabled);
}
}
+
+void
+bus_context_complain_about_message (BusContext *context,
+ const char *error_name,
+ const char *complaint,
+ int matched_rules,
+ DBusMessage *message,
+ DBusConnection *sender,
+ DBusConnection *proposed_recipient,
+ dbus_bool_t requested_reply,
+ dbus_bool_t log,
+ const char *privilege,
+ DBusError *error)
+{
+ complain_about_message(context, error_name, complaint, matched_rules, message, sender,
+ proposed_recipient, requested_reply, log, privilege, error, NULL);
+}
+
+dbus_bool_t bus_context_check_recipient_message_limits (BusContext *context,
+ DBusConnection *recipient,
+ DBusConnection *sender,
+ DBusMessage *message,
+ dbus_bool_t requested_reply,
+ DBusError *error)
+
+{
+ if (recipient &&
+ ((dbus_connection_get_outgoing_size (recipient) > context->limits.max_outgoing_bytes) ||
+ (dbus_connection_get_outgoing_unix_fds (recipient) > context->limits.max_outgoing_unix_fds)))
+ {
+ complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED,
+ "Rejected: destination has a full message queue",
+ 0, message, sender, recipient, requested_reply, TRUE, NULL,
+ error, NULL);
+ _dbus_verbose ("security policy disallowing message due to full message queue\n");
+ return FALSE;
+ }
+ return TRUE;
+}