source: libabac/abac_attribute.c @ 13b087a

abac0-leakabac0-meimei-idtvf-new-xml
Last change on this file since 13b087a was 13b087a, checked in by Mei <mei@…>, 11 years ago

1) fix some compiling warnings

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