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 "gsignond/gsignond-signonui.h"
37 #include "common/gsignond-identity-info-internal.h"
38 #include "plugins/gsignond-plugin-proxy-factory.h"
50 SIG_CREDENTIALS_UPDATED,
56 static GParamSpec *properties[N_PROPERTIES];
57 static guint signals[SIG_MAX];
59 struct _GSignondIdentityPrivate
61 GSignondIdentityInfo *info;
62 GSignondDaemon *owner;
63 GHashTable *auth_sessions; // (auth_method,auth_session) table
66 typedef struct _GSignondIdentityCbData
68 GSignondIdentity *identity;
69 GSignondAuthSession *session;
70 } GSignondIdentityCbData;
72 G_DEFINE_TYPE (GSignondIdentity, gsignond_identity, G_TYPE_OBJECT);
75 static void _on_session_close (gpointer data, GObject *session);
76 static void _on_refresh_dialog (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata);
77 static void _on_process_canceled (GSignondAuthSession *session, GSignondIdentityCbData *cb_data);
78 static void _on_user_action_required (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata);
79 static void _on_store_token (GSignondAuthSession *session, GSignondDictionary *token_data, gpointer userdata);
81 #define GSIGNOND_IDENTITY_PRIV(obj) G_TYPE_INSTANCE_GET_PRIVATE ((obj), GSIGNOND_TYPE_IDENTITY, GSignondIdentityPrivate)
83 #define VALIDATE_IDENTITY_READ_ACCESS(identity, ctx, ret) \
85 GSignondAccessControlManager *acm = gsignond_daemon_get_access_control_manager (identity->priv->owner); \
86 GSignondSecurityContextList *acl = gsignond_identity_info_get_access_control_list (identity->priv->info); \
87 GSignondSecurityContext *owner = gsignond_identity_info_get_owner (identity->priv->info); \
88 gboolean valid = gsignond_access_control_manager_peer_is_allowed_to_use_identity (acm, ctx, owner, acl); \
89 gsignond_security_context_free (owner); \
90 gsignond_security_context_list_free (acl); \
92 WARN ("cannot access identity."); \
93 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_PERMISSION_DENIED, "identity can not be accessed"); \
98 #define VALIDATE_IDENTITY_WRITE_ACCESS(identity, ctx, ret) \
100 GSignondAccessControlManager *acm = gsignond_daemon_get_access_control_manager (identity->priv->owner); \
101 GSignondSecurityContext *owner = gsignond_identity_info_get_owner (identity->priv->info); \
102 gboolean valid = gsignond_access_control_manager_peer_is_owner_of_identity (acm, ctx, owner); \
103 gsignond_security_context_free (owner); \
105 WARN ("is_owner_of_identity check failed."); \
106 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_PERMISSION_DENIED, "identity can not be accessed"); \
111 #define VALIDATE_IDENTITY_WRITE_ACL(identity, ctx, ret) \
113 GSignondAccessControlManager *acm = gsignond_daemon_get_access_control_manager (identity->priv->owner); \
114 GSignondSecurityContextList *acl = gsignond_identity_info_get_access_control_list (identity->priv->info); \
115 gboolean valid = gsignond_access_control_manager_acl_is_valid (acm, ctx, acl); \
116 gsignond_security_context_list_free (acl); \
118 WARN ("acl validity check failed."); \
119 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_PERMISSION_DENIED, "invalid access control list"); \
125 _set_id (GSignondIdentity *identity, guint32 id)
127 gsignond_identity_info_set_id (identity->priv->info, id);
128 g_object_notify_by_pspec (G_OBJECT(identity), properties[PROP_INFO]);
134 _get_property (GObject *object, guint property_id, GValue *value,
137 GSignondIdentity *self = GSIGNOND_IDENTITY (object);
142 g_value_set_boxed (value, self->priv->info);
145 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
150 _set_property (GObject *object, guint property_id, const GValue *value,
153 GSignondIdentity *self = GSIGNOND_IDENTITY (object);
159 (GSignondIdentityInfo *)g_value_get_boxed (value);
162 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
167 _release_weak_ref_on_session (gpointer key, gpointer value, gpointer data)
169 GObject *session = G_OBJECT (value);
170 g_signal_handlers_disconnect_by_func (session, G_CALLBACK (_on_user_action_required), data);
171 g_signal_handlers_disconnect_by_func (session, G_CALLBACK (_on_store_token), data);
172 g_object_weak_unref (session, _on_session_dead, data);
176 _dispose (GObject *object)
178 GSignondIdentity *self = GSIGNOND_IDENTITY(object);
180 if (self->priv->auth_sessions) {
181 g_hash_table_foreach (self->priv->auth_sessions, _release_weak_ref_on_session, self);
182 g_hash_table_unref (self->priv->auth_sessions);
183 self->priv->auth_sessions = NULL;
186 if (self->priv->owner) {
187 DBG("unref owner %p", self->priv->owner);
188 g_object_unref (self->priv->owner);
189 self->priv->owner = NULL;
192 if (self->priv->info) {
193 gsignond_identity_info_unref (self->priv->info);
194 self->priv->info = NULL;
197 G_OBJECT_CLASS (gsignond_identity_parent_class)->dispose (object);
201 _finalize (GObject *object)
203 G_OBJECT_CLASS (gsignond_identity_parent_class)->finalize (object);
207 gsignond_identity_init (GSignondIdentity *self)
209 self->priv = GSIGNOND_IDENTITY_PRIV(self);
211 self->priv->auth_sessions = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
215 gsignond_identity_class_init (GSignondIdentityClass *klass)
217 GObjectClass* object_class = G_OBJECT_CLASS (klass);
219 g_type_class_add_private (object_class, sizeof (GSignondIdentityPrivate));
221 object_class->get_property = _get_property;
222 object_class->set_property = _set_property;
223 object_class->dispose = _dispose;
224 object_class->finalize = _finalize;
226 properties[PROP_INFO] =
227 g_param_spec_boxed ("info",
229 "IdentityInfo structure",
230 GSIGNOND_TYPE_IDENTITY_INFO,
231 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
232 G_PARAM_STATIC_STRINGS);
234 g_object_class_install_properties (object_class, N_PROPERTIES, properties);
236 signals[SIG_USER_VERIFIED] = g_signal_new ("user-verified",
237 GSIGNOND_TYPE_IDENTITY,
248 signals[SIG_SECRET_VERIFIED] = g_signal_new ("secret-verified",
249 GSIGNOND_TYPE_IDENTITY,
260 signals[SIG_CREDENTIALS_UPDATED] = g_signal_new ("credentials-updated",
261 GSIGNOND_TYPE_IDENTITY,
272 signals[SIG_INFO_UPDATED] = g_signal_new ("info-updated",
273 GSIGNOND_TYPE_IDENTITY,
281 GSIGNOND_TYPE_IDENTITY_CHANGE_TYPE);
286 gsignond_identity_get_info (GSignondIdentity *identity, const GSignondSecurityContext *ctx, GError **error)
288 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
289 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
290 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
294 GSignondIdentityInfo *info = NULL;
295 GVariant *vinfo = NULL;
297 if (!identity->priv->info) {
298 WARN ("assertion (identity->priv->info) failed");
299 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Identity not found.");
303 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, NULL);
305 info = gsignond_identity_info_copy (identity->priv->info);
307 /* remove password */
308 gsignond_identity_info_remove_secret (info);
310 /* remove username if its secret */
311 if (gsignond_identity_info_get_is_username_secret (info))
312 gsignond_identity_info_remove_username (info);
314 /* prepare identity info, excluding password and username if secret */
315 vinfo = gsignond_dictionary_to_variant (identity->priv->info);
316 gsignond_identity_info_unref (info);
318 WARN ("identity info to variant convertion failed.");
319 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Identity internal eror.");
327 _on_dialog_refreshed (GError *error, gpointer user_data)
329 GSignondIdentityCbData *cb_data = (GSignondIdentityCbData *)user_data;
331 g_signal_handlers_disconnect_by_func(cb_data->session, _on_refresh_dialog, user_data);
333 WARN ("Error : %s", error->message);
334 g_error_free (error);
339 _on_refresh_dialog (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata)
341 GSignondIdentityCbData *cb_data = (GSignondIdentityCbData *) userdata;
343 if (!gsignond_daemon_refresh_dialog (GSIGNOND_DAEMON (cb_data->identity->priv->owner),
344 G_OBJECT (cb_data->session), ui_data, _on_dialog_refreshed, userdata)) {
345 WARN ("Dialog Refresh Failed");
350 _on_refresh_requested_by_ui (GSignondSignonuiData *ui_data, gpointer user_data)
352 GSignondIdentityCbData *cb_data = (GSignondIdentityCbData *) user_data;
354 /* check for dialog refresh requests */
355 g_signal_connect (cb_data->session, "process-refreshed", G_CALLBACK (_on_refresh_dialog), cb_data);
356 gsignond_auth_session_refresh (cb_data->session, ui_data);
360 _on_user_action_completed (GSignondSignonuiData *reply, GError *error, gpointer user_data)
362 GSignondIdentityCbData *cb_data = (GSignondIdentityCbData *) user_data;
363 GSignondIdentityPrivate *priv = GSIGNOND_IDENTITY_PRIV (cb_data->identity);
364 GSignondSignonuiError ui_error = SIGNONUI_ERROR_NONE;
366 g_return_if_fail (cb_data && GSIGNOND_IS_AUTH_SESSION (cb_data->session));
368 g_signal_handlers_disconnect_by_func(cb_data->session, _on_refresh_dialog, user_data);
369 g_signal_handlers_disconnect_by_func(cb_data->session, _on_process_canceled, user_data);
372 WARN ("UI-Error: %s on identity %d",
374 gsignond_identity_info_get_id (priv->info));
375 if (cb_data->session) {
376 GSignondSignonuiData *reply = gsignond_signonui_data_new();
377 gsignond_signonui_data_set_query_error (reply, SIGNONUI_ERROR_GENERAL);
378 gsignond_auth_session_user_action_finished (cb_data->session, reply);
379 gsignond_signonui_data_unref(reply);
381 g_error_free (error);
382 g_slice_free (GSignondIdentityCbData, cb_data);
386 if (gsignond_signonui_data_get_query_error (reply, &ui_error)
387 && ui_error != SIGNONUI_ERROR_NONE) {
388 WARN ("signonui error %d for identity %d",
389 ui_error, gsignond_identity_info_get_id (priv->info));
392 if (!gsignond_identity_info_get_validated (priv->info) &&
393 ui_error == SIGNONUI_ERROR_NONE) {
394 gsignond_identity_info_set_username (priv->info,
395 gsignond_signonui_data_get_username (reply));
398 /* storing secret allowed? */
399 if (gsignond_identity_info_get_store_secret (priv->info)) {
400 gboolean remember = TRUE;
402 /* and there was no opt-out? */
403 if (!gsignond_signonui_data_get_remember_password (reply, &remember))
404 DBG ("identity %d - don't remember password",
405 gsignond_identity_info_get_id (priv->info));
406 if (remember && ui_error == SIGNONUI_ERROR_NONE) {
407 gsignond_identity_info_set_secret (priv->info,
408 gsignond_signonui_data_get_password (reply));
409 } else if (!remember ||
410 (ui_error == SIGNONUI_ERROR_CANCELED ||
411 ui_error == SIGNONUI_ERROR_FORGOT_PASSWORD)) {
412 /* reset to empty in case user canceled or forgot,
413 * or doesn't want password to be remebered anymore */
414 gsignond_identity_info_set_secret (priv->info, "");
417 /* TODO: auto-set to validated on successful process() cycle */
418 /* store if not a new identity (new is stored later) */
419 if (!gsignond_identity_info_get_is_identity_new (priv->info)) {
420 if (!gsignond_daemon_store_identity (priv->owner, cb_data->identity))
421 WARN ("failed to update identity %d",
422 gsignond_identity_info_get_id (priv->info));
425 if (cb_data->session) {
426 gsignond_auth_session_user_action_finished (cb_data->session, reply);
429 g_slice_free (GSignondIdentityCbData, cb_data);
433 _on_process_canceled (GSignondAuthSession *session, GSignondIdentityCbData *cb_data)
435 g_signal_handlers_disconnect_by_func(session, G_CALLBACK(_on_process_canceled), cb_data);
438 WARN ("assert (cb_data)");
441 if (!gsignond_daemon_cancel_dialog (
442 cb_data->identity->priv->owner, G_OBJECT(session), NULL, NULL)) {
443 WARN ("Fail to cancel dialog");
445 g_slice_free (GSignondIdentityCbData, cb_data);
449 _on_user_action_required (GSignondAuthSession *session, GSignondSignonuiData *ui_data, gpointer userdata)
451 GSignondIdentity *identity = GSIGNOND_IDENTITY (userdata);
452 GSignondIdentityCbData *cb_data = g_slice_new (GSignondIdentityCbData);
454 cb_data->identity = identity;
455 cb_data->session = session;
457 gsignond_daemon_show_dialog (GSIGNOND_DAEMON (identity->priv->owner), G_OBJECT(session),
458 ui_data, _on_user_action_completed, _on_refresh_requested_by_ui, cb_data);
460 g_signal_connect (session, "process-canceled", G_CALLBACK(_on_process_canceled), cb_data);
464 _on_store_token (GSignondAuthSession *session, GSignondDictionary *token_data, gpointer userdata)
466 GSignondIdentity *identity = GSIGNOND_IDENTITY (userdata);
467 guint32 identity_id = GSIGNOND_IDENTITY_INFO_NEW_IDENTITY;
469 g_return_if_fail (identity && session && GSIGNOND_IS_AUTH_SESSION (session));
471 identity_id = gsignond_identity_info_get_id (identity->priv->info);
473 if (identity_id != GSIGNOND_IDENTITY_INFO_NEW_IDENTITY) {
474 gsignond_daemon_store_identity_data (identity->priv->owner, identity_id,
475 gsignond_auth_session_get_method (session), token_data);
480 _compare_session_by_pointer (gpointer key, gpointer value, gpointer dead_object)
482 return value == dead_object;
486 _on_session_close (gpointer data, GObject *session)
488 GSignondIdentity *identity = GSIGNOND_IDENTITY (data);
490 DBG ("identity %p session %p disposed", identity, session);
492 g_hash_table_foreach_remove (identity->priv->auth_sessions,
493 _compare_session_by_pointer, session);
496 GSignondAuthSession *
497 gsignond_identity_get_auth_session (GSignondIdentity *identity,
499 const GSignondSecurityContext *ctx,
502 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
503 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
504 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
507 GSignondAuthSession *session = NULL;
508 GHashTable *supported_methods = NULL;
509 gboolean method_available = FALSE;
510 guint32 identity_id ;
511 GSignondDictionary *token_data = NULL;
513 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, NULL);
516 WARN ("assertion (method) failed");
517 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_METHOD_NOT_KNOWN,
518 "authentication method not provided");
522 DBG ("get auth session for method '%s'", method);
523 session = g_hash_table_lookup (identity->priv->auth_sessions, method);
525 if (session && GSIGNOND_IS_AUTH_SESSION (session)) {
526 DBG("using cashed auth session '%p' for method '%s'", session, method);
527 return GSIGNOND_AUTH_SESSION(g_object_ref (session));
530 if (!gsignond_plugin_proxy_factory_get_plugin_mechanisms (gsignond_get_plugin_proxy_factory (),
532 WARN ("method '%s' doesn't exist", method);
533 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_METHOD_NOT_KNOWN,
534 "authentication method '%s' doesn't exist",
539 supported_methods = gsignond_identity_info_get_methods (identity->priv->info);
541 if (supported_methods) {
542 method_available = g_hash_table_contains (supported_methods, method);
543 g_hash_table_unref (supported_methods);
544 } else if (gsignond_identity_info_get_is_identity_new (
545 identity->priv->info))
546 method_available = TRUE;
548 method_available = FALSE;
551 if (!method_available) {
552 WARN ("authentication method '%s' is not supported", method);
553 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_METHOD_NOT_AVAILABLE,
554 "authentication method '%s' not supported for this identity", method);
558 if ( (identity_id = gsignond_identity_info_get_id (identity->priv->info)) !=
559 GSIGNOND_IDENTITY_INFO_NEW_IDENTITY) {
560 token_data = gsignond_daemon_load_identity_data (identity->priv->owner, identity_id, method);
562 if (!token_data) token_data = gsignond_dictionary_new();
564 session = gsignond_auth_session_new (identity->priv->info, method, token_data);
566 if (token_data) gsignond_dictionary_unref (token_data);
569 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
573 /* Handle 'ui' signanls on session */
574 g_signal_connect (session, "process-user-action-required", G_CALLBACK (_on_user_action_required), identity);
575 g_signal_connect (session, "process-store", G_CALLBACK (_on_store_token), identity);
577 g_hash_table_insert (identity->priv->auth_sessions, g_strdup (method), session);
578 g_object_weak_ref (G_OBJECT (session), _on_session_close, identity);
580 DBG ("session %p creation for method '%s' complete", session, method);
586 _on_credentials_updated (GSignondSignonuiData *reply, GError *error, gpointer user_data)
588 GSignondIdentity *identity = GSIGNOND_IDENTITY (user_data);
593 WARN ("failed to verify user : %s", error->message);
594 g_error_free (error);
596 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED, "Operation cancled");
600 GSignondSignonuiError err_id = SIGNONUI_ERROR_NONE;
601 gboolean res = gsignond_signonui_data_get_query_error (reply, &err_id);
604 DBG ("No error code set by UI daemon, treating as ERROR_NONE");
607 if (err_id != SIGNONUI_ERROR_NONE) {
609 case SIGNONUI_ERROR_CANCELED:
610 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED,
611 "Operation cancled");
614 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
615 "signon ui returned with error : %d", err_id);
620 const gchar *secret = gsignond_signonui_data_get_password (reply);
623 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
624 "Server internal error occured");
625 } else if (identity->priv->info) {
626 gsignond_identity_info_set_secret (identity->priv->info, secret) ;
628 /* Save new secret in db */
629 id = gsignond_daemon_store_identity (identity->priv->owner, identity);
630 if (!id) err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_STORE_FAILED, "Failed to store secret");
635 g_signal_emit (identity, signals[SIG_CREDENTIALS_UPDATED], 0 , id, err);
637 if (err) g_error_free (err);
641 gsignond_identity_request_credentials_update (GSignondIdentity *identity,
642 const gchar *message,
643 const GSignondSecurityContext *ctx,
646 GSignondSignonuiData *ui_data = NULL;
648 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
649 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
650 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
654 if (!identity->priv->info) {
655 WARN ("assertion (identity->priv->info) failed");
656 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Identity not found.");
660 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, FALSE);
662 if (!gsignond_identity_info_get_store_secret (identity->priv->info)) {
663 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_CREDENTIALS_NOT_AVAILABLE, "Password can not be stored.");
667 ui_data = gsignond_signonui_data_new ();
669 gsignond_signonui_data_set_query_password (ui_data, TRUE);
670 gsignond_signonui_data_set_username (ui_data, gsignond_identity_info_get_username (identity->priv->info));
671 gsignond_signonui_data_set_caption (ui_data, gsignond_identity_info_get_caption (identity->priv->info));
672 gsignond_signonui_data_set_message (ui_data, message);
674 gsignond_daemon_show_dialog (GSIGNOND_DAEMON (identity->priv->owner), G_OBJECT(identity),
675 ui_data, _on_credentials_updated, NULL, identity);
677 gsignond_signonui_data_unref (ui_data);
683 _on_user_verified (GSignondSignonuiData *reply, GError *error, gpointer user_data)
685 GSignondIdentity *identity = GSIGNOND_IDENTITY (user_data);
686 gboolean res = FALSE;
690 WARN ("failed to verify user : %s", error->message);
691 g_error_free (error);
693 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED, "Operation cancled");
697 GSignondSignonuiError err_id = SIGNONUI_ERROR_NONE;
698 gboolean res = gsignond_signonui_data_get_query_error (reply, &err_id);
700 DBG ("No error code set by UI daemon, treating as ERROR_NONE");
702 if (err_id != SIGNONUI_ERROR_NONE) {
704 case SIGNONUI_ERROR_CANCELED:
705 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_OPERATION_CANCELED,
706 "Operation cancled");
708 case SIGNONUI_ERROR_FORGOT_PASSWORD:
709 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_FORGOT_PASSWORD, "Forgot password");
712 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
713 "signon ui returned error : %d", err_id);
718 const gchar *secret = gsignond_signonui_data_get_password (reply);
721 err = gsignond_get_gerror_for_id (GSIGNOND_ERROR_INTERNAL_SERVER,
722 "Server internal error occured");
723 } else if (identity->priv->info) {
724 res = g_strcmp0 (secret, gsignond_identity_info_get_secret
725 (identity->priv->info)) == 0;
730 g_signal_emit (identity, signals[SIG_USER_VERIFIED], 0, res, err);
732 if (err) g_error_free (err);
736 gsignond_identity_verify_user (GSignondIdentity *identity,
738 const GSignondSecurityContext *ctx,
741 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
742 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) == 0) failed");
743 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
746 const gchar *passwd = 0;
747 GSignondSignonuiData *ui_data = NULL;
749 if (!identity->priv->info) {
750 WARN ("assertion (identity->priv->info) failed");
751 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_IDENTITY_ERR, "Identity not found.");
755 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, FALSE);
757 if (!gsignond_identity_info_get_store_secret (identity->priv->info) ||
758 !(passwd = gsignond_identity_info_get_secret (identity->priv->info)) ||
760 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_CREDENTIALS_NOT_AVAILABLE,
761 "user can not be verified as credentials are not stored");
765 ui_data = gsignond_signonui_data_new_from_variant (params);
766 gsignond_signonui_data_set_query_password (ui_data, TRUE);
767 gsignond_signonui_data_set_username (ui_data, gsignond_identity_info_get_username (identity->priv->info));
768 gsignond_signonui_data_set_caption (ui_data, gsignond_identity_info_get_caption (identity->priv->info));
770 gsignond_daemon_show_dialog (GSIGNOND_DAEMON (identity->priv->owner), G_OBJECT (identity),
771 ui_data, _on_user_verified, NULL, identity);
773 gsignond_signonui_data_unref (ui_data);
779 gsignond_identity_verify_secret (GSignondIdentity *identity,
781 const GSignondSecurityContext *ctx,
784 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
785 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
786 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
790 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, FALSE);
792 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Not supported");
798 gsignond_identity_sign_out (GSignondIdentity *identity,
799 const GSignondSecurityContext *ctx,
802 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
803 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
804 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
807 gboolean success = FALSE;
808 guint32 identity_id = GSIGNOND_IDENTITY_INFO_NEW_IDENTITY;
810 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, FALSE);
812 identity_id = gsignond_identity_info_get_id (identity->priv->info);
814 if (identity_id == GSIGNOND_IDENTITY_INFO_NEW_IDENTITY) {
815 /* TODO; clear the cached secret for unstored identity */
819 success = gsignond_daemon_clear_identity_data (identity->priv->owner, identity_id);
822 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Failed to clear data");
826 g_signal_emit (identity, signals[SIG_INFO_UPDATED], 0, GSIGNOND_IDENTITY_SIGNED_OUT, NULL);
832 GSignondDaemon *daemon;
834 }_StoreCachedTokenCbInfo;
836 _store_cached_token_data (const gchar *method, GSignondAuthSession *session, _StoreCachedTokenCbInfo *data)
838 if (!data || !method || !session) return ;
840 GSignondDictionary *token_data = gsignond_auth_session_get_token_data (session);
843 gsignond_daemon_store_identity_data (data->daemon, data->identity_id, method, token_data);
847 gsignond_identity_store (GSignondIdentity *identity,
848 const GVariant *info,
849 const GSignondSecurityContext *ctx,
852 GSignondIdentityInfo *identity_info = NULL;
853 gboolean was_new_identity = FALSE;
854 GSignondSecurityContextList *contexts = NULL;
855 GSignondSecurityContext *owner = NULL;
858 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
859 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
860 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
864 VALIDATE_IDENTITY_WRITE_ACCESS (identity, ctx, 0);
866 identity_info = gsignond_dictionary_new_from_variant ((GVariant *)info);
867 /* dont trust 'identity id' passed via 'info' */
868 id = gsignond_identity_info_get_id (identity->priv->info);
869 gsignond_identity_info_set_id (identity_info, id);
871 was_new_identity = gsignond_identity_info_get_is_identity_new (identity_info);
873 contexts = gsignond_identity_info_get_access_control_list (identity_info);
875 contexts = gsignond_identity_info_get_access_control_list (identity->priv->info);
876 gsignond_identity_info_set_access_control_list (identity_info, contexts);
879 VALIDATE_IDENTITY_WRITE_ACL (identity, ctx, 0);
881 gsignond_security_context_list_free (contexts);
883 owner = gsignond_identity_info_get_owner (identity_info);
885 owner = gsignond_identity_info_get_owner (identity->priv->info);
886 gsignond_identity_info_set_owner (identity_info, owner);
888 gsignond_security_context_free (owner);
891 /* update object cache */
892 if (identity->priv->info)
893 gsignond_identity_info_unref (identity->priv->info);
894 identity->priv->info = identity_info;
896 /* Ask daemon to store identity info to db */
897 id = gsignond_daemon_store_identity (identity->priv->owner, identity);
899 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_STORE_FAILED,
900 "Failed to store identity");
903 if (was_new_identity) {
904 _set_id (identity, id);
905 _StoreCachedTokenCbInfo data = { identity->priv->owner, id };
906 /* store any cached token data if available at auth sessions */
907 g_hash_table_foreach (identity->priv->auth_sessions, (GHFunc)_store_cached_token_data, (gpointer)&data);
910 g_signal_emit (identity, signals[SIG_INFO_UPDATED], 0, GSIGNOND_IDENTITY_DATA_UPDATED);
917 gsignond_identity_remove (GSignondIdentity *identity,
918 const GSignondSecurityContext *ctx,
921 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
922 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
923 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
926 gboolean is_removed = FALSE;
928 VALIDATE_IDENTITY_WRITE_ACCESS (identity, ctx, FALSE);
930 is_removed = gsignond_identity_clear (identity);
932 if (!is_removed && error)
933 *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_REMOVE_FAILED, "failed to remove identity");
940 gsignond_identity_clear (GSignondIdentity *identity)
942 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
943 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
946 gboolean is_removed = FALSE;
948 if (gsignond_identity_info_get_is_identity_new (identity->priv->info))
951 is_removed = gsignond_daemon_remove_identity (
952 identity->priv->owner,
953 gsignond_identity_info_get_id (identity->priv->info));
956 g_signal_emit (identity, signals[SIG_INFO_UPDATED], 0, GSIGNOND_IDENTITY_REMOVED);
958 WARN ("request to remove identity %u failed",
959 gsignond_identity_info_get_id (identity->priv->info));
966 gsignond_identity_add_reference (GSignondIdentity *identity,
967 const gchar *reference,
968 const GSignondSecurityContext *ctx,
971 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
972 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
973 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
977 guint32 identity_id = 0;
979 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, 0);
981 identity_id = gsignond_identity_info_get_id (identity->priv->info);
983 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_STORE_FAILED, "Cannot add reference to unsaved identity");
986 res = gsignond_daemon_add_identity_reference (identity->priv->owner, identity_id, ctx, reference);
989 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
996 gsignond_identity_remove_reference (GSignondIdentity *identity,
997 const gchar *reference,
998 const GSignondSecurityContext *ctx,
1001 if (!(identity && GSIGNOND_IS_IDENTITY (identity))) {
1002 WARN ("assertion (identity && GSIGNOND_IS_IDENTITY(identity)) failed");
1003 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_UNKNOWN, "Unknown error");
1008 guint32 identity_id = 0;
1010 VALIDATE_IDENTITY_READ_ACCESS (identity, ctx, 0);
1012 identity_id = gsignond_identity_info_get_id (identity->priv->info);
1014 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_REFERENCE_NOT_FOUND, "reference not '%s' found", reference);
1018 res = gsignond_daemon_remove_identity_reference (identity->priv->owner, identity_id, ctx, reference);
1020 if (error) *error = gsignond_get_gerror_for_id (GSIGNOND_ERROR_REFERENCE_NOT_FOUND,
1021 "reference '%s' not found", reference);
1026 GSignondAccessControlManager *
1027 gsignond_identity_get_acm (GSignondIdentity *identity)
1029 g_return_val_if_fail (identity && GSIGNOND_IS_IDENTITY(identity), NULL);
1031 return gsignond_daemon_get_access_control_manager (identity->priv->owner);
1035 gsignond_identity_get_auth_session_timeout (GSignondIdentity *identity)
1037 g_return_val_if_fail (identity && GSIGNOND_IS_IDENTITY(identity), 0);
1039 return gsignond_daemon_get_auth_session_timeout (identity->priv->owner);
1043 * gsignond_identity_get_id:
1044 * @identity: instance of #GSignondIdentity
1046 * Retrieves identity id.
1048 * Returns: identity id
1051 gsignond_identity_get_id (GSignondIdentity *identity)
1053 g_assert (GSIGNOND_IS_IDENTITY (identity));
1055 return gsignond_identity_info_get_id (identity->priv->info);
1059 * gsignond_identity_get_identity_info:
1060 * @identity: instance of #GSignondIdentity
1062 * Retrieves identity's #GSignondIdentityInfo.
1064 * Returns: (transfer none) #GSignondIdentityInfo
1066 GSignondIdentityInfo *
1067 gsignond_identity_get_identity_info (GSignondIdentity *identity)
1069 g_assert (GSIGNOND_IS_IDENTITY (identity));
1070 g_assert (identity->priv != NULL);
1072 return identity->priv->info;
1076 * gsignond_identity_new:
1077 * @owner: Owner of this object, instance of #GSignondAuthServiceIface
1078 * @info (transfer full): Identity info, instance of #GSignondIdentityInfo
1080 * Creates new instance of #GSignondIdentity
1082 * Returns[transfer full]: new instance of #GSignondIdentity
1084 GSignondIdentity * gsignond_identity_new (GSignondDaemon *owner,
1085 GSignondIdentityInfo *info)
1087 GSignondIdentity *identity =
1088 GSIGNOND_IDENTITY(g_object_new (GSIGNOND_TYPE_IDENTITY,
1092 identity->priv->owner = g_object_ref (owner);