1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
4 * This file is part of gsignond
6 * Copyright (C) 2012-2013 Intel Corporation.
8 * Contact: Jussi Laako <jussi.laako@linux.intel.com>
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28 #include <sys/types.h>
29 #include <sys/socket.h>
35 #include "gsignond/gsignond-log.h"
36 #include "gsignond/gsignond-access-control-manager.h"
39 * SECTION:gsignond-access-control-manager
40 * @short_description: an object that performs access control checks
41 * @include: gsignond/gsignond-access-control-manager.h
43 * #GSignondAccessControlManager performs access control checks using
44 * available system services. gSSO can be configured to use a custom extension
45 * that provides a subclassed implementation of #GSignondAccessControlManager
46 * (see #GSignondExtension), otherwise a default implementation is used.
49 * GSignondAccessControlManager:
51 * Opaque #GSignondAccessControlManager data structure.
54 #define GSIGNOND_ACCESS_CONTROL_MANAGER_GET_PRIVATE(obj) \
55 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), \
56 GSIGNOND_TYPE_ACCESS_CONTROL_MANAGER, \
57 GSignondAccessControlManagerPrivate))
59 #define DBUS_SERVICE_DBUS "org.freedesktop.DBus"
60 #define DBUS_PATH_DBUS "/org/freedesktop/DBus"
61 #define DBUS_INTERFACE_DBUS "org.freedesktop.DBus"
62 #ifndef GSIGNOND_BUS_TYPE
63 # define GSIGNOND_BUS_TYPE G_BUS_TYPE_SESSION
66 struct _GSignondAccessControlManagerPrivate
77 static GParamSpec *properties[N_PROPERTIES] = { NULL, };
79 G_DEFINE_TYPE (GSignondAccessControlManager, gsignond_access_control_manager,
83 _set_property (GObject *object, guint prop_id, const GValue *value,
86 GSignondAccessControlManager *self =
87 GSIGNOND_ACCESS_CONTROL_MANAGER (object);
91 g_assert (self->config == NULL);
92 self->config = g_value_dup_object (value);
95 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
100 _get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
102 GSignondAccessControlManager *self =
103 GSIGNOND_ACCESS_CONTROL_MANAGER (object);
107 g_value_set_object (value, self->config);
110 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
115 _dispose (GObject *object)
117 GSignondAccessControlManager *self =
118 GSIGNOND_ACCESS_CONTROL_MANAGER (object);
121 g_object_unref (self->config);
125 G_OBJECT_CLASS (gsignond_access_control_manager_parent_class)->dispose (object);
129 _security_context_of_peer (GSignondAccessControlManager *self,
130 GSignondSecurityContext *peer_ctx,
131 int peer_fd, const gchar *peer_service,
132 const gchar *peer_app_ctx)
134 pid_t remote_pid = 0;
141 gsignond_security_context_set_system_context (peer_ctx, "");
142 gsignond_security_context_set_application_context (peer_ctx,
146 struct ucred peer_cred;
147 socklen_t cred_size = sizeof(peer_cred);
149 if (getsockopt (peer_fd, SOL_SOCKET, SO_PEERCRED,
150 &peer_cred, &cred_size) != 0) {
151 WARN ("getsockopt() for SO_PEERCRED failed");
154 DBG ("remote peer pid=%d uid=%d gid=%d",
155 peer_cred.pid, peer_cred.uid, peer_cred.gid);
156 remote_pid = peer_cred.pid;
157 } else if (peer_service) {
158 GError *error = NULL;
159 GDBusConnection *connection;
160 GVariant *response = NULL;
163 connection = g_bus_get_sync (GSIGNOND_BUS_TYPE, NULL, &error);
165 WARN ("failed to open connection to session bus: %s",
167 g_error_free (error);
172 response = g_dbus_connection_call_sync (connection,
176 "GetConnectionUnixProcessID",
177 g_variant_new ("(s)", peer_service),
178 ((const GVariantType *) "(u)"),
179 G_DBUS_CALL_FLAGS_NONE,
184 g_object_unref (connection);
187 WARN ("request for peer pid failed: %s",
189 g_error_free (error);
193 g_variant_get (response, "(u)", &upid);
194 DBG ("remote peer service=%s pid=%u", peer_service, upid);
195 remote_pid = (pid_t) upid;
197 g_variant_unref (response);
203 procfname = g_strdup_printf ("/proc/%d/exe", remote_pid);
204 peerpath = g_malloc0 (PATH_MAX + 1);
205 res = readlink (procfname, peerpath, PATH_MAX);
208 WARN ("failed to follow link for pid %d", remote_pid);
213 DBG ("identity of pid %d is [%s:%s]", remote_pid, peerpath, peer_app_ctx);
214 gsignond_security_context_set_system_context (peer_ctx, peerpath);
220 _peer_is_allowed_to_use_identity (GSignondAccessControlManager *self,
221 const GSignondSecurityContext *peer_ctx,
222 const GSignondSecurityContext *owner_ctx,
223 const GSignondSecurityContextList *identity_acl)
225 GSignondSecurityContext *acl_ctx;
230 for ( ; identity_acl != NULL; identity_acl = g_list_next (identity_acl)) {
231 acl_ctx = (GSignondSecurityContext *) identity_acl->data;
232 DBG ("ACL check [%p=(%s:%s)] vs [%p=(%s:%s)]",
234 gsignond_security_context_get_system_context (acl_ctx),
235 gsignond_security_context_get_application_context (acl_ctx),
237 gsignond_security_context_get_system_context (peer_ctx),
238 gsignond_security_context_get_application_context (peer_ctx));
239 if (gsignond_security_context_check (acl_ctx, peer_ctx)) {
240 DBG (" - ACL check passed");
244 DBG (" - ACL check failed");
249 _peer_is_owner_of_identity (GSignondAccessControlManager *self,
250 const GSignondSecurityContext *peer_ctx,
251 const GSignondSecurityContext *owner_ctx)
255 DBG ("Owner check [%p=(%s:%s)] vs [%p=(%s:%s)]",
257 gsignond_security_context_get_system_context (owner_ctx),
258 gsignond_security_context_get_application_context (owner_ctx),
260 gsignond_security_context_get_system_context (peer_ctx),
261 gsignond_security_context_get_application_context (peer_ctx));
262 return gsignond_security_context_check (owner_ctx, peer_ctx);
266 _acl_is_valid (GSignondAccessControlManager *self,
267 const GSignondSecurityContext *peer_ctx,
268 const GSignondSecurityContextList *identity_acl)
277 GSignondSecurityContext *
278 _security_context_of_keychain (GSignondAccessControlManager *self)
280 const gchar *keychain_sysctx = NULL;
284 # if defined(ENABLE_DEBUG)
285 keychain_sysctx = g_getenv ("SSO_KEYCHAIN_SYSCTX");
286 # elif defined(KEYCHAIN_SYSCTX)
287 keychain_sysctx = KEYCHAIN_SYSCTX;
289 if (!keychain_sysctx)
290 keychain_sysctx = "";
291 return gsignond_security_context_new_from_values (keychain_sysctx, "");
295 * GSignondAccessControlManagerClass:
296 * @parent_class: parent class.
297 * @security_context_of_peer: an implementation of gsignond_access_control_manager_security_context_of_peer()
298 * @peer_is_allowed_to_use_identity: an implementation of gsignond_access_control_manager_peer_is_allowed_to_use_identity()
299 * @peer_is_owner_of_identity: an implementation of gsignond_access_control_manager_peer_is_owner_of_identity()
300 * @acl_is_valid: an implementation of gsignond_access_control_manager_acl_is_valid()
301 * @security_context_of_keychain: an implementation of gsignond_access_control_manager_security_context_of_keychain()
303 * #GSignondAccessControlManagerClass class containing pointers to class methods.
306 gsignond_access_control_manager_class_init (
307 GSignondAccessControlManagerClass *klass)
309 GObjectClass *base = G_OBJECT_CLASS (klass);
311 base->set_property = _set_property;
312 base->get_property = _get_property;
313 base->dispose = _dispose;
314 properties[PROP_CONFIG] = g_param_spec_object ("config",
316 "Configuration object",
317 GSIGNOND_TYPE_CONFIG,
318 G_PARAM_CONSTRUCT_ONLY|
320 G_PARAM_STATIC_STRINGS);
321 g_object_class_install_properties (base, N_PROPERTIES, properties);
323 /*g_type_class_add_private (klass,
324 sizeof(GSignondAccessControlManagerPrivate));*/
326 klass->security_context_of_peer = _security_context_of_peer;
327 klass->peer_is_allowed_to_use_identity = _peer_is_allowed_to_use_identity;
328 klass->peer_is_owner_of_identity = _peer_is_owner_of_identity;
329 klass->acl_is_valid = _acl_is_valid;
330 klass->security_context_of_keychain = _security_context_of_keychain;
334 gsignond_access_control_manager_init (GSignondAccessControlManager *self)
336 /*self->priv = GSIGNOND_ACCESS_CONTROL_MANAGER_GET_PRIVATE (self);*/
342 * gsignond_access_control_manager_security_context_of_peer:
343 * @self: object instance.
344 * @peer_ctx: instance of security context to be set.
345 * @peer_fd: file descriptor of the peer connection if using peer-to-peer dbus, -1 otherwise.
346 * @peer_service: g_dbus_method_invocation_get_sender() of the peer connection, if not using peer-to-peer dbus, NULL otherwise
347 * @peer_app_ctx: application context of the peer connection.
349 * Retrieves and sets #GSignondSecurityContext of the specified peer.
351 * The default implementation sets the app context as it was passed, and sets
352 * the system context to the binary path of the process that is determined from
353 * @peer_fd and @peer_service parameters.
356 gsignond_access_control_manager_security_context_of_peer (
357 GSignondAccessControlManager *self,
358 GSignondSecurityContext *peer_ctx,
359 int peer_fd, const gchar *peer_service,
360 const gchar *peer_app_ctx)
362 GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
363 security_context_of_peer (self, peer_ctx, peer_fd,
364 peer_service, peer_app_ctx);
368 * gsignond_access_control_manager_peer_is_allowed_to_use_identity:
369 * @self: object instance.
370 * @peer_ctx: security context of the peer connection.
371 * @owner_ctx: security context of the identity owner.
372 * @identity_acl: access control list for the identity in question. Includes the @owner_ctx as well.
374 * Checks if specified peer is allowed to access the specified identity.
376 * The default implementation goes over items in @identity_acl, using
377 * gsignond_security_context_check() to check them against @peer_ctx.
379 * Returns: access is allowed?
382 gsignond_access_control_manager_peer_is_allowed_to_use_identity (
383 GSignondAccessControlManager *self,
384 const GSignondSecurityContext *peer_ctx,
385 const GSignondSecurityContext *owner_ctx,
386 const GSignondSecurityContextList *identity_acl)
388 return GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
389 peer_is_allowed_to_use_identity (self, peer_ctx, owner_ctx, identity_acl);
393 * gsignond_access_control_manager_peer_is_owner_of_identity:
394 * @self: object instance.
395 * @peer_ctx: security context of the peer connection.
396 * @owner_ctx: security context of the identity owner.
398 * Checks if the peer specified in @peer_ctx is the owner of the identity.
400 * The default implementation is using gsignond_security_context_check()
401 * to check @peer_ctx against @owner_ctx directly.
406 gsignond_access_control_manager_peer_is_owner_of_identity (
407 GSignondAccessControlManager *self,
408 const GSignondSecurityContext *peer_ctx,
409 const GSignondSecurityContext *owner_ctx)
411 return GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
412 peer_is_owner_of_identity (self, peer_ctx, owner_ctx);
416 * gsignond_access_control_manager_acl_is_valid:
417 * @self: object instance.
418 * @peer_ctx: security context of the peer connection.
419 * @identity_acl: access control list for the identity.
421 * Checks if the specified peer is allowed to set the specified access
422 * control list. gsignond_access_control_manager_peer_is_owner_of_identity()
423 * is used before calling this method to verify identity ownership.
425 * The default implementation always returns TRUE.
427 * Returns: access control list is OK?
430 gsignond_access_control_manager_acl_is_valid (
431 GSignondAccessControlManager *self,
432 const GSignondSecurityContext *peer_ctx,
433 const GSignondSecurityContextList *identity_acl)
435 return GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
436 acl_is_valid (self, peer_ctx, identity_acl);
440 * gsignond_access_control_manager_security_context_of_keychain:
441 * @self: object instance.
443 * Retrieves security context of the keychain application. Keychain application
444 * has a special management access to all stored identities and is able to
445 * perform deletion of all identities from storage.
447 * The default implementation returns an empty context. If gSSO was compiled
448 * with --enable-debug and SSO_KEYCHAIN_SYSCTX environment variable is set, then
449 * the value of that variable is used to set the returned system context instead.
451 * Returns: security context of the keychain application.
453 GSignondSecurityContext *
454 gsignond_access_control_manager_security_context_of_keychain (
455 GSignondAccessControlManager *self)
457 return GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
458 security_context_of_keychain (self);