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
15static 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
33static 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
66static 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
149int 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
195int 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
209int 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