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