• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice,
8  *       this list of conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice,
11  *       this list of conditions and the following disclaimer in the documentation
12  *       and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * The views and conclusions contained in the software and documentation are those
26  * of the authors and should not be interpreted as representing official policies,
27  * either expressed or implied, of Tresys Technology, LLC.
28  */
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34 
35 #include <sepol/policydb/conditional.h>
36 
37 #include "cil_internal.h"
38 #include "cil_flavor.h"
39 #include "cil_log.h"
40 #include "cil_mem.h"
41 #include "cil_tree.h"
42 #include "cil_list.h"
43 #include "cil_parser.h"
44 #include "cil_build_ast.h"
45 #include "cil_copy_ast.h"
46 #include "cil_verify.h"
47 #include "cil_strpool.h"
48 
49 struct cil_args_build {
50 	struct cil_tree_node *ast;
51 	struct cil_db *db;
52 	struct cil_tree_node *tunif;
53 	struct cil_tree_node *in;
54 	struct cil_tree_node *macro;
55 	struct cil_tree_node *optional;
56 	struct cil_tree_node *boolif;
57 };
58 
cil_fill_list(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** list)59 static int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list)
60 {
61 	int rc = SEPOL_ERR;
62 	struct cil_tree_node *curr;
63 	enum cil_syntax syntax[] = {
64 		CIL_SYN_N_STRINGS,
65 		CIL_SYN_END
66 	};
67 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
68 
69 	rc = __cil_verify_syntax(current, syntax, syntax_len);
70 	if (rc != SEPOL_OK) {
71 		goto exit;
72  	}
73 
74 	cil_list_init(list, flavor);
75 
76 	for (curr = current; curr != NULL; curr = curr->next) {
77 		cil_list_append(*list, CIL_STRING, curr->data);
78 	}
79 
80 	return SEPOL_OK;
81 
82 exit:
83 	return rc;
84 }
85 
cil_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 static 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 static 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 static 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 static 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_ANY) {
4233 		filecon->type = CIL_FILECON_ANY;
4234 	} else if (type == CIL_KEY_FILE) {
4235 		filecon->type = CIL_FILECON_FILE;
4236 	} else if (type == CIL_KEY_DIR) {
4237 		filecon->type = CIL_FILECON_DIR;
4238 	} else if (type == CIL_KEY_CHAR) {
4239 		filecon->type = CIL_FILECON_CHAR;
4240 	} else if (type == CIL_KEY_BLOCK) {
4241 		filecon->type = CIL_FILECON_BLOCK;
4242 	} else if (type == CIL_KEY_SOCKET) {
4243 		filecon->type = CIL_FILECON_SOCKET;
4244 	} else if (type == CIL_KEY_PIPE) {
4245 		filecon->type = CIL_FILECON_PIPE;
4246 	} else if (type == CIL_KEY_SYMLINK) {
4247 		filecon->type = CIL_FILECON_SYMLINK;
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_STRING | CIL_SYN_LIST | CIL_SYN_END,
4576 		CIL_SYN_END
4577 	};
4578 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4579 	struct cil_tree_node *context_node;
4580 	int rc = SEPOL_ERR;
4581 	struct cil_genfscon *genfscon = NULL;
4582 
4583 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4584 		goto exit;
4585 	}
4586 
4587 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4588 	if (rc != SEPOL_OK) {
4589 		goto exit;
4590 	}
4591 
4592 	cil_genfscon_init(&genfscon);
4593 
4594 	genfscon->fs_str = parse_current->next->data;
4595 	genfscon->path_str = parse_current->next->next->data;
4596 
4597 	if (parse_current->next->next->next->next) {
4598 		/* (genfscon <FS_STR> <PATH_STR> <FILE_TYPE> ... */
4599 		char *file_type = parse_current->next->next->next->data;
4600 		if (file_type == CIL_KEY_ANY) {
4601 			genfscon->file_type = CIL_FILECON_ANY;
4602 		} else if (file_type == CIL_KEY_FILE) {
4603 			genfscon->file_type = CIL_FILECON_FILE;
4604 		} else if (file_type == CIL_KEY_DIR) {
4605 			genfscon->file_type = CIL_FILECON_DIR;
4606 		} else if (file_type == CIL_KEY_CHAR) {
4607 			genfscon->file_type = CIL_FILECON_CHAR;
4608 		} else if (file_type == CIL_KEY_BLOCK) {
4609 			genfscon->file_type = CIL_FILECON_BLOCK;
4610 		} else if (file_type == CIL_KEY_SOCKET) {
4611 			genfscon->file_type = CIL_FILECON_SOCKET;
4612 		} else if (file_type == CIL_KEY_PIPE) {
4613 			genfscon->file_type = CIL_FILECON_PIPE;
4614 		} else if (file_type == CIL_KEY_SYMLINK) {
4615 			genfscon->file_type = CIL_FILECON_SYMLINK;
4616 		} else {
4617 			if (parse_current->next->next->next->cl_head) {
4618 				cil_log(CIL_ERR, "Expecting file type, but found a list\n");
4619 			} else {
4620 				cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type);
4621 			}
4622 			rc = SEPOL_ERR;
4623 			goto exit;
4624 		}
4625 		context_node = parse_current->next->next->next->next;
4626 	} else {
4627 		/* (genfscon <FS_STR> <PATH_STR> ... */
4628 		context_node = parse_current->next->next->next;
4629 	}
4630 
4631 	if (context_node->cl_head) {
4632 		cil_context_init(&genfscon->context);
4633 		rc = cil_fill_context(context_node->cl_head, genfscon->context);
4634 		if (rc != SEPOL_OK) {
4635 			goto exit;
4636 		}
4637 	} else {
4638 		genfscon->context_str = context_node->data;
4639 	}
4640 
4641 	ast_node->data = genfscon;
4642 	ast_node->flavor = CIL_GENFSCON;
4643 
4644 	return SEPOL_OK;
4645 
4646 exit:
4647 	cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
4648 	cil_destroy_genfscon(genfscon);
4649 	return SEPOL_ERR;
4650 }
4651 
cil_destroy_genfscon(struct cil_genfscon * genfscon)4652 void cil_destroy_genfscon(struct cil_genfscon *genfscon)
4653 {
4654 	if (genfscon == NULL) {
4655 		return;
4656 	}
4657 
4658 	if (genfscon->context_str == NULL && genfscon->context != NULL) {
4659 		cil_destroy_context(genfscon->context);
4660 	}
4661 
4662 	free(genfscon);
4663 }
4664 
4665 
cil_gen_netifcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4666 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4667 {
4668 	enum cil_syntax syntax[] = {
4669 		CIL_SYN_STRING,
4670 		CIL_SYN_STRING,
4671 		CIL_SYN_STRING | CIL_SYN_LIST,
4672 		CIL_SYN_STRING | CIL_SYN_LIST,
4673 		CIL_SYN_END
4674 	};
4675 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4676 	int rc = SEPOL_ERR;
4677 	struct cil_netifcon *netifcon = NULL;
4678 
4679 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4680 		goto exit;
4681 	}
4682 
4683 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4684 	if (rc != SEPOL_OK) {
4685 		goto exit;
4686 	}
4687 
4688 	cil_netifcon_init(&netifcon);
4689 
4690 	netifcon->interface_str = parse_current->next->data;
4691 
4692 	if (parse_current->next->next->cl_head == NULL) {
4693 		netifcon->if_context_str = parse_current->next->next->data;
4694 	} else {
4695 		cil_context_init(&netifcon->if_context);
4696 
4697 		rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context);
4698 		if (rc != SEPOL_OK) {
4699 			goto exit;
4700 		}
4701 	}
4702 
4703 	if (parse_current->next->next->next->cl_head == NULL) {
4704 		netifcon->packet_context_str = parse_current->next->next->next->data;
4705 	} else {
4706 		cil_context_init(&netifcon->packet_context);
4707 
4708 		rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context);
4709 		if (rc != SEPOL_OK) {
4710 			goto exit;
4711 		}
4712 	}
4713 
4714 	ast_node->data = netifcon;
4715 	ast_node->flavor = CIL_NETIFCON;
4716 
4717 	return SEPOL_OK;
4718 
4719 exit:
4720 	cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
4721 	cil_destroy_netifcon(netifcon);
4722 	return SEPOL_ERR;
4723 }
4724 
cil_destroy_netifcon(struct cil_netifcon * netifcon)4725 void cil_destroy_netifcon(struct cil_netifcon *netifcon)
4726 {
4727 	if (netifcon == NULL) {
4728 		return;
4729 	}
4730 
4731 	if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
4732 		cil_destroy_context(netifcon->if_context);
4733 	}
4734 
4735 	if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) {
4736 		cil_destroy_context(netifcon->packet_context);
4737 	}
4738 
4739 	free(netifcon);
4740 }
4741 
cil_gen_ibendportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4742 int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4743 {
4744 	enum cil_syntax syntax[] = {
4745 		CIL_SYN_STRING,
4746 		CIL_SYN_STRING,
4747 		CIL_SYN_STRING,
4748 		CIL_SYN_STRING | CIL_SYN_LIST,
4749 		CIL_SYN_END
4750 	};
4751 	size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4752 	int rc = SEPOL_ERR;
4753 	struct cil_ibendportcon *ibendportcon = NULL;
4754 
4755 	if (!parse_current || !ast_node)
4756 		goto exit;
4757 
4758 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4759 	if (rc != SEPOL_OK)
4760 		goto exit;
4761 
4762 	cil_ibendportcon_init(&ibendportcon);
4763 
4764 	ibendportcon->dev_name_str = parse_current->next->data;
4765 
4766 	rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10);
4767 	if (rc != SEPOL_OK) {
4768 		cil_log(CIL_ERR, "Improper ibendport port specified\n");
4769 		goto exit;
4770 	}
4771 
4772 	if (!parse_current->next->next->next->cl_head) {
4773 		ibendportcon->context_str = parse_current->next->next->next->data;
4774 	} else {
4775 		cil_context_init(&ibendportcon->context);
4776 
4777 		rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context);
4778 		if (rc != SEPOL_OK)
4779 			goto exit;
4780 	}
4781 
4782 	ast_node->data = ibendportcon;
4783 	ast_node->flavor = CIL_IBENDPORTCON;
4784 
4785 	return SEPOL_OK;
4786 
4787 exit:
4788 	cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration");
4789 	cil_destroy_ibendportcon(ibendportcon);
4790 	return SEPOL_ERR;
4791 }
4792 
cil_destroy_ibendportcon(struct cil_ibendportcon * ibendportcon)4793 void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon)
4794 {
4795 	if (!ibendportcon)
4796 		return;
4797 
4798 	if (!ibendportcon->context_str && ibendportcon->context)
4799 		cil_destroy_context(ibendportcon->context);
4800 
4801 	free(ibendportcon);
4802 }
4803 
cil_gen_pirqcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4804 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4805 {
4806 	enum cil_syntax syntax[] = {
4807 		CIL_SYN_STRING,
4808 		CIL_SYN_STRING,
4809 		CIL_SYN_STRING | CIL_SYN_LIST,
4810 		CIL_SYN_END
4811 	};
4812 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4813 	int rc = SEPOL_ERR;
4814 	struct cil_pirqcon *pirqcon = NULL;
4815 
4816 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4817 		goto exit;
4818 	}
4819 
4820 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4821 	if (rc != SEPOL_OK) {
4822 		goto exit;
4823 	}
4824 
4825 	cil_pirqcon_init(&pirqcon);
4826 
4827 	rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
4828 	if (rc != SEPOL_OK) {
4829 		goto exit;
4830 	}
4831 
4832 	if (parse_current->next->next->cl_head == NULL) {
4833 		pirqcon->context_str = parse_current->next->next->data;
4834 	} else {
4835 		cil_context_init(&pirqcon->context);
4836 
4837 		rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context);
4838 		if (rc != SEPOL_OK) {
4839 			goto exit;
4840 		}
4841 	}
4842 
4843 	ast_node->data = pirqcon;
4844 	ast_node->flavor = CIL_PIRQCON;
4845 
4846 	return SEPOL_OK;
4847 
4848 exit:
4849 	cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
4850 	cil_destroy_pirqcon(pirqcon);
4851 	return rc;
4852 }
4853 
cil_destroy_pirqcon(struct cil_pirqcon * pirqcon)4854 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
4855 {
4856 	if (pirqcon == NULL) {
4857 		return;
4858 	}
4859 
4860 	if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
4861 		cil_destroy_context(pirqcon->context);
4862 	}
4863 
4864 	free(pirqcon);
4865 }
4866 
cil_gen_iomemcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4867 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4868 {
4869 	enum cil_syntax syntax[] = {
4870 		CIL_SYN_STRING,
4871 		CIL_SYN_STRING | CIL_SYN_LIST,
4872 		CIL_SYN_STRING | CIL_SYN_LIST,
4873 		CIL_SYN_END
4874 	};
4875 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4876 	int rc = SEPOL_ERR;
4877 	struct cil_iomemcon *iomemcon = NULL;
4878 
4879 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4880 		goto exit;
4881 	}
4882 
4883 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4884 	if (rc != SEPOL_OK) {
4885 		goto exit;
4886 	}
4887 
4888 	cil_iomemcon_init(&iomemcon);
4889 
4890 	if (parse_current->next->cl_head != NULL) {
4891 		if (parse_current->next->cl_head->next != NULL &&
4892 		    parse_current->next->cl_head->next->next == NULL) {
4893 			rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0);
4894 			if (rc != SEPOL_OK) {
4895 				cil_log(CIL_ERR, "Improper iomem specified\n");
4896 				goto exit;
4897 			}
4898 			rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0);
4899 			if (rc != SEPOL_OK) {
4900 				cil_log(CIL_ERR, "Improper iomem specified\n");
4901 				goto exit;
4902 			}
4903 		} else {
4904 			cil_log(CIL_ERR, "Improper iomem range specified\n");
4905 			rc = SEPOL_ERR;
4906 			goto exit;
4907 		}
4908 	} else {
4909 		rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0);
4910 		if (rc != SEPOL_OK) {
4911 			cil_log(CIL_ERR, "Improper iomem specified\n");
4912 			goto exit;
4913 		}
4914 		iomemcon->iomem_high = iomemcon->iomem_low;
4915 	}
4916 
4917 	if (parse_current->next->next->cl_head == NULL ) {
4918 		iomemcon->context_str = parse_current->next->next->data;
4919 	} else {
4920 		cil_context_init(&iomemcon->context);
4921 
4922 		rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context);
4923 		if (rc != SEPOL_OK) {
4924 			goto exit;
4925 		}
4926 	}
4927 
4928 	ast_node->data = iomemcon;
4929 	ast_node->flavor = CIL_IOMEMCON;
4930 
4931 	return SEPOL_OK;
4932 
4933 exit:
4934 	cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
4935 	cil_destroy_iomemcon(iomemcon);
4936 	return rc;
4937 }
4938 
cil_destroy_iomemcon(struct cil_iomemcon * iomemcon)4939 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
4940 {
4941 	if (iomemcon == NULL) {
4942 		return;
4943 	}
4944 
4945 	if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
4946 		cil_destroy_context(iomemcon->context);
4947 	}
4948 
4949 	free(iomemcon);
4950 }
4951 
cil_gen_ioportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4952 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4953 {
4954 	enum cil_syntax syntax[] = {
4955 		CIL_SYN_STRING,
4956 		CIL_SYN_STRING | CIL_SYN_LIST,
4957 		CIL_SYN_STRING | CIL_SYN_LIST,
4958 		CIL_SYN_END
4959 	};
4960 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4961 	int rc = SEPOL_ERR;
4962 	struct cil_ioportcon *ioportcon = NULL;
4963 
4964 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4965 		goto exit;
4966 	}
4967 
4968 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4969 	if (rc != SEPOL_OK) {
4970 		goto exit;
4971 	}
4972 
4973 	cil_ioportcon_init(&ioportcon);
4974 
4975 	if (parse_current->next->cl_head != NULL) {
4976 		if (parse_current->next->cl_head->next != NULL &&
4977 		    parse_current->next->cl_head->next->next == NULL) {
4978 			rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0);
4979 			if (rc != SEPOL_OK) {
4980 				cil_log(CIL_ERR, "Improper ioport specified\n");
4981 				goto exit;
4982 			}
4983 			rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0);
4984 			if (rc != SEPOL_OK) {
4985 				cil_log(CIL_ERR, "Improper ioport specified\n");
4986 				goto exit;
4987 			}
4988 		} else {
4989 			cil_log(CIL_ERR, "Improper ioport range specified\n");
4990 			rc = SEPOL_ERR;
4991 			goto exit;
4992 		}
4993 	} else {
4994 		rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0);
4995 		if (rc != SEPOL_OK) {
4996 			cil_log(CIL_ERR, "Improper ioport specified\n");
4997 			goto exit;
4998 		}
4999 		ioportcon->ioport_high = ioportcon->ioport_low;
5000 	}
5001 
5002 	if (parse_current->next->next->cl_head == NULL ) {
5003 		ioportcon->context_str = parse_current->next->next->data;
5004 	} else {
5005 		cil_context_init(&ioportcon->context);
5006 
5007 		rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context);
5008 		if (rc != SEPOL_OK) {
5009 			goto exit;
5010 		}
5011 	}
5012 
5013 	ast_node->data = ioportcon;
5014 	ast_node->flavor = CIL_IOPORTCON;
5015 
5016 	return SEPOL_OK;
5017 
5018 exit:
5019 	cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
5020 	cil_destroy_ioportcon(ioportcon);
5021 	return rc;
5022 }
5023 
cil_destroy_ioportcon(struct cil_ioportcon * ioportcon)5024 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
5025 {
5026 	if (ioportcon == NULL) {
5027 		return;
5028 	}
5029 
5030 	if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
5031 		cil_destroy_context(ioportcon->context);
5032 	}
5033 
5034 	free(ioportcon);
5035 }
5036 
cil_gen_pcidevicecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5037 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5038 {
5039 	enum cil_syntax syntax[] = {
5040 		CIL_SYN_STRING,
5041 		CIL_SYN_STRING,
5042 		CIL_SYN_STRING | CIL_SYN_LIST,
5043 		CIL_SYN_END
5044 	};
5045 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5046 	int rc = SEPOL_ERR;
5047 	struct cil_pcidevicecon *pcidevicecon = NULL;
5048 
5049 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5050 		goto exit;
5051 	}
5052 
5053 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5054 	if (rc != SEPOL_OK) {
5055 		goto exit;
5056 	}
5057 
5058 	cil_pcidevicecon_init(&pcidevicecon);
5059 
5060 	rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
5061 	if (rc != SEPOL_OK) {
5062 		goto exit;
5063 	}
5064 
5065 	if (parse_current->next->next->cl_head == NULL) {
5066 		pcidevicecon->context_str = parse_current->next->next->data;
5067 	} else {
5068 		cil_context_init(&pcidevicecon->context);
5069 
5070 		rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context);
5071 		if (rc != SEPOL_OK) {
5072 			goto exit;
5073 		}
5074 	}
5075 
5076 	ast_node->data = pcidevicecon;
5077 	ast_node->flavor = CIL_PCIDEVICECON;
5078 
5079 	return SEPOL_OK;
5080 
5081 exit:
5082 	cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
5083 	cil_destroy_pcidevicecon(pcidevicecon);
5084 	return rc;
5085 }
5086 
cil_destroy_pcidevicecon(struct cil_pcidevicecon * pcidevicecon)5087 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
5088 {
5089 	if (pcidevicecon == NULL) {
5090 		return;
5091 	}
5092 
5093 	if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) {
5094 		cil_destroy_context(pcidevicecon->context);
5095 	}
5096 
5097 	free(pcidevicecon);
5098 }
5099 
cil_gen_devicetreecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5100 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5101 {
5102 	enum cil_syntax syntax[] = {
5103 		CIL_SYN_STRING,
5104 		CIL_SYN_STRING,
5105 		CIL_SYN_STRING | CIL_SYN_LIST,
5106 		CIL_SYN_END
5107 	};
5108 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5109 	int rc = SEPOL_ERR;
5110 	struct cil_devicetreecon *devicetreecon = NULL;
5111 
5112 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5113 		goto exit;
5114 	}
5115 
5116 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5117 	if (rc != SEPOL_OK) {
5118 		goto exit;
5119 	}
5120 
5121 	cil_devicetreecon_init(&devicetreecon);
5122 
5123 	devicetreecon->path = parse_current->next->data;
5124 
5125 	if (parse_current->next->next->cl_head == NULL) {
5126 		devicetreecon->context_str = parse_current->next->next->data;
5127 	} else {
5128 		cil_context_init(&devicetreecon->context);
5129 
5130 		rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context);
5131 		if (rc != SEPOL_OK) {
5132 			goto exit;
5133 		}
5134 	}
5135 
5136 	ast_node->data = devicetreecon;
5137 	ast_node->flavor = CIL_DEVICETREECON;
5138 
5139 	return SEPOL_OK;
5140 
5141 exit:
5142 	cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
5143 	cil_destroy_devicetreecon(devicetreecon);
5144 	return rc;
5145 }
5146 
cil_destroy_devicetreecon(struct cil_devicetreecon * devicetreecon)5147 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
5148 {
5149 	if (devicetreecon == NULL) {
5150 		return;
5151 	}
5152 
5153 	if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) {
5154 		cil_destroy_context(devicetreecon->context);
5155 	}
5156 
5157 	free(devicetreecon);
5158 }
5159 
cil_gen_fsuse(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5160 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5161 {
5162 	enum cil_syntax syntax[] = {
5163 		CIL_SYN_STRING,
5164 		CIL_SYN_STRING,
5165 		CIL_SYN_STRING,
5166 		CIL_SYN_STRING | CIL_SYN_LIST,
5167 		CIL_SYN_END
5168 	};
5169 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5170 	char *type = NULL;
5171 	struct cil_fsuse *fsuse = NULL;
5172 	int rc = SEPOL_ERR;
5173 
5174 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5175 		goto exit;
5176 	}
5177 
5178 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5179 	if (rc != SEPOL_OK) {
5180 		goto exit;
5181 	}
5182 
5183 	type = parse_current->next->data;
5184 
5185 	cil_fsuse_init(&fsuse);
5186 
5187 	if (type == CIL_KEY_XATTR) {
5188 		fsuse->type = CIL_FSUSE_XATTR;
5189 	} else if (type == CIL_KEY_TASK) {
5190 		fsuse->type = CIL_FSUSE_TASK;
5191 	} else if (type == CIL_KEY_TRANS) {
5192 		fsuse->type = CIL_FSUSE_TRANS;
5193 	} else {
5194 		cil_log(CIL_ERR, "Invalid fsuse type\n");
5195 		goto exit;
5196 	}
5197 
5198 	fsuse->fs_str = parse_current->next->next->data;
5199 
5200 	if (parse_current->next->next->next->cl_head == NULL) {
5201 		fsuse->context_str = parse_current->next->next->next->data;
5202 	} else {
5203 		cil_context_init(&fsuse->context);
5204 
5205 		rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context);
5206 		if (rc != SEPOL_OK) {
5207 			goto exit;
5208 		}
5209 	}
5210 
5211 	ast_node->data = fsuse;
5212 	ast_node->flavor = CIL_FSUSE;
5213 
5214 	return SEPOL_OK;
5215 
5216 exit:
5217 	cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
5218 	cil_destroy_fsuse(fsuse);
5219 	return SEPOL_ERR;
5220 }
5221 
cil_destroy_fsuse(struct cil_fsuse * fsuse)5222 void cil_destroy_fsuse(struct cil_fsuse *fsuse)
5223 {
5224 	if (fsuse == NULL) {
5225 		return;
5226 	}
5227 
5228 	if (fsuse->context_str == NULL && fsuse->context != NULL) {
5229 		cil_destroy_context(fsuse->context);
5230 	}
5231 
5232 	free(fsuse);
5233 }
5234 
cil_destroy_param(struct cil_param * param)5235 void cil_destroy_param(struct cil_param *param)
5236 {
5237 	if (param == NULL) {
5238 		return;
5239 	}
5240 
5241 	free(param);
5242 }
5243 
cil_gen_macro(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5244 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5245 {
5246 	int rc = SEPOL_ERR;
5247 	char *key = NULL;
5248 	struct cil_macro *macro = NULL;
5249 	struct cil_tree_node *macro_content = NULL;
5250 	struct cil_tree_node *current_item;
5251 	enum cil_syntax syntax[] = {
5252 		CIL_SYN_STRING,
5253 		CIL_SYN_STRING,
5254 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
5255 		CIL_SYN_N_LISTS | CIL_SYN_END,
5256 		CIL_SYN_END
5257 	};
5258 	size_t syntax_len = sizeof(syntax)/ sizeof(*syntax);
5259 
5260 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5261 		goto exit;
5262 	}
5263 
5264 	rc =__cil_verify_syntax(parse_current, syntax, syntax_len);
5265 	if (rc != SEPOL_OK) {
5266 		goto exit;
5267 	}
5268 
5269 	cil_macro_init(&macro);
5270 
5271 	key = parse_current->next->data;
5272 
5273 	current_item = parse_current->next->next->cl_head;
5274 	while (current_item != NULL) {
5275 		enum cil_syntax param_syntax[] = {
5276 			CIL_SYN_STRING,
5277 			CIL_SYN_STRING,
5278 			CIL_SYN_END
5279 		};
5280 		int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
5281 		char *kind = NULL;
5282 		struct cil_param *param = NULL;
5283 		struct cil_list_item *curr_param;
5284 
5285 		rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
5286 		if (rc != SEPOL_OK) {
5287 			goto exit;
5288 		}
5289 
5290 		if (macro->params == NULL) {
5291 			cil_list_init(&macro->params, CIL_LIST_ITEM);
5292 		}
5293 
5294 		kind = current_item->cl_head->data;
5295 		cil_param_init(&param);
5296 
5297 		if (kind == CIL_KEY_TYPE) {
5298 			param->flavor = CIL_TYPE;
5299 		} else if (kind == CIL_KEY_ROLE) {
5300 			param->flavor = CIL_ROLE;
5301 		} else if (kind == CIL_KEY_USER) {
5302 			param->flavor = CIL_USER;
5303 		} else if (kind == CIL_KEY_SENSITIVITY) {
5304 			param->flavor = CIL_SENS;
5305 		} else if (kind == CIL_KEY_CATEGORY) {
5306 			param->flavor = CIL_CAT;
5307 		} else if (kind == CIL_KEY_CATSET) {
5308 			param->flavor = CIL_CATSET;
5309 		} else if (kind == CIL_KEY_LEVEL) {
5310 			param->flavor = CIL_LEVEL;
5311 		} else if (kind == CIL_KEY_LEVELRANGE) {
5312 			param->flavor = CIL_LEVELRANGE;
5313 		} else if (kind == CIL_KEY_CLASS) {
5314 			param->flavor = CIL_CLASS;
5315 		} else if (kind == CIL_KEY_IPADDR) {
5316 			param->flavor = CIL_IPADDR;
5317 		} else if (kind == CIL_KEY_MAP_CLASS) {
5318 			param->flavor = CIL_MAP_CLASS;
5319 		} else if (kind == CIL_KEY_CLASSPERMISSION) {
5320 			param->flavor = CIL_CLASSPERMISSION;
5321 		} else if (kind == CIL_KEY_BOOL) {
5322 			param->flavor = CIL_BOOL;
5323 		} else if (kind == CIL_KEY_STRING) {
5324 			param->flavor = CIL_NAME;
5325 		} else if (kind == CIL_KEY_NAME) {
5326 			param->flavor = CIL_NAME;
5327 		} else {
5328 			cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind);
5329 			cil_destroy_param(param);
5330 			goto exit;
5331 		}
5332 
5333 		param->str =  current_item->cl_head->next->data;
5334 
5335 		rc = cil_verify_name(db, param->str, param->flavor);
5336 		if (rc != SEPOL_OK) {
5337 			cil_destroy_param(param);
5338 			goto exit;
5339 		}
5340 
5341 		//walk current list and check for duplicate parameters
5342 		cil_list_for_each(curr_param, macro->params) {
5343 			if (param->str == ((struct cil_param*)curr_param->data)->str) {
5344 				cil_log(CIL_ERR, "Duplicate parameter\n");
5345 				cil_destroy_param(param);
5346 				goto exit;
5347 			}
5348 		}
5349 
5350 		cil_list_append(macro->params, CIL_PARAM, param);
5351 
5352 		current_item = current_item->next;
5353 	}
5354 
5355 	/* 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
5356            node containing the macro name is updated to point to the start of the macro content */
5357 	macro_content = parse_current->next->next->next;
5358 	cil_tree_subtree_destroy(parse_current->next->next);
5359 	parse_current->next->next = macro_content;
5360 	if (macro_content == NULL) {
5361 		/* No statements in macro and macro parameter list was last node */
5362 		parse_current->parent->cl_tail = parse_current->next;
5363 	}
5364 
5365 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
5366 	if (rc != SEPOL_OK) {
5367 		goto exit;
5368 	}
5369 
5370 	return SEPOL_OK;
5371 
5372 exit:
5373 	cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
5374 	cil_destroy_macro(macro);
5375 	cil_clear_node(ast_node);
5376 	return SEPOL_ERR;
5377 }
5378 
cil_destroy_macro(struct cil_macro * macro)5379 void cil_destroy_macro(struct cil_macro *macro)
5380 {
5381 	if (macro == NULL) {
5382 		return;
5383 	}
5384 
5385 	cil_symtab_datum_destroy(&macro->datum);
5386 	cil_symtab_array_destroy(macro->symtab);
5387 
5388 	if (macro->params != NULL) {
5389 		cil_list_destroy(&macro->params, 1);
5390 	}
5391 
5392 	free(macro);
5393 }
5394 
cil_gen_call(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5395 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5396 {
5397 	enum cil_syntax syntax[] = {
5398 		CIL_SYN_STRING,
5399 		CIL_SYN_STRING,
5400 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
5401 		CIL_SYN_END
5402 	};
5403 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5404 	struct cil_call *call = NULL;
5405 	int rc = SEPOL_ERR;
5406 
5407 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5408 		goto exit;
5409 	}
5410 
5411 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5412 	if (rc != SEPOL_OK) {
5413 		goto exit;
5414 	}
5415 
5416 	cil_call_init(&call);
5417 
5418 	call->macro_str = parse_current->next->data;
5419 
5420 	if (parse_current->next->next != NULL) {
5421 		cil_tree_init(&call->args_tree);
5422 		cil_copy_ast(db, parse_current->next->next, call->args_tree->root);
5423 	}
5424 
5425 	ast_node->data = call;
5426 	ast_node->flavor = CIL_CALL;
5427 
5428 	return SEPOL_OK;
5429 
5430 exit:
5431 	cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
5432 	cil_destroy_call(call);
5433 	return rc;
5434 }
5435 
cil_destroy_call(struct cil_call * call)5436 void cil_destroy_call(struct cil_call *call)
5437 {
5438 	if (call == NULL) {
5439 		return;
5440 	}
5441 
5442 	call->macro = NULL;
5443 
5444 	if (call->args_tree != NULL) {
5445 		cil_tree_destroy(&call->args_tree);
5446 	}
5447 
5448 	if (call->args != NULL) {
5449 		cil_list_destroy(&call->args, 1);
5450 	}
5451 
5452 	free(call);
5453 }
5454 
cil_destroy_args(struct cil_args * args)5455 void cil_destroy_args(struct cil_args *args)
5456 {
5457 	if (args == NULL) {
5458 		return;
5459 	}
5460 
5461 	if (args->arg_str != NULL) {
5462 		args->arg_str = NULL;
5463 	} else if (args->arg != NULL) {
5464 		struct cil_tree_node *node = args->arg->nodes->head->data;
5465 		switch (args->flavor) {
5466 		case CIL_NAME:
5467 			break;
5468 		case CIL_CATSET:
5469 			cil_destroy_catset((struct cil_catset *)args->arg);
5470 			free(node);
5471 			break;
5472 		case CIL_LEVEL:
5473 			cil_destroy_level((struct cil_level *)args->arg);
5474 			free(node);
5475 			break;
5476 		case CIL_LEVELRANGE:
5477 			cil_destroy_levelrange((struct cil_levelrange *)args->arg);
5478 			free(node);
5479 			break;
5480 		case CIL_IPADDR:
5481 			cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
5482 			free(node);
5483 			break;
5484 		case CIL_CLASSPERMISSION:
5485 			cil_destroy_classpermission((struct cil_classpermission *)args->arg);
5486 			free(node);
5487 			break;
5488 		default:
5489 			cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor);
5490 			break;
5491 		}
5492 	}
5493 
5494 	args->param_str = NULL;
5495 	args->arg = NULL;
5496 
5497 	free(args);
5498 }
5499 
cil_gen_optional(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5500 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5501 {
5502 	enum cil_syntax syntax[] = {
5503 		CIL_SYN_STRING,
5504 		CIL_SYN_STRING,
5505 		CIL_SYN_N_LISTS | CIL_SYN_END,
5506 		CIL_SYN_END
5507 	};
5508 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5509 	char *key = NULL;
5510 	struct cil_optional *optional = NULL;
5511 	int rc = SEPOL_ERR;
5512 
5513 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5514 		goto exit;
5515 	}
5516 
5517 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5518 	if (rc != SEPOL_OK) {
5519 		goto exit;
5520 	}
5521 
5522 	cil_optional_init(&optional);
5523 
5524 	key = parse_current->next->data;
5525 
5526 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
5527 	if (rc != SEPOL_OK) {
5528 		if (rc == SEPOL_EEXIST) {
5529 			cil_destroy_optional(optional);
5530 			optional = NULL;
5531 		} else {
5532 			goto exit;
5533 		}
5534 	}
5535 
5536 	return SEPOL_OK;
5537 
5538 exit:
5539 	cil_tree_log(parse_current, CIL_ERR, "Bad optional");
5540 	cil_destroy_optional(optional);
5541 	cil_clear_node(ast_node);
5542 	return rc;
5543 }
5544 
cil_destroy_optional(struct cil_optional * optional)5545 void cil_destroy_optional(struct cil_optional *optional)
5546 {
5547 	if (optional == NULL) {
5548 		return;
5549 	}
5550 
5551 	cil_symtab_datum_destroy(&optional->datum);
5552 	free(optional);
5553 }
5554 
cil_gen_policycap(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5555 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5556 {
5557 	enum cil_syntax syntax[] = {
5558 		CIL_SYN_STRING,
5559 		CIL_SYN_STRING,
5560 		CIL_SYN_END
5561 	};
5562 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5563 	char *key = NULL;
5564 	struct cil_policycap *polcap = NULL;
5565 	int rc = SEPOL_ERR;
5566 
5567 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5568 		goto exit;
5569 	}
5570 
5571 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5572 	if (rc != SEPOL_OK) {
5573 		goto exit;
5574 	}
5575 
5576 	cil_policycap_init(&polcap);
5577 
5578 	key = parse_current->next->data;
5579 
5580 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP);
5581 	if (rc != SEPOL_OK)
5582 		goto exit;
5583 
5584 	return SEPOL_OK;
5585 
5586 exit:
5587 	cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
5588 	cil_destroy_policycap(polcap);
5589 	cil_clear_node(ast_node);
5590 	return rc;
5591 }
5592 
cil_destroy_policycap(struct cil_policycap * polcap)5593 void cil_destroy_policycap(struct cil_policycap *polcap)
5594 {
5595 	if (polcap == NULL) {
5596 		return;
5597 	}
5598 
5599 	cil_symtab_datum_destroy(&polcap->datum);
5600 	free(polcap);
5601 }
5602 
cil_gen_ipaddr(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5603 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5604 {
5605 	enum cil_syntax syntax[] = {
5606 		CIL_SYN_STRING,
5607 		CIL_SYN_STRING,
5608 		CIL_SYN_STRING,
5609 		CIL_SYN_END
5610 	};
5611 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5612 	char *key = NULL;
5613 	struct cil_ipaddr *ipaddr = NULL;
5614 	int rc = SEPOL_ERR;
5615 
5616 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5617 		goto exit;
5618 	}
5619 
5620 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5621 	if (rc != SEPOL_OK) {
5622 		goto exit;
5623 	}
5624 
5625 	cil_ipaddr_init(&ipaddr);
5626 
5627 	key  = parse_current->next->data;
5628 
5629 	rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
5630 	if (rc != SEPOL_OK) {
5631 		goto exit;
5632 	}
5633 
5634 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
5635 	if (rc != SEPOL_OK) {
5636 		goto exit;
5637 	}
5638 
5639 	return SEPOL_OK;
5640 
5641 exit:
5642 	cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
5643 	cil_destroy_ipaddr(ipaddr);
5644 	cil_clear_node(ast_node);
5645 	return rc;
5646 }
5647 
cil_destroy_ipaddr(struct cil_ipaddr * ipaddr)5648 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
5649 {
5650 	if (ipaddr == NULL) {
5651 		return;
5652 	}
5653 
5654 	cil_symtab_datum_destroy(&ipaddr->datum);
5655 	free(ipaddr);
5656 }
5657 
cil_fill_integer(struct cil_tree_node * int_node,uint32_t * integer,int base)5658 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
5659 {
5660 	int rc = SEPOL_ERR;
5661 
5662 	if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5663 		goto exit;
5664 	}
5665 
5666 	rc = cil_string_to_uint32(int_node->data, integer, base);
5667 	if (rc != SEPOL_OK) {
5668 		goto exit;
5669 	}
5670 
5671 	return SEPOL_OK;
5672 
5673 exit:
5674 	cil_log(CIL_ERR, "Failed to fill 32-bit integer\n");
5675 	return rc;
5676 }
5677 
cil_fill_integer64(struct cil_tree_node * int_node,uint64_t * integer,int base)5678 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
5679 {
5680 	int rc = SEPOL_ERR;
5681 
5682 	if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5683 		goto exit;
5684 	}
5685 
5686 	rc = cil_string_to_uint64(int_node->data, integer, base);
5687 	if (rc != SEPOL_OK) {
5688 		goto exit;
5689 	}
5690 
5691 	return SEPOL_OK;
5692 
5693 exit:
5694 	cil_log(CIL_ERR, "Failed to fill 64-bit integer\n");
5695 	return rc;
5696 }
5697 
cil_fill_ipaddr(struct cil_tree_node * addr_node,struct cil_ipaddr * addr)5698 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
5699 {
5700 	int rc = SEPOL_ERR;
5701 
5702 	if (addr_node == NULL || addr_node->data == NULL || addr == NULL) {
5703 		goto exit;
5704 	}
5705 
5706 	if (strchr(addr_node->data, ':') != NULL) {
5707 		addr->family = AF_INET6;
5708 	} else {
5709 		addr->family = AF_INET;
5710 	}
5711 
5712 	rc = inet_pton(addr->family, addr_node->data, &addr->ip);
5713 	if (rc != 1) {
5714 		rc = SEPOL_ERR;
5715 		goto exit;
5716 	}
5717 
5718 	return SEPOL_OK;
5719 
5720 exit:
5721 	cil_log(CIL_ERR, "Bad ip address or netmask: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "n/a");
5722 	return rc;
5723 }
5724 
cil_fill_level(struct cil_tree_node * curr,struct cil_level * level)5725 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
5726 {
5727 	int rc = SEPOL_ERR;
5728 	enum cil_syntax syntax[] = {
5729 		CIL_SYN_STRING,
5730 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
5731 		CIL_SYN_END
5732 	};
5733 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5734 
5735 	if (curr == NULL) {
5736 		goto exit;
5737 	}
5738 
5739 	rc = __cil_verify_syntax(curr, syntax, syntax_len);
5740 	if (rc != SEPOL_OK) {
5741 		goto exit;
5742 	}
5743 
5744 	level->sens_str = curr->data;
5745 	if (curr->next != NULL) {
5746 		rc = cil_fill_cats(curr->next, &level->cats);
5747 		if (rc != SEPOL_OK) {
5748 			goto exit;
5749 		}
5750 	}
5751 
5752 	return SEPOL_OK;
5753 
5754 exit:
5755 	cil_log(CIL_ERR, "Bad level\n");
5756 	return rc;
5757 }
5758 
cil_fill_cats(struct cil_tree_node * curr,struct cil_cats ** cats)5759 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
5760 {
5761 	int rc = SEPOL_ERR;
5762 
5763 	cil_cats_init(cats);
5764 
5765 	rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
5766 	if (rc != SEPOL_OK) {
5767 		cil_destroy_cats(*cats);
5768 		*cats = NULL;
5769 	}
5770 
5771 	return rc;
5772 }
5773 
cil_destroy_cats(struct cil_cats * cats)5774 void cil_destroy_cats(struct cil_cats *cats)
5775 {
5776 	if (cats == NULL) {
5777 		return;
5778 	}
5779 
5780 	cil_list_destroy(&cats->str_expr, CIL_TRUE);
5781 
5782 	cil_list_destroy(&cats->datum_expr, CIL_FALSE);
5783 
5784 	free(cats);
5785 }
cil_gen_bounds(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5786 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5787 {
5788 	enum cil_syntax syntax[] = {
5789 		CIL_SYN_STRING,
5790 		CIL_SYN_STRING,
5791 		CIL_SYN_STRING,
5792 		CIL_SYN_END
5793 	};
5794 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5795 	struct cil_bounds *bounds = NULL;
5796 	int rc = SEPOL_ERR;
5797 
5798 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5799 		goto exit;
5800 	}
5801 
5802 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5803 	if (rc != SEPOL_OK) {
5804 		goto exit;
5805 	}
5806 
5807 	cil_bounds_init(&bounds);
5808 
5809 	bounds->parent_str = parse_current->next->data;
5810 	bounds->child_str = parse_current->next->next->data;
5811 
5812 	ast_node->data = bounds;
5813 
5814 	switch (flavor) {
5815 	case CIL_USER:
5816 		ast_node->flavor = CIL_USERBOUNDS;
5817 		break;
5818 	case CIL_ROLE:
5819 		ast_node->flavor = CIL_ROLEBOUNDS;
5820 		break;
5821 	case CIL_TYPE:
5822 		ast_node->flavor = CIL_TYPEBOUNDS;
5823 		break;
5824 	default:
5825 		break;
5826 	}
5827 
5828 	return SEPOL_OK;
5829 
5830 exit:
5831 	cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
5832 	cil_destroy_bounds(bounds);
5833 	return rc;
5834 }
5835 
cil_destroy_bounds(struct cil_bounds * bounds)5836 void cil_destroy_bounds(struct cil_bounds *bounds)
5837 {
5838 	if (bounds == NULL) {
5839 		return;
5840 	}
5841 
5842 	free(bounds);
5843 }
5844 
cil_gen_default(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5845 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5846 {
5847 	int rc = SEPOL_ERR;
5848 	struct cil_default *def = NULL;
5849 	char *object;
5850 	enum cil_syntax syntax[] = {
5851 		CIL_SYN_STRING,
5852 		CIL_SYN_STRING | CIL_SYN_LIST,
5853 		CIL_SYN_STRING,
5854 		CIL_SYN_END
5855 	};
5856 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5857 
5858 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5859 	if (rc != SEPOL_OK) {
5860 		goto exit;
5861 	}
5862 
5863 	cil_default_init(&def);
5864 
5865 	def->flavor = flavor;
5866 
5867 	if (parse_current->next->cl_head == NULL) {
5868 		cil_list_init(&def->class_strs, CIL_CLASS);
5869 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5870 	} else {
5871 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5872 		if (rc != SEPOL_OK) {
5873 			goto exit;
5874 		}
5875 	}
5876 
5877 	object = parse_current->next->next->data;
5878 	if (object == CIL_KEY_SOURCE) {
5879 		def->object = CIL_DEFAULT_SOURCE;
5880 	} else if (object == CIL_KEY_TARGET) {
5881 		def->object = CIL_DEFAULT_TARGET;
5882 	} else {
5883 		cil_log(CIL_ERR,"Expected either 'source' or 'target'\n");
5884 		rc = SEPOL_ERR;
5885 		goto exit;
5886 	}
5887 
5888 	ast_node->data = def;
5889 	ast_node->flavor = flavor;
5890 
5891 	return SEPOL_OK;
5892 
5893 exit:
5894 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current));
5895 	cil_destroy_default(def);
5896 	return rc;
5897 }
5898 
cil_destroy_default(struct cil_default * def)5899 void cil_destroy_default(struct cil_default *def)
5900 {
5901 	if (def == NULL) {
5902 		return;
5903 	}
5904 
5905 	cil_list_destroy(&def->class_strs, CIL_TRUE);
5906 
5907 	cil_list_destroy(&def->class_datums, CIL_FALSE);
5908 
5909 	free(def);
5910 }
5911 
cil_gen_defaultrange(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5912 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5913 {
5914 	int rc = SEPOL_ERR;
5915 	struct cil_defaultrange *def = NULL;
5916 	char *object;
5917 	char *range;
5918 	enum cil_syntax syntax[] = {
5919 		CIL_SYN_STRING,
5920 		CIL_SYN_STRING | CIL_SYN_LIST,
5921 		CIL_SYN_STRING,
5922 		CIL_SYN_STRING | CIL_SYN_END,
5923 		CIL_SYN_END
5924 	};
5925 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5926 
5927 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5928 	if (rc != SEPOL_OK) {
5929 		goto exit;
5930 	}
5931 
5932 	cil_defaultrange_init(&def);
5933 
5934 	if (parse_current->next->cl_head == NULL) {
5935 		cil_list_init(&def->class_strs, CIL_CLASS);
5936 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5937 	} else {
5938 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5939 		if (rc != SEPOL_OK) {
5940 			goto exit;
5941 		}
5942 	}
5943 
5944 	object = parse_current->next->next->data;
5945 	if (object == CIL_KEY_SOURCE) {
5946 		if (!parse_current->next->next->next) {
5947 			cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5948 			rc = SEPOL_ERR;
5949 			goto exit;
5950 		}
5951 		range = parse_current->next->next->next->data;
5952 		if (range == CIL_KEY_LOW) {
5953 			def->object_range = CIL_DEFAULT_SOURCE_LOW;
5954 		} else if (range == CIL_KEY_HIGH) {
5955 			def->object_range = CIL_DEFAULT_SOURCE_HIGH;
5956 		} else if (range == CIL_KEY_LOW_HIGH) {
5957 			def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
5958 		} else {
5959 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5960 			rc = SEPOL_ERR;
5961 			goto exit;
5962 		}
5963 	} else if (object == CIL_KEY_TARGET) {
5964 		if (!parse_current->next->next->next) {
5965 			cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5966 			rc = SEPOL_ERR;
5967 			goto exit;
5968 		}
5969 		range = parse_current->next->next->next->data;
5970 		if (range == CIL_KEY_LOW) {
5971 			def->object_range = CIL_DEFAULT_TARGET_LOW;
5972 		} else if (range == CIL_KEY_HIGH) {
5973 			def->object_range = CIL_DEFAULT_TARGET_HIGH;
5974 		} else if (range == CIL_KEY_LOW_HIGH) {
5975 			def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
5976 		} else {
5977 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5978 			rc = SEPOL_ERR;
5979 			goto exit;
5980 		}
5981 	} else if (object == CIL_KEY_GLBLUB) {
5982 		def->object_range = CIL_DEFAULT_GLBLUB;
5983 	} else {
5984 		cil_log(CIL_ERR,"Expected \'source\', \'target\', or \'glblub\'\n");
5985 		rc = SEPOL_ERR;
5986 		goto exit;
5987 	}
5988 
5989 	ast_node->data = def;
5990 	ast_node->flavor = CIL_DEFAULTRANGE;
5991 
5992 	return SEPOL_OK;
5993 
5994 exit:
5995 	cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
5996 	cil_destroy_defaultrange(def);
5997 	return rc;
5998 }
5999 
cil_destroy_defaultrange(struct cil_defaultrange * def)6000 void cil_destroy_defaultrange(struct cil_defaultrange *def)
6001 {
6002 	if (def == NULL) {
6003 		return;
6004 	}
6005 
6006 	cil_list_destroy(&def->class_strs, CIL_TRUE);
6007 
6008 	cil_list_destroy(&def->class_datums, CIL_FALSE);
6009 
6010 	free(def);
6011 }
6012 
cil_gen_handleunknown(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6013 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6014 {
6015 	int rc = SEPOL_ERR;
6016 	enum cil_syntax syntax[] = {
6017 		CIL_SYN_STRING,
6018 		CIL_SYN_STRING,
6019 		CIL_SYN_END
6020 	};
6021 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6022 	struct cil_handleunknown *unknown = NULL;
6023 	char *unknown_key;
6024 
6025 	if (parse_current == NULL || ast_node == NULL) {
6026 		goto exit;
6027 	}
6028 
6029 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6030 	if (rc != SEPOL_OK) {
6031 		goto exit;
6032 	}
6033 
6034 	cil_handleunknown_init(&unknown);
6035 
6036 	unknown_key = parse_current->next->data;
6037 	if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
6038 		unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
6039 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
6040 		unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
6041 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
6042 		unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
6043 	} else {
6044 		cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT);
6045 		rc = SEPOL_ERR;
6046 		goto exit;
6047 	}
6048 
6049 	ast_node->data = unknown;
6050 	ast_node->flavor = CIL_HANDLEUNKNOWN;
6051 
6052 	return SEPOL_OK;
6053 
6054 exit:
6055 	cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
6056 	cil_destroy_handleunknown(unknown);
6057 	return rc;
6058 }
6059 
cil_destroy_handleunknown(struct cil_handleunknown * unk)6060 void cil_destroy_handleunknown(struct cil_handleunknown *unk)
6061 {
6062 	free(unk);
6063 }
6064 
cil_gen_mls(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6065 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6066 {
6067 	int rc = SEPOL_ERR;
6068 	enum cil_syntax syntax[] = {
6069 		CIL_SYN_STRING,
6070 		CIL_SYN_STRING,
6071 		CIL_SYN_END
6072 	};
6073 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6074 	struct cil_mls *mls = NULL;
6075 
6076 	if (parse_current == NULL || ast_node == NULL) {
6077 		goto exit;
6078 	}
6079 
6080 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6081 	if (rc != SEPOL_OK) {
6082 		goto exit;
6083 	}
6084 
6085 	cil_mls_init(&mls);
6086 
6087 	if (parse_current->next->data == CIL_KEY_CONDTRUE) {
6088 		mls->value = CIL_TRUE;
6089 	} else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
6090 		mls->value = CIL_FALSE;
6091 	} else {
6092 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
6093 		rc = SEPOL_ERR;
6094 		goto exit;
6095 	}
6096 
6097 	ast_node->data = mls;
6098 	ast_node->flavor = CIL_MLS;
6099 
6100 	return SEPOL_OK;
6101 
6102 exit:
6103 	cil_tree_log(parse_current, CIL_ERR, "Bad mls");
6104 	cil_destroy_mls(mls);
6105 	return rc;
6106 }
6107 
cil_destroy_mls(struct cil_mls * mls)6108 void cil_destroy_mls(struct cil_mls *mls)
6109 {
6110 	free(mls);
6111 }
6112 
cil_gen_src_info(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6113 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6114 {
6115 	int rc = SEPOL_ERR;
6116 	enum cil_syntax syntax[] = {
6117 		CIL_SYN_STRING,
6118 		CIL_SYN_STRING,
6119 		CIL_SYN_STRING,
6120 		CIL_SYN_STRING,
6121 		CIL_SYN_N_LISTS | CIL_SYN_END,
6122 		CIL_SYN_END
6123 	};
6124 	size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6125 	struct cil_src_info *info = NULL;
6126 
6127 	if (parse_current == NULL || ast_node == NULL) {
6128 		goto exit;
6129 	}
6130 
6131 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6132 	if (rc != SEPOL_OK) {
6133 		goto exit;
6134 	}
6135 
6136 	cil_src_info_init(&info);
6137 
6138 	info->kind = parse_current->next->data;
6139 	if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) {
6140 		cil_log(CIL_ERR, "Invalid src info kind\n");
6141 		rc = SEPOL_ERR;
6142 		goto exit;
6143 	}
6144 
6145 	rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10);
6146 	if (rc != SEPOL_OK) {
6147 		goto exit;
6148 	}
6149 
6150 	info->path = parse_current->next->next->next->data;
6151 
6152 	ast_node->data = info;
6153 	ast_node->flavor = CIL_SRC_INFO;
6154 
6155 	return SEPOL_OK;
6156 
6157 exit:
6158 	cil_tree_log(parse_current, CIL_ERR, "Bad src info");
6159 	cil_destroy_src_info(info);
6160 	return rc;
6161 }
6162 
cil_destroy_src_info(struct cil_src_info * info)6163 void cil_destroy_src_info(struct cil_src_info *info)
6164 {
6165 	free(info);
6166 }
6167 
check_for_illegal_statement(struct cil_tree_node * parse_current,struct cil_args_build * args)6168 static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args)
6169 {
6170 	if (args->tunif != NULL) {
6171 		if (parse_current->data == CIL_KEY_TUNABLE) {
6172 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data);
6173 			return SEPOL_ERR;
6174 		}
6175 	}
6176 
6177 	if (args->in != NULL) {
6178 		struct cil_in *in_block = args->in->data;
6179 		if (parse_current->data == CIL_KEY_TUNABLE ||
6180 			parse_current->data == CIL_KEY_IN) {
6181 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data);
6182 			return SEPOL_ERR;
6183 		}
6184 		if (in_block->is_after == CIL_TRUE) {
6185 			if (parse_current->data == CIL_KEY_BLOCKINHERIT ||
6186 				parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6187 				cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data);
6188 				return SEPOL_ERR;
6189 			}
6190 		}
6191 	}
6192 
6193 	if (args->macro != NULL) {
6194 		if (parse_current->data == CIL_KEY_TUNABLE ||
6195 			parse_current->data == CIL_KEY_IN ||
6196 			parse_current->data == CIL_KEY_BLOCK ||
6197 			parse_current->data == CIL_KEY_BLOCKINHERIT ||
6198 			parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6199 			parse_current->data == CIL_KEY_MACRO) {
6200 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data);
6201 			return SEPOL_ERR;
6202 		}
6203 	}
6204 
6205 	if (args->optional != NULL) {
6206 		if (parse_current->data == CIL_KEY_TUNABLE ||
6207 			parse_current->data == CIL_KEY_IN ||
6208 			parse_current->data == CIL_KEY_BLOCK ||
6209 			parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6210 			parse_current->data == CIL_KEY_MACRO) {
6211 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data);
6212 			return SEPOL_ERR;
6213 		}
6214 	}
6215 
6216 	if (args->boolif != NULL) {
6217 		if (parse_current->data != CIL_KEY_TUNABLEIF &&
6218 			parse_current->data != CIL_KEY_CALL &&
6219 			parse_current->data != CIL_KEY_CONDTRUE &&
6220 			parse_current->data != CIL_KEY_CONDFALSE &&
6221 			parse_current->data != CIL_KEY_ALLOW &&
6222 			parse_current->data != CIL_KEY_DONTAUDIT &&
6223 			parse_current->data != CIL_KEY_AUDITALLOW &&
6224 			parse_current->data != CIL_KEY_TYPETRANSITION &&
6225 			parse_current->data != CIL_KEY_TYPECHANGE &&
6226 			parse_current->data != CIL_KEY_TYPEMEMBER) {
6227 			if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) {
6228 				cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data);
6229 			} else {
6230 				cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data);
6231 			}
6232 			return SEPOL_ERR;
6233 		}
6234 	}
6235 
6236 	return SEPOL_OK;
6237 }
6238 
parse_statement(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_parent)6239 static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent)
6240 {
6241 	struct cil_tree_node *new_ast_node = NULL;
6242 	int rc = SEPOL_ERR;
6243 
6244 	cil_tree_node_init(&new_ast_node);
6245 	new_ast_node->parent = ast_parent;
6246 	new_ast_node->line = parse_current->line;
6247 	new_ast_node->hll_offset = parse_current->hll_offset;
6248 
6249 	if (parse_current->data == CIL_KEY_BLOCK) {
6250 		rc = cil_gen_block(db, parse_current, new_ast_node, 0);
6251 	} else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
6252 		rc = cil_gen_blockinherit(db, parse_current, new_ast_node);
6253 	} else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6254 		rc = cil_gen_blockabstract(db, parse_current, new_ast_node);
6255 	} else if (parse_current->data == CIL_KEY_IN) {
6256 		rc = cil_gen_in(db, parse_current, new_ast_node);
6257 	} else if (parse_current->data == CIL_KEY_CLASS) {
6258 		rc = cil_gen_class(db, parse_current, new_ast_node);
6259 	} else if (parse_current->data == CIL_KEY_CLASSORDER) {
6260 		rc = cil_gen_classorder(db, parse_current, new_ast_node);
6261 	} else if (parse_current->data == CIL_KEY_MAP_CLASS) {
6262 		rc = cil_gen_map_class(db, parse_current, new_ast_node);
6263 	} else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
6264 		rc = cil_gen_classmapping(db, parse_current, new_ast_node);
6265 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
6266 		rc = cil_gen_classpermission(db, parse_current, new_ast_node);
6267 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
6268 		rc = cil_gen_classpermissionset(db, parse_current, new_ast_node);
6269 	} else if (parse_current->data == CIL_KEY_COMMON) {
6270 		rc = cil_gen_common(db, parse_current, new_ast_node);
6271 	} else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
6272 		rc = cil_gen_classcommon(db, parse_current, new_ast_node);
6273 	} else if (parse_current->data == CIL_KEY_SID) {
6274 		rc = cil_gen_sid(db, parse_current, new_ast_node);
6275 	} else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
6276 		rc = cil_gen_sidcontext(db, parse_current, new_ast_node);
6277 	} else if (parse_current->data == CIL_KEY_SIDORDER) {
6278 		rc = cil_gen_sidorder(db, parse_current, new_ast_node);
6279 	} else if (parse_current->data == CIL_KEY_USER) {
6280 		rc = cil_gen_user(db, parse_current, new_ast_node);
6281 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
6282 		rc = cil_gen_userattribute(db, parse_current, new_ast_node);
6283 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
6284 		rc = cil_gen_userattributeset(db, parse_current, new_ast_node);
6285 	} else if (parse_current->data == CIL_KEY_USERLEVEL) {
6286 		rc = cil_gen_userlevel(db, parse_current, new_ast_node);
6287 	} else if (parse_current->data == CIL_KEY_USERRANGE) {
6288 		rc = cil_gen_userrange(db, parse_current, new_ast_node);
6289 	} else if (parse_current->data == CIL_KEY_USERBOUNDS) {
6290 		rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER);
6291 	} else if (parse_current->data == CIL_KEY_USERPREFIX) {
6292 		rc = cil_gen_userprefix(db, parse_current, new_ast_node);
6293 	} else if (parse_current->data == CIL_KEY_SELINUXUSER) {
6294 		rc = cil_gen_selinuxuser(db, parse_current, new_ast_node);
6295 	} else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
6296 		rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node);
6297 	} else if (parse_current->data == CIL_KEY_TYPE) {
6298 		rc = cil_gen_type(db, parse_current, new_ast_node);
6299 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
6300 		rc = cil_gen_typeattribute(db, parse_current, new_ast_node);
6301 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
6302 		rc = cil_gen_typeattributeset(db, parse_current, new_ast_node);
6303 	} else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
6304 		rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node);
6305 	} else if (parse_current->data == CIL_KEY_TYPEALIAS) {
6306 		rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS);
6307 	} else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
6308 		rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL);
6309 	} else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
6310 		rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE);
6311 	} else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
6312 		rc = cil_gen_typepermissive(db, parse_current, new_ast_node);
6313 	} else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
6314 		rc = cil_gen_rangetransition(db, parse_current, new_ast_node);
6315 	} else if (parse_current->data == CIL_KEY_ROLE) {
6316 		rc = cil_gen_role(db, parse_current, new_ast_node);
6317 	} else if (parse_current->data == CIL_KEY_USERROLE) {
6318 		rc = cil_gen_userrole(db, parse_current, new_ast_node);
6319 	} else if (parse_current->data == CIL_KEY_ROLETYPE) {
6320 		rc = cil_gen_roletype(db, parse_current, new_ast_node);
6321 	} else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
6322 		rc = cil_gen_roletransition(parse_current, new_ast_node);
6323 	} else if (parse_current->data == CIL_KEY_ROLEALLOW) {
6324 		rc = cil_gen_roleallow(db, parse_current, new_ast_node);
6325 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
6326 		rc = cil_gen_roleattribute(db, parse_current, new_ast_node);
6327 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
6328 		rc = cil_gen_roleattributeset(db, parse_current, new_ast_node);
6329 	} else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
6330 		rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE);
6331 	} else if (parse_current->data == CIL_KEY_BOOL) {
6332 		rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE);
6333 	} else if (parse_current->data == CIL_KEY_BOOLEANIF) {
6334 		rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE);
6335 	} else if(parse_current->data == CIL_KEY_TUNABLE) {
6336 		if (db->preserve_tunables) {
6337 			rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE);
6338 		} else {
6339 			rc = cil_gen_tunable(db, parse_current, new_ast_node);
6340 		}
6341 	} else if (parse_current->data == CIL_KEY_TUNABLEIF) {
6342 		if (db->preserve_tunables) {
6343 			rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE);
6344 		} else {
6345 			rc = cil_gen_tunif(db, parse_current, new_ast_node);
6346 		}
6347 	} else if (parse_current->data == CIL_KEY_CONDTRUE) {
6348 		rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE);
6349 	} else if (parse_current->data == CIL_KEY_CONDFALSE) {
6350 		rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE);
6351 	} else if (parse_current->data == CIL_KEY_ALLOW) {
6352 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6353 	} else if (parse_current->data == CIL_KEY_AUDITALLOW) {
6354 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6355 	} else if (parse_current->data == CIL_KEY_DONTAUDIT) {
6356 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6357 	} else if (parse_current->data == CIL_KEY_NEVERALLOW) {
6358 		rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6359 	} else if (parse_current->data == CIL_KEY_ALLOWX) {
6360 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6361 	} else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
6362 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6363 	} else if (parse_current->data == CIL_KEY_DONTAUDITX) {
6364 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6365 	} else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
6366 		rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6367 	} else if (parse_current->data == CIL_KEY_PERMISSIONX) {
6368 		rc = cil_gen_permissionx(db, parse_current, new_ast_node);
6369 	} else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
6370 		rc = cil_gen_typetransition(db, parse_current, new_ast_node);
6371 	} else if (parse_current->data == CIL_KEY_TYPECHANGE) {
6372 		rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE);
6373 	} else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
6374 		rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER);
6375 	} else if (parse_current->data == CIL_KEY_SENSITIVITY) {
6376 		rc = cil_gen_sensitivity(db, parse_current, new_ast_node);
6377 	} else if (parse_current->data == CIL_KEY_SENSALIAS) {
6378 		rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS);
6379 	} else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
6380 		rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL);
6381 	} else if (parse_current->data == CIL_KEY_CATEGORY) {
6382 		rc = cil_gen_category(db, parse_current, new_ast_node);
6383 	} else if (parse_current->data == CIL_KEY_CATALIAS) {
6384 		rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS);
6385 	} else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
6386 		rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL);
6387 	} else if (parse_current->data == CIL_KEY_CATSET) {
6388 		rc = cil_gen_catset(db, parse_current, new_ast_node);
6389 	} else if (parse_current->data == CIL_KEY_CATORDER) {
6390 		rc = cil_gen_catorder(db, parse_current, new_ast_node);
6391 	} else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
6392 		rc = cil_gen_sensitivityorder(db, parse_current, new_ast_node);
6393 	} else if (parse_current->data == CIL_KEY_SENSCAT) {
6394 		rc = cil_gen_senscat(db, parse_current, new_ast_node);
6395 	} else if (parse_current->data == CIL_KEY_LEVEL) {
6396 		rc = cil_gen_level(db, parse_current, new_ast_node);
6397 	} else if (parse_current->data == CIL_KEY_LEVELRANGE) {
6398 		rc = cil_gen_levelrange(db, parse_current, new_ast_node);
6399 	} else if (parse_current->data == CIL_KEY_CONSTRAIN) {
6400 		rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN);
6401 	} else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
6402 		rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN);
6403 	} else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
6404 		rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS);
6405 	} else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
6406 		rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS);
6407 	} else if (parse_current->data == CIL_KEY_CONTEXT) {
6408 		rc = cil_gen_context(db, parse_current, new_ast_node);
6409 	} else if (parse_current->data == CIL_KEY_FILECON) {
6410 		rc = cil_gen_filecon(db, parse_current, new_ast_node);
6411 	} else if (parse_current->data == CIL_KEY_IBPKEYCON) {
6412 		rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node);
6413 	} else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
6414 		rc = cil_gen_ibendportcon(db, parse_current, new_ast_node);
6415 	} else if (parse_current->data == CIL_KEY_PORTCON) {
6416 		rc = cil_gen_portcon(db, parse_current, new_ast_node);
6417 	} else if (parse_current->data == CIL_KEY_NODECON) {
6418 		rc = cil_gen_nodecon(db, parse_current, new_ast_node);
6419 	} else if (parse_current->data == CIL_KEY_GENFSCON) {
6420 		rc = cil_gen_genfscon(db, parse_current, new_ast_node);
6421 	} else if (parse_current->data == CIL_KEY_NETIFCON) {
6422 		rc = cil_gen_netifcon(db, parse_current, new_ast_node);
6423 	} else if (parse_current->data == CIL_KEY_PIRQCON) {
6424 		rc = cil_gen_pirqcon(db, parse_current, new_ast_node);
6425 	} else if (parse_current->data == CIL_KEY_IOMEMCON) {
6426 		rc = cil_gen_iomemcon(db, parse_current, new_ast_node);
6427 	} else if (parse_current->data == CIL_KEY_IOPORTCON) {
6428 		rc = cil_gen_ioportcon(db, parse_current, new_ast_node);
6429 	} else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
6430 		rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node);
6431 	} else if (parse_current->data == CIL_KEY_DEVICETREECON) {
6432 		rc = cil_gen_devicetreecon(db, parse_current, new_ast_node);
6433 	} else if (parse_current->data == CIL_KEY_FSUSE) {
6434 		rc = cil_gen_fsuse(db, parse_current, new_ast_node);
6435 	} else if (parse_current->data == CIL_KEY_MACRO) {
6436 		rc = cil_gen_macro(db, parse_current, new_ast_node);
6437 	} else if (parse_current->data == CIL_KEY_CALL) {
6438 		rc = cil_gen_call(db, parse_current, new_ast_node);
6439 	} else if (parse_current->data == CIL_KEY_POLICYCAP) {
6440 		rc = cil_gen_policycap(db, parse_current, new_ast_node);
6441 	} else if (parse_current->data == CIL_KEY_OPTIONAL) {
6442 		rc = cil_gen_optional(db, parse_current, new_ast_node);
6443 	} else if (parse_current->data == CIL_KEY_IPADDR) {
6444 		rc = cil_gen_ipaddr(db, parse_current, new_ast_node);
6445 	} else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
6446 		rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER);
6447 	} else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
6448 		rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE);
6449 	} else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
6450 		rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE);
6451 	} else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
6452 		rc = cil_gen_defaultrange(parse_current, new_ast_node);
6453 	} else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
6454 		rc = cil_gen_handleunknown(parse_current, new_ast_node);
6455 	} else if (parse_current->data == CIL_KEY_MLS) {
6456 		rc = cil_gen_mls(parse_current, new_ast_node);
6457 	} else if (parse_current->data == CIL_KEY_SRC_INFO) {
6458 		rc = cil_gen_src_info(parse_current, new_ast_node);
6459 	} else {
6460 		cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
6461 		rc = SEPOL_ERR;
6462 	}
6463 
6464 	if (rc == SEPOL_OK) {
6465 		if (ast_parent->cl_head == NULL) {
6466 			ast_parent->cl_head = new_ast_node;
6467 		} else {
6468 			ast_parent->cl_tail->next = new_ast_node;
6469 		}
6470 		ast_parent->cl_tail = new_ast_node;
6471 	} else {
6472 		cil_tree_node_destroy(&new_ast_node);
6473 		new_ast_node = NULL;
6474 	}
6475 
6476 	return new_ast_node;
6477 }
6478 
__cil_build_ast_node_helper(struct cil_tree_node * parse_current,uint32_t * finished,void * extra_args)6479 static int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
6480 {
6481 	struct cil_args_build *args = extra_args;
6482 	struct cil_tree_node *new_ast_node = NULL;
6483 	int rc = SEPOL_ERR;
6484 
6485 	if (parse_current->parent->cl_head != parse_current) {
6486 		/* ignore anything that isn't following a parenthesis */
6487 		return SEPOL_OK;
6488 	} else if (parse_current->data == NULL) {
6489 		/* the only time parenthesis can immediately following parenthesis is if
6490 		 * the parent is the root node */
6491 		if (parse_current->parent->parent == NULL) {
6492 			return SEPOL_OK;
6493 		} else {
6494 			cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
6495 			return SEPOL_ERR;
6496 		}
6497 	}
6498 
6499 	rc = check_for_illegal_statement(parse_current, args);
6500 	if (rc != SEPOL_OK) {
6501 		return SEPOL_ERR;
6502 	}
6503 
6504 	new_ast_node = parse_statement(args->db, parse_current, args->ast);
6505 	if (!new_ast_node) {
6506 		return SEPOL_ERR;
6507 	}
6508 
6509 	args->ast = new_ast_node;
6510 
6511 	if (parse_current->data != CIL_KEY_BLOCK &&
6512 		parse_current->data != CIL_KEY_IN &&
6513 		parse_current->data != CIL_KEY_TUNABLEIF &&
6514 		parse_current->data != CIL_KEY_BOOLEANIF &&
6515 		parse_current->data != CIL_KEY_CONDTRUE &&
6516 		parse_current->data != CIL_KEY_CONDFALSE &&
6517 		parse_current->data != CIL_KEY_MACRO &&
6518 		parse_current->data != CIL_KEY_OPTIONAL &&
6519 		parse_current->data != CIL_KEY_SRC_INFO) {
6520 		/* Skip anything that does not contain a list of policy statements */
6521 		*finished = CIL_TREE_SKIP_NEXT;
6522 	}
6523 
6524 	return SEPOL_OK;
6525 }
6526 
__cil_build_ast_first_child_helper(struct cil_tree_node * parse_current,void * extra_args)6527 static int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args)
6528 {
6529 	struct cil_args_build *args = extra_args;
6530 	struct cil_tree_node *ast = args->ast;
6531 
6532 	if (ast->flavor == CIL_TUNABLEIF) {
6533 		args->tunif = ast;
6534 	} else if (ast->flavor == CIL_IN) {
6535 		args->in = ast;
6536 	} else if (ast->flavor == CIL_MACRO) {
6537 		args->macro = ast;
6538 	} else if (ast->flavor == CIL_OPTIONAL) {
6539 		args->optional = ast;
6540 	} else if (ast->flavor == CIL_BOOLEANIF) {
6541 		args->boolif = ast;
6542 	}
6543 
6544 	return SEPOL_OK;
6545 }
6546 
__cil_build_ast_last_child_helper(struct cil_tree_node * parse_current,void * extra_args)6547 static int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
6548 {
6549 	struct cil_args_build *args = extra_args;
6550 	struct cil_tree_node *ast = args->ast;
6551 
6552 	if (ast->flavor == CIL_ROOT) {
6553 		return SEPOL_OK;
6554 	}
6555 
6556 	args->ast = ast->parent;
6557 
6558 	if (ast->flavor == CIL_TUNABLEIF) {
6559 		args->tunif = NULL;
6560 	}
6561 
6562 	if (ast->flavor == CIL_IN) {
6563 		args->in = NULL;
6564 	}
6565 
6566 	if (ast->flavor == CIL_MACRO) {
6567 		args->macro = NULL;
6568 	}
6569 
6570 	if (ast->flavor == CIL_OPTIONAL) {
6571 		struct cil_tree_node *n = ast->parent;
6572 		args->optional = NULL;
6573 		/* Optionals can be nested */
6574 		while (n && n->flavor != CIL_ROOT) {
6575 			if (n->flavor == CIL_OPTIONAL) {
6576 				args->optional = n;
6577 				break;
6578 			}
6579 			n = n->parent;
6580 		}
6581 	}
6582 
6583 	if (ast->flavor == CIL_BOOLEANIF) {
6584 		args->boolif = NULL;
6585 	}
6586 
6587 	// At this point we no longer have any need for parse_current or any of its
6588 	// siblings; they have all been converted to the appropriate AST node. The
6589 	// full parse tree will get deleted elsewhere, but in an attempt to
6590 	// minimize memory usage (of which the parse tree uses a lot), start
6591 	// deleting the parts we don't need now.
6592 	cil_tree_children_destroy(parse_current->parent);
6593 
6594 	return SEPOL_OK;
6595 }
6596 
cil_build_ast(struct cil_db * db,struct cil_tree_node * parse_tree,struct cil_tree_node * ast)6597 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
6598 {
6599 	int rc = SEPOL_ERR;
6600 	struct cil_args_build extra_args;
6601 
6602 	if (db == NULL || parse_tree == NULL || ast == NULL) {
6603 		goto exit;
6604 	}
6605 
6606 	extra_args.ast = ast;
6607 	extra_args.db = db;
6608 	extra_args.tunif = NULL;
6609 	extra_args.in = NULL;
6610 	extra_args.macro = NULL;
6611 	extra_args.optional = NULL;
6612 	extra_args.boolif = NULL;
6613 
6614 	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);
6615 	if (rc != SEPOL_OK) {
6616 		goto exit;
6617 	}
6618 
6619 	return SEPOL_OK;
6620 
6621 exit:
6622 	return rc;
6623 }
6624