147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include "context_internal.h"
247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <string.h>
347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdio.h>
447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <stdlib.h>
547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#include <errno.h>
647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#define COMP_USER  0
847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#define COMP_ROLE  1
947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#define COMP_TYPE  2
1047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#define COMP_RANGE 3
1147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
1247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnertypedef struct {
1347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	char *current_str;	/* This is made up-to-date only when needed */
1447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	char *(component[4]);
1547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} context_private_t;
1647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
1747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/*
1847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Allocate a new context, initialized from str.  There must be 3 or
1947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * 4 colon-separated components and no whitespace in any component other
2047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * than the MLS component.
2147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */
2247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnercontext_t context_new(const char *str)
2347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{
2447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	int i, count;
2547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	errno = 0;
2647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	context_private_t *n =
2747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	    (context_private_t *) malloc(sizeof(context_private_t));
2847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	context_t result = (context_t) malloc(sizeof(context_s_t));
2947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	const char *p, *tok;
3047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
3147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (result)
3247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		result->ptr = n;
3347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	else
3447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		free(n);
3547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (n == 0 || result == 0) {
3647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		goto err;
3747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
3847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	n->current_str = n->component[0] = n->component[1] = n->component[2] =
3947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	    n->component[3] = 0;
4047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	for (i = count = 0, p = str; *p; p++) {
4147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		switch (*p) {
4247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		case ':':
4347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			count++;
4447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			break;
4547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		case '\n':
4647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		case '\t':
4747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		case '\r':
4847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			goto err;	/* sanity check */
4947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		case ' ':
5047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			if (count < 3)
5147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner				goto err;	/* sanity check */
5247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		}
5347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
5447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	/*
5547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	 * Could be anywhere from 2 - 5
5647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	 * e.g user:role:type to user:role:type:sens1:cata-sens2:catb
5747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	 */
5847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (count < 2 || count > 5) {	/* might not have a range */
5947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		goto err;
6047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
6147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
6247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	n->component[3] = 0;
6347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	for (i = 0, tok = str; *tok; i++) {
6447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		if (i < 3)
6547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			for (p = tok; *p && *p != ':'; p++) {	/* empty */
6647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		} else {
6747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			/* MLS range is one component */
6847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			for (p = tok; *p; p++) {	/* empty */
6947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			}
7047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		}
7147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		n->component[i] = (char *)malloc(p - tok + 1);
7247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		if (n->component[i] == 0)
7347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			goto err;
7447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		strncpy(n->component[i], tok, p - tok);
7547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		n->component[i][p - tok] = '\0';
7647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		tok = *p ? p + 1 : p;
7747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
7847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	return result;
7947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner      err:
8047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (errno == 0) errno = EINVAL;
8147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	context_free(result);
8247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	return 0;
8347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}
8447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
8547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerhidden_def(context_new)
8647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
8747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic void conditional_free(char **v)
8847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{
8947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (*v) {
9047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		free(*v);
9147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
9247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	*v = 0;
9347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}
9447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
9547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/*
9647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * free all storage used by a context.  Safe to call with
9747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * null pointer.
9847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */
9947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnervoid context_free(context_t context)
10047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{
10147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	context_private_t *n;
10247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	int i;
10347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (context) {
10447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		n = context->ptr;
10547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		if (n) {
10647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			conditional_free(&n->current_str);
10747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			for (i = 0; i < 4; i++) {
10847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner				conditional_free(&n->component[i]);
10947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			}
11047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			free(n);
11147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		}
11247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		free(context);
11347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
11447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}
11547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
11647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerhidden_def(context_free)
11747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
11847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/*
11947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner * Return a pointer to the string value of the context.
12047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner */
12147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerchar *context_str(context_t context)
12247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{
12347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	context_private_t *n = context->ptr;
12447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	int i;
12547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	size_t total = 0;
12647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	conditional_free(&n->current_str);
12747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	for (i = 0; i < 4; i++) {
12847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		if (n->component[i]) {
12947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			total += strlen(n->component[i]) + 1;
13047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		}
13147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
13247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	n->current_str = malloc(total);
13347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (n->current_str != 0) {
13447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		char *cp = n->current_str;
13547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
13647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		strcpy(cp, n->component[0]);
13747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		cp += strlen(cp);
13847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		for (i = 1; i < 4; i++) {
13947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			if (n->component[i]) {
14047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner				*cp++ = ':';
14147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner				strcpy(cp, n->component[i]);
14247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner				cp += strlen(cp);
14347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			}
14447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		}
14547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
14647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	return n->current_str;
14747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}
14847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
14947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerhidden_def(context_str)
15047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
15147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner/* Returns nonzero iff failed */
15247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerstatic int set_comp(context_private_t * n, int idx, const char *str)
15347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{
15447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	char *t = NULL;
15547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	const char *p;
15647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	if (str) {
15747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		t = (char *)malloc(strlen(str) + 1);
15847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		if (!t) {
15947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			return 1;
16047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		}
16147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		for (p = str; *p; p++) {
16247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			if (*p == '\t' || *p == '\n' || *p == '\r' ||
16347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			    ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) {
16447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner				free(t);
16547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner				errno = EINVAL;
16647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner				return 1;
16747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner			}
16847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		}
16947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner		strcpy(t, str);
17047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	}
17147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	conditional_free(&n->component[idx]);
17247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	n->component[idx] = t;
17347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner	return 0;
17447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner}
17547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
17647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#define def_get(name,tag) \
17747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerconst char * context_ ## name ## _get(context_t context) \
17847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ \
17947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner        context_private_t *n = context->ptr; \
18047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner        return n->component[tag]; \
18147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} \
18247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerhidden_def(context_ ## name ## _get)
18347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner
18447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerdef_get(type, COMP_TYPE)
18547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner    def_get(user, COMP_USER)
18647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner    def_get(range, COMP_RANGE)
18747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner    def_get(role, COMP_ROLE)
18847173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner#define def_set(name,tag) \
18947173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerint context_ ## name ## _set(context_t context, const char* str) \
19047173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner{ \
19147173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner        return set_comp(context->ptr,tag,str);\
19247173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner} \
19347173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turnerhidden_def(context_ ## name ## _set)
19447173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner    def_set(type, COMP_TYPE)
19547173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner    def_set(role, COMP_ROLE)
19647173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner    def_set(user, COMP_USER)
19747173c7d6704f1258b2d85537caa09185f6920c8David 'Digit' Turner    def_set(range, COMP_RANGE)
198