source: libabac/abac_verifier.c @ 13c9479

mei_rt2mei_rt2_fix_1
Last change on this file since 13c9479 was 8bd77b5, checked in by Mei <mei@…>, 12 years ago

1) convert parser and libabac to use id cred and attr cred like

creddy (move those 2 files to libabac).

2) fix up abac.hh to work with expanded libabac. can now build

structure from python script

3) redid the credential dump using the internal credential table

instead of depending on a search in db.

  • Property mode set to 100644
File size: 18.4 KB
Line 
1/**
2**  abac_verifier.c
3**/
4
5// include the GNU extension of asprintf
6#define _GNU_SOURCE
7
8#include <assert.h>
9#include <stdio.h>
10
11#include <library.h>
12
13#include "abac_internal.h"
14#include "abac_verifier.h"
15
16#include "abac_util.h"
17#include "abac_rt.h"
18
19static int debug=0;
20
21extern abac_aspect_t *abac_yy_get_rule_head_aspect();
22extern abac_aspect_t *abac_yy_get_rule_tail_aspect();
23extern abac_list_t *abac_yy_get_rule_clauses();
24extern char* abac_decode_string(char *);
25extern void abac_yy_free_rule_clauses();
26extern char *generate_pl_type_clause(char *, int);
27
28extern void abac_print_aspect_string_with_condition(abac_aspect_t *role, FILE*);
29
30struct _abac_id_credential_t {
31    char *hashkeyid; 
32    abac_id_t *id;
33    char *pl_clause;
34
35    UT_hash_handle hh;
36};
37/* hash table base on sha with a p */
38abac_id_credential_t *id_creds = NULL;
39
40/* can store either role or oset */
41struct _abac_credential_t {
42    char *hashkeyid;
43    abac_attribute_t *attr;
44    abac_list_t *pl_clauses;
45
46    UT_hash_handle hh;
47};
48/* hash table base on encoded attr rule */
49abac_credential_t *attr_creds = NULL;
50/* linked list of all the attr's hashkeyid */
51abac_list_t *attr_hashkeyid_list = NULL;
52
53/*****************************************************************************/
54void abac_print_cred_info(abac_credential_t *cred, FILE *fp)
55{
56    if(fp == NULL)
57        fp=stdout;
58
59    abac_attribute_t *ptr=cred->attr;
60    abac_aspect_t *head=abac_attribute_head(ptr);
61    abac_aspect_t *tail=abac_attribute_tail(ptr);
62
63    if(debug) {
64        fprintf(fp,"---> printing out credential info cred(%d)..\n", (int) cred);
65        if(head) {
66            abac_print_aspect_string_with_condition(head,fp);
67        }
68        if(tail) {
69            abac_print_aspect_string_with_condition(tail,fp);
70        }
71
72        abac_list_t *clauses=cred->pl_clauses;
73        if (clauses != NULL) {
74            char *cur=NULL;
75            abac_list_foreach(clauses, cur,
76                fprintf(fp,"\n  a clause(%d):\n",(int)cur);
77                if(cur)
78                    fprintf(fp,"strlen(%d)loc(%d)(%s)\n", strlen(cur),(int)cur, cur);
79            );
80        }
81        } else {
82            fprintf(fp," ");
83            abac_print_aspect_string_with_condition(head,fp);
84            fprintf(fp," <- ");
85            abac_print_aspect_string_with_condition(tail,fp);
86            fprintf(fp,"\n");
87   }
88}
89
90//
91int abac_verify_idtype_type(char *type) {
92    int i;
93
94    if (type == NULL)
95        return 0;
96
97    for (i = 1; i <= _idtypename_cnt ; i++)
98        if(strcmp(type,_idtypename[i])==0)
99            return i;
100    return 0;
101}
102
103char *abac_idtype_string(int i)
104{
105    if(i > _idtypename_cnt)
106        panic("abac_idtype_string: went out of range on idtypename");
107    return _idtypename[i];
108}
109
110// convert a chunk to a lowercase binary string
111// malloc's the string
112static char *_chunk_to_string(chunk_t chunk) {
113    int i;
114
115    char *ret = abac_xmalloc(chunk.len * 2 + 1);
116
117    for (i = 0; i < chunk.len; ++i)
118        sprintf(ret + 2 * i, "%02x", chunk.ptr[i]);
119
120    return ret;
121}
122
123// verify that cert was issued by issuer
124// cert and issuer can be the same, in which case the self-sig is validated
125static int _verify_signature(certificate_t *issuer_cert, certificate_t *cert) {
126    if (cert->issued_by(cert, issuer_cert))
127        if (cert->get_validity(cert, NULL, NULL, NULL))
128            return 1;
129    return 0;
130}
131
132/**
133 * Init the verifier subsystem.
134 */
135void abac_verifier_init(void) {
136    // silence all debugging
137
138    if (!library_init(NULL))
139        exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
140
141    if (!lib->plugins->load(lib->plugins, NULL,
142            lib->settings->get_str(lib->settings, "pki.load", PLUGINS)))
143        exit(SS_RC_INITIALIZATION_FAILED);
144
145    attr_hashkeyid_list = abac_list_new();
146}
147
148/**
149 * Uninitialize the system, free up any allocated memory.
150 */
151void abac_verifier_deinit(void) {
152    abac_id_credential_t *ptr;
153    while ((ptr = id_creds) != NULL) {
154        HASH_DEL(id_creds, ptr);
155
156        free(ptr->hashkeyid);
157        free(ptr->pl_clause);
158        abac_id_free(ptr->id);
159        free(ptr);
160    }
161
162    abac_credential_t *ptr2;
163    while ((ptr2 = attr_creds) != NULL) {
164        HASH_DEL(attr_creds, ptr2);
165        if(debug) {
166           printf("attr_creds -- %s\n",ptr2->hashkeyid); 
167        }
168        free(ptr2->hashkeyid);
169        abac_attribute_free(ptr2->attr);
170        char *cur=NULL;
171        abac_list_foreach(ptr2->pl_clauses, cur,
172              free(cur);
173        );
174        free(ptr2->pl_clauses);
175        free(ptr2);
176    }
177
178    if(attr_hashkeyid_list) { 
179        char *cur;
180        if(attr_hashkeyid_list) {
181            abac_list_foreach(attr_hashkeyid_list, cur,
182                if(cur) free(cur);
183            );
184        }
185        abac_list_free(attr_hashkeyid_list);
186    }
187    library_deinit();
188}
189
190abac_id_credential_t *abac_verifier_add_id_credential(abac_id_t *a_id)
191{ 
192    abac_id_credential_t *id_cred;
193    char *cn=abac_id_cn(a_id);
194    char *keyid=NULL;
195    asprintf(&keyid,"p%s",abac_id_keyid(a_id));
196
197    // add the abac_id to the map of id credentials
198    id_cred = abac_xmalloc(sizeof(abac_id_credential_t));
199    id_cred->hashkeyid = abac_xstrdup(keyid);
200    id_cred->id=abac_id_dup(a_id);
201
202    /* special handling here */
203    if(USE("ABAC_CN")) {
204        id_cred->pl_clause = generate_pl_type_clause(cn, abac_id_idtype(a_id));
205        } else {
206           id_cred->pl_clause=generate_pl_type_clause(keyid, abac_id_idtype(a_id));
207    }
208    HASH_ADD_KEYPTR(hh, id_creds, id_cred->hashkeyid, strlen(id_cred->hashkeyid), id_cred);
209    if(debug)
210        printf("-->adding into id_creds, (%s)..cnt(%d)\n",
211                                   id_cred->hashkeyid, HASH_COUNT(id_creds));
212
213     free(keyid);
214     return id_cred;
215}
216
217/**
218 * Load an ID certificate.
219 */
220static int _load_id(abac_id_t **a_id,certificate_t *cert, abac_id_credential_t **id_cred_ret) {
221    abac_id_credential_t *id_cred = NULL;
222    char *okeyid, *keyid = NULL;
223    chunk_t id;
224    int ret;
225    x509_t *x509 = (x509_t *)cert;
226
227    assert(cert != NULL);
228
229    // get the key ID, add p to keyid SHA here */
230    id = x509->get_subjectKeyIdentifier(x509);
231    okeyid = _chunk_to_string(id);
232    asprintf(&keyid,"p%s",okeyid);
233
234    /* Mike said this is the way it is */
235    char *str;
236    int rv = asprintf(&str, "%Y", cert->get_issuer(cert));
237
238    /* add p to cn name here */
239    char *cn=(char *)abac_xmalloc(strlen(str)+2);
240    cn[0]='p';
241    int n=sscanf(str,"CN=%s", &(cn[1]));
242    if ( n!=1 ) { 
243        ret = ABAC_CERT_BAD_CN;
244        goto error;
245    }
246
247    if(debug) {
248        printf ("DEBUG:keyid %s \n", keyid);
249        printf( "DEBUG:issuer '%s' \n", str);
250        printf ("DEBUG:cn %s \n", cn);
251    }
252    free(str);
253
254    // if we already have this cert 'error' with success
255    HASH_FIND_STR(id_creds, keyid, id_cred);
256    if (id_cred != NULL) {
257        ret = ABAC_CERT_SUCCESS;
258        goto error;
259    }
260
261    // validate sig
262    ret = _verify_signature(cert, cert);
263    if (!ret) {
264        ret = ABAC_CERT_BAD_SIG;
265        goto error;
266    }
267
268    // success, add a new abac_id
269    if(*a_id ==NULL)
270        *a_id = abac_id_keyid_new(okeyid,cn,cert);
271
272    abac_id_credential_t *n_id_cred=abac_verifier_add_id_credential(*a_id);
273    *id_cred_ret=n_id_cred;
274
275    return ABAC_CERT_SUCCESS;
276
277error:
278    if (keyid != NULL) free(keyid);
279    if (cn != NULL) free(cn);
280
281    return ret;
282}
283
284/* collect all the creds stored so far */
285abac_stack_t *abac_verifier_dump_creds()
286{
287    abac_stack_t *cred_list = abac_stack_new();
288
289    int cnt=0;
290    if(attr_hashkeyid_list) {
291        char *keyid;
292        abac_credential_t *cred;
293        abac_list_foreach(attr_hashkeyid_list, keyid,
294            cred=abac_credential_lookup(keyid);
295            abac_stack_push(cred_list, cred);
296            cnt++;
297        );
298    }
299    return cred_list;
300}
301
302
303static void check_id_cred(abac_id_credential_t *id_cred)
304{
305    if(id_cred) {
306        printf("checking on this id_cred location %d\n", (int)id_cred);
307        printf("  --> sha is (%s)\n", abac_id_keyid(id_cred->id));
308        printf("  --> cn is (%s)\n", abac_id_cn(id_cred->id));
309    }
310}
311
312/**
313 * Load an attribute cert as string.
314 * have minimum syntax & validity check
315 */
316static int _load_attribute_string(char* attr_string) {
317    printf("NOT implemented yet!!!");
318    return ABAC_CERT_INVALID;
319}
320
321/**
322 * Load an ID cert from a file.
323 */
324int abac_verifier_load_id_file(char *filename, abac_id_credential_t **id_cred_ret) {
325    abac_id_t *id=NULL;
326    if (lib == NULL)
327        errx(1, "looks like you didn't call libabac_init() (lib is NULL)");
328
329    // load the cert
330    certificate_t *cert = lib->creds->create(
331        lib->creds, CRED_CERTIFICATE, CERT_X509,
332        BUILD_FROM_FILE, filename,
333        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
334        BUILD_END
335    );
336    if (cert == NULL)
337        return ABAC_CERT_INVALID;
338    return _load_id(&id,cert,id_cred_ret);
339}
340
341/**
342 * Load an ID cert from a abac_id_t
343 */
344int abac_verifier_load_id_id(abac_id_t *id, abac_id_credential_t **id_cred_ret) {
345    certificate_t *cert = abac_id_cert(id);
346    return _load_id(&id,cert,id_cred_ret);
347}
348
349/**
350 * Load an ID cert from a chunk.
351 */
352int abac_verifier_load_id_chunk(chunk_t chunk, abac_id_credential_t **id_cred_ret) {
353    abac_id_t *id=NULL;
354    // load the cert
355    certificate_t *cert = lib->creds->create(
356        lib->creds, CRED_CERTIFICATE, CERT_X509,
357        BUILD_BLOB_ASN1_DER, chunk,
358        BUILD_X509_FLAG, X509_AA, // attribute authority, dumb
359        BUILD_END
360    );
361    if (cert == NULL)
362        return ABAC_CERT_INVALID;
363    return _load_id(&id, cert,id_cred_ret);
364}
365
366
367void abac_print_clauses(abac_list_t *clauses, FILE *fp)
368{
369    if (clauses != NULL) {
370        char *cur;
371        printf("total-- %d clauses\n", abac_list_size(clauses));
372        abac_list_foreach(clauses, cur,
373            if(cur) {
374                if(fp)
375                    fprintf (fp,"a clause, %d(%s)\n", (int)cur,cur);
376                    else printf ("a clause, %d(%s)\n", (int)cur,cur);
377            }
378        );
379    }
380}
381
382abac_id_credential_t *abac_id_credential_dup(abac_id_credential_t *ptr) {
383    assert(ptr != NULL);
384    abac_id_dup(ptr->id);
385    return ptr;
386}
387
388abac_id_t *abac_id_credential_id(abac_id_credential_t *ptr)
389{
390    assert(ptr);
391    return ptr->id;
392}
393
394
395abac_id_credential_t *abac_id_credential_lookup(char *pname)
396{
397    abac_id_credential_t *id_cred=NULL;
398    HASH_FIND_STR(id_creds, pname, id_cred);
399    return id_cred;
400}
401
402void abac_id_credential_free(abac_id_credential_t *ptr)
403{
404    if (ptr == NULL)
405        return;
406
407    // this is very hacky...
408    int last=abac_id_lastone(ptr->id);
409    if(!last) {
410        abac_id_free(ptr->id);
411        } else {
412            free(ptr->hashkeyid);
413            if(ptr->pl_clause)
414                free(ptr->pl_clause);
415            abac_id_free(ptr->id);
416            HASH_DEL(id_creds, ptr);
417            free(ptr);
418    }
419}
420
421/****************************************************************************/
422
423static int _verify_valid_credential(certificate_t *cert,
424abac_credential_t **cred_ret, char *encoded_attr_string)
425{
426    abac_aspect_t *head_aspect = NULL;
427    abac_aspect_t *tail_aspect = NULL;
428    abac_list_t *clauses=NULL;
429    abac_id_credential_t *id_cred;
430    abac_id_t *issuer_id;
431    int ret, i;
432
433    // get the attr
434    head_aspect = abac_yy_get_rule_head_aspect();
435    tail_aspect = abac_yy_get_rule_tail_aspect();
436    clauses = abac_yy_get_rule_clauses();
437
438    // get the issuer based on keyid
439    char *principalname = abac_aspect_principal_principalname(head_aspect);
440    if(debug) printf("LOOKING for %s\n", principalname);
441
442    HASH_FIND_STR(id_creds, principalname, id_cred);
443    issuer_id=id_cred->id;
444    if (issuer_id == NULL) {
445        ret = ABAC_CERT_MISSING_ISSUER;
446        if(debug)
447             printf("can not find %s in id_creds\n", principalname);
448        goto error;
449    }
450
451
452    // make sure the issuer's signed it
453    ret = _verify_signature(abac_id_cert(issuer_id), cert);
454    if (!ret) {
455        abac_yy_set_error_code(ABAC_RT_CERT_BAD_SIG);
456        goto error;
457    }
458
459    // at this point we know we have a good attribute cert baked it in
460    abac_attribute_t *attr=abac_attribute_new(issuer_id, cert, cert->get_ref(cert));
461    abac_attribute_set_head(attr, head_aspect);
462    abac_attribute_add_tail(attr, tail_aspect);
463
464    abac_credential_t *cred = abac_xmalloc(sizeof(abac_credential_t));
465    cred->hashkeyid=abac_xstrdup(encoded_attr_string);
466    cred->attr=attr;
467    cred->pl_clauses = clauses;
468    *cred_ret = cred;
469
470    // success, add the key to the map of certificates
471    HASH_ADD_KEYPTR(hh, attr_creds, cred->hashkeyid, strlen(cred->hashkeyid), cred);
472
473    assert(attr_hashkeyid_list);
474    abac_list_add(attr_hashkeyid_list, abac_xstrdup(cred->hashkeyid));
475    return ABAC_CERT_SUCCESS;
476
477error:
478    if (head_aspect) abac_aspect_free(head_aspect);
479    if (tail_aspect) abac_aspect_free(tail_aspect);
480    abac_yy_free_rule_clauses();
481
482    return ret;
483}
484
485/**
486 * Load an attribute cert.
487 * Returns true only if the certificate is valid and is issued by the proper
488 * authority.
489 */
490static int _load_attribute_cert(certificate_t *cert, abac_credential_t **cred_ret) {
491    ietf_attributes_t *attr_cert = NULL;
492    abac_id_credential_t *issuer;
493    int ret, i;
494
495    // get the attr
496    ac_t *ac = (ac_t *)cert;
497    attr_cert = ac->get_groups(ac);
498    if (attr_cert == NULL) {
499        ret = ABAC_CERT_INVALID;
500        goto error;
501    }
502
503    char *encoded_attr_string=attr_cert->get_string(attr_cert);
504    char *attr_string = abac_decode_string(encoded_attr_string);
505    if(debug)
506         printf("string to be yyparse..(%s)\n",attr_string);
507
508    if (attr_string == NULL) {
509        ret = ABAC_CERT_INVALID;
510        goto error;
511    }
512
513    /* call into yacc parser */
514    abac_reset_yyfptr(attr_string);
515    abac_yy_init();
516    int rc=yyparse();
517    if (rc) {
518        ret = ABAC_CERT_INVALID;
519        goto error;
520    }
521
522    ret=_verify_valid_credential(cert,cred_ret,encoded_attr_string);
523
524    // free up some crap
525    attr_cert->destroy(attr_cert);
526
527    return ABAC_CERT_SUCCESS;
528
529error:
530    if (cert) cert->destroy(cert);
531    if (attr_cert) attr_cert->destroy(attr_cert);
532    return ret;
533}
534
535/**
536 * Load an attribute cert from a abac_attribute_t.
537 */
538int abac_verifier_load_attribute_cert_attribute(abac_attribute_t *attr, abac_credential_t **cred) {
539    // load the cert
540    certificate_t *cert = abac_attribute_cert(attr);
541    if (cert == NULL)
542        return ABAC_CERT_INVALID;
543   
544    // XXX need to skip the parsing part
545    return _load_attribute_cert(cert, cred);
546}
547
548/**
549 * Load an attribute cert from a file.
550 */
551int abac_verifier_load_attribute_cert_file(char *filename, abac_credential_t **cred) {
552    // load the cert
553    certificate_t *cert = lib->creds->create(
554        lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
555        BUILD_FROM_FILE, filename,
556        BUILD_END
557    );
558    if (cert == NULL)
559        return ABAC_CERT_INVALID;
560    return _load_attribute_cert(cert, cred);
561}
562
563/**
564 * Load an attribute cert from a chunk.
565 */
566int abac_verifier_load_attribute_cert_chunk(chunk_t chunk, abac_credential_t **cred) {
567    // load the cert
568    certificate_t *cert = lib->creds->create(
569        lib->creds, CRED_CERTIFICATE, CERT_X509_AC,
570        BUILD_BLOB_ASN1_DER, chunk,
571        BUILD_END
572    );
573    if (cert == NULL)
574        return ABAC_CERT_INVALID;
575    return _load_attribute_cert(cert, cred);
576}
577
578/**
579 * Return the encoding of the attribute cert.
580 */
581abac_chunk_t abac_credential_attribute_cert(abac_credential_t *cred) {
582    abac_attribute_t *ptr=cred->attr;
583    certificate_t *cert=abac_attribute_cert(ptr);
584    chunk_t encoding = cert->get_encoding(cert);
585    abac_chunk_t ret = { encoding.ptr, encoding.len };
586    return ret;
587}
588
589/**
590 * Return the encoding of the issuer cert.
591 */
592abac_chunk_t abac_credential_issuer_cert(abac_credential_t *cred) {
593    certificate_t *issuer_cert=abac_attribute_issuer_cert(cred->attr);
594    assert(issuer_cert);
595    chunk_t encoding = issuer_cert->get_encoding(issuer_cert);
596    abac_chunk_t ret = { encoding.ptr, encoding.len };
597    return ret;
598}
599
600/**
601 * Return the clause of the cert
602 */
603abac_list_t *abac_credential_clauses(abac_credential_t *cred) {
604    return cred->pl_clauses;
605}
606
607abac_attribute_t *abac_credential_attribute(abac_credential_t *cred) {
608    assert(cred);
609    return cred->attr;
610}
611
612/**
613 * Increase the ref count of a credential.
614 */
615abac_credential_t *abac_credential_dup(abac_credential_t *cred) {
616    assert(cred != NULL);
617
618    abac_attribute_dup(cred->attr);
619    return cred;
620}
621
622/**
623 *  lookup for a credential.
624 */
625abac_credential_t *abac_credential_lookup(char* cred_string)
626{
627    if(debug)
628        printf("abac_credential_lookup: looking for (%s)\n", cred_string);
629    abac_credential_t *attr_cred;
630    HASH_FIND_STR(attr_creds, cred_string, attr_cred);
631    if (attr_cred == NULL) {
632        if(debug) printf("DEBUG:NOT FOUND..\n");
633        return NULL;
634    }
635    abac_credential_t *rt=abac_credential_dup(attr_cred);
636    if(debug) printf("DEBUG:FOUND.. (%d) returning, (%d)\n", (int)attr_cred, (int) rt);
637    return rt;
638}
639
640/**
641 * Decrease the reference count of a credential, freeing it when it reaches 0.
642 */
643void abac_credential_free(abac_credential_t *cred)
644{
645    if(debug)
646        printf("abac_credential_free:freeing cred(%d)clause(%d)\n", (int)cred, (int)cred->pl_clauses);
647
648    if (cred == NULL)
649        return;
650
651    // this is very hacky...
652    int last=abac_attribute_lastone(cred->attr);
653    if(!last) {
654        abac_attribute_free(cred->attr);
655        } else {
656            free(cred->hashkeyid);
657            char *cur=NULL;
658            abac_list_foreach(cred->pl_clauses, cur,
659                free(cur);
660            );
661            abac_attribute_free(cred->attr);
662            HASH_DEL(attr_creds, cred);
663            free(cred);
664    }
665}
666
667char *abac_id_clause(abac_id_credential_t *id_cred)
668{
669    if(id_cred)
670        return id_cred->pl_clause;
671    return NULL;
672}
673
674/* retrieve the cn that is associated with this sha_string */
675char *abac_cn_with_sha(char *sha_string) {
676
677    // get the issuer based on keyid
678    abac_id_credential_t *id_cred;
679    HASH_FIND_STR(id_creds, sha_string, id_cred);
680    if (id_cred == NULL) {
681        return NULL;
682    }
683    if(debug)
684        check_id_cred(id_cred);
685    return abac_id_cn(id_cred->id);
686}
687
688char *abac_idtype_with_sha(char* sha_string)
689{ 
690    // get the issuer based on keyid
691    abac_id_credential_t *id_cred;
692    HASH_FIND_STR(id_creds, sha_string, id_cred);
693    if (id_cred == NULL) {
694        return NULL;
695    }
696    int idtype=abac_id_idtype(id_cred->id);
697   
698    return abac_idtype_string(idtype);
699}
700
701abac_aspect_t *abac_credential_head(abac_credential_t *cred) {
702    return abac_attribute_head(cred->attr); 
703}
704
705abac_aspect_t *abac_credential_tail(abac_credential_t *cred) {
706    return abac_attribute_tail(cred->attr); 
707}
708
709
Note: See TracBrowser for help on using the repository browser.