source: libabac/abac_oset.c @ c586a3c

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

1) add support for float static range constraint
2) add a testcase for testing float static range constraint
3) add runall-fast (skipping the creddy part)

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