source: libabac/abac_attribute.c @ af8e9b9

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

1) tweak for porting try

  • Property mode set to 100644
File size: 10.8 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 *rstring, char *xml)
271{
272    /* make a copy of rle_string */
273    char *role_string=abac_xstrdup(rstring);
274
275if(debug) fprintf(stderr,"loading -> %s \n", role_string);
276
277    char *head_tail[2];
278    int ret;
279    abac_split(role_string, "<-", head_tail, &ret);
280    if (ret != 2) return NULL; 
281
282    char *keyid=get_keyid_from_xml(xml);
283    abac_id_t *issuer_id=abac_verifier_lookup_id(keyid);
284
285    long validity=get_validity_from_xml(xml);
286   
287    abac_attribute_t *attr = abac_xmalloc(sizeof(abac_attribute_t));
288    if(issuer_id)
289        attr->issuer_id = abac_id_dup(issuer_id);
290        else attr->issuer_id=NULL;
291    attr->validity = validity;
292
293    attr->head_string = abac_xstrdup(head_tail[0]);
294    attr->tail_string = abac_xstrdup(head_tail[1]);
295    char *tmp=strstr(attr->head_string,".");
296    attr->role =abac_xstrdup(tmp+1);
297
298    attr->cert.ptr=(unsigned char *)abac_xstrdup(xml);
299    attr->cert.len=strlen(xml);
300
301    return attr;
302}
303
304abac_list_t *abac_attribute_certs_from_file(char *filename)
305{
306    abac_list_t *alist=abac_list_new();
307    char *xml=NULL;
308    char *rt0=NULL;
309
310    char **rt0s=my_read_credential(filename, &xml);
311    if(rt0s == NULL) return alist;
312    if(xml == NULL || strlen(xml)==0) return alist;
313
314    abac_attribute_t *attr;
315
316    int i=0;
317    do {
318        rt0 = rt0s[i]; 
319        if(rt0 == NULL) break;
320        attr=_load_attr(rt0, xml);
321        if(attr)
322            abac_list_add(alist, attr);
323        free(rt0);
324        i++;
325    } while (rt0s[i] !=NULL);
326
327    free(rt0s);
328    free(xml);
329
330    return alist;
331}
332
333abac_list_t *abac_attribute_certs_from_chunk(abac_chunk_t chunk) {
334
335    abac_list_t *alist=abac_list_new();
336    char *xml=(char *)chunk.ptr;
337    if(chunk.len==0) return alist;
338
339    char **rt0s=get_rt0_from_xml(xml);
340    char *rt0=NULL;
341    if(rt0s==NULL) return alist;
342
343    abac_attribute_t *attr;
344    int i=0;
345    do {
346        rt0 = rt0s[i]; 
347        if(rt0 == NULL) break;
348        attr=_load_attr(rt0, xml);
349        if(attr)
350            abac_list_add(alist, attr);
351        free(rt0);
352        i++;
353    } while (rt0s[i] !=NULL);
354
355    free(rt0s);
356    return alist;
357}
358
359// returns ABAC_FAILURE if the cert hasn't been baked
360int abac_attribute_write(abac_attribute_t *attr, FILE *out) {
361    assert(attr != NULL);
362
363    if (attr->cert.ptr == NULL)
364        return ABAC_FAILURE;
365
366    // write to file
367    fwrite(attr->cert.ptr, attr->cert.len, 1, out);
368
369    return ABAC_SUCCESS;
370}
371
372// returns ABAC_FAILURE if the cert hasn't been baked
373int abac_attribute_write_file(abac_attribute_t *attr, const char *fname) {
374    if (attr->cert.ptr == NULL)
375        return ABAC_FAILURE;
376
377    FILE *fp=fopen(fname,"w+");
378    if(fp) {
379         // write to file
380         fwrite(attr->cert.ptr, attr->cert.len, 1, fp);
381    } else return ABAC_FAILURE;
382    fclose(fp);
383
384    return ABAC_SUCCESS;
385}
386
387
388void abac_attribute_free(abac_attribute_t *attr) {
389
390if(debug) fprintf(stderr,"calling abac_attribute_free on %s\n", attr->head_string);
391
392    if (attr == NULL)
393        return;
394
395    if(attr->issuer_id) abac_id_free(attr->issuer_id);
396
397    free(attr->role);
398    free(attr->head_string);
399    free(attr->tail_string);
400
401/* XXX this can not be free as if it is a char string
402    free(attr->cert.ptr);
403*/
404
405    free(attr);
406}
407
408//
409// Helper functions below
410//
411
412// validate a princpal's name
413// makes sure it's a valid SHA1 identifier
414// return values:
415//  success: malloc'd copy with all hex digits lowercase
416//  fail: NULL
417static char *_validate_principal(char *keyid) {
418    int i;
419    char *copy = NULL;
420
421    if (strlen(keyid) != SHA1_LENGTH)
422        return NULL;
423
424    copy = abac_xstrdup(keyid);
425    for (i = 0; i < SHA1_LENGTH; ++i) {
426        copy[i] = tolower(copy[i]);
427        if (!isxdigit(copy[i]))
428            goto error;
429    }
430
431    return copy;
432
433error:
434    free(copy);
435    return NULL;
436}
437
438// combine up the attribute's rule string, explicit copy
439char *abac_attribute_role_string(abac_attribute_t *attr) {
440    assert(attr);
441
442    char *role_string=NULL;
443    asprintf(&role_string,"%s<-%s",attr->head_string,attr->tail_string);
444    return role_string;
445}
446
447
Note: See TracBrowser for help on using the repository browser.