source: libabac/abac_attribute.c @ 4e10a0f

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

1) wrap up regression testing
Z

  • Property mode set to 100644
File size: 10.7 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    /* if there is a tail already, this is intersection */
184    char *oldtail=abac_attribute_get_tail(attr);
185    char *newcopy=NULL;
186    if(oldtail) {
187        asprintf(&newcopy,"%s & %s.%s", oldtail, copy,role);
188        free(oldtail);
189        } else {
190            asprintf(&newcopy,"%s.%s", copy,role);
191    }
192    free(copy);
193
194    abac_attribute_set_tail(attr,newcopy);
195    return 1;
196}
197
198int abac_attribute_linking_role(abac_attribute_t *attr, char *keyid, char *role, char *linked) {
199    if (!abac_clean_name(role) || !abac_clean_name(linked))
200        return 0;
201
202    char *copy = _validate_principal(keyid);
203    if (copy == NULL)
204        return 0;
205
206    /* if there is a tail already, this is intersection */
207    char *oldtail=abac_attribute_get_tail(attr);
208    char *newcopy=NULL;
209    if(oldtail) {
210        asprintf(&newcopy,"%s & %s.%s.%s", oldtail, copy,role,linked);
211        free(oldtail);
212        } else {
213            asprintf(&newcopy,"%s.%s.%s", copy,role,linked);
214    }
215    free(copy);
216
217    abac_attribute_set_tail(attr,newcopy);
218    return 1;
219}
220
221
222
223// 0 for fail to bake, 1 is baked okay
224int abac_attribute_bake(abac_attribute_t *attr) {
225    assert(attr);
226    assert(attr->head_string);
227    assert(attr->tail_string);
228
229    abac_chunk_t id_chunk = { NULL, 0 };
230    int ret=abac_id_PEM(attr->issuer_id, &id_chunk);
231    if(ret != ABAC_CERT_SUCCESS)
232        return 0; 
233
234    char *role_string = abac_attribute_role_string(attr);
235
236/* Make an new GENI abac credential with the rt0 rule that expires secs from
237 * now.  cert is the PEM encoded X.509 of the issuer's certificate as a string.
238 * certlen is the length of cert.  Returns the XML. Caller is responsible for
239 * freeing it. */
240    char *attr_cert=my_make_credential(role_string, attr->validity, (char *)id_chunk.ptr, id_chunk.len);
241
242    if (attr_cert == NULL)
243        return 0;
244
245    attr->cert.ptr = (unsigned char *)attr_cert;
246    attr->cert.len = strlen(attr_cert);
247
248    free(role_string);
249    return 1;
250}
251
252// make an explicit copy
253abac_chunk_t abac_attribute_cert_chunk(abac_attribute_t *attr) {
254    abac_chunk_t chunk= {NULL,0};
255
256    if (attr->cert.ptr == NULL)
257        return chunk;
258
259    /* return the xml chunk */
260    chunk.ptr= (unsigned char *)abac_xstrdup((char *)attr->cert.ptr);
261    chunk.len=attr->cert.len;
262    return chunk;
263}
264
265int abac_attribute_baked(abac_attribute_t *attr) {
266    return (attr->cert.ptr != NULL);
267}
268
269
270static abac_attribute_t *_load_attr(char *role_string, char *xml)
271{
272
273if(debug) fprintf(stderr,"loading -> %s \n", role_string);
274
275    char *head_tail[2];
276    int ret;
277    abac_split(role_string, "<-", head_tail, &ret);
278    if (ret != 2) return NULL; 
279
280    char *keyid=get_keyid_from_xml(xml);
281    abac_id_t *issuer_id=abac_verifier_lookup_id(keyid);
282
283    long validity=get_validity_from_xml(xml);
284   
285    abac_attribute_t *attr = abac_xmalloc(sizeof(abac_attribute_t));
286    if(issuer_id)
287        attr->issuer_id = abac_id_dup(issuer_id);
288        else attr->issuer_id=NULL;
289    attr->validity = validity;
290
291    attr->head_string = abac_xstrdup(head_tail[0]);
292    attr->tail_string = abac_xstrdup(head_tail[1]);
293    char *tmp=strstr(attr->head_string,".");
294    attr->role =abac_xstrdup(tmp+1);
295
296    attr->cert.ptr=(unsigned char *)abac_xstrdup(xml);
297    attr->cert.len=strlen(xml);
298
299    return attr;
300}
301
302abac_list_t *abac_attribute_certs_from_file(char *filename)
303{
304    abac_list_t *alist=abac_list_new();
305    char *xml=NULL;
306    char *rt0=NULL;
307
308    char **rt0s=my_read_credential(filename, &xml);
309    if(rt0s == NULL) return alist;
310    if(xml == NULL || strlen(xml)==0) return alist;
311
312    abac_attribute_t *attr;
313
314    int i=0;
315    do {
316        rt0 = rt0s[i]; 
317        if(rt0 == NULL) break;
318        attr=_load_attr(rt0, xml);
319        if(attr)
320            abac_list_add(alist, attr);
321        free(rt0);
322        i++;
323    } while (rt0s[i] !=NULL);
324
325    free(rt0s);
326    free(xml);
327
328    return alist;
329}
330
331abac_list_t *abac_attribute_certs_from_chunk(abac_chunk_t chunk) {
332
333    abac_list_t *alist=abac_list_new();
334    char *xml=(char *)chunk.ptr;
335    if(chunk.len==0) return alist;
336
337    char **rt0s=get_rt0_from_xml(xml);
338    char *rt0=NULL;
339    if(rt0s==NULL) return alist;
340
341    abac_attribute_t *attr;
342    int i=0;
343    do {
344        rt0 = rt0s[i]; 
345        if(rt0 == NULL) break;
346        attr=_load_attr(rt0, xml);
347        if(attr)
348            abac_list_add(alist, attr);
349        free(rt0);
350        i++;
351    } while (rt0s[i] !=NULL);
352
353    free(rt0s);
354    return alist;
355}
356
357// returns ABAC_FAILURE if the cert hasn't been baked
358int abac_attribute_write(abac_attribute_t *attr, FILE *out) {
359    assert(attr != NULL);
360
361    if (attr->cert.ptr == NULL)
362        return ABAC_FAILURE;
363
364    // write to file
365    fwrite(attr->cert.ptr, attr->cert.len, 1, out);
366
367    return ABAC_SUCCESS;
368}
369
370// returns ABAC_FAILURE if the cert hasn't been baked
371int abac_attribute_write_file(abac_attribute_t *attr, const char *fname) {
372    if (attr->cert.ptr == NULL)
373        return ABAC_FAILURE;
374
375    FILE *fp=fopen(fname,"w+");
376    if(fp) {
377         // write to file
378         fwrite(attr->cert.ptr, attr->cert.len, 1, fp);
379    } else return ABAC_FAILURE;
380    fclose(fp);
381
382    return ABAC_SUCCESS;
383}
384
385
386void abac_attribute_free(abac_attribute_t *attr) {
387
388if(debug) fprintf(stderr,"calling abac_attribute_free on %s\n", attr->head_string);
389
390    if (attr == NULL)
391        return;
392
393    if(attr->issuer_id) abac_id_free(attr->issuer_id);
394
395    free(attr->role);
396    free(attr->head_string);
397    free(attr->tail_string);
398
399/* XXX this can not be free as if it is a char string
400    free(attr->cert.ptr);
401*/
402
403    free(attr);
404}
405
406//
407// Helper functions below
408//
409
410// validate a princpal's name
411// makes sure it's a valid SHA1 identifier
412// return values:
413//  success: malloc'd copy with all hex digits lowercase
414//  fail: NULL
415static char *_validate_principal(char *keyid) {
416    int i;
417    char *copy = NULL;
418
419    if (strlen(keyid) != SHA1_LENGTH)
420        return NULL;
421
422    copy = abac_xstrdup(keyid);
423    for (i = 0; i < SHA1_LENGTH; ++i) {
424        copy[i] = tolower(copy[i]);
425        if (!isxdigit(copy[i]))
426            goto error;
427    }
428
429    return copy;
430
431error:
432    free(copy);
433    return NULL;
434}
435
436// combine up the attribute's rule string, explicit copy
437char *abac_attribute_role_string(abac_attribute_t *attr) {
438    assert(attr);
439
440    char *role_string=NULL;
441    asprintf(&role_string,"%s<-%s",attr->head_string,attr->tail_string);
442    return role_string;
443}
444
445
Note: See TracBrowser for help on using the repository browser.