/* copied from abac_graph.c implementation of the low level using yap prolog */ #include #include #include #include #include #include #include "abac_pl.h" #include "abac_pl_yap.h" #include "abac_list.h" #include "abac_util.h" #include "uthash.h" extern char *abac_cn_with_role(abac_role_t *); extern char *abac_cn_with_oset(abac_oset_t *); extern abac_list_t *abac_credential_clauses(abac_credential_t *); extern char *abac_id_clause(abac_id_cert_t *); static int debug=0; // pl -- place holder for now struct _abac_pl_t { FILE *fptr; char *fname; char *yap_certs; }; static int _insert_clause(char *str) { YAP_Term *eterm; YAP_Term goalArgs=YAP_ReadBuffer(str, eterm); char *tmp=YAP_CompileClause(goalArgs); if (tmp!=NULL) { /* something is wrong */ printf("error: result of compile clause (%s)\n", tmp); printf("error: str used (%s)\n", str); return 1; } return 0; } static int _insert_cred_clause(char *cstr) { int ret=ABAC_CERT_SUCCESS; int rc=_insert_clause(cstr); if (rc) return ABAC_CERT_BAD_YAP; return ABAC_CERT_SUCCESS; } static void _show_yap_db(char *msg) { char lstr[]="listing"; YAP_Term *eterm; /* error term */ printf("\n\n========= yap db (%s)\n",msg); YAP_Term goal=YAP_ReadBuffer(lstr, eterm); int rc =YAP_RunGoal( goal ); if (rc) { printf("listing ok.. \n"); } else { printf("listing's rc is bad.. \n"); YAP_Exit(1); } printf("========= \n\n"); } static void _set_dbg(abac_pl_t *pl) { char *fname=strdup( "/tmp/abac_yap-XXXXXX.pl" ); int fd = mkstemps( pl->fname, 3 ); if ( fd == -1) { printf("Couldn't get a valid temp name %s\n", fname); free((void*)fname); YAP_Exit(1); } FILE *fptr = fdopen(fd, "w"); if (fptr == NULL) { printf("Couldn't open %s for writing\n", fname); free((void*)fname); YAP_Exit(1); } pl->fptr=fptr; pl->fname=fname; } /** * Include some utility routines */ abac_pl_t *abac_pl_utility(void) { /* append([],L,L). append([X|L1],L2,[X|L3]):-append(L1,L2,L3). appendL([],[]). appendL([H|T], L) :- appendL(T,L2), append(H,L2,L). */ if(_insert_clause("append([],L,L)")) YAP_Exit(1); if(_insert_clause("append([X|L1],L2,[X|L3]):-append(L1,L2,L3)")) YAP_Exit(1); if(_insert_clause("appendL([],[])")) YAP_Exit(1); if(_insert_clause("appendL([H|T], L) :- appendL(T,L2), append(H,L2,L)")) YAP_Exit(1); } /** * Create a new yap structure. */ abac_pl_t *abac_pl_new(void) { if (YAP_FastInit(NULL) == YAP_BOOT_ERROR) YAP_Exit(1); if (YAP_RunGoal(YAP_MkAtomTerm(YAP_LookupAtom("source")))) { if(debug) printf("calling source..\n"); } else { if(debug) printf("calling source failed..\n"); YAP_Exit(1); } abac_pl_utility(); abac_pl_t *pl = abac_xmalloc(sizeof(abac_pl_t)); pl->fptr=NULL; pl->fname=NULL; pl->yap_certs=NULL; return pl; } /** * Add a credential to the db */ int abac_pl_add_credential(abac_pl_t *pl, abac_credential_t *cred) { int rc=0; abac_list_t *clauses=abac_credential_clauses(cred); if (clauses != NULL) { char *cur; abac_list_foreach(clauses, cur, if(cur) { if(debug) printf("inserting =>%s\n",cur); rc=_insert_cred_clause(cur); } ); } return rc; } int abac_pl_add_type_credential(abac_pl_t *pl, abac_id_cert_t *id_cert) { char *clause=abac_id_clause(id_cert); if (clause != NULL) { int rc=_insert_cred_clause(clause); return rc; } return 0; } /* cases, ['str'] ['str1','str2'] ([] is not possible, and don't care) */ static void _credentials_from_string(abac_stack_t *credentials,char *slist) { char *cptr=slist; /* current ptr */ char *sptr; /* string ptr */ char *ptr; int len=0; char *string; abac_credential_t *cred=NULL; int cnt=0; if(debug) printf("DEBUG:responds from yap(%s)\n",slist); /* find first [' */ ptr=strstr(cptr,"['"); if(ptr == NULL) return; cptr=ptr+2; sptr=cptr; while (1) { /* find next ',' or '] */ ptr=strstr(cptr,"','"); if(ptr!=NULL) { cptr=ptr+3; len=(ptr-sptr); string=strndup(sptr,len); cred=abac_credential_lookup(string); free(string); if(cred) { abac_stack_unique_push(credentials, cred); cnt++; } else { printf("BAD BAD BAD\n"); } sptr=cptr; } else { ptr=strstr(cptr,"']"); if(ptr!=NULL) { len=(ptr-sptr); string=strndup(sptr,len); cred=abac_credential_lookup(string); free(string); if(cred) { abac_stack_unique_push(credentials, cred); cnt++; } else { printf("BAD BAD BAD\n"); } break; } } } if(debug) printf("DEBUG:total %d credentials\n", cnt); } static abac_stack_t *_make_yap_query(char *cn_prin, char *cn_rule, char* estring) { YAP_Term *eterm; YAP_Term arg[3]; char tmp[5000]; abac_stack_t *cred_list = abac_stack_new(); if(debug) printf(" the role part(%s)\n", estring); arg[0]=YAP_MkAtomTerm(YAP_LookupAtom(cn_prin)); if(debug) printf(" the principal part(%s)\n", cn_prin); arg[1]=YAP_ReadBuffer(estring,eterm); arg[2]=YAP_MkVarTerm(); YAP_Atom f = YAP_LookupAtom("isMember"); YAP_Functor func = YAP_MkFunctor(f, 3); YAP_Term goal=YAP_MkApplTerm(func, 3, arg); int rc =YAP_RunGoal( goal ); if (rc) { printf("YAP query succeed\n"); YAP_WriteBuffer(arg[2], tmp, 5000,YAP_WRITE_HANDLE_VARS); if(debug) printf(" query answer : %s\n", tmp); /* this is returned as ['string1','string2'] */ _credentials_from_string(cred_list,tmp); /**** XXX somehow this got stuck in yap ??? while (YAP_RestartGoal()) { if(debug) printf("another success\n"); YAP_WriteBuffer(arg[2], tmp, 5000,YAP_WRITE_HANDLE_VARS); if(debug) printf(" query answer : %s\n", tmp); _credentials_from_string(cred_list,tmp); } ***/ } else { printf("YAP query failed\n"); /* YAP_Exit(1); */ } return cred_list; } /* 2 types acme.buys_rocket <- coyote (coyote=prin, acme.buys_rocket=role) ==> isMember(coyote,role(acme,buys_rocket), L) acme.buys_rocket <- acme.preferred_customer -- NOT DONE YET */ static abac_stack_t *_query_with_role(abac_pl_t *pl, abac_role_t* role, abac_role_t* role_prin) { char tmp[5000]; abac_stack_t *ret=NULL; if(1) _show_yap_db("DEBUG:calling within _query_with_role"); char *cn_prin=abac_cn_with_role(role_prin); char *cn_role=abac_cn_with_role(role); if(abac_role_role_name(role_prin)!=NULL) { printf("fail, a.r <- b.r query is not implemented yet !!!\n"); YAP_Exit(1); } if (cn_prin == NULL || cn_role == NULL) { printf("fail, query's call got bad roles.. \n"); YAP_Exit(1); } if(debug) printf("printing up the yap query ..\n"); char *pstring=abac_role_role_param_string(role); if(pstring) { sprintf(tmp,"role(%s,%s,%s)", cn_role, abac_role_role_name(role),pstring); free(pstring); } else { sprintf(tmp,"role(%s,%s)", cn_role, abac_role_role_name(role)); } ret=_make_yap_query(cn_prin,cn_role,tmp); return ret; } static abac_stack_t *_query_with_oset(abac_pl_t *pl, abac_oset_t* oset, abac_oset_t* oset_obj) { char tmp[5000]; abac_stack_t *ret=NULL; if(debug) _show_yap_db("DEBUG:calling within _query_with_oset"); char *cn_oset=abac_cn_with_oset(oset); /* could be obj or principal */ char *cn_prin=NULL; if(abac_oset_is_object(oset_obj)) { cn_prin=abac_oset_object_cn(oset_obj); } else { cn_prin=abac_oset_principal_cn(oset_obj); } if(abac_oset_oset_name(oset_obj)!=NULL) { printf("fail, a.o <- b.o query is not implemented yet !!!\n"); YAP_Exit(1); } if (cn_prin == NULL || cn_oset == NULL) { printf("fail, query's call got bad oset.. \n"); YAP_Exit(1); } if(debug) printf("printing up the yap query ..\n"); char *pstring=abac_oset_oset_param_string(oset); if(pstring) { sprintf(tmp,"oset(%s,%s,%s)", cn_oset, abac_oset_oset_name(oset),pstring); free(pstring); } else { sprintf(tmp,"oset(%s,%s)", cn_oset, abac_oset_oset_name(oset)); } ret=_make_yap_query(cn_prin,cn_oset,tmp); return ret; } static abac_stack_t *_dump(abac_pl_t *pl) { YAP_Term *eterm; YAP_Term arg[3]; char tmp[5000]; abac_stack_t *cred_list = abac_stack_new(); if(debug) _show_yap_db("DEBUG:calling within _dump"); arg[0]=YAP_MkVarTerm(); arg[1]=YAP_MkVarTerm(); arg[2]=YAP_MkVarTerm(); YAP_Atom f = YAP_LookupAtom("isMember"); YAP_Functor func = YAP_MkFunctor(f, 3); YAP_Term goal=YAP_MkApplTerm(func, 3, arg); int rc =YAP_RunGoal( goal ); if (rc) { printf("YAP dump succeed\n"); YAP_WriteBuffer(arg[2], tmp, 5000,YAP_WRITE_HANDLE_VARS); if(debug) printf(" dump answer : %s\n", tmp); /* this is returned as ['string1','string2'] */ _credentials_from_string(cred_list,tmp); while (YAP_RestartGoal()) { if(debug) printf("another dump success\n"); YAP_WriteBuffer(arg[2], tmp, 5000,YAP_WRITE_HANDLE_VARS); if(debug) printf(" dump restart answer : %s\n", tmp); _credentials_from_string(cred_list,tmp); } } else { printf("YAP _dump query failed\n"); /* YAP_Exit(1); */ } return cred_list; } /** * Get all the credentials (attribute/issuer cert pairs) from prolog * (which returns in string form) */ abac_stack_t *abac_pl_credentials(abac_pl_t *pl) { abac_stack_t *ret=_dump(pl); return ret; } /** * Make a query into prolog db --role acme.preferred_customer --principal coyote --role acme.prefer_customer.buy_rockets --principlal coyote --oset acme.rockets -- object mrx-21 --oset acme.villans -- principal coyote */ abac_stack_t *abac_pl_query(abac_pl_t *pl, char *roleoset, char *prinobj) { abac_stack_t *ret=NULL; int len=strlen(roleoset)+strlen(prinobj)+5; char* attr_string=(char *) abac_xmalloc(sizeof(char)*len); sprintf(attr_string,"%s<-%s", roleoset, prinobj); if(debug) printf("abac_pl_query, query string is (%s)\n",attr_string); /* call into yacc parser */ abac_reset_yyfptr(attr_string); abac_yyinit(); int rc=yyparse(); if (rc) { free(attr_string); return NULL; } if(abac_get_yap_is_oset()) { abac_oset_t *head_oset = abac_get_yap_head_oset(); abac_oset_t *tail_oset = abac_get_yap_tail_oset(); ret=_query_with_oset(pl,head_oset,tail_oset); } else { abac_role_t *head_role = abac_get_yap_head_role(); abac_role_t *tail_role = abac_get_yap_tail_role(); ret=_query_with_role(pl,head_role,tail_role); } return ret; } void abac_pl_free(abac_pl_t *pl) { if(pl->fptr) { fflush(pl->fptr); free(pl->fptr); } if(pl->fname) { unlink(pl->fname); free(pl->fname); } free(pl); }