source: libabac/abac_role.c @ fbb591e

abac0-leakabac0-meicompt_changesgec13mei-idmei-rt0-nmei_rt0mei_rt2mei_rt2_fix_1meiyap-rt1meiyap1rt2tvf-new-xml
Last change on this file since fbb591e was fbb591e, checked in by Mike Ryan <mikeryan@…>, 14 years ago

reference count roles and credentials

  • Property mode set to 100644
File size: 6.8 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_util.h"
8
9// typedef'd in role.h
10struct _abac_role_t {
11    char *principal;
12    char *linked_role;
13    char *abac_role_name;
14
15    char *string;
16    char *linked;
17
18    int refcount;
19};
20
21/**
22 * Create a new principal and initialize it.
23 */
24abac_role_t *abac_role_principal_new(char *principal) {
25    assert(principal != NULL);
26
27    abac_role_t *role;
28
29    if (strlen(principal) == 0)
30        return NULL;
31
32    role = abac_xmalloc(sizeof(abac_role_t));
33
34    role->principal = abac_xstrdup(principal);
35    role->abac_role_name = NULL;
36    role->linked_role = NULL;
37
38    role->string = abac_xstrdup(principal);
39    role->linked = NULL;
40
41    role->refcount = 1;
42
43    return role;
44}
45
46/**
47 * Create a new role and initialize it.
48 */
49abac_role_t *abac_role_role_new(char *principal, char *abac_role_name) {
50    assert(principal != NULL);
51    assert(abac_role_name != NULL);
52
53    abac_role_t *role;
54
55    if (strlen(principal) == 0 || strlen(abac_role_name) == 0)
56        return NULL;
57
58    role = abac_xmalloc(sizeof(abac_role_t));
59
60    role->principal = abac_xstrdup(principal);
61    role->abac_role_name = abac_xstrdup(abac_role_name);
62    role->linked_role = NULL;
63
64    int prin_len = strlen(principal);
65    int abac_role_len = strlen(abac_role_name);
66
67    role->string = abac_xmalloc(prin_len + 1 + abac_role_len + 1);
68    memcpy(role->string, principal, prin_len);
69    role->string[prin_len] = '.';
70    memcpy(role->string + prin_len + 1, abac_role_name, abac_role_len);
71    role->string[prin_len + 1 + abac_role_len] = 0;
72
73    role->linked = NULL;
74
75    role->refcount = 1;
76
77    return role;
78}
79
80/**
81 * Created a new linking role and initialize it.
82 */
83abac_role_t *abac_role_linking_new(char *principal, char *linked, char *abac_role_name) {
84    assert(principal != NULL);
85    assert(linked != NULL);
86    assert(abac_role_name != NULL);
87
88    abac_role_t *role;
89
90    if (strlen(principal) == 0 || strlen(linked) == 0 || strlen(abac_role_name) == 0)
91        return NULL;
92
93    role = abac_xmalloc(sizeof(abac_role_t));
94
95    role->principal = abac_xstrdup(principal);
96    role->linked_role = abac_xstrdup(linked);
97    role->abac_role_name = abac_xstrdup(abac_role_name);
98
99    int prin_len = strlen(principal);
100    int link_len = strlen(linked);
101    int abac_role_len = strlen(abac_role_name);
102
103    role->string = abac_xmalloc(prin_len + 1 + link_len + 1 + abac_role_len + 1);
104
105    memcpy(role->string, principal, prin_len);
106    role->string[prin_len] = '.';
107    memcpy(role->string + prin_len + 1, linked, link_len);
108    role->string[prin_len + 1 + link_len] = 0;
109
110    // hack: linked role is first two parts of full string
111    role->linked = abac_xstrdup(role->string);
112
113    role->string[prin_len + 1 + link_len] = '.';
114    memcpy(role->string + prin_len + 1 + link_len + 1, abac_role_name, abac_role_len);
115    role->string[prin_len + 1 + link_len + 1 + abac_role_len] = 0;
116
117    role->refcount = 1;
118
119    return role;
120}
121
122/**
123 * Decrease a role's reference count, freeing it when it reaches 0.
124 */
125void abac_role_free(abac_role_t *role) {
126    if (role == NULL)
127        return;
128
129    --role->refcount;
130    if (role->refcount > 0)
131        return;
132
133    free(role->principal);
134    free(role->linked_role);
135    free(role->abac_role_name);
136
137    free(role->string);
138    free(role->linked);
139
140    free(role);
141}
142
143/**
144 * Create a role from a string. Handles principals, roles, and linking roles.
145 */
146abac_role_t *abac_role_from_string(char *string) {
147    int num_dots = 0;
148    char *dot = string;
149
150    // count the dots
151    while ((dot = strchr(dot, '.')) != NULL) {
152        ++num_dots;
153        ++dot;
154    }
155
156    // no dots: easy case, principal
157    if (num_dots == 0)
158        return abac_role_principal_new(string);
159
160    abac_role_t *ret = NULL;
161
162    // make a copy so we can mess with it
163    string = abac_xstrdup(string);
164
165    // a role has exactly 1 dot
166    if (num_dots == 1) {
167        char *principal = string;
168
169        // terminate the principal part
170        dot = strchr(principal, '.');
171        *dot = 0;
172
173        // role name comes after the dot
174        char *abac_role_name = dot + 1;
175
176        // create the role (if possible)
177        ret = abac_role_role_new(string, abac_role_name);
178    }
179
180    // a linked role has 2 dots
181    else if (num_dots == 2) {
182        char *principal = string;
183
184        // terminate the principal part
185        dot = strchr(principal, '.');
186        *dot = 0;
187
188        // linked name is next, terminate it
189        char *linked = dot + 1;
190        dot = strchr(linked, '.');
191        *dot = 0;
192
193        // role name is last, already terminated
194        char *abac_role_name = dot + 1;
195
196        ret = abac_role_linking_new(principal, linked, abac_role_name);
197    }
198
199    // more than two dots: return NULL
200
201    free(string);
202
203    return ret;
204}
205
206/**
207 * Increase a role's reference count.
208 */
209abac_role_t *abac_role_dup(abac_role_t *role) {
210    assert(role != NULL);
211
212    ++role->refcount;
213    return role;
214}
215
216/**
217 * True if a role is a principal.
218 */
219int abac_role_is_principal(abac_role_t *role) {
220    assert(role != NULL);
221    return role->abac_role_name == NULL && role->linked_role == NULL;
222}
223
224/**
225 * True if a role is a role.
226 */
227int abac_role_is_role(abac_role_t *role) {
228    assert(role != NULL);
229    return role->abac_role_name != NULL && role->linked_role == NULL; 
230}
231
232/**
233 * True if a role is a linked role.
234 */
235int abac_role_is_linking(abac_role_t *role) {
236    assert(role != NULL);
237    return role->linked_role != NULL;
238}
239
240/**
241 * Returns the string representation of the role.
242 */
243char *abac_role_string(abac_role_t *role) {
244    assert(role != NULL);
245    return role->string;
246}
247
248/**
249 * Returns the name of a role. If the role is A.r1 then return r1. If the role
250 * is A.r1.r2 then return r2.
251 */
252char *abac_role_role_name(abac_role_t *role) {
253    assert(role != NULL);
254    return role->abac_role_name;
255}
256
257/**
258 * Returns the linked part of a linking role. For instance, if the role is
259 * A.r1.r2, this returns A.r1.
260 */
261char *abac_role_linked_role(abac_role_t *role) {
262    assert(role != NULL);
263    return role->linked;
264}
265
266/**
267 * Returns the principal part of a role. The stuff before the first dot.
268 */
269char *abac_role_principal(abac_role_t *role) {
270    assert(role != NULL);
271    return role->principal;
272}
273
274/**
275 * Build an attribute key from head and tail roles. Static.
276 */
277#define ROLE_SEPARATOR " <- "
278char *abac_role_attr_key(abac_role_t *head_role, abac_role_t *tail_role) {
279    char *head = abac_role_string(head_role);
280    int head_len = strlen(head);
281
282    char *tail = abac_role_string(tail_role);
283    int tail_len = strlen(tail);
284
285    int sep_len = sizeof(ROLE_SEPARATOR) - 1;
286
287    // "head <- tail"
288    char *ret = abac_xmalloc(head_len + tail_len + sep_len + 1);
289    memcpy(ret, head, head_len);
290    memcpy(ret + head_len, ROLE_SEPARATOR, sep_len);
291    memcpy(ret + head_len + sep_len, tail, tail_len);
292    ret[head_len + sep_len + tail_len] = 0;
293
294    return ret;
295}
Note: See TracBrowser for help on using the repository browser.