/***********************************************************************/ /* 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_internal.h" #include "abac_set.h" #include "abac_util.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 */ char *clause; } abac_id_cert_t; abac_list_t *abac_pl_id_certs = NULL; extern int using_this; extern char* abac_yyfptr_encoded; void generate_pl_set_abac_yyfptr_encoded(char *string) { abac_yyfptr_encoded=abac_xstrdup(string); } char *generate_pl_type_clause(char *principalname, int type); /***********************************************************************/ char *prologIt(char *str) { char *tmp=NULL; asprintf(&tmp,"p%s",str); return tmp; } static char* isX() { static char x_string[2]="X"; static char this_string[5]="This"; if(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->clause); 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() { int first=1; char *tmp=NULL; abac_id_cert_t *cur; abac_list_foreach(abac_pl_id_certs, cur, if(cur) if(first) { tmp=abac_xstrdup(cur->clause); first=0; } else { int cnt=asprintf(&tmp,"%s,%s", tmp, cur->clause); } ); 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; id_cert->clause=generate_pl_type_clause(principalname,type); abac_list_add(abac_pl_id_certs, id_cert); } } /***********************************************************************/ /* generate role(p_name, r_name, param..) */ /* or oset(p_name, r_name, param..) */ 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 ?? */ static char* generate_pl_tail_string(abac_aspect_t *ptr) { char *tmp=NULL; /* 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(Y,role(%s,%s,%s),C%d),isMember(%s,%s(Y,%s,%s),C%d)", principalname, linkedname,linked_param_string,fst, isX(), typestring, aspectname,param_string,snd); free(param_string); } else { cnt=asprintf(&tmp,"isMember(Y,role(%s,%s,%s),C%d),isMember(%s,%s(Y,%s),C%d)", principalname, linkedname,linked_param_string,fst, isX(), typestring, aspectname,snd); } free(linked_param_string); } else { if (aspect_params != NULL) { cnt=asprintf(&tmp,"isMember(Y,role(%s,%s),C%d),isMember(%s,%s(Y,%s,%s),C%d)", principalname, linkedname,fst, isX(),typestring, aspectname,param_string,snd); free(param_string); } else { cnt=asprintf(&tmp,"isMember(Y,role(%s,%s),C%d),isMember(%s,%s(Y,%s),C%d)", principalname, linkedname,fst, isX(),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),C%d)", isX(),typestring, principalname, aspectname, param_string, fst); free(param_string); } else { cnt=asprintf(&tmp,"isMember(%s,%s(%s,%s),C%d)", isX(), 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(char *head_string, char *tail_string) { /*only, 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,C%d)", tail_string,head_string,idx); return tmp; } static char *_build_rule_clause(char *aspectname, char *head_string, char *tail_string, char *id_string, char *constraint_string) { char *tmp=NULL; if(aspectname == NULL) { /* A.R <- B */ if(id_string == NULL && constraint_string == NULL) { asprintf(&tmp, "isMember(%s,%s,['%s'])", tail_string,head_string,abac_yyfptr_encoded); } else { if(id_string == NULL) { asprintf(&tmp, "isMember(%s,%s,['%s']) :- %s", tail_string,head_string,abac_yyfptr_encoded, constraint_string); } else if(constraint_string == NULL) { asprintf(&tmp, "isMember(%s,%s,['%s']) :- %s", tail_string,head_string,abac_yyfptr_encoded, id_string); } else { asprintf(&tmp, "isMember(%s,%s,['%s']) :- %s,%s", tail_string,head_string,abac_yyfptr_encoded, 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", isX(), head_string, abac_yyfptr_encoded, tail_string); } else { if(id_string == NULL) { asprintf(&tmp,"isMember(%s,%s,['%s']):-%s,%s", isX(), head_string, abac_yyfptr_encoded, tail_string, constraint_string); } else if(constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,['%s']):-%s,%s", isX(), head_string, abac_yyfptr_encoded, id_string, tail_string); } else { asprintf(&tmp,"isMember(%s,%s,['%s']):-%s,%s,%s", isX(), head_string, abac_yyfptr_encoded, 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,L):-%s, appendL([['%s'],%s],L)", isX(), head_string, tail_string, abac_yyfptr_encoded, tmp_cred_list); } else { if(id_string == NULL) { asprintf(&tmp,"isMember(%s,%s,L):-%s, %s, appendL([['%s'],%s],L)", isX(), head_string, tail_string, constraint_string, abac_yyfptr_encoded, tmp_cred_list); } else if(constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,L):-%s, %s, appendL([['%s'],%s],L)", isX(), head_string, id_string, tail_string, abac_yyfptr_encoded, tmp_cred_list); } else { asprintf(&tmp,"isMember(%s,%s,L):-%s, %s, %s, appendL([['%s'],%s],L)", isX(), head_string, id_string, tail_string, constraint_string, abac_yyfptr_encoded, tmp_cred_list); } } free(tmp_cred_list); cred_count=0; } } return tmp; } static char *generate_pl_rule_clause(char *head_rule_string, abac_aspect_t *tail_rule, char *id_string, char *constraint_string) { char *aspectname=abac_aspect_aspect_name(tail_rule); char *tail_rule_string=generate_pl_tail_string(tail_rule); if(aspectname == NULL && tail_rule_string == NULL) goto error; char *tmp=_build_rule_clause(aspectname,head_rule_string, tail_rule_string, id_string, constraint_string); 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(char *head_role_string, char *tail_role_string, char* id_string, char* constraint_string) { char *tmp; if (cred_count==0) { if(id_string == NULL && constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,['%s']):-%s", isX(), head_role_string, abac_yyfptr_encoded, tail_role_string); } else { if(id_string == NULL) { asprintf(&tmp,"isMember(%s,%s,['%s']):-%s, %s", isX(), head_role_string, abac_yyfptr_encoded, tail_role_string, constraint_string); } else if(constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,['%s']):-%s, %s", isX(), head_role_string, abac_yyfptr_encoded, id_string, tail_role_string); } else { asprintf(&tmp,"isMember(%s,%s,['%s']):-%s, %s, %s", isX(), head_role_string, abac_yyfptr_encoded, 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,L):-%s, appendL([['%s'],%s],L)", isX(), head_role_string, tail_role_string, abac_yyfptr_encoded, tmp_cred_list); } else { if(id_string == NULL) { asprintf(&tmp,"isMember(%s,%s,L):-%s, %s, appendL([['%s'],%s],L)", isX(), head_role_string, tail_role_string, constraint_string, abac_yyfptr_encoded, tmp_cred_list); } else if(constraint_string == NULL) { asprintf(&tmp,"isMember(%s,%s,L):-%s, %s, appendL([['%s'],%s],L)", isX(), head_role_string, id_string, tail_role_string, abac_yyfptr_encoded, tmp_cred_list); } else { asprintf(&tmp,"isMember(%s,%s,L):-%s, %s, %s, appendL([['%s'],%s],L)", isX(), head_role_string, id_string, tail_role_string, constraint_string, abac_yyfptr_encoded, tmp_cred_list); } } free(tmp_cred_list); cred_count=0; } return tmp; } static char *generate_pl_intersecting_clause(char *head_role_string, abac_aspect_t *tail_role, char* id_string, char* constraint_string) { 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(cur); 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(head_role_string, tail_role_string, id_string,constraint_string); if(tail_role_string) free(tail_role_string); return tmp; } /* generate the prolog isMember rule clause for the credential stmt */ abac_list_t *generate_pl_clauses(abac_aspect_t *head_aspect, abac_aspect_t *tail_aspect) { char *tmp=NULL; char *id_clauses_string=NULL; char *constraint_clauses_string=NULL; abac_list_t *clauses=abac_list_new(); int cnt=abac_pl_cnt_id_certs(); if(cnt > 0) { /* string it up */ id_clauses_string=abac_pl_string_id_certs(); 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(head_string, tail_aspect, id_clauses_string, constraint_clauses_string); } else { tmp=generate_pl_rule_clause(head_string, tail_aspect, id_clauses_string, constraint_clauses_string); } 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; } /* should be just 1 */ char *generate_pl_constraint_clause(abac_aspect_t *head_aspect, char *tail_string) { /* generate head's role or oset string */ char *head_string=generate_pl_head_string(head_aspect); if(head_string == NULL) goto error; /* tail side */ char *tmp=_build_constraint_rule_clause(head_string, tail_string); if(tmp==NULL) goto error; return tmp; error: if(head_string) free(head_string); return NULL; } /* 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(Acme, keyid); */ char *generate_pl_type_clause(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)", principalname, typeid); return tmp; }