source: libabac/abac_verifier.c @ bc0ce98

mei_rt2
Last change on this file since bc0ce98 was 2e9455f, checked in by Mei <mei@…>, 11 years ago

1) added namespace
2) tweak ?This,
3) allowing linking role/oset as constraining conditions
4) adding access_tests regression testing that uses GENI's access policy
5) added couple multi contexts regression tests
6) add compression/uncompression calls to abac_encode_string/abac_decode_string
(libstrongwan only allows 512 char for attribute rule storage)
7) add attribute_now option to creddy that takes a whole char string for attribute
rule

  • Property mode set to 100644
File size: 17.4 KB
Line 
1/**
2**  abac_verifier.c
3**/
4
5// include the GNU extension of asprintf
6#define _GNU_SOURCE
7
8#include <stdio.h>
9#include <sys/types.h>
10#include <assert.h>
11
12#include <library.h>
13
14#include <chunk.h>
15#include "abac_internal.h"
16#include "abac_util.h"
17#include "abac_context.h"
18#include "abac_list.h"
19#include "abac_stack.h"
20#include "uthash.h"
21#include "abac_id.h"
22#include "abac_attribute.h"
23#include "abac_pl_yap.h"
24
25static int debug=0;
26static int hack=1;
27
28/* need to add locks onto theseXXX */
29/* hash table base on sha with a p */
30struct _abac_id_credential_t {
31    char *hashkeyid;
32    abac_id_t *id;
33    UT_hash_handle hh;
34};
35
36/* can store either role or oset */
37struct _abac_credential_t {
38    char *hashkeyid;
39    abac_attribute_t *attr;
40    UT_hash_handle hh;
41};
42
43typedef struct _abac_verifier_session_t {
44    abac_list_t *contexts;
45    char *stub; /* namespace stub */
46
47    abac_id_credential_t *id_creds;
48/* linked list of all the ids's hashkeyid */
49    abac_list_t *id_hashkeyid_list;
50
51/* hash table base on encoded attr rule */
52/* can store either role or oset */
53    abac_credential_t *attr_creds;
54    abac_list_t *attr_hashkeyid_list;
55
56} abac_verifier_session_t;
57
58
59/* **GLOBAL** the one and only */
60abac_verifier_session_t *abac_session=NULL;
61
62/* local */
63abac_id_t *abac_id_credential_id(abac_id_credential_t *ptr);
64char *abac_idtype_string(int i);
65/****************************************************************/
66void show_debug_info(const char *msg)
67{
68    int ctxt_sz=0;
69    int id_sz=0;
70    int attr_sz=0;
71    if(abac_session !=NULL) {
72        ctxt_sz=abac_list_size(abac_session->contexts);
73        id_sz=abac_list_size(abac_session->id_hashkeyid_list);
74        attr_sz=abac_list_size(abac_session->attr_hashkeyid_list);
75    }
76    fprintf(stderr,"/* ===== %s ======== */\n",msg);
77    fprintf(stderr,"  number of contexts: %d\n",ctxt_sz);
78    fprintf(stderr,"  number of principals: %d\n",id_sz);
79    fprintf(stderr,"  number of attributes: %d\n",attr_sz);
80   
81}
82
83static void _check_id_cred(abac_id_credential_t *id_cred)
84{
85    if(id_cred) {
86        printf("checking on this id_cred location %d\n", (int)id_cred);
87        printf("  --> sha is (%s)\n", abac_id_keyid(id_cred->id));
88        printf("  --> cn is (%s)\n", abac_id_cn(id_cred->id));
89    }
90}
91
92/* retrieve the cn that is associated with this sha_string, checking
93   with just the master list */
94char *abac_cn_with_sha(char *sha_string)
95{
96   // get the issuer based on keyid
97    abac_id_credential_t *id_cred;
98    HASH_FIND_STR(abac_session->id_creds, sha_string, id_cred);
99    if (id_cred == NULL) {
100        return NULL;
101    }
102    if(debug)
103        _check_id_cred(id_cred);
104    return abac_id_cn(id_cred->id);
105}
106
107char *abac_idtype_with_sha(char* sha_string)
108{
109    // get the issuer based on keyid
110    abac_id_credential_t *id_cred;
111    HASH_FIND_STR(abac_session->id_creds, sha_string, id_cred);
112    if (id_cred == NULL) {
113        // this id, sha string is not in the db...
114        DEBUG_PRINTF("abac_idtype_with_sha: this id is not in the id_creds list\n");
115        return NULL;
116    }
117    int idtype=abac_id_idtype(id_cred->id);
118    return abac_idtype_string(idtype);
119}
120
121/****************************************************************/
122/**
123 * abac_credential_t                               
124**/
125abac_id_credential_t *abac_id_credential_new(abac_id_t *a_id)
126{
127    char *keyid=abac_id_keyid(a_id);
128
129    abac_id_credential_t *id_cred = abac_xmalloc(sizeof(abac_id_credential_t));
130    id_cred->hashkeyid = abac_xstrdup(keyid);
131    id_cred->id=abac_id_dup(a_id);
132    return id_cred;
133}
134
135abac_id_credential_t *abac_id_credential_dup(abac_id_credential_t *ptr)
136{
137    assert(ptr != NULL);
138    DEBUG_PRINTF("calling abac_id_credential_dup, increment id ref count\n");
139    abac_id_dup(ptr->id);
140    return ptr;
141}
142
143abac_id_t *abac_id_credential_id(abac_id_credential_t *ptr)
144{
145    assert(ptr);
146    return ptr->id;
147}
148
149char *abac_id_credential_hashkey(abac_id_credential_t *ptr)
150{
151    assert(ptr);
152    return ptr->hashkeyid;
153}
154
155/* XXX needs to lock this !! */
156void abac_add_id_cred(abac_id_credential_t *id_cred)
157{
158    HASH_ADD_KEYPTR(hh, abac_session->id_creds, id_cred->hashkeyid,
159                                     strlen(id_cred->hashkeyid), id_cred);
160    abac_list_add(abac_session->id_hashkeyid_list,
161                                        abac_xstrdup(id_cred->hashkeyid));
162
163    DEBUG_PRINTF("-->adding into master id_creds, key(%s)..idx(%d)sz(%d)\n",
164       id_cred->hashkeyid, HASH_COUNT(abac_session->id_creds),
165       abac_list_size(abac_session->id_hashkeyid_list));
166}
167
168abac_id_credential_t *abac_check_id_cred(char *keyid)
169{
170    abac_id_credential_t *id_cred=NULL;
171    HASH_FIND_STR(abac_session->id_creds, keyid, id_cred);
172    return id_cred;
173}
174
175void abac_id_credential_free(abac_id_credential_t *ptr)
176{
177    char *keyid=ptr->hashkeyid;
178    int found=0;
179
180    DEBUG_PRINTF("abac_id_credential_free: keyid(%s)\n", keyid);
181
182    char *cur=NULL;
183    abac_list_foreach(abac_session->id_hashkeyid_list, cur,
184        if(strcmp(cur,keyid)==0) {
185            found=1;
186            break;
187        }
188    );
189    assert(found==1); // big panic
190
191    // this is very tricky...
192    int last=abac_id_lastone(ptr->id);
193    if(!last) {
194        abac_id_free(ptr->id);
195        } else {
196            DEBUG_PRINTF("abac_id_credential_free: deleting id (%s)(%s)\n",abac_id_name(ptr->id), cur);
197            abac_list_remove(abac_session->id_hashkeyid_list, cur);
198            free(cur);
199
200            free(ptr->hashkeyid);
201            abac_id_free(ptr->id);
202            HASH_DEL(abac_session->id_creds, ptr);
203            free(ptr);
204    }
205}
206
207/****************************************************************/
208/**
209 * abac_credential_t                               
210**/
211
212abac_credential_t *abac_credential_new(abac_attribute_t *attr, char* key)
213{
214    abac_credential_t *cred = abac_xmalloc(sizeof(abac_credential_t));
215    cred->hashkeyid=abac_xstrdup(key);
216    cred->attr=abac_attribute_dup(attr);
217    return cred;
218}
219
220abac_attribute_t *abac_credential_attribute(abac_credential_t *ptr)
221{
222    assert(ptr!=NULL);
223    return ptr->attr;
224}
225
226abac_credential_t *abac_credential_dup(abac_credential_t *ptr)
227{
228    assert(ptr != NULL);
229    abac_attribute_dup(ptr->attr);
230    return ptr;
231}
232
233void abac_add_cred(abac_credential_t *cred)
234{
235    HASH_ADD_KEYPTR(hh, abac_session->attr_creds, cred->hashkeyid,
236                                         strlen(cred->hashkeyid), cred);
237    abac_list_add(abac_session->attr_hashkeyid_list,
238                                     abac_xstrdup(cred->hashkeyid));
239
240    DEBUG_PRINTF("-->adding into master attr_creds, key(%s)..idx(%d)sz(%d)\n",
241          abac_decode_string(cred->hashkeyid), HASH_COUNT(abac_session->attr_creds),
242          abac_list_size(abac_session->attr_hashkeyid_list));
243}
244
245
246abac_aspect_t *abac_credential_head(abac_credential_t *cred)
247{
248    return abac_attribute_head(cred->attr);
249}
250
251abac_aspect_t *abac_credential_tail(abac_credential_t *cred) 
252{
253    return abac_attribute_tail(cred->attr);
254}
255
256char *abac_credential_hashkey(abac_credential_t *ptr)
257{
258    assert(ptr);
259    return ptr->hashkeyid;
260}
261
262abac_credential_t *abac_check_cred(char *keyid)
263{
264    abac_credential_t *cred=NULL;
265    HASH_FIND_STR(abac_session->attr_creds, keyid, cred);
266    return cred;
267}
268
269/**
270 * Decrease the reference count of a credential, freeing it when it reaches 0.
271 */
272void abac_credential_free(abac_credential_t *ptr)
273{
274    /* first make sure it is there */
275    char *keyid=ptr->hashkeyid;
276    int found=0;
277
278    DEBUG_PRINTF("abac_credential_free: keyid(%s)\n", keyid);
279
280    char *cur;
281    abac_list_foreach(abac_session->attr_hashkeyid_list, cur,
282        if(strcmp(cur,keyid)==0) {
283            found=1;
284            break;
285        }
286    );
287    assert(found==1); // big panic
288
289    // this is very tricky...
290    int last=abac_attribute_lastone(ptr->attr);
291    if(!last) {
292        abac_attribute_free(ptr->attr);
293        } else {
294
295            abac_list_remove(abac_session->attr_hashkeyid_list, cur);
296            free(cur);
297
298            DEBUG_PRINTF("abac_credential_free: real free for (%d)\n",(int) ptr);
299            free(ptr->hashkeyid);
300            abac_attribute_free(ptr->attr);
301            HASH_DEL(abac_session->attr_creds, ptr);
302            free(ptr);
303    }
304}
305
306/****************************************************************/
307void abac_print_cred_info(abac_credential_t *cred, FILE *fp)
308{
309    if(fp == NULL)
310        fp=stdout;
311
312    abac_attribute_t *ptr=cred->attr;
313    abac_aspect_t *head=abac_attribute_head(ptr);
314    abac_aspect_t *tail=abac_attribute_tail(ptr);
315
316    fprintf(fp," ");
317    abac_print_aspect_string_with_condition(head,fp);
318    fprintf(fp," <- ");
319    abac_print_aspect_string_with_condition(tail,fp);
320    fprintf(fp,"\n");
321}
322
323void abac_print_prin_info(abac_id_credential_t *prin, FILE *fp)
324{
325    if(fp == NULL)
326        fp=stdout;
327
328    abac_id_t *ptr=abac_id_credential_id(prin);
329    if(abac_id_has_privkey(ptr))
330        fprintf(fp," [%s,%s] #y\n",abac_id_idtype_string(ptr), abac_id_name(ptr));
331        else
332            fprintf(fp," [%s,%s] #n\n", abac_id_idtype_string(ptr), abac_id_name(ptr));
333}
334
335void abac_print_typed_cred_info(abac_credential_t *cred, FILE *fp)
336{
337    if(fp == NULL)
338        fp=stdout;
339
340    abac_attribute_t *ptr=cred->attr;
341    abac_aspect_t *head=abac_attribute_head(ptr);
342    abac_aspect_t *tail=abac_attribute_tail(ptr);
343
344    fprintf(fp," ");
345    abac_print_aspect_typed_string_with_condition(head,fp);
346    fprintf(fp," <- ");
347    abac_print_aspect_typed_string_with_condition(tail,fp);
348    fprintf(fp,"\n");
349}
350
351
352/* not duplicated */
353abac_credential_t *abac_credential_lookup(char* cred_string)
354{
355    assert(cred_string);
356    DEBUG_PRINTF("abac_credential_lookup: looking for (%s)\n", cred_string);
357    abac_credential_t *attr_cred;
358    HASH_FIND_STR(abac_session->attr_creds, cred_string, attr_cred);
359    if (attr_cred == NULL) {
360        DEBUG_PRINTF("abac_credential_lookup:NOT FOUND..\n");
361        return NULL;
362    }
363    DEBUG_PRINTF("abac_credential_lookup:FOUND, looking for (%s)\n", cred_string);
364    abac_credential_t *rt=attr_cred;
365    return rt;
366}
367
368/* not duplicated */
369abac_id_credential_t *abac_id_credential_lookup(char* name)
370{
371    assert(name);
372    DEBUG_PRINTF("abac_id_credential_lookup: looking for (%s)\n", name);
373    abac_id_credential_t *id_cred;
374    HASH_FIND_STR(abac_session->id_creds, name, id_cred);
375    if (id_cred == NULL) {
376        DEBUG_PRINTF("abac_id_credential_lookup:NOT FOUND..\n");
377        return NULL;
378    }
379    DEBUG_PRINTF("  --> sha is (%s)\n", abac_id_keyid(id_cred->id));
380    DEBUG_PRINTF("  --> cn is (%s)\n", abac_id_cn(id_cred->id));
381    return id_cred;
382}
383
384/* collect all the creds stored so far for the session */
385abac_stack_t *abac_dump_creds()
386{
387    abac_stack_t *cred_list = abac_stack_new();
388
389    int cnt=0;
390    if(abac_session->attr_hashkeyid_list) {
391        char *keyid;
392        abac_credential_t *cred;
393        abac_list_foreach(abac_session->attr_hashkeyid_list, keyid,
394            cred=abac_credential_lookup(keyid);
395            abac_stack_push(cred_list, cred);
396            cnt++;
397        );
398    }
399    DEBUG_PRINTF("abac_dump_cred: %d\n",cnt);
400    return cred_list;
401}
402
403
404/* collect all the id creds stored so far for the session */
405abac_stack_t *abac_dump_principals()
406{
407    abac_stack_t *id_list = abac_stack_new();
408
409    int cnt=0;
410    if(abac_session->id_hashkeyid_list) {
411        char *keyid;
412        abac_id_credential_t *id;
413        abac_list_foreach(abac_session->id_hashkeyid_list, keyid,
414            id=abac_id_credential_lookup(keyid);
415            abac_stack_push(id_list, id);
416            cnt++;
417        );
418    }
419    DEBUG_PRINTF("abac_dump_principals: %d\n",cnt);
420    return id_list;
421}
422
423/**
424 * Return the encoding of the attribute cert.
425 */
426abac_chunk_t abac_credential_attribute_cert(abac_credential_t *cred) {
427    abac_attribute_t *ptr=cred->attr;
428    certificate_t *cert=abac_attribute_cert(ptr);
429    chunk_t encoding = chunk_empty;
430    int rc=cert->get_encoding(cert,CERT_ASN1_DER,&encoding);
431    abac_chunk_t ret = { encoding.ptr, encoding.len };
432    return ret;
433}
434
435/**
436 * Return the encoding of the issuer cert.
437 */
438abac_chunk_t abac_credential_issuer_cert(abac_credential_t *cred)
439{
440    certificate_t *issuer_cert=abac_attribute_issuer_cert(cred->attr);
441    assert(issuer_cert);
442    chunk_t encoding = chunk_empty;
443// XXX MEI, not sure ??
444    int rc=issuer_cert->get_encoding(issuer_cert,CERT_ASN1_DER,&encoding);
445    abac_chunk_t ret = { encoding.ptr, encoding.len };
446    return ret;
447}
448
449
450/****************************************************************/
451
452void abac_verifier_session_new() 
453{
454    assert(abac_session==NULL);
455    abac_session = abac_xmalloc(sizeof(abac_verifier_session_t));
456    abac_session->stub=abac_xstrdup("abac_");
457    abac_session->contexts=abac_list_new();
458
459    abac_session->attr_hashkeyid_list = abac_list_new();
460    abac_session->id_hashkeyid_list = abac_list_new();
461    abac_session->id_creds=NULL;
462    abac_session->attr_creds=NULL;
463 
464    abac_pl_init();
465}
466
467void abac_verifier_session_free() 
468{
469    DEBUG_PRINTF("abac_verifier_session_free: freeing...\n");
470    if(abac_session->stub) free(abac_session->stub);
471
472    int size=abac_list_size(abac_session->contexts);
473    if(size) {
474        abac_context_t *cur;
475        abac_stack_t *tmp=abac_stack_new();
476        abac_list_foreach(abac_session->contexts, cur,
477            if(cur) abac_stack_push(tmp,cur);
478        );
479        while(size) {
480            cur=(abac_context_t *) abac_stack_pop(tmp);
481            abac_context_free(cur);
482            size--;
483        }
484        abac_stack_free(tmp);
485    }
486    abac_list_free(abac_session->contexts);
487
488    abac_id_credential_t *ptr;
489    int id_sz=abac_list_size(abac_session->id_hashkeyid_list);
490    DEBUG_PRINTF("abac_verifier_session_free: number of ids(%d)\n",id_sz);
491    while ((ptr = abac_session->id_creds) != NULL) {
492        DEBUG_PRINTF("abac_verifier_session_free: deleting id (%s)\n",abac_id_name(ptr->id));
493        HASH_DEL(abac_session->id_creds, ptr);
494        free(ptr->hashkeyid);
495        abac_id_free(ptr->id);
496        free(ptr);
497    }
498
499    abac_credential_t *ptr2;
500    int attr_sz=abac_list_size(abac_session->attr_hashkeyid_list);
501    DEBUG_PRINTF("abac_verifier_session_free: number of attrs(%d)\n",attr_sz);
502    while ((ptr2 = abac_session->attr_creds) != NULL) {
503        HASH_DEL(abac_session->attr_creds, ptr2);
504        DEBUG_PRINTF("abac_verifier_session_free: deleting attr hashkey(%s)\n",ptr2->hashkeyid);
505        free(ptr2->hashkeyid); 
506        abac_attribute_free(ptr2->attr); 
507        free(ptr2);
508    }
509
510    if(abac_session->attr_hashkeyid_list) {
511        DEBUG_PRINTF("looking to free attr_hashkeyid_list..\n");
512        char *cur;
513        abac_list_foreach(abac_session->attr_hashkeyid_list, cur,
514            if(cur) free(cur);
515        );
516        abac_list_free(abac_session->attr_hashkeyid_list);
517    }
518
519    if(abac_session->id_hashkeyid_list) {
520        DEBUG_PRINTF("looking to free id_hashkeyid_list..\n");
521        char *cur;
522        abac_list_foreach(abac_session->id_hashkeyid_list, cur,
523            if(cur) {
524               DEBUG_PRINTF("hum.. id hashkey being freed.. %s\n", cur);
525               free(cur);
526            }
527        );
528        abac_list_free(abac_session->id_hashkeyid_list);
529    }
530    free(abac_session);
531    abac_session=NULL;
532}
533
534/* long int random(void); */
535char *abac_verifier_session_next_namespace()
536{
537    char *tmp=NULL;
538    asprintf(&tmp,"%s_%ld",abac_session->stub,random());
539    return tmp;
540}
541
542void abac_verifier_session_add_context(abac_context_t *ctx)
543{
544    abac_list_add(abac_session->contexts, ctx);
545}
546
547void abac_verifier_session_dump()
548{
549     printf("....SESSION....\n");
550     int cnt=abac_list_size(abac_session->contexts);
551     abac_context_t *cur;
552     abac_list_foreach(abac_session->contexts, cur,
553        if(cur) abac_context_dump(cur);
554     );
555}
556
557int abac_verifier_session_remove_context(abac_context_t *ctx)
558{
559    int rc=abac_list_remove(abac_session->contexts, ctx);
560    if(rc!=1) {
561        DEBUG_PRINTF("abac_verifier_session_remove_context, ??? did not find context\n");
562        exit(ABAC_VERIFIER_UNKNOWN_CONTEXT);
563    }
564    return rc;
565}
566
567abac_context_t *abac_verifier_session_context_lookup(char *namespace)
568{
569    abac_context_t  *cur;
570    abac_list_foreach(abac_session->contexts, cur,
571           if(strcmp(abac_context_namespace(cur),namespace)==0)
572               return cur;
573    );
574    return NULL;
575}
576
577/****************************************************************/
578int abac_verify_idtype_type(char *type) {
579    if (type == NULL) return 0;
580    return abac_idtype_lookup(type);
581}
582
583// verify that cert was issued by issuer
584// cert and issuer can be the same, in which case the self-sig is validated
585int verify_signature(certificate_t *issuer_cert, certificate_t *cert)
586{
587/** XXX for strongswan 5.0.1
588    if (cert->issued_by(cert, issuer_cert, NULL))
589*/
590    if (cert->issued_by(cert, issuer_cert))
591        if (cert->get_validity(cert, NULL, NULL, NULL)) {
592            return 1;
593        }
594    return 0;
595}
596
597/**
598 * Init the verifier subsystem.
599 */
600void abac_verifier_init(void) {
601    // silence all debugging
602
603    DEBUG_PRINTF("abac_verifier_init... init strongswan..\n");
604    if (!library_init(NULL))
605        exit(SS_RC_LIBSTRONGSWAN_INTEGRITY);
606
607    if (!lib->plugins->load(lib->plugins, NULL,
608            lib->settings->get_str(lib->settings, "pki.load", PLUGINS)))
609        exit(SS_RC_INITIALIZATION_FAILED);
610
611    abac_verifier_session_new();
612}
613
614/**
615 * Uninitialize the system, free up any allocated memory.
616 */
617void abac_verifier_deinit(void) {
618    DEBUG_PRINTF("abac_verifier_deinit... being called..\n");
619    abac_verifier_session_free();
620/* XXX crashs in swig/python?java, it is as some threads before
621   getting into library deinit */
622    if(!hack) {
623        DEBUG_PRINTF("now it is time to deinit strongswan lib..\n");
624        library_deinit();
625    }
626}
Note: See TracBrowser for help on using the repository browser.