• 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 			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 
291 int 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 
322 int 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