1#include <string.h>
2#include <stdlib.h>
3
4#include "handle.h"
5#include "private.h"
6#include "debug.h"
7
8#include <sepol/booleans.h>
9#include <sepol/policydb/hashtab.h>
10#include <sepol/policydb/policydb.h>
11#include <sepol/policydb/conditional.h>
12#include "boolean_internal.h"
13
14static int bool_update(sepol_handle_t * handle,
15		       policydb_t * policydb,
16		       const sepol_bool_key_t * key, const sepol_bool_t * data)
17{
18
19	const char *cname;
20	char *name;
21	int value;
22
23	sepol_bool_key_unpack(key, &cname);
24	name = strdup(cname);
25	value = sepol_bool_get_value(data);
26
27	if (!name)
28		goto omem;
29
30	cond_bool_datum_t *datum =
31	    hashtab_search(policydb->p_bools.table, name);
32	if (!datum) {
33		ERR(handle, "boolean %s no longer in policy", name);
34		goto err;
35	}
36	if (value != 0 && value != 1) {
37		ERR(handle, "illegal value %d for boolean %s", value, name);
38		goto err;
39	}
40
41	free(name);
42	datum->state = value;
43	return STATUS_SUCCESS;
44
45      omem:
46	ERR(handle, "out of memory");
47
48      err:
49	free(name);
50	ERR(handle, "could not update boolean %s", cname);
51	return STATUS_ERR;
52}
53
54static int bool_to_record(sepol_handle_t * handle,
55			  const policydb_t * policydb,
56			  int bool_idx, sepol_bool_t ** record)
57{
58
59	const char *name = policydb->p_bool_val_to_name[bool_idx];
60	cond_bool_datum_t *booldatum = policydb->bool_val_to_struct[bool_idx];
61	int value = booldatum->state;
62
63	sepol_bool_t *tmp_record = NULL;
64
65	if (sepol_bool_create(handle, &tmp_record) < 0)
66		goto err;
67
68	if (sepol_bool_set_name(handle, tmp_record, name) < 0)
69		goto err;
70
71	sepol_bool_set_value(tmp_record, value);
72
73	*record = tmp_record;
74	return STATUS_SUCCESS;
75
76      err:
77	ERR(handle, "could not convert boolean %s to record", name);
78	sepol_bool_free(tmp_record);
79	return STATUS_ERR;
80}
81
82int sepol_bool_set(sepol_handle_t * handle,
83		   sepol_policydb_t * p,
84		   const sepol_bool_key_t * key, const sepol_bool_t * data)
85{
86
87	const char *name;
88	sepol_bool_key_unpack(key, &name);
89
90	policydb_t *policydb = &p->p;
91	if (bool_update(handle, policydb, key, data) < 0)
92		goto err;
93
94	if (evaluate_conds(policydb) < 0) {
95		ERR(handle, "error while re-evaluating conditionals");
96		goto err;
97	}
98
99	return STATUS_SUCCESS;
100
101      err:
102	ERR(handle, "could not set boolean %s", name);
103	return STATUS_ERR;
104}
105
106int sepol_bool_count(sepol_handle_t * handle __attribute__ ((unused)),
107		     const sepol_policydb_t * p, unsigned int *response)
108{
109
110	const policydb_t *policydb = &p->p;
111	*response = policydb->p_bools.nprim;
112
113	handle = NULL;
114	return STATUS_SUCCESS;
115}
116
117int sepol_bool_exists(sepol_handle_t * handle,
118		      const sepol_policydb_t * p,
119		      const sepol_bool_key_t * key, int *response)
120{
121
122	const policydb_t *policydb = &p->p;
123
124	const char *cname;
125	char *name = NULL;
126	sepol_bool_key_unpack(key, &cname);
127	name = strdup(cname);
128
129	if (!name) {
130		ERR(handle, "out of memory, could not check "
131		    "if user %s exists", cname);
132		return STATUS_ERR;
133	}
134
135	*response = (hashtab_search(policydb->p_bools.table, name) != NULL);
136	free(name);
137	return STATUS_SUCCESS;
138}
139
140int sepol_bool_query(sepol_handle_t * handle,
141		     const sepol_policydb_t * p,
142		     const sepol_bool_key_t * key, sepol_bool_t ** response)
143{
144
145	const policydb_t *policydb = &p->p;
146	cond_bool_datum_t *booldatum = NULL;
147
148	const char *cname;
149	char *name = NULL;
150	sepol_bool_key_unpack(key, &cname);
151	name = strdup(cname);
152
153	if (!name)
154		goto omem;
155
156	booldatum = hashtab_search(policydb->p_bools.table, name);
157	if (!booldatum) {
158		*response = NULL;
159		return STATUS_SUCCESS;
160	}
161
162	if (bool_to_record(handle, policydb,
163			   booldatum->s.value - 1, response) < 0)
164		goto err;
165
166	free(name);
167	return STATUS_SUCCESS;
168
169      omem:
170	ERR(handle, "out of memory");
171
172      err:
173	ERR(handle, "could not query boolean %s", cname);
174	free(name);
175	return STATUS_ERR;
176}
177
178int sepol_bool_iterate(sepol_handle_t * handle,
179		       const sepol_policydb_t * p,
180		       int (*fn) (const sepol_bool_t * boolean,
181				  void *fn_arg), void *arg)
182{
183
184	const policydb_t *policydb = &p->p;
185	unsigned int nbools = policydb->p_bools.nprim;
186	sepol_bool_t *boolean = NULL;
187	unsigned int i;
188
189	/* For each boolean */
190	for (i = 0; i < nbools; i++) {
191
192		int status;
193
194		if (bool_to_record(handle, policydb, i, &boolean) < 0)
195			goto err;
196
197		/* Invoke handler */
198		status = fn(boolean, arg);
199		if (status < 0)
200			goto err;
201
202		sepol_bool_free(boolean);
203		boolean = NULL;
204
205		/* Handler requested exit */
206		if (status > 0)
207			break;
208	}
209
210	return STATUS_SUCCESS;
211
212      err:
213	ERR(handle, "could not iterate over booleans");
214	sepol_bool_free(boolean);
215	return STATUS_ERR;
216}
217