source: libabac/abac_role.c @ 718ad924

mei_rt2mei_rt2_fix_1meiyap-rt1rt2
Last change on this file since 718ad924 was 53e540d, checked in by Mei <mei@…>, 13 years ago

1) adding appendL to do the credential list appending

  • Property mode set to 100644
File size: 9.1 KB
Line 
1#include <assert.h>
2#include <stdlib.h>
3#include <stdio.h>
4#include <string.h>
5
6#include "abac.h"
7#include "abac_list.h"
8#include "abac_util.h"
9
10// typedef'd in role.h
11struct _abac_role_t {
12    char *principal;
13    char *linked_role;
14    char *role_name;
15
16    char *string;
17    char *linked;
18
19    abac_list_t *prereqs;
20
21    int refcount;
22};
23
24/**
25 * Create a new principal and initialize it.
26 */
27abac_role_t *abac_role_principal_new(char *principal) {
28    assert(principal != NULL);
29
30    abac_role_t *role;
31
32    if (strlen(principal) == 0)
33        return NULL;
34
35    role = abac_xmalloc(sizeof(abac_role_t));
36
37    /* XXX */
38
39    role->principal = abac_xstrdup(principal);
40    role->role_name = NULL;
41    role->linked_role = NULL;
42
43    role->string = abac_xstrdup(principal);
44    role->linked = NULL;
45    role->prereqs = NULL;
46
47    role->refcount = 1;
48
49    return role;
50}
51
52/**
53 * Create a new role and initialize it.
54 */
55abac_role_t *abac_role_role_new(char *principal, char *role_name) {
56    assert(principal != NULL);
57    assert(role_name != NULL);
58
59    abac_role_t *role;
60
61    if (strlen(principal) == 0 || strlen(role_name) == 0)
62        return NULL;
63
64    /* MEI */
65    printf("XXX adding a new role (%s) to principal (%s)\n", role_name, principal);
66
67    role = abac_xmalloc(sizeof(abac_role_t));
68
69    role->principal = abac_xstrdup(principal);
70    role->role_name = abac_xstrdup(role_name);
71    role->linked_role = NULL;
72
73    int prin_len = strlen(principal);
74    int role_len = strlen(role_name);
75
76    role->string = abac_xmalloc(prin_len + 1 + role_len + 1);
77    memcpy(role->string, principal, prin_len);
78    role->string[prin_len] = '.';
79    memcpy(role->string + prin_len + 1, role_name, role_len);
80    role->string[prin_len + 1 + role_len] = 0;
81
82    role->linked = NULL;
83    role->prereqs = NULL;
84
85    role->refcount = 1;
86
87    return role;
88}
89
90/**
91 * Created a new linking role and initialize it.
92 */
93abac_role_t *abac_role_linking_new(char *principal, char *linked, char *role_name) {
94    assert(principal != NULL);
95    assert(linked != NULL);
96    assert(role_name != NULL);
97
98    abac_role_t *role;
99
100    if (strlen(principal) == 0 || strlen(linked) == 0 || strlen(role_name) == 0)
101        return NULL;
102
103    /* MEI */
104    printf(" XXX adding a new linked (%s) to role(%s) for principal(%s)\n",
105                        linked, role_name, principal);
106
107    role = abac_xmalloc(sizeof(abac_role_t));
108
109    role->principal = abac_xstrdup(principal);
110    role->linked_role = abac_xstrdup(linked);
111    role->role_name = abac_xstrdup(role_name);
112
113    int prin_len = strlen(principal);
114    int link_len = strlen(linked);
115    int role_len = strlen(role_name);
116
117    role->string = abac_xmalloc(prin_len + 1 + link_len + 1 + role_len + 1);
118
119    memcpy(role->string, principal, prin_len);
120    role->string[prin_len] = '.';
121    memcpy(role->string + prin_len + 1, linked, link_len);
122    role->string[prin_len + 1 + link_len] = 0;
123
124    // hack: linked role is first two parts of full string
125    role->linked = abac_xstrdup(role->string);
126
127    role->string[prin_len + 1 + link_len] = '.';
128    memcpy(role->string + prin_len + 1 + link_len + 1, role_name, role_len);
129    role->string[prin_len + 1 + link_len + 1 + role_len] = 0;
130
131    role->prereqs = NULL;
132
133    role->refcount = 1;
134
135    return role;
136}
137
138/**
139 * Create an intersection role.
140 */
141abac_role_t *abac_role_intersection_new(char *name, abac_list_t *prereqs) {
142    abac_role_t *role = abac_xmalloc(sizeof(abac_role_t));
143
144    role->principal = role->linked_role = role->role_name = NULL;
145    role->linked = NULL;
146
147    role->string = abac_xstrdup(name);
148    role->prereqs = prereqs;
149
150    role->refcount = 1;
151
152    return role;
153}
154
155/**
156 * Decrease a role's reference count, freeing it when it reaches 0.
157 */
158void abac_role_free(abac_role_t *role) {
159    if (role == NULL)
160        return;
161
162    --role->refcount;
163    if (role->refcount > 0)
164        return;
165
166    free(role->principal);
167    free(role->linked_role);
168    free(role->role_name);
169
170    free(role->string);
171    free(role->linked);
172
173    if (role->prereqs != NULL) {
174        abac_role_t *cur;
175        abac_list_foreach(role->prereqs, cur,
176            abac_role_free(cur);
177        );
178        abac_list_free(role->prereqs);
179    }
180
181    free(role);
182}
183
184/**
185 * Create a non-intersecting role from a string. Handles principals, roles,
186 * and linking roles.
187 */
188static abac_role_t *_abac_single_role_from_string(char *string) {
189    int num_dots = 0;
190    char *dot = string;
191    abac_role_t *ret = NULL;
192
193    // count the dots
194    while ((dot = strchr(dot, '.')) != NULL) {
195        ++num_dots;
196        ++dot;
197    }
198
199    // no dots: easy case, principal
200    if (num_dots == 0)
201        ret = abac_role_principal_new(string);
202
203    // a role has exactly 1 dot
204    else if (num_dots == 1) {
205        char *principal = string;
206
207        // terminate the principal part
208        dot = strchr(principal, '.');
209        *dot = 0;
210
211        // role name comes after the dot
212        char *role_name = dot + 1;
213
214        // create the role (if possible)
215        ret = abac_role_role_new(string, role_name);
216    }
217
218    // a linked role has 2 dots
219    else if (num_dots == 2) {
220        char *principal = string;
221
222        // terminate the principal part
223        dot = strchr(principal, '.');
224        *dot = 0;
225
226        // linked name is next, terminate it
227        char *linked = dot + 1;
228        dot = strchr(linked, '.');
229        *dot = 0;
230
231        // role name is last, already terminated
232        char *role_name = dot + 1;
233
234        ret = abac_role_linking_new(principal, linked, role_name);
235    }
236
237    // more than two dots: return NULL
238
239    return ret;
240}
241
242/**
243 * Create a role from a string. Handles intersecting and normal roles.
244 */
245abac_role_t *abac_role_from_string(char *string) {
246    abac_list_t *prereqs = NULL;
247    abac_role_t *ret = NULL, *role;
248    char *roles[256];
249    int num_roles, i;
250
251    char *original = string;
252
253    // make a copy so we can mess with it
254    string = abac_xstrdup(string);
255
256    // split the string (in case of an intersection num_roles > 1)
257    abac_split(string, " & ", roles, &num_roles);
258
259    // normal role:
260    if (num_roles == 1)
261        ret = _abac_single_role_from_string(string);
262
263    else {
264        prereqs = abac_list_new();
265
266        for (i = 0; i < num_roles; ++i) {
267            // make sure the tail role is valid
268            role = abac_role_from_string(roles[i]);
269            if (role == NULL)
270                goto error;
271
272            abac_list_add(prereqs, role);
273        }
274
275        ret = abac_role_intersection_new(original, prereqs);
276    }
277
278    free(string);
279    return ret;
280
281error:
282    if (prereqs != NULL) {
283        abac_list_foreach(prereqs, role,
284            abac_role_free(role);
285        );
286        abac_list_free(prereqs);
287    }
288    free(string);
289
290    return NULL;
291}
292
293
294/**
295 * Increase a role's reference count.
296 */
297abac_role_t *abac_role_dup(abac_role_t *role) {
298    assert(role != NULL);
299
300    ++role->refcount;
301    return role;
302}
303
304/**
305 * True if a role is a principal.
306 */
307int abac_role_is_principal(abac_role_t *role) {
308    assert(role != NULL);
309    return role->role_name == NULL && role->linked_role == NULL && role->prereqs == NULL;
310}
311
312/**
313 * True if a role is a role.
314 */
315int abac_role_is_role(abac_role_t *role) {
316    assert(role != NULL);
317    return role->role_name != NULL && role->linked_role == NULL && role->prereqs == NULL; 
318}
319
320/**
321 * True if a role is a linked role.
322 */
323int abac_role_is_linking(abac_role_t *role) {
324    assert(role != NULL);
325    return role->linked_role != NULL;
326}
327
328/**
329 * True if a role is an intersection.
330 */
331int abac_role_is_intersection(abac_role_t *role) {
332    assert(role != NULL);
333    return role->prereqs != NULL;
334}
335
336/**
337 * Returns the string representation of the role.
338 */
339char *abac_role_string(abac_role_t *role) {
340    assert(role != NULL);
341    return role->string;
342}
343
344/**
345 * Returns the name of a role. If the role is A.r1 then return r1. If the role
346 * is A.r1.r2 then return r2.
347 */
348char *abac_role_role_name(abac_role_t *role) {
349    assert(role != NULL);
350    return role->role_name;
351}
352
353/**
354 * Returns the linked part of a linking role. For instance, if the role is
355 * A.r1.r2, this returns A.r1.
356 */
357char *abac_role_linked_role(abac_role_t *role) {
358    assert(role != NULL);
359    return role->linked;
360}
361
362/**
363 * Returns the principal part of a role. The stuff before the first dot.
364 */
365char *abac_role_principal(abac_role_t *role) {
366    assert(role != NULL);
367    return role->principal;
368}
369
370/**
371 * Returns the prereqs of an intersection.
372 */
373abac_list_t *abac_role_prereqs(abac_role_t *role) {
374    assert(role != NULL);
375    return role->prereqs;
376}
377
378/**
379 * Build an attribute key from head and tail roles. Static.
380 */
381#define ROLE_SEPARATOR " <- "
382char *abac_role_attr_key(abac_role_t *head_role, abac_role_t *tail_role) {
383    char *head = abac_role_string(head_role);
384    int head_len = strlen(head);
385
386    char *tail = abac_role_string(tail_role);
387    int tail_len = strlen(tail);
388
389    int sep_len = sizeof(ROLE_SEPARATOR) - 1;
390
391    // "head <- tail"
392    char *ret = abac_xmalloc(head_len + tail_len + sep_len + 1);
393    memcpy(ret, head, head_len);
394    memcpy(ret + head_len, ROLE_SEPARATOR, sep_len);
395    memcpy(ret + head_len + sep_len, tail, tail_len);
396    ret[head_len + sep_len + tail_len] = 0;
397
398    return ret;
399}
Note: See TracBrowser for help on using the repository browser.