1 /* smack.c - Provide interface to query smack context
3 * Author: Brian McGillion <brian.mcgillion@intel.com>
4 * Copyright © 2011 Intel Corporation
6 * Licensed under the Academic Free License version 2.1
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., 51 Franklin Street, Fifth Floor, Boston, MA
27 #include <dbus/dbus-internals.h>
29 #include "connection.h"
34 #ifdef DBUS_ENABLE_SMACK
35 #include <sys/smack.h>
38 #define SMACK_WRITE "W"
39 #define SMACK_READ "R"
40 #define SMACK_READ_WRITE "RW"
44 bus_smack_handle_get_connection_context (DBusConnection *connection,
45 BusTransaction *transaction,
49 #ifdef DBUS_ENABLE_SMACK
50 const char *remote_end = NULL;
51 BusRegistry *registry;
52 DBusString remote_end_str;
54 DBusConnection *remote_connection;
55 DBusMessage *reply = NULL;
58 _DBUS_ASSERT_ERROR_IS_CLEAR (error);
60 registry = bus_connection_get_registry (connection);
62 if (!dbus_message_get_args (message, error, DBUS_TYPE_STRING, &remote_end,
64 return BUS_RESULT_FALSE;
66 _dbus_verbose ("asked for label of connection %s\n", remote_end);
68 _dbus_string_init_const (&remote_end_str, remote_end);
70 service = bus_registry_lookup (registry, &remote_end_str);
73 dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER,
74 "Bus name '%s' has no owner", remote_end);
75 return BUS_RESULT_FALSE;
78 remote_connection = bus_service_get_primary_owners_connection (service);
79 if (remote_connection == NULL)
82 reply = dbus_message_new_method_return (message);
86 if (!dbus_connection_get_smack_label(remote_connection, &label))
88 dbus_set_error (error, DBUS_ERROR_FAILED,
89 "Failed to get the socket fd of the connection",
94 if (!dbus_message_append_args (reply, DBUS_TYPE_STRING,
95 &label, DBUS_TYPE_INVALID))
98 if (!bus_transaction_send_from_driver (transaction, connection, reply))
101 dbus_message_unref (reply);
103 return BUS_RESULT_TRUE;
110 dbus_message_unref (reply);
112 return BUS_RESULT_FALSE;
114 dbus_set_error (error, DBUS_ERROR_NOT_SUPPORTED,
115 "SMACK support is not enabled");
116 return BUS_RESULT_FALSE;
120 #ifdef DBUS_ENABLE_SMACK
122 bus_smack_has_access (const char *subject, const char *object,
125 return (smack_have_access (subject, object, access) == 1 ? TRUE : FALSE);
131 * Calculate the list of rules that apply to a connection.
133 * @param connection The inbound conenction
134 * @param rules_by_smack_label The table of object labels -> rules mapping
135 * @param nomem_err (out) If a nomem situation is encountered this value is set to TRUE.
136 * @returns the list of permitted rules if it exists and no errors were encountered otherwise NULL.
139 bus_smack_generate_allowed_list (DBusConnection *connection,
140 DBusHashTable *rules_by_smack_label,
141 dbus_bool_t *nomem_err)
143 #ifdef DBUS_ENABLE_SMACK
144 const char *subject_label;
146 dbus_bool_t is_allowed;
147 DBusList **allowed_list;
149 /* the label of the subject, is the label on the new connection,
150 either the service itself or one of its clients */
152 if (!dbus_connection_get_smack_label(connection, &subject_label))
155 allowed_list = dbus_new0 (DBusList*, 1);
156 if (allowed_list == NULL)
159 /* Iterate over all the smack labels we have parsed from the .conf files */
160 _dbus_hash_iter_init (rules_by_smack_label, &iter);
161 while (_dbus_hash_iter_next (&iter))
164 const char *object_label = _dbus_hash_iter_get_string_key (&iter);
165 /* the list here is all the rules that are 'protected'
166 by the SMACK label named $object_label */
167 DBusList **list = _dbus_hash_iter_get_value (&iter);
169 link = _dbus_list_get_first_link (list);
172 BusPolicyRule *rule = link->data;
173 link = _dbus_list_get_next_link (list, link);
178 case BUS_POLICY_RULE_OWN:
179 is_allowed = bus_smack_has_access (subject_label,
183 case BUS_POLICY_RULE_SEND:
184 is_allowed = bus_smack_has_access (subject_label,
188 case BUS_POLICY_RULE_RECEIVE:
189 is_allowed = bus_smack_has_access (subject_label,
199 if (!_dbus_list_append (allowed_list, rule))
202 bus_policy_rule_ref (rule);
205 _dbus_verbose ("permission request subject (%s) -> object (%s) : %s", subject_label, object_label, (is_allowed ? "GRANTED" : "REJECTED"));
212 if (allowed_list != NULL) {
213 _dbus_list_clear (allowed_list);
214 dbus_free (allowed_list);