source: libabac/abac_verifier.c @ d845403

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

1) add abac_oset.c
2) reorganized some yyparse related files

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