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