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