/***********************************************************************/ /* clause generation called to generate credential clauses with a */ /* given credential syntax structure (made from parser or from a */ /* pre-existing structure */ /* There are 2 passes, */ /* first pass, process named cred id, and constraint range/role/oset */ /* 2nd pass, process rule left / right */ /***********************************************************************/ #include #include #include #include "abac_pl_gen.h" #include "abac_internal.h" #include "abac_list.h" #include "abac_util.h" #include "abac_context.h" #include "abac_aspect.h" #include "abac_term.h" #include "abac_verifier.h" #include "uthash.h" // index to generate C1,C2.. static int cred_count=0; static int debug=0; int ABAC_IN_PROLOG=0; abac_list_t *abac_pl_constraints=NULL; /* to track id certs within a rule clause */ typedef struct _abac_id_cert_t { char *principalname; int type; /* keyidtype */ } abac_id_cert_t; abac_list_t *abac_pl_id_certs = NULL; static int gg_using_this=0; char* yyfptr_encode=NULL; /* local */ char *generate_pl_type_clause(abac_context_t *,char *, int); /***********************************************************************/ /* this is called by creddy as a shortcut */ int generate_pl_clauses_dump(abac_context_t *ctxt, abac_aspect_t *head_aspect, abac_aspect_t *tail_aspect, char *attr_string, char *encoded_attr_string, char *filename, int using_this) { FILE *out; abac_list_t *clauses = generate_pl_clauses(ctxt,head_aspect, tail_aspect, encoded_attr_string,using_this); int cnt=abac_list_size(clauses); out = fopen(filename, "a+"); char *cur=NULL; fprintf(out,"##########################################\n"); fprintf(out,"## %s <- %s\n", abac_aspect_string_with_condition(head_aspect), abac_aspect_string_with_condition(tail_aspect)); fprintf(out,"## %s\n",attr_string); abac_list_foreach(clauses, cur, fprintf(out,"##\n%s\n",cur); if(cur) free(cur); ); fprintf(out,"\n"); fclose(out); abac_list_free(clauses); return cnt; } /***********************************************************************/ static void _set_yyfptr_encode(char *string) { yyfptr_encode=abac_xstrdup(string); } /***********************************************************************/ static char* isX() { static char x_string[2]="X"; static char this_string[5]="This"; if(gg_using_this) return this_string; else return x_string; } static int _get_next_cred_idx() { cred_count++; return cred_count; } /* remember to free the returned string */ static char *_compose_cred_list() { int i=cred_count; if(cred_count==0) return ""; char *clist=(char *)abac_xmalloc(sizeof(char)*(cred_count)*3); strcpy(clist,"C1"); if (cred_count==1) return clist; i=1; while(i!=cred_count) { i++; sprintf(clist,"%s,C%d",clist,i); } return clist; } /************************************************************************/ /* this is for tracking prolog constraints */ void abac_pl_init_constraints() { abac_pl_constraints = abac_list_new(); } void abac_pl_free_constraints() { char *cur; abac_list_foreach(abac_pl_constraints, cur, if(cur) free(cur); ); abac_list_free(abac_pl_constraints); abac_pl_constraints=NULL; } int abac_pl_cnt_constraints() { return abac_list_size(abac_pl_constraints); } char *abac_pl_string_constraints() { int first=1; char *tmp=NULL; char *final=NULL; char* cur; abac_list_foreach(abac_pl_constraints, cur, if(cur) if(first) { final=abac_xstrdup(cur); first=0; } else { tmp=final; final=NULL; int cnt=asprintf(&final,"%s,%s", tmp, cur); } ); return final; } void abac_pl_add_constraints(char *constraint) { if(abac_pl_constraints == NULL) abac_pl_init_constraints(); char* nptr=abac_xstrdup(constraint); abac_list_add(abac_pl_constraints, nptr); } /************************************************************************/ void abac_pl_init_id_certs() { abac_pl_id_certs = abac_list_new(); } void abac_pl_free_id_certs() { if(abac_pl_id_certs==NULL) return; abac_id_cert_t *id; abac_list_foreach(abac_pl_id_certs, id, if(id) free(id->principalname); free(id); ); abac_list_free(abac_pl_id_certs); abac_pl_id_certs = NULL; } int abac_pl_cnt_id_certs() { return abac_list_size(abac_pl_id_certs); } char *abac_pl_string_id_certs(abac_context_t *ctxt) { char *tmp=NULL; abac_id_cert_t *cur; abac_list_foreach(abac_pl_id_certs, cur, if(cur) if(tmp==NULL) { tmp=generate_pl_type_clause(ctxt,cur->principalname,cur->type); } else { asprintf(&tmp,"%s,%s", tmp, generate_pl_type_clause(ctxt,cur->principalname,cur->type)); } ); return tmp; } void abac_pl_add_id_certs(char *principalname, int type) { abac_id_cert_t *id_cert=NULL; int found=0; abac_id_cert_t *cur; if(debug) { fprintf(stderr,"add_id_certs: adding --> (%s)\n", principalname); } if(abac_pl_id_certs == NULL) { abac_pl_init_id_certs(); } else { abac_list_foreach(abac_pl_id_certs, cur, if(cur) if(strcmp(cur->principalname,principalname)==0) { found=1; break; } ); } if (found) { return; } else { id_cert=abac_xmalloc(sizeof(abac_id_cert_t)); id_cert->principalname=abac_xstrdup(principalname); id_cert->type=type; abac_list_add(abac_pl_id_certs, id_cert); } } /***********************************************************************/ /* generate role(p_name, r_name, param..) */ /* or oset(p_name, r_name, param..) */ /* mainly for aspect that is if A.R <- B format */ static char* generate_pl_head_string(abac_aspect_t *ptr) { char *tmp=NULL; char *principalname; PROLOG(principalname=abac_aspect_principal_name(ptr);); char *aspectname=abac_aspect_aspect_name(ptr); char *typestring=abac_aspect_type_string(ptr); char *param_string=NULL; int cnt=0; /* can not be a linked role */ abac_param_list_t *aspect_params=abac_aspect_aspect_params(ptr); if(aspect_params) { PROLOG(param_string=abac_param_list_string(aspect_params);); } if (param_string != NULL) { cnt=asprintf(&tmp,"%s(%s,%s,%s)", typestring, principalname, aspectname, param_string); free(param_string); } else { cnt=asprintf(&tmp,"%s(%s,%s)", typestring, principalname, aspectname); } if(debug && tmp) fprintf(stderr,"generate_pl_head_string: (%s)\n",tmp); if(cnt>0) return tmp; else return NULL; } /* generate role(p_name, r_name, param..) with isMember call ?? */ /* generate oset(p_name, r_name, param..) with isMember call ?? */ /* for aspect that could also be with linked role */ static char* generate_pl_tail_string(abac_context_t *ctxt,abac_aspect_t *ptr, char *varX) { char *tmp=NULL; char *namespace=abac_context_namespace(ctxt); /* for oset case, A.oset <- B A.oset <- Obj A.oset <- B.oset A.oset <- B.role.oset */ /* o only if it is an oset and object */ if(abac_aspect_is_object(ptr)) { char *objectname=abac_aspect_object_name(ptr); tmp=abac_xstrdup(objectname); return tmp; } else { char *principalname; PROLOG(principalname=abac_aspect_principal_name(ptr);); char *aspectname=abac_aspect_aspect_name(ptr); char *linkedname=abac_aspect_linked_role_name(ptr); char *typestring=abac_aspect_type_string(ptr); char *param_string=NULL; char *linked_param_string=NULL; int cnt=0; abac_param_list_t *aspect_params=abac_aspect_aspect_params(ptr); if(aspect_params) { PROLOG(param_string=abac_param_list_string(aspect_params);); } abac_param_list_t *linked_role_params=abac_aspect_linked_role_params(ptr); if(linked_role_params) { PROLOG(linked_param_string=abac_param_list_string(linked_role_params);); } /* b.r.r */ if(linkedname!=NULL && aspectname!=NULL && principalname!=NULL ) { int fst=_get_next_cred_idx(); int snd=_get_next_cred_idx(); if(linked_param_string !=NULL) { if (param_string != NULL) { cnt=asprintf(&tmp,"isMember(%s,Y,role(%s,%s,%s),C%d),isMember(%s,%s,%s(Y,%s,%s),C%d)", namespace, principalname, linkedname,linked_param_string,fst, namespace,varX, typestring, aspectname,param_string,snd); free(param_string); } else { cnt=asprintf(&tmp,"isMember(%s,Y,role(%s,%s,%s),C%d),isMember(%s,%s,%s(Y,%s),C%d)", namespace, principalname, linkedname,linked_param_string,fst, namespace, varX, typestring, aspectname,snd); } free(linked_param_string); } else { if (aspect_params != NULL) { cnt=asprintf(&tmp,"isMember(%s,Y,role(%s,%s),C%d),isMember(%s,%s,%s(Y,%s,%s),C%d)", namespace, principalname,linkedname,fst, namespace, varX,typestring, aspectname,param_string,snd); free(param_string); } else { cnt=asprintf(&tmp,"isMember(%s,Y,role(%s,%s),C%d),isMember(%s,%s,%s(Y,%s),C%d)", namespace, principalname, linkedname,fst, namespace, varX,typestring, aspectname,snd); } } if(cnt>0) return tmp; else return NULL; } /* b.r */ if(linkedname==NULL && aspectname!=NULL && principalname!=NULL ) { int fst=_get_next_cred_idx(); if(param_string != NULL) { cnt=asprintf(&tmp,"isMember(%s,%s,%s(%s,%s,%s),C%d)", namespace,varX,typestring, principalname, aspectname, param_string, fst); free(param_string); } else { cnt=asprintf(&tmp,"isMember(%s,%s,%s(%s,%s),C%d)", namespace,varX, typestring, principalname, aspectname, fst); } if(cnt>0) return tmp; else return NULL; } /* b */ if(linkedname==NULL && aspectname==NULL && principalname!=NULL ) { tmp=abac_xstrdup(principalname); return tmp; } return tmp; } return tmp; } /********************************************************************************/ static char *_build_constraint_rule_clause(abac_context_t *ctxt,char *head_string, char *tail_string) { /*for A.R <- B */ if(debug) fprintf(stderr,"calling _build_constraint_rule_clause (%s)(%s)\n", head_string, tail_string); char *tmp; int idx=_get_next_cred_idx(); asprintf(&tmp, "isMember(%s,%s,%s,C%d)", abac_context_namespace(ctxt),tail_string,head_string,idx); return tmp; } static char *_build_rule_clause(abac_context_t *ctxt, char *aspectname, char *head_string, char *tail_string, char *id_string, char *constraint_string, char *varX) { char *tmp=NULL; char *namespace=abac_context_namespace(ctxt); if(aspectname == NULL) { /* A.R <- B */ if(id_string == NULL && constraint_string == NULL) { asprintf(&tmp, "isMember(%s,%s,%s,['%s'])", namespace, tail_string,head_string,yyfptr_encode); } else { if(id_string == NULL) { asprintf(&tmp, "isMember(%s,%s,%s,['%s']) :- %s", namespace, tail_string,head_string,yyfptr_encode, constraint_string); } else if(constraint_string == NULL) { asprintf(&tmp, "isMember(%s,%s,%s,['%s']) :- %s", namespace, tail_string,head_string,yyfptr_encode, id_string); } else { asprintf(&tmp, "isMember(%s,%s,%s,['%s']) :- %s,%s", namespace, tail_string,head_string,yyfptr_encode, id_string, constraint_string); } } } else { /* A.R <- B.R */ /* A.R <- B.R.R */ if (cred_count==0) { if(id_string == NULL && constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,['%s']):-%s", namespace,varX, head_string, yyfptr_encode, tail_string); } else { if(id_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,['%s']):-%s,%s", namespace,varX, head_string, yyfptr_encode, tail_string, constraint_string); } else if(constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,['%s']):-%s,%s", namespace,varX, head_string, yyfptr_encode, id_string, tail_string); } else { asprintf(&tmp,"isMember(%s,%s,%s,['%s']):-%s,%s,%s", namespace,varX, head_string, yyfptr_encode, id_string, tail_string, constraint_string); } } } else { char *tmp_cred_list=_compose_cred_list(); if(id_string == NULL && constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,L):-%s, appendL([['%s'],%s],L)", namespace,varX, head_string, tail_string, yyfptr_encode, tmp_cred_list); } else { if(id_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,L):-%s, %s, appendL([['%s'],%s],L)", namespace,varX, head_string, tail_string, constraint_string, yyfptr_encode, tmp_cred_list); } else if(constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,L):-%s, %s, appendL([['%s'],%s],L)", namespace,varX, head_string, id_string, tail_string, yyfptr_encode, tmp_cred_list); } else { asprintf(&tmp,"isMember(%s,%s,%s,L):-%s, %s, %s, appendL([['%s'],%s],L)", namespace,varX, head_string, id_string, tail_string, constraint_string, yyfptr_encode, tmp_cred_list); } } free(tmp_cred_list); cred_count=0; } } return tmp; } static char *generate_pl_rule_clause(abac_context_t *ctxt,char *head_rule_string, abac_aspect_t *tail_rule, char *id_string, char *constraint_string, char* varX) { char *aspectname=abac_aspect_aspect_name(tail_rule); char *tail_rule_string=generate_pl_tail_string(ctxt,tail_rule,varX); if(aspectname == NULL && tail_rule_string == NULL) goto error; char *tmp=_build_rule_clause(ctxt,aspectname, head_rule_string, tail_rule_string, id_string, constraint_string, varX); if(tail_rule_string) free(tail_rule_string); return tmp; error: if(tail_rule_string) free(tail_rule_string); return NULL; } static char *_add_string(char *dstr, char *nstr) { if(strlen(dstr)==0) { dstr=abac_xstrdup(nstr); return dstr; } else { int len = strlen(dstr)+strlen(nstr)+2; char *tmp=abac_xmalloc(len*sizeof(char)); sprintf(tmp,"%s,%s", dstr,nstr); free(dstr); return tmp; } return NULL; } static char *_build_intersecting_clause(abac_context_t *ctxt, char *head_role_string, char *tail_role_string, char* id_string, char* constraint_string,char *varX) { char *tmp; char *namespace=abac_context_namespace(ctxt); if (cred_count==0) { if(id_string == NULL && constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,['%s']):-%s", namespace,varX, head_role_string, yyfptr_encode, tail_role_string); } else { if(id_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,['%s']):-%s, %s", namespace,varX, head_role_string, yyfptr_encode, tail_role_string, constraint_string); } else if(constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,['%s']):-%s, %s", namespace,varX, head_role_string, yyfptr_encode, id_string, tail_role_string); } else { asprintf(&tmp,"isMember(%s,%s,%s,['%s']):-%s, %s, %s", namespace,varX, head_role_string, yyfptr_encode, id_string, tail_role_string, constraint_string); } } } else { char *tmp_cred_list=_compose_cred_list(); if(id_string == NULL && constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,L):-%s, appendL([['%s'],%s],L)", namespace,varX, head_role_string, tail_role_string, yyfptr_encode, tmp_cred_list); } else { if(id_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,L):-%s, %s, appendL([['%s'],%s],L)", namespace,varX, head_role_string, tail_role_string, constraint_string, yyfptr_encode, tmp_cred_list); } else if(constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,%s,L):-%s, %s, appendL([['%s'],%s],L)", namespace,varX, head_role_string, id_string, tail_role_string, yyfptr_encode, tmp_cred_list); } else { asprintf(&tmp,"isMember(%s,%s,%s,L):-%s, %s, %s, appendL([['%s'],%s],L)", namespace,varX, head_role_string, id_string, tail_role_string, constraint_string, yyfptr_encode, tmp_cred_list); } } free(tmp_cred_list); cred_count=0; } return tmp; } static char *generate_pl_intersecting_clause(abac_context_t *ctxt, char *head_role_string, abac_aspect_t *tail_role, char* id_string, char* constraint_string, char *varX) { char *tmp=NULL; char* tail_role_string=NULL; abac_list_t *list=abac_aspect_prereqs(tail_role); /* A.R <- B.R & C.R.R */ /* A.O <- B.O & C.R.O */ if (list != NULL) { abac_aspect_t *cur; abac_list_foreach(list, cur, char *ntmp=generate_pl_tail_string(ctxt,cur,varX); if(debug) fprintf(stderr," intersecting tail: (%s)\n",ntmp); if(tail_role_string==NULL) { tail_role_string=abac_xstrdup(ntmp); } else { tmp=tail_role_string; tail_role_string=NULL; asprintf(&tail_role_string,"%s, %s",tmp,ntmp); free(tmp); } free(ntmp); ); } if(debug) fprintf(stderr," final intersecting tail: (%s)\n",tail_role_string); tmp=_build_intersecting_clause(ctxt,head_role_string, tail_role_string, id_string,constraint_string, varX); if(tail_role_string) free(tail_role_string); return tmp; } /**** THIS NEEDS TO BE LOCKED *****/ /* XXXX */ /* generate the prolog isMember rule clause for the credential stmt */ abac_list_t *generate_pl_clauses(abac_context_t *ctxt,abac_aspect_t *head_aspect, abac_aspect_t *tail_aspect,char *encoded_attr_string, int using_this) { char *tmp=NULL; char *id_clauses_string=NULL; char *constraint_clauses_string=NULL; abac_list_t *clauses=abac_list_new(); gg_using_this=using_this; if(encoded_attr_string!=NULL) _set_yyfptr_encode(encoded_attr_string); /* preprocess both sides first */ preprocess_pl_head(ctxt,head_aspect); preprocess_pl_tail(ctxt,tail_aspect); int cnt=abac_pl_cnt_id_certs(); if(cnt > 0) { /* string it up */ id_clauses_string=abac_pl_string_id_certs(ctxt); abac_pl_free_id_certs(); } /* make a loop here */ cnt=abac_pl_cnt_constraints(); if(cnt > 0) { constraint_clauses_string=abac_pl_string_constraints(); abac_pl_free_constraints(); } /* generate head's string */ char *head_string=generate_pl_head_string(head_aspect); if(head_string == NULL) goto error; /* tail side */ if(abac_aspect_is_intersection(tail_aspect)) { tmp=generate_pl_intersecting_clause(ctxt,head_string, tail_aspect, id_clauses_string, constraint_clauses_string, isX()); } else { tmp=generate_pl_rule_clause(ctxt,head_string, tail_aspect, id_clauses_string, constraint_clauses_string, isX()); } if(tmp==NULL) goto error; abac_list_add(clauses,tmp); return clauses; error: if(head_string) free(head_string); if(id_clauses_string) free(id_clauses_string); if(constraint_clauses_string) free(constraint_clauses_string); return clauses; } char *generate_pl_constraint_clause(abac_context_t *ctxt,abac_aspect_t *head_aspect, char *tail_string) { char *tmp=NULL; char *head_string=NULL; if(abac_aspect_is_linking(head_aspect)) { /* leverage on its b.r.r gen code */ tmp= generate_pl_tail_string(ctxt,head_aspect,tail_string); } else { /* generate head's role or oset string */ char *head_string=generate_pl_head_string(head_aspect); if(head_string == NULL) goto error; /* tail side */ tmp=_build_constraint_rule_clause(ctxt,head_string, tail_string); if(tmp==NULL) goto error; if(head_string) free(head_string); } error: if(head_string) free(head_string); return tmp; } /* integer(X)<10 */ /* X='abc' */ char *generate_pl_range_constraint(char *typestr,char *var,char *val,char *op) { char *tmp=NULL; if(typestr) asprintf(&tmp,"%s(%s)%s%s",typestr,var,op,val); else asprintf(&tmp,"%s%s%s",var,op,val); return tmp; } /* compare(op,var,val) */ char *generate_pl_range_time_constraint(char *var,char *val,char *op) { char *tmp=NULL; asprintf(&tmp,"compare(%s,%s,%s)",op,var,val); return tmp; } /* generate the prolog isType rule clause for the type, isType(namespace,Acme, keyid); */ char *generate_pl_type_clause(abac_context_t *ctxt,char *principalname, int type) { char *tmp=NULL; char *typeid= abac_idtype_string(type); if(typeid==NULL || strcmp(typeid,"NULL")==0) panic("generate_pl_type_clause: can not have null typeid"); if(debug) fprintf(stderr,"generate type clause, (%s)\n", principalname); int cnt=asprintf(&tmp,"isType(%s,%s,%s)", abac_context_namespace(ctxt),principalname, typeid); return tmp; }