/** ** abac_aspect.c **/ #include #include "abac_defines.h" #include "abac_util.h" #include "abac_term.h" #include "abac_verifier.h" #include "abac_list.h" #include "abac_context.h" #include "abac_id.h" static int debug=0; extern int ABAC_IN_PROLOG; /* A.role <- B A.role <- B.role A.role <- B.role.role A.oset <- B A.oset <- Obj A.oset <- B.oset A.oset <- B.role.oset */ /* can store either a role or oset */ struct _abac_aspect_t { int aspect_type; int is_object; char *principal_name; char *principal_name_p; // pPrincipal_name abac_term_t *principal_object; char *linked_role_name; abac_param_list_t *linked_role_params; char *aspect_name; abac_param_list_t *aspect_params; char *type_string; // "oset" or "role" abac_list_t *prereqs; int refcount; }; /* local */ char *abac_aspect_string_with_condition(abac_aspect_t *); char *abac_aspect_typed_string_with_condition(abac_aspect_t *); static abac_aspect_t *_abac_aspect_init(); /**************************************************************/ int abac_aspect_is_oset(abac_aspect_t *ptr) { assert(ptr); if(ptr->aspect_type == e_ASPECTTYPE_OSET) return 1; return 0; } int abac_aspect_is_role(abac_aspect_t *ptr) { assert(ptr); if(ptr->aspect_type==e_ASPECTTYPE_ROLE) return 1; return 0; } int abac_aspect_is_intersecting(abac_aspect_t *ptr) { assert(ptr); if(ptr->aspect_type == e_ASPECTTYPE_INTERSECTING) return 1; else return 0; } /* A.role->B or A.oset->B */ int abac_aspect_is_principal(abac_aspect_t *ptr) { assert(ptr != NULL); return ptr->is_object == 0 && ptr->aspect_name == NULL && ptr->linked_role_name == NULL && ptr->prereqs == NULL; } /* A.oset->O */ int abac_aspect_is_object(abac_aspect_t *ptr) { assert(ptr); if(ptr->aspect_type == e_ASPECTTYPE_OSET) return ptr->is_object; return 0; } /* A.role->B.role.role or A.oset->B.role.oset */ int abac_aspect_is_linking(abac_aspect_t *ptr) { assert(ptr); return ptr->linked_role_name != NULL; } /** * True if an aspect is an intersection. */ int abac_aspect_is_intersection(abac_aspect_t *ptr) { assert(ptr); return ptr->prereqs != NULL; } /** * return the type that is common to all the intersecting aspects */ int abac_aspect_intersecting_aspect_type(abac_aspect_t *ptr) { assert(ptr); assert(ptr->prereqs); abac_aspect_t *cur; int first=1; int type; abac_list_foreach(ptr->prereqs, cur, if(first) { type=abac_aspect_aspect_type(cur); first=0; } else { if(abac_aspect_aspect_type(cur) != type) errx(1,"Intersecting tails are not of the same type"); } ); return type; } /** * Returns the prereqs of an intersection. */ abac_list_t *abac_aspect_prereqs(abac_aspect_t *ptr) { assert(ptr); return ptr->prereqs; } char* abac_aspect_type_string(abac_aspect_t *ptr) { assert(ptr); return ptr->type_string; } int abac_aspect_aspect_type(abac_aspect_t *ptr) { assert(ptr); return ptr->aspect_type; } /** * Returns the linked part of a linking aspect. * For instance, if the aspect is A.r1.r2, this returns r1. */ char *abac_aspect_linked_role_name(abac_aspect_t *ptr) { assert(ptr); return ptr->linked_role_name; } /* A.r1 without params or constraints, callee needs to free it*/ char *abac_aspect_linked_role_bare(abac_aspect_t *ptr) { assert(ptr); assert(ptr->principal_name); assert(ptr->linked_role_name); char *tmp=NULL; asprintf(&tmp,"%s.%s",ptr->principal_name,ptr->linked_role_name); return tmp; } abac_param_list_t *abac_aspect_linked_role_params(abac_aspect_t *ptr) { assert(ptr); return ptr->linked_role_params; } /** * Returns the name of an aspect. If the aspect is A.r1 then return r1. * If the aspect is A.r1.r2 then return r2. */ char *abac_aspect_aspect_name(abac_aspect_t *ptr) { assert(ptr); return ptr->aspect_name; } abac_param_list_t *abac_aspect_aspect_params(abac_aspect_t *ptr) { assert(ptr); return ptr->aspect_params; } /** * Returns the principal part of an aspect. The stuff before the first dot. */ char *abac_aspect_principal_name(abac_aspect_t *ptr) { assert(ptr); if(USE("ABAC_CN")) return abac_cn_with_sha(ptr->principal_name); if(ABAC_IN_PROLOG) { return ptr->principal_name_p; } else return ptr->principal_name; } char *abac_aspect_principal_principalname(abac_aspect_t *ptr) { assert(ptr); if(ABAC_IN_PROLOG) return ptr->principal_name_p; return ptr->principal_name; } char *abac_aspect_principal_type(abac_aspect_t *ptr) { assert(ptr); return abac_idtype_with_sha(ptr->principal_name); } char *abac_aspect_principal_cn(abac_aspect_t *ptr) { assert(ptr); return abac_cn_with_sha(ptr->principal_name); } abac_term_t *abac_aspect_object_term(abac_aspect_t *ptr) { return ptr->principal_object; } char *abac_aspect_object_name(abac_aspect_t *ptr) { assert(ptr); assert(ptr->is_object); abac_term_t *obj=ptr->principal_object; return abac_term_name(obj); } int _abac_aspect_object_is_time_type(abac_aspect_t *ptr) { abac_term_t *obj=ptr->principal_object; return abac_term_is_time_type(obj); } char *abac_aspect_object_type(abac_aspect_t *ptr) { assert(ptr); assert(ptr->is_object); abac_term_t *obj=ptr->principal_object; char *tmp=abac_term_type_name(obj); if(debug) fprintf(stderr,"abac_aspect_object_type: checking on object type, %s\n",tmp); return tmp; } abac_condition_t *abac_aspect_object_constraint(abac_aspect_t *ptr) { assert(ptr != NULL); assert(ptr->is_object); abac_term_t *obj=ptr->principal_object; return abac_term_constraint(obj); } /* currently the issuer's id is extracted from session's master copy instead of checking through context's list first This might allow some loopholes of incomplete validation somewhere.. need to revisit again XXX */ char* abac_aspect_get_issuer_keytype(abac_aspect_t *ptr) { abac_id_t *issuer_id=NULL; char *principalname=abac_aspect_principal_principalname(ptr); if(principalname) { abac_id_credential_t *id_cred=abac_id_credential_lookup(principalname); if(id_cred) { issuer_id=abac_id_credential_id(id_cred); return abac_id_keyid(issuer_id); } } return NULL; } int abac_aspect_get_issuer_idtype(abac_aspect_t *ptr) { abac_id_t *issuer_id=NULL; char *principalname=abac_aspect_principal_principalname(ptr); if(principalname) { abac_id_credential_t *id_cred=abac_id_credential_lookup(principalname); if(id_cred) { issuer_id=abac_id_credential_id(id_cred); return abac_id_idtype(issuer_id); } } return 0; } abac_id_t *abac_aspect_get_issuer_id(abac_aspect_t *ptr) { abac_id_t *issuer_id=NULL; char *principalname=abac_aspect_principal_principalname(ptr); if(principalname) { abac_id_credential_t *id_cred=abac_id_credential_lookup(principalname); if(id_cred) { issuer_id=abac_id_credential_id(id_cred); } } return issuer_id; } /** * deep copy of aspect */ abac_aspect_t *abac_aspect_copy(abac_aspect_t *ptr) { if(ptr == NULL) return NULL; abac_aspect_t *nptr=_abac_aspect_init(); nptr->aspect_type=ptr->aspect_type; nptr->is_object=ptr->is_object; if(ptr->principal_name) nptr->principal_name=abac_xstrdup(ptr->principal_name); if(ptr->principal_name_p) nptr->principal_name_p=abac_xstrdup(ptr->principal_name_p); if(ptr->principal_object) nptr->principal_object=abac_term_copy(ptr->principal_object); if(ptr->linked_role_name) nptr->linked_role_name=abac_xstrdup(ptr->linked_role_name); nptr->linked_role_params=abac_param_list_copy(ptr->linked_role_params); if(ptr->aspect_name) nptr->aspect_name=abac_xstrdup(ptr->aspect_name); nptr->aspect_params=abac_param_list_copy(ptr->aspect_params); if(ptr->type_string) nptr->type_string=abac_xstrdup(ptr->type_string); if (ptr->prereqs != NULL) { nptr->prereqs=abac_list_new(); abac_aspect_t *cur=NULL; abac_aspect_t *ncur=NULL; abac_list_foreach(ptr->prereqs, cur, ncur=abac_aspect_copy(cur); abac_list_add(nptr->prereqs,ncur); ); } return nptr; } /** * Increase a aspect's reference count. */ abac_aspect_t *abac_aspect_dup(abac_aspect_t *ptr) { assert(ptr != NULL); ++ptr->refcount; return ptr; } /** * Decrease an aspect's reference count, freeing it when it reaches 0. */ void abac_aspect_free(abac_aspect_t *ptr) { if(debug) { if(ptr->aspect_name) fprintf(stderr,"DEBUG:trying to freeing an aspect loc(%ld)(%s:%d)\n",(long)ptr, ptr->aspect_name, ptr->refcount); else fprintf(stderr,"DEBUG:trying to freeing an aspect loc(%ld)(M:%d)\n",(long)ptr,ptr->refcount); } assert(ptr); --ptr->refcount; if (ptr->refcount > 0) return; if(debug) { if(ptr->aspect_name) fprintf(stderr,"DEBUG:freeing this aspect loc(%ld)(%s:%d)\n",(long)ptr, ptr->aspect_name, ptr->refcount); else fprintf(stderr,"DEBUG:freeing this aspect loc(%ld)(M:%d)\n",(long)ptr, ptr->refcount); } if(ptr->principal_name) free(ptr->principal_name); if(ptr->principal_name_p) free(ptr->principal_name_p); if(ptr->linked_role_name) free(ptr->linked_role_name); if(ptr->aspect_name) free(ptr->aspect_name); if(ptr->type_string) free(ptr->type_string); if (ptr->aspect_params != NULL) { abac_param_list_free(ptr->aspect_params); } if (ptr->linked_role_params != NULL) { abac_param_list_free(ptr->linked_role_params); } if (ptr->prereqs != NULL) { abac_aspect_t *cur=NULL; abac_list_foreach(ptr->prereqs, cur, abac_aspect_free(cur); ); abac_list_free(ptr->prereqs); } free(ptr); } /**********************************************************************/ void abac_aspect_add_param(abac_aspect_t *ptr, abac_term_t *param) { if(ptr->aspect_params == NULL) { ptr->aspect_params=abac_param_list_new(param); } else { abac_param_list_add_term(ptr->aspect_params, param); } } void abac_aspect_add_intersecting_aspect(abac_aspect_t *ptr, abac_aspect_t *aspect) { abac_list_add(ptr->prereqs, abac_aspect_dup(aspect)); } void abac_aspect_add_linked_param(abac_aspect_t *ptr, abac_term_t *param) { if(ptr->linked_role_params == NULL) { ptr->linked_role_params=abac_param_list_new(param); } else { abac_param_list_add_term(ptr->linked_role_params, param); } } /**********************************************************************/ /** * Create a new principal and initialize it. * always with the proper SHA string */ static abac_aspect_t *_abac_aspect_init() { abac_aspect_t *ptr = (abac_aspect_t *) abac_xmalloc(sizeof(abac_aspect_t)); ptr->aspect_type=e_ASPECTTYPE_NULL; ptr->is_object=0; ptr->principal_name = NULL; ptr->principal_name_p = NULL; ptr->principal_object = NULL; ptr->aspect_name = NULL; ptr->aspect_params = NULL; ptr->linked_role_name = NULL; ptr->linked_role_params = NULL; ptr->type_string=NULL; ptr->prereqs = NULL; ptr->refcount = 1; } abac_aspect_t *abac_aspect_principal_new(int type, char *principal_name) { assert(principal_name != NULL); if (strlen(principal_name) == 0) return NULL; /* XXX currently, it might be good if the principal_name is used o lookup the hashed id table and somehow link to the ID that it belongs too, currently, we check it later.. */ abac_aspect_t *ptr = _abac_aspect_init(); ptr->aspect_type=type; ptr->principal_name = abac_xstrdup(principal_name); ptr->principal_name_p = prologIt(principal_name); if(type==e_ASPECTTYPE_ROLE) ptr->type_string=abac_xstrdup("role"); if(type==e_ASPECTTYPE_OSET) ptr->type_string=abac_xstrdup("oset"); return ptr; } abac_aspect_t *abac_aspect_role_principal_new(char *principal_name) { return abac_aspect_principal_new(e_ASPECTTYPE_ROLE,principal_name); } abac_aspect_t *abac_aspect_role_principal_create(char *principal_name) { return abac_aspect_principal_new(e_ASPECTTYPE_ROLE,principal_name); } abac_aspect_t *abac_aspect_oset_principal_new(char *principal_name) { return abac_aspect_principal_new(e_ASPECTTYPE_OSET,principal_name); } abac_aspect_t *abac_aspect_oset_principal_create(char *principal_name) { return abac_aspect_principal_new(e_ASPECTTYPE_OSET,principal_name); } abac_aspect_t *abac_aspect_object_new(int type, abac_term_t *object) { assert(object != NULL); abac_aspect_t *ptr = _abac_aspect_init(); ptr->aspect_type=type; ptr->is_object =1; ptr->principal_object = object; /* can not be role type */ if(type==e_ASPECTTYPE_OSET) ptr->type_string=abac_xstrdup("oset"); return ptr; } abac_aspect_t *abac_aspect_oset_object_new(abac_term_t *object) { return abac_aspect_object_new(e_ASPECTTYPE_OSET, object); } abac_aspect_t *abac_aspect_oset_object_create(abac_term_t *object) { return abac_aspect_object_new(e_ASPECTTYPE_OSET,object); } abac_aspect_t *abac_aspect_new(int type, char *principal_name, char *aspect_name) { assert(principal_name != NULL); assert(aspect_name != NULL); if (strlen(principal_name) == 0 || strlen(aspect_name) == 0) return NULL; abac_aspect_t *ptr = _abac_aspect_init(); ptr->principal_name = abac_xstrdup(principal_name); ptr->principal_name_p = prologIt(principal_name); ptr->aspect_type=type; ptr->aspect_name = abac_xstrdup(aspect_name); if(type==e_ASPECTTYPE_OSET) ptr->type_string= abac_xstrdup("oset"); else ptr->type_string= abac_xstrdup("role"); if(debug) fprintf(stderr,"abac_aspect_new:adding a new aspect type(%d) (%s) to principal (%s)\n", type, ptr->aspect_name, ptr->principal_name); return ptr; } abac_aspect_t *abac_aspect_oset_new(char *principal_name, char *oset_name) { return abac_aspect_new(e_ASPECTTYPE_OSET,principal_name, oset_name); } abac_aspect_t *abac_aspect_oset_create(char *principal_name, char *oset_name) { return abac_aspect_new(e_ASPECTTYPE_OSET,principal_name,oset_name); } abac_aspect_t *abac_aspect_role_new(char *principal_name, char *oset_name) { return abac_aspect_new(e_ASPECTTYPE_ROLE,principal_name, oset_name); } abac_aspect_t *abac_aspect_role_create(char *principal_name, char *role_name) { return abac_aspect_new(e_ASPECTTYPE_ROLE,principal_name,role_name); } /** * Created a new linking role/oset and initialize it. */ abac_aspect_t *abac_aspect_linking_new(int type, char *principal_name, char *linked_role_name, char *aspect_name) { assert(principal_name != NULL); assert(linked_role_name != NULL); assert(aspect_name != NULL); if (strlen(principal_name) == 0 || strlen(linked_role_name) == 0 || strlen(aspect_name) == 0) return NULL; abac_aspect_t *ptr = _abac_aspect_init(); ptr->is_object=0; ptr->aspect_type=type; ptr->principal_name = abac_xstrdup(principal_name); ptr->principal_name_p = prologIt(principal_name); ptr->linked_role_name = abac_xstrdup(linked_role_name); ptr->aspect_name = abac_xstrdup(aspect_name); if(debug) fprintf(stderr,"DEBUG:adding a new linked (%s) to oset/role(%s) for principal(%s)\n", ptr->linked_role_name, ptr->aspect_name, ptr->principal_name); if(type==e_ASPECTTYPE_OSET) ptr->type_string=abac_xstrdup("oset"); else ptr->type_string=abac_xstrdup("role"); return ptr; } abac_aspect_t *abac_aspect_role_linking_new(char *principal_name, char *linked_role_name, char *role_name) { return abac_aspect_linking_new(e_ASPECTTYPE_ROLE, principal_name, linked_role_name, role_name); } abac_aspect_t *abac_aspect_oset_linking_new(char *principal_name, char *linked_role_name, char *oset_name) { return abac_aspect_linking_new(e_ASPECTTYPE_OSET, principal_name, linked_role_name, oset_name); } /** * Create an intersection oset/role. */ abac_aspect_t *abac_aspect_intersection_new(abac_aspect_t *aspect) { abac_aspect_t *ptr = _abac_aspect_init(); ptr->aspect_type=e_ASPECTTYPE_INTERSECTING; abac_list_t *prereqs = abac_list_new(); abac_list_add(prereqs, abac_aspect_dup(aspect)); ptr->prereqs = prereqs; return ptr; } /*******************************************************************/ char *abac_aspect_intersecting_string_with_condition(int typed,abac_aspect_t *ptr) { assert(ptr != NULL); char *tmp=NULL; if (ptr->prereqs != NULL) { abac_aspect_t *cur; abac_list_foreach(ptr->prereqs, cur, char *ntmp=NULL; if(typed) ntmp=abac_aspect_typed_string_with_condition(cur); else ntmp=abac_aspect_string_with_condition(cur); if(tmp==NULL) { asprintf(&tmp,"%s",ntmp); } else { asprintf(&tmp,"%s & %s",tmp, ntmp); } ); } return tmp; } /** * Returns the string representation of the role/oset. * principal.osetname(params..) * principal.rolename(params..) */ char *abac_aspect_string_with_condition(abac_aspect_t *ptr) { assert(ptr != NULL); if(abac_aspect_is_intersection(ptr)) { return abac_aspect_intersecting_string_with_condition(0,ptr); } char *tmp=NULL; char *principal_name; if(abac_aspect_is_object(ptr)) { principal_name = abac_aspect_object_name(ptr); if(_abac_aspect_object_is_time_type(ptr)) principal_name=abac_time_to_term(principal_name); } else principal_name = abac_aspect_principal_name(ptr); char *aspect_name= ptr->aspect_name; char *linked_role_name = ptr->linked_role_name; char *params_string=NULL; char *linked_params_string=NULL; int len = 0; if(principal_name) len=len+strlen(principal_name)+1; if(aspect_name) len = len+strlen(aspect_name)+1; if(linked_role_name) len = len+strlen(linked_role_name)+1; if(ptr->aspect_params) { params_string=abac_param_list_string_with_condition(ptr->aspect_params); len = len+strlen(params_string)+3; } if(ptr->linked_role_params) { linked_params_string=abac_param_list_string_with_condition(ptr->linked_role_params); len = len+strlen(linked_params_string)+3; } /* principal */ /* principal.oset/role */ /* principal.oset/role(params_string) */ /* principal.linked_role(linked_params_string).oset/role(params_string) */ tmp = abac_xmalloc(len); if(principal_name) sprintf(tmp,"%s",principal_name); if(linked_role_name) { strcat(tmp,"."); strcat(tmp,linked_role_name); } if(linked_params_string) { strcat(tmp,"("); strcat(tmp,linked_params_string); strcat(tmp,")"); } if(aspect_name) { strcat(tmp,"."); strcat(tmp,aspect_name); } if(params_string) { strcat(tmp,"("); strcat(tmp,params_string); strcat(tmp,")"); } if(linked_params_string) free(linked_params_string); if(params_string) free(params_string); return tmp; } char *abac_aspect_string(abac_aspect_t *ptr) { return abac_aspect_string_with_condition(ptr); } char *abac_aspect_typed_string(abac_aspect_t *ptr) { return abac_aspect_typed_string_with_condition(ptr); } void abac_print_aspect_string_with_condition(abac_aspect_t *ptr,FILE *fp) { char *string=abac_aspect_string_with_condition(ptr); if(fp==NULL) printf("%s ",string); else fprintf(fp,"%s ",string); } void abac_print_aspect_typed_string_with_condition(abac_aspect_t *ptr,FILE *fp) { char *string=abac_aspect_typed_string_with_condition(ptr); if(fp==NULL) printf("%s ",string); else fprintf(fp,"%s ",string); } int abac_aspect_aspect_param_cnt(abac_aspect_t *ptr) { if(ptr->aspect_params) { return abac_param_list_cnt(ptr->aspect_params); } return 0; } char *abac_aspect_aspect_param_string(abac_aspect_t *ptr) { assert(ptr != NULL); if(ptr->aspect_params) { return abac_param_list_string_with_condition(ptr->aspect_params); } return NULL; } char *abac_aspect_aspect_param_typed_string(abac_aspect_t *ptr) { assert(ptr != NULL); if(ptr->aspect_params) { return abac_param_list_typed_string_with_condition(ptr->aspect_params); } return NULL; } /** * Returns the typed string representation of the role/oset. */ char *abac_aspect_typed_string_with_condition(abac_aspect_t *ptr) { assert(ptr != NULL); if(abac_aspect_is_intersection(ptr)) { return abac_aspect_intersecting_string_with_condition(1,ptr); } char *tmp=NULL, *final=NULL; char *principal_name; char *principal_name_type=NULL; if(abac_aspect_is_object(ptr)) { principal_name = abac_aspect_object_name(ptr); /*special case is when it is time type */ if(_abac_aspect_object_is_time_type(ptr)) principal_name=abac_time_to_term(principal_name); principal_name_type = abac_aspect_object_type(ptr); } else { principal_name = abac_aspect_principal_name(ptr); principal_name_type=abac_aspect_principal_type(ptr); if(debug) fprintf(stderr,"aspect's typed_string (%s)(%s)\n", principal_name_type, principal_name); } /* the principal id is probably not in the idcreds list */ if(principal_name_type == NULL) { if(debug)fprintf(stderr,"THIS IS BAD, %s \n", principal_name); errx(1,"Can not find idtype for principal_name, don't see it in context?"); } if(debug) fprintf(stderr,"aspect's typed_string (%s)(%s)\n", principal_name_type, principal_name); char *aspect_name=abac_aspect_aspect_name(ptr); char *aspect_name_type=abac_aspect_type_string(ptr); char *linked_role_name=abac_aspect_linked_role_name(ptr); char *params_string=NULL; char *linked_params_string=NULL; if(ptr->aspect_params) { params_string=abac_param_list_typed_string_with_condition(ptr->aspect_params); } if(ptr->linked_role_params) { linked_params_string=abac_param_list_typed_string_with_condition(ptr->linked_role_params); } asprintf(&final,"[%s:%s]",principal_name_type,principal_name); if(linked_role_name) { tmp=final; final=NULL; asprintf(&final,"%s.role:%s",tmp,linked_role_name); free(tmp); } if(linked_params_string) { tmp=final; final=NULL; asprintf(&final,"%s(%s)",tmp,linked_params_string); free(tmp); } if(aspect_name) { tmp=final; final=NULL; asprintf(&final,"%s.%s:%s",tmp,aspect_name_type,aspect_name); free(tmp); } if(params_string) { tmp=final; final=NULL; asprintf(&final,"%s(%s)",tmp,params_string); free(tmp); } if(linked_params_string) free(linked_params_string); if(params_string) free(params_string); /* XXX */ fprintf(stderr,"final is at(%ld)(%s)\n",(long)final, final); return final; } /** * Build an attribute key from head and tail osets/role. Static. */ #define ROLE_SEPARATOR " <- " char *abac_aspect_attr_key(abac_aspect_t *head_ptr, abac_aspect_t *tail_ptr) { char *head = abac_aspect_string_with_condition(head_ptr); int head_len = strlen(head); char *tail = abac_aspect_string_with_condition(tail_ptr); int tail_len = strlen(tail); int sep_len = sizeof(ROLE_SEPARATOR) - 1; // "head <- tail" char *ret = abac_xmalloc(head_len + tail_len + sep_len + 1); memcpy(ret, head, head_len); memcpy(ret + head_len, ROLE_SEPARATOR, sep_len); memcpy(ret + head_len + sep_len, tail, tail_len); ret[head_len + sep_len + tail_len] = 0; return ret; }