1/* Authors: Jason Tang <jtang@tresys.com>
2 *
3 * Functions that manipulate a logical block (conditional, optional,
4 * or global scope) for a policy module.
5 *
6 * Copyright (C) 2005 Tresys Technology, LLC
7 *
8 *  This library is free software; you can redistribute it and/or
9 *  modify it under the terms of the GNU Lesser General Public
10 *  License as published by the Free Software Foundation; either
11 *  version 2.1 of the License, or (at your option) any later version.
12 *
13 *  This library is distributed in the hope that it will be useful,
14 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16 *  Lesser General Public License for more details.
17 *
18 *  You should have received a copy of the GNU Lesser General Public
19 *  License along with this library; if not, write to the Free Software
20 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
21 */
22
23#include <sepol/policydb/policydb.h>
24#include <sepol/policydb/conditional.h>
25#include <sepol/policydb/avrule_block.h>
26
27#include <assert.h>
28#include <stdlib.h>
29
30/* It is anticipated that there be less declarations within an avrule
31 * block than the global policy.  Thus the symbol table sizes are
32 * smaller than those listed in policydb.c */
33static unsigned int symtab_sizes[SYM_NUM] = {
34	2,
35	4,
36	8,
37	32,
38	16,
39	4,
40	2,
41	2,
42};
43
44avrule_block_t *avrule_block_create(void)
45{
46	avrule_block_t *block;
47	if ((block = calloc(1, sizeof(*block))) == NULL) {
48		return NULL;
49	}
50	return block;
51}
52
53avrule_decl_t *avrule_decl_create(uint32_t decl_id)
54{
55	avrule_decl_t *decl;
56	int i;
57	if ((decl = calloc(1, sizeof(*decl))) == NULL) {
58		return NULL;
59	}
60	decl->decl_id = decl_id;
61	for (i = 0; i < SYM_NUM; i++) {
62		if (symtab_init(&decl->symtab[i], symtab_sizes[i])) {
63			avrule_decl_destroy(decl);
64			return NULL;
65		}
66	}
67
68	for (i = 0; i < SYM_NUM; i++) {
69		ebitmap_init(&decl->required.scope[i]);
70		ebitmap_init(&decl->declared.scope[i]);
71	}
72	return decl;
73}
74
75/* note that unlike the other destroy functions, this one does /NOT/
76 * destroy the pointer itself */
77static void scope_index_destroy(scope_index_t * scope)
78{
79	unsigned int i;
80	if (scope == NULL) {
81		return;
82	}
83	for (i = 0; i < SYM_NUM; i++) {
84		ebitmap_destroy(scope->scope + i);
85	}
86	if (scope->class_perms_map) {
87		for (i = 0; i < scope->class_perms_len; i++) {
88			ebitmap_destroy(scope->class_perms_map + i);
89		}
90	}
91	free(scope->class_perms_map);
92}
93
94void avrule_decl_destroy(avrule_decl_t * x)
95{
96	if (x == NULL) {
97		return;
98	}
99	cond_list_destroy(x->cond_list);
100	avrule_list_destroy(x->avrules);
101	role_trans_rule_list_destroy(x->role_tr_rules);
102	filename_trans_rule_list_destroy(x->filename_trans_rules);
103	role_allow_rule_list_destroy(x->role_allow_rules);
104	range_trans_rule_list_destroy(x->range_tr_rules);
105	scope_index_destroy(&x->required);
106	scope_index_destroy(&x->declared);
107	symtabs_destroy(x->symtab);
108	free(x->module_name);
109	free(x);
110}
111
112void avrule_block_destroy(avrule_block_t * x)
113{
114	avrule_decl_t *decl;
115	if (x == NULL) {
116		return;
117	}
118	decl = x->branch_list;
119	while (decl != NULL) {
120		avrule_decl_t *next_decl = decl->next;
121		avrule_decl_destroy(decl);
122		decl = next_decl;
123	}
124	free(x);
125}
126
127void avrule_block_list_destroy(avrule_block_t * x)
128{
129	while (x != NULL) {
130		avrule_block_t *next = x->next;
131		avrule_block_destroy(x);
132		x = next;
133	}
134}
135
136/* Get a conditional node from a avrule_decl with the same expression.
137 * If that expression does not exist then create one. */
138cond_list_t *get_decl_cond_list(policydb_t * p, avrule_decl_t * decl,
139				cond_list_t * cond)
140{
141	cond_list_t *result;
142	int was_created;
143	result = cond_node_find(p, cond, decl->cond_list, &was_created);
144	if (result != NULL && was_created) {
145		result->next = decl->cond_list;
146		decl->cond_list = result;
147	}
148	return result;
149}
150
151/* Look up an identifier in a policy's scoping table.  If it is there,
152 * marked as SCOPE_DECL, and any of its declaring block has been enabled,
153 * then return 1.  Otherwise return 0. Can only be called after the
154 * decl_val_to_struct index has been created */
155int is_id_enabled(char *id, policydb_t * p, int symbol_table)
156{
157	scope_datum_t *scope =
158	    (scope_datum_t *) hashtab_search(p->scope[symbol_table].table, id);
159	avrule_decl_t *decl;
160	uint32_t len = scope->decl_ids_len;
161
162	if (scope == NULL) {
163		return 0;
164	}
165	if (scope->scope != SCOPE_DECL) {
166		return 0;
167	}
168
169	if (len < 1) {
170		return 0;
171	}
172
173	if (symbol_table == SYM_ROLES || symbol_table == SYM_USERS) {
174		uint32_t i;
175		for (i = 0; i < len; i++) {
176			decl = p->decl_val_to_struct[scope->decl_ids[i] - 1];
177			if (decl != NULL && decl->enabled) {
178				return 1;
179			}
180		}
181	} else {
182		decl = p->decl_val_to_struct[scope->decl_ids[len-1] - 1];
183		if (decl != NULL && decl->enabled) {
184			return 1;
185		}
186	}
187
188	return 0;
189}
190
191/* Check if a particular permission is present within the given class,
192 * and that the class is enabled.  Returns 1 if both conditions are
193 * true, 0 if neither could be found or if the class id disabled. */
194int is_perm_enabled(char *class_id, char *perm_id, policydb_t * p)
195{
196	class_datum_t *cladatum;
197	perm_datum_t *perm;
198	if (!is_id_enabled(class_id, p, SYM_CLASSES)) {
199		return 0;
200	}
201	cladatum =
202	    (class_datum_t *) hashtab_search(p->p_classes.table, class_id);
203	if (cladatum == NULL) {
204		return 0;
205	}
206	perm = hashtab_search(cladatum->permissions.table, perm_id);
207	if (perm == NULL && cladatum->comdatum != 0) {
208		/* permission was not in this class.  before giving
209		 * up, check the class's parent */
210		perm =
211		    hashtab_search(cladatum->comdatum->permissions.table,
212				   perm_id);
213	}
214	if (perm == NULL) {
215		return 0;
216	}
217	return 1;
218}
219