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 g_return_val_if_fail (self != NULL, NULL);
282 const gchar *keychain_sysctx;
284 keychain_sysctx = gsignond_config_get_string (
286 GSIGNOND_CONFIG_GENERAL_KEYCHAIN_SYSCTX);
287 if (!keychain_sysctx)
288 # ifdef KEYCHAIN_SYSCTX
289 keychain_sysctx = KEYCHAIN_SYSCTX;
291 keychain_sysctx = "";
294 const gchar *keychain_env = g_getenv ("SSO_KEYCHAIN_SYSCTX");
296 keychain_sysctx = keychain_env;
299 return gsignond_security_context_new_from_values (keychain_sysctx, NULL);
303 * GSignondAccessControlManagerClass:
304 * @parent_class: parent class.
305 * @security_context_of_peer: an implementation of gsignond_access_control_manager_security_context_of_peer()
306 * @peer_is_allowed_to_use_identity: an implementation of gsignond_access_control_manager_peer_is_allowed_to_use_identity()
307 * @peer_is_owner_of_identity: an implementation of gsignond_access_control_manager_peer_is_owner_of_identity()
308 * @acl_is_valid: an implementation of gsignond_access_control_manager_acl_is_valid()
309 * @security_context_of_keychain: an implementation of gsignond_access_control_manager_security_context_of_keychain()
311 * #GSignondAccessControlManagerClass class containing pointers to class methods.
314 gsignond_access_control_manager_class_init (
315 GSignondAccessControlManagerClass *klass)
317 GObjectClass *base = G_OBJECT_CLASS (klass);
319 base->set_property = _set_property;
320 base->get_property = _get_property;
321 base->dispose = _dispose;
322 properties[PROP_CONFIG] = g_param_spec_object ("config",
324 "Configuration object",
325 GSIGNOND_TYPE_CONFIG,
326 G_PARAM_CONSTRUCT_ONLY|
328 G_PARAM_STATIC_STRINGS);
329 g_object_class_install_properties (base, N_PROPERTIES, properties);
331 /*g_type_class_add_private (klass,
332 sizeof(GSignondAccessControlManagerPrivate));*/
334 klass->security_context_of_peer = _security_context_of_peer;
335 klass->peer_is_allowed_to_use_identity = _peer_is_allowed_to_use_identity;
336 klass->peer_is_owner_of_identity = _peer_is_owner_of_identity;
337 klass->acl_is_valid = _acl_is_valid;
338 klass->security_context_of_keychain = _security_context_of_keychain;
342 gsignond_access_control_manager_init (GSignondAccessControlManager *self)
344 /*self->priv = GSIGNOND_ACCESS_CONTROL_MANAGER_GET_PRIVATE (self);*/
350 * gsignond_access_control_manager_security_context_of_peer:
351 * @self: object instance.
352 * @peer_ctx: instance of security context to be set.
353 * @peer_fd: file descriptor of the peer connection if using peer-to-peer dbus, -1 otherwise.
354 * @peer_service: g_dbus_method_invocation_get_sender() of the peer connection, if not using peer-to-peer dbus, NULL otherwise
355 * @peer_app_ctx: application context of the peer connection.
357 * Retrieves and sets #GSignondSecurityContext of the specified peer.
359 * The default implementation sets the app context as it was passed, and sets
360 * the system context to the binary path of the process that is determined from
361 * @peer_fd and @peer_service parameters.
364 gsignond_access_control_manager_security_context_of_peer (
365 GSignondAccessControlManager *self,
366 GSignondSecurityContext *peer_ctx,
367 int peer_fd, const gchar *peer_service,
368 const gchar *peer_app_ctx)
370 GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
371 security_context_of_peer (self, peer_ctx, peer_fd,
372 peer_service, peer_app_ctx);
376 * gsignond_access_control_manager_peer_is_allowed_to_use_identity:
377 * @self: object instance.
378 * @peer_ctx: security context of the peer connection.
379 * @owner_ctx: security context of the identity owner.
380 * @identity_acl: access control list for the identity in question. Includes the @owner_ctx as well.
382 * Checks if specified peer is allowed to access the specified identity.
384 * The default implementation goes over items in @identity_acl, using
385 * gsignond_security_context_check() to check them against @peer_ctx.
387 * Returns: access is allowed?
390 gsignond_access_control_manager_peer_is_allowed_to_use_identity (
391 GSignondAccessControlManager *self,
392 const GSignondSecurityContext *peer_ctx,
393 const GSignondSecurityContext *owner_ctx,
394 const GSignondSecurityContextList *identity_acl)
396 return GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
397 peer_is_allowed_to_use_identity (self, peer_ctx, owner_ctx, identity_acl);
401 * gsignond_access_control_manager_peer_is_owner_of_identity:
402 * @self: object instance.
403 * @peer_ctx: security context of the peer connection.
404 * @owner_ctx: security context of the identity owner.
406 * Checks if the peer specified in @peer_ctx is the owner of the identity.
408 * The default implementation is using gsignond_security_context_check()
409 * to check @peer_ctx against @owner_ctx directly.
414 gsignond_access_control_manager_peer_is_owner_of_identity (
415 GSignondAccessControlManager *self,
416 const GSignondSecurityContext *peer_ctx,
417 const GSignondSecurityContext *owner_ctx)
419 return GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
420 peer_is_owner_of_identity (self, peer_ctx, owner_ctx);
424 * gsignond_access_control_manager_acl_is_valid:
425 * @self: object instance.
426 * @peer_ctx: security context of the peer connection.
427 * @identity_acl: access control list for the identity.
429 * Checks if the specified peer is allowed to set the specified access
430 * control list. gsignond_access_control_manager_peer_is_owner_of_identity()
431 * is used before calling this method to verify identity ownership.
433 * The default implementation always returns TRUE.
435 * Returns: access control list is OK?
438 gsignond_access_control_manager_acl_is_valid (
439 GSignondAccessControlManager *self,
440 const GSignondSecurityContext *peer_ctx,
441 const GSignondSecurityContextList *identity_acl)
443 return GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
444 acl_is_valid (self, peer_ctx, identity_acl);
448 * gsignond_access_control_manager_security_context_of_keychain:
449 * @self: object instance.
451 * Retrieves security context of the keychain application. Keychain application
452 * has a special management access to all stored identities and is able to
453 * perform deletion of all identities from storage.
455 * The default implementation returns a context either set in #GSignondConfig,
456 * or if not set, a value specified through a configure --enable-keychain
458 * <link linkend="gsignond-building">Building gsignond</link>), or if that is not
459 * set either then an empty string "" is returned.
461 * If gSSO was compiled
462 * with --enable-debug and SSO_KEYCHAIN_SYSCTX environment variable is set, then
463 * the value of that variable is used to set the returned system context instead.
465 * Returns: security context of the keychain application.
467 GSignondSecurityContext *
468 gsignond_access_control_manager_security_context_of_keychain (
469 GSignondAccessControlManager *self)
471 return GSIGNOND_ACCESS_CONTROL_MANAGER_GET_CLASS (self)->
472 security_context_of_keychain (self);