#include "context_internal.h" #include #include #include #define COMP_USER 0 #define COMP_ROLE 1 #define COMP_TYPE 2 #define COMP_RANGE 3 typedef struct { char *current_str; /* This is made up-to-date only when needed */ char *(component[4]); } context_private_t; /* * Allocate a new context, initialized from str. There must be 3 or * 4 colon-separated components and no whitespace in any component other * than the MLS component. */ context_t context_new(const char *str) { int i,count; context_private_t *n = (context_private_t*) malloc(sizeof(context_private_t)); context_t result = (context_t) malloc(sizeof(context_s_t)); const char *p,*tok; if (result) result->ptr = n; else free(n); if ( n == 0 || result == 0 ) { goto err; } n->current_str = n->component[0] = n->component[1] = n->component[2] = n->component[3] = 0; for ( i = count = 0, p = str; *p; p++ ) { switch ( *p ) { case ':': count++; break; case '\n': case '\t': case '\r': goto err; /* sanity check */ case ' ': if (count < 3) goto err; /* sanity check */ } } /* * Could be anywhere from 2 - 5 * e.g user:role:type to user:role:type:sens1:cata-sens2:catb */ if ( count < 2 || count > 5 ) { /* might not have a range */ goto err; } n->component[3] = 0; for ( i = 0, tok = str; *tok; i++ ) { if (i<3) for ( p = tok; *p && *p != ':'; p++ ) { /* empty */ } else { /* MLS range is one component */ for ( p = tok; *p; p++ ) { /* empty */ } } n->component[i] = (char*) malloc(p-tok+1); if (n->component[i] == 0) goto err; strncpy(n->component[i],tok,p-tok); n->component[i][p-tok] = '\0'; tok = *p ? p+1 : p; } return result; err: context_free(result); return 0; } hidden_def(context_new) static void conditional_free(char** v) { if ( *v ) { free(*v); } *v = 0; } /* * free all storage used by a context. Safe to call with * null pointer. */ void context_free(context_t context) { context_private_t *n; int i; if ( context ) { n = context->ptr; if ( n ) { conditional_free(&n->current_str); for ( i = 0; i < 4; i++ ) { conditional_free(&n->component[i]); } free(n); } free(context); } } hidden_def(context_free) /* * Return a pointer to the string value of the context. */ char * context_str(context_t context) { context_private_t *n = context->ptr; int i; size_t total = 0; conditional_free(&n->current_str); for ( i = 0; i < 4; i++ ) { if ( n->component[i] ) { total += strlen(n->component[i])+1; } } n->current_str = malloc(total); if ( n->current_str != 0 ) { char *cp = n->current_str; cp = stpcpy(cp, n->component[0]); for (i = 1; i < 4; i++) { if (n->component[i]) { *cp++ = ':'; cp = stpcpy(cp, n->component[i]); } } } return n->current_str; } hidden_def(context_str) /* Returns nonzero iff failed */ static int set_comp(context_private_t* n,int index, const char *str) { char *t = NULL; const char *p; if (str) { t = (char*) malloc(strlen(str)+1); if ( !t ) { return 1; } for ( p = str; *p; p++ ) { if ( *p == '\t' || *p == '\n' || *p == '\r' || ((*p == ':' || *p == ' ') && index != COMP_RANGE) ) { free(t); return 1; } } strcpy(t,str); } conditional_free(&n->component[index]); n->component[index] = t; return 0; } #define def_get(name,tag) \ const char * context_ ## name ## _get(context_t context) \ { \ context_private_t *n = context->ptr; \ return n->component[tag]; \ } \ hidden_def(context_ ## name ## _get) def_get(type,COMP_TYPE) def_get(user,COMP_USER) def_get(range,COMP_RANGE) def_get(role,COMP_ROLE) #define def_set(name,tag) \ int context_ ## name ## _set(context_t context, const char* str) \ { \ return set_comp(context->ptr,tag,str);\ } \ hidden_def(context_ ## name ## _set) def_set(type,COMP_TYPE) def_set(role,COMP_ROLE) def_set(user,COMP_USER) def_set(range,COMP_RANGE)