source: libabac/abac_role.c @ 59ea648

mei_rt2mei_rt2_fix_1meiyap-rt1rt2
Last change on this file since 59ea648 was 7727f26, checked in by Mei <mei@…>, 13 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
RevLine 
[7f25a67f]1#include <assert.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5
[9a411d7]6#include "abac_list.h"
[3c251d0]7#include "abac_util.h"
[7f25a67f]8
[202a7f9]9#include "abac_pl.h"
10
11static int debug=0;
12
[1743825]13struct _abac_role_t {
[202a7f9]14    char *principal_name;
15
16    char *linked_role_name;
17    abac_param_list_t *linked_role_params;
18
[9a411d7]19    char *role_name;
[202a7f9]20    abac_param_list_t *role_params;
[7e05a2f]21
22    char *string;
[d4cbf71]23    char *linked;
[fbb591e]24
[9a411d7]25    abac_list_t *prereqs;
26
[fbb591e]27    int refcount;
[7f25a67f]28};
29
[202a7f9]30
[7f25a67f]31/**
32 * Create a new principal and initialize it.
33 */
[7727f26]34abac_role_t *abac_role_principal_new(char *principal_name) {
35    assert(principal_name != NULL);
[7f25a67f]36
[1743825]37    abac_role_t *role;
[7f25a67f]38
[7727f26]39    if (strlen(principal_name) == 0)
[7f25a67f]40        return NULL;
41
[3c251d0]42    role = abac_xmalloc(sizeof(abac_role_t));
[7727f26]43 
44    role->principal_name = abac_xstrdup(principal_name);
[53e540d]45
[9a411d7]46    role->role_name = NULL;
[202a7f9]47    role->role_params = NULL;
48
49    role->linked_role_name = NULL;
50    role->linked_role_params = NULL;
[7f25a67f]51
[7727f26]52    role->string = abac_xstrdup(role->principal_name);
[d4cbf71]53    role->linked = NULL;
[9a411d7]54    role->prereqs = NULL;
[7e05a2f]55
[fbb591e]56    role->refcount = 1;
57
[7f25a67f]58    return role;
59}
60
61/**
62 * Create a new role and initialize it.
63 */
[202a7f9]64abac_role_t *abac_role_role_new(char *principal_name, char *role_name) {
65    assert(principal_name != NULL);
[9a411d7]66    assert(role_name != NULL);
[7f25a67f]67
[1743825]68    abac_role_t *role;
[7f25a67f]69
[202a7f9]70    if (strlen(principal_name) == 0 || strlen(role_name) == 0)
[7f25a67f]71        return NULL;
72
[3c251d0]73    role = abac_xmalloc(sizeof(abac_role_t));
[7f25a67f]74
[202a7f9]75    role->principal_name = abac_xstrdup(principal_name);
[7727f26]76
[9a411d7]77    role->role_name = abac_xstrdup(role_name);
[202a7f9]78    role->role_params = NULL;
79
80    role->linked_role_name = NULL;
81    role->linked_role_params = NULL;
[7f25a67f]82
[202a7f9]83    int prin_len = strlen(principal_name);
[9a411d7]84    int role_len = strlen(role_name);
[7e05a2f]85
[7727f26]86    if(debug)
87        printf("DEBUG:adding a new role (%s) to principal (%s)\n",
88                     role->role_name, role->principal_name);
89
[9a411d7]90    role->string = abac_xmalloc(prin_len + 1 + role_len + 1);
[202a7f9]91    memcpy(role->string, principal_name, prin_len);
[7e05a2f]92    role->string[prin_len] = '.';
[9a411d7]93    memcpy(role->string + prin_len + 1, role_name, role_len);
94    role->string[prin_len + 1 + role_len] = 0;
[7e05a2f]95
[202a7f9]96
[d4cbf71]97    role->linked = NULL;
[9a411d7]98    role->prereqs = NULL;
[d4cbf71]99
[fbb591e]100    role->refcount = 1;
101
[7f25a67f]102    return role;
103}
104
105/**
106 * Created a new linking role and initialize it.
107 */
[202a7f9]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);
[9a411d7]111    assert(role_name != NULL);
[7f25a67f]112
[1743825]113    abac_role_t *role;
[7f25a67f]114
[202a7f9]115    if (strlen(principal_name) == 0 || strlen(linked_role_name) == 0 || strlen(role_name) == 0)
[7f25a67f]116        return NULL;
117
[3c251d0]118    role = abac_xmalloc(sizeof(abac_role_t));
[7f25a67f]119
[202a7f9]120    role->principal_name = abac_xstrdup(principal_name);
121    role->linked_role_name = abac_xstrdup(linked_role_name);
122    role->linked_role_params = NULL;
[9a411d7]123    role->role_name = abac_xstrdup(role_name);
[202a7f9]124    role->role_params = NULL;
[7f25a67f]125
[7727f26]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);
[202a7f9]132    int link_len = strlen(linked_role_name);
[9a411d7]133    int role_len = strlen(role_name);
[7e05a2f]134
[9a411d7]135    role->string = abac_xmalloc(prin_len + 1 + link_len + 1 + role_len + 1);
[7e05a2f]136
[7727f26]137    memcpy(role->string, role->principal_name, prin_len);
[7e05a2f]138    role->string[prin_len] = '.';
[202a7f9]139    memcpy(role->string + prin_len + 1, linked_role_name, link_len);
[d4cbf71]140    role->string[prin_len + 1 + link_len] = 0;
141
142    // hack: linked role is first two parts of full string
[3c251d0]143    role->linked = abac_xstrdup(role->string);
[d4cbf71]144
[7e05a2f]145    role->string[prin_len + 1 + link_len] = '.';
[9a411d7]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
[202a7f9]161    role->principal_name = role->linked_role_name = role->role_name = NULL;
162    role->linked_role_params = NULL;
163    role->role_params = NULL;
[9a411d7]164
[202a7f9]165    role->linked = NULL;
[9a411d7]166    role->string = abac_xstrdup(name);
167    role->prereqs = prereqs;
[7e05a2f]168
[fbb591e]169    role->refcount = 1;
170
[7f25a67f]171    return role;
172}
173
[c66e07c]174/**
[fbb591e]175 * Decrease a role's reference count, freeing it when it reaches 0.
[c66e07c]176 */
[dcc1a8e]177void abac_role_free(abac_role_t *role) {
[202a7f9]178
179    if(debug)
180        printf("DEBUG:trying to freeing a role %d\n",(int)role);
181 
[c66e07c]182    if (role == NULL)
183        return;
184
[202a7f9]185    if(debug)
186        printf("DEBUG:freeing a role %d\n",(int)role);
187
[fbb591e]188    --role->refcount;
189    if (role->refcount > 0)
190        return;
191
[da5afdf]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);
[c66e07c]195
[da5afdf]196    if(role->string) free(role->string);
197    if(role->linked) free(role->linked);
[7e05a2f]198
[202a7f9]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
[9a411d7]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
[c66e07c]215    free(role);
216}
217
[da5afdf]218abac_role_t *abac_role_role_add_param(abac_role_t *role, abac_term_t *param)
[202a7f9]219{
220     if(role->role_params == NULL) {
221        role->role_params=abac_param_list_new(param);
222        } else {
[da5afdf]223            abac_param_list_add_term(role->role_params, param);
[202a7f9]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
[da5afdf]234abac_role_t *abac_role_role_add_linked_param(abac_role_t *role, abac_term_t *param)
[202a7f9]235{
236     if(role->linked_role_params == NULL) {
237        role->linked_role_params=abac_param_list_new(param);
238        } else {
[da5afdf]239            abac_param_list_add_term(role->linked_role_params, param);
[202a7f9]240     }
241     return role;
242}
243
244
[7f25a67f]245/**
[9a411d7]246 * Create a non-intersecting role from a string. Handles principals, roles,
247 * and linking roles.
[7f25a67f]248 */
[9a411d7]249static abac_role_t *_abac_single_role_from_string(char *string) {
[7f25a67f]250    int num_dots = 0;
251    char *dot = string;
[9a411d7]252    abac_role_t *ret = NULL;
[7f25a67f]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)
[9a411d7]262        ret = abac_role_principal_new(string);
[7f25a67f]263
264    // a role has exactly 1 dot
[9a411d7]265    else if (num_dots == 1) {
[7f25a67f]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
[9a411d7]273        char *role_name = dot + 1;
[7f25a67f]274
275        // create the role (if possible)
[9a411d7]276        ret = abac_role_role_new(string, role_name);
[7f25a67f]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
[9a411d7]293        char *role_name = dot + 1;
[7f25a67f]294
[9a411d7]295        ret = abac_role_linking_new(principal, linked, role_name);
[7f25a67f]296    }
297
298    // more than two dots: return NULL
299
[9a411d7]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);
[7f25a67f]323
[9a411d7]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);
[7f25a67f]339    return ret;
[9a411d7]340
341error:
[202a7f9]342
[9a411d7]343    if (prereqs != NULL) {
[202a7f9]344       abac_role_t *cur;
345       abac_list_foreach(prereqs, cur,
346           abac_role_free(cur);
347       );
348       abac_list_free(prereqs);
[9a411d7]349    }
350    free(string);
351    return NULL;
[7f25a67f]352}
353
[9a411d7]354
[ea401bc]355/**
[fbb591e]356 * Increase a role's reference count.
[ea401bc]357 */
[dcc1a8e]358abac_role_t *abac_role_dup(abac_role_t *role) {
[fbb591e]359    assert(role != NULL);
[ea401bc]360
[fbb591e]361    ++role->refcount;
362    return role;
[ea401bc]363}
364
[7f25a67f]365/**
366 * True if a role is a principal.
367 */
[dcc1a8e]368int abac_role_is_principal(abac_role_t *role) {
[7f25a67f]369    assert(role != NULL);
[202a7f9]370    return role->role_name == NULL && role->linked_role_name == NULL && role->prereqs == NULL;
[7f25a67f]371}
372
373/**
374 * True if a role is a role.
375 */
[dcc1a8e]376int abac_role_is_role(abac_role_t *role) {
[7f25a67f]377    assert(role != NULL);
[202a7f9]378    return role->role_name != NULL && role->linked_role_name == NULL && role->prereqs == NULL; 
[7f25a67f]379}
380
381/**
382 * True if a role is a linked role.
383 */
[dcc1a8e]384int abac_role_is_linking(abac_role_t *role) {
[7f25a67f]385    assert(role != NULL);
[202a7f9]386    return role->linked_role_name != NULL;
[7f25a67f]387}
388
[9a411d7]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
[202a7f9]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}
[7e05a2f]414/**
415 * Returns the string representation of the role.
[202a7f9]416 * principal.role(params..)
[7e05a2f]417 */
[202a7f9]418char *abac_role_string_with_condition(abac_role_t *role) {
[7e05a2f]419    assert(role != NULL);
[202a7f9]420
421    if(abac_role_is_intersection(role)) {
422        return abac_role_intersecting_string_with_condition(role);
423    }
424
425    char *tmp=NULL;
[7727f26]426    char *principal_name = abac_role_principal_name(role);
[202a7f9]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}
[923b4dd]481char *abac_role_string(abac_role_t *role) { 
482    abac_role_string_with_condition(role);
483}
[202a7f9]484
[da5afdf]485void abac_print_role_string_with_condition(abac_role_t *role,FILE *fp)
[202a7f9]486{
487    char *string=abac_role_string_with_condition(role);
[da5afdf]488    if(fp==NULL)
[7727f26]489        printf("%s ",string);
490        else fprintf(fp,"%s ",string);
[7f25a67f]491}
[d4cbf71]492
[ebde9dd]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 */
[dcc1a8e]497char *abac_role_role_name(abac_role_t *role) {
[ebde9dd]498    assert(role != NULL);
[9a411d7]499    return role->role_name;
[ebde9dd]500}
501
[da5afdf]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
[d4cbf71]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 */
[dcc1a8e]514char *abac_role_linked_role(abac_role_t *role) {
[d4cbf71]515    assert(role != NULL);
[202a7f9]516    return role->linked_role_name;
[d4cbf71]517}
[c03fe9b]518
519/**
520 * Returns the principal part of a role. The stuff before the first dot.
521 */
[7727f26]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) {
[c03fe9b]528    assert(role != NULL);
[7727f26]529    if(USE("ABAC_CN"))
530        return abac_cn_with_sha(role->principal_name);
[202a7f9]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);
[c03fe9b]537}
[85f33fd]538
[9a411d7]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
[202a7f9]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
[85f33fd]558/**
559 * Build an attribute key from head and tail roles. Static.
560 */
561#define ROLE_SEPARATOR " <- "
[dcc1a8e]562char *abac_role_attr_key(abac_role_t *head_role, abac_role_t *tail_role) {
[202a7f9]563    char *head = abac_role_string_with_condition(head_role);
[85f33fd]564    int head_len = strlen(head);
565
[202a7f9]566    char *tail = abac_role_string_with_condition(tail_role);
[85f33fd]567    int tail_len = strlen(tail);
568
569    int sep_len = sizeof(ROLE_SEPARATOR) - 1;
570
571    // "head <- tail"
[3c251d0]572    char *ret = abac_xmalloc(head_len + tail_len + sep_len + 1);
[85f33fd]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.