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