Refresh upstream 2.1.0 release
[profile/ivi/libgsignon-glib.git] / libgsignon-glib / signon-identity-info.c
1 /* vi: set et sw=4 ts=4 cino=t0,(0: */
2 /* -*- Mode: C; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 /*
4  * This file is part of libgsignon-glib
5  *
6  * Copyright (C) 2009-2010 Nokia Corporation.
7  * Copyright (C) 2011-2012 Canonical Ltd.
8  * Copyright (C) 2012-2014 Intel Corporation.
9  *
10  * Contact: Alberto Mardegan <alberto.mardegan@canonical.com>
11  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
12  *
13  * This library is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU Lesser General Public License
15  * version 2.1 as published by the Free Software Foundation.
16  *
17  * This library is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20  * Lesser General Public License for more details.
21  *
22  * You should have received a copy of the GNU Lesser General Public
23  * License along with this library; if not, write to the Free Software
24  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25  * 02110-1301 USA
26  */
27
28 /**
29  * SECTION:signon-identity-info
30  * @title: SignonIdentityInfo
31  * @short_description: data contained in a SignonIdentity.
32  *
33  * #SignonIdentityInfo represents data contained in a database record for an identity
34  * and provides getters and setters for individual items.
35  * 
36  * See #SignonIdentity for a detailed discussion
37  * of what each item means and how and when it's used. 
38  */
39
40 #include "signon-identity-info.h"
41
42 #include "signon-internals.h"
43 #include "signon-utils.h"
44
45 G_DEFINE_BOXED_TYPE (SignonIdentityInfo, signon_identity_info,
46                      (GBoxedCopyFunc)signon_identity_info_copy,
47                      (GBoxedFreeFunc)signon_identity_info_free);
48
49
50 static GVariant *
51 signon_variant_new_string (const gchar *string)
52 {
53     return g_variant_new_string (string != NULL ? string : "");
54 }
55
56 static const gchar *identity_info_get_secret (const SignonIdentityInfo *info)
57 {
58     g_return_val_if_fail (info != NULL, NULL);
59
60     return info->secret;
61 }
62
63 static void identity_info_set_id (SignonIdentityInfo *info, gint id)
64 {
65     g_return_if_fail (info != NULL);
66     g_return_if_fail (id >= 0);
67
68     info->id = id;
69 }
70
71 static void identity_methods_copy (gpointer key,
72                                    gpointer value,
73                                    gpointer user_data)
74 {
75     g_hash_table_insert ((GHashTable *) user_data,
76                          g_strdup ((const gchar *) key),
77                          g_strdupv ((gchar **) value));
78 }
79
80 /**
81  * signon_identity_info_set_methods:
82  * @info: the #SignonIdentityInfo.
83  * @methods: (transfer none): (element-type utf8 GStrv): methods.
84  *
85  * Set authentication methods that are allowed to be used with this identity.
86  */
87 void signon_identity_info_set_methods (SignonIdentityInfo *info,
88                                        GHashTable *methods)
89 {
90     g_return_if_fail (info != NULL);
91     g_return_if_fail (methods != NULL);
92
93     DEBUG("%s", G_STRFUNC);
94
95     GHashTable *new_methods =
96         g_hash_table_new_full (g_str_hash,
97                                g_str_equal,
98                                g_free,
99                                (GDestroyNotify) g_strfreev);
100     g_hash_table_foreach (methods, identity_methods_copy, new_methods);
101     g_hash_table_unref (info->methods);
102     info->methods = new_methods;
103 }
104
105 /**
106  * signon_identity_info_own_methods:
107  * @info: the #SignonIdentityInfo.
108  * @methods: (transfer none): (element-type utf8 GStrv): methods.
109  *
110  * Set authentication methods that are allowed to be used with this identity.
111  *
112  * This function will just increment reference count of hash table, so
113  * it should be constructed with #g_hash_table_new_full.
114  */
115 void signon_identity_info_own_methods (SignonIdentityInfo *info,
116                                        GHashTable *methods)
117 {
118     g_return_if_fail (info != NULL);
119     g_return_if_fail (methods != NULL);
120
121     DEBUG("%s", G_STRFUNC);
122
123     g_hash_table_ref (methods);
124     info->methods = methods;
125 }
126
127 SignonIdentityInfo *
128 signon_identity_info_new_from_variant (GVariant *variant)
129 {
130     GVariant *method_map;
131     GVariant *owner;
132     GVariant *acl;
133
134     if (!variant)
135         return NULL;
136
137     SignonIdentityInfo *info = signon_identity_info_new ();
138
139     DEBUG("%s: ", G_STRFUNC);
140
141     g_variant_lookup (variant,
142                       SIGNOND_IDENTITY_INFO_ID,
143                       "u",
144                       &info->id);
145
146     g_variant_lookup (variant,
147                       SIGNOND_IDENTITY_INFO_USERNAME,
148                       "s",
149                       &info->username);
150
151     g_variant_lookup (variant,
152                       SIGNOND_IDENTITY_INFO_SECRET,
153                       "s",
154                       &info->secret);
155
156     g_variant_lookup (variant,
157                       SIGNOND_IDENTITY_INFO_STORESECRET,
158                       "b",
159                       &info->store_secret);
160
161     g_variant_lookup (variant,
162                       SIGNOND_IDENTITY_INFO_CAPTION,
163                       "s",
164                       &info->caption);
165
166     g_variant_lookup (variant,
167                       SIGNOND_IDENTITY_INFO_REALMS,
168                       "^as",
169                       &info->realms);
170
171     /* get the methods */
172     if (g_variant_lookup (variant,
173                           SIGNOND_IDENTITY_INFO_AUTHMETHODS,
174                           "@a{sas}",
175                           &method_map))
176     {
177         GVariantIter iter;
178         gchar *method;
179         gchar **mechanisms;
180
181         g_variant_iter_init (&iter, method_map);
182         while (g_variant_iter_next (&iter, "{s^as}", &method, &mechanisms))
183         {
184             g_hash_table_insert (info->methods, method, mechanisms);
185         }
186         g_variant_unref (method_map);
187     }
188
189     if (g_variant_lookup (variant,
190                       SIGNOND_IDENTITY_INFO_OWNER,
191                       "@(ss)",
192                       &owner))
193     {
194         info->owner = signon_security_context_deconstruct_variant (owner);
195         g_variant_unref (owner);
196     }
197
198     if (g_variant_lookup (variant,
199                           SIGNOND_IDENTITY_INFO_ACL,
200                           "@a(ss)",
201                           &acl))
202     {
203         info->access_control_list =
204             signon_security_context_list_deconstruct_variant (acl);
205         g_variant_unref (acl);
206     }
207
208     g_variant_lookup (variant,
209                       SIGNOND_IDENTITY_INFO_TYPE,
210                       "u",
211                       &info->type);
212
213     return info;
214 }
215
216 GVariant *
217 signon_identity_info_to_variant (const SignonIdentityInfo *self)
218 {
219     GVariantBuilder builder;
220     GVariantBuilder method_builder;
221     GVariant *method_map;
222     GHashTableIter iter;
223     const gchar *method;
224     const gchar **mechanisms;
225
226     g_variant_builder_init (&builder, G_VARIANT_TYPE_VARDICT);
227
228     g_variant_builder_add (&builder, "{sv}",
229                            SIGNOND_IDENTITY_INFO_ID,
230                            g_variant_new_uint32 (self->id));
231
232     if (self->username != NULL) {
233         g_variant_builder_add (&builder, "{sv}",
234                                SIGNOND_IDENTITY_INFO_USERNAME,
235                                signon_variant_new_string (self->username));
236     }
237
238     if (self->secret != NULL) {
239         g_variant_builder_add (&builder, "{sv}",
240                                SIGNOND_IDENTITY_INFO_SECRET,
241                                signon_variant_new_string (self->secret));
242     }
243
244     if (self->caption != NULL) {
245         g_variant_builder_add (&builder, "{sv}",
246                                SIGNOND_IDENTITY_INFO_CAPTION,
247                                signon_variant_new_string (self->caption));
248     }
249
250     g_variant_builder_add (&builder, "{sv}",
251                            SIGNOND_IDENTITY_INFO_STORESECRET,
252                            g_variant_new_boolean (self->store_secret));
253
254     if (g_hash_table_size(self->methods) > 0) {
255         g_variant_builder_init (&method_builder,
256                                 (const GVariantType *)"a{sas}");
257         g_hash_table_iter_init (&iter, self->methods);
258         while (g_hash_table_iter_next (&iter,
259                                        (gpointer)&method,
260                                        (gpointer)&mechanisms))
261         {
262             g_variant_builder_add (&method_builder, "{s^as}",
263                                    method,
264                                    mechanisms);
265         }
266         method_map = g_variant_builder_end (&method_builder);
267
268         g_variant_builder_add (&builder, "{sv}",
269                                SIGNOND_IDENTITY_INFO_AUTHMETHODS,
270                                method_map);
271     }
272
273     if (self->realms != NULL)
274     {
275         g_variant_builder_add (&builder, "{sv}",
276                                SIGNOND_IDENTITY_INFO_REALMS,
277                                g_variant_new_strv ((const gchar * const *)
278                                                    self->realms,
279                                                    -1));
280     }
281
282     if (self->owner != NULL)
283     {
284         g_variant_builder_add (&builder, "{sv}",
285                                SIGNOND_IDENTITY_INFO_OWNER,
286                                signon_security_context_build_variant (
287                                                                   self->owner));
288     }
289
290     if (self->access_control_list != NULL)
291     {
292         g_variant_builder_add (&builder, "{sv}",
293                                SIGNOND_IDENTITY_INFO_ACL,
294                                signon_security_context_list_build_variant (
295                                                     self->access_control_list));
296     }
297
298     g_variant_builder_add (&builder, "{sv}",
299                            SIGNOND_IDENTITY_INFO_TYPE,
300                            g_variant_new_int32 (self->type));
301
302     return g_variant_builder_end (&builder);
303 }
304
305 /*
306  * Public methods:
307  */
308
309 /**
310  * signon_identity_info_new:
311  *
312  * Creates a new #SignonIdentityInfo item.
313  *
314  * Returns: a new #SignonIdentityInfo item.
315  */
316 SignonIdentityInfo *signon_identity_info_new ()
317 {
318     SignonIdentityInfo *info = g_slice_new0 (SignonIdentityInfo);
319     info->methods = g_hash_table_new_full (g_str_hash,
320                                            g_str_equal,
321                                            g_free,
322                                            (GDestroyNotify) g_strfreev);
323     info->store_secret = FALSE;
324
325     return info;
326 }
327
328 /**
329  * signon_identity_info_free:
330  * @info: the #SignonIdentityInfo.
331  *
332  * Destroys the given #SignonIdentityInfo item.
333  */
334 void signon_identity_info_free (SignonIdentityInfo *info)
335 {
336     if (info == NULL) return;
337
338     g_free (info->username);
339     g_free (info->secret);
340     g_free (info->caption);
341
342     g_hash_table_unref (info->methods);
343
344     g_strfreev (info->realms);
345     signon_security_context_free (info->owner);
346     signon_security_context_list_free (info->access_control_list);
347
348     g_slice_free (SignonIdentityInfo, info);
349 }
350
351 /**
352  * signon_identity_info_copy:
353  * @other: the #SignonIdentityInfo.
354  *
355  * Get a newly-allocated copy of @info.
356  *
357  * Returns: a copy of the given #SignonIdentityInfo, or %NULL on failure.
358  */
359 SignonIdentityInfo *signon_identity_info_copy (const SignonIdentityInfo *other)
360 {
361     g_return_val_if_fail (other != NULL, NULL);
362     SignonIdentityInfo *info = signon_identity_info_new ();
363
364     identity_info_set_id (info, signon_identity_info_get_id (other));
365
366     signon_identity_info_set_username (info,
367         signon_identity_info_get_username (other));
368
369     signon_identity_info_set_secret (info, identity_info_get_secret(other),
370         signon_identity_info_get_storing_secret (other));
371
372     signon_identity_info_set_caption (info,
373         signon_identity_info_get_caption(other));
374
375     signon_identity_info_set_methods (info,
376         signon_identity_info_get_methods (other));
377
378     signon_identity_info_set_realms (info,
379         signon_identity_info_get_realms (other));
380
381     signon_identity_info_set_owner (info,
382         signon_identity_info_get_owner (other));
383
384     signon_identity_info_set_access_control_list (info,
385         signon_identity_info_get_access_control_list (other));
386
387     signon_identity_info_set_identity_type (info,
388         signon_identity_info_get_identity_type (other));
389
390     return info;
391 }
392
393 /**
394  * signon_identity_info_get_id:
395  * @info: the #SignonIdentityInfo.
396  *
397  * Get the numeric identity ID of @info.
398  *
399  * Returns: the numeric ID of the identity.
400  */
401 gint signon_identity_info_get_id (const SignonIdentityInfo *info)
402 {
403     g_return_val_if_fail (info != NULL, -1);
404     return info->id;
405 }
406
407 /**
408  * signon_identity_info_get_username:
409  * @info: the #SignonIdentityInfo.
410  *
411  * Get the username associated with an identity.
412  *
413  * Returns: the username, or %NULL.
414  */
415 const gchar *signon_identity_info_get_username (const SignonIdentityInfo *info)
416 {
417     g_return_val_if_fail (info != NULL, NULL);
418     return info->username;
419 }
420
421 /**
422  * signon_identity_info_get_storing_secret:
423  * @info: the #SignonIdentityInfo.
424  *
425  * Get whether the secret of @info should be stored by gSSO in the secret database.
426  *
427  * Returns: %TRUE if gSSO must store the secret, %FALSE otherwise.
428  */
429 gboolean signon_identity_info_get_storing_secret (const SignonIdentityInfo *info)
430 {
431     g_return_val_if_fail (info != NULL, FALSE);
432     return info->store_secret;
433 }
434
435 /**
436  * signon_identity_info_get_caption:
437  * @info: the #SignonIdentityInfo.
438  *
439  * Get the display name of @info.
440  *
441  * Returns: the display name for the identity.
442  */
443 const gchar *signon_identity_info_get_caption (const SignonIdentityInfo *info)
444 {
445     g_return_val_if_fail (info != NULL, NULL);
446     return info->caption;
447 }
448
449 /**
450  * signon_identity_info_get_methods:
451  * @info: the #SignonIdentityInfo.
452  *
453  * Get a hash table of the methods and mechanisms of @info. See 
454  * signon_identity_info_set_methods().
455  *
456  * Returns: (transfer none): (element-type utf8 GStrv): the table of allowed
457  * methods and mechanisms.
458  */
459 GHashTable *signon_identity_info_get_methods (const SignonIdentityInfo *info)
460 {
461     g_return_val_if_fail (info != NULL, NULL);
462     return info->methods;
463 }
464
465 /**
466  * signon_identity_info_get_realms:
467  * @info: the #SignonIdentityInfo.
468  *
469  * Get an array of the allowed realms of @info.
470  *
471  * Returns: (transfer none): a %NULL terminated array of realms.
472  */
473 const gchar* const *signon_identity_info_get_realms (const SignonIdentityInfo *info)
474 {
475     g_return_val_if_fail (info != NULL, NULL);
476     return (const gchar* const *)info->realms;
477 }
478
479 /**
480  * signon_identity_info_get_owner:
481  * @info: the #SignonIdentityInfo.
482  *
483  * Get identity owner's security context. 
484  * 
485  * Returns: (transfer none): a security context.
486  */
487 const SignonSecurityContext *signon_identity_info_get_owner (const SignonIdentityInfo *info)
488 {
489     g_return_val_if_fail (info != NULL, NULL);
490     return info->owner;
491 }
492
493 /**
494  * signon_identity_info_get_access_control_list:
495  * @info: the #SignonIdentityInfo.
496  *
497  * Get an access control list associated with an identity. 
498  *
499  * Returns: (transfer none): a list of ACL security contexts.
500  */
501 SignonSecurityContextList *signon_identity_info_get_access_control_list (const SignonIdentityInfo *info)
502 {
503     g_return_val_if_fail (info != NULL, NULL);
504     return info->access_control_list;
505 }
506
507 /**
508  * signon_identity_info_get_identity_type:
509  * @info: the #SignonIdentityInfo.
510  *
511  * Get the type of the identity.
512  *
513  * Returns: the type of the identity.
514  */
515 SignonIdentityType signon_identity_info_get_identity_type (const SignonIdentityInfo *info)
516 {
517     g_return_val_if_fail (info != NULL, -1);
518     return (SignonIdentityType)info->type;
519 }
520
521
522 static void _replace_string (gchar **dst, const gchar *src)
523 {
524     gchar *new_str = g_strdup (src);
525     g_free (*dst);
526     *dst = new_str;
527 }
528
529 /**
530  * signon_identity_info_set_username:
531  * @info: the #SignonIdentityInfo.
532  * @username: the username.
533  *
534  * Sets the username for the identity.
535  *
536  */
537 void signon_identity_info_set_username (SignonIdentityInfo *info,
538                                         const gchar *username)
539 {
540     g_return_if_fail (info != NULL);
541
542     _replace_string (&info->username, username);
543 }
544
545 /**
546  * signon_identity_info_set_secret:
547  * @info: the #SignonIdentityInfo.
548  * @secret: the secret.
549  * @store_secret: whether signond should store the secret in its DB.
550  *
551  * Sets the secret (password) for the identity, and whether the gSSO daemon
552  * should remember it.
553  *
554  */
555 void signon_identity_info_set_secret (SignonIdentityInfo *info,
556                                       const gchar *secret,
557                                       gboolean store_secret)
558 {
559     g_return_if_fail (info != NULL);
560
561     _replace_string (&info->secret, secret);
562     info->store_secret = store_secret;
563 }
564
565 /**
566  * signon_identity_info_set_caption:
567  * @info: the #SignonIdentityInfo.
568  * @caption: the caption.
569  *
570  * Sets the caption (display name) for the identity.
571  *
572  */
573 void signon_identity_info_set_caption (SignonIdentityInfo *info,
574                                        const gchar *caption)
575 {
576     g_return_if_fail (info != NULL);
577
578     _replace_string (&info->caption, caption);
579 }
580
581 /**
582  * signon_identity_info_set_method:
583  * @info: the #SignonIdentityInfo.
584  * @method: an authentication method.
585  * @mechanisms: a %NULL-terminated list of mechanisms.
586  *
587  * Adds a method to the list of allowed authentication methods. 
588  */
589 void signon_identity_info_set_method (SignonIdentityInfo *info, const gchar *method,
590                                       const gchar* const *mechanisms)
591 {
592     g_return_if_fail (info != NULL);
593
594     g_return_if_fail (info->methods != NULL);
595     g_return_if_fail (method != NULL);
596     g_return_if_fail (mechanisms != NULL);
597
598     g_hash_table_replace (info->methods,
599                           g_strdup(method), g_strdupv((gchar **)mechanisms));
600 }
601
602 /**
603  * signon_identity_info_remove_method:
604  * @info: the #SignonIdentityInfo.
605  * @method: an authentication method.
606  *
607  * Remove @method from the list of allowed authentication methods.
608  */
609 void signon_identity_info_remove_method (SignonIdentityInfo *info, const gchar *method)
610 {
611     g_return_if_fail (info != NULL);
612     g_return_if_fail (info->methods != NULL);
613
614     g_hash_table_remove (info->methods, method);
615 }
616
617 /**
618  * signon_identity_info_set_realms:
619  * @info: the #SignonIdentityInfo.
620  * @realms: a %NULL-terminated list of realms.
621  *
622  * Specify what realms this identity can be used in. 
623  */
624 void signon_identity_info_set_realms (SignonIdentityInfo *info,
625                                       const gchar* const *realms)
626 {
627     g_return_if_fail (info != NULL);
628
629     gchar **new_realms = g_strdupv ((gchar **) realms);
630
631     if (info->realms) g_strfreev (info->realms);
632
633     info->realms = new_realms;
634 }
635
636 /**
637  * signon_identity_info_set_owner:
638  * @info: the #SignonIdentityInfo.
639  * @owner: (transfer none): a security context of owner.
640  *
641  * Set identity owner's security context. 
642  */
643 void signon_identity_info_set_owner (SignonIdentityInfo *info,
644                                      const SignonSecurityContext *owner)
645 {
646     g_return_if_fail (info != NULL);
647
648     SignonSecurityContext *new_owner = signon_security_context_copy (owner);
649
650     if (info->owner) signon_security_context_free (info->owner);
651
652     info->owner = new_owner;
653 }
654
655 /**
656  * signon_identity_info_set_owner_from_values:
657  * @info: the #SignonIdentityInfo.
658  * @system_context: owner's system context.
659  * @application_context: owner's application context.
660  *
661  * Set identity owner's security context. 
662  */
663 void signon_identity_info_set_owner_from_values (
664                                                SignonIdentityInfo *info,
665                                                const gchar *system_context,
666                                                const gchar *application_context)
667 {
668     g_return_if_fail (info != NULL &&
669                       system_context != NULL &&
670                       application_context != NULL);
671
672     if (info->owner) signon_security_context_free (info->owner);
673
674     info->owner = signon_security_context_new_from_values(system_context,
675                                                           application_context);
676 }
677
678 /**
679  * signon_identity_info_set_access_control_list:
680  * @info: the #SignonIdentityInfo.
681  * @access_control_list: (transfer none): a list of ACL security contexts.
682  *
683  * Set an access control list associated with an identity. 
684  */
685 void signon_identity_info_set_access_control_list (SignonIdentityInfo *info,
686                                  SignonSecurityContextList *access_control_list)
687 {
688     g_return_if_fail (info != NULL);
689
690     SignonSecurityContextList *new_acl =
691         signon_security_context_list_copy (access_control_list);
692
693     if (info->access_control_list)
694         signon_security_context_list_free (info->access_control_list);
695
696     info->access_control_list = new_acl;
697 }
698
699 /**
700  * signon_identity_info_access_control_list_append:
701  * @info: the #SignonIdentityInfo.
702  * @security_context: (transfer full): a security context to be appended.
703  *
704  * Appends a new #SignonSecurityContext item to the access control list.
705  */
706 void signon_identity_info_access_control_list_append (
707                                         SignonIdentityInfo *info,
708                                         SignonSecurityContext *security_context)
709 {
710     g_return_if_fail (info != NULL);
711     g_return_if_fail (security_context != NULL);
712
713     info->access_control_list = g_list_append (info->access_control_list,
714                                                security_context);
715 }
716
717 /**
718  * signon_identity_info_set_identity_type:
719  * @info: the #SignonIdentityInfo.
720  * @type: the type of the identity.
721  *
722  * Specifies the type of this identity.
723  */
724 void signon_identity_info_set_identity_type (SignonIdentityInfo *info,
725                                              SignonIdentityType type)
726 {
727     g_return_if_fail (info != NULL);
728     info->type = (gint) type;
729 }