genusers.c revision b1db49d77789525ac1f4e73e978e35694f21ea1a
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			/* Adding a new user definition. */
96			usrdatum =
97			    (user_datum_t *) malloc(sizeof(user_datum_t));
98			if (!id || !usrdatum) {
99				ERR(NULL, "out of memory");
100				free(buffer);
101				fclose(fp);
102				return -1;
103			}
104			memset(usrdatum, 0, sizeof(user_datum_t));
105			usrdatum->s.value = ++policydb->p_users.nprim;
106			ebitmap_init(&usrdatum->roles.roles);
107			if (hashtab_insert(policydb->p_users.table,
108					   id, (hashtab_datum_t) usrdatum)) {
109				ERR(NULL, "out of memory");
110				free(buffer);
111				fclose(fp);
112				return -1;
113			}
114		}
115
116		while (*p && isspace(*p))
117			p++;
118		if (!(*p))
119			BADLINE();
120		if (strncasecmp(p, "roles", 5))
121			BADLINE();
122		p += 5;
123		if (!isspace(*p))
124			BADLINE();
125		while (*p && isspace(*p))
126			p++;
127		if (!(*p))
128			BADLINE();
129		if (*p == '{') {
130			islist = 1;
131			p++;
132		} else
133			islist = 0;
134
135		oldc = 0;
136		do {
137			while (*p && isspace(*p))
138				p++;
139			if (!(*p))
140				break;
141
142			q = p;
143			while (*p && *p != ';' && *p != '}' && !isspace(*p))
144				p++;
145			if (!(*p))
146				break;
147			if (*p == '}')
148				islist = 0;
149			oldc = *p;
150			*p++ = 0;
151			if (!q[0])
152				break;
153
154			roldatum = hashtab_search(policydb->p_roles.table, q);
155			if (!roldatum) {
156				ERR(NULL, "undefined role %s (%s:%u)",
157				    q, path, lineno);
158				continue;
159			}
160			/* Set the role and every role it dominates */
161			ebitmap_for_each_bit(&roldatum->dominates, rnode, bit) {
162				if (ebitmap_node_get_bit(rnode, bit))
163					if (ebitmap_set_bit
164					    (&usrdatum->roles.roles, bit, 1)) {
165						ERR(NULL, "out of memory");
166						free(buffer);
167						fclose(fp);
168						return -1;
169					}
170			}
171		} while (islist);
172		if (oldc == 0)
173			BADLINE();
174
175		if (policydb->mls) {
176			context_struct_t context;
177			char *scontext, *r, *s;
178
179			while (*p && isspace(*p))
180				p++;
181			if (!(*p))
182				BADLINE();
183			if (strncasecmp(p, "level", 5))
184				BADLINE();
185			p += 5;
186			if (!isspace(*p))
187				BADLINE();
188			while (*p && isspace(*p))
189				p++;
190			if (!(*p))
191				BADLINE();
192			q = p;
193			while (*p && strncasecmp(p, "range", 5))
194				p++;
195			if (!(*p))
196				BADLINE();
197			*--p = 0;
198			p++;
199
200			scontext = malloc(p - q);
201			if (!scontext) {
202				ERR(NULL, "out of memory");
203				free(buffer);
204				fclose(fp);
205				return -1;
206			}
207			r = scontext;
208			s = q;
209			while (*s) {
210				if (!isspace(*s))
211					*r++ = *s;
212				s++;
213			}
214			*r = 0;
215			r = scontext;
216
217			context_init(&context);
218			if (mls_context_to_sid(policydb, oldc, &r, &context) <
219			    0) {
220				ERR(NULL, "invalid level %s (%s:%u)", scontext,
221				    path, lineno);
222				free(scontext);
223				continue;
224
225			}
226			free(scontext);
227			memcpy(&usrdatum->dfltlevel, &context.range.level[0],
228			       sizeof(usrdatum->dfltlevel));
229
230			if (strncasecmp(p, "range", 5))
231				BADLINE();
232			p += 5;
233			if (!isspace(*p))
234				BADLINE();
235			while (*p && isspace(*p))
236				p++;
237			if (!(*p))
238				BADLINE();
239			q = p;
240			while (*p && *p != ';')
241				p++;
242			if (!(*p))
243				BADLINE();
244			*p++ = 0;
245
246			scontext = malloc(p - q);
247			if (!scontext) {
248				ERR(NULL, "out of memory");
249				free(buffer);
250				fclose(fp);
251				return -1;
252			}
253			r = scontext;
254			s = q;
255			while (*s) {
256				if (!isspace(*s))
257					*r++ = *s;
258				s++;
259			}
260			*r = 0;
261			r = scontext;
262
263			context_init(&context);
264			if (mls_context_to_sid(policydb, oldc, &r, &context) <
265			    0) {
266				ERR(NULL, "invalid range %s (%s:%u)", scontext,
267				    path, lineno);
268				free(scontext);
269				continue;
270			}
271			free(scontext);
272			memcpy(&usrdatum->range, &context.range,
273			       sizeof(usrdatum->range));
274		}
275	}
276
277	free(buffer);
278	fclose(fp);
279	return 0;
280}
281
282int sepol_genusers(void *data, size_t len,
283		   const char *usersdir, void **newdata, size_t * newlen)
284{
285	struct policydb policydb;
286	char path[PATH_MAX];
287
288	/* Construct policy database */
289	if (policydb_init(&policydb))
290		goto err;
291	if (policydb_from_image(NULL, data, len, &policydb) < 0)
292		goto err;
293
294	/* Load locally defined users. */
295	snprintf(path, sizeof path, "%s/local.users", usersdir);
296	if (load_users(&policydb, path) < 0)
297		goto err_destroy;
298
299	/* Write policy database */
300	if (policydb_to_image(NULL, &policydb, newdata, newlen) < 0)
301		goto err_destroy;
302
303	policydb_destroy(&policydb);
304	return 0;
305
306      err_destroy:
307	policydb_destroy(&policydb);
308
309      err:
310	return -1;
311}
312
313int hidden sepol_genusers_policydb(policydb_t * policydb, const char *usersdir)
314{
315	char path[PATH_MAX];
316
317	/* Load locally defined users. */
318	snprintf(path, sizeof path, "%s/local.users", usersdir);
319	if (load_users(policydb, path) < 0) {
320		ERR(NULL, "unable to load local.users: %s", strerror(errno));
321		return -1;
322	}
323
324	if (policydb_reindex_users(policydb) < 0) {
325		ERR(NULL, "unable to reindex users: %s", strerror(errno));
326		return -1;
327
328	}
329
330	return 0;
331}
332
333/* -- End Deprecated -- */
334