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 Intel Corporation.
8 * Contact: Jussi Laako <jussi.laako@linux.intel.com>
9 Amarnath Valluri <amarnath.valluri@linux.intel.com>
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
16 * This library is distributed in the hope that it will be useful, but
17 * WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
27 #include "gsignond-identity.h"
30 #include "gsignond/gsignond-log.h"
31 #include "gsignond/gsignond-error.h"
32 #include "gsignond-daemon.h"
33 #include "gsignond-identity-enum-types.h"
34 #include "gsignond-auth-session.h"
35 #include "gsignond/gsignond-config-dbus.h"
36 #include "common/gsignond-identity-info-internal.h"
37 #include "plugins/gsignond-plugin-proxy-factory.h"
49 SIG_CREDENTIALS_UPDATED,
55 static GParamSpec *properties[N_PROPERTIES];
56 static guint signals[SIG_MAX];
58 struct _GSignondIdentityPrivate
60 GSignondIdentityInfo *info;
61 GSignondDaemon *owner;
62 GHashTable *auth_sessions; // (auth_method,auth_session) table
65 typedef struct _GSignondIdentityCbData
67 GSignondIdentity *identity;
68 GSignondAuthSession *session;
69 } GSignondIdentityCbData;
71 G_DEFINE_TYPE (GSignondIdentity, gsignond_identity, G_TYPE_OBJECT);
74 static void _on_session_dead (gpointer data, GObject *session);
75 static void _on_refresh_dialog (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata);
76 static void _on_process_canceled (GSignondAuthSession *session, GSignondIdentityCbData *cb_data);
77 static void _on_user_action_required (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata);
78 static void _on_store_token (GSignondAuthSession *session, GSignondDictionary *token_data, gpointer userdata);
80 #define GSIGNOND_IDENTITY_PRIV(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_IDENTITY, GSignondIdentityPrivate)
82 #define VALIDATE_IDENTITY_READ_ACCESS(identity, ctx, ret) \
84 GSignondAccessControlManager *acm = gsignond_daemon_get_access_control_manager (identity->priv->owner); \
85 GSignondSecurityContextList *acl = gsignond_identity_info_get_access_control_list (identity->priv->info); \
86 GSignondSecurityContext *owner = gsignond_identity_info_get_owner (identity->priv->info); \
87 gboolean valid = gsignond_access_control_manager_peer_is_allowed_to_use_identity (acm, ctx, owner, acl); \
88 gsignond_security_context_free (owner); \
89 gsignond_security_context_list_free (acl); \
91 WARN ("cannot access identity."); \
92 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_PERMISSION_DENIED, "identity can not be accessed"); \
97 #define VALIDATE_IDENTITY_WRITE_ACCESS(identity, ctx, ret) \
99 GSignondAccessControlManager *acm = gsignond_daemon_get_access_control_manager (identity->priv->owner); \
100 GSignondSecurityContext *owner = gsignond_identity_info_get_owner (identity->priv->info); \
101 gboolean valid = gsignond_access_control_manager_peer_is_owner_of_identity (acm, ctx, owner); \
102 gsignond_security_context_free (owner); \
104 WARN ("is_owner_of_identity check failed."); \
105 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_PERMISSION_DENIED, "identity can not be accessed"); \
110 #define VALIDATE_IDENTITY_WRITE_ACL(identity, ctx, ret) \
112 GSignondAccessControlManager *acm = gsignond_daemon_get_access_control_manager (identity->priv->owner); \
113 GSignondSecurityContextList *acl = gsignond_identity_info_get_access_control_list (identity->priv->info); \
114 gboolean valid = gsignond_access_control_manager_acl_is_valid (acm, ctx, acl); \
115 gsignond_security_context_list_free (acl); \
117 WARN ("acl validity check failed."); \
118 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_PERMISSION_DENIED, "invalid access control list"); \
124 _set_id (GSignondIdentity *identity, guint32 id)
126 gsignond_identity_info_set_id (identity->priv->info, id);
127 g_object_notify_by_pspec (G_OBJECT(identity), properties[PROP_INFO]);
133 _get_property (GObject *object, guint property_id, GValue *value,
136 GSignondIdentity *self = GSIGNOND_IDENTITY (object);
141 g_value_set_boxed (value, self->priv->info);
144 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
149 _set_property (GObject *object, guint property_id, const GValue *value,
152 GSignondIdentity *self = GSIGNOND_IDENTITY (object);
158 (GSignondIdentityInfo *)g_value_get_boxed (value);
161 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
166 _release_weak_ref_on_session (gpointer key, gpointer value, gpointer data)
168 GObject *session = G_OBJECT (value);
169 g_signal_handlers_disconnect_by_func (session, G_CALLBACK (_on_user_action_required), data);
170 g_signal_handlers_disconnect_by_func (session, G_CALLBACK (_on_store_token), data);
171 g_object_weak_unref (session, _on_session_dead, data);
175 _dispose (GObject *object)
177 GSignondIdentity *self = GSIGNOND_IDENTITY(object);
179 if (self->priv->auth_sessions) {
180 g_hash_table_foreach (self->priv->auth_sessions, _release_weak_ref_on_session, self);
181 g_hash_table_unref (self->priv->auth_sessions);
182 self->priv->auth_sessions = NULL;
185 if (self->priv->owner) {
186 DBG("unref owner %p", self->priv->owner);
187 g_object_unref (self->priv->owner);
188 self->priv->owner = NULL;
191 if (self->priv->info) {
192 gsignond_identity_info_unref (self->priv->info);
193 self->priv->info = NULL;
196 G_OBJECT_CLASS (gsignond_identity_parent_class)->dispose (object);
200 _finalize (GObject *object)
202 G_OBJECT_CLASS (gsignond_identity_parent_class)->finalize (object);
206 gsignond_identity_init (GSignondIdentity *self)
208 self->priv = GSIGNOND_IDENTITY_PRIV(self);
210 self->priv->auth_sessions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
214 gsignond_identity_class_init (GSignondIdentityClass *klass)
216 GObjectClass* object_class = G_OBJECT_CLASS (klass);
218 g_type_class_add_private (object_class, sizeof (GSignondIdentityPrivate));
220 object_class->get_property = _get_property;
221 object_class->set_property = _set_property;
222 object_class->dispose = _dispose;
223 object_class->finalize = _finalize;
225 properties[PROP_INFO] =
226 g_param_spec_boxed ("info",
228 "IdentityInfo structure",
229 GSIGNOND_TYPE_IDENTITY_INFO,
230 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
231 G_PARAM_STATIC_STRINGS);
233 g_object_class_install_properties (object_class, N_PROPERTIES, properties);
235 signals[SIG_USER_VERIFIED] = g_signal_new ("user-verified",
236 GSIGNOND_TYPE_IDENTITY,
247 signals[SIG_SECRET_VERIFIED] = g_signal_new ("secret-verified",
248 GSIGNOND_TYPE_IDENTITY,
259 signals[SIG_CREDENTIALS_UPDATED] = g_signal_new ("credentials-updated",
260 GSIGNOND_TYPE_IDENTITY,
271 signals[SIG_INFO_UPDATED] = g_signal_new ("info-updated",
272 GSIGNOND_TYPE_IDENTITY,
280 GSIGNOND_TYPE_IDENTITY_CHANGE_TYPE);
285 gsignond_identity_get_info (GSignondIdentity *identity, const GSignondSecurityContext *ctx, GError **error)
287 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
288 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
289 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
293 GSignondIdentityInfo *info = NULL;
294 GVariant *vinfo = NULL;
296 if (!identity->priv->info) {
297 WARN ("assertion (identity->priv->info) failed");
298 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Identity not found.");
302 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, NULL);
304 info = gsignond_identity_info_copy (identity->priv->info);
306 /* remove password */
307 gsignond_identity_info_remove_secret (info);
309 /* remove username if its secret */
310 if (gsignond_identity_info_get_is_username_secret (info))
311 gsignond_identity_info_remove_username (info);
313 /* prepare identity info, excluding password and username if secret */
314 vinfo = gsignond_dictionary_to_variant (identity->priv->info);
315 gsignond_identity_info_unref (info);
317 WARN ("identity info to variant convertion failed.");
318 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Identity internal eror.");
326 _on_dialog_refreshed (GError *error, gpointer user_data)
328 GSignondIdentityCbData *cb_data = (GSignondIdentityCbData *)user_data;
330 g_signal_handlers_disconnect_by_func(cb_data->session, _on_refresh_dialog, user_data);
332 WARN ("Error : %s", error->message);
333 g_error_free (error);
338 _on_refresh_dialog (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata)
340 GSignondIdentityCbData *cb_data = (GSignondIdentityCbData *) userdata;
342 if (!gsignond_daemon_refresh_dialog (GSIGNOND_DAEMON (cb_data->identity->priv->owner),
343 G_OBJECT (cb_data->session), ui_data, _on_dialog_refreshed, userdata)) {
344 WARN ("Dialog Refresh Failed");
349 _on_refresh_requested_by_ui (GSignondSignonuiData *ui_data, gpointer user_data)
351 GSignondIdentityCbData *cb_data = (GSignondIdentityCbData *) user_data;
353 /* check for dialog refresh requests */
354 g_signal_connect (cb_data->session, "process-refreshed", G_CALLBACK (_on_refresh_dialog), cb_data);
355 gsignond_auth_session_refresh (cb_data->session, ui_data);
359 _on_user_action_completed (GSignondSignonuiData *reply, GError *error, gpointer user_data)
361 GSignondIdentityCbData *cb_data = (GSignondIdentityCbData *) user_data;
362 GSignondIdentityPrivate *priv = GSIGNOND_IDENTITY_PRIV (cb_data->identity);
363 GSignondSignonuiError ui_error = SIGNONUI_ERROR_NONE;
365 g_return_if_fail (cb_data && GSIGNOND_IS_AUTH_SESSION (cb_data->session));
367 g_signal_handlers_disconnect_by_func(cb_data->session, _on_refresh_dialog, user_data);
368 g_signal_handlers_disconnect_by_func(cb_data->session, _on_process_canceled, user_data);
371 WARN ("UI-Error: %s on identity %d",
373 gsignond_identity_info_get_id (priv->info));
374 if (cb_data->session) {
375 GSignondSignonuiData *reply = gsignond_dictionary_new();
376 gsignond_signonui_data_set_query_error (reply, SIGNONUI_ERROR_GENERAL);
377 gsignond_auth_session_user_action_finished (cb_data->session, reply);
378 gsignond_dictionary_unref(reply);
380 g_error_free (error);
381 g_slice_free (GSignondIdentityCbData, cb_data);
385 if (gsignond_signonui_data_get_query_error (reply, &ui_error)
386 && ui_error != SIGNONUI_ERROR_NONE) {
387 WARN ("signonui error %d for identity %d",
388 ui_error, gsignond_identity_info_get_id (priv->info));
391 if (!gsignond_identity_info_get_validated (priv->info) &&
392 ui_error == SIGNONUI_ERROR_NONE) {
393 gsignond_identity_info_set_username (priv->info,
394 gsignond_signonui_data_get_username (reply));
397 /* storing secret allowed? */
398 if (gsignond_identity_info_get_store_secret (priv->info)) {
399 gboolean remember = TRUE;
401 /* and there was no opt-out? */
402 if (!gsignond_signonui_data_get_remember_password (reply, &remember))
403 DBG ("identity %d - don't remember password",
404 gsignond_identity_info_get_id (priv->info));
405 if (remember && ui_error == SIGNONUI_ERROR_NONE) {
406 gsignond_identity_info_set_secret (priv->info,
407 gsignond_signonui_data_get_password (reply));
408 } else if (!remember ||
409 (ui_error == SIGNONUI_ERROR_CANCELED ||
410 ui_error == SIGNONUI_ERROR_FORGOT_PASSWORD)) {
411 /* reset to empty in case user canceled or forgot,
412 * or doesn't want password to be remebered anymore */
413 gsignond_identity_info_set_secret (priv->info, "");
416 /* TODO: auto-set to validated on successful process() cycle */
417 /* store if not a new identity (new is stored later) */
418 if (!gsignond_identity_info_get_is_identity_new (priv->info)) {
419 if (!gsignond_daemon_store_identity (priv->owner, cb_data->identity))
420 WARN ("failed to update identity %d",
421 gsignond_identity_info_get_id (priv->info));
424 if (cb_data->session) {
425 gsignond_auth_session_user_action_finished (cb_data->session, reply);
428 g_slice_free (GSignondIdentityCbData, cb_data);
432 _on_process_canceled (GSignondAuthSession *session, GSignondIdentityCbData *cb_data)
434 g_signal_handlers_disconnect_by_func(session, G_CALLBACK(_on_process_canceled), cb_data);
437 WARN ("assert (cb_data)");
440 if (!gsignond_daemon_cancel_dialog (
441 cb_data->identity->priv->owner, G_OBJECT(session), NULL, NULL)) {
442 WARN ("Fail to cancel dialog");
444 g_slice_free (GSignondIdentityCbData, cb_data);
448 _on_user_action_required (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata)
450 GSignondIdentity *identity = GSIGNOND_IDENTITY (userdata);
451 GSignondIdentityCbData *cb_data = g_slice_new (GSignondIdentityCbData);
453 cb_data->identity = identity;
454 cb_data->session = session;
456 gsignond_daemon_show_dialog (GSIGNOND_DAEMON (identity->priv->owner), G_OBJECT(session),
457 ui_data, _on_user_action_completed, _on_refresh_requested_by_ui, cb_data);
459 g_signal_connect (session, "process-canceled", G_CALLBACK(_on_process_canceled), cb_data);
463 _on_store_token (GSignondAuthSession *session, GSignondDictionary *token_data, gpointer userdata)
465 GSignondIdentity *identity = GSIGNOND_IDENTITY (userdata);
466 guint32 identity_id = GSIGNOND_IDENTITY_INFO_NEW_IDENTITY;
468 g_return_if_fail (identity && session && GSIGNOND_IS_AUTH_SESSION (session));
470 identity_id = gsignond_identity_info_get_id (identity->priv->info);
472 if (identity_id != GSIGNOND_IDENTITY_INFO_NEW_IDENTITY) {
473 gsignond_daemon_store_identity_data (identity->priv->owner, identity_id,
474 gsignond_auth_session_get_method (session), token_data);
479 _compare_session_by_pointer (gpointer key, gpointer value, gpointer dead_object)
481 return value == dead_object;
485 _on_session_dead (gpointer data, GObject *session)
487 GSignondIdentity *identity = GSIGNOND_IDENTITY (data);
489 DBG ("identity %p session %p disposed", identity, session);
491 g_hash_table_foreach_remove (identity->priv->auth_sessions,
492 _compare_session_by_pointer, session);
495 GSignondAuthSession *
496 gsignond_identity_get_auth_session (GSignondIdentity *identity,
498 const GSignondSecurityContext *ctx,
501 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
502 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
503 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
506 GSignondAuthSession *session = NULL;
507 GHashTable *supported_methods = NULL;
508 gboolean method_available = FALSE;
509 guint32 identity_id ;
510 GSignondDictionary *token_data = NULL;
512 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, NULL);
515 WARN ("assertion (method) failed");
516 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_METHOD_NOT_KNOWN,
517 "authentication method not provided");
521 DBG ("get auth session for method '%s'", method);
522 session = g_hash_table_lookup (identity->priv->auth_sessions, method);
524 if (session && GSIGNOND_IS_AUTH_SESSION (session)) {
525 DBG("using cashed auth session '%p' for method '%s'", session, method);
526 return GSIGNOND_AUTH_SESSION(g_object_ref (session));
529 if (!gsignond_plugin_proxy_factory_get_plugin_mechanisms (gsignond_get_plugin_proxy_factory (),
531 WARN ("method '%s' doesn't exist", method);
532 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_METHOD_NOT_KNOWN,
533 "authentication method '%s' doesn't exist",
538 supported_methods = gsignond_identity_info_get_methods (identity->priv->info);
540 if (supported_methods) {
541 method_available = g_hash_table_contains (supported_methods, method);
542 g_hash_table_unref (supported_methods);
543 } else if (gsignond_identity_info_get_is_identity_new (
544 identity->priv->info))
545 method_available = TRUE;
547 method_available = FALSE;
550 if (!method_available) {
551 WARN ("authentication method '%s' is not supported", method);
552 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_METHOD_NOT_AVAILABLE,
553 "authentication method '%s' not supported for this identity", method);
557 if ( (identity_id = gsignond_identity_info_get_id (identity->priv->info)) !=
558 GSIGNOND_IDENTITY_INFO_NEW_IDENTITY) {
559 token_data = gsignond_daemon_load_identity_data (identity->priv->owner, identity_id, method);
561 if (!token_data) token_data = gsignond_dictionary_new();
563 session = gsignond_auth_session_new (identity->priv->info, method, token_data);
565 if (token_data) gsignond_dictionary_unref (token_data);
568 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
572 /* Handle 'ui' signanls on session */
573 g_signal_connect (session, "process-user-action-required", G_CALLBACK (_on_user_action_required), identity);
574 g_signal_connect (session, "process-store", G_CALLBACK (_on_store_token), identity);
576 g_hash_table_insert (identity->priv->auth_sessions, g_strdup (method), session);
577 g_object_weak_ref (G_OBJECT (session), _on_session_dead, identity);
579 DBG ("session %p creation for method '%s' complete", session, method);
585 _on_credentials_updated (GSignondSignonuiData *reply, GError *error, gpointer user_data)
587 GSignondIdentity *identity = GSIGNOND_IDENTITY (user_data);
592 WARN ("failed to verify user : %s", error->message);
593 g_error_free (error);
595 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED, "Operation canceled");
599 GSignondSignonuiError err_id = SIGNONUI_ERROR_NONE;
600 gboolean res = gsignond_signonui_data_get_query_error (reply, &err_id);
603 DBG ("No error code set by UI daemon, treating as ERROR_NONE");
606 if (err_id != SIGNONUI_ERROR_NONE) {
608 case SIGNONUI_ERROR_CANCELED:
609 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED,
610 "Operation canceled");
613 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
614 "signon ui returned with error : %d", err_id);
619 const gchar *secret = gsignond_signonui_data_get_password (reply);
622 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
623 "Server internal error occured");
624 } else if (identity->priv->info) {
625 gsignond_identity_info_set_secret (identity->priv->info, secret) ;
627 /* Save new secret in db */
628 id = gsignond_daemon_store_identity (identity->priv->owner, identity);
629 if (!id) err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_STORE_FAILED, "Failed to store secret");
634 g_signal_emit (identity, signals[SIG_CREDENTIALS_UPDATED], 0 , id, err);
636 if (err) g_error_free (err);
640 gsignond_identity_request_credentials_update (GSignondIdentity *identity,
641 const gchar *message,
642 const GSignondSecurityContext *ctx,
645 GSignondSignonuiData *ui_data = NULL;
647 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
648 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
649 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
653 if (!identity->priv->info) {
654 WARN ("assertion (identity->priv->info) failed");
655 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Identity not found.");
659 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, FALSE);
661 if (!gsignond_identity_info_get_store_secret (identity->priv->info)) {
662 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_CREDENTIALS_NOT_AVAILABLE, "Password can not be stored.");
666 ui_data = gsignond_dictionary_new ();
668 gsignond_signonui_data_set_query_password (ui_data, TRUE);
669 gsignond_signonui_data_set_username (ui_data, gsignond_identity_info_get_username (identity->priv->info));
670 gsignond_signonui_data_set_caption (ui_data, gsignond_identity_info_get_caption (identity->priv->info));
671 gsignond_signonui_data_set_message (ui_data, message);
673 gsignond_daemon_show_dialog (GSIGNOND_DAEMON (identity->priv->owner), G_OBJECT(identity),
674 ui_data, _on_credentials_updated, NULL, identity);
676 gsignond_dictionary_unref (ui_data);
682 _on_user_verified (GSignondSignonuiData *reply, GError *error, gpointer user_data)
684 GSignondIdentity *identity = GSIGNOND_IDENTITY (user_data);
685 gboolean res = FALSE;
689 WARN ("failed to verify user : %s", error->message);
690 g_error_free (error);
692 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED, "Operation canceled");
696 GSignondSignonuiError err_id = SIGNONUI_ERROR_NONE;
697 gboolean res = gsignond_signonui_data_get_query_error (reply, &err_id);
699 DBG ("No error code set by UI daemon, treating as ERROR_NONE");
701 if (err_id != SIGNONUI_ERROR_NONE) {
703 case SIGNONUI_ERROR_CANCELED:
704 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED,
705 "Operation canceled");
707 case SIGNONUI_ERROR_FORGOT_PASSWORD:
708 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_FORGOT_PASSWORD, "Forgot password");
711 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
712 "signon ui returned error : %d", err_id);
717 const gchar *secret = gsignond_signonui_data_get_password (reply);
720 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
721 "Server internal error occured");
722 } else if (identity->priv->info) {
723 res = g_strcmp0 (secret, gsignond_identity_info_get_secret
724 (identity->priv->info)) == 0;
729 g_signal_emit (identity, signals[SIG_USER_VERIFIED], 0, res, err);
731 if (err) g_error_free (err);
735 gsignond_identity_verify_user (GSignondIdentity *identity,
737 const GSignondSecurityContext *ctx,
740 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
741 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) == 0) failed");
742 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
745 const gchar *passwd = 0;
746 GSignondSignonuiData *ui_data = NULL;
748 if (!identity->priv->info) {
749 WARN ("assertion (identity->priv->info) failed");
750 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Identity not found.");
754 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, FALSE);
756 if (!gsignond_identity_info_get_store_secret (identity->priv->info) ||
757 !(passwd = gsignond_identity_info_get_secret (identity->priv->info)) ||
759 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_CREDENTIALS_NOT_AVAILABLE,
760 "user can not be verified as credentials are not stored");
764 ui_data = gsignond_dictionary_new_from_variant (params);
765 gsignond_signonui_data_set_query_password (ui_data, TRUE);
766 gsignond_signonui_data_set_username (ui_data, gsignond_identity_info_get_username (identity->priv->info));
767 gsignond_signonui_data_set_caption (ui_data, gsignond_identity_info_get_caption (identity->priv->info));
769 gsignond_daemon_show_dialog (GSIGNOND_DAEMON (identity->priv->owner), G_OBJECT (identity),
770 ui_data, _on_user_verified, NULL, identity);
772 gsignond_dictionary_unref (ui_data);
778 gsignond_identity_verify_secret (GSignondIdentity *identity,
780 const GSignondSecurityContext *ctx,
783 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
784 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
785 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
789 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, FALSE);
791 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Not supported");
797 gsignond_identity_sign_out (GSignondIdentity *identity,
798 const GSignondSecurityContext *ctx,
801 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
802 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
803 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
806 gboolean success = FALSE;
807 guint32 identity_id = GSIGNOND_IDENTITY_INFO_NEW_IDENTITY;
809 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, FALSE);
811 identity_id = gsignond_identity_info_get_id (identity->priv->info);
813 if (identity_id == GSIGNOND_IDENTITY_INFO_NEW_IDENTITY) {
814 /* TODO; clear the cached secret for unstored identity */
818 success = gsignond_daemon_clear_identity_data (identity->priv->owner, identity_id);
821 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Failed to clear data");
825 g_signal_emit (identity, signals[SIG_INFO_UPDATED], 0, GSIGNOND_IDENTITY_SIGNED_OUT, NULL);
831 GSignondDaemon *daemon;
833 }_StoreCachedTokenCbInfo;
835 _store_cached_token_data (const gchar *method, GSignondAuthSession *session, _StoreCachedTokenCbInfo *data)
837 if (!data || !method || !session) return ;
839 GSignondDictionary *token_data = gsignond_auth_session_get_token_data (session);
842 gsignond_daemon_store_identity_data (data->daemon, data->identity_id, method, token_data);
846 gsignond_identity_store (GSignondIdentity *identity,
847 const GVariant *info,
848 const GSignondSecurityContext *ctx,
851 GSignondIdentityInfo *identity_info = NULL;
852 gboolean was_new_identity = FALSE;
853 GSignondSecurityContextList *contexts = NULL;
854 GSignondSecurityContext *owner = NULL;
857 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
858 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
859 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
863 VALIDATE_IDENTITY_WRITE_ACCESS (identity, ctx, 0);
865 identity_info = gsignond_dictionary_new_from_variant ((GVariant *)info);
866 /* dont trust 'identity id' passed via 'info' */
867 id = gsignond_identity_info_get_id (identity->priv->info);
868 gsignond_identity_info_set_id (identity_info, id);
870 was_new_identity = gsignond_identity_info_get_is_identity_new (identity_info);
872 contexts = gsignond_identity_info_get_access_control_list (identity_info);
874 contexts = gsignond_identity_info_get_access_control_list (identity->priv->info);
875 gsignond_identity_info_set_access_control_list (identity_info, contexts);
878 VALIDATE_IDENTITY_WRITE_ACL (identity, ctx, 0);
880 gsignond_security_context_list_free (contexts);
882 owner = gsignond_identity_info_get_owner (identity_info);
884 owner = gsignond_identity_info_get_owner (identity->priv->info);
885 gsignond_identity_info_set_owner (identity_info, owner);
887 gsignond_security_context_free (owner);
890 /* update object cache */
891 if (identity->priv->info)
892 gsignond_identity_info_unref (identity->priv->info);
893 identity->priv->info = identity_info;
895 /* Ask daemon to store identity info to db */
896 id = gsignond_daemon_store_identity (identity->priv->owner, identity);
898 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_STORE_FAILED,
899 "Failed to store identity");
902 if (was_new_identity) {
903 _set_id (identity, id);
904 _StoreCachedTokenCbInfo data = { identity->priv->owner, id };
905 /* store any cached token data if available at auth sessions */
906 g_hash_table_foreach (identity->priv->auth_sessions, (GHFunc)_store_cached_token_data, (gpointer)&data);
909 g_signal_emit (identity, signals[SIG_INFO_UPDATED], 0, GSIGNOND_IDENTITY_DATA_UPDATED);
916 gsignond_identity_remove (GSignondIdentity *identity,
917 const GSignondSecurityContext *ctx,
920 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
921 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
922 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
925 gboolean is_removed = FALSE;
927 VALIDATE_IDENTITY_WRITE_ACCESS (identity, ctx, FALSE);
929 is_removed = gsignond_identity_clear (identity);
931 if (!is_removed && error)
932 *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_REMOVE_FAILED, "failed to remove identity");
939 gsignond_identity_clear (GSignondIdentity *identity)
941 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
942 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
945 gboolean is_removed = FALSE;
947 if (gsignond_identity_info_get_is_identity_new (identity->priv->info))
950 is_removed = gsignond_daemon_remove_identity (
951 identity->priv->owner,
952 gsignond_identity_info_get_id (identity->priv->info));
955 g_signal_emit (identity, signals[SIG_INFO_UPDATED], 0, GSIGNOND_IDENTITY_REMOVED);
957 WARN ("request to remove identity %u failed",
958 gsignond_identity_info_get_id (identity->priv->info));
965 gsignond_identity_add_reference (GSignondIdentity *identity,
966 const gchar *reference,
967 const GSignondSecurityContext *ctx,
970 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
971 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
972 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
976 guint32 identity_id = 0;
978 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, 0);
980 identity_id = gsignond_identity_info_get_id (identity->priv->info);
982 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_STORE_FAILED, "Cannot add reference to unsaved identity");
985 res = gsignond_daemon_add_identity_reference (identity->priv->owner, identity_id, ctx, reference);
988 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
995 gsignond_identity_remove_reference (GSignondIdentity *identity,
996 const gchar *reference,
997 const GSignondSecurityContext *ctx,
1000 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
1001 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
1002 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
1007 guint32 identity_id = 0;
1009 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, 0);
1011 identity_id = gsignond_identity_info_get_id (identity->priv->info);
1013 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_REFERENCE_NOT_FOUND, "reference not '%s' found", reference);
1017 res = gsignond_daemon_remove_identity_reference (identity->priv->owner, identity_id, ctx, reference);
1019 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_REFERENCE_NOT_FOUND,
1020 "reference '%s' not found", reference);
1025 GSignondAccessControlManager *
1026 gsignond_identity_get_acm (GSignondIdentity *identity)
1028 g_return_val_if_fail (identity && GSIGNOND_IS_IDENTITY(identity), NULL);
1030 return gsignond_daemon_get_access_control_manager (identity->priv->owner);
1034 gsignond_identity_get_auth_session_timeout (GSignondIdentity *identity)
1036 g_return_val_if_fail (identity && GSIGNOND_IS_IDENTITY(identity), 0);
1038 return gsignond_daemon_get_auth_session_timeout (identity->priv->owner);
1042 * gsignond_identity_get_id:
1043 * @identity: instance of #GSignondIdentity
1045 * Retrieves identity id.
1047 * Returns: identity id
1050 gsignond_identity_get_id (GSignondIdentity *identity)
1052 g_assert (GSIGNOND_IS_IDENTITY (identity));
1054 return gsignond_identity_info_get_id (identity->priv->info);
1058 * gsignond_identity_get_identity_info:
1059 * @identity: instance of #GSignondIdentity
1061 * Retrieves identity's #GSignondIdentityInfo.
1063 * Returns: (transfer none) #GSignondIdentityInfo
1065 GSignondIdentityInfo *
1066 gsignond_identity_get_identity_info (GSignondIdentity *identity)
1068 g_assert (GSIGNOND_IS_IDENTITY (identity));
1069 g_assert (identity->priv != NULL);
1071 return identity->priv->info;
1075 * gsignond_identity_new:
1076 * @owner: Owner of this object, instance of #GSignondAuthServiceIface
1077 * @info (transfer full): Identity info, instance of #GSignondIdentityInfo
1079 * Creates new instance of #GSignondIdentity
1081 * Returns[transfer full]: new instance of #GSignondIdentity
1083 GSignondIdentity * gsignond_identity_new (GSignondDaemon *owner,
1084 GSignondIdentityInfo *info)
1086 GSignondIdentity *identity =
1087 GSIGNOND_IDENTITY(g_object_new (GSIGNOND_TYPE_IDENTITY,
1091 identity->priv->owner = g_object_ref (owner);