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