source: libabac/abac_oset.c @ 907af43

mei_rt2mei_rt2_fix_1meiyap-rt1rt2
Last change on this file since 907af43 was b5a3da4, checked in by Mei <mei@…>, 13 years ago

1) add abac_oset.c
2) reorganized some yyparse related files

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