Commit 056d76d8 authored by Havoc Pennington's avatar Havoc Pennington

2003-03-20 Havoc Pennington <hp@pobox.com>

	* bus/connection.c (bus_connection_send_oom_error): assert that
	message has a sender
	(connection_execute_transaction): ditto
	(bus_connection_preallocate_oom_error): fix to set the sender, and
	set recipient to the destination service, not the bus driver

	* bus/policy.c: hacking

	* dbus/dbus-message.c (dbus_message_service_is): new function
	(dbus_message_sender_is): new
parent a284a148
2003-03-20 Havoc Pennington <hp@pobox.com>
* bus/connection.c (bus_connection_send_oom_error): assert that
message has a sender
(connection_execute_transaction): ditto
(bus_connection_preallocate_oom_error): fix to set the sender, and
set recipient to the destination service, not the bus driver
* bus/policy.c: hacking
* dbus/dbus-message.c (dbus_message_service_is): new function
(dbus_message_sender_is): new
2003-03-19 Havoc Pennington <hp@redhat.com>
* bus/policy.c: start sketching code for policy restrictions on
......
......@@ -21,6 +21,8 @@ BUS_SOURCES= \
driver.h \
loop.c \
loop.h \
policy.c \
policy.h \
services.c \
services.h \
test.c \
......
......@@ -504,7 +504,8 @@ bus_connection_preallocate_oom_error (DBusConnection *connection)
if (preallocated == NULL)
return FALSE;
message = dbus_message_new (DBUS_SERVICE_DBUS,
/* d->name may be NULL, but that should be OK */
message = dbus_message_new (d->name,
DBUS_ERROR_NO_MEMORY);
if (message == NULL)
{
......@@ -513,6 +514,14 @@ bus_connection_preallocate_oom_error (DBusConnection *connection)
}
dbus_message_set_is_error (message, TRUE);
if (!dbus_message_set_sender (message,
DBUS_SERVICE_DBUS))
{
dbus_connection_free_preallocated_send (connection, preallocated);
dbus_message_unref (message);
return FALSE;
}
/* set reply serial to placeholder value just so space is already allocated
* for it.
......@@ -546,6 +555,8 @@ bus_connection_send_oom_error (DBusConnection *connection,
dbus_message_get_serial (in_reply_to)))
_dbus_assert_not_reached ("Failed to set reply serial for preallocated oom message");
_dbus_assert (dbus_message_get_sender (d->oom_message) != NULL);
dbus_connection_send_preallocated (connection, d->oom_preallocated,
d->oom_message, NULL);
......@@ -681,6 +692,8 @@ bus_transaction_send_message (BusTransaction *transaction,
dbus_message_get_name (message),
dbus_connection_get_is_connected (connection) ?
"" : " (disconnected)");
_dbus_assert (dbus_message_get_sender (message) != NULL);
if (!dbus_connection_get_is_connected (connection))
return TRUE; /* silently ignore disconnected connections */
......@@ -811,6 +824,8 @@ connection_execute_transaction (DBusConnection *connection,
_dbus_list_remove_link (&d->transaction_messages,
link);
_dbus_assert (dbus_message_get_sender (m->message) != NULL);
dbus_connection_send_preallocated (connection,
m->preallocated,
m->message,
......
......@@ -22,6 +22,9 @@
*/
#include "policy.h"
#include "services.h"
#include <dbus/dbus-list.h>
#include <dbus/dbus-internals.h>
BusPolicyRule*
bus_policy_rule_new (BusPolicyRuleType type,
......@@ -59,15 +62,15 @@ bus_policy_rule_unref (BusPolicyRule *rule)
{
switch (rule->type)
{
case DBUS_POLICY_RULE_SEND:
case BUS_POLICY_RULE_SEND:
dbus_free (rule->d.send.message_name);
dbus_free (rule->d.send.destination);
break;
case DBUS_POLICY_RULE_RECEIVE:
case BUS_POLICY_RULE_RECEIVE:
dbus_free (rule->d.receive.message_name);
dbus_free (rule->d.receive.origin);
break;
case DBUS_POLICY_RULE_OWN:
case BUS_POLICY_RULE_OWN:
dbus_free (rule->d.own.service_name);
break;
}
......@@ -133,31 +136,262 @@ bus_policy_unref (BusPolicy *policy)
}
}
static void
remove_rules_by_type_up_to (BusPolicy *policy,
BusPolicyRuleType type,
DBusList *up_to)
{
DBusList *link;
link = _dbus_list_get_first (&policy->rules);
while (link != up_to)
{
BusPolicyRule *rule = link->data;
DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
bus_policy_rule_unref (rule);
_dbus_list_remove_link (&policy->rules, link);
link = next;
}
}
static void
bus_policy_optimize (BusPolicy *policy)
{
DBusList *link;
/* The idea here is that if we have:
*
* <allow send="foo"/>
* <deny send="*"/>
*
* (for example) the deny will always override the allow. So we
* delete the allow. Ditto for deny followed by allow, etc. This is
* a dumb thing to put in a config file, but the <include> feature
* of files allows for an "inheritance and override" pattern where
* it could make sense. If an included file wants to "start over"
* with a blanket deny, no point keeping the rules from the parent
* file.
*/
link = _dbus_list_get_first (&policy->rules);
while (link != NULL)
{
BusPolicyRule *rule = link->data;
DBusList *next = _dbus_list_get_next_link (&policy->rules, link);
dbus_bool_t remove_preceding;
remove_preceding = FALSE;
switch (rule->type)
{
case BUS_POLICY_RULE_SEND:
remove_preceding =
rule->d.send.message_name == NULL &&
rule->d.send.destination == NULL;
break;
case BUS_POLICY_RULE_RECEIVE:
remove_preceding =
rule->d.receive.message_name == NULL &&
rule->d.receive.origin == NULL;
break;
case BUS_POLICY_RULE_OWN:
remove_preceding =
rule->d.own.service_name == NULL;
break;
}
if (remove_preceding)
remove_rules_by_type_up_to (policy, rule->type,
link);
link = next;
}
}
dbus_bool_t
bus_policy_check_can_send (BusPolicy *policy,
DBusConnection *sender,
BusRegistry *registry,
DBusConnection *receiver,
DBusMessage *message)
{
DBusList *link;
dbus_bool_t allowed;
/* policy->rules is in the order the rules appeared
* in the config file, i.e. last rule that applies wins
*/
allowed = FALSE;
link = _dbus_list_get_first (&policy->rules);
while (link != NULL)
{
BusPolicyRule *rule = link->data;
link = _dbus_list_get_next_link (&policy->rules, link);
/* Rule is skipped if it specifies a different
* message name from the message, or a different
* destination from the message
*/
if (rule->type != BUS_POLICY_RULE_SEND)
continue;
if (rule->d.send.message_name != NULL)
{
if (!dbus_message_name_is (message,
rule->d.send.message_name))
continue;
}
if (rule->d.send.destination != NULL)
{
/* receiver can be NULL for messages that are sent to the
* 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.
*/
if (receiver == NULL)
{
if (!dbus_message_sender_is (message,
rule->d.send.destination))
continue;
}
else
{
DBusString str;
BusService *service;
_dbus_string_init_const (&str, rule->d.send.destination);
service = bus_registry_lookup (registry, &str);
if (service == NULL)
continue;
if (!bus_service_has_owner (service, receiver))
continue;
}
}
/* Use this rule */
allowed = rule->allow;
}
return allowed;
}
dbus_bool_t
bus_policy_check_can_receive (BusPolicy *policy,
DBusConnection *receiver,
BusRegistry *registry,
DBusConnection *sender,
DBusMessage *message)
{
DBusList *link;
dbus_bool_t allowed;
/* policy->rules is in the order the rules appeared
* in the config file, i.e. last rule that applies wins
*/
allowed = FALSE;
link = _dbus_list_get_first (&policy->rules);
while (link != NULL)
{
BusPolicyRule *rule = link->data;
link = _dbus_list_get_next_link (&policy->rules, link);
/* Rule is skipped if it specifies a different
* message name from the message, or a different
* origin from the message
*/
if (rule->type != BUS_POLICY_RULE_RECEIVE)
continue;
if (rule->d.receive.message_name != NULL)
{
if (!dbus_message_name_is (message,
rule->d.receive.message_name))
continue;
}
if (rule->d.receive.origin != NULL)
{
/* sender can be NULL for messages that originate from the
* message bus itself, we check the strings in that case as
* built-in services don't have a DBusConnection but will
* still set the sender on their messages.
*/
if (sender == NULL)
{
if (!dbus_message_sender_is (message,
rule->d.receive.origin))
continue;
}
else
{
BusService *service;
DBusString str;
_dbus_string_init_const (&str, rule->d.receive.origin);
service = bus_registry_lookup (registry, &str);
if (service == NULL)
continue;
if (!bus_service_has_owner (service, sender))
continue;
}
}
/* Use this rule */
allowed = rule->allow;
}
return allowed;
}
dbus_bool_t
bus_policy_check_can_own (BusPolicy *policy,
DBusConnection *connection,
const char *service_name)
bus_policy_check_can_own (BusPolicy *policy,
DBusConnection *connection,
const DBusString *service_name)
{
DBusList *link;
dbus_bool_t allowed;
/* policy->rules is in the order the rules appeared
* in the config file, i.e. last rule that applies wins
*/
allowed = FALSE;
link = _dbus_list_get_first (&policy->rules);
while (link != NULL)
{
BusPolicyRule *rule = link->data;
}
link = _dbus_list_get_next_link (&policy->rules, link);
/* Rule is skipped if it specifies a different service name from
* the desired one.
*/
if (rule->type != BUS_POLICY_RULE_OWN)
continue;
if (rule->d.own.service_name != NULL)
{
if (!_dbus_string_equal_c_str (service_name,
rule->d.own.service_name))
continue;
}
#endif /* BUS_POLICY_H */
/* Use this rule */
allowed = rule->allow;
}
return allowed;
}
......@@ -25,6 +25,7 @@
#define BUS_POLICY_H
#include <dbus/dbus.h>
#include <dbus/dbus-string.h>
#include "bus.h"
typedef struct BusPolicy BusPolicy;
......@@ -32,9 +33,9 @@ typedef struct BusPolicyRule BusPolicyRule;
typedef enum
{
DBUS_POLICY_RULE_SEND,
DBUS_POLICY_RULE_RECEIVE,
DBUS_POLICY_RULE_OWN
BUS_POLICY_RULE_SEND,
BUS_POLICY_RULE_RECEIVE,
BUS_POLICY_RULE_OWN
} BusPolicyRuleType;
struct BusPolicyRule
......@@ -76,17 +77,19 @@ void bus_policy_rule_ref (BusPolicyRule *rule);
void bus_policy_rule_unref (BusPolicyRule *rule);
BusPolicy* bus_policy_new (void);
void bus_policy_ref (BusPolicy *policy);
void bus_policy_unref (BusPolicy *policy);
dbus_bool_t bus_policy_check_can_send (BusPolicy *policy,
DBusConnection *sender,
DBusMessage *message);
dbus_bool_t bus_policy_check_can_receive (BusPolicy *policy,
DBusConnection *receiver,
DBusMessage *message);
dbus_bool_t bus_policy_check_can_own (BusPolicy *policy,
DBusConnection *connection,
const char *service_name);
void bus_policy_ref (BusPolicy *policy);
void bus_policy_unref (BusPolicy *policy);
dbus_bool_t bus_policy_check_can_send (BusPolicy *policy,
BusRegistry *registry,
DBusConnection *receiver,
DBusMessage *message);
dbus_bool_t bus_policy_check_can_receive (BusPolicy *policy,
BusRegistry *registry,
DBusConnection *sender,
DBusMessage *message);
dbus_bool_t bus_policy_check_can_own (BusPolicy *policy,
DBusConnection *connection,
const DBusString *service_name);
......
......@@ -1018,6 +1018,11 @@ dbus_message_get_name (DBusMessage *message)
/**
* Gets the destination service of a message.
*
* @todo I think if we have set_sender/get_sender,
* this function might be better named set_destination/
* get_destination for clarity, as the sender
* is also a service name.
*
* @param message the message
* @returns the message destination service (should not be freed)
*/
......@@ -2326,6 +2331,62 @@ dbus_message_name_is (DBusMessage *message,
return FALSE;
}
/**
* Checks whether the message was sent to the given service. If the
* message has no service specified or has a different name, returns
* #FALSE.
*
* @param message the message
* @param service the service to check (must not be #NULL)
*
* @returns #TRUE if the message has the given destination service
*/
dbus_bool_t
dbus_message_service_is (DBusMessage *message,
const char *service)
{
const char *s;
_dbus_assert (service != NULL);
s = dbus_message_get_service (message);
if (s && strcmp (s, service) == 0)
return TRUE;
else
return FALSE;
}
/**
* Checks whether the message has the given service as its sender. If
* the message has no sender specified or has a different sender,
* returns #FALSE. Note that if a peer application owns multiple
* services, its messages will have only one of those services as the
* sender (usually the base service). So you can't use this
* function to prove the sender didn't own service Foo, you can
* only use it to prove that it did.
*
* @param message the message
* @param service the service to check (must not be #NULL)
*
* @returns #TRUE if the message has the given origin service
*/
dbus_bool_t
dbus_message_sender_is (DBusMessage *message,
const char *service)
{
const char *s;
_dbus_assert (service != NULL);
s = dbus_message_get_sender (message);
if (s && strcmp (s, service) == 0)
return TRUE;
else
return FALSE;
}
/** @} */
/**
......
......@@ -58,6 +58,10 @@ void dbus_message_set_is_error (DBusMessage *message,
dbus_bool_t dbus_message_get_is_error (DBusMessage *message);
dbus_bool_t dbus_message_name_is (DBusMessage *message,
const char *name);
dbus_bool_t dbus_message_service_is (DBusMessage *message,
const char *service);
dbus_bool_t dbus_message_sender_is (DBusMessage *message,
const char *service);
dbus_int32_t dbus_message_get_serial (DBusMessage *message);
dbus_bool_t dbus_message_set_reply_serial (DBusMessage *message,
dbus_int32_t reply_serial);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment