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 && strncasecmp(p, "range", 5))
205 p++;
206 if (!(*p))
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