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