source: libabac/abac_oset.c @ 7727f26

mei_rt2mei_rt2_fix_1meiyap-rt1rt2
Last change on this file since 7727f26 was 7727f26, checked in by Mei <mei@…>, 12 years ago

1) add environment variables DUMP_DB, ABAC_CN.

ABAC_CN will switch to using CNs for keyid insead of SHAs

2) add/modified couple of doc files.

  • Property mode set to 100644
File size: 15.5 KB
Line 
1#include <assert.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5
6#include "abac_list.h"
7#include "abac_util.h"
8
9#include "abac_pl.h"
10
11static int debug=0;
12/*
13   A.oset <- B
14   A.oset <- Obj
15   A.oset <- B.oset
16   A.oset <- B.role.oset
17*/
18struct _abac_oset_t {
19    int is_object;
20    union {
21        char *principal_name;
22        abac_term_t *principal_object;
23    };
24
25    char *linked_role_name;
26    abac_param_list_t *linked_role_params;
27
28    char *oset_name;
29    abac_param_list_t *oset_params;
30
31    char *string;
32    char *linked;
33
34    abac_list_t *prereqs;
35    int refcount;
36};
37
38
39int abac_oset_is_object(abac_oset_t *ptr)
40{
41    return ptr->is_object;
42}
43
44/**
45 * Create a new principal and initialize it.
46 * always with the proper pCN or pSHA string
47 */
48abac_oset_t *abac_oset_principal_new(char *principal_name) {
49    assert(principal_name != NULL);
50
51    if (strlen(principal_name) == 0)
52        return NULL;
53
54    abac_oset_t *oset = (abac_oset_t *) abac_xmalloc(sizeof(abac_oset_t));
55
56    oset->is_object =0;
57
58    oset->principal_name = abac_xstrdup(principal_name);
59
60    oset->oset_name = NULL;
61    oset->oset_params = NULL;
62
63    oset->linked_role_name = NULL;
64    oset->linked_role_params = NULL;
65
66    oset->string = abac_xstrdup(oset->principal_name);
67    oset->linked = NULL;
68    oset->prereqs = NULL;
69
70    oset->refcount = 1;
71
72    return oset;
73}
74
75abac_oset_t *abac_oset_object_new(abac_term_t *object) {
76    assert(object != NULL);
77
78    abac_oset_t *oset = (abac_oset_t *) abac_xmalloc(sizeof(abac_oset_t));
79
80    oset->is_object =1;
81    oset->principal_object = object;
82    oset->oset_name = NULL;
83    oset->oset_params = NULL;
84
85    oset->linked_role_name = NULL;
86    oset->linked_role_params = NULL;
87
88    oset->string = strdup(abac_term_name(object));
89    oset->linked = NULL;
90    oset->prereqs = NULL;
91
92    oset->refcount = 1;
93
94    return oset;
95}
96
97/**
98 * Create a new oset and initialize it.
99 */
100abac_oset_t *abac_oset_oset_new(char *principal_name, char *oset_name) {
101    assert(principal_name != NULL);
102    assert(oset_name != NULL);
103
104    abac_oset_t *oset;
105
106    if (strlen(principal_name) == 0 || strlen(oset_name) == 0)
107        return NULL;
108
109    oset = abac_xmalloc(sizeof(abac_oset_t));
110
111    oset->is_object=0;
112    oset->principal_name = abac_xstrdup(principal_name);
113
114    oset->oset_name = abac_xstrdup(oset_name);
115    oset->oset_params = NULL;
116
117    oset->linked_role_name = NULL;
118    oset->linked_role_params = NULL;
119
120    int prin_len = strlen(oset->principal_name);
121    int oset_len = strlen(oset_name);
122
123    oset->string = abac_xmalloc(prin_len + 1 + oset_len + 1);
124    memcpy(oset->string, oset->principal_name, prin_len);
125    oset->string[prin_len] = '.';
126    memcpy(oset->string + prin_len + 1, oset_name, oset_len);
127    oset->string[prin_len + 1 + oset_len] = 0;
128
129    if(debug)
130        printf("DEBUG:adding a new oset (%s) to principal (%s)\n",
131                  oset->oset_name, oset->principal_name);
132
133
134
135    oset->linked = NULL;
136    oset->prereqs = NULL;
137
138    oset->refcount = 1;
139
140    return oset;
141}
142
143/**
144 * Created a new linking oset and initialize it.
145 */
146abac_oset_t *abac_oset_linking_new(char *principal_name, char *linked_role_name, char *oset_name) {
147    assert(principal_name != NULL);
148    assert(linked_role_name != NULL);
149    assert(oset_name != NULL);
150
151    abac_oset_t *oset;
152    if (strlen(principal_name) == 0 || strlen(linked_role_name) == 0 || strlen(oset_name) == 0)
153        return NULL;
154
155    oset = abac_xmalloc(sizeof(abac_oset_t));
156
157    oset->is_object=0;
158    oset->principal_name = abac_xstrdup(principal_name);
159
160    oset->linked_role_name = abac_xstrdup(linked_role_name);
161    oset->linked_role_params = NULL;
162    oset->oset_name = abac_xstrdup(oset_name);
163    oset->oset_params = NULL;
164
165    if(debug)
166        printf("DEBUG:adding a new linked (%s) to oset(%s) for principal(%s)\n",
167                  oset->linked_role_name, oset->oset_name, oset->principal_name);
168
169
170    int prin_len = strlen(oset->principal_name);
171    int link_len = strlen(linked_role_name);
172    int oset_len = strlen(oset_name);
173
174    oset->string = abac_xmalloc(prin_len + 1 + link_len + 1 + oset_len + 1);
175
176    memcpy(oset->string, oset->principal_name, prin_len);
177    oset->string[prin_len] = '.';
178    memcpy(oset->string + prin_len + 1, linked_role_name, link_len);
179    oset->string[prin_len + 1 + link_len] = 0;
180
181    // hack: linked role is first two parts of full string
182    oset->linked = abac_xstrdup(oset->string);
183
184    oset->string[prin_len + 1 + link_len] = '.';
185    memcpy(oset->string + prin_len + 1 + link_len + 1, oset_name, oset_len);
186    oset->string[prin_len + 1 + link_len + 1 + oset_len] = 0;
187
188    oset->prereqs = NULL;
189    oset->refcount = 1;
190
191    return oset;
192}
193
194/**
195 * Create an intersection oset.
196 */
197abac_oset_t *abac_oset_intersection_new(char *name, abac_list_t *prereqs) {
198    abac_oset_t *oset = abac_xmalloc(sizeof(abac_oset_t));
199
200    oset->principal_name = oset->linked_role_name = oset->oset_name = NULL;
201    oset->linked_role_params = NULL;
202    oset->oset_params = NULL;
203
204    oset->linked = NULL;
205    oset->string = abac_xstrdup(name);
206    oset->prereqs = prereqs;
207
208    oset->refcount = 1;
209
210    return oset;
211}
212
213/**
214 * Decrease a oset's reference count, freeing it when it reaches 0.
215 */
216void abac_oset_free(abac_oset_t *oset) {
217
218    if(debug)
219        printf("DEBUG:trying to freeing a oset %d\n",(int)oset);
220 
221    if (oset == NULL)
222        return;
223
224    if(debug)
225        printf("DEBUG:freeing a oset %d\n",(int)oset);
226
227    --oset->refcount;
228    if (oset->refcount > 0)
229        return;
230
231    if(oset->principal_name) free(oset->principal_name);
232    if(oset->linked_role_name) free(oset->linked_role_name);
233    if(oset->oset_name) free(oset->oset_name);
234
235    if(oset->string) free(oset->string);
236    if(oset->linked) free(oset->linked);
237
238    if (oset->oset_params != NULL) {
239        abac_param_list_free(oset->oset_params);
240    }
241
242    if (oset->linked_role_params != NULL) {
243        abac_param_list_free(oset->linked_role_params);
244    }
245
246    if (oset->prereqs != NULL) {
247        abac_oset_t *cur;
248        abac_list_foreach(oset->prereqs, cur,
249            abac_oset_free(cur);
250        );
251        abac_list_free(oset->prereqs);
252    }
253
254    free(oset);
255}
256
257abac_oset_t *abac_oset_oset_add_param(abac_oset_t *oset, abac_term_t *param)
258{
259     if(oset->oset_params == NULL) {
260        oset->oset_params=abac_param_list_new(param);
261        } else {
262            abac_param_list_add_term(oset->oset_params, param);
263     }
264     return oset;
265}
266
267abac_oset_t *abac_oset_add_intersecting_oset(abac_oset_t *oset, abac_oset_t *noset)
268{
269     abac_list_add(oset->prereqs, noset);
270     return oset;
271}
272
273abac_oset_t *abac_oset_oset_add_linked_param(abac_oset_t *oset, abac_term_t *param)
274{
275     if(oset->linked_role_params == NULL) {
276        oset->linked_role_params=abac_param_list_new(param);
277        } else {
278            abac_param_list_add_term(oset->linked_role_params, param);
279     }
280     return oset;
281}
282
283
284/**
285 * Create a non-intersecting oset from a string. Handles principals, osets,
286 * and linking osets.
287 */
288static abac_oset_t *_abac_single_oset_from_string(char *string) {
289    int num_dots = 0;
290    char *dot = string;
291    abac_oset_t *ret = NULL;
292
293    // count the dots
294    while ((dot = strchr(dot, '.')) != NULL) {
295        ++num_dots;
296        ++dot;
297    }
298
299    // no dots: easy case, principal
300    if (num_dots == 0)
301        ret = abac_oset_principal_new(string);
302
303    // a oset has exactly 1 dot
304    else if (num_dots == 1) {
305        char *principal = string;
306
307        // terminate the principal part
308        dot = strchr(principal, '.');
309        *dot = 0;
310
311        // oset name comes after the dot
312        char *oset_name = dot + 1;
313
314        // create the oset (if possible)
315        ret = abac_oset_oset_new(string, oset_name);
316    }
317
318    // a linked oset has 2 dots
319    else if (num_dots == 2) {
320        char *principal = string;
321
322        // terminate the principal part
323        dot = strchr(principal, '.');
324        *dot = 0;
325
326        // linked name is next, terminate it
327        char *linked = dot + 1;
328        dot = strchr(linked, '.');
329        *dot = 0;
330
331        // oset name is last, already terminated
332        char *oset_name = dot + 1;
333
334        ret = abac_oset_linking_new(principal, linked, oset_name);
335    }
336
337    // more than two dots: return NULL
338
339    return ret;
340}
341
342/**
343 * Create a oset from a string. Handles intersecting and normal osets.
344 */
345abac_oset_t *abac_oset_from_string(char *string) {
346    abac_list_t *prereqs = NULL;
347    abac_oset_t *ret = NULL, *oset;
348    char *osets[256];
349    int num_osets, i;
350
351    char *original = string;
352
353    // make a copy so we can mess with it
354    string = abac_xstrdup(string);
355
356    // split the string (in case of an intersection num_osets > 1)
357    abac_split(string, " & ", osets, &num_osets);
358
359    // normal oset:
360    if (num_osets == 1)
361        ret = _abac_single_oset_from_string(string);
362
363    else {
364        prereqs = abac_list_new();
365
366        for (i = 0; i < num_osets; ++i) {
367            // make sure the tail oset is valid
368            oset = abac_oset_from_string(osets[i]);
369            if (oset == NULL)
370                goto error;
371
372            abac_list_add(prereqs, oset);
373        }
374        ret = abac_oset_intersection_new(original, prereqs);
375    }
376
377    free(string);
378    return ret;
379
380error:
381
382    if (prereqs != NULL) {
383       abac_oset_t *cur;
384       abac_list_foreach(prereqs, cur,
385           abac_oset_free(cur);
386       );
387       abac_list_free(prereqs);
388    }
389    free(string);
390    return NULL;
391}
392
393
394/**
395 * Increase a oset's reference count.
396 */
397abac_oset_t *abac_oset_dup(abac_oset_t *oset) {
398    assert(oset != NULL);
399
400    ++oset->refcount;
401    return oset;
402}
403
404/**
405 * True if a oset is a principal.
406 */
407int abac_oset_is_principal(abac_oset_t *oset) {
408    assert(oset != NULL);
409    return oset->oset_name == NULL && oset->linked_role_name == NULL && oset->prereqs == NULL;
410}
411
412/**
413 * True if a oset is a oset.
414 */
415int abac_oset_is_oset(abac_oset_t *oset) {
416    assert(oset != NULL);
417    return oset->oset_name != NULL && oset->linked_role_name == NULL && oset->prereqs == NULL; 
418}
419
420/**
421 * True if a oset is a linked oset.
422 */
423int abac_oset_is_linking(abac_oset_t *oset) {
424    assert(oset != NULL);
425    return oset->linked_role_name != NULL;
426}
427
428/**
429 * True if a oset is an intersection.
430 */
431int abac_oset_is_intersection(abac_oset_t *oset) {
432    assert(oset != NULL);
433    return oset->prereqs != NULL;
434}
435
436char *abac_oset_intersecting_string_with_condition(abac_oset_t *oset)
437{
438    assert(oset != NULL);
439    char *tmp=NULL;
440    if (oset->prereqs != NULL) {
441        abac_oset_t *cur;
442        abac_list_foreach(oset->prereqs, cur,
443            char *ntmp=abac_oset_string_with_condition(cur);
444            if(tmp==NULL) {
445                asprintf(&tmp,"%s",ntmp);
446                } else {
447                    asprintf(&tmp,"%s & %s",tmp, ntmp);
448            }
449        );
450    }
451    return tmp;
452}
453/**
454 * Returns the string representation of the oset.
455 * principal.oset(params..)
456 */
457char *abac_oset_string_with_condition(abac_oset_t *oset) {
458    assert(oset != NULL);
459
460    if(abac_oset_is_intersection(oset)) {
461        return abac_oset_intersecting_string_with_condition(oset);
462    }
463
464    char *tmp=NULL;
465    char *principal_name;
466    if(abac_oset_is_object(oset))
467        principal_name = abac_oset_object_name(oset);
468        else principal_name = abac_oset_principal_name(oset);
469    char *oset_name= oset->oset_name;
470    char *linked_role_name = oset->linked_role_name;
471    char *params_string=NULL;
472    char *linked_params_string=NULL;
473
474    int len = 0;
475    if(principal_name)
476        len=len+strlen(principal_name)+1;
477    if(oset_name)
478        len = len+strlen(oset_name)+1;
479    if(linked_role_name)
480        len = len+strlen(linked_role_name)+1;
481
482    if(oset->oset_params) {
483         params_string=abac_param_list_string_with_condition(oset->oset_params);
484         len = len+strlen(params_string)+3;
485    } 
486    if(oset->linked_role_params) {
487         linked_params_string=abac_param_list_string_with_condition(oset->linked_role_params);
488         len = len+strlen(linked_params_string)+3;
489    }
490
491    /* principal */
492    /* principal.oset */
493    /* principal.oset(params_string) */
494    /* principal.linked_role(linked_params_string).oset(params_string) */
495    tmp = abac_xmalloc(len);
496
497    if(principal_name)
498        sprintf(tmp,"%s",principal_name);
499
500    if(linked_role_name) {
501        strcat(tmp,".");
502        strcat(tmp,linked_role_name);
503    }
504    if(linked_params_string) {
505        strcat(tmp,"(");
506        strcat(tmp,linked_params_string);
507        strcat(tmp,")");
508    }
509    if(oset_name) {
510        strcat(tmp,".");
511        strcat(tmp,oset_name);
512    }
513    if(params_string) {
514        strcat(tmp,"(");
515        strcat(tmp,params_string);
516        strcat(tmp,")");
517    }
518
519    if(linked_params_string) free(linked_params_string);
520    if(params_string) free(params_string);
521    return tmp;
522}
523
524char *abac_oset_string(abac_oset_t *oset) { 
525    return abac_oset_string_with_condition(oset);
526}
527void abac_print_oset_string_with_condition(abac_oset_t *oset,FILE *fp)
528{
529    char *string=abac_oset_string_with_condition(oset);
530    if(fp==NULL)
531        printf("%s ",string);
532        else fprintf(fp,"%s ",string);
533}
534
535/**
536 * Returns the name of a oset. If the oset is A.r1 then return r1. If the oset
537 * is A.r1.r2 then return r2.
538 */
539char *abac_oset_oset_name(abac_oset_t *oset) {
540    assert(oset != NULL);
541    return oset->oset_name;
542}
543
544char *abac_oset_oset_param_string(abac_oset_t *oset) {
545    assert(oset != NULL);
546    if(oset->oset_params) {
547         return abac_param_list_string(oset->oset_params);
548    }
549    return NULL;
550}
551
552/**
553 * Returns the linked part of a linking oset. For instance, if the oset is
554 * A.r1.r2, this returns A.r1.
555 */
556char *abac_oset_linked_role(abac_oset_t *oset) {
557    assert(oset != NULL);
558    return oset->linked_role_name;
559}
560
561/**
562 * Returns the principal part of a oset. The stuff before the first dot.
563 */
564char *abac_oset_principal_principalname(abac_oset_t *oset) {
565    assert(oset != NULL);
566    return oset->principal_name;
567}
568
569char *abac_oset_principal_name(abac_oset_t *oset) {
570    assert(oset != NULL);
571    if(USE("ABAC_CN"))
572        return abac_cn_with_sha(oset->principal_name);
573    return oset->principal_name;
574}
575
576char *abac_oset_principal_cn(abac_oset_t *oset) {
577    assert(oset != NULL);
578    return abac_cn_with_sha(oset->principal_name);
579}
580
581char *abac_oset_object_name(abac_oset_t *oset) {
582    assert(oset != NULL && oset->is_object);
583    abac_term_t *obj=oset->principal_object;
584    char *tmp=abac_term_name(obj);
585    return abac_term_name(obj);
586}
587
588abac_condition_t *abac_oset_object_constraint(abac_oset_t *oset) {
589    assert(oset != NULL && oset->is_object);
590    abac_term_t *obj=oset->principal_object;
591    return abac_term_constraint(obj);
592}
593/**
594 * Returns the prereqs of an intersection.
595 */
596abac_list_t *abac_oset_prereqs(abac_oset_t *oset) {
597    assert(oset != NULL);
598    return oset->prereqs;
599}
600
601abac_param_list_t *abac_oset_linked_role_params(abac_oset_t *oset) {
602    assert(oset != NULL);
603    return oset->linked_role_params;
604}
605
606abac_param_list_t *abac_oset_oset_params(abac_oset_t *oset) {
607    assert(oset != NULL);
608    return oset->oset_params;
609}
610
611
612/**
613 * Build an attribute key from head and tail osets. Static.
614 */
615#define ROLE_SEPARATOR " <- "
616char *abac_oset_attr_key(abac_oset_t *head_oset, abac_oset_t *tail_oset) {
617    char *head = abac_oset_string_with_condition(head_oset);
618    int head_len = strlen(head);
619
620    char *tail = abac_oset_string_with_condition(tail_oset);
621    int tail_len = strlen(tail);
622
623    int sep_len = sizeof(ROLE_SEPARATOR) - 1;
624
625    // "head <- tail"
626    char *ret = abac_xmalloc(head_len + tail_len + sep_len + 1);
627    memcpy(ret, head, head_len);
628    memcpy(ret + head_len, ROLE_SEPARATOR, sep_len);
629    memcpy(ret + head_len + sep_len, tail, tail_len);
630    ret[head_len + sep_len + tail_len] = 0;
631
632    return ret;
633}
Note: See TracBrowser for help on using the repository browser.