source: libabac/abac_attribute.c @ 2cdbe49

mei_rt2mei_rt2_fix_1
Last change on this file since 2cdbe49 was 137b55f, checked in by Mei <mei@…>, 12 years ago

1) upgraded to use strongswan-4.6.4

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