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	return STATUS_SUCCESS;
114}
115
116int sepol_bool_exists(sepol_handle_t * handle,
117		      const sepol_policydb_t * p,
118		      const sepol_bool_key_t * key, int *response)
119{
120
121	const policydb_t *policydb = &p->p;
122
123	const char *cname;
124	char *name = NULL;
125	sepol_bool_key_unpack(key, &cname);
126	name = strdup(cname);
127
128	if (!name) {
129		ERR(handle, "out of memory, could not check "
130		    "if user %s exists", cname);
131		return STATUS_ERR;
132	}
133
134	*response = (hashtab_search(policydb->p_bools.table, name) != NULL);
135	free(name);
136	return STATUS_SUCCESS;
137}
138
139int sepol_bool_query(sepol_handle_t * handle,
140		     const sepol_policydb_t * p,
141		     const sepol_bool_key_t * key, sepol_bool_t ** response)
142{
143
144	const policydb_t *policydb = &p->p;
145	cond_bool_datum_t *booldatum = NULL;
146
147	const char *cname;
148	char *name = NULL;
149	sepol_bool_key_unpack(key, &cname);
150	name = strdup(cname);
151
152	if (!name)
153		goto omem;
154
155	booldatum = hashtab_search(policydb->p_bools.table, name);
156	if (!booldatum) {
157		*response = NULL;
158		return STATUS_SUCCESS;
159	}
160
161	if (bool_to_record(handle, policydb,
162			   booldatum->s.value - 1, response) < 0)
163		goto err;
164
165	free(name);
166	return STATUS_SUCCESS;
167
168      omem:
169	ERR(handle, "out of memory");
170
171      err:
172	ERR(handle, "could not query boolean %s", cname);
173	free(name);
174	return STATUS_ERR;
175}
176
177int sepol_bool_iterate(sepol_handle_t * handle,
178		       const sepol_policydb_t * p,
179		       int (*fn) (const sepol_bool_t * boolean,
180				  void *fn_arg), void *arg)
181{
182
183	const policydb_t *policydb = &p->p;
184	unsigned int nbools = policydb->p_bools.nprim;
185	sepol_bool_t *boolean = NULL;
186	unsigned int i;
187
188	/* For each boolean */
189	for (i = 0; i < nbools; i++) {
190
191		int status;
192
193		if (bool_to_record(handle, policydb, i, &boolean) < 0)
194			goto err;
195
196		/* Invoke handler */
197		status = fn(boolean, arg);
198		if (status < 0)
199			goto err;
200
201		sepol_bool_free(boolean);
202		boolean = NULL;
203
204		/* Handler requested exit */
205		if (status > 0)
206			break;
207	}
208
209	return STATUS_SUCCESS;
210
211      err:
212	ERR(handle, "could not iterate over booleans");
213	sepol_bool_free(boolean);
214	return STATUS_ERR;
215}
216