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