source: libabac/abac_pl_yap.c @ fc943ee

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

1) getting ready to make a releaseZ

  • Property mode set to 100644
File size: 15.8 KB
Line 
1
2/* copied from abac_graph.c
3   implementation of the low level using
4   yap prolog
5*/
6
7#include <err.h>
8#include <stdio.h>
9#include <assert.h>
10#include <stdlib.h>
11#include <string.h>
12#include <Yap/YapInterface.h>
13
14#include "abac_internal.h"
15
16#include "abac_pl_yap.h"
17#include "abac_util.h"
18
19#include "uthash.h"
20
21extern abac_list_t *abac_credential_clauses(abac_credential_t *);
22extern char *abac_id_clause(abac_id_credential_t *);
23extern abac_aspect_t *abac_yy_get_rule_tail_aspect();
24extern abac_aspect_t *abac_yy_get_rule_head_aspect();
25
26static int debug=0;
27
28/* track constraint's external clause's -unique name id */
29
30static int constraint_label_count=0;
31static char *constraint_label="isABAC_constraint";
32
33// pl -- place holder for now
34struct _abac_pl_t {
35   /* a_term <- prin */
36    char *aspect_term;
37    char *prin_term;
38    int query_made; /* 1+ yes, 0 no, rc is valid only if a query is made */
39    int query_rc; /* rc of query call */
40    int next_rc; /* rc of next-last query */
41      /* proof count = abac_list_size(proof_list) */
42    abac_list_t *proof_list; /* list of list of cred_list */ 
43    long safe_t; /* holding the YAP slot for the goal */
44};
45
46/***********************************************************/
47static int _get_next_constraint_label_idx()
48{
49    constraint_label_count++;
50    return constraint_label_count;
51}
52
53static int _get_constraint_label_idx()
54{
55    return constraint_label_count;
56}
57
58/***********************************************************/
59
60static int _insert_clause(char *str)
61{
62    YAP_Term *eterm;
63    YAP_Term goalArgs=YAP_ReadBuffer(str, eterm);
64    char *tmp=YAP_CompileClause(goalArgs);
65    if (tmp!=NULL) { /* something is wrong */
66        printf("error: result of compile clause (%s)\n", tmp);
67        printf("error: str used (%s)\n", str);
68        return 1;
69    }
70    return 0;
71}
72
73static int _insert_cred_clause(char *cstr)
74{
75    int ret=ABAC_CERT_SUCCESS;
76    int rc=_insert_clause(cstr);
77    if (rc)
78        return ABAC_CERT_BAD_YAP;
79    return ABAC_CERT_SUCCESS;
80}
81
82void show_yap_db(const char *msg)
83{
84    char lstr[]="listing";
85    YAP_Term *eterm; /* error term */
86
87    printf("\n\n========= yap db (%s)\n",msg);
88    YAP_Term goal=YAP_ReadBuffer(lstr, eterm);
89    int rc =YAP_RunGoal( goal );
90    if (rc) {
91        printf("listing ok.. \n");
92    } else {
93        printf("listing's rc is bad.. \n");
94        YAP_Exit(1);
95    }
96    printf("========= \n\n");
97}
98
99/**
100 * Include some utility routines
101 */
102abac_pl_t *abac_pl_utility(void) {
103/*
104append([],L,L).
105append([X|L1],L2,[X|L3]):-append(L1,L2,L3).
106
107appendL([],[]).
108appendL([H|T], L) :-
109   appendL(T,L2), append(H,L2,L).
110*/
111    if(_insert_clause("append([],L,L)"))
112        YAP_Exit(1);
113    if(_insert_clause("append([X|L1],L2,[X|L3]):-append(L1,L2,L3)"))
114        YAP_Exit(1);
115    if(_insert_clause("appendL([],[])"))
116        YAP_Exit(1);
117    if(_insert_clause("appendL([H|T], L) :- appendL(T,L2), append(H,L2,L)"))
118        YAP_Exit(1);
119}
120
121/**
122 * Create a new yap structure.
123 */
124abac_pl_t *abac_pl_new(void) {
125
126    if (YAP_FastInit(NULL) == YAP_BOOT_ERROR)
127        YAP_Exit(1);
128
129    if (YAP_RunGoal(YAP_MkAtomTerm(YAP_LookupAtom("source")))) {
130        if(debug) fprintf(stderr, "calling source..\n");
131        } else {
132            if(debug) fprintf(stderr,"calling source failed..\n");
133            YAP_Exit(1);
134    }
135
136    abac_pl_utility();
137 
138    abac_pl_t *pl = abac_xmalloc(sizeof(abac_pl_t));
139    pl->aspect_term=NULL;
140    pl->prin_term=NULL;
141    pl->query_made=0;
142    pl->query_rc=0;
143    pl->next_rc=0;
144      /* proof count = abac_list_size(proof_list) */
145    pl->proof_list=NULL;
146    pl->safe_t=0;
147    return pl;
148}
149
150/* returns the number of solution so far */
151int abac_pl_proof_cnt(abac_pl_t *pl)
152{
153    if(pl->proof_list)
154        return abac_list_size(pl->proof_list);
155    return 0;
156}
157
158/* is this the conclusion of the query ? */
159/* 1 is yes, 0 N/A */
160int abac_pl_done_yet(abac_pl_t *pl)
161{
162    if(pl->query_made) {
163        if(pl->query_rc) {
164            if(!pl->next_rc) return 1;
165            return 0;
166        } else return 1; /* even init query failed */
167    }
168    return 0;
169}
170
171static void _free_p_list(abac_list_t *p)
172{
173    if( p != NULL ) {
174        if(abac_list_size(p) != 0) {
175            abac_credential_t *cur=NULL;
176            abac_list_foreach(p, cur,
177                abac_credential_free(cur);
178            );
179        }
180        abac_list_free(p);
181    }
182}
183
184static void _free_pf_list(abac_list_t *p)
185{
186   
187    if(p != NULL) {
188        if(abac_list_size(p) != 0) {
189            abac_list_t *cur=NULL;
190            abac_list_foreach(p, cur,
191                _free_p_list(cur);
192            );
193        }
194        abac_list_free(p);
195    }
196}
197
198void abac_pl_free(abac_pl_t *pl) {
199    if(pl->aspect_term) free(pl->aspect_term);
200    if(pl->prin_term) free(pl->prin_term);
201    _free_pf_list(pl->proof_list);
202    free(pl);
203}
204
205/* this is done whenever a new query starts in */
206static void _reset_pl(abac_pl_t *pl, char *aspect_term, char *prin_term)
207{
208    if(pl->safe_t) {
209        YAP_RecoverSlots(1);
210        YAP_Reset();
211    }
212    /* free the old ones */
213    if(pl->aspect_term) free(pl->aspect_term);
214    if(pl->prin_term) free(pl->prin_term);
215    pl->aspect_term = abac_xstrdup(aspect_term);
216    pl->prin_term = abac_xstrdup(prin_term);
217    pl->query_made=0;
218    pl->query_rc=0;
219    pl->next_rc=0;
220    _free_pf_list(pl->proof_list);
221    pl->proof_list=abac_list_new();
222    pl->safe_t=0;
223   
224}
225
226/**
227 * Add a credential to the db, not duplicating a copy and so
228 * don't try to free it after this call.
229 */
230int abac_pl_add_credential(abac_pl_t *pl, abac_credential_t *cred)
231{
232    int rc=0;
233    abac_list_t *clauses=abac_credential_clauses(cred);
234    if (clauses != NULL) {
235        char *cur;
236        abac_list_foreach(clauses, cur,
237            if(cur) {
238                if(debug) fprintf(stderr,"inserting =>%s\n",cur);
239                rc=_insert_cred_clause(cur);
240            }
241        );
242    }
243    return rc;
244}
245
246int abac_pl_add_type_credential(abac_pl_t *pl, abac_id_credential_t *id_cert)
247{
248    char *clause=abac_id_clause(id_cert);
249    if (clause != NULL) {
250        int rc=_insert_cred_clause(clause);
251        return rc;
252    }
253    return 0;
254}
255
256/*  string1(S):- S="abc";S="efg";S="ijk" */
257char *abac_pl_add_range_constraint_clause(char *var, char *tmplist)
258{
259    int i=_get_next_constraint_label_idx();
260    char *tmp=NULL;
261    asprintf(&tmp,"%s_%d(%s) :- %s", constraint_label, i, var, tmplist); 
262    int rc=_insert_cred_clause(tmp);
263    free(tmp);
264    if(rc) 
265        panic("abac_pl_add_range_constraint_clause, failed to insert");
266    asprintf(&tmp,"%s_%d(%s)", constraint_label, i, var);
267    return tmp;
268}
269
270/* cases,
271     ['str']
272     ['str1','str2']
273     ([] is not possible, and don't care)
274*/
275static void _credentials_from_string(abac_list_t *credentials,char *slist) {
276    char *cptr=slist; /* current ptr */
277    char *sptr; /* string ptr */
278    char *ptr;
279    int len=0;
280    char *string;
281    abac_credential_t *cred=NULL;
282    int cnt=0;
283
284    /* find first [' */ 
285    ptr=strstr(cptr,"['");
286    if(ptr == NULL) 
287         return;
288    cptr=ptr+2;
289    sptr=cptr;
290    while (1) {
291        /* find next ',' or '] */
292        ptr=strstr(cptr,"','");
293        if(ptr!=NULL) {
294             cptr=ptr+3;
295             len=(ptr-sptr);
296             string=strndup(sptr,len);
297             cred=abac_credential_lookup(string);
298             free(string); 
299             if(cred) {
300                 int i=abac_list_unique_add(credentials, cred);
301                 if(i) cnt++;
302                 } else {
303                 printf("BAD BAD\n");
304             }
305             sptr=cptr;
306             } else {
307             ptr=strstr(cptr,"']");
308             if(ptr!=NULL) {
309                 len=(ptr-sptr);
310                 string=strndup(sptr,len);
311                 cred=abac_credential_lookup(string);
312                 free(string);
313                 if(cred) {
314                     int i=abac_list_unique_add(credentials, cred);
315                     if(i) cnt++;
316                     } else {
317                     printf("BAD BAD BAD\n");
318                 }
319                 break;
320             }
321        }
322    }
323    if(debug)
324        fprintf(stderr,"DEBUG:total %d credentials\n", cnt);
325}
326
327/* MAX 1024x1024, double as it goes */
328static int try_again(int sz, char **tptr)
329{
330   int blk=1024*2; /* 2048 */
331   int max=1024*1024;
332   int size;
333   char *tmp = NULL;
334
335   if(sz==0) {
336       size = (sizeof(char) * (blk+1));
337       } else {
338           if (sz>=max) {
339               size=0;
340               *tptr=tmp;
341               return 0;
342           }
343           size=sz*2+1;
344           if(size > max) size=max;
345   }
346
347   tmp = (char *) YAP_AllocSpaceFromYap(size);
348   if(tmp==NULL) {
349       fprintf(stderr,"ERROR: malloc failed !!!\n");
350       YAP_Exit(1);
351   }
352   *tptr=tmp;
353   return size;
354}
355
356/* make a query and extract just first set of result */
357static abac_list_t *_make_yap_query(abac_pl_t *pl, char *prin, char *nm, char* estring)
358{
359    YAP_Term *eterm0;
360    YAP_Term *eterm1;
361    YAP_Term arg[3];
362
363    abac_list_t *cred_list = abac_list_new();
364
365    if(debug) { 
366       fprintf(stderr," the principal part(%s)\n", prin);
367       fprintf(stderr," the role/oset part(%s)\n", estring);
368       fprintf(stderr," nm part(%s)\n", nm);
369    } 
370    if(prin[0]=='\'' || prin[0]=='"') {
371        arg[0]=YAP_ReadBuffer(prin,eterm0);
372        } else {
373            arg[0]=YAP_MkAtomTerm(YAP_LookupAtom(prin)); 
374    }
375    if(debug) fprintf(stderr," the role/oset part(%s)\n", estring);
376    arg[1]=YAP_ReadBuffer(estring,eterm1);
377
378    /* var for credential list */
379    arg[2]=YAP_MkVarTerm();
380
381    YAP_Atom f = YAP_LookupAtom("isMember");
382    YAP_Functor func = YAP_MkFunctor(f, 3);
383    YAP_Term goal=YAP_MkApplTerm(func, 3, arg);
384
385    pl->safe_t = YAP_InitSlot(goal);
386    pl->query_rc =YAP_RunGoal(goal);
387    pl->query_made=1;
388    pl->next_rc=pl->query_rc;
389    if (pl->query_rc) {
390        printf("YAP query succeed\n");
391        char *tmp=NULL;
392        int tmp_sz=try_again(0, &tmp);
393        YAP_Term argterm=YAP_ArgOfTerm(3,YAP_GetFromSlot(pl->safe_t));
394        while(1) {
395/* not in 6.2.2
396            int rc=YAP_WriteBuffer(argterm, tmp, tmp_sz,YAP_WRITE_HANDLE_VARS);
397*/
398            YAP_WriteBuffer(argterm, tmp, tmp_sz,YAP_WRITE_HANDLE_VARS);
399/*
400if(debug) fprintf(stderr,"call YAP_WriteBuffer: rc(%d) tmp_sz(%d)\n", rc, tmp_sz);
401*/
402            if(strlen(tmp) > 5 && tmp[0]=='\[') {
403if(debug) fprintf(stderr,"what came back .. (%s)\n", tmp);
404                break;
405            }
406            tmp_sz=try_again(tmp_sz,&tmp);
407if(debug) fprintf(stderr,"try_again: tmp_sz(%d)\n", tmp_sz);
408            if(tmp_sz==0) {
409                fprintf(stderr," PANIC, run out of heap space..\n");
410                YAP_Exit(1);
411            }
412        }
413        /* this is returned as ['string1','string2'] */
414        if(debug) fprintf(stderr,"    query answer : %s(%d)\n", tmp, strlen(tmp));
415        _credentials_from_string(cred_list,tmp); 
416        if(abac_list_size(cred_list)==0) {
417            fprintf(stderr,"CAN NOT retrieve result properly from YAP!!!\n");
418            YAP_Exit(1);
419        }
420        abac_list_add(pl->proof_list, cred_list);
421        YAP_FreeSpaceFromYap(tmp);
422    } else {
423        printf("YAP query failed\n");
424        /* YAP_Exit(1); */
425    }
426    return cred_list;
427}
428
429/* make a query for next possible solution proof */
430static abac_list_t *_query_again(abac_pl_t *pl)
431{
432    abac_list_t *cred_list=abac_list_new();
433
434    pl->next_rc=YAP_RestartGoal();
435    pl->query_made++;
436    if(debug) fprintf(stderr,"query_again: another success\n");
437
438    char *tmp=NULL;
439    int tmp_sz=try_again(0, &tmp);
440    YAP_Term argterm=YAP_ArgOfTerm(3,YAP_GetFromSlot(pl->safe_t));
441    if(pl->next_rc) {
442        while(1) {
443            YAP_WriteBuffer(argterm, tmp, tmp_sz,YAP_WRITE_HANDLE_VARS);
444            if(strlen(tmp) > 5 && tmp[0]=='\[')
445                break;
446            tmp_sz=try_again(tmp_sz,&tmp);
447            if(tmp_sz==0) {
448                fprintf(stderr," PANIC, run out of heap space..\n");
449                YAP_Exit(1);
450            }
451        }
452        /* this is returned as ['string1','string2'] */
453        if(debug) fprintf(stderr,"    query answer : %s(%d)\n", tmp, strlen(tmp));
454        _credentials_from_string(cred_list,tmp); 
455        if(abac_list_size(cred_list)==0) {
456            fprintf(stderr,"CAN NOT retrieve result properly from YAP!!!\n");
457            YAP_Exit(1);
458        }
459        abac_list_add(pl->proof_list, cred_list);
460        YAP_FreeSpaceFromYap(tmp);
461    }
462    return cred_list;
463}
464
465abac_stack_t *_make_cred_stack(abac_list_t *p)
466{
467    abac_stack_t *ret=abac_stack_new();
468    if(abac_list_size(p) != 0) {
469        abac_credential_t *cur=NULL;
470        abac_list_foreach(p, cur,
471            abac_stack_push(ret, (void *)abac_credential_dup(cur));
472        );
473    }
474    return ret;
475}
476
477/* force a  backtrack to get next solution proof */
478abac_stack_t *abac_pl_query_again(abac_pl_t *pl)
479{
480    abac_list_t *rlist=_query_again(pl);
481    abac_stack_t *ret=_make_cred_stack(rlist);
482    return ret;
483}
484
485/* 2 types
486      acme.buys_rocket <- coyote (coyote=prin, acme.buys_rocket=role)
487        ==> isMember(coyote,role(acme,buys_rocket), L)
488      acme.buys_rocket <- acme.preferred_customer  -- NOT valid
489*/
490static abac_stack_t *_query_with_aspect(abac_pl_t *pl, abac_aspect_t* head, abac_aspect_t* tail)
491{
492    abac_stack_t *ret=NULL;
493    char *tmp=NULL;
494
495    if(0)
496        show_yap_db("DEBUG:calling within _query_with_aspect");
497
498    char *nm;
499    PROLOG(nm=abac_aspect_principal_name(head););
500
501    /* could be obj or principal */
502    char *prin_nm=NULL;
503    if(abac_aspect_is_object(tail)) {
504        prin_nm=abac_aspect_object_name(tail);
505        } else {
506            PROLOG(prin_nm=abac_aspect_principal_name(tail););
507    }
508
509    if(abac_aspect_aspect_name(tail)!=NULL) {
510        printf("fail, a.o <- b.o and a.r <- a.r query is not implemented yet !!!\n");
511        YAP_Exit(1);
512    }
513
514    if (prin_nm == NULL || nm == NULL) {
515        printf("fail, query's call got bad aspect names .. \n");
516        YAP_Exit(1);
517    }
518
519    if(debug) fprintf(stderr,"printing up the yap query ..\n");
520
521    char *pstring;
522    PROLOG(pstring=abac_aspect_aspect_param_string(head););
523
524    char *stub=abac_aspect_type_string(head);
525    if(pstring) {
526        asprintf(&tmp,"%s(%s,%s,%s)", stub, nm, abac_aspect_aspect_name(head),pstring);
527        free(pstring);
528        } else {
529            asprintf(&tmp,"%s(%s,%s)", stub, nm, abac_aspect_aspect_name(head));
530    }
531
532    _reset_pl(pl,tmp,prin_nm);
533    abac_list_t *rlist=_make_yap_query(pl,prin_nm,nm,tmp);
534    /* generate the resulting stack from a list */
535    ret=_make_cred_stack(rlist);
536    return ret;
537}
538
539/**
540 * Get all the credentials (attribute/issuer cert pairs) from prolog
541 * (which returns in string form)
542 */
543abac_stack_t *abac_pl_credentials(abac_pl_t *pl)
544{
545    abac_stack_t *ret=abac_verifier_dump_creds();
546    return ret;
547}
548
549abac_stack_t *abac_pl_principals(abac_pl_t *pl)
550{
551    abac_stack_t *ret=abac_verifier_dump_principals();
552    return ret;
553}
554
555/**
556 * Make a query into prolog db
557--role acme.preferred_customer --principal coyote
558--role acme.prefer_customer.buy_rockets --principlal coyote
559--oset acme.rockets -- object mrx-21
560--oset acme.villans -- principal coyote
561 */
562abac_stack_t *abac_pl_query(abac_pl_t *pl, char *roleoset, char *prinobj)
563{
564    abac_stack_t *ret=NULL;
565    int len=strlen(roleoset)+strlen(prinobj)+5;
566    char* attr_string=(char *) abac_xmalloc(sizeof(char)*len);
567    sprintf(attr_string,"%s<-%s", roleoset, prinobj);
568
569    if(debug)
570        fprintf(stderr,"abac_pl_query, query string is (%s)\n",attr_string);
571
572    /* call into yacc parser */
573    abac_reset_yyfptr(attr_string);
574    abac_yy_init();
575    int rc=yyparse();
576    if (rc) {
577        free(attr_string);
578        return NULL;
579    }
580
581    abac_aspect_t *head_aspect = abac_yy_get_rule_head_aspect();
582    abac_aspect_t *tail_aspect = abac_yy_get_rule_tail_aspect();
583
584    ret=_query_with_aspect(pl,head_aspect,tail_aspect);
585
586    return ret;
587}
588
589abac_stack_t *abac_pl_query_with_structure(abac_pl_t *pl, abac_aspect_t *head_aspect, abac_aspect_t *tail_aspect)
590{
591    abac_stack_t *ret=NULL;
592    ret=_query_with_aspect(pl,head_aspect,tail_aspect);
593
594    return ret;
595}
Note: See TracBrowser for help on using the repository browser.