1 /* -*- mode: C; c-file-style: "gnu" -*- */
2 /* bus.c message bus context object
4 * Copyright (C) 2003 Red Hat, Inc.
6 * Licensed under the Academic Free License version 1.2
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 #include "activation.h"
27 #include "connection.h"
31 #include "config-parser.h"
32 #include <dbus/dbus-list.h>
33 #include <dbus/dbus-hash.h>
34 #include <dbus/dbus-internals.h>
42 BusConnections *connections;
43 BusActivation *activation;
44 BusRegistry *registry;
45 DBusList *default_rules; /**< Default policy rules */
46 DBusList *mandatory_rules; /**< Mandatory policy rules */
47 DBusHashTable *rules_by_uid; /**< per-UID policy rules */
48 DBusHashTable *rules_by_gid; /**< per-GID policy rules */
52 server_watch_callback (DBusWatch *watch,
53 unsigned int condition,
56 DBusServer *server = data;
58 return dbus_server_handle_watch (server, watch, condition);
62 add_server_watch (DBusWatch *watch,
65 return bus_loop_add_watch (watch, server_watch_callback, data,
70 remove_server_watch (DBusWatch *watch,
73 bus_loop_remove_watch (watch, server_watch_callback, data);
78 server_timeout_callback (DBusTimeout *timeout,
81 /* can return FALSE on OOM but we just let it fire again later */
82 dbus_timeout_handle (timeout);
86 add_server_timeout (DBusTimeout *timeout,
89 return bus_loop_add_timeout (timeout, server_timeout_callback, data, NULL);
93 remove_server_timeout (DBusTimeout *timeout,
96 bus_loop_remove_timeout (timeout, server_timeout_callback, data);
100 new_connection_callback (DBusServer *server,
101 DBusConnection *new_connection,
104 BusContext *context = data;
106 if (!bus_connections_setup_connection (context->connections, new_connection))
108 _dbus_verbose ("No memory to setup new connection\n");
110 /* if we don't do this, it will get unref'd without
111 * being disconnected... kind of strange really
112 * that we have to do this, people won't get it right
115 dbus_connection_disconnect (new_connection);
118 /* on OOM, we won't have ref'd the connection so it will die. */
122 free_rule_func (void *data,
125 BusPolicyRule *rule = data;
127 bus_policy_rule_unref (rule);
131 free_rule_list_func (void *data)
133 DBusList **list = data;
135 _dbus_list_foreach (list, free_rule_func, NULL);
137 _dbus_list_clear (list);
143 setup_server (BusContext *context,
145 char **auth_mechanisms,
148 if (!dbus_server_set_auth_mechanisms (server, (const char**) auth_mechanisms))
154 dbus_server_set_new_connection_function (server,
155 new_connection_callback,
158 if (!dbus_server_set_watch_functions (server,
169 if (!dbus_server_set_timeout_functions (server,
171 remove_server_timeout,
183 bus_context_new (const DBusString *config_file,
188 DBusList **addresses;
189 BusConfigParser *parser;
190 DBusString full_address;
192 char **auth_mechanisms;
193 DBusList **auth_mechanisms_list;
196 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
198 if (!_dbus_string_init (&full_address))
203 auth_mechanisms = NULL;
205 parser = bus_config_load (config_file, error);
209 context = dbus_new0 (BusContext, 1);
216 context->refcount = 1;
218 /* Build an array of auth mechanisms */
220 auth_mechanisms_list = bus_config_parser_get_mechanisms (parser);
221 len = _dbus_list_get_length (auth_mechanisms_list);
227 auth_mechanisms = dbus_new0 (char*, len + 1);
228 if (auth_mechanisms == NULL)
232 link = _dbus_list_get_first_link (auth_mechanisms_list);
235 auth_mechanisms[i] = _dbus_strdup (link->data);
236 if (auth_mechanisms[i] == NULL)
238 link = _dbus_list_get_next_link (auth_mechanisms_list, link);
243 auth_mechanisms = NULL;
246 /* Listen on our addresses */
248 addresses = bus_config_parser_get_addresses (parser);
250 link = _dbus_list_get_first_link (addresses);
255 server = dbus_server_listen (link->data, error);
258 else if (!setup_server (context, server, auth_mechanisms, error))
261 if (!_dbus_list_append (&context->servers, server))
267 link = _dbus_list_get_next_link (addresses, link);
270 /* Here we change our credentials if required,
271 * as soon as we've set up our sockets
273 user = bus_config_parser_get_user (parser);
276 DBusCredentials creds;
279 _dbus_string_init_const (&u, user);
281 if (!_dbus_credentials_from_username (&u, &creds) ||
285 dbus_set_error (error, DBUS_ERROR_FAILED,
286 "Could not get UID and GID for username \"%s\"",
291 if (!_dbus_change_identity (creds.uid, creds.gid, error))
295 /* note that type may be NULL */
296 context->type = _dbus_strdup (bus_config_parser_get_type (parser));
298 /* We have to build the address backward, so that
299 * <listen> later in the config file have priority
301 link = _dbus_list_get_last_link (&context->servers);
306 addr = dbus_server_get_address (link->data);
313 if (_dbus_string_get_length (&full_address) > 0)
315 if (!_dbus_string_append (&full_address, ";"))
322 if (!_dbus_string_append (&full_address, addr))
330 link = _dbus_list_get_prev_link (&context->servers, link);
333 if (!_dbus_string_copy_data (&full_address, &context->address))
339 /* Create activation subsystem */
341 context->activation = bus_activation_new (context, &full_address,
342 bus_config_parser_get_service_dirs (parser),
344 if (context->activation == NULL)
346 _DBUS_ASSERT_ERROR_IS_SET (error);
350 context->connections = bus_connections_new (context);
351 if (context->connections == NULL)
357 context->registry = bus_registry_new (context);
358 if (context->registry == NULL)
364 context->rules_by_uid = _dbus_hash_table_new (DBUS_HASH_ULONG,
366 free_rule_list_func);
367 if (context->rules_by_uid == NULL)
373 context->rules_by_gid = _dbus_hash_table_new (DBUS_HASH_ULONG,
375 free_rule_list_func);
376 if (context->rules_by_gid == NULL)
382 /* Now become a daemon if appropriate */
383 if (bus_config_parser_get_fork (parser))
385 if (!_dbus_become_daemon (error))
389 bus_config_parser_unref (parser);
390 _dbus_string_free (&full_address);
391 dbus_free_string_array (auth_mechanisms);
397 bus_config_parser_unref (parser);
400 bus_context_unref (context);
402 _dbus_string_free (&full_address);
403 dbus_free_string_array (auth_mechanisms);
408 shutdown_server (BusContext *context,
411 if (server == NULL ||
412 !dbus_server_get_is_connected (server))
415 if (!dbus_server_set_watch_functions (server,
419 _dbus_assert_not_reached ("setting watch functions to NULL failed");
421 if (!dbus_server_set_timeout_functions (server,
425 _dbus_assert_not_reached ("setting timeout functions to NULL failed");
427 dbus_server_disconnect (server);
431 bus_context_shutdown (BusContext *context)
435 link = _dbus_list_get_first_link (&context->servers);
438 shutdown_server (context, link->data);
440 link = _dbus_list_get_next_link (&context->servers, link);
445 bus_context_ref (BusContext *context)
447 _dbus_assert (context->refcount > 0);
448 context->refcount += 1;
452 bus_context_unref (BusContext *context)
454 _dbus_assert (context->refcount > 0);
455 context->refcount -= 1;
457 if (context->refcount == 0)
461 _dbus_verbose ("Finalizing bus context %p\n", context);
463 bus_context_shutdown (context);
465 if (context->connections)
467 bus_connections_unref (context->connections);
468 context->connections = NULL;
471 if (context->registry)
473 bus_registry_unref (context->registry);
474 context->registry = NULL;
477 if (context->activation)
479 bus_activation_unref (context->activation);
480 context->activation = NULL;
483 link = _dbus_list_get_first_link (&context->servers);
486 dbus_server_unref (link->data);
488 link = _dbus_list_get_next_link (&context->servers, link);
490 _dbus_list_clear (&context->servers);
492 if (context->rules_by_uid)
494 _dbus_hash_table_unref (context->rules_by_uid);
495 context->rules_by_uid = NULL;
498 if (context->rules_by_gid)
500 _dbus_hash_table_unref (context->rules_by_gid);
501 context->rules_by_gid = NULL;
504 dbus_free (context->type);
505 dbus_free (context->address);
510 /* type may be NULL */
512 bus_context_get_type (BusContext *context)
514 return context->type;
518 bus_context_get_registry (BusContext *context)
520 return context->registry;
524 bus_context_get_connections (BusContext *context)
526 return context->connections;
530 bus_context_get_activation (BusContext *context)
532 return context->activation;
536 list_allows_user (dbus_bool_t def,
539 const unsigned long *group_ids,
547 link = _dbus_list_get_first_link (list);
550 BusPolicyRule *rule = link->data;
551 link = _dbus_list_get_next_link (list, link);
553 if (rule->type == BUS_POLICY_RULE_USER)
555 if (rule->d.user.uid != uid)
558 else if (rule->type == BUS_POLICY_RULE_GROUP)
563 while (i < n_group_ids)
565 if (rule->d.group.gid == group_ids[i])
570 if (i == n_group_ids)
576 allowed = rule->allow;
583 bus_context_allow_user (BusContext *context,
587 unsigned long *group_ids;
590 /* On OOM or error we always reject the user */
591 if (!_dbus_get_groups (uid, &group_ids, &n_group_ids))
593 _dbus_verbose ("Did not get any groups for UID %lu\n",
600 allowed = list_allows_user (allowed,
601 &context->default_rules,
603 group_ids, n_group_ids);
605 allowed = list_allows_user (allowed,
606 &context->mandatory_rules,
608 group_ids, n_group_ids);
610 dbus_free (group_ids);
616 add_list_to_policy (DBusList **list,
621 link = _dbus_list_get_first_link (list);
624 BusPolicyRule *rule = link->data;
625 link = _dbus_list_get_next_link (list, link);
629 case BUS_POLICY_RULE_USER:
630 case BUS_POLICY_RULE_GROUP:
631 /* These aren't per-connection policies */
634 case BUS_POLICY_RULE_OWN:
635 case BUS_POLICY_RULE_SEND:
636 case BUS_POLICY_RULE_RECEIVE:
637 /* These are per-connection */
638 if (!bus_policy_append_rule (policy, rule))
648 bus_context_create_connection_policy (BusContext *context,
649 DBusConnection *connection)
655 _dbus_assert (dbus_connection_get_is_authenticated (connection));
657 policy = bus_policy_new ();
661 if (!add_list_to_policy (&context->default_rules,
665 /* we avoid the overhead of looking up user's groups
666 * if we don't have any group rules anyway
668 if (_dbus_hash_table_get_n_entries (context->rules_by_gid) > 0)
670 const unsigned long *groups;
674 if (!bus_connection_get_groups (connection, &groups, &n_groups))
680 list = _dbus_hash_table_lookup_ulong (context->rules_by_gid,
685 if (!add_list_to_policy (list, policy))
693 if (!dbus_connection_get_unix_user (connection, &uid))
696 list = _dbus_hash_table_lookup_ulong (context->rules_by_uid,
699 if (!add_list_to_policy (list, policy))
702 if (!add_list_to_policy (&context->mandatory_rules,
706 bus_policy_optimize (policy);
711 bus_policy_unref (policy);