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