• 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 			/* 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 
282 int 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 
313 int 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