#include #include #include #include #include "abac.h" #include "abac_util.h" // typedef'd in role.h struct _abac_role_t { char *principal; char *linked_role; char *abac_role_name; char *string; char *linked; int refcount; }; /** * Create a new principal and initialize it. */ abac_role_t *abac_role_principal_new(char *principal) { assert(principal != NULL); abac_role_t *role; if (strlen(principal) == 0) return NULL; role = abac_xmalloc(sizeof(abac_role_t)); role->principal = abac_xstrdup(principal); role->abac_role_name = NULL; role->linked_role = NULL; role->string = abac_xstrdup(principal); role->linked = NULL; role->refcount = 1; return role; } /** * Create a new role and initialize it. */ abac_role_t *abac_role_role_new(char *principal, char *abac_role_name) { assert(principal != NULL); assert(abac_role_name != NULL); abac_role_t *role; if (strlen(principal) == 0 || strlen(abac_role_name) == 0) return NULL; role = abac_xmalloc(sizeof(abac_role_t)); role->principal = abac_xstrdup(principal); role->abac_role_name = abac_xstrdup(abac_role_name); role->linked_role = NULL; int prin_len = strlen(principal); int abac_role_len = strlen(abac_role_name); role->string = abac_xmalloc(prin_len + 1 + abac_role_len + 1); memcpy(role->string, principal, prin_len); role->string[prin_len] = '.'; memcpy(role->string + prin_len + 1, abac_role_name, abac_role_len); role->string[prin_len + 1 + abac_role_len] = 0; role->linked = NULL; role->refcount = 1; return role; } /** * Created a new linking role and initialize it. */ abac_role_t *abac_role_linking_new(char *principal, char *linked, char *abac_role_name) { assert(principal != NULL); assert(linked != NULL); assert(abac_role_name != NULL); abac_role_t *role; if (strlen(principal) == 0 || strlen(linked) == 0 || strlen(abac_role_name) == 0) return NULL; role = abac_xmalloc(sizeof(abac_role_t)); role->principal = abac_xstrdup(principal); role->linked_role = abac_xstrdup(linked); role->abac_role_name = abac_xstrdup(abac_role_name); int prin_len = strlen(principal); int link_len = strlen(linked); int abac_role_len = strlen(abac_role_name); role->string = abac_xmalloc(prin_len + 1 + link_len + 1 + abac_role_len + 1); memcpy(role->string, principal, prin_len); role->string[prin_len] = '.'; memcpy(role->string + prin_len + 1, linked, link_len); role->string[prin_len + 1 + link_len] = 0; // hack: linked role is first two parts of full string role->linked = abac_xstrdup(role->string); role->string[prin_len + 1 + link_len] = '.'; memcpy(role->string + prin_len + 1 + link_len + 1, abac_role_name, abac_role_len); role->string[prin_len + 1 + link_len + 1 + abac_role_len] = 0; role->refcount = 1; return role; } /** * Decrease a role's reference count, freeing it when it reaches 0. */ void abac_role_free(abac_role_t *role) { if (role == NULL) return; --role->refcount; if (role->refcount > 0) return; free(role->principal); free(role->linked_role); free(role->abac_role_name); free(role->string); free(role->linked); free(role); } /** * Create a role from a string. Handles principals, roles, and linking roles. */ abac_role_t *abac_role_from_string(char *string) { int num_dots = 0; char *dot = string; // count the dots while ((dot = strchr(dot, '.')) != NULL) { ++num_dots; ++dot; } // no dots: easy case, principal if (num_dots == 0) return abac_role_principal_new(string); abac_role_t *ret = NULL; // make a copy so we can mess with it string = abac_xstrdup(string); // a role has exactly 1 dot if (num_dots == 1) { char *principal = string; // terminate the principal part dot = strchr(principal, '.'); *dot = 0; // role name comes after the dot char *abac_role_name = dot + 1; // create the role (if possible) ret = abac_role_role_new(string, abac_role_name); } // a linked role has 2 dots else if (num_dots == 2) { char *principal = string; // terminate the principal part dot = strchr(principal, '.'); *dot = 0; // linked name is next, terminate it char *linked = dot + 1; dot = strchr(linked, '.'); *dot = 0; // role name is last, already terminated char *abac_role_name = dot + 1; ret = abac_role_linking_new(principal, linked, abac_role_name); } // more than two dots: return NULL free(string); return ret; } /** * Increase a role's reference count. */ abac_role_t *abac_role_dup(abac_role_t *role) { assert(role != NULL); ++role->refcount; return role; } /** * True if a role is a principal. */ int abac_role_is_principal(abac_role_t *role) { assert(role != NULL); return role->abac_role_name == NULL && role->linked_role == NULL; } /** * True if a role is a role. */ int abac_role_is_role(abac_role_t *role) { assert(role != NULL); return role->abac_role_name != NULL && role->linked_role == NULL; } /** * True if a role is a linked role. */ int abac_role_is_linking(abac_role_t *role) { assert(role != NULL); return role->linked_role != NULL; } /** * Returns the string representation of the role. */ char *abac_role_string(abac_role_t *role) { assert(role != NULL); return role->string; } /** * Returns the name of a role. If the role is A.r1 then return r1. If the role * is A.r1.r2 then return r2. */ char *abac_role_role_name(abac_role_t *role) { assert(role != NULL); return role->abac_role_name; } /** * Returns the linked part of a linking role. For instance, if the role is * A.r1.r2, this returns A.r1. */ char *abac_role_linked_role(abac_role_t *role) { assert(role != NULL); return role->linked; } /** * Returns the principal part of a role. The stuff before the first dot. */ char *abac_role_principal(abac_role_t *role) { assert(role != NULL); return role->principal; } /** * Build an attribute key from head and tail roles. Static. */ #define ROLE_SEPARATOR " <- " char *abac_role_attr_key(abac_role_t *head_role, abac_role_t *tail_role) { char *head = abac_role_string(head_role); int head_len = strlen(head); char *tail = abac_role_string(tail_role); 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; }