source: libabac/abac_verifier.c @ f89b991

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

1) less bsd compiler complaints

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