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 goto exit;
4623 }
4624 context_node = parse_current->next->next->next->next;
4625 } else {
4626 /* (genfscon <FS_STR> <PATH_STR> ... */
4627 context_node = parse_current->next->next->next;
4628 }
4629
4630 if (context_node->cl_head) {
4631 cil_context_init(&genfscon->context);
4632 rc = cil_fill_context(context_node->cl_head, genfscon->context);
4633 if (rc != SEPOL_OK) {
4634 goto exit;
4635 }
4636 } else {
4637 genfscon->context_str = context_node->data;
4638 }
4639
4640 ast_node->data = genfscon;
4641 ast_node->flavor = CIL_GENFSCON;
4642
4643 return SEPOL_OK;
4644
4645 exit:
4646 cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
4647 cil_destroy_genfscon(genfscon);
4648 return SEPOL_ERR;
4649 }
4650
cil_destroy_genfscon(struct cil_genfscon * genfscon)4651 void cil_destroy_genfscon(struct cil_genfscon *genfscon)
4652 {
4653 if (genfscon == NULL) {
4654 return;
4655 }
4656
4657 if (genfscon->context_str == NULL && genfscon->context != NULL) {
4658 cil_destroy_context(genfscon->context);
4659 }
4660
4661 free(genfscon);
4662 }
4663
4664
cil_gen_netifcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4665 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4666 {
4667 enum cil_syntax syntax[] = {
4668 CIL_SYN_STRING,
4669 CIL_SYN_STRING,
4670 CIL_SYN_STRING | CIL_SYN_LIST,
4671 CIL_SYN_STRING | CIL_SYN_LIST,
4672 CIL_SYN_END
4673 };
4674 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4675 int rc = SEPOL_ERR;
4676 struct cil_netifcon *netifcon = NULL;
4677
4678 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4679 goto exit;
4680 }
4681
4682 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4683 if (rc != SEPOL_OK) {
4684 goto exit;
4685 }
4686
4687 cil_netifcon_init(&netifcon);
4688
4689 netifcon->interface_str = parse_current->next->data;
4690
4691 if (parse_current->next->next->cl_head == NULL) {
4692 netifcon->if_context_str = parse_current->next->next->data;
4693 } else {
4694 cil_context_init(&netifcon->if_context);
4695
4696 rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context);
4697 if (rc != SEPOL_OK) {
4698 goto exit;
4699 }
4700 }
4701
4702 if (parse_current->next->next->next->cl_head == NULL) {
4703 netifcon->packet_context_str = parse_current->next->next->next->data;
4704 } else {
4705 cil_context_init(&netifcon->packet_context);
4706
4707 rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context);
4708 if (rc != SEPOL_OK) {
4709 goto exit;
4710 }
4711 }
4712
4713 ast_node->data = netifcon;
4714 ast_node->flavor = CIL_NETIFCON;
4715
4716 return SEPOL_OK;
4717
4718 exit:
4719 cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
4720 cil_destroy_netifcon(netifcon);
4721 return SEPOL_ERR;
4722 }
4723
cil_destroy_netifcon(struct cil_netifcon * netifcon)4724 void cil_destroy_netifcon(struct cil_netifcon *netifcon)
4725 {
4726 if (netifcon == NULL) {
4727 return;
4728 }
4729
4730 if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
4731 cil_destroy_context(netifcon->if_context);
4732 }
4733
4734 if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) {
4735 cil_destroy_context(netifcon->packet_context);
4736 }
4737
4738 free(netifcon);
4739 }
4740
cil_gen_ibendportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4741 int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4742 {
4743 enum cil_syntax syntax[] = {
4744 CIL_SYN_STRING,
4745 CIL_SYN_STRING,
4746 CIL_SYN_STRING,
4747 CIL_SYN_STRING | CIL_SYN_LIST,
4748 CIL_SYN_END
4749 };
4750 size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4751 int rc = SEPOL_ERR;
4752 struct cil_ibendportcon *ibendportcon = NULL;
4753
4754 if (!parse_current || !ast_node)
4755 goto exit;
4756
4757 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4758 if (rc != SEPOL_OK)
4759 goto exit;
4760
4761 cil_ibendportcon_init(&ibendportcon);
4762
4763 ibendportcon->dev_name_str = parse_current->next->data;
4764
4765 rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10);
4766 if (rc != SEPOL_OK) {
4767 cil_log(CIL_ERR, "Improper ibendport port specified\n");
4768 goto exit;
4769 }
4770
4771 if (!parse_current->next->next->next->cl_head) {
4772 ibendportcon->context_str = parse_current->next->next->next->data;
4773 } else {
4774 cil_context_init(&ibendportcon->context);
4775
4776 rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context);
4777 if (rc != SEPOL_OK)
4778 goto exit;
4779 }
4780
4781 ast_node->data = ibendportcon;
4782 ast_node->flavor = CIL_IBENDPORTCON;
4783
4784 return SEPOL_OK;
4785
4786 exit:
4787 cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration");
4788 cil_destroy_ibendportcon(ibendportcon);
4789 return SEPOL_ERR;
4790 }
4791
cil_destroy_ibendportcon(struct cil_ibendportcon * ibendportcon)4792 void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon)
4793 {
4794 if (!ibendportcon)
4795 return;
4796
4797 if (!ibendportcon->context_str && ibendportcon->context)
4798 cil_destroy_context(ibendportcon->context);
4799
4800 free(ibendportcon);
4801 }
4802
cil_gen_pirqcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4803 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4804 {
4805 enum cil_syntax syntax[] = {
4806 CIL_SYN_STRING,
4807 CIL_SYN_STRING,
4808 CIL_SYN_STRING | CIL_SYN_LIST,
4809 CIL_SYN_END
4810 };
4811 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4812 int rc = SEPOL_ERR;
4813 struct cil_pirqcon *pirqcon = NULL;
4814
4815 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4816 goto exit;
4817 }
4818
4819 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4820 if (rc != SEPOL_OK) {
4821 goto exit;
4822 }
4823
4824 cil_pirqcon_init(&pirqcon);
4825
4826 rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
4827 if (rc != SEPOL_OK) {
4828 goto exit;
4829 }
4830
4831 if (parse_current->next->next->cl_head == NULL) {
4832 pirqcon->context_str = parse_current->next->next->data;
4833 } else {
4834 cil_context_init(&pirqcon->context);
4835
4836 rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context);
4837 if (rc != SEPOL_OK) {
4838 goto exit;
4839 }
4840 }
4841
4842 ast_node->data = pirqcon;
4843 ast_node->flavor = CIL_PIRQCON;
4844
4845 return SEPOL_OK;
4846
4847 exit:
4848 cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
4849 cil_destroy_pirqcon(pirqcon);
4850 return rc;
4851 }
4852
cil_destroy_pirqcon(struct cil_pirqcon * pirqcon)4853 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
4854 {
4855 if (pirqcon == NULL) {
4856 return;
4857 }
4858
4859 if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
4860 cil_destroy_context(pirqcon->context);
4861 }
4862
4863 free(pirqcon);
4864 }
4865
cil_gen_iomemcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4866 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4867 {
4868 enum cil_syntax syntax[] = {
4869 CIL_SYN_STRING,
4870 CIL_SYN_STRING | CIL_SYN_LIST,
4871 CIL_SYN_STRING | CIL_SYN_LIST,
4872 CIL_SYN_END
4873 };
4874 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4875 int rc = SEPOL_ERR;
4876 struct cil_iomemcon *iomemcon = NULL;
4877
4878 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4879 goto exit;
4880 }
4881
4882 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4883 if (rc != SEPOL_OK) {
4884 goto exit;
4885 }
4886
4887 cil_iomemcon_init(&iomemcon);
4888
4889 if (parse_current->next->cl_head != NULL) {
4890 if (parse_current->next->cl_head->next != NULL &&
4891 parse_current->next->cl_head->next->next == NULL) {
4892 rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0);
4893 if (rc != SEPOL_OK) {
4894 cil_log(CIL_ERR, "Improper iomem specified\n");
4895 goto exit;
4896 }
4897 rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0);
4898 if (rc != SEPOL_OK) {
4899 cil_log(CIL_ERR, "Improper iomem specified\n");
4900 goto exit;
4901 }
4902 } else {
4903 cil_log(CIL_ERR, "Improper iomem range specified\n");
4904 rc = SEPOL_ERR;
4905 goto exit;
4906 }
4907 } else {
4908 rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0);
4909 if (rc != SEPOL_OK) {
4910 cil_log(CIL_ERR, "Improper iomem specified\n");
4911 goto exit;
4912 }
4913 iomemcon->iomem_high = iomemcon->iomem_low;
4914 }
4915
4916 if (parse_current->next->next->cl_head == NULL ) {
4917 iomemcon->context_str = parse_current->next->next->data;
4918 } else {
4919 cil_context_init(&iomemcon->context);
4920
4921 rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context);
4922 if (rc != SEPOL_OK) {
4923 goto exit;
4924 }
4925 }
4926
4927 ast_node->data = iomemcon;
4928 ast_node->flavor = CIL_IOMEMCON;
4929
4930 return SEPOL_OK;
4931
4932 exit:
4933 cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
4934 cil_destroy_iomemcon(iomemcon);
4935 return rc;
4936 }
4937
cil_destroy_iomemcon(struct cil_iomemcon * iomemcon)4938 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
4939 {
4940 if (iomemcon == NULL) {
4941 return;
4942 }
4943
4944 if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
4945 cil_destroy_context(iomemcon->context);
4946 }
4947
4948 free(iomemcon);
4949 }
4950
cil_gen_ioportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4951 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4952 {
4953 enum cil_syntax syntax[] = {
4954 CIL_SYN_STRING,
4955 CIL_SYN_STRING | CIL_SYN_LIST,
4956 CIL_SYN_STRING | CIL_SYN_LIST,
4957 CIL_SYN_END
4958 };
4959 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4960 int rc = SEPOL_ERR;
4961 struct cil_ioportcon *ioportcon = NULL;
4962
4963 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4964 goto exit;
4965 }
4966
4967 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4968 if (rc != SEPOL_OK) {
4969 goto exit;
4970 }
4971
4972 cil_ioportcon_init(&ioportcon);
4973
4974 if (parse_current->next->cl_head != NULL) {
4975 if (parse_current->next->cl_head->next != NULL &&
4976 parse_current->next->cl_head->next->next == NULL) {
4977 rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0);
4978 if (rc != SEPOL_OK) {
4979 cil_log(CIL_ERR, "Improper ioport specified\n");
4980 goto exit;
4981 }
4982 rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0);
4983 if (rc != SEPOL_OK) {
4984 cil_log(CIL_ERR, "Improper ioport specified\n");
4985 goto exit;
4986 }
4987 } else {
4988 cil_log(CIL_ERR, "Improper ioport range specified\n");
4989 rc = SEPOL_ERR;
4990 goto exit;
4991 }
4992 } else {
4993 rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0);
4994 if (rc != SEPOL_OK) {
4995 cil_log(CIL_ERR, "Improper ioport specified\n");
4996 goto exit;
4997 }
4998 ioportcon->ioport_high = ioportcon->ioport_low;
4999 }
5000
5001 if (parse_current->next->next->cl_head == NULL ) {
5002 ioportcon->context_str = parse_current->next->next->data;
5003 } else {
5004 cil_context_init(&ioportcon->context);
5005
5006 rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context);
5007 if (rc != SEPOL_OK) {
5008 goto exit;
5009 }
5010 }
5011
5012 ast_node->data = ioportcon;
5013 ast_node->flavor = CIL_IOPORTCON;
5014
5015 return SEPOL_OK;
5016
5017 exit:
5018 cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
5019 cil_destroy_ioportcon(ioportcon);
5020 return rc;
5021 }
5022
cil_destroy_ioportcon(struct cil_ioportcon * ioportcon)5023 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
5024 {
5025 if (ioportcon == NULL) {
5026 return;
5027 }
5028
5029 if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
5030 cil_destroy_context(ioportcon->context);
5031 }
5032
5033 free(ioportcon);
5034 }
5035
cil_gen_pcidevicecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5036 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5037 {
5038 enum cil_syntax syntax[] = {
5039 CIL_SYN_STRING,
5040 CIL_SYN_STRING,
5041 CIL_SYN_STRING | CIL_SYN_LIST,
5042 CIL_SYN_END
5043 };
5044 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5045 int rc = SEPOL_ERR;
5046 struct cil_pcidevicecon *pcidevicecon = NULL;
5047
5048 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5049 goto exit;
5050 }
5051
5052 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5053 if (rc != SEPOL_OK) {
5054 goto exit;
5055 }
5056
5057 cil_pcidevicecon_init(&pcidevicecon);
5058
5059 rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
5060 if (rc != SEPOL_OK) {
5061 goto exit;
5062 }
5063
5064 if (parse_current->next->next->cl_head == NULL) {
5065 pcidevicecon->context_str = parse_current->next->next->data;
5066 } else {
5067 cil_context_init(&pcidevicecon->context);
5068
5069 rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context);
5070 if (rc != SEPOL_OK) {
5071 goto exit;
5072 }
5073 }
5074
5075 ast_node->data = pcidevicecon;
5076 ast_node->flavor = CIL_PCIDEVICECON;
5077
5078 return SEPOL_OK;
5079
5080 exit:
5081 cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
5082 cil_destroy_pcidevicecon(pcidevicecon);
5083 return rc;
5084 }
5085
cil_destroy_pcidevicecon(struct cil_pcidevicecon * pcidevicecon)5086 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
5087 {
5088 if (pcidevicecon == NULL) {
5089 return;
5090 }
5091
5092 if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) {
5093 cil_destroy_context(pcidevicecon->context);
5094 }
5095
5096 free(pcidevicecon);
5097 }
5098
cil_gen_devicetreecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5099 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5100 {
5101 enum cil_syntax syntax[] = {
5102 CIL_SYN_STRING,
5103 CIL_SYN_STRING,
5104 CIL_SYN_STRING | CIL_SYN_LIST,
5105 CIL_SYN_END
5106 };
5107 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5108 int rc = SEPOL_ERR;
5109 struct cil_devicetreecon *devicetreecon = NULL;
5110
5111 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5112 goto exit;
5113 }
5114
5115 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5116 if (rc != SEPOL_OK) {
5117 goto exit;
5118 }
5119
5120 cil_devicetreecon_init(&devicetreecon);
5121
5122 devicetreecon->path = parse_current->next->data;
5123
5124 if (parse_current->next->next->cl_head == NULL) {
5125 devicetreecon->context_str = parse_current->next->next->data;
5126 } else {
5127 cil_context_init(&devicetreecon->context);
5128
5129 rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context);
5130 if (rc != SEPOL_OK) {
5131 goto exit;
5132 }
5133 }
5134
5135 ast_node->data = devicetreecon;
5136 ast_node->flavor = CIL_DEVICETREECON;
5137
5138 return SEPOL_OK;
5139
5140 exit:
5141 cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
5142 cil_destroy_devicetreecon(devicetreecon);
5143 return rc;
5144 }
5145
cil_destroy_devicetreecon(struct cil_devicetreecon * devicetreecon)5146 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
5147 {
5148 if (devicetreecon == NULL) {
5149 return;
5150 }
5151
5152 if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) {
5153 cil_destroy_context(devicetreecon->context);
5154 }
5155
5156 free(devicetreecon);
5157 }
5158
cil_gen_fsuse(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5159 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5160 {
5161 enum cil_syntax syntax[] = {
5162 CIL_SYN_STRING,
5163 CIL_SYN_STRING,
5164 CIL_SYN_STRING,
5165 CIL_SYN_STRING | CIL_SYN_LIST,
5166 CIL_SYN_END
5167 };
5168 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5169 char *type = NULL;
5170 struct cil_fsuse *fsuse = NULL;
5171 int rc = SEPOL_ERR;
5172
5173 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5174 goto exit;
5175 }
5176
5177 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5178 if (rc != SEPOL_OK) {
5179 goto exit;
5180 }
5181
5182 type = parse_current->next->data;
5183
5184 cil_fsuse_init(&fsuse);
5185
5186 if (type == CIL_KEY_XATTR) {
5187 fsuse->type = CIL_FSUSE_XATTR;
5188 } else if (type == CIL_KEY_TASK) {
5189 fsuse->type = CIL_FSUSE_TASK;
5190 } else if (type == CIL_KEY_TRANS) {
5191 fsuse->type = CIL_FSUSE_TRANS;
5192 } else {
5193 cil_log(CIL_ERR, "Invalid fsuse type\n");
5194 goto exit;
5195 }
5196
5197 fsuse->fs_str = parse_current->next->next->data;
5198
5199 if (parse_current->next->next->next->cl_head == NULL) {
5200 fsuse->context_str = parse_current->next->next->next->data;
5201 } else {
5202 cil_context_init(&fsuse->context);
5203
5204 rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context);
5205 if (rc != SEPOL_OK) {
5206 goto exit;
5207 }
5208 }
5209
5210 ast_node->data = fsuse;
5211 ast_node->flavor = CIL_FSUSE;
5212
5213 return SEPOL_OK;
5214
5215 exit:
5216 cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
5217 cil_destroy_fsuse(fsuse);
5218 return SEPOL_ERR;
5219 }
5220
cil_destroy_fsuse(struct cil_fsuse * fsuse)5221 void cil_destroy_fsuse(struct cil_fsuse *fsuse)
5222 {
5223 if (fsuse == NULL) {
5224 return;
5225 }
5226
5227 if (fsuse->context_str == NULL && fsuse->context != NULL) {
5228 cil_destroy_context(fsuse->context);
5229 }
5230
5231 free(fsuse);
5232 }
5233
cil_destroy_param(struct cil_param * param)5234 void cil_destroy_param(struct cil_param *param)
5235 {
5236 if (param == NULL) {
5237 return;
5238 }
5239
5240 free(param);
5241 }
5242
cil_gen_macro(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5243 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5244 {
5245 int rc = SEPOL_ERR;
5246 char *key = NULL;
5247 struct cil_macro *macro = NULL;
5248 struct cil_tree_node *macro_content = NULL;
5249 struct cil_tree_node *current_item;
5250 enum cil_syntax syntax[] = {
5251 CIL_SYN_STRING,
5252 CIL_SYN_STRING,
5253 CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
5254 CIL_SYN_N_LISTS | CIL_SYN_END,
5255 CIL_SYN_END
5256 };
5257 size_t syntax_len = sizeof(syntax)/ sizeof(*syntax);
5258
5259 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5260 goto exit;
5261 }
5262
5263 rc =__cil_verify_syntax(parse_current, syntax, syntax_len);
5264 if (rc != SEPOL_OK) {
5265 goto exit;
5266 }
5267
5268 cil_macro_init(¯o);
5269
5270 key = parse_current->next->data;
5271
5272 current_item = parse_current->next->next->cl_head;
5273 while (current_item != NULL) {
5274 enum cil_syntax param_syntax[] = {
5275 CIL_SYN_STRING,
5276 CIL_SYN_STRING,
5277 CIL_SYN_END
5278 };
5279 int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
5280 char *kind = NULL;
5281 struct cil_param *param = NULL;
5282 struct cil_list_item *curr_param;
5283
5284 rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
5285 if (rc != SEPOL_OK) {
5286 goto exit;
5287 }
5288
5289 if (macro->params == NULL) {
5290 cil_list_init(¯o->params, CIL_LIST_ITEM);
5291 }
5292
5293 kind = current_item->cl_head->data;
5294 cil_param_init(¶m);
5295
5296 if (kind == CIL_KEY_TYPE) {
5297 param->flavor = CIL_TYPE;
5298 } else if (kind == CIL_KEY_ROLE) {
5299 param->flavor = CIL_ROLE;
5300 } else if (kind == CIL_KEY_USER) {
5301 param->flavor = CIL_USER;
5302 } else if (kind == CIL_KEY_SENSITIVITY) {
5303 param->flavor = CIL_SENS;
5304 } else if (kind == CIL_KEY_CATEGORY) {
5305 param->flavor = CIL_CAT;
5306 } else if (kind == CIL_KEY_CATSET) {
5307 param->flavor = CIL_CATSET;
5308 } else if (kind == CIL_KEY_LEVEL) {
5309 param->flavor = CIL_LEVEL;
5310 } else if (kind == CIL_KEY_LEVELRANGE) {
5311 param->flavor = CIL_LEVELRANGE;
5312 } else if (kind == CIL_KEY_CLASS) {
5313 param->flavor = CIL_CLASS;
5314 } else if (kind == CIL_KEY_IPADDR) {
5315 param->flavor = CIL_IPADDR;
5316 } else if (kind == CIL_KEY_MAP_CLASS) {
5317 param->flavor = CIL_MAP_CLASS;
5318 } else if (kind == CIL_KEY_CLASSPERMISSION) {
5319 param->flavor = CIL_CLASSPERMISSION;
5320 } else if (kind == CIL_KEY_BOOL) {
5321 param->flavor = CIL_BOOL;
5322 } else if (kind == CIL_KEY_STRING) {
5323 param->flavor = CIL_NAME;
5324 } else if (kind == CIL_KEY_NAME) {
5325 param->flavor = CIL_NAME;
5326 } else {
5327 cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind);
5328 cil_destroy_param(param);
5329 goto exit;
5330 }
5331
5332 param->str = current_item->cl_head->next->data;
5333
5334 rc = cil_verify_name(db, param->str, param->flavor);
5335 if (rc != SEPOL_OK) {
5336 cil_destroy_param(param);
5337 goto exit;
5338 }
5339
5340 //walk current list and check for duplicate parameters
5341 cil_list_for_each(curr_param, macro->params) {
5342 if (param->str == ((struct cil_param*)curr_param->data)->str) {
5343 cil_log(CIL_ERR, "Duplicate parameter\n");
5344 cil_destroy_param(param);
5345 goto exit;
5346 }
5347 }
5348
5349 cil_list_append(macro->params, CIL_PARAM, param);
5350
5351 current_item = current_item->next;
5352 }
5353
5354 /* 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
5355 node containing the macro name is updated to point to the start of the macro content */
5356 macro_content = parse_current->next->next->next;
5357 cil_tree_subtree_destroy(parse_current->next->next);
5358 parse_current->next->next = macro_content;
5359 if (macro_content == NULL) {
5360 /* No statements in macro and macro parameter list was last node */
5361 parse_current->parent->cl_tail = parse_current->next;
5362 }
5363
5364 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
5365 if (rc != SEPOL_OK) {
5366 goto exit;
5367 }
5368
5369 return SEPOL_OK;
5370
5371 exit:
5372 cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
5373 cil_destroy_macro(macro);
5374 cil_clear_node(ast_node);
5375 return SEPOL_ERR;
5376 }
5377
cil_destroy_macro(struct cil_macro * macro)5378 void cil_destroy_macro(struct cil_macro *macro)
5379 {
5380 if (macro == NULL) {
5381 return;
5382 }
5383
5384 cil_symtab_datum_destroy(¯o->datum);
5385 cil_symtab_array_destroy(macro->symtab);
5386
5387 if (macro->params != NULL) {
5388 cil_list_destroy(¯o->params, 1);
5389 }
5390
5391 free(macro);
5392 }
5393
cil_gen_call(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5394 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5395 {
5396 enum cil_syntax syntax[] = {
5397 CIL_SYN_STRING,
5398 CIL_SYN_STRING,
5399 CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
5400 CIL_SYN_END
5401 };
5402 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5403 struct cil_call *call = NULL;
5404 int rc = SEPOL_ERR;
5405
5406 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5407 goto exit;
5408 }
5409
5410 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5411 if (rc != SEPOL_OK) {
5412 goto exit;
5413 }
5414
5415 cil_call_init(&call);
5416
5417 call->macro_str = parse_current->next->data;
5418
5419 if (parse_current->next->next != NULL) {
5420 cil_tree_init(&call->args_tree);
5421 cil_copy_ast(db, parse_current->next->next, call->args_tree->root);
5422 }
5423
5424 ast_node->data = call;
5425 ast_node->flavor = CIL_CALL;
5426
5427 return SEPOL_OK;
5428
5429 exit:
5430 cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
5431 cil_destroy_call(call);
5432 return rc;
5433 }
5434
cil_destroy_call(struct cil_call * call)5435 void cil_destroy_call(struct cil_call *call)
5436 {
5437 if (call == NULL) {
5438 return;
5439 }
5440
5441 call->macro = NULL;
5442
5443 if (call->args_tree != NULL) {
5444 cil_tree_destroy(&call->args_tree);
5445 }
5446
5447 if (call->args != NULL) {
5448 cil_list_destroy(&call->args, 1);
5449 }
5450
5451 free(call);
5452 }
5453
cil_destroy_args(struct cil_args * args)5454 void cil_destroy_args(struct cil_args *args)
5455 {
5456 if (args == NULL) {
5457 return;
5458 }
5459
5460 if (args->arg_str != NULL) {
5461 args->arg_str = NULL;
5462 } else if (args->arg != NULL) {
5463 struct cil_tree_node *node = args->arg->nodes->head->data;
5464 switch (args->flavor) {
5465 case CIL_NAME:
5466 break;
5467 case CIL_CATSET:
5468 cil_destroy_catset((struct cil_catset *)args->arg);
5469 free(node);
5470 break;
5471 case CIL_LEVEL:
5472 cil_destroy_level((struct cil_level *)args->arg);
5473 free(node);
5474 break;
5475 case CIL_LEVELRANGE:
5476 cil_destroy_levelrange((struct cil_levelrange *)args->arg);
5477 free(node);
5478 break;
5479 case CIL_IPADDR:
5480 cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
5481 free(node);
5482 break;
5483 case CIL_CLASSPERMISSION:
5484 cil_destroy_classpermission((struct cil_classpermission *)args->arg);
5485 free(node);
5486 break;
5487 default:
5488 cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor);
5489 break;
5490 }
5491 }
5492
5493 args->param_str = NULL;
5494 args->arg = NULL;
5495
5496 free(args);
5497 }
5498
cil_gen_optional(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5499 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5500 {
5501 enum cil_syntax syntax[] = {
5502 CIL_SYN_STRING,
5503 CIL_SYN_STRING,
5504 CIL_SYN_N_LISTS | CIL_SYN_END,
5505 CIL_SYN_END
5506 };
5507 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5508 char *key = NULL;
5509 struct cil_optional *optional = NULL;
5510 int rc = SEPOL_ERR;
5511
5512 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5513 goto exit;
5514 }
5515
5516 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5517 if (rc != SEPOL_OK) {
5518 goto exit;
5519 }
5520
5521 cil_optional_init(&optional);
5522
5523 key = parse_current->next->data;
5524
5525 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
5526 if (rc != SEPOL_OK) {
5527 if (rc == SEPOL_EEXIST) {
5528 cil_destroy_optional(optional);
5529 optional = NULL;
5530 } else {
5531 goto exit;
5532 }
5533 }
5534
5535 return SEPOL_OK;
5536
5537 exit:
5538 cil_tree_log(parse_current, CIL_ERR, "Bad optional");
5539 cil_destroy_optional(optional);
5540 cil_clear_node(ast_node);
5541 return rc;
5542 }
5543
cil_destroy_optional(struct cil_optional * optional)5544 void cil_destroy_optional(struct cil_optional *optional)
5545 {
5546 if (optional == NULL) {
5547 return;
5548 }
5549
5550 cil_symtab_datum_destroy(&optional->datum);
5551 free(optional);
5552 }
5553
cil_gen_policycap(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5554 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5555 {
5556 enum cil_syntax syntax[] = {
5557 CIL_SYN_STRING,
5558 CIL_SYN_STRING,
5559 CIL_SYN_END
5560 };
5561 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5562 char *key = NULL;
5563 struct cil_policycap *polcap = NULL;
5564 int rc = SEPOL_ERR;
5565
5566 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5567 goto exit;
5568 }
5569
5570 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5571 if (rc != SEPOL_OK) {
5572 goto exit;
5573 }
5574
5575 cil_policycap_init(&polcap);
5576
5577 key = parse_current->next->data;
5578
5579 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP);
5580 if (rc != SEPOL_OK)
5581 goto exit;
5582
5583 return SEPOL_OK;
5584
5585 exit:
5586 cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
5587 cil_destroy_policycap(polcap);
5588 cil_clear_node(ast_node);
5589 return rc;
5590 }
5591
cil_destroy_policycap(struct cil_policycap * polcap)5592 void cil_destroy_policycap(struct cil_policycap *polcap)
5593 {
5594 if (polcap == NULL) {
5595 return;
5596 }
5597
5598 cil_symtab_datum_destroy(&polcap->datum);
5599 free(polcap);
5600 }
5601
cil_gen_ipaddr(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5602 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5603 {
5604 enum cil_syntax syntax[] = {
5605 CIL_SYN_STRING,
5606 CIL_SYN_STRING,
5607 CIL_SYN_STRING,
5608 CIL_SYN_END
5609 };
5610 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5611 char *key = NULL;
5612 struct cil_ipaddr *ipaddr = NULL;
5613 int rc = SEPOL_ERR;
5614
5615 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5616 goto exit;
5617 }
5618
5619 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5620 if (rc != SEPOL_OK) {
5621 goto exit;
5622 }
5623
5624 cil_ipaddr_init(&ipaddr);
5625
5626 key = parse_current->next->data;
5627
5628 rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
5629 if (rc != SEPOL_OK) {
5630 goto exit;
5631 }
5632
5633 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
5634 if (rc != SEPOL_OK) {
5635 goto exit;
5636 }
5637
5638 return SEPOL_OK;
5639
5640 exit:
5641 cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
5642 cil_destroy_ipaddr(ipaddr);
5643 cil_clear_node(ast_node);
5644 return rc;
5645 }
5646
cil_destroy_ipaddr(struct cil_ipaddr * ipaddr)5647 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
5648 {
5649 if (ipaddr == NULL) {
5650 return;
5651 }
5652
5653 cil_symtab_datum_destroy(&ipaddr->datum);
5654 free(ipaddr);
5655 }
5656
cil_fill_integer(struct cil_tree_node * int_node,uint32_t * integer,int base)5657 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
5658 {
5659 int rc = SEPOL_ERR;
5660
5661 if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5662 goto exit;
5663 }
5664
5665 rc = cil_string_to_uint32(int_node->data, integer, base);
5666 if (rc != SEPOL_OK) {
5667 goto exit;
5668 }
5669
5670 return SEPOL_OK;
5671
5672 exit:
5673 cil_log(CIL_ERR, "Failed to fill 32-bit integer\n");
5674 return rc;
5675 }
5676
cil_fill_integer64(struct cil_tree_node * int_node,uint64_t * integer,int base)5677 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
5678 {
5679 int rc = SEPOL_ERR;
5680
5681 if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5682 goto exit;
5683 }
5684
5685 rc = cil_string_to_uint64(int_node->data, integer, base);
5686 if (rc != SEPOL_OK) {
5687 goto exit;
5688 }
5689
5690 return SEPOL_OK;
5691
5692 exit:
5693 cil_log(CIL_ERR, "Failed to fill 64-bit integer\n");
5694 return rc;
5695 }
5696
cil_fill_ipaddr(struct cil_tree_node * addr_node,struct cil_ipaddr * addr)5697 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
5698 {
5699 int rc = SEPOL_ERR;
5700
5701 if (addr_node == NULL || addr_node->data == NULL || addr == NULL) {
5702 goto exit;
5703 }
5704
5705 if (strchr(addr_node->data, ':') != NULL) {
5706 addr->family = AF_INET6;
5707 } else {
5708 addr->family = AF_INET;
5709 }
5710
5711 rc = inet_pton(addr->family, addr_node->data, &addr->ip);
5712 if (rc != 1) {
5713 rc = SEPOL_ERR;
5714 goto exit;
5715 }
5716
5717 return SEPOL_OK;
5718
5719 exit:
5720 cil_log(CIL_ERR, "Bad ip address or netmask: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "n/a");
5721 return rc;
5722 }
5723
cil_fill_level(struct cil_tree_node * curr,struct cil_level * level)5724 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
5725 {
5726 int rc = SEPOL_ERR;
5727 enum cil_syntax syntax[] = {
5728 CIL_SYN_STRING,
5729 CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
5730 CIL_SYN_END
5731 };
5732 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5733
5734 if (curr == NULL) {
5735 goto exit;
5736 }
5737
5738 rc = __cil_verify_syntax(curr, syntax, syntax_len);
5739 if (rc != SEPOL_OK) {
5740 goto exit;
5741 }
5742
5743 level->sens_str = curr->data;
5744 if (curr->next != NULL) {
5745 rc = cil_fill_cats(curr->next, &level->cats);
5746 if (rc != SEPOL_OK) {
5747 goto exit;
5748 }
5749 }
5750
5751 return SEPOL_OK;
5752
5753 exit:
5754 cil_log(CIL_ERR, "Bad level\n");
5755 return rc;
5756 }
5757
cil_fill_cats(struct cil_tree_node * curr,struct cil_cats ** cats)5758 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
5759 {
5760 int rc = SEPOL_ERR;
5761
5762 cil_cats_init(cats);
5763
5764 rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
5765 if (rc != SEPOL_OK) {
5766 cil_destroy_cats(*cats);
5767 *cats = NULL;
5768 }
5769
5770 return rc;
5771 }
5772
cil_destroy_cats(struct cil_cats * cats)5773 void cil_destroy_cats(struct cil_cats *cats)
5774 {
5775 if (cats == NULL) {
5776 return;
5777 }
5778
5779 cil_list_destroy(&cats->str_expr, CIL_TRUE);
5780
5781 cil_list_destroy(&cats->datum_expr, CIL_FALSE);
5782
5783 free(cats);
5784 }
cil_gen_bounds(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5785 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5786 {
5787 enum cil_syntax syntax[] = {
5788 CIL_SYN_STRING,
5789 CIL_SYN_STRING,
5790 CIL_SYN_STRING,
5791 CIL_SYN_END
5792 };
5793 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5794 struct cil_bounds *bounds = NULL;
5795 int rc = SEPOL_ERR;
5796
5797 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5798 goto exit;
5799 }
5800
5801 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5802 if (rc != SEPOL_OK) {
5803 goto exit;
5804 }
5805
5806 cil_bounds_init(&bounds);
5807
5808 bounds->parent_str = parse_current->next->data;
5809 bounds->child_str = parse_current->next->next->data;
5810
5811 ast_node->data = bounds;
5812
5813 switch (flavor) {
5814 case CIL_USER:
5815 ast_node->flavor = CIL_USERBOUNDS;
5816 break;
5817 case CIL_ROLE:
5818 ast_node->flavor = CIL_ROLEBOUNDS;
5819 break;
5820 case CIL_TYPE:
5821 ast_node->flavor = CIL_TYPEBOUNDS;
5822 break;
5823 default:
5824 break;
5825 }
5826
5827 return SEPOL_OK;
5828
5829 exit:
5830 cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
5831 cil_destroy_bounds(bounds);
5832 return rc;
5833 }
5834
cil_destroy_bounds(struct cil_bounds * bounds)5835 void cil_destroy_bounds(struct cil_bounds *bounds)
5836 {
5837 if (bounds == NULL) {
5838 return;
5839 }
5840
5841 free(bounds);
5842 }
5843
cil_gen_default(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5844 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5845 {
5846 int rc = SEPOL_ERR;
5847 struct cil_default *def = NULL;
5848 char *object;
5849 enum cil_syntax syntax[] = {
5850 CIL_SYN_STRING,
5851 CIL_SYN_STRING | CIL_SYN_LIST,
5852 CIL_SYN_STRING,
5853 CIL_SYN_END
5854 };
5855 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5856
5857 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5858 if (rc != SEPOL_OK) {
5859 goto exit;
5860 }
5861
5862 cil_default_init(&def);
5863
5864 def->flavor = flavor;
5865
5866 if (parse_current->next->cl_head == NULL) {
5867 cil_list_init(&def->class_strs, CIL_CLASS);
5868 cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5869 } else {
5870 rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5871 if (rc != SEPOL_OK) {
5872 goto exit;
5873 }
5874 }
5875
5876 object = parse_current->next->next->data;
5877 if (object == CIL_KEY_SOURCE) {
5878 def->object = CIL_DEFAULT_SOURCE;
5879 } else if (object == CIL_KEY_TARGET) {
5880 def->object = CIL_DEFAULT_TARGET;
5881 } else {
5882 cil_log(CIL_ERR,"Expected either 'source' or 'target'\n");
5883 rc = SEPOL_ERR;
5884 goto exit;
5885 }
5886
5887 ast_node->data = def;
5888 ast_node->flavor = flavor;
5889
5890 return SEPOL_OK;
5891
5892 exit:
5893 cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current));
5894 cil_destroy_default(def);
5895 return rc;
5896 }
5897
cil_destroy_default(struct cil_default * def)5898 void cil_destroy_default(struct cil_default *def)
5899 {
5900 if (def == NULL) {
5901 return;
5902 }
5903
5904 cil_list_destroy(&def->class_strs, CIL_TRUE);
5905
5906 cil_list_destroy(&def->class_datums, CIL_FALSE);
5907
5908 free(def);
5909 }
5910
cil_gen_defaultrange(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5911 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5912 {
5913 int rc = SEPOL_ERR;
5914 struct cil_defaultrange *def = NULL;
5915 char *object;
5916 char *range;
5917 enum cil_syntax syntax[] = {
5918 CIL_SYN_STRING,
5919 CIL_SYN_STRING | CIL_SYN_LIST,
5920 CIL_SYN_STRING,
5921 CIL_SYN_STRING | CIL_SYN_END,
5922 CIL_SYN_END
5923 };
5924 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5925
5926 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5927 if (rc != SEPOL_OK) {
5928 goto exit;
5929 }
5930
5931 cil_defaultrange_init(&def);
5932
5933 if (parse_current->next->cl_head == NULL) {
5934 cil_list_init(&def->class_strs, CIL_CLASS);
5935 cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5936 } else {
5937 rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5938 if (rc != SEPOL_OK) {
5939 goto exit;
5940 }
5941 }
5942
5943 object = parse_current->next->next->data;
5944 if (object == CIL_KEY_SOURCE) {
5945 if (!parse_current->next->next->next) {
5946 cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5947 rc = SEPOL_ERR;
5948 goto exit;
5949 }
5950 range = parse_current->next->next->next->data;
5951 if (range == CIL_KEY_LOW) {
5952 def->object_range = CIL_DEFAULT_SOURCE_LOW;
5953 } else if (range == CIL_KEY_HIGH) {
5954 def->object_range = CIL_DEFAULT_SOURCE_HIGH;
5955 } else if (range == CIL_KEY_LOW_HIGH) {
5956 def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
5957 } else {
5958 cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5959 rc = SEPOL_ERR;
5960 goto exit;
5961 }
5962 } else if (object == CIL_KEY_TARGET) {
5963 if (!parse_current->next->next->next) {
5964 cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5965 rc = SEPOL_ERR;
5966 goto exit;
5967 }
5968 range = parse_current->next->next->next->data;
5969 if (range == CIL_KEY_LOW) {
5970 def->object_range = CIL_DEFAULT_TARGET_LOW;
5971 } else if (range == CIL_KEY_HIGH) {
5972 def->object_range = CIL_DEFAULT_TARGET_HIGH;
5973 } else if (range == CIL_KEY_LOW_HIGH) {
5974 def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
5975 } else {
5976 cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5977 rc = SEPOL_ERR;
5978 goto exit;
5979 }
5980 } else if (object == CIL_KEY_GLBLUB) {
5981 def->object_range = CIL_DEFAULT_GLBLUB;
5982 } else {
5983 cil_log(CIL_ERR,"Expected \'source\', \'target\', or \'glblub\'\n");
5984 rc = SEPOL_ERR;
5985 goto exit;
5986 }
5987
5988 ast_node->data = def;
5989 ast_node->flavor = CIL_DEFAULTRANGE;
5990
5991 return SEPOL_OK;
5992
5993 exit:
5994 cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
5995 cil_destroy_defaultrange(def);
5996 return rc;
5997 }
5998
cil_destroy_defaultrange(struct cil_defaultrange * def)5999 void cil_destroy_defaultrange(struct cil_defaultrange *def)
6000 {
6001 if (def == NULL) {
6002 return;
6003 }
6004
6005 cil_list_destroy(&def->class_strs, CIL_TRUE);
6006
6007 cil_list_destroy(&def->class_datums, CIL_FALSE);
6008
6009 free(def);
6010 }
6011
cil_gen_handleunknown(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6012 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6013 {
6014 int rc = SEPOL_ERR;
6015 enum cil_syntax syntax[] = {
6016 CIL_SYN_STRING,
6017 CIL_SYN_STRING,
6018 CIL_SYN_END
6019 };
6020 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6021 struct cil_handleunknown *unknown = NULL;
6022 char *unknown_key;
6023
6024 if (parse_current == NULL || ast_node == NULL) {
6025 goto exit;
6026 }
6027
6028 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6029 if (rc != SEPOL_OK) {
6030 goto exit;
6031 }
6032
6033 cil_handleunknown_init(&unknown);
6034
6035 unknown_key = parse_current->next->data;
6036 if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
6037 unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
6038 } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
6039 unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
6040 } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
6041 unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
6042 } else {
6043 cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT);
6044 rc = SEPOL_ERR;
6045 goto exit;
6046 }
6047
6048 ast_node->data = unknown;
6049 ast_node->flavor = CIL_HANDLEUNKNOWN;
6050
6051 return SEPOL_OK;
6052
6053 exit:
6054 cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
6055 cil_destroy_handleunknown(unknown);
6056 return rc;
6057 }
6058
cil_destroy_handleunknown(struct cil_handleunknown * unk)6059 void cil_destroy_handleunknown(struct cil_handleunknown *unk)
6060 {
6061 free(unk);
6062 }
6063
cil_gen_mls(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6064 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6065 {
6066 int rc = SEPOL_ERR;
6067 enum cil_syntax syntax[] = {
6068 CIL_SYN_STRING,
6069 CIL_SYN_STRING,
6070 CIL_SYN_END
6071 };
6072 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6073 struct cil_mls *mls = NULL;
6074
6075 if (parse_current == NULL || ast_node == NULL) {
6076 goto exit;
6077 }
6078
6079 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6080 if (rc != SEPOL_OK) {
6081 goto exit;
6082 }
6083
6084 cil_mls_init(&mls);
6085
6086 if (parse_current->next->data == CIL_KEY_CONDTRUE) {
6087 mls->value = CIL_TRUE;
6088 } else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
6089 mls->value = CIL_FALSE;
6090 } else {
6091 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
6092 rc = SEPOL_ERR;
6093 goto exit;
6094 }
6095
6096 ast_node->data = mls;
6097 ast_node->flavor = CIL_MLS;
6098
6099 return SEPOL_OK;
6100
6101 exit:
6102 cil_tree_log(parse_current, CIL_ERR, "Bad mls");
6103 cil_destroy_mls(mls);
6104 return rc;
6105 }
6106
cil_destroy_mls(struct cil_mls * mls)6107 void cil_destroy_mls(struct cil_mls *mls)
6108 {
6109 free(mls);
6110 }
6111
cil_gen_src_info(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6112 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6113 {
6114 int rc = SEPOL_ERR;
6115 enum cil_syntax syntax[] = {
6116 CIL_SYN_STRING,
6117 CIL_SYN_STRING,
6118 CIL_SYN_STRING,
6119 CIL_SYN_STRING,
6120 CIL_SYN_N_LISTS | CIL_SYN_END,
6121 CIL_SYN_END
6122 };
6123 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6124 struct cil_src_info *info = NULL;
6125
6126 if (parse_current == NULL || ast_node == NULL) {
6127 goto exit;
6128 }
6129
6130 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6131 if (rc != SEPOL_OK) {
6132 goto exit;
6133 }
6134
6135 cil_src_info_init(&info);
6136
6137 info->kind = parse_current->next->data;
6138 if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) {
6139 cil_log(CIL_ERR, "Invalid src info kind\n");
6140 rc = SEPOL_ERR;
6141 goto exit;
6142 }
6143
6144 rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10);
6145 if (rc != SEPOL_OK) {
6146 goto exit;
6147 }
6148
6149 info->path = parse_current->next->next->next->data;
6150
6151 ast_node->data = info;
6152 ast_node->flavor = CIL_SRC_INFO;
6153
6154 return SEPOL_OK;
6155
6156 exit:
6157 cil_tree_log(parse_current, CIL_ERR, "Bad src info");
6158 cil_destroy_src_info(info);
6159 return rc;
6160 }
6161
cil_destroy_src_info(struct cil_src_info * info)6162 void cil_destroy_src_info(struct cil_src_info *info)
6163 {
6164 free(info);
6165 }
6166
check_for_illegal_statement(struct cil_tree_node * parse_current,struct cil_args_build * args)6167 static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args)
6168 {
6169 if (args->tunif != NULL) {
6170 if (parse_current->data == CIL_KEY_TUNABLE) {
6171 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data);
6172 return SEPOL_ERR;
6173 }
6174 }
6175
6176 if (args->in != NULL) {
6177 struct cil_in *in_block = args->in->data;
6178 if (parse_current->data == CIL_KEY_TUNABLE ||
6179 parse_current->data == CIL_KEY_IN) {
6180 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data);
6181 return SEPOL_ERR;
6182 }
6183 if (in_block->is_after == CIL_TRUE) {
6184 if (parse_current->data == CIL_KEY_BLOCKINHERIT ||
6185 parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6186 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data);
6187 return SEPOL_ERR;
6188 }
6189 }
6190 }
6191
6192 if (args->macro != NULL) {
6193 if (parse_current->data == CIL_KEY_TUNABLE ||
6194 parse_current->data == CIL_KEY_IN ||
6195 parse_current->data == CIL_KEY_BLOCK ||
6196 parse_current->data == CIL_KEY_BLOCKINHERIT ||
6197 parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6198 parse_current->data == CIL_KEY_MACRO) {
6199 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data);
6200 return SEPOL_ERR;
6201 }
6202 }
6203
6204 if (args->optional != NULL) {
6205 if (parse_current->data == CIL_KEY_TUNABLE ||
6206 parse_current->data == CIL_KEY_IN ||
6207 parse_current->data == CIL_KEY_BLOCK ||
6208 parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6209 parse_current->data == CIL_KEY_MACRO) {
6210 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data);
6211 return SEPOL_ERR;
6212 }
6213 }
6214
6215 if (args->boolif != NULL) {
6216 if (parse_current->data != CIL_KEY_TUNABLEIF &&
6217 parse_current->data != CIL_KEY_CALL &&
6218 parse_current->data != CIL_KEY_CONDTRUE &&
6219 parse_current->data != CIL_KEY_CONDFALSE &&
6220 parse_current->data != CIL_KEY_ALLOW &&
6221 parse_current->data != CIL_KEY_DONTAUDIT &&
6222 parse_current->data != CIL_KEY_AUDITALLOW &&
6223 parse_current->data != CIL_KEY_TYPETRANSITION &&
6224 parse_current->data != CIL_KEY_TYPECHANGE &&
6225 parse_current->data != CIL_KEY_TYPEMEMBER) {
6226 if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) {
6227 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data);
6228 } else {
6229 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data);
6230 }
6231 return SEPOL_ERR;
6232 }
6233 }
6234
6235 return SEPOL_OK;
6236 }
6237
parse_statement(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_parent)6238 static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent)
6239 {
6240 struct cil_tree_node *new_ast_node = NULL;
6241 int rc = SEPOL_ERR;
6242
6243 cil_tree_node_init(&new_ast_node);
6244 new_ast_node->parent = ast_parent;
6245 new_ast_node->line = parse_current->line;
6246 new_ast_node->hll_offset = parse_current->hll_offset;
6247
6248 if (parse_current->data == CIL_KEY_BLOCK) {
6249 rc = cil_gen_block(db, parse_current, new_ast_node, 0);
6250 } else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
6251 rc = cil_gen_blockinherit(db, parse_current, new_ast_node);
6252 } else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6253 rc = cil_gen_blockabstract(db, parse_current, new_ast_node);
6254 } else if (parse_current->data == CIL_KEY_IN) {
6255 rc = cil_gen_in(db, parse_current, new_ast_node);
6256 } else if (parse_current->data == CIL_KEY_CLASS) {
6257 rc = cil_gen_class(db, parse_current, new_ast_node);
6258 } else if (parse_current->data == CIL_KEY_CLASSORDER) {
6259 rc = cil_gen_classorder(db, parse_current, new_ast_node);
6260 } else if (parse_current->data == CIL_KEY_MAP_CLASS) {
6261 rc = cil_gen_map_class(db, parse_current, new_ast_node);
6262 } else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
6263 rc = cil_gen_classmapping(db, parse_current, new_ast_node);
6264 } else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
6265 rc = cil_gen_classpermission(db, parse_current, new_ast_node);
6266 } else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
6267 rc = cil_gen_classpermissionset(db, parse_current, new_ast_node);
6268 } else if (parse_current->data == CIL_KEY_COMMON) {
6269 rc = cil_gen_common(db, parse_current, new_ast_node);
6270 } else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
6271 rc = cil_gen_classcommon(db, parse_current, new_ast_node);
6272 } else if (parse_current->data == CIL_KEY_SID) {
6273 rc = cil_gen_sid(db, parse_current, new_ast_node);
6274 } else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
6275 rc = cil_gen_sidcontext(db, parse_current, new_ast_node);
6276 } else if (parse_current->data == CIL_KEY_SIDORDER) {
6277 rc = cil_gen_sidorder(db, parse_current, new_ast_node);
6278 } else if (parse_current->data == CIL_KEY_USER) {
6279 rc = cil_gen_user(db, parse_current, new_ast_node);
6280 } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
6281 rc = cil_gen_userattribute(db, parse_current, new_ast_node);
6282 } else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
6283 rc = cil_gen_userattributeset(db, parse_current, new_ast_node);
6284 } else if (parse_current->data == CIL_KEY_USERLEVEL) {
6285 rc = cil_gen_userlevel(db, parse_current, new_ast_node);
6286 } else if (parse_current->data == CIL_KEY_USERRANGE) {
6287 rc = cil_gen_userrange(db, parse_current, new_ast_node);
6288 } else if (parse_current->data == CIL_KEY_USERBOUNDS) {
6289 rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER);
6290 } else if (parse_current->data == CIL_KEY_USERPREFIX) {
6291 rc = cil_gen_userprefix(db, parse_current, new_ast_node);
6292 } else if (parse_current->data == CIL_KEY_SELINUXUSER) {
6293 rc = cil_gen_selinuxuser(db, parse_current, new_ast_node);
6294 } else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
6295 rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node);
6296 } else if (parse_current->data == CIL_KEY_TYPE) {
6297 rc = cil_gen_type(db, parse_current, new_ast_node);
6298 } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
6299 rc = cil_gen_typeattribute(db, parse_current, new_ast_node);
6300 } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
6301 rc = cil_gen_typeattributeset(db, parse_current, new_ast_node);
6302 } else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
6303 rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node);
6304 } else if (parse_current->data == CIL_KEY_TYPEALIAS) {
6305 rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS);
6306 } else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
6307 rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL);
6308 } else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
6309 rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE);
6310 } else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
6311 rc = cil_gen_typepermissive(db, parse_current, new_ast_node);
6312 } else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
6313 rc = cil_gen_rangetransition(db, parse_current, new_ast_node);
6314 } else if (parse_current->data == CIL_KEY_ROLE) {
6315 rc = cil_gen_role(db, parse_current, new_ast_node);
6316 } else if (parse_current->data == CIL_KEY_USERROLE) {
6317 rc = cil_gen_userrole(db, parse_current, new_ast_node);
6318 } else if (parse_current->data == CIL_KEY_ROLETYPE) {
6319 rc = cil_gen_roletype(db, parse_current, new_ast_node);
6320 } else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
6321 rc = cil_gen_roletransition(parse_current, new_ast_node);
6322 } else if (parse_current->data == CIL_KEY_ROLEALLOW) {
6323 rc = cil_gen_roleallow(db, parse_current, new_ast_node);
6324 } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
6325 rc = cil_gen_roleattribute(db, parse_current, new_ast_node);
6326 } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
6327 rc = cil_gen_roleattributeset(db, parse_current, new_ast_node);
6328 } else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
6329 rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE);
6330 } else if (parse_current->data == CIL_KEY_BOOL) {
6331 rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE);
6332 } else if (parse_current->data == CIL_KEY_BOOLEANIF) {
6333 rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE);
6334 } else if(parse_current->data == CIL_KEY_TUNABLE) {
6335 if (db->preserve_tunables) {
6336 rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE);
6337 } else {
6338 rc = cil_gen_tunable(db, parse_current, new_ast_node);
6339 }
6340 } else if (parse_current->data == CIL_KEY_TUNABLEIF) {
6341 if (db->preserve_tunables) {
6342 rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE);
6343 } else {
6344 rc = cil_gen_tunif(db, parse_current, new_ast_node);
6345 }
6346 } else if (parse_current->data == CIL_KEY_CONDTRUE) {
6347 rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE);
6348 } else if (parse_current->data == CIL_KEY_CONDFALSE) {
6349 rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE);
6350 } else if (parse_current->data == CIL_KEY_ALLOW) {
6351 rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6352 } else if (parse_current->data == CIL_KEY_AUDITALLOW) {
6353 rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6354 } else if (parse_current->data == CIL_KEY_DONTAUDIT) {
6355 rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6356 } else if (parse_current->data == CIL_KEY_NEVERALLOW) {
6357 rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6358 } else if (parse_current->data == CIL_KEY_ALLOWX) {
6359 rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6360 } else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
6361 rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6362 } else if (parse_current->data == CIL_KEY_DONTAUDITX) {
6363 rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6364 } else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
6365 rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6366 } else if (parse_current->data == CIL_KEY_PERMISSIONX) {
6367 rc = cil_gen_permissionx(db, parse_current, new_ast_node);
6368 } else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
6369 rc = cil_gen_typetransition(db, parse_current, new_ast_node);
6370 } else if (parse_current->data == CIL_KEY_TYPECHANGE) {
6371 rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE);
6372 } else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
6373 rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER);
6374 } else if (parse_current->data == CIL_KEY_SENSITIVITY) {
6375 rc = cil_gen_sensitivity(db, parse_current, new_ast_node);
6376 } else if (parse_current->data == CIL_KEY_SENSALIAS) {
6377 rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS);
6378 } else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
6379 rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL);
6380 } else if (parse_current->data == CIL_KEY_CATEGORY) {
6381 rc = cil_gen_category(db, parse_current, new_ast_node);
6382 } else if (parse_current->data == CIL_KEY_CATALIAS) {
6383 rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS);
6384 } else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
6385 rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL);
6386 } else if (parse_current->data == CIL_KEY_CATSET) {
6387 rc = cil_gen_catset(db, parse_current, new_ast_node);
6388 } else if (parse_current->data == CIL_KEY_CATORDER) {
6389 rc = cil_gen_catorder(db, parse_current, new_ast_node);
6390 } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
6391 rc = cil_gen_sensitivityorder(db, parse_current, new_ast_node);
6392 } else if (parse_current->data == CIL_KEY_SENSCAT) {
6393 rc = cil_gen_senscat(db, parse_current, new_ast_node);
6394 } else if (parse_current->data == CIL_KEY_LEVEL) {
6395 rc = cil_gen_level(db, parse_current, new_ast_node);
6396 } else if (parse_current->data == CIL_KEY_LEVELRANGE) {
6397 rc = cil_gen_levelrange(db, parse_current, new_ast_node);
6398 } else if (parse_current->data == CIL_KEY_CONSTRAIN) {
6399 rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN);
6400 } else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
6401 rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN);
6402 } else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
6403 rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS);
6404 } else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
6405 rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS);
6406 } else if (parse_current->data == CIL_KEY_CONTEXT) {
6407 rc = cil_gen_context(db, parse_current, new_ast_node);
6408 } else if (parse_current->data == CIL_KEY_FILECON) {
6409 rc = cil_gen_filecon(db, parse_current, new_ast_node);
6410 } else if (parse_current->data == CIL_KEY_IBPKEYCON) {
6411 rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node);
6412 } else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
6413 rc = cil_gen_ibendportcon(db, parse_current, new_ast_node);
6414 } else if (parse_current->data == CIL_KEY_PORTCON) {
6415 rc = cil_gen_portcon(db, parse_current, new_ast_node);
6416 } else if (parse_current->data == CIL_KEY_NODECON) {
6417 rc = cil_gen_nodecon(db, parse_current, new_ast_node);
6418 } else if (parse_current->data == CIL_KEY_GENFSCON) {
6419 rc = cil_gen_genfscon(db, parse_current, new_ast_node);
6420 } else if (parse_current->data == CIL_KEY_NETIFCON) {
6421 rc = cil_gen_netifcon(db, parse_current, new_ast_node);
6422 } else if (parse_current->data == CIL_KEY_PIRQCON) {
6423 rc = cil_gen_pirqcon(db, parse_current, new_ast_node);
6424 } else if (parse_current->data == CIL_KEY_IOMEMCON) {
6425 rc = cil_gen_iomemcon(db, parse_current, new_ast_node);
6426 } else if (parse_current->data == CIL_KEY_IOPORTCON) {
6427 rc = cil_gen_ioportcon(db, parse_current, new_ast_node);
6428 } else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
6429 rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node);
6430 } else if (parse_current->data == CIL_KEY_DEVICETREECON) {
6431 rc = cil_gen_devicetreecon(db, parse_current, new_ast_node);
6432 } else if (parse_current->data == CIL_KEY_FSUSE) {
6433 rc = cil_gen_fsuse(db, parse_current, new_ast_node);
6434 } else if (parse_current->data == CIL_KEY_MACRO) {
6435 rc = cil_gen_macro(db, parse_current, new_ast_node);
6436 } else if (parse_current->data == CIL_KEY_CALL) {
6437 rc = cil_gen_call(db, parse_current, new_ast_node);
6438 } else if (parse_current->data == CIL_KEY_POLICYCAP) {
6439 rc = cil_gen_policycap(db, parse_current, new_ast_node);
6440 } else if (parse_current->data == CIL_KEY_OPTIONAL) {
6441 rc = cil_gen_optional(db, parse_current, new_ast_node);
6442 } else if (parse_current->data == CIL_KEY_IPADDR) {
6443 rc = cil_gen_ipaddr(db, parse_current, new_ast_node);
6444 } else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
6445 rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER);
6446 } else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
6447 rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE);
6448 } else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
6449 rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE);
6450 } else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
6451 rc = cil_gen_defaultrange(parse_current, new_ast_node);
6452 } else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
6453 rc = cil_gen_handleunknown(parse_current, new_ast_node);
6454 } else if (parse_current->data == CIL_KEY_MLS) {
6455 rc = cil_gen_mls(parse_current, new_ast_node);
6456 } else if (parse_current->data == CIL_KEY_SRC_INFO) {
6457 rc = cil_gen_src_info(parse_current, new_ast_node);
6458 } else {
6459 cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
6460 rc = SEPOL_ERR;
6461 }
6462
6463 if (rc == SEPOL_OK) {
6464 if (ast_parent->cl_head == NULL) {
6465 ast_parent->cl_head = new_ast_node;
6466 } else {
6467 ast_parent->cl_tail->next = new_ast_node;
6468 }
6469 ast_parent->cl_tail = new_ast_node;
6470 } else {
6471 cil_tree_node_destroy(&new_ast_node);
6472 new_ast_node = NULL;
6473 }
6474
6475 return new_ast_node;
6476 }
6477
__cil_build_ast_node_helper(struct cil_tree_node * parse_current,uint32_t * finished,void * extra_args)6478 static int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
6479 {
6480 struct cil_args_build *args = extra_args;
6481 struct cil_tree_node *new_ast_node = NULL;
6482 int rc = SEPOL_ERR;
6483
6484 if (parse_current->parent->cl_head != parse_current) {
6485 /* ignore anything that isn't following a parenthesis */
6486 return SEPOL_OK;
6487 } else if (parse_current->data == NULL) {
6488 /* the only time parenthesis can immediately following parenthesis is if
6489 * the parent is the root node */
6490 if (parse_current->parent->parent == NULL) {
6491 return SEPOL_OK;
6492 } else {
6493 cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
6494 return SEPOL_ERR;
6495 }
6496 }
6497
6498 rc = check_for_illegal_statement(parse_current, args);
6499 if (rc != SEPOL_OK) {
6500 return SEPOL_ERR;
6501 }
6502
6503 new_ast_node = parse_statement(args->db, parse_current, args->ast);
6504 if (!new_ast_node) {
6505 return SEPOL_ERR;
6506 }
6507
6508 args->ast = new_ast_node;
6509
6510 if (parse_current->data != CIL_KEY_BLOCK &&
6511 parse_current->data != CIL_KEY_IN &&
6512 parse_current->data != CIL_KEY_TUNABLEIF &&
6513 parse_current->data != CIL_KEY_BOOLEANIF &&
6514 parse_current->data != CIL_KEY_CONDTRUE &&
6515 parse_current->data != CIL_KEY_CONDFALSE &&
6516 parse_current->data != CIL_KEY_MACRO &&
6517 parse_current->data != CIL_KEY_OPTIONAL &&
6518 parse_current->data != CIL_KEY_SRC_INFO) {
6519 /* Skip anything that does not contain a list of policy statements */
6520 *finished = CIL_TREE_SKIP_NEXT;
6521 }
6522
6523 return SEPOL_OK;
6524 }
6525
__cil_build_ast_first_child_helper(struct cil_tree_node * parse_current,void * extra_args)6526 static int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args)
6527 {
6528 struct cil_args_build *args = extra_args;
6529 struct cil_tree_node *ast = args->ast;
6530
6531 if (ast->flavor == CIL_TUNABLEIF) {
6532 args->tunif = ast;
6533 } else if (ast->flavor == CIL_IN) {
6534 args->in = ast;
6535 } else if (ast->flavor == CIL_MACRO) {
6536 args->macro = ast;
6537 } else if (ast->flavor == CIL_OPTIONAL) {
6538 args->optional = ast;
6539 } else if (ast->flavor == CIL_BOOLEANIF) {
6540 args->boolif = ast;
6541 }
6542
6543 return SEPOL_OK;
6544 }
6545
__cil_build_ast_last_child_helper(struct cil_tree_node * parse_current,void * extra_args)6546 static int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
6547 {
6548 struct cil_args_build *args = extra_args;
6549 struct cil_tree_node *ast = args->ast;
6550
6551 if (ast->flavor == CIL_ROOT) {
6552 return SEPOL_OK;
6553 }
6554
6555 args->ast = ast->parent;
6556
6557 if (ast->flavor == CIL_TUNABLEIF) {
6558 args->tunif = NULL;
6559 }
6560
6561 if (ast->flavor == CIL_IN) {
6562 args->in = NULL;
6563 }
6564
6565 if (ast->flavor == CIL_MACRO) {
6566 args->macro = NULL;
6567 }
6568
6569 if (ast->flavor == CIL_OPTIONAL) {
6570 struct cil_tree_node *n = ast->parent;
6571 args->optional = NULL;
6572 /* Optionals can be nested */
6573 while (n && n->flavor != CIL_ROOT) {
6574 if (n->flavor == CIL_OPTIONAL) {
6575 args->optional = n;
6576 break;
6577 }
6578 n = n->parent;
6579 }
6580 }
6581
6582 if (ast->flavor == CIL_BOOLEANIF) {
6583 args->boolif = NULL;
6584 }
6585
6586 // At this point we no longer have any need for parse_current or any of its
6587 // siblings; they have all been converted to the appropriate AST node. The
6588 // full parse tree will get deleted elsewhere, but in an attempt to
6589 // minimize memory usage (of which the parse tree uses a lot), start
6590 // deleting the parts we don't need now.
6591 cil_tree_children_destroy(parse_current->parent);
6592
6593 return SEPOL_OK;
6594 }
6595
cil_build_ast(struct cil_db * db,struct cil_tree_node * parse_tree,struct cil_tree_node * ast)6596 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
6597 {
6598 int rc = SEPOL_ERR;
6599 struct cil_args_build extra_args;
6600
6601 if (db == NULL || parse_tree == NULL || ast == NULL) {
6602 goto exit;
6603 }
6604
6605 extra_args.ast = ast;
6606 extra_args.db = db;
6607 extra_args.tunif = NULL;
6608 extra_args.in = NULL;
6609 extra_args.macro = NULL;
6610 extra_args.optional = NULL;
6611 extra_args.boolif = NULL;
6612
6613 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);
6614 if (rc != SEPOL_OK) {
6615 goto exit;
6616 }
6617
6618 return SEPOL_OK;
6619
6620 exit:
6621 return rc;
6622 }
6623