Release 0.0.3
[profile/ivi/gsignond.git] / src / common / gsignond-security-context.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 gsignond
5  *
6  * Copyright (C) 2012 Intel Corporation.
7  *
8  * Contact: Jussi Laako <jussi.laako@linux.intel.com>
9  *
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.
14  *
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.
19  *
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
23  * 02110-1301 USA
24  */
25
26 #include "gsignond/gsignond-security-context.h"
27
28
29 /**
30  * SECTION:gsignond-security-context
31  * @title: GSignondSecurityContext
32  * @short_description: security context descriptor used in access control checks
33  * @include: gsignond/gsignond-security-context.h
34  *
35  * Security context is a string tuple of system context and application context.
36  * 
37  * System context can be a binary path, SMACK-label, or MSSF token.
38  * 
39  * Application context identifies a script or a webpage within an application,
40  * and it's used for providing access control to runtime environments (when making an access
41  * control decision requires not only a binary identifier, but also information
42  * about what the binary is doing).
43  *
44  * When an application is trying to access the gSSO service, the system context
45  * is determined by a specific #GSignondAccessControlManager instance using
46  * system services of a specific platform. Application context is set by the
47  * application itself. Then both contexts are used by #GSignondAccessControlManager
48  * to perform an access control check.
49  */
50
51 /**
52  * GSignondSecurityContext:
53  * @sys_ctx: system context
54  * @app_ctx: application context
55  * 
56  * Security context descriptor used for access control checks. System context
57  * and application context can contain a wildcard match "*" which has special
58  * meaning in gsignond_security_context_match() and
59  * gsignond_security_context_check().
60  */
61
62 /**
63  * GSignondSecurityContextList:
64  * 
65  * GList of #GSignondSecurityContext items.
66  */
67 static void
68 _security_context_free (gpointer ptr)
69 {
70     GSignondSecurityContext *ctx = (GSignondSecurityContext *) ptr;
71
72     gsignond_security_context_free (ctx);
73 }
74
75 /**
76  * gsignond_security_context_new:
77  *
78  * Allocates a new security context item. System and app context are empty strings.
79  *
80  * Returns: (transfer full): allocated #GSignondSecurityContext.
81  */
82 GSignondSecurityContext *
83 gsignond_security_context_new ()
84 {
85     GSignondSecurityContext *ctx;
86
87     ctx = g_slice_new0 (GSignondSecurityContext);
88     ctx->sys_ctx = g_strdup ("");
89     ctx->app_ctx = g_strdup ("");
90
91     return ctx;
92 }
93
94 /**
95  * gsignond_security_context_new_from_values:
96  * @system_context: system security context
97  * @application_context: application security context
98  *
99  * Allocates and initializes a new security context item.
100  *
101  * Returns: (transfer full): allocated #GSignondSecurityContext.
102  */
103 GSignondSecurityContext *
104 gsignond_security_context_new_from_values (const gchar *system_context,
105                                            const gchar *application_context)
106 {
107     GSignondSecurityContext *ctx;
108
109     g_return_val_if_fail (system_context != NULL, NULL);
110
111     ctx = g_slice_new0 (GSignondSecurityContext);
112     ctx->sys_ctx = g_strdup (system_context);
113     if (application_context)
114         ctx->app_ctx = g_strdup (application_context);
115     else
116         ctx->app_ctx = g_strdup ("");
117
118     return ctx;
119 }
120
121 /**
122  * gsignond_security_context_copy:
123  * @src_ctx: source security context to copy.
124  *
125  * Copies a security context item.
126  *
127  * Returns: (transfer full): a copy of the #GSignondSecurityContext item.
128  */
129 GSignondSecurityContext *
130 gsignond_security_context_copy (const GSignondSecurityContext *src_ctx)
131 {
132     g_return_val_if_fail (src_ctx != NULL, NULL);
133
134     return gsignond_security_context_new_from_values (src_ctx->sys_ctx,
135                                                       src_ctx->app_ctx);
136 }
137
138 /**
139  * gsignond_security_context_free:
140  * @ctx: #GSignondSecurityContext to be freed.
141  *
142  * Frees a security context item.
143  */
144 void
145 gsignond_security_context_free (GSignondSecurityContext *ctx)
146 {
147     if (ctx == NULL) return;
148
149     g_free (ctx->sys_ctx);
150     g_free (ctx->app_ctx);
151     g_slice_free (GSignondSecurityContext, ctx);
152 }
153
154 /**
155  * gsignond_security_context_set_system_context:
156  * @ctx: #GSignondSecurityContext item.
157  * @system_context: system security context.
158  *
159  * Sets the system context part of the
160  * #GSignondSecurityContext.
161  */
162 void
163 gsignond_security_context_set_system_context (GSignondSecurityContext *ctx,
164                                               const gchar *system_context)
165 {
166     g_return_if_fail (ctx != NULL);
167
168     g_free (ctx->sys_ctx);
169     ctx->sys_ctx = (system_context) ?
170         g_strdup (system_context) : g_strdup ("");
171 }
172
173 /**
174  * gsignond_security_context_get_system_context:
175  * @ctx: #GSignondSecurityContext item.
176  * 
177  * Get the system context partof the
178  * #GSignondSecurityContext.
179  *
180  * Returns: (transfer none): system context.
181  */
182 const gchar *
183 gsignond_security_context_get_system_context (
184                                              const GSignondSecurityContext *ctx)
185 {
186     g_return_val_if_fail (ctx != NULL, NULL);
187
188     return ctx->sys_ctx;
189 }
190
191 /**
192  * gsignond_security_context_set_application_context:
193  * @ctx: #GSignondSecurityContext item.
194  * @application_context: application security context.
195  *
196  * Sets the application context part of
197  * the #GSignondSecurityContext.
198  */
199 void
200 gsignond_security_context_set_application_context (
201                                                GSignondSecurityContext *ctx,
202                                                const gchar *application_context)
203 {
204     g_return_if_fail (ctx != NULL);
205
206     g_free (ctx->app_ctx);
207     ctx->app_ctx = (application_context) ?
208         g_strdup (application_context) : g_strdup ("");
209 }
210
211 /**
212  * gsignond_security_context_get_application_context:
213  * @ctx: #GSignondSecurityContext item.
214  *
215  * Get the application context part of
216  * the #GSignondSecurityContext.
217  *
218  * Returns: (transfer none): application context.
219  */
220 const gchar *
221 gsignond_security_context_get_application_context (
222                                              const GSignondSecurityContext *ctx)
223 {
224     g_return_val_if_fail (ctx != NULL, NULL);
225
226     return ctx->app_ctx;
227 }
228
229 /**
230  * gsignond_security_context_to_variant:
231  * @ctx: #GSignondSecurityContext item.
232  *
233  * Build a GVariant of type "(ss)" from a #GSignondSecurityContext item.
234  *
235  * Returns: (transfer full): GVariant construct of a #GSignondSecurityContext.
236  */
237 GVariant *
238 gsignond_security_context_to_variant (const GSignondSecurityContext *ctx)
239 {
240     GVariant *variant;
241
242     g_return_val_if_fail (ctx != NULL, NULL);
243
244     variant = g_variant_new ("(ss)",
245                              ctx->sys_ctx ? ctx->sys_ctx : "",
246                              ctx->app_ctx ? ctx->app_ctx : "");
247
248     return variant;
249 }
250
251 /**
252  * gsignond_security_context_from_variant:
253  * @variant: GVariant item with a #GSignondSecurityContext construct.
254  *
255  * Builds a #GSignondSecurityContext item from a GVariant of type "(ss)".
256  *
257  * Returns: (transfer full): #GSignondSecurityContext item.
258  */
259 GSignondSecurityContext *
260 gsignond_security_context_from_variant (GVariant *variant)
261 {
262     gchar *sys_ctx = NULL;
263     gchar *app_ctx = NULL;
264     GSignondSecurityContext *ctx;
265
266     g_return_val_if_fail (variant != NULL, NULL);
267
268     g_variant_get (variant, "(ss)", &sys_ctx, &app_ctx);
269     ctx = gsignond_security_context_new_from_values (sys_ctx, app_ctx);
270     g_free (sys_ctx);
271     g_free (app_ctx);
272     return ctx;
273 }
274
275 /**
276  * gsignond_security_context_compare:
277  * @ctx1: first item to compare.
278  * @ctx2: second item to compare.
279  *
280  * Compare two #GSignondSecurityContext items in a similar way to strcmp().
281  *
282  * Returns: negative if ctx1 < ctx2, 0 if ctx1 == ctx2 and positive if ctx1 > ctx2.
283  */
284 int
285 gsignond_security_context_compare (const GSignondSecurityContext *ctx1,
286                                    const GSignondSecurityContext *ctx2)
287 {
288     int res;
289
290     if (ctx1 == ctx2) return 0;
291
292     if (ctx1 == NULL)
293         return -1;
294     if (ctx2 == NULL)
295         return 1;
296
297     res = g_strcmp0(ctx1->sys_ctx, ctx2->sys_ctx);
298     if (res == 0)
299         res = g_strcmp0(ctx1->app_ctx, ctx2->app_ctx);
300
301     return res;
302 }
303
304 /**
305  * gsignond_security_context_match:
306  * @ctx1: first item to compare.
307  * @ctx2: second item to compare.
308  *
309  * Compare two #GSignondSecurityContext items match.
310  *
311  * Returns: TRUE if contexts are equal or if either side has a wildcard match for 
312  * system context, or if system contexts are equal and either side has a wildcard
313  * match for the app context,
314  * otherwise FALSE. Two NULL contexts match.
315  */
316 gboolean
317 gsignond_security_context_match (const GSignondSecurityContext *ctx1,
318                                  const GSignondSecurityContext *ctx2)
319 {
320     if (ctx1 == ctx2) return TRUE;
321
322     if (ctx1 == NULL || ctx2 == NULL)
323          return FALSE;
324
325     if (g_strcmp0(ctx1->sys_ctx, "*") == 0 ||
326         g_strcmp0(ctx2->sys_ctx, "*") == 0) return TRUE;
327
328     if (g_strcmp0(ctx1->sys_ctx, ctx2->sys_ctx) == 0) {
329         if (g_strcmp0(ctx1->app_ctx, "*") == 0 ||
330             g_strcmp0(ctx2->app_ctx, "*") == 0) return TRUE;
331         if (g_strcmp0(ctx1->app_ctx, ctx2->app_ctx) == 0) return TRUE;
332     }
333
334     return FALSE;
335 }
336
337 /**
338  * gsignond_security_context_check:
339  * @reference: reference security context item to check against.
340  * @test: security context item to be checked.
341  *
342  * Check if @test is covered by @reference.
343  *
344  * Returns: TRUE if contexts are equal or the @reference has a wildcard
345  * system context, or if system contexts are equal and @reference has a wildcard
346  * application context, otherwise FALSE. If either or both contexts are NULL, 
347  * FALSE is returned.
348  */
349 gboolean
350 gsignond_security_context_check (const GSignondSecurityContext *reference,
351                                  const GSignondSecurityContext *test)
352 {
353     if (reference == NULL || test == NULL)
354          return FALSE;
355
356     if (g_strcmp0(reference->sys_ctx, "*") == 0) return TRUE;
357     if (g_strcmp0(reference->sys_ctx, test->sys_ctx) == 0) {
358         if (g_strcmp0(reference->app_ctx, "*") == 0) return TRUE;
359         if (g_strcmp0(reference->app_ctx, test->app_ctx) == 0) return TRUE;
360     }
361
362     return FALSE;
363 }
364
365 /**
366  * gsignond_security_context_list_to_variant:
367  * @list: #GSignondSecurityContextList item.
368  *
369  * Builds a GVariant of type "a(ss)" from a GList of #GSignondSecurityContext
370  * items.
371  *
372  * Returns: (transfer full): GVariant construct of a #GSignondSecurityContextList.
373  */
374 GVariant *
375 gsignond_security_context_list_to_variant (
376                                         const GSignondSecurityContextList *list)
377 {
378     GVariantBuilder builder;
379     GVariant *variant;
380     GSignondSecurityContext *ctx;
381
382     g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
383     for ( ; list != NULL; list = g_list_next (list)) {
384         ctx = (GSignondSecurityContext *) list->data;
385         g_variant_builder_add_value (
386                                     &builder,
387                                     gsignond_security_context_to_variant (ctx));
388     }
389     variant = g_variant_builder_end (&builder);
390
391     return variant;
392 }
393
394 /**
395  * gsignond_security_context_list_from_variant:
396  * @variant: GVariant item with a list of security context tuples.
397  *
398  * Builds a GList of #GSignondSecurityContext items from a GVariant of type
399  * "a(ss)".
400  *
401  * Returns: (transfer full): #GSignondSecurityContextList item.
402  */
403 GSignondSecurityContextList *
404 gsignond_security_context_list_from_variant (GVariant *variant)
405 {
406     GSignondSecurityContextList *list = NULL;
407     GVariantIter iter;
408     GVariant *value;
409
410     g_return_val_if_fail (variant != NULL, NULL);
411
412     g_variant_iter_init (&iter, variant);
413     while ((value = g_variant_iter_next_value (&iter))) {
414         list = g_list_append (list,
415                               gsignond_security_context_from_variant (value));
416         g_variant_unref (value);
417     }
418
419     return list;
420 }
421
422 /**
423  * gsignond_security_context_list_copy:
424  * @src_list: source #GSignondSecurityContextList.
425  *
426  * Copies a GList of #GSignondSecurityContext items.
427  *
428  * Returns: (transfer full): #GSignondSecurityContextList item.
429  */
430 GSignondSecurityContextList *
431 gsignond_security_context_list_copy (
432                                     const GSignondSecurityContextList *src_list)
433 {
434     GSignondSecurityContext *ctx;
435     GSignondSecurityContextList *dst_list = NULL;
436
437     for ( ; src_list != NULL; src_list = g_list_next (src_list)) {
438         ctx = (GSignondSecurityContext *) src_list->data;
439         dst_list = g_list_append (dst_list,
440                                   gsignond_security_context_copy (ctx));
441     }
442
443     return dst_list;
444 }
445
446 /**
447  * gsignond_security_context_list_free:
448  * @seclist: (transfer full): #GSignondSecurityContextList item.
449  *
450  * Frees all items and the GList of #GSignondSecurityContext.
451  */
452 void
453 gsignond_security_context_list_free (GSignondSecurityContextList *seclist)
454 {
455     g_list_free_full (seclist, _security_context_free);
456 }
457