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