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
RevLine 
[461541a]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"
[4721618]12#include "abac_list.h"
[461541a]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);
[13b087a]40extern abac_id_t *abac_verifier_lookup_id(abac_list_t*, char *keyid);
[461541a]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) {
[ef68ac9]59    libabac_init();
[461541a]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
[7e3f5e2]69    if(validity == 0) validity = (long)(60*60*24*(365));
70
[461541a]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;
[4721618]78    asprintf(&attr->head_string,"%s.%s",abac_id_keyid(issuer_id),role);
[461541a]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);
[9ac7fb4]100    char *xml=(char *)attr->cert.ptr;
[461541a]101    long validity=get_validity_from_xml(xml);
102
103    time_t etime = now + validity;
104    gmtime_r(&etime, not_after);
105
[7e3f5e2]106    if(debug) fprintf(stderr,"validity from the xml blob is %ld\n",validity);
[461541a]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);
[9ac7fb4]116    long v=get_validity_from_xml((char *)attr->cert.ptr);
[461541a]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
[4e10a0f]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);
[461541a]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
[4e10a0f]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);
[461541a]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. */
[9ac7fb4]241    char *attr_cert=my_make_credential(role_string, attr->validity, (char *)id_chunk.ptr, id_chunk.len);
[461541a]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
[4721618]254abac_chunk_t abac_attribute_cert_chunk(abac_attribute_t *attr) {
255    abac_chunk_t chunk= {NULL,0};
[461541a]256
257    if (attr->cert.ptr == NULL)
[4721618]258        return chunk;
[461541a]259
260    /* return the xml chunk */
[4721618]261    chunk.ptr= (unsigned char *)abac_xstrdup((char *)attr->cert.ptr);
262    chunk.len=attr->cert.len;
263    return chunk;
[461541a]264}
265
266int abac_attribute_baked(abac_attribute_t *attr) {
267    return (attr->cert.ptr != NULL);
268}
269
270
[bec30b5]271static abac_attribute_t *_load_attr(abac_list_t *id_certs,char *rstring, char *xml)
[461541a]272{
[02036f4]273    /* make a copy of rle_string */
274    char *role_string=abac_xstrdup(rstring);
[461541a]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);
[bec30b5]284    abac_id_t *issuer_id=abac_verifier_lookup_id(id_certs,keyid);
[461541a]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
[9e063cb]299    attr->cert.ptr=(unsigned char *)abac_xstrdup(xml);
[461541a]300    attr->cert.len=strlen(xml);
301
302    return attr;
303}
304
[bec30b5]305abac_list_t *abac_attribute_certs_from_file(abac_list_t *id_certs,char *filename)
[461541a]306{
[ef68ac9]307    libabac_init();
[461541a]308    abac_list_t *alist=abac_list_new();
309    char *xml=NULL;
310    char *rt0=NULL;
311
[bec30b5]312    char **rt0s=my_read_credential((void *)id_certs,filename, &xml);
[4721618]313    if(rt0s == NULL) return alist;
314    if(xml == NULL || strlen(xml)==0) return alist;
[461541a]315
316    abac_attribute_t *attr;
317
318    int i=0;
319    do {
320        rt0 = rt0s[i]; 
321        if(rt0 == NULL) break;
[bec30b5]322        attr=_load_attr(id_certs,rt0, xml);
[461541a]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
[bec30b5]335abac_list_t *abac_attribute_certs_from_chunk(abac_list_t *id_certs,abac_chunk_t chunk) {
[ef68ac9]336    libabac_init();
[461541a]337
338    abac_list_t *alist=abac_list_new();
339    char *xml=(char *)chunk.ptr;
[4721618]340    if(chunk.len==0) return alist;
341
[bec30b5]342    char **rt0s=get_rt0_from_xml((void *) id_certs,xml);
[461541a]343    char *rt0=NULL;
[4721618]344    if(rt0s==NULL) return alist;
[461541a]345
346    abac_attribute_t *attr;
347    int i=0;
348    do {
349        rt0 = rt0s[i]; 
350        if(rt0 == NULL) break;
[bec30b5]351        attr=_load_attr(id_certs,rt0, xml);
[461541a]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
[4721618]362// returns ABAC_FAILURE if the cert hasn't been baked
[461541a]363int abac_attribute_write(abac_attribute_t *attr, FILE *out) {
364    assert(attr != NULL);
365
366    if (attr->cert.ptr == NULL)
[4721618]367        return ABAC_FAILURE;
[461541a]368
369    // write to file
370    fwrite(attr->cert.ptr, attr->cert.len, 1, out);
371
[4721618]372    return ABAC_SUCCESS;
[461541a]373}
374
[4721618]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
[461541a]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.