1f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include "context_internal.h"
2f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <string.h>
3f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdio.h>
4f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <stdlib.h>
5f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#include <errno.h>
6f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
7f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define COMP_USER  0
8f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define COMP_ROLE  1
9f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define COMP_TYPE  2
10f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define COMP_RANGE 3
11f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
12f074036424618c130dacb3464465a8b40bffef5Stephen Smalleytypedef struct {
13f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *current_str;	/* This is made up-to-date only when needed */
14f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *(component[4]);
15f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} context_private_t;
16f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
17f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/*
18f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Allocate a new context, initialized from str.  There must be 3 or
19f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * 4 colon-separated components and no whitespace in any component other
20f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * than the MLS component.
21f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */
22f074036424618c130dacb3464465a8b40bffef5Stephen Smalleycontext_t context_new(const char *str)
23f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
24f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	int i, count;
25f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	errno = 0;
26f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	context_private_t *n =
27f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	    (context_private_t *) malloc(sizeof(context_private_t));
28f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	context_t result = (context_t) malloc(sizeof(context_s_t));
29f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	const char *p, *tok;
30f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
31f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (result)
32f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		result->ptr = n;
33f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	else
34f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		free(n);
35f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (n == 0 || result == 0) {
36f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto err;
37f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
38f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	n->current_str = n->component[0] = n->component[1] = n->component[2] =
39f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	    n->component[3] = 0;
40f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	for (i = count = 0, p = str; *p; p++) {
41f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		switch (*p) {
42f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		case ':':
43f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			count++;
44f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			break;
45f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		case '\n':
46f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		case '\t':
47f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		case '\r':
48f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			goto err;	/* sanity check */
49f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		case ' ':
50f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (count < 3)
51f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				goto err;	/* sanity check */
52f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
53f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
54f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	/*
55f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	 * Could be anywhere from 2 - 5
56f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	 * e.g user:role:type to user:role:type:sens1:cata-sens2:catb
57f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	 */
58f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (count < 2 || count > 5) {	/* might not have a range */
59f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		goto err;
60f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
61f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
62f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	n->component[3] = 0;
63f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	for (i = 0, tok = str; *tok; i++) {
64f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (i < 3)
65f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			for (p = tok; *p && *p != ':'; p++) {	/* empty */
66f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		} else {
67f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			/* MLS range is one component */
68f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			for (p = tok; *p; p++) {	/* empty */
69f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
70f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
71f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		n->component[i] = (char *)malloc(p - tok + 1);
72f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (n->component[i] == 0)
73f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			goto err;
74f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		strncpy(n->component[i], tok, p - tok);
75f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		n->component[i][p - tok] = '\0';
76f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		tok = *p ? p + 1 : p;
77f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
78f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return result;
79f074036424618c130dacb3464465a8b40bffef5Stephen Smalley      err:
80f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (errno == 0) errno = EINVAL;
81f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	context_free(result);
82f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return 0;
83f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
84f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
85f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(context_new)
86f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
87f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic void conditional_free(char **v)
88f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
89f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (*v) {
90f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		free(*v);
91f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
92f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	*v = 0;
93f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
94f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
95f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/*
96f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * free all storage used by a context.  Safe to call with
97f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * null pointer.
98f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */
99f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyvoid context_free(context_t context)
100f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
101f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	context_private_t *n;
102f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	int i;
103f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (context) {
104f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		n = context->ptr;
105f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (n) {
106f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			conditional_free(&n->current_str);
107f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			for (i = 0; i < 4; i++) {
108f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				conditional_free(&n->component[i]);
109f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
110f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			free(n);
111f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
112f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		free(context);
113f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
114f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
115f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
116f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(context_free)
117f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
118f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/*
119f074036424618c130dacb3464465a8b40bffef5Stephen Smalley * Return a pointer to the string value of the context.
120f074036424618c130dacb3464465a8b40bffef5Stephen Smalley */
121f074036424618c130dacb3464465a8b40bffef5Stephen Smalleychar *context_str(context_t context)
122f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
123f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	context_private_t *n = context->ptr;
124f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	int i;
125f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	size_t total = 0;
126f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	conditional_free(&n->current_str);
127f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	for (i = 0; i < 4; i++) {
128f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (n->component[i]) {
129f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			total += strlen(n->component[i]) + 1;
130f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
131f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
132f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	n->current_str = malloc(total);
133f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (n->current_str != 0) {
134f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		char *cp = n->current_str;
135f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
136f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		strcpy(cp, n->component[0]);
137f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		cp += strlen(cp);
138f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		for (i = 1; i < 4; i++) {
139f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (n->component[i]) {
140f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				*cp++ = ':';
141f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				strcpy(cp, n->component[i]);
142f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				cp += strlen(cp);
143f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
144f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
145f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
146f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return n->current_str;
147f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
148f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
149f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(context_str)
150f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
151f074036424618c130dacb3464465a8b40bffef5Stephen Smalley/* Returns nonzero iff failed */
152f074036424618c130dacb3464465a8b40bffef5Stephen Smalleystatic int set_comp(context_private_t * n, int idx, const char *str)
153f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{
154f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	char *t = NULL;
155f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	const char *p;
156f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	if (str) {
157f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		t = (char *)malloc(strlen(str) + 1);
158f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		if (!t) {
159f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			return 1;
160f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
161f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		for (p = str; *p; p++) {
162f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			if (*p == '\t' || *p == '\n' || *p == '\r' ||
163f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			    ((*p == ':' || *p == ' ') && idx != COMP_RANGE)) {
164f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				free(t);
165f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				errno = EINVAL;
166f074036424618c130dacb3464465a8b40bffef5Stephen Smalley				return 1;
167f074036424618c130dacb3464465a8b40bffef5Stephen Smalley			}
168f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		}
169f074036424618c130dacb3464465a8b40bffef5Stephen Smalley		strcpy(t, str);
170f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	}
171f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	conditional_free(&n->component[idx]);
172f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	n->component[idx] = t;
173f074036424618c130dacb3464465a8b40bffef5Stephen Smalley	return 0;
174f074036424618c130dacb3464465a8b40bffef5Stephen Smalley}
175f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
176f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define def_get(name,tag) \
177f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyconst char * context_ ## name ## _get(context_t context) \
178f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ \
179f074036424618c130dacb3464465a8b40bffef5Stephen Smalley        context_private_t *n = context->ptr; \
180f074036424618c130dacb3464465a8b40bffef5Stephen Smalley        return n->component[tag]; \
181f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} \
182f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(context_ ## name ## _get)
183f074036424618c130dacb3464465a8b40bffef5Stephen Smalley
184f074036424618c130dacb3464465a8b40bffef5Stephen Smalleydef_get(type, COMP_TYPE)
185f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    def_get(user, COMP_USER)
186f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    def_get(range, COMP_RANGE)
187f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    def_get(role, COMP_ROLE)
188f074036424618c130dacb3464465a8b40bffef5Stephen Smalley#define def_set(name,tag) \
189f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyint context_ ## name ## _set(context_t context, const char* str) \
190f074036424618c130dacb3464465a8b40bffef5Stephen Smalley{ \
191f074036424618c130dacb3464465a8b40bffef5Stephen Smalley        return set_comp(context->ptr,tag,str);\
192f074036424618c130dacb3464465a8b40bffef5Stephen Smalley} \
193f074036424618c130dacb3464465a8b40bffef5Stephen Smalleyhidden_def(context_ ## name ## _set)
194f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    def_set(type, COMP_TYPE)
195f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    def_set(role, COMP_ROLE)
196f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    def_set(user, COMP_USER)
197f074036424618c130dacb3464465a8b40bffef5Stephen Smalley    def_set(range, COMP_RANGE)
198