source: libabac/abac_attribute.c @ 7e3f5e2

abac0-leakabac0-meimei-idmei-rt0-nmei_rt0tvf-new-xml
Last change on this file since 7e3f5e2 was 7e3f5e2, checked in by Mei <mei@…>, 11 years ago

1) converted daisychain scaling tests

  • Property mode set to 100644
File size: 10.4 KB
Line 
1
2/* abac_attribute.c */
3
4#define _GNU_SOURCE
5#include <stdio.h>
6#include <assert.h>
7#include <ctype.h>
8#include <string.h>
9#include <time.h>
10
11#include "libabac_common.h"
12#include "abac_list.h"
13#include "abac_util.h"
14#include "abac_xml.h"
15
16#define ROLE_SEPARATOR " <- "
17#define INTERSECTION_SEP " & "
18#define SHA1_LENGTH 40
19
20static int debug=0;
21
22// a GENI XML attribute chunk might contain multiple
23// attribute rules. It will be translate into multiple
24// abac_attribute structures but with cert ptr pointing
25// to the same xml chunk
26// issuer can be missing but then it won't be bakable
27// unless it is baked just for creddy's roles call
28struct _abac_attribute_t {
29    abac_id_t *issuer_id; 
30    char *role;
31    long validity;
32
33    char *head_string;
34    char *tail_string;
35
36    abac_chunk_t cert; // the XML chunk
37};
38
39char *abac_attribute_role_string(abac_attribute_t *attr);
40extern abac_id_t *abac_verifier_lookup_id(char *keyid);
41static char *_validate_principal(char *keyid);
42
43/************************************************************/
44abac_chunk_t abac_attribute_cert(abac_attribute_t *ptr)
45{
46    assert(ptr);
47    return ptr->cert;
48}
49
50abac_id_t *abac_attribute_issuer_id(abac_attribute_t *ptr)
51{
52    assert(ptr);
53    return ptr->issuer_id;
54}
55
56// validity is measured in seconds (as of 0.2.0)
57// Acme.customer
58int abac_attribute_create(abac_attribute_t **ret, abac_id_t *issuer_id, char *role, long validity) {
59    if (!abac_id_has_privkey(issuer_id))
60        return ABAC_ATTRIBUTE_ISSUER_NOKEY;
61    if (!abac_clean_name(role))
62        return ABAC_ATTRIBUTE_INVALID_ROLE;
63    if (validity < 0)
64        return ABAC_ATTRIBUTE_INVALID_VALIDITY;
65    if (!abac_id_still_valid(issuer_id))
66        return ABAC_ATTRIBUTE_INVALID_ISSUER;
67
68    if(validity == 0) validity = (long)(60*60*24*(365));
69
70    abac_attribute_t *attr = abac_xmalloc(sizeof(abac_attribute_t));
71    if(issuer_id) attr->issuer_id = abac_id_dup(issuer_id);
72        else attr->issuer_id = NULL;
73    attr->role = abac_xstrdup(role);
74    attr->validity = validity;
75
76    attr->head_string = NULL;
77    asprintf(&attr->head_string,"%s.%s",abac_id_keyid(issuer_id),role);
78    attr->tail_string = NULL;
79
80    // NULL until baked
81    attr->cert.ptr=NULL;
82    attr->cert.len=0;
83
84    *ret = attr;
85    return ABAC_SUCCESS;
86}
87
88/**
89 * Get the validity period.(xml module returns the diff from expire time - now()
90 */
91int abac_attribute_validity(abac_attribute_t *attr,struct tm *not_before,struct tm *not_after) {
92    assert(attr);
93    memset(not_before, 0, sizeof(struct tm));
94    memset(not_after, 0, sizeof(struct tm));
95
96    time_t now;
97    time(&now);
98    gmtime_r(&now, not_before);
99    char *xml=(char *)attr->cert.ptr;
100    long validity=get_validity_from_xml(xml);
101
102    time_t etime = now + validity;
103    gmtime_r(&etime, not_after);
104
105    if(debug) fprintf(stderr,"validity from the xml blob is %ld\n",validity);
106    if(validity == 0)
107        return ABAC_FAILURE;
108    return ABAC_SUCCESS;
109}
110
111int abac_attribute_still_valid(abac_attribute_t *attr)
112{
113    assert(attr);
114    assert(attr->cert.ptr);
115    long v=get_validity_from_xml((char *)attr->cert.ptr);
116    if (v > 0.0)
117        return 1;
118    else return 0;
119}
120
121void abac_attribute_set_head(abac_attribute_t *attr, char *string)
122{
123    assert(attr);
124    attr->head_string=string;
125}
126
127char *abac_attribute_get_head(abac_attribute_t *attr)
128{
129    assert(attr);
130    return attr->head_string;
131}
132
133void abac_attribute_set_tail(abac_attribute_t *attr, char *string)
134{
135    assert(attr);
136    attr->tail_string=string;
137}
138
139char *abac_attribute_get_tail(abac_attribute_t *attr)
140{
141    assert(attr);
142    return attr->tail_string;
143}
144
145/* A.b->C, return copy of a A */
146char *abac_attribute_get_principal(abac_attribute_t *attr)
147{
148    char *role_string=abac_attribute_role_string(attr);
149    /* make an copy */
150    char *tmp=strdup(role_string);
151    char *head_tail[2];
152    int ret;
153    abac_split(tmp, "<-", head_tail, &ret);
154    if (ret != 2) goto err;
155    abac_split(head_tail[0], ".", head_tail, &ret);
156    if (ret != 2) goto err;
157    char *prin=strdup(head_tail[0]);
158    free(tmp);
159    return prin;
160
161err:     
162     free(tmp);
163     return NULL;
164}
165
166int abac_attribute_principal(abac_attribute_t *attr, char *keyid) {
167    char *copy = _validate_principal(keyid);
168    if (copy == NULL)
169        return 0;
170
171    abac_attribute_set_tail(attr,copy);
172    return 1;
173}
174
175int abac_attribute_role(abac_attribute_t *attr, char *keyid, char *role) {
176    if (!abac_clean_name(role))
177        return 0;
178
179    char *copy = _validate_principal(keyid);
180    if (copy == NULL)
181        return 0;
182
183    int len = strlen(copy) + strlen(role) + strlen(ROLE_SEPARATOR) + 1;
184    copy = abac_xrealloc(copy, len);
185    strcat(copy, ".");
186    strcat(copy, role);
187
188    abac_attribute_set_tail(attr,copy);
189    return 1;
190}
191
192int abac_attribute_linking_role(abac_attribute_t *attr, char *keyid, char *role, char *linked) {
193    if (!abac_clean_name(role) || !abac_clean_name(linked))
194        return 0;
195
196    char *copy = _validate_principal(keyid);
197    if (copy == NULL)
198        return 0;
199
200    int len = strlen(copy) + strlen(role) + strlen(linked) + strlen(ROLE_SEPARATOR) + 2;
201    copy = abac_xrealloc(copy, len);
202    strcat(copy, ".");
203    strcat(copy, role);
204    strcat(copy, ".");
205    strcat(copy, linked);
206
207    abac_attribute_set_tail(attr,copy);
208    return 1;
209}
210
211
212
213// 0 for fail to bake, 1 is baked okay
214int abac_attribute_bake(abac_attribute_t *attr) {
215    assert(attr);
216    assert(attr->head_string);
217    assert(attr->tail_string);
218
219    abac_chunk_t id_chunk = { NULL, 0 };
220    int ret=abac_id_PEM(attr->issuer_id, &id_chunk);
221    if(ret != ABAC_CERT_SUCCESS)
222        return 0; 
223
224    char *role_string = abac_attribute_role_string(attr);
225
226/* Make an new GENI abac credential with the rt0 rule that expires secs from
227 * now.  cert is the PEM encoded X.509 of the issuer's certificate as a string.
228 * certlen is the length of cert.  Returns the XML. Caller is responsible for
229 * freeing it. */
230    char *attr_cert=my_make_credential(role_string, attr->validity, (char *)id_chunk.ptr, id_chunk.len);
231
232    if (attr_cert == NULL)
233        return 0;
234
235    attr->cert.ptr = (unsigned char *)attr_cert;
236    attr->cert.len = strlen(attr_cert);
237
238    free(role_string);
239    return 1;
240}
241
242// make an explicit copy
243abac_chunk_t abac_attribute_cert_chunk(abac_attribute_t *attr) {
244    abac_chunk_t chunk= {NULL,0};
245
246    if (attr->cert.ptr == NULL)
247        return chunk;
248
249    /* return the xml chunk */
250    chunk.ptr= (unsigned char *)abac_xstrdup((char *)attr->cert.ptr);
251    chunk.len=attr->cert.len;
252    return chunk;
253}
254
255int abac_attribute_baked(abac_attribute_t *attr) {
256    return (attr->cert.ptr != NULL);
257}
258
259
260static abac_attribute_t *_load_attr(char *role_string, char *xml)
261{
262
263if(debug) fprintf(stderr,"loading -> %s \n", role_string);
264
265    char *head_tail[2];
266    int ret;
267    abac_split(role_string, "<-", head_tail, &ret);
268    if (ret != 2) return NULL; 
269
270    char *keyid=get_keyid_from_xml(xml);
271    abac_id_t *issuer_id=abac_verifier_lookup_id(keyid);
272
273    long validity=get_validity_from_xml(xml);
274   
275    abac_attribute_t *attr = abac_xmalloc(sizeof(abac_attribute_t));
276    if(issuer_id)
277        attr->issuer_id = abac_id_dup(issuer_id);
278        else attr->issuer_id=NULL;
279    attr->validity = validity;
280
281    attr->head_string = abac_xstrdup(head_tail[0]);
282    attr->tail_string = abac_xstrdup(head_tail[1]);
283    char *tmp=strstr(attr->head_string,".");
284    attr->role =abac_xstrdup(tmp+1);
285
286    attr->cert.ptr=(unsigned char *)xml;
287    attr->cert.len=strlen(xml);
288
289    return attr;
290}
291
292abac_list_t *abac_attribute_certs_from_file(char *filename)
293{
294    abac_list_t *alist=abac_list_new();
295    char *xml=NULL;
296    char *rt0=NULL;
297
298    char **rt0s=my_read_credential(filename, &xml);
299    if(rt0s == NULL) return alist;
300    if(xml == NULL || strlen(xml)==0) return alist;
301
302    abac_attribute_t *attr;
303
304    int i=0;
305    do {
306        rt0 = rt0s[i]; 
307        if(rt0 == NULL) break;
308        attr=_load_attr(rt0, xml);
309        if(attr)
310            abac_list_add(alist, attr);
311        free(rt0);
312        i++;
313    } while (rt0s[i] !=NULL);
314
315    free(rt0s);
316    free(xml);
317
318    return alist;
319}
320
321abac_list_t *abac_attribute_certs_from_chunk(abac_chunk_t chunk) {
322
323    abac_list_t *alist=abac_list_new();
324    char *xml=(char *)chunk.ptr;
325    if(chunk.len==0) return alist;
326
327    char **rt0s=get_rt0_from_xml(xml);
328    char *rt0=NULL;
329    if(rt0s==NULL) return alist;
330
331    abac_attribute_t *attr;
332    int i=0;
333    do {
334        rt0 = rt0s[i]; 
335        if(rt0 == NULL) break;
336        attr=_load_attr(rt0, xml);
337        if(attr)
338            abac_list_add(alist, attr);
339        free(rt0);
340        i++;
341    } while (rt0s[i] !=NULL);
342
343    free(rt0s);
344    return alist;
345}
346
347// returns ABAC_FAILURE if the cert hasn't been baked
348int abac_attribute_write(abac_attribute_t *attr, FILE *out) {
349    assert(attr != NULL);
350
351    if (attr->cert.ptr == NULL)
352        return ABAC_FAILURE;
353
354    // write to file
355    fwrite(attr->cert.ptr, attr->cert.len, 1, out);
356
357    return ABAC_SUCCESS;
358}
359
360// returns ABAC_FAILURE if the cert hasn't been baked
361int abac_attribute_write_file(abac_attribute_t *attr, const char *fname) {
362    if (attr->cert.ptr == NULL)
363        return ABAC_FAILURE;
364
365    FILE *fp=fopen(fname,"w+");
366    if(fp) {
367         // write to file
368         fwrite(attr->cert.ptr, attr->cert.len, 1, fp);
369    } else return ABAC_FAILURE;
370    fclose(fp);
371
372    return ABAC_SUCCESS;
373}
374
375
376void abac_attribute_free(abac_attribute_t *attr) {
377
378if(debug) fprintf(stderr,"calling abac_attribute_free on %s\n", attr->head_string);
379
380    if (attr == NULL)
381        return;
382
383    if(attr->issuer_id) abac_id_free(attr->issuer_id);
384
385    free(attr->role);
386    free(attr->head_string);
387    free(attr->tail_string);
388
389/* XXX this can not be free as if it is a char string
390    free(attr->cert.ptr);
391*/
392
393    free(attr);
394}
395
396//
397// Helper functions below
398//
399
400// validate a princpal's name
401// makes sure it's a valid SHA1 identifier
402// return values:
403//  success: malloc'd copy with all hex digits lowercase
404//  fail: NULL
405static char *_validate_principal(char *keyid) {
406    int i;
407    char *copy = NULL;
408
409    if (strlen(keyid) != SHA1_LENGTH)
410        return NULL;
411
412    copy = abac_xstrdup(keyid);
413    for (i = 0; i < SHA1_LENGTH; ++i) {
414        copy[i] = tolower(copy[i]);
415        if (!isxdigit(copy[i]))
416            goto error;
417    }
418
419    return copy;
420
421error:
422    free(copy);
423    return NULL;
424}
425
426// combine up the attribute's rule string, explicit copy
427char *abac_attribute_role_string(abac_attribute_t *attr) {
428    assert(attr);
429
430    char *role_string=NULL;
431    asprintf(&role_string,"%s<-%s",attr->head_string,attr->tail_string);
432    return role_string;
433}
434
435
Note: See TracBrowser for help on using the repository browser.