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