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) 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
26 #include "gsignond-auth-session.h"
27 #include "gsignond/gsignond-error.h"
28 #include "gsignond/gsignond-log.h"
29 #include "gsignond/gsignond-session-data.h"
30 #include "plugins/gsignond-plugin-proxy-factory.h"
31 #include "gsignond-daemon.h"
40 static GParamSpec *properties[N_PROPERTIES];
44 SIG_PROCESS_USER_ACTION_REQUIRED,
45 SIG_PROCESS_REFRESHED,
51 static guint signals[SIG_MAX] = { 0 };
54 GSignondAuthSession *self;
55 ProcessReadyCb ready_cb;
56 StateChangeCb state_change_cb;
60 struct _GSignondAuthSessionPrivate
63 GSignondPluginProxy *proxy;
64 GSequence *available_mechanisms;
65 GSignondIdentityInfo *identity_info;
66 GSignondDictionary *token_data;
69 G_DEFINE_TYPE (GSignondAuthSession, gsignond_auth_session, G_TYPE_OBJECT)
71 #define GSIGNOND_AUTH_SESSION_PRIV(obj) \
72 G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_AUTH_SESSION, \
73 GSignondAuthSessionPrivate)
75 #define VALIDATE_READ_ACCESS(info, ctx, ret) \
77 GSignondAccessControlManager *acm = gsignond_get_access_control_manager(); \
78 GSignondSecurityContextList *acl = gsignond_identity_info_get_access_control_list (info); \
79 GSignondSecurityContext *owner = gsignond_identity_info_get_owner (info); \
80 gboolean valid = gsignond_access_control_manager_peer_is_allowed_to_use_identity (acm, ctx, owner, acl); \
81 gsignond_security_context_free (owner); \
82 gsignond_security_context_list_free (acl); \
84 WARN ("security check failed"); \
86 *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_PERMISSION_DENIED, "Can not access identity"); \
93 _sort_cmp (gconstpointer str1, gconstpointer str2, gpointer user_data)
97 return g_strcmp0 ((const gchar *) str1, (const gchar *) str2);
101 _create_mechanism_cache (GSignondAuthSession *self)
103 GSignondAuthSessionPrivate *priv = self->priv;
105 if (priv->available_mechanisms)
108 gchar **mechanisms, **iter;
109 GSequence *allowed_mechanisms = NULL;
110 GSequenceIter *wcard = NULL;
112 self->priv->available_mechanisms = g_sequence_new (g_free);
113 if (!gsignond_identity_info_get_is_identity_new (priv->identity_info)) {
114 allowed_mechanisms = gsignond_identity_info_get_mechanisms (
117 if (!allowed_mechanisms)
119 wcard = g_sequence_lookup (allowed_mechanisms,
124 g_object_get (self->priv->proxy,
125 "mechanisms", &mechanisms,
128 if (allowed_mechanisms)
129 g_sequence_free (allowed_mechanisms);
132 if (wcard || !allowed_mechanisms) {
133 DBG ("add all mechanisms to allowed");
134 for (iter = mechanisms; *iter != NULL; iter++) {
135 g_sequence_insert_sorted (priv->available_mechanisms,
139 DBG (" allow '%s'", *iter);
142 DBG ("allow intersection of plugin and ACL mechanisms");
143 for (iter = mechanisms; *iter != NULL; iter++) {
144 GSequenceIter *pos = g_sequence_lookup (allowed_mechanisms,
149 DBG (" allow: '%s'", *iter);
150 g_sequence_insert_sorted (priv->available_mechanisms,
157 if (allowed_mechanisms)
158 g_sequence_free (allowed_mechanisms);
163 gsignond_auth_session_query_available_mechanisms (GSignondAuthSession *self,
164 const gchar **wanted_mechanisms,
165 const GSignondSecurityContext *ctx,
168 if (!self || !GSIGNOND_IS_AUTH_SESSION (self)) {
169 WARN ("assertion (iself && GSIGNOND_IS_AUTH_SESSION (self)) failed");
170 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
174 VALIDATE_READ_ACCESS (self->priv->identity_info, ctx, NULL);
176 gchar **mechanisms, **iter;
177 const gchar **src_iter;
179 _create_mechanism_cache (self);
180 mechanisms = (gchar **)
181 g_malloc0 ((g_sequence_get_length (self->priv->available_mechanisms) +
182 1) * sizeof(gchar *));
184 for (src_iter = wanted_mechanisms; *src_iter != NULL; src_iter++) {
185 GSequenceIter *pos = g_sequence_lookup (
186 self->priv->available_mechanisms,
187 (gpointer) *src_iter,
191 *iter = g_sequence_get (pos);
201 gsignond_auth_session_process (GSignondAuthSession *self,
202 GSignondSessionData *session_data,
203 const gchar *mechanism,
204 const GSignondSecurityContext *ctx,
205 ProcessReadyCb ready_cb,
206 StateChangeCb state_change_cb,
210 if (!self || !GSIGNOND_IS_AUTH_SESSION (self)) {
211 WARN ("assertion (self && GSIGNOND_IS_AUTH_SESSION (self)) failed");
212 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
216 VALIDATE_READ_ACCESS (self->priv->identity_info, ctx, FALSE);
218 _create_mechanism_cache (self);
219 if (!g_sequence_lookup (self->priv->available_mechanisms,
220 (gpointer) mechanism,
223 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_MECHANISM_NOT_AVAILABLE, "Mechanism is not available");
228 self->priv->identity_info) {
229 if (!gsignond_session_data_get_username (session_data)) {
230 const gchar *username =
231 gsignond_identity_info_get_username (self->priv->identity_info);
233 gsignond_session_data_set_username (session_data, username);
235 if (!gsignond_session_data_get_secret (session_data)) {
236 const gchar *secret =
237 gsignond_identity_info_get_secret (self->priv->identity_info);
239 gsignond_session_data_set_secret (session_data, secret);
242 gsignond_identity_info_get_realms (self->priv->identity_info);
244 gsignond_session_data_set_allowed_realms (session_data,
248 _ProcessData * data = g_slice_new0 (_ProcessData);
250 data->ready_cb = ready_cb;
251 data->state_change_cb = state_change_cb;
252 data->userdata = userdata;
253 gsignond_plugin_proxy_process(self->priv->proxy, self, session_data,
254 self->priv->token_data,
261 gsignond_auth_session_cancel (GSignondAuthSession *self,
262 const GSignondSecurityContext *ctx,
265 if (!self || !GSIGNOND_IS_AUTH_SESSION (self)) {
266 WARN ("assertion (self && GSIGNOND_IS_AUTH_SESSION (self)) failed");
267 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
270 VALIDATE_READ_ACCESS (self->priv->identity_info, ctx, FALSE);
272 gsignond_plugin_proxy_cancel(self->priv->proxy, self);
273 g_signal_emit (self, signals[SIG_PROCESS_CANCELED], 0, NULL);
279 gsignond_auth_session_abort_process (GSignondAuthSession *self)
281 g_return_if_fail (self && GSIGNOND_IS_AUTH_SESSION (self));
283 gsignond_plugin_proxy_cancel (self->priv->proxy, self);
284 g_signal_emit (self, signals[SIG_PROCESS_CANCELED], 0, NULL);
288 gsignond_auth_session_user_action_finished (GSignondAuthSession *self,
289 GSignondSignonuiData *ui_data)
291 gsignond_plugin_proxy_user_action_finished(self->priv->proxy, ui_data);
295 gsignond_auth_session_refresh (GSignondAuthSession *self,
296 GSignondSignonuiData *ui_data)
298 gsignond_plugin_proxy_refresh(self->priv->proxy, ui_data);
301 GSignondAccessControlManager *
302 gsignond_auth_session_get_acm (GSignondAuthSession *session)
304 return gsignond_get_access_control_manager ();
308 _get_property (GObject *object, guint property_id, GValue *value,
311 GSignondAuthSession *self = GSIGNOND_AUTH_SESSION (object);
316 g_value_set_string (value, self->priv->method);
319 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
324 _set_property (GObject *object, guint property_id, const GValue *value,
327 GSignondAuthSession *self = GSIGNOND_AUTH_SESSION (object);
332 self->priv->method = g_value_dup_string (value);
335 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
340 _dispose (GObject *object)
342 GSignondAuthSession *self = GSIGNOND_AUTH_SESSION (object);
344 if (self->priv->proxy) {
345 g_object_unref (self->priv->proxy);
346 self->priv->proxy = NULL;
349 if (self->priv->identity_info) {
350 gsignond_identity_info_unref (self->priv->identity_info);
351 self->priv->identity_info = NULL;
354 if (self->priv->token_data) {
355 gsignond_dictionary_unref (self->priv->token_data);
356 self->priv->token_data = NULL;
359 G_OBJECT_CLASS (gsignond_auth_session_parent_class)->dispose (object);
363 _finalize (GObject *object)
365 GSignondAuthSession *self = GSIGNOND_AUTH_SESSION (object);
367 if (self->priv->method) {
368 g_free (self->priv->method);
369 self->priv->method = NULL;
372 if (self->priv->available_mechanisms) {
373 g_sequence_free (self->priv->available_mechanisms);
374 self->priv->available_mechanisms = NULL;
377 G_OBJECT_CLASS (gsignond_auth_session_parent_class)->finalize (object);
381 gsignond_auth_session_init (GSignondAuthSession *self)
383 self->priv = GSIGNOND_AUTH_SESSION_PRIV (self);
385 self->priv->method = NULL;
386 self->priv->proxy = NULL;
387 self->priv->identity_info = NULL;
388 self->priv->token_data = NULL;
389 self->priv->available_mechanisms = NULL;
393 gsignond_auth_session_class_init (GSignondAuthSessionClass *klass)
395 GObjectClass *object_class = G_OBJECT_CLASS (klass);
397 g_type_class_add_private (klass, sizeof (GSignondAuthSessionPrivate));
399 object_class->get_property = _get_property;
400 object_class->set_property = _set_property;
401 object_class->dispose = _dispose;
402 object_class->finalize = _finalize;
404 properties[PROP_METHOD] =
405 g_param_spec_string ("method",
406 "authentication method",
407 "Authentication method used",
409 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY
410 | G_PARAM_STATIC_STRINGS);
412 g_object_class_install_properties (object_class, N_PROPERTIES, properties);
414 signals[SIG_PROCESS_STORE] = g_signal_new ("process-store",
415 GSIGNOND_TYPE_AUTH_SESSION,
423 GSIGNOND_TYPE_DICTIONARY);
425 signals[SIG_PROCESS_USER_ACTION_REQUIRED] = g_signal_new ("process-user-action-required",
426 GSIGNOND_TYPE_AUTH_SESSION,
434 GSIGNOND_TYPE_SIGNONUI_DATA);
436 signals[SIG_PROCESS_REFRESHED] = g_signal_new ("process-refreshed",
437 GSIGNOND_TYPE_AUTH_SESSION,
445 GSIGNOND_TYPE_SIGNONUI_DATA);
447 signals[SIG_PROCESS_CANCELED] = g_signal_new ("process-canceled",
448 GSIGNOND_TYPE_AUTH_SESSION,
461 * gsignond_auth_session_get_method:
462 * @session: instance of #GSignondAuthSession
464 * Retrieves authentication method used by #session.
466 * Returns: (transfer none) authenticaiton method if success, NULL otherwise
469 gsignond_auth_session_get_method (GSignondAuthSession *session)
471 g_return_val_if_fail (session && GSIGNOND_IS_AUTH_SESSION (session), NULL);
473 return session->priv->method;
477 gsignond_auth_session_get_token_data (GSignondAuthSession *session)
479 g_return_val_if_fail (session && GSIGNOND_IS_AUTH_SESSION (session), NULL);
481 return session->priv->token_data;
485 gsignond_auth_session_notify_process_result (GSignondAuthSession *iface,
486 GSignondSessionData *result,
490 WARN("assert (userdata)");
493 _ProcessData *data = (_ProcessData *)userdata;
495 if (data->ready_cb) data->ready_cb (result, NULL, data->userdata);
497 g_slice_free (_ProcessData, data);
501 gsignond_auth_session_notify_process_error (GSignondAuthSession *iface,
506 WARN("assert (userdata)");
509 _ProcessData *data = (_ProcessData *)userdata;
511 if (data->ready_cb) data->ready_cb (NULL, error, data->userdata);
513 g_slice_free (_ProcessData, data);
517 gsignond_auth_session_notify_state_changed (GSignondAuthSession *self,
519 const gchar *message,
523 WARN("assert (userdata)");
526 _ProcessData *data = (_ProcessData *)userdata;
528 if (data->state_change_cb) data->state_change_cb (state, message, data->userdata);
532 gsignond_auth_session_notify_store (GSignondAuthSession *self,
533 GSignondDictionary *token_data)
535 g_return_if_fail (self && GSIGNOND_IS_AUTH_SESSION (self));
536 g_return_if_fail (token_data);
538 /* cache token data */
539 if (self->priv->token_data)
540 gsignond_dictionary_unref (self->priv->token_data);
541 self->priv->token_data = gsignond_dictionary_ref (token_data);
543 g_signal_emit (self, signals[SIG_PROCESS_STORE], 0, token_data);
547 gsignond_auth_session_notify_user_action_required (GSignondAuthSession *self,
548 GSignondSignonuiData *ui_data)
550 g_signal_emit (self, signals[SIG_PROCESS_USER_ACTION_REQUIRED], 0, ui_data);
554 gsignond_auth_session_notify_refreshed (GSignondAuthSession *self,
555 GSignondSignonuiData *ui_data)
557 g_signal_emit (self, signals[SIG_PROCESS_REFRESHED], 0, ui_data);
562 * gsignond_auth_session_new:
563 * @info: instance of #GSignondIdentityInfo
564 * @method: authentication method
565 * @token_data: (transfer full) stored token data stored for #method
567 * Creates instance of #GSignondAuthSession.
569 * Returns: (transfer full) newly created object
571 GSignondAuthSession *
572 gsignond_auth_session_new (GSignondIdentityInfo *info, const gchar *method, GSignondDictionary *token_data)
574 GSignondPluginProxy* proxy = NULL;
576 g_return_val_if_fail (method, NULL);
578 proxy = gsignond_plugin_proxy_factory_get_plugin(
579 gsignond_get_plugin_proxy_factory(), method);
580 if (!proxy) return NULL;
582 GSignondAuthSession *auth_session =
583 g_object_new (GSIGNOND_TYPE_AUTH_SESSION,
584 "method", method, NULL);
585 auth_session->priv->proxy = proxy;
586 auth_session->priv->identity_info = gsignond_identity_info_ref (info);
587 auth_session->priv->token_data = token_data ? gsignond_dictionary_ref(token_data)
588 : gsignond_dictionary_new();