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