genusers.c revision 13cd4c8960688af11ad23b4c946149015c80d549
1#include <stdio.h>
2#include <stdio_ext.h>
3#include <stdlib.h>
4#include <ctype.h>
5#include <errno.h>
6#include <limits.h>
7
8#include <sepol/policydb/policydb.h>
9#include <stdarg.h>
10
11#include "debug.h"
12#include "private.h"
13#include "dso.h"
14#include "mls.h"
15
16/* -- Deprecated -- */
17
18void sepol_set_delusers(int on __attribute((unused)))
19{
20	WARN(NULL, "Deprecated interface");
21}
22
23#undef BADLINE
24#define BADLINE() { \
25	ERR(NULL, "invalid entry %s (%s:%u)", \
26		buffer, path, lineno); \
27	continue; \
28}
29
30static int load_users(struct policydb *policydb, const char *path)
31{
32	FILE *fp;
33	char *buffer = NULL, *p, *q, oldc;
34	size_t len = 0;
35	ssize_t nread;
36	unsigned lineno = 0, islist = 0, bit;
37	user_datum_t *usrdatum;
38	role_datum_t *roldatum;
39	ebitmap_node_t *rnode;
40
41	fp = fopen(path, "r");
42	if (fp == NULL)
43		return -1;
44	__fsetlocking(fp, FSETLOCKING_BYCALLER);
45
46	while ((nread = getline(&buffer, &len, fp)) > 0) {
47		lineno++;
48		if (buffer[nread - 1] == '\n')
49			buffer[nread - 1] = 0;
50		p = buffer;
51		while (*p && isspace(*p))
52			p++;
53		if (!(*p) || *p == '#')
54			continue;
55
56		if (strncasecmp(p, "user", 4))
57			BADLINE();
58		p += 4;
59		if (!isspace(*p))
60			BADLINE();
61		while (*p && isspace(*p))
62			p++;
63		if (!(*p))
64			BADLINE();
65		q = p;
66		while (*p && !isspace(*p))
67			p++;
68		if (!(*p))
69			BADLINE();
70		*p++ = 0;
71
72		usrdatum = hashtab_search(policydb->p_users.table, q);
73		if (usrdatum) {
74			/* Replacing an existing user definition. */
75			ebitmap_destroy(&usrdatum->roles.roles);
76			ebitmap_init(&usrdatum->roles.roles);
77		} else {
78			char *id = strdup(q);
79
80			/* Adding a new user definition. */
81			usrdatum =
82			    (user_datum_t *) malloc(sizeof(user_datum_t));
83			if (!id || !usrdatum) {
84				ERR(NULL, "out of memory");
85				free(buffer);
86				fclose(fp);
87				return -1;
88			}
89			memset(usrdatum, 0, sizeof(user_datum_t));
90			usrdatum->s.value = ++policydb->p_users.nprim;
91			ebitmap_init(&usrdatum->roles.roles);
92			if (hashtab_insert(policydb->p_users.table,
93					   id, (hashtab_datum_t) usrdatum)) {
94				ERR(NULL, "out of memory");
95				free(buffer);
96				fclose(fp);
97				return -1;
98			}
99		}
100
101		while (*p && isspace(*p))
102			p++;
103		if (!(*p))
104			BADLINE();
105		if (strncasecmp(p, "roles", 5))
106			BADLINE();
107		p += 5;
108		if (!isspace(*p))
109			BADLINE();
110		while (*p && isspace(*p))
111			p++;
112		if (!(*p))
113			BADLINE();
114		if (*p == '{') {
115			islist = 1;
116			p++;
117		} else
118			islist = 0;
119
120		oldc = 0;
121		do {
122			while (*p && isspace(*p))
123				p++;
124			if (!(*p))
125				break;
126
127			q = p;
128			while (*p && *p != ';' && *p != '}' && !isspace(*p))
129				p++;
130			if (!(*p))
131				break;
132			if (*p == '}')
133				islist = 0;
134			oldc = *p;
135			*p++ = 0;
136			if (!q[0])
137				break;
138
139			roldatum = hashtab_search(policydb->p_roles.table, q);
140			if (!roldatum) {
141				ERR(NULL, "undefined role %s (%s:%u)",
142				    q, path, lineno);
143				continue;
144			}
145			/* Set the role and every role it dominates */
146			ebitmap_for_each_bit(&roldatum->dominates, rnode, bit) {
147				if (ebitmap_node_get_bit(rnode, bit))
148					if (ebitmap_set_bit
149					    (&usrdatum->roles.roles, bit, 1)) {
150						ERR(NULL, "out of memory");
151						free(buffer);
152						fclose(fp);
153						return -1;
154					}
155			}
156		} while (islist);
157		if (oldc == 0)
158			BADLINE();
159
160		if (policydb->mls) {
161			context_struct_t context;
162			char *scontext, *r, *s;
163
164			while (*p && isspace(*p))
165				p++;
166			if (!(*p))
167				BADLINE();
168			if (strncasecmp(p, "level", 5))
169				BADLINE();
170			p += 5;
171			if (!isspace(*p))
172				BADLINE();
173			while (*p && isspace(*p))
174				p++;
175			if (!(*p))
176				BADLINE();
177			q = p;
178			while (*p && strncasecmp(p, "range", 5))
179				p++;
180			if (!(*p))
181				BADLINE();
182			*--p = 0;
183			p++;
184
185			scontext = malloc(p - q);
186			if (!scontext) {
187				ERR(NULL, "out of memory");
188				free(buffer);
189				fclose(fp);
190				return -1;
191			}
192			r = scontext;
193			s = q;
194			while (*s) {
195				if (!isspace(*s))
196					*r++ = *s;
197				s++;
198			}
199			*r = 0;
200			r = scontext;
201
202			context_init(&context);
203			if (mls_context_to_sid(policydb, oldc, &r, &context) <
204			    0) {
205				ERR(NULL, "invalid level %s (%s:%u)", scontext,
206				    path, lineno);
207				free(scontext);
208				continue;
209
210			}
211			free(scontext);
212			memcpy(&usrdatum->dfltlevel, &context.range.level[0],
213			       sizeof(usrdatum->dfltlevel));
214
215			if (strncasecmp(p, "range", 5))
216				BADLINE();
217			p += 5;
218			if (!isspace(*p))
219				BADLINE();
220			while (*p && isspace(*p))
221				p++;
222			if (!(*p))
223				BADLINE();
224			q = p;
225			while (*p && *p != ';')
226				p++;
227			if (!(*p))
228				BADLINE();
229			*p++ = 0;
230
231			scontext = malloc(p - q);
232			if (!scontext) {
233				ERR(NULL, "out of memory");
234				free(buffer);
235				fclose(fp);
236				return -1;
237			}
238			r = scontext;
239			s = q;
240			while (*s) {
241				if (!isspace(*s))
242					*r++ = *s;
243				s++;
244			}
245			*r = 0;
246			r = scontext;
247
248			context_init(&context);
249			if (mls_context_to_sid(policydb, oldc, &r, &context) <
250			    0) {
251				ERR(NULL, "invalid range %s (%s:%u)", scontext,
252				    path, lineno);
253				free(scontext);
254				continue;
255			}
256			free(scontext);
257			memcpy(&usrdatum->range, &context.range,
258			       sizeof(usrdatum->range));
259		}
260	}
261
262	free(buffer);
263	fclose(fp);
264	return 0;
265}
266
267int sepol_genusers(void *data, size_t len,
268		   const char *usersdir, void **newdata, size_t * newlen)
269{
270	struct policydb policydb;
271	char path[PATH_MAX];
272
273	/* Construct policy database */
274	if (policydb_init(&policydb))
275		goto err;
276	if (policydb_from_image(NULL, data, len, &policydb) < 0)
277		goto err;
278
279	/* Load locally defined users. */
280	snprintf(path, sizeof path, "%s/local.users", usersdir);
281	if (load_users(&policydb, path) < 0)
282		goto err_destroy;
283
284	/* Write policy database */
285	if (policydb_to_image(NULL, &policydb, newdata, newlen) < 0)
286		goto err_destroy;
287
288	policydb_destroy(&policydb);
289	return 0;
290
291      err_destroy:
292	policydb_destroy(&policydb);
293
294      err:
295	return -1;
296}
297
298int hidden sepol_genusers_policydb(policydb_t * policydb, const char *usersdir)
299{
300	char path[PATH_MAX];
301
302	/* Load locally defined users. */
303	snprintf(path, sizeof path, "%s/local.users", usersdir);
304	if (load_users(policydb, path) < 0) {
305		ERR(NULL, "unable to load local.users: %s", strerror(errno));
306		return -1;
307	}
308
309	if (policydb_reindex_users(policydb) < 0) {
310		ERR(NULL, "unable to reindex users: %s", strerror(errno));
311		return -1;
312
313	}
314
315	return 0;
316}
317
318/* -- End Deprecated -- */
319