/** ** abac_aspect.c **/ #include #include #include #include #include "abac_internal.h" static int debug=0; /* 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; }; /**************************************************************/ void abac_aspect_dump(abac_aspect_t *ptr, char* offset) { char *tmp=NULL; asprintf(&tmp," %s",offset); if(ptr->prereqs != 0) { abac_aspect_t *cur; abac_list_foreach(ptr->prereqs, cur, if(cur) abac_aspect_dump(cur, tmp); ); return; } printf("\n..... an aspect .....\n"); printf("%s aspect_type: %d(%s)\n", offset, ptr->aspect_type, abac_aspect_type_string(ptr)); printf("%s is_object: %d\n", offset, ptr->is_object); printf("%s principal_name: %s\n", offset, ptr->principal_name); if(ptr->principal_name_p) printf("%s principal_name_p: %s\n", offset, ptr->principal_name_p); else printf("%s principal_name_p: --\n", offset); if(ptr->principal_object) abac_term_dump(ptr->principal_object, tmp); else ("%s principal_object: --\n", offset); if(ptr->linked_role_name) printf("%s linked_role_name: %s\n", offset, ptr->linked_role_name); else printf("%s linked_role_name: --\n", offset); if(ptr->linked_role_params) abac_param_dump(ptr->linked_role_params, tmp); else printf("%s linked_role_params: --\n", offset); if(ptr->aspect_name) printf("%s aspect_name: %s\n", offset, ptr->aspect_name); else printf("%s aspect_name: --\n", offset); if(ptr->aspect_params) abac_param_dump(ptr->aspect_params, tmp); else printf("%s aspect_params: --\n", offset); if(ptr->type_string) printf("%s type_string:- %s\n", offset, ptr->type_string); else printf("%s type_string: --\n", offset); printf("%s refcount:- %d\n", offset, ptr->refcount); printf(".................................."); free(tmp); } bool abac_aspect_is_oset(abac_aspect_t *ptr) { assert(ptr); if(ptr->aspect_type==e_ASPECTTYPE_OSET) return 1; return 0; } bool abac_aspect_is_role(abac_aspect_t *ptr) { assert(ptr); if(ptr->aspect_type==e_ASPECTTYPE_ROLE) return 1; return 0; } bool abac_aspect_is_intersecting(abac_aspect_t *ptr) { assert(ptr); if(ptr->aspect_type==e_ASPECTTYPE_INTERSECTING) return 1; return 0; } /* A.role->B or A.oset->B */ bool 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 */ bool 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 */ bool abac_aspect_is_linking(abac_aspect_t *ptr) { assert(ptr); return ptr->linked_role_name != NULL; } /** * True if an aspect is an intersection. */ bool 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); } bool _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); } 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; } /** * 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(%d)(%s:%d)\n",(int)ptr, ptr->aspect_name, ptr->refcount); else fprintf(stderr,"DEBUG:trying to freeing an aspect loc(%d)(M:%d)\n",(int)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(%d)(%s:%d)\n",(int)ptr, ptr->aspect_name, ptr->refcount); else fprintf(stderr,"DEBUG:freeing this aspect loc(%d)(M:%d)\n",(int)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->is_object=0; ptr->principal_name = NULL; ptr->principal_name_p = NULL; ptr->aspect_type=e_ASPECTTYPE_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 = strdup(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 = strdup(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,"DEBUG:adding a new aspect (%s) to principal (%s)\n", 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 = strdup(principal_name); ptr->principal_name_p = prologIt(principal_name); ptr->linked_role_name = strdup(linked_role_name); ptr->aspect_name = strdup(aspect_name); ptr->aspect_params = NULL; 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; ptr->refcount = 1; 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); } 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) { errx(1,"Can not find idtype for principal_name, wrong filename suffix?"); } 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); 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; }