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>
41 BusConnections *connections;
42 BusActivation *activation;
43 BusRegistry *registry;
44 DBusList *default_rules; /**< Default policy rules */
45 DBusList *mandatory_rules; /**< Mandatory policy rules */
46 DBusHashTable *rules_by_uid; /**< per-UID policy rules */
47 DBusHashTable *rules_by_gid; /**< per-GID policy rules */
51 server_watch_callback (DBusWatch *watch,
52 unsigned int condition,
55 DBusServer *server = data;
57 return dbus_server_handle_watch (server, watch, condition);
61 add_server_watch (DBusWatch *watch,
64 return bus_loop_add_watch (watch, server_watch_callback, data,
69 remove_server_watch (DBusWatch *watch,
72 bus_loop_remove_watch (watch, server_watch_callback, data);
77 server_timeout_callback (DBusTimeout *timeout,
80 /* can return FALSE on OOM but we just let it fire again later */
81 dbus_timeout_handle (timeout);
85 add_server_timeout (DBusTimeout *timeout,
88 return bus_loop_add_timeout (timeout, server_timeout_callback, data, NULL);
92 remove_server_timeout (DBusTimeout *timeout,
95 bus_loop_remove_timeout (timeout, server_timeout_callback, data);
99 new_connection_callback (DBusServer *server,
100 DBusConnection *new_connection,
103 BusContext *context = data;
105 if (!bus_connections_setup_connection (context->connections, new_connection))
107 _dbus_verbose ("No memory to setup new connection\n");
109 /* if we don't do this, it will get unref'd without
110 * being disconnected... kind of strange really
111 * that we have to do this, people won't get it right
114 dbus_connection_disconnect (new_connection);
117 /* on OOM, we won't have ref'd the connection so it will die. */
121 free_rule_func (void *data,
124 BusPolicyRule *rule = data;
126 bus_policy_rule_unref (rule);
130 free_rule_list_func (void *data)
132 DBusList **list = data;
134 _dbus_list_foreach (list, free_rule_func, NULL);
136 _dbus_list_clear (list);
142 setup_server (BusContext *context,
146 dbus_server_set_new_connection_function (server,
147 new_connection_callback,
150 if (!dbus_server_set_watch_functions (server,
161 if (!dbus_server_set_timeout_functions (server,
163 remove_server_timeout,
175 bus_context_new (const DBusString *config_file,
180 DBusList **addresses;
181 BusConfigParser *parser;
182 DBusString full_address;
183 const char *service_dirs[] = { NULL, NULL };
185 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
187 if (!_dbus_string_init (&full_address))
193 parser = bus_config_load (config_file, error);
197 context = dbus_new0 (BusContext, 1);
204 context->refcount = 1;
206 addresses = bus_config_parser_get_addresses (parser);
208 link = _dbus_list_get_first_link (addresses);
213 server = dbus_server_listen (link->data, error);
216 else if (!setup_server (context, server, error))
219 if (!_dbus_list_append (&context->servers, server))
225 link = _dbus_list_get_next_link (addresses, link);
228 /* We have to build the address backward, so that
229 * <listen> later in the config file have priority
231 link = _dbus_list_get_last_link (&context->servers);
236 addr = dbus_server_get_address (link->data);
243 if (_dbus_string_get_length (&full_address) > 0)
245 if (!_dbus_string_append (&full_address, ";"))
252 if (!_dbus_string_append (&full_address, addr))
260 link = _dbus_list_get_prev_link (&context->servers, link);
263 if (!_dbus_string_copy_data (&full_address, &context->address))
269 context->activation = bus_activation_new (context, &full_address,
270 service_dirs, error);
271 if (context->activation == NULL)
273 _DBUS_ASSERT_ERROR_IS_SET (error);
277 context->connections = bus_connections_new (context);
278 if (context->connections == NULL)
284 context->registry = bus_registry_new (context);
285 if (context->registry == NULL)
291 context->rules_by_uid = _dbus_hash_table_new (DBUS_HASH_ULONG,
293 free_rule_list_func);
294 if (context->rules_by_uid == NULL)
300 context->rules_by_gid = _dbus_hash_table_new (DBUS_HASH_ULONG,
302 free_rule_list_func);
303 if (context->rules_by_gid == NULL)
309 bus_config_parser_unref (parser);
310 _dbus_string_free (&full_address);
316 bus_config_parser_unref (parser);
319 bus_context_unref (context);
321 _dbus_string_free (&full_address);
326 shutdown_server (BusContext *context,
329 if (server == NULL ||
330 !dbus_server_get_is_connected (server))
333 if (!dbus_server_set_watch_functions (server,
337 _dbus_assert_not_reached ("setting watch functions to NULL failed");
339 if (!dbus_server_set_timeout_functions (server,
343 _dbus_assert_not_reached ("setting timeout functions to NULL failed");
345 dbus_server_disconnect (server);
349 bus_context_shutdown (BusContext *context)
353 link = _dbus_list_get_first_link (&context->servers);
356 shutdown_server (context, link->data);
358 link = _dbus_list_get_next_link (&context->servers, link);
363 bus_context_ref (BusContext *context)
365 _dbus_assert (context->refcount > 0);
366 context->refcount += 1;
370 bus_context_unref (BusContext *context)
372 _dbus_assert (context->refcount > 0);
373 context->refcount -= 1;
375 if (context->refcount == 0)
379 _dbus_verbose ("Finalizing bus context %p\n", context);
381 bus_context_shutdown (context);
383 if (context->connections)
385 bus_connections_unref (context->connections);
386 context->connections = NULL;
389 if (context->registry)
391 bus_registry_unref (context->registry);
392 context->registry = NULL;
395 if (context->activation)
397 bus_activation_unref (context->activation);
398 context->activation = NULL;
401 link = _dbus_list_get_first_link (&context->servers);
404 dbus_server_unref (link->data);
406 link = _dbus_list_get_next_link (&context->servers, link);
408 _dbus_list_clear (&context->servers);
410 if (context->rules_by_uid)
412 _dbus_hash_table_unref (context->rules_by_uid);
413 context->rules_by_uid = NULL;
416 if (context->rules_by_gid)
418 _dbus_hash_table_unref (context->rules_by_gid);
419 context->rules_by_gid = NULL;
422 dbus_free (context->address);
428 bus_context_get_registry (BusContext *context)
430 return context->registry;
434 bus_context_get_connections (BusContext *context)
436 return context->connections;
440 bus_context_get_activation (BusContext *context)
442 return context->activation;
446 list_allows_user (dbus_bool_t def,
449 const unsigned long *group_ids,
457 link = _dbus_list_get_first_link (list);
460 BusPolicyRule *rule = link->data;
461 link = _dbus_list_get_next_link (list, link);
463 if (rule->type == BUS_POLICY_RULE_USER)
465 if (rule->d.user.uid != uid)
468 else if (rule->type == BUS_POLICY_RULE_GROUP)
473 while (i < n_group_ids)
475 if (rule->d.group.gid == group_ids[i])
480 if (i == n_group_ids)
486 allowed = rule->allow;
493 bus_context_allow_user (BusContext *context,
497 unsigned long *group_ids;
500 /* On OOM or error we always reject the user */
501 if (!_dbus_get_groups (uid, &group_ids, &n_group_ids))
503 _dbus_verbose ("Did not get any groups for UID %lu\n",
510 allowed = list_allows_user (allowed,
511 &context->default_rules,
513 group_ids, n_group_ids);
515 allowed = list_allows_user (allowed,
516 &context->mandatory_rules,
518 group_ids, n_group_ids);
520 dbus_free (group_ids);
526 add_list_to_policy (DBusList **list,
531 link = _dbus_list_get_first_link (list);
534 BusPolicyRule *rule = link->data;
535 link = _dbus_list_get_next_link (list, link);
539 case BUS_POLICY_RULE_USER:
540 case BUS_POLICY_RULE_GROUP:
541 /* These aren't per-connection policies */
544 case BUS_POLICY_RULE_OWN:
545 case BUS_POLICY_RULE_SEND:
546 case BUS_POLICY_RULE_RECEIVE:
547 /* These are per-connection */
548 if (!bus_policy_append_rule (policy, rule))
558 bus_context_create_connection_policy (BusContext *context,
559 DBusConnection *connection)
565 _dbus_assert (dbus_connection_get_is_authenticated (connection));
567 policy = bus_policy_new ();
571 if (!add_list_to_policy (&context->default_rules,
575 /* we avoid the overhead of looking up user's groups
576 * if we don't have any group rules anyway
578 if (_dbus_hash_table_get_n_entries (context->rules_by_gid) > 0)
580 const unsigned long *groups;
584 if (!bus_connection_get_groups (connection, &groups, &n_groups))
590 list = _dbus_hash_table_lookup_ulong (context->rules_by_gid,
595 if (!add_list_to_policy (list, policy))
603 if (!dbus_connection_get_unix_user (connection, &uid))
606 list = _dbus_hash_table_lookup_ulong (context->rules_by_uid,
609 if (!add_list_to_policy (list, policy))
612 if (!add_list_to_policy (&context->mandatory_rules,
616 bus_policy_optimize (policy);
621 bus_policy_unref (policy);