source: libabac/abac_attribute.c @ 05f6d35

mei_rt2mei_rt2_fix_1
Last change on this file since 05f6d35 was 6244e28, checked in by Mei <mei@…>, 12 years ago

1) added extract_cn for abac_verifier.c
2) update example directory's save log for the new multi proof case

  • Property mode set to 100644
File size: 10.9 KB
Line 
1
2/**
3**  abac_attribute.c
4**/
5
6#include <assert.h>
7#include <ctype.h>
8#include <string.h>
9#include <time.h>
10
11#include "abac_internal.h"
12#include "abac_util.h"
13
14#define SHA1_LENGTH 40
15
16extern char* abac_encode_string(char*);
17extern abac_key_t *abac_id_keyptr(abac_id_t *id);
18
19static int debug=0;
20
21struct _abac_attribute_t {
22    abac_id_t *issuer_id; 
23    abac_aspect_t *head;
24    abac_aspect_t *tail;
25    int validity;
26    certificate_t *cert; // NULL until baked
27    certificate_t *issuer_cert;
28
29    int refcount;
30};
31
32/********************************************************************/
33char *get_cred_encoding(abac_attribute_t *ptr)
34{
35    char *encoding=NULL;
36 
37    /* must have a head aspect and tail aspect */
38    assert(ptr->head != NULL);
39    assert(ptr->tail != NULL);
40
41    char *head_string=abac_aspect_typed_string_with_condition(ptr->head);
42    char *tail_string=abac_aspect_typed_string_with_condition(ptr->tail);
43
44    asprintf(&encoding,"%s<-%s", head_string,tail_string);
45    char* base64_encoding=abac_encode_string(encoding);
46
47    if(debug) fprintf(stderr,"XXX abac_attribute_bake (%s)\n", encoding);
48
49    free(encoding);
50    free(head_string);
51    free(tail_string);
52    return base64_encoding;
53}
54
55/********************************************************************/
56abac_attribute_t *abac_attribute_new(abac_id_t *issuer, certificate_t *cert,
57certificate_t *issuer_cert)
58{
59    abac_attribute_t *ptr = abac_xmalloc(sizeof(abac_attribute_t));
60    ptr->issuer_id = abac_id_dup(issuer);
61    ptr->head = NULL;
62    ptr->tail = NULL;
63    ptr->validity= 365 * 86400; // default
64    ptr->cert=cert; // already baked..
65    ptr->issuer_cert=issuer_cert;
66    ptr->refcount=1;
67
68    return ptr;
69}
70
71// validity is measured in seconds (as of 0.2.0)
72int abac_attribute_create(abac_attribute_t **ret, 
73abac_aspect_t *head, abac_aspect_t *tail, int validity)
74{
75    abac_id_t *issuer_id=abac_aspect_get_issuer_id(head);
76    if(debug)
77        print_abac_key("abac_attribute_create" , abac_id_keyptr(issuer_id));
78
79    char *name=abac_aspect_aspect_name(head);
80
81    if (!abac_id_has_privkey(issuer_id))
82        return ABAC_ATTRIBUTE_ISSUER_NOKEY;
83    if (!abac_validate_clean_aspect_name(name))
84        return ABAC_ATTRIBUTE_INVALID_ROLE;
85    if (validity < 0)
86        return ABAC_ATTRIBUTE_INVALID_VALIDITY;
87
88    abac_attribute_t *ptr = abac_xmalloc(sizeof(abac_attribute_t));
89    ptr->issuer_id = abac_id_dup(issuer_id);
90    ptr->head = abac_aspect_dup(head);
91    ptr->tail = (tail!=NULL) ? abac_aspect_dup(tail):NULL;
92    ptr->validity=(validity==0?(365 * 86400):validity);
93
94    // NULL until baked
95    ptr->cert=NULL;
96    ptr->issuer_cert=NULL;
97    ptr->refcount=1;
98    *ret = ptr;
99    return ABAC_ATTRIBUTE_SUCCESS;
100}
101
102// validity is measured in seconds (as of 0.2.0)
103int abac_attribute_create_creddy(abac_attribute_t **ret, abac_id_t *issuer, 
104abac_aspect_t *head_aspect, abac_aspect_t *tail_aspect, char *name, int validity)
105{
106    if (!abac_id_has_privkey(issuer))
107        return ABAC_ATTRIBUTE_ISSUER_NOKEY;
108    if (!abac_validate_clean_aspect_name(name))
109        return ABAC_ATTRIBUTE_INVALID_ROLE;
110    if (validity < 0)
111        return ABAC_ATTRIBUTE_INVALID_VALIDITY;
112
113    abac_attribute_t *ptr = abac_xmalloc(sizeof(abac_attribute_t));
114    ptr->issuer_id = abac_id_dup(issuer);
115
116    ptr->head=head_aspect;
117    ptr->tail=tail_aspect;
118    ptr->validity = validity;
119
120    // NULL until baked
121    ptr->cert = NULL;
122    ptr->issuer_cert = NULL;
123    *ret = ptr;
124    return ABAC_ATTRIBUTE_SUCCESS;
125}
126
127int abac_attribute_bake(abac_attribute_t *ptr) {
128    assert(ptr);
129
130    char *cred_encoding = get_cred_encoding(ptr);
131
132    // create attribute cert
133    time_t not_before = time(NULL);
134    time_t not_after = not_before + ptr->validity;
135    chunk_t serial = abac_generate_serial();
136
137    private_key_t *private = abac_id_privkey(ptr->issuer_id);
138
139    if(private==NULL)
140        errx(1,"can not bake without a private key!!!"); 
141
142    certificate_t *attr_cert = lib->creds->create(lib->creds,
143        CRED_CERTIFICATE, CERT_X509_AC,
144        BUILD_CERT, abac_id_cert(ptr->issuer_id),
145        BUILD_NOT_BEFORE_TIME, not_before,
146        BUILD_NOT_AFTER_TIME, not_after,
147        BUILD_SERIAL, serial,
148        BUILD_IETF_GROUP_ATTR, cred_encoding,
149        BUILD_SIGNING_CERT, abac_id_cert(ptr->issuer_id),
150        BUILD_SIGNING_KEY, private,
151        BUILD_END
152    );
153
154    DESTROY_IF(private);
155
156    if (attr_cert == NULL)
157        return 0;
158
159    ptr->cert = attr_cert;
160// cert and issuer can be the same, in which case it is the self signing
161    ptr->issuer_cert= attr_cert->get_ref(attr_cert);
162 
163    free(cred_encoding);
164    free(serial.ptr);
165    return 1;
166}
167
168abac_chunk_t abac_attribute_cert_chunk(abac_attribute_t *ptr) {
169    assert(ptr->cert);
170    chunk_t encoding = chunk_empty;
171    int rc=ptr->cert->get_encoding(ptr->cert,CERT_ASN1_DER,&encoding);
172    abac_chunk_t ret = { encoding.ptr, encoding.len };
173    return ret;
174}
175
176/* just loading it without any verifying */
177certificate_t *abac_attribute_from_file(char *filename) {
178
179    if(!file_exist(filename)) return NULL;
180
181    libabac_init();
182    certificate_t *cert = lib->creds->create(lib->creds,
183        CRED_CERTIFICATE, CERT_X509_AC,
184        BUILD_FROM_FILE, filename,
185        BUILD_END
186    );
187    if (cert == NULL)
188        errx(1, "Couldn't load attribute cert %s", filename);
189
190    return cert;
191}
192
193
194int abac_attribute_baked(abac_attribute_t *ptr) {
195    return ptr->cert != NULL;
196}
197
198// returns 0 if the cert hasn't been baked
199int abac_attribute_write_cert(abac_attribute_t *ptr, FILE *out) {
200    assert(ptr != NULL);
201
202    if (ptr->cert == NULL)
203        return 0;
204
205    // write to file
206    chunk_t encoding = chunk_empty;
207    int rc=ptr->cert->get_encoding(ptr->cert,CERT_ASN1_DER,&encoding);
208
209    if(rc) {
210        fwrite(encoding.ptr, encoding.len, 1, out);
211        free(encoding.ptr);
212        return 1;
213    }
214    return 0;
215}
216
217abac_attribute_t *abac_attribute_dup(abac_attribute_t *ptr)
218{
219    assert(ptr);
220    ++ptr->refcount;
221    return ptr;
222}
223
224void abac_attribute_free(abac_attribute_t *ptr) {
225    int i;
226
227    if (ptr == NULL)
228        return;
229
230    --ptr->refcount;
231    if (ptr->refcount > 0)
232        return;
233
234    if(ptr->issuer_id) abac_id_free(ptr->issuer_id);
235    if(ptr->head) abac_aspect_free(ptr->head);
236    if(ptr->tail) abac_aspect_free(ptr->tail);
237
238    if(ptr->cert) DESTROY_IF(ptr->cert);
239    if(ptr->issuer_cert) DESTROY_IF(ptr->issuer_cert);
240
241    free(ptr);
242}
243
244
245char *abac_attribute_string(abac_attribute_t *ptr) 
246{
247    char *head=abac_aspect_string_with_condition(ptr->head);
248    char *tail=abac_aspect_string_with_condition(ptr->tail);
249    if(head==NULL || tail==NULL)
250        errx(1, "attribute string, head and tail can not be NULL");
251    char *tmp=NULL;
252    asprintf(&tmp,"%s<-%s",head,tail);
253    return tmp;
254}
255char *abac_attribute_typed_string(abac_attribute_t *ptr) 
256{
257    char *head=abac_aspect_typed_string_with_condition(ptr->head);
258    char *tail=abac_aspect_typed_string_with_condition(ptr->tail);
259    if(head==NULL || tail==NULL)
260        errx(1, "attribute typed string, head and tail can not be NULL");
261    char *tmp=NULL;
262    asprintf(&tmp,"%s<-%s",head,tail);
263    return tmp;
264}
265
266/********************************************************************/
267certificate_t *abac_attribute_issuer_cert(abac_attribute_t *ptr)
268{
269   assert(ptr);
270   return ptr->issuer_cert;
271}
272
273abac_aspect_t *abac_attribute_head(abac_attribute_t *ptr)
274{
275    assert(ptr);
276    return ptr->head;
277}
278
279bool abac_attribute_is_role(abac_attribute_t *ptr)
280{
281    assert(ptr);
282    assert(ptr->head);
283    return abac_aspect_is_role(ptr->head);
284}
285
286abac_attribute_t *abac_attribute_set_head(abac_attribute_t *ptr, abac_aspect_t *head)
287{
288    assert(ptr);
289    ptr->head=head;
290    return ptr;
291}
292
293abac_aspect_t *abac_attribute_tail(abac_attribute_t *ptr)
294{
295    assert(ptr);
296    return ptr->tail;
297}
298
299abac_attribute_t *abac_attribute_add_tail(abac_attribute_t *ptr, abac_aspect_t *tail)
300{
301    assert(ptr);
302    assert(tail);
303
304    /* type of head and tail has to match */
305    abac_aspect_t *head=abac_attribute_head(ptr);
306    if(debug) {
307        fprintf(stderr, "head->(%s)\n",abac_aspect_type_string(head));
308        fprintf(stderr, "tail->(%s)\n",abac_aspect_type_string(tail));
309    }
310    if(abac_aspect_is_intersecting(tail)) {
311        if(debug) {
312            fprintf(stderr, "tail is intersection \n");
313            fprintf(stderr, "tail is (%s)\n", abac_aspect_string_with_condition(tail));
314        }
315        if(abac_aspect_intersecting_aspect_type(tail) != abac_aspect_aspect_type(head))
316            errx(1, "head and intersecting tail's aspect type does not match");
317        } else {
318            if(abac_aspect_aspect_type(head) != abac_aspect_aspect_type(tail)) {
319                if(debug)
320                    fprintf(stderr, "tail is (%s)\n", abac_aspect_string_with_condition(tail));
321                errx(1, "head and tail's aspect type does not match");
322            }
323    }
324
325    if(ptr->tail == NULL) {
326        ptr->tail=abac_aspect_dup(tail);
327        } else {
328            if(abac_aspect_is_intersecting(ptr->tail)) {
329                abac_aspect_add_intersecting_aspect(ptr->tail, tail);
330                } else {
331    /* special case.. if there is a tail there already and it is not an intersecting
332       tail, need to turn this into an intersecting tails */
333                    abac_aspect_t *nptr=abac_aspect_intersection_new(ptr->tail);
334                    abac_aspect_add_intersecting_aspect(nptr, tail);
335                    ptr->tail=nptr;
336            }
337    }
338    return ptr;
339}
340
341certificate_t *abac_attribute_cert(abac_attribute_t *ptr)
342{
343    assert(ptr);
344    return ptr->cert;
345}
346
347int abac_attribute_lastone(abac_attribute_t *ptr)
348{
349    assert(ptr);
350    if(ptr->refcount == 1)
351        return 1;
352    return 0;
353}
354
355
356abac_aspect_t **abac_attribute_tail_vectorized(abac_attribute_t *ptr)
357{
358    abac_aspect_t **tails=NULL;
359    abac_aspect_t *tail=ptr->tail;
360    abac_list_t *list=NULL;
361    int cnt=0;
362    if(tail != NULL) {
363        if(!abac_aspect_is_intersecting(tail)) {
364            tails = abac_xmalloc(sizeof(abac_aspect_t *) * 2);
365            tails[0] = abac_aspect_dup(tail);
366            tails[1] = NULL;
367            if(debug) {
368               fprintf(stderr, "abac_attribute_tail_vectorized, only 1 tail\n");
369            }
370            return tails;
371            } else {
372                abac_list_t *list=abac_aspect_prereqs(tail);
373                cnt=abac_list_size(list);
374        }
375    }
376    // make the array (leave space to NULL terminate it)
377    //      n.b., even if the list is empty, we still return an array that
378    //            only contains the NULL terminator
379    tails = abac_xmalloc(sizeof(abac_aspect_t *) * (cnt + 1));
380    abac_aspect_t  *cur;
381    int i = 0;
382    if(i<cnt) {
383        abac_list_foreach(list, cur,
384            tails[i++] = abac_aspect_dup(cur);
385        );
386    }
387    tails[i] = NULL;
388    if(debug)
389        fprintf(stderr, "abac_attribute_tail_vectorized, %d tails\n", cnt);
390    return tails;
391}
392
393void abac_aspects_free(abac_aspect_t **aspects)
394{
395    /* always null terminating */
396    assert(aspects);
397    int i;
398    for (i = 0; aspects[i] != NULL; ++i) {
399        abac_aspect_free(aspects[i]);
400    }
401    free(aspects);
402}
Note: See TracBrowser for help on using the repository browser.