Commit 64f5ae1a authored by Havoc Pennington's avatar Havoc Pennington

2003-10-14 Havoc Pennington <hp@redhat.com>

	* bus/connection.c: implement pending reply tracking using
	BusExpireList

	* bus/bus.c (bus_context_check_security_policy): verify that a
	reply is pending in order to allow a reply to be sent. Deny
	messages of unknown type.

	* bus/dbus-daemon-1.1.in: update to mention new resource limits

	* bus/bus.c (bus_context_get_max_replies_per_connection): new
	(bus_context_get_reply_timeout): new
parent bfb5de51
2003-10-14 Havoc Pennington <hp@redhat.com>
* bus/connection.c: implement pending reply tracking using
BusExpireList
* bus/bus.c (bus_context_check_security_policy): verify that a
reply is pending in order to allow a reply to be sent. Deny
messages of unknown type.
* bus/dbus-daemon-1.1.in: update to mention new resource limits
* bus/bus.c (bus_context_get_max_replies_per_connection): new
(bus_context_get_reply_timeout): new
2003-10-13 Seth Nickell <seth@gnome.org>
* python/Makefile.am:
......
......@@ -872,6 +872,18 @@ bus_context_get_max_match_rules_per_connection (BusContext *context)
return context->limits.max_match_rules_per_connection;
}
int
bus_context_get_max_replies_per_connection (BusContext *context)
{
return context->limits.max_replies_per_connection;
}
int
bus_context_get_reply_timeout (BusContext *context)
{
return context->limits.reply_timeout;
}
/*
* addressed_recipient is the recipient specified in the message.
*
......@@ -887,6 +899,7 @@ bus_context_get_max_match_rules_per_connection (BusContext *context)
*/
dbus_bool_t
bus_context_check_security_policy (BusContext *context,
BusTransaction *transaction,
DBusConnection *sender,
DBusConnection *addressed_recipient,
DBusConnection *proposed_recipient,
......@@ -895,10 +908,16 @@ bus_context_check_security_policy (BusContext *context,
{
BusClientPolicy *sender_policy;
BusClientPolicy *recipient_policy;
_dbus_assert (dbus_message_get_destination (message) == NULL || /* Signal */
(addressed_recipient != NULL ||
strcmp (dbus_message_get_destination (message), DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0)); /* Destination specified or is the bus driver */
int type;
type = dbus_message_get_type (message);
/* dispatch.c was supposed to ensure these invariants */
_dbus_assert (dbus_message_get_destination (message) != NULL ||
type == DBUS_MESSAGE_TYPE_SIGNAL);
_dbus_assert (type == DBUS_MESSAGE_TYPE_SIGNAL ||
addressed_recipient != NULL ||
strcmp (dbus_message_get_destination (message), DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0);
if (sender != NULL)
{
......@@ -906,6 +925,44 @@ bus_context_check_security_policy (BusContext *context,
{
sender_policy = bus_connection_get_policy (sender);
_dbus_assert (sender_policy != NULL);
switch (type)
{
case DBUS_MESSAGE_TYPE_METHOD_CALL:
case DBUS_MESSAGE_TYPE_SIGNAL:
/* Continue below to check security policy */
break;
case DBUS_MESSAGE_TYPE_METHOD_RETURN:
case DBUS_MESSAGE_TYPE_ERROR:
/* These are only allowed if the reply is listed
* as pending, or the connection is eavesdropping.
* The idea is to prohibit confusing/fake replies.
* FIXME In principle a client that's asked to eavesdrop
* specifically should probably get bogus replies
* even to itself, but here we prohibit that.
*/
if (proposed_recipient != NULL /* not to the bus driver */ &&
addressed_recipient == proposed_recipient /* not eavesdropping */ &&
!bus_connections_check_reply (bus_connection_get_connections (sender),
transaction,
sender, addressed_recipient, message,
error))
return FALSE;
/* Continue below to check security policy, since reply was expected */
break;
default:
_dbus_verbose ("security check disallowing message of unknown type\n");
dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED,
"Message bus will not accept messages of unknown type\n");
return FALSE;
}
}
else
{
......@@ -1029,6 +1086,23 @@ bus_context_check_security_policy (BusContext *context,
return FALSE;
}
if (type == DBUS_MESSAGE_TYPE_METHOD_CALL)
{
/* Record that we will allow a reply here in the future (don't
* bother if the recipient is the bus). Only the addressed recipient
* may reply.
*/
if (sender && addressed_recipient &&
!bus_connections_expect_reply (bus_connection_get_connections (sender),
transaction,
sender, addressed_recipient,
message, error))
{
_dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n");
return FALSE;
}
}
_dbus_verbose ("security policy allowing message\n");
return TRUE;
}
......@@ -45,7 +45,7 @@ typedef struct BusMatchRule BusMatchRule;
typedef struct
{
long max_incoming_bytes; /**< How many incoming messages for a single connection */
long max_incoming_bytes; /**< How many incoming message bytes for a single connection */
long max_outgoing_bytes; /**< How many outgoing bytes can be queued for a single connection */
long max_message_size; /**< Max size of a single message in bytes */
int activation_timeout; /**< How long to wait for an activation to time out */
......@@ -56,6 +56,8 @@ typedef struct
int max_pending_activations; /**< Max number of pending activations for the entire bus */
int max_services_per_connection; /**< Max number of owned services for a single connection */
int max_match_rules_per_connection; /**< Max number of match rules for a single connection */
int max_replies_per_connection; /**< Max number of replies that can be pending for each connection */
int reply_timeout; /**< How long to wait before timing out a reply */
} BusLimits;
BusContext* bus_context_new (const DBusString *config_file,
......@@ -87,7 +89,10 @@ int bus_context_get_max_connections_per_user (BusContext
int bus_context_get_max_pending_activations (BusContext *context);
int bus_context_get_max_services_per_connection (BusContext *context);
int bus_context_get_max_match_rules_per_connection (BusContext *context);
int bus_context_get_max_replies_per_connection (BusContext *context);
int bus_context_get_reply_timeout (BusContext *context);
dbus_bool_t bus_context_check_security_policy (BusContext *context,
BusTransaction *transaction,
DBusConnection *sender,
DBusConnection *addressed_recipient,
DBusConnection *proposed_recipient,
......
......@@ -336,6 +336,9 @@ bus_config_parser_new (const DBusString *basedir,
parser->limits.max_services_per_connection = 256;
parser->limits.max_match_rules_per_connection = 128;
parser->limits.reply_timeout = 5 * 60 * 1000; /* 5 minutes */
parser->limits.max_replies_per_connection = 32;
parser->refcount = 1;
......@@ -1397,6 +1400,12 @@ set_limit (BusConfigParser *parser,
must_be_int = TRUE;
parser->limits.auth_timeout = value;
}
else if (strcmp (name, "reply_timeout") == 0)
{
must_be_positive = TRUE;
must_be_int = TRUE;
parser->limits.reply_timeout = value;
}
else if (strcmp (name, "max_completed_connections") == 0)
{
must_be_positive = TRUE;
......@@ -1427,6 +1436,12 @@ set_limit (BusConfigParser *parser,
must_be_int = TRUE;
parser->limits.max_services_per_connection = value;
}
else if (strcmp (name, "max_replies_per_connection") == 0)
{
must_be_positive = TRUE;
must_be_int = TRUE;
parser->limits.max_replies_per_connection = value;
}
else
{
dbus_set_error (error, DBUS_ERROR_FAILED,
......
This diff is collapsed.
......@@ -55,6 +55,19 @@ dbus_bool_t bus_connections_check_limits (BusConnections
DBusError *error);
void bus_connections_expire_incomplete (BusConnections *connections);
dbus_bool_t bus_connections_expect_reply (BusConnections *connections,
BusTransaction *transaction,
DBusConnection *will_get_reply,
DBusConnection *will_send_reply,
DBusMessage *reply_to_this,
DBusError *error);
dbus_bool_t bus_connections_check_reply (BusConnections *connections,
BusTransaction *transaction,
DBusConnection *sending_reply,
DBusConnection *receiving_reply,
DBusMessage *reply,
DBusError *error);
dbus_bool_t bus_connection_mark_stamp (DBusConnection *connection);
dbus_bool_t bus_connection_is_active (DBusConnection *connection);
......
......@@ -280,6 +280,11 @@ Available limit names are:
progress at the same time
"max_services_per_connection": max number of services a single
connection can own
"max_replies_per_connection" : max number of pending method
replies per connection
(number of calls-in-progress)
"reply_timeout" : milliseconds (thousandths)
until a method call times out
.fi
.PP
......
......@@ -42,7 +42,7 @@ send_one_message (DBusConnection *connection,
BusTransaction *transaction,
DBusError *error)
{
if (!bus_context_check_security_policy (context,
if (!bus_context_check_security_policy (context, transaction,
sender,
addressed_recipient,
connection,
......@@ -229,7 +229,7 @@ bus_dispatch (DBusConnection *connection,
if (service_name &&
strcmp (service_name, DBUS_SERVICE_ORG_FREEDESKTOP_DBUS) == 0) /* to bus driver */
{
if (!bus_context_check_security_policy (context,
if (!bus_context_check_security_policy (context, transaction,
connection, NULL, NULL, message, &error))
{
_dbus_verbose ("Security policy rejected message\n");
......@@ -272,7 +272,7 @@ bus_dispatch (DBusConnection *connection,
addressed_recipient = bus_service_get_primary_owner (service);
_dbus_assert (addressed_recipient != NULL);
if (!bus_context_check_security_policy (context,
if (!bus_context_check_security_policy (context, transaction,
connection, addressed_recipient,
addressed_recipient,
message, &error))
......
......@@ -141,7 +141,13 @@ do_expiration_with_current_time (BusExpireList *list,
if (elapsed >= (double) list->expire_after)
{
_dbus_verbose ("Expiring an item %p\n", item);
(* list->expire_func) (list, item, list->data);
/* If the expire function fails, we just end up expiring
* this item next time we walk through the list. Which is in
* indeterminate time since we don't know what next_interval
* will be.
*/
(* list->expire_func) (list, link, list->data);
}
else
{
......@@ -201,12 +207,12 @@ typedef struct
static void
test_expire_func (BusExpireList *list,
BusExpireItem *item,
DBusList *link,
void *data)
{
TestExpireItem *t;
t = (TestExpireItem*) item;
t = (TestExpireItem*) link->data;
t->expire_count += 1;
}
......
......@@ -32,7 +32,7 @@ typedef struct BusExpireList BusExpireList;
typedef struct BusExpireItem BusExpireItem;
typedef void (* BusExpireFunc) (BusExpireList *list,
BusExpireItem *item,
DBusList *link,
void *data);
struct BusExpireList
......
......@@ -31,9 +31,6 @@
some basic spec'ing out of the GLib/Qt level stubs/skels stuff will be
needed to understand the right approach.
- there are various bits of code to manage ref/unref of data slots, that should
be merged into a generic facility
- assorted _-prefixed symbols in libdbus aren't actually used by
libdbus, only by the message bus. These bloat up the library
size. Not sure how to fix, really.
......@@ -73,7 +70,10 @@
async calls.
- the invalid messages in the test suite are all useless because
they are invalid for the wrong reasons due to protocol changes
they are invalid for the wrong reasons due to protocol changes.
(Consider extending test suite to validate that they are
invalid for right reason, e.g. an "INVALID_ERROR Foo" line
in the message files)
- I don't want to introduce DBusObject, but refcounting and object
data could still be factored out into an internal "base class"
......@@ -111,3 +111,10 @@
- the GLib bindings varargs take DBUS_TYPE_WHATEVER and
return stuff allocated with dbus_malloc(); should this
be made more "G" at some expense in code duplication?
- need to define bus behavior if you send a message to
yourself; is it an error, or allowed? If allowed,
we need to have a test for it in the test suite.
- the max_replies_per_connection resource limit isn't implemented
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