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