source: libabac/abac_pl_yap.c @ 46df1bc

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

1) get ready for release 0.2.3
2) add forward function declaration in abac_pl_yap.c for

abac_credential_dup

3) tested against freebsd82 and freebsd91

  • Property mode set to 100644
File size: 28.9 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_credential_t *abac_credential_dup(abac_credential_t *cred);
22extern abac_list_t *abac_credential_clauses(abac_credential_t *);
23extern char *abac_id_clause(abac_id_credential_t *);
24extern abac_aspect_t *abac_yy_get_rule_tail_aspect();
25extern abac_aspect_t *abac_yy_get_rule_head_aspect();
26
27static int debug=0;
28
29/* track constraint's external clause's -unique name id */
30
31static int constraint_label_count=0;
32static char *constraint_label="isABAC_constraint";
33
34/*
35x    can pLadybug buy_rockets from pAcme ? (_arg_for_fact)
36x    can pLadybug What from pAcme ? (_arg_for_what)
37x    Who can buy_rockets from pAcme ? (_arg_for_who)
38x    can pLadybug buy_rockets from Whom ? (_arg_for_whom)
39x    can pLadybug What from Whom ? (_arg_for_what_whom)
40the type ordering also dictates the order of partial proof query
41sequence
42*/
43enum _query_type_t {
44   e_PL_FACT=0,
45   e_PL_WHAT=1,
46   e_PL_WHAT_DFLT=2,
47   e_PL_WHO=3,   
48   e_PL_WHOM=4,
49   e_PL_WHAT_WHOM=5,
50   e_PL_NOMORE=6
51};
52
53static const char *const _queryname[] =
54{
55  "fact",
56  "what",
57  "what_default",
58  "who",
59  "whom",
60  "what_whom",
61  "nomore"
62};
63static int _queryname_cnt=6;
64
65
66// pl -- place holder for now
67struct _abac_pl_t {
68   /* a_term <- prin */
69    char *whom;
70    char *who;
71    char *aspect;
72    char *what;
73    char *whatwith;
74    int pcnt; /* pcnt=number of params in whatwith */
75
76    int query_made; /* 1+ yes, 0 no, rc is valid only if a query is made */
77    int query_rc; /* rc of query call */
78    int next_rc; /* rc of next-last query */
79      /* proof count = abac_list_size(proof_list) */
80    int is_partial;
81    int want_partial;
82    int query_type;
83    abac_list_t *proof_list; /* list of list of cred_list */ 
84    long safe_t; /* holding the YAP's saved goal */
85};
86
87/***********************************************************/
88static int _get_next_constraint_label_idx()
89{
90    constraint_label_count++;
91    return constraint_label_count;
92}
93
94static int _get_constraint_label_idx()
95{
96    return constraint_label_count;
97}
98
99/***********************************************************/
100
101static int _insert_clause(char *str)
102{
103    YAP_Term eterm;
104    YAP_Term goalArgs=YAP_ReadBuffer(str, &eterm);
105    char *tmp=YAP_CompileClause(goalArgs);
106    if (tmp!=NULL) { /* something is wrong */
107        printf("error: result of compile clause (%s)\n", tmp);
108        printf("error: str used (%s)\n", str);
109        return 1;
110    }
111    return 0;
112}
113
114static int _insert_cred_clause(char *cstr)
115{
116    int ret=ABAC_CERT_SUCCESS;
117    int rc=_insert_clause(cstr);
118    if (rc)
119        return ABAC_CERT_BAD_YAP;
120    return ABAC_CERT_SUCCESS;
121}
122
123void show_yap_db(const char *msg)
124{
125    char lstr[]="listing";
126    YAP_Term eterm; /* error term */
127
128    printf("\n\n/* ========= yap db (%s) */\n",msg);
129    int rc=YAP_RunGoalOnce(YAP_ReadBuffer(lstr,&eterm));
130    if (rc) {
131        printf("/* listing ok.. */\n");
132    } else {
133        printf("/* listing's rc is bad.. */ \n");
134        YAP_Exit(1);
135    }
136    printf("/* ========= */\n\n");
137}
138
139/**
140 * Include some utility routines
141 */
142abac_pl_t *abac_pl_utility(void) {
143/*
144append([],L,L).
145append([X|L1],L2,[X|L3]):-append(L1,L2,L3).
146
147appendL([],[]).
148appendL([H|T], L) :-
149   appendL(T,L2), append(H,L2,L).
150*/
151    if(_insert_clause("append([],L,L)"))
152        YAP_Exit(1);
153    if(_insert_clause("append([X|L1],L2,[X|L3]):-append(L1,L2,L3)"))
154        YAP_Exit(1);
155    if(_insert_clause("appendL([],[])"))
156        YAP_Exit(1);
157    if(_insert_clause("appendL([H|T], L) :- appendL(T,L2), append(H,L2,L)"))
158        YAP_Exit(1);
159}
160
161/**
162 * Create a new yap structure.
163 */
164abac_pl_t *abac_pl_new(void) {
165
166    YAP_Term eterm;
167
168    if (YAP_FastInit(NULL) == YAP_BOOT_ERROR)
169        YAP_Exit(1);
170
171    int rc=YAP_RunGoalOnce(YAP_ReadBuffer("source",&eterm));
172    if(rc) {
173        if(debug) fprintf(stderr, "calling source..\n");
174        } else {
175            if(debug) fprintf(stderr,"calling source failed..\n");
176            YAP_Exit(1);
177    }
178
179    abac_pl_utility();
180 
181    abac_pl_t *pl = abac_xmalloc(sizeof(abac_pl_t));
182
183    pl->who=NULL;
184    pl->whom = NULL;
185    pl->what = NULL;
186    pl->whatwith = NULL;
187    pl->aspect = NULL;
188    pl->pcnt=0;
189    pl->query_made=0;
190    pl->query_rc=0;
191    pl->is_partial=0;
192    pl->want_partial=1;
193    pl->query_type=e_PL_FACT;
194    pl->next_rc=0;
195    pl->proof_list=NULL;
196    pl->safe_t=0;
197    return pl;
198}
199
200int abac_pl_returning_partial(abac_pl_t *pl)
201{
202    return pl->is_partial;
203}
204
205/* returns the number of solution so far */
206int abac_pl_proof_cnt(abac_pl_t *pl)
207{
208    if(pl->proof_list)
209        return abac_list_size(pl->proof_list);
210    return 0;
211}
212
213int abac_pl_is_partial(abac_pl_t *pl)
214{
215    return pl->is_partial;
216}
217
218/* is this the conclusion of the query ? */
219/* 1 is yes, 0 N/A */
220int abac_pl_done_yet(abac_pl_t *pl)
221{
222    if(pl->query_made) {
223        if(pl->query_rc) {
224            if(!pl->next_rc) return 1;
225            return 0;
226        } else return 1; /* even init query failed */
227    }
228    return 0;
229}
230
231void abac_pl_set_no_partial(abac_pl_t *pl)
232{
233   pl->want_partial=0;
234}
235
236void abac_pl_set_want_partial(abac_pl_t *pl)
237{
238   pl->want_partial=1;
239}
240
241static void _free_p_list(abac_list_t *p)
242{
243    if( p != NULL ) {
244        if(abac_list_size(p) != 0) {
245            abac_credential_t *cur=NULL;
246            abac_list_foreach(p, cur,
247                abac_credential_free(cur);
248            );
249        }
250        abac_list_free(p);
251    }
252}
253
254static void _free_pf_list(abac_list_t *p)
255{
256   
257    if(p != NULL) {
258        if(abac_list_size(p) != 0) {
259            abac_list_t *cur=NULL;
260            abac_list_foreach(p, cur,
261                _free_p_list(cur);
262            );
263        }
264        abac_list_free(p);
265    }
266}
267
268void abac_pl_free(abac_pl_t *pl) {
269    if(pl->who) free(pl->who);
270    if(pl->whom) free(pl->whom);
271    if(pl->what) free(pl->what);
272    if(pl->whatwith) free(pl->whatwith);
273    if(pl->aspect) free(pl->aspect);
274    _free_pf_list(pl->proof_list);
275    free(pl);
276}
277
278/* this is done whenever a new query starts in */
279static void _reset_pl(abac_pl_t *pl, char *who,
280char *what, char *whom, char *aspect, char *whatwith, int pcnt)
281{
282    if(pl->safe_t != 0) {
283#ifdef  YAP_VERSION
284        if(YAP_VERSION == "6.2.3") {
285            YAP_RecoverSlots(1); 
286            YAP_Reset(); 
287            } else { /* 6.3.2 seems to have YAP_Reset problem */
288                YAP_RecoverSlots(1); 
289        }
290    }
291#endif
292
293    /* free the old ones */
294    if(pl->who) free(pl->who);
295    if(pl->whom) free(pl->whom);
296    if(pl->what) free(pl->what);
297    if(pl->whatwith) free(pl->whatwith);
298    if(pl->aspect) free(pl->aspect);
299
300    pl->who = (who !=NULL)?abac_xstrdup(who):NULL;
301    pl->whom = (whom !=NULL)?abac_xstrdup(whom):NULL;
302    pl->what = (what!=NULL)?abac_xstrdup(what):NULL;
303    pl->whatwith = (whatwith!=NULL)?abac_xstrdup(whatwith):NULL;
304    pl->aspect = (aspect!=NULL)?abac_xstrdup(aspect):NULL;
305
306    pl->pcnt=pcnt;
307
308    pl->query_made=0;
309    pl->query_rc=0;
310    pl->next_rc=0;
311    pl->is_partial=0;
312    pl->query_type=e_PL_FACT;
313    _free_pf_list(pl->proof_list);
314    pl->proof_list=abac_list_new();
315    pl->safe_t=0;
316}
317
318/**
319 * Add a credential to the db, not duplicating a copy and so
320 * don't try to free it after this call.
321 */
322int abac_pl_add_credential(abac_pl_t *pl, abac_credential_t *cred)
323{
324    int rc=0;
325    abac_list_t *clauses=abac_credential_clauses(cred);
326    if (clauses != NULL) {
327        char *cur;
328        abac_list_foreach(clauses, cur,
329            if(cur) {
330                if(debug) fprintf(stderr,"inserting =>%s\n",cur);
331                rc=_insert_cred_clause(cur);
332            }
333        );
334    }
335    return rc;
336}
337
338int abac_pl_add_type_credential(abac_pl_t *pl, abac_id_credential_t *id_cert)
339{
340    char *clause=abac_id_clause(id_cert);
341    if (clause != NULL) {
342        int rc=_insert_cred_clause(clause);
343        return rc;
344    }
345    return 0;
346}
347
348/*  string1(S):- S="abc";S="efg";S="ijk" */
349char *abac_pl_add_range_constraint_clause(char *var, char *tmplist)
350{
351    int i=_get_next_constraint_label_idx();
352    char *tmp=NULL;
353    asprintf(&tmp,"%s_%d(%s) :- %s", constraint_label, i, var, tmplist); 
354    int rc=_insert_cred_clause(tmp);
355    free(tmp);
356    if(rc) 
357        panic("abac_pl_add_range_constraint_clause, failed to insert");
358    asprintf(&tmp,"%s_%d(%s)", constraint_label, i, var);
359    return tmp;
360}
361
362/* cases, for YAP 6.2.x
363     ['str']
364     ['str1','str2']
365     ([] is not possible, and don't care)
366*/
367static void _credentials_from_string_2(abac_list_t *credentials,char *slist) 
368{
369    char *cptr=slist; /* current ptr */
370    char *sptr; /* string ptr */
371    char *ptr;
372    int len=0;
373    char *string;
374    abac_credential_t *cred=NULL;
375    int cnt=0;
376
377    /* find first [' */ 
378    ptr=strstr(cptr,"['");
379    if(ptr == NULL) 
380         return;
381    cptr=ptr+2;
382    sptr=cptr;
383    while (1) {
384        /* find next ',' or '] */
385        if(debug) fprintf(stderr,"START with %d\n", strlen(cptr));
386        ptr=strstr(cptr,"','");
387        if(ptr!=NULL) {
388             cptr=ptr+3;
389             len=(ptr-sptr);
390             string=strndup(sptr,len);
391             cred=abac_credential_lookup(string);
392             free(string); 
393             if(cred) {
394                 int i=abac_list_unique_add(credentials, cred);
395                 if(i) cnt++;
396                 } else {
397                 printf("BAD BAD\n");
398             }
399             sptr=cptr;
400             } else {
401             ptr=strstr(cptr,"']");
402             if(ptr!=NULL) {
403                 len=(ptr-sptr);
404                 string=strndup(sptr,len);
405                 cred=abac_credential_lookup(string);
406                 free(string);
407                 if(cred) {
408                     int i=abac_list_unique_add(credentials, cred);
409                     if(i) cnt++;
410                     } else {
411                     printf("BAD BAD BAD\n");
412                 }
413                 break;
414             }
415        }
416    }
417    if(debug)
418        fprintf(stderr,"DEBUG:total %d credentials\n", cnt);
419}
420
421/*  XXX just for yap 6.3.2
422     [str]
423     [str1,str2]
424     ([] is not possible, and don't care)
425*/
426static void _credentials_from_string_3(abac_list_t *credentials,char *slist)
427{
428    char *cptr=slist; /* current ptr */
429    char *sptr; /* string ptr */
430    char *ptr;
431    int len=0;
432    char *string;
433    abac_credential_t *cred=NULL;
434    int cnt=0;
435
436    /* find first [ */ 
437    ptr=strstr(cptr,"[");
438    if(ptr == NULL) 
439         return;
440    cptr=ptr+1;
441    sptr=cptr;
442    while (1) {
443        /* find next "," or "]" */
444        if(debug) fprintf(stderr,"START with %d\n", strlen(cptr));
445        ptr=strstr(cptr,",");
446        if(ptr!=NULL) {
447             cptr=ptr+1;
448             len=(ptr-sptr);
449             string=strndup(sptr,len);
450             cred=abac_credential_lookup(string);
451             free(string); 
452             if(cred) {
453                 int i=abac_list_unique_add(credentials, cred);
454                 if(i) cnt++;
455                 } else {
456                 printf("BAD BAD\n");
457             }
458             sptr=cptr;
459             } else {
460             ptr=strstr(cptr,"]");
461             if(ptr!=NULL) {
462                 len=(ptr-sptr);
463                 string=strndup(sptr,len);
464                 cred=abac_credential_lookup(string);
465                 free(string);
466                 if(cred) {
467                     int i=abac_list_unique_add(credentials, cred);
468                     if(i) cnt++;
469                     } else {
470                     printf("BAD BAD BAD\n");
471                 }
472                 break;
473             }
474        }
475    }
476    if(debug)
477        fprintf(stderr,"DEBUG:total %d credentials\n", cnt);
478}
479
480static void _credentials_from_string(abac_list_t *credentials,char *slist) {
481#ifdef YAP_VERSION
482    if(YAP_VERSION == "6.2.3")
483         _credentials_from_string_2(credentials,slist);
484    else
485         _credentials_from_string_3(credentials,slist);
486#endif
487    if(debug) 
488         fprintf(stderr,"_credentials_from_string: missing YAP_VERSION\n");
489}
490
491/* MAX 1024x1024, double as it goes */
492static int try_again(int sz, char **tptr)
493{
494   int debug=1;
495   int blk=1024*2; /* 2048 */
496   int max=1024*1024;
497   int size;
498   char *tmp = NULL;
499
500   if(sz==0) {
501/* XXX size = (sizeof(char) * (blk+1)); */
502       size = (sizeof(char) * (blk+1));
503       } else {
504           if(debug) fprintf(stderr,"calling try_again needing extra space!!\n");
505           if (sz>=max) {
506               size=0;
507               *tptr=tmp;
508               return 0;
509           }
510           size=sz*2+1;
511           if(size > max) size=max;
512   }
513
514   tmp = (char *) YAP_AllocSpaceFromYap(size);
515   if(tmp==NULL) {
516       fprintf(stderr,"ERROR: malloc failed !!!\n");
517       YAP_Exit(1);
518   }
519   *tptr=tmp;
520   return size;
521}
522
523static int _check_buffer(char *tmp)
524{
525    int len=strlen(tmp); /* just for reference :-( */
526    if (len < 3) return 0;
527    if (tmp[0] != '[') return 0;
528    if (tmp[len-1] == ']') return 1;
529    int i=0; 
530    for(i=3; i<=len; i++) {
531        if(tmp[i]==']') {
532           if(i==len) fprintf(stderr," _check_buffer, match up..\n");
533             else {
534                 fprintf(stderr," _check_buffer, did not match up ..\n");
535                 tmp[i+1]='\0';
536           }
537           return 1;
538        }
539    }
540    if(debug)
541        fprintf(stderr," _check_buffer, did not find the closing square bracket ..\n");
542    return 0;
543}
544
545abac_list_t *run_goal(abac_pl_t *pl, YAP_Term *arg)
546{
547    abac_list_t *cred_list=abac_list_new();
548    YAP_Atom f = YAP_LookupAtom("isMember");
549    YAP_Functor func = YAP_MkFunctor(f, 3);
550    YAP_Term goal=YAP_MkApplTerm(func, 3, arg);
551
552    pl->safe_t = YAP_InitSlot(goal);
553if(debug) fprintf(stderr," run_goal, safe_t is %ld\n", pl->safe_t);
554    pl->query_rc =YAP_RunGoal(goal);
555    goal=YAP_GetFromSlot(pl->safe_t);
556    pl->query_made=1;
557    pl->next_rc=pl->query_rc;
558    if (pl->query_rc) {
559        if(pl->is_partial) 
560            printf("A partial proof(type:%s)\n",_queryname[pl->query_type]);
561            else printf("YAP query succeed\n");
562        char *tmp=NULL;
563        int tmp_sz=0; 
564        if(YAP_VERSION == "6.2.3")
565            tmp_sz=try_again(0, &tmp);
566        YAP_Term argterm=YAP_ArgOfTerm(3,goal);
567        while(1) {
568            int rc=1; /* XXX rc does not seems to be right... */
569            if(YAP_VERSION == "6.2.3") {
570                YAP_WriteBuffer(argterm, tmp, tmp_sz,YAP_WRITE_HANDLE_VARS); 
571                } else {
572                    rc=YAP_WriteBuffer(argterm, tmp, tmp_sz,YAP_WRITE_HANDLE_VARS);
573            }
574if(debug) fprintf(stderr,"call YAP_WriteBuffer: rc(%d) tmp_sz(%d)\n", rc, tmp_sz);
575if(debug) fprintf(stderr,"what came back .. rc(%d)(%d:%c)\n",rc,strlen(tmp),tmp[strlen(tmp)-1]);
576
577/** it seems that 6.3 gives me some garbage at the back.. */
578            if(rc==1 && _check_buffer(tmp)) {
579if(debug) fprintf(stderr,".. okay\n");
580                break;
581            } else {
582if(debug) fprintf(stderr,".. not okay\n");
583                tmp_sz=try_again(tmp_sz,&tmp);
584if(debug) fprintf(stderr,"try_again: tmp_sz(%d)\n", tmp_sz);
585                if(tmp_sz==0) {
586                    fprintf(stderr," PANIC, run out of heap space..\n");
587                    YAP_Exit(1);
588                }
589            }
590        }
591        /* this is returned as ['string1','string2'] */
592        if(debug) fprintf(stderr,"    query answer : %s(%d)\n", tmp, strlen(tmp));
593        _credentials_from_string(cred_list,tmp); 
594        if(abac_list_size(cred_list)==0) {
595            fprintf(stderr,"CAN NOT retrieve result properly from YAP!!!\n");
596            YAP_Exit(1);
597        }
598        abac_list_add(pl->proof_list, cred_list);
599        YAP_FreeSpaceFromYap(tmp);
600    } else {
601        /* don't print anything if it is running a partial proof goal */
602        if(!pl->is_partial) 
603            printf("YAP query failed\n");
604 
605    }
606    return cred_list;
607}
608
609/*************************************************************************/
610YAP_Term _make_term(char *term) {
611    YAP_Term eterm;
612    YAP_Term ret;
613    if(term[0]=='\'' || term[0]=='"') {
614        ret =YAP_ReadBuffer(term,&eterm);
615        } else {
616            ret = YAP_MkAtomTerm(YAP_LookupAtom(term));
617    }
618}
619
620// isMember(who,aspect(whom,what,whatwith))
621/* aspect(whom, what, whatwith) */
622YAP_Term _aspect_base(char *whom,char *aspect, char *what, char *whatwith)
623{
624    YAP_Term eterm;
625    YAP_Term ret;
626
627    char *estring=NULL;
628    if(whatwith)
629       asprintf(&estring, "%s(%s,%s,%s)",aspect,whom,what,whatwith);
630       else asprintf(&estring, "%s(%s,%s)",aspect,whom,what);
631    if(debug) fprintf(stderr,"_aspect_base, doing %s\n",estring);
632    ret=YAP_ReadBuffer(estring,&eterm);
633    free(estring);
634    return ret;
635}
636
637/* generate a string of whatwith that are of ?variable */
638char *_make_whatwith_var(char *whatwith, int pcnt)
639{
640/* this is a dumb count since it is in porting directory */
641   if(whatwith==NULL || pcnt==0) return NULL; 
642   char *tmp=NULL;
643   char *ptr=NULL;
644   int i;
645   for(i=0;i<pcnt;i++) {
646       ptr=tmp;
647       tmp=NULL;
648       if(i == 0)
649           asprintf(&tmp,"Whatwith%d",i);
650           else asprintf(&tmp,"%s,Whatwith%d",ptr,i);
651   }
652   return tmp;
653}
654
655/* aspect(X, Y, Whatwith) */
656YAP_Term _aspect_what_whom(char *whom,char *aspect, char *what, char *whatwith)
657{
658    YAP_Term ret=_aspect_base("Whom",aspect,"What",whatwith);
659    return ret;
660}
661
662/* aspect(whom,Y,Whatwith) */
663/* call with char *tmp=_make_whatwith_var(whatwith); */
664YAP_Term _aspect_what(char *whom,char *aspect, char *what, char *whatwith)
665{
666    YAP_Term ret=_aspect_base(whom,aspect,"What",whatwith);
667    return ret;
668}
669
670/* aspect(X,what,whatwith) */
671YAP_Term _aspect_whom(char *whom,char *aspect, char *what, char *whatwith)
672{
673    YAP_Term ret=_aspect_base("Whom",aspect,what,whatwith);
674    return ret;
675}
676
677/* aspect(whom,what,whatwith) */
678YAP_Term _aspect_fact(char *whom,char *aspect, char *what, char* whatwith)
679{
680    YAP_Term ret=_aspect_base(whom,aspect,what,whatwith);
681    return ret;
682}
683
684// Whom.What <- ladybug
685// isMember(ladybug, role(W1, W2), R)
686static void _arg_for_what_whom(YAP_Term *arg,char *who, char *whom,
687char *aspect, char*what, char *whatwith, int pcnt)
688{
689    arg[0] = _make_term(who);
690    char *tmp=_make_whatwith_var(whatwith,pcnt); 
691    arg[1] = _aspect_what_whom(who,aspect,what,tmp);
692    if(tmp) free(tmp);
693    arg[2] = YAP_MkVarTerm();
694}
695
696// pAcme.What <- ladybug
697// isMember(ladybug, role(pAcme, W), R)
698static void _arg_for_what(YAP_Term *arg,char *who, char* whom, 
699char *aspect, char*what, char*whatwith, int pcnt)
700{
701    arg[0] = _make_term(who);
702    char *tmp=_make_whatwith_var(whatwith,pcnt); 
703    arg[1] = _aspect_what(whom,aspect,what,tmp);
704    if(tmp) free(tmp);
705    arg[2] = YAP_MkVarTerm();
706}
707
708// W.rocket <- ladybug
709// isMember(ladybug, role(W, buy_rockets), R)
710static void _arg_for_whom(YAP_Term *arg, char *who, char*whom,
711char *aspect, char *what, char*whatwith)
712{
713    arg[0] = _make_term(who);
714    arg[1] = _aspect_whom(whom,aspect,what,whatwith);
715    arg[2] = YAP_MkVarTerm();
716}
717
718// Acme.rocket <- V
719// isMember(V, role(pAcme, buy_rockets), R)
720static int _arg_for_who(YAP_Term *arg, char *who,char *whom, 
721char *aspect, char* what, char*whatwith)
722{
723    arg[0] = YAP_MkVarTerm();
724    arg[1] = _aspect_fact(whom, aspect, what, whatwith);
725    arg[2] = YAP_MkVarTerm();
726}
727
728// Acme.rocket <- x
729// isMember(x, role(pAcme, buy_rockets), R)
730static void _arg_for_fact(YAP_Term *arg,char *who,char *whom, 
731char* aspect, char *what, char*whatwith)
732{
733    arg[0] = _make_term(who);
734    arg[1] = _aspect_fact(whom, aspect, what, whatwith);
735    arg[2] = YAP_MkVarTerm();
736}
737
738
739static abac_list_t *_make_partial_query(abac_pl_t *pl)
740{
741    abac_list_t *ret=abac_list_new();
742    pl->is_partial=1;
743    char *who=pl->who;
744    char *whom=pl->whom;
745    char *aspect=pl->aspect;
746    char *what=pl->what;
747    char *whatwith=pl->whatwith;
748    int pcnt=pl->pcnt;
749    if(debug) fprintf(stderr,"making make_partial_query..\n");
750
751    switch (pl->query_type) { 
752        case e_PL_FACT: /* try what */
753            {
754            YAP_Term arg[3];
755            if(debug) fprintf(stderr,"... 1st partial attempt\n");
756            pl->query_type = e_PL_WHAT;
757            _arg_for_what(arg,who,whom, aspect, what, whatwith, pcnt);
758            ret=run_goal(pl,arg);
759            if(pcnt==0) pl->query_type= e_PL_WHAT_DFLT;
760            if(pl->query_rc) return ret;
761            break;
762            }
763        case e_PL_WHAT: /* try what with no params if need to */
764            {
765            YAP_Term arg[3];
766            if(debug) fprintf(stderr,"... 2nd partial attempt\n");
767            pl->query_type = e_PL_WHAT_DFLT;
768            _arg_for_what(arg,who,whom, aspect, what, whatwith, 0);
769            ret=run_goal(pl,arg);
770            if(pl->query_rc) return ret;
771            break;
772            }
773        case e_PL_WHAT_DFLT: /* try who */
774            {
775            YAP_Term arg[3];
776            if(debug) fprintf(stderr,"... 2nd half partial attempt\n");
777            pl->query_type = e_PL_WHO;
778            _arg_for_who(arg,who,whom, aspect, what, whatwith);
779            ret=run_goal(pl,arg);
780            if(pl->query_rc) return ret;
781            break;
782            }
783        case e_PL_WHO: /* try whom */
784            {
785            YAP_Term arg[3];
786            if(debug) fprintf(stderr,"... 3rd partial attempt\n");
787            pl->query_type = e_PL_WHOM;
788            _arg_for_whom(arg,who,whom, aspect, what, whatwith);
789            ret=run_goal(pl,arg);
790            if(pl->query_rc) return ret;
791            break;
792            }
793        case e_PL_WHOM: /* try what-whom */
794            {
795            YAP_Term arg[3];
796            if(debug) fprintf(stderr,"... 4th partial attempt\n");
797            pl->query_type = e_PL_WHAT_WHOM;
798            _arg_for_what_whom(arg,who,whom, aspect, what, whatwith,pcnt);
799            ret=run_goal(pl,arg);
800            if(pl->query_rc) return ret;
801            break;
802            }
803        default :
804            {
805            if(debug) fprintf(stderr,"... no more partial query to try\n");
806            pl->query_type = e_PL_NOMORE;
807            }
808    }
809    return ret;
810}
811
812/* make a query and extract just first set of result,
813   simple = rt0
814   aspect => role/oset
815   aspect_string => rest of params
816   prin => principal
817   issuer => issuer
818   estring =>  aspect(issuer, aspect_type_string)
819*/
820static abac_list_t *_make_yap_query(abac_pl_t *pl, char *who,
821char *whom, char *aspect, char *what, char *whatwith, int pcnt)
822{
823    if(debug) { 
824       fprintf(stderr,"_make_yap_query: the who part(%s)\n", who);
825       fprintf(stderr,"_make_yap_query: whom part(%s)\n", whom);
826       fprintf(stderr,"_make_yap_query: the role/oset (%s)\n", aspect);
827       fprintf(stderr,"_make_yap_query: aspect what (%s)\n", what);
828       fprintf(stderr,"_make_yap_query: pcnt (%d)\n", pcnt);
829       if(whatwith)
830           fprintf(stderr,"_make_yap_query: aspect what part(%s)\n", whatwith);
831    } 
832    if(debug) fprintf(stderr,"making a yap query..\n");
833
834/* run query on fact goal */
835    YAP_Term arg[3];
836    _arg_for_fact(arg, who,whom, aspect, what, whatwith);
837    abac_list_t *ret=run_goal(pl,arg);
838
839/* fact query failed and so run partial query */
840    if(!pl->query_rc && pl->want_partial) {
841        while(pl->query_type != e_PL_NOMORE) {
842            abac_list_free(ret);
843            ret=_make_partial_query(pl);
844            if( pl->query_rc ) break;
845        }
846    }
847    return ret;
848}
849
850/* make a query for next possible solution proof */
851static abac_list_t *_query_again(abac_pl_t *pl)
852{
853    abac_list_t *cred_list=abac_list_new();
854
855    if(debug) fprintf(stderr,"making query_again call..\n");
856    pl->next_rc=YAP_RestartGoal();
857    pl->query_made++;
858    YAP_Term goal=YAP_GetFromSlot(pl->safe_t);
859
860    char *tmp=NULL;
861    int tmp_sz=try_again(0, &tmp);
862    YAP_Term argterm=YAP_ArgOfTerm(3,goal);
863    if(pl->next_rc) {
864        if(debug) fprintf(stderr,"query_again: another success\n");
865        if(pl->is_partial)
866            printf("A partial proof(type:%s)\n",_queryname[pl->query_type]);
867        while(1) {
868            YAP_WriteBuffer(argterm, tmp, tmp_sz,YAP_WRITE_HANDLE_VARS);
869            if(strlen(tmp) > 5 && tmp[0]=='\[')
870                break;
871            tmp_sz=try_again(tmp_sz,&tmp);
872            if(tmp_sz==0) {
873                fprintf(stderr," PANIC, run out of heap space..\n");
874                YAP_Exit(1);
875            }
876        }
877        /* this is returned as ['string1','string2'] */
878        if(debug) fprintf(stderr,"    query answer : %s(%d)\n", tmp, strlen(tmp));
879        _credentials_from_string(cred_list,tmp); 
880        if(abac_list_size(cred_list)==0) {
881            fprintf(stderr,"CAN NOT retrieve result properly from YAP!!!\n");
882            YAP_Exit(1);
883        }
884        abac_list_add(pl->proof_list, cred_list);
885        YAP_FreeSpaceFromYap(tmp);
886        } else {
887            if(debug) fprintf(stderr,"query_again: fail finding next\n");
888            if(pl->is_partial) { /* if there is more partial query to make */
889                while(pl->query_type != e_PL_NOMORE) {
890                    abac_list_free(cred_list);
891                    cred_list=_make_partial_query(pl);
892                    if( pl->query_rc ) break;
893                }
894            }
895    }
896    return cred_list;
897}
898
899/* print a list of abac_credential_t */
900void _print_cred_list(abac_list_t *p)
901{
902    if(debug) fprintf(stderr,"_print_cred_list(%d)items:\n",abac_list_size(p));
903    if(abac_list_size(p) != 0) {
904        abac_credential_t *cur=NULL;
905        abac_list_foreach(p, cur,
906            if(debug) fprintf(stderr,"printing (%d),\n",(int)cur);
907            abac_print_cred_info(cur, NULL);
908        );
909    }
910}
911
912
913abac_stack_t *_make_cred_stack(abac_list_t *p)
914{
915    abac_stack_t *ret=abac_stack_new();
916    if(abac_list_size(p) != 0) {
917        abac_credential_t *cur=NULL;
918        abac_list_foreach(p, cur,
919            abac_stack_push(ret, (void *)abac_credential_dup(cur));
920        );
921    }
922    return ret;
923}
924
925/* force a  backtrack to get next solution proof */
926abac_stack_t *abac_pl_query_again(abac_pl_t *pl)
927{
928    abac_list_t *rlist=_query_again(pl);
929    abac_stack_t *ret=_make_cred_stack(rlist);
930    return ret;
931}
932
933/* 2 types
934      acme.buys_rocket <- coyote (coyote=prin, acme.buys_rocket=role)
935        ==> isMember(coyote,role(acme,buys_rocket), L)
936      acme.buys_rocket <- acme.preferred_customer  -- NOT valid
937*/
938static abac_stack_t *_query_with_aspect(abac_pl_t *pl, abac_aspect_t* head, abac_aspect_t* tail)
939{
940    abac_stack_t *ret=NULL;
941    char *tmp=NULL;
942
943    if(0)
944        show_yap_db("DEBUG:calling within _query_with_aspect");
945
946    char *whom=NULL;
947    PROLOG(whom=abac_aspect_principal_name(head););
948
949    /* could be obj or principal */
950    char *who=NULL;
951    if(abac_aspect_is_object(tail)) {
952        who=abac_aspect_object_name(tail);
953        } else {
954            PROLOG(who=abac_aspect_principal_name(tail););
955    }
956
957    if(abac_aspect_aspect_name(tail)!=NULL) {
958        printf("fail, a.o <- b.o and a.r <- a.r query is not implemented yet !!!\n");
959        YAP_Exit(1);
960    }
961
962    if (who == NULL || whom == NULL) {
963        printf("fail, query's call got bad aspect names .. \n");
964        YAP_Exit(1);
965    }
966
967    if(debug) fprintf(stderr,"printing up the yap query ..\n");
968
969    char *pstring;
970    PROLOG(pstring=abac_aspect_aspect_param_string(head););
971
972    char *aspect=abac_aspect_type_string(head);
973    int pcnt=abac_aspect_aspect_param_cnt(head);
974    char *what=abac_aspect_aspect_name(head);
975
976    _reset_pl(pl, who, what, whom, aspect, pstring, pcnt);
977
978    abac_list_t *rlist=NULL;
979    if(pcnt)
980        rlist=_make_yap_query(pl,who,whom,aspect,abac_aspect_aspect_name(head),pstring,pcnt);
981        else
982            rlist=_make_yap_query(pl,who,whom,aspect,abac_aspect_aspect_name(head),NULL,0);
983
984    /* generate the resulting stack from a list */
985    ret=_make_cred_stack(rlist);
986    if(tmp) free(tmp);
987    if(pstring) free(pstring);
988    return ret;
989}
990
991/**
992 * Get all the credentials (attribute/issuer cert pairs) from prolog
993 * (which returns in string form)
994 */
995abac_stack_t *abac_pl_credentials(abac_pl_t *pl)
996{
997    abac_stack_t *ret=abac_verifier_dump_creds();
998    return ret;
999}
1000
1001abac_stack_t *abac_pl_principals(abac_pl_t *pl)
1002{
1003    abac_stack_t *ret=abac_verifier_dump_principals();
1004    return ret;
1005}
1006
1007/**
1008 * Make a query into prolog db
1009--role acme.preferred_customer --principal coyote
1010--role acme.prefer_customer.buy_rockets --principlal coyote
1011--oset acme.rockets -- object mrx-21
1012--oset acme.villans -- principal coyote
1013 */
1014abac_stack_t *abac_pl_query(abac_pl_t *pl, char *roleoset, char *prinobj)
1015{
1016    abac_stack_t *ret=NULL;
1017    int len=strlen(roleoset)+strlen(prinobj)+5;
1018    char* attr_string=(char *) abac_xmalloc(sizeof(char)*len);
1019    sprintf(attr_string,"%s<-%s", roleoset, prinobj);
1020
1021    if(debug)
1022        fprintf(stderr,"abac_pl_query, query string is (%s)\n",attr_string);
1023
1024    /* call into yacc parser */
1025    abac_reset_yyfptr(attr_string);
1026    abac_yy_init();
1027    int rc=yyparse();
1028    if (rc) {
1029        free(attr_string);
1030        return NULL;
1031    }
1032
1033    abac_aspect_t *head_aspect = abac_yy_get_rule_head_aspect();
1034    abac_aspect_t *tail_aspect = abac_yy_get_rule_tail_aspect();
1035
1036    ret=_query_with_aspect(pl,head_aspect,tail_aspect);
1037
1038    return ret;
1039}
1040
1041abac_stack_t *abac_pl_query_with_structure(abac_pl_t *pl, abac_aspect_t *head_aspect, abac_aspect_t *tail_aspect)
1042{
1043    abac_stack_t *ret=NULL;
1044    ret=_query_with_aspect(pl,head_aspect,tail_aspect);
1045
1046    return ret;
1047}
Note: See TracBrowser for help on using the repository browser.