source: libabac/abac_role.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: 14.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
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_name) {
35    assert(principal_name != NULL);
36
37    abac_role_t *role;
38
39    if (strlen(principal_name) == 0)
40        return NULL;
41
42    role = abac_xmalloc(sizeof(abac_role_t));
43 
44    role->principal_name = abac_xstrdup(principal_name);
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(role->principal_name);
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    role = abac_xmalloc(sizeof(abac_role_t));
74
75    role->principal_name = abac_xstrdup(principal_name);
76
77    role->role_name = abac_xstrdup(role_name);
78    role->role_params = NULL;
79
80    role->linked_role_name = NULL;
81    role->linked_role_params = NULL;
82
83    int prin_len = strlen(principal_name);
84    int role_len = strlen(role_name);
85
86    if(debug)
87        printf("DEBUG:adding a new role (%s) to principal (%s)\n",
88                     role->role_name, role->principal_name);
89
90    role->string = abac_xmalloc(prin_len + 1 + role_len + 1);
91    memcpy(role->string, principal_name, prin_len);
92    role->string[prin_len] = '.';
93    memcpy(role->string + prin_len + 1, role_name, role_len);
94    role->string[prin_len + 1 + role_len] = 0;
95
96
97    role->linked = NULL;
98    role->prereqs = NULL;
99
100    role->refcount = 1;
101
102    return role;
103}
104
105/**
106 * Created a new linking role and initialize it.
107 */
108abac_role_t *abac_role_linking_new(char *principal_name, char *linked_role_name, char *role_name) {
109    assert(principal_name != NULL);
110    assert(linked_role_name != NULL);
111    assert(role_name != NULL);
112
113    abac_role_t *role;
114
115    if (strlen(principal_name) == 0 || strlen(linked_role_name) == 0 || strlen(role_name) == 0)
116        return NULL;
117
118    role = abac_xmalloc(sizeof(abac_role_t));
119
120    role->principal_name = abac_xstrdup(principal_name);
121    role->linked_role_name = abac_xstrdup(linked_role_name);
122    role->linked_role_params = NULL;
123    role->role_name = abac_xstrdup(role_name);
124    role->role_params = NULL;
125
126    /* MEI */
127    if(debug)
128        printf("DEBUG:adding a new linked (%s) to role(%s) for principal(%s)\n",
129                   role->linked_role_name, role->role_name, role->principal_name);
130
131    int prin_len = strlen(role->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, role->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    char *principal_name = abac_role_principal_name(role);
427    char *role_name= role->role_name;
428    char *linked_role_name = role->linked_role_name;
429    char *params_string=NULL;
430    char *linked_params_string=NULL;
431
432    int len = 0;
433    if(principal_name)
434        len=len+strlen(principal_name)+1;
435    if(role_name)
436        len = len+strlen(role_name)+1;
437    if(linked_role_name)
438        len = len+strlen(linked_role_name)+1;
439
440    if(role->role_params) {
441         params_string=abac_param_list_string_with_condition(role->role_params);
442         len = len+strlen(params_string)+3;
443    } 
444    if(role->linked_role_params) {
445         linked_params_string=abac_param_list_string_with_condition(role->linked_role_params);
446         len = len+strlen(linked_params_string)+3;
447    }
448
449    /* principal */
450    /* principal.role */
451    /* principal.role(params_string) */
452    /* principal.linked_role(linked_params_string).role(params_string) */
453    tmp = abac_xmalloc(len);
454
455    if(principal_name)
456        sprintf(tmp,"%s",principal_name);
457
458    if(linked_role_name) {
459        strcat(tmp,".");
460        strcat(tmp,linked_role_name);
461    }
462    if(linked_params_string) {
463        strcat(tmp,"(");
464        strcat(tmp,linked_params_string);
465        strcat(tmp,")");
466    }
467    if(role_name) {
468        strcat(tmp,".");
469        strcat(tmp,role_name);
470    }
471    if(params_string) {
472        strcat(tmp,"(");
473        strcat(tmp,params_string);
474        strcat(tmp,")");
475    }
476
477    if(linked_params_string) free(linked_params_string);
478    if(params_string) free(params_string);
479    return tmp;
480}
481char *abac_role_string(abac_role_t *role) { 
482    abac_role_string_with_condition(role);
483}
484
485void abac_print_role_string_with_condition(abac_role_t *role,FILE *fp)
486{
487    char *string=abac_role_string_with_condition(role);
488    if(fp==NULL)
489        printf("%s ",string);
490        else fprintf(fp,"%s ",string);
491}
492
493/**
494 * Returns the name of a role. If the role is A.r1 then return r1. If the role
495 * is A.r1.r2 then return r2.
496 */
497char *abac_role_role_name(abac_role_t *role) {
498    assert(role != NULL);
499    return role->role_name;
500}
501
502char *abac_role_role_param_string(abac_role_t *role) {
503    assert(role != NULL);
504    if(role->role_params) {
505         return abac_param_list_string(role->role_params);
506    }
507    return NULL;
508}
509
510/**
511 * Returns the linked part of a linking role. For instance, if the role is
512 * A.r1.r2, this returns A.r1.
513 */
514char *abac_role_linked_role(abac_role_t *role) {
515    assert(role != NULL);
516    return role->linked_role_name;
517}
518
519/**
520 * Returns the principal part of a role. The stuff before the first dot.
521 */
522char *abac_role_principal_principalname(abac_role_t *role) {
523    assert(role != NULL);
524    return role->principal_name;
525}
526
527char *abac_role_principal_name(abac_role_t *role) {
528    assert(role != NULL);
529    if(USE("ABAC_CN"))
530        return abac_cn_with_sha(role->principal_name);
531    return role->principal_name;
532}
533
534char *abac_role_principal_cn(abac_role_t *role) {
535    assert(role != NULL);
536    return abac_cn_with_sha(role->principal_name);
537}
538
539/**
540 * Returns the prereqs of an intersection.
541 */
542abac_list_t *abac_role_prereqs(abac_role_t *role) {
543    assert(role != NULL);
544    return role->prereqs;
545}
546
547abac_param_list_t *abac_role_linked_role_params(abac_role_t *role) {
548    assert(role != NULL);
549    return role->linked_role_params;
550}
551
552abac_param_list_t *abac_role_role_params(abac_role_t *role) {
553    assert(role != NULL);
554    return role->role_params;
555}
556
557
558/**
559 * Build an attribute key from head and tail roles. Static.
560 */
561#define ROLE_SEPARATOR " <- "
562char *abac_role_attr_key(abac_role_t *head_role, abac_role_t *tail_role) {
563    char *head = abac_role_string_with_condition(head_role);
564    int head_len = strlen(head);
565
566    char *tail = abac_role_string_with_condition(tail_role);
567    int tail_len = strlen(tail);
568
569    int sep_len = sizeof(ROLE_SEPARATOR) - 1;
570
571    // "head <- tail"
572    char *ret = abac_xmalloc(head_len + tail_len + sep_len + 1);
573    memcpy(ret, head, head_len);
574    memcpy(ret + head_len, ROLE_SEPARATOR, sep_len);
575    memcpy(ret + head_len + sep_len, tail, tail_len);
576    ret[head_len + sep_len + tail_len] = 0;
577
578    return ret;
579}
Note: See TracBrowser for help on using the repository browser.