source: libabac/abac_role.c @ 91a6b20

abac0-leak
Last change on this file since 91a6b20 was f2622ee, checked in by Mei-Hui Su <mei@…>, 11 years ago

1) ran with valgrind and did some leak patching

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