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