source: libabac/abac_role.c @ 202a7f9

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

commited modified files for rt1

  • Property mode set to 100644
File size: 13.8 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    free(role->principal_name);
196    free(role->linked_role_name);
197    free(role->role_name);
198
199    free(role->string);
200    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, int type, char *name, char *cond)
222{
223     abac_param_t *param=abac_param_new(type,name,cond);
224     if(role->role_params == NULL) {
225        role->role_params=abac_param_list_new(param);
226        } else {
227            abac_param_list_add_param(role->role_params, param);
228     }
229     return role;
230}
231
232abac_role_t *abac_role_add_intersecting_role(abac_role_t *role, abac_role_t *nrole)
233{
234     abac_list_add(role->prereqs, nrole);
235     return role;
236}
237
238abac_role_t *abac_role_role_add_linked_param(abac_role_t *role, int type, char *name, char *cond)
239{
240     abac_param_t *param=abac_param_new(type,name,cond);
241     if(role->linked_role_params == NULL) {
242        role->linked_role_params=abac_param_list_new(param);
243        } else {
244            abac_param_list_add_param(role->linked_role_params, param);
245     }
246     return role;
247}
248
249
250/**
251 * Create a non-intersecting role from a string. Handles principals, roles,
252 * and linking roles.
253 */
254static abac_role_t *_abac_single_role_from_string(char *string) {
255    int num_dots = 0;
256    char *dot = string;
257    abac_role_t *ret = NULL;
258
259    // count the dots
260    while ((dot = strchr(dot, '.')) != NULL) {
261        ++num_dots;
262        ++dot;
263    }
264
265    // no dots: easy case, principal
266    if (num_dots == 0)
267        ret = abac_role_principal_new(string);
268
269    // a role has exactly 1 dot
270    else if (num_dots == 1) {
271        char *principal = string;
272
273        // terminate the principal part
274        dot = strchr(principal, '.');
275        *dot = 0;
276
277        // role name comes after the dot
278        char *role_name = dot + 1;
279
280        // create the role (if possible)
281        ret = abac_role_role_new(string, role_name);
282    }
283
284    // a linked role has 2 dots
285    else if (num_dots == 2) {
286        char *principal = string;
287
288        // terminate the principal part
289        dot = strchr(principal, '.');
290        *dot = 0;
291
292        // linked name is next, terminate it
293        char *linked = dot + 1;
294        dot = strchr(linked, '.');
295        *dot = 0;
296
297        // role name is last, already terminated
298        char *role_name = dot + 1;
299
300        ret = abac_role_linking_new(principal, linked, role_name);
301    }
302
303    // more than two dots: return NULL
304
305    return ret;
306}
307
308/**
309 * Create a role from a string. Handles intersecting and normal roles.
310 */
311abac_role_t *abac_role_from_string(char *string) {
312    abac_list_t *prereqs = NULL;
313    abac_role_t *ret = NULL, *role;
314    char *roles[256];
315    int num_roles, i;
316
317    char *original = string;
318
319    // make a copy so we can mess with it
320    string = abac_xstrdup(string);
321
322    // split the string (in case of an intersection num_roles > 1)
323    abac_split(string, " & ", roles, &num_roles);
324
325    // normal role:
326    if (num_roles == 1)
327        ret = _abac_single_role_from_string(string);
328
329    else {
330        prereqs = abac_list_new();
331
332        for (i = 0; i < num_roles; ++i) {
333            // make sure the tail role is valid
334            role = abac_role_from_string(roles[i]);
335            if (role == NULL)
336                goto error;
337
338            abac_list_add(prereqs, role);
339        }
340        ret = abac_role_intersection_new(original, prereqs);
341    }
342
343    free(string);
344    return ret;
345
346error:
347
348    if (prereqs != NULL) {
349       abac_role_t *cur;
350       abac_list_foreach(prereqs, cur,
351           abac_role_free(cur);
352       );
353       abac_list_free(prereqs);
354    }
355    free(string);
356    return NULL;
357}
358
359
360/**
361 * Increase a role's reference count.
362 */
363abac_role_t *abac_role_dup(abac_role_t *role) {
364    assert(role != NULL);
365
366    ++role->refcount;
367    return role;
368}
369
370/**
371 * True if a role is a principal.
372 */
373int abac_role_is_principal(abac_role_t *role) {
374    assert(role != NULL);
375    return role->role_name == NULL && role->linked_role_name == NULL && role->prereqs == NULL;
376}
377
378/**
379 * True if a role is a role.
380 */
381int abac_role_is_role(abac_role_t *role) {
382    assert(role != NULL);
383    return role->role_name != NULL && role->linked_role_name == NULL && role->prereqs == NULL; 
384}
385
386/**
387 * True if a role is a linked role.
388 */
389int abac_role_is_linking(abac_role_t *role) {
390    assert(role != NULL);
391    return role->linked_role_name != NULL;
392}
393
394/**
395 * True if a role is an intersection.
396 */
397int abac_role_is_intersection(abac_role_t *role) {
398    assert(role != NULL);
399    return role->prereqs != NULL;
400}
401
402char *abac_role_intersecting_string_with_condition(abac_role_t *role)
403{
404    assert(role != NULL);
405    char *tmp=NULL;
406    if (role->prereqs != NULL) {
407        abac_role_t *cur;
408        abac_list_foreach(role->prereqs, cur,
409            char *ntmp=abac_role_string_with_condition(cur);
410            if(tmp==NULL) {
411                asprintf(&tmp,"%s",ntmp);
412                } else {
413                    asprintf(&tmp,"%s & %s",tmp, ntmp);
414            }
415        );
416    }
417    return tmp;
418}
419/**
420 * Returns the string representation of the role.
421 * principal.role(params..)
422 */
423char *abac_role_string_with_condition(abac_role_t *role) {
424    assert(role != NULL);
425
426    if(abac_role_is_intersection(role)) {
427        return abac_role_intersecting_string_with_condition(role);
428    }
429
430    char *tmp=NULL;
431/* use cn for now, easy to debug XXX */
432    char *principal_name = abac_role_principal_cn(role);
433    char *role_name= role->role_name;
434    char *linked_role_name = role->linked_role_name;
435    char *params_string=NULL;
436    char *linked_params_string=NULL;
437
438    int len = 0;
439    if(principal_name)
440        len=len+strlen(principal_name)+1;
441    if(role_name)
442        len = len+strlen(role_name)+1;
443    if(linked_role_name)
444        len = len+strlen(linked_role_name)+1;
445
446    if(role->role_params) {
447         params_string=abac_param_list_string_with_condition(role->role_params);
448         len = len+strlen(params_string)+3;
449    } 
450    if(role->linked_role_params) {
451         linked_params_string=abac_param_list_string_with_condition(role->linked_role_params);
452         len = len+strlen(linked_params_string)+3;
453    }
454
455    /* principal */
456    /* principal.role */
457    /* principal.role(params_string) */
458    /* principal.linked_role(linked_params_string).role(params_string) */
459    tmp = abac_xmalloc(len);
460
461    if(principal_name)
462        sprintf(tmp,"%s",principal_name);
463
464    if(linked_role_name) {
465        strcat(tmp,".");
466        strcat(tmp,linked_role_name);
467    }
468    if(linked_params_string) {
469        strcat(tmp,"(");
470        strcat(tmp,linked_params_string);
471        strcat(tmp,")");
472    }
473    if(role_name) {
474        strcat(tmp,".");
475        strcat(tmp,role_name);
476    }
477    if(params_string) {
478        strcat(tmp,"(");
479        strcat(tmp,params_string);
480        strcat(tmp,")");
481    }
482
483    if(linked_params_string) free(linked_params_string);
484    if(params_string) free(params_string);
485    return tmp;
486}
487
488void abac_print_role_string_with_condition(abac_role_t *role)
489{
490    char *string=abac_role_string_with_condition(role);
491    printf("%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
503/**
504 * Returns the linked part of a linking role. For instance, if the role is
505 * A.r1.r2, this returns A.r1.
506 */
507char *abac_role_linked_role(abac_role_t *role) {
508    assert(role != NULL);
509    return role->linked_role_name;
510}
511
512/**
513 * Returns the principal part of a role. The stuff before the first dot.
514 */
515char *abac_role_principal(abac_role_t *role) {
516    assert(role != NULL);
517    return role->principal_name;
518}
519
520char *abac_role_principal_cn(abac_role_t *role) {
521    assert(role != NULL);
522    return abac_cn_with_sha(role->principal_name);
523}
524
525/**
526 * Returns the prereqs of an intersection.
527 */
528abac_list_t *abac_role_prereqs(abac_role_t *role) {
529    assert(role != NULL);
530    return role->prereqs;
531}
532
533abac_param_list_t *abac_role_linked_role_params(abac_role_t *role) {
534    assert(role != NULL);
535    return role->linked_role_params;
536}
537
538abac_param_list_t *abac_role_role_params(abac_role_t *role) {
539    assert(role != NULL);
540    return role->role_params;
541}
542
543
544/**
545 * Build an attribute key from head and tail roles. Static.
546 */
547#define ROLE_SEPARATOR " <- "
548char *abac_role_attr_key(abac_role_t *head_role, abac_role_t *tail_role) {
549    char *head = abac_role_string_with_condition(head_role);
550    int head_len = strlen(head);
551
552    char *tail = abac_role_string_with_condition(tail_role);
553    int tail_len = strlen(tail);
554
555    int sep_len = sizeof(ROLE_SEPARATOR) - 1;
556
557    // "head <- tail"
558    char *ret = abac_xmalloc(head_len + tail_len + sep_len + 1);
559    memcpy(ret, head, head_len);
560    memcpy(ret + head_len, ROLE_SEPARATOR, sep_len);
561    memcpy(ret + head_len + sep_len, tail, tail_len);
562    ret[head_len + sep_len + tail_len] = 0;
563
564    return ret;
565}
Note: See TracBrowser for help on using the repository browser.