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