2 #include "dbus-internals.h"
3 #include "dbus-authorization.h"
4 #include "dbus-connection.h"
5 #include "dbus-connection-internal.h"
7 struct DBusAuthorization {
10 DBusConnection *connection;
12 /* Authorization functions, used as callback by SASL (implemented by
14 DBusAllowUnixUserFunction unix_authorization_cb;
16 DBusFreeFunction unix_data_free;
18 DBusAllowWindowsUserFunction windows_authorization_cb;
20 DBusFreeFunction windows_data_free;
22 dbus_bool_t allow_anonymous;
27 _dbus_authorization_new (void)
29 DBusAuthorization *ret;
31 ret = dbus_malloc0 (sizeof (DBusAuthorization));
34 _dbus_verbose ("OOM\n");
35 return NULL; /* OOM */
44 _dbus_authorization_ref (DBusAuthorization *self)
46 _dbus_assert (self != NULL);
54 _dbus_authorization_unref (DBusAuthorization *self)
56 _dbus_assert (self != NULL);
57 _dbus_assert (self->refcount > 0);
61 if (self->refcount == 0)
63 _dbus_verbose ("last reference, finalizing\n");
65 if (self->unix_data && self->unix_data_free)
67 _dbus_verbose ("freeing unix authorization callback data\n");
68 (*self->unix_data_free) (self->unix_data);
69 self->unix_data = NULL;
72 if (self->windows_data && self->windows_data_free)
74 _dbus_verbose ("freeing windows authorization callback data\n");
75 (*self->windows_data_free) (self->windows_data);
76 self->windows_data = NULL;
83 /* Called by transport's set_connection with the connection locked */
85 _dbus_authorization_set_connection (DBusAuthorization *self,
86 DBusConnection *connection)
88 _dbus_assert (connection != NULL);
89 _dbus_assert (self->connection == NULL);
91 self->connection = connection;
96 * Set the user set authorization callback for Unix identities authorizations.
97 * The callback will be called at the end of the EXTERNAL authentication
98 * mechanism and on every message.
100 * See dbus_connection_set_unix_authorization_callback() and
101 * _dbus_transport_set_unix_authorization_callback().
103 * @param self the authorization struct
104 * @param function the predicate
105 * @param data data to pass to the predicate
106 * @param free_data_function function to free the data
107 * @param old_data the old user data to be freed
108 * @param old_free_data_function old free data function to free it with
111 _dbus_authorization_set_unix_authorization_callback (DBusAuthorization *self,
112 DBusAllowUnixUserFunction function,
114 DBusFreeFunction free_data_function,
116 DBusFreeFunction *old_free_data_function)
118 *old_data = self->unix_data;
119 *old_free_data_function = self->unix_data_free;
121 self->unix_authorization_cb = function;
122 self->unix_data = data;
123 self->unix_data_free = free_data_function;
127 * Set the user set authorization callback for Windows identities
129 * The callback will be called at the end of the EXTERNAL authentication
130 * mechanism and on every message.
132 * See dbus_connection_set_windows_authorization_callback() and
133 * _dbus_transport_set_windows_authorization_callback().
135 * @param self the authorization struct
136 * @param function the predicate
137 * @param data data to pass to the predicate
138 * @param free_data_function function to free the data
139 * @param old_data the old user data to be freed
140 * @param old_free_data_function old free data function to free it with
144 _dbus_authorization_set_windows_authorization_callback (DBusAuthorization *self,
145 DBusAllowWindowsUserFunction function,
147 DBusFreeFunction free_data_function,
149 DBusFreeFunction *old_free_data_function)
151 *old_data = self->windows_data;
152 *old_free_data_function = self->windows_data_free;
154 self->windows_authorization_cb = function;
155 self->windows_data = data;
156 self->windows_data_free = free_data_function;
160 auth_via_unix_authorization_callback (DBusAuthorization *self,
161 DBusCredentials *auth_identity)
167 /* Dropping the lock here probably isn't that safe. */
169 _dbus_assert (auth_identity != NULL);
171 uid = _dbus_credentials_get_unix_uid (auth_identity);
173 _dbus_verbose ("unlock connection before executing user's authorization callback\n");
174 _dbus_connection_unlock (self->connection);
176 allow = (*self->unix_authorization_cb) (self->connection,
180 _dbus_verbose ("lock connection post unix-authorization callback\n");
181 _dbus_connection_lock (self->connection);
185 _dbus_verbose ("Client UID "DBUS_UID_FORMAT" authorized\n", uid);
189 _dbus_verbose ("Client UID "DBUS_UID_FORMAT " wasn't authorized.\n",
190 _dbus_credentials_get_unix_uid (auth_identity));
198 auth_via_windows_authorization_callback (DBusAuthorization *self,
199 DBusCredentials *auth_identity)
204 /* Dropping the lock here probably isn't that safe. */
206 _dbus_assert (auth_identity != NULL);
208 windows_sid = _dbus_strdup (_dbus_credentials_get_windows_sid (auth_identity));
210 if (windows_sid == NULL)
211 return FALSE; /* OOM */
213 _dbus_verbose ("unlock connection before executing user's authorization callback\n");
214 _dbus_connection_unlock (self->connection);
216 allow = (*self->windows_authorization_cb) (self->connection,
220 _dbus_verbose ("lock connection post windows user's authorization callback\n");
221 _dbus_connection_lock (self->connection);
225 _dbus_verbose ("Client SID '%s' authorized\n", windows_sid);
229 _dbus_verbose ("Client SID '%s' wasn't authorized\n",
230 _dbus_credentials_get_windows_sid (auth_identity));
233 dbus_free (windows_sid);
239 auth_via_default_rules (DBusAuthorization *self,
240 DBusCredentials *auth_identity)
243 DBusCredentials *our_identity;
246 _dbus_assert (auth_identity != NULL);
248 /* By default, connection is allowed if the client is 1) root or 2)
249 * has the same UID as us or 3) anonymous is allowed.
252 our_identity = _dbus_credentials_new_from_current_process ();
253 if (our_identity == NULL)
254 return FALSE; /* OOM */
256 if (self->allow_anonymous ||
257 _dbus_credentials_get_unix_uid (auth_identity) == 0 ||
258 _dbus_credentials_same_user (our_identity, auth_identity))
260 if (_dbus_credentials_include (our_identity, DBUS_CREDENTIAL_WINDOWS_SID))
261 _dbus_verbose ("Client authenticated as SID '%s'"
262 "matching our SID '%s': authorized\n",
263 _dbus_credentials_get_windows_sid (auth_identity),
264 _dbus_credentials_get_windows_sid (our_identity));
266 _dbus_verbose ("Client authenticated as UID "DBUS_UID_FORMAT
267 " matching our UID "DBUS_UID_FORMAT": authorized\n",
268 _dbus_credentials_get_unix_uid (auth_identity),
269 _dbus_credentials_get_unix_uid (our_identity));
270 /* We have authenticated! */
275 if (_dbus_credentials_include(our_identity,DBUS_CREDENTIAL_WINDOWS_SID))
276 _dbus_verbose ("Client authenticated as SID '%s'"
277 " but our SID is '%s', not authorizing\n",
278 (_dbus_credentials_get_windows_sid(auth_identity) ?
279 _dbus_credentials_get_windows_sid(auth_identity) : "<null>"),
280 (_dbus_credentials_get_windows_sid(our_identity) ?
281 _dbus_credentials_get_windows_sid(our_identity) : "<null>"));
283 _dbus_verbose ("Client authenticated as UID "DBUS_UID_FORMAT
284 " but our UID is "DBUS_UID_FORMAT", not authorizing\n",
285 _dbus_credentials_get_unix_uid(auth_identity),
286 _dbus_credentials_get_unix_uid(our_identity));
290 _dbus_credentials_unref (our_identity);
295 /* Called with DBusConnection lock held */
297 _dbus_authorization_do_authorization (DBusAuthorization *self,
298 DBusCredentials *auth_identity)
302 /* maybe-FIXME: at this point we *should* have a connection set unless we
303 * are in some test case, but we assert its presence only in some if's
304 * branches since default_rules does not need one and is used in a test case
305 * without a connection set */
307 if (_dbus_credentials_are_anonymous (auth_identity))
309 allow = self->allow_anonymous;
311 if (self->unix_authorization_cb != NULL &&
312 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_UNIX_USER_ID))
314 _dbus_assert (self->connection != NULL);
315 allow = auth_via_unix_authorization_callback (self, auth_identity);
317 else if (self->windows_authorization_cb != NULL &&
318 _dbus_credentials_include (auth_identity, DBUS_CREDENTIAL_WINDOWS_SID))
320 _dbus_assert (self->connection != NULL);
321 allow = auth_via_windows_authorization_callback (self, auth_identity);
325 allow = auth_via_default_rules (self, auth_identity);
334 * See dbus_connection_set_allow_anonymous()
336 * @param self an authorization struct
337 * @param value #TRUE to allow anonymous connection
340 _dbus_authorization_set_allow_anonymous (DBusAuthorization *self,
343 self->allow_anonymous = value != FALSE;