• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice,
8  *       this list of conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice,
11  *       this list of conditions and the following disclaimer in the documentation
12  *       and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * The views and conclusions contained in the software and documentation are those
26  * of the authors and should not be interpreted as representing official policies,
27  * either expressed or implied, of Tresys Technology, LLC.
28  */
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34 
35 #include <sepol/policydb/conditional.h>
36 
37 #include "cil_internal.h"
38 #include "cil_flavor.h"
39 #include "cil_log.h"
40 #include "cil_mem.h"
41 #include "cil_tree.h"
42 #include "cil_list.h"
43 #include "cil_parser.h"
44 #include "cil_build_ast.h"
45 #include "cil_copy_ast.h"
46 #include "cil_verify.h"
47 #include "cil_strpool.h"
48 
49 struct cil_args_build {
50 	struct cil_tree_node *ast;
51 	struct cil_db *db;
52 	struct cil_tree_node *tunif;
53 	struct cil_tree_node *in;
54 	struct cil_tree_node *macro;
55 	struct cil_tree_node *optional;
56 	struct cil_tree_node *boolif;
57 };
58 
cil_fill_list(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** list)59 static int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list)
60 {
61 	int rc = SEPOL_ERR;
62 	struct cil_tree_node *curr;
63 	enum cil_syntax syntax[] = {
64 		CIL_SYN_N_STRINGS,
65 		CIL_SYN_END
66 	};
67 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
68 
69 	rc = __cil_verify_syntax(current, syntax, syntax_len);
70 	if (rc != SEPOL_OK) {
71 		goto exit;
72  	}
73 
74 	cil_list_init(list, flavor);
75 
76 	for (curr = current; curr != NULL; curr = curr->next) {
77 		cil_list_append(*list, CIL_STRING, curr->data);
78 	}
79 
80 	return SEPOL_OK;
81 
82 exit:
83 	return rc;
84 }
85 
cil_gen_declared_string(struct cil_db * db,hashtab_key_t key,struct cil_tree_node * ast_node)86 struct cil_symtab_datum *cil_gen_declared_string(struct cil_db *db, hashtab_key_t key, struct cil_tree_node *ast_node)
87 {
88 	struct cil_tree_node *parent = ast_node->parent;
89 	struct cil_macro *macro = NULL;
90 	symtab_t *symtab;
91 	struct cil_symtab_datum *datum;
92 
93 	while (parent) {
94 		if (parent->flavor == CIL_MACRO) {
95 			/* This condition is only reached in the build phase */
96 			macro = parent->data;
97 			break;
98 		} else if (parent->flavor == CIL_CALL) {
99 			/* This condition is only reached in the resolve phase */
100 			struct cil_call *call = parent->data;
101 			macro = call->macro;
102 			break;
103 		}
104 		parent = parent->parent;
105 	}
106 
107 	if (macro && macro->params) {
108 		struct cil_list_item *item;
109 		cil_list_for_each(item, macro->params) {
110 			struct cil_param *param = item->data;
111 			if (param->flavor == CIL_DECLARED_STRING && param->str == key) {
112 				return NULL;
113 			}
114 		}
115 	}
116 
117 	symtab = &((struct cil_root *)db->ast->root->data)->symtab[CIL_SYM_STRINGS];
118 	cil_symtab_get_datum(symtab, key, &datum);
119 	if (datum != NULL) {
120 		return datum;
121 	}
122 
123 	datum = cil_malloc(sizeof(*datum));
124 	cil_symtab_datum_init(datum);
125 	cil_symtab_insert(symtab, key, datum, ast_node);
126 	cil_list_append(db->declared_strings, CIL_DATUM, datum);
127 	return datum;
128 }
129 
130 
cil_allow_multiple_decls(struct cil_db * db,enum cil_flavor f_new,enum cil_flavor f_old)131 static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, enum cil_flavor f_old)
132 {
133 	if (f_new != f_old) {
134 		return CIL_FALSE;
135 	}
136 
137 	switch (f_new) {
138 	case CIL_TYPE:
139 	case CIL_TYPEATTRIBUTE:
140 		if (db->multiple_decls) {
141 			return CIL_TRUE;
142 		}
143 		break;
144 	case CIL_OPTIONAL:
145 		return CIL_TRUE;
146 		break;
147 	default:
148 		break;
149 	}
150 
151 	return CIL_FALSE;
152 }
153 
cil_add_decl_to_symtab(struct cil_db * db,symtab_t * symtab,hashtab_key_t key,struct cil_symtab_datum * datum,struct cil_tree_node * node)154 int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node)
155 {
156 	int rc;
157 
158 	if (symtab == NULL || datum == NULL || node == NULL) {
159 		return SEPOL_ERR;
160 	}
161 
162 	rc = cil_symtab_insert(symtab, key, datum, node);
163 	if (rc == SEPOL_EEXIST) {
164 		struct cil_symtab_datum *prev;
165 		rc = cil_symtab_get_datum(symtab, key, &prev);
166 		if (rc != SEPOL_OK) {
167 			cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(node), key);
168 			return SEPOL_ERR;
169 		}
170 		if (!cil_allow_multiple_decls(db, node->flavor, FLAVOR(prev))) {
171 			/* multiple_decls not ok, ret error */
172 			struct cil_tree_node *n = NODE(prev);
173 			cil_log(CIL_ERR, "Re-declaration of %s %s\n",
174 				cil_node_to_string(node), key);
175 			cil_tree_log(node, CIL_ERR, "Previous declaration of %s",
176 				     cil_node_to_string(n));
177 			return SEPOL_ERR;
178 		}
179 		/* multiple_decls is enabled and works for this datum type, add node */
180 		cil_list_append(prev->nodes, CIL_NODE, node);
181 		node->data = prev;
182 		return SEPOL_EEXIST;
183 	}
184 
185 	return SEPOL_OK;
186 }
187 
cil_gen_node(struct cil_db * db,struct cil_tree_node * ast_node,struct cil_symtab_datum * datum,hashtab_key_t key,enum cil_sym_index sflavor,enum cil_flavor nflavor)188 int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor)
189 {
190 	int rc = SEPOL_ERR;
191 	symtab_t *symtab = NULL;
192 
193 	rc = cil_verify_name(db, (const char*)key, nflavor);
194 	if (rc != SEPOL_OK) {
195 		goto exit;
196 	}
197 
198 	rc = cil_get_symtab(ast_node->parent, &symtab, sflavor);
199 	if (rc != SEPOL_OK) {
200 		goto exit;
201 	}
202 
203 	ast_node->data = datum;
204 	ast_node->flavor = nflavor;
205 
206 	rc = cil_add_decl_to_symtab(db, symtab, key, datum, ast_node);
207 	if (rc != SEPOL_OK) {
208 		goto exit;
209 	}
210 
211 	if (ast_node->parent->flavor == CIL_MACRO) {
212 		rc = cil_verify_decl_does_not_shadow_macro_parameter(ast_node->parent->data, ast_node, key);
213 		if (rc != SEPOL_OK) {
214 			goto exit;
215 		}
216 	}
217 
218 	return SEPOL_OK;
219 
220 exit:
221 	return rc;
222 }
223 
cil_clear_node(struct cil_tree_node * ast_node)224 static void cil_clear_node(struct cil_tree_node *ast_node)
225 {
226 	if (ast_node == NULL) {
227 		return;
228 	}
229 
230 	ast_node->data = NULL;
231 	ast_node->flavor = CIL_NONE;
232 }
233 
cil_gen_ordered(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)234 int cil_gen_ordered(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
235 {
236 	enum cil_syntax syntax[] = {
237 		CIL_SYN_STRING,
238 		CIL_SYN_LIST,
239 		CIL_SYN_END
240 	};
241 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
242 	struct cil_ordered *ordered = NULL;
243 	struct cil_list_item *curr = NULL;
244 
245 	int rc = SEPOL_ERR;
246 
247 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
248 		goto exit;
249 	}
250 
251 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
252 	if (rc !=  SEPOL_OK) {
253 		goto exit;
254 	}
255 
256 	cil_ordered_init(&ordered);
257 
258 	rc = cil_fill_list(parse_current->next->cl_head, flavor, &ordered->strs);
259 	if (rc != SEPOL_OK) {
260 		goto exit;
261 	}
262 
263 	cil_list_for_each(curr, ordered->strs) {
264 		if (curr->data == CIL_KEY_UNORDERED) {
265 			if (flavor == CIL_CLASSORDER) {
266 				if (curr == ordered->strs->head && curr->next == NULL) {
267 					cil_log(CIL_ERR, "classorder 'unordered' keyword must be followed by one or more class.\n");
268 					rc = SEPOL_ERR;
269 					goto exit;
270 				} else if (curr != ordered->strs->head) {
271 					cil_log(CIL_ERR, "classorder can only use 'unordered' keyword as the first item in the list.\n");
272 					rc = SEPOL_ERR;
273 					goto exit;
274 				}
275 			} else {
276 				cil_log(CIL_ERR, "The 'unordered' keyword can only be used with classorder rules.\n");
277 				rc = SEPOL_ERR;
278 				goto exit;
279 			}
280 		}
281 	}
282 
283 	ast_node->data = ordered;
284 	ast_node->flavor = flavor;
285 
286 	return SEPOL_OK;
287 
288 exit:
289 	cil_tree_log(parse_current, CIL_ERR, "Bad ordered declaration");
290 	cil_destroy_ordered(ordered);
291 	return rc;
292 }
293 
cil_destroy_ordered(struct cil_ordered * ordered)294 void cil_destroy_ordered(struct cil_ordered *ordered)
295 {
296 	if (ordered == NULL) {
297 		return;
298 	}
299 
300 	if (ordered->strs != NULL) {
301 		cil_list_destroy(&ordered->strs, CIL_FALSE);
302 	}
303 	if (ordered->datums != NULL) {
304 		cil_list_destroy(&ordered->datums, CIL_FALSE);
305 	}
306 
307 	free(ordered);
308 }
309 
310 
cil_gen_block(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint16_t is_abstract)311 int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract)
312 {
313 	enum cil_syntax syntax[] = {
314 		CIL_SYN_STRING,
315 		CIL_SYN_STRING,
316 		CIL_SYN_N_LISTS | CIL_SYN_END,
317 		CIL_SYN_END
318 	};
319 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
320 	char *key = NULL;
321 	struct cil_block *block = NULL;
322 	int rc = SEPOL_ERR;
323 
324 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
325 		goto exit;
326 	}
327 
328 	if (db->qualified_names) {
329 		cil_log(CIL_ERR, "Blocks are not allowed when the option for qualified names is used\n");
330 		goto exit;
331 	}
332 
333 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
334 	if (rc != SEPOL_OK) {
335 		goto exit;
336 	}
337 
338 	cil_block_init(&block);
339 
340 	block->is_abstract = is_abstract;
341 
342 	key = parse_current->next->data;
343 
344 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)block, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_BLOCK);
345 	if (rc != SEPOL_OK) {
346 		goto exit;
347 	}
348 
349 	return SEPOL_OK;
350 
351 exit:
352 	cil_tree_log(parse_current, CIL_ERR, "Bad block declaration");
353 	cil_destroy_block(block);
354 	cil_clear_node(ast_node);
355 	return rc;
356 }
357 
cil_destroy_block(struct cil_block * block)358 void cil_destroy_block(struct cil_block *block)
359 {
360 	struct cil_list_item *item;
361 	struct cil_tree_node *bi_node;
362 	struct cil_blockinherit *inherit;
363 
364 	if (block == NULL) {
365 		return;
366 	}
367 
368 	cil_symtab_datum_destroy(&block->datum);
369 	cil_symtab_array_destroy(block->symtab);
370 	if (block->bi_nodes != NULL) {
371 		/* unlink blockinherit->block */
372 		cil_list_for_each(item, block->bi_nodes) {
373 			bi_node = item->data;
374 			/* the conditions should always be true, but better be sure */
375 			if (bi_node->flavor == CIL_BLOCKINHERIT) {
376 				inherit = bi_node->data;
377 				if (inherit->block == block) {
378 					inherit->block = NULL;
379 				}
380 			}
381 		}
382 		cil_list_destroy(&block->bi_nodes, CIL_FALSE);
383 	}
384 
385 	free(block);
386 }
387 
cil_gen_blockinherit(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)388 int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
389 {
390 	enum cil_syntax syntax[] = {
391 		CIL_SYN_STRING,
392 		CIL_SYN_STRING,
393 		CIL_SYN_END
394 	};
395 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
396 	struct cil_blockinherit *inherit = NULL;
397 	int rc = SEPOL_ERR;
398 
399 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
400 		goto exit;
401 	}
402 
403 	if (db->qualified_names) {
404 		cil_log(CIL_ERR, "Block inherit rules are not allowed when the option for qualified names is used\n");
405 		goto exit;
406 	}
407 
408 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
409 	if (rc != SEPOL_OK) {
410 		goto exit;
411 	}
412 
413 	cil_blockinherit_init(&inherit);
414 
415 	inherit->block_str = parse_current->next->data;
416 
417 	ast_node->data = inherit;
418 	ast_node->flavor = CIL_BLOCKINHERIT;
419 
420 	return SEPOL_OK;
421 
422 exit:
423 	cil_tree_log(parse_current, CIL_ERR, "Bad blockinherit declaration");
424 	cil_destroy_blockinherit(inherit);
425 	return rc;
426 }
427 
cil_destroy_blockinherit(struct cil_blockinherit * inherit)428 void cil_destroy_blockinherit(struct cil_blockinherit *inherit)
429 {
430 	if (inherit == NULL) {
431 		return;
432 	}
433 
434 	if (inherit->block != NULL && inherit->block->bi_nodes != NULL) {
435 		struct cil_tree_node *node;
436 		struct cil_list_item *item;
437 
438 		cil_list_for_each(item, inherit->block->bi_nodes) {
439 			node = item->data;
440 			if (node->data == inherit) {
441 				cil_list_remove(inherit->block->bi_nodes, CIL_NODE, node, CIL_FALSE);
442 				break;
443 			}
444 		}
445 	}
446 
447 	free(inherit);
448 }
449 
cil_gen_blockabstract(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)450 int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
451 {
452 	enum cil_syntax syntax[] = {
453 		CIL_SYN_STRING,
454 		CIL_SYN_STRING,
455 		CIL_SYN_END
456 	};
457 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
458 	struct cil_blockabstract *abstract = NULL;
459 	int rc = SEPOL_ERR;
460 
461 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
462 		goto exit;
463 	}
464 
465 	if (db->qualified_names) {
466 		cil_log(CIL_ERR, "Block abstract rules are not allowed when the option for qualified names is used\n");
467 		goto exit;
468 	}
469 
470 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
471 	if (rc != SEPOL_OK) {
472 		goto exit;
473 	}
474 
475 	cil_blockabstract_init(&abstract);
476 
477 	abstract->block_str = parse_current->next->data;
478 
479 	ast_node->data = abstract;
480 	ast_node->flavor = CIL_BLOCKABSTRACT;
481 
482 	return SEPOL_OK;
483 
484 exit:
485 	cil_tree_log(parse_current, CIL_ERR, "Bad blockabstract declaration");
486 	cil_destroy_blockabstract(abstract);
487 	return rc;
488 }
489 
cil_destroy_blockabstract(struct cil_blockabstract * abstract)490 void cil_destroy_blockabstract(struct cil_blockabstract *abstract)
491 {
492 	if (abstract == NULL) {
493 		return;
494 	}
495 
496 	free(abstract);
497 }
498 
cil_gen_in(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)499 int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
500 {
501 	enum cil_syntax syntax[] = {
502 		CIL_SYN_STRING,
503 		CIL_SYN_STRING,
504 		CIL_SYN_STRING | CIL_SYN_N_LISTS,
505 		CIL_SYN_N_LISTS | CIL_SYN_END,
506 		CIL_SYN_END
507 	};
508 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
509 	int rc = SEPOL_ERR;
510 	struct cil_in *in = NULL;
511 
512 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
513 		goto exit;
514 	}
515 
516 	if (db->qualified_names) {
517 		cil_log(CIL_ERR, "In-statements are not allowed when the option for qualified names is used\n");
518 		goto exit;
519 	}
520 
521 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
522 	if (rc != SEPOL_OK) {
523 		goto exit;
524 	}
525 
526 	cil_in_init(&in);
527 
528 	if (parse_current->next->next->data) {
529 		char *is_after_str = parse_current->next->data;
530 		if (is_after_str == CIL_KEY_IN_BEFORE) {
531 			in->is_after = CIL_FALSE;
532 		} else if (is_after_str == CIL_KEY_IN_AFTER) {
533 			in->is_after = CIL_TRUE;
534 		} else {
535 			cil_log(CIL_ERR, "Value must be either \'before\' or \'after\'\n");
536 			rc = SEPOL_ERR;
537 			goto exit;
538 		}
539 		in->block_str = parse_current->next->next->data;
540 	} else {
541 		in->is_after = CIL_FALSE;
542 		in->block_str = parse_current->next->data;
543 	}
544 
545 	ast_node->data = in;
546 	ast_node->flavor = CIL_IN;
547 
548 	return SEPOL_OK;
549 exit:
550 	cil_tree_log(parse_current, CIL_ERR, "Bad in-statement");
551 	cil_destroy_in(in);
552 	return rc;
553 }
554 
cil_destroy_in(struct cil_in * in)555 void cil_destroy_in(struct cil_in *in)
556 {
557 	if (in == NULL) {
558 		return;
559 	}
560 
561 	cil_symtab_array_destroy(in->symtab);
562 
563 	free(in);
564 }
565 
cil_gen_class(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)566 int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
567 {
568 	enum cil_syntax syntax[] = {
569 		CIL_SYN_STRING,
570 		CIL_SYN_STRING,
571 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
572 		CIL_SYN_END
573 	};
574 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
575 	char *key = NULL;
576 	struct cil_class *class = NULL;
577 	struct cil_tree_node *perms = NULL;
578 	int rc = SEPOL_ERR;
579 
580 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
581 	if (rc != SEPOL_OK) {
582 		goto exit;
583 	}
584 
585 	cil_class_init(&class);
586 
587 	key = parse_current->next->data;
588 	if (key == CIL_KEY_UNORDERED) {
589 		cil_log(CIL_ERR, "'unordered' keyword is reserved and not a valid class name.\n");
590 		rc = SEPOL_ERR;
591 		goto exit;
592 	}
593 
594 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)class, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_CLASS);
595 	if (rc != SEPOL_OK) {
596 		goto exit;
597 	}
598 
599 	if (parse_current->next->next != NULL) {
600 		perms = parse_current->next->next->cl_head;
601 		rc = cil_gen_perm_nodes(db, perms, ast_node, CIL_PERM, &class->num_perms);
602 		if (rc != SEPOL_OK) {
603 			goto exit;
604 		}
605 		if (class->num_perms > CIL_PERMS_PER_CLASS) {
606 			cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name);
607 			cil_tree_children_destroy(ast_node);
608 			rc = SEPOL_ERR;
609 			goto exit;
610 		}
611 
612 	}
613 
614 	return SEPOL_OK;
615 
616 exit:
617 	cil_tree_log(parse_current, CIL_ERR, "Bad class declaration");
618 	cil_destroy_class(class);
619 	cil_clear_node(ast_node);
620 	return rc;
621 }
622 
cil_destroy_class(struct cil_class * class)623 void cil_destroy_class(struct cil_class *class)
624 {
625 	if (class == NULL) {
626 		return;
627 	}
628 
629 	cil_symtab_datum_destroy(&class->datum);
630 	cil_symtab_destroy(&class->perms);
631 
632 	free(class);
633 }
634 
cil_gen_perm(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor,unsigned int * num_perms)635 int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms)
636 {
637 	char *key = NULL;
638 	struct cil_perm *perm = NULL;
639 	int rc = SEPOL_ERR;
640 
641 	cil_perm_init(&perm);
642 
643 	key = parse_current->data;
644 	if (key == NULL) {
645 		cil_log(CIL_ERR, "Bad permission\n");
646 		goto exit;
647 	}
648 
649 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)perm, (hashtab_key_t)key, CIL_SYM_PERMS, flavor);
650 	if (rc != SEPOL_OK) {
651 		goto exit;
652 	}
653 
654 	perm->value = *num_perms;
655 	(*num_perms)++;
656 
657 	return SEPOL_OK;
658 
659 exit:
660 	cil_destroy_perm(perm);
661 	cil_clear_node(ast_node);
662 	return rc;
663 }
664 
cil_destroy_perm(struct cil_perm * perm)665 void cil_destroy_perm(struct cil_perm *perm)
666 {
667 	if (perm == NULL) {
668 		return;
669 	}
670 
671 	cil_symtab_datum_destroy(&perm->datum);
672 	cil_list_destroy(&perm->classperms, CIL_FALSE);
673 
674 	free(perm);
675 }
676 
cil_gen_perm_nodes(struct cil_db * db,struct cil_tree_node * current_perm,struct cil_tree_node * ast_node,enum cil_flavor flavor,unsigned int * num_perms)677 int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm, struct cil_tree_node *ast_node, enum cil_flavor flavor, unsigned int *num_perms)
678 {
679 	int rc = SEPOL_ERR;
680 	struct cil_tree_node *new_ast = NULL;
681 
682 	while(current_perm != NULL) {
683 		if (current_perm->cl_head != NULL) {
684 
685 			rc = SEPOL_ERR;
686 			goto exit;
687 		}
688 		cil_tree_node_init(&new_ast);
689 		new_ast->parent = ast_node;
690 		new_ast->line = current_perm->line;
691 		new_ast->hll_offset = current_perm->hll_offset;
692 
693 		rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms);
694 		if (rc != SEPOL_OK) {
695 			cil_tree_node_destroy(&new_ast);
696 			goto exit;
697 		}
698 
699 		if (ast_node->cl_head == NULL) {
700 			ast_node->cl_head = new_ast;
701 		} else {
702 			ast_node->cl_tail->next = new_ast;
703 		}
704 		ast_node->cl_tail = new_ast;
705 
706 		current_perm = current_perm->next;
707 	}
708 
709 	return SEPOL_OK;
710 
711 exit:
712 	cil_log(CIL_ERR, "Bad permissions\n");
713 	cil_tree_children_destroy(ast_node);
714 	cil_clear_node(ast_node);
715 	return rc;
716 }
717 
cil_fill_perms(struct cil_tree_node * start_perm,struct cil_list ** perms)718 int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms)
719 {
720 	int rc = SEPOL_ERR;
721 	enum cil_syntax syntax[] = {
722 		CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS,
723 		CIL_SYN_END
724 	};
725 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
726 
727 	rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len);
728 	if (rc != SEPOL_OK) {
729 		goto exit;
730 	}
731 
732 	rc = cil_gen_expr(start_perm, CIL_PERM, perms);
733 	if (rc != SEPOL_OK) {
734 		goto exit;
735 	}
736 
737 	return SEPOL_OK;
738 
739 exit:
740 	cil_log(CIL_ERR, "Bad permission list or expression\n");
741 	return rc;
742 }
743 
cil_fill_classperms(struct cil_tree_node * parse_current,struct cil_classperms ** cp)744 int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classperms **cp)
745 {
746 	int rc = SEPOL_ERR;
747 	enum cil_syntax syntax[] = {
748 		CIL_SYN_STRING,
749 		CIL_SYN_LIST,
750 		CIL_SYN_END
751 	};
752 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
753 
754 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
755 	if (rc != SEPOL_OK) {
756 		goto exit;
757 	}
758 
759 	cil_classperms_init(cp);
760 
761 	(*cp)->class_str = parse_current->data;
762 
763 	rc = cil_fill_perms(parse_current->next, &(*cp)->perm_strs);
764 	if (rc != SEPOL_OK) {
765 		cil_destroy_classperms(*cp);
766 		goto exit;
767 	}
768 
769 	return SEPOL_OK;
770 
771 exit:
772 	cil_log(CIL_ERR, "Bad class-permissions\n");
773 	*cp = NULL;
774 	return rc;
775 }
776 
cil_destroy_classperms(struct cil_classperms * cp)777 void cil_destroy_classperms(struct cil_classperms *cp)
778 {
779 	if (cp == NULL) {
780 		return;
781 	}
782 
783 	cil_list_destroy(&cp->perm_strs, CIL_TRUE);
784 	cil_list_destroy(&cp->perms, CIL_FALSE);
785 
786 	free(cp);
787 }
788 
cil_fill_classperms_set(struct cil_tree_node * parse_current,struct cil_classperms_set ** cp_set)789 void cil_fill_classperms_set(struct cil_tree_node *parse_current, struct cil_classperms_set **cp_set)
790 {
791 	cil_classperms_set_init(cp_set);
792 	(*cp_set)->set_str = parse_current->data;
793 }
794 
cil_destroy_classperms_set(struct cil_classperms_set * cp_set)795 void cil_destroy_classperms_set(struct cil_classperms_set *cp_set)
796 {
797 	if (cp_set == NULL) {
798 		return;
799 	}
800 
801 	free(cp_set);
802 }
803 
cil_fill_classperms_list(struct cil_tree_node * parse_current,struct cil_list ** cp_list)804 int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_list **cp_list)
805 {
806 	int rc = SEPOL_ERR;
807 	struct cil_tree_node *curr;
808 
809 	if (parse_current == NULL || cp_list == NULL) {
810 		goto exit;
811 	}
812 
813 	cil_list_init(cp_list, CIL_CLASSPERMS);
814 
815 	curr = parse_current->cl_head;
816 
817 	if (curr == NULL) {
818 		/* Class-perms form: SET1 */
819 		struct cil_classperms_set *new_cp_set;
820 		cil_fill_classperms_set(parse_current, &new_cp_set);
821 		cil_list_append(*cp_list, CIL_CLASSPERMS_SET, new_cp_set);
822 	} else if (curr->cl_head == NULL) {
823 		/* Class-perms form: (CLASS1 (PERM1 ...)) */
824 		struct cil_classperms *new_cp;
825 		rc = cil_fill_classperms(curr, &new_cp);
826 		if (rc != SEPOL_OK) {
827 			goto exit;
828 		}
829 		cil_list_append(*cp_list, CIL_CLASSPERMS, new_cp);
830 	} else {
831 		cil_log(CIL_ERR, "Bad class-permissions list syntax\n");
832 		rc = SEPOL_ERR;
833 		goto exit;
834 	}
835 
836 	return SEPOL_OK;
837 
838 exit:
839 	cil_log(CIL_ERR, "Problem filling class-permissions list\n");
840 	cil_list_destroy(cp_list, CIL_TRUE);
841 	return rc;
842 }
843 
cil_destroy_classperms_list(struct cil_list ** cp_list)844 void cil_destroy_classperms_list(struct cil_list **cp_list)
845 {
846 	struct cil_list_item *curr;
847 
848 	if (cp_list == NULL || *cp_list == NULL) {
849 		return;
850 	}
851 
852 	cil_list_for_each(curr, *cp_list) {
853 		if (curr->flavor == CIL_CLASSPERMS) {
854 			cil_destroy_classperms(curr->data);
855 		} else {
856 			cil_destroy_classperms_set(curr->data);
857 		}
858 	}
859 
860 	cil_list_destroy(cp_list, CIL_FALSE);
861 }
862 
cil_gen_classpermission(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)863 int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
864 {
865 	int rc = SEPOL_ERR;
866 	char *key = NULL;
867 	struct cil_classpermission *cp = NULL;
868 	enum cil_syntax syntax[] = {
869 		CIL_SYN_STRING,
870 		CIL_SYN_STRING,
871 		CIL_SYN_END
872 	};
873 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
874 
875 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
876 		goto exit;
877 	}
878 
879 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
880 	if (rc != SEPOL_OK) {
881 		goto exit;
882 	}
883 
884 	cil_classpermission_init(&cp);
885 
886 	key = parse_current->next->data;
887 
888 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cp, (hashtab_key_t)key, CIL_SYM_CLASSPERMSETS, CIL_CLASSPERMISSION);
889 	if (rc != SEPOL_OK) {
890 		goto exit;
891 	}
892 
893 	return SEPOL_OK;
894 
895 exit:
896 	cil_tree_log(parse_current, CIL_ERR, "Bad classpermission declaration");
897 	cil_destroy_classpermission(cp);
898 	cil_clear_node(ast_node);
899 	return rc;
900 }
901 
cil_destroy_classpermission(struct cil_classpermission * cp)902 void cil_destroy_classpermission(struct cil_classpermission *cp)
903 {
904 	if (cp == NULL) {
905 		return;
906 	}
907 
908 	if (cp->datum.name != NULL) {
909 		cil_list_destroy(&cp->classperms, CIL_FALSE);
910 	} else {
911 		/* anonymous classpermission from call */
912 		cil_destroy_classperms_list(&cp->classperms);
913 	}
914 
915 	cil_symtab_datum_destroy(&cp->datum);
916 
917 
918 	free(cp);
919 }
920 
cil_gen_classpermissionset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)921 int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
922 {
923 	int rc = SEPOL_ERR;
924 	struct cil_classpermissionset *cps = NULL;
925 	enum cil_syntax syntax[] = {
926 		CIL_SYN_STRING,
927 		CIL_SYN_STRING,
928 		CIL_SYN_STRING | CIL_SYN_LIST,
929 		CIL_SYN_END
930 	};
931 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
932 
933 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
934 		goto exit;
935 	}
936 
937 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
938 	if (rc != SEPOL_OK) {
939 		goto exit;
940 	}
941 
942 	cil_classpermissionset_init(&cps);
943 
944 	cps->set_str = parse_current->next->data;
945 
946 	rc = cil_fill_classperms_list(parse_current->next->next, &cps->classperms);
947 	if (rc != SEPOL_OK) {
948 		goto exit;
949 	}
950 
951 	ast_node->data = cps;
952 	ast_node->flavor = CIL_CLASSPERMISSIONSET;
953 
954 	return SEPOL_OK;
955 
956 exit:
957 	cil_tree_log(parse_current, CIL_ERR, "Bad classpermissionset");
958 	cil_destroy_classpermissionset(cps);
959 	return rc;
960 }
961 
cil_destroy_classpermissionset(struct cil_classpermissionset * cps)962 void cil_destroy_classpermissionset(struct cil_classpermissionset *cps)
963 {
964 	if (cps == NULL) {
965 		return;
966 	}
967 
968 	cil_destroy_classperms_list(&cps->classperms);
969 
970 	free(cps);
971 }
972 
cil_gen_map_class(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)973 int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
974 {
975 	enum cil_syntax syntax[] = {
976 		CIL_SYN_STRING,
977 		CIL_SYN_STRING,
978 		CIL_SYN_LIST,
979 		CIL_SYN_END
980 	};
981 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
982 	char *key = NULL;
983 	struct cil_class *map = NULL;
984 	int rc = SEPOL_ERR;
985 
986 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
987 	if (rc != SEPOL_OK) {
988 		goto exit;
989 	}
990 
991 	cil_class_init(&map);
992 
993 	key = parse_current->next->data;
994 
995 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)map, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_MAP_CLASS);
996 	if (rc != SEPOL_OK) {
997 		goto exit;
998 	}
999 
1000 	rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_MAP_PERM, &map->num_perms);
1001 	if (rc != SEPOL_OK) {
1002 		goto exit;
1003 	}
1004 
1005 	return SEPOL_OK;
1006 
1007 exit:
1008 	cil_tree_log(parse_current, CIL_ERR, "Bad map class declaration");
1009 	cil_destroy_class(map);
1010 	cil_clear_node(ast_node);
1011 	return rc;
1012 }
1013 
cil_gen_classmapping(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1014 int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1015 {
1016 	int rc = SEPOL_ERR;
1017 	struct cil_classmapping *mapping = NULL;
1018 	enum cil_syntax syntax[] = {
1019 		CIL_SYN_STRING,
1020 		CIL_SYN_STRING,
1021 		CIL_SYN_STRING,
1022 		CIL_SYN_STRING | CIL_SYN_LIST,
1023 		CIL_SYN_END
1024 	};
1025 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1026 
1027 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1028 		goto exit;
1029 	}
1030 
1031 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1032 	if (rc != SEPOL_OK) {
1033 		goto exit;
1034 	}
1035 
1036 	cil_classmapping_init(&mapping);
1037 
1038 	mapping->map_class_str = parse_current->next->data;
1039 	mapping->map_perm_str = parse_current->next->next->data;
1040 
1041 	rc = cil_fill_classperms_list(parse_current->next->next->next, &mapping->classperms);
1042 	if (rc != SEPOL_OK) {
1043 		goto exit;
1044 	}
1045 
1046 	ast_node->data = mapping;
1047 	ast_node->flavor = CIL_CLASSMAPPING;
1048 
1049 	return SEPOL_OK;
1050 
1051 exit:
1052 	cil_tree_log(parse_current, CIL_ERR, "Bad classmapping declaration");
1053 	cil_destroy_classmapping(mapping);
1054 	return rc;
1055 }
1056 
cil_destroy_classmapping(struct cil_classmapping * mapping)1057 void cil_destroy_classmapping(struct cil_classmapping *mapping)
1058 {
1059 	if (mapping == NULL) {
1060 		return;
1061 	}
1062 
1063 	cil_destroy_classperms_list(&mapping->classperms);
1064 
1065 	free(mapping);
1066 }
1067 
1068 // TODO try to merge some of this with cil_gen_class (helper function for both)
cil_gen_common(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1069 int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1070 {
1071 	enum cil_syntax syntax[] = {
1072 		CIL_SYN_STRING,
1073 		CIL_SYN_STRING,
1074 		CIL_SYN_LIST,
1075 		CIL_SYN_END
1076 	};
1077 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1078 	char *key = NULL;
1079 	struct cil_class *common = NULL;
1080 	int rc = SEPOL_ERR;
1081 
1082 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1083 		goto exit;
1084 	}
1085 
1086 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1087 	if (rc != SEPOL_OK) {
1088 		goto exit;
1089 	}
1090 
1091 	cil_class_init(&common);
1092 
1093 	key = parse_current->next->data;
1094 
1095 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)common, (hashtab_key_t)key, CIL_SYM_COMMONS, CIL_COMMON);
1096 	if (rc != SEPOL_OK) {
1097 		goto exit;
1098 	}
1099 
1100 	rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_PERM, &common->num_perms);
1101 	if (rc != SEPOL_OK) {
1102 		goto exit;
1103 	}
1104 	if (common->num_perms > CIL_PERMS_PER_CLASS) {
1105 		cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name);
1106 		cil_tree_children_destroy(ast_node);
1107 		rc = SEPOL_ERR;
1108 		goto exit;
1109 	}
1110 
1111 	return SEPOL_OK;
1112 
1113 exit:
1114 	cil_tree_log(parse_current, CIL_ERR, "Bad common declaration");
1115 	cil_destroy_class(common);
1116 	cil_clear_node(ast_node);
1117 	return rc;
1118 
1119 }
1120 
cil_gen_classcommon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1121 int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1122 {
1123 	enum cil_syntax syntax[] = {
1124 		CIL_SYN_STRING,
1125 		CIL_SYN_STRING,
1126 		CIL_SYN_STRING,
1127 		CIL_SYN_END
1128 	};
1129 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1130 	struct cil_classcommon *clscom = NULL;
1131 	int rc = SEPOL_ERR;
1132 
1133 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1134 		goto exit;
1135 	}
1136 
1137 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1138 	if (rc != SEPOL_OK) {
1139 		goto exit;
1140 	}
1141 
1142 	cil_classcommon_init(&clscom);
1143 
1144 	clscom->class_str = parse_current->next->data;
1145 	clscom->common_str = parse_current->next->next->data;
1146 
1147 	ast_node->data = clscom;
1148 	ast_node->flavor = CIL_CLASSCOMMON;
1149 
1150 	return SEPOL_OK;
1151 
1152 exit:
1153 	cil_tree_log(parse_current, CIL_ERR, "Bad classcommon declaration");
1154 	cil_destroy_classcommon(clscom);
1155 	return rc;
1156 
1157 }
1158 
cil_destroy_classcommon(struct cil_classcommon * clscom)1159 void cil_destroy_classcommon(struct cil_classcommon *clscom)
1160 {
1161 	if (clscom == NULL) {
1162 		return;
1163 	}
1164 
1165 	free(clscom);
1166 }
1167 
cil_gen_sid(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1168 int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1169 {
1170 	enum cil_syntax syntax[] = {
1171 		CIL_SYN_STRING,
1172 		CIL_SYN_STRING,
1173 		CIL_SYN_END
1174 	};
1175 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1176 	char *key = NULL;
1177 	struct cil_sid *sid = NULL;
1178 	int rc = SEPOL_ERR;
1179 
1180 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1181 		goto exit;
1182 	}
1183 
1184 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1185 	if (rc != SEPOL_OK) {
1186 		goto exit;
1187 	}
1188 
1189 	cil_sid_init(&sid);
1190 
1191 	key = parse_current->next->data;
1192 
1193 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sid, (hashtab_key_t)key, CIL_SYM_SIDS, CIL_SID);
1194 	if (rc != SEPOL_OK) {
1195 		goto exit;
1196 	}
1197 
1198 	return SEPOL_OK;
1199 
1200 exit:
1201 	cil_tree_log(parse_current, CIL_ERR, "Bad sid declaration");
1202 	cil_destroy_sid(sid);
1203 	cil_clear_node(ast_node);
1204 	return rc;
1205 }
1206 
cil_destroy_sid(struct cil_sid * sid)1207 void cil_destroy_sid(struct cil_sid *sid)
1208 {
1209 	if (sid == NULL) {
1210 		return;
1211 	}
1212 
1213 	cil_symtab_datum_destroy(&sid->datum);
1214 	free(sid);
1215 }
1216 
cil_gen_sidcontext(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1217 int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1218 {
1219 	enum cil_syntax syntax[] = {
1220 		CIL_SYN_STRING,
1221 		CIL_SYN_STRING,
1222 		CIL_SYN_STRING | CIL_SYN_LIST,
1223 		CIL_SYN_END
1224 	};
1225 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1226 	struct cil_sidcontext *sidcon = NULL;
1227 	int rc = SEPOL_ERR;
1228 
1229 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1230 		goto exit;
1231 	}
1232 
1233 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1234 	if (rc != SEPOL_OK) {
1235 		goto exit;
1236 	}
1237 
1238 	cil_sidcontext_init(&sidcon);
1239 
1240 	sidcon->sid_str = parse_current->next->data;
1241 
1242 	if (parse_current->next->next->cl_head == NULL) {
1243 		sidcon->context_str = parse_current->next->next->data;
1244 	} else {
1245 		cil_context_init(&sidcon->context);
1246 
1247 		rc = cil_fill_context(parse_current->next->next->cl_head, sidcon->context);
1248 		if (rc != SEPOL_OK) {
1249 			goto exit;
1250 		}
1251 	}
1252 
1253 	ast_node->data = sidcon;
1254 	ast_node->flavor = CIL_SIDCONTEXT;
1255 
1256 	return SEPOL_OK;
1257 
1258 exit:
1259 	cil_tree_log(parse_current, CIL_ERR, "Bad sidcontext declaration");
1260 	cil_destroy_sidcontext(sidcon);
1261 	return rc;
1262 }
1263 
cil_destroy_sidcontext(struct cil_sidcontext * sidcon)1264 void cil_destroy_sidcontext(struct cil_sidcontext *sidcon)
1265 {
1266 	if (sidcon == NULL) {
1267 		return;
1268 	}
1269 
1270 	if (sidcon->context_str == NULL && sidcon->context != NULL) {
1271 		cil_destroy_context(sidcon->context);
1272 	}
1273 
1274 	free(sidcon);
1275 }
1276 
cil_gen_user(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1277 int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1278 {
1279 	enum cil_syntax syntax[] = {
1280 		CIL_SYN_STRING,
1281 		CIL_SYN_STRING,
1282 		CIL_SYN_END
1283 	};
1284 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1285 	char *key = NULL;
1286 	struct cil_user *user = NULL;
1287 	int rc = SEPOL_ERR;
1288 
1289 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1290 		goto exit;
1291 	}
1292 
1293 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1294 	if (rc != SEPOL_OK) {
1295 		goto exit;
1296 	}
1297 
1298 	cil_user_init(&user);
1299 
1300 	key = parse_current->next->data;
1301 
1302 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)user, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USER);
1303 	if (rc != SEPOL_OK) {
1304 		goto exit;
1305 	}
1306 
1307 	return SEPOL_OK;
1308 
1309 exit:
1310 	cil_tree_log(parse_current, CIL_ERR, "Bad user declaration");
1311 	cil_destroy_user(user);
1312 	cil_clear_node(ast_node);
1313 	return rc;
1314 }
1315 
cil_destroy_user(struct cil_user * user)1316 void cil_destroy_user(struct cil_user *user)
1317 {
1318 	if (user == NULL) {
1319 		return;
1320 	}
1321 
1322 	cil_symtab_datum_destroy(&user->datum);
1323 	ebitmap_destroy(user->roles);
1324 	free(user->roles);
1325 	free(user);
1326 }
1327 
cil_gen_userattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1328 int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1329 {
1330 	enum cil_syntax syntax[] = {
1331 		CIL_SYN_STRING,
1332 		CIL_SYN_STRING,
1333 		CIL_SYN_END
1334 	};
1335 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1336 	char *key = NULL;
1337 	struct cil_userattribute *attr = NULL;
1338 	int rc = SEPOL_ERR;
1339 
1340 	if (parse_current == NULL || ast_node == NULL) {
1341 		goto exit;
1342 	}
1343 
1344 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1345 	if (rc != SEPOL_OK) {
1346 		goto exit;
1347 	}
1348 
1349 	cil_userattribute_init(&attr);
1350 
1351 	key = parse_current->next->data;
1352 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE);
1353 	if (rc != SEPOL_OK) {
1354 		goto exit;
1355 	}
1356 
1357 	return SEPOL_OK;
1358 exit:
1359 	cil_tree_log(parse_current, CIL_ERR, "Bad userattribute declaration");
1360 	cil_destroy_userattribute(attr);
1361 	cil_clear_node(ast_node);
1362 	return rc;
1363 }
1364 
cil_destroy_userattribute(struct cil_userattribute * attr)1365 void cil_destroy_userattribute(struct cil_userattribute *attr)
1366 {
1367 	struct cil_list_item *expr = NULL;
1368 	struct cil_list_item *next = NULL;
1369 
1370 	if (attr == NULL) {
1371 		return;
1372 	}
1373 
1374 	if (attr->expr_list != NULL) {
1375 		/* we don't want to destroy the expression stacks (cil_list) inside
1376 		 * this list cil_list_destroy destroys sublists, so we need to do it
1377 		 * manually */
1378 		expr = attr->expr_list->head;
1379 		while (expr != NULL) {
1380 			next = expr->next;
1381 			cil_list_item_destroy(&expr, CIL_FALSE);
1382 			expr = next;
1383 		}
1384 		free(attr->expr_list);
1385 		attr->expr_list = NULL;
1386 	}
1387 
1388 	cil_symtab_datum_destroy(&attr->datum);
1389 	ebitmap_destroy(attr->users);
1390 	free(attr->users);
1391 	free(attr);
1392 }
1393 
cil_gen_userattributeset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1394 int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1395 {
1396 	enum cil_syntax syntax[] = {
1397 		CIL_SYN_STRING,
1398 		CIL_SYN_STRING,
1399 		CIL_SYN_STRING | CIL_SYN_LIST,
1400 		CIL_SYN_END
1401 	};
1402 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1403 	struct cil_userattributeset *attrset = NULL;
1404 	int rc = SEPOL_ERR;
1405 
1406 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1407 		goto exit;
1408 	}
1409 
1410 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1411 	if (rc != SEPOL_OK) {
1412 		goto exit;
1413 	}
1414 
1415 	cil_userattributeset_init(&attrset);
1416 
1417 	attrset->attr_str = parse_current->next->data;
1418 
1419 	rc = cil_gen_expr(parse_current->next->next, CIL_USER, &attrset->str_expr);
1420 	if (rc != SEPOL_OK) {
1421 		goto exit;
1422 	}
1423 	ast_node->data = attrset;
1424 	ast_node->flavor = CIL_USERATTRIBUTESET;
1425 
1426 	return SEPOL_OK;
1427 
1428 exit:
1429 	cil_tree_log(parse_current, CIL_ERR, "Bad userattributeset declaration");
1430 	cil_destroy_userattributeset(attrset);
1431 
1432 	return rc;
1433 }
1434 
cil_destroy_userattributeset(struct cil_userattributeset * attrset)1435 void cil_destroy_userattributeset(struct cil_userattributeset *attrset)
1436 {
1437 	if (attrset == NULL) {
1438 		return;
1439 	}
1440 
1441 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
1442 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
1443 
1444 	free(attrset);
1445 }
1446 
cil_gen_userlevel(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1447 int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1448 {
1449 	enum cil_syntax syntax[] = {
1450 		CIL_SYN_STRING,
1451 		CIL_SYN_STRING,
1452 		CIL_SYN_STRING | CIL_SYN_LIST,
1453 		CIL_SYN_END
1454 	};
1455 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1456 	struct cil_userlevel *usrlvl = NULL;
1457 	int rc = SEPOL_ERR;
1458 
1459 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1460 		goto exit;
1461 	}
1462 
1463 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1464 	if (rc != SEPOL_OK) {
1465 		goto exit;
1466 	}
1467 
1468 	cil_userlevel_init(&usrlvl);
1469 
1470 	usrlvl->user_str = parse_current->next->data;
1471 
1472 	if (parse_current->next->next->cl_head == NULL) {
1473 		usrlvl->level_str = parse_current->next->next->data;
1474 	} else {
1475 		cil_level_init(&usrlvl->level);
1476 
1477 		rc = cil_fill_level(parse_current->next->next->cl_head, usrlvl->level);
1478 		if (rc != SEPOL_OK) {
1479 			goto exit;
1480 		}
1481 	}
1482 
1483 	ast_node->data = usrlvl;
1484 	ast_node->flavor = CIL_USERLEVEL;
1485 
1486 	return SEPOL_OK;
1487 
1488 exit:
1489 	cil_tree_log(parse_current, CIL_ERR, "Bad userlevel declaration");
1490 	cil_destroy_userlevel(usrlvl);
1491 	return rc;
1492 }
1493 
cil_destroy_userlevel(struct cil_userlevel * usrlvl)1494 void cil_destroy_userlevel(struct cil_userlevel *usrlvl)
1495 {
1496 	if (usrlvl == NULL) {
1497 		return;
1498 	}
1499 
1500 	if (usrlvl->level_str == NULL && usrlvl->level != NULL) {
1501 		cil_destroy_level(usrlvl->level);
1502 	}
1503 
1504 	free(usrlvl);
1505 }
1506 
cil_gen_userrange(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1507 int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1508 {
1509 	enum cil_syntax syntax[] = {
1510 		CIL_SYN_STRING,
1511 		CIL_SYN_STRING,
1512 		CIL_SYN_STRING | CIL_SYN_LIST,
1513 		CIL_SYN_END
1514 	};
1515 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1516 	struct cil_userrange *userrange = NULL;
1517 	int rc = SEPOL_ERR;
1518 
1519 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1520 		goto exit;
1521 	}
1522 
1523 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1524 	if (rc != SEPOL_OK) {
1525 		goto exit;
1526 	}
1527 
1528 	cil_userrange_init(&userrange);
1529 
1530 	userrange->user_str = parse_current->next->data;
1531 
1532 	if (parse_current->next->next->cl_head == NULL) {
1533 		userrange->range_str = parse_current->next->next->data;
1534 	} else {
1535 		cil_levelrange_init(&userrange->range);
1536 
1537 		rc = cil_fill_levelrange(parse_current->next->next->cl_head, userrange->range);
1538 		if (rc != SEPOL_OK) {
1539 			goto exit;
1540 		}
1541 	}
1542 
1543 	ast_node->data = userrange;
1544 	ast_node->flavor = CIL_USERRANGE;
1545 
1546 	return SEPOL_OK;
1547 
1548 exit:
1549 	cil_tree_log(parse_current, CIL_ERR, "Bad userrange declaration");
1550 	cil_destroy_userrange(userrange);
1551 	return rc;
1552 }
1553 
cil_destroy_userrange(struct cil_userrange * userrange)1554 void cil_destroy_userrange(struct cil_userrange *userrange)
1555 {
1556 	if (userrange == NULL) {
1557 		return;
1558 	}
1559 
1560 	if (userrange->range_str == NULL && userrange->range != NULL) {
1561 		cil_destroy_levelrange(userrange->range);
1562 	}
1563 
1564 	free(userrange);
1565 }
1566 
cil_gen_userprefix(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1567 int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1568 {
1569 	enum cil_syntax syntax[] = {
1570 		CIL_SYN_STRING,
1571 		CIL_SYN_STRING,
1572 		CIL_SYN_STRING,
1573 		CIL_SYN_END
1574 	};
1575 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1576 	struct cil_userprefix *userprefix = NULL;
1577 	int rc = SEPOL_ERR;
1578 
1579 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1580 		goto exit;
1581 	}
1582 
1583 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1584 	if (rc != SEPOL_OK) {
1585 		goto exit;
1586 	}
1587 
1588 	cil_userprefix_init(&userprefix);
1589 
1590 	userprefix->user_str = parse_current->next->data;
1591 	userprefix->prefix_str = parse_current->next->next->data;
1592 
1593 	ast_node->data = userprefix;
1594 	ast_node->flavor = CIL_USERPREFIX;
1595 
1596 	return SEPOL_OK;
1597 exit:
1598 	cil_tree_log(parse_current, CIL_ERR, "Bad userprefix declaration");
1599 	cil_destroy_userprefix(userprefix);
1600 	return rc;
1601 }
1602 
cil_destroy_userprefix(struct cil_userprefix * userprefix)1603 void cil_destroy_userprefix(struct cil_userprefix *userprefix)
1604 {
1605 	if (userprefix == NULL) {
1606 		return;
1607 	}
1608 
1609 	free(userprefix);
1610 }
1611 
cil_gen_selinuxuser(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1612 int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1613 {
1614 	enum cil_syntax syntax[] = {
1615 		CIL_SYN_STRING,
1616 		CIL_SYN_STRING,
1617 		CIL_SYN_STRING,
1618 		CIL_SYN_STRING | CIL_SYN_LIST,
1619 		CIL_SYN_END
1620 	};
1621 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1622 	struct cil_selinuxuser *selinuxuser = NULL;
1623 	int rc = SEPOL_ERR;
1624 
1625 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1626 		goto exit;
1627 	}
1628 
1629 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1630 	if (rc != SEPOL_OK) {
1631 		goto exit;
1632 	}
1633 
1634 	cil_selinuxuser_init(&selinuxuser);
1635 
1636 	selinuxuser->name_str = parse_current->next->data;
1637 	selinuxuser->user_str = parse_current->next->next->data;
1638 
1639 	if (parse_current->next->next->next->cl_head == NULL) {
1640 		selinuxuser->range_str = parse_current->next->next->next->data;
1641 	} else {
1642 		cil_levelrange_init(&selinuxuser->range);
1643 
1644 		rc = cil_fill_levelrange(parse_current->next->next->next->cl_head, selinuxuser->range);
1645 		if (rc != SEPOL_OK) {
1646 			goto exit;
1647 		}
1648 	}
1649 
1650 	ast_node->data = selinuxuser;
1651 	ast_node->flavor = CIL_SELINUXUSER;
1652 
1653 	return SEPOL_OK;
1654 exit:
1655 	cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuser declaration");
1656 	cil_destroy_selinuxuser(selinuxuser);
1657 	return rc;
1658 }
1659 
cil_gen_selinuxuserdefault(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1660 int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1661 {
1662 	enum cil_syntax syntax[] = {
1663 		CIL_SYN_STRING,
1664 		CIL_SYN_STRING,
1665 		CIL_SYN_STRING | CIL_SYN_LIST,
1666 		CIL_SYN_END
1667 	};
1668 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1669 	struct cil_selinuxuser *selinuxuser = NULL;
1670 	int rc = SEPOL_ERR;
1671 
1672 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1673 		goto exit;
1674 	}
1675 
1676 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1677 	if (rc != SEPOL_OK) {
1678 		goto exit;
1679 	}
1680 
1681 	cil_selinuxuser_init(&selinuxuser);
1682 
1683 	selinuxuser->name_str = cil_strpool_add("__default__");
1684 	selinuxuser->user_str = parse_current->next->data;
1685 
1686 	if (parse_current->next->next->cl_head == NULL) {
1687 		selinuxuser->range_str = parse_current->next->next->data;
1688 	} else {
1689 		cil_levelrange_init(&selinuxuser->range);
1690 
1691 		rc = cil_fill_levelrange(parse_current->next->next->cl_head, selinuxuser->range);
1692 		if (rc != SEPOL_OK) {
1693 			goto exit;
1694 		}
1695 	}
1696 
1697 	ast_node->data = selinuxuser;
1698 	ast_node->flavor = CIL_SELINUXUSERDEFAULT;
1699 
1700 	return SEPOL_OK;
1701 exit:
1702 	cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuserdefault declaration");
1703 	cil_destroy_selinuxuser(selinuxuser);
1704 	return rc;
1705 }
1706 
cil_destroy_selinuxuser(struct cil_selinuxuser * selinuxuser)1707 void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser)
1708 {
1709 	if (selinuxuser == NULL) {
1710 		return;
1711 	}
1712 
1713 	if (selinuxuser->range_str == NULL && selinuxuser->range != NULL) {
1714 		cil_destroy_levelrange(selinuxuser->range);
1715 	}
1716 
1717 	free(selinuxuser);
1718 }
1719 
cil_gen_role(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1720 int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1721 {
1722 	enum cil_syntax syntax[] = {
1723 		CIL_SYN_STRING,
1724 		CIL_SYN_STRING,
1725 		CIL_SYN_END
1726 	};
1727 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1728 	char *key = NULL;
1729 	struct cil_role *role = NULL;
1730 	int rc = SEPOL_ERR;
1731 
1732 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1733 		goto exit;
1734 	}
1735 
1736 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1737 	if (rc != SEPOL_OK) {
1738 		goto exit;
1739 	}
1740 
1741 	cil_role_init(&role);
1742 
1743 	key = parse_current->next->data;
1744 
1745 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)role, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLE);
1746 	if (rc != SEPOL_OK) {
1747 		goto exit;
1748 	}
1749 
1750 	return SEPOL_OK;
1751 
1752 exit:
1753 	cil_tree_log(parse_current, CIL_ERR, "Bad role declaration");
1754 	cil_destroy_role(role);
1755 	cil_clear_node(ast_node);
1756 	return rc;
1757 }
1758 
cil_destroy_role(struct cil_role * role)1759 void cil_destroy_role(struct cil_role *role)
1760 {
1761 	if (role == NULL) {
1762 		return;
1763 	}
1764 
1765 	cil_symtab_datum_destroy(&role->datum);
1766 	ebitmap_destroy(role->types);
1767 	free(role->types);
1768 	free(role);
1769 }
1770 
cil_gen_roletype(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1771 int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1772 {
1773 	enum cil_syntax syntax[] = {
1774 		CIL_SYN_STRING,
1775 		CIL_SYN_STRING,
1776 		CIL_SYN_STRING,
1777 		CIL_SYN_END
1778 	};
1779 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1780 	struct cil_roletype *roletype = NULL;
1781 	int rc = SEPOL_ERR;
1782 
1783 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1784 		goto exit;
1785 	}
1786 
1787 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1788 	if (rc != SEPOL_OK) {
1789 		goto exit;
1790 	}
1791 
1792 	cil_roletype_init(&roletype);
1793 
1794 	roletype->role_str = parse_current->next->data;
1795 	roletype->type_str = parse_current->next->next->data;
1796 
1797 	ast_node->data = roletype;
1798 	ast_node->flavor = CIL_ROLETYPE;
1799 
1800 	return SEPOL_OK;
1801 
1802 exit:
1803 	cil_tree_log(parse_current, CIL_ERR, "Bad roletype declaration");
1804 	cil_destroy_roletype(roletype);
1805 	return rc;
1806 }
1807 
cil_destroy_roletype(struct cil_roletype * roletype)1808 void cil_destroy_roletype(struct cil_roletype *roletype)
1809 {
1810 	if (roletype == NULL) {
1811 		return;
1812 	}
1813 
1814 	free(roletype);
1815 }
1816 
cil_gen_userrole(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1817 int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1818 {
1819 	enum cil_syntax syntax[] = {
1820 		CIL_SYN_STRING,
1821 		CIL_SYN_STRING,
1822 		CIL_SYN_STRING,
1823 		CIL_SYN_END
1824 	};
1825 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1826 	struct cil_userrole *userrole = NULL;
1827 	int rc = SEPOL_ERR;
1828 
1829 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1830 		goto exit;
1831 	}
1832 
1833 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1834 	if (rc != SEPOL_OK) {
1835 		goto exit;
1836 	}
1837 
1838 	cil_userrole_init(&userrole);
1839 
1840 	userrole->user_str = parse_current->next->data;
1841 	userrole->role_str = parse_current->next->next->data;
1842 
1843 	ast_node->data = userrole;
1844 	ast_node->flavor = CIL_USERROLE;
1845 
1846 	return SEPOL_OK;
1847 
1848 exit:
1849 	cil_tree_log(parse_current, CIL_ERR, "Bad userrole declaration");
1850 	cil_destroy_userrole(userrole);
1851 	return rc;
1852 }
1853 
cil_destroy_userrole(struct cil_userrole * userrole)1854 void cil_destroy_userrole(struct cil_userrole *userrole)
1855 {
1856 	if (userrole == NULL) {
1857 		return;
1858 	}
1859 
1860 	free(userrole);
1861 }
1862 
cil_gen_roletransition(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1863 int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1864 {
1865 	enum cil_syntax syntax[] = {
1866 		CIL_SYN_STRING,
1867 		CIL_SYN_STRING,
1868 		CIL_SYN_STRING,
1869 		CIL_SYN_STRING,
1870 		CIL_SYN_STRING,
1871 		CIL_SYN_END
1872 	};
1873 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1874 	struct cil_roletransition *roletrans = NULL;
1875 	int rc = SEPOL_ERR;
1876 
1877 	if (parse_current == NULL || ast_node == NULL) {
1878 		goto exit;
1879 	}
1880 
1881 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1882 	if (rc != SEPOL_OK) {
1883 		goto exit;
1884 	}
1885 
1886 	cil_roletransition_init(&roletrans);
1887 
1888 	roletrans->src_str = parse_current->next->data;
1889 	roletrans->tgt_str = parse_current->next->next->data;
1890 	roletrans->obj_str = parse_current->next->next->next->data;
1891 	roletrans->result_str = parse_current->next->next->next->next->data;
1892 
1893 	ast_node->data = roletrans;
1894 	ast_node->flavor = CIL_ROLETRANSITION;
1895 
1896 	return SEPOL_OK;
1897 
1898 exit:
1899 	cil_tree_log(parse_current, CIL_ERR, "Bad roletransition rule");
1900 	cil_destroy_roletransition(roletrans);
1901 	return rc;
1902 }
1903 
cil_destroy_roletransition(struct cil_roletransition * roletrans)1904 void cil_destroy_roletransition(struct cil_roletransition *roletrans)
1905 {
1906 	if (roletrans == NULL) {
1907 		return;
1908 	}
1909 
1910 	free(roletrans);
1911 }
1912 
cil_gen_roleallow(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1913 int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1914 {
1915 	enum cil_syntax syntax[] = {
1916 		CIL_SYN_STRING,
1917 		CIL_SYN_STRING,
1918 		CIL_SYN_STRING,
1919 		CIL_SYN_END
1920 	};
1921 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1922 	struct cil_roleallow *roleallow = NULL;
1923 	int rc = SEPOL_ERR;
1924 
1925 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1926 		goto exit;
1927 	}
1928 
1929 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1930 	if (rc != SEPOL_OK) {
1931 		goto exit;
1932 	}
1933 
1934 	cil_roleallow_init(&roleallow);
1935 
1936 	roleallow->src_str = parse_current->next->data;
1937 	roleallow->tgt_str = parse_current->next->next->data;
1938 
1939 	ast_node->data = roleallow;
1940 	ast_node->flavor = CIL_ROLEALLOW;
1941 
1942 	return SEPOL_OK;
1943 
1944 exit:
1945 	cil_tree_log(parse_current, CIL_ERR, "Bad roleallow rule");
1946 	cil_destroy_roleallow(roleallow);
1947 	return rc;
1948 }
1949 
cil_destroy_roleallow(struct cil_roleallow * roleallow)1950 void cil_destroy_roleallow(struct cil_roleallow *roleallow)
1951 {
1952 	if (roleallow == NULL) {
1953 		return;
1954 	}
1955 
1956 	free(roleallow);
1957 }
1958 
cil_gen_roleattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)1959 int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
1960 {
1961 	enum cil_syntax syntax[] = {
1962 		CIL_SYN_STRING,
1963 		CIL_SYN_STRING,
1964 		CIL_SYN_END
1965 	};
1966 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
1967 	char *key = NULL;
1968 	struct cil_roleattribute *attr = NULL;
1969 	int rc = SEPOL_ERR;
1970 
1971 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
1972 		goto exit;
1973 	}
1974 
1975 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1976 	if (rc != SEPOL_OK) {
1977 		goto exit;
1978 	}
1979 
1980 	cil_roleattribute_init(&attr);
1981 
1982 	key = parse_current->next->data;
1983 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLEATTRIBUTE);
1984 	if (rc != SEPOL_OK) {
1985 		goto exit;
1986 	}
1987 
1988 	return SEPOL_OK;
1989 exit:
1990 	cil_tree_log(parse_current, CIL_ERR, "Bad roleattribute declaration");
1991 	cil_destroy_roleattribute(attr);
1992 	cil_clear_node(ast_node);
1993 	return rc;
1994 }
1995 
cil_destroy_roleattribute(struct cil_roleattribute * attr)1996 void cil_destroy_roleattribute(struct cil_roleattribute *attr)
1997 {
1998 	if (attr == NULL) {
1999 		return;
2000 	}
2001 
2002 	if (attr->expr_list != NULL) {
2003 		/* we don't want to destroy the expression stacks (cil_list) inside
2004 		 * this list cil_list_destroy destroys sublists, so we need to do it
2005 		 * manually */
2006 		struct cil_list_item *expr = attr->expr_list->head;
2007 		while (expr != NULL) {
2008 			struct cil_list_item *next = expr->next;
2009 			cil_list_item_destroy(&expr, CIL_FALSE);
2010 			expr = next;
2011 		}
2012 		free(attr->expr_list);
2013 		attr->expr_list = NULL;
2014 	}
2015 
2016 	cil_symtab_datum_destroy(&attr->datum);
2017 	ebitmap_destroy(attr->roles);
2018 	free(attr->roles);
2019 	free(attr);
2020 }
2021 
cil_gen_roleattributeset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2022 int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2023 {
2024 	enum cil_syntax syntax[] = {
2025 		CIL_SYN_STRING,
2026 		CIL_SYN_STRING,
2027 		CIL_SYN_STRING | CIL_SYN_LIST,
2028 		CIL_SYN_END
2029 	};
2030 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2031 	struct cil_roleattributeset *attrset = NULL;
2032 	int rc = SEPOL_ERR;
2033 
2034 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2035 		goto exit;
2036 	}
2037 
2038 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2039 	if (rc != SEPOL_OK) {
2040 		goto exit;
2041 	}
2042 
2043 	cil_roleattributeset_init(&attrset);
2044 
2045 	attrset->attr_str = parse_current->next->data;
2046 
2047 	rc = cil_gen_expr(parse_current->next->next, CIL_ROLE, &attrset->str_expr);
2048 	if (rc != SEPOL_OK) {
2049 		goto exit;
2050 	}
2051 	ast_node->data = attrset;
2052 	ast_node->flavor = CIL_ROLEATTRIBUTESET;
2053 
2054 	return SEPOL_OK;
2055 
2056 exit:
2057 	cil_tree_log(parse_current, CIL_ERR, "Bad roleattributeset declaration");
2058 	cil_destroy_roleattributeset(attrset);
2059 
2060 	return rc;
2061 }
2062 
cil_destroy_roleattributeset(struct cil_roleattributeset * attrset)2063 void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset)
2064 {
2065 	if (attrset == NULL) {
2066 		return;
2067 	}
2068 
2069 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
2070 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
2071 
2072 	free(attrset);
2073 }
2074 
cil_gen_avrule(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint32_t rule_kind)2075 int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
2076 {
2077 	enum cil_syntax syntax[] = {
2078 		CIL_SYN_STRING,
2079 		CIL_SYN_STRING,
2080 		CIL_SYN_STRING,
2081 		CIL_SYN_STRING | CIL_SYN_LIST,
2082 		CIL_SYN_END
2083 	};
2084 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2085 	struct cil_avrule *rule = NULL;
2086 	int rc = SEPOL_ERR;
2087 
2088 	if (parse_current == NULL || ast_node == NULL) {
2089 		goto exit;
2090 	}
2091 
2092 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2093 	if (rc != SEPOL_OK) {
2094 		goto exit;
2095 	}
2096 
2097 	cil_avrule_init(&rule);
2098 
2099 	rule->is_extended = 0;
2100 	rule->rule_kind = rule_kind;
2101 
2102 	rule->src_str = parse_current->next->data;
2103 	rule->tgt_str = parse_current->next->next->data;
2104 
2105 	rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->perms.classperms);
2106 	if (rc != SEPOL_OK) {
2107 		goto exit;
2108 	}
2109 
2110 	ast_node->data = rule;
2111 	ast_node->flavor = CIL_AVRULE;
2112 
2113 	return SEPOL_OK;
2114 
2115 exit:
2116 	cil_tree_log(parse_current, CIL_ERR, "Bad allow rule");
2117 	cil_destroy_avrule(rule);
2118 	return rc;
2119 }
2120 
cil_destroy_avrule(struct cil_avrule * rule)2121 void cil_destroy_avrule(struct cil_avrule *rule)
2122 {
2123 	if (rule == NULL) {
2124 		return;
2125 	}
2126 
2127 	if (!rule->is_extended) {
2128 		cil_destroy_classperms_list(&rule->perms.classperms);
2129 	} else {
2130 		if (rule->perms.x.permx_str == NULL && rule->perms.x.permx != NULL) {
2131 			cil_destroy_permissionx(rule->perms.x.permx);
2132 		}
2133 	}
2134 
2135 	free(rule);
2136 }
2137 
cil_fill_permissionx(struct cil_tree_node * parse_current,struct cil_permissionx * permx)2138 static int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permissionx *permx)
2139 {
2140 	enum cil_syntax syntax[] = {
2141 		CIL_SYN_STRING,
2142 		CIL_SYN_STRING,
2143 		CIL_SYN_LIST,
2144 		CIL_SYN_END
2145 	};
2146 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2147 	int rc = SEPOL_ERR;
2148 
2149 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2150 	if (rc != SEPOL_OK) {
2151 		goto exit;
2152 	}
2153 
2154 	if (parse_current->data == CIL_KEY_IOCTL) {
2155 		permx->kind = CIL_PERMX_KIND_IOCTL;
2156 	} else {
2157 		cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\"\n", (char *)parse_current->data);
2158 		rc = SEPOL_ERR;
2159 		goto exit;
2160 	}
2161 
2162 	permx->obj_str = parse_current->next->data;
2163 
2164 	rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX, &permx->expr_str);
2165 	if (rc != SEPOL_OK) {
2166 		goto exit;
2167 	}
2168 
2169 	return SEPOL_OK;
2170 
2171 exit:
2172 	cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content");
2173 	return rc;
2174 }
2175 
cil_gen_permissionx(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2176 int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2177 {
2178 	enum cil_syntax syntax[] = {
2179 		CIL_SYN_STRING,
2180 		CIL_SYN_STRING,
2181 		CIL_SYN_LIST,
2182 		CIL_SYN_END
2183 	};
2184 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2185 	char *key = NULL;
2186 	struct cil_permissionx *permx = NULL;
2187 	int rc = SEPOL_ERR;
2188 
2189 	if (parse_current == NULL || ast_node == NULL) {
2190 		goto exit;
2191 	}
2192 
2193 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2194 	if (rc != SEPOL_OK) {
2195 		goto exit;
2196 	}
2197 
2198 	cil_permissionx_init(&permx);
2199 
2200 	key = parse_current->next->data;
2201 
2202 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)permx, (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX);
2203 	if (rc != SEPOL_OK) {
2204 		goto exit;
2205 	}
2206 
2207 	rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx);
2208 	if (rc != SEPOL_OK) {
2209 		goto exit;
2210 	}
2211 
2212 	return SEPOL_OK;
2213 
2214 exit:
2215 	cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement");
2216 	cil_destroy_permissionx(permx);
2217 	cil_clear_node(ast_node);
2218 	return rc;
2219 }
2220 
cil_destroy_permissionx(struct cil_permissionx * permx)2221 void cil_destroy_permissionx(struct cil_permissionx *permx)
2222 {
2223 	if (permx == NULL) {
2224 		return;
2225 	}
2226 
2227 	cil_symtab_datum_destroy(&permx->datum);
2228 
2229 	cil_list_destroy(&permx->expr_str, CIL_TRUE);
2230 	ebitmap_destroy(permx->perms);
2231 	free(permx->perms);
2232 	free(permx);
2233 }
2234 
cil_gen_avrulex(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint32_t rule_kind)2235 int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
2236 {
2237 	enum cil_syntax syntax[] = {
2238 		CIL_SYN_STRING,
2239 		CIL_SYN_STRING,
2240 		CIL_SYN_STRING,
2241 		CIL_SYN_STRING | CIL_SYN_LIST,
2242 		CIL_SYN_END
2243 	};
2244 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2245 	struct cil_avrule *rule = NULL;
2246 	int rc = SEPOL_ERR;
2247 
2248 	if (parse_current == NULL || ast_node == NULL) {
2249 		goto exit;
2250 	}
2251 
2252 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2253 	if (rc != SEPOL_OK) {
2254 		goto exit;
2255 	}
2256 
2257 	cil_avrule_init(&rule);
2258 
2259 	rule->is_extended = 1;
2260 	rule->rule_kind = rule_kind;
2261 	rule->src_str = parse_current->next->data;
2262 	rule->tgt_str = parse_current->next->next->data;
2263 
2264 	if (parse_current->next->next->next->cl_head == NULL) {
2265 		rule->perms.x.permx_str = parse_current->next->next->next->data;
2266 	} else {
2267 		cil_permissionx_init(&rule->perms.x.permx);
2268 
2269 		rc = cil_fill_permissionx(parse_current->next->next->next->cl_head, rule->perms.x.permx);
2270 		if (rc != SEPOL_OK) {
2271 			goto exit;
2272 		}
2273 	}
2274 
2275 	ast_node->data = rule;
2276 	ast_node->flavor = CIL_AVRULEX;
2277 
2278 	return SEPOL_OK;
2279 
2280 exit:
2281 	cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule");
2282 	cil_destroy_avrule(rule);
2283 	return rc;
2284 }
2285 
cil_gen_deny_rule(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2286 int cil_gen_deny_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2287 {
2288 	enum cil_syntax syntax[] = {
2289 		CIL_SYN_STRING,
2290 		CIL_SYN_STRING,
2291 		CIL_SYN_STRING,
2292 		CIL_SYN_STRING | CIL_SYN_LIST,
2293 		CIL_SYN_END
2294 	};
2295 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2296 	struct cil_deny_rule *rule = NULL;
2297 	int rc = SEPOL_ERR;
2298 
2299 	if (parse_current == NULL || ast_node == NULL) {
2300 		goto exit;
2301 	}
2302 
2303 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2304 	if (rc != SEPOL_OK) {
2305 		goto exit;
2306 	}
2307 
2308 	cil_deny_rule_init(&rule);
2309 
2310 	rule->src_str = parse_current->next->data;
2311 	rule->tgt_str = parse_current->next->next->data;
2312 
2313 	rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->classperms);
2314 	if (rc != SEPOL_OK) {
2315 		goto exit;
2316 	}
2317 
2318 	ast_node->data = rule;
2319 	ast_node->flavor = CIL_DENY_RULE;
2320 
2321 	return SEPOL_OK;
2322 
2323 exit:
2324 	cil_tree_log(parse_current, CIL_ERR, "Bad deny rule");
2325 	cil_destroy_deny_rule(rule);
2326 	return rc;
2327 }
2328 
cil_destroy_deny_rule(struct cil_deny_rule * rule)2329 void cil_destroy_deny_rule(struct cil_deny_rule *rule)
2330 {
2331 	if (rule == NULL) {
2332 		return;
2333 	}
2334 
2335 	cil_destroy_classperms_list(&rule->classperms);
2336 
2337 	free(rule);
2338 }
2339 
cil_gen_type_rule(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint32_t rule_kind)2340 int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
2341 {
2342 	enum cil_syntax syntax[] = {
2343 		CIL_SYN_STRING,
2344 		CIL_SYN_STRING,
2345 		CIL_SYN_STRING,
2346 		CIL_SYN_STRING,
2347 		CIL_SYN_STRING,
2348 		CIL_SYN_END
2349 	};
2350 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2351 	struct cil_type_rule *rule = NULL;
2352 	int rc = SEPOL_ERR;
2353 
2354 	if (parse_current == NULL || ast_node == NULL) {
2355 		goto exit;
2356 	}
2357 
2358 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2359 	if (rc != SEPOL_OK) {
2360 		goto exit;
2361 	}
2362 
2363 	cil_type_rule_init(&rule);
2364 
2365 	rule->rule_kind = rule_kind;
2366 	rule->src_str = parse_current->next->data;
2367 	rule->tgt_str = parse_current->next->next->data;
2368 	rule->obj_str = parse_current->next->next->next->data;
2369 	rule->result_str = parse_current->next->next->next->next->data;
2370 
2371 	ast_node->data = rule;
2372 	ast_node->flavor = CIL_TYPE_RULE;
2373 
2374 	return SEPOL_OK;
2375 
2376 exit:
2377 	cil_tree_log(parse_current, CIL_ERR, "Bad type rule");
2378 	cil_destroy_type_rule(rule);
2379 	return rc;
2380 }
2381 
cil_destroy_type_rule(struct cil_type_rule * rule)2382 void cil_destroy_type_rule(struct cil_type_rule *rule)
2383 {
2384 	if (rule == NULL) {
2385 		return;
2386 	}
2387 
2388 	free(rule);
2389 }
2390 
cil_gen_type(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2391 int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2392 {
2393 	enum cil_syntax syntax[] = {
2394 		CIL_SYN_STRING,
2395 		CIL_SYN_STRING,
2396 		CIL_SYN_END
2397 	};
2398 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2399 	char *key = NULL;
2400 	struct cil_type *type = NULL;
2401 	int rc = SEPOL_ERR;
2402 
2403 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2404 		goto exit;
2405 	}
2406 
2407 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2408 	if (rc != SEPOL_OK) {
2409 		goto exit;
2410 	}
2411 
2412 	cil_type_init(&type);
2413 
2414 	key = parse_current->next->data;
2415 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE);
2416 	if (rc != SEPOL_OK) {
2417 		if (rc == SEPOL_EEXIST) {
2418 			cil_destroy_type(type);
2419 			type = NULL;
2420 		} else {
2421 			goto exit;
2422 		}
2423 	}
2424 
2425 	return SEPOL_OK;
2426 
2427 exit:
2428 	cil_tree_log(parse_current, CIL_ERR, "Bad type declaration");
2429 	cil_destroy_type(type);
2430 	cil_clear_node(ast_node);
2431 	return rc;
2432 }
2433 
cil_destroy_type(struct cil_type * type)2434 void cil_destroy_type(struct cil_type *type)
2435 {
2436 	if (type == NULL) {
2437 		return;
2438 	}
2439 
2440 	cil_symtab_datum_destroy(&type->datum);
2441 	free(type);
2442 }
2443 
cil_gen_typeattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2444 int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2445 {
2446 	enum cil_syntax syntax[] = {
2447 		CIL_SYN_STRING,
2448 		CIL_SYN_STRING,
2449 		CIL_SYN_END
2450 	};
2451 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2452 	char *key = NULL;
2453 	struct cil_typeattribute *attr = NULL;
2454 	int rc = SEPOL_ERR;
2455 
2456 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2457 		goto exit;
2458 	}
2459 
2460 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2461 	if (rc != SEPOL_OK) {
2462 		goto exit;
2463 	}
2464 
2465 	cil_typeattribute_init(&attr);
2466 
2467 	key = parse_current->next->data;
2468 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
2469 	if (rc != SEPOL_OK) {
2470 		if (rc == SEPOL_EEXIST) {
2471 			cil_destroy_typeattribute(attr);
2472 			attr = NULL;
2473 		} else {
2474 			goto exit;
2475 		}
2476 	}
2477 
2478 	return SEPOL_OK;
2479 
2480 exit:
2481 	cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration");
2482 	cil_destroy_typeattribute(attr);
2483 	cil_clear_node(ast_node);
2484 	return rc;
2485 }
2486 
cil_destroy_typeattribute(struct cil_typeattribute * attr)2487 void cil_destroy_typeattribute(struct cil_typeattribute *attr)
2488 {
2489 	if (attr == NULL) {
2490 		return;
2491 	}
2492 
2493 	cil_symtab_datum_destroy(&attr->datum);
2494 
2495 	if (attr->expr_list != NULL) {
2496 		/* we don't want to destroy the expression stacks (cil_list) inside
2497 		 * this list cil_list_destroy destroys sublists, so we need to do it
2498 		 * manually */
2499 		struct cil_list_item *expr = attr->expr_list->head;
2500 		while (expr != NULL) {
2501 			struct cil_list_item *next = expr->next;
2502 			cil_list_item_destroy(&expr, CIL_FALSE);
2503 			expr = next;
2504 		}
2505 		free(attr->expr_list);
2506 		attr->expr_list = NULL;
2507 	}
2508 	ebitmap_destroy(attr->types);
2509 	free(attr->types);
2510 	free(attr);
2511 }
2512 
cil_gen_bool(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,int tunableif)2513 int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif)
2514 {
2515 	enum cil_syntax syntax[] = {
2516 		CIL_SYN_STRING,
2517 		CIL_SYN_STRING,
2518 		CIL_SYN_STRING,
2519 		CIL_SYN_END
2520 	};
2521 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2522 	char *key = NULL;
2523 	struct cil_bool *boolean = NULL;
2524 	int rc = SEPOL_ERR;
2525 
2526 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2527 		goto exit;
2528 	}
2529 
2530 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2531 	if (rc != SEPOL_OK) {
2532 		goto exit;
2533 	}
2534 
2535 	cil_bool_init(&boolean);
2536 
2537 	key = parse_current->next->data;
2538 
2539 	if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
2540 		boolean->value = CIL_TRUE;
2541 	} else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
2542 		boolean->value = CIL_FALSE;
2543 	} else {
2544 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
2545 		rc = SEPOL_ERR;
2546 		goto exit;
2547 	}
2548 
2549 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)boolean, (hashtab_key_t)key, CIL_SYM_BOOLS, CIL_BOOL);
2550 	if (rc != SEPOL_OK) {
2551 		goto exit;
2552 	}
2553 
2554 	return SEPOL_OK;
2555 
2556 exit:
2557 	if (tunableif) {
2558 		cil_tree_log(parse_current, CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration");
2559 	} else {
2560 		cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration");
2561 	}
2562 	cil_destroy_bool(boolean);
2563 	cil_clear_node(ast_node);
2564 	return rc;
2565 }
2566 
cil_destroy_bool(struct cil_bool * boolean)2567 void cil_destroy_bool(struct cil_bool *boolean)
2568 {
2569 	if (boolean == NULL) {
2570 		return;
2571 	}
2572 
2573 	cil_symtab_datum_destroy(&boolean->datum);
2574 	free(boolean);
2575 }
2576 
cil_gen_tunable(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2577 int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2578 {
2579 	enum cil_syntax syntax[] = {
2580 		CIL_SYN_STRING,
2581 		CIL_SYN_STRING,
2582 		CIL_SYN_STRING,
2583 		CIL_SYN_END
2584 	};
2585 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2586 	char *key = NULL;
2587 	struct cil_tunable *tunable = NULL;
2588 	int rc = SEPOL_ERR;
2589 
2590 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2591 		goto exit;
2592 	}
2593 
2594 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2595 	if (rc != SEPOL_OK) {
2596 		goto exit;
2597 	}
2598 
2599 	cil_tunable_init(&tunable);
2600 
2601 	key = parse_current->next->data;
2602 
2603 	if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
2604 		tunable->value = CIL_TRUE;
2605 	} else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
2606 		tunable->value = CIL_FALSE;
2607 	} else {
2608 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
2609 		rc = SEPOL_ERR;
2610 		goto exit;
2611 	}
2612 
2613 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)tunable, (hashtab_key_t)key, CIL_SYM_TUNABLES, CIL_TUNABLE);
2614 	if (rc != SEPOL_OK) {
2615 		goto exit;
2616 	}
2617 
2618 	return SEPOL_OK;
2619 
2620 exit:
2621 	cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration");
2622 	cil_destroy_tunable(tunable);
2623 	cil_clear_node(ast_node);
2624 	return rc;
2625 }
2626 
cil_destroy_tunable(struct cil_tunable * tunable)2627 void cil_destroy_tunable(struct cil_tunable *tunable)
2628 {
2629 	if (tunable == NULL) {
2630 		return;
2631 	}
2632 
2633 	cil_symtab_datum_destroy(&tunable->datum);
2634 	free(tunable);
2635 }
2636 
__cil_get_expr_operator_flavor(const char * op)2637 static enum cil_flavor __cil_get_expr_operator_flavor(const char *op)
2638 {
2639 	if (op == NULL) return CIL_NONE;
2640 	else if (op == CIL_KEY_AND)   return CIL_AND;
2641 	else if (op == CIL_KEY_OR)    return CIL_OR;
2642 	else if (op == CIL_KEY_NOT)   return CIL_NOT;
2643 	else if (op == CIL_KEY_EQ)    return CIL_EQ;    /* Only conditional */
2644 	else if (op == CIL_KEY_NEQ)   return CIL_NEQ;   /* Only conditional */
2645 	else if (op == CIL_KEY_XOR)   return CIL_XOR;
2646 	else if (op == CIL_KEY_ALL)   return CIL_ALL;   /* Only set and permissionx */
2647 	else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset and permissionx */
2648 	else return CIL_NONE;
2649 }
2650 
2651 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr);
2652 
__cil_fill_expr_helper(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list * expr)2653 static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
2654 {
2655 	int rc = SEPOL_ERR;
2656 	enum cil_flavor op;
2657 
2658 	op = __cil_get_expr_operator_flavor(current->data);
2659 
2660 	rc = cil_verify_expr_syntax(current, op, flavor);
2661 	if (rc != SEPOL_OK) {
2662 		goto exit;
2663 	}
2664 
2665 	if (op != CIL_NONE) {
2666 		cil_list_append(expr, CIL_OP, (void *)op);
2667 		current = current->next;
2668 	}
2669 
2670 	for (;current != NULL; current = current->next) {
2671 		rc = __cil_fill_expr(current, flavor, expr);
2672 		if (rc != SEPOL_OK) {
2673 			goto exit;
2674 		}
2675 	}
2676 
2677 	return SEPOL_OK;
2678 
2679 exit:
2680 	return rc;
2681 }
2682 
__cil_fill_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list * expr)2683 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
2684 {
2685 	int rc = SEPOL_ERR;
2686 
2687 	if (current->cl_head == NULL) {
2688 		enum cil_flavor op = __cil_get_expr_operator_flavor(current->data);
2689 		if (op != CIL_NONE) {
2690 			cil_log(CIL_ERR, "Operator (%s) not in an expression\n", (char*)current->data);
2691 			goto exit;
2692 		}
2693 		cil_list_append(expr, CIL_STRING, current->data);
2694 	} else {
2695 		struct cil_list *sub_expr;
2696 		cil_list_init(&sub_expr, flavor);
2697 		rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr);
2698 		if (rc != SEPOL_OK) {
2699 			cil_list_destroy(&sub_expr, CIL_TRUE);
2700 			goto exit;
2701 		}
2702 		cil_list_append(expr, CIL_LIST, sub_expr);
2703 	}
2704 
2705 	return SEPOL_OK;
2706 
2707 exit:
2708 	return rc;
2709 }
2710 
2711 
cil_gen_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2712 int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2713 {
2714 	int rc = SEPOL_ERR;
2715 
2716 	cil_list_init(expr, flavor);
2717 
2718 	if (current->cl_head == NULL) {
2719 		rc = __cil_fill_expr(current, flavor, *expr);
2720 	} else {
2721 		rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr);
2722 	}
2723 
2724 	if (rc != SEPOL_OK) {
2725 		cil_list_destroy(expr, CIL_TRUE);
2726 		cil_log(CIL_ERR, "Bad expression\n");
2727 	}
2728 
2729 	return rc;
2730 }
2731 
__cil_get_constraint_operator_flavor(const char * op)2732 static enum cil_flavor __cil_get_constraint_operator_flavor(const char *op)
2733 {
2734 	if (op == CIL_KEY_AND)         return CIL_AND;
2735 	else if (op == CIL_KEY_OR)     return CIL_OR;
2736 	else if (op == CIL_KEY_NOT)    return CIL_NOT;
2737 	else if (op == CIL_KEY_EQ)     return CIL_EQ;
2738 	else if (op == CIL_KEY_NEQ)    return CIL_NEQ;
2739 	else if (op == CIL_KEY_CONS_DOM)    return CIL_CONS_DOM;
2740 	else if (op == CIL_KEY_CONS_DOMBY)  return CIL_CONS_DOMBY;
2741 	else if (op == CIL_KEY_CONS_INCOMP) return CIL_CONS_INCOMP;
2742 	else return CIL_NONE;
2743 }
2744 
__cil_get_constraint_operand_flavor(const char * operand)2745 static enum cil_flavor __cil_get_constraint_operand_flavor(const char *operand)
2746 {
2747 	if (operand == NULL) return CIL_LIST;
2748 	else if (operand == CIL_KEY_CONS_T1) return CIL_CONS_T1;
2749 	else if (operand == CIL_KEY_CONS_T2) return CIL_CONS_T2;
2750 	else if (operand == CIL_KEY_CONS_T3) return CIL_CONS_T3;
2751 	else if (operand == CIL_KEY_CONS_R1) return CIL_CONS_R1;
2752 	else if (operand == CIL_KEY_CONS_R2) return CIL_CONS_R2;
2753 	else if (operand == CIL_KEY_CONS_R3) return CIL_CONS_R3;
2754 	else if (operand == CIL_KEY_CONS_U1) return CIL_CONS_U1;
2755 	else if (operand == CIL_KEY_CONS_U2) return CIL_CONS_U2;
2756 	else if (operand == CIL_KEY_CONS_U3) return CIL_CONS_U3;
2757 	else if (operand == CIL_KEY_CONS_L1) return CIL_CONS_L1;
2758 	else if (operand == CIL_KEY_CONS_L2) return CIL_CONS_L2;
2759 	else if (operand == CIL_KEY_CONS_H1) return CIL_CONS_H1;
2760 	else if (operand == CIL_KEY_CONS_H2) return CIL_CONS_H2;
2761 	else return CIL_STRING;
2762 }
2763 
__cil_fill_constraint_leaf_expr(struct cil_tree_node * current,enum cil_flavor expr_flavor,enum cil_flavor op,struct cil_list ** leaf_expr)2764 static int __cil_fill_constraint_leaf_expr(struct cil_tree_node *current, enum cil_flavor expr_flavor, enum cil_flavor op, struct cil_list **leaf_expr)
2765 {
2766 	int rc = SEPOL_ERR;
2767 	enum cil_flavor leaf_expr_flavor = CIL_NONE;
2768 	enum cil_flavor l_flavor = CIL_NONE;
2769 	enum cil_flavor r_flavor = CIL_NONE;
2770 
2771 	l_flavor = __cil_get_constraint_operand_flavor(current->next->data);
2772 	r_flavor = __cil_get_constraint_operand_flavor(current->next->next->data);
2773 
2774 	switch (l_flavor) {
2775 	case CIL_CONS_U1:
2776 	case CIL_CONS_U2:
2777 	case CIL_CONS_U3:
2778 		leaf_expr_flavor = CIL_USER;
2779 		break;
2780 	case CIL_CONS_R1:
2781 	case CIL_CONS_R2:
2782 	case CIL_CONS_R3:
2783 		leaf_expr_flavor = CIL_ROLE;
2784 		break;
2785 	case CIL_CONS_T1:
2786 	case CIL_CONS_T2:
2787 	case CIL_CONS_T3:
2788 		leaf_expr_flavor = CIL_TYPE;
2789 		break;
2790 	case CIL_CONS_L1:
2791 	case CIL_CONS_L2:
2792 	case CIL_CONS_H1:
2793 	case CIL_CONS_H2:
2794 		leaf_expr_flavor = CIL_LEVEL;
2795 		break;
2796 	default:
2797 		cil_log(CIL_ERR, "Invalid left operand (%s)\n", (char*)current->next->data);
2798 		goto exit;
2799 	}
2800 
2801 	rc = cil_verify_constraint_leaf_expr_syntax(l_flavor, r_flavor, op, expr_flavor);
2802 	if (rc != SEPOL_OK) {
2803 		goto exit;
2804 	}
2805 
2806 	cil_list_init(leaf_expr, leaf_expr_flavor);
2807 
2808 	cil_list_append(*leaf_expr, CIL_OP, (void *)op);
2809 
2810 	cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)l_flavor);
2811 
2812 	if (r_flavor == CIL_STRING) {
2813 		cil_list_append(*leaf_expr, CIL_STRING, current->next->next->data);
2814 	} else if (r_flavor == CIL_LIST) {
2815 		struct cil_list *sub_list;
2816 		rc = cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
2817 		if (rc != SEPOL_OK) {
2818 			cil_list_destroy(leaf_expr, CIL_TRUE);
2819 			goto exit;
2820 		}
2821 		cil_list_append(*leaf_expr, CIL_LIST, sub_list);
2822 	} else {
2823 		cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor);
2824 	}
2825 
2826 	return SEPOL_OK;
2827 
2828 exit:
2829 
2830 	return SEPOL_ERR;
2831 }
2832 
__cil_fill_constraint_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2833 static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2834 {
2835 	int rc = SEPOL_ERR;
2836 	enum cil_flavor op;
2837 	struct cil_list *lexpr;
2838 	struct cil_list *rexpr;
2839 
2840 	if (current->data == NULL || current->cl_head != NULL) {
2841 		cil_log(CIL_ERR, "Expected a string at the start of the constraint expression\n");
2842 		goto exit;
2843 	}
2844 
2845 	op = __cil_get_constraint_operator_flavor(current->data);
2846 
2847 	rc = cil_verify_constraint_expr_syntax(current, op);
2848 	if (rc != SEPOL_OK) {
2849 		goto exit;
2850 	}
2851 
2852 	switch (op) {
2853 	case CIL_EQ:
2854 	case CIL_NEQ:
2855 	case CIL_CONS_DOM:
2856 	case CIL_CONS_DOMBY:
2857 	case CIL_CONS_INCOMP:
2858 		rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr);
2859 		if (rc != SEPOL_OK) {
2860 			goto exit;
2861 		}
2862 		break;
2863 	case CIL_NOT:
2864 		rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr);
2865 		if (rc != SEPOL_OK) {
2866 			goto exit;
2867 		}
2868 		cil_list_init(expr, flavor);
2869 		cil_list_append(*expr, CIL_OP, (void *)op);
2870 		cil_list_append(*expr, CIL_LIST, lexpr);
2871 		break;
2872 	default:
2873 		rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr);
2874 		if (rc != SEPOL_OK) {
2875 			goto exit;
2876 		}
2877 		rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr);
2878 		if (rc != SEPOL_OK) {
2879 			cil_list_destroy(&lexpr, CIL_TRUE);
2880 			goto exit;
2881 		}
2882 		cil_list_init(expr, flavor);
2883 		cil_list_append(*expr, CIL_OP, (void *)op);
2884 		cil_list_append(*expr, CIL_LIST, lexpr);
2885 		cil_list_append(*expr, CIL_LIST, rexpr);
2886 		break;
2887 	}
2888 
2889 	return SEPOL_OK;
2890 exit:
2891 
2892 	return rc;
2893 }
2894 
cil_gen_constraint_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2895 static int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2896 {
2897 	int rc = SEPOL_ERR;
2898 
2899 	if (current->cl_head == NULL) {
2900 		goto exit;
2901 	}
2902 
2903 	rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr);
2904 	if (rc != SEPOL_OK) {
2905 		goto exit;
2906 	}
2907 
2908 	return SEPOL_OK;
2909 
2910 exit:
2911 
2912 	cil_log(CIL_ERR, "Bad expression tree for constraint\n");
2913 	return rc;
2914 }
2915 
cil_gen_boolif(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,int tunableif)2916 int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif)
2917 {
2918 	enum cil_syntax syntax[] = {
2919 		CIL_SYN_STRING,
2920 		CIL_SYN_STRING | CIL_SYN_LIST,
2921 		CIL_SYN_LIST,
2922 		CIL_SYN_LIST | CIL_SYN_END,
2923 		CIL_SYN_END
2924 	};
2925 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2926 	struct cil_booleanif *bif = NULL;
2927 	struct cil_tree_node *next = NULL;
2928 	int rc = SEPOL_ERR;
2929 
2930 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2931 		goto exit;
2932 	}
2933 
2934 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2935 	if (rc != SEPOL_OK) {
2936 		goto exit;
2937 	}
2938 
2939 	cil_boolif_init(&bif);
2940 	bif->preserved_tunable = tunableif;
2941 
2942 	rc = cil_gen_expr(parse_current->next, CIL_BOOL, &bif->str_expr);
2943 	if (rc != SEPOL_OK) {
2944 		goto exit;
2945 	}
2946 
2947 	rc = cil_verify_conditional_blocks(parse_current->next->next);
2948 	if (rc != SEPOL_OK) {
2949 		goto exit;
2950 	}
2951 
2952 	/* Destroying expr tree */
2953 	next = parse_current->next->next;
2954 	cil_tree_subtree_destroy(parse_current->next);
2955 	parse_current->next = next;
2956 
2957 	ast_node->flavor = CIL_BOOLEANIF;
2958 	ast_node->data = bif;
2959 
2960 	return SEPOL_OK;
2961 
2962 exit:
2963 	if (tunableif) {
2964 		cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration");
2965 	} else {
2966 		cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration");
2967 	}
2968 	cil_destroy_boolif(bif);
2969 	return rc;
2970 }
2971 
cil_destroy_boolif(struct cil_booleanif * bif)2972 void cil_destroy_boolif(struct cil_booleanif *bif)
2973 {
2974 	if (bif == NULL) {
2975 		return;
2976 	}
2977 
2978 	cil_list_destroy(&bif->str_expr, CIL_TRUE);
2979 	cil_list_destroy(&bif->datum_expr, CIL_FALSE);
2980 
2981 	free(bif);
2982 }
2983 
cil_gen_tunif(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2984 int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2985 {
2986 	enum cil_syntax syntax[] = {
2987 		CIL_SYN_STRING,
2988 		CIL_SYN_STRING | CIL_SYN_LIST,
2989 		CIL_SYN_LIST,
2990 		CIL_SYN_LIST | CIL_SYN_END,
2991 		CIL_SYN_END
2992 	};
2993 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2994 	struct cil_tunableif *tif = NULL;
2995 	struct cil_tree_node *next = NULL;
2996 	int rc = SEPOL_ERR;
2997 
2998 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2999 		goto exit;
3000 	}
3001 
3002 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3003 	if (rc != SEPOL_OK) {
3004 		goto exit;
3005 	}
3006 
3007 	cil_tunif_init(&tif);
3008 
3009 	rc = cil_gen_expr(parse_current->next, CIL_TUNABLE, &tif->str_expr);
3010 	if (rc != SEPOL_OK) {
3011 		goto exit;
3012 	}
3013 
3014 	rc = cil_verify_conditional_blocks(parse_current->next->next);
3015 	if (rc != SEPOL_OK) {
3016 		goto exit;
3017 	}
3018 
3019 	/* Destroying expr tree */
3020 	next = parse_current->next->next;
3021 	cil_tree_subtree_destroy(parse_current->next);
3022 	parse_current->next = next;
3023 
3024 	ast_node->flavor = CIL_TUNABLEIF;
3025 	ast_node->data = tif;
3026 
3027 	return SEPOL_OK;
3028 
3029 exit:
3030 	cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration");
3031 	cil_destroy_tunif(tif);
3032 	return rc;
3033 }
3034 
cil_destroy_tunif(struct cil_tunableif * tif)3035 void cil_destroy_tunif(struct cil_tunableif *tif)
3036 {
3037 	if (tif == NULL) {
3038 		return;
3039 	}
3040 
3041 	cil_list_destroy(&tif->str_expr, CIL_TRUE);
3042 	cil_list_destroy(&tif->datum_expr, CIL_FALSE);
3043 
3044 	free(tif);
3045 }
3046 
cil_gen_condblock(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3047 int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3048 {
3049 	enum cil_syntax syntax[] = {
3050 		CIL_SYN_STRING,
3051 		CIL_SYN_N_LISTS,
3052 		CIL_SYN_END
3053 	};
3054 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3055 	int rc = SEPOL_ERR;
3056 	struct cil_condblock *cb = NULL;
3057 
3058 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3059 		goto exit;
3060 	}
3061 
3062 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3063 	if (rc != SEPOL_OK) {
3064 		goto exit;
3065 	}
3066 
3067 	if (ast_node->parent->flavor != CIL_BOOLEANIF && ast_node->parent->flavor != CIL_TUNABLEIF) {
3068 		rc = SEPOL_ERR;
3069 		cil_log(CIL_ERR, "Conditional statements must be a direct child of a tunableif or booleanif statement.\n");
3070 		goto exit;
3071 	}
3072 
3073 	ast_node->flavor = CIL_CONDBLOCK;
3074 
3075 	cil_condblock_init(&cb);
3076 	cb->flavor = flavor;
3077 
3078 	ast_node->data = cb;
3079 
3080 	return SEPOL_OK;
3081 
3082 exit:
3083 	cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration",
3084 		(char*)parse_current->data);
3085 	cil_destroy_condblock(cb);
3086 	return rc;
3087 }
3088 
cil_destroy_condblock(struct cil_condblock * cb)3089 void cil_destroy_condblock(struct cil_condblock *cb)
3090 {
3091 	if (cb == NULL) {
3092 		return;
3093 	}
3094 
3095 	cil_symtab_array_destroy(cb->symtab);
3096 	free(cb);
3097 }
3098 
cil_gen_alias(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3099 int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3100 {
3101 	enum cil_syntax syntax[] = {
3102 		CIL_SYN_STRING,
3103 		CIL_SYN_STRING,
3104 		CIL_SYN_END
3105 	};
3106 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3107 	char *key = NULL;
3108 	struct cil_alias *alias = NULL;
3109 	enum cil_sym_index sym_index;
3110 	int rc = SEPOL_ERR;
3111 
3112 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3113 		goto exit;
3114 	}
3115 
3116 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3117 	if (rc != SEPOL_OK) {
3118 		goto exit;
3119 	}
3120 
3121 	cil_alias_init(&alias);
3122 
3123 	key = parse_current->next->data;
3124 
3125 	rc = cil_flavor_to_symtab_index(flavor, &sym_index);
3126 	if (rc != SEPOL_OK) {
3127 		goto exit;
3128 	}
3129 
3130 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)alias, (hashtab_key_t)key, sym_index, flavor);
3131 	if (rc != SEPOL_OK) {
3132 		goto exit;
3133 	}
3134 
3135 	return SEPOL_OK;
3136 
3137 exit:
3138 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data);
3139 	cil_destroy_alias(alias);
3140 	cil_clear_node(ast_node);
3141 	return rc;
3142 }
3143 
cil_destroy_alias(struct cil_alias * alias)3144 void cil_destroy_alias(struct cil_alias *alias)
3145 {
3146 	if (alias == NULL) {
3147 		return;
3148 	}
3149 
3150 	cil_symtab_datum_destroy(&alias->datum);
3151 	alias->actual = NULL;
3152 
3153 	free(alias);
3154 }
3155 
cil_gen_aliasactual(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3156 int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3157 {
3158 	int rc = SEPOL_ERR;
3159 	enum cil_syntax syntax[] = {
3160 		CIL_SYN_STRING,
3161 		CIL_SYN_STRING,
3162 		CIL_SYN_STRING,
3163 		CIL_SYN_END
3164 	};
3165 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3166 	struct cil_aliasactual *aliasactual = NULL;
3167 
3168 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3169 		goto exit;
3170 	}
3171 
3172 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3173 	if (rc != SEPOL_OK) {
3174 		goto exit;
3175 	}
3176 
3177 	rc = cil_verify_name(db, parse_current->next->data, flavor);
3178 	if (rc != SEPOL_OK) {
3179 		goto exit;
3180 	}
3181 
3182 	rc = cil_verify_name(db, parse_current->next->next->data, flavor);
3183 	if (rc != SEPOL_OK) {
3184 		goto exit;
3185 	}
3186 
3187 	cil_aliasactual_init(&aliasactual);
3188 
3189 	aliasactual->alias_str = parse_current->next->data;
3190 
3191 	aliasactual->actual_str = parse_current->next->next->data;
3192 
3193 	ast_node->data = aliasactual;
3194 	ast_node->flavor = flavor;
3195 
3196 	return SEPOL_OK;
3197 
3198 exit:
3199 	cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current));
3200 	cil_clear_node(ast_node);
3201 	return rc;
3202 }
3203 
cil_destroy_aliasactual(struct cil_aliasactual * aliasactual)3204 void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual)
3205 {
3206 	if (aliasactual == NULL) {
3207 		return;
3208 	}
3209 
3210 	free(aliasactual);
3211 }
3212 
cil_gen_typeattributeset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3213 int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3214 {
3215 	enum cil_syntax syntax[] = {
3216 		CIL_SYN_STRING,
3217 		CIL_SYN_STRING,
3218 		CIL_SYN_STRING | CIL_SYN_LIST,
3219 		CIL_SYN_END
3220 	};
3221 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3222 	struct cil_typeattributeset *attrset = NULL;
3223 	int rc = SEPOL_ERR;
3224 
3225 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3226 		goto exit;
3227 	}
3228 
3229 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3230 	if (rc != SEPOL_OK) {
3231 		goto exit;
3232 	}
3233 
3234 	cil_typeattributeset_init(&attrset);
3235 
3236 	attrset->attr_str = parse_current->next->data;
3237 
3238 	rc = cil_gen_expr(parse_current->next->next, CIL_TYPE, &attrset->str_expr);
3239 	if (rc != SEPOL_OK) {
3240 		goto exit;
3241 	}
3242 	ast_node->data = attrset;
3243 	ast_node->flavor = CIL_TYPEATTRIBUTESET;
3244 
3245 	return SEPOL_OK;
3246 
3247 exit:
3248 	cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement");
3249 	cil_destroy_typeattributeset(attrset);
3250 	return rc;
3251 }
3252 
cil_destroy_typeattributeset(struct cil_typeattributeset * attrset)3253 void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset)
3254 {
3255 	if (attrset == NULL) {
3256 		return;
3257 	}
3258 
3259 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
3260 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
3261 
3262 	free(attrset);
3263 }
3264 
cil_gen_expandtypeattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3265 int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3266 {
3267 	enum cil_syntax syntax[] = {
3268 		CIL_SYN_STRING,
3269 		CIL_SYN_STRING | CIL_SYN_LIST,
3270 		CIL_SYN_STRING,
3271 		CIL_SYN_END
3272 	};
3273 	char *expand_str;
3274 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3275 	struct cil_expandtypeattribute *expandattr = NULL;
3276 	int rc = SEPOL_ERR;
3277 
3278 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3279 		goto exit;
3280 	}
3281 
3282 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3283 	if (rc != SEPOL_OK) {
3284 		goto exit;
3285 	}
3286 
3287 	cil_expandtypeattribute_init(&expandattr);
3288 
3289 	if (parse_current->next->cl_head == NULL) {
3290 		cil_list_init(&expandattr->attr_strs, CIL_TYPE);
3291 		cil_list_append(expandattr->attr_strs, CIL_STRING, parse_current->next->data);
3292 	} else {
3293 		rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE, &expandattr->attr_strs);
3294 		if (rc != SEPOL_OK) {
3295 			goto exit;
3296 		}
3297 	}
3298 
3299 	expand_str = parse_current->next->next->data;
3300 
3301 	if (expand_str == CIL_KEY_CONDTRUE) {
3302 		expandattr->expand = CIL_TRUE;
3303 	} else if (expand_str == CIL_KEY_CONDFALSE) {
3304 		expandattr->expand = CIL_FALSE;
3305 	} else {
3306 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
3307 		rc = SEPOL_ERR;
3308 		goto exit;
3309 	}
3310 
3311 	ast_node->data = expandattr;
3312 	ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE;
3313 
3314 	return SEPOL_OK;
3315 
3316 exit:
3317 	cil_tree_log(parse_current, CIL_ERR, "Bad expandtypeattribute statement");
3318 	cil_destroy_expandtypeattribute(expandattr);
3319 	return rc;
3320 }
3321 
cil_destroy_expandtypeattribute(struct cil_expandtypeattribute * expandattr)3322 void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr)
3323 {
3324 	if (expandattr == NULL) {
3325 		return;
3326 	}
3327 
3328 	cil_list_destroy(&expandattr->attr_strs, CIL_TRUE);
3329 
3330 	cil_list_destroy(&expandattr->attr_datums, CIL_FALSE);
3331 
3332 	free(expandattr);
3333 }
3334 
cil_gen_typepermissive(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3335 int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3336 {
3337 	enum cil_syntax syntax[] = {
3338 		CIL_SYN_STRING,
3339 		CIL_SYN_STRING,
3340 		CIL_SYN_END
3341 	};
3342 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3343 	struct cil_typepermissive *typeperm = NULL;
3344 	int rc = SEPOL_ERR;
3345 
3346 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3347 		goto exit;
3348 	}
3349 
3350 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3351 	if (rc != SEPOL_OK) {
3352 		goto exit;
3353 	}
3354 
3355 	cil_typepermissive_init(&typeperm);
3356 
3357 	typeperm->type_str = parse_current->next->data;
3358 
3359 	ast_node->data = typeperm;
3360 	ast_node->flavor = CIL_TYPEPERMISSIVE;
3361 
3362 	return SEPOL_OK;
3363 
3364 exit:
3365 	cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration");
3366 	cil_destroy_typepermissive(typeperm);
3367 	return rc;
3368 }
3369 
cil_destroy_typepermissive(struct cil_typepermissive * typeperm)3370 void cil_destroy_typepermissive(struct cil_typepermissive *typeperm)
3371 {
3372 	if (typeperm == NULL) {
3373 		return;
3374 	}
3375 
3376 	free(typeperm);
3377 }
3378 
cil_gen_typetransition(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3379 int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3380 {
3381 	int rc = SEPOL_ERR;
3382 	enum cil_syntax syntax[] = {
3383 		CIL_SYN_STRING,
3384 		CIL_SYN_STRING,
3385 		CIL_SYN_STRING,
3386 		CIL_SYN_STRING,
3387 		CIL_SYN_STRING,
3388 		CIL_SYN_STRING | CIL_SYN_END,
3389 		CIL_SYN_END
3390 	};
3391 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3392 	char *s1, *s2, *s3, *s4, *s5;
3393 
3394 	if (db == NULL || parse_current == NULL || ast_node == NULL ) {
3395 		goto exit;
3396 	}
3397 
3398 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3399 	if (rc != SEPOL_OK) {
3400 		goto exit;
3401 	}
3402 
3403 	s1 = parse_current->next->data;
3404 	s2 = parse_current->next->next->data;
3405 	s3 = parse_current->next->next->next->data;
3406 	s4 = parse_current->next->next->next->next->data;
3407 	s5 = NULL;
3408 
3409 	if (parse_current->next->next->next->next->next) {
3410 		if (s4 == CIL_KEY_STAR) {
3411 			s4 = parse_current->next->next->next->next->next->data;
3412 		} else {
3413 			s5 = parse_current->next->next->next->next->next->data;
3414 		}
3415 	}
3416 
3417 	if (s5) {
3418 		struct cil_nametypetransition *nametypetrans = NULL;
3419 		cil_nametypetransition_init(&nametypetrans);
3420 
3421 		ast_node->data = nametypetrans;
3422 		ast_node->flavor = CIL_NAMETYPETRANSITION;
3423 
3424 		nametypetrans->src_str = s1;
3425 		nametypetrans->tgt_str = s2;
3426 		nametypetrans->obj_str = s3;
3427 		nametypetrans->name_str = s4;
3428 		nametypetrans->name = cil_gen_declared_string(db, s4, ast_node);
3429 		nametypetrans->result_str = s5;
3430 	} else {
3431 		struct cil_type_rule *rule = NULL;
3432 		cil_type_rule_init(&rule);
3433 
3434 		ast_node->data = rule;
3435 		ast_node->flavor = CIL_TYPE_RULE;
3436 
3437 		rule->rule_kind = CIL_TYPE_TRANSITION;
3438 		rule->src_str = s1;
3439 		rule->tgt_str = s2;
3440 		rule->obj_str = s3;
3441 		rule->result_str = s4;
3442 	}
3443 
3444 	return SEPOL_OK;
3445 
3446 exit:
3447 	cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration");
3448 	return rc;
3449 }
3450 
cil_destroy_typetransition(struct cil_nametypetransition * nametypetrans)3451 void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans)
3452 {
3453 	if (nametypetrans == NULL) {
3454 		return;
3455 	}
3456 
3457 	free(nametypetrans);
3458 }
3459 
cil_gen_rangetransition(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3460 int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3461 {
3462 	enum cil_syntax syntax[] = {
3463 		CIL_SYN_STRING,
3464 		CIL_SYN_STRING,
3465 		CIL_SYN_STRING,
3466 		CIL_SYN_STRING,
3467 		CIL_SYN_STRING | CIL_SYN_LIST,
3468 		CIL_SYN_END
3469 	};
3470 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3471 	struct cil_rangetransition *rangetrans = NULL;
3472 	int rc = SEPOL_ERR;
3473 
3474 	if (db == NULL || parse_current == NULL || ast_node == NULL ) {
3475 		goto exit;
3476 	}
3477 
3478 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3479 	if (rc != SEPOL_OK) {
3480 		goto exit;
3481 	}
3482 
3483 	cil_rangetransition_init(&rangetrans);
3484 
3485 	rangetrans->src_str = parse_current->next->data;
3486 	rangetrans->exec_str = parse_current->next->next->data;
3487 	rangetrans->obj_str = parse_current->next->next->next->data;
3488 
3489 	rangetrans->range_str = NULL;
3490 
3491 	if (parse_current->next->next->next->next->cl_head == NULL) {
3492 		rangetrans->range_str = parse_current->next->next->next->next->data;
3493 	} else {
3494 		cil_levelrange_init(&rangetrans->range);
3495 
3496 		rc = cil_fill_levelrange(parse_current->next->next->next->next->cl_head, rangetrans->range);
3497 		if (rc != SEPOL_OK) {
3498 			goto exit;
3499 		}
3500 	}
3501 
3502 	ast_node->data = rangetrans;
3503 	ast_node->flavor = CIL_RANGETRANSITION;
3504 
3505 	return SEPOL_OK;
3506 
3507 exit:
3508 	cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration");
3509 	cil_destroy_rangetransition(rangetrans);
3510 	return rc;
3511 }
3512 
cil_destroy_rangetransition(struct cil_rangetransition * rangetrans)3513 void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans)
3514 {
3515 	if (rangetrans == NULL) {
3516 		return;
3517 	}
3518 
3519 	if (rangetrans->range_str == NULL && rangetrans->range != NULL) {
3520 		cil_destroy_levelrange(rangetrans->range);
3521 	}
3522 
3523 	free(rangetrans);
3524 }
3525 
cil_gen_sensitivity(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3526 int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3527 {
3528 	enum cil_syntax syntax[] = {
3529 		CIL_SYN_STRING,
3530 		CIL_SYN_STRING,
3531 		CIL_SYN_END
3532 	};
3533 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3534 	char *key = NULL;
3535 	struct cil_sens *sens = NULL;
3536 	int rc = SEPOL_ERR;
3537 
3538 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3539 		goto exit;
3540 	}
3541 
3542 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3543 	if (rc != SEPOL_OK) {
3544 		goto exit;
3545 	}
3546 
3547 	cil_sens_init(&sens);
3548 
3549 	key = parse_current->next->data;
3550 
3551 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sens, (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS);
3552 	if (rc != SEPOL_OK) {
3553 		goto exit;
3554 	}
3555 
3556 	return SEPOL_OK;
3557 
3558 exit:
3559 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration");
3560 	cil_destroy_sensitivity(sens);
3561 	cil_clear_node(ast_node);
3562 	return rc;
3563 }
3564 
cil_destroy_sensitivity(struct cil_sens * sens)3565 void cil_destroy_sensitivity(struct cil_sens *sens)
3566 {
3567 	if (sens == NULL) {
3568 		return;
3569 	}
3570 
3571 	cil_symtab_datum_destroy(&sens->datum);
3572 
3573 	cil_list_destroy(&sens->cats_list, CIL_FALSE);
3574 
3575 	free(sens);
3576 }
3577 
cil_gen_category(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3578 int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3579 {
3580 	enum cil_syntax syntax[] = {
3581 		CIL_SYN_STRING,
3582 		CIL_SYN_STRING,
3583 		CIL_SYN_END
3584 	};
3585 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3586 	char *key = NULL;
3587 	struct cil_cat *cat = NULL;
3588 	int rc = SEPOL_ERR;
3589 
3590 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3591 		goto exit;
3592 	}
3593 
3594 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3595 	if (rc != SEPOL_OK) {
3596 		goto exit;
3597 	}
3598 
3599 	cil_cat_init(&cat);
3600 
3601 	key = parse_current->next->data;
3602 
3603 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cat, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT);
3604 	if (rc != SEPOL_OK) {
3605 		goto exit;
3606 	}
3607 
3608 	return SEPOL_OK;
3609 
3610 exit:
3611 	cil_tree_log(parse_current, CIL_ERR, "Bad category declaration");
3612 	cil_destroy_category(cat);
3613 	cil_clear_node(ast_node);
3614 	return rc;
3615 }
3616 
cil_destroy_category(struct cil_cat * cat)3617 void cil_destroy_category(struct cil_cat *cat)
3618 {
3619 	if (cat == NULL) {
3620 		return;
3621 	}
3622 
3623 	cil_symtab_datum_destroy(&cat->datum);
3624 	free(cat);
3625 }
3626 
cil_gen_catset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3627 static int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3628 {
3629 	enum cil_syntax syntax[] = {
3630 		CIL_SYN_STRING,
3631 		CIL_SYN_STRING,
3632 		CIL_SYN_LIST,
3633 		CIL_SYN_END
3634 	};
3635 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3636 	char *key = NULL;
3637 	struct cil_catset *catset = NULL;
3638 	int rc = SEPOL_ERR;
3639 
3640 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3641 		goto exit;
3642 	}
3643 
3644 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3645 	if (rc != SEPOL_OK) {
3646 		goto exit;
3647 	}
3648 
3649 	cil_catset_init(&catset);
3650 
3651 	key = parse_current->next->data;
3652 
3653 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)catset, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET);
3654 	if (rc != SEPOL_OK) {
3655 		goto exit;
3656 	}
3657 
3658 	rc = cil_fill_cats(parse_current->next->next, &catset->cats);
3659 	if (rc != SEPOL_OK) {
3660 		goto exit;
3661 	}
3662 
3663 	return SEPOL_OK;
3664 
3665 exit:
3666 	cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration");
3667 	cil_destroy_catset(catset);
3668 	cil_clear_node(ast_node);
3669 	return rc;
3670 }
3671 
cil_destroy_catset(struct cil_catset * catset)3672 void cil_destroy_catset(struct cil_catset *catset)
3673 {
3674 	if (catset == NULL) {
3675 		return;
3676 	}
3677 
3678 	cil_symtab_datum_destroy(&catset->datum);
3679 
3680 	cil_destroy_cats(catset->cats);
3681 
3682 	free(catset);
3683 }
3684 
cil_gen_senscat(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3685 int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3686 {
3687 	enum cil_syntax syntax[] = {
3688 		CIL_SYN_STRING,
3689 		CIL_SYN_STRING,
3690 		CIL_SYN_STRING | CIL_SYN_LIST,
3691 		CIL_SYN_END
3692 	};
3693 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3694 	struct cil_senscat *senscat = NULL;
3695 	int rc = SEPOL_ERR;
3696 
3697 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3698 		goto exit;
3699 	}
3700 
3701 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3702 	if (rc != SEPOL_OK) {
3703 		goto exit;
3704 	}
3705 
3706 	cil_senscat_init(&senscat);
3707 
3708 	senscat->sens_str = parse_current->next->data;
3709 
3710 	rc = cil_fill_cats(parse_current->next->next, &senscat->cats);
3711 	if (rc != SEPOL_OK) {
3712 		goto exit;
3713 	}
3714 
3715 	ast_node->data = senscat;
3716 	ast_node->flavor = CIL_SENSCAT;
3717 
3718 	return SEPOL_OK;
3719 
3720 exit:
3721 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration");
3722 	cil_destroy_senscat(senscat);
3723 	return rc;
3724 }
3725 
cil_destroy_senscat(struct cil_senscat * senscat)3726 void cil_destroy_senscat(struct cil_senscat *senscat)
3727 {
3728 	if (senscat == NULL) {
3729 		return;
3730 	}
3731 
3732 	cil_destroy_cats(senscat->cats);
3733 
3734 	free(senscat);
3735 }
3736 
cil_gen_level(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3737 int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3738 {
3739 	enum cil_syntax syntax[] = {
3740 		CIL_SYN_STRING,
3741 		CIL_SYN_STRING,
3742 		CIL_SYN_LIST,
3743 		CIL_SYN_END
3744 	};
3745 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3746 	char *key = NULL;
3747 	struct cil_level *level = NULL;
3748 	int rc = SEPOL_ERR;
3749 
3750 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3751 		goto exit;
3752 	}
3753 
3754 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3755 	if (rc != SEPOL_OK) {
3756 		goto exit;
3757 	}
3758 
3759 	cil_level_init(&level);
3760 
3761 	key = parse_current->next->data;
3762 
3763 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)level, (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL);
3764 	if (rc != SEPOL_OK) {
3765 		goto exit;
3766 	}
3767 
3768 	rc = cil_fill_level(parse_current->next->next->cl_head, level);
3769 	if (rc != SEPOL_OK) {
3770 		goto exit;
3771 	}
3772 
3773 	return SEPOL_OK;
3774 
3775 exit:
3776 	cil_tree_log(parse_current, CIL_ERR, "Bad level declaration");
3777 	cil_destroy_level(level);
3778 	cil_clear_node(ast_node);
3779 	return rc;
3780 }
3781 
cil_destroy_level(struct cil_level * level)3782 void cil_destroy_level(struct cil_level *level)
3783 {
3784 	if (level == NULL) {
3785 		return;
3786 	}
3787 
3788 	cil_symtab_datum_destroy(&level->datum);
3789 
3790 	cil_destroy_cats(level->cats);
3791 
3792 	free(level);
3793 }
3794 
3795 /* low should be pointing to either the name of the low level or to an open paren for an anonymous low level */
cil_fill_levelrange(struct cil_tree_node * low,struct cil_levelrange * lvlrange)3796 int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange)
3797 {
3798 	enum cil_syntax syntax[] = {
3799 		CIL_SYN_STRING | CIL_SYN_LIST,
3800 		CIL_SYN_STRING | CIL_SYN_LIST,
3801 		CIL_SYN_END
3802 	};
3803 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3804 	int rc = SEPOL_ERR;
3805 
3806 	if (low == NULL || lvlrange == NULL) {
3807 		goto exit;
3808 	}
3809 
3810 	rc = __cil_verify_syntax(low, syntax, syntax_len);
3811 	if (rc != SEPOL_OK) {
3812 
3813 		goto exit;
3814 	}
3815 
3816 	if (low->cl_head == NULL) {
3817 		lvlrange->low_str = low->data;
3818 	} else {
3819 		cil_level_init(&lvlrange->low);
3820 		rc = cil_fill_level(low->cl_head, lvlrange->low);
3821 		if (rc != SEPOL_OK) {
3822 			goto exit;
3823 		}
3824 	}
3825 
3826 	if (low->next->cl_head == NULL) {
3827 		lvlrange->high_str = low->next->data;
3828 	} else {
3829 		cil_level_init(&lvlrange->high);
3830 		rc = cil_fill_level(low->next->cl_head, lvlrange->high);
3831 		if (rc != SEPOL_OK) {
3832 			goto exit;
3833 		}
3834 	}
3835 
3836 	return SEPOL_OK;
3837 
3838 exit:
3839 	cil_log(CIL_ERR, "Bad levelrange\n");
3840 	return rc;
3841 }
3842 
cil_gen_levelrange(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3843 int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3844 {
3845 	enum cil_syntax syntax[] = {
3846 		CIL_SYN_STRING,
3847 		CIL_SYN_STRING,
3848 		CIL_SYN_LIST,
3849 		CIL_SYN_END
3850 	};
3851 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3852 	char *key = NULL;
3853 	struct cil_levelrange *lvlrange = NULL;
3854 	int rc = SEPOL_ERR;
3855 
3856 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3857 		goto exit;
3858 	}
3859 
3860 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3861 	if (rc != SEPOL_OK) {
3862 		goto exit;
3863 	}
3864 
3865 	cil_levelrange_init(&lvlrange);
3866 
3867 	key = parse_current->next->data;
3868 
3869 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)lvlrange, (hashtab_key_t)key, CIL_SYM_LEVELRANGES, CIL_LEVELRANGE);
3870 	if (rc != SEPOL_OK) {
3871 		goto exit;
3872 	}
3873 
3874 	rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange);
3875 	if (rc != SEPOL_OK) {
3876 		goto exit;
3877 	}
3878 
3879 	return SEPOL_OK;
3880 
3881 exit:
3882 	cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration");
3883 	cil_destroy_levelrange(lvlrange);
3884 	cil_clear_node(ast_node);
3885 	return rc;
3886 }
3887 
cil_destroy_levelrange(struct cil_levelrange * lvlrange)3888 void cil_destroy_levelrange(struct cil_levelrange *lvlrange)
3889 {
3890 	if (lvlrange == NULL) {
3891 		return;
3892 	}
3893 
3894 	cil_symtab_datum_destroy(&lvlrange->datum);
3895 
3896 	if (lvlrange->low_str == NULL) {
3897 		cil_destroy_level(lvlrange->low);
3898 	}
3899 
3900 	if (lvlrange->high_str == NULL) {
3901 		cil_destroy_level(lvlrange->high);
3902 	}
3903 
3904 	free(lvlrange);
3905 }
3906 
cil_gen_constrain(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3907 int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3908 {
3909 	enum cil_syntax syntax[] = {
3910 		CIL_SYN_STRING,
3911 		CIL_SYN_STRING | CIL_SYN_LIST,
3912 		CIL_SYN_LIST,
3913 		CIL_SYN_END
3914 	};
3915 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3916 	struct cil_constrain *cons = NULL;
3917 	int rc = SEPOL_ERR;
3918 
3919 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3920 		goto exit;
3921 	}
3922 
3923 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3924 	if (rc != SEPOL_OK) {
3925 		goto exit;
3926 	}
3927 
3928 	cil_constrain_init(&cons);
3929 
3930 	rc = cil_fill_classperms_list(parse_current->next, &cons->classperms);
3931 	if (rc != SEPOL_OK) {
3932 		goto exit;
3933 	}
3934 
3935 	rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &cons->str_expr);
3936 	if (rc != SEPOL_OK) {
3937 		goto exit;
3938 	}
3939 
3940 	ast_node->data = cons;
3941 	ast_node->flavor = flavor;
3942 
3943 	return SEPOL_OK;
3944 
3945 exit:
3946 	cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration");
3947 	cil_destroy_constrain(cons);
3948 	return rc;
3949 }
3950 
cil_destroy_constrain(struct cil_constrain * cons)3951 void cil_destroy_constrain(struct cil_constrain *cons)
3952 {
3953 	if (cons == NULL) {
3954 		return;
3955 	}
3956 
3957 	cil_destroy_classperms_list(&cons->classperms);
3958 	cil_list_destroy(&cons->str_expr, CIL_TRUE);
3959 	cil_list_destroy(&cons->datum_expr, CIL_FALSE);
3960 
3961 	free(cons);
3962 }
3963 
cil_gen_validatetrans(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3964 int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3965 {
3966 	enum cil_syntax syntax[] = {
3967 		CIL_SYN_STRING,
3968 		CIL_SYN_STRING,
3969 		CIL_SYN_LIST,
3970 		CIL_SYN_END
3971 	};
3972 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3973 	struct cil_validatetrans *validtrans = NULL;
3974 	int rc = SEPOL_ERR;
3975 
3976 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3977 		goto exit;
3978 	}
3979 
3980 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3981 	if (rc != SEPOL_OK) {
3982 		goto exit;
3983 	}
3984 
3985 	cil_validatetrans_init(&validtrans);
3986 
3987 	validtrans->class_str = parse_current->next->data;
3988 
3989 	rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &validtrans->str_expr);
3990 	if (rc != SEPOL_OK) {
3991 		goto exit;
3992 	}
3993 
3994 	ast_node->data = validtrans;
3995 	ast_node->flavor = flavor;
3996 
3997 	return SEPOL_OK;
3998 
3999 exit:
4000 	cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration");
4001 	cil_destroy_validatetrans(validtrans);
4002 	return rc;
4003 
4004 
4005 }
4006 
cil_destroy_validatetrans(struct cil_validatetrans * validtrans)4007 void cil_destroy_validatetrans(struct cil_validatetrans *validtrans)
4008 {
4009 	if (validtrans == NULL) {
4010 		return;
4011 	}
4012 
4013 	cil_list_destroy(&validtrans->str_expr, CIL_TRUE);
4014 	cil_list_destroy(&validtrans->datum_expr, CIL_FALSE);
4015 
4016 	free(validtrans);
4017 }
4018 
4019 /* Fills in context starting from user */
cil_fill_context(struct cil_tree_node * user_node,struct cil_context * context)4020 int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context)
4021 {
4022 	enum cil_syntax syntax[] = {
4023 		CIL_SYN_STRING,
4024 		CIL_SYN_STRING,
4025 		CIL_SYN_STRING,
4026 		CIL_SYN_STRING | CIL_SYN_LIST,
4027 		CIL_SYN_END
4028 	};
4029 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4030 	int rc = SEPOL_ERR;
4031 
4032 	if (user_node == NULL || context == NULL) {
4033 		goto exit;
4034 	}
4035 
4036 	rc = __cil_verify_syntax(user_node, syntax, syntax_len);
4037 	if (rc != SEPOL_OK) {
4038 		goto exit;
4039 	}
4040 
4041 	context->user_str = user_node->data;
4042 	context->role_str = user_node->next->data;
4043 	context->type_str = user_node->next->next->data;
4044 
4045 	context->range_str = NULL;
4046 
4047 	if (user_node->next->next->next->cl_head == NULL) {
4048 		context->range_str = user_node->next->next->next->data;
4049 	} else {
4050 		cil_levelrange_init(&context->range);
4051 
4052 		rc = cil_fill_levelrange(user_node->next->next->next->cl_head, context->range);
4053 		if (rc != SEPOL_OK) {
4054 			goto exit;
4055 		}
4056 	}
4057 
4058 	return SEPOL_OK;
4059 
4060 exit:
4061 	cil_log(CIL_ERR, "Bad context\n");
4062 	return rc;
4063 }
4064 
cil_gen_context(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4065 int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4066 {
4067 	enum cil_syntax syntax[] = {
4068 		CIL_SYN_STRING,
4069 		CIL_SYN_STRING,
4070 		CIL_SYN_LIST,
4071 		CIL_SYN_END
4072 	};
4073 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4074 	char *key = NULL;
4075 	struct cil_context *context = NULL;
4076 	int rc = SEPOL_ERR;
4077 
4078 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4079 		goto exit;
4080 	}
4081 
4082 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4083 	if (rc != SEPOL_OK) {
4084 		goto exit;
4085 	}
4086 
4087 	cil_context_init(&context);
4088 
4089 	key = parse_current->next->data;
4090 
4091 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)context, (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT);
4092 	if (rc != SEPOL_OK) {
4093 		goto exit;
4094 	}
4095 
4096 	rc = cil_fill_context(parse_current->next->next->cl_head, context);
4097 	if (rc != SEPOL_OK) {
4098 		goto exit;
4099 	}
4100 
4101 	return SEPOL_OK;
4102 
4103 exit:
4104 	cil_tree_log(parse_current, CIL_ERR, "Bad context declaration");
4105 	cil_destroy_context(context);
4106 	cil_clear_node(ast_node);
4107 	return SEPOL_ERR;
4108 }
4109 
cil_destroy_context(struct cil_context * context)4110 void cil_destroy_context(struct cil_context *context)
4111 {
4112 	if (context == NULL) {
4113 		return;
4114 	}
4115 
4116 	cil_symtab_datum_destroy(&context->datum);
4117 
4118 	if (context->range_str == NULL && context->range != NULL) {
4119 		cil_destroy_levelrange(context->range);
4120 	}
4121 
4122 	free(context);
4123 }
4124 
cil_gen_filecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4125 int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4126 {
4127 	enum cil_syntax syntax[] = {
4128 		CIL_SYN_STRING,
4129 		CIL_SYN_STRING,
4130 		CIL_SYN_STRING,
4131 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
4132 		CIL_SYN_END
4133 	};
4134 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4135 	int rc = SEPOL_ERR;
4136 	struct cil_filecon *filecon = NULL;
4137 	char *type = NULL;
4138 
4139 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4140 		goto exit;
4141 	}
4142 
4143 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4144 	if (rc != SEPOL_OK) {
4145 		goto exit;
4146 	}
4147 
4148 	type = parse_current->next->next->data;
4149 	cil_filecon_init(&filecon);
4150 
4151 	ast_node->data = filecon;
4152 	ast_node->flavor = CIL_FILECON;
4153 
4154 	filecon->path_str = parse_current->next->data;
4155 	/* filecon->path will be NULL if in a macro and the path is an argument */
4156 	filecon->path = cil_gen_declared_string(db, filecon->path_str, ast_node);
4157 
4158 	if (type == CIL_KEY_ANY) {
4159 		filecon->type = CIL_FILECON_ANY;
4160 	} else if (type == CIL_KEY_FILE) {
4161 		filecon->type = CIL_FILECON_FILE;
4162 	} else if (type == CIL_KEY_DIR) {
4163 		filecon->type = CIL_FILECON_DIR;
4164 	} else if (type == CIL_KEY_CHAR) {
4165 		filecon->type = CIL_FILECON_CHAR;
4166 	} else if (type == CIL_KEY_BLOCK) {
4167 		filecon->type = CIL_FILECON_BLOCK;
4168 	} else if (type == CIL_KEY_SOCKET) {
4169 		filecon->type = CIL_FILECON_SOCKET;
4170 	} else if (type == CIL_KEY_PIPE) {
4171 		filecon->type = CIL_FILECON_PIPE;
4172 	} else if (type == CIL_KEY_SYMLINK) {
4173 		filecon->type = CIL_FILECON_SYMLINK;
4174 	} else {
4175 		cil_log(CIL_ERR, "Invalid file type\n");
4176 		rc = SEPOL_ERR;
4177 		goto exit;
4178 	}
4179 
4180 	if (parse_current->next->next->next->cl_head == NULL) {
4181 		filecon->context_str = parse_current->next->next->next->data;
4182 	} else {
4183 		if (parse_current->next->next->next->cl_head->next == NULL) {
4184 			filecon->context = NULL;
4185 		} else {
4186 			cil_context_init(&filecon->context);
4187 
4188 			rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context);
4189 			if (rc != SEPOL_OK) {
4190 				goto exit;
4191 			}
4192 		}
4193 	}
4194 
4195 	return SEPOL_OK;
4196 
4197 exit:
4198 	cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration");
4199 	cil_destroy_filecon(filecon);
4200 	cil_clear_node(ast_node);
4201 	return rc;
4202 }
4203 
4204 //TODO: Should we be checking if the pointer is NULL when passed in?
cil_destroy_filecon(struct cil_filecon * filecon)4205 void cil_destroy_filecon(struct cil_filecon *filecon)
4206 {
4207 	if (filecon == NULL) {
4208 		return;
4209 	}
4210 
4211 	if (filecon->context_str == NULL && filecon->context != NULL) {
4212 		cil_destroy_context(filecon->context);
4213 	}
4214 
4215 	free(filecon);
4216 }
4217 
cil_gen_ibpkeycon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4218 int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4219 {
4220 	enum cil_syntax syntax[] = {
4221 		CIL_SYN_STRING,
4222 		CIL_SYN_STRING,
4223 		CIL_SYN_STRING | CIL_SYN_LIST,
4224 		CIL_SYN_STRING | CIL_SYN_LIST,
4225 		CIL_SYN_END
4226 	};
4227 	size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4228 	int rc = SEPOL_ERR;
4229 	struct cil_ibpkeycon *ibpkeycon = NULL;
4230 
4231 	if (!parse_current || !ast_node)
4232 		goto exit;
4233 
4234 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4235 	if (rc != SEPOL_OK)
4236 		goto exit;
4237 
4238 	cil_ibpkeycon_init(&ibpkeycon);
4239 
4240 	ibpkeycon->subnet_prefix_str = parse_current->next->data;
4241 
4242 	if (parse_current->next->next->cl_head) {
4243 		if (parse_current->next->next->cl_head->next &&
4244 		    !parse_current->next->next->cl_head->next->next) {
4245 			rc = cil_fill_integer(parse_current->next->next->cl_head, &ibpkeycon->pkey_low, 0);
4246 			if (rc != SEPOL_OK) {
4247 				cil_log(CIL_ERR, "Improper ibpkey specified\n");
4248 				goto exit;
4249 			}
4250 			rc = cil_fill_integer(parse_current->next->next->cl_head->next, &ibpkeycon->pkey_high, 0);
4251 			if (rc != SEPOL_OK) {
4252 				cil_log(CIL_ERR, "Improper ibpkey specified\n");
4253 				goto exit;
4254 			}
4255 		} else {
4256 			cil_log(CIL_ERR, "Improper ibpkey range specified\n");
4257 			rc = SEPOL_ERR;
4258 			goto exit;
4259 		}
4260 	} else {
4261 		rc = cil_fill_integer(parse_current->next->next, &ibpkeycon->pkey_low, 0);
4262 		if (rc != SEPOL_OK) {
4263 			cil_log(CIL_ERR, "Improper ibpkey specified\n");
4264 			goto exit;
4265 		}
4266 		ibpkeycon->pkey_high = ibpkeycon->pkey_low;
4267 	}
4268 
4269 	if (!parse_current->next->next->next->cl_head) {
4270 		ibpkeycon->context_str = parse_current->next->next->next->data;
4271 	} else {
4272 		cil_context_init(&ibpkeycon->context);
4273 
4274 		rc = cil_fill_context(parse_current->next->next->next->cl_head, ibpkeycon->context);
4275 		if (rc != SEPOL_OK)
4276 			goto exit;
4277 	}
4278 
4279 	ast_node->data = ibpkeycon;
4280 	ast_node->flavor = CIL_IBPKEYCON;
4281 	return SEPOL_OK;
4282 
4283 exit:
4284 	cil_tree_log(parse_current, CIL_ERR, "Bad ibpkeycon declaration");
4285 	cil_destroy_ibpkeycon(ibpkeycon);
4286 
4287 	return rc;
4288 }
4289 
cil_destroy_ibpkeycon(struct cil_ibpkeycon * ibpkeycon)4290 void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
4291 {
4292 	if (!ibpkeycon)
4293 		return;
4294 
4295 	if (!ibpkeycon->context_str && ibpkeycon->context)
4296 		cil_destroy_context(ibpkeycon->context);
4297 
4298 	free(ibpkeycon);
4299 }
4300 
cil_gen_portcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4301 int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4302 {
4303 	enum cil_syntax syntax[] = {
4304 		CIL_SYN_STRING,
4305 		CIL_SYN_STRING,
4306 		CIL_SYN_STRING | CIL_SYN_LIST,
4307 		CIL_SYN_STRING | CIL_SYN_LIST,
4308 		CIL_SYN_END
4309 	};
4310 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4311 	int rc = SEPOL_ERR;
4312 	struct cil_portcon *portcon = NULL;
4313 	char *proto;
4314 
4315 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4316 		goto exit;
4317 	}
4318 
4319 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4320 	if (rc != SEPOL_OK) {
4321 		goto exit;
4322 	}
4323 
4324 	cil_portcon_init(&portcon);
4325 
4326 	proto = parse_current->next->data;
4327 	if (proto == CIL_KEY_UDP) {
4328 		portcon->proto = CIL_PROTOCOL_UDP;
4329 	} else if (proto == CIL_KEY_TCP) {
4330 		portcon->proto = CIL_PROTOCOL_TCP;
4331 	} else if (proto == CIL_KEY_DCCP) {
4332 		portcon->proto = CIL_PROTOCOL_DCCP;
4333 	} else if (proto == CIL_KEY_SCTP) {
4334 		portcon->proto = CIL_PROTOCOL_SCTP;
4335 	} else {
4336 		cil_log(CIL_ERR, "Invalid protocol\n");
4337 		rc = SEPOL_ERR;
4338 		goto exit;
4339 	}
4340 
4341 	if (parse_current->next->next->cl_head != NULL) {
4342 		if (parse_current->next->next->cl_head->next != NULL
4343 		&& parse_current->next->next->cl_head->next->next == NULL) {
4344 			rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10);
4345 			if (rc != SEPOL_OK) {
4346 				cil_log(CIL_ERR, "Improper port specified\n");
4347 				goto exit;
4348 			}
4349 			rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10);
4350 			if (rc != SEPOL_OK) {
4351 				cil_log(CIL_ERR, "Improper port specified\n");
4352 				goto exit;
4353 			}
4354 		} else {
4355 			cil_log(CIL_ERR, "Improper port range specified\n");
4356 			rc = SEPOL_ERR;
4357 			goto exit;
4358 		}
4359 	} else {
4360 		rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10);
4361 		if (rc != SEPOL_OK) {
4362 			cil_log(CIL_ERR, "Improper port specified\n");
4363 			goto exit;
4364 		}
4365 		portcon->port_high = portcon->port_low;
4366 	}
4367 
4368 	if (parse_current->next->next->next->cl_head == NULL ) {
4369 		portcon->context_str = parse_current->next->next->next->data;
4370 	} else {
4371 		cil_context_init(&portcon->context);
4372 
4373 		rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context);
4374 		if (rc != SEPOL_OK) {
4375 			goto exit;
4376 		}
4377 	}
4378 
4379 	ast_node->data = portcon;
4380 	ast_node->flavor = CIL_PORTCON;
4381 
4382 	return SEPOL_OK;
4383 
4384 exit:
4385 	cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration");
4386 	cil_destroy_portcon(portcon);
4387 	return rc;
4388 }
4389 
cil_destroy_portcon(struct cil_portcon * portcon)4390 void cil_destroy_portcon(struct cil_portcon *portcon)
4391 {
4392 	if (portcon == NULL) {
4393 		return;
4394 	}
4395 
4396 	if (portcon->context_str == NULL && portcon->context != NULL) {
4397 		cil_destroy_context(portcon->context);
4398 	}
4399 
4400 	free(portcon);
4401 }
4402 
cil_gen_nodecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4403 int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4404 {
4405 	enum cil_syntax syntax[] = {
4406 		CIL_SYN_STRING,
4407 		CIL_SYN_STRING | CIL_SYN_LIST,
4408 		CIL_SYN_STRING | CIL_SYN_LIST,
4409 		CIL_SYN_STRING | CIL_SYN_LIST,
4410 		CIL_SYN_END
4411 	};
4412 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4413 	int rc = SEPOL_ERR;
4414 	struct cil_nodecon *nodecon = NULL;
4415 
4416 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4417 		goto exit;
4418 	}
4419 
4420 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4421 	if (rc != SEPOL_OK) {
4422 		goto exit;
4423 	}
4424 
4425 	cil_nodecon_init(&nodecon);
4426 
4427 	if (parse_current->next->cl_head) {
4428 		cil_ipaddr_init(&nodecon->addr);
4429 		rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr);
4430 		if (rc != SEPOL_OK) {
4431 			goto exit;
4432 		}
4433 	} else {
4434 		char *addr = parse_current->next->data;
4435 		if (strchr(addr, ':') || (strchr(addr, '.') && isdigit(addr[0]))) {
4436 			cil_ipaddr_init(&nodecon->addr);
4437 			rc = cil_fill_ipaddr(parse_current->next, nodecon->addr);
4438 			if (rc != SEPOL_OK) {
4439 				goto exit;
4440 			}
4441 		} else {
4442 			nodecon->addr_str = addr;
4443 		}
4444 	}
4445 
4446 	if (parse_current->next->next->cl_head) {
4447 		cil_ipaddr_init(&nodecon->mask);
4448 		rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask);
4449 		if (rc != SEPOL_OK) {
4450 			goto exit;
4451 		}
4452 	} else {
4453 		char *mask = parse_current->next->next->data;
4454 		if (strchr(mask, ':') || (strchr(mask, '.') && isdigit(mask[0]))) {
4455 			cil_ipaddr_init(&nodecon->mask);
4456 			rc = cil_fill_ipaddr(parse_current->next->next, nodecon->mask);
4457 			if (rc != SEPOL_OK) {
4458 				goto exit;
4459 			}
4460 		} else {
4461 			nodecon->mask_str = mask;
4462 		}
4463 	}
4464 
4465 	if (parse_current->next->next->next->cl_head == NULL ) {
4466 		nodecon->context_str = parse_current->next->next->next->data;
4467 	} else {
4468 		cil_context_init(&nodecon->context);
4469 
4470 		rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context);
4471 		if (rc != SEPOL_OK) {
4472 			goto exit;
4473 		}
4474 	}
4475 
4476 	ast_node->data = nodecon;
4477 	ast_node->flavor = CIL_NODECON;
4478 
4479 	return SEPOL_OK;
4480 
4481 exit:
4482 	cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration");
4483 	cil_destroy_nodecon(nodecon);
4484 	return rc;
4485 }
4486 
cil_destroy_nodecon(struct cil_nodecon * nodecon)4487 void cil_destroy_nodecon(struct cil_nodecon *nodecon)
4488 {
4489 	if (nodecon == NULL) {
4490 		return;
4491 	}
4492 
4493 	if (nodecon->addr_str == NULL && nodecon->addr != NULL) {
4494 		cil_destroy_ipaddr(nodecon->addr);
4495 	}
4496 
4497 	if (nodecon->mask_str == NULL && nodecon->mask != NULL) {
4498 		cil_destroy_ipaddr(nodecon->mask);
4499 	}
4500 
4501 	if (nodecon->context_str == NULL && nodecon->context != NULL) {
4502 		cil_destroy_context(nodecon->context);
4503 	}
4504 
4505 	free(nodecon);
4506 }
4507 
cil_gen_genfscon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4508 int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4509 {
4510 	enum cil_syntax syntax[] = {
4511 		CIL_SYN_STRING,
4512 		CIL_SYN_STRING,
4513 		CIL_SYN_STRING,
4514 		CIL_SYN_STRING | CIL_SYN_LIST,
4515 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
4516 		CIL_SYN_END
4517 	};
4518 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4519 	struct cil_tree_node *context_node;
4520 	int rc = SEPOL_ERR;
4521 	struct cil_genfscon *genfscon = NULL;
4522 
4523 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4524 		goto exit;
4525 	}
4526 
4527 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4528 	if (rc != SEPOL_OK) {
4529 		goto exit;
4530 	}
4531 
4532 	cil_genfscon_init(&genfscon);
4533 
4534 	genfscon->fs_str = parse_current->next->data;
4535 	genfscon->path_str = parse_current->next->next->data;
4536 
4537 	if (parse_current->next->next->next->next) {
4538 		/* (genfscon <FS_STR> <PATH_STR> <FILE_TYPE> ... */
4539 		char *file_type = parse_current->next->next->next->data;
4540 		if (file_type == CIL_KEY_ANY) {
4541 			genfscon->file_type = CIL_FILECON_ANY;
4542 		} else if (file_type == CIL_KEY_FILE) {
4543 			genfscon->file_type = CIL_FILECON_FILE;
4544 		} else if (file_type == CIL_KEY_DIR) {
4545 			genfscon->file_type = CIL_FILECON_DIR;
4546 		} else if (file_type == CIL_KEY_CHAR) {
4547 			genfscon->file_type = CIL_FILECON_CHAR;
4548 		} else if (file_type == CIL_KEY_BLOCK) {
4549 			genfscon->file_type = CIL_FILECON_BLOCK;
4550 		} else if (file_type == CIL_KEY_SOCKET) {
4551 			genfscon->file_type = CIL_FILECON_SOCKET;
4552 		} else if (file_type == CIL_KEY_PIPE) {
4553 			genfscon->file_type = CIL_FILECON_PIPE;
4554 		} else if (file_type == CIL_KEY_SYMLINK) {
4555 			genfscon->file_type = CIL_FILECON_SYMLINK;
4556 		} else {
4557 			if (parse_current->next->next->next->cl_head) {
4558 				cil_log(CIL_ERR, "Expecting file type, but found a list\n");
4559 			} else {
4560 				cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type);
4561 			}
4562 			goto exit;
4563 		}
4564 		context_node = parse_current->next->next->next->next;
4565 	} else {
4566 		/* (genfscon <FS_STR> <PATH_STR> ... */
4567 		context_node = parse_current->next->next->next;
4568 	}
4569 
4570 	if (context_node->cl_head) {
4571 		cil_context_init(&genfscon->context);
4572 		rc = cil_fill_context(context_node->cl_head, genfscon->context);
4573 		if (rc != SEPOL_OK) {
4574 			goto exit;
4575 		}
4576 	} else {
4577 		genfscon->context_str = context_node->data;
4578 	}
4579 
4580 	ast_node->data = genfscon;
4581 	ast_node->flavor = CIL_GENFSCON;
4582 
4583 	return SEPOL_OK;
4584 
4585 exit:
4586 	cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
4587 	cil_destroy_genfscon(genfscon);
4588 	return SEPOL_ERR;
4589 }
4590 
cil_destroy_genfscon(struct cil_genfscon * genfscon)4591 void cil_destroy_genfscon(struct cil_genfscon *genfscon)
4592 {
4593 	if (genfscon == NULL) {
4594 		return;
4595 	}
4596 
4597 	if (genfscon->context_str == NULL && genfscon->context != NULL) {
4598 		cil_destroy_context(genfscon->context);
4599 	}
4600 
4601 	free(genfscon);
4602 }
4603 
4604 
cil_gen_netifcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4605 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4606 {
4607 	enum cil_syntax syntax[] = {
4608 		CIL_SYN_STRING,
4609 		CIL_SYN_STRING,
4610 		CIL_SYN_STRING | CIL_SYN_LIST,
4611 		CIL_SYN_STRING | CIL_SYN_LIST,
4612 		CIL_SYN_END
4613 	};
4614 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4615 	int rc = SEPOL_ERR;
4616 	struct cil_netifcon *netifcon = NULL;
4617 
4618 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4619 		goto exit;
4620 	}
4621 
4622 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4623 	if (rc != SEPOL_OK) {
4624 		goto exit;
4625 	}
4626 
4627 	cil_netifcon_init(&netifcon);
4628 
4629 	netifcon->interface_str = parse_current->next->data;
4630 
4631 	if (parse_current->next->next->cl_head == NULL) {
4632 		netifcon->if_context_str = parse_current->next->next->data;
4633 	} else {
4634 		cil_context_init(&netifcon->if_context);
4635 
4636 		rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context);
4637 		if (rc != SEPOL_OK) {
4638 			goto exit;
4639 		}
4640 	}
4641 
4642 	if (parse_current->next->next->next->cl_head == NULL) {
4643 		netifcon->packet_context_str = parse_current->next->next->next->data;
4644 	} else {
4645 		cil_context_init(&netifcon->packet_context);
4646 
4647 		rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context);
4648 		if (rc != SEPOL_OK) {
4649 			goto exit;
4650 		}
4651 	}
4652 
4653 	ast_node->data = netifcon;
4654 	ast_node->flavor = CIL_NETIFCON;
4655 
4656 	return SEPOL_OK;
4657 
4658 exit:
4659 	cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
4660 	cil_destroy_netifcon(netifcon);
4661 	return SEPOL_ERR;
4662 }
4663 
cil_destroy_netifcon(struct cil_netifcon * netifcon)4664 void cil_destroy_netifcon(struct cil_netifcon *netifcon)
4665 {
4666 	if (netifcon == NULL) {
4667 		return;
4668 	}
4669 
4670 	if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
4671 		cil_destroy_context(netifcon->if_context);
4672 	}
4673 
4674 	if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) {
4675 		cil_destroy_context(netifcon->packet_context);
4676 	}
4677 
4678 	free(netifcon);
4679 }
4680 
cil_gen_ibendportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4681 int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4682 {
4683 	enum cil_syntax syntax[] = {
4684 		CIL_SYN_STRING,
4685 		CIL_SYN_STRING,
4686 		CIL_SYN_STRING,
4687 		CIL_SYN_STRING | CIL_SYN_LIST,
4688 		CIL_SYN_END
4689 	};
4690 	size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4691 	int rc = SEPOL_ERR;
4692 	struct cil_ibendportcon *ibendportcon = NULL;
4693 
4694 	if (!parse_current || !ast_node)
4695 		goto exit;
4696 
4697 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4698 	if (rc != SEPOL_OK)
4699 		goto exit;
4700 
4701 	cil_ibendportcon_init(&ibendportcon);
4702 
4703 	ibendportcon->dev_name_str = parse_current->next->data;
4704 
4705 	rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10);
4706 	if (rc != SEPOL_OK) {
4707 		cil_log(CIL_ERR, "Improper ibendport port specified\n");
4708 		goto exit;
4709 	}
4710 
4711 	if (!parse_current->next->next->next->cl_head) {
4712 		ibendportcon->context_str = parse_current->next->next->next->data;
4713 	} else {
4714 		cil_context_init(&ibendportcon->context);
4715 
4716 		rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context);
4717 		if (rc != SEPOL_OK)
4718 			goto exit;
4719 	}
4720 
4721 	ast_node->data = ibendportcon;
4722 	ast_node->flavor = CIL_IBENDPORTCON;
4723 
4724 	return SEPOL_OK;
4725 
4726 exit:
4727 	cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration");
4728 	cil_destroy_ibendportcon(ibendportcon);
4729 	return SEPOL_ERR;
4730 }
4731 
cil_destroy_ibendportcon(struct cil_ibendportcon * ibendportcon)4732 void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon)
4733 {
4734 	if (!ibendportcon)
4735 		return;
4736 
4737 	if (!ibendportcon->context_str && ibendportcon->context)
4738 		cil_destroy_context(ibendportcon->context);
4739 
4740 	free(ibendportcon);
4741 }
4742 
cil_gen_pirqcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4743 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4744 {
4745 	enum cil_syntax syntax[] = {
4746 		CIL_SYN_STRING,
4747 		CIL_SYN_STRING,
4748 		CIL_SYN_STRING | CIL_SYN_LIST,
4749 		CIL_SYN_END
4750 	};
4751 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4752 	int rc = SEPOL_ERR;
4753 	struct cil_pirqcon *pirqcon = NULL;
4754 
4755 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4756 		goto exit;
4757 	}
4758 
4759 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4760 	if (rc != SEPOL_OK) {
4761 		goto exit;
4762 	}
4763 
4764 	cil_pirqcon_init(&pirqcon);
4765 
4766 	rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
4767 	if (rc != SEPOL_OK) {
4768 		goto exit;
4769 	}
4770 
4771 	if (parse_current->next->next->cl_head == NULL) {
4772 		pirqcon->context_str = parse_current->next->next->data;
4773 	} else {
4774 		cil_context_init(&pirqcon->context);
4775 
4776 		rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context);
4777 		if (rc != SEPOL_OK) {
4778 			goto exit;
4779 		}
4780 	}
4781 
4782 	ast_node->data = pirqcon;
4783 	ast_node->flavor = CIL_PIRQCON;
4784 
4785 	return SEPOL_OK;
4786 
4787 exit:
4788 	cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
4789 	cil_destroy_pirqcon(pirqcon);
4790 	return rc;
4791 }
4792 
cil_destroy_pirqcon(struct cil_pirqcon * pirqcon)4793 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
4794 {
4795 	if (pirqcon == NULL) {
4796 		return;
4797 	}
4798 
4799 	if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
4800 		cil_destroy_context(pirqcon->context);
4801 	}
4802 
4803 	free(pirqcon);
4804 }
4805 
cil_gen_iomemcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4806 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4807 {
4808 	enum cil_syntax syntax[] = {
4809 		CIL_SYN_STRING,
4810 		CIL_SYN_STRING | CIL_SYN_LIST,
4811 		CIL_SYN_STRING | CIL_SYN_LIST,
4812 		CIL_SYN_END
4813 	};
4814 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4815 	int rc = SEPOL_ERR;
4816 	struct cil_iomemcon *iomemcon = NULL;
4817 
4818 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4819 		goto exit;
4820 	}
4821 
4822 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4823 	if (rc != SEPOL_OK) {
4824 		goto exit;
4825 	}
4826 
4827 	cil_iomemcon_init(&iomemcon);
4828 
4829 	if (parse_current->next->cl_head != NULL) {
4830 		if (parse_current->next->cl_head->next != NULL &&
4831 		    parse_current->next->cl_head->next->next == NULL) {
4832 			rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0);
4833 			if (rc != SEPOL_OK) {
4834 				cil_log(CIL_ERR, "Improper iomem specified\n");
4835 				goto exit;
4836 			}
4837 			rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0);
4838 			if (rc != SEPOL_OK) {
4839 				cil_log(CIL_ERR, "Improper iomem specified\n");
4840 				goto exit;
4841 			}
4842 		} else {
4843 			cil_log(CIL_ERR, "Improper iomem range specified\n");
4844 			rc = SEPOL_ERR;
4845 			goto exit;
4846 		}
4847 	} else {
4848 		rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0);
4849 		if (rc != SEPOL_OK) {
4850 			cil_log(CIL_ERR, "Improper iomem specified\n");
4851 			goto exit;
4852 		}
4853 		iomemcon->iomem_high = iomemcon->iomem_low;
4854 	}
4855 
4856 	if (parse_current->next->next->cl_head == NULL ) {
4857 		iomemcon->context_str = parse_current->next->next->data;
4858 	} else {
4859 		cil_context_init(&iomemcon->context);
4860 
4861 		rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context);
4862 		if (rc != SEPOL_OK) {
4863 			goto exit;
4864 		}
4865 	}
4866 
4867 	ast_node->data = iomemcon;
4868 	ast_node->flavor = CIL_IOMEMCON;
4869 
4870 	return SEPOL_OK;
4871 
4872 exit:
4873 	cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
4874 	cil_destroy_iomemcon(iomemcon);
4875 	return rc;
4876 }
4877 
cil_destroy_iomemcon(struct cil_iomemcon * iomemcon)4878 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
4879 {
4880 	if (iomemcon == NULL) {
4881 		return;
4882 	}
4883 
4884 	if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
4885 		cil_destroy_context(iomemcon->context);
4886 	}
4887 
4888 	free(iomemcon);
4889 }
4890 
cil_gen_ioportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4891 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4892 {
4893 	enum cil_syntax syntax[] = {
4894 		CIL_SYN_STRING,
4895 		CIL_SYN_STRING | CIL_SYN_LIST,
4896 		CIL_SYN_STRING | CIL_SYN_LIST,
4897 		CIL_SYN_END
4898 	};
4899 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4900 	int rc = SEPOL_ERR;
4901 	struct cil_ioportcon *ioportcon = NULL;
4902 
4903 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4904 		goto exit;
4905 	}
4906 
4907 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4908 	if (rc != SEPOL_OK) {
4909 		goto exit;
4910 	}
4911 
4912 	cil_ioportcon_init(&ioportcon);
4913 
4914 	if (parse_current->next->cl_head != NULL) {
4915 		if (parse_current->next->cl_head->next != NULL &&
4916 		    parse_current->next->cl_head->next->next == NULL) {
4917 			rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0);
4918 			if (rc != SEPOL_OK) {
4919 				cil_log(CIL_ERR, "Improper ioport specified\n");
4920 				goto exit;
4921 			}
4922 			rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0);
4923 			if (rc != SEPOL_OK) {
4924 				cil_log(CIL_ERR, "Improper ioport specified\n");
4925 				goto exit;
4926 			}
4927 		} else {
4928 			cil_log(CIL_ERR, "Improper ioport range specified\n");
4929 			rc = SEPOL_ERR;
4930 			goto exit;
4931 		}
4932 	} else {
4933 		rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0);
4934 		if (rc != SEPOL_OK) {
4935 			cil_log(CIL_ERR, "Improper ioport specified\n");
4936 			goto exit;
4937 		}
4938 		ioportcon->ioport_high = ioportcon->ioport_low;
4939 	}
4940 
4941 	if (parse_current->next->next->cl_head == NULL ) {
4942 		ioportcon->context_str = parse_current->next->next->data;
4943 	} else {
4944 		cil_context_init(&ioportcon->context);
4945 
4946 		rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context);
4947 		if (rc != SEPOL_OK) {
4948 			goto exit;
4949 		}
4950 	}
4951 
4952 	ast_node->data = ioportcon;
4953 	ast_node->flavor = CIL_IOPORTCON;
4954 
4955 	return SEPOL_OK;
4956 
4957 exit:
4958 	cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
4959 	cil_destroy_ioportcon(ioportcon);
4960 	return rc;
4961 }
4962 
cil_destroy_ioportcon(struct cil_ioportcon * ioportcon)4963 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
4964 {
4965 	if (ioportcon == NULL) {
4966 		return;
4967 	}
4968 
4969 	if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
4970 		cil_destroy_context(ioportcon->context);
4971 	}
4972 
4973 	free(ioportcon);
4974 }
4975 
cil_gen_pcidevicecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4976 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4977 {
4978 	enum cil_syntax syntax[] = {
4979 		CIL_SYN_STRING,
4980 		CIL_SYN_STRING,
4981 		CIL_SYN_STRING | CIL_SYN_LIST,
4982 		CIL_SYN_END
4983 	};
4984 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4985 	int rc = SEPOL_ERR;
4986 	struct cil_pcidevicecon *pcidevicecon = NULL;
4987 
4988 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4989 		goto exit;
4990 	}
4991 
4992 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4993 	if (rc != SEPOL_OK) {
4994 		goto exit;
4995 	}
4996 
4997 	cil_pcidevicecon_init(&pcidevicecon);
4998 
4999 	rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
5000 	if (rc != SEPOL_OK) {
5001 		goto exit;
5002 	}
5003 
5004 	if (parse_current->next->next->cl_head == NULL) {
5005 		pcidevicecon->context_str = parse_current->next->next->data;
5006 	} else {
5007 		cil_context_init(&pcidevicecon->context);
5008 
5009 		rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context);
5010 		if (rc != SEPOL_OK) {
5011 			goto exit;
5012 		}
5013 	}
5014 
5015 	ast_node->data = pcidevicecon;
5016 	ast_node->flavor = CIL_PCIDEVICECON;
5017 
5018 	return SEPOL_OK;
5019 
5020 exit:
5021 	cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
5022 	cil_destroy_pcidevicecon(pcidevicecon);
5023 	return rc;
5024 }
5025 
cil_destroy_pcidevicecon(struct cil_pcidevicecon * pcidevicecon)5026 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
5027 {
5028 	if (pcidevicecon == NULL) {
5029 		return;
5030 	}
5031 
5032 	if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) {
5033 		cil_destroy_context(pcidevicecon->context);
5034 	}
5035 
5036 	free(pcidevicecon);
5037 }
5038 
cil_gen_devicetreecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5039 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5040 {
5041 	enum cil_syntax syntax[] = {
5042 		CIL_SYN_STRING,
5043 		CIL_SYN_STRING,
5044 		CIL_SYN_STRING | CIL_SYN_LIST,
5045 		CIL_SYN_END
5046 	};
5047 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5048 	int rc = SEPOL_ERR;
5049 	struct cil_devicetreecon *devicetreecon = NULL;
5050 
5051 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5052 		goto exit;
5053 	}
5054 
5055 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5056 	if (rc != SEPOL_OK) {
5057 		goto exit;
5058 	}
5059 
5060 	cil_devicetreecon_init(&devicetreecon);
5061 
5062 	devicetreecon->path = parse_current->next->data;
5063 
5064 	if (parse_current->next->next->cl_head == NULL) {
5065 		devicetreecon->context_str = parse_current->next->next->data;
5066 	} else {
5067 		cil_context_init(&devicetreecon->context);
5068 
5069 		rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context);
5070 		if (rc != SEPOL_OK) {
5071 			goto exit;
5072 		}
5073 	}
5074 
5075 	ast_node->data = devicetreecon;
5076 	ast_node->flavor = CIL_DEVICETREECON;
5077 
5078 	return SEPOL_OK;
5079 
5080 exit:
5081 	cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
5082 	cil_destroy_devicetreecon(devicetreecon);
5083 	return rc;
5084 }
5085 
cil_destroy_devicetreecon(struct cil_devicetreecon * devicetreecon)5086 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
5087 {
5088 	if (devicetreecon == NULL) {
5089 		return;
5090 	}
5091 
5092 	if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) {
5093 		cil_destroy_context(devicetreecon->context);
5094 	}
5095 
5096 	free(devicetreecon);
5097 }
5098 
cil_gen_fsuse(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5099 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5100 {
5101 	enum cil_syntax syntax[] = {
5102 		CIL_SYN_STRING,
5103 		CIL_SYN_STRING,
5104 		CIL_SYN_STRING,
5105 		CIL_SYN_STRING | CIL_SYN_LIST,
5106 		CIL_SYN_END
5107 	};
5108 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5109 	char *type = NULL;
5110 	struct cil_fsuse *fsuse = NULL;
5111 	int rc = SEPOL_ERR;
5112 
5113 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5114 		goto exit;
5115 	}
5116 
5117 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5118 	if (rc != SEPOL_OK) {
5119 		goto exit;
5120 	}
5121 
5122 	type = parse_current->next->data;
5123 
5124 	cil_fsuse_init(&fsuse);
5125 
5126 	if (type == CIL_KEY_XATTR) {
5127 		fsuse->type = CIL_FSUSE_XATTR;
5128 	} else if (type == CIL_KEY_TASK) {
5129 		fsuse->type = CIL_FSUSE_TASK;
5130 	} else if (type == CIL_KEY_TRANS) {
5131 		fsuse->type = CIL_FSUSE_TRANS;
5132 	} else {
5133 		cil_log(CIL_ERR, "Invalid fsuse type\n");
5134 		goto exit;
5135 	}
5136 
5137 	fsuse->fs_str = parse_current->next->next->data;
5138 
5139 	if (parse_current->next->next->next->cl_head == NULL) {
5140 		fsuse->context_str = parse_current->next->next->next->data;
5141 	} else {
5142 		cil_context_init(&fsuse->context);
5143 
5144 		rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context);
5145 		if (rc != SEPOL_OK) {
5146 			goto exit;
5147 		}
5148 	}
5149 
5150 	ast_node->data = fsuse;
5151 	ast_node->flavor = CIL_FSUSE;
5152 
5153 	return SEPOL_OK;
5154 
5155 exit:
5156 	cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
5157 	cil_destroy_fsuse(fsuse);
5158 	return SEPOL_ERR;
5159 }
5160 
cil_destroy_fsuse(struct cil_fsuse * fsuse)5161 void cil_destroy_fsuse(struct cil_fsuse *fsuse)
5162 {
5163 	if (fsuse == NULL) {
5164 		return;
5165 	}
5166 
5167 	if (fsuse->context_str == NULL && fsuse->context != NULL) {
5168 		cil_destroy_context(fsuse->context);
5169 	}
5170 
5171 	free(fsuse);
5172 }
5173 
cil_destroy_param(struct cil_param * param)5174 void cil_destroy_param(struct cil_param *param)
5175 {
5176 	if (param == NULL) {
5177 		return;
5178 	}
5179 
5180 	free(param);
5181 }
5182 
cil_gen_macro(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5183 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5184 {
5185 	int rc = SEPOL_ERR;
5186 	char *key = NULL;
5187 	struct cil_macro *macro = NULL;
5188 	struct cil_tree_node *macro_content = NULL;
5189 	struct cil_tree_node *current_item;
5190 	enum cil_syntax syntax[] = {
5191 		CIL_SYN_STRING,
5192 		CIL_SYN_STRING,
5193 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
5194 		CIL_SYN_N_LISTS | CIL_SYN_END,
5195 		CIL_SYN_END
5196 	};
5197 	size_t syntax_len = sizeof(syntax)/ sizeof(*syntax);
5198 
5199 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5200 		goto exit;
5201 	}
5202 
5203 	rc =__cil_verify_syntax(parse_current, syntax, syntax_len);
5204 	if (rc != SEPOL_OK) {
5205 		goto exit;
5206 	}
5207 
5208 	cil_macro_init(&macro);
5209 
5210 	key = parse_current->next->data;
5211 
5212 	current_item = parse_current->next->next->cl_head;
5213 	while (current_item != NULL) {
5214 		enum cil_syntax param_syntax[] = {
5215 			CIL_SYN_STRING,
5216 			CIL_SYN_STRING,
5217 			CIL_SYN_END
5218 		};
5219 		int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
5220 		char *kind = NULL;
5221 		struct cil_param *param = NULL;
5222 		struct cil_list_item *curr_param;
5223 
5224 		rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
5225 		if (rc != SEPOL_OK) {
5226 			goto exit;
5227 		}
5228 
5229 		if (macro->params == NULL) {
5230 			cil_list_init(&macro->params, CIL_LIST_ITEM);
5231 		}
5232 
5233 		kind = current_item->cl_head->data;
5234 		cil_param_init(&param);
5235 
5236 		if (kind == CIL_KEY_TYPE) {
5237 			param->flavor = CIL_TYPE;
5238 		} else if (kind == CIL_KEY_ROLE) {
5239 			param->flavor = CIL_ROLE;
5240 		} else if (kind == CIL_KEY_USER) {
5241 			param->flavor = CIL_USER;
5242 		} else if (kind == CIL_KEY_SENSITIVITY) {
5243 			param->flavor = CIL_SENS;
5244 		} else if (kind == CIL_KEY_CATEGORY) {
5245 			param->flavor = CIL_CAT;
5246 		} else if (kind == CIL_KEY_CATSET) {
5247 			param->flavor = CIL_CATSET;
5248 		} else if (kind == CIL_KEY_LEVEL) {
5249 			param->flavor = CIL_LEVEL;
5250 		} else if (kind == CIL_KEY_LEVELRANGE) {
5251 			param->flavor = CIL_LEVELRANGE;
5252 		} else if (kind == CIL_KEY_CLASS) {
5253 			param->flavor = CIL_CLASS;
5254 		} else if (kind == CIL_KEY_IPADDR) {
5255 			param->flavor = CIL_IPADDR;
5256 		} else if (kind == CIL_KEY_MAP_CLASS) {
5257 			param->flavor = CIL_MAP_CLASS;
5258 		} else if (kind == CIL_KEY_CLASSPERMISSION) {
5259 			param->flavor = CIL_CLASSPERMISSION;
5260 		} else if (kind == CIL_KEY_BOOL) {
5261 			param->flavor = CIL_BOOL;
5262 		} else if (kind == CIL_KEY_STRING) {
5263 			param->flavor = CIL_DECLARED_STRING;
5264 		} else if (kind == CIL_KEY_NAME) {
5265 			param->flavor = CIL_DECLARED_STRING;
5266 		} else {
5267 			cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind);
5268 			cil_destroy_param(param);
5269 			goto exit;
5270 		}
5271 
5272 		param->str =  current_item->cl_head->next->data;
5273 
5274 		rc = cil_verify_name(db, param->str, param->flavor);
5275 		if (rc != SEPOL_OK) {
5276 			cil_destroy_param(param);
5277 			goto exit;
5278 		}
5279 
5280 		//walk current list and check for duplicate parameters
5281 		cil_list_for_each(curr_param, macro->params) {
5282 			if (param->str == ((struct cil_param*)curr_param->data)->str) {
5283 				cil_log(CIL_ERR, "Duplicate parameter\n");
5284 				cil_destroy_param(param);
5285 				goto exit;
5286 			}
5287 		}
5288 
5289 		cil_list_append(macro->params, CIL_PARAM, param);
5290 
5291 		current_item = current_item->next;
5292 	}
5293 
5294 	/* we don't want the tree walker to walk the macro parameters (they were just handled above), so the subtree is deleted, and the next pointer of the
5295            node containing the macro name is updated to point to the start of the macro content */
5296 	macro_content = parse_current->next->next->next;
5297 	cil_tree_subtree_destroy(parse_current->next->next);
5298 	parse_current->next->next = macro_content;
5299 	if (macro_content == NULL) {
5300 		/* No statements in macro and macro parameter list was last node */
5301 		parse_current->parent->cl_tail = parse_current->next;
5302 	}
5303 
5304 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
5305 	if (rc != SEPOL_OK) {
5306 		goto exit;
5307 	}
5308 
5309 	return SEPOL_OK;
5310 
5311 exit:
5312 	cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
5313 	cil_destroy_macro(macro);
5314 	cil_clear_node(ast_node);
5315 	return SEPOL_ERR;
5316 }
5317 
cil_destroy_macro(struct cil_macro * macro)5318 void cil_destroy_macro(struct cil_macro *macro)
5319 {
5320 	if (macro == NULL) {
5321 		return;
5322 	}
5323 
5324 	cil_symtab_datum_destroy(&macro->datum);
5325 	cil_symtab_array_destroy(macro->symtab);
5326 
5327 	if (macro->params != NULL) {
5328 		cil_list_destroy(&macro->params, 1);
5329 	}
5330 
5331 	free(macro);
5332 }
5333 
cil_gen_call(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5334 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5335 {
5336 	enum cil_syntax syntax[] = {
5337 		CIL_SYN_STRING,
5338 		CIL_SYN_STRING,
5339 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
5340 		CIL_SYN_END
5341 	};
5342 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5343 	struct cil_call *call = NULL;
5344 	int rc = SEPOL_ERR;
5345 
5346 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5347 		goto exit;
5348 	}
5349 
5350 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5351 	if (rc != SEPOL_OK) {
5352 		goto exit;
5353 	}
5354 
5355 	cil_call_init(&call);
5356 
5357 	call->macro_str = parse_current->next->data;
5358 
5359 	if (parse_current->next->next != NULL) {
5360 		cil_tree_init(&call->args_tree);
5361 		cil_copy_ast(db, parse_current->next->next, call->args_tree->root);
5362 	}
5363 
5364 	ast_node->data = call;
5365 	ast_node->flavor = CIL_CALL;
5366 
5367 	return SEPOL_OK;
5368 
5369 exit:
5370 	cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
5371 	cil_destroy_call(call);
5372 	return rc;
5373 }
5374 
cil_destroy_call(struct cil_call * call)5375 void cil_destroy_call(struct cil_call *call)
5376 {
5377 	if (call == NULL) {
5378 		return;
5379 	}
5380 
5381 	call->macro = NULL;
5382 
5383 	if (call->args_tree != NULL) {
5384 		cil_tree_destroy(&call->args_tree);
5385 	}
5386 
5387 	if (call->args != NULL) {
5388 		cil_list_destroy(&call->args, 1);
5389 	}
5390 
5391 	free(call);
5392 }
5393 
cil_destroy_args(struct cil_args * args)5394 void cil_destroy_args(struct cil_args *args)
5395 {
5396 	if (args == NULL) {
5397 		return;
5398 	}
5399 
5400 	if (args->arg_str != NULL) {
5401 		args->arg_str = NULL;
5402 	} else if (args->arg != NULL) {
5403 		struct cil_tree_node *node = args->arg->nodes->head->data;
5404 		switch (args->flavor) {
5405 		case CIL_DECLARED_STRING:
5406 			break;
5407 		case CIL_CATSET:
5408 			cil_destroy_catset((struct cil_catset *)args->arg);
5409 			free(node);
5410 			break;
5411 		case CIL_LEVEL:
5412 			cil_destroy_level((struct cil_level *)args->arg);
5413 			free(node);
5414 			break;
5415 		case CIL_LEVELRANGE:
5416 			cil_destroy_levelrange((struct cil_levelrange *)args->arg);
5417 			free(node);
5418 			break;
5419 		case CIL_IPADDR:
5420 			cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
5421 			free(node);
5422 			break;
5423 		case CIL_CLASSPERMISSION:
5424 			cil_destroy_classpermission((struct cil_classpermission *)args->arg);
5425 			free(node);
5426 			break;
5427 		default:
5428 			cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor);
5429 			break;
5430 		}
5431 	}
5432 
5433 	args->param_str = NULL;
5434 	args->arg = NULL;
5435 
5436 	free(args);
5437 }
5438 
cil_gen_optional(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5439 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5440 {
5441 	enum cil_syntax syntax[] = {
5442 		CIL_SYN_STRING,
5443 		CIL_SYN_STRING,
5444 		CIL_SYN_N_LISTS | CIL_SYN_END,
5445 		CIL_SYN_END
5446 	};
5447 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5448 	char *key = NULL;
5449 	struct cil_optional *optional = NULL;
5450 	int rc = SEPOL_ERR;
5451 
5452 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5453 		goto exit;
5454 	}
5455 
5456 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5457 	if (rc != SEPOL_OK) {
5458 		goto exit;
5459 	}
5460 
5461 	cil_optional_init(&optional);
5462 
5463 	key = parse_current->next->data;
5464 
5465 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
5466 	if (rc != SEPOL_OK) {
5467 		if (rc == SEPOL_EEXIST) {
5468 			cil_destroy_optional(optional);
5469 			optional = NULL;
5470 		} else {
5471 			goto exit;
5472 		}
5473 	}
5474 
5475 	return SEPOL_OK;
5476 
5477 exit:
5478 	cil_tree_log(parse_current, CIL_ERR, "Bad optional");
5479 	cil_destroy_optional(optional);
5480 	cil_clear_node(ast_node);
5481 	return rc;
5482 }
5483 
cil_destroy_optional(struct cil_optional * optional)5484 void cil_destroy_optional(struct cil_optional *optional)
5485 {
5486 	if (optional == NULL) {
5487 		return;
5488 	}
5489 
5490 	cil_symtab_datum_destroy(&optional->datum);
5491 	free(optional);
5492 }
5493 
cil_gen_policycap(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5494 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5495 {
5496 	enum cil_syntax syntax[] = {
5497 		CIL_SYN_STRING,
5498 		CIL_SYN_STRING,
5499 		CIL_SYN_END
5500 	};
5501 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5502 	char *key = NULL;
5503 	struct cil_policycap *polcap = NULL;
5504 	int rc = SEPOL_ERR;
5505 
5506 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5507 		goto exit;
5508 	}
5509 
5510 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5511 	if (rc != SEPOL_OK) {
5512 		goto exit;
5513 	}
5514 
5515 	cil_policycap_init(&polcap);
5516 
5517 	key = parse_current->next->data;
5518 
5519 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP);
5520 	if (rc != SEPOL_OK)
5521 		goto exit;
5522 
5523 	return SEPOL_OK;
5524 
5525 exit:
5526 	cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
5527 	cil_destroy_policycap(polcap);
5528 	cil_clear_node(ast_node);
5529 	return rc;
5530 }
5531 
cil_destroy_policycap(struct cil_policycap * polcap)5532 void cil_destroy_policycap(struct cil_policycap *polcap)
5533 {
5534 	if (polcap == NULL) {
5535 		return;
5536 	}
5537 
5538 	cil_symtab_datum_destroy(&polcap->datum);
5539 	free(polcap);
5540 }
5541 
cil_gen_ipaddr(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5542 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5543 {
5544 	enum cil_syntax syntax[] = {
5545 		CIL_SYN_STRING,
5546 		CIL_SYN_STRING,
5547 		CIL_SYN_STRING,
5548 		CIL_SYN_END
5549 	};
5550 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5551 	char *key = NULL;
5552 	struct cil_ipaddr *ipaddr = NULL;
5553 	int rc = SEPOL_ERR;
5554 
5555 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5556 		goto exit;
5557 	}
5558 
5559 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5560 	if (rc != SEPOL_OK) {
5561 		goto exit;
5562 	}
5563 
5564 	cil_ipaddr_init(&ipaddr);
5565 
5566 	key  = parse_current->next->data;
5567 
5568 	rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
5569 	if (rc != SEPOL_OK) {
5570 		goto exit;
5571 	}
5572 
5573 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
5574 	if (rc != SEPOL_OK) {
5575 		goto exit;
5576 	}
5577 
5578 	return SEPOL_OK;
5579 
5580 exit:
5581 	cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
5582 	cil_destroy_ipaddr(ipaddr);
5583 	cil_clear_node(ast_node);
5584 	return rc;
5585 }
5586 
cil_destroy_ipaddr(struct cil_ipaddr * ipaddr)5587 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
5588 {
5589 	if (ipaddr == NULL) {
5590 		return;
5591 	}
5592 
5593 	cil_symtab_datum_destroy(&ipaddr->datum);
5594 	free(ipaddr);
5595 }
5596 
cil_fill_integer(struct cil_tree_node * int_node,uint32_t * integer,int base)5597 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
5598 {
5599 	int rc = SEPOL_ERR;
5600 
5601 	if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5602 		goto exit;
5603 	}
5604 
5605 	rc = cil_string_to_uint32(int_node->data, integer, base);
5606 	if (rc != SEPOL_OK) {
5607 		goto exit;
5608 	}
5609 
5610 	return SEPOL_OK;
5611 
5612 exit:
5613 	cil_log(CIL_ERR, "Failed to fill 32-bit integer\n");
5614 	return rc;
5615 }
5616 
cil_fill_integer64(struct cil_tree_node * int_node,uint64_t * integer,int base)5617 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
5618 {
5619 	int rc = SEPOL_ERR;
5620 
5621 	if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5622 		goto exit;
5623 	}
5624 
5625 	rc = cil_string_to_uint64(int_node->data, integer, base);
5626 	if (rc != SEPOL_OK) {
5627 		goto exit;
5628 	}
5629 
5630 	return SEPOL_OK;
5631 
5632 exit:
5633 	cil_log(CIL_ERR, "Failed to fill 64-bit integer\n");
5634 	return rc;
5635 }
5636 
cil_fill_ipaddr(struct cil_tree_node * addr_node,struct cil_ipaddr * addr)5637 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
5638 {
5639 	int rc = SEPOL_ERR;
5640 	char *addr_str;
5641 
5642 	if (addr_node == NULL || addr_node->data == NULL || addr == NULL) {
5643 		goto exit;
5644 	}
5645 
5646 	addr_str = addr_node->data;
5647 	if (strchr(addr_str, ':')) {
5648 		addr->family = AF_INET6;
5649 	} else if (strchr(addr_str, '.') && isdigit(addr_str[0])) {
5650 		addr->family = AF_INET;
5651 	} else {
5652 		goto exit;
5653 	}
5654 
5655 	rc = inet_pton(addr->family, addr_node->data, &addr->ip);
5656 	if (rc != 1) {
5657 		rc = SEPOL_ERR;
5658 		goto exit;
5659 	}
5660 
5661 	return SEPOL_OK;
5662 
5663 exit:
5664 	cil_log(CIL_ERR, "Bad ip address or netmask: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "NULL");
5665 	return rc;
5666 }
5667 
cil_fill_level(struct cil_tree_node * curr,struct cil_level * level)5668 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
5669 {
5670 	int rc = SEPOL_ERR;
5671 	enum cil_syntax syntax[] = {
5672 		CIL_SYN_STRING,
5673 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
5674 		CIL_SYN_END
5675 	};
5676 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5677 
5678 	if (curr == NULL) {
5679 		goto exit;
5680 	}
5681 
5682 	rc = __cil_verify_syntax(curr, syntax, syntax_len);
5683 	if (rc != SEPOL_OK) {
5684 		goto exit;
5685 	}
5686 
5687 	level->sens_str = curr->data;
5688 	if (curr->next != NULL) {
5689 		rc = cil_fill_cats(curr->next, &level->cats);
5690 		if (rc != SEPOL_OK) {
5691 			goto exit;
5692 		}
5693 	}
5694 
5695 	return SEPOL_OK;
5696 
5697 exit:
5698 	cil_log(CIL_ERR, "Bad level\n");
5699 	return rc;
5700 }
5701 
cil_fill_cats(struct cil_tree_node * curr,struct cil_cats ** cats)5702 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
5703 {
5704 	int rc = SEPOL_ERR;
5705 
5706 	cil_cats_init(cats);
5707 
5708 	rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
5709 	if (rc != SEPOL_OK) {
5710 		cil_destroy_cats(*cats);
5711 		*cats = NULL;
5712 	}
5713 
5714 	return rc;
5715 }
5716 
cil_destroy_cats(struct cil_cats * cats)5717 void cil_destroy_cats(struct cil_cats *cats)
5718 {
5719 	if (cats == NULL) {
5720 		return;
5721 	}
5722 
5723 	cil_list_destroy(&cats->str_expr, CIL_TRUE);
5724 
5725 	cil_list_destroy(&cats->datum_expr, CIL_FALSE);
5726 
5727 	free(cats);
5728 }
cil_gen_bounds(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5729 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5730 {
5731 	enum cil_syntax syntax[] = {
5732 		CIL_SYN_STRING,
5733 		CIL_SYN_STRING,
5734 		CIL_SYN_STRING,
5735 		CIL_SYN_END
5736 	};
5737 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5738 	struct cil_bounds *bounds = NULL;
5739 	int rc = SEPOL_ERR;
5740 
5741 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5742 		goto exit;
5743 	}
5744 
5745 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5746 	if (rc != SEPOL_OK) {
5747 		goto exit;
5748 	}
5749 
5750 	cil_bounds_init(&bounds);
5751 
5752 	bounds->parent_str = parse_current->next->data;
5753 	bounds->child_str = parse_current->next->next->data;
5754 
5755 	ast_node->data = bounds;
5756 
5757 	switch (flavor) {
5758 	case CIL_USER:
5759 		ast_node->flavor = CIL_USERBOUNDS;
5760 		break;
5761 	case CIL_ROLE:
5762 		ast_node->flavor = CIL_ROLEBOUNDS;
5763 		break;
5764 	case CIL_TYPE:
5765 		ast_node->flavor = CIL_TYPEBOUNDS;
5766 		break;
5767 	default:
5768 		break;
5769 	}
5770 
5771 	return SEPOL_OK;
5772 
5773 exit:
5774 	cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
5775 	cil_destroy_bounds(bounds);
5776 	return rc;
5777 }
5778 
cil_destroy_bounds(struct cil_bounds * bounds)5779 void cil_destroy_bounds(struct cil_bounds *bounds)
5780 {
5781 	if (bounds == NULL) {
5782 		return;
5783 	}
5784 
5785 	free(bounds);
5786 }
5787 
cil_gen_default(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5788 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5789 {
5790 	int rc = SEPOL_ERR;
5791 	struct cil_default *def = NULL;
5792 	char *object;
5793 	enum cil_syntax syntax[] = {
5794 		CIL_SYN_STRING,
5795 		CIL_SYN_STRING | CIL_SYN_LIST,
5796 		CIL_SYN_STRING,
5797 		CIL_SYN_END
5798 	};
5799 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5800 
5801 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5802 	if (rc != SEPOL_OK) {
5803 		goto exit;
5804 	}
5805 
5806 	cil_default_init(&def);
5807 
5808 	def->flavor = flavor;
5809 
5810 	if (parse_current->next->cl_head == NULL) {
5811 		cil_list_init(&def->class_strs, CIL_CLASS);
5812 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5813 	} else {
5814 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5815 		if (rc != SEPOL_OK) {
5816 			goto exit;
5817 		}
5818 	}
5819 
5820 	object = parse_current->next->next->data;
5821 	if (object == CIL_KEY_SOURCE) {
5822 		def->object = CIL_DEFAULT_SOURCE;
5823 	} else if (object == CIL_KEY_TARGET) {
5824 		def->object = CIL_DEFAULT_TARGET;
5825 	} else {
5826 		cil_log(CIL_ERR,"Expected either 'source' or 'target'\n");
5827 		rc = SEPOL_ERR;
5828 		goto exit;
5829 	}
5830 
5831 	ast_node->data = def;
5832 	ast_node->flavor = flavor;
5833 
5834 	return SEPOL_OK;
5835 
5836 exit:
5837 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current));
5838 	cil_destroy_default(def);
5839 	return rc;
5840 }
5841 
cil_destroy_default(struct cil_default * def)5842 void cil_destroy_default(struct cil_default *def)
5843 {
5844 	if (def == NULL) {
5845 		return;
5846 	}
5847 
5848 	cil_list_destroy(&def->class_strs, CIL_TRUE);
5849 
5850 	cil_list_destroy(&def->class_datums, CIL_FALSE);
5851 
5852 	free(def);
5853 }
5854 
cil_gen_defaultrange(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5855 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5856 {
5857 	int rc = SEPOL_ERR;
5858 	struct cil_defaultrange *def = NULL;
5859 	char *object;
5860 	char *range;
5861 	enum cil_syntax syntax[] = {
5862 		CIL_SYN_STRING,
5863 		CIL_SYN_STRING | CIL_SYN_LIST,
5864 		CIL_SYN_STRING,
5865 		CIL_SYN_STRING | CIL_SYN_END,
5866 		CIL_SYN_END
5867 	};
5868 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5869 
5870 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5871 	if (rc != SEPOL_OK) {
5872 		goto exit;
5873 	}
5874 
5875 	cil_defaultrange_init(&def);
5876 
5877 	if (parse_current->next->cl_head == NULL) {
5878 		cil_list_init(&def->class_strs, CIL_CLASS);
5879 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5880 	} else {
5881 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5882 		if (rc != SEPOL_OK) {
5883 			goto exit;
5884 		}
5885 	}
5886 
5887 	object = parse_current->next->next->data;
5888 	if (object == CIL_KEY_SOURCE) {
5889 		if (!parse_current->next->next->next) {
5890 			cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5891 			rc = SEPOL_ERR;
5892 			goto exit;
5893 		}
5894 		range = parse_current->next->next->next->data;
5895 		if (range == CIL_KEY_LOW) {
5896 			def->object_range = CIL_DEFAULT_SOURCE_LOW;
5897 		} else if (range == CIL_KEY_HIGH) {
5898 			def->object_range = CIL_DEFAULT_SOURCE_HIGH;
5899 		} else if (range == CIL_KEY_LOW_HIGH) {
5900 			def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
5901 		} else {
5902 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5903 			rc = SEPOL_ERR;
5904 			goto exit;
5905 		}
5906 	} else if (object == CIL_KEY_TARGET) {
5907 		if (!parse_current->next->next->next) {
5908 			cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5909 			rc = SEPOL_ERR;
5910 			goto exit;
5911 		}
5912 		range = parse_current->next->next->next->data;
5913 		if (range == CIL_KEY_LOW) {
5914 			def->object_range = CIL_DEFAULT_TARGET_LOW;
5915 		} else if (range == CIL_KEY_HIGH) {
5916 			def->object_range = CIL_DEFAULT_TARGET_HIGH;
5917 		} else if (range == CIL_KEY_LOW_HIGH) {
5918 			def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
5919 		} else {
5920 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5921 			rc = SEPOL_ERR;
5922 			goto exit;
5923 		}
5924 	} else if (object == CIL_KEY_GLBLUB) {
5925 		def->object_range = CIL_DEFAULT_GLBLUB;
5926 	} else {
5927 		cil_log(CIL_ERR,"Expected \'source\', \'target\', or \'glblub\'\n");
5928 		rc = SEPOL_ERR;
5929 		goto exit;
5930 	}
5931 
5932 	ast_node->data = def;
5933 	ast_node->flavor = CIL_DEFAULTRANGE;
5934 
5935 	return SEPOL_OK;
5936 
5937 exit:
5938 	cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
5939 	cil_destroy_defaultrange(def);
5940 	return rc;
5941 }
5942 
cil_destroy_defaultrange(struct cil_defaultrange * def)5943 void cil_destroy_defaultrange(struct cil_defaultrange *def)
5944 {
5945 	if (def == NULL) {
5946 		return;
5947 	}
5948 
5949 	cil_list_destroy(&def->class_strs, CIL_TRUE);
5950 
5951 	cil_list_destroy(&def->class_datums, CIL_FALSE);
5952 
5953 	free(def);
5954 }
5955 
cil_gen_handleunknown(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5956 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5957 {
5958 	int rc = SEPOL_ERR;
5959 	enum cil_syntax syntax[] = {
5960 		CIL_SYN_STRING,
5961 		CIL_SYN_STRING,
5962 		CIL_SYN_END
5963 	};
5964 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5965 	struct cil_handleunknown *unknown = NULL;
5966 	char *unknown_key;
5967 
5968 	if (parse_current == NULL || ast_node == NULL) {
5969 		goto exit;
5970 	}
5971 
5972 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5973 	if (rc != SEPOL_OK) {
5974 		goto exit;
5975 	}
5976 
5977 	cil_handleunknown_init(&unknown);
5978 
5979 	unknown_key = parse_current->next->data;
5980 	if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
5981 		unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
5982 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
5983 		unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
5984 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
5985 		unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
5986 	} else {
5987 		cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT);
5988 		rc = SEPOL_ERR;
5989 		goto exit;
5990 	}
5991 
5992 	ast_node->data = unknown;
5993 	ast_node->flavor = CIL_HANDLEUNKNOWN;
5994 
5995 	return SEPOL_OK;
5996 
5997 exit:
5998 	cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
5999 	cil_destroy_handleunknown(unknown);
6000 	return rc;
6001 }
6002 
cil_destroy_handleunknown(struct cil_handleunknown * unk)6003 void cil_destroy_handleunknown(struct cil_handleunknown *unk)
6004 {
6005 	free(unk);
6006 }
6007 
cil_gen_mls(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6008 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6009 {
6010 	int rc = SEPOL_ERR;
6011 	enum cil_syntax syntax[] = {
6012 		CIL_SYN_STRING,
6013 		CIL_SYN_STRING,
6014 		CIL_SYN_END
6015 	};
6016 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6017 	struct cil_mls *mls = NULL;
6018 
6019 	if (parse_current == NULL || ast_node == NULL) {
6020 		goto exit;
6021 	}
6022 
6023 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6024 	if (rc != SEPOL_OK) {
6025 		goto exit;
6026 	}
6027 
6028 	cil_mls_init(&mls);
6029 
6030 	if (parse_current->next->data == CIL_KEY_CONDTRUE) {
6031 		mls->value = CIL_TRUE;
6032 	} else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
6033 		mls->value = CIL_FALSE;
6034 	} else {
6035 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
6036 		rc = SEPOL_ERR;
6037 		goto exit;
6038 	}
6039 
6040 	ast_node->data = mls;
6041 	ast_node->flavor = CIL_MLS;
6042 
6043 	return SEPOL_OK;
6044 
6045 exit:
6046 	cil_tree_log(parse_current, CIL_ERR, "Bad mls");
6047 	cil_destroy_mls(mls);
6048 	return rc;
6049 }
6050 
cil_destroy_mls(struct cil_mls * mls)6051 void cil_destroy_mls(struct cil_mls *mls)
6052 {
6053 	free(mls);
6054 }
6055 
cil_gen_src_info(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6056 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6057 {
6058 	int rc = SEPOL_ERR;
6059 	enum cil_syntax syntax[] = {
6060 		CIL_SYN_STRING,
6061 		CIL_SYN_STRING,
6062 		CIL_SYN_STRING,
6063 		CIL_SYN_STRING,
6064 		CIL_SYN_N_LISTS | CIL_SYN_END,
6065 		CIL_SYN_END
6066 	};
6067 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6068 	struct cil_src_info *info = NULL;
6069 
6070 	if (parse_current == NULL || ast_node == NULL) {
6071 		goto exit;
6072 	}
6073 
6074 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6075 	if (rc != SEPOL_OK) {
6076 		goto exit;
6077 	}
6078 
6079 	cil_src_info_init(&info);
6080 
6081 	info->kind = parse_current->next->data;
6082 	if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) {
6083 		cil_log(CIL_ERR, "Invalid src info kind\n");
6084 		rc = SEPOL_ERR;
6085 		goto exit;
6086 	}
6087 
6088 	rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10);
6089 	if (rc != SEPOL_OK) {
6090 		goto exit;
6091 	}
6092 
6093 	info->path = parse_current->next->next->next->data;
6094 
6095 	ast_node->data = info;
6096 	ast_node->flavor = CIL_SRC_INFO;
6097 
6098 	return SEPOL_OK;
6099 
6100 exit:
6101 	cil_tree_log(parse_current, CIL_ERR, "Bad src info");
6102 	cil_destroy_src_info(info);
6103 	return rc;
6104 }
6105 
cil_destroy_src_info(struct cil_src_info * info)6106 void cil_destroy_src_info(struct cil_src_info *info)
6107 {
6108 	free(info);
6109 }
6110 
check_for_illegal_statement(struct cil_tree_node * parse_current,struct cil_args_build * args)6111 static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args)
6112 {
6113 	if (args->tunif != NULL) {
6114 		if (parse_current->data == CIL_KEY_TUNABLE) {
6115 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data);
6116 			return SEPOL_ERR;
6117 		}
6118 	}
6119 
6120 	if (args->in != NULL) {
6121 		struct cil_in *in_block = args->in->data;
6122 		if (parse_current->data == CIL_KEY_TUNABLE ||
6123 			parse_current->data == CIL_KEY_IN) {
6124 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data);
6125 			return SEPOL_ERR;
6126 		}
6127 		if (in_block->is_after == CIL_TRUE) {
6128 			if (parse_current->data == CIL_KEY_BLOCKINHERIT ||
6129 				parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6130 				cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data);
6131 				return SEPOL_ERR;
6132 			}
6133 		}
6134 	}
6135 
6136 	if (args->macro != NULL) {
6137 		if (parse_current->data == CIL_KEY_TUNABLE ||
6138 			parse_current->data == CIL_KEY_IN ||
6139 			parse_current->data == CIL_KEY_BLOCK ||
6140 			parse_current->data == CIL_KEY_BLOCKINHERIT ||
6141 			parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6142 			parse_current->data == CIL_KEY_MACRO) {
6143 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data);
6144 			return SEPOL_ERR;
6145 		}
6146 	}
6147 
6148 	if (args->optional != NULL) {
6149 		if (parse_current->data == CIL_KEY_TUNABLE ||
6150 			parse_current->data == CIL_KEY_IN ||
6151 			parse_current->data == CIL_KEY_BLOCK ||
6152 			parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6153 			parse_current->data == CIL_KEY_MACRO) {
6154 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data);
6155 			return SEPOL_ERR;
6156 		}
6157 	}
6158 
6159 	if (args->boolif != NULL) {
6160 		if (parse_current->data != CIL_KEY_TUNABLEIF &&
6161 			parse_current->data != CIL_KEY_CALL &&
6162 			parse_current->data != CIL_KEY_CONDTRUE &&
6163 			parse_current->data != CIL_KEY_CONDFALSE &&
6164 			parse_current->data != CIL_KEY_ALLOW &&
6165 			parse_current->data != CIL_KEY_DONTAUDIT &&
6166 			parse_current->data != CIL_KEY_AUDITALLOW &&
6167 			parse_current->data != CIL_KEY_TYPETRANSITION &&
6168 			parse_current->data != CIL_KEY_TYPECHANGE &&
6169 			parse_current->data != CIL_KEY_TYPEMEMBER) {
6170 			if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) {
6171 				cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data);
6172 			} else {
6173 				cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data);
6174 			}
6175 			return SEPOL_ERR;
6176 		}
6177 	}
6178 
6179 	return SEPOL_OK;
6180 }
6181 
parse_statement(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_parent)6182 static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent)
6183 {
6184 	struct cil_tree_node *new_ast_node = NULL;
6185 	int rc = SEPOL_ERR;
6186 
6187 	cil_tree_node_init(&new_ast_node);
6188 	new_ast_node->parent = ast_parent;
6189 	new_ast_node->line = parse_current->line;
6190 	new_ast_node->hll_offset = parse_current->hll_offset;
6191 
6192 	if (parse_current->data == CIL_KEY_BLOCK) {
6193 		rc = cil_gen_block(db, parse_current, new_ast_node, 0);
6194 	} else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
6195 		rc = cil_gen_blockinherit(db, parse_current, new_ast_node);
6196 	} else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6197 		rc = cil_gen_blockabstract(db, parse_current, new_ast_node);
6198 	} else if (parse_current->data == CIL_KEY_IN) {
6199 		rc = cil_gen_in(db, parse_current, new_ast_node);
6200 	} else if (parse_current->data == CIL_KEY_CLASS) {
6201 		rc = cil_gen_class(db, parse_current, new_ast_node);
6202 	} else if (parse_current->data == CIL_KEY_CLASSORDER) {
6203 		rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CLASSORDER);
6204 	} else if (parse_current->data == CIL_KEY_MAP_CLASS) {
6205 		rc = cil_gen_map_class(db, parse_current, new_ast_node);
6206 	} else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
6207 		rc = cil_gen_classmapping(db, parse_current, new_ast_node);
6208 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
6209 		rc = cil_gen_classpermission(db, parse_current, new_ast_node);
6210 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
6211 		rc = cil_gen_classpermissionset(db, parse_current, new_ast_node);
6212 	} else if (parse_current->data == CIL_KEY_COMMON) {
6213 		rc = cil_gen_common(db, parse_current, new_ast_node);
6214 	} else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
6215 		rc = cil_gen_classcommon(db, parse_current, new_ast_node);
6216 	} else if (parse_current->data == CIL_KEY_SID) {
6217 		rc = cil_gen_sid(db, parse_current, new_ast_node);
6218 	} else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
6219 		rc = cil_gen_sidcontext(db, parse_current, new_ast_node);
6220 	} else if (parse_current->data == CIL_KEY_SIDORDER) {
6221 		rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SIDORDER);
6222 	} else if (parse_current->data == CIL_KEY_USER) {
6223 		rc = cil_gen_user(db, parse_current, new_ast_node);
6224 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
6225 		rc = cil_gen_userattribute(db, parse_current, new_ast_node);
6226 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
6227 		rc = cil_gen_userattributeset(db, parse_current, new_ast_node);
6228 	} else if (parse_current->data == CIL_KEY_USERLEVEL) {
6229 		rc = cil_gen_userlevel(db, parse_current, new_ast_node);
6230 	} else if (parse_current->data == CIL_KEY_USERRANGE) {
6231 		rc = cil_gen_userrange(db, parse_current, new_ast_node);
6232 	} else if (parse_current->data == CIL_KEY_USERBOUNDS) {
6233 		rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER);
6234 	} else if (parse_current->data == CIL_KEY_USERPREFIX) {
6235 		rc = cil_gen_userprefix(db, parse_current, new_ast_node);
6236 	} else if (parse_current->data == CIL_KEY_SELINUXUSER) {
6237 		rc = cil_gen_selinuxuser(db, parse_current, new_ast_node);
6238 	} else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
6239 		rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node);
6240 	} else if (parse_current->data == CIL_KEY_TYPE) {
6241 		rc = cil_gen_type(db, parse_current, new_ast_node);
6242 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
6243 		rc = cil_gen_typeattribute(db, parse_current, new_ast_node);
6244 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
6245 		rc = cil_gen_typeattributeset(db, parse_current, new_ast_node);
6246 	} else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
6247 		rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node);
6248 	} else if (parse_current->data == CIL_KEY_TYPEALIAS) {
6249 		rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS);
6250 	} else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
6251 		rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL);
6252 	} else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
6253 		rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE);
6254 	} else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
6255 		rc = cil_gen_typepermissive(db, parse_current, new_ast_node);
6256 	} else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
6257 		rc = cil_gen_rangetransition(db, parse_current, new_ast_node);
6258 	} else if (parse_current->data == CIL_KEY_ROLE) {
6259 		rc = cil_gen_role(db, parse_current, new_ast_node);
6260 	} else if (parse_current->data == CIL_KEY_USERROLE) {
6261 		rc = cil_gen_userrole(db, parse_current, new_ast_node);
6262 	} else if (parse_current->data == CIL_KEY_ROLETYPE) {
6263 		rc = cil_gen_roletype(db, parse_current, new_ast_node);
6264 	} else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
6265 		rc = cil_gen_roletransition(parse_current, new_ast_node);
6266 	} else if (parse_current->data == CIL_KEY_ROLEALLOW) {
6267 		rc = cil_gen_roleallow(db, parse_current, new_ast_node);
6268 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
6269 		rc = cil_gen_roleattribute(db, parse_current, new_ast_node);
6270 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
6271 		rc = cil_gen_roleattributeset(db, parse_current, new_ast_node);
6272 	} else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
6273 		rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE);
6274 	} else if (parse_current->data == CIL_KEY_BOOL) {
6275 		rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE);
6276 	} else if (parse_current->data == CIL_KEY_BOOLEANIF) {
6277 		rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE);
6278 	} else if(parse_current->data == CIL_KEY_TUNABLE) {
6279 		if (db->preserve_tunables) {
6280 			rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE);
6281 		} else {
6282 			rc = cil_gen_tunable(db, parse_current, new_ast_node);
6283 		}
6284 	} else if (parse_current->data == CIL_KEY_TUNABLEIF) {
6285 		if (db->preserve_tunables) {
6286 			rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE);
6287 		} else {
6288 			rc = cil_gen_tunif(db, parse_current, new_ast_node);
6289 		}
6290 	} else if (parse_current->data == CIL_KEY_CONDTRUE) {
6291 		rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE);
6292 	} else if (parse_current->data == CIL_KEY_CONDFALSE) {
6293 		rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE);
6294 	} else if (parse_current->data == CIL_KEY_ALLOW) {
6295 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6296 	} else if (parse_current->data == CIL_KEY_AUDITALLOW) {
6297 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6298 	} else if (parse_current->data == CIL_KEY_DONTAUDIT) {
6299 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6300 	} else if (parse_current->data == CIL_KEY_NEVERALLOW) {
6301 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6302 	} else if (parse_current->data == CIL_KEY_ALLOWX) {
6303 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6304 	} else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
6305 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6306 	} else if (parse_current->data == CIL_KEY_DONTAUDITX) {
6307 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6308 	} else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
6309 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6310 	} else if (parse_current->data == CIL_KEY_PERMISSIONX) {
6311 		rc = cil_gen_permissionx(db, parse_current, new_ast_node);
6312 	} else if (parse_current->data == CIL_KEY_DENY_RULE) {
6313 		rc = cil_gen_deny_rule(parse_current, new_ast_node);
6314 	} else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
6315 		rc = cil_gen_typetransition(db, parse_current, new_ast_node);
6316 	} else if (parse_current->data == CIL_KEY_TYPECHANGE) {
6317 		rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE);
6318 	} else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
6319 		rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER);
6320 	} else if (parse_current->data == CIL_KEY_SENSITIVITY) {
6321 		rc = cil_gen_sensitivity(db, parse_current, new_ast_node);
6322 	} else if (parse_current->data == CIL_KEY_SENSALIAS) {
6323 		rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS);
6324 	} else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
6325 		rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL);
6326 	} else if (parse_current->data == CIL_KEY_CATEGORY) {
6327 		rc = cil_gen_category(db, parse_current, new_ast_node);
6328 	} else if (parse_current->data == CIL_KEY_CATALIAS) {
6329 		rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS);
6330 	} else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
6331 		rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL);
6332 	} else if (parse_current->data == CIL_KEY_CATSET) {
6333 		rc = cil_gen_catset(db, parse_current, new_ast_node);
6334 	} else if (parse_current->data == CIL_KEY_CATORDER) {
6335 		rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CATORDER);
6336 	} else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
6337 		rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SENSITIVITYORDER);
6338 	} else if (parse_current->data == CIL_KEY_SENSCAT) {
6339 		rc = cil_gen_senscat(db, parse_current, new_ast_node);
6340 	} else if (parse_current->data == CIL_KEY_LEVEL) {
6341 		rc = cil_gen_level(db, parse_current, new_ast_node);
6342 	} else if (parse_current->data == CIL_KEY_LEVELRANGE) {
6343 		rc = cil_gen_levelrange(db, parse_current, new_ast_node);
6344 	} else if (parse_current->data == CIL_KEY_CONSTRAIN) {
6345 		rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN);
6346 	} else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
6347 		rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN);
6348 	} else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
6349 		rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS);
6350 	} else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
6351 		rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS);
6352 	} else if (parse_current->data == CIL_KEY_CONTEXT) {
6353 		rc = cil_gen_context(db, parse_current, new_ast_node);
6354 	} else if (parse_current->data == CIL_KEY_FILECON) {
6355 		rc = cil_gen_filecon(db, parse_current, new_ast_node);
6356 	} else if (parse_current->data == CIL_KEY_IBPKEYCON) {
6357 		rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node);
6358 	} else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
6359 		rc = cil_gen_ibendportcon(db, parse_current, new_ast_node);
6360 	} else if (parse_current->data == CIL_KEY_PORTCON) {
6361 		rc = cil_gen_portcon(db, parse_current, new_ast_node);
6362 	} else if (parse_current->data == CIL_KEY_NODECON) {
6363 		rc = cil_gen_nodecon(db, parse_current, new_ast_node);
6364 	} else if (parse_current->data == CIL_KEY_GENFSCON) {
6365 		rc = cil_gen_genfscon(db, parse_current, new_ast_node);
6366 	} else if (parse_current->data == CIL_KEY_NETIFCON) {
6367 		rc = cil_gen_netifcon(db, parse_current, new_ast_node);
6368 	} else if (parse_current->data == CIL_KEY_PIRQCON) {
6369 		rc = cil_gen_pirqcon(db, parse_current, new_ast_node);
6370 	} else if (parse_current->data == CIL_KEY_IOMEMCON) {
6371 		rc = cil_gen_iomemcon(db, parse_current, new_ast_node);
6372 	} else if (parse_current->data == CIL_KEY_IOPORTCON) {
6373 		rc = cil_gen_ioportcon(db, parse_current, new_ast_node);
6374 	} else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
6375 		rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node);
6376 	} else if (parse_current->data == CIL_KEY_DEVICETREECON) {
6377 		rc = cil_gen_devicetreecon(db, parse_current, new_ast_node);
6378 	} else if (parse_current->data == CIL_KEY_FSUSE) {
6379 		rc = cil_gen_fsuse(db, parse_current, new_ast_node);
6380 	} else if (parse_current->data == CIL_KEY_MACRO) {
6381 		rc = cil_gen_macro(db, parse_current, new_ast_node);
6382 	} else if (parse_current->data == CIL_KEY_CALL) {
6383 		rc = cil_gen_call(db, parse_current, new_ast_node);
6384 	} else if (parse_current->data == CIL_KEY_POLICYCAP) {
6385 		rc = cil_gen_policycap(db, parse_current, new_ast_node);
6386 	} else if (parse_current->data == CIL_KEY_OPTIONAL) {
6387 		rc = cil_gen_optional(db, parse_current, new_ast_node);
6388 	} else if (parse_current->data == CIL_KEY_IPADDR) {
6389 		rc = cil_gen_ipaddr(db, parse_current, new_ast_node);
6390 	} else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
6391 		rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER);
6392 	} else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
6393 		rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE);
6394 	} else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
6395 		rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE);
6396 	} else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
6397 		rc = cil_gen_defaultrange(parse_current, new_ast_node);
6398 	} else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
6399 		rc = cil_gen_handleunknown(parse_current, new_ast_node);
6400 	} else if (parse_current->data == CIL_KEY_MLS) {
6401 		rc = cil_gen_mls(parse_current, new_ast_node);
6402 	} else if (parse_current->data == CIL_KEY_SRC_INFO) {
6403 		rc = cil_gen_src_info(parse_current, new_ast_node);
6404 	} else {
6405 		cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
6406 		rc = SEPOL_ERR;
6407 	}
6408 
6409 	if (rc == SEPOL_OK) {
6410 		if (ast_parent->cl_head == NULL) {
6411 			ast_parent->cl_head = new_ast_node;
6412 		} else {
6413 			ast_parent->cl_tail->next = new_ast_node;
6414 		}
6415 		ast_parent->cl_tail = new_ast_node;
6416 	} else {
6417 		cil_tree_node_destroy(&new_ast_node);
6418 		new_ast_node = NULL;
6419 	}
6420 
6421 	return new_ast_node;
6422 }
6423 
__cil_build_ast_node_helper(struct cil_tree_node * parse_current,uint32_t * finished,void * extra_args)6424 static int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
6425 {
6426 	struct cil_args_build *args = extra_args;
6427 	struct cil_tree_node *new_ast_node = NULL;
6428 	int rc = SEPOL_ERR;
6429 
6430 	if (parse_current->parent->cl_head != parse_current) {
6431 		/* ignore anything that isn't following a parenthesis */
6432 		return SEPOL_OK;
6433 	} else if (parse_current->data == NULL) {
6434 		/* the only time parenthesis can immediately following parenthesis is if
6435 		 * the parent is the root node */
6436 		if (parse_current->parent->parent == NULL) {
6437 			return SEPOL_OK;
6438 		} else {
6439 			cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
6440 			return SEPOL_ERR;
6441 		}
6442 	}
6443 
6444 	rc = check_for_illegal_statement(parse_current, args);
6445 	if (rc != SEPOL_OK) {
6446 		return SEPOL_ERR;
6447 	}
6448 
6449 	new_ast_node = parse_statement(args->db, parse_current, args->ast);
6450 	if (!new_ast_node) {
6451 		return SEPOL_ERR;
6452 	}
6453 
6454 	args->ast = new_ast_node;
6455 
6456 	if (parse_current->data != CIL_KEY_BLOCK &&
6457 		parse_current->data != CIL_KEY_IN &&
6458 		parse_current->data != CIL_KEY_TUNABLEIF &&
6459 		parse_current->data != CIL_KEY_BOOLEANIF &&
6460 		parse_current->data != CIL_KEY_CONDTRUE &&
6461 		parse_current->data != CIL_KEY_CONDFALSE &&
6462 		parse_current->data != CIL_KEY_MACRO &&
6463 		parse_current->data != CIL_KEY_OPTIONAL &&
6464 		parse_current->data != CIL_KEY_SRC_INFO) {
6465 		/* Skip anything that does not contain a list of policy statements */
6466 		*finished = CIL_TREE_SKIP_NEXT;
6467 	}
6468 
6469 	return SEPOL_OK;
6470 }
6471 
__cil_build_ast_first_child_helper(struct cil_tree_node * parse_current,void * extra_args)6472 static int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args)
6473 {
6474 	struct cil_args_build *args = extra_args;
6475 	struct cil_tree_node *ast = args->ast;
6476 
6477 	if (ast->flavor == CIL_TUNABLEIF) {
6478 		args->tunif = ast;
6479 	} else if (ast->flavor == CIL_IN) {
6480 		args->in = ast;
6481 	} else if (ast->flavor == CIL_MACRO) {
6482 		args->macro = ast;
6483 	} else if (ast->flavor == CIL_OPTIONAL) {
6484 		args->optional = ast;
6485 	} else if (ast->flavor == CIL_BOOLEANIF) {
6486 		args->boolif = ast;
6487 	}
6488 
6489 	return SEPOL_OK;
6490 }
6491 
__cil_build_ast_last_child_helper(struct cil_tree_node * parse_current,void * extra_args)6492 static int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
6493 {
6494 	struct cil_args_build *args = extra_args;
6495 	struct cil_tree_node *ast = args->ast;
6496 
6497 	if (ast->flavor == CIL_ROOT) {
6498 		return SEPOL_OK;
6499 	}
6500 
6501 	args->ast = ast->parent;
6502 
6503 	if (ast->flavor == CIL_TUNABLEIF) {
6504 		args->tunif = NULL;
6505 	}
6506 
6507 	if (ast->flavor == CIL_IN) {
6508 		args->in = NULL;
6509 	}
6510 
6511 	if (ast->flavor == CIL_MACRO) {
6512 		args->macro = NULL;
6513 	}
6514 
6515 	if (ast->flavor == CIL_OPTIONAL) {
6516 		struct cil_tree_node *n = ast->parent;
6517 		args->optional = NULL;
6518 		/* Optionals can be nested */
6519 		while (n && n->flavor != CIL_ROOT) {
6520 			if (n->flavor == CIL_OPTIONAL) {
6521 				args->optional = n;
6522 				break;
6523 			}
6524 			n = n->parent;
6525 		}
6526 	}
6527 
6528 	if (ast->flavor == CIL_BOOLEANIF) {
6529 		args->boolif = NULL;
6530 	}
6531 
6532 	// At this point we no longer have any need for parse_current or any of its
6533 	// siblings; they have all been converted to the appropriate AST node. The
6534 	// full parse tree will get deleted elsewhere, but in an attempt to
6535 	// minimize memory usage (of which the parse tree uses a lot), start
6536 	// deleting the parts we don't need now.
6537 	cil_tree_children_destroy(parse_current->parent);
6538 
6539 	return SEPOL_OK;
6540 }
6541 
cil_build_ast(struct cil_db * db,struct cil_tree_node * parse_tree,struct cil_tree_node * ast)6542 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
6543 {
6544 	int rc = SEPOL_ERR;
6545 	struct cil_args_build extra_args;
6546 
6547 	if (db == NULL || parse_tree == NULL || ast == NULL) {
6548 		goto exit;
6549 	}
6550 
6551 	extra_args.ast = ast;
6552 	extra_args.db = db;
6553 	extra_args.tunif = NULL;
6554 	extra_args.in = NULL;
6555 	extra_args.macro = NULL;
6556 	extra_args.optional = NULL;
6557 	extra_args.boolif = NULL;
6558 
6559 	rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, __cil_build_ast_first_child_helper, __cil_build_ast_last_child_helper, &extra_args);
6560 	if (rc != SEPOL_OK) {
6561 		goto exit;
6562 	}
6563 
6564 	return SEPOL_OK;
6565 
6566 exit:
6567 	return rc;
6568 }
6569