source: libabac/abac_role.c @ c586a3c

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

1) adding missing extern forward declarations that is causing

freeBSD compiled prover to coredump

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