source: libabac/abac_role.c @ da5afdf

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

1) add static contraint

(limited to integer at this time)

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