DBusHashTable *entries;
} BusServiceDirectory;
-typedef struct
+struct BusActivationEntry
{
int refcount;
char *name;
unsigned long mtime;
BusServiceDirectory *s_dir;
char *filename;
-} BusActivationEntry;
+};
typedef struct BusPendingActivationEntry BusPendingActivationEntry;
if (!entry)
return BUS_RESULT_FALSE;
+ if (auto_activation && entry != NULL)
+ {
+ switch (bus_context_check_security_policy (activation->context,
+ transaction,
+ connection, /* sender */
+ NULL, /* addressed recipient */
+ NULL, /* proposed recipient */
+ activation_message,
+ entry,
+ error,
+ deferred_message))
+ {
+ case BUS_RESULT_TRUE:
+ break;
+ case BUS_RESULT_FALSE:
+ _DBUS_ASSERT_ERROR_IS_SET (error);
+ _dbus_verbose ("activation not authorized: %s: %s\n",
+ error != NULL ? error->name : "(error ignored)",
+ error != NULL ? error->message : "(error ignored)");
+ return BUS_RESULT_FALSE;
+ case BUS_RESULT_LATER:
+ return BUS_RESULT_LATER;
+ }
+ }
+
/* Bypass the registry lookup if we're auto-activating, bus_dispatch would not
* call us if the service is already active.
*/
const char *error_name,
const char *destination,
const char *source,
+ BusActivationEntry *activation_entry,
DBusError *error)
{
#ifdef HAVE_APPARMOR
if (!apparmor_enabled)
return TRUE;
+ /* We do not mediate activation attempts yet. */
+ if (activation_entry != NULL)
+ return TRUE;
+
_dbus_assert (sender != NULL);
src_con = bus_connection_dup_apparmor_confinement (sender);
const char *error_name,
const char *destination,
const char *source,
+ BusActivationEntry *activation_entry,
DBusError *error);
dbus_bool_t bus_apparmor_allows_eavesdropping (DBusConnection *connection,
*
* sender is the sender of the message.
*
- * NULL for proposed_recipient or sender definitely means the bus driver.
+ * NULL for sender definitely means the bus driver.
+ *
+ * NULL for proposed_recipient may mean the bus driver, or may mean
+ * we are checking whether service-activation is allowed as a first
+ * pass before all details of the activated service are known.
*
* NULL for addressed_recipient may mean the bus driver, or may mean
* no destination was specified in the message (e.g. a signal).
DBusConnection *addressed_recipient,
DBusConnection *proposed_recipient,
DBusMessage *message,
+ BusActivationEntry *activation_entry,
DBusError *error,
BusDeferredMessage **deferred_message)
{
(sender == NULL && !bus_connection_is_active (proposed_recipient)));
_dbus_assert (type == DBUS_MESSAGE_TYPE_SIGNAL ||
addressed_recipient != NULL ||
+ activation_entry != NULL ||
strcmp (dest, DBUS_SERVICE_DBUS) == 0);
switch (type)
dbus_message_get_interface (message),
dbus_message_get_member (message),
dbus_message_get_error_name (message),
- dest ? dest : DBUS_SERVICE_DBUS, error))
+ dest ? dest : DBUS_SERVICE_DBUS,
+ activation_entry,
+ error))
{
if (error != NULL && !dbus_error_is_set (error))
{
dbus_message_get_error_name (message),
dest ? dest : DBUS_SERVICE_DBUS,
src ? src : DBUS_SERVICE_DBUS,
+ activation_entry,
error))
return 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
* connection). Only the addressed recipient may reply.
+ *
+ * This isn't done for activation attempts because they have no addressed
+ * or proposed recipient; when we check whether to actually deliver the
+ * message, later, we'll record the reply expectation at that point.
*/
if (type == DBUS_MESSAGE_TYPE_METHOD_CALL &&
sender &&
typedef struct BusTransaction BusTransaction;
typedef struct BusMatchmaker BusMatchmaker;
typedef struct BusMatchRule BusMatchRule;
+typedef struct BusActivationEntry BusActivationEntry;
typedef struct BusCheck BusCheck;
typedef struct BusDeferredMessage BusDeferredMessage;
typedef struct BusCynara BusCynara;
DBusConnection *addressed_recipient,
DBusConnection *proposed_recipient,
DBusMessage *message,
+ BusActivationEntry *activation_entry,
DBusError *error,
BusDeferredMessage **deferred_message);
deferred_message->sender,
deferred_message->addressed_recipient,
deferred_message->proposed_recipient,
- deferred_message->message, NULL,
+ deferred_message->message, NULL, NULL,
&deferred_message2);
if (result == BUS_RESULT_LATER)
*/
switch (bus_context_check_security_policy (bus_transaction_get_context (transaction),
transaction,
- NULL, connection, connection, message, &error,
+ NULL, connection, connection,
+ message, NULL, &error,
&deferred_message))
{
case BUS_RESULT_TRUE:
BusResult result;
result = bus_context_check_security_policy (context, transaction, sender, addressed_recipient,
- connection, message, &stack_error, &deferred_message);
+ connection, message, NULL, &stack_error, &deferred_message);
if (result == BUS_RESULT_FALSE)
{
if (result == BUS_RESULT_LATER)
result = bus_context_check_security_policy(context, transaction,
- sender, addressed_recipient, addressed_recipient, message, error,
+ sender, addressed_recipient, addressed_recipient, message, NULL, error,
&deferred_message);
switch (result)
BusDeferredMessage *deferred_message;
switch (bus_context_check_security_policy (context, transaction,
- connection, NULL, NULL, message, &error,
+ connection, NULL, NULL, message,
+ NULL, &error,
&deferred_message))
{
case BUS_RESULT_TRUE:
BusActivation *activation;
BusDeferredMessage *deferred_message;
- /* We can't do the security policy check here, since the addressed
- * recipient service doesn't exist yet. We do it before sending the
- * message after the service has been created.
- */
activation = bus_connection_get_activation (connection);
+ /* This will do as much of a security policy check as it can.
+ * We can't do the full security policy check here, since the
+ * addressed recipient service doesn't exist yet. We do it before
+ * sending the message after the service has been created.
+ */
switch (bus_activation_activate_service (activation, connection, transaction, TRUE,
message, service_name, &error,
&deferred_message))
* message bus itself, we check the strings in that case as
* built-in services don't have a DBusConnection but messages
* to them have a destination service name.
+ *
+ * Similarly, receiver can be NULL when we're deciding whether
+ * activation should be allowed; we make the authorization decision
+ * on the assumption that the activated service will have the
+ * requested name and no others.
*/
if (receiver == NULL)
{
const char *member,
const char *error_name,
const char *destination,
+ BusActivationEntry *activation_entry,
DBusError *error)
{
#ifdef HAVE_SELINUX
if (!selinux_enabled)
return TRUE;
+ /* We do not mediate activation attempts yet. */
+ if (activation_entry)
+ return TRUE;
+
if (!sender || !dbus_connection_get_unix_process_id (sender, &spid))
spid = 0;
if (!proposed_recipient || !dbus_connection_get_unix_process_id (proposed_recipient, &tpid))
}
sender_sid = bus_connection_get_selinux_id (sender);
- /* A NULL proposed_recipient means the bus itself. */
+
+ /* A NULL proposed_recipient with no activation entry means the bus itself. */
if (proposed_recipient)
recipient_sid = bus_connection_get_selinux_id (proposed_recipient);
else
const char *member,
const char *error_name,
const char *destination,
+ BusActivationEntry *activation_entry,
DBusError *error);
BusSELinuxID* bus_selinux_init_connection_id (DBusConnection *connection,
dbus_connection_send (f->caller, m, NULL);
dbus_message_unref (m);
- /* The fake systemd connects to the bus. */
- f->systemd = test_connect_to_bus (f->ctx, f->address);
- if (!dbus_connection_add_filter (f->systemd, systemd_filter, f, NULL))
- g_error ("OOM");
- f->systemd_filter_added = TRUE;
- f->systemd_name = dbus_bus_get_unique_name (f->systemd);
- take_well_known_name (f, f->systemd, "org.freedesktop.systemd1");
-
- /* It gets its activation request. */
- while (f->caller_message == NULL && f->systemd_message == NULL)
- test_main_context_iterate (f->ctx, TRUE);
-
- g_assert (f->caller_message == NULL);
- g_assert (f->systemd_message != NULL);
-
- m = f->systemd_message;
- f->systemd_message = NULL;
- assert_signal (m, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS,
- "org.freedesktop.systemd1.Activator", "ActivationRequest", "s",
- "org.freedesktop.systemd1");
- dbus_message_unref (m);
-
- /* systemd starts the activatable service. */
- f->activated = test_connect_to_bus (f->ctx, f->address);
- if (!dbus_connection_add_filter (f->activated, activated_filter,
- f, NULL))
- g_error ("OOM");
- f->activated_filter_added = TRUE;
- f->activated_name = dbus_bus_get_unique_name (f->activated);
- take_well_known_name (f, f->activated, "com.example.SendDenied");
+ /* Even before the fake systemd connects to the bus, we get an error
+ * back: activation is not allowed. */
- /* We re-do the message matching, and now the message is
- * forbidden by the receive policy. */
- while (f->activated_message == NULL && f->caller_message == NULL)
+ while (f->caller_message == NULL)
test_main_context_iterate (f->ctx, TRUE);
- g_assert (f->activated_message == NULL);
-
m = f->caller_message;
f->caller_message = NULL;
assert_error_reply (m, DBUS_SERVICE_DBUS, f->caller_name,