1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <ctype.h>
4 #include <errno.h>
5
6 #include <sepol/policydb/policydb.h>
7 #include <sepol/policydb/conditional.h>
8
9 #include "debug.h"
10 #include "private.h"
11 #include "dso.h"
12
13 /* -- Deprecated -- */
14
strtrim(char * dest,char * source,int size)15 static char *strtrim(char *dest, char *source, int size)
16 {
17 int i = 0;
18 char *ptr = source;
19 i = 0;
20 while (isspace(*ptr) && i < size) {
21 ptr++;
22 i++;
23 }
24 strncpy(dest, ptr, size);
25 for (i = strlen(dest) - 1; i > 0; i--) {
26 if (!isspace(dest[i]))
27 break;
28 }
29 dest[i + 1] = '\0';
30 return dest;
31 }
32
process_boolean(char * buffer,char * name,int namesize,int * val)33 static int process_boolean(char *buffer, char *name, int namesize, int *val)
34 {
35 char name1[BUFSIZ];
36 char *ptr = NULL;
37 char *tok;
38
39 /* Skip spaces */
40 while (isspace(buffer[0]))
41 buffer++;
42 /* Ignore comments */
43 if (buffer[0] == '#')
44 return 0;
45
46 tok = strtok_r(buffer, "=", &ptr);
47 if (!tok) {
48 ERR(NULL, "illegal boolean definition %s", buffer);
49 return -1;
50 }
51 strncpy(name1, tok, BUFSIZ - 1);
52 strtrim(name, name1, namesize - 1);
53
54 tok = strtok_r(NULL, "\0", &ptr);
55 if (!tok) {
56 ERR(NULL, "illegal boolean definition %s=%s", name, buffer);
57 return -1;
58 }
59
60 while (isspace(*tok))
61 tok++;
62
63 *val = -1;
64 if (isdigit(tok[0]))
65 *val = atoi(tok);
66 else if (!strncasecmp(tok, "true", sizeof("true") - 1))
67 *val = 1;
68 else if (!strncasecmp(tok, "false", sizeof("false") - 1))
69 *val = 0;
70 if (*val != 0 && *val != 1) {
71 ERR(NULL, "illegal value for boolean %s=%s", name, tok);
72 return -1;
73 }
74 return 1;
75 }
76
load_booleans(struct policydb * policydb,const char * path,int * changesp)77 static int load_booleans(struct policydb *policydb, const char *path,
78 int *changesp)
79 {
80 FILE *boolf;
81 char *buffer = NULL;
82 char localbools[BUFSIZ];
83 char name[BUFSIZ];
84 int val;
85 int errors = 0, changes = 0;
86 struct cond_bool_datum *datum;
87
88 boolf = fopen(path, "r");
89 if (boolf == NULL)
90 goto localbool;
91
92 #ifdef __APPLE__
93 if ((buffer = (char *)malloc(255 * sizeof(char))) == NULL) {
94 ERR(NULL, "out of memory");
95 return -1;
96 }
97
98 while(fgets(buffer, 255, boolf) != NULL) {
99 #else
100 size_t size = 0;
101 while (getline(&buffer, &size, boolf) > 0) {
102 #endif
103 int ret = process_boolean(buffer, name, sizeof(name), &val);
104 if (ret == -1)
105 errors++;
106 if (ret == 1) {
107 datum = hashtab_search(policydb->p_bools.table, name);
108 if (!datum) {
109 ERR(NULL, "unknown boolean %s", name);
110 errors++;
111 continue;
112 }
113 if (datum->state != val) {
114 datum->state = val;
115 changes++;
116 }
117 }
118 }
119 fclose(boolf);
120 localbool:
121 snprintf(localbools, sizeof(localbools), "%s.local", path);
122 boolf = fopen(localbools, "r");
123 if (boolf != NULL) {
124
125 #ifdef __APPLE__
126
127 while(fgets(buffer, 255, boolf) != NULL) {
128 #else
129
130 while (getline(&buffer, &size, boolf) > 0) {
131 #endif
132 int ret =
133 process_boolean(buffer, name, sizeof(name), &val);
134 if (ret == -1)
135 errors++;
136 if (ret == 1) {
137 datum =
138 hashtab_search(policydb->p_bools.table,
139 name);
140 if (!datum) {
141 ERR(NULL, "unknown boolean %s", name);
142 errors++;
143 continue;
144 }
145 if (datum->state != val) {
146 datum->state = val;
147 changes++;
148 }
149 }
150 }
151 fclose(boolf);
152 }
153 free(buffer);
154 if (errors)
155 errno = EINVAL;
156 *changesp = changes;
157 return errors ? -1 : 0;
158 }
159
160 int sepol_genbools(void *data, size_t len, const char *booleans)
161 {
162 struct policydb policydb;
163 struct policy_file pf;
164 int rc, changes = 0;
165
166 if (policydb_init(&policydb))
167 goto err;
168 if (policydb_from_image(NULL, data, len, &policydb) < 0)
169 goto err;
170
171 if (load_booleans(&policydb, booleans, &changes) < 0) {
172 WARN(NULL, "error while reading %s", booleans);
173 }
174
175 if (!changes)
176 goto out;
177
178 if (evaluate_conds(&policydb) < 0) {
179 ERR(NULL, "error while re-evaluating conditionals");
180 errno = EINVAL;
181 goto err_destroy;
182 }
183
184 policy_file_init(&pf);
185 pf.type = PF_USE_MEMORY;
186 pf.data = data;
187 pf.len = len;
188 rc = policydb_write(&policydb, &pf);
189 if (rc) {
190 ERR(NULL, "unable to write new binary policy image");
191 errno = EINVAL;
192 goto err_destroy;
193 }
194
195 out:
196 policydb_destroy(&policydb);
197 return 0;
198
199 err_destroy:
200 policydb_destroy(&policydb);
201
202 err:
203 return -1;
204 }
205
206 int hidden sepol_genbools_policydb(policydb_t * policydb, const char *booleans)
207 {
208 int rc, changes = 0;
209
210 rc = load_booleans(policydb, booleans, &changes);
211 if (!rc && changes)
212 rc = evaluate_conds(policydb);
213 if (rc)
214 errno = EINVAL;
215 return rc;
216 }
217
218 /* -- End Deprecated -- */
219
220 int sepol_genbools_array(void *data, size_t len, char **names, int *values,
221 int nel)
222 {
223 struct policydb policydb;
224 struct policy_file pf;
225 int rc, i, errors = 0;
226 struct cond_bool_datum *datum;
227
228 /* Create policy database from image */
229 if (policydb_init(&policydb))
230 goto err;
231 if (policydb_from_image(NULL, data, len, &policydb) < 0)
232 goto err;
233
234 for (i = 0; i < nel; i++) {
235 datum = hashtab_search(policydb.p_bools.table, names[i]);
236 if (!datum) {
237 ERR(NULL, "boolean %s no longer in policy", names[i]);
238 errors++;
239 continue;
240 }
241 if (values[i] != 0 && values[i] != 1) {
242 ERR(NULL, "illegal value %d for boolean %s",
243 values[i], names[i]);
244 errors++;
245 continue;
246 }
247 datum->state = values[i];
248 }
249
250 if (evaluate_conds(&policydb) < 0) {
251 ERR(NULL, "error while re-evaluating conditionals");
252 errno = EINVAL;
253 goto err_destroy;
254 }
255
256 policy_file_init(&pf);
257 pf.type = PF_USE_MEMORY;
258 pf.data = data;
259 pf.len = len;
260 rc = policydb_write(&policydb, &pf);
261 if (rc) {
262 ERR(NULL, "unable to write binary policy");
263 errno = EINVAL;
264 goto err_destroy;
265 }
266 if (errors) {
267 errno = EINVAL;
268 goto err_destroy;
269 }
270
271 policydb_destroy(&policydb);
272 return 0;
273
274 err_destroy:
275 policydb_destroy(&policydb);
276
277 err:
278 return -1;
279 }
280