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