source: libabac/abac_verifier.c @ a9494ad

mei_rt2mei_rt2_fix_1meiyap-rt1rt2
Last change on this file since a9494ad was 202a7f9, checked in by Mei <mei@…>, 12 years ago

commited modified files for rt1

  • Property mode set to 100644
File size: 14.5 KB
Line 
1
2// include the GNU extension of asprintf
3#define _GNU_SOURCE
4
5#include <assert.h>
6#include <stdio.h>
7
8#include <library.h>
9#include <credentials/certificates/certificate.h>
10#include <credentials/certificates/x509.h>
11#include <credentials/certificates/ac.h>
12
13#include "abac_verifier.h"
14
15#include "abac_list.h"
16#include "abac_util.h"
17#include "abac_rt.h"
18
19extern abac_role_t *abac_get_yap_head_role();
20extern abac_role_t *abac_get_yap_tail_role();
21extern abac_list_t *abac_get_yap_clauses();
22
23/* keeping this a fixed enum is to have tighter control of
24   what are acceptabletypes of keyid are we allowing */
25enum keyidtype {
26    KEYID = 1
27};
28/* keyidname[keyidtype] */
29static const char *const keyidname[] =
30{
31  "badidtype", "keyid", 0
32};
33static int keyidname_cnt=1;
34
35enum dtermtype {
36    INT = 1,
37    URN = 2,
38    FLOAT = 3,
39    BOOLEAN = 4,
40    STRING = 5,
41    TIME = 6,
42    PRINCIPAL = 7,
43    ANONYMOUS = 8
44};
45/* dtermname[dtermtype] */
46static const char *const dtermname[] =
47{
48  "baddterm", "int", "urn", "float", "boolean", "string", "time" , "principal", "anonymous", 0
49};
50static int dtermname_cnt=8;
51
52struct _abac_id_cert_t {
53    char *keyid;
54    char *cn;
55    int type; /* keyidtype */
56    certificate_t *cert;
57    char *clause;
58
59    UT_hash_handle hh;
60};
61
62
63struct _abac_credential_t {
64    abac_role_t *head;
65    abac_role_t *tail;
66    certificate_t *cert;
67    certificate_t *issuer;
68    abac_list_t *clauses;
69
70    int refcount;
71};
72
73typedef struct _abac_str_cred_t {
74    char *strid;
75    abac_credential_t *cred;
76
77    UT_hash_handle hh;
78} abac_str_cred_t;
79
80abac_id_cert_t *id_certs = NULL;
81abac_str_cred_t *str_creds = NULL;
82
83static int debug=0;
84static void check_id_cert(abac_id_cert_t *id_cert);
85extern void abac_print_role_string_with_condition(abac_role_t *role);
86
87//
88void abac_print_cred_info(abac_credential_t *cred)
89{
90    if(debug) {
91        printf("---> printing out credential info cred(%d)..\n", (int) cred);
92        if(cred->head) {
93            printf("  head role(%d):\n",(int)cred->head);
94            abac_print_role_string_with_condition(cred->head);
95        }
96        if(cred->tail) {
97            printf("  tail role(%d):\n",(int)cred->tail);
98            abac_print_role_string_with_condition(cred->tail);
99        }
100
101        abac_list_t *clauses=cred->clauses;
102        if (clauses != NULL) {
103            char *cur=NULL;
104            abac_list_foreach(clauses, cur,
105                printf("  a clause(%d):\n",(int)cur);
106                if(cur)
107                    printf ("strlen(%d)loc(%d)(%s)\n", strlen(cur),(int)cur, cur);
108            );
109        }
110        } else {
111            printf(" ");
112            abac_print_role_string_with_condition(cred->head);
113            printf(" <- ");
114            abac_print_role_string_with_condition(cred->tail);
115            printf("\n");
116   }
117}
118
119//
120int abac_verify_keyid_type(char *type) {
121    int i;
122
123    if (type == NULL)
124        return 0;
125
126    for (i = 1; i <= keyidname_cnt ; i++)
127        if(strcmp(type,keyidname[i])==0)
128            return i;
129    return 0;
130}
131
132char *abac_keyid_type(int i)
133{
134    return keyidname[i];
135}
136
137int abac_verify_dterm_type(char *type) {
138    int i;
139
140    if (type == NULL)
141        return 0;
142
143    for (i = 1; i <= dtermname_cnt ; i++)
144        if(strcmp(type,dtermname[i])==0)
145            return i;
146    return 0;
147}
148
149// convert a chunk to a lowercase binary string
150// malloc's the string
151static char *_chunk_to_string(chunk_t chunk) {
152    int i;
153
154    char *ret = abac_xmalloc(chunk.len * 2 + 1);
155
156    for (i = 0; i < chunk.len; ++i)
157        sprintf(ret + 2 * i, "%02x", chunk.ptr[i]);
158
159    return ret;
160}
161
162// verify that cert was issued by issuer
163// cert and issuer can be the same, in which case the self-sig is validated
164static int _verify_signature(certificate_t *issuer, certificate_t *cert) {
165    if (cert->issued_by(cert, issuer))
166        if (cert->get_validity(cert, NULL, NULL, NULL))
167            return 1;
168    return 0;
169}
170
171/**
172 * Init the verifier subsystem.
173 */
174void abac_verifier_init(void) {
175    // silence all debugging
176
177    if (!library_init(NULL))
178        exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
179
180    if (!lib->plugins->load(lib->plugins, NULL,
181            lib->settings->get_str(lib->settings, "pki.load", PLUGINS)))
182        exit(SS_RC_INITIALIZATION_FAILED);
183}
184
185/**
186 * Uninitialize the system, free up any allocated memory.
187 */
188void abac_verifier_deinit(void) {
189    abac_id_cert_t *id;
190    while ((id = id_certs) != NULL) {
191        HASH_DEL(id_certs, id);
192
193        free(id->keyid);
194        free(id->cn);
195        id->cert->destroy(id->cert);
196        free(id);
197    }
198
199    abac_str_cred_t *id2;
200    while ((id2 = str_creds) != NULL) {
201        HASH_DEL(str_creds, id2);
202
203        free(id2->strid);
204        free(id2);
205    }
206
207    library_deinit();
208}
209
210/**
211 * Load an ID certificate.
212 */
213static int _load_id(certificate_t *cert, abac_id_cert_t **id_cert_ret) {
214    abac_id_cert_t *id_cert = NULL;
215    char *keyid = NULL;
216    chunk_t id;
217    int ret;
218    x509_t *x509 = (x509_t *)cert;
219
220    assert(cert != NULL);
221
222    // get the key ID
223    id = x509->get_subjectKeyIdentifier(x509);
224    keyid = _chunk_to_string(id);
225
226    char *str;
227    int rv = asprintf(&str, "%Y", cert->get_issuer(cert));
228
229    char *cn=(char *)abac_xmalloc(strlen(str)+2);
230    cn[0]='p';
231    int n=sscanf(str,"CN=%s", &(cn[1]));
232    if ( n!=1 ) { 
233        ret = ABAC_CERT_BAD_CN;
234        goto error;
235    }
236
237    if(debug) {
238        printf ("DEBUG:keyid %s \n", keyid);
239        printf( "DEBUG:issuer '%s' \n", str);
240        printf ("DEBUG:cn %s \n", cn);
241    }
242    free(str);
243
244    // if we already have this cert 'error' with success
245    HASH_FIND_STR(id_certs, keyid, id_cert);
246    if (id_cert != NULL) {
247        ret = ABAC_CERT_SUCCESS;
248        goto error;
249    }
250
251    // validate sig
252    ret = _verify_signature(cert, cert);
253    if (!ret) {
254        ret = ABAC_CERT_BAD_SIG;
255        goto error;
256    }
257
258    // success, add the key to the map of certificates
259    id_cert = abac_xmalloc(sizeof(abac_id_cert_t));
260    id_cert->keyid = keyid;
261    id_cert->cert = cert;
262    id_cert->cn = cn;
263    /* XXX default it to it now */
264    id_cert->type = KEYID;
265    id_cert->clause = generate_pl_type_clause(cn, id_cert->type);
266
267    HASH_ADD_KEYPTR(hh, id_certs, id_cert->keyid, strlen(id_cert->keyid), id_cert);
268
269    *id_cert_ret=id_cert;
270
271    return ABAC_CERT_SUCCESS;
272
273error:
274    if (keyid != NULL) free(keyid);
275    if (cn != NULL) free(cn);
276
277    return ret;
278}
279
280static void check_id_cert(abac_id_cert_t *id_cert)
281{
282    if(id_cert) {
283        printf("checking on this id_cert %d\n", (int)id_cert);
284        printf("  --> sha is (%s)\n", id_cert->keyid);
285        printf("  --> cn is (%s)\n", id_cert->cn);
286    }
287}
288
289/**
290 * Load an attribute cert as string.
291 * have minimum syntax & validity check
292XXXX
293 */
294static int _load_attribute_string(char* attr_string) {
295    printf("NOT implemented yet!!!");
296    return ABAC_CERT_INVALID;
297}
298
299/**
300 * Load an ID cert from a file.
301 */
302int abac_verifier_load_id_file(char *filename, abac_id_cert_t **id_cert_ret) {
303    if (lib == NULL)
304        errx(1, "looks like you didn't call libabac_init() (lib is NULL)");
305
306    // load the cert
307    certificate_t *cert = lib->creds->create(
308        lib->creds, CRED_CERTIFICATE, CERT_X509,
309        BUILD_FROM_FILE, filename,
310        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
311        BUILD_END
312    );
313    if (cert == NULL)
314        return ABAC_CERT_INVALID;
315    return _load_id(cert,id_cert_ret);
316}
317
318/**
319 * Load an ID cert from a chunk.
320 */
321int abac_verifier_load_id_chunk(chunk_t chunk, abac_id_cert_t **id_cert_ret) {
322    // load the cert
323    certificate_t *cert = lib->creds->create(
324        lib->creds, CRED_CERTIFICATE, CERT_X509,
325        BUILD_BLOB_ASN1_DER, chunk,
326        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
327        BUILD_END
328    );
329    if (cert == NULL)
330        return ABAC_CERT_INVALID;
331    return _load_id(cert,id_cert_ret);
332}
333
334
335void abac_print_clauses(abac_list_t *clauses)
336{
337    if (clauses != NULL) {
338        char *cur;
339        abac_list_foreach(clauses, cur,
340            if(cur)
341                printf ("a clause, %d(%s)\n", (int)cur,cur);
342        );
343    }
344}
345
346/**
347 * Load an attribute cert.
348 * Returns true only if the certificate is valid and is issued by the proper
349 * authority.
350 */
351static int _load_attribute_cert(certificate_t *cert, abac_credential_t **cred_ret) {
352    ietf_attributes_t *attr_cert = NULL;
353    abac_role_t *head_role = NULL;
354    abac_role_t *tail_role = NULL;
355    abac_list_t *clauses=NULL;
356    abac_id_cert_t *issuer;
357    char *attr_string_copy;
358    int ret, i;
359
360    // get the attr
361    ac_t *ac = (ac_t *)cert;
362    attr_cert = ac->get_groups(ac);
363    if (attr_cert == NULL) {
364        ret = ABAC_CERT_INVALID;
365        goto error;
366    }
367
368    char *attr_string = attr_cert->get_string(attr_cert);
369    if (attr_string == NULL) {
370        ret = ABAC_CERT_INVALID;
371        goto error;
372    }
373
374    /* call into yacc parser */
375    attr_string_copy = strdup(attr_string);
376    abac_reset_yyfptr(attr_string_copy);
377    abac_yyinit();
378    int rc=yyparse();
379    if (rc) {
380        ret = ABAC_CERT_INVALID;
381        goto error;
382    }
383    head_role = abac_get_yap_head_role();
384    tail_role = abac_get_yap_tail_role();
385    clauses = abac_get_yap_clauses();
386
387    // get the issuer based on keyid
388    char *principalname = abac_role_principal(head_role);
389    HASH_FIND_STR(id_certs, principalname, issuer);
390    if (issuer == NULL) {
391        ret = ABAC_CERT_MISSING_ISSUER;
392        goto error;
393    }
394
395    // make sure the issuer's signed it
396    ret = _verify_signature(issuer->cert, cert);
397    if (!ret) {
398        set_error_code(ABAC_RT_CERT_BAD_SIG);
399        goto error;
400    }
401
402    // at this point we know we have a good attribute cert
403    abac_credential_t *cred = abac_xmalloc(sizeof(abac_credential_t));
404    cred->head = head_role;
405    cred->tail = tail_role;
406    cred->cert = cert;
407    cred->issuer = issuer->cert->get_ref(issuer->cert);
408    cred->clauses = clauses;
409    cred->refcount = 1;
410    *cred_ret = cred;
411
412    // success, add the key to the map of certificates
413    abac_str_cred_t *str_cred;
414    str_cred=abac_xmalloc(sizeof(abac_str_cred_t));
415    str_cred->strid=attr_string_copy;
416    str_cred->cred=cred;
417    HASH_ADD_KEYPTR(hh, str_creds, str_cred->strid, strlen(str_cred->strid), str_cred);
418
419    // free up some crap
420    attr_cert->destroy(attr_cert);
421
422    return ABAC_CERT_SUCCESS;
423
424error:
425    if (cert) cert->destroy(cert);
426    if (attr_cert) attr_cert->destroy(attr_cert);
427    if (head_role) abac_role_free(head_role);
428    if (tail_role) abac_role_free(tail_role);
429    if (attr_string_copy) free(attr_string_copy);
430    abac_free_yap_clauses();
431
432    return ret;
433}
434
435/**
436 * Load an attribute cert from a file.
437 */
438int abac_verifier_load_attribute_cert_file(char *filename, abac_credential_t **cred) {
439    // load the cert
440    certificate_t *cert = lib->creds->create(
441        lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
442        BUILD_FROM_FILE, filename,
443        BUILD_END
444    );
445    if (cert == NULL)
446        return ABAC_CERT_INVALID;
447    return _load_attribute_cert(cert, cred);
448}
449
450/**
451 * Load attribute cert rules from a file. (this should only be used to test)
452 */
453int abac_verifier_load_certs_file(char *filename) {
454    size_t nbytes=0;
455    char *input=NULL;
456    FILE *fp;
457    int ret;
458
459    fp=fopen(filename, "r");
460
461    if(fp == NULL)
462        return ABAC_CERT_INVALID;
463
464    while( (ret=getline(&input, &nbytes, fp)) != -1 ) {
465        ret=_load_attribute_string(input);
466        free(input);
467        if(ret != ABAC_CERT_SUCCESS )
468            fclose(fp);
469            return ret;
470    }
471    fclose(fp);
472    return ABAC_CERT_SUCCESS;
473}
474
475
476/**
477 * Load an attribute cert from a chunk.
478 */
479int abac_verifier_load_attribute_cert_chunk(chunk_t chunk, abac_credential_t **cred) {
480    // load the cert
481    certificate_t *cert = lib->creds->create(
482        lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
483        BUILD_BLOB_ASN1_DER, chunk,
484        BUILD_END
485    );
486    if (cert == NULL)
487        return ABAC_CERT_INVALID;
488    return _load_attribute_cert(cert, cred);
489}
490
491/**
492 * Return the head role.
493 */
494abac_role_t *abac_credential_head(abac_credential_t *cred) {
495    return cred->head;
496}
497
498/**
499 * Return the tail role.
500 */
501abac_role_t *abac_credential_tail(abac_credential_t *cred) {
502    return cred->tail;
503}
504
505/**
506 * Return the encoding of the attribute cert.
507 */
508abac_chunk_t abac_credential_attribute_cert(abac_credential_t *cred) {
509    chunk_t encoding = cred->cert->get_encoding(cred->cert);
510    abac_chunk_t ret = { encoding.ptr, encoding.len };
511    return ret;
512}
513
514/**
515 * Return the encoding of the issuer cert.
516 */
517abac_chunk_t abac_credential_issuer_cert(abac_credential_t *cred) {
518    chunk_t encoding = cred->issuer->get_encoding(cred->issuer);
519    abac_chunk_t ret = { encoding.ptr, encoding.len };
520    return ret;
521}
522
523/**
524 * Return the clause of the cert
525 */
526abac_list_t *abac_credential_clauses(abac_credential_t *cred) {
527    return cred->clauses;
528}
529
530
531/**
532 * Increase the ref count of a credential.
533 */
534abac_credential_t *abac_credential_dup(abac_credential_t *cred) {
535    assert(cred != NULL);
536
537    ++cred->refcount;
538    return cred;
539}
540
541/**
542 *  lookup for a credential.
543 */
544abac_credential_t *abac_credential_lookup(char* cred_string)
545{
546    if(debug)
547        printf("DEBUG:doing abac_crendential_lookup ... (%s)\n", cred_string);
548    abac_str_cred_t *str_cred;
549    HASH_FIND_STR(str_creds, cred_string, str_cred);
550    if (str_cred == NULL) {
551        if(debug) printf("DEBUG:NOT FOUND..\n");
552        return NULL;
553    }
554    if(debug) printf("DEBUG:FOUND..(%d)\n", (int) str_cred->cred);
555    return str_cred->cred;
556}
557
558/**
559 * Decrease the reference count of a credential, freeing it when it reaches 0.
560 */
561void abac_credential_free(abac_credential_t *cred)
562{
563    if(debug)
564        printf("DEBUG:freeing cred(%d)clause(%d)\n", (int)cred, (int)cred->clauses);
565
566    if (cred == NULL)
567        return;
568
569    --cred->refcount;
570    if (cred->refcount > 0)
571        return;
572
573    abac_role_free(cred->head);
574    abac_role_free(cred->tail);
575    cred->cert->destroy(cred->cert);
576    cred->issuer->destroy(cred->issuer); // reference counted
577    /* no need to free yap_clauses here */
578    free(cred);
579}
580
581char *abac_id_clause(abac_id_cert_t *id_cert)
582{
583    if(id_cert)
584        return id_cert->clause;
585    return NULL;
586}
587
588/* retrieve the cn that is associated with this sha_string */
589char *abac_cn_with_sha(char *sha_string) {
590
591    // get the issuer based on keyid
592    abac_id_cert_t *id_cert;
593    HASH_FIND_STR(id_certs, sha_string, id_cert);
594    if (id_cert == NULL) {
595        return NULL;
596    }
597    if(debug)
598        check_id_cert(id_cert);
599    return id_cert->cn;
600}
601
602/* retrieve the cn that is associated with the principal of this role */
603char *abac_cn_with_role(abac_role_t *role) {
604
605    char *principal = abac_role_principal(role);
606    return abac_cn_with_sha(principal);
607}
608
Note: See TracBrowser for help on using the repository browser.