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