Commit a683a80c authored by Havoc Pennington's avatar Havoc Pennington

2003-09-21 Havoc Pennington <hp@pobox.com>

	Get matching rules mostly working in the bus; only actually
	parsing the rule text remains. However, the client side of
	"signal connections" hasn't been started, this patch is only the
	bus side.

	* dbus/dispatch.c: fix for the matching rules changes

	* bus/driver.c (bus_driver_handle_remove_match)
	(bus_driver_handle_add_match): send an ack reply from these
	method calls

	* glib/dbus-gproxy.c (dbus_gproxy_begin_call): fix order of
	arguments, reported by Seth Nickell

	* bus/config-parser.c (append_rule_from_element): support
	eavesdrop=true|false attribute on policies so match rules
	can be prevented from snooping on the system bus.

	* bus/dbus-daemon-1.1.in: consistently use terminology "sender"
	and "destination" in attribute names; fix some docs bugs;
	add eavesdrop=true|false attribute

	* bus/driver.c (bus_driver_handle_add_match)
	(bus_driver_handle_remove_match): handle AddMatch, RemoveMatch
	messages

	* dbus/dbus-protocol.h (DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST): get
	rid of broadcast service concept, signals are just always broadcast

	* bus/signals.c, bus/dispatch.c, bus/connection.c, bus/bus.c:
	mostly implement matching rules stuff (currently only exposed as signal
	connections)
parent daf8d657
2003-09-21 Havoc Pennington <hp@pobox.com>
Get matching rules mostly working in the bus; only actually
parsing the rule text remains. However, the client side of
"signal connections" hasn't been started, this patch is only the
bus side.
* dbus/dispatch.c: fix for the matching rules changes
* bus/driver.c (bus_driver_handle_remove_match)
(bus_driver_handle_add_match): send an ack reply from these
method calls
* glib/dbus-gproxy.c (dbus_gproxy_begin_call): fix order of
arguments, reported by Seth Nickell
* bus/config-parser.c (append_rule_from_element): support
eavesdrop=true|false attribute on policies so match rules
can be prevented from snooping on the system bus.
* bus/dbus-daemon-1.1.in: consistently use terminology "sender"
and "destination" in attribute names; fix some docs bugs;
add eavesdrop=true|false attribute
* bus/driver.c (bus_driver_handle_add_match)
(bus_driver_handle_remove_match): handle AddMatch, RemoveMatch
messages
* dbus/dbus-protocol.h (DBUS_SERVICE_ORG_FREEDESKTOP_BROADCAST): get
rid of broadcast service concept, signals are just always broadcast
* bus/signals.c, bus/dispatch.c, bus/connection.c, bus/bus.c:
mostly implement matching rules stuff (currently only exposed as signal
connections)
2003-09-21 Mark McLoughlin <mark@skynet.ie>
* doc/dbus-specification.sgml: Change the header field name
......
......@@ -44,6 +44,8 @@ BUS_SOURCES= \
policy.h \
services.c \
services.h \
signals.c \
signals.h \
test.c \
test.h \
utils.c \
......
......@@ -28,6 +28,7 @@
#include "utils.h"
#include "policy.h"
#include "config-parser.h"
#include "signals.h"
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-internals.h>
......@@ -44,6 +45,7 @@ struct BusContext
BusActivation *activation;
BusRegistry *registry;
BusPolicy *policy;
BusMatchmaker *matchmaker;
DBusUserDatabase *user_database;
BusLimits limits;
};
......@@ -505,6 +507,13 @@ bus_context_new (const DBusString *config_file,
goto failed;
}
context->matchmaker = bus_matchmaker_new ();
if (context->matchmaker == NULL)
{
BUS_SET_OOM (error);
goto failed;
}
context->policy = bus_config_parser_steal_policy (parser);
_dbus_assert (context->policy != NULL);
......@@ -715,6 +724,12 @@ bus_context_unref (BusContext *context)
_dbus_loop_unref (context->loop);
context->loop = NULL;
}
if (context->matchmaker)
{
bus_matchmaker_unref (context->matchmaker);
context->matchmaker = NULL;
}
dbus_free (context->type);
dbus_free (context->address);
......@@ -771,6 +786,12 @@ bus_context_get_activation (BusContext *context)
return context->activation;
}
BusMatchmaker*
bus_context_get_matchmaker (BusContext *context)
{
return context->matchmaker;
}
DBusLoop*
bus_context_get_loop (BusContext *context)
{
......@@ -845,18 +866,33 @@ bus_context_get_max_services_per_connection (BusContext *context)
return context->limits.max_services_per_connection;
}
int
bus_context_get_max_match_rules_per_connection (BusContext *context)
{
return context->limits.max_match_rules_per_connection;
}
dbus_bool_t
bus_context_check_security_policy (BusContext *context,
DBusConnection *sender,
DBusConnection *recipient,
DBusConnection *addressed_recipient,
DBusConnection *proposed_recipient,
DBusMessage *message,
DBusError *error)
{
BusClientPolicy *sender_policy;
BusClientPolicy *recipient_policy;
/* NULL sender/receiver means the bus driver */
/* NULL sender, proposed_recipient means the bus driver. NULL
* addressed_recipient means the message didn't specify an explicit
* target. If proposed_recipient is NULL, then addressed_recipient
* is also NULL but is implicitly the bus driver.
*/
_dbus_assert (proposed_recipient == NULL ||
(dbus_message_get_destination (message) == NULL ||
addressed_recipient != NULL));
if (sender != NULL)
{
if (bus_connection_is_active (sender))
......@@ -869,7 +905,7 @@ bus_context_check_security_policy (BusContext *context,
/* Policy for inactive connections is that they can only send
* the hello message to the bus driver
*/
if (recipient == NULL &&
if (proposed_recipient == NULL &&
dbus_message_is_method_call (message,
DBUS_INTERFACE_ORG_FREEDESKTOP_DBUS,
"Hello"))
......@@ -897,15 +933,15 @@ bus_context_check_security_policy (BusContext *context,
_dbus_assert ((sender != NULL && sender_policy != NULL) ||
(sender == NULL && sender_policy == NULL));
if (recipient != NULL)
if (proposed_recipient != NULL)
{
/* only the bus driver can send to an inactive recipient (as it
* owns no services, so other apps can't address it). Inactive
* recipients can receive any message.
*/
if (bus_connection_is_active (recipient))
if (bus_connection_is_active (proposed_recipient))
{
recipient_policy = bus_connection_get_policy (recipient);
recipient_policy = bus_connection_get_policy (proposed_recipient);
_dbus_assert (recipient_policy != NULL);
}
else if (sender == NULL)
......@@ -922,13 +958,13 @@ bus_context_check_security_policy (BusContext *context,
else
recipient_policy = NULL;
_dbus_assert ((recipient != NULL && recipient_policy != NULL) ||
(recipient != NULL && sender == NULL && recipient_policy == NULL) ||
(recipient == NULL && recipient_policy == NULL));
_dbus_assert ((proposed_recipient != NULL && recipient_policy != NULL) ||
(proposed_recipient != NULL && sender == NULL && recipient_policy == NULL) ||
(proposed_recipient == NULL && recipient_policy == NULL));
if (sender_policy &&
!bus_client_policy_check_can_send (sender_policy,
context->registry, recipient,
context->registry, proposed_recipient,
message))
{
const char *dest = dbus_message_get_destination (message);
......@@ -951,6 +987,7 @@ bus_context_check_security_policy (BusContext *context,
if (recipient_policy &&
!bus_client_policy_check_can_receive (recipient_policy,
context->registry, sender,
addressed_recipient, proposed_recipient,
message))
{
const char *dest = dbus_message_get_destination (message);
......@@ -971,14 +1008,16 @@ bus_context_check_security_policy (BusContext *context,
}
/* See if limits on size have been exceeded */
if (recipient &&
dbus_connection_get_outgoing_size (recipient) >
if (proposed_recipient &&
dbus_connection_get_outgoing_size (proposed_recipient) >
context->limits.max_outgoing_bytes)
{
const char *dest = dbus_message_get_destination (message);
dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
"The destination service \"%s\" has a full message queue",
dest ? dest : DBUS_SERVICE_ORG_FREEDESKTOP_DBUS);
dest ? dest : (proposed_recipient ?
bus_connection_get_name (proposed_recipient) :
DBUS_SERVICE_ORG_FREEDESKTOP_DBUS));
_dbus_verbose ("security policy disallowing message due to full message queue\n");
return FALSE;
}
......
......@@ -40,7 +40,8 @@ typedef struct BusPolicyRule BusPolicyRule;
typedef struct BusRegistry BusRegistry;
typedef struct BusService BusService;
typedef struct BusTransaction BusTransaction;
typedef struct BusMatchmaker BusMatchmaker;
typedef struct BusMatchRule BusMatchRule;
typedef struct
{
......@@ -54,40 +55,44 @@ typedef struct
int max_connections_per_user; /**< Max number of connections auth'd as same user */
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 */
} BusLimits;
BusContext* bus_context_new (const DBusString *config_file,
dbus_bool_t force_fork,
int print_addr_fd,
int print_pid_fd,
DBusError *error);
void bus_context_shutdown (BusContext *context);
void bus_context_ref (BusContext *context);
void bus_context_unref (BusContext *context);
const char* bus_context_get_type (BusContext *context);
const char* bus_context_get_address (BusContext *context);
BusRegistry* bus_context_get_registry (BusContext *context);
BusConnections* bus_context_get_connections (BusContext *context);
BusActivation* bus_context_get_activation (BusContext *context);
DBusLoop* bus_context_get_loop (BusContext *context);
DBusUserDatabase* bus_context_get_user_database (BusContext *context);
dbus_bool_t bus_context_allow_user (BusContext *context,
unsigned long uid);
BusClientPolicy* bus_context_create_client_policy (BusContext *context,
DBusConnection *connection,
DBusError *error);
BusContext* bus_context_new (const DBusString *config_file,
dbus_bool_t force_fork,
int print_addr_fd,
int print_pid_fd,
DBusError *error);
void bus_context_shutdown (BusContext *context);
void bus_context_ref (BusContext *context);
void bus_context_unref (BusContext *context);
const char* bus_context_get_type (BusContext *context);
const char* bus_context_get_address (BusContext *context);
BusRegistry* bus_context_get_registry (BusContext *context);
BusConnections* bus_context_get_connections (BusContext *context);
BusActivation* bus_context_get_activation (BusContext *context);
BusMatchmaker* bus_context_get_matchmaker (BusContext *context);
DBusLoop* bus_context_get_loop (BusContext *context);
DBusUserDatabase* bus_context_get_user_database (BusContext *context);
dbus_bool_t bus_context_allow_user (BusContext *context,
unsigned long uid);
BusClientPolicy* bus_context_create_client_policy (BusContext *context,
DBusConnection *connection,
DBusError *error);
int bus_context_get_activation_timeout (BusContext *context);
int bus_context_get_auth_timeout (BusContext *context);
int bus_context_get_max_completed_connections (BusContext *context);
int bus_context_get_max_incomplete_connections (BusContext *context);
int bus_context_get_max_connections_per_user (BusContext *context);
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);
dbus_bool_t bus_context_check_security_policy (BusContext *context,
DBusConnection *sender,
DBusConnection *addressed_recipient,
DBusConnection *proposed_recipient,
DBusMessage *message,
DBusError *error);
int bus_context_get_activation_timeout (BusContext *context);
int bus_context_get_auth_timeout (BusContext *context);
int bus_context_get_max_completed_connections (BusContext *context);
int bus_context_get_max_incomplete_connections (BusContext *context);
int bus_context_get_max_connections_per_user (BusContext *context);
int bus_context_get_max_pending_activations (BusContext *context);
int bus_context_get_max_services_per_connection (BusContext *context);
dbus_bool_t bus_context_check_security_policy (BusContext *context,
DBusConnection *sender,
DBusConnection *recipient,
DBusMessage *message,
DBusError *error);
#endif /* BUS_BUS_H */
This diff is collapsed.
......@@ -25,6 +25,7 @@
#include "policy.h"
#include "services.h"
#include "utils.h"
#include "signals.h"
#include <dbus/dbus-list.h>
#include <dbus/dbus-hash.h>
#include <dbus/dbus-timeout.h>
......@@ -41,6 +42,7 @@ struct BusConnections
BusContext *context;
DBusHashTable *completed_by_user; /**< Number of completed connections for each UID */
DBusTimeout *expire_timeout; /**< Timeout for expiring incomplete connections. */
int stamp; /**< Incrementing number */
};
static dbus_int32_t connection_data_slot = -1;
......@@ -52,6 +54,8 @@ typedef struct
DBusConnection *connection;
DBusList *services_owned;
int n_services_owned;
DBusList *match_rules;
int n_match_rules;
char *name;
DBusList *transaction_messages; /**< Stuff we need to send as part of a transaction */
DBusMessage *oom_message;
......@@ -60,6 +64,7 @@ typedef struct
long connection_tv_sec; /**< Time when we connected (seconds component) */
long connection_tv_usec; /**< Time when we connected (microsec component) */
int stamp; /**< connections->stamp last time we were traversed */
} BusConnectionData;
static dbus_bool_t expire_incomplete_timeout (void *data);
......@@ -140,12 +145,20 @@ bus_connection_disconnected (DBusConnection *connection)
{
BusConnectionData *d;
BusService *service;
BusMatchmaker *matchmaker;
d = BUS_CONNECTION_DATA (connection);
_dbus_assert (d != NULL);
_dbus_verbose ("%s disconnected, dropping all service ownership and releasing\n",
d->name ? d->name : "(inactive)");
/* Delete our match rules */
if (d->n_match_rules > 0)
{
matchmaker = bus_context_get_matchmaker (d->connections->context);
bus_matchmaker_disconnected (matchmaker, connection);
}
/* Drop any service ownership. FIXME Unfortunately, this requires
* memory allocation and there doesn't seem to be a good way to
......@@ -881,6 +894,40 @@ bus_connections_get_context (BusConnections *connections)
return connections->context;
}
/*
* This is used to avoid covering the same connection twice when
* traversing connections. Note that it assumes we will
* bus_connection_mark_stamp() each connection at least once per
* INT_MAX increments of the global stamp, or wraparound would break
* things.
*/
void
bus_connections_increment_stamp (BusConnections *connections)
{
connections->stamp += 1;
}
/* Mark connection with current stamp, return TRUE if it
* didn't already have that stamp
*/
dbus_bool_t
bus_connection_mark_stamp (DBusConnection *connection)
{
BusConnectionData *d;
d = BUS_CONNECTION_DATA (connection);
_dbus_assert (d != NULL);
if (d->stamp == d->connections->stamp)
return FALSE;
else
{
d->stamp = d->connections->stamp;
return TRUE;
}
}
BusContext*
bus_connection_get_context (DBusConnection *connection)
{
......@@ -929,6 +976,18 @@ bus_connection_get_activation (DBusConnection *connection)
return bus_context_get_activation (d->connections->context);
}
BusMatchmaker*
bus_connection_get_matchmaker (DBusConnection *connection)
{
BusConnectionData *d;
d = BUS_CONNECTION_DATA (connection);
_dbus_assert (d != NULL);
return bus_context_get_matchmaker (d->connections->context);
}
/**
* Checks whether the connection is registered with the message bus.
*
......@@ -1024,6 +1083,62 @@ bus_connection_send_oom_error (DBusConnection *connection,
d->oom_preallocated = NULL;
}
void
bus_connection_add_match_rule_link (DBusConnection *connection,
DBusList *link)
{
BusConnectionData *d;
d = BUS_CONNECTION_DATA (connection);
_dbus_assert (d != NULL);
_dbus_list_append_link (&d->match_rules, link);
d->n_match_rules += 1;
}
dbus_bool_t
bus_connection_add_match_rule (DBusConnection *connection,
BusMatchRule *rule)
{
DBusList *link;
link = _dbus_list_alloc_link (rule);
if (link == NULL)
return FALSE;
bus_connection_add_match_rule_link (connection, link);
return TRUE;
}
void
bus_connection_remove_match_rule (DBusConnection *connection,
BusMatchRule *rule)
{
BusConnectionData *d;
d = BUS_CONNECTION_DATA (connection);
_dbus_assert (d != NULL);
_dbus_list_remove_last (&d->match_rules, rule);
d->n_match_rules -= 1;
_dbus_assert (d->n_match_rules >= 0);
}
int
bus_connection_get_n_match_rules (DBusConnection *connection)
{
BusConnectionData *d;
d = BUS_CONNECTION_DATA (connection);
_dbus_assert (d != NULL);
return d->n_match_rules;
}
void
bus_connection_add_owned_service_link (DBusConnection *connection,
DBusList *link)
......@@ -1092,6 +1207,8 @@ bus_connection_complete (DBusConnection *connection,
_dbus_assert (d != NULL);
_dbus_assert (d->name == NULL);
_dbus_assert (d->policy == NULL);
_dbus_assert (!bus_connection_is_active (connection));
if (!_dbus_string_copy_data (name, &d->name))
{
......@@ -1147,6 +1264,8 @@ bus_connection_complete (DBusConnection *connection,
/* See if we can remove the timeout */
bus_connections_expire_incomplete (d->connections);
_dbus_assert (bus_connection_is_active (connection));
return TRUE;
}
......@@ -1327,7 +1446,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction,
* eat it; the driver doesn't care about getting a reply.
*/
if (!bus_context_check_security_policy (bus_transaction_get_context (transaction),
NULL, connection, message, NULL))
NULL, connection, connection, message, NULL))
return TRUE;
return bus_transaction_send (transaction, connection, message);
......
......@@ -44,16 +44,18 @@ void bus_connections_foreach_active (BusConnections
BusConnectionForeachFunction function,
void *data);
BusContext* bus_connections_get_context (BusConnections *connections);
void bus_connections_increment_stamp (BusConnections *connections);
BusContext* bus_connection_get_context (DBusConnection *connection);
BusConnections* bus_connection_get_connections (DBusConnection *connection);
BusRegistry* bus_connection_get_registry (DBusConnection *connection);
BusActivation* bus_connection_get_activation (DBusConnection *connection);
BusMatchmaker* bus_connection_get_matchmaker (DBusConnection *connection);
dbus_bool_t bus_connections_check_limits (BusConnections *connections,
DBusConnection *requesting_completion,
DBusError *error);
void bus_connections_expire_incomplete (BusConnections *connections);
dbus_bool_t bus_connection_mark_stamp (DBusConnection *connection);
dbus_bool_t bus_connection_is_active (DBusConnection *connection);
const char *bus_connection_get_name (DBusConnection *connection);
......@@ -62,6 +64,15 @@ dbus_bool_t bus_connection_preallocate_oom_error (DBusConnection *connection);
void bus_connection_send_oom_error (DBusConnection *connection,
DBusMessage *in_reply_to);
/* called by signals.c */
dbus_bool_t bus_connection_add_match_rule (DBusConnection *connection,
BusMatchRule *rule);
void bus_connection_add_match_rule_link (DBusConnection *connection,
DBusList *link);
void bus_connection_remove_match_rule (DBusConnection *connection,
BusMatchRule *rule);
int bus_connection_get_n_match_rules (DBusConnection *connection);
/* called by services.c */
dbus_bool_t bus_connection_add_owned_service (DBusConnection *connection,
......
......@@ -328,26 +328,32 @@ in the config file.
.TP
.I "<deny>"
.I "<allow>"
.PP
A <deny> element appears below a <policy> element and prohibits some
action. The <allow> element makes an exception to previous <deny>
statements, and works just like <deny> but with the inverse meaning.
.PP
A <deny> element appears below a <policy> element and prohibits
some action. The possible attributes of a <deny> element are:
The possible attributes of these elements are:
.nf
send_interface="interface_name"
send_member="method_or_signal_name"
send_error="error_name"
send_service="service_name"
send_type="method_call|method_return|signal|error"
send_destination="service_name"
send_type="method_call" | "method_return" | "signal" | "error"
send_path="/path/name"
receive_interface="interface_name"
receive_member="method_or_signal_name"
receive_error="error_name"
receive_service="service_name"
receive_type="method_call|method_return|signal|error"
receive_sender="service_name"
receive_type="method_call" | "method_return" | "signal" | "error"
receive_path="/path/name"
eavesdrop="true" | "false"
receive="messagename"
own="servicename"
user="username"
group="groupname"
......@@ -359,8 +365,8 @@ Examples:
<deny send_interface="org.freedesktop.System" send_member="Reboot"/>
<deny receive_interface="org.freedesktop.System" receive_member="Reboot"/>
<deny own="org.freedesktop.System"/>
<deny send_service="org.freedesktop.System"/>
<deny receive_service="org.freedesktop.System"/>
<deny send_destination="org.freedesktop.System"/>
<deny receive_sender="org.freedesktop.System"/>
<deny user="john"/>
<deny group="enemies"/>
.fi
......@@ -371,7 +377,7 @@ particular action. If it matches, the action is denied (unless later
rules in the config file allow it).
.PP
send_service and receive_service rules mean that messages may not be
send_destination and receive_sender rules mean that messages may not be
sent to or received from the *owner* of the given service, not that
they may not be sent *to that service name*. That is, if a connection
owns services A, B, C, and sending to A is denied, sending to B or C
......@@ -381,6 +387,22 @@ will not work either.
The other send_* and receive_* attributes are purely textual/by-value
matches against the given field in the message header.
.PP
"Eavesdropping" occurs when an application receives a message that
was explicitly addressed to a service the application does not own.
Eavesdropping thus only applies to messages that are addressed to
services (i.e. it does not apply to signals).
.PP
For <allow>, eavesdrop="true" indicates that the rule matches even
when eavesdropping. eavesdrop="false" is the default and means that
the rule only allows messages to go to their specified recipient.
For <deny>, eavesdrop="true" indicates that the rule matches
only when eavesdropping. eavesdrop="false" is the default for <deny>
also, but here it means that the rule applies always, even when
not eavesdropping. The eavesdrop attribute can only be combined with
receive rules (with receive_* attributes).
.PP
user and group denials mean that the given user or group may
not connect to the message bus.
......@@ -413,13 +435,6 @@ received" are evaluated separately.
Be careful with send_interface/receive_interface, because the
interface field in messages is optional.
.TP
.I "<allow>"
.PP
Makes an exception to previous <deny> statements. Works
just like <deny> but with the inverse meaning.
.SH AUTHOR
See http://www.freedesktop.org/software/dbus/doc/AUTHORS
......
This diff is collapsed.
......@@ -29,8 +29,9 @@
dbus_bool_t bus_dispatch_add_connection (DBusConnection *connection);
void bus_dispatch_remove_connection (DBusConnection *connection);
dbus_bool_t bus_dispatch_broadcast_message (BusTransaction *transaction,
dbus_bool_t bus_dispatch_matches (BusTransaction *transaction,
DBusConnection *sender,
DBusConnection *recipient,
DBusMessage *message,
DBusError *error);
......
......@@ -27,6 +27,7 @@
#include "driver.h"
#include "dispatch.h"
#include "services.h"
#include "signals.h"
#include "utils.h"
#include <dbus/dbus-string.h>
#include <dbus/dbus-internals.h>
......@@ -69,7 +70,7 @@ bus_driver_send_service_deleted (const char *service_name,
return FALSE;
}
retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
dbus_message_unref (message);
return retval;
......@@ -111,7 +112,7 @@ bus_driver_send_service_created (const char *service_name,
return FALSE;
}
retval = bus_dispatch_broadcast_message (transaction, NULL, message, error);
retval = bus_dispatch_matches (transaction, NULL, NULL, message, error);
dbus_message_unref (message);
return retval;
......@@ -331,6 +332,7 @@ bus_driver_handle_hello (DBusConnection *connection,
bus_service_set_prohibit_replacement (service, TRUE);
_dbus_assert (bus_connection_is_active (connection));
retval = TRUE;
out_0:
......@@ -600,6 +602,160 @@ bus_driver_handle_activate_service (DBusConnection *connection,
return retval;
}
static dbus_bool_t
send_ack_reply (DBusConnection *connection,
BusTransaction *transaction,
DBusMessage *message,
DBusError *error)
{
DBusMessage *reply;
reply = dbus_message_new_method_return (message);
if (reply == NULL)
{
BUS_SET_OOM (error);
return FALSE;
}
if (!bus_transaction_send_from_driver (transaction, connection, reply))
{
BUS_SET_OOM (error);
dbus_message_unref (reply);
return FALSE;
}
dbus_message_unref (reply);
return TRUE;
}
static dbus_bool_t
bus_driver_handle_add_match (DBusConnection *connection,
BusTransaction *transaction,
DBusMessage *message,
DBusError *error)
{
BusMatchRule *rule;
char *text;
DBusString str;
BusMatchmaker *matchmaker;
_DBUS_ASSERT_ERROR_IS_CLEAR (error);
text = NULL;
rule = NULL;
if (bus_connection_get_n_match_rules (connection) >=
bus_context_get_max_match_rules_per_connection (bus_transaction_get_context (transaction)))
{
dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED,
"Connection \"%s\" is not allowed to add more match rules "
"(increase limits in configuration file if required)",
bus_connection_is_active (connection) ?
bus_connection_get_name (connection) :
"(inactive)");
goto failed;
}
if (!dbus_message_get_args (message, error,
DBUS_TYPE_STRING, &text,
DBUS_TYPE_INVALID))
{
_dbus_verbose ("No memory to get arguments to AddMatch\n");