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