diff options
-rw-r--r-- | ChangeLog | 29 | ||||
-rw-r--r-- | bus/activation.c | 18 | ||||
-rw-r--r-- | bus/bus.c | 63 | ||||
-rw-r--r-- | bus/bus.h | 5 | ||||
-rw-r--r-- | bus/config-parser.c | 14 | ||||
-rw-r--r-- | bus/connection.c | 40 | ||||
-rw-r--r-- | bus/connection.h | 5 | ||||
-rw-r--r-- | bus/dispatch.c | 152 | ||||
-rw-r--r-- | bus/dispatch.h | 1 | ||||
-rw-r--r-- | bus/driver.c | 55 | ||||
-rw-r--r-- | bus/policy.c | 100 | ||||
-rw-r--r-- | bus/policy.h | 4 | ||||
-rw-r--r-- | bus/session.conf.in | 1 | ||||
-rw-r--r-- | bus/system.conf.in | 2 | ||||
-rw-r--r-- | dbus/dbus-connection.c | 4 | ||||
-rw-r--r-- | dbus/dbus-mainloop.c | 65 | ||||
-rw-r--r-- | dbus/dbus-message.c | 2 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.c | 75 | ||||
-rw-r--r-- | dbus/dbus-sysdeps.h | 3 | ||||
-rw-r--r-- | dbus/dbus-transport-protected.h | 1 | ||||
-rw-r--r-- | dbus/dbus-transport.c | 38 | ||||
-rw-r--r-- | doc/TODO | 4 | ||||
-rw-r--r-- | test/data/valid-config-files/debug-allow-all.conf.in | 1 |
23 files changed, 425 insertions, 257 deletions
@@ -1,5 +1,34 @@ 2003-04-13 Havoc Pennington <hp@pobox.com> + * dbus/dbus-mainloop.c: fix some reentrancy issues by refcounting + callbacks + + * test/data/valid-config-files/debug-allow-all.conf.in: allow all + users + + * dbus/dbus-transport.c (_dbus_transport_get_dispatch_status): + fix to only recover unused bytes if we're already authenticated + (_dbus_transport_get_is_authenticated): fix to still mark us + authenticated if there are unused bytes. + + * bus/dispatch.c: implement security policy checking + + * bus/connection.c (bus_transaction_send_from_driver): new + + * bus/bus.c (bus_context_check_security_policy): new + + * bus/dispatch.c (send_service_nonexistent_error): delete this, + now we just set the DBusError and it gets converted to an error + reply. + + * bus/connection.c (allow_user_function): enable code using actual + data from the config file + + * bus/policy.c (list_allows_user): handle wildcard rules for + user/group connection perms + +2003-04-13 Havoc Pennington <hp@pobox.com> + * bus/config-parser.c: Load up the BusPolicy and BusPolicyRules * dbus/dbus-sysdeps.c (_dbus_get_user_id): new function diff --git a/bus/activation.c b/bus/activation.c index 1a448a79..0a70d6b1 100644 --- a/bus/activation.c +++ b/bus/activation.c @@ -582,8 +582,7 @@ bus_activation_service_created (BusActivation *activation, goto error; } - if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) || - !dbus_message_append_args (message, + if (!dbus_message_append_args (message, DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ACTIVATED, 0)) { @@ -592,7 +591,7 @@ bus_activation_service_created (BusActivation *activation, goto error; } - if (!bus_transaction_send_message (transaction, entry->connection, message)) + if (!bus_transaction_send_from_driver (transaction, entry->connection, message)) { dbus_message_unref (message); BUS_SET_OOM (error); @@ -654,14 +653,8 @@ try_send_activation_failure (BusPendingActivation *pending_activation, how->message); if (!message) goto error; - - if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) - { - dbus_message_unref (message); - goto error; - } - if (!bus_transaction_send_message (transaction, entry->connection, message)) + if (!bus_transaction_send_from_driver (transaction, entry->connection, message)) { dbus_message_unref (message); goto error; @@ -861,8 +854,7 @@ bus_activation_activate_service (BusActivation *activation, return FALSE; } - if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS) || - !dbus_message_append_args (message, + if (!dbus_message_append_args (message, DBUS_TYPE_UINT32, DBUS_ACTIVATION_REPLY_ALREADY_ACTIVE, 0)) { @@ -872,7 +864,7 @@ bus_activation_activate_service (BusActivation *activation, return FALSE; } - retval = bus_transaction_send_message (transaction, connection, message); + retval = bus_transaction_send_from_driver (transaction, connection, message); dbus_message_unref (message); if (!retval) { @@ -796,3 +796,66 @@ bus_context_get_activation_timeout (BusContext *context) return context->activation_timeout; } + +dbus_bool_t +bus_context_check_security_policy (BusContext *context, + DBusConnection *sender, + DBusConnection *recipient, + DBusMessage *message, + DBusError *error) +{ + BusClientPolicy *sender_policy; + BusClientPolicy *recipient_policy; + + /* NULL sender/receiver means the bus driver */ + + if (sender != NULL) + { + _dbus_assert (dbus_connection_get_is_authenticated (sender)); + sender_policy = bus_connection_get_policy (sender); + } + else + sender_policy = NULL; + + if (recipient != NULL) + { + _dbus_assert (dbus_connection_get_is_authenticated (recipient)); + recipient_policy = bus_connection_get_policy (recipient); + } + else + recipient_policy = NULL; + + if (sender_policy && + !bus_client_policy_check_can_send (sender_policy, + context->registry, recipient, + message)) + { + const char *dest = dbus_message_get_service (message); + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "A security policy in place prevents this sender " + "from sending this message to this recipient, " + "see message bus configuration file (rejected message " + "had name \"%s\" destination \"%s\")", + dbus_message_get_name (message), + dest ? dest : DBUS_SERVICE_DBUS); + return FALSE; + } + + if (recipient_policy && + !bus_client_policy_check_can_receive (recipient_policy, + context->registry, sender, + message)) + { + const char *dest = dbus_message_get_service (message); + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "A security policy in place prevents this recipient " + "from receiving this message from this sender, " + "see message bus configuration file (rejected message " + "had name \"%s\" destination \"%s\")", + dbus_message_get_name (message), + dest ? dest : DBUS_SERVICE_DBUS); + return FALSE; + } + + return TRUE; +} @@ -57,6 +57,11 @@ dbus_bool_t bus_context_allow_user (BusContext *context, BusClientPolicy* bus_context_create_client_policy (BusContext *context, DBusConnection *connection); int bus_context_get_activation_timeout (BusContext *context); +dbus_bool_t bus_context_check_security_policy (BusContext *context, + DBusConnection *sender, + DBusConnection *recipient, + DBusMessage *message, + DBusError *error); #endif /* BUS_BUS_H */ diff --git a/bus/config-parser.c b/bus/config-parser.c index 85c367b3..bf959ae2 100644 --- a/bus/config-parser.c +++ b/bus/config-parser.c @@ -859,7 +859,7 @@ append_rule_from_element (BusConfigParser *parser, if (rule == NULL) goto nomem; - /* FIXME the wildcard needs storing in the rule somehow */ + rule->d.user.uid = DBUS_UID_UNSET; } else { @@ -873,10 +873,7 @@ append_rule_from_element (BusConfigParser *parser, rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); if (rule == NULL) goto nomem; - - rule->d.user.user = _dbus_strdup (user); - if (rule->d.user.user == NULL) - goto nomem; + rule->d.user.uid = uid; } else @@ -894,7 +891,7 @@ append_rule_from_element (BusConfigParser *parser, if (rule == NULL) goto nomem; - /* FIXME the wildcard needs storing in the rule somehow */ + rule->d.group.gid = DBUS_GID_UNSET; } else { @@ -908,10 +905,7 @@ append_rule_from_element (BusConfigParser *parser, rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); if (rule == NULL) goto nomem; - - rule->d.group.group = _dbus_strdup (group); - if (rule->d.group.group == NULL) - goto nomem; + rule->d.group.gid = gid; } else diff --git a/bus/connection.c b/bus/connection.c index 21c8f1a3..4c48fbd6 100644 --- a/bus/connection.c +++ b/bus/connection.c @@ -283,8 +283,6 @@ allow_user_function (DBusConnection *connection, d = BUS_CONNECTION_DATA (connection); _dbus_assert (d != NULL); - - return TRUE; /* FIXME - this is just until we can parse a config file */ return bus_context_allow_user (d->connections->context, uid); } @@ -504,7 +502,7 @@ bus_connection_get_groups (DBusConnection *connection, if (dbus_connection_get_unix_user (connection, &uid)) { - if (!_dbus_get_groups (uid, &d->group_ids, &d->n_group_ids)) + if (!_dbus_get_groups (uid, &d->group_ids, &d->n_group_ids, NULL)) { _dbus_verbose ("Did not get any groups for UID %lu\n", uid); @@ -924,9 +922,34 @@ bus_transaction_get_connections (BusTransaction *transaction) } dbus_bool_t -bus_transaction_send_message (BusTransaction *transaction, - DBusConnection *connection, - DBusMessage *message) +bus_transaction_send_from_driver (BusTransaction *transaction, + DBusConnection *connection, + DBusMessage *message) +{ + /* We have to set the sender to the driver, and have + * to check security policy since it was not done in + * dispatch.c + */ + _dbus_verbose ("Sending %s from driver\n", + dbus_message_get_name (message)); + + if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) + return FALSE; + + /* If security policy doesn't allow the message, we silently + * 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)) + return TRUE; + + return bus_transaction_send (transaction, connection, message); +} + +dbus_bool_t +bus_transaction_send (BusTransaction *transaction, + DBusConnection *connection, + DBusMessage *message) { MessageToSend *to_send; BusConnectionData *d; @@ -934,7 +957,7 @@ bus_transaction_send_message (BusTransaction *transaction, _dbus_verbose (" trying to add %s %s to transaction%s\n", dbus_message_get_is_error (message) ? "error" : - dbus_message_get_reply_serial (message) != 0 ? "reply" : + dbus_message_get_reply_serial (message) != -1 ? "reply" : "message", dbus_message_get_name (message), dbus_connection_get_is_connected (connection) ? @@ -1152,8 +1175,7 @@ bus_transaction_send_error_reply (BusTransaction *transaction, if (reply == NULL) return FALSE; - if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS) || - !bus_transaction_send_message (transaction, connection, reply)) + if (!bus_transaction_send_from_driver (transaction, connection, reply)) { dbus_message_unref (reply); return FALSE; diff --git a/bus/connection.h b/bus/connection.h index 4962211e..ead47673 100644 --- a/bus/connection.h +++ b/bus/connection.h @@ -84,7 +84,10 @@ typedef void (* BusTransactionCancelFunction) (void *data); BusTransaction* bus_transaction_new (BusContext *context); BusContext* bus_transaction_get_context (BusTransaction *transaction); BusConnections* bus_transaction_get_connections (BusTransaction *transaction); -dbus_bool_t bus_transaction_send_message (BusTransaction *transaction, +dbus_bool_t bus_transaction_send (BusTransaction *transaction, + DBusConnection *connection, + DBusMessage *message); +dbus_bool_t bus_transaction_send_from_driver (BusTransaction *transaction, DBusConnection *connection, DBusMessage *message); dbus_bool_t bus_transaction_send_error_reply (BusTransaction *transaction, diff --git a/bus/dispatch.c b/bus/dispatch.c index 41317549..3ce7731c 100644 --- a/bus/dispatch.c +++ b/bus/dispatch.c @@ -37,6 +37,8 @@ static int message_handler_slot_refcount; typedef struct { + BusContext *context; + DBusConnection *sender; DBusMessage *message; BusTransaction *transaction; DBusError *error; @@ -50,9 +52,16 @@ send_one_message (DBusConnection *connection, void *data) if (!bus_connection_is_active (connection)) return TRUE; - if (!bus_transaction_send_message (d->transaction, - connection, - d->message)) + if (!bus_context_check_security_policy (d->context, + d->sender, + connection, + d->message, + NULL)) + return TRUE; /* silently don't send it */ + + if (!bus_transaction_send (d->transaction, + connection, + d->message)) { BUS_SET_OOM (d->error); return FALSE; @@ -63,6 +72,7 @@ send_one_message (DBusConnection *connection, void *data) dbus_bool_t bus_dispatch_broadcast_message (BusTransaction *transaction, + DBusConnection *sender, DBusMessage *message, DBusError *error) { @@ -77,6 +87,8 @@ bus_dispatch_broadcast_message (BusTransaction *transaction, connections = bus_transaction_get_connections (transaction); dbus_error_init (&tmp_error); + d.sender = sender; + d.context = bus_transaction_get_context (transaction); d.message = message; d.transaction = transaction; d.error = &tmp_error; @@ -92,70 +104,6 @@ bus_dispatch_broadcast_message (BusTransaction *transaction, return TRUE; } -static dbus_bool_t -send_service_nonexistent_error (BusTransaction *transaction, - DBusConnection *connection, - const char *service_name, - DBusMessage *in_reply_to, - DBusError *error) -{ - DBusMessage *error_reply; - DBusString error_message; - const char *error_str; - - _DBUS_ASSERT_ERROR_IS_CLEAR (error); - - /* Trying to send a message to a non-existant service, - * bounce back an error message. - */ - - if (!_dbus_string_init (&error_message)) - { - BUS_SET_OOM (error); - return FALSE; - } - - if (!_dbus_string_append (&error_message, "Service \"") || - !_dbus_string_append (&error_message, service_name) || - !_dbus_string_append (&error_message, "\" does not exist")) - { - _dbus_string_free (&error_message); - BUS_SET_OOM (error); - return FALSE; - } - - error_str = _dbus_string_get_const_data (&error_message); - error_reply = dbus_message_new_error_reply (in_reply_to, - DBUS_ERROR_SERVICE_DOES_NOT_EXIST, - error_str); - - _dbus_string_free (&error_message); - - if (error_reply == NULL) - { - BUS_SET_OOM (error); - return FALSE; - } - - if (!dbus_message_set_sender (error_reply, DBUS_SERVICE_DBUS)) - { - dbus_message_unref (error_reply); - BUS_SET_OOM (error); - return FALSE; - } - - if (!bus_transaction_send_message (transaction, connection, error_reply)) - { - dbus_message_unref (error_reply); - BUS_SET_OOM (error); - return FALSE; - } - - dbus_message_unref (error_reply); - - return TRUE; -} - static void bus_dispatch (DBusConnection *connection, DBusMessage *message) @@ -188,9 +136,10 @@ bus_dispatch (DBusConnection *connection, _dbus_verbose ("DISPATCH: %s to %s\n", message_name, service_name ? service_name : "peer"); - /* If service_name is NULL, this is a message to the bus daemon, not intended - * to actually go "on the bus"; e.g. a peer-to-peer ping. Handle these - * immediately, especially disconnection messages. + /* If service_name is NULL, this is a message to the bus daemon, not + * intended to actually go "on the bus"; e.g. a peer-to-peer + * ping. Handle these immediately, especially disconnection + * messages. There are no security policy checks on these. */ if (service_name == NULL) { @@ -235,6 +184,10 @@ bus_dispatch (DBusConnection *connection, if (strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */ { + if (!bus_context_check_security_policy (context, + connection, NULL, message, &error)) + goto out; + if (!bus_driver_handle_message (connection, transaction, message, &error)) goto out; } @@ -249,7 +202,7 @@ bus_dispatch (DBusConnection *connection, */ else if (strcmp (service_name, DBUS_SERVICE_BROADCAST) == 0) /* spam! */ { - if (!bus_dispatch_broadcast_message (transaction, message, &error)) + if (!bus_dispatch_broadcast_message (transaction, connection, message, &error)) goto out; } else /* route to named service */ @@ -265,19 +218,25 @@ bus_dispatch (DBusConnection *connection, if (service == NULL) { - if (!send_service_nonexistent_error (transaction, connection, - service_name, - message, &error)) - goto out; + dbus_set_error (&error, + DBUS_ERROR_SERVICE_DOES_NOT_EXIST, + "Service \"%s\" does not exist", + service_name); + goto out; } else { - _dbus_assert (bus_service_get_primary_owner (service) != NULL); - + DBusConnection *recipient; + + recipient = bus_service_get_primary_owner (service); + _dbus_assert (recipient != NULL); + + if (!bus_context_check_security_policy (context, + connection, recipient, message, &error)) + goto out; + /* Dispatch the message */ - if (!bus_transaction_send_message (transaction, - bus_service_get_primary_owner (service), - message)) + if (!bus_transaction_send (transaction, recipient, message)) { BUS_SET_OOM (&error); goto out; @@ -316,7 +275,7 @@ bus_dispatch (DBusConnection *connection, &error, message)) { bus_connection_send_oom_error (connection, message); - + /* cancel transaction due to OOM */ if (transaction != NULL) { @@ -608,8 +567,9 @@ kill_client_connection_unchecked (DBusConnection *connection) /* dispatching disconnect handler will unref once */ if (bus_connection_dispatch_one_message (connection)) _dbus_assert_not_reached ("message other than disconnect dispatched after failure to register"); - dbus_connection_unref (connection); + _dbus_assert (!bus_test_client_listed (connection)); + dbus_connection_unref (connection); } typedef struct @@ -740,10 +700,12 @@ check_hello_message (BusContext *context, DBusError error; char *name; char *acquired; - + + retval = FALSE; dbus_error_init (&error); name = NULL; acquired = NULL; + message = NULL; message = dbus_message_new (DBUS_SERVICE_DBUS, DBUS_MESSAGE_HELLO); @@ -760,15 +722,22 @@ check_hello_message (BusContext *context, dbus_message_unref (message); message = NULL; - bus_test_run_everything (context); + /* send our message */ + bus_test_run_clients_loop (TRUE); + + dbus_connection_ref (connection); /* because we may get disconnected */ + block_connection_until_message_from_bus (context, connection); if (!dbus_connection_get_is_connected (connection)) { _dbus_verbose ("connection was disconnected\n"); + + dbus_connection_unref (connection); + return TRUE; } - - retval = FALSE; + + dbus_connection_unref (connection); message = pop_message_waiting_for_memory (connection); if (message == NULL) @@ -1390,7 +1359,10 @@ check_send_exit_to_service (BusContext *context, message = dbus_connection_borrow_message (connection); got_error = message != NULL && dbus_message_get_is_error (message); if (message) - dbus_connection_return_message (connection, message); + { + dbus_connection_return_message (connection, message); + message = NULL; + } if (!got_error) { @@ -1944,6 +1916,12 @@ bus_dispatch_test (const DBusString *test_data_dir) if (!check_hello_message (context, baz)) _dbus_assert_not_reached ("hello message failed"); + if (!check_no_leftovers (context)) + { + _dbus_warn ("Messages were left over after setting up initial connections"); + _dbus_assert_not_reached ("initial connection setup failed"); + } + check1_try_iterations (context, "create_and_hello", check_hello_connection); diff --git a/bus/dispatch.h b/bus/dispatch.h index c24170dc..18f74529 100644 --- a/bus/dispatch.h +++ b/bus/dispatch.h @@ -30,6 +30,7 @@ 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, + DBusConnection *sender, DBusMessage *message, DBusError *error); diff --git a/bus/driver.c b/bus/driver.c index f89b70a3..c7d66d53 100644 --- a/bus/driver.c +++ b/bus/driver.c @@ -67,7 +67,7 @@ bus_driver_send_service_deleted (const char *service_name, return FALSE; } - retval = bus_dispatch_broadcast_message (transaction, message, error); + retval = bus_dispatch_broadcast_message (transaction, NULL, message, error); dbus_message_unref (message); return retval; @@ -107,7 +107,7 @@ bus_driver_send_service_created (const char *service_name, return FALSE; } - retval = bus_dispatch_broadcast_message (transaction, message, error); + retval = bus_dispatch_broadcast_message (transaction, NULL, message, error); dbus_message_unref (message); return retval; @@ -131,13 +131,6 @@ bus_driver_send_service_lost (DBusConnection *connection, return FALSE; } - if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) - { - dbus_message_unref (message); - BUS_SET_OOM (error); - return FALSE; - } - if (!dbus_message_append_args (message, DBUS_TYPE_STRING, service_name, 0)) @@ -147,7 +140,7 @@ bus_driver_send_service_lost (DBusConnection *connection, return FALSE; } - if (!bus_transaction_send_message (transaction, connection, message)) + if (!bus_transaction_send_from_driver (transaction, connection, message)) { dbus_message_unref (message); BUS_SET_OOM (error); @@ -178,13 +171,6 @@ bus_driver_send_service_acquired (DBusConnection *connection, return FALSE; } - if (!dbus_message_set_sender (message, DBUS_SERVICE_DBUS)) - { - dbus_message_unref (message); - BUS_SET_OOM (error); - return FALSE; - } - if (!dbus_message_append_args (message, DBUS_TYPE_STRING, service_name, 0)) @@ -194,7 +180,7 @@ bus_driver_send_service_acquired (DBusConnection *connection, return FALSE; } - if (!bus_transaction_send_message (transaction, connection, message)) + if (!bus_transaction_send_from_driver (transaction, connection, message)) { dbus_message_unref (message); BUS_SET_OOM (error); @@ -347,13 +333,6 @@ bus_driver_send_welcome_message (DBusConnection *connection, return FALSE; } - if (!dbus_message_set_sender (welcome, DBUS_SERVICE_DBUS)) - { - dbus_message_unref (welcome); - BUS_SET_OOM (error); - return FALSE; - } - if (!dbus_message_append_args (welcome, DBUS_TYPE_STRING, name, NULL)) @@ -363,7 +342,7 @@ bus_driver_send_welcome_message (DBusConnection *connection, return FALSE; } - if (!bus_transaction_send_message (transaction, connection, welcome)) + if (!bus_transaction_send_from_driver (transaction, connection, welcome)) { dbus_message_unref (welcome); BUS_SET_OOM (error); @@ -417,7 +396,7 @@ bus_driver_handle_list_services (DBusConnection *connection, dbus_free_string_array (services); - if (!bus_transaction_send_message (transaction, connection, reply)) + if (!bus_transaction_send_from_driver (transaction, connection, reply)) { dbus_message_unref (reply); BUS_SET_OOM (error); @@ -474,19 +453,13 @@ bus_driver_handle_acquire_service (DBusConnection *connection, goto out; } - if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS)) - { - BUS_SET_OOM (error); - goto out; - } - if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, service_reply, DBUS_TYPE_INVALID)) { BUS_SET_OOM (error); goto out; } - if (!bus_transaction_send_message (transaction, connection, reply)) + if (!bus_transaction_send_from_driver (transaction, connection, reply)) { BUS_SET_OOM (error); goto out; @@ -534,12 +507,6 @@ bus_driver_handle_service_exists (DBusConnection *connection, BUS_SET_OOM (error); goto out; } - - if (!dbus_message_set_sender (reply, DBUS_SERVICE_DBUS)) - { - BUS_SET_OOM (error); - goto out; - } if (!dbus_message_append_args (reply, DBUS_TYPE_UINT32, service != NULL, @@ -549,7 +516,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, goto out; } - if (!bus_transaction_send_message (transaction, connection, reply)) + if (!bus_transaction_send_from_driver (transaction, connection, reply)) { BUS_SET_OOM (error); goto out; @@ -653,6 +620,12 @@ bus_driver_handle_message (DBusConnection *connection, return FALSE; } + if (dbus_message_get_reply_serial (message) != -1) + { + _dbus_verbose ("Client sent a reply to the bus driver, ignoring it\n"); + return TRUE; + } + i = 0; while (i < _DBUS_N_ELEMENTS (message_handlers)) { diff --git a/bus/policy.c b/bus/policy.c index 81894b8b..ad0cfaef 100644 --- a/bus/policy.c +++ b/bus/policy.c @@ -73,7 +73,7 @@ bus_policy_rule_unref (BusPolicyRule *rule) _dbus_assert (rule->refcount > 0); rule->refcount -= 1; - + if (rule->refcount == 0) { switch (rule->type) @@ -90,10 +90,8 @@ bus_policy_rule_unref (BusPolicyRule *rule) dbus_free (rule->d.own.service_name); break; case BUS_POLICY_RULE_USER: - dbus_free (rule->d.user.user); break; case BUS_POLICY_RULE_GROUP: - dbus_free (rule->d.group.group); break; } @@ -239,7 +237,6 @@ bus_policy_create_client_policy (BusPolicy *policy, { BusClientPolicy *client; unsigned long uid; - DBusList **list; _dbus_assert (dbus_connection_get_is_authenticated (connection)); @@ -266,6 +263,8 @@ bus_policy_create_client_policy (BusPolicy *policy, i = 0; while (i < n_groups) { + DBusList **list; + list = _dbus_hash_table_lookup_ulong (policy->rules_by_gid, groups[i]); @@ -282,12 +281,20 @@ bus_policy_create_client_policy (BusPolicy *policy, if (!dbus_connection_get_unix_user (connection, &uid)) goto failed; - list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid, - uid); + if (_dbus_hash_table_get_n_entries (policy->rules_by_uid) > 0) + { + DBusList **list; + + list = _dbus_hash_table_lookup_ulong (policy->rules_by_uid, + uid); + + if (list != NULL) + { + if (!add_list_to_client (list, client)) + goto failed; + } + } - if (!add_list_to_client (list, client)) - goto failed; - if (!add_list_to_client (&policy->mandatory_rules, client)) goto failed; @@ -310,9 +317,6 @@ list_allows_user (dbus_bool_t def, { DBusList *link; dbus_bool_t allowed; - - /* FIXME there's currently no handling of wildcard user/group rules. - */ allowed = def; @@ -324,23 +328,36 @@ list_allows_user (dbus_bool_t def, if (rule->type == BUS_POLICY_RULE_USER) { - if (rule->d.user.uid != uid) + _dbus_verbose ("List %p user rule uid="DBUS_UID_FORMAT"\n", + list, rule->d.user.uid); + + if (rule->d.user.uid == DBUS_UID_UNSET) + ; /* '*' wildcard */ + else if (rule->d.user.uid != uid) continue; } else if (rule->type == BUS_POLICY_RULE_GROUP) { - int i; - - i = 0; - while (i < n_group_ids) + _dbus_verbose ("List %p group rule uid="DBUS_UID_FORMAT"\n", + list, rule->d.user.uid); + + if (rule->d.group.gid == DBUS_GID_UNSET) + ; /* '*' wildcard */ + else { - if (rule->d.group.gid == group_ids[i]) - break; - ++i; + int i; + + i = 0; + while (i < n_group_ids) + { + if (rule->d.group.gid == group_ids[i]) + break; + ++i; + } + + if (i == n_group_ids) + continue; } - - if (i == n_group_ids) - continue; } else continue; @@ -360,7 +377,7 @@ bus_policy_allow_user (BusPolicy *policy, int n_group_ids; /* On OOM or error we always reject the user */ - if (!_dbus_get_groups (uid, &group_ids, &n_group_ids)) + if (!_dbus_get_groups (uid, &group_ids, &n_group_ids, NULL)) { _dbus_verbose ("Did not get any groups for UID %lu\n", uid); @@ -381,6 +398,8 @@ bus_policy_allow_user (BusPolicy *policy, dbus_free (group_ids); + _dbus_verbose ("UID %lu allowed = %d\n", uid, allowed); + return allowed; } @@ -536,15 +555,18 @@ remove_rules_by_type_up_to (BusClientPolicy *policy, { DBusList *link; - link = _dbus_list_get_first (&policy->rules); + link = _dbus_list_get_first_link (&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); - + if (rule->type == type) + { + _dbus_list_remove_link (&policy->rules, link); + bus_policy_rule_unref (rule); + } + link = next; } } @@ -571,14 +593,19 @@ bus_client_policy_optimize (BusClientPolicy *policy) _dbus_verbose ("Optimizing policy with %d rules\n", _dbus_list_get_length (&policy->rules)); - link = _dbus_list_get_first (&policy->rules); + link = _dbus_list_get_first_link (&policy->rules); while (link != NULL) { - BusPolicyRule *rule = link->data; - DBusList *next = _dbus_list_get_next_link (&policy->rules, link); + BusPolicyRule *rule; + DBusList *next; dbus_bool_t remove_preceding; + next = _dbus_list_get_next_link (&policy->rules, link); + rule = link->data; + remove_preceding = FALSE; + + _dbus_assert (rule != NULL); switch (rule->type) { @@ -601,7 +628,7 @@ bus_client_policy_optimize (BusClientPolicy *policy) _dbus_assert_not_reached ("invalid rule"); break; } - + if (remove_preceding) remove_rules_by_type_up_to (policy, rule->type, link); @@ -617,6 +644,9 @@ dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy, BusPolicyRule *rule) { + _dbus_verbose ("Appending rule %p with type %d to policy %p\n", + rule, rule->type, policy); + if (!_dbus_list_append (&policy->rules, rule)) return FALSE; @@ -639,7 +669,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, */ allowed = FALSE; - link = _dbus_list_get_first (&policy->rules); + link = _dbus_list_get_first_link (&policy->rules); while (link != NULL) { BusPolicyRule *rule = link->data; @@ -711,7 +741,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, */ allowed = FALSE; - link = _dbus_list_get_first (&policy->rules); + link = _dbus_list_get_first_link (&policy->rules); while (link != NULL) { BusPolicyRule *rule = link->data; @@ -783,7 +813,7 @@ bus_client_policy_check_can_own (BusClientPolicy *policy, */ allowed = FALSE; - link = _dbus_list_get_first (&policy->rules); + link = _dbus_list_get_first_link (&policy->rules); while (link != NULL) { BusPolicyRule *rule = link->data; diff --git a/bus/policy.h b/bus/policy.h index 986cfe07..53e30e77 100644 --- a/bus/policy.h +++ b/bus/policy.h @@ -74,13 +74,13 @@ struct BusPolicyRule struct { - char *user; + /* can be DBUS_UID_UNSET meaning "any" */ dbus_uid_t uid; } user; struct { - char *group; + /* can be DBUS_GID_UNSET meaning "any" */ dbus_gid_t gid; } group; diff --git a/bus/session.conf.in b/bus/session.conf.in index d430d990..4feca235 100644 --- a/bus/session.conf.in +++ b/bus/session.conf.in @@ -15,6 +15,7 @@ <allow send="*"/> <allow receive="*"/> <allow own="*"/> + <allow user="*"/> </policy> <!-- This is included last so local configuration can override what's diff --git a/bus/system.conf.in b/bus/system.conf.in index 0e570575..e65c4af1 100644 --- a/bus/system.conf.in +++ b/bus/system.conf.in @@ -34,6 +34,8 @@ <deny send="*"/> <deny receive="*"/> <deny own="*"/> + <!-- But allow all users to connect --> + <allow user="*"/> </policy> <!-- This is included last so local configuration can override what's diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c index 9595f48a..94fe075c 100644 --- a/dbus/dbus-connection.c +++ b/dbus/dbus-connection.c @@ -2082,8 +2082,8 @@ dbus_connection_dispatch (DBusConnection *connection) } } - _dbus_verbose (" done dispatching %p (%s)\n", message, - dbus_message_get_name (message)); + _dbus_verbose (" done dispatching %p (%s) on connection %p\n", message, + dbus_message_get_name (message), connection); out: _dbus_connection_release_dispatch (connection); diff --git a/dbus/dbus-mainloop.c b/dbus/dbus-mainloop.c index bf011082..3c810f22 100644 --- a/dbus/dbus-mainloop.c +++ b/dbus/dbus-mainloop.c @@ -47,6 +47,7 @@ typedef enum typedef struct { + int refcount; CallbackType type; void *data; DBusFreeFunction free_data_func; @@ -74,10 +75,10 @@ typedef struct #define TIMEOUT_CALLBACK(callback) ((TimeoutCallback*)callback) static WatchCallback* -watch_callback_new (DBusWatch *watch, +watch_callback_new (DBusWatch *watch, DBusWatchFunction function, - void *data, - DBusFreeFunction free_data_func) + void *data, + DBusFreeFunction free_data_func) { WatchCallback *cb; @@ -88,18 +89,19 @@ watch_callback_new (DBusWatch *watch, cb->watch = watch; cb->function = function; cb->last_iteration_oom = FALSE; + cb->callback.refcount = 1; cb->callback.type = CALLBACK_WATCH; cb->callback.data = data; cb->callback.free_data_func = free_data_func; - + return cb; } static TimeoutCallback* -timeout_callback_new (DBusTimeout *timeout, +timeout_callback_new (DBusTimeout *timeout, DBusTimeoutFunction function, - void *data, - DBusFreeFunction free_data_func) + void *data, + DBusFreeFunction free_data_func) { TimeoutCallback *cb; @@ -111,6 +113,7 @@ timeout_callback_new (DBusTimeout *timeout, cb->function = function; _dbus_get_current_time (&cb->last_tv_sec, &cb->last_tv_usec); + cb->callback.refcount = 1; cb->callback.type = CALLBACK_TIMEOUT; cb->callback.data = data; cb->callback.free_data_func = free_data_func; @@ -119,12 +122,27 @@ timeout_callback_new (DBusTimeout *timeout, } static void -callback_free (Callback *cb) +callback_ref (Callback *cb) +{ + _dbus_assert (cb->refcount > 0); + + cb->refcount += 1; +} + +static void +callback_unref (Callback *cb) { - if (cb->free_data_func) - (* cb->free_data_func) (cb->data); + _dbus_assert (cb->refcount > 0); + + cb->refcount -= 1; - dbus_free (cb); + if (cb->refcount == 0) + { + if (cb->free_data_func) + (* cb->free_data_func) (cb->data); + + dbus_free (cb); + } } static dbus_bool_t @@ -165,7 +183,7 @@ remove_callback (DBusLoop *loop, break; } - callback_free (cb); + callback_unref (cb); _dbus_list_remove_link (&loop->callbacks, link); loop->callback_list_serial += 1; } @@ -229,7 +247,7 @@ _dbus_loop_add_watch (DBusLoop *loop, if (!add_callback (loop, (Callback*) wcb)) { wcb->callback.free_data_func = NULL; /* don't want to have this side effect */ - callback_free ((Callback*) wcb); + callback_unref ((Callback*) wcb); return FALSE; } @@ -283,7 +301,7 @@ _dbus_loop_add_timeout (DBusLoop *loop, if (!add_callback (loop, (Callback*) tcb)) { tcb->callback.free_data_func = NULL; /* don't want to have this side effect */ - callback_free ((Callback*) tcb); + callback_unref ((Callback*) tcb); return FALSE; } @@ -490,6 +508,7 @@ _dbus_loop_iterate (DBusLoop *loop, fds = NULL; watches_for_fds = NULL; + n_fds = 0; oom_watch_pending = FALSE; orig_depth = loop->depth; @@ -578,6 +597,8 @@ _dbus_loop_iterate (DBusLoop *loop, else if (dbus_watch_get_enabled (wcb->watch)) { watches_for_fds[i] = wcb; + + callback_ref (cb); flags = dbus_watch_get_flags (wcb->watch); @@ -726,7 +747,7 @@ _dbus_loop_iterate (DBusLoop *loop, unsigned int condition; wcb = watches_for_fds[i]; - + condition = 0; if (fds[i].revents & _DBUS_POLLIN) condition |= DBUS_WATCH_READABLE; @@ -765,8 +786,18 @@ _dbus_loop_iterate (DBusLoop *loop, next_iteration: if (fds && fds != static_fds) dbus_free (fds); - if (watches_for_fds && watches_for_fds != static_watches_for_fds) - dbus_free (watches_for_fds); + if (watches_for_fds) + { + i = 0; + while (i < n_fds) + { + callback_unref (&watches_for_fds[i]->callback); + ++i; + } + + if (watches_for_fds != static_watches_for_fds) + dbus_free (watches_for_fds); + } if (_dbus_loop_dispatch (loop)) retval = TRUE; diff --git a/dbus/dbus-message.c b/dbus/dbus-message.c index 0044913e..5e6a2c60 100644 --- a/dbus/dbus-message.c +++ b/dbus/dbus-message.c @@ -585,7 +585,7 @@ _dbus_message_set_serial (DBusMessage *message, */ dbus_bool_t dbus_message_set_reply_serial (DBusMessage *message, - dbus_int32_t reply_serial) + dbus_int32_t reply_serial) { _dbus_assert (!message->locked); diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c index f706d08a..0877a293 100644 --- a/dbus/dbus-sysdeps.c +++ b/dbus/dbus-sysdeps.c @@ -1315,7 +1315,8 @@ static dbus_bool_t store_user_info (struct passwd *p, DBusCredentials *credentials, DBusString *homedir, - DBusString *username_out) + DBusString *username_out, + DBusError *error) { int old_homedir_len; @@ -1332,7 +1333,7 @@ store_user_info (struct passwd *p, if (!_dbus_string_append (homedir, p->pw_dir)) { - _dbus_verbose ("No memory to get homedir\n"); + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; } } @@ -1342,7 +1343,7 @@ store_user_info (struct passwd *p, { if (homedir) _dbus_string_set_length (homedir, old_homedir_len); - _dbus_verbose ("No memory to get username\n"); + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return FALSE; } @@ -1363,6 +1364,7 @@ store_user_info (struct passwd *p, * @param credentials to fill in or #NULL * @param homedir string to append homedir to or #NULL * @param username_out string to append username to or #NULL + * @param error return location for reason for failure * * @returns #TRUE on success */ @@ -1371,7 +1373,8 @@ get_user_info (const DBusString *username, dbus_uid_t uid, DBusCredentials *credentials, DBusString *homedir, - DBusString *username_out) + DBusString *username_out, + DBusError *error) { const char *username_c_str; @@ -1417,10 +1420,13 @@ get_user_info (const DBusString *username, if (result == 0 && p == &p_str) { return store_user_info (p, credentials, homedir, - username_out); + username_out, error); } else { + dbus_set_error (error, DBUS_ERROR_FAILED, + "User \"%s\" unknown or no memory to allocate password entry\n", + username_c_str); _dbus_verbose ("User %s unknown\n", username_c_str); return FALSE; } @@ -1438,10 +1444,13 @@ get_user_info (const DBusString *username, if (p != NULL) { return store_user_info (p, credentials, homedir, - username_out); + username_out, error); } else { + dbus_set_error (error, DBUS_ERROR_FAILED, + "User \"%s\" unknown or no memory to allocate password entry\n", + username_c_str); _dbus_verbose ("User %s unknown\n", username_c_str); return FALSE; } @@ -1474,7 +1483,7 @@ dbus_bool_t _dbus_credentials_from_username (const DBusString *username, DBusCredentials *credentials) { - return get_user_info (username, -1, credentials, NULL, NULL); + return get_user_info (username, -1, credentials, NULL, NULL, NULL); } /** @@ -1512,7 +1521,7 @@ dbus_bool_t _dbus_credentials_from_user_id (unsigned long user_id, DBusCredentials *credentials) { - return get_user_info (NULL, user_id, credentials, NULL, NULL); + return get_user_info (NULL, user_id, credentials, NULL, NULL, NULL); } _DBUS_DEFINE_GLOBAL_LOCK (user_info); @@ -1570,7 +1579,7 @@ _dbus_user_info_from_current_process (const DBusString **username, _dbus_credentials_clear (&u.creds); if (!get_user_info (NULL, getuid (), - &u.creds, &u.dir, &u.name)) + &u.creds, &u.dir, &u.name, NULL)) goto fail_init; if (!_dbus_register_shutdown_func (shutdown_user_info, @@ -1611,7 +1620,7 @@ dbus_bool_t _dbus_homedir_from_username (const DBusString *username, DBusString *homedir) { - return get_user_info (username, -1, NULL, homedir, NULL); + return get_user_info (username, -1, NULL, homedir, NULL, NULL); } /** @@ -1773,21 +1782,20 @@ _dbus_get_group_id (const DBusString *group_name, /** * Gets all groups for a particular user. Returns #FALSE * if no memory, or user isn't known, but always initializes - * group_ids to a NULL array. - * - * @todo failing to distinguish "out of memory" from - * "unknown user" is kind of bogus and would probably - * result in a failure in a comprehensive test suite. + * group_ids to a NULL array. Sets error to the reason + * for returning #FALSE. * * @param uid the user ID * @param group_ids return location for array of group IDs * @param n_group_ids return location for length of returned array + * @param error return location for error * @returns #TRUE on success */ dbus_bool_t _dbus_get_groups (unsigned long uid, unsigned long **group_ids, - int *n_group_ids) + int *n_group_ids, + DBusError *error) { DBusCredentials creds; DBusString username; @@ -1800,10 +1808,13 @@ _dbus_get_groups (unsigned long uid, retval = FALSE; if (!_dbus_string_init (&username)) - return FALSE; + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + return FALSE; + } if (!get_user_info (NULL, uid, &creds, - NULL, &username) || + NULL, &username, error) || creds.gid == DBUS_GID_UNSET) goto out; @@ -1818,7 +1829,10 @@ _dbus_get_groups (unsigned long uid, buf_count = 17; buf = dbus_new (gid_t, buf_count); if (buf == NULL) - goto out; + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + goto out; + } if (getgrouplist (username_c, creds.gid, @@ -1827,6 +1841,7 @@ _dbus_get_groups (unsigned long uid, gid_t *new = dbus_realloc (buf, buf_count * sizeof (buf[0])); if (new == NULL) { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); dbus_free (buf); goto out; } @@ -1839,6 +1854,7 @@ _dbus_get_groups (unsigned long uid, *group_ids = dbus_new (unsigned long, buf_count); if (*group_ids == NULL) { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); dbus_free (buf); goto out; } @@ -1855,19 +1871,28 @@ _dbus_get_groups (unsigned long uid, /* We just get the one group ID */ *group_ids = dbus_new (unsigned long, 1); if (*group_ids == NULL) - goto out; + { + dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); + goto out; + } *n_group_ids = 1; (*group_ids)[0] = creds.gid; } #endif /* HAVE_GETGROUPLIST */ + + retval = TRUE; + + out: + _dbus_string_free (&username); - retval = TRUE; - - out: - _dbus_string_free (&username); - return retval; + if (retval) + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + else + _DBUS_ASSERT_ERROR_IS_SET (error); + + return retval; } /** diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h index 4edfe94a..27f27b58 100644 --- a/dbus/dbus-sysdeps.h +++ b/dbus/dbus-sysdeps.h @@ -148,7 +148,8 @@ dbus_bool_t _dbus_get_group_id (const DBusString *group_name, dbus_gid_t *gid); dbus_bool_t _dbus_get_groups (dbus_uid_t uid, dbus_gid_t **group_ids, - int *n_group_ids); + int *n_group_ids, + DBusError *error); unsigned long _dbus_getpid (void); diff --git a/dbus/dbus-transport-protected.h b/dbus/dbus-transport-protected.h index 052c15fa..1c5b4208 100644 --- a/dbus/dbus-transport-protected.h +++ b/dbus/dbus-transport-protected.h @@ -100,6 +100,7 @@ struct DBusTransport unsigned int send_credentials_pending : 1; /**< #TRUE if we need to send credentials */ unsigned int receive_credentials_pending : 1; /**< #TRUE if we need to receive credentials */ unsigned int is_server : 1; /**< #TRUE if on the server side */ + unsigned int unused_bytes_recovered : 1; /**< #TRUE if we've recovered unused bytes from auth */ }; dbus_bool_t _dbus_transport_init_base (DBusTransport *transport, diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c index f9b3d8a8..e726de24 100644 --- a/dbus/dbus-transport.c +++ b/dbus/dbus-transport.c @@ -459,9 +459,21 @@ _dbus_transport_get_is_authenticated (DBusTransport *transport) maybe_authenticated = (!(transport->send_credentials_pending || - transport->receive_credentials_pending)) && - _dbus_auth_do_work (transport->auth) == DBUS_AUTH_STATE_AUTHENTICATED; + transport->receive_credentials_pending)); + if (maybe_authenticated) + { + switch (_dbus_auth_do_work (transport->auth)) + { + case DBUS_AUTH_STATE_AUTHENTICATED: + case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES: + /* leave as maybe_authenticated */ + break; + default: + maybe_authenticated = FALSE; + } + } + /* If we've authenticated as some identity, check that the auth * identity is the same as our own identity. In the future, we * may have API allowing applications to specify how this is @@ -768,18 +780,18 @@ _dbus_transport_get_dispatch_status (DBusTransport *transport) if (!_dbus_transport_get_is_authenticated (transport)) { - switch (_dbus_auth_do_work (transport->auth)) - { - case DBUS_AUTH_STATE_WAITING_FOR_MEMORY: - return DBUS_DISPATCH_NEED_MEMORY; - case DBUS_AUTH_STATE_AUTHENTICATED_WITH_UNUSED_BYTES: - if (!recover_unused_bytes (transport)) - return DBUS_DISPATCH_NEED_MEMORY; - break; - default: - break; - } + if (_dbus_auth_do_work (transport->auth) == + DBUS_AUTH_STATE_WAITING_FOR_MEMORY) + return DBUS_DISPATCH_NEED_MEMORY; + else + return DBUS_DISPATCH_COMPLETE; } + + if (!transport->unused_bytes_recovered && + !recover_unused_bytes (transport)) + return DBUS_DISPATCH_NEED_MEMORY; + + transport->unused_bytes_recovered = TRUE; if (!_dbus_message_loader_queue_messages (transport->loader)) return DBUS_DISPATCH_NEED_MEMORY; @@ -82,3 +82,7 @@ after the message bus has processed your message but before the service has replied, it would be nice if the message bus sent you an error reply. + - We have a limit on the number of messages a connection can send, but + not on how many can be buffered for a given connection. + + - make client serial and reply serial unsigned and add dbus_message_get_is_reply() diff --git a/test/data/valid-config-files/debug-allow-all.conf.in b/test/data/valid-config-files/debug-allow-all.conf.in index c4308988..0dd8ed4a 100644 --- a/test/data/valid-config-files/debug-allow-all.conf.in +++ b/test/data/valid-config-files/debug-allow-all.conf.in @@ -10,5 +10,6 @@ <allow send="*"/> <allow receive="*"/> <allow own="*"/> + <allow user="*"/> </policy> </busconfig> |