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