/* 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" static int _insert_clause(char*); static void _show_yap_db(char*); extern char *abac_cn_with_role(abac_role_t *); // pl struct _abac_pl_t { FILE *fptr; char *fname; char *yap_certs; }; /** * 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")))) { printf("calling source..\n"); } else { printf("calling source failed..\n"); YAP_Exit(1); } 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 credential pl. */ int abac_pl_add_credential(abac_pl_t *pl, abac_credential_t *cred) { int rc=0; char *str = abac_credential_clause(cred); if (str != NULL) { rc=_insert_clause(str); } _show_yap_db("calling within abac_pl_add_credential"); return rc; } static int _insert_clause(char *cstr) { int ret=ABAC_CERT_SUCCESS; YAP_Term *eterm; YAP_Term goalArgs=YAP_ReadBuffer(cstr, eterm); char *tmp=YAP_CompileClause(goalArgs); if (tmp!=NULL) { /* something is wrong */ printf("error: result of compile clause (%s)\n", tmp); ret=ABAC_CERT_BAD_YAP; } return ret; } static void _show_yap_db(char *msg) { char lstr[]="listing"; YAP_Term *eterm; YAP_Term goal=YAP_ReadBuffer(lstr, eterm); printf("calling listing..from(%s) \n",msg); int rc =YAP_RunGoal( goal ); if (rc) { printf("listing ok.. \n"); } else { printf("listing's rc is bad.. \n"); YAP_Exit(1); } } 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; } static abac_list_t *_linked_query(abac_pl_t *pl, abac_role_t* role, abac_role_t* role_prin ) { abac_list_t *cred_list = abac_list_new(); return cred_list; } static abac_list_t *_intersect_query(abac_pl_t *pl, abac_role_t* role, abac_role_t* role_prin ) { abac_list_t *cred_list = abac_list_new(); return cred_list; } /* cases, ['str'] ['str1','str2'] ([] is not possible, and don't care) */ static void _credentials_from_string(abac_list_t *credentials,char *slist) { char *cptr=slist; /* current ptr */ char *sptr; /* string ptr */ char *ptr; int len=strlen(ptr); char *string; abac_credential_t *cred=NULL; /* 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); printf("string found(%s)\n", string); cred=abac_credential_lookup(string); if(cred) { abac_list_add(credentials, abac_credential_dup(cred)); } else { printf("BAD BAD BAD\n"); } sptr=cptr; } else { ptr=strstr(cptr,"']"); if(ptr!=NULL) { len=ptr-sptr; string=strndup(sptr,len); printf("last string found(%s)\n", string); cred=abac_credential_lookup(string); if(cred) { abac_list_add(credentials, abac_credential_dup(cred)); } else { printf("BAD BAD BAD\n"); } break; } } } } /* 2 types acme.buys_rocket <- coyote acme.buys_rocket <- acme.preferred_customer -- NOT DONE YET */ static abac_list_t *_query(abac_pl_t *pl, abac_role_t* role, abac_role_t* role_prin ) { YAP_Term *eterm; YAP_Term arg[3]; char tmp[1000]; abac_list_t *cred_list = NULL; 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("NOT YET DONE, role_prin is B.R !!!\n"); YAP_Exit(1); } if (cn_prin == NULL || cn_role == NULL) { printf("fail, query's call got bad roles.. \n"); YAP_Exit(1); } sprintf(tmp,"role(%s,%s)", cn_role, abac_role_role_name(role)); arg[0]=YAP_MkAtomTerm(YAP_LookupAtom(cn_prin)); arg[1]=YAP_ReadBuffer(tmp,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) { cred_list = abac_list_new(); printf("success, query call ok.. \n"); YAP_WriteBuffer(arg[2], tmp, 1000,YAP_WRITE_HANDLE_VARS); printf(" answer : %s(%d)\n", tmp, strlen(tmp)); /* this is returned as ['string1','string2'] */ _credentials_from_string(cred_list,tmp); while (YAP_RestartGoal()) { printf("another success\n"); YAP_WriteBuffer(arg[2], tmp, 1000,YAP_WRITE_HANDLE_VARS); printf(" answer : %s\n", tmp); _credentials_from_string(cred_list,tmp); } } else { printf("fail, query's call is bad.. \n"); YAP_Exit(1); } return cred_list; } /** * Make a query into prolog db --role acme.preferred_customer --principal coyote --role acme.prefer_customer.buy_rockets --principlal coyote */ abac_list_t *abac_pl_query(abac_pl_t *pl, char *role_name, char *principal) { abac_role_t *role = abac_role_from_string(role_name); abac_role_t *prin_role = abac_role_from_string(principal); char *query_clause = NULL; abac_list_t *ret=NULL; // give up on bogus roles if (role == NULL || prin_role == NULL) { free(role); free(prin_role); return NULL; } /* should be using yacc */ /* if role->prereqs != NULL (&) */ if (abac_role_is_intersection(role)) { /* XXX */ ret=_intersect_query(pl,role,prin_role); /* prin.role.role1 */ } else if( abac_role_linked_role(role) ) { /* XXX */ ret=_linked_query(pl,role,prin_role); } else { /* prin.role, */ ret=_query(pl,role,prin_role); } return ret; } /** * Get all the credentials (attribute/issuer cert pairs) from prolog * (which returns in string form) */ abac_list_t *abac_pl_credentials(abac_pl_t *pl) { abac_list_t *credentials = abac_list_new(); /* fix up a stream to stream the credentials from prolog engine */ return credentials; } 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); }