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