gsignond first release 0.0.1
[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 static void
29 _security_context_free (gpointer ptr)
30 {
31     GSignondSecurityContext *ctx = (GSignondSecurityContext *) ptr;
32
33     gsignond_security_context_free (ctx);
34 }
35
36 /**
37  * gsignond_security_context_new:
38  *
39  * Allocates a new security context item.
40  *
41  * Returns: (transfer full) allocated #GSignondSecurityContext.
42  */
43 GSignondSecurityContext *
44 gsignond_security_context_new ()
45 {
46     GSignondSecurityContext *ctx;
47
48     ctx = g_slice_new0 (GSignondSecurityContext);
49     ctx->sys_ctx = g_strdup ("");
50     ctx->app_ctx = g_strdup ("");
51
52     return ctx;
53 }
54
55 /**
56  * gsignond_security_context_new_from_vaues:
57  * @system_context: system security context (such as SMACK/MSSF label/token).
58  * @application_context: application security context (such as a script name).
59  *
60  * Allocates and initializes a new security context item.
61  *
62  * Returns: (transfer full) allocated #GSignondSecurityContext.
63  */
64 GSignondSecurityContext *
65 gsignond_security_context_new_from_values (const gchar *system_context,
66                                            const gchar *application_context)
67 {
68     GSignondSecurityContext *ctx;
69
70     g_return_val_if_fail (system_context != NULL, NULL);
71
72     ctx = g_slice_new0 (GSignondSecurityContext);
73     ctx->sys_ctx = g_strdup (system_context);
74     if (application_context)
75         ctx->app_ctx = g_strdup (application_context);
76     else
77         ctx->app_ctx = g_strdup ("");
78
79     return ctx;
80 }
81
82 /**
83  * gsignond_security_context_copy:
84  * @src_ctx: source security context to copy.
85  *
86  * Copy a security context item.
87  *
88  * Returns: (transfer full) a copy of the #GSignondSecurityContext item.
89  */
90 GSignondSecurityContext *
91 gsignond_security_context_copy (const GSignondSecurityContext *src_ctx)
92 {
93     g_return_val_if_fail (src_ctx != NULL, NULL);
94
95     return gsignond_security_context_new_from_values (src_ctx->sys_ctx,
96                                                       src_ctx->app_ctx);
97 }
98
99 /**
100  * gsignond_security_context_free:
101  * @ctx: #GSignondSecurityContext to be freed.
102  *
103  * Frees a security context item.
104  */
105 void
106 gsignond_security_context_free (GSignondSecurityContext *ctx)
107 {
108     if (ctx == NULL) return;
109
110     g_free (ctx->sys_ctx);
111     g_free (ctx->app_ctx);
112     g_slice_free (GSignondSecurityContext, ctx);
113 }
114
115 /**
116  * gsignond_security_context_set_system_context:
117  * @ctx: #GSignondSecurityContext item.
118  * @system_context: system security context.
119  *
120  * Sets the system context part (such as SMACK label or MSSF token) of the
121  * #GSignondSecurityContext.
122  */
123 void
124 gsignond_security_context_set_system_context (GSignondSecurityContext *ctx,
125                                               const gchar *system_context)
126 {
127     g_return_if_fail (ctx != NULL);
128
129     g_free (ctx->sys_ctx);
130     ctx->sys_ctx = (system_context) ?
131         g_strdup (system_context) : g_strdup ("");
132 }
133
134 /**
135  * gsignond_security_context_get_system_context:
136  * @ctx: #GSignondSecurityContext item.
137  * 
138  * Get the system context part (such as SMACK label or MSSF token) of the
139  * #GSignondSecurityContext.
140  *
141  * Returns: (transfer none) system context.
142  */
143 const gchar *
144 gsignond_security_context_get_system_context (
145                                              const GSignondSecurityContext *ctx)
146 {
147     g_return_val_if_fail (ctx != NULL, NULL);
148
149     return ctx->sys_ctx;
150 }
151
152 /**
153  * gsignond_security_context_set_application_context:
154  * @ctx: #GSignondSecurityContext item.
155  * @application_context: application security context.
156  *
157  * Sets the application context part (such as a script name or a web page) of
158  * the #GSignondSecurityContext.
159  */
160 void
161 gsignond_security_context_set_application_context (
162                                                GSignondSecurityContext *ctx,
163                                                const gchar *application_context)
164 {
165     g_return_if_fail (ctx != NULL);
166
167     g_free (ctx->app_ctx);
168     ctx->app_ctx = (application_context) ?
169         g_strdup (application_context) : g_strdup ("");
170 }
171
172 /**
173  * gsignond_security_context_get_application_context:
174  * @ctx: #GSignondSecurityContext item.
175  *
176  * Get the application context part (such as script name or a web page) of
177  * the #GSignondSecurityContext.
178  *
179  * Returns: (transfer none) application context.
180  */
181 const gchar *
182 gsignond_security_context_get_application_context (
183                                              const GSignondSecurityContext *ctx)
184 {
185     g_return_val_if_fail (ctx != NULL, NULL);
186
187     return ctx->app_ctx;
188 }
189
190 /**
191  * signon_security_conetxt_to_variant:
192  * @ctx: #GSignondSecurityContext item.
193  *
194  * Build a GVariant of type "(ss)" from a #GSignondSecurityContext item.
195  *
196  * Returns: (transfer full) GVariant construct of a #GSignondSecurityContext.
197  */
198 GVariant *
199 gsignond_security_context_to_variant (const GSignondSecurityContext *ctx)
200 {
201     GVariant *variant;
202
203     g_return_val_if_fail (ctx != NULL, NULL);
204
205     variant = g_variant_new ("(ss)",
206                              ctx->sys_ctx ? ctx->sys_ctx : "",
207                              ctx->app_ctx ? ctx->app_ctx : "");
208
209     return variant;
210 }
211
212 /**
213  * gsignond_security_context_from_variant:
214  * @variant: GVariant item with a #GSignondSecurityContext construct.
215  *
216  * Builds a #GSignondSecurityContext item from a GVariant of type "(ss)".
217  *
218  * Returns: (transfer full) #GSignondSecurityContext item.
219  */
220 GSignondSecurityContext *
221 gsignond_security_context_from_variant (GVariant *variant)
222 {
223     gchar *sys_ctx = NULL;
224     gchar *app_ctx = NULL;
225     GSignondSecurityContext *ctx;
226
227     g_return_val_if_fail (variant != NULL, NULL);
228
229     g_variant_get (variant, "(ss)", &sys_ctx, &app_ctx);
230     ctx = gsignond_security_context_new_from_values (sys_ctx, app_ctx);
231     g_free (sys_ctx);
232     g_free (app_ctx);
233     return ctx;
234 }
235
236 /**
237  * gsignond_security_context_compare:
238  * @ctx1: first item to compare.
239  * @ctx2: second item to compare.
240  *
241  * Compare two #GSignondSecurityContext items similar in a way to strcmp().
242  *
243  * Returns: negative if ctx1 < ctx2, 0 if ctx1 == ctx2 and positive if ctx1 > ctx2.
244  */
245 int
246 gsignond_security_context_compare (const GSignondSecurityContext *ctx1,
247                                    const GSignondSecurityContext *ctx2)
248 {
249     int res;
250
251     if (ctx1 == ctx2) return 0;
252
253     g_return_val_if_fail (ctx1 != NULL, -1);
254     g_return_val_if_fail (ctx2 != NULL, 1);
255
256     res = g_strcmp0(ctx1->sys_ctx, ctx2->sys_ctx);
257     if (res == 0)
258         res = g_strcmp0(ctx1->app_ctx, ctx2->app_ctx);
259
260     return res;
261 }
262
263 /**
264  * gsignond_security_context_match:
265  * @ctx1: first item to compare.
266  * @ctx2: second item to compare.
267  *
268  * Compare two #GSignondSecurityContext items match.
269  *
270  * Returns: TRUE if contexts are equal or either side has wildcard match, otherwise FALSE. Two NULL contexts match.
271  */
272 gboolean
273 gsignond_security_context_match (const GSignondSecurityContext *ctx1,
274                                  const GSignondSecurityContext *ctx2)
275 {
276     if (ctx1 == ctx2) return TRUE;
277
278     g_return_val_if_fail (ctx1 != NULL && ctx2 != NULL, FALSE);
279
280     if (g_strcmp0(ctx1->sys_ctx, "*") == 0 ||
281         g_strcmp0(ctx2->sys_ctx, "*") == 0) return TRUE;
282
283     if (g_strcmp0(ctx1->sys_ctx, ctx2->sys_ctx) == 0) {
284         if (g_strcmp0(ctx1->app_ctx, "*") == 0 ||
285             g_strcmp0(ctx2->app_ctx, "*") == 0) return TRUE;
286         if (g_strcmp0(ctx1->app_ctx, ctx2->app_ctx) == 0) return TRUE;
287     }
288
289     return FALSE;
290 }
291
292 /**
293  * gsignond_security_context_check:
294  * @reference: reference security context item to check against.
295  * @test: security context item to be checked.
296  *
297  * Check if item @test is covered by @reference.
298  *
299  * Returns: TRUE if contexts are equal or wildcards of the @reference arguments match, otherwise FALSE. If either or both contexts are NULL, FALSE is returned.
300  */
301 gboolean
302 gsignond_security_context_check (const GSignondSecurityContext *reference,
303                                  const GSignondSecurityContext *test)
304 {
305     g_return_val_if_fail (reference != NULL && test != NULL, FALSE);
306
307     if (g_strcmp0(reference->sys_ctx, "*") == 0) return TRUE;
308     if (g_strcmp0(reference->sys_ctx, test->sys_ctx) == 0) {
309         if (g_strcmp0(reference->app_ctx, "*") == 0) return TRUE;
310         if (g_strcmp0(reference->app_ctx, test->app_ctx) == 0) return TRUE;
311     }
312
313     return FALSE;
314 }
315
316 /**
317  * gsignond_security_context_list_to_variant:
318  * @list: #GSignondSecurityContextList item.
319  *
320  * Builds a GVariant of type "a(ss)" from a GList of #GSignondSecurityContext
321  * items.
322  *
323  * Returns: (transfer full) GVariant construct of a #GSignondSecurityContextList.
324  */
325 GVariant *
326 gsignond_security_context_list_to_variant (
327                                         const GSignondSecurityContextList *list)
328 {
329     GVariantBuilder builder;
330     GVariant *variant;
331     GSignondSecurityContext *ctx;
332
333     g_variant_builder_init (&builder, G_VARIANT_TYPE_ARRAY);
334     for ( ; list != NULL; list = g_list_next (list)) {
335         ctx = (GSignondSecurityContext *) list->data;
336         g_variant_builder_add_value (
337                                     &builder,
338                                     gsignond_security_context_to_variant (ctx));
339     }
340     variant = g_variant_builder_end (&builder);
341
342     return variant;
343 }
344
345 /**
346  * gsignond_security_context_list_from_variant:
347  * @variant: GVariant item with a list of security context tuples.
348  *
349  * Builds a GList of #GSignondSecurityContext items from a GVariant of type
350  * "a(ss)".
351  *
352  * Returns: (transfer full) #GSignondSecurityContextList item.
353  */
354 GSignondSecurityContextList *
355 gsignond_security_context_list_from_variant (GVariant *variant)
356 {
357     GSignondSecurityContextList *list = NULL;
358     GVariantIter iter;
359     GVariant *value;
360
361     g_return_val_if_fail (variant != NULL, NULL);
362
363     g_variant_iter_init (&iter, variant);
364     while ((value = g_variant_iter_next_value (&iter))) {
365         list = g_list_append (list,
366                               gsignond_security_context_from_variant (value));
367         g_variant_unref (value);
368     }
369
370     return list;
371 }
372
373 /**
374  * gsignond_security_context_list_copy:
375  * @src_list: source #GSignondSecurityContextList.
376  *
377  * Copies a GList of #GSignondSecurityContext items.
378  *
379  * Returns: (transfer full) #GSignondSecurityContextList item.
380  */
381 GSignondSecurityContextList *
382 gsignond_security_context_list_copy (
383                                     const GSignondSecurityContextList *src_list)
384 {
385     GSignondSecurityContext *ctx;
386     GSignondSecurityContextList *dst_list = NULL;
387
388     for ( ; src_list != NULL; src_list = g_list_next (src_list)) {
389         ctx = (GSignondSecurityContext *) src_list->data;
390         dst_list = g_list_append (dst_list,
391                                   gsignond_security_context_copy (ctx));
392     }
393
394     return dst_list;
395 }
396
397 /**
398  * gsignond_security_context_list_free:
399  * @seclist: (transfer full) #GSignondSecurityContextList item.
400  *
401  * Frees all items and the GList of #GSignondSecurityContext.
402  */
403 void
404 gsignond_security_context_list_free (GSignondSecurityContextList *seclist)
405 {
406     g_list_free_full (seclist, _security_context_free);
407 }
408