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