• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
sepol_set_delusers(int on __attribute ((unused)))23 void 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 
load_users(struct policydb * policydb,const char * path)35 static 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 
292 int 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 
323 int 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