source: libabac/abac_attribute.c @ 4721618

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

1) tested out python and perl test scripts along with

abac_chunk_t calls in libabac's abac.hh

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