source: libabac/abac_attribute.c @ 888df49

mei_rt2mei_rt2_fix_1
Last change on this file since 888df49 was 2efdff5, checked in by Mei <mei@…>, 12 years ago

1) fix the missing check for 'This' rt2.y when called from creddy/prover

combo

2) patch up the stringify of abac_term that is of time type.
3) update the testing to reflect the changes to baseline output

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