source: libabac/abac_role.c @ c0fe894

abac0-leak
Last change on this file since c0fe894 was 94605f2, checked in by Ted Faber <faber@…>, 11 years ago

checkpoint Lots of the way toward mnemonic names, some parsing fixes

  • 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
199    if (num_dots == 0)
[9a411d7]200        ret = abac_role_principal_new(string);
[7f25a67f]201
202    // a role has exactly 1 dot
[9a411d7]203    else if (num_dots == 1) {
[7f25a67f]204        char *principal = string;
205
206        // terminate the principal part
207        dot = strchr(principal, '.');
208        *dot = 0;
209
210        // role name comes after the dot
[9a411d7]211        char *role_name = dot + 1;
[7f25a67f]212
213        // create the role (if possible)
[9a411d7]214        ret = abac_role_role_new(string, role_name);
[7f25a67f]215    }
216
217    // a linked role has 2 dots
218    else if (num_dots == 2) {
219        char *principal = string;
220
221        // terminate the principal part
222        dot = strchr(principal, '.');
223        *dot = 0;
224
225        // linked name is next, terminate it
226        char *linked = dot + 1;
227        dot = strchr(linked, '.');
228        *dot = 0;
229
230        // role name is last, already terminated
[9a411d7]231        char *role_name = dot + 1;
[7f25a67f]232
[9a411d7]233        ret = abac_role_linking_new(principal, linked, role_name);
[7f25a67f]234    }
235
236    // more than two dots: return NULL
237
[9a411d7]238    return ret;
239}
240
241/**
242 * Create a role from a string. Handles intersecting and normal roles.
243 */
244abac_role_t *abac_role_from_string(char *string) {
245    abac_list_t *prereqs = NULL;
246    abac_role_t *ret = NULL, *role;
247    char *roles[256];
248    int num_roles, i;
249
250    char *original = string;
251
252    // make a copy so we can mess with it
253    string = abac_xstrdup(string);
254
255    // split the string (in case of an intersection num_roles > 1)
[9f78e4c]256    num_roles = 256;
[9a411d7]257    abac_split(string, " & ", roles, &num_roles);
258
259    // normal role:
260    if (num_roles == 1)
261        ret = _abac_single_role_from_string(string);
[7f25a67f]262
[9a411d7]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);
[7f25a67f]279    return ret;
[9a411d7]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;
[7f25a67f]291}
292
[9a411d7]293
[ea401bc]294/**
[fbb591e]295 * Increase a role's reference count.
[ea401bc]296 */
[dcc1a8e]297abac_role_t *abac_role_dup(abac_role_t *role) {
[fbb591e]298    assert(role != NULL);
[ea401bc]299
[fbb591e]300    ++role->refcount;
301    return role;
[ea401bc]302}
303
[7f25a67f]304/**
305 * True if a role is a principal.
306 */
[dcc1a8e]307int abac_role_is_principal(abac_role_t *role) {
[7f25a67f]308    assert(role != NULL);
[9a411d7]309    return role->role_name == NULL && role->linked_role == NULL && role->prereqs == NULL;
[7f25a67f]310}
311
312/**
313 * True if a role is a role.
314 */
[dcc1a8e]315int abac_role_is_role(abac_role_t *role) {
[7f25a67f]316    assert(role != NULL);
[9a411d7]317    return role->role_name != NULL && role->linked_role == NULL && role->prereqs == NULL; 
[7f25a67f]318}
319
320/**
321 * True if a role is a linked role.
322 */
[dcc1a8e]323int abac_role_is_linking(abac_role_t *role) {
[7f25a67f]324    assert(role != NULL);
325    return role->linked_role != NULL;
326}
327
[9a411d7]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
[7e05a2f]336/**
337 * Returns the string representation of the role.
338 */
[dcc1a8e]339char *abac_role_string(abac_role_t *role) {
[7e05a2f]340    assert(role != NULL);
341    return role->string;
[7f25a67f]342}
[d4cbf71]343
[94605f2]344/**
345 * Returns the string representation of the role, with keyids converted to
346 * mnemonic names where possible.  The return value must *not* be freed.
347 */
348char *abac_role_short_string(abac_role_t *role, abac_context_t *ctxt) {
349    assert(role != NULL);
350    if (!ctxt) return role->string;
351    if ( role->short_string) 
352        free(role->short_string);
353    role->short_string = abac_context_expand_key(ctxt, role->string);
354    return role->short_string;
355}
356
[ebde9dd]357/**
358 * Returns the name of a role. If the role is A.r1 then return r1. If the role
359 * is A.r1.r2 then return r2.
360 */
[dcc1a8e]361char *abac_role_role_name(abac_role_t *role) {
[ebde9dd]362    assert(role != NULL);
[9a411d7]363    return role->role_name;
[ebde9dd]364}
365
[d4cbf71]366/**
367 * Returns the linked part of a linking role. For instance, if the role is
368 * A.r1.r2, this returns A.r1.
369 */
[dcc1a8e]370char *abac_role_linked_role(abac_role_t *role) {
[d4cbf71]371    assert(role != NULL);
372    return role->linked;
373}
[c03fe9b]374
[e50f807]375/**
376 * Returns the linkinged part of a linking role. For instance, if the role is
377 * A.r1.r2, this returns r1.
378 */
379char *abac_role_linking_role(abac_role_t *role) {
380    assert(role != NULL);
381    return role->linked_role;
382}
383
[c03fe9b]384/**
385 * Returns the principal part of a role. The stuff before the first dot.
386 */
[dcc1a8e]387char *abac_role_principal(abac_role_t *role) {
[c03fe9b]388    assert(role != NULL);
389    return role->principal;
390}
[85f33fd]391
[9a411d7]392/**
393 * Returns the prereqs of an intersection.
394 */
395abac_list_t *abac_role_prereqs(abac_role_t *role) {
396    assert(role != NULL);
397    return role->prereqs;
398}
399
[85f33fd]400/**
401 * Build an attribute key from head and tail roles. Static.
402 */
403#define ROLE_SEPARATOR " <- "
[dcc1a8e]404char *abac_role_attr_key(abac_role_t *head_role, abac_role_t *tail_role) {
405    char *head = abac_role_string(head_role);
[85f33fd]406    int head_len = strlen(head);
407
[dcc1a8e]408    char *tail = abac_role_string(tail_role);
[85f33fd]409    int tail_len = strlen(tail);
410
411    int sep_len = sizeof(ROLE_SEPARATOR) - 1;
412
413    // "head <- tail"
[3c251d0]414    char *ret = abac_xmalloc(head_len + tail_len + sep_len + 1);
[85f33fd]415    memcpy(ret, head, head_len);
416    memcpy(ret + head_len, ROLE_SEPARATOR, sep_len);
417    memcpy(ret + head_len + sep_len, tail, tail_len);
418    ret[head_len + sep_len + tail_len] = 0;
419
420    return ret;
421}
Note: See TracBrowser for help on using the repository browser.