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