source: libabac/abac_context.c @ d0efdec

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

1) less bsd compiler complaints

  • Property mode set to 100644
File size: 45.4 KB
Line 
1/**
2**  abac_context.c
3**/
4
5#include <assert.h>
6#include <err.h>
7#include <glob.h>
8#include <stdio.h>
9#include <regex.h>
10#include <sys/mman.h>
11#include <fcntl.h>
12#include <sys/types.h>
13#include <sys/stat.h>
14#include <unistd.h>
15
16#include <chunk.h>
17
18#include "abac_util.h"
19
20#include "abac_context.h"
21#include "abac_list.h"
22#include "abac_stack.h"
23#include "abac_pl_yap.h"
24#include "abac_pl_yy.h"
25#include "uthash.h"
26#include "abac_id.h"
27#include "abac_verifier.h"
28#include "abac_id.h"
29#include "abac_pl_gen.h"
30#include "abac_attribute.h"
31#include "abac_aspect.h"
32#include "abac_m64.h"
33#include "rt2_yy.h"
34#include "abac_util_cert.h"
35
36static int debug=0;
37
38#define KEY_PAT "/*_private.{der,pem}"
39#define ID_PAT "/*_ID.{der,pem}"
40#define ATTR_PAT "/*_attr.der"
41#define IDKEY_PAT "/*_IDKEY.{der,pem}"
42
43struct _abac_context_t {
44    char *namespace;
45    abac_pl_t *pl; /* prolog query structure */
46
47    abac_list_t *context_pl_clauses;
48
49/* linked list of all the ids's hashkeyid */
50    abac_list_t *context_id_hashkeyid_list;
51
52/* linked list of all the attr's hashkeyid */
53    abac_list_t *context_attr_hashkeyid_list;
54};
55
56/* local */
57int abac_context_load_id_id(abac_context_t *ctxt,abac_id_t *id);
58static chunk_t _extract_chunk(char *data, char* startline, char* endline);
59int abac_context_load_attribute_credential(abac_context_t *, abac_attribute_t *, abac_credential_t *);
60/****************************************************************/
61/**
62 * Create a new abac context.
63 */
64abac_context_t *abac_context_new(void)
65{
66    libabac_init();
67
68    DEBUG_PRINTF("creating a new context... \n");
69
70    abac_context_t *ctxt = abac_xmalloc(sizeof(abac_context_t));
71    ctxt->namespace=abac_verifier_session_next_namespace();
72    ctxt->pl = abac_pl_new(ctxt);
73    ctxt->context_attr_hashkeyid_list = abac_list_new();
74    ctxt->context_id_hashkeyid_list = abac_list_new();
75    ctxt->context_pl_clauses = abac_list_new();
76    abac_verifier_session_add_context(ctxt);
77    return ctxt;
78}
79
80/* create a new context with a specific namespace */
81abac_context_t *abac_context_named_new(char *namespace)
82{
83    assert(namespace!=NULL);
84    libabac_init();
85
86    abac_context_t *ctxt = abac_xmalloc(sizeof(abac_context_t));
87    ctxt->namespace=abac_xstrdup(namespace);
88    ctxt->pl = abac_pl_new(ctxt);
89    ctxt->context_attr_hashkeyid_list = abac_list_new();
90    ctxt->context_id_hashkeyid_list = abac_list_new();
91    ctxt->context_pl_clauses = abac_list_new();
92    abac_verifier_session_add_context(ctxt);
93    return ctxt;
94}
95
96char *abac_context_namespace(abac_context_t *ctxt)
97{
98    assert(ctxt!=NULL);
99    return abac_xstrdup(ctxt->namespace);
100}
101
102/**
103 * Deep copy an abac context. --
104 */
105abac_context_t *abac_context_dup(abac_context_t *ctxt)
106{
107    assert(ctxt!=NULL);
108    abac_context_t *dup = abac_xmalloc(sizeof(abac_context_t));
109    dup->namespace=abac_verifier_session_next_namespace();
110    dup->pl = abac_pl_new(dup);
111
112    dup->context_attr_hashkeyid_list = abac_list_new();
113    dup->context_id_hashkeyid_list = abac_list_new();
114    dup->context_pl_clauses = abac_list_new();
115
116/* copy over and build up the prolog */
117   if(ctxt->context_id_hashkeyid_list) {
118        abac_id_credential_t *id_cred;
119        abac_id_t *id;
120        char *cur;
121        abac_list_foreach(ctxt->context_id_hashkeyid_list, cur,
122            if(cur) {
123/* id_cred=abac_check_id_cred(cur); */
124                id_cred=abac_id_credential_lookup(cur);
125                id=abac_id_credential_id(id_cred);
126                assert(id!=NULL);
127                /* id=abac_id_dup(id); */
128                abac_context_load_id_id(dup,id);
129            }
130        );
131    }
132    if(ctxt->context_attr_hashkeyid_list) {
133        abac_credential_t *attr_cred;
134        abac_attribute_t *attr;
135        char *cur;
136        int sz=abac_list_size(ctxt->context_attr_hashkeyid_list);
137        abac_list_foreach(ctxt->context_attr_hashkeyid_list, cur,
138            if(cur) { /* cur is the hash key */
139/* attr_cred=abac_check_cred(cur); */
140                attr_cred=abac_credential_lookup(cur);
141                assert(attr_cred);
142                attr=abac_credential_attribute(attr_cred);
143                assert(attr);
144                /* attr=abac_attribute_dup(attr);
145                abac_context_load_attribute_credential(dup,attr,attr_cred);
146                */
147                abac_context_load_attribute_attribute(dup,attr);
148            }
149        );
150    }
151    abac_verifier_session_add_context(dup);
152    return dup;
153}
154
155/**************************************************************/
156abac_id_credential_t *abac_context_add_id_credential(abac_context_t *ctxt, abac_id_t *a_id)
157{ 
158    char *cn=abac_id_cn(a_id);
159    char *keyid=abac_id_keyid(a_id);
160
161    /* see if it already exist */
162    abac_id_credential_t *id_cred;
163    id_cred=abac_id_credential_lookup(keyid);
164
165    /* add to master list if new */
166    if(id_cred == NULL) {
167        id_cred=abac_id_credential_new(a_id);
168        abac_add_id_cred(id_cred); 
169        } else { /* increment the reference count */
170            id_cred=abac_id_credential_dup(id_cred);
171    }
172
173    DEBUG_PRINTF("abac_context_add_id_credential, cn(%s)keyid(%s)\n",cn,keyid);
174    /* special handling here */
175    char *tmp;
176    if(USE("ABAC_CN")) {
177        tmp=generate_pl_type_clause(ctxt, cn, abac_id_idtype(a_id));
178        } else {
179           tmp=generate_pl_type_clause(ctxt, prologIt(keyid), abac_id_idtype(a_id));
180    }
181    abac_list_add(ctxt->context_pl_clauses,tmp);
182
183    /* insert into db */
184   int rc=abac_pl_add_type_credential(tmp);
185   
186    /* add to local hash list */
187    abac_list_add(ctxt->context_id_hashkeyid_list,
188                   abac_xstrdup(abac_id_credential_hashkey(id_cred)));
189
190    return id_cred;
191}
192
193/* have to find the last cn
194   CN=test/emailAddress=abac.isi.edu, CN=12345678
195   CN=client
196   ..CN=255a03f3-ed30/emailAddress=..
197*/
198static char* _extract_cn(char *string)
199{
200    /* find the first CN= */
201    char *ptr=strstr(string,"CN=");
202    if(ptr == NULL) return NULL;
203
204    /* look for last CN= */
205    while(1) {
206       char *tptr=ptr+3;
207       char *p=strstr(tptr,"CN=");
208       if(p) ptr=p;
209           else break;
210    }
211
212    /* remove the possible additional stuff */
213    char *cn=abac_xstrdup(ptr); /* it would get write over */
214    char *nptr=strtok(cn,"/");
215    char *pcn=abac_xmalloc(sizeof(char) * strlen(nptr));
216    pcn[0]='p';
217    /* special case.. replace empty space with _ */
218    int i=strlen(nptr);
219    while(i--) 
220       if(nptr[i]==' ') nptr[i]='_';
221    sscanf(nptr,"CN=%s", &pcn[1]);
222    free(cn);
223    return pcn;
224}
225
226// convert a chunk to a lowercase binary string
227// malloc's the string
228static char *_chunk_to_string(chunk_t chunk) {
229    int i;
230
231    char *ret = abac_xmalloc(chunk.len * 2 + 1);
232
233    for (i = 0; i < chunk.len; ++i)
234        sprintf(ret + 2 * i, "%02x", chunk.ptr[i]);
235
236    return ret;
237}
238
239// verify that cert is still valid
240static int _verify_validity(certificate_t *cert) {
241    if (cert->get_validity(cert, NULL, NULL, NULL))
242        return 1;
243    return 0;
244}
245
246/**
247 * Load an ID
248 */
249static int _load_id(abac_context_t *ctxt, abac_id_t **a_id,certificate_t *cert)
250{
251    int ret;
252    abac_id_credential_t *id_cred = NULL;
253
254    assert(cert != NULL);
255
256    // get the key ID, add p to keyid SHA here */
257    char *keyid =cert_get_keyid(cert);
258
259    /* Mike said this is the way it is */
260    char *str=NULL;
261    int rv = asprintf(&str, "%Y", cert->get_issuer(cert));
262
263    /* add p to cn name here, if there is no useable one
264       reuse keyid */
265    char *cn=_extract_cn(str);
266    if(cn == NULL) {
267        DEBUG_PRINTF("DEBUG:did not find usable cn, reuse keyid\n");
268        cn=abac_xstrdup(keyid);
269    }
270
271    DEBUG_PRINTF("DEBUG:keyid %s \n", keyid);
272    DEBUG_PRINTF("DEBUG:issuer '%s' \n", str);
273    DEBUG_PRINTF("DEBUG:cn %s \n", cn);
274    free(str);
275
276    // validate validity
277    ret = _verify_validity(cert);
278    if (!ret) {
279        ret = ABAC_CERT_INVALID;
280        goto error;
281    }
282
283    // validate sig
284    ret = verify_signature(cert, cert);
285    if (!ret) {
286        /* well.. this is not a self signed cert, don't fault it anymore */
287        DEBUG_PRINTF("This is not a self-signed cert \n");
288        } else {
289            DEBUG_PRINTF("This is a self-signed cert \n");
290    }
291
292    // if we already have this cert in the context, 'error' with success
293    id_cred=abac_context_id_credential_lookup(ctxt, keyid);
294    if (id_cred != NULL) {
295        DEBUG_PRINTF("existing cert \n");
296        /* needs to increment the ref count */
297        abac_id_credential_dup(id_cred);
298        ret = ABAC_CERT_EXISTS;
299        goto error;
300        } else {
301            // if we don't have it in context but in session, then
302            // we need to insert into the local context
303            abac_id_credential_t *icred=abac_id_credential_lookup(keyid);
304            if(icred!=NULL) {
305                *a_id=abac_id_credential_id(icred);
306                 DEBUG_PRINTF("_load_id:already exists in session.(%s)\n",abac_id_cn(*a_id));
307                } else  {
308                   // all else fail.. insert as a new id
309                   if(*a_id==NULL) *a_id=abac_id_keyid_new(keyid,cn,cert);
310            }
311            id_cred=abac_context_add_id_credential(ctxt,*a_id);
312    }
313
314    if (keyid != NULL) free(keyid);
315    if (cn != NULL) free(cn);
316    return ABAC_CERT_SUCCESS;
317
318error:
319    if (keyid != NULL) free(keyid);
320    if (cn != NULL) free(cn);
321
322    return ret;
323}
324
325
326int abac_context_creds_count(abac_context_t *ctxt)
327{
328    int sz=abac_list_size(ctxt->context_attr_hashkeyid_list);
329    return sz;
330}
331
332int abac_context_id_creds_count(abac_context_t *ctxt)
333{
334    int sz=abac_list_size(ctxt->context_id_hashkeyid_list);
335    return sz;
336}
337
338/* collect all the creds for this context */
339abac_stack_t *abac_context_dump_creds(abac_context_t *ctxt)
340{
341    abac_stack_t *cred_list = abac_stack_new();
342
343    int cnt=0;
344    if(ctxt->context_attr_hashkeyid_list) {
345        char *keyid=NULL;
346        abac_credential_t *cred=NULL;
347        abac_list_foreach(ctxt->context_attr_hashkeyid_list, keyid,
348            cred=abac_credential_lookup(keyid);
349            if(cred!=NULL)
350                abac_stack_push(cred_list, abac_credential_dup(cred));
351                else {
352                    char *btmp=abac_decode_string(keyid);
353                    fprintf(stderr,"??? BADDD (%s)\n", btmp);
354                    assert(0);
355                }
356            cnt++;
357        );
358    }
359    DEBUG_PRINTF("abac_context_dump_creds: %d\n",cnt);
360    return cred_list;
361}
362
363/* collect all the id stored for this context */
364abac_stack_t *abac_context_dump_principals(abac_context_t *ctxt)
365{
366    abac_stack_t *id_list = abac_stack_new();
367
368    int cnt=0;
369    int sz=abac_list_size(ctxt->context_id_hashkeyid_list);
370
371    if(ctxt->context_id_hashkeyid_list) {
372        char *keyid;
373        abac_id_credential_t *id;
374        abac_list_foreach(ctxt->context_id_hashkeyid_list, keyid,
375            id=abac_id_credential_lookup(keyid);
376            abac_stack_push(id_list, abac_id_credential_dup(id));
377            cnt++;
378        );
379    }
380    DEBUG_PRINTF("abac_context_dump_principals: %d\n",cnt);
381    return id_list;
382}
383
384/**
385 * Load an attribute cert as string.
386 * have minimum syntax & validity check
387 */
388static int _load_attribute_string(abac_context_t *ctxt, char* attr_string) {
389    printf("NOT implemented yet!!!");
390    return ABAC_CERT_INVALID;
391}
392
393/**
394 * Load an ID cert from a file and key from a file.
395 */
396int abac_context_load_id_id_key_files(abac_context_t *ctxt, char *filename,
397char *keyfilename)
398{
399    struct stat sb;
400
401    assert(ctxt != NULL);
402    assert(filename != NULL);
403
404    abac_id_t *id=NULL;
405    if (lib == NULL)
406        errx(1, "looks like you didn't call libabac_init() (lib is NULL)");
407
408    DEBUG_PRINTF("loading id & key files... %s\n", filename);
409    certificate_t *cert = cert_get_id_cert_from_file(filename);
410
411    if (cert == NULL)
412        return ABAC_CERT_INVALID;
413
414    int rc=_load_id(ctxt,&id,cert);
415
416    if(rc==ABAC_CERT_EXISTS) {
417        DEBUG_PRINTF("abac_context_load_id_id_key_files: id already exists\n");
418        return ABAC_CERT_SUCCESS;
419    } 
420
421    /* try to load the private key if it is there */
422    if((rc==ABAC_CERT_SUCCESS) && keyfilename!=NULL && file_exist(keyfilename)) {
423        DEBUG_PRINTF("loading... %s\n", keyfilename);
424        int keyrc=abac_id_load_privkey_file(id, keyfilename);
425        if(keyrc == 1)
426            DEBUG_PRINTF("..load id: load(%s) with a private key\n",filename)
427
428            else DEBUG_PRINTF("..load id: load(%s) without a private key\n",filename)
429    }
430
431    return ABAC_CERT_SUCCESS;
432}
433
434/**
435 * Load an ID cert from files.
436 */
437int abac_context_load_id_enc_id_key_files(abac_context_t *ctxt, char *filename,
438char *keyfilename, char *pfile)
439{
440    abac_id_t *id=NULL;
441    assert(ctxt != NULL); assert(filename != NULL); assert(keyfilename!=NULL);
442
443    if (lib == NULL)
444        errx(1, "looks like you didn't call libabac_init() (lib is NULL)");
445
446    DEBUG_PRINTF("loading enc id & key files... %s\n", filename);
447
448    // load the cert, with public key
449    certificate_t *cert = cert_get_id_cert_from_file(filename);
450    if (cert == NULL) return ABAC_CERT_INVALID;
451
452    int rc=_load_id(ctxt,&id,cert);
453    if(rc==ABAC_CERT_EXISTS) {
454        DEBUG_PRINTF("abac_context_load_id_id_key_files: id already exists\n");
455        return ABAC_CERT_SUCCESS;
456    } 
457
458    /* try to load the private key if it is there */
459    if((rc==ABAC_CERT_SUCCESS) && keyfilename!=NULL && file_exist(keyfilename)) {
460        DEBUG_PRINTF("loading... %s\n", keyfilename);
461        int keyrc=abac_id_load_enc_privkey_file(id, keyfilename, pfile);
462        if(keyrc == 1) 
463            DEBUG_PRINTF("..load id: load(%s) with a private key\n",filename)
464           else DEBUG_PRINTF("..load id: load(%s) without a private key\n",filename)
465    }
466    return ABAC_CERT_SUCCESS;
467}
468
469/**
470 * Load an ID cert from a abac_id_t, used from abac.hh and actually
471 * makes a separate copy
472 */
473int abac_context_load_id(abac_context_t *ctxt,abac_id_t *id)
474{
475    assert(ctxt != NULL); assert(id);
476    abac_id_t *nid = abac_id_copy(id);
477    certificate_t *cert = abac_id_cert(nid);
478    int ret=_load_id(ctxt,&nid,cert);
479    return ret;
480}
481
482/**
483 * Load an ID cert from a abac_id_t
484 */
485int abac_context_load_id_id(abac_context_t *ctxt,abac_id_t *id)
486{
487    assert(ctxt != NULL); assert(id);
488
489    certificate_t *cert = abac_id_cert(id);
490    int ret=_load_id(ctxt,&id,cert);
491    return ret;
492}
493
494/**
495 * Load an ID cert from a pem chunk.
496 */
497int abac_context_load_id_pem_chunk(abac_context_t *ctxt, chunk_t chunk)
498{
499    abac_id_t *id=NULL;
500
501    // load the cert
502    certificate_t *cert = cert_get_id_cert_from_pem_chunk(chunk);
503    if (cert == NULL) return ABAC_CERT_INVALID;
504
505    return _load_id(ctxt,&id,cert);
506}
507
508/* used locally */
509static int _abac_context_load_id_pem_chunk(abac_context_t *ctxt, abac_id_t **a_id, chunk_t chunk)
510{
511    // load the cert
512    certificate_t *cert = cert_get_id_cert_from_pem_chunk(chunk);
513    if (cert == NULL) return ABAC_CERT_INVALID;
514
515    return _load_id(ctxt,a_id,cert);
516}
517
518/**
519 * Load an ID cert from a chunk, Note, this only loads the id cert part
520 * and so it is not suitable for creating an attribute credential with.
521 * Only a complete id cert + privkey could create attribute credential.
522 */
523int abac_context_load_id_chunk(abac_context_t *ctxt, abac_chunk_t ccert)
524{
525    assert(ctxt != NULL);
526
527    chunk_t cert_chunk = { ccert.ptr, ccert.len };
528    abac_id_t *id=NULL;
529
530    // load the cert
531    certificate_t *cert = cert_get_id_cert_from_chunk(cert_chunk);
532
533    if (cert == NULL) return ABAC_CERT_INVALID;
534
535    int ret=_load_id(ctxt,&id,cert);
536    return ret;
537}
538
539/**
540 * Load an ID cert from a cert chunk and a privkey chunk,
541 * this complete id cert + privkey could create attribute credential.
542 */
543int abac_context_load_id_privkey_chunk(abac_context_t *ctxt,abac_chunk_t ccert,
544abac_chunk_t privkey)
545{
546    assert(ctxt != NULL);
547    chunk_t cert_chunk = { ccert.ptr, ccert.len };
548/*A HACK/SWIG, this is to work around the swig's stub that seems to
549  mess up the transformation from abac_chunk_t to chunk_t and calling of
550  load_id_chunks to here */
551    chunk_t privkey_chunk = { strndup(privkey.ptr,privkey.len), privkey.len };
552
553    abac_id_t *id=NULL;
554
555    // load the cert
556    certificate_t *cert = cert_get_id_cert_from_chunk(cert_chunk);
557    if (cert == NULL) return ABAC_CERT_INVALID;
558
559    int rc=_load_id(ctxt,&id,cert);
560    if(rc == ABAC_CERT_SUCCESS) {
561        rc=abac_id_load_privkey_chunk(id, privkey_chunk);
562    }
563
564    return rc;
565}
566
567/**
568 * Load an ID cert and privkey from chunks.
569 */
570int 
571abac_context_load_id_enc_privkey_chunk(abac_context_t *ctxt, abac_chunk_t ccert,
572abac_chunk_t privkey, char* pfile) {
573
574    assert(ctxt != NULL);
575    chunk_t cert_chunk = { ccert.ptr, ccert.len };
576/*A HACK/SWIG, this is to work around the swig's stub that seems to
577  mess up the transformation from abac_chunk_t to chunk_t and calling of
578  load_id_chunks to here */
579    chunk_t privkey_chunk = { strndup(privkey.ptr,privkey.len), privkey.len };
580
581    abac_id_t *id=NULL;
582    certificate_t *cert = cert_get_id_cert_from_chunk(cert_chunk);
583    if (cert == NULL) return ABAC_CERT_INVALID;
584
585    int rc=_load_id(ctxt,&id,cert);
586    if(rc == ABAC_CERT_SUCCESS) {
587        rc=abac_id_load_enc_privkey_chunk(id, privkey_chunk, pfile);
588    }
589    return rc;
590}
591
592
593static int matchex(const char *subject, const char *pattern, int *so, int *eo)
594{
595    int rc; // Returned code
596    regmatch_t pmatch;
597
598    regex_t re; // Compiled regexp pattern
599
600    if (regcomp(&re, pattern, 0) != 0) return 0;
601
602    rc = regexec(&re, subject, 1 , &pmatch, 0);
603    regfree(&re); 
604
605    if (rc == REG_NOMATCH ) return 0; 
606
607    *so=pmatch.rm_so;
608    *eo=pmatch.rm_eo;
609
610    return 1;
611}
612
613
614static chunk_t _extract_chunk(char *data, char* startline, char* endline)
615{
616    int found=0;
617    int startos=0;
618    int endos=0;
619    regex_t re;
620    regmatch_t pm;
621    int rc;
622
623    int st;
624    int et;
625
626    rc=matchex(data, startline, &st, &et);
627    if(rc==0) return chunk_empty;
628    startos=st;
629
630    rc=matchex(data, endline, &st, &et);
631    if(rc==0) return chunk_empty;
632    endos=et;
633   
634    int len=endos - startos; 
635
636    DEBUG_PRINTF("making a chunk of size (%d) from %d and %d\n",len, startos,endos);
637    char *ptr=strndup(data+startos,len);
638
639    chunk_t ret = { ptr, len };
640    return ret;
641}
642
643/**
644 * Load an ID cert from a file, it may contain key part but not necessary.
645 */
646int abac_context_load_id_idkey_file(abac_context_t *ctxt, char *filename)
647{
648    struct stat sb;
649    int fd;
650    int rc;
651    assert(ctxt != NULL); assert(filename != NULL);
652    abac_id_t *id=NULL;
653
654    DEBUG_PRINTF("abac_context_load_id_idkey_file(%s)\n", filename);
655
656    fd = open(filename, O_RDONLY);
657    if (fd == -1) { return 1; }
658    if(stat(filename, &sb) == -1) {
659        close(fd);
660        return 1;
661    }
662    char* data = (char *)mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
663    if(data == MAP_FAILED) {
664        close(fd);
665        return 1;
666    }
667    close(fd);
668
669    chunk_t key_pem_chunk=_extract_chunk(data,
670               "-----BEGIN RSA PRIVATE KEY-----","-----END RSA PRIVATE KEY-----");
671    chunk_t cert_pem_chunk=_extract_chunk(data,
672                   "-----BEGIN CERTIFICATE-----","-----END CERTIFICATE-----");
673
674    /* key=0, cert=0 */
675    if(key_pem_chunk.len==0 && cert_pem_chunk.len==0) {
676        DEBUG_PRINTF("abac_context_load_id_idkey_file: no key or id in idkey_file\n");
677        goto error;
678    }
679
680    /* key=0, cert=1 */
681    if(key_pem_chunk.len==0) {
682        DEBUG_PRINTF("abac_context_load_id_idkey_file: no key in idkey_file\n");
683        munmap(data, sb.st_size);
684        chunk_free(&key_pem_chunk);
685        return abac_context_load_id_id_key_files(ctxt,filename,NULL);
686    }
687
688    /* key=1, cert=1 */
689    if(cert_pem_chunk.len!=0) {
690        DEBUG_PRINTF("loading cert pem chunk len(%d)\n", cert_pem_chunk.len);
691        rc=_abac_context_load_id_pem_chunk(ctxt,&id,cert_pem_chunk);
692        if(rc != 0) {
693            DEBUG_PRINTF("abac_context_load_id_idkey_file: fail to load the id\n");
694            goto error;
695        }
696    /* key=1, cert=0 */
697        } else {
698            DEBUG_PRINTF("abac_context_load_id_idkey_file: there is no id info in there\n");
699            goto error;
700    }
701   
702    /* handle the key_pem_chunk */
703    DEBUG_PRINTF("loading key pem chunk len(%d)\n", key_pem_chunk.len);
704    rc=abac_id_load_privkey_chunk(id, key_pem_chunk);
705    if(rc==0) {
706        printf("abac_context_load_id_idkey_file:failed to load priv key!!!\n");
707        goto error;
708    }
709
710    munmap(data, sb.st_size);
711    return 0;
712
713error:
714    munmap(data, sb.st_size);
715    return 1;
716}
717
718/**
719 * Load an ID cert from a file, it may contain encrypted key part but not necessary.
720 */
721int abac_context_load_id_enc_idkey_file(abac_context_t *ctxt, char *filename, char *pfile)
722{
723    struct stat sb;
724    int fd;
725    int rc;
726    abac_id_t *id=NULL;
727
728    assert(ctxt != NULL); assert(filename != NULL);
729    abac_id_credential_t *id_cert=NULL;
730
731    fd = open(filename, O_RDONLY);
732    if (fd == -1) { return 1; }
733    if(stat(filename, &sb) == -1) {
734        close(fd);
735        return 1;
736    }
737    char* data = (char *)mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
738    if(data == MAP_FAILED) {
739   
740        return 1;
741    }
742    close(fd);
743
744    chunk_t key_pem_chunk=_extract_chunk(data,
745               "-----BEGIN RSA PRIVATE KEY-----","-----END RSA PRIVATE KEY-----");
746    chunk_t cert_pem_chunk=_extract_chunk(data,
747                   "-----BEGIN CERTIFICATE-----","-----END CERTIFICATE-----");
748
749    /* key=0, cert=0 */
750    if(key_pem_chunk.len==0 && cert_pem_chunk.len==0) {
751        DEBUG_PRINTF("abac_context_load_id_idkey_file: no key or id in idkey_file\n");
752        goto error;
753    }
754
755    /* key=0, cert=1 */
756    if(key_pem_chunk.len==0) {
757        DEBUG_PRINTF("abac_context_load_id_idkey_file: no key in idkey_file\n");
758        munmap(data, sb.st_size);
759        chunk_free(&key_pem_chunk);
760        return abac_context_load_id_id_key_files(ctxt,filename,NULL);
761    }
762
763    /* key=1, cert=1 */
764    if(cert_pem_chunk.len!=0) {
765        DEBUG_PRINTF("loading cert pem chunk len(%d)\n", cert_pem_chunk.len);
766        rc=_abac_context_load_id_pem_chunk(ctxt,&id,cert_pem_chunk);
767        if(rc != 0) {
768            DEBUG_PRINTF("abac_context_load_id_idkey_file: fail to load the id\n");
769            goto error;
770        }
771    /* key=1, cert=0 */
772        } else {
773            DEBUG_PRINTF("abac_context_load_id_idkey_file: there is no id info in there\n");
774            goto error;
775    }
776   
777    /* handle the key_pem_chunk */
778    DEBUG_PRINTF("loading key pem chunk len(%d)\n", key_pem_chunk.len);
779
780    rc=abac_id_load_enc_privkey_chunk(id, key_pem_chunk, pfile);
781    if(rc==0) {
782        printf("abac_context_load_id_idkey_file:failed to load priv key!!!\n");
783        goto error;
784    }
785
786    munmap(data, sb.st_size);
787    return 0;
788
789error:
790    munmap(data, sb.st_size);
791    return 1;
792}
793
794/* not duplicated */
795abac_id_credential_t *abac_context_id_credential_lookup(abac_context_t *ctxt,char *pname)
796{
797    int cnt=0;
798    assert(pname);
799    if(ctxt->context_id_hashkeyid_list) {
800        char *keyid;
801        abac_id_credential_t *id_cred;
802        abac_list_foreach(ctxt->context_id_hashkeyid_list, keyid,
803            if(strcmp(keyid,pname)==0) {
804                id_cred=abac_id_credential_lookup(keyid);
805                return id_cred;
806            }
807        );
808    }
809    return NULL;
810}
811
812void abac_context_id_credential_free(abac_context_t *ctxt, abac_id_credential_t *ptr)
813{
814    if (ptr == NULL)
815        return;
816
817    char *keyid=abac_id_credential_hashkey(ptr);
818
819    /* make sure it belongs to this context */
820    char *cur=NULL;
821    abac_list_foreach(ctxt->context_id_hashkeyid_list, cur,
822        if(strcmp(cur,keyid)==0) 
823            break;
824    );
825    assert(cur!=NULL);
826    abac_list_remove(ctxt->context_id_hashkeyid_list, cur);
827    free(cur);
828
829    abac_id_credential_free(ptr);
830}
831
832/****************************************************************************/
833static char *_get_keyid_from_cert(certificate_t *cert)
834{
835    assert(cert);
836    ac_t *ac=(ac_t *)cert;
837    ietf_attributes_t *attr_cert=ac->get_groups(ac);
838    if(attr_cert == NULL) {
839        char *tmp=NULL;
840        asprintf(&tmp,"_get_keyid_from_cert: fail to get keyid from certificate_t");
841        panic(tmp);
842    }
843    char *encoded_attr_string=attr_cert->get_string(attr_cert);
844    attr_cert->destroy(attr_cert);
845    return encoded_attr_string;
846}
847
848static int _verify_valid_credential_issuer(abac_context_t *ctxt, char* keyid,
849certificate_t *cert, abac_id_t **issuer_id)
850{
851    abac_id_credential_t *id_cred;
852    int ret, i;
853
854    // get the issuer based on keyid
855    id_cred=abac_context_id_credential_lookup(ctxt,keyid);
856    if(id_cred == NULL) {
857        ret = ABAC_CERT_MISSING_ISSUER;
858        DEBUG_PRINTF("_verify_valid_credential_issuer:can not find %s in id_creds\n", keyid);
859        goto error;
860    }
861
862    *issuer_id=abac_id_credential_id(id_cred);
863    if (*issuer_id == NULL) {
864        ret = ABAC_CERT_MISSING_ISSUER;
865        DEBUG_PRINTF("_verify_valid_credential_issuer:can not find %s in id_creds\n", keyid);
866        goto error;
867    }
868
869    // make sure the issuer's signed it
870    ret = verify_signature(abac_id_cert(*issuer_id), cert);
871    if (!ret) {
872        abac_yy_set_error_code(ABAC_RT_CERT_BAD_SIG);
873        ret=ABAC_CERT_BAD_SIG;
874        DEBUG_PRINTF("_verify_valid_credential_issuer:signing policy failed for %s \n", keyid);
875        goto error;
876    }
877
878    return ABAC_CERT_SUCCESS;
879
880error:
881    return ret;
882}
883
884/* at this point we know we have a good attribute cert baked it in */
885static int _insert_valid_cred(abac_context_t *ctxt, abac_id_t *issuer_id,
886abac_aspect_t *head_aspect, abac_aspect_t *tail_aspect, certificate_t *cert,
887abac_credential_t **cred_ret, char *encoded_attr_string, int using_this)
888{
889    abac_list_t *clauses=NULL;
890    abac_id_credential_t *id_cred;
891    int ret, i;
892
893    // generate prolog clauses from aspect structures
894    clauses = generate_pl_clauses(ctxt,head_aspect, tail_aspect, encoded_attr_string,using_this);
895
896    // make a new credential if only is first
897    if(*cred_ret == NULL) {
898        abac_attribute_t *attr=abac_attribute_new(issuer_id, cert, cert->get_ref(cert));
899        abac_attribute_set_head(attr, head_aspect);
900        abac_attribute_add_tail(attr, tail_aspect);
901        if(using_this) abac_attribute_set_using_this(attr,using_this);
902        *cred_ret=abac_credential_new(abac_attribute_copy(attr),encoded_attr_string); /* need a deep copy ? */
903        abac_add_cred(*cred_ret);
904    }
905
906    // add clauses
907    char *cur=NULL;
908    abac_list_foreach(clauses, cur,
909        abac_list_add(ctxt->context_pl_clauses, abac_xstrdup(cur));
910    );
911
912    /* add locally */
913    abac_list_add(ctxt->context_attr_hashkeyid_list, abac_xstrdup(encoded_attr_string));
914    /* insert into db */
915    int add_ret=abac_pl_add_credential(clauses);
916
917    DEBUG_PRINTF("-->adding into context attr_creds, [%s]hashkey(%s)..cnt(%d)\n",
918       ctxt->namespace,
919       encoded_attr_string, abac_list_size(ctxt->context_attr_hashkeyid_list));
920
921    return ABAC_CERT_SUCCESS;
922
923error:
924    if(head_aspect) abac_aspect_free(head_aspect);
925    if(tail_aspect) abac_aspect_free(tail_aspect);
926    return ABAC_CERT_INVALID;
927}
928
929/**
930 * Load an attribute cert.
931 * Returns true only if the certificate is valid and is issued by the proper
932 * authority.
933 * attribute string is parsed via yyparse call
934 */
935static int _load_attribute_cert(abac_context_t *ctxt, certificate_t *cert,
936abac_credential_t **cred_ret)
937{
938    int ret, i;
939    abac_aspect_t *head_aspect = NULL;
940    abac_aspect_t *tail_aspect = NULL;
941    int using_this=0;
942    assert(cert);
943
944    char *encoded_attr_string=_get_keyid_from_cert(cert);
945    if(encoded_attr_string==NULL ) {
946       fprintf(stderr,"this is bad in loading the cert, empty encoded_attr_string\n");
947       goto error;
948    }
949    /* see if it already exists in context */
950    abac_credential_t *cred=abac_context_credential_lookup(ctxt,encoded_attr_string);
951    if(cred != NULL) {
952        if(debug) fprintf(stderr,"trying to insert identical attribute into a context\n");
953        ret = ABAC_CERT_INVALID;
954        goto error;
955    }
956
957    char *attr_string = abac_decode_string(encoded_attr_string);
958    if (attr_string == NULL) {
959        ret = ABAC_CERT_INVALID;
960        goto error;
961    }
962
963    /* see if it exist ... */
964    *cred_ret=abac_credential_lookup(encoded_attr_string);
965    if(*cred_ret != NULL ) {
966       //already exist in session
967       abac_attribute_t *attr=abac_credential_attribute(*cred_ret);
968       head_aspect=abac_attribute_head(attr);
969       tail_aspect=abac_attribute_tail(attr);
970       using_this=abac_attribute_get_this(attr);
971       } else {
972           /* call into yacc parser */
973           int rc=abac_yy_parse(ctxt, attr_string, &head_aspect, &tail_aspect, &using_this);
974           if(rc) {
975               ret = ABAC_CERT_INVALID;
976               goto error;
977           }
978    }
979
980    char *keyid=abac_aspect_principal_principalname(head_aspect);
981    abac_id_t *issuer_id=NULL;
982    ret= _verify_valid_credential_issuer(ctxt,keyid,cert,&issuer_id);
983    if(ret != ABAC_CERT_SUCCESS) {
984        char *tmp=NULL;
985        asprintf(&tmp,"_load_attribute_cert: fail to verify credential's issuer (%s)",attr_string);
986        panic(tmp);
987    }
988
989    ret=_insert_valid_cred(ctxt, issuer_id, head_aspect, tail_aspect,
990                                    cert,cred_ret,encoded_attr_string, using_this);
991
992    if(ret != ABAC_CERT_SUCCESS) {
993        char *tmp=NULL;
994        asprintf(&tmp,"_load_attribute_cert: fail to verify credential (%s)",attr_string);
995        panic(tmp);
996    }
997
998    return ABAC_CERT_SUCCESS;
999
1000error:
1001    return ret;
1002}
1003
1004void abac_print_clauses(abac_list_t *clauses, FILE *fp)
1005{
1006    if (clauses != NULL) {
1007        char *cur;
1008        printf("total-- %d clauses\n", abac_list_size(clauses));
1009        abac_list_foreach(clauses, cur,
1010            if(cur) {
1011                if(fp)
1012                    fprintf (fp,"a clause, %ld(%s)\n", (long)cur,cur);
1013                    else printf ("a clause, %ld(%s)\n", (long)cur,cur);
1014            }
1015        );
1016    }
1017}
1018
1019/**
1020 * Load an attribute cert from a abac_attribute_t.
1021 * attr should be all checked out before arriving here
1022 * but because of preloading of id, need to check the issuer id's
1023 * validity in this context
1024 */
1025int abac_context_load_attribute_attribute(abac_context_t *ctxt, abac_attribute_t *ptr)
1026{
1027    assert(ctxt != NULL);
1028    abac_credential_t *cred=NULL;
1029
1030    certificate_t *cert=abac_attribute_cert(ptr);
1031    return _load_attribute_cert(ctxt, cert, &cred);
1032}
1033
1034/* this is especially made for abac_context_dup to avoid trying to do
1035   yyparse again */
1036int abac_context_load_attribute_credential(abac_context_t *ctxt, abac_attribute_t *ptr,
1037abac_credential_t *cred)
1038{
1039    assert(ctxt != NULL);
1040    certificate_t *cert=abac_attribute_cert(ptr);
1041    return _load_attribute_cert(ctxt, cert, &cred);
1042}
1043
1044
1045/**
1046 * Load an attribute cert from a abac_attribute_t.
1047 * attr should be all checked out before arriving here
1048 * this is called from abac.hh and so must make a
1049 * separate copy of attr
1050 */
1051int abac_context_load_attribute(abac_context_t *ctxt, abac_attribute_t *ptr)
1052{
1053    assert(ctxt != NULL);
1054    abac_attribute_t *nptr=abac_attribute_copy(ptr);
1055    int ret= abac_context_load_attribute_attribute(ctxt, nptr);
1056    return ret;
1057}
1058
1059/**
1060 * Load an attribute cert from a file.
1061 */
1062int abac_context_load_attribute_file(abac_context_t *ctxt, char *filename)
1063{
1064    abac_credential_t *cred=NULL;
1065    assert(ctxt != NULL); assert(filename != NULL);
1066
1067    // load the cert
1068    DEBUG_PRINTF("..loading attr file %s\n", filename);
1069    certificate_t *cert = cert_get_attr_cert_from_file(filename);
1070    if (cert == NULL) return ABAC_CERT_INVALID;
1071
1072    int ret=_load_attribute_cert(ctxt, cert, &cred);
1073    return ret;
1074}
1075
1076/**
1077 * Load an attribute cert from a chunk.
1078 */
1079int abac_context_load_attribute_chunk(abac_context_t *ctxt, abac_chunk_t ccert)
1080{
1081    abac_credential_t *cred=NULL;
1082    assert(ctxt != NULL);
1083    chunk_t chunk = { ccert.ptr, ccert.len };
1084
1085    // load the cert
1086    certificate_t *cert = cert_get_attr_cert_from_chunk(chunk);
1087    if (cert == NULL) return ABAC_CERT_INVALID;
1088
1089    int ret=_load_attribute_cert(ctxt, cert, &cred);
1090    return ret;
1091}
1092
1093
1094/**
1095 *  lookup for a credential/duplicated.
1096 */
1097abac_credential_t *abac_context_credential_lookup(abac_context_t *ctxt, char* cred_string)
1098{
1099    assert(cred_string); 
1100    abac_credential_t *attr_cred=NULL;
1101    int sz=abac_list_size(ctxt->context_attr_hashkeyid_list);
1102    if(ctxt->context_attr_hashkeyid_list) {
1103        char *keyid;
1104        abac_list_foreach(ctxt->context_attr_hashkeyid_list, keyid,
1105            if(strcmp(keyid,cred_string)==0) {
1106                attr_cred=abac_credential_lookup(keyid);
1107                break;
1108            }
1109        );
1110    }
1111    if (attr_cred == NULL) {
1112        DEBUG_PRINTF("DEBUG:credential_lookup, NOT FOUND..(%d)(%s)\n",sz,abac_decode_string(cred_string));
1113        return NULL;
1114    }
1115    abac_credential_t *rt=abac_credential_dup(attr_cred);
1116    DEBUG_PRINTF("DEBUG:crential_lookup, FOUND.. (%d)(%s) \n", sz,abac_decode_string(cred_string));
1117    return rt;
1118}
1119
1120void abac_context_credential_free(abac_context_t *ctxt, abac_credential_t *ptr)
1121{
1122    if (ptr == NULL)
1123        return;
1124
1125    char *keyid=abac_credential_hashkey(ptr);
1126
1127    /* make sure it belongs to this context */
1128    char *cur=NULL;
1129    abac_list_foreach(ctxt->context_attr_hashkeyid_list, cur,
1130        if(strcmp(cur,keyid)==0)
1131            break;
1132    );
1133    assert(cur!=NULL);
1134    abac_list_remove(ctxt->context_attr_hashkeyid_list, cur);
1135    free(cur);
1136
1137    abac_credential_free(ptr);
1138}
1139
1140/**************************************************************/
1141char *_make_key_filename(char *cert_file)
1142{
1143    char *p=strstr(cert_file,"_ID.");
1144    char *head=strndup(cert_file,p-cert_file);
1145    char *tail=p+4;
1146    char *keyfile=NULL;
1147    asprintf(&keyfile,"%s_private.%s",head,tail);
1148    free(head);
1149    return keyfile;
1150}
1151
1152/**
1153 * Load a directory full of principal certs.
1154 */
1155void abac_context_load_principals(abac_context_t *ctxt, char *path) {
1156    char *glob_pat, *key_pat;
1157    glob_t glob_buf;
1158    int i, ret;
1159
1160    assert(ctxt != NULL); assert(path != NULL);
1161
1162    int dirlen = strlen(path);
1163
1164    /* make sure pick the larger one */
1165    glob_pat = abac_xmalloc(dirlen + sizeof(IDKEY_PAT));
1166    memcpy(glob_pat, path, dirlen);
1167
1168    // load ID certs
1169    memcpy(glob_pat + dirlen, ID_PAT, sizeof(ID_PAT));
1170    glob(glob_pat, GLOB_BRACE, NULL, &glob_buf); // TODO check for error
1171    for (i = 0; i < glob_buf.gl_pathc; ++i) {
1172        /* blah_ID.pem */
1173        char *cert_file = glob_buf.gl_pathv[i];
1174        /* blah_private.pem */
1175        char *key_file=_make_key_filename(cert_file);
1176        DEBUG_PRINTF("--> ID cert... %s\n", cert_file);
1177        DEBUG_PRINTF("--> KEY cert... %s\n", key_file);
1178        ret = abac_context_load_id_id_key_files(ctxt, cert_file, key_file);
1179        if (ret != ABAC_CERT_SUCCESS)
1180            warnx("Couldn't load ID cert %s", cert_file);
1181    }
1182    globfree(&glob_buf);
1183
1184    // next load IDKEY certs
1185    memcpy(glob_pat + dirlen, IDKEY_PAT, sizeof(IDKEY_PAT));
1186    glob(glob_pat, GLOB_BRACE, NULL, &glob_buf); // TODO check for error
1187    for (i = 0; i < glob_buf.gl_pathc; ++i) {
1188        /* blah_IDKEY.pem */
1189        char *certkey_file = glob_buf.gl_pathv[i];
1190        DEBUG_PRINTF("--> IDKEY certkey... %s\n", certkey_file);
1191        ret = abac_context_load_id_idkey_file(ctxt, certkey_file);
1192        if (ret != ABAC_CERT_SUCCESS)
1193            warnx("Couldn't load ID/KEY IDKEY cert %s", certkey_file);
1194    }
1195    globfree(&glob_buf);
1196
1197    free(glob_pat);
1198}
1199
1200/**
1201 * Load a directory full of certs.
1202 */
1203void abac_context_load_directory(abac_context_t *ctxt, char *path) {
1204    char *glob_pat, *key_pat;
1205    glob_t glob_buf;
1206    int i, ret;
1207
1208    abac_context_load_principals(ctxt,path);
1209    int dirlen = strlen(path);
1210
1211    /* make sure pick the larger one */
1212    glob_pat = abac_xmalloc(dirlen + sizeof(IDKEY_PAT));
1213    memcpy(glob_pat, path, dirlen);
1214
1215    memcpy(glob_pat + dirlen, ATTR_PAT, sizeof(ATTR_PAT));
1216    glob(glob_pat, 0, NULL, &glob_buf); // TODO check for error
1217    DEBUG_PRINTF("glob_pat is (%s)\n", glob_pat);
1218    for (i = 0; i < glob_buf.gl_pathc; ++i) {
1219        char *cert_file = glob_buf.gl_pathv[i];
1220
1221        DEBUG_PRINTF("--> attr file... (%s)\n", cert_file);
1222        ret = abac_context_load_attribute_file(ctxt, cert_file);
1223        if (ret != ABAC_CERT_SUCCESS)
1224            warnx("Couldn't load attribute cert --(%d)%s", ret,cert_file);
1225        DEBUG_PRINTF("Loaded.. (%s)\n", cert_file);
1226    }
1227    globfree(&glob_buf);
1228
1229    free(glob_pat);
1230}
1231
1232/**
1233 * Run a query on the data in an abac context. Returns a NULL-terminated array
1234 * of abac_credential_t. Success/failure in *success.
1235 * queryfor(either role or oset), with(either keyid or object type)
1236 */
1237abac_credential_t **abac_context_query(abac_context_t *ctxt, char *queryfor, char *with, int *success) {
1238    DEBUG_PRINTF("abac_context_query about(%s) with(%s)\n", queryfor, with);
1239    abac_credential_t **credentials = NULL, *cur;
1240    assert(ctxt != NULL); assert(queryfor != NULL);
1241    assert(with != NULL); assert(success != NULL);
1242
1243    abac_stack_t *result = abac_pl_query(ctxt->pl, queryfor, with);
1244
1245    int size = abac_stack_size(result);
1246    if (size > 0) {
1247       if(!abac_pl_returning_partial(ctxt->pl))
1248            *success = 1;
1249            else *success = 0;
1250    } else {
1251        *success = 0;
1252    }
1253
1254    // make the array (leave space to NULL terminate it)
1255    //      n.b., even if the list is empty, we still return an array that
1256    //            only contains the NULL terminator
1257    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
1258    int i = 0;
1259    if(size) {
1260        while(i<size) { 
1261            cur=(abac_credential_t *) abac_stack_pop(result);
1262            credentials[i++] = cur;
1263        } 
1264    }
1265    credentials[i] = NULL;
1266
1267    if(result)
1268        abac_stack_free(result);
1269
1270    return credentials;
1271}
1272
1273/**
1274 * Run a repeated query on the data in an abac context to get the next
1275 * solution proof. Returns a NULL-terminated array
1276 * of abac_credential_t. Success/failure in *success.
1277 */
1278abac_credential_t **abac_context_query_again(abac_context_t *ctxt, int *success)
1279{
1280    DEBUG_PRINTF("abac_context_query_again\n");
1281    abac_credential_t **credentials = NULL, *cur;
1282    assert(ctxt != NULL);
1283    assert(success != NULL);
1284
1285    abac_stack_t *result = abac_pl_query_again(ctxt->pl);
1286
1287    int size = abac_stack_size(result);
1288    if (size > 0) {
1289        *success = 1;
1290        } else {
1291            *success = 0;
1292    }
1293
1294    // make the array (leave space to NULL terminate it)
1295    //      n.b., even if the list is empty, we still return an array that
1296    //            only contains the NULL terminator
1297    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
1298    int i = 0;
1299    if(size) {
1300        while(i<size) { 
1301            cur=(abac_credential_t *) abac_stack_pop(result);
1302            credentials[i++] = cur;
1303        } 
1304    }
1305    credentials[i] = NULL;
1306
1307    if(result)
1308        abac_stack_free(result);
1309
1310    return credentials;
1311}
1312
1313
1314abac_credential_t **abac_context_query_with_structure(abac_context_t *ctxt,
1315abac_aspect_t *queryfor, abac_aspect_t *with, int *success)
1316{
1317    DEBUG_PRINTF("abac_context_query_with_structure\n");
1318    abac_credential_t **credentials = NULL, *cur;
1319    assert(ctxt != NULL); assert(queryfor != NULL);
1320    assert(with != NULL); assert(success != NULL);
1321
1322    abac_stack_t *result = abac_pl_query_with_structure(ctxt->pl, queryfor, with);
1323
1324    int size = abac_stack_size(result);
1325    if (size > 0) {
1326        *success = 1;
1327    } else {
1328    // XXX NOT SURE YET..
1329    // return partial proof
1330        *success = 0;
1331    }
1332
1333    // make the array (leave space to NULL terminate it)
1334    //      n.b., even if the list is empty, we still return an array that
1335    //            only contains the NULL terminator
1336    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
1337    int i = 0;
1338    if(size) {
1339        while(i<size) { 
1340            cur=(abac_credential_t *) abac_stack_pop(result);
1341            credentials[i++] = cur;
1342        } 
1343    }
1344    credentials[i] = NULL;
1345
1346    if(result)
1347        abac_stack_free(result);
1348
1349    return credentials;
1350}
1351
1352/**
1353 * A NULL-terminated array of all the credentials in the context.
1354 */
1355abac_credential_t **abac_context_credentials(abac_context_t *ctxt) {
1356    abac_credential_t **credentials = NULL, *cur;
1357    assert(ctxt != NULL);
1358
1359    abac_stack_t *result = abac_context_dump_creds(ctxt);
1360    int size = abac_stack_size(result);
1361
1362    // make the array (leave space to NULL terminate it)
1363    //      n.b., even if the list is empty, we still return an array that
1364    //            only contains the NULL terminator
1365    credentials = abac_xmalloc(sizeof(abac_credential_t *) * (size + 1));
1366    int i = 0;
1367    if(size) {
1368        while(i<size) { 
1369            cur=(abac_credential_t *) abac_stack_pop(result);
1370            /* if not in there yet, add into it */
1371            credentials[i++] = cur;
1372        } 
1373    }
1374    credentials[i] = NULL;
1375
1376    if(result)
1377        abac_stack_free(result);
1378    return credentials;
1379}
1380
1381/**
1382 * Frees a NULL-terminated list of credentials. context independent
1383 */
1384void abac_free_credentials(abac_credential_t **credentials) {
1385    int i;
1386
1387    if (credentials == NULL)
1388        return;
1389
1390    for (i = 0; credentials[i] != NULL; ++i)
1391        abac_credential_free(credentials[i]);
1392    free(credentials);
1393}
1394
1395/**
1396 * A NULL-terminated array of all the principals in the context.
1397 */
1398abac_id_credential_t **abac_context_principals(abac_context_t *ctxt)
1399{
1400    abac_id_credential_t **principals = NULL, *cur;
1401    assert(ctxt != NULL);
1402
1403    abac_stack_t *result = abac_context_dump_principals(ctxt);
1404
1405    int size = abac_stack_size(result);
1406
1407    // make the array (leave space to NULL terminate it)
1408    //      n.b., even if the list is empty, we still return an array that
1409    //            only contains the NULL terminator
1410    principals = abac_xmalloc(sizeof(abac_id_credential_t *) * (size + 1));
1411    int i = 0;
1412    if(size) {
1413        while(i<size) {
1414            cur=(abac_id_credential_t *) abac_stack_pop(result);
1415            /* if not in there yet, add into it */
1416            principals[i++] = cur;
1417        }
1418    }
1419    principals[i] = NULL;
1420
1421    if(result)
1422        abac_stack_free(result);
1423    return principals;
1424}
1425
1426/**
1427 * Frees a NULL-terminated list of principals, context independent
1428 */
1429void abac_free_principals(abac_id_credential_t **principals)
1430{
1431    int i;
1432
1433    if (principals == NULL)
1434        return;
1435
1436    for (i = 0; principals[i] != NULL; ++i)
1437        abac_id_credential_free(principals[i]);
1438    free(principals);
1439}
1440
1441
1442
1443/**
1444 * Free an abac context.
1445 */
1446void abac_context_free(abac_context_t *ctxt) 
1447{
1448    assert(ctxt != NULL);
1449    DEBUG_PRINTF("abac_conext_free..\n");
1450
1451    abac_verifier_session_remove_context(ctxt);
1452
1453    if(ctxt->namespace) free(ctxt->namespace);
1454    abac_pl_free(ctxt->pl);
1455
1456    DEBUG_PRINTF("looking to free context_attr_hashkeyid_list..\n");
1457    if(ctxt->context_attr_hashkeyid_list) { 
1458        if( abac_list_size(ctxt->context_attr_hashkeyid_list)>0) {
1459           /* free all the keys */
1460           char *cur;
1461           abac_list_foreach(ctxt->context_attr_hashkeyid_list, cur,
1462              if(cur) { 
1463                 DEBUG_PRINTF("hum.. attr hashkey being freed.. %s\n", cur);
1464                 abac_credential_t *attr=abac_credential_lookup(cur);
1465/* XXX abac_check_cred(cur); */
1466                 assert(attr!=NULL);
1467                 abac_credential_free(attr);
1468                 free(cur);
1469              }
1470           );
1471        }
1472        abac_list_free(ctxt->context_attr_hashkeyid_list);
1473    }
1474
1475    DEBUG_PRINTF("looking to free context_id_hashkeyid_list..\n");
1476    if(ctxt->context_id_hashkeyid_list) {
1477 
1478        if(abac_list_size(ctxt->context_id_hashkeyid_list)) {
1479            char *cur;
1480            abac_list_foreach(ctxt->context_id_hashkeyid_list, cur,
1481                if(cur) {
1482                    DEBUG_PRINTF("hum.. id hashkey being freed.. %s\n", cur);
1483/* abac_id_credential_t *id=abac_check_id_cred(cur); */
1484                    abac_id_credential_t *id=abac_id_credential_lookup(cur);
1485                    assert(id!=NULL);
1486                    abac_id_credential_free(id);
1487                    free(cur);
1488                }
1489            );
1490        }
1491        abac_list_free(ctxt->context_id_hashkeyid_list);
1492    }
1493
1494    DEBUG_PRINTF("looking to free context_pl_clauses..\n");
1495    if(ctxt->context_pl_clauses) {
1496        if(abac_list_size(ctxt->context_pl_clauses)) {
1497            abac_pl_remove_credential(ctxt->context_pl_clauses);
1498            char *cur;
1499            abac_list_foreach(ctxt->context_pl_clauses, cur,
1500                if(cur) free(cur);
1501            );
1502        }
1503        abac_list_free(ctxt->context_pl_clauses);
1504    }
1505    free(ctxt);
1506}
1507
1508void abac_context_set_no_partial_proof(abac_context_t *ctxt)
1509{ abac_pl_set_no_partial(ctxt->pl); }
1510
1511void abac_context_set_want_partial_proof(abac_context_t *ctxt)
1512{ abac_pl_set_want_partial(ctxt->pl); }
1513
1514/****************************************************************************/
1515void abac_context_dump_clauses(abac_context_t *ctxt)
1516{
1517    printf("===YAP clauses for [%s]===\n", ctxt->namespace);
1518    if(ctxt->context_pl_clauses) {
1519        char *cur;
1520        abac_list_foreach(ctxt->context_pl_clauses, cur,
1521            if(cur) {
1522               printf("%s\n", cur);
1523            }
1524        );
1525        } else {
1526            DEBUG_PRINTF("abac_contxt_dump_clauses: no yap clauses!!!!\n");
1527    }
1528    printf("==========================\n");
1529}
1530
1531
1532void abac_context_dump(abac_context_t *ctxt)
1533{
1534    abac_stack_t *result = abac_context_dump_creds(ctxt);
1535    int size = abac_stack_size(result);
1536    int i=0;
1537
1538    printf("CONTEXT: [%s]\n", ctxt->namespace); 
1539
1540    if(size) {
1541        abac_credential_t *cur;
1542        while(i<size) {
1543            cur=(abac_credential_t *) abac_stack_pop(result);
1544            abac_print_typed_cred_info(cur,NULL);
1545            abac_credential_free(cur);
1546            i++; 
1547        }
1548    }
1549    abac_stack_free(result);
1550
1551    result = abac_context_dump_principals(ctxt);
1552    size = abac_stack_size(result);
1553    i=0;
1554    if(size) {
1555        abac_id_credential_t *cur;
1556        while(i<size) {
1557            cur=(abac_id_credential_t *) abac_stack_pop(result);
1558            abac_print_prin_info(cur,NULL);
1559            abac_id_credential_free(cur);
1560            i++; 
1561        }
1562    }
1563    abac_stack_free(result);
1564    abac_context_dump_clauses(ctxt);
1565
1566}
Note: See TracBrowser for help on using the repository browser.