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