• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice,
8  *       this list of conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice,
11  *       this list of conditions and the following disclaimer in the documentation
12  *       and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * The views and conclusions contained in the software and documentation are those
26  * of the authors and should not be interpreted as representing official policies,
27  * either expressed or implied, of Tresys Technology, LLC.
28  */
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <ctype.h>
34 
35 #include <sepol/policydb/conditional.h>
36 
37 #include "cil_internal.h"
38 #include "cil_flavor.h"
39 #include "cil_log.h"
40 #include "cil_mem.h"
41 #include "cil_tree.h"
42 #include "cil_list.h"
43 #include "cil_parser.h"
44 #include "cil_build_ast.h"
45 #include "cil_copy_ast.h"
46 #include "cil_verify.h"
47 #include "cil_strpool.h"
48 
49 struct cil_args_build {
50 	struct cil_tree_node *ast;
51 	struct cil_db *db;
52 	struct cil_tree_node *macro;
53 	struct cil_tree_node *boolif;
54 	struct cil_tree_node *tunif;
55 	struct cil_tree_node *in;
56 };
57 
cil_fill_list(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** list)58 int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list)
59 {
60 	int rc = SEPOL_ERR;
61 	struct cil_tree_node *curr;
62 	enum cil_syntax syntax[] = {
63 		CIL_SYN_N_STRINGS,
64 		CIL_SYN_END
65 	};
66 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
67 
68 	rc = __cil_verify_syntax(current, syntax, syntax_len);
69 	if (rc != SEPOL_OK) {
70 		goto exit;
71  	}
72 
73 	cil_list_init(list, flavor);
74 
75 	for (curr = current; curr != NULL; curr = curr->next) {
76 		cil_list_append(*list, CIL_STRING, curr->data);
77 	}
78 
79 	return SEPOL_OK;
80 
81 exit:
82 	return rc;
83 }
84 
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 			cil_list_destroy(&lexpr, CIL_TRUE);
2757 			goto exit;
2758 		}
2759 		cil_list_init(expr, flavor);
2760 		cil_list_append(*expr, CIL_OP, (void *)op);
2761 		cil_list_append(*expr, CIL_LIST, lexpr);
2762 		cil_list_append(*expr, CIL_LIST, rexpr);
2763 		break;
2764 	}
2765 
2766 	(*depth)--;
2767 
2768 	return SEPOL_OK;
2769 exit:
2770 
2771 	return rc;
2772 }
2773 
cil_gen_constraint_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2774 int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2775 {
2776 	int rc = SEPOL_ERR;
2777 	int depth = 0;
2778 
2779 	if (current->cl_head == NULL) {
2780 		goto exit;
2781 	}
2782 
2783 	rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr, &depth);
2784 	if (rc != SEPOL_OK) {
2785 		goto exit;
2786 	}
2787 
2788 	return SEPOL_OK;
2789 
2790 exit:
2791 
2792 	cil_log(CIL_ERR, "Bad expression tree for constraint\n");
2793 	return rc;
2794 }
2795 
cil_gen_boolif(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,int tunableif)2796 int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif)
2797 {
2798 	enum cil_syntax syntax[] = {
2799 		CIL_SYN_STRING,
2800 		CIL_SYN_STRING | CIL_SYN_LIST,
2801 		CIL_SYN_LIST,
2802 		CIL_SYN_LIST | CIL_SYN_END,
2803 		CIL_SYN_END
2804 	};
2805 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
2806 	struct cil_booleanif *bif = NULL;
2807 	struct cil_tree_node *next = NULL;
2808 	struct cil_tree_node *cond = NULL;
2809 	int rc = SEPOL_ERR;
2810 
2811 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2812 		goto exit;
2813 	}
2814 
2815 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2816 	if (rc != SEPOL_OK) {
2817 		goto exit;
2818 	}
2819 
2820 	cil_boolif_init(&bif);
2821 	bif->preserved_tunable = tunableif;
2822 
2823 	rc = cil_gen_expr(parse_current->next, CIL_BOOL, &bif->str_expr);
2824 	if (rc != SEPOL_OK) {
2825 		goto exit;
2826 	}
2827 
2828 	cond = parse_current->next->next;
2829 
2830 	/* Destroying expr tree after stack is created*/
2831 	if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
2832 		cond->cl_head->data != CIL_KEY_CONDFALSE) {
2833 		rc = SEPOL_ERR;
2834 		cil_log(CIL_ERR, "Conditional neither true nor false\n");
2835 		goto exit;
2836 	}
2837 
2838 	if (cond->next != NULL) {
2839 		cond = cond->next;
2840 		if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
2841 			cond->cl_head->data != CIL_KEY_CONDFALSE) {
2842 			rc = SEPOL_ERR;
2843 			cil_log(CIL_ERR, "Conditional neither true nor false\n");
2844 			goto exit;
2845 		}
2846 	}
2847 
2848 
2849 	next = parse_current->next->next;
2850 	cil_tree_subtree_destroy(parse_current->next);
2851 	parse_current->next = next;
2852 
2853 	ast_node->flavor = CIL_BOOLEANIF;
2854 	ast_node->data = bif;
2855 
2856 	return SEPOL_OK;
2857 
2858 exit:
2859 	if (tunableif) {
2860 		cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration");
2861 	} else {
2862 		cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration");
2863 	}
2864 	cil_destroy_boolif(bif);
2865 	return rc;
2866 }
2867 
cil_destroy_boolif(struct cil_booleanif * bif)2868 void cil_destroy_boolif(struct cil_booleanif *bif)
2869 {
2870 	if (bif == NULL) {
2871 		return;
2872 	}
2873 
2874 	cil_list_destroy(&bif->str_expr, CIL_TRUE);
2875 	cil_list_destroy(&bif->datum_expr, CIL_FALSE);
2876 
2877 	free(bif);
2878 }
2879 
cil_gen_tunif(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2880 int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2881 {
2882 	enum cil_syntax syntax[] = {
2883 		CIL_SYN_STRING,
2884 		CIL_SYN_STRING | CIL_SYN_LIST,
2885 		CIL_SYN_LIST,
2886 		CIL_SYN_LIST | CIL_SYN_END,
2887 		CIL_SYN_END
2888 	};
2889 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
2890 	struct cil_tunableif *tif = NULL;
2891 	struct cil_tree_node *next = NULL;
2892 	struct cil_tree_node *cond = NULL;
2893 	int rc = SEPOL_ERR;
2894 
2895 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2896 		goto exit;
2897 	}
2898 
2899 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2900 	if (rc != SEPOL_OK) {
2901 		goto exit;
2902 	}
2903 
2904 	cil_tunif_init(&tif);
2905 
2906 	rc = cil_gen_expr(parse_current->next, CIL_TUNABLE, &tif->str_expr);
2907 	if (rc != SEPOL_OK) {
2908 		goto exit;
2909 	}
2910 
2911 	cond = parse_current->next->next;
2912 
2913 	if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
2914 		cond->cl_head->data != CIL_KEY_CONDFALSE) {
2915 		rc = SEPOL_ERR;
2916 		cil_log(CIL_ERR, "Conditional neither true nor false\n");
2917 		goto exit;
2918 	}
2919 
2920 	if (cond->next != NULL) {
2921 		cond = cond->next;
2922 
2923 		if (cond->cl_head->data != CIL_KEY_CONDTRUE &&
2924 			cond->cl_head->data != CIL_KEY_CONDFALSE) {
2925 			rc = SEPOL_ERR;
2926 			cil_log(CIL_ERR, "Conditional neither true nor false\n");
2927 			goto exit;
2928 		}
2929 	}
2930 
2931 	/* Destroying expr tree after stack is created*/
2932 	next = parse_current->next->next;
2933 	cil_tree_subtree_destroy(parse_current->next);
2934 	parse_current->next = next;
2935 
2936 	ast_node->flavor = CIL_TUNABLEIF;
2937 	ast_node->data = tif;
2938 
2939 	return SEPOL_OK;
2940 
2941 exit:
2942 	cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration");
2943 	cil_destroy_tunif(tif);
2944 	return rc;
2945 }
2946 
cil_destroy_tunif(struct cil_tunableif * tif)2947 void cil_destroy_tunif(struct cil_tunableif *tif)
2948 {
2949 	if (tif == NULL) {
2950 		return;
2951 	}
2952 
2953 	cil_list_destroy(&tif->str_expr, CIL_TRUE);
2954 	cil_list_destroy(&tif->datum_expr, CIL_FALSE);
2955 
2956 	free(tif);
2957 }
2958 
cil_gen_condblock(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)2959 int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
2960 {
2961 	enum cil_syntax syntax[] = {
2962 		CIL_SYN_STRING,
2963 		CIL_SYN_N_LISTS,
2964 		CIL_SYN_END
2965 	};
2966 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
2967 	int rc = SEPOL_ERR;
2968 	struct cil_condblock *cb = NULL;
2969 
2970 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
2971 		goto exit;
2972 	}
2973 
2974 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2975 	if (rc != SEPOL_OK) {
2976 		goto exit;
2977 	}
2978 
2979 	if (ast_node->parent->flavor != CIL_BOOLEANIF && ast_node->parent->flavor != CIL_TUNABLEIF) {
2980 		rc = SEPOL_ERR;
2981 		cil_log(CIL_ERR, "Conditional statements must be a direct child of a tunableif or booleanif statement.\n");
2982 		goto exit;
2983 	}
2984 
2985 	ast_node->flavor = CIL_CONDBLOCK;
2986 
2987 	cil_condblock_init(&cb);
2988 	cb->flavor = flavor;
2989 
2990 	ast_node->data = cb;
2991 
2992 	return SEPOL_OK;
2993 
2994 exit:
2995 	cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration",
2996 		(char*)parse_current->data);
2997 	cil_destroy_condblock(cb);
2998 	return rc;
2999 }
3000 
cil_destroy_condblock(struct cil_condblock * cb)3001 void cil_destroy_condblock(struct cil_condblock *cb)
3002 {
3003 	if (cb == NULL) {
3004 		return;
3005 	}
3006 
3007 	cil_symtab_array_destroy(cb->symtab);
3008 	free(cb);
3009 }
3010 
cil_gen_alias(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3011 int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3012 {
3013 	enum cil_syntax syntax[] = {
3014 		CIL_SYN_STRING,
3015 		CIL_SYN_STRING,
3016 		CIL_SYN_END
3017 	};
3018 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3019 	char *key = NULL;
3020 	struct cil_alias *alias = NULL;
3021 	enum cil_sym_index sym_index;
3022 	int rc = SEPOL_ERR;
3023 
3024 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3025 		goto exit;
3026 	}
3027 
3028 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3029 	if (rc != SEPOL_OK) {
3030 		goto exit;
3031 	}
3032 
3033 	if (flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) {
3034 		cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
3035 		rc = SEPOL_ERR;
3036 		goto exit;
3037 	}
3038 
3039 	cil_alias_init(&alias);
3040 
3041 	key = parse_current->next->data;
3042 
3043 	rc = cil_flavor_to_symtab_index(flavor, &sym_index);
3044 	if (rc != SEPOL_OK) {
3045 		goto exit;
3046 	}
3047 
3048 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)alias, (hashtab_key_t)key, sym_index, flavor);
3049 	if (rc != SEPOL_OK) {
3050 		goto exit;
3051 	}
3052 
3053 	return SEPOL_OK;
3054 
3055 exit:
3056 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data);
3057 	cil_destroy_alias(alias);
3058 	cil_clear_node(ast_node);
3059 	return rc;
3060 }
3061 
cil_destroy_alias(struct cil_alias * alias)3062 void cil_destroy_alias(struct cil_alias *alias)
3063 {
3064 	if (alias == NULL) {
3065 		return;
3066 	}
3067 
3068 	cil_symtab_datum_destroy(&alias->datum);
3069 	alias->actual = NULL;
3070 
3071 	free(alias);
3072 }
3073 
cil_gen_aliasactual(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3074 int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3075 {
3076 	int rc = SEPOL_ERR;
3077 	enum cil_syntax syntax[] = {
3078 		CIL_SYN_STRING,
3079 		CIL_SYN_STRING,
3080 		CIL_SYN_STRING,
3081 		CIL_SYN_END
3082 	};
3083 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3084 	struct cil_aliasactual *aliasactual = NULL;
3085 
3086 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3087 		goto exit;
3088 	}
3089 
3090 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3091 	if (rc != SEPOL_OK) {
3092 		goto exit;
3093 	}
3094 
3095 	if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) {
3096 		cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF);
3097 		rc = SEPOL_ERR;
3098 		goto exit;
3099 	}
3100 
3101 	cil_aliasactual_init(&aliasactual);
3102 
3103 	aliasactual->alias_str = parse_current->next->data;
3104 
3105 	aliasactual->actual_str = parse_current->next->next->data;
3106 
3107 	ast_node->data = aliasactual;
3108 	ast_node->flavor = flavor;
3109 
3110 	return SEPOL_OK;
3111 
3112 exit:
3113 	cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current));
3114 	cil_clear_node(ast_node);
3115 	return rc;
3116 }
3117 
cil_destroy_aliasactual(struct cil_aliasactual * aliasactual)3118 void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual)
3119 {
3120 	if (aliasactual == NULL) {
3121 		return;
3122 	}
3123 
3124 	free(aliasactual);
3125 }
3126 
cil_gen_typeattributeset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3127 int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3128 {
3129 	enum cil_syntax syntax[] = {
3130 		CIL_SYN_STRING,
3131 		CIL_SYN_STRING,
3132 		CIL_SYN_STRING | CIL_SYN_LIST,
3133 		CIL_SYN_END
3134 	};
3135 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3136 	struct cil_typeattributeset *attrset = NULL;
3137 	int rc = SEPOL_ERR;
3138 
3139 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3140 		goto exit;
3141 	}
3142 
3143 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3144 	if (rc != SEPOL_OK) {
3145 		goto exit;
3146 	}
3147 
3148 	cil_typeattributeset_init(&attrset);
3149 
3150 	attrset->attr_str = parse_current->next->data;
3151 
3152 	rc = cil_gen_expr(parse_current->next->next, CIL_TYPE, &attrset->str_expr);
3153 	if (rc != SEPOL_OK) {
3154 		goto exit;
3155 	}
3156 	ast_node->data = attrset;
3157 	ast_node->flavor = CIL_TYPEATTRIBUTESET;
3158 
3159 	return SEPOL_OK;
3160 
3161 exit:
3162 	cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement");
3163 	cil_destroy_typeattributeset(attrset);
3164 	return rc;
3165 }
3166 
cil_destroy_typeattributeset(struct cil_typeattributeset * attrset)3167 void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset)
3168 {
3169 	if (attrset == NULL) {
3170 		return;
3171 	}
3172 
3173 	cil_list_destroy(&attrset->str_expr, CIL_TRUE);
3174 	cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
3175 
3176 	free(attrset);
3177 }
3178 
cil_gen_expandtypeattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3179 int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3180 {
3181 	enum cil_syntax syntax[] = {
3182 		CIL_SYN_STRING,
3183 		CIL_SYN_STRING | CIL_SYN_LIST,
3184 		CIL_SYN_STRING,
3185 		CIL_SYN_END
3186 	};
3187 	char *expand_str;
3188 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3189 	struct cil_expandtypeattribute *expandattr = NULL;
3190 	int rc = SEPOL_ERR;
3191 
3192 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3193 		goto exit;
3194 	}
3195 
3196 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3197 	if (rc != SEPOL_OK) {
3198 		goto exit;
3199 	}
3200 
3201 	cil_expandtypeattribute_init(&expandattr);
3202 
3203 	if (parse_current->next->cl_head == NULL) {
3204 		cil_list_init(&expandattr->attr_strs, CIL_TYPE);
3205 		cil_list_append(expandattr->attr_strs, CIL_STRING, parse_current->next->data);
3206 	} else {
3207 		rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE, &expandattr->attr_strs);
3208 		if (rc != SEPOL_OK) {
3209 			goto exit;
3210 		}
3211 	}
3212 
3213 	expand_str = parse_current->next->next->data;
3214 
3215 	if (expand_str == CIL_KEY_CONDTRUE) {
3216 		expandattr->expand = CIL_TRUE;
3217 	} else if (expand_str == CIL_KEY_CONDFALSE) {
3218 		expandattr->expand = CIL_FALSE;
3219 	} else {
3220 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
3221 		goto exit;
3222 	}
3223 
3224 	ast_node->data = expandattr;
3225 	ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE;
3226 
3227 	return SEPOL_OK;
3228 
3229 exit:
3230 	cil_tree_log(parse_current, CIL_ERR, "Bad expandtypeattribute statement");
3231 	cil_destroy_expandtypeattribute(expandattr);
3232 	return rc;
3233 }
3234 
cil_destroy_expandtypeattribute(struct cil_expandtypeattribute * expandattr)3235 void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr)
3236 {
3237 	if (expandattr == NULL) {
3238 		return;
3239 	}
3240 
3241 	cil_list_destroy(&expandattr->attr_strs, CIL_TRUE);
3242 
3243 	cil_list_destroy(&expandattr->attr_datums, CIL_FALSE);
3244 
3245 	free(expandattr);
3246 }
3247 
cil_gen_typepermissive(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3248 int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3249 {
3250 	enum cil_syntax syntax[] = {
3251 		CIL_SYN_STRING,
3252 		CIL_SYN_STRING,
3253 		CIL_SYN_END
3254 	};
3255 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3256 	struct cil_typepermissive *typeperm = NULL;
3257 	int rc = SEPOL_ERR;
3258 
3259 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3260 		goto exit;
3261 	}
3262 
3263 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3264 	if (rc != SEPOL_OK) {
3265 		goto exit;
3266 	}
3267 
3268 	cil_typepermissive_init(&typeperm);
3269 
3270 	typeperm->type_str = parse_current->next->data;
3271 
3272 	ast_node->data = typeperm;
3273 	ast_node->flavor = CIL_TYPEPERMISSIVE;
3274 
3275 	return SEPOL_OK;
3276 
3277 exit:
3278 	cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration");
3279 	cil_destroy_typepermissive(typeperm);
3280 	return rc;
3281 }
3282 
cil_destroy_typepermissive(struct cil_typepermissive * typeperm)3283 void cil_destroy_typepermissive(struct cil_typepermissive *typeperm)
3284 {
3285 	if (typeperm == NULL) {
3286 		return;
3287 	}
3288 
3289 	free(typeperm);
3290 }
3291 
cil_gen_typetransition(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3292 int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3293 {
3294 	int rc = SEPOL_ERR;
3295 	enum cil_syntax syntax[] = {
3296 		CIL_SYN_STRING,
3297 		CIL_SYN_STRING,
3298 		CIL_SYN_STRING,
3299 		CIL_SYN_STRING,
3300 		CIL_SYN_STRING,
3301 		CIL_SYN_STRING | CIL_SYN_END,
3302 		CIL_SYN_END
3303 	};
3304 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3305 	char *s1, *s2, *s3, *s4, *s5;
3306 
3307 	if (db == NULL || parse_current == NULL || ast_node == NULL ) {
3308 		goto exit;
3309 	}
3310 
3311 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3312 	if (rc != SEPOL_OK) {
3313 		goto exit;
3314 	}
3315 
3316 	s1 = parse_current->next->data;
3317 	s2 = parse_current->next->next->data;
3318 	s3 = parse_current->next->next->next->data;
3319 	s4 = parse_current->next->next->next->next->data;
3320 	s5 = NULL;
3321 
3322 	if (parse_current->next->next->next->next->next) {
3323 		if (s4 == CIL_KEY_STAR) {
3324 			s4 = parse_current->next->next->next->next->next->data;
3325 		} else {
3326 			s5 = parse_current->next->next->next->next->next->data;
3327 		}
3328 	}
3329 
3330 	if (s5) {
3331 		struct cil_nametypetransition *nametypetrans = NULL;
3332 
3333 		cil_nametypetransition_init(&nametypetrans);
3334 
3335 		nametypetrans->src_str = s1;
3336 		nametypetrans->tgt_str = s2;
3337 		nametypetrans->obj_str = s3;
3338 		nametypetrans->result_str = s5;
3339 		nametypetrans->name_str = s4;
3340 
3341 		ast_node->data = nametypetrans;
3342 		ast_node->flavor = CIL_NAMETYPETRANSITION;
3343 	} else {
3344 		struct cil_type_rule *rule = NULL;
3345 
3346 		cil_type_rule_init(&rule);
3347 
3348 		rule->rule_kind = CIL_TYPE_TRANSITION;
3349 		rule->src_str = s1;
3350 		rule->tgt_str = s2;
3351 		rule->obj_str = s3;
3352 		rule->result_str = s4;
3353 
3354 		ast_node->data = rule;
3355 		ast_node->flavor = CIL_TYPE_RULE;
3356 	}
3357 
3358 	return SEPOL_OK;
3359 
3360 exit:
3361 	cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration");
3362 	return rc;
3363 }
3364 
cil_destroy_name(struct cil_name * name)3365 void cil_destroy_name(struct cil_name *name)
3366 {
3367 	if (name == NULL) {
3368 		return;
3369 	}
3370 
3371 	cil_symtab_datum_destroy(&name->datum);
3372 	free(name);
3373 }
3374 
cil_destroy_typetransition(struct cil_nametypetransition * nametypetrans)3375 void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans)
3376 {
3377 	if (nametypetrans == NULL) {
3378 		return;
3379 	}
3380 
3381 	free(nametypetrans);
3382 }
3383 
cil_gen_rangetransition(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3384 int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3385 {
3386 	enum cil_syntax syntax[] = {
3387 		CIL_SYN_STRING,
3388 		CIL_SYN_STRING,
3389 		CIL_SYN_STRING,
3390 		CIL_SYN_STRING,
3391 		CIL_SYN_STRING | CIL_SYN_LIST,
3392 		CIL_SYN_END
3393 	};
3394 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3395 	struct cil_rangetransition *rangetrans = NULL;
3396 	int rc = SEPOL_ERR;
3397 
3398 	if (db == NULL || parse_current == NULL || ast_node == NULL ) {
3399 		goto exit;
3400 	}
3401 
3402 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3403 	if (rc != SEPOL_OK) {
3404 		goto exit;
3405 	}
3406 
3407 	cil_rangetransition_init(&rangetrans);
3408 
3409 	rangetrans->src_str = parse_current->next->data;
3410 	rangetrans->exec_str = parse_current->next->next->data;
3411 	rangetrans->obj_str = parse_current->next->next->next->data;
3412 
3413 	rangetrans->range_str = NULL;
3414 
3415 	if (parse_current->next->next->next->next->cl_head == NULL) {
3416 		rangetrans->range_str = parse_current->next->next->next->next->data;
3417 	} else {
3418 		cil_levelrange_init(&rangetrans->range);
3419 
3420 		rc = cil_fill_levelrange(parse_current->next->next->next->next->cl_head, rangetrans->range);
3421 		if (rc != SEPOL_OK) {
3422 			goto exit;
3423 		}
3424 	}
3425 
3426 	ast_node->data = rangetrans;
3427 	ast_node->flavor = CIL_RANGETRANSITION;
3428 
3429 	return SEPOL_OK;
3430 
3431 exit:
3432 	cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration");
3433 	cil_destroy_rangetransition(rangetrans);
3434 	return rc;
3435 }
3436 
cil_destroy_rangetransition(struct cil_rangetransition * rangetrans)3437 void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans)
3438 {
3439 	if (rangetrans == NULL) {
3440 		return;
3441 	}
3442 
3443 	if (rangetrans->range_str == NULL && rangetrans->range != NULL) {
3444 		cil_destroy_levelrange(rangetrans->range);
3445 	}
3446 
3447 	free(rangetrans);
3448 }
3449 
cil_gen_sensitivity(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3450 int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3451 {
3452 	enum cil_syntax syntax[] = {
3453 		CIL_SYN_STRING,
3454 		CIL_SYN_STRING,
3455 		CIL_SYN_END
3456 	};
3457 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3458 	char *key = NULL;
3459 	struct cil_sens *sens = NULL;
3460 	int rc = SEPOL_ERR;
3461 
3462 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3463 		goto exit;
3464 	}
3465 
3466 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3467 	if (rc != SEPOL_OK) {
3468 		goto exit;
3469 	}
3470 
3471 	cil_sens_init(&sens);
3472 
3473 	key = parse_current->next->data;
3474 
3475 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sens, (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS);
3476 	if (rc != SEPOL_OK) {
3477 		goto exit;
3478 	}
3479 
3480 	return SEPOL_OK;
3481 
3482 exit:
3483 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration");
3484 	cil_destroy_sensitivity(sens);
3485 	cil_clear_node(ast_node);
3486 	return rc;
3487 }
3488 
cil_destroy_sensitivity(struct cil_sens * sens)3489 void cil_destroy_sensitivity(struct cil_sens *sens)
3490 {
3491 	if (sens == NULL) {
3492 		return;
3493 	}
3494 
3495 	cil_symtab_datum_destroy(&sens->datum);
3496 
3497 	cil_list_destroy(&sens->cats_list, CIL_FALSE);
3498 
3499 	free(sens);
3500 }
3501 
cil_gen_category(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3502 int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3503 {
3504 	enum cil_syntax syntax[] = {
3505 		CIL_SYN_STRING,
3506 		CIL_SYN_STRING,
3507 		CIL_SYN_END
3508 	};
3509 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3510 	char *key = NULL;
3511 	struct cil_cat *cat = NULL;
3512 	int rc = SEPOL_ERR;
3513 
3514 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3515 		goto exit;
3516 	}
3517 
3518 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3519 	if (rc != SEPOL_OK) {
3520 		goto exit;
3521 	}
3522 
3523 	cil_cat_init(&cat);
3524 
3525 	key = parse_current->next->data;
3526 
3527 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cat, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT);
3528 	if (rc != SEPOL_OK) {
3529 		goto exit;
3530 	}
3531 
3532 	return SEPOL_OK;
3533 
3534 exit:
3535 	cil_tree_log(parse_current, CIL_ERR, "Bad category declaration");
3536 	cil_destroy_category(cat);
3537 	cil_clear_node(ast_node);
3538 	return rc;
3539 }
3540 
cil_destroy_category(struct cil_cat * cat)3541 void cil_destroy_category(struct cil_cat *cat)
3542 {
3543 	if (cat == NULL) {
3544 		return;
3545 	}
3546 
3547 	cil_symtab_datum_destroy(&cat->datum);
3548 	free(cat);
3549 }
3550 
cil_gen_catset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3551 int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3552 {
3553 	enum cil_syntax syntax[] = {
3554 		CIL_SYN_STRING,
3555 		CIL_SYN_STRING,
3556 		CIL_SYN_LIST,
3557 		CIL_SYN_END
3558 	};
3559 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3560 	char *key = NULL;
3561 	struct cil_catset *catset = NULL;
3562 	int rc = SEPOL_ERR;
3563 
3564 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3565 		goto exit;
3566 	}
3567 
3568 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3569 	if (rc != SEPOL_OK) {
3570 		goto exit;
3571 	}
3572 
3573 	cil_catset_init(&catset);
3574 
3575 	key = parse_current->next->data;
3576 
3577 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)catset, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET);
3578 	if (rc != SEPOL_OK) {
3579 		goto exit;
3580 	}
3581 
3582 	rc = cil_fill_cats(parse_current->next->next, &catset->cats);
3583 	if (rc != SEPOL_OK) {
3584 		goto exit;
3585 	}
3586 
3587 	return SEPOL_OK;
3588 
3589 exit:
3590 	cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration");
3591 	cil_destroy_catset(catset);
3592 	cil_clear_node(ast_node);
3593 	return rc;
3594 }
3595 
cil_destroy_catset(struct cil_catset * catset)3596 void cil_destroy_catset(struct cil_catset *catset)
3597 {
3598 	if (catset == NULL) {
3599 		return;
3600 	}
3601 
3602 	cil_symtab_datum_destroy(&catset->datum);
3603 
3604 	cil_destroy_cats(catset->cats);
3605 
3606 	free(catset);
3607 }
3608 
cil_gen_catorder(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3609 int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3610 {
3611 	enum cil_syntax syntax[] = {
3612 		CIL_SYN_STRING,
3613 		CIL_SYN_LIST,
3614 		CIL_SYN_END
3615 	};
3616 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3617 	struct cil_catorder *catorder = NULL;
3618 	struct cil_list_item *curr = NULL;
3619 	int rc = SEPOL_ERR;
3620 
3621 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3622 		goto exit;
3623 	}
3624 
3625 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3626 	if (rc !=  SEPOL_OK) {
3627 		goto exit;
3628 	}
3629 
3630 	cil_catorder_init(&catorder);
3631 
3632 	rc = cil_fill_list(parse_current->next->cl_head, CIL_CATORDER, &catorder->cat_list_str);
3633 	if (rc != SEPOL_OK) {
3634 		goto exit;
3635 	}
3636 
3637 	cil_list_for_each(curr, catorder->cat_list_str) {
3638 		if (curr->data == CIL_KEY_UNORDERED) {
3639 			cil_log(CIL_ERR, "Category order cannot be unordered.\n");
3640 			rc = SEPOL_ERR;
3641 			goto exit;
3642 		}
3643 	}
3644 
3645 	ast_node->data = catorder;
3646 	ast_node->flavor = CIL_CATORDER;
3647 
3648 	return SEPOL_OK;
3649 
3650 exit:
3651 	cil_tree_log(parse_current, CIL_ERR, "Bad categoryorder declaration");
3652 	cil_destroy_catorder(catorder);
3653 	return rc;
3654 }
3655 
cil_destroy_catorder(struct cil_catorder * catorder)3656 void cil_destroy_catorder(struct cil_catorder *catorder)
3657 {
3658 	if (catorder == NULL) {
3659 		return;
3660 	}
3661 
3662 	if (catorder->cat_list_str != NULL) {
3663 		cil_list_destroy(&catorder->cat_list_str, 1);
3664 	}
3665 
3666 	free(catorder);
3667 }
3668 
cil_gen_sensitivityorder(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3669 int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3670 {
3671 	enum cil_syntax syntax[] = {
3672 		CIL_SYN_STRING,
3673 		CIL_SYN_LIST,
3674 		CIL_SYN_END
3675 	};
3676 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3677 	struct cil_sensorder *sensorder = NULL;
3678 	struct cil_list_item *curr = NULL;
3679 	int rc = SEPOL_ERR;
3680 
3681 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3682 		goto exit;
3683 	}
3684 
3685 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3686 	if (rc != SEPOL_OK) {
3687 		goto exit;
3688 	}
3689 
3690 	cil_sensorder_init(&sensorder);
3691 
3692 	rc = cil_fill_list(parse_current->next->cl_head, CIL_SENSITIVITYORDER, &sensorder->sens_list_str);
3693 	if (rc != SEPOL_OK) {
3694 		goto exit;
3695 	}
3696 
3697 	cil_list_for_each(curr, sensorder->sens_list_str) {
3698 		if (curr->data == CIL_KEY_UNORDERED) {
3699 			cil_log(CIL_ERR, "Sensitivy order cannot be unordered.\n");
3700 			rc = SEPOL_ERR;
3701 			goto exit;
3702 		}
3703 	}
3704 
3705 	ast_node->data = sensorder;
3706 	ast_node->flavor = CIL_SENSITIVITYORDER;
3707 
3708 	return SEPOL_OK;
3709 
3710 exit:
3711 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivityorder declaration");
3712 	cil_destroy_sensitivityorder(sensorder);
3713 	return rc;
3714 }
3715 
cil_destroy_sensitivityorder(struct cil_sensorder * sensorder)3716 void cil_destroy_sensitivityorder(struct cil_sensorder *sensorder)
3717 {
3718 	if (sensorder == NULL) {
3719 		return;
3720 	}
3721 
3722 	if (sensorder->sens_list_str != NULL) {
3723 		cil_list_destroy(&sensorder->sens_list_str, CIL_TRUE);
3724 	}
3725 
3726 	free(sensorder);
3727 }
3728 
cil_gen_senscat(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3729 int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3730 {
3731 	enum cil_syntax syntax[] = {
3732 		CIL_SYN_STRING,
3733 		CIL_SYN_STRING,
3734 		CIL_SYN_STRING | CIL_SYN_LIST,
3735 		CIL_SYN_END
3736 	};
3737 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3738 	struct cil_senscat *senscat = NULL;
3739 	int rc = SEPOL_ERR;
3740 
3741 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3742 		goto exit;
3743 	}
3744 
3745 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3746 	if (rc != SEPOL_OK) {
3747 		goto exit;
3748 	}
3749 
3750 	cil_senscat_init(&senscat);
3751 
3752 	senscat->sens_str = parse_current->next->data;
3753 
3754 	rc = cil_fill_cats(parse_current->next->next, &senscat->cats);
3755 	if (rc != SEPOL_OK) {
3756 		goto exit;
3757 	}
3758 
3759 	ast_node->data = senscat;
3760 	ast_node->flavor = CIL_SENSCAT;
3761 
3762 	return SEPOL_OK;
3763 
3764 exit:
3765 	cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration");
3766 	cil_destroy_senscat(senscat);
3767 	return rc;
3768 }
3769 
cil_destroy_senscat(struct cil_senscat * senscat)3770 void cil_destroy_senscat(struct cil_senscat *senscat)
3771 {
3772 	if (senscat == NULL) {
3773 		return;
3774 	}
3775 
3776 	cil_destroy_cats(senscat->cats);
3777 
3778 	free(senscat);
3779 }
3780 
cil_gen_level(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3781 int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3782 {
3783 	enum cil_syntax syntax[] = {
3784 		CIL_SYN_STRING,
3785 		CIL_SYN_STRING,
3786 		CIL_SYN_LIST,
3787 		CIL_SYN_END
3788 	};
3789 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3790 	char *key = NULL;
3791 	struct cil_level *level = NULL;
3792 	int rc = SEPOL_ERR;
3793 
3794 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3795 		goto exit;
3796 	}
3797 
3798 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3799 	if (rc != SEPOL_OK) {
3800 		goto exit;
3801 	}
3802 
3803 	cil_level_init(&level);
3804 
3805 	key = parse_current->next->data;
3806 
3807 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)level, (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL);
3808 	if (rc != SEPOL_OK) {
3809 		goto exit;
3810 	}
3811 
3812 	rc = cil_fill_level(parse_current->next->next->cl_head, level);
3813 	if (rc != SEPOL_OK) {
3814 		goto exit;
3815 	}
3816 
3817 	return SEPOL_OK;
3818 
3819 exit:
3820 	cil_tree_log(parse_current, CIL_ERR, "Bad level declaration");
3821 	cil_destroy_level(level);
3822 	cil_clear_node(ast_node);
3823 	return rc;
3824 }
3825 
cil_destroy_level(struct cil_level * level)3826 void cil_destroy_level(struct cil_level *level)
3827 {
3828 	if (level == NULL) {
3829 		return;
3830 	}
3831 
3832 	cil_symtab_datum_destroy(&level->datum);
3833 
3834 	cil_destroy_cats(level->cats);
3835 
3836 	free(level);
3837 }
3838 
3839 /* 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)3840 int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange)
3841 {
3842 	enum cil_syntax syntax[] = {
3843 		CIL_SYN_STRING | CIL_SYN_LIST,
3844 		CIL_SYN_STRING | CIL_SYN_LIST,
3845 		CIL_SYN_END
3846 	};
3847 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3848 	int rc = SEPOL_ERR;
3849 
3850 	if (low == NULL || lvlrange == NULL) {
3851 		goto exit;
3852 	}
3853 
3854 	rc = __cil_verify_syntax(low, syntax, syntax_len);
3855 	if (rc != SEPOL_OK) {
3856 
3857 		goto exit;
3858 	}
3859 
3860 	if (low->cl_head == NULL) {
3861 		lvlrange->low_str = low->data;
3862 	} else {
3863 		cil_level_init(&lvlrange->low);
3864 		rc = cil_fill_level(low->cl_head, lvlrange->low);
3865 		if (rc != SEPOL_OK) {
3866 			goto exit;
3867 		}
3868 	}
3869 
3870 	if (low->next->cl_head == NULL) {
3871 		lvlrange->high_str = low->next->data;
3872 	} else {
3873 		cil_level_init(&lvlrange->high);
3874 		rc = cil_fill_level(low->next->cl_head, lvlrange->high);
3875 		if (rc != SEPOL_OK) {
3876 			goto exit;
3877 		}
3878 	}
3879 
3880 	return SEPOL_OK;
3881 
3882 exit:
3883 	cil_log(CIL_ERR, "Bad levelrange\n");
3884 	return rc;
3885 }
3886 
cil_gen_levelrange(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3887 int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3888 {
3889 	enum cil_syntax syntax[] = {
3890 		CIL_SYN_STRING,
3891 		CIL_SYN_STRING,
3892 		CIL_SYN_LIST,
3893 		CIL_SYN_END
3894 	};
3895 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3896 	char *key = NULL;
3897 	struct cil_levelrange *lvlrange = NULL;
3898 	int rc = SEPOL_ERR;
3899 
3900 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3901 		goto exit;
3902 	}
3903 
3904 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3905 	if (rc != SEPOL_OK) {
3906 		goto exit;
3907 	}
3908 
3909 	cil_levelrange_init(&lvlrange);
3910 
3911 	key = parse_current->next->data;
3912 
3913 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)lvlrange, (hashtab_key_t)key, CIL_SYM_LEVELRANGES, CIL_LEVELRANGE);
3914 	if (rc != SEPOL_OK) {
3915 		goto exit;
3916 	}
3917 
3918 	rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange);
3919 	if (rc != SEPOL_OK) {
3920 		goto exit;
3921 	}
3922 
3923 	return SEPOL_OK;
3924 
3925 exit:
3926 	cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration");
3927 	cil_destroy_levelrange(lvlrange);
3928 	cil_clear_node(ast_node);
3929 	return rc;
3930 }
3931 
cil_destroy_levelrange(struct cil_levelrange * lvlrange)3932 void cil_destroy_levelrange(struct cil_levelrange *lvlrange)
3933 {
3934 	if (lvlrange == NULL) {
3935 		return;
3936 	}
3937 
3938 	cil_symtab_datum_destroy(&lvlrange->datum);
3939 
3940 	if (lvlrange->low_str == NULL) {
3941 		cil_destroy_level(lvlrange->low);
3942 	}
3943 
3944 	if (lvlrange->high_str == NULL) {
3945 		cil_destroy_level(lvlrange->high);
3946 	}
3947 
3948 	free(lvlrange);
3949 }
3950 
cil_gen_constrain(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3951 int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3952 {
3953 	enum cil_syntax syntax[] = {
3954 		CIL_SYN_STRING,
3955 		CIL_SYN_STRING | CIL_SYN_LIST,
3956 		CIL_SYN_LIST,
3957 		CIL_SYN_END
3958 	};
3959 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
3960 	struct cil_constrain *cons = NULL;
3961 	int rc = SEPOL_ERR;
3962 
3963 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
3964 		goto exit;
3965 	}
3966 
3967 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3968 	if (rc != SEPOL_OK) {
3969 		goto exit;
3970 	}
3971 
3972 	cil_constrain_init(&cons);
3973 
3974 	rc = cil_fill_classperms_list(parse_current->next, &cons->classperms);
3975 	if (rc != SEPOL_OK) {
3976 		goto exit;
3977 	}
3978 
3979 	rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &cons->str_expr);
3980 	if (rc != SEPOL_OK) {
3981 		goto exit;
3982 	}
3983 
3984 	ast_node->data = cons;
3985 	ast_node->flavor = flavor;
3986 
3987 	return SEPOL_OK;
3988 
3989 exit:
3990 	cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration");
3991 	cil_destroy_constrain(cons);
3992 	return rc;
3993 }
3994 
cil_destroy_constrain(struct cil_constrain * cons)3995 void cil_destroy_constrain(struct cil_constrain *cons)
3996 {
3997 	if (cons == NULL) {
3998 		return;
3999 	}
4000 
4001 	cil_destroy_classperms_list(&cons->classperms);
4002 	cil_list_destroy(&cons->str_expr, CIL_TRUE);
4003 	cil_list_destroy(&cons->datum_expr, CIL_FALSE);
4004 
4005 	free(cons);
4006 }
4007 
cil_gen_validatetrans(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)4008 int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
4009 {
4010 	enum cil_syntax syntax[] = {
4011 		CIL_SYN_STRING,
4012 		CIL_SYN_STRING,
4013 		CIL_SYN_LIST,
4014 		CIL_SYN_END
4015 	};
4016 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4017 	struct cil_validatetrans *validtrans = NULL;
4018 	int rc = SEPOL_ERR;
4019 
4020 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4021 		goto exit;
4022 	}
4023 
4024 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4025 	if (rc != SEPOL_OK) {
4026 		goto exit;
4027 	}
4028 
4029 	cil_validatetrans_init(&validtrans);
4030 
4031 	validtrans->class_str = parse_current->next->data;
4032 
4033 	rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &validtrans->str_expr);
4034 	if (rc != SEPOL_OK) {
4035 		goto exit;
4036 	}
4037 
4038 	ast_node->data = validtrans;
4039 	ast_node->flavor = flavor;
4040 
4041 	return SEPOL_OK;
4042 
4043 exit:
4044 	cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration");
4045 	cil_destroy_validatetrans(validtrans);
4046 	return rc;
4047 
4048 
4049 }
4050 
cil_destroy_validatetrans(struct cil_validatetrans * validtrans)4051 void cil_destroy_validatetrans(struct cil_validatetrans *validtrans)
4052 {
4053 	if (validtrans == NULL) {
4054 		return;
4055 	}
4056 
4057 	cil_list_destroy(&validtrans->str_expr, CIL_TRUE);
4058 	cil_list_destroy(&validtrans->datum_expr, CIL_FALSE);
4059 
4060 	free(validtrans);
4061 }
4062 
4063 /* Fills in context starting from user */
cil_fill_context(struct cil_tree_node * user_node,struct cil_context * context)4064 int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context)
4065 {
4066 	enum cil_syntax syntax[] = {
4067 		CIL_SYN_STRING,
4068 		CIL_SYN_STRING,
4069 		CIL_SYN_STRING,
4070 		CIL_SYN_STRING | CIL_SYN_LIST,
4071 		CIL_SYN_END
4072 	};
4073 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4074 	int rc = SEPOL_ERR;
4075 
4076 	if (user_node == NULL || context == NULL) {
4077 		goto exit;
4078 	}
4079 
4080 	rc = __cil_verify_syntax(user_node, syntax, syntax_len);
4081 	if (rc != SEPOL_OK) {
4082 		goto exit;
4083 	}
4084 
4085 	context->user_str = user_node->data;
4086 	context->role_str = user_node->next->data;
4087 	context->type_str = user_node->next->next->data;
4088 
4089 	context->range_str = NULL;
4090 
4091 	if (user_node->next->next->next->cl_head == NULL) {
4092 		context->range_str = user_node->next->next->next->data;
4093 	} else {
4094 		cil_levelrange_init(&context->range);
4095 
4096 		rc = cil_fill_levelrange(user_node->next->next->next->cl_head, context->range);
4097 		if (rc != SEPOL_OK) {
4098 			goto exit;
4099 		}
4100 	}
4101 
4102 	return SEPOL_OK;
4103 
4104 exit:
4105 	cil_log(CIL_ERR, "Bad context\n");
4106 	return rc;
4107 }
4108 
cil_gen_context(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4109 int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4110 {
4111 	enum cil_syntax syntax[] = {
4112 		CIL_SYN_STRING,
4113 		CIL_SYN_STRING,
4114 		CIL_SYN_LIST,
4115 		CIL_SYN_END
4116 	};
4117 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4118 	char *key = NULL;
4119 	struct cil_context *context = NULL;
4120 	int rc = SEPOL_ERR;
4121 
4122 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4123 		goto exit;
4124 	}
4125 
4126 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4127 	if (rc != SEPOL_OK) {
4128 		goto exit;
4129 	}
4130 
4131 	cil_context_init(&context);
4132 
4133 	key = parse_current->next->data;
4134 
4135 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)context, (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT);
4136 	if (rc != SEPOL_OK) {
4137 		goto exit;
4138 	}
4139 
4140 	rc = cil_fill_context(parse_current->next->next->cl_head, context);
4141 	if (rc != SEPOL_OK) {
4142 		goto exit;
4143 	}
4144 
4145 	return SEPOL_OK;
4146 
4147 exit:
4148 	cil_tree_log(parse_current, CIL_ERR, "Bad context declaration");
4149 	cil_destroy_context(context);
4150 	cil_clear_node(ast_node);
4151 	return SEPOL_ERR;
4152 }
4153 
cil_destroy_context(struct cil_context * context)4154 void cil_destroy_context(struct cil_context *context)
4155 {
4156 	if (context == NULL) {
4157 		return;
4158 	}
4159 
4160 	cil_symtab_datum_destroy(&context->datum);;
4161 
4162 	if (context->range_str == NULL && context->range != NULL) {
4163 		cil_destroy_levelrange(context->range);
4164 	}
4165 
4166 	free(context);
4167 }
4168 
cil_gen_filecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4169 int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4170 {
4171 	enum cil_syntax syntax[] = {
4172 		CIL_SYN_STRING,
4173 		CIL_SYN_STRING,
4174 		CIL_SYN_STRING,
4175 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
4176 		CIL_SYN_END
4177 	};
4178 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4179 	int rc = SEPOL_ERR;
4180 	struct cil_filecon *filecon = NULL;
4181 	char *type = NULL;
4182 
4183 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4184 		goto exit;
4185 	}
4186 
4187 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4188 	if (rc != SEPOL_OK) {
4189 		goto exit;
4190 	}
4191 
4192 	type = parse_current->next->next->data;
4193 	cil_filecon_init(&filecon);
4194 
4195 	filecon->path_str = parse_current->next->data;
4196 
4197 	if (type == CIL_KEY_FILE) {
4198 		filecon->type = CIL_FILECON_FILE;
4199 	} else if (type == CIL_KEY_DIR) {
4200 		filecon->type = CIL_FILECON_DIR;
4201 	} else if (type == CIL_KEY_CHAR) {
4202 		filecon->type = CIL_FILECON_CHAR;
4203 	} else if (type == CIL_KEY_BLOCK) {
4204 		filecon->type = CIL_FILECON_BLOCK;
4205 	} else if (type == CIL_KEY_SOCKET) {
4206 		filecon->type = CIL_FILECON_SOCKET;
4207 	} else if (type == CIL_KEY_PIPE) {
4208 		filecon->type = CIL_FILECON_PIPE;
4209 	} else if (type == CIL_KEY_SYMLINK) {
4210 		filecon->type = CIL_FILECON_SYMLINK;
4211 	} else if (type == CIL_KEY_ANY) {
4212 		filecon->type = CIL_FILECON_ANY;
4213 	} else {
4214 		cil_log(CIL_ERR, "Invalid file type\n");
4215 		rc = SEPOL_ERR;
4216 		goto exit;
4217 	}
4218 
4219 	if (parse_current->next->next->next->cl_head == NULL) {
4220 		filecon->context_str = parse_current->next->next->next->data;
4221 	} else {
4222 		if (parse_current->next->next->next->cl_head->next == NULL) {
4223 			filecon->context = NULL;
4224 		} else {
4225 			cil_context_init(&filecon->context);
4226 
4227 			rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context);
4228 			if (rc != SEPOL_OK) {
4229 				goto exit;
4230 			}
4231 		}
4232 	}
4233 
4234 	ast_node->data = filecon;
4235 	ast_node->flavor = CIL_FILECON;
4236 
4237 	return SEPOL_OK;
4238 
4239 exit:
4240 	cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration");
4241 	cil_destroy_filecon(filecon);
4242 	return rc;
4243 }
4244 
4245 //TODO: Should we be checking if the pointer is NULL when passed in?
cil_destroy_filecon(struct cil_filecon * filecon)4246 void cil_destroy_filecon(struct cil_filecon *filecon)
4247 {
4248 	if (filecon == NULL) {
4249 		return;
4250 	}
4251 
4252 	if (filecon->context_str == NULL && filecon->context != NULL) {
4253 		cil_destroy_context(filecon->context);
4254 	}
4255 
4256 	free(filecon);
4257 }
4258 
cil_gen_portcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4259 int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4260 {
4261 	enum cil_syntax syntax[] = {
4262 		CIL_SYN_STRING,
4263 		CIL_SYN_STRING,
4264 		CIL_SYN_STRING | CIL_SYN_LIST,
4265 		CIL_SYN_STRING | CIL_SYN_LIST,
4266 		CIL_SYN_END
4267 	};
4268 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4269 	int rc = SEPOL_ERR;
4270 	struct cil_portcon *portcon = NULL;
4271 	char *proto;
4272 
4273 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4274 		goto exit;
4275 	}
4276 
4277 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4278 	if (rc != SEPOL_OK) {
4279 		goto exit;
4280 	}
4281 
4282 	cil_portcon_init(&portcon);
4283 
4284 	proto = parse_current->next->data;
4285 	if (proto == CIL_KEY_UDP) {
4286 		portcon->proto = CIL_PROTOCOL_UDP;
4287 	} else if (proto == CIL_KEY_TCP) {
4288 		portcon->proto = CIL_PROTOCOL_TCP;
4289 	} else if (proto == CIL_KEY_DCCP) {
4290 		portcon->proto = CIL_PROTOCOL_DCCP;
4291 	} else {
4292 		cil_log(CIL_ERR, "Invalid protocol\n");
4293 		rc = SEPOL_ERR;
4294 		goto exit;
4295 	}
4296 
4297 	if (parse_current->next->next->cl_head != NULL) {
4298 		if (parse_current->next->next->cl_head->next != NULL
4299 		&& parse_current->next->next->cl_head->next->next == NULL) {
4300 			rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10);
4301 			if (rc != SEPOL_OK) {
4302 				cil_log(CIL_ERR, "Improper port specified\n");
4303 				goto exit;
4304 			}
4305 			rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10);
4306 			if (rc != SEPOL_OK) {
4307 				cil_log(CIL_ERR, "Improper port specified\n");
4308 				goto exit;
4309 			}
4310 		} else {
4311 			cil_log(CIL_ERR, "Improper port range specified\n");
4312 			rc = SEPOL_ERR;
4313 			goto exit;
4314 		}
4315 	} else {
4316 		rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10);
4317 		if (rc != SEPOL_OK) {
4318 			cil_log(CIL_ERR, "Improper port specified\n");
4319 			goto exit;
4320 		}
4321 		portcon->port_high = portcon->port_low;
4322 	}
4323 
4324 	if (parse_current->next->next->next->cl_head == NULL ) {
4325 		portcon->context_str = parse_current->next->next->next->data;
4326 	} else {
4327 		cil_context_init(&portcon->context);
4328 
4329 		rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context);
4330 		if (rc != SEPOL_OK) {
4331 			goto exit;
4332 		}
4333 	}
4334 
4335 	ast_node->data = portcon;
4336 	ast_node->flavor = CIL_PORTCON;
4337 
4338 	return SEPOL_OK;
4339 
4340 exit:
4341 	cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration");
4342 	cil_destroy_portcon(portcon);
4343 	return rc;
4344 }
4345 
cil_destroy_portcon(struct cil_portcon * portcon)4346 void cil_destroy_portcon(struct cil_portcon *portcon)
4347 {
4348 	if (portcon == NULL) {
4349 		return;
4350 	}
4351 
4352 	if (portcon->context_str == NULL && portcon->context != NULL) {
4353 		cil_destroy_context(portcon->context);
4354 	}
4355 
4356 	free(portcon);
4357 }
4358 
cil_gen_nodecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4359 int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4360 {
4361 	enum cil_syntax syntax[] = {
4362 		CIL_SYN_STRING,
4363 		CIL_SYN_STRING | CIL_SYN_LIST,
4364 		CIL_SYN_STRING | CIL_SYN_LIST,
4365 		CIL_SYN_STRING | CIL_SYN_LIST,
4366 		CIL_SYN_END
4367 	};
4368 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4369 	int rc = SEPOL_ERR;
4370 	struct cil_nodecon *nodecon = NULL;
4371 
4372 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4373 		goto exit;
4374 	}
4375 
4376 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4377 	if (rc != SEPOL_OK) {
4378 		goto exit;
4379 	}
4380 
4381 	cil_nodecon_init(&nodecon);
4382 
4383 	if (parse_current->next->cl_head == NULL ) {
4384 		nodecon->addr_str = parse_current->next->data;
4385 	} else {
4386 		cil_ipaddr_init(&nodecon->addr);
4387 
4388 		rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr);
4389 		if (rc != SEPOL_OK) {
4390 			goto exit;
4391 		}
4392 	}
4393 
4394 	if (parse_current->next->next->cl_head == NULL ) {
4395 		nodecon->mask_str = parse_current->next->next->data;
4396 	} else {
4397 		cil_ipaddr_init(&nodecon->mask);
4398 
4399 		rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask);
4400 		if (rc != SEPOL_OK) {
4401 			goto exit;
4402 		}
4403 	}
4404 
4405 	if (parse_current->next->next->next->cl_head == NULL ) {
4406 		nodecon->context_str = parse_current->next->next->next->data;
4407 	} else {
4408 		cil_context_init(&nodecon->context);
4409 
4410 		rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context);
4411 		if (rc != SEPOL_OK) {
4412 			goto exit;
4413 		}
4414 	}
4415 
4416 	ast_node->data = nodecon;
4417 	ast_node->flavor = CIL_NODECON;
4418 
4419 	return SEPOL_OK;
4420 
4421 exit:
4422 	cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration");
4423 	cil_destroy_nodecon(nodecon);
4424 	return rc;
4425 }
4426 
cil_destroy_nodecon(struct cil_nodecon * nodecon)4427 void cil_destroy_nodecon(struct cil_nodecon *nodecon)
4428 {
4429 	if (nodecon == NULL) {
4430 		return;
4431 	}
4432 
4433 	if (nodecon->addr_str == NULL && nodecon->addr != NULL) {
4434 		cil_destroy_ipaddr(nodecon->addr);
4435 	}
4436 
4437 	if (nodecon->mask_str == NULL && nodecon->mask != NULL) {
4438 		cil_destroy_ipaddr(nodecon->mask);
4439 	}
4440 
4441 	if (nodecon->context_str == NULL && nodecon->context != NULL) {
4442 		cil_destroy_context(nodecon->context);
4443 	}
4444 
4445 	free(nodecon);
4446 }
4447 
cil_gen_genfscon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4448 int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4449 {
4450 	enum cil_syntax syntax[] = {
4451 		CIL_SYN_STRING,
4452 		CIL_SYN_STRING,
4453 		CIL_SYN_STRING,
4454 		CIL_SYN_STRING | CIL_SYN_LIST,
4455 		CIL_SYN_END
4456 	};
4457 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4458 	int rc = SEPOL_ERR;
4459 	struct cil_genfscon *genfscon = NULL;
4460 
4461 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4462 		goto exit;
4463 	}
4464 
4465 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4466 	if (rc != SEPOL_OK) {
4467 		goto exit;
4468 	}
4469 
4470 	cil_genfscon_init(&genfscon);
4471 
4472 	genfscon->fs_str = parse_current->next->data;
4473 	genfscon->path_str = parse_current->next->next->data;
4474 
4475 	if (parse_current->next->next->next->cl_head == NULL ) {
4476 		genfscon->context_str = parse_current->next->next->next->data;
4477 	} else {
4478 		cil_context_init(&genfscon->context);
4479 
4480 		rc = cil_fill_context(parse_current->next->next->next->cl_head, genfscon->context);
4481 		if (rc != SEPOL_OK) {
4482 			goto exit;
4483 		}
4484 	}
4485 
4486 	ast_node->data = genfscon;
4487 	ast_node->flavor = CIL_GENFSCON;
4488 
4489 	return SEPOL_OK;
4490 
4491 exit:
4492 	cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
4493 	cil_destroy_genfscon(genfscon);
4494 	return SEPOL_ERR;
4495 }
4496 
cil_destroy_genfscon(struct cil_genfscon * genfscon)4497 void cil_destroy_genfscon(struct cil_genfscon *genfscon)
4498 {
4499 	if (genfscon == NULL) {
4500 		return;
4501 	}
4502 
4503 	if (genfscon->context_str == NULL && genfscon->context != NULL) {
4504 		cil_destroy_context(genfscon->context);
4505 	}
4506 
4507 	free(genfscon);
4508 }
4509 
4510 
cil_gen_netifcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4511 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4512 {
4513 	enum cil_syntax syntax[] = {
4514 		CIL_SYN_STRING,
4515 		CIL_SYN_STRING,
4516 		CIL_SYN_STRING | CIL_SYN_LIST,
4517 		CIL_SYN_STRING | CIL_SYN_LIST,
4518 		CIL_SYN_END
4519 	};
4520 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4521 	int rc = SEPOL_ERR;
4522 	struct cil_netifcon *netifcon = NULL;
4523 
4524 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4525 		goto exit;
4526 	}
4527 
4528 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4529 	if (rc != SEPOL_OK) {
4530 		goto exit;
4531 	}
4532 
4533 	cil_netifcon_init(&netifcon);
4534 
4535 	netifcon->interface_str = parse_current->next->data;
4536 
4537 	if (parse_current->next->next->cl_head == NULL) {
4538 		netifcon->if_context_str = parse_current->next->next->data;
4539 	} else {
4540 		cil_context_init(&netifcon->if_context);
4541 
4542 		rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context);
4543 		if (rc != SEPOL_OK) {
4544 			goto exit;
4545 		}
4546 	}
4547 
4548 	if (parse_current->next->next->next->cl_head == NULL) {
4549 		netifcon->packet_context_str = parse_current->next->next->next->data;
4550 	} else {
4551 		cil_context_init(&netifcon->packet_context);
4552 
4553 		rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context);
4554 		if (rc != SEPOL_OK) {
4555 			goto exit;
4556 		}
4557 	}
4558 
4559 	ast_node->data = netifcon;
4560 	ast_node->flavor = CIL_NETIFCON;
4561 
4562 	return SEPOL_OK;
4563 
4564 exit:
4565 	cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
4566 	cil_destroy_netifcon(netifcon);
4567 	return SEPOL_ERR;
4568 }
4569 
cil_destroy_netifcon(struct cil_netifcon * netifcon)4570 void cil_destroy_netifcon(struct cil_netifcon *netifcon)
4571 {
4572 	if (netifcon == NULL) {
4573 		return;
4574 	}
4575 
4576 	if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
4577 		cil_destroy_context(netifcon->if_context);
4578 	}
4579 
4580 	if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) {
4581 		cil_destroy_context(netifcon->packet_context);
4582 	}
4583 
4584 	free(netifcon);
4585 }
4586 
cil_gen_pirqcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4587 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4588 {
4589 	enum cil_syntax syntax[] = {
4590 		CIL_SYN_STRING,
4591 		CIL_SYN_STRING,
4592 		CIL_SYN_STRING | CIL_SYN_LIST,
4593 		CIL_SYN_END
4594 	};
4595 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4596 	int rc = SEPOL_ERR;
4597 	struct cil_pirqcon *pirqcon = NULL;
4598 
4599 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4600 		goto exit;
4601 	}
4602 
4603 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4604 	if (rc != SEPOL_OK) {
4605 		goto exit;
4606 	}
4607 
4608 	cil_pirqcon_init(&pirqcon);
4609 
4610 	rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
4611 	if (rc != SEPOL_OK) {
4612 		goto exit;
4613 	}
4614 
4615 	if (parse_current->next->next->cl_head == NULL) {
4616 		pirqcon->context_str = parse_current->next->next->data;
4617 	} else {
4618 		cil_context_init(&pirqcon->context);
4619 
4620 		rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context);
4621 		if (rc != SEPOL_OK) {
4622 			goto exit;
4623 		}
4624 	}
4625 
4626 	ast_node->data = pirqcon;
4627 	ast_node->flavor = CIL_PIRQCON;
4628 
4629 	return SEPOL_OK;
4630 
4631 exit:
4632 	cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
4633 	cil_destroy_pirqcon(pirqcon);
4634 	return rc;
4635 }
4636 
cil_destroy_pirqcon(struct cil_pirqcon * pirqcon)4637 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
4638 {
4639 	if (pirqcon == NULL) {
4640 		return;
4641 	}
4642 
4643 	if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
4644 		cil_destroy_context(pirqcon->context);
4645 	}
4646 
4647 	free(pirqcon);
4648 }
4649 
cil_gen_iomemcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4650 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4651 {
4652 	enum cil_syntax syntax[] = {
4653 		CIL_SYN_STRING,
4654 		CIL_SYN_STRING | CIL_SYN_LIST,
4655 		CIL_SYN_STRING | CIL_SYN_LIST,
4656 		CIL_SYN_END
4657 	};
4658 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4659 	int rc = SEPOL_ERR;
4660 	struct cil_iomemcon *iomemcon = NULL;
4661 
4662 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4663 		goto exit;
4664 	}
4665 
4666 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4667 	if (rc != SEPOL_OK) {
4668 		goto exit;
4669 	}
4670 
4671 	cil_iomemcon_init(&iomemcon);
4672 
4673 	if (parse_current->next->cl_head != NULL) {
4674 		if (parse_current->next->cl_head->next != NULL &&
4675 		    parse_current->next->cl_head->next->next == NULL) {
4676 			rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0);
4677 			if (rc != SEPOL_OK) {
4678 				cil_log(CIL_ERR, "Improper iomem specified\n");
4679 				goto exit;
4680 			}
4681 			rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0);
4682 			if (rc != SEPOL_OK) {
4683 				cil_log(CIL_ERR, "Improper iomem specified\n");
4684 				goto exit;
4685 			}
4686 		} else {
4687 			cil_log(CIL_ERR, "Improper iomem range specified\n");
4688 			rc = SEPOL_ERR;
4689 			goto exit;
4690 		}
4691 	} else {
4692 		rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0);
4693 		if (rc != SEPOL_OK) {
4694 			cil_log(CIL_ERR, "Improper iomem specified\n");
4695 			goto exit;
4696 		}
4697 		iomemcon->iomem_high = iomemcon->iomem_low;
4698 	}
4699 
4700 	if (parse_current->next->next->cl_head == NULL ) {
4701 		iomemcon->context_str = parse_current->next->next->data;
4702 	} else {
4703 		cil_context_init(&iomemcon->context);
4704 
4705 		rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context);
4706 		if (rc != SEPOL_OK) {
4707 			goto exit;
4708 		}
4709 	}
4710 
4711 	ast_node->data = iomemcon;
4712 	ast_node->flavor = CIL_IOMEMCON;
4713 
4714 	return SEPOL_OK;
4715 
4716 exit:
4717 	cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
4718 	cil_destroy_iomemcon(iomemcon);
4719 	return rc;
4720 }
4721 
cil_destroy_iomemcon(struct cil_iomemcon * iomemcon)4722 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
4723 {
4724 	if (iomemcon == NULL) {
4725 		return;
4726 	}
4727 
4728 	if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
4729 		cil_destroy_context(iomemcon->context);
4730 	}
4731 
4732 	free(iomemcon);
4733 }
4734 
cil_gen_ioportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4735 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4736 {
4737 	enum cil_syntax syntax[] = {
4738 		CIL_SYN_STRING,
4739 		CIL_SYN_STRING | CIL_SYN_LIST,
4740 		CIL_SYN_STRING | CIL_SYN_LIST,
4741 		CIL_SYN_END
4742 	};
4743 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4744 	int rc = SEPOL_ERR;
4745 	struct cil_ioportcon *ioportcon = NULL;
4746 
4747 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4748 		goto exit;
4749 	}
4750 
4751 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4752 	if (rc != SEPOL_OK) {
4753 		goto exit;
4754 	}
4755 
4756 	cil_ioportcon_init(&ioportcon);
4757 
4758 	if (parse_current->next->cl_head != NULL) {
4759 		if (parse_current->next->cl_head->next != NULL &&
4760 		    parse_current->next->cl_head->next->next == NULL) {
4761 			rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0);
4762 			if (rc != SEPOL_OK) {
4763 				cil_log(CIL_ERR, "Improper ioport specified\n");
4764 				goto exit;
4765 			}
4766 			rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0);
4767 			if (rc != SEPOL_OK) {
4768 				cil_log(CIL_ERR, "Improper ioport specified\n");
4769 				goto exit;
4770 			}
4771 		} else {
4772 			cil_log(CIL_ERR, "Improper ioport range specified\n");
4773 			rc = SEPOL_ERR;
4774 			goto exit;
4775 		}
4776 	} else {
4777 		rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0);
4778 		if (rc != SEPOL_OK) {
4779 			cil_log(CIL_ERR, "Improper ioport specified\n");
4780 			goto exit;
4781 		}
4782 		ioportcon->ioport_high = ioportcon->ioport_low;
4783 	}
4784 
4785 	if (parse_current->next->next->cl_head == NULL ) {
4786 		ioportcon->context_str = parse_current->next->next->data;
4787 	} else {
4788 		cil_context_init(&ioportcon->context);
4789 
4790 		rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context);
4791 		if (rc != SEPOL_OK) {
4792 			goto exit;
4793 		}
4794 	}
4795 
4796 	ast_node->data = ioportcon;
4797 	ast_node->flavor = CIL_IOPORTCON;
4798 
4799 	return SEPOL_OK;
4800 
4801 exit:
4802 	cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
4803 	cil_destroy_ioportcon(ioportcon);
4804 	return rc;
4805 }
4806 
cil_destroy_ioportcon(struct cil_ioportcon * ioportcon)4807 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
4808 {
4809 	if (ioportcon == NULL) {
4810 		return;
4811 	}
4812 
4813 	if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
4814 		cil_destroy_context(ioportcon->context);
4815 	}
4816 
4817 	free(ioportcon);
4818 }
4819 
cil_gen_pcidevicecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4820 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4821 {
4822 	enum cil_syntax syntax[] = {
4823 		CIL_SYN_STRING,
4824 		CIL_SYN_STRING,
4825 		CIL_SYN_STRING | CIL_SYN_LIST,
4826 		CIL_SYN_END
4827 	};
4828 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4829 	int rc = SEPOL_ERR;
4830 	struct cil_pcidevicecon *pcidevicecon = NULL;
4831 
4832 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4833 		goto exit;
4834 	}
4835 
4836 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4837 	if (rc != SEPOL_OK) {
4838 		goto exit;
4839 	}
4840 
4841 	cil_pcidevicecon_init(&pcidevicecon);
4842 
4843 	rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
4844 	if (rc != SEPOL_OK) {
4845 		goto exit;
4846 	}
4847 
4848 	if (parse_current->next->next->cl_head == NULL) {
4849 		pcidevicecon->context_str = parse_current->next->next->data;
4850 	} else {
4851 		cil_context_init(&pcidevicecon->context);
4852 
4853 		rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context);
4854 		if (rc != SEPOL_OK) {
4855 			goto exit;
4856 		}
4857 	}
4858 
4859 	ast_node->data = pcidevicecon;
4860 	ast_node->flavor = CIL_PCIDEVICECON;
4861 
4862 	return SEPOL_OK;
4863 
4864 exit:
4865 	cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
4866 	cil_destroy_pcidevicecon(pcidevicecon);
4867 	return rc;
4868 }
4869 
cil_destroy_pcidevicecon(struct cil_pcidevicecon * pcidevicecon)4870 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
4871 {
4872 	if (pcidevicecon == NULL) {
4873 		return;
4874 	}
4875 
4876 	if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) {
4877 		cil_destroy_context(pcidevicecon->context);
4878 	}
4879 
4880 	free(pcidevicecon);
4881 }
4882 
cil_gen_devicetreecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4883 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4884 {
4885 	enum cil_syntax syntax[] = {
4886 		CIL_SYN_STRING,
4887 		CIL_SYN_STRING,
4888 		CIL_SYN_STRING | CIL_SYN_LIST,
4889 		CIL_SYN_END
4890 	};
4891 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4892 	int rc = SEPOL_ERR;
4893 	struct cil_devicetreecon *devicetreecon = NULL;
4894 
4895 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4896 		goto exit;
4897 	}
4898 
4899 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4900 	if (rc != SEPOL_OK) {
4901 		goto exit;
4902 	}
4903 
4904 	cil_devicetreecon_init(&devicetreecon);
4905 
4906 	devicetreecon->path = parse_current->next->data;
4907 
4908 	if (parse_current->next->next->cl_head == NULL) {
4909 		devicetreecon->context_str = parse_current->next->next->data;
4910 	} else {
4911 		cil_context_init(&devicetreecon->context);
4912 
4913 		rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context);
4914 		if (rc != SEPOL_OK) {
4915 			goto exit;
4916 		}
4917 	}
4918 
4919 	ast_node->data = devicetreecon;
4920 	ast_node->flavor = CIL_DEVICETREECON;
4921 
4922 	return SEPOL_OK;
4923 
4924 exit:
4925 	cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
4926 	cil_destroy_devicetreecon(devicetreecon);
4927 	return rc;
4928 }
4929 
cil_destroy_devicetreecon(struct cil_devicetreecon * devicetreecon)4930 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
4931 {
4932 	if (devicetreecon == NULL) {
4933 		return;
4934 	}
4935 
4936 	if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) {
4937 		cil_destroy_context(devicetreecon->context);
4938 	}
4939 
4940 	free(devicetreecon);
4941 }
4942 
cil_gen_fsuse(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4943 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4944 {
4945 	enum cil_syntax syntax[] = {
4946 		CIL_SYN_STRING,
4947 		CIL_SYN_STRING,
4948 		CIL_SYN_STRING,
4949 		CIL_SYN_STRING | CIL_SYN_LIST,
4950 		CIL_SYN_END
4951 	};
4952 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
4953 	char *type = NULL;
4954 	struct cil_fsuse *fsuse = NULL;
4955 	int rc = SEPOL_ERR;
4956 
4957 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
4958 		goto exit;
4959 	}
4960 
4961 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4962 	if (rc != SEPOL_OK) {
4963 		goto exit;
4964 	}
4965 
4966 	type = parse_current->next->data;
4967 
4968 	cil_fsuse_init(&fsuse);
4969 
4970 	if (type == CIL_KEY_XATTR) {
4971 		fsuse->type = CIL_FSUSE_XATTR;
4972 	} else if (type == CIL_KEY_TASK) {
4973 		fsuse->type = CIL_FSUSE_TASK;
4974 	} else if (type == CIL_KEY_TRANS) {
4975 		fsuse->type = CIL_FSUSE_TRANS;
4976 	} else {
4977 		cil_log(CIL_ERR, "Invalid fsuse type\n");
4978 		goto exit;
4979 	}
4980 
4981 	fsuse->fs_str = parse_current->next->next->data;
4982 
4983 	if (parse_current->next->next->next->cl_head == NULL) {
4984 		fsuse->context_str = parse_current->next->next->next->data;
4985 	} else {
4986 		cil_context_init(&fsuse->context);
4987 
4988 		rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context);
4989 		if (rc != SEPOL_OK) {
4990 			goto exit;
4991 		}
4992 	}
4993 
4994 	ast_node->data = fsuse;
4995 	ast_node->flavor = CIL_FSUSE;
4996 
4997 	return SEPOL_OK;
4998 
4999 exit:
5000 	cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
5001 	cil_destroy_fsuse(fsuse);
5002 	return SEPOL_ERR;
5003 }
5004 
cil_destroy_fsuse(struct cil_fsuse * fsuse)5005 void cil_destroy_fsuse(struct cil_fsuse *fsuse)
5006 {
5007 	if (fsuse == NULL) {
5008 		return;
5009 	}
5010 
5011 	if (fsuse->context_str == NULL && fsuse->context != NULL) {
5012 		cil_destroy_context(fsuse->context);
5013 	}
5014 
5015 	free(fsuse);
5016 }
5017 
cil_destroy_param(struct cil_param * param)5018 void cil_destroy_param(struct cil_param *param)
5019 {
5020 	if (param == NULL) {
5021 		return;
5022 	}
5023 
5024 	free(param);
5025 }
5026 
cil_gen_macro(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5027 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5028 {
5029 	int rc = SEPOL_ERR;
5030 	char *key = NULL;
5031 	struct cil_macro *macro = NULL;
5032 	struct cil_tree_node *macro_content = NULL;
5033 	enum cil_syntax syntax[] = {
5034 		CIL_SYN_STRING,
5035 		CIL_SYN_STRING,
5036 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
5037 		CIL_SYN_N_LISTS | CIL_SYN_END,
5038 		CIL_SYN_END
5039 	};
5040 	int syntax_len = sizeof(syntax)/ sizeof(*syntax);
5041 
5042 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5043 		goto exit;
5044 	}
5045 
5046 	rc =__cil_verify_syntax(parse_current, syntax, syntax_len);
5047 	if (rc != SEPOL_OK) {
5048 		goto exit;
5049 	}
5050 
5051 	cil_macro_init(&macro);
5052 
5053 	key = parse_current->next->data;
5054 
5055 	struct cil_tree_node *current_item = parse_current->next->next->cl_head;
5056 	while (current_item != NULL) {
5057 		enum cil_syntax param_syntax[] = {
5058 			CIL_SYN_STRING,
5059 			CIL_SYN_STRING,
5060 			CIL_SYN_END
5061 		};
5062 		int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
5063 		char *kind = NULL;
5064 		struct cil_param *param = NULL;
5065 
5066 		rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
5067 		if (rc != SEPOL_OK) {
5068 			goto exit;
5069 		}
5070 
5071 		if (macro->params == NULL) {
5072 			cil_list_init(&macro->params, CIL_LIST_ITEM);
5073 		}
5074 
5075 		kind = current_item->cl_head->data;
5076 		cil_param_init(&param);
5077 
5078 		if (kind == CIL_KEY_TYPE) {
5079 			param->flavor = CIL_TYPE;
5080 		} else if (kind == CIL_KEY_ROLE) {
5081 			param->flavor = CIL_ROLE;
5082 		} else if (kind == CIL_KEY_USER) {
5083 			param->flavor = CIL_USER;
5084 		} else if (kind == CIL_KEY_SENSITIVITY) {
5085 			param->flavor = CIL_SENS;
5086 		} else if (kind == CIL_KEY_CATEGORY) {
5087 			param->flavor = CIL_CAT;
5088 		} else if (kind == CIL_KEY_CATSET) {
5089 			param->flavor = CIL_CATSET;
5090 		} else if (kind == CIL_KEY_LEVEL) {
5091 			param->flavor = CIL_LEVEL;
5092 		} else if (kind == CIL_KEY_LEVELRANGE) {
5093 			param->flavor = CIL_LEVELRANGE;
5094 		} else if (kind == CIL_KEY_CLASS) {
5095 			param->flavor = CIL_CLASS;
5096 		} else if (kind == CIL_KEY_IPADDR) {
5097 			param->flavor = CIL_IPADDR;
5098 		} else if (kind == CIL_KEY_MAP_CLASS) {
5099 			param->flavor = CIL_MAP_CLASS;
5100 		} else if (kind == CIL_KEY_CLASSPERMISSION) {
5101 			param->flavor = CIL_CLASSPERMISSION;
5102 		} else if (kind == CIL_KEY_BOOL) {
5103 			param->flavor = CIL_BOOL;
5104 		} else if (kind == CIL_KEY_STRING) {
5105 			param->flavor = CIL_NAME;
5106 		} else if (kind == CIL_KEY_NAME) {
5107 			param->flavor = CIL_NAME;
5108 		} else {
5109 			cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind);
5110 			cil_destroy_param(param);
5111 			goto exit;
5112 		}
5113 
5114 		param->str =  current_item->cl_head->next->data;
5115 
5116 		rc = __cil_verify_name(param->str);
5117 		if (rc != SEPOL_OK) {
5118 			cil_destroy_param(param);
5119 			goto exit;
5120 		}
5121 
5122 		//walk current list and check for duplicate parameters
5123 		struct cil_list_item *curr_param;
5124 		cil_list_for_each(curr_param, macro->params) {
5125 			if (param->str == ((struct cil_param*)curr_param->data)->str) {
5126 				if (param->flavor == ((struct cil_param*)curr_param->data)->flavor) {
5127 					cil_log(CIL_ERR, "Duplicate parameter\n");
5128 					cil_destroy_param(param);
5129 					goto exit;
5130 				}
5131 			}
5132 		}
5133 
5134 		cil_list_append(macro->params, CIL_PARAM, param);
5135 
5136 		current_item = current_item->next;
5137 	}
5138 
5139 	/* 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
5140            node containing the macro name is updated to point to the start of the macro content */
5141 	macro_content = parse_current->next->next->next;
5142 	cil_tree_subtree_destroy(parse_current->next->next);
5143 	parse_current->next->next = macro_content;
5144 	if (macro_content == NULL) {
5145 		/* No statements in macro and macro parameter list was last node */
5146 		parse_current->parent->cl_tail = parse_current->next;
5147 	}
5148 
5149 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
5150 	if (rc != SEPOL_OK) {
5151 		goto exit;
5152 	}
5153 
5154 	return SEPOL_OK;
5155 
5156 exit:
5157 	cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
5158 	cil_destroy_macro(macro);
5159 	cil_clear_node(ast_node);
5160 	return SEPOL_ERR;
5161 }
5162 
cil_destroy_macro(struct cil_macro * macro)5163 void cil_destroy_macro(struct cil_macro *macro)
5164 {
5165 	if (macro == NULL) {
5166 		return;
5167 	}
5168 
5169 	cil_symtab_datum_destroy(&macro->datum);
5170 	cil_symtab_array_destroy(macro->symtab);
5171 
5172 	if (macro->params != NULL) {
5173 		cil_list_destroy(&macro->params, 1);
5174 	}
5175 
5176 	free(macro);
5177 }
5178 
cil_gen_call(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5179 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5180 {
5181 	enum cil_syntax syntax[] = {
5182 		CIL_SYN_STRING,
5183 		CIL_SYN_STRING,
5184 		CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
5185 		CIL_SYN_END
5186 	};
5187 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5188 	struct cil_call *call = NULL;
5189 	int rc = SEPOL_ERR;
5190 
5191 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5192 		goto exit;
5193 	}
5194 
5195 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5196 	if (rc != SEPOL_OK) {
5197 		goto exit;
5198 	}
5199 
5200 	cil_call_init(&call);
5201 
5202 	call->macro_str = parse_current->next->data;
5203 
5204 	if (parse_current->next->next != NULL) {
5205 		cil_tree_init(&call->args_tree);
5206 		cil_copy_ast(db, parse_current->next->next, call->args_tree->root);
5207 	}
5208 
5209 	ast_node->data = call;
5210 	ast_node->flavor = CIL_CALL;
5211 
5212 	return SEPOL_OK;
5213 
5214 exit:
5215 	cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
5216 	cil_destroy_call(call);
5217 	return rc;
5218 }
5219 
cil_destroy_call(struct cil_call * call)5220 void cil_destroy_call(struct cil_call *call)
5221 {
5222 	if (call == NULL) {
5223 		return;
5224 	}
5225 
5226 	call->macro = NULL;
5227 
5228 	if (call->args_tree != NULL) {
5229 		cil_tree_destroy(&call->args_tree);
5230 	}
5231 
5232 	if (call->args != NULL) {
5233 		cil_list_destroy(&call->args, 1);
5234 	}
5235 
5236 	free(call);
5237 }
5238 
cil_destroy_args(struct cil_args * args)5239 void cil_destroy_args(struct cil_args *args)
5240 {
5241 	if (args == NULL) {
5242 		return;
5243 	}
5244 
5245 	if (args->arg_str != NULL) {
5246 		args->arg_str = NULL;
5247 	} else if (args->arg != NULL) {
5248 		struct cil_tree_node *node = args->arg->nodes->head->data;
5249 		switch (args->flavor) {
5250 		case CIL_NAME:
5251 			break;
5252 		case CIL_CATSET:
5253 			cil_destroy_catset((struct cil_catset *)args->arg);
5254 			free(node);
5255 			break;
5256 		case CIL_LEVEL:
5257 			cil_destroy_level((struct cil_level *)args->arg);
5258 			free(node);
5259 			break;
5260 		case CIL_LEVELRANGE:
5261 			cil_destroy_levelrange((struct cil_levelrange *)args->arg);
5262 			free(node);
5263 			break;
5264 		case CIL_IPADDR:
5265 			cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
5266 			free(node);
5267 			break;
5268 		case CIL_CLASSPERMISSION:
5269 			cil_destroy_classpermission((struct cil_classpermission *)args->arg);
5270 			free(node);
5271 			break;
5272 		default:
5273 			cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor);
5274 			break;
5275 		}
5276 	}
5277 
5278 	args->param_str = NULL;
5279 	args->arg = NULL;
5280 
5281 	free(args);
5282 }
5283 
cil_gen_optional(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5284 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5285 {
5286 	enum cil_syntax syntax[] = {
5287 		CIL_SYN_STRING,
5288 		CIL_SYN_STRING,
5289 		CIL_SYN_N_LISTS | CIL_SYN_END,
5290 		CIL_SYN_END
5291 	};
5292 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5293 	char *key = NULL;
5294 	struct cil_optional *optional = NULL;
5295 	int rc = SEPOL_ERR;
5296 
5297 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5298 		goto exit;
5299 	}
5300 
5301 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5302 	if (rc != SEPOL_OK) {
5303 		goto exit;
5304 	}
5305 
5306 	cil_optional_init(&optional);
5307 
5308 	key = parse_current->next->data;
5309 
5310 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
5311 	if (rc != SEPOL_OK)
5312 		goto exit;
5313 
5314 	return SEPOL_OK;
5315 
5316 exit:
5317 	cil_tree_log(parse_current, CIL_ERR, "Bad optional");
5318 	cil_destroy_optional(optional);
5319 	cil_clear_node(ast_node);
5320 	return rc;
5321 }
5322 
cil_destroy_optional(struct cil_optional * optional)5323 void cil_destroy_optional(struct cil_optional *optional)
5324 {
5325 	if (optional == NULL) {
5326 		return;
5327 	}
5328 
5329 	cil_symtab_datum_destroy(&optional->datum);
5330 	free(optional);
5331 }
5332 
cil_gen_policycap(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5333 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5334 {
5335 	enum cil_syntax syntax[] = {
5336 		CIL_SYN_STRING,
5337 		CIL_SYN_STRING,
5338 		CIL_SYN_END
5339 	};
5340 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5341 	char *key = NULL;
5342 	struct cil_policycap *polcap = NULL;
5343 	int rc = SEPOL_ERR;
5344 
5345 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5346 		goto exit;
5347 	}
5348 
5349 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5350 	if (rc != SEPOL_OK) {
5351 		goto exit;
5352 	}
5353 
5354 	cil_policycap_init(&polcap);
5355 
5356 	key = parse_current->next->data;
5357 
5358 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP);
5359 	if (rc != SEPOL_OK)
5360 		goto exit;
5361 
5362 	return SEPOL_OK;
5363 
5364 exit:
5365 	cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
5366 	cil_destroy_policycap(polcap);
5367 	cil_clear_node(ast_node);
5368 	return rc;
5369 }
5370 
cil_destroy_policycap(struct cil_policycap * polcap)5371 void cil_destroy_policycap(struct cil_policycap *polcap)
5372 {
5373 	if (polcap == NULL) {
5374 		return;
5375 	}
5376 
5377 	cil_symtab_datum_destroy(&polcap->datum);
5378 	free(polcap);
5379 }
5380 
cil_gen_ipaddr(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5381 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5382 {
5383 	enum cil_syntax syntax[] = {
5384 		CIL_SYN_STRING,
5385 		CIL_SYN_STRING,
5386 		CIL_SYN_STRING,
5387 		CIL_SYN_END
5388 	};
5389 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5390 	char *key = NULL;
5391 	struct cil_ipaddr *ipaddr = NULL;
5392 	int rc = SEPOL_ERR;
5393 
5394 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5395 		goto exit;
5396 	}
5397 
5398 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5399 	if (rc != SEPOL_OK) {
5400 		goto exit;
5401 	}
5402 
5403 	cil_ipaddr_init(&ipaddr);
5404 
5405 	key  = parse_current->next->data;
5406 
5407 	rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
5408 	if (rc != SEPOL_OK) {
5409 		goto exit;
5410 	}
5411 
5412 	rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
5413 	if (rc != SEPOL_OK) {
5414 		goto exit;
5415 	}
5416 
5417 	return SEPOL_OK;
5418 
5419 exit:
5420 	cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
5421 	cil_destroy_ipaddr(ipaddr);
5422 	cil_clear_node(ast_node);
5423 	return rc;
5424 }
5425 
cil_destroy_ipaddr(struct cil_ipaddr * ipaddr)5426 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
5427 {
5428 	if (ipaddr == NULL) {
5429 		return;
5430 	}
5431 
5432 	cil_symtab_datum_destroy(&ipaddr->datum);
5433 	free(ipaddr);
5434 }
5435 
cil_fill_integer(struct cil_tree_node * int_node,uint32_t * integer,int base)5436 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
5437 {
5438 	int rc = SEPOL_ERR;
5439 	char *endptr = NULL;
5440 	int val;
5441 
5442 	if (int_node == NULL || integer == NULL) {
5443 		goto exit;
5444 	}
5445 
5446 	errno = 0;
5447 	val = strtol(int_node->data, &endptr, base);
5448 	if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
5449 		rc = SEPOL_ERR;
5450 		goto exit;
5451 	}
5452 
5453 	*integer = val;
5454 
5455 	return SEPOL_OK;
5456 
5457 exit:
5458 	cil_log(CIL_ERR, "Failed to create integer from string\n");
5459 	return rc;
5460 }
5461 
cil_fill_integer64(struct cil_tree_node * int_node,uint64_t * integer,int base)5462 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
5463 {
5464 	int rc = SEPOL_ERR;
5465 	char *endptr = NULL;
5466 	uint64_t val;
5467 
5468 	if (int_node == NULL || integer == NULL) {
5469 		goto exit;
5470 	}
5471 
5472 	errno = 0;
5473 	val = strtoull(int_node->data, &endptr, base);
5474 	if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
5475 		rc = SEPOL_ERR;
5476 		goto exit;
5477 	}
5478 
5479 	*integer = val;
5480 
5481 	return SEPOL_OK;
5482 
5483 exit:
5484 	cil_log(CIL_ERR, "Failed to create integer from string\n");
5485 	return rc;
5486 }
5487 
cil_fill_ipaddr(struct cil_tree_node * addr_node,struct cil_ipaddr * addr)5488 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
5489 {
5490 	int rc = SEPOL_ERR;
5491 
5492 	if (addr_node == NULL || addr == NULL) {
5493 		goto exit;
5494 	}
5495 
5496 	if (addr_node->cl_head != NULL ||  addr_node->next != NULL) {
5497 		goto exit;
5498 	}
5499 
5500 	if (strchr(addr_node->data, '.') != NULL) {
5501 		addr->family = AF_INET;
5502 	} else {
5503 		addr->family = AF_INET6;
5504 	}
5505 
5506 	rc = inet_pton(addr->family, addr_node->data, &addr->ip);
5507 	if (rc != 1) {
5508 		rc = SEPOL_ERR;
5509 		goto exit;
5510 	}
5511 
5512 	return SEPOL_OK;
5513 
5514 exit:
5515 	cil_log(CIL_ERR, "Bad ip address or netmask\n");
5516 	return rc;
5517 }
5518 
cil_fill_level(struct cil_tree_node * curr,struct cil_level * level)5519 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
5520 {
5521 	int rc = SEPOL_ERR;
5522 	enum cil_syntax syntax[] = {
5523 		CIL_SYN_STRING,
5524 		CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
5525 		CIL_SYN_END
5526 	};
5527 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5528 
5529 	if (curr == NULL) {
5530 		goto exit;
5531 	}
5532 
5533 	rc = __cil_verify_syntax(curr, syntax, syntax_len);
5534 	if (rc != SEPOL_OK) {
5535 		goto exit;
5536 	}
5537 
5538 	level->sens_str = curr->data;
5539 	if (curr->next != NULL) {
5540 		rc = cil_fill_cats(curr->next, &level->cats);
5541 		if (rc != SEPOL_OK) {
5542 			goto exit;
5543 		}
5544 	}
5545 
5546 	return SEPOL_OK;
5547 
5548 exit:
5549 	cil_log(CIL_ERR, "Bad level\n");
5550 	return rc;
5551 }
5552 
cil_fill_cats(struct cil_tree_node * curr,struct cil_cats ** cats)5553 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
5554 {
5555 	int rc = SEPOL_ERR;
5556 
5557 	cil_cats_init(cats);
5558 
5559 	rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
5560 	if (rc != SEPOL_OK) {
5561 		cil_destroy_cats(*cats);
5562 		*cats = NULL;
5563 	}
5564 
5565 	return rc;
5566 }
5567 
cil_destroy_cats(struct cil_cats * cats)5568 void cil_destroy_cats(struct cil_cats *cats)
5569 {
5570 	if (cats == NULL) {
5571 		return;
5572 	}
5573 
5574 	cil_list_destroy(&cats->str_expr, CIL_TRUE);
5575 
5576 	cil_list_destroy(&cats->datum_expr, CIL_FALSE);
5577 
5578 	free(cats);
5579 }
cil_gen_bounds(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5580 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5581 {
5582 	enum cil_syntax syntax[] = {
5583 		CIL_SYN_STRING,
5584 		CIL_SYN_STRING,
5585 		CIL_SYN_STRING,
5586 		CIL_SYN_END
5587 	};
5588 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5589 	struct cil_bounds *bounds = NULL;
5590 	int rc = SEPOL_ERR;
5591 
5592 	if (db == NULL || parse_current == NULL || ast_node == NULL) {
5593 		goto exit;
5594 	}
5595 
5596 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5597 	if (rc != SEPOL_OK) {
5598 		goto exit;
5599 	}
5600 
5601 	cil_bounds_init(&bounds);
5602 
5603 	bounds->parent_str = parse_current->next->data;
5604 	bounds->child_str = parse_current->next->next->data;
5605 
5606 	ast_node->data = bounds;
5607 
5608 	switch (flavor) {
5609 	case CIL_USER:
5610 		ast_node->flavor = CIL_USERBOUNDS;
5611 		break;
5612 	case CIL_ROLE:
5613 		ast_node->flavor = CIL_ROLEBOUNDS;
5614 		break;
5615 	case CIL_TYPE:
5616 		ast_node->flavor = CIL_TYPEBOUNDS;
5617 		break;
5618 	default:
5619 		break;
5620 	}
5621 
5622 	return SEPOL_OK;
5623 
5624 exit:
5625 	cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
5626 	cil_destroy_bounds(bounds);
5627 	return rc;
5628 }
5629 
cil_destroy_bounds(struct cil_bounds * bounds)5630 void cil_destroy_bounds(struct cil_bounds *bounds)
5631 {
5632 	if (bounds == NULL) {
5633 		return;
5634 	}
5635 
5636 	free(bounds);
5637 }
5638 
cil_gen_default(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5639 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5640 {
5641 	int rc = SEPOL_ERR;
5642 	struct cil_default *def = NULL;
5643 	char *object;
5644 	enum cil_syntax syntax[] = {
5645 		CIL_SYN_STRING,
5646 		CIL_SYN_STRING | CIL_SYN_LIST,
5647 		CIL_SYN_STRING,
5648 		CIL_SYN_END
5649 	};
5650 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5651 
5652 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5653 	if (rc != SEPOL_OK) {
5654 		goto exit;
5655 	}
5656 
5657 	cil_default_init(&def);
5658 
5659 	def->flavor = flavor;
5660 
5661 	if (parse_current->next->cl_head == NULL) {
5662 		cil_list_init(&def->class_strs, CIL_CLASS);
5663 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5664 	} else {
5665 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5666 		if (rc != SEPOL_OK) {
5667 			goto exit;
5668 		}
5669 	}
5670 
5671 	object = parse_current->next->next->data;
5672 	if (object == CIL_KEY_SOURCE) {
5673 		def->object = CIL_DEFAULT_SOURCE;
5674 	} else if (object == CIL_KEY_TARGET) {
5675 		def->object = CIL_DEFAULT_TARGET;
5676 	} else {
5677 		cil_log(CIL_ERR,"Expected either 'source' or 'target'\n");
5678 		rc = SEPOL_ERR;
5679 		goto exit;
5680 	}
5681 
5682 	ast_node->data = def;
5683 	ast_node->flavor = flavor;
5684 
5685 	return SEPOL_OK;
5686 
5687 exit:
5688 	cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current));
5689 	cil_destroy_default(def);
5690 	return rc;
5691 }
5692 
cil_destroy_default(struct cil_default * def)5693 void cil_destroy_default(struct cil_default *def)
5694 {
5695 	if (def == NULL) {
5696 		return;
5697 	}
5698 
5699 	cil_list_destroy(&def->class_strs, CIL_TRUE);
5700 
5701 	cil_list_destroy(&def->class_datums, CIL_FALSE);
5702 
5703 	free(def);
5704 }
5705 
cil_gen_defaultrange(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5706 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5707 {
5708 	int rc = SEPOL_ERR;
5709 	struct cil_defaultrange *def = NULL;
5710 	char *object;
5711 	char *range;
5712 	enum cil_syntax syntax[] = {
5713 		CIL_SYN_STRING,
5714 		CIL_SYN_STRING | CIL_SYN_LIST,
5715 		CIL_SYN_STRING,
5716 		CIL_SYN_STRING,
5717 		CIL_SYN_END
5718 	};
5719 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5720 
5721 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5722 	if (rc != SEPOL_OK) {
5723 		goto exit;
5724 	}
5725 
5726 	cil_defaultrange_init(&def);
5727 
5728 	if (parse_current->next->cl_head == NULL) {
5729 		cil_list_init(&def->class_strs, CIL_CLASS);
5730 		cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5731 	} else {
5732 		rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5733 		if (rc != SEPOL_OK) {
5734 			goto exit;
5735 		}
5736 	}
5737 
5738 	object = parse_current->next->next->data;
5739 	range = parse_current->next->next->next->data;
5740 	if (object == CIL_KEY_SOURCE) {
5741 		if (range == CIL_KEY_LOW) {
5742 			def->object_range = CIL_DEFAULT_SOURCE_LOW;
5743 		} else if (range == CIL_KEY_HIGH) {
5744 			def->object_range = CIL_DEFAULT_SOURCE_HIGH;
5745 		} else if (range == CIL_KEY_LOW_HIGH) {
5746 			def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
5747 		} else {
5748 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5749 			rc = SEPOL_ERR;
5750 			goto exit;
5751 		}
5752 	} else if (parse_current->next->next->data == CIL_KEY_TARGET) {
5753 		if (range == CIL_KEY_LOW) {
5754 			def->object_range = CIL_DEFAULT_TARGET_LOW;
5755 		} else if (range == CIL_KEY_HIGH) {
5756 			def->object_range = CIL_DEFAULT_TARGET_HIGH;
5757 		} else if (range == CIL_KEY_LOW_HIGH) {
5758 			def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
5759 		} else {
5760 			cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5761 			rc = SEPOL_ERR;
5762 			goto exit;
5763 		}
5764 	} else {
5765 		cil_log(CIL_ERR,"Expected either \'source\' or \'target\'\n");
5766 		rc = SEPOL_ERR;
5767 		goto exit;
5768 	}
5769 
5770 	ast_node->data = def;
5771 	ast_node->flavor = CIL_DEFAULTRANGE;
5772 
5773 	return SEPOL_OK;
5774 
5775 exit:
5776 	cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
5777 	cil_destroy_defaultrange(def);
5778 	return rc;
5779 }
5780 
cil_destroy_defaultrange(struct cil_defaultrange * def)5781 void cil_destroy_defaultrange(struct cil_defaultrange *def)
5782 {
5783 	if (def == NULL) {
5784 		return;
5785 	}
5786 
5787 	cil_list_destroy(&def->class_strs, CIL_TRUE);
5788 
5789 	cil_list_destroy(&def->class_datums, CIL_FALSE);
5790 
5791 	free(def);
5792 }
5793 
cil_gen_handleunknown(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5794 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5795 {
5796 	int rc = SEPOL_ERR;
5797 	enum cil_syntax syntax[] = {
5798 		CIL_SYN_STRING,
5799 		CIL_SYN_STRING,
5800 		CIL_SYN_END
5801 	};
5802 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5803 	struct cil_handleunknown *unknown = NULL;
5804 	char *unknown_key;
5805 
5806 	if (parse_current == NULL || ast_node == NULL) {
5807 		goto exit;
5808 	}
5809 
5810 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5811 	if (rc != SEPOL_OK) {
5812 		goto exit;
5813 	}
5814 
5815 	cil_handleunknown_init(&unknown);
5816 
5817 	unknown_key = parse_current->next->data;
5818 	if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
5819 		unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
5820 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
5821 		unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
5822 	} else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
5823 		unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
5824 	} else {
5825 		cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT);
5826 		rc = SEPOL_ERR;
5827 		goto exit;
5828 	}
5829 
5830 	ast_node->data = unknown;
5831 	ast_node->flavor = CIL_HANDLEUNKNOWN;
5832 
5833 	return SEPOL_OK;
5834 
5835 exit:
5836 	cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
5837 	cil_destroy_handleunknown(unknown);
5838 	return rc;
5839 }
5840 
cil_destroy_handleunknown(struct cil_handleunknown * unk)5841 void cil_destroy_handleunknown(struct cil_handleunknown *unk)
5842 {
5843 	free(unk);
5844 }
5845 
cil_gen_mls(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5846 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5847 {
5848 	int rc = SEPOL_ERR;
5849 	enum cil_syntax syntax[] = {
5850 		CIL_SYN_STRING,
5851 		CIL_SYN_STRING,
5852 		CIL_SYN_END
5853 	};
5854 	int syntax_len = sizeof(syntax)/sizeof(*syntax);
5855 	struct cil_mls *mls = NULL;
5856 
5857 	if (parse_current == NULL || ast_node == NULL) {
5858 		goto exit;
5859 	}
5860 
5861 	rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5862 	if (rc != SEPOL_OK) {
5863 		goto exit;
5864 	}
5865 
5866 	cil_mls_init(&mls);
5867 
5868 	if (parse_current->next->data == CIL_KEY_CONDTRUE) {
5869 		mls->value = CIL_TRUE;
5870 	} else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
5871 		mls->value = CIL_FALSE;
5872 	} else {
5873 		cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
5874 		rc = SEPOL_ERR;
5875 		goto exit;
5876 	}
5877 
5878 	ast_node->data = mls;
5879 	ast_node->flavor = CIL_MLS;
5880 
5881 	return SEPOL_OK;
5882 
5883 exit:
5884 	cil_tree_log(parse_current, CIL_ERR, "Bad mls");
5885 	cil_destroy_mls(mls);
5886 	return rc;
5887 }
5888 
cil_destroy_mls(struct cil_mls * mls)5889 void cil_destroy_mls(struct cil_mls *mls)
5890 {
5891 	free(mls);
5892 }
5893 
cil_gen_src_info(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5894 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5895 {
5896 	/* No need to check syntax, because this is auto generated */
5897 	struct cil_src_info *info = NULL;
5898 
5899 	cil_src_info_init(&info);
5900 
5901 	info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE;
5902 	info->path = parse_current->next->next->data;
5903 
5904 	ast_node->data = info;
5905 	ast_node->flavor = CIL_SRC_INFO;
5906 
5907 	return SEPOL_OK;
5908 }
5909 
cil_destroy_src_info(struct cil_src_info * info)5910 void cil_destroy_src_info(struct cil_src_info *info)
5911 {
5912 	free(info);
5913 }
5914 
__cil_build_ast_node_helper(struct cil_tree_node * parse_current,uint32_t * finished,void * extra_args)5915 int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
5916 {
5917 	struct cil_args_build *args = NULL;
5918 	struct cil_tree_node *ast_current = NULL;
5919 	struct cil_db *db = NULL;
5920 	struct cil_tree_node *ast_node = NULL;
5921 	struct cil_tree_node *macro = NULL;
5922 	struct cil_tree_node *boolif = NULL;
5923 	struct cil_tree_node *tunif = NULL;
5924 	struct cil_tree_node *in = NULL;
5925 	int rc = SEPOL_ERR;
5926 
5927 	if (parse_current == NULL || finished == NULL || extra_args == NULL) {
5928 		goto exit;
5929 	}
5930 
5931 	args = extra_args;
5932 	ast_current = args->ast;
5933 	db = args->db;
5934 	macro = args->macro;
5935 	boolif = args->boolif;
5936 	tunif = args->tunif;
5937 	in = args->in;
5938 
5939 	if (parse_current->parent->cl_head != parse_current) {
5940 		/* ignore anything that isn't following a parenthesis */
5941 		rc = SEPOL_OK;
5942 		goto exit;
5943 	} else if (parse_current->data == NULL) {
5944 		/* the only time parenthsis can immediately following parenthesis is if
5945 		 * the parent is the root node */
5946 		if (parse_current->parent->parent == NULL) {
5947 			rc = SEPOL_OK;
5948 		} else {
5949 			cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
5950 		}
5951 		goto exit;
5952 	}
5953 
5954 	if (macro != NULL) {
5955 		if (parse_current->data == CIL_KEY_MACRO ||
5956 			parse_current->data == CIL_KEY_TUNABLE ||
5957 			parse_current->data == CIL_KEY_IN ||
5958 			parse_current->data == CIL_KEY_BLOCK ||
5959 			parse_current->data == CIL_KEY_BLOCKINHERIT ||
5960 			parse_current->data == CIL_KEY_BLOCKABSTRACT) {
5961 			rc = SEPOL_ERR;
5962 			cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data);
5963 			goto exit;
5964 		}
5965 	}
5966 
5967 	if (boolif != NULL) {
5968 		if (parse_current->data != CIL_KEY_CONDTRUE &&
5969 			parse_current->data != CIL_KEY_CONDFALSE &&
5970 			parse_current->data != CIL_KEY_AUDITALLOW &&
5971 			parse_current->data != CIL_KEY_TUNABLEIF &&
5972 			parse_current->data != CIL_KEY_ALLOW &&
5973 			parse_current->data != CIL_KEY_DONTAUDIT &&
5974 			parse_current->data != CIL_KEY_TYPETRANSITION &&
5975 			parse_current->data != CIL_KEY_TYPECHANGE &&
5976 			parse_current->data != CIL_KEY_CALL) {
5977 			rc = SEPOL_ERR;
5978 			cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data);
5979 			if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
5980 				cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n",
5981 						(char*)parse_current->data);
5982 			} else {
5983 				cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n",
5984 						(char*)parse_current->data);
5985 			}
5986 			goto exit;
5987 		}
5988 	}
5989 
5990 	if (tunif != NULL) {
5991 		if (parse_current->data == CIL_KEY_TUNABLE) {
5992 			rc = SEPOL_ERR;
5993 			cil_tree_log(parse_current, CIL_ERR, "Found tunable");
5994 			cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n");
5995 			goto exit;
5996 		}
5997 	}
5998 
5999 	if (in != NULL) {
6000 		if (parse_current->data == CIL_KEY_IN) {
6001 			rc = SEPOL_ERR;
6002 			cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
6003 			cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
6004 			goto exit;
6005 		}
6006 	}
6007 
6008 	cil_tree_node_init(&ast_node);
6009 
6010 	ast_node->parent = ast_current;
6011 	ast_node->line = parse_current->line;
6012 	ast_node->hll_line = parse_current->hll_line;
6013 
6014 	if (parse_current->data == CIL_KEY_BLOCK) {
6015 		rc = cil_gen_block(db, parse_current, ast_node, 0);
6016 	} else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
6017 		rc = cil_gen_blockinherit(db, parse_current, ast_node);
6018 	} else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6019 		rc = cil_gen_blockabstract(db, parse_current, ast_node);
6020 	} else if (parse_current->data == CIL_KEY_IN) {
6021 		rc = cil_gen_in(db, parse_current, ast_node);
6022 	} else if (parse_current->data == CIL_KEY_CLASS) {
6023 		rc = cil_gen_class(db, parse_current, ast_node);
6024 		// To avoid parsing list of perms again
6025 		*finished = CIL_TREE_SKIP_NEXT;
6026 	} else if (parse_current->data == CIL_KEY_CLASSORDER) {
6027 		rc = cil_gen_classorder(db, parse_current, ast_node);
6028 		*finished = CIL_TREE_SKIP_NEXT;
6029 	} else if (parse_current->data == CIL_KEY_MAP_CLASS) {
6030 		rc = cil_gen_map_class(db, parse_current, ast_node);
6031 		*finished = CIL_TREE_SKIP_NEXT;
6032 	} else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
6033 		rc = cil_gen_classmapping(db, parse_current, ast_node);
6034 		*finished = CIL_TREE_SKIP_NEXT;
6035 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
6036 		rc = cil_gen_classpermission(db, parse_current, ast_node);
6037 		*finished = CIL_TREE_SKIP_NEXT;
6038 	} else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
6039 		rc = cil_gen_classpermissionset(db, parse_current, ast_node);
6040 		*finished = CIL_TREE_SKIP_NEXT;
6041 	} else if (parse_current->data == CIL_KEY_COMMON) {
6042 		rc = cil_gen_common(db, parse_current, ast_node);
6043 		*finished = CIL_TREE_SKIP_NEXT;
6044 	} else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
6045 		rc = cil_gen_classcommon(db, parse_current, ast_node);
6046 	} else if (parse_current->data == CIL_KEY_SID) {
6047 		rc = cil_gen_sid(db, parse_current, ast_node);
6048 		*finished = CIL_TREE_SKIP_NEXT;
6049 	} else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
6050 		rc = cil_gen_sidcontext(db, parse_current, ast_node);
6051 		*finished = CIL_TREE_SKIP_NEXT;
6052 	} else if (parse_current->data == CIL_KEY_SIDORDER) {
6053 		rc = cil_gen_sidorder(db, parse_current, ast_node);
6054 		*finished = CIL_TREE_SKIP_NEXT;
6055 	} else if (parse_current->data == CIL_KEY_USER) {
6056 		rc = cil_gen_user(db, parse_current, ast_node);
6057 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
6058 		rc = cil_gen_userattribute(db, parse_current, ast_node);
6059 	} else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
6060 		rc = cil_gen_userattributeset(db, parse_current, ast_node);
6061 		*finished = CIL_TREE_SKIP_NEXT;
6062 	} else if (parse_current->data == CIL_KEY_USERLEVEL) {
6063 		rc = cil_gen_userlevel(db, parse_current, ast_node);
6064 		*finished = CIL_TREE_SKIP_NEXT;
6065 	} else if (parse_current->data == CIL_KEY_USERRANGE) {
6066 		rc = cil_gen_userrange(db, parse_current, ast_node);
6067 		*finished = CIL_TREE_SKIP_NEXT;
6068 	} else if (parse_current->data == CIL_KEY_USERBOUNDS) {
6069 		rc = cil_gen_bounds(db, parse_current, ast_node, CIL_USER);
6070 	} else if (parse_current->data == CIL_KEY_USERPREFIX) {
6071 		rc = cil_gen_userprefix(db, parse_current, ast_node);
6072 	} else if (parse_current->data == CIL_KEY_SELINUXUSER) {
6073 		rc = cil_gen_selinuxuser(db, parse_current, ast_node);
6074 		*finished = CIL_TREE_SKIP_NEXT;
6075 	} else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
6076 		rc = cil_gen_selinuxuserdefault(db, parse_current, ast_node);
6077 		*finished = CIL_TREE_SKIP_NEXT;
6078 	} else if (parse_current->data == CIL_KEY_TYPE) {
6079 		rc = cil_gen_type(db, parse_current, ast_node);
6080 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
6081 		rc = cil_gen_typeattribute(db, parse_current, ast_node);
6082 	} else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
6083 		rc = cil_gen_typeattributeset(db, parse_current, ast_node);
6084 		*finished = CIL_TREE_SKIP_NEXT;
6085 	} else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
6086 		rc = cil_gen_expandtypeattribute(db, parse_current, ast_node);
6087 		*finished = CIL_TREE_SKIP_NEXT;
6088 	} else if (parse_current->data == CIL_KEY_TYPEALIAS) {
6089 		rc = cil_gen_alias(db, parse_current, ast_node, CIL_TYPEALIAS);
6090 	} else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
6091 		rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_TYPEALIASACTUAL);
6092 	} else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
6093 		rc = cil_gen_bounds(db, parse_current, ast_node, CIL_TYPE);
6094 	} else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
6095 		rc = cil_gen_typepermissive(db, parse_current, ast_node);
6096 	} else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
6097 		rc = cil_gen_rangetransition(db, parse_current, ast_node);
6098 		*finished = CIL_TREE_SKIP_NEXT;
6099 	} else if (parse_current->data == CIL_KEY_ROLE) {
6100 		rc = cil_gen_role(db, parse_current, ast_node);
6101 	} else if (parse_current->data == CIL_KEY_USERROLE) {
6102 		rc = cil_gen_userrole(db, parse_current, ast_node);
6103 	} else if (parse_current->data == CIL_KEY_ROLETYPE) {
6104 		rc = cil_gen_roletype(db, parse_current, ast_node);
6105 	} else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
6106 		rc = cil_gen_roletransition(parse_current, ast_node);
6107 	} else if (parse_current->data == CIL_KEY_ROLEALLOW) {
6108 		rc = cil_gen_roleallow(db, parse_current, ast_node);
6109 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
6110 		rc = cil_gen_roleattribute(db, parse_current, ast_node);
6111 	} else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
6112 		rc = cil_gen_roleattributeset(db, parse_current, ast_node);
6113 		*finished = CIL_TREE_SKIP_NEXT;
6114 	} else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
6115 		rc = cil_gen_bounds(db, parse_current, ast_node, CIL_ROLE);
6116 	} else if (parse_current->data == CIL_KEY_BOOL) {
6117 		rc = cil_gen_bool(db, parse_current, ast_node, CIL_FALSE);
6118 	} else if (parse_current->data == CIL_KEY_BOOLEANIF) {
6119 		rc = cil_gen_boolif(db, parse_current, ast_node, CIL_FALSE);
6120 	} else if(parse_current->data == CIL_KEY_TUNABLE) {
6121 		if (db->preserve_tunables) {
6122 			rc = cil_gen_bool(db, parse_current, ast_node, CIL_TRUE);
6123 		} else {
6124 			rc = cil_gen_tunable(db, parse_current, ast_node);
6125 		}
6126 	} else if (parse_current->data == CIL_KEY_TUNABLEIF) {
6127 		if (db->preserve_tunables) {
6128 			rc = cil_gen_boolif(db, parse_current, ast_node, CIL_TRUE);
6129 		} else {
6130 			rc = cil_gen_tunif(db, parse_current, ast_node);
6131 		}
6132 	} else if (parse_current->data == CIL_KEY_CONDTRUE) {
6133 		rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDTRUE);
6134 	} else if (parse_current->data == CIL_KEY_CONDFALSE) {
6135 		rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDFALSE);
6136 	} else if (parse_current->data == CIL_KEY_ALLOW) {
6137 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_ALLOWED);
6138 		// So that the object and perms lists do not get parsed again
6139 		*finished = CIL_TREE_SKIP_NEXT;
6140 	} else if (parse_current->data == CIL_KEY_AUDITALLOW) {
6141 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
6142 		*finished = CIL_TREE_SKIP_NEXT;
6143 	} else if (parse_current->data == CIL_KEY_DONTAUDIT) {
6144 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
6145 		*finished = CIL_TREE_SKIP_NEXT;
6146 	} else if (parse_current->data == CIL_KEY_NEVERALLOW) {
6147 		rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
6148 		*finished = CIL_TREE_SKIP_NEXT;
6149 	} else if (parse_current->data == CIL_KEY_ALLOWX) {
6150 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED);
6151 		*finished = CIL_TREE_SKIP_NEXT;
6152 	} else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
6153 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
6154 		*finished = CIL_TREE_SKIP_NEXT;
6155 	} else if (parse_current->data == CIL_KEY_DONTAUDITX) {
6156 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
6157 		*finished = CIL_TREE_SKIP_NEXT;
6158 	} else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
6159 		rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
6160 		*finished = CIL_TREE_SKIP_NEXT;
6161 	} else if (parse_current->data == CIL_KEY_PERMISSIONX) {
6162 		rc = cil_gen_permissionx(db, parse_current, ast_node);
6163 		*finished = CIL_TREE_SKIP_NEXT;
6164 	} else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
6165 		rc = cil_gen_typetransition(db, parse_current, ast_node);
6166 	} else if (parse_current->data == CIL_KEY_TYPECHANGE) {
6167 		rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_CHANGE);
6168 	} else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
6169 		rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_MEMBER);
6170 	} else if (parse_current->data == CIL_KEY_SENSITIVITY) {
6171 		rc = cil_gen_sensitivity(db, parse_current, ast_node);
6172 	} else if (parse_current->data == CIL_KEY_SENSALIAS) {
6173 		rc = cil_gen_alias(db, parse_current, ast_node, CIL_SENSALIAS);
6174 	} else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
6175 		rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_SENSALIASACTUAL);
6176 	} else if (parse_current->data == CIL_KEY_CATEGORY) {
6177 		rc = cil_gen_category(db, parse_current, ast_node);
6178 	} else if (parse_current->data == CIL_KEY_CATALIAS) {
6179 		rc = cil_gen_alias(db, parse_current, ast_node, CIL_CATALIAS);
6180 	} else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
6181 		rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_CATALIASACTUAL);
6182 	} else if (parse_current->data == CIL_KEY_CATSET) {
6183 		rc = cil_gen_catset(db, parse_current, ast_node);
6184 		*finished = CIL_TREE_SKIP_NEXT;
6185 	} else if (parse_current->data == CIL_KEY_CATORDER) {
6186 		rc = cil_gen_catorder(db, parse_current, ast_node);
6187 		*finished = CIL_TREE_SKIP_NEXT;
6188 	} else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
6189 		rc = cil_gen_sensitivityorder(db, parse_current, ast_node);
6190 		*finished = CIL_TREE_SKIP_NEXT;
6191 	} else if (parse_current->data == CIL_KEY_SENSCAT) {
6192 		rc = cil_gen_senscat(db, parse_current, ast_node);
6193 		*finished = CIL_TREE_SKIP_NEXT;
6194 	} else if (parse_current->data == CIL_KEY_LEVEL) {
6195 		rc = cil_gen_level(db, parse_current, ast_node);
6196 		*finished = CIL_TREE_SKIP_NEXT;
6197 	} else if (parse_current->data == CIL_KEY_LEVELRANGE) {
6198 		rc = cil_gen_levelrange(db, parse_current, ast_node);
6199 		*finished = CIL_TREE_SKIP_NEXT;
6200 	} else if (parse_current->data == CIL_KEY_CONSTRAIN) {
6201 		rc = cil_gen_constrain(db, parse_current, ast_node, CIL_CONSTRAIN);
6202 		*finished = CIL_TREE_SKIP_NEXT;
6203 	} else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
6204 		rc = cil_gen_constrain(db, parse_current, ast_node, CIL_MLSCONSTRAIN);
6205 		*finished = CIL_TREE_SKIP_NEXT;
6206 	} else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
6207 		rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_VALIDATETRANS);
6208 		*finished = CIL_TREE_SKIP_NEXT;
6209 	} else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
6210 		rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_MLSVALIDATETRANS);
6211 		*finished = CIL_TREE_SKIP_NEXT;
6212 	} else if (parse_current->data == CIL_KEY_CONTEXT) {
6213 		rc = cil_gen_context(db, parse_current, ast_node);
6214 		*finished = CIL_TREE_SKIP_NEXT;
6215 	} else if (parse_current->data == CIL_KEY_FILECON) {
6216 		rc = cil_gen_filecon(db, parse_current, ast_node);
6217 		*finished = CIL_TREE_SKIP_NEXT;
6218 	} else if (parse_current->data == CIL_KEY_PORTCON) {
6219 		rc = cil_gen_portcon(db, parse_current, ast_node);
6220 		*finished = CIL_TREE_SKIP_NEXT;
6221 	} else if (parse_current->data == CIL_KEY_NODECON) {
6222 		rc = cil_gen_nodecon(db, parse_current, ast_node);
6223 		*finished = CIL_TREE_SKIP_NEXT;
6224 	} else if (parse_current->data == CIL_KEY_GENFSCON) {
6225 		rc = cil_gen_genfscon(db, parse_current, ast_node);
6226 		*finished = CIL_TREE_SKIP_NEXT;
6227 	} else if (parse_current->data == CIL_KEY_NETIFCON) {
6228 		rc = cil_gen_netifcon(db, parse_current, ast_node);
6229 		*finished = CIL_TREE_SKIP_NEXT;
6230 	} else if (parse_current->data == CIL_KEY_PIRQCON) {
6231 		rc = cil_gen_pirqcon(db, parse_current, ast_node);
6232 		*finished = CIL_TREE_SKIP_NEXT;
6233 	} else if (parse_current->data == CIL_KEY_IOMEMCON) {
6234 		rc = cil_gen_iomemcon(db, parse_current, ast_node);
6235 		*finished = CIL_TREE_SKIP_NEXT;
6236 	} else if (parse_current->data == CIL_KEY_IOPORTCON) {
6237 		rc = cil_gen_ioportcon(db, parse_current, ast_node);
6238 		*finished = CIL_TREE_SKIP_NEXT;
6239 	} else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
6240 		rc = cil_gen_pcidevicecon(db, parse_current, ast_node);
6241 		*finished = CIL_TREE_SKIP_NEXT;
6242 	} else if (parse_current->data == CIL_KEY_DEVICETREECON) {
6243 		rc = cil_gen_devicetreecon(db, parse_current, ast_node);
6244 		*finished = CIL_TREE_SKIP_NEXT;
6245 	} else if (parse_current->data == CIL_KEY_FSUSE) {
6246 		rc = cil_gen_fsuse(db, parse_current, ast_node);
6247 		*finished = CIL_TREE_SKIP_NEXT;
6248 	} else if (parse_current->data == CIL_KEY_MACRO) {
6249 		rc = cil_gen_macro(db, parse_current, ast_node);
6250 	} else if (parse_current->data == CIL_KEY_CALL) {
6251 		rc = cil_gen_call(db, parse_current, ast_node);
6252 		*finished = 1;
6253 	} else if (parse_current->data == CIL_KEY_POLICYCAP) {
6254 		rc = cil_gen_policycap(db, parse_current, ast_node);
6255 		*finished = 1;
6256 	} else if (parse_current->data == CIL_KEY_OPTIONAL) {
6257 		rc = cil_gen_optional(db, parse_current, ast_node);
6258 	} else if (parse_current->data == CIL_KEY_IPADDR) {
6259 		rc = cil_gen_ipaddr(db, parse_current, ast_node);
6260 	} else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
6261 		rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTUSER);
6262 		*finished = CIL_TREE_SKIP_NEXT;
6263 	} else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
6264 		rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTROLE);
6265 		*finished = CIL_TREE_SKIP_NEXT;
6266 	} else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
6267 		rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTTYPE);
6268 		*finished = CIL_TREE_SKIP_NEXT;
6269 	} else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
6270 		rc = cil_gen_defaultrange(parse_current, ast_node);
6271 		*finished = CIL_TREE_SKIP_NEXT;
6272 	} else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
6273 		rc = cil_gen_handleunknown(parse_current, ast_node);
6274 		*finished = CIL_TREE_SKIP_NEXT;
6275 	} else if (parse_current->data == CIL_KEY_MLS) {
6276 		rc = cil_gen_mls(parse_current, ast_node);
6277 		*finished = CIL_TREE_SKIP_NEXT;
6278 	} else if (parse_current->data == CIL_KEY_SRC_INFO) {
6279 		rc = cil_gen_src_info(parse_current, ast_node);
6280 	} else {
6281 		cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
6282 		rc = SEPOL_ERR;
6283 	}
6284 
6285 	if (rc == SEPOL_OK) {
6286 		if (ast_current->cl_head == NULL) {
6287 			if (ast_current->flavor == CIL_MACRO) {
6288 				args->macro = ast_current;
6289 			}
6290 
6291 			if (ast_current->flavor == CIL_BOOLEANIF) {
6292 				args->boolif = ast_current;
6293 			}
6294 
6295 			if (ast_current->flavor == CIL_TUNABLEIF) {
6296 				args->tunif = ast_current;
6297 			}
6298 
6299 			if (ast_current->flavor == CIL_IN) {
6300 				args->in = ast_current;
6301 			}
6302 
6303 			ast_current->cl_head = ast_node;
6304 		} else {
6305 			ast_current->cl_tail->next = ast_node;
6306 		}
6307 		ast_current->cl_tail = ast_node;
6308 		ast_current = ast_node;
6309 		args->ast = ast_current;
6310 	} else {
6311 		cil_tree_node_destroy(&ast_node);
6312 	}
6313 
6314 exit:
6315 	return rc;
6316 }
6317 
__cil_build_ast_last_child_helper(struct cil_tree_node * parse_current,void * extra_args)6318 int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
6319 {
6320 	int rc = SEPOL_ERR;
6321 	struct cil_tree_node *ast = NULL;
6322 	struct cil_args_build *args = NULL;
6323 
6324 	if (extra_args == NULL) {
6325 		goto exit;
6326 	}
6327 
6328 	args = extra_args;
6329 	ast = args->ast;
6330 
6331 	if (ast->flavor == CIL_ROOT) {
6332 		rc = SEPOL_OK;
6333 		goto exit;
6334 	}
6335 
6336 	args->ast = ast->parent;
6337 
6338 	if (ast->flavor == CIL_MACRO) {
6339 		args->macro = NULL;
6340 	}
6341 
6342 	if (ast->flavor == CIL_BOOLEANIF) {
6343 		args->boolif = NULL;
6344 	}
6345 
6346 	if (ast->flavor == CIL_TUNABLEIF) {
6347 		args->tunif = NULL;
6348 	}
6349 
6350 	if (ast->flavor == CIL_IN) {
6351 		args->in = NULL;
6352 	}
6353 
6354 	// At this point we no longer have any need for parse_current or any of its
6355 	// siblings; they have all been converted to the appropriate AST node. The
6356 	// full parse tree will get deleted elsewhere, but in an attempt to
6357 	// minimize memory useage (of which the parse tree uses alot), start
6358 	// deleting the parts we don't need now.
6359 	cil_tree_children_destroy(parse_current->parent);
6360 
6361 	return SEPOL_OK;
6362 
6363 exit:
6364 	return rc;
6365 }
6366 
cil_build_ast(struct cil_db * db,struct cil_tree_node * parse_tree,struct cil_tree_node * ast)6367 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
6368 {
6369 	int rc = SEPOL_ERR;
6370 	struct cil_args_build extra_args;
6371 
6372 	if (db == NULL || parse_tree == NULL || ast == NULL) {
6373 		goto exit;
6374 	}
6375 
6376 	extra_args.ast = ast;
6377 	extra_args.db = db;
6378 	extra_args.macro = NULL;
6379 	extra_args.boolif = NULL;
6380 	extra_args.tunif = NULL;
6381 	extra_args.in = NULL;
6382 
6383 	rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, NULL, __cil_build_ast_last_child_helper, &extra_args);
6384 	if (rc != SEPOL_OK) {
6385 		goto exit;
6386 	}
6387 
6388 	return SEPOL_OK;
6389 
6390 exit:
6391 	return rc;
6392 }
6393