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