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 {
2157 cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\"\n", (char *)parse_current->data);
2158 rc = SEPOL_ERR;
2159 goto exit;
2160 }
2161
2162 permx->obj_str = parse_current->next->data;
2163
2164 rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX, &permx->expr_str);
2165 if (rc != SEPOL_OK) {
2166 goto exit;
2167 }
2168
2169 return SEPOL_OK;
2170
2171 exit:
2172 cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content");
2173 return rc;
2174 }
2175
cil_gen_permissionx(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2176 int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2177 {
2178 enum cil_syntax syntax[] = {
2179 CIL_SYN_STRING,
2180 CIL_SYN_STRING,
2181 CIL_SYN_LIST,
2182 CIL_SYN_END
2183 };
2184 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2185 char *key = NULL;
2186 struct cil_permissionx *permx = NULL;
2187 int rc = SEPOL_ERR;
2188
2189 if (parse_current == NULL || ast_node == NULL) {
2190 goto exit;
2191 }
2192
2193 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2194 if (rc != SEPOL_OK) {
2195 goto exit;
2196 }
2197
2198 cil_permissionx_init(&permx);
2199
2200 key = parse_current->next->data;
2201
2202 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)permx, (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX);
2203 if (rc != SEPOL_OK) {
2204 goto exit;
2205 }
2206
2207 rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx);
2208 if (rc != SEPOL_OK) {
2209 goto exit;
2210 }
2211
2212 return SEPOL_OK;
2213
2214 exit:
2215 cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement");
2216 cil_destroy_permissionx(permx);
2217 cil_clear_node(ast_node);
2218 return rc;
2219 }
2220
cil_destroy_permissionx(struct cil_permissionx * permx)2221 void cil_destroy_permissionx(struct cil_permissionx *permx)
2222 {
2223 if (permx == NULL) {
2224 return;
2225 }
2226
2227 cil_symtab_datum_destroy(&permx->datum);
2228
2229 cil_list_destroy(&permx->expr_str, CIL_TRUE);
2230 ebitmap_destroy(permx->perms);
2231 free(permx->perms);
2232 free(permx);
2233 }
2234
cil_gen_avrulex(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint32_t rule_kind)2235 int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
2236 {
2237 enum cil_syntax syntax[] = {
2238 CIL_SYN_STRING,
2239 CIL_SYN_STRING,
2240 CIL_SYN_STRING,
2241 CIL_SYN_STRING | CIL_SYN_LIST,
2242 CIL_SYN_END
2243 };
2244 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2245 struct cil_avrule *rule = NULL;
2246 int rc = SEPOL_ERR;
2247
2248 if (parse_current == NULL || ast_node == NULL) {
2249 goto exit;
2250 }
2251
2252 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2253 if (rc != SEPOL_OK) {
2254 goto exit;
2255 }
2256
2257 cil_avrule_init(&rule);
2258
2259 rule->is_extended = 1;
2260 rule->rule_kind = rule_kind;
2261 rule->src_str = parse_current->next->data;
2262 rule->tgt_str = parse_current->next->next->data;
2263
2264 if (parse_current->next->next->next->cl_head == NULL) {
2265 rule->perms.x.permx_str = parse_current->next->next->next->data;
2266 } else {
2267 cil_permissionx_init(&rule->perms.x.permx);
2268
2269 rc = cil_fill_permissionx(parse_current->next->next->next->cl_head, rule->perms.x.permx);
2270 if (rc != SEPOL_OK) {
2271 goto exit;
2272 }
2273 }
2274
2275 ast_node->data = rule;
2276 ast_node->flavor = CIL_AVRULEX;
2277
2278 return SEPOL_OK;
2279
2280 exit:
2281 cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule");
2282 cil_destroy_avrule(rule);
2283 return rc;
2284 }
2285
cil_gen_deny_rule(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2286 int cil_gen_deny_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2287 {
2288 enum cil_syntax syntax[] = {
2289 CIL_SYN_STRING,
2290 CIL_SYN_STRING,
2291 CIL_SYN_STRING,
2292 CIL_SYN_STRING | CIL_SYN_LIST,
2293 CIL_SYN_END
2294 };
2295 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2296 struct cil_deny_rule *rule = NULL;
2297 int rc = SEPOL_ERR;
2298
2299 if (parse_current == NULL || ast_node == NULL) {
2300 goto exit;
2301 }
2302
2303 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2304 if (rc != SEPOL_OK) {
2305 goto exit;
2306 }
2307
2308 cil_deny_rule_init(&rule);
2309
2310 rule->src_str = parse_current->next->data;
2311 rule->tgt_str = parse_current->next->next->data;
2312
2313 rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->classperms);
2314 if (rc != SEPOL_OK) {
2315 goto exit;
2316 }
2317
2318 ast_node->data = rule;
2319 ast_node->flavor = CIL_DENY_RULE;
2320
2321 return SEPOL_OK;
2322
2323 exit:
2324 cil_tree_log(parse_current, CIL_ERR, "Bad deny rule");
2325 cil_destroy_deny_rule(rule);
2326 return rc;
2327 }
2328
cil_destroy_deny_rule(struct cil_deny_rule * rule)2329 void cil_destroy_deny_rule(struct cil_deny_rule *rule)
2330 {
2331 if (rule == NULL) {
2332 return;
2333 }
2334
2335 cil_destroy_classperms_list(&rule->classperms);
2336
2337 free(rule);
2338 }
2339
cil_gen_type_rule(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,uint32_t rule_kind)2340 int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind)
2341 {
2342 enum cil_syntax syntax[] = {
2343 CIL_SYN_STRING,
2344 CIL_SYN_STRING,
2345 CIL_SYN_STRING,
2346 CIL_SYN_STRING,
2347 CIL_SYN_STRING,
2348 CIL_SYN_END
2349 };
2350 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2351 struct cil_type_rule *rule = NULL;
2352 int rc = SEPOL_ERR;
2353
2354 if (parse_current == NULL || ast_node == NULL) {
2355 goto exit;
2356 }
2357
2358 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2359 if (rc != SEPOL_OK) {
2360 goto exit;
2361 }
2362
2363 cil_type_rule_init(&rule);
2364
2365 rule->rule_kind = rule_kind;
2366 rule->src_str = parse_current->next->data;
2367 rule->tgt_str = parse_current->next->next->data;
2368 rule->obj_str = parse_current->next->next->next->data;
2369 rule->result_str = parse_current->next->next->next->next->data;
2370
2371 ast_node->data = rule;
2372 ast_node->flavor = CIL_TYPE_RULE;
2373
2374 return SEPOL_OK;
2375
2376 exit:
2377 cil_tree_log(parse_current, CIL_ERR, "Bad type rule");
2378 cil_destroy_type_rule(rule);
2379 return rc;
2380 }
2381
cil_destroy_type_rule(struct cil_type_rule * rule)2382 void cil_destroy_type_rule(struct cil_type_rule *rule)
2383 {
2384 if (rule == NULL) {
2385 return;
2386 }
2387
2388 free(rule);
2389 }
2390
cil_gen_type(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2391 int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2392 {
2393 enum cil_syntax syntax[] = {
2394 CIL_SYN_STRING,
2395 CIL_SYN_STRING,
2396 CIL_SYN_END
2397 };
2398 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2399 char *key = NULL;
2400 struct cil_type *type = NULL;
2401 int rc = SEPOL_ERR;
2402
2403 if (db == NULL || parse_current == NULL || ast_node == NULL) {
2404 goto exit;
2405 }
2406
2407 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2408 if (rc != SEPOL_OK) {
2409 goto exit;
2410 }
2411
2412 cil_type_init(&type);
2413
2414 key = parse_current->next->data;
2415 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE);
2416 if (rc != SEPOL_OK) {
2417 if (rc == SEPOL_EEXIST) {
2418 cil_destroy_type(type);
2419 type = NULL;
2420 } else {
2421 goto exit;
2422 }
2423 }
2424
2425 return SEPOL_OK;
2426
2427 exit:
2428 cil_tree_log(parse_current, CIL_ERR, "Bad type declaration");
2429 cil_destroy_type(type);
2430 cil_clear_node(ast_node);
2431 return rc;
2432 }
2433
cil_destroy_type(struct cil_type * type)2434 void cil_destroy_type(struct cil_type *type)
2435 {
2436 if (type == NULL) {
2437 return;
2438 }
2439
2440 cil_symtab_datum_destroy(&type->datum);
2441 free(type);
2442 }
2443
cil_gen_typeattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2444 int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2445 {
2446 enum cil_syntax syntax[] = {
2447 CIL_SYN_STRING,
2448 CIL_SYN_STRING,
2449 CIL_SYN_END
2450 };
2451 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2452 char *key = NULL;
2453 struct cil_typeattribute *attr = NULL;
2454 int rc = SEPOL_ERR;
2455
2456 if (db == NULL || parse_current == NULL || ast_node == NULL) {
2457 goto exit;
2458 }
2459
2460 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2461 if (rc != SEPOL_OK) {
2462 goto exit;
2463 }
2464
2465 cil_typeattribute_init(&attr);
2466
2467 key = parse_current->next->data;
2468 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
2469 if (rc != SEPOL_OK) {
2470 if (rc == SEPOL_EEXIST) {
2471 cil_destroy_typeattribute(attr);
2472 attr = NULL;
2473 } else {
2474 goto exit;
2475 }
2476 }
2477
2478 return SEPOL_OK;
2479
2480 exit:
2481 cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration");
2482 cil_destroy_typeattribute(attr);
2483 cil_clear_node(ast_node);
2484 return rc;
2485 }
2486
cil_destroy_typeattribute(struct cil_typeattribute * attr)2487 void cil_destroy_typeattribute(struct cil_typeattribute *attr)
2488 {
2489 if (attr == NULL) {
2490 return;
2491 }
2492
2493 cil_symtab_datum_destroy(&attr->datum);
2494
2495 if (attr->expr_list != NULL) {
2496 /* we don't want to destroy the expression stacks (cil_list) inside
2497 * this list cil_list_destroy destroys sublists, so we need to do it
2498 * manually */
2499 struct cil_list_item *expr = attr->expr_list->head;
2500 while (expr != NULL) {
2501 struct cil_list_item *next = expr->next;
2502 cil_list_item_destroy(&expr, CIL_FALSE);
2503 expr = next;
2504 }
2505 free(attr->expr_list);
2506 attr->expr_list = NULL;
2507 }
2508 ebitmap_destroy(attr->types);
2509 free(attr->types);
2510 free(attr);
2511 }
2512
cil_gen_bool(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,int tunableif)2513 int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif)
2514 {
2515 enum cil_syntax syntax[] = {
2516 CIL_SYN_STRING,
2517 CIL_SYN_STRING,
2518 CIL_SYN_STRING,
2519 CIL_SYN_END
2520 };
2521 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2522 char *key = NULL;
2523 struct cil_bool *boolean = NULL;
2524 int rc = SEPOL_ERR;
2525
2526 if (db == NULL || parse_current == NULL || ast_node == NULL) {
2527 goto exit;
2528 }
2529
2530 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2531 if (rc != SEPOL_OK) {
2532 goto exit;
2533 }
2534
2535 cil_bool_init(&boolean);
2536
2537 key = parse_current->next->data;
2538
2539 if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
2540 boolean->value = CIL_TRUE;
2541 } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
2542 boolean->value = CIL_FALSE;
2543 } else {
2544 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
2545 rc = SEPOL_ERR;
2546 goto exit;
2547 }
2548
2549 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)boolean, (hashtab_key_t)key, CIL_SYM_BOOLS, CIL_BOOL);
2550 if (rc != SEPOL_OK) {
2551 goto exit;
2552 }
2553
2554 return SEPOL_OK;
2555
2556 exit:
2557 if (tunableif) {
2558 cil_tree_log(parse_current, CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration");
2559 } else {
2560 cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration");
2561 }
2562 cil_destroy_bool(boolean);
2563 cil_clear_node(ast_node);
2564 return rc;
2565 }
2566
cil_destroy_bool(struct cil_bool * boolean)2567 void cil_destroy_bool(struct cil_bool *boolean)
2568 {
2569 if (boolean == NULL) {
2570 return;
2571 }
2572
2573 cil_symtab_datum_destroy(&boolean->datum);
2574 free(boolean);
2575 }
2576
cil_gen_tunable(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2577 int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2578 {
2579 enum cil_syntax syntax[] = {
2580 CIL_SYN_STRING,
2581 CIL_SYN_STRING,
2582 CIL_SYN_STRING,
2583 CIL_SYN_END
2584 };
2585 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2586 char *key = NULL;
2587 struct cil_tunable *tunable = NULL;
2588 int rc = SEPOL_ERR;
2589
2590 if (db == NULL || parse_current == NULL || ast_node == NULL) {
2591 goto exit;
2592 }
2593
2594 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2595 if (rc != SEPOL_OK) {
2596 goto exit;
2597 }
2598
2599 cil_tunable_init(&tunable);
2600
2601 key = parse_current->next->data;
2602
2603 if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
2604 tunable->value = CIL_TRUE;
2605 } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
2606 tunable->value = CIL_FALSE;
2607 } else {
2608 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
2609 rc = SEPOL_ERR;
2610 goto exit;
2611 }
2612
2613 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)tunable, (hashtab_key_t)key, CIL_SYM_TUNABLES, CIL_TUNABLE);
2614 if (rc != SEPOL_OK) {
2615 goto exit;
2616 }
2617
2618 return SEPOL_OK;
2619
2620 exit:
2621 cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration");
2622 cil_destroy_tunable(tunable);
2623 cil_clear_node(ast_node);
2624 return rc;
2625 }
2626
cil_destroy_tunable(struct cil_tunable * tunable)2627 void cil_destroy_tunable(struct cil_tunable *tunable)
2628 {
2629 if (tunable == NULL) {
2630 return;
2631 }
2632
2633 cil_symtab_datum_destroy(&tunable->datum);
2634 free(tunable);
2635 }
2636
__cil_get_expr_operator_flavor(const char * op)2637 static enum cil_flavor __cil_get_expr_operator_flavor(const char *op)
2638 {
2639 if (op == NULL) return CIL_NONE;
2640 else if (op == CIL_KEY_AND) return CIL_AND;
2641 else if (op == CIL_KEY_OR) return CIL_OR;
2642 else if (op == CIL_KEY_NOT) return CIL_NOT;
2643 else if (op == CIL_KEY_EQ) return CIL_EQ; /* Only conditional */
2644 else if (op == CIL_KEY_NEQ) return CIL_NEQ; /* Only conditional */
2645 else if (op == CIL_KEY_XOR) return CIL_XOR;
2646 else if (op == CIL_KEY_ALL) return CIL_ALL; /* Only set and permissionx */
2647 else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset and permissionx */
2648 else return CIL_NONE;
2649 }
2650
2651 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr);
2652
__cil_fill_expr_helper(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list * expr)2653 static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
2654 {
2655 int rc = SEPOL_ERR;
2656 enum cil_flavor op;
2657
2658 op = __cil_get_expr_operator_flavor(current->data);
2659
2660 rc = cil_verify_expr_syntax(current, op, flavor);
2661 if (rc != SEPOL_OK) {
2662 goto exit;
2663 }
2664
2665 if (op != CIL_NONE) {
2666 cil_list_append(expr, CIL_OP, (void *)op);
2667 current = current->next;
2668 }
2669
2670 for (;current != NULL; current = current->next) {
2671 rc = __cil_fill_expr(current, flavor, expr);
2672 if (rc != SEPOL_OK) {
2673 goto exit;
2674 }
2675 }
2676
2677 return SEPOL_OK;
2678
2679 exit:
2680 return rc;
2681 }
2682
__cil_fill_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list * expr)2683 static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr)
2684 {
2685 int rc = SEPOL_ERR;
2686
2687 if (current->cl_head == NULL) {
2688 enum cil_flavor op = __cil_get_expr_operator_flavor(current->data);
2689 if (op != CIL_NONE) {
2690 cil_log(CIL_ERR, "Operator (%s) not in an expression\n", (char*)current->data);
2691 goto exit;
2692 }
2693 cil_list_append(expr, CIL_STRING, current->data);
2694 } else {
2695 struct cil_list *sub_expr;
2696 cil_list_init(&sub_expr, flavor);
2697 rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr);
2698 if (rc != SEPOL_OK) {
2699 cil_list_destroy(&sub_expr, CIL_TRUE);
2700 goto exit;
2701 }
2702 cil_list_append(expr, CIL_LIST, sub_expr);
2703 }
2704
2705 return SEPOL_OK;
2706
2707 exit:
2708 return rc;
2709 }
2710
2711
cil_gen_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2712 int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2713 {
2714 int rc = SEPOL_ERR;
2715
2716 cil_list_init(expr, flavor);
2717
2718 if (current->cl_head == NULL) {
2719 rc = __cil_fill_expr(current, flavor, *expr);
2720 } else {
2721 rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr);
2722 }
2723
2724 if (rc != SEPOL_OK) {
2725 cil_list_destroy(expr, CIL_TRUE);
2726 cil_log(CIL_ERR, "Bad expression\n");
2727 }
2728
2729 return rc;
2730 }
2731
__cil_get_constraint_operator_flavor(const char * op)2732 static enum cil_flavor __cil_get_constraint_operator_flavor(const char *op)
2733 {
2734 if (op == CIL_KEY_AND) return CIL_AND;
2735 else if (op == CIL_KEY_OR) return CIL_OR;
2736 else if (op == CIL_KEY_NOT) return CIL_NOT;
2737 else if (op == CIL_KEY_EQ) return CIL_EQ;
2738 else if (op == CIL_KEY_NEQ) return CIL_NEQ;
2739 else if (op == CIL_KEY_CONS_DOM) return CIL_CONS_DOM;
2740 else if (op == CIL_KEY_CONS_DOMBY) return CIL_CONS_DOMBY;
2741 else if (op == CIL_KEY_CONS_INCOMP) return CIL_CONS_INCOMP;
2742 else return CIL_NONE;
2743 }
2744
__cil_get_constraint_operand_flavor(const char * operand)2745 static enum cil_flavor __cil_get_constraint_operand_flavor(const char *operand)
2746 {
2747 if (operand == NULL) return CIL_LIST;
2748 else if (operand == CIL_KEY_CONS_T1) return CIL_CONS_T1;
2749 else if (operand == CIL_KEY_CONS_T2) return CIL_CONS_T2;
2750 else if (operand == CIL_KEY_CONS_T3) return CIL_CONS_T3;
2751 else if (operand == CIL_KEY_CONS_R1) return CIL_CONS_R1;
2752 else if (operand == CIL_KEY_CONS_R2) return CIL_CONS_R2;
2753 else if (operand == CIL_KEY_CONS_R3) return CIL_CONS_R3;
2754 else if (operand == CIL_KEY_CONS_U1) return CIL_CONS_U1;
2755 else if (operand == CIL_KEY_CONS_U2) return CIL_CONS_U2;
2756 else if (operand == CIL_KEY_CONS_U3) return CIL_CONS_U3;
2757 else if (operand == CIL_KEY_CONS_L1) return CIL_CONS_L1;
2758 else if (operand == CIL_KEY_CONS_L2) return CIL_CONS_L2;
2759 else if (operand == CIL_KEY_CONS_H1) return CIL_CONS_H1;
2760 else if (operand == CIL_KEY_CONS_H2) return CIL_CONS_H2;
2761 else return CIL_STRING;
2762 }
2763
__cil_fill_constraint_leaf_expr(struct cil_tree_node * current,enum cil_flavor expr_flavor,enum cil_flavor op,struct cil_list ** leaf_expr)2764 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)
2765 {
2766 int rc = SEPOL_ERR;
2767 enum cil_flavor leaf_expr_flavor = CIL_NONE;
2768 enum cil_flavor l_flavor = CIL_NONE;
2769 enum cil_flavor r_flavor = CIL_NONE;
2770
2771 l_flavor = __cil_get_constraint_operand_flavor(current->next->data);
2772 r_flavor = __cil_get_constraint_operand_flavor(current->next->next->data);
2773
2774 switch (l_flavor) {
2775 case CIL_CONS_U1:
2776 case CIL_CONS_U2:
2777 case CIL_CONS_U3:
2778 leaf_expr_flavor = CIL_USER;
2779 break;
2780 case CIL_CONS_R1:
2781 case CIL_CONS_R2:
2782 case CIL_CONS_R3:
2783 leaf_expr_flavor = CIL_ROLE;
2784 break;
2785 case CIL_CONS_T1:
2786 case CIL_CONS_T2:
2787 case CIL_CONS_T3:
2788 leaf_expr_flavor = CIL_TYPE;
2789 break;
2790 case CIL_CONS_L1:
2791 case CIL_CONS_L2:
2792 case CIL_CONS_H1:
2793 case CIL_CONS_H2:
2794 leaf_expr_flavor = CIL_LEVEL;
2795 break;
2796 default:
2797 cil_log(CIL_ERR, "Invalid left operand (%s)\n", (char*)current->next->data);
2798 goto exit;
2799 }
2800
2801 rc = cil_verify_constraint_leaf_expr_syntax(l_flavor, r_flavor, op, expr_flavor);
2802 if (rc != SEPOL_OK) {
2803 goto exit;
2804 }
2805
2806 cil_list_init(leaf_expr, leaf_expr_flavor);
2807
2808 cil_list_append(*leaf_expr, CIL_OP, (void *)op);
2809
2810 cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)l_flavor);
2811
2812 if (r_flavor == CIL_STRING) {
2813 cil_list_append(*leaf_expr, CIL_STRING, current->next->next->data);
2814 } else if (r_flavor == CIL_LIST) {
2815 struct cil_list *sub_list;
2816 rc = cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list);
2817 if (rc != SEPOL_OK) {
2818 cil_list_destroy(leaf_expr, CIL_TRUE);
2819 goto exit;
2820 }
2821 cil_list_append(*leaf_expr, CIL_LIST, sub_list);
2822 } else {
2823 cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor);
2824 }
2825
2826 return SEPOL_OK;
2827
2828 exit:
2829
2830 return SEPOL_ERR;
2831 }
2832
__cil_fill_constraint_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2833 static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2834 {
2835 int rc = SEPOL_ERR;
2836 enum cil_flavor op;
2837 struct cil_list *lexpr;
2838 struct cil_list *rexpr;
2839
2840 if (current->data == NULL || current->cl_head != NULL) {
2841 cil_log(CIL_ERR, "Expected a string at the start of the constraint expression\n");
2842 goto exit;
2843 }
2844
2845 op = __cil_get_constraint_operator_flavor(current->data);
2846
2847 rc = cil_verify_constraint_expr_syntax(current, op);
2848 if (rc != SEPOL_OK) {
2849 goto exit;
2850 }
2851
2852 switch (op) {
2853 case CIL_EQ:
2854 case CIL_NEQ:
2855 case CIL_CONS_DOM:
2856 case CIL_CONS_DOMBY:
2857 case CIL_CONS_INCOMP:
2858 rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr);
2859 if (rc != SEPOL_OK) {
2860 goto exit;
2861 }
2862 break;
2863 case CIL_NOT:
2864 rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr);
2865 if (rc != SEPOL_OK) {
2866 goto exit;
2867 }
2868 cil_list_init(expr, flavor);
2869 cil_list_append(*expr, CIL_OP, (void *)op);
2870 cil_list_append(*expr, CIL_LIST, lexpr);
2871 break;
2872 default:
2873 rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr);
2874 if (rc != SEPOL_OK) {
2875 goto exit;
2876 }
2877 rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr);
2878 if (rc != SEPOL_OK) {
2879 cil_list_destroy(&lexpr, CIL_TRUE);
2880 goto exit;
2881 }
2882 cil_list_init(expr, flavor);
2883 cil_list_append(*expr, CIL_OP, (void *)op);
2884 cil_list_append(*expr, CIL_LIST, lexpr);
2885 cil_list_append(*expr, CIL_LIST, rexpr);
2886 break;
2887 }
2888
2889 return SEPOL_OK;
2890 exit:
2891
2892 return rc;
2893 }
2894
cil_gen_constraint_expr(struct cil_tree_node * current,enum cil_flavor flavor,struct cil_list ** expr)2895 static int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr)
2896 {
2897 int rc = SEPOL_ERR;
2898
2899 if (current->cl_head == NULL) {
2900 goto exit;
2901 }
2902
2903 rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr);
2904 if (rc != SEPOL_OK) {
2905 goto exit;
2906 }
2907
2908 return SEPOL_OK;
2909
2910 exit:
2911
2912 cil_log(CIL_ERR, "Bad expression tree for constraint\n");
2913 return rc;
2914 }
2915
cil_gen_boolif(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,int tunableif)2916 int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif)
2917 {
2918 enum cil_syntax syntax[] = {
2919 CIL_SYN_STRING,
2920 CIL_SYN_STRING | CIL_SYN_LIST,
2921 CIL_SYN_LIST,
2922 CIL_SYN_LIST | CIL_SYN_END,
2923 CIL_SYN_END
2924 };
2925 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2926 struct cil_booleanif *bif = NULL;
2927 struct cil_tree_node *next = NULL;
2928 int rc = SEPOL_ERR;
2929
2930 if (db == NULL || parse_current == NULL || ast_node == NULL) {
2931 goto exit;
2932 }
2933
2934 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2935 if (rc != SEPOL_OK) {
2936 goto exit;
2937 }
2938
2939 cil_boolif_init(&bif);
2940 bif->preserved_tunable = tunableif;
2941
2942 rc = cil_gen_expr(parse_current->next, CIL_BOOL, &bif->str_expr);
2943 if (rc != SEPOL_OK) {
2944 goto exit;
2945 }
2946
2947 rc = cil_verify_conditional_blocks(parse_current->next->next);
2948 if (rc != SEPOL_OK) {
2949 goto exit;
2950 }
2951
2952 /* Destroying expr tree */
2953 next = parse_current->next->next;
2954 cil_tree_subtree_destroy(parse_current->next);
2955 parse_current->next = next;
2956
2957 ast_node->flavor = CIL_BOOLEANIF;
2958 ast_node->data = bif;
2959
2960 return SEPOL_OK;
2961
2962 exit:
2963 if (tunableif) {
2964 cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration");
2965 } else {
2966 cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration");
2967 }
2968 cil_destroy_boolif(bif);
2969 return rc;
2970 }
2971
cil_destroy_boolif(struct cil_booleanif * bif)2972 void cil_destroy_boolif(struct cil_booleanif *bif)
2973 {
2974 if (bif == NULL) {
2975 return;
2976 }
2977
2978 cil_list_destroy(&bif->str_expr, CIL_TRUE);
2979 cil_list_destroy(&bif->datum_expr, CIL_FALSE);
2980
2981 free(bif);
2982 }
2983
cil_gen_tunif(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)2984 int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
2985 {
2986 enum cil_syntax syntax[] = {
2987 CIL_SYN_STRING,
2988 CIL_SYN_STRING | CIL_SYN_LIST,
2989 CIL_SYN_LIST,
2990 CIL_SYN_LIST | CIL_SYN_END,
2991 CIL_SYN_END
2992 };
2993 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
2994 struct cil_tunableif *tif = NULL;
2995 struct cil_tree_node *next = NULL;
2996 int rc = SEPOL_ERR;
2997
2998 if (db == NULL || parse_current == NULL || ast_node == NULL) {
2999 goto exit;
3000 }
3001
3002 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3003 if (rc != SEPOL_OK) {
3004 goto exit;
3005 }
3006
3007 cil_tunif_init(&tif);
3008
3009 rc = cil_gen_expr(parse_current->next, CIL_TUNABLE, &tif->str_expr);
3010 if (rc != SEPOL_OK) {
3011 goto exit;
3012 }
3013
3014 rc = cil_verify_conditional_blocks(parse_current->next->next);
3015 if (rc != SEPOL_OK) {
3016 goto exit;
3017 }
3018
3019 /* Destroying expr tree */
3020 next = parse_current->next->next;
3021 cil_tree_subtree_destroy(parse_current->next);
3022 parse_current->next = next;
3023
3024 ast_node->flavor = CIL_TUNABLEIF;
3025 ast_node->data = tif;
3026
3027 return SEPOL_OK;
3028
3029 exit:
3030 cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration");
3031 cil_destroy_tunif(tif);
3032 return rc;
3033 }
3034
cil_destroy_tunif(struct cil_tunableif * tif)3035 void cil_destroy_tunif(struct cil_tunableif *tif)
3036 {
3037 if (tif == NULL) {
3038 return;
3039 }
3040
3041 cil_list_destroy(&tif->str_expr, CIL_TRUE);
3042 cil_list_destroy(&tif->datum_expr, CIL_FALSE);
3043
3044 free(tif);
3045 }
3046
cil_gen_condblock(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3047 int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3048 {
3049 enum cil_syntax syntax[] = {
3050 CIL_SYN_STRING,
3051 CIL_SYN_N_LISTS,
3052 CIL_SYN_END
3053 };
3054 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3055 int rc = SEPOL_ERR;
3056 struct cil_condblock *cb = NULL;
3057
3058 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3059 goto exit;
3060 }
3061
3062 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3063 if (rc != SEPOL_OK) {
3064 goto exit;
3065 }
3066
3067 if (ast_node->parent->flavor != CIL_BOOLEANIF && ast_node->parent->flavor != CIL_TUNABLEIF) {
3068 rc = SEPOL_ERR;
3069 cil_log(CIL_ERR, "Conditional statements must be a direct child of a tunableif or booleanif statement.\n");
3070 goto exit;
3071 }
3072
3073 ast_node->flavor = CIL_CONDBLOCK;
3074
3075 cil_condblock_init(&cb);
3076 cb->flavor = flavor;
3077
3078 ast_node->data = cb;
3079
3080 return SEPOL_OK;
3081
3082 exit:
3083 cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration",
3084 (char*)parse_current->data);
3085 cil_destroy_condblock(cb);
3086 return rc;
3087 }
3088
cil_destroy_condblock(struct cil_condblock * cb)3089 void cil_destroy_condblock(struct cil_condblock *cb)
3090 {
3091 if (cb == NULL) {
3092 return;
3093 }
3094
3095 cil_symtab_array_destroy(cb->symtab);
3096 free(cb);
3097 }
3098
cil_gen_alias(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3099 int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3100 {
3101 enum cil_syntax syntax[] = {
3102 CIL_SYN_STRING,
3103 CIL_SYN_STRING,
3104 CIL_SYN_END
3105 };
3106 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3107 char *key = NULL;
3108 struct cil_alias *alias = NULL;
3109 enum cil_sym_index sym_index;
3110 int rc = SEPOL_ERR;
3111
3112 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3113 goto exit;
3114 }
3115
3116 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3117 if (rc != SEPOL_OK) {
3118 goto exit;
3119 }
3120
3121 cil_alias_init(&alias);
3122
3123 key = parse_current->next->data;
3124
3125 rc = cil_flavor_to_symtab_index(flavor, &sym_index);
3126 if (rc != SEPOL_OK) {
3127 goto exit;
3128 }
3129
3130 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)alias, (hashtab_key_t)key, sym_index, flavor);
3131 if (rc != SEPOL_OK) {
3132 goto exit;
3133 }
3134
3135 return SEPOL_OK;
3136
3137 exit:
3138 cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data);
3139 cil_destroy_alias(alias);
3140 cil_clear_node(ast_node);
3141 return rc;
3142 }
3143
cil_destroy_alias(struct cil_alias * alias)3144 void cil_destroy_alias(struct cil_alias *alias)
3145 {
3146 if (alias == NULL) {
3147 return;
3148 }
3149
3150 cil_symtab_datum_destroy(&alias->datum);
3151 alias->actual = NULL;
3152
3153 free(alias);
3154 }
3155
cil_gen_aliasactual(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3156 int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3157 {
3158 int rc = SEPOL_ERR;
3159 enum cil_syntax syntax[] = {
3160 CIL_SYN_STRING,
3161 CIL_SYN_STRING,
3162 CIL_SYN_STRING,
3163 CIL_SYN_END
3164 };
3165 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3166 struct cil_aliasactual *aliasactual = NULL;
3167
3168 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3169 goto exit;
3170 }
3171
3172 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3173 if (rc != SEPOL_OK) {
3174 goto exit;
3175 }
3176
3177 rc = cil_verify_name(db, parse_current->next->data, flavor);
3178 if (rc != SEPOL_OK) {
3179 goto exit;
3180 }
3181
3182 rc = cil_verify_name(db, parse_current->next->next->data, flavor);
3183 if (rc != SEPOL_OK) {
3184 goto exit;
3185 }
3186
3187 cil_aliasactual_init(&aliasactual);
3188
3189 aliasactual->alias_str = parse_current->next->data;
3190
3191 aliasactual->actual_str = parse_current->next->next->data;
3192
3193 ast_node->data = aliasactual;
3194 ast_node->flavor = flavor;
3195
3196 return SEPOL_OK;
3197
3198 exit:
3199 cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current));
3200 cil_clear_node(ast_node);
3201 return rc;
3202 }
3203
cil_destroy_aliasactual(struct cil_aliasactual * aliasactual)3204 void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual)
3205 {
3206 if (aliasactual == NULL) {
3207 return;
3208 }
3209
3210 free(aliasactual);
3211 }
3212
cil_gen_typeattributeset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3213 int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3214 {
3215 enum cil_syntax syntax[] = {
3216 CIL_SYN_STRING,
3217 CIL_SYN_STRING,
3218 CIL_SYN_STRING | CIL_SYN_LIST,
3219 CIL_SYN_END
3220 };
3221 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3222 struct cil_typeattributeset *attrset = NULL;
3223 int rc = SEPOL_ERR;
3224
3225 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3226 goto exit;
3227 }
3228
3229 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3230 if (rc != SEPOL_OK) {
3231 goto exit;
3232 }
3233
3234 cil_typeattributeset_init(&attrset);
3235
3236 attrset->attr_str = parse_current->next->data;
3237
3238 rc = cil_gen_expr(parse_current->next->next, CIL_TYPE, &attrset->str_expr);
3239 if (rc != SEPOL_OK) {
3240 goto exit;
3241 }
3242 ast_node->data = attrset;
3243 ast_node->flavor = CIL_TYPEATTRIBUTESET;
3244
3245 return SEPOL_OK;
3246
3247 exit:
3248 cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement");
3249 cil_destroy_typeattributeset(attrset);
3250 return rc;
3251 }
3252
cil_destroy_typeattributeset(struct cil_typeattributeset * attrset)3253 void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset)
3254 {
3255 if (attrset == NULL) {
3256 return;
3257 }
3258
3259 cil_list_destroy(&attrset->str_expr, CIL_TRUE);
3260 cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
3261
3262 free(attrset);
3263 }
3264
cil_gen_expandtypeattribute(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3265 int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3266 {
3267 enum cil_syntax syntax[] = {
3268 CIL_SYN_STRING,
3269 CIL_SYN_STRING | CIL_SYN_LIST,
3270 CIL_SYN_STRING,
3271 CIL_SYN_END
3272 };
3273 char *expand_str;
3274 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3275 struct cil_expandtypeattribute *expandattr = NULL;
3276 int rc = SEPOL_ERR;
3277
3278 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3279 goto exit;
3280 }
3281
3282 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3283 if (rc != SEPOL_OK) {
3284 goto exit;
3285 }
3286
3287 cil_expandtypeattribute_init(&expandattr);
3288
3289 if (parse_current->next->cl_head == NULL) {
3290 cil_list_init(&expandattr->attr_strs, CIL_TYPE);
3291 cil_list_append(expandattr->attr_strs, CIL_STRING, parse_current->next->data);
3292 } else {
3293 rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE, &expandattr->attr_strs);
3294 if (rc != SEPOL_OK) {
3295 goto exit;
3296 }
3297 }
3298
3299 expand_str = parse_current->next->next->data;
3300
3301 if (expand_str == CIL_KEY_CONDTRUE) {
3302 expandattr->expand = CIL_TRUE;
3303 } else if (expand_str == CIL_KEY_CONDFALSE) {
3304 expandattr->expand = CIL_FALSE;
3305 } else {
3306 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
3307 rc = SEPOL_ERR;
3308 goto exit;
3309 }
3310
3311 ast_node->data = expandattr;
3312 ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE;
3313
3314 return SEPOL_OK;
3315
3316 exit:
3317 cil_tree_log(parse_current, CIL_ERR, "Bad expandtypeattribute statement");
3318 cil_destroy_expandtypeattribute(expandattr);
3319 return rc;
3320 }
3321
cil_destroy_expandtypeattribute(struct cil_expandtypeattribute * expandattr)3322 void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr)
3323 {
3324 if (expandattr == NULL) {
3325 return;
3326 }
3327
3328 cil_list_destroy(&expandattr->attr_strs, CIL_TRUE);
3329
3330 cil_list_destroy(&expandattr->attr_datums, CIL_FALSE);
3331
3332 free(expandattr);
3333 }
3334
cil_gen_typepermissive(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3335 int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3336 {
3337 enum cil_syntax syntax[] = {
3338 CIL_SYN_STRING,
3339 CIL_SYN_STRING,
3340 CIL_SYN_END
3341 };
3342 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3343 struct cil_typepermissive *typeperm = NULL;
3344 int rc = SEPOL_ERR;
3345
3346 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3347 goto exit;
3348 }
3349
3350 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3351 if (rc != SEPOL_OK) {
3352 goto exit;
3353 }
3354
3355 cil_typepermissive_init(&typeperm);
3356
3357 typeperm->type_str = parse_current->next->data;
3358
3359 ast_node->data = typeperm;
3360 ast_node->flavor = CIL_TYPEPERMISSIVE;
3361
3362 return SEPOL_OK;
3363
3364 exit:
3365 cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration");
3366 cil_destroy_typepermissive(typeperm);
3367 return rc;
3368 }
3369
cil_destroy_typepermissive(struct cil_typepermissive * typeperm)3370 void cil_destroy_typepermissive(struct cil_typepermissive *typeperm)
3371 {
3372 if (typeperm == NULL) {
3373 return;
3374 }
3375
3376 free(typeperm);
3377 }
3378
cil_gen_typetransition(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3379 int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3380 {
3381 int rc = SEPOL_ERR;
3382 enum cil_syntax syntax[] = {
3383 CIL_SYN_STRING,
3384 CIL_SYN_STRING,
3385 CIL_SYN_STRING,
3386 CIL_SYN_STRING,
3387 CIL_SYN_STRING,
3388 CIL_SYN_STRING | CIL_SYN_END,
3389 CIL_SYN_END
3390 };
3391 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3392 char *s1, *s2, *s3, *s4, *s5;
3393
3394 if (db == NULL || parse_current == NULL || ast_node == NULL ) {
3395 goto exit;
3396 }
3397
3398 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3399 if (rc != SEPOL_OK) {
3400 goto exit;
3401 }
3402
3403 s1 = parse_current->next->data;
3404 s2 = parse_current->next->next->data;
3405 s3 = parse_current->next->next->next->data;
3406 s4 = parse_current->next->next->next->next->data;
3407 s5 = NULL;
3408
3409 if (parse_current->next->next->next->next->next) {
3410 if (s4 == CIL_KEY_STAR) {
3411 s4 = parse_current->next->next->next->next->next->data;
3412 } else {
3413 s5 = parse_current->next->next->next->next->next->data;
3414 }
3415 }
3416
3417 if (s5) {
3418 struct cil_nametypetransition *nametypetrans = NULL;
3419 cil_nametypetransition_init(&nametypetrans);
3420
3421 ast_node->data = nametypetrans;
3422 ast_node->flavor = CIL_NAMETYPETRANSITION;
3423
3424 nametypetrans->src_str = s1;
3425 nametypetrans->tgt_str = s2;
3426 nametypetrans->obj_str = s3;
3427 nametypetrans->name_str = s4;
3428 nametypetrans->name = cil_gen_declared_string(db, s4, ast_node);
3429 nametypetrans->result_str = s5;
3430 } else {
3431 struct cil_type_rule *rule = NULL;
3432 cil_type_rule_init(&rule);
3433
3434 ast_node->data = rule;
3435 ast_node->flavor = CIL_TYPE_RULE;
3436
3437 rule->rule_kind = CIL_TYPE_TRANSITION;
3438 rule->src_str = s1;
3439 rule->tgt_str = s2;
3440 rule->obj_str = s3;
3441 rule->result_str = s4;
3442 }
3443
3444 return SEPOL_OK;
3445
3446 exit:
3447 cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration");
3448 return rc;
3449 }
3450
cil_destroy_typetransition(struct cil_nametypetransition * nametypetrans)3451 void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans)
3452 {
3453 if (nametypetrans == NULL) {
3454 return;
3455 }
3456
3457 free(nametypetrans);
3458 }
3459
cil_gen_rangetransition(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3460 int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3461 {
3462 enum cil_syntax syntax[] = {
3463 CIL_SYN_STRING,
3464 CIL_SYN_STRING,
3465 CIL_SYN_STRING,
3466 CIL_SYN_STRING,
3467 CIL_SYN_STRING | CIL_SYN_LIST,
3468 CIL_SYN_END
3469 };
3470 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3471 struct cil_rangetransition *rangetrans = NULL;
3472 int rc = SEPOL_ERR;
3473
3474 if (db == NULL || parse_current == NULL || ast_node == NULL ) {
3475 goto exit;
3476 }
3477
3478 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3479 if (rc != SEPOL_OK) {
3480 goto exit;
3481 }
3482
3483 cil_rangetransition_init(&rangetrans);
3484
3485 rangetrans->src_str = parse_current->next->data;
3486 rangetrans->exec_str = parse_current->next->next->data;
3487 rangetrans->obj_str = parse_current->next->next->next->data;
3488
3489 rangetrans->range_str = NULL;
3490
3491 if (parse_current->next->next->next->next->cl_head == NULL) {
3492 rangetrans->range_str = parse_current->next->next->next->next->data;
3493 } else {
3494 cil_levelrange_init(&rangetrans->range);
3495
3496 rc = cil_fill_levelrange(parse_current->next->next->next->next->cl_head, rangetrans->range);
3497 if (rc != SEPOL_OK) {
3498 goto exit;
3499 }
3500 }
3501
3502 ast_node->data = rangetrans;
3503 ast_node->flavor = CIL_RANGETRANSITION;
3504
3505 return SEPOL_OK;
3506
3507 exit:
3508 cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration");
3509 cil_destroy_rangetransition(rangetrans);
3510 return rc;
3511 }
3512
cil_destroy_rangetransition(struct cil_rangetransition * rangetrans)3513 void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans)
3514 {
3515 if (rangetrans == NULL) {
3516 return;
3517 }
3518
3519 if (rangetrans->range_str == NULL && rangetrans->range != NULL) {
3520 cil_destroy_levelrange(rangetrans->range);
3521 }
3522
3523 free(rangetrans);
3524 }
3525
cil_gen_sensitivity(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3526 int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3527 {
3528 enum cil_syntax syntax[] = {
3529 CIL_SYN_STRING,
3530 CIL_SYN_STRING,
3531 CIL_SYN_END
3532 };
3533 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3534 char *key = NULL;
3535 struct cil_sens *sens = NULL;
3536 int rc = SEPOL_ERR;
3537
3538 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3539 goto exit;
3540 }
3541
3542 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3543 if (rc != SEPOL_OK) {
3544 goto exit;
3545 }
3546
3547 cil_sens_init(&sens);
3548
3549 key = parse_current->next->data;
3550
3551 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sens, (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS);
3552 if (rc != SEPOL_OK) {
3553 goto exit;
3554 }
3555
3556 return SEPOL_OK;
3557
3558 exit:
3559 cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration");
3560 cil_destroy_sensitivity(sens);
3561 cil_clear_node(ast_node);
3562 return rc;
3563 }
3564
cil_destroy_sensitivity(struct cil_sens * sens)3565 void cil_destroy_sensitivity(struct cil_sens *sens)
3566 {
3567 if (sens == NULL) {
3568 return;
3569 }
3570
3571 cil_symtab_datum_destroy(&sens->datum);
3572
3573 cil_list_destroy(&sens->cats_list, CIL_FALSE);
3574
3575 free(sens);
3576 }
3577
cil_gen_category(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3578 int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3579 {
3580 enum cil_syntax syntax[] = {
3581 CIL_SYN_STRING,
3582 CIL_SYN_STRING,
3583 CIL_SYN_END
3584 };
3585 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3586 char *key = NULL;
3587 struct cil_cat *cat = NULL;
3588 int rc = SEPOL_ERR;
3589
3590 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3591 goto exit;
3592 }
3593
3594 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3595 if (rc != SEPOL_OK) {
3596 goto exit;
3597 }
3598
3599 cil_cat_init(&cat);
3600
3601 key = parse_current->next->data;
3602
3603 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cat, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT);
3604 if (rc != SEPOL_OK) {
3605 goto exit;
3606 }
3607
3608 return SEPOL_OK;
3609
3610 exit:
3611 cil_tree_log(parse_current, CIL_ERR, "Bad category declaration");
3612 cil_destroy_category(cat);
3613 cil_clear_node(ast_node);
3614 return rc;
3615 }
3616
cil_destroy_category(struct cil_cat * cat)3617 void cil_destroy_category(struct cil_cat *cat)
3618 {
3619 if (cat == NULL) {
3620 return;
3621 }
3622
3623 cil_symtab_datum_destroy(&cat->datum);
3624 free(cat);
3625 }
3626
cil_gen_catset(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3627 static int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3628 {
3629 enum cil_syntax syntax[] = {
3630 CIL_SYN_STRING,
3631 CIL_SYN_STRING,
3632 CIL_SYN_LIST,
3633 CIL_SYN_END
3634 };
3635 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3636 char *key = NULL;
3637 struct cil_catset *catset = NULL;
3638 int rc = SEPOL_ERR;
3639
3640 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3641 goto exit;
3642 }
3643
3644 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3645 if (rc != SEPOL_OK) {
3646 goto exit;
3647 }
3648
3649 cil_catset_init(&catset);
3650
3651 key = parse_current->next->data;
3652
3653 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)catset, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET);
3654 if (rc != SEPOL_OK) {
3655 goto exit;
3656 }
3657
3658 rc = cil_fill_cats(parse_current->next->next, &catset->cats);
3659 if (rc != SEPOL_OK) {
3660 goto exit;
3661 }
3662
3663 return SEPOL_OK;
3664
3665 exit:
3666 cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration");
3667 cil_destroy_catset(catset);
3668 cil_clear_node(ast_node);
3669 return rc;
3670 }
3671
cil_destroy_catset(struct cil_catset * catset)3672 void cil_destroy_catset(struct cil_catset *catset)
3673 {
3674 if (catset == NULL) {
3675 return;
3676 }
3677
3678 cil_symtab_datum_destroy(&catset->datum);
3679
3680 cil_destroy_cats(catset->cats);
3681
3682 free(catset);
3683 }
3684
cil_gen_senscat(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3685 int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3686 {
3687 enum cil_syntax syntax[] = {
3688 CIL_SYN_STRING,
3689 CIL_SYN_STRING,
3690 CIL_SYN_STRING | CIL_SYN_LIST,
3691 CIL_SYN_END
3692 };
3693 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3694 struct cil_senscat *senscat = NULL;
3695 int rc = SEPOL_ERR;
3696
3697 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3698 goto exit;
3699 }
3700
3701 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3702 if (rc != SEPOL_OK) {
3703 goto exit;
3704 }
3705
3706 cil_senscat_init(&senscat);
3707
3708 senscat->sens_str = parse_current->next->data;
3709
3710 rc = cil_fill_cats(parse_current->next->next, &senscat->cats);
3711 if (rc != SEPOL_OK) {
3712 goto exit;
3713 }
3714
3715 ast_node->data = senscat;
3716 ast_node->flavor = CIL_SENSCAT;
3717
3718 return SEPOL_OK;
3719
3720 exit:
3721 cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration");
3722 cil_destroy_senscat(senscat);
3723 return rc;
3724 }
3725
cil_destroy_senscat(struct cil_senscat * senscat)3726 void cil_destroy_senscat(struct cil_senscat *senscat)
3727 {
3728 if (senscat == NULL) {
3729 return;
3730 }
3731
3732 cil_destroy_cats(senscat->cats);
3733
3734 free(senscat);
3735 }
3736
cil_gen_level(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3737 int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3738 {
3739 enum cil_syntax syntax[] = {
3740 CIL_SYN_STRING,
3741 CIL_SYN_STRING,
3742 CIL_SYN_LIST,
3743 CIL_SYN_END
3744 };
3745 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3746 char *key = NULL;
3747 struct cil_level *level = NULL;
3748 int rc = SEPOL_ERR;
3749
3750 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3751 goto exit;
3752 }
3753
3754 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3755 if (rc != SEPOL_OK) {
3756 goto exit;
3757 }
3758
3759 cil_level_init(&level);
3760
3761 key = parse_current->next->data;
3762
3763 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)level, (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL);
3764 if (rc != SEPOL_OK) {
3765 goto exit;
3766 }
3767
3768 rc = cil_fill_level(parse_current->next->next->cl_head, level);
3769 if (rc != SEPOL_OK) {
3770 goto exit;
3771 }
3772
3773 return SEPOL_OK;
3774
3775 exit:
3776 cil_tree_log(parse_current, CIL_ERR, "Bad level declaration");
3777 cil_destroy_level(level);
3778 cil_clear_node(ast_node);
3779 return rc;
3780 }
3781
cil_destroy_level(struct cil_level * level)3782 void cil_destroy_level(struct cil_level *level)
3783 {
3784 if (level == NULL) {
3785 return;
3786 }
3787
3788 cil_symtab_datum_destroy(&level->datum);
3789
3790 cil_destroy_cats(level->cats);
3791
3792 free(level);
3793 }
3794
3795 /* 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)3796 int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange)
3797 {
3798 enum cil_syntax syntax[] = {
3799 CIL_SYN_STRING | CIL_SYN_LIST,
3800 CIL_SYN_STRING | CIL_SYN_LIST,
3801 CIL_SYN_END
3802 };
3803 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3804 int rc = SEPOL_ERR;
3805
3806 if (low == NULL || lvlrange == NULL) {
3807 goto exit;
3808 }
3809
3810 rc = __cil_verify_syntax(low, syntax, syntax_len);
3811 if (rc != SEPOL_OK) {
3812
3813 goto exit;
3814 }
3815
3816 if (low->cl_head == NULL) {
3817 lvlrange->low_str = low->data;
3818 } else {
3819 cil_level_init(&lvlrange->low);
3820 rc = cil_fill_level(low->cl_head, lvlrange->low);
3821 if (rc != SEPOL_OK) {
3822 goto exit;
3823 }
3824 }
3825
3826 if (low->next->cl_head == NULL) {
3827 lvlrange->high_str = low->next->data;
3828 } else {
3829 cil_level_init(&lvlrange->high);
3830 rc = cil_fill_level(low->next->cl_head, lvlrange->high);
3831 if (rc != SEPOL_OK) {
3832 goto exit;
3833 }
3834 }
3835
3836 return SEPOL_OK;
3837
3838 exit:
3839 cil_log(CIL_ERR, "Bad levelrange\n");
3840 return rc;
3841 }
3842
cil_gen_levelrange(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)3843 int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
3844 {
3845 enum cil_syntax syntax[] = {
3846 CIL_SYN_STRING,
3847 CIL_SYN_STRING,
3848 CIL_SYN_LIST,
3849 CIL_SYN_END
3850 };
3851 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3852 char *key = NULL;
3853 struct cil_levelrange *lvlrange = NULL;
3854 int rc = SEPOL_ERR;
3855
3856 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3857 goto exit;
3858 }
3859
3860 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3861 if (rc != SEPOL_OK) {
3862 goto exit;
3863 }
3864
3865 cil_levelrange_init(&lvlrange);
3866
3867 key = parse_current->next->data;
3868
3869 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)lvlrange, (hashtab_key_t)key, CIL_SYM_LEVELRANGES, CIL_LEVELRANGE);
3870 if (rc != SEPOL_OK) {
3871 goto exit;
3872 }
3873
3874 rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange);
3875 if (rc != SEPOL_OK) {
3876 goto exit;
3877 }
3878
3879 return SEPOL_OK;
3880
3881 exit:
3882 cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration");
3883 cil_destroy_levelrange(lvlrange);
3884 cil_clear_node(ast_node);
3885 return rc;
3886 }
3887
cil_destroy_levelrange(struct cil_levelrange * lvlrange)3888 void cil_destroy_levelrange(struct cil_levelrange *lvlrange)
3889 {
3890 if (lvlrange == NULL) {
3891 return;
3892 }
3893
3894 cil_symtab_datum_destroy(&lvlrange->datum);
3895
3896 if (lvlrange->low_str == NULL) {
3897 cil_destroy_level(lvlrange->low);
3898 }
3899
3900 if (lvlrange->high_str == NULL) {
3901 cil_destroy_level(lvlrange->high);
3902 }
3903
3904 free(lvlrange);
3905 }
3906
cil_gen_constrain(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3907 int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3908 {
3909 enum cil_syntax syntax[] = {
3910 CIL_SYN_STRING,
3911 CIL_SYN_STRING | CIL_SYN_LIST,
3912 CIL_SYN_LIST,
3913 CIL_SYN_END
3914 };
3915 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3916 struct cil_constrain *cons = NULL;
3917 int rc = SEPOL_ERR;
3918
3919 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3920 goto exit;
3921 }
3922
3923 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3924 if (rc != SEPOL_OK) {
3925 goto exit;
3926 }
3927
3928 cil_constrain_init(&cons);
3929
3930 rc = cil_fill_classperms_list(parse_current->next, &cons->classperms);
3931 if (rc != SEPOL_OK) {
3932 goto exit;
3933 }
3934
3935 rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &cons->str_expr);
3936 if (rc != SEPOL_OK) {
3937 goto exit;
3938 }
3939
3940 ast_node->data = cons;
3941 ast_node->flavor = flavor;
3942
3943 return SEPOL_OK;
3944
3945 exit:
3946 cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration");
3947 cil_destroy_constrain(cons);
3948 return rc;
3949 }
3950
cil_destroy_constrain(struct cil_constrain * cons)3951 void cil_destroy_constrain(struct cil_constrain *cons)
3952 {
3953 if (cons == NULL) {
3954 return;
3955 }
3956
3957 cil_destroy_classperms_list(&cons->classperms);
3958 cil_list_destroy(&cons->str_expr, CIL_TRUE);
3959 cil_list_destroy(&cons->datum_expr, CIL_FALSE);
3960
3961 free(cons);
3962 }
3963
cil_gen_validatetrans(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)3964 int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
3965 {
3966 enum cil_syntax syntax[] = {
3967 CIL_SYN_STRING,
3968 CIL_SYN_STRING,
3969 CIL_SYN_LIST,
3970 CIL_SYN_END
3971 };
3972 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
3973 struct cil_validatetrans *validtrans = NULL;
3974 int rc = SEPOL_ERR;
3975
3976 if (db == NULL || parse_current == NULL || ast_node == NULL) {
3977 goto exit;
3978 }
3979
3980 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3981 if (rc != SEPOL_OK) {
3982 goto exit;
3983 }
3984
3985 cil_validatetrans_init(&validtrans);
3986
3987 validtrans->class_str = parse_current->next->data;
3988
3989 rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &validtrans->str_expr);
3990 if (rc != SEPOL_OK) {
3991 goto exit;
3992 }
3993
3994 ast_node->data = validtrans;
3995 ast_node->flavor = flavor;
3996
3997 return SEPOL_OK;
3998
3999 exit:
4000 cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration");
4001 cil_destroy_validatetrans(validtrans);
4002 return rc;
4003
4004
4005 }
4006
cil_destroy_validatetrans(struct cil_validatetrans * validtrans)4007 void cil_destroy_validatetrans(struct cil_validatetrans *validtrans)
4008 {
4009 if (validtrans == NULL) {
4010 return;
4011 }
4012
4013 cil_list_destroy(&validtrans->str_expr, CIL_TRUE);
4014 cil_list_destroy(&validtrans->datum_expr, CIL_FALSE);
4015
4016 free(validtrans);
4017 }
4018
4019 /* Fills in context starting from user */
cil_fill_context(struct cil_tree_node * user_node,struct cil_context * context)4020 int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context)
4021 {
4022 enum cil_syntax syntax[] = {
4023 CIL_SYN_STRING,
4024 CIL_SYN_STRING,
4025 CIL_SYN_STRING,
4026 CIL_SYN_STRING | CIL_SYN_LIST,
4027 CIL_SYN_END
4028 };
4029 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4030 int rc = SEPOL_ERR;
4031
4032 if (user_node == NULL || context == NULL) {
4033 goto exit;
4034 }
4035
4036 rc = __cil_verify_syntax(user_node, syntax, syntax_len);
4037 if (rc != SEPOL_OK) {
4038 goto exit;
4039 }
4040
4041 context->user_str = user_node->data;
4042 context->role_str = user_node->next->data;
4043 context->type_str = user_node->next->next->data;
4044
4045 context->range_str = NULL;
4046
4047 if (user_node->next->next->next->cl_head == NULL) {
4048 context->range_str = user_node->next->next->next->data;
4049 } else {
4050 cil_levelrange_init(&context->range);
4051
4052 rc = cil_fill_levelrange(user_node->next->next->next->cl_head, context->range);
4053 if (rc != SEPOL_OK) {
4054 goto exit;
4055 }
4056 }
4057
4058 return SEPOL_OK;
4059
4060 exit:
4061 cil_log(CIL_ERR, "Bad context\n");
4062 return rc;
4063 }
4064
cil_gen_context(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4065 int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4066 {
4067 enum cil_syntax syntax[] = {
4068 CIL_SYN_STRING,
4069 CIL_SYN_STRING,
4070 CIL_SYN_LIST,
4071 CIL_SYN_END
4072 };
4073 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4074 char *key = NULL;
4075 struct cil_context *context = NULL;
4076 int rc = SEPOL_ERR;
4077
4078 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4079 goto exit;
4080 }
4081
4082 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4083 if (rc != SEPOL_OK) {
4084 goto exit;
4085 }
4086
4087 cil_context_init(&context);
4088
4089 key = parse_current->next->data;
4090
4091 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)context, (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT);
4092 if (rc != SEPOL_OK) {
4093 goto exit;
4094 }
4095
4096 rc = cil_fill_context(parse_current->next->next->cl_head, context);
4097 if (rc != SEPOL_OK) {
4098 goto exit;
4099 }
4100
4101 return SEPOL_OK;
4102
4103 exit:
4104 cil_tree_log(parse_current, CIL_ERR, "Bad context declaration");
4105 cil_destroy_context(context);
4106 cil_clear_node(ast_node);
4107 return SEPOL_ERR;
4108 }
4109
cil_destroy_context(struct cil_context * context)4110 void cil_destroy_context(struct cil_context *context)
4111 {
4112 if (context == NULL) {
4113 return;
4114 }
4115
4116 cil_symtab_datum_destroy(&context->datum);
4117
4118 if (context->range_str == NULL && context->range != NULL) {
4119 cil_destroy_levelrange(context->range);
4120 }
4121
4122 free(context);
4123 }
4124
cil_gen_filecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4125 int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4126 {
4127 enum cil_syntax syntax[] = {
4128 CIL_SYN_STRING,
4129 CIL_SYN_STRING,
4130 CIL_SYN_STRING,
4131 CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
4132 CIL_SYN_END
4133 };
4134 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4135 int rc = SEPOL_ERR;
4136 struct cil_filecon *filecon = NULL;
4137 char *type = NULL;
4138
4139 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4140 goto exit;
4141 }
4142
4143 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4144 if (rc != SEPOL_OK) {
4145 goto exit;
4146 }
4147
4148 type = parse_current->next->next->data;
4149 cil_filecon_init(&filecon);
4150
4151 ast_node->data = filecon;
4152 ast_node->flavor = CIL_FILECON;
4153
4154 filecon->path_str = parse_current->next->data;
4155 /* filecon->path will be NULL if in a macro and the path is an argument */
4156 filecon->path = cil_gen_declared_string(db, filecon->path_str, ast_node);
4157
4158 if (type == CIL_KEY_ANY) {
4159 filecon->type = CIL_FILECON_ANY;
4160 } else if (type == CIL_KEY_FILE) {
4161 filecon->type = CIL_FILECON_FILE;
4162 } else if (type == CIL_KEY_DIR) {
4163 filecon->type = CIL_FILECON_DIR;
4164 } else if (type == CIL_KEY_CHAR) {
4165 filecon->type = CIL_FILECON_CHAR;
4166 } else if (type == CIL_KEY_BLOCK) {
4167 filecon->type = CIL_FILECON_BLOCK;
4168 } else if (type == CIL_KEY_SOCKET) {
4169 filecon->type = CIL_FILECON_SOCKET;
4170 } else if (type == CIL_KEY_PIPE) {
4171 filecon->type = CIL_FILECON_PIPE;
4172 } else if (type == CIL_KEY_SYMLINK) {
4173 filecon->type = CIL_FILECON_SYMLINK;
4174 } else {
4175 cil_log(CIL_ERR, "Invalid file type\n");
4176 rc = SEPOL_ERR;
4177 goto exit;
4178 }
4179
4180 if (parse_current->next->next->next->cl_head == NULL) {
4181 filecon->context_str = parse_current->next->next->next->data;
4182 } else {
4183 if (parse_current->next->next->next->cl_head->next == NULL) {
4184 filecon->context = NULL;
4185 } else {
4186 cil_context_init(&filecon->context);
4187
4188 rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context);
4189 if (rc != SEPOL_OK) {
4190 goto exit;
4191 }
4192 }
4193 }
4194
4195 return SEPOL_OK;
4196
4197 exit:
4198 cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration");
4199 cil_destroy_filecon(filecon);
4200 cil_clear_node(ast_node);
4201 return rc;
4202 }
4203
4204 //TODO: Should we be checking if the pointer is NULL when passed in?
cil_destroy_filecon(struct cil_filecon * filecon)4205 void cil_destroy_filecon(struct cil_filecon *filecon)
4206 {
4207 if (filecon == NULL) {
4208 return;
4209 }
4210
4211 if (filecon->context_str == NULL && filecon->context != NULL) {
4212 cil_destroy_context(filecon->context);
4213 }
4214
4215 free(filecon);
4216 }
4217
cil_gen_ibpkeycon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4218 int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4219 {
4220 enum cil_syntax syntax[] = {
4221 CIL_SYN_STRING,
4222 CIL_SYN_STRING,
4223 CIL_SYN_STRING | CIL_SYN_LIST,
4224 CIL_SYN_STRING | CIL_SYN_LIST,
4225 CIL_SYN_END
4226 };
4227 size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4228 int rc = SEPOL_ERR;
4229 struct cil_ibpkeycon *ibpkeycon = NULL;
4230
4231 if (!parse_current || !ast_node)
4232 goto exit;
4233
4234 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4235 if (rc != SEPOL_OK)
4236 goto exit;
4237
4238 cil_ibpkeycon_init(&ibpkeycon);
4239
4240 ibpkeycon->subnet_prefix_str = parse_current->next->data;
4241
4242 if (parse_current->next->next->cl_head) {
4243 if (parse_current->next->next->cl_head->next &&
4244 !parse_current->next->next->cl_head->next->next) {
4245 rc = cil_fill_integer(parse_current->next->next->cl_head, &ibpkeycon->pkey_low, 0);
4246 if (rc != SEPOL_OK) {
4247 cil_log(CIL_ERR, "Improper ibpkey specified\n");
4248 goto exit;
4249 }
4250 rc = cil_fill_integer(parse_current->next->next->cl_head->next, &ibpkeycon->pkey_high, 0);
4251 if (rc != SEPOL_OK) {
4252 cil_log(CIL_ERR, "Improper ibpkey specified\n");
4253 goto exit;
4254 }
4255 } else {
4256 cil_log(CIL_ERR, "Improper ibpkey range specified\n");
4257 rc = SEPOL_ERR;
4258 goto exit;
4259 }
4260 } else {
4261 rc = cil_fill_integer(parse_current->next->next, &ibpkeycon->pkey_low, 0);
4262 if (rc != SEPOL_OK) {
4263 cil_log(CIL_ERR, "Improper ibpkey specified\n");
4264 goto exit;
4265 }
4266 ibpkeycon->pkey_high = ibpkeycon->pkey_low;
4267 }
4268
4269 if (!parse_current->next->next->next->cl_head) {
4270 ibpkeycon->context_str = parse_current->next->next->next->data;
4271 } else {
4272 cil_context_init(&ibpkeycon->context);
4273
4274 rc = cil_fill_context(parse_current->next->next->next->cl_head, ibpkeycon->context);
4275 if (rc != SEPOL_OK)
4276 goto exit;
4277 }
4278
4279 ast_node->data = ibpkeycon;
4280 ast_node->flavor = CIL_IBPKEYCON;
4281 return SEPOL_OK;
4282
4283 exit:
4284 cil_tree_log(parse_current, CIL_ERR, "Bad ibpkeycon declaration");
4285 cil_destroy_ibpkeycon(ibpkeycon);
4286
4287 return rc;
4288 }
4289
cil_destroy_ibpkeycon(struct cil_ibpkeycon * ibpkeycon)4290 void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
4291 {
4292 if (!ibpkeycon)
4293 return;
4294
4295 if (!ibpkeycon->context_str && ibpkeycon->context)
4296 cil_destroy_context(ibpkeycon->context);
4297
4298 free(ibpkeycon);
4299 }
4300
cil_gen_portcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4301 int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4302 {
4303 enum cil_syntax syntax[] = {
4304 CIL_SYN_STRING,
4305 CIL_SYN_STRING,
4306 CIL_SYN_STRING | CIL_SYN_LIST,
4307 CIL_SYN_STRING | CIL_SYN_LIST,
4308 CIL_SYN_END
4309 };
4310 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4311 int rc = SEPOL_ERR;
4312 struct cil_portcon *portcon = NULL;
4313 char *proto;
4314
4315 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4316 goto exit;
4317 }
4318
4319 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4320 if (rc != SEPOL_OK) {
4321 goto exit;
4322 }
4323
4324 cil_portcon_init(&portcon);
4325
4326 proto = parse_current->next->data;
4327 if (proto == CIL_KEY_UDP) {
4328 portcon->proto = CIL_PROTOCOL_UDP;
4329 } else if (proto == CIL_KEY_TCP) {
4330 portcon->proto = CIL_PROTOCOL_TCP;
4331 } else if (proto == CIL_KEY_DCCP) {
4332 portcon->proto = CIL_PROTOCOL_DCCP;
4333 } else if (proto == CIL_KEY_SCTP) {
4334 portcon->proto = CIL_PROTOCOL_SCTP;
4335 } else {
4336 cil_log(CIL_ERR, "Invalid protocol\n");
4337 rc = SEPOL_ERR;
4338 goto exit;
4339 }
4340
4341 if (parse_current->next->next->cl_head != NULL) {
4342 if (parse_current->next->next->cl_head->next != NULL
4343 && parse_current->next->next->cl_head->next->next == NULL) {
4344 rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10);
4345 if (rc != SEPOL_OK) {
4346 cil_log(CIL_ERR, "Improper port specified\n");
4347 goto exit;
4348 }
4349 rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10);
4350 if (rc != SEPOL_OK) {
4351 cil_log(CIL_ERR, "Improper port specified\n");
4352 goto exit;
4353 }
4354 } else {
4355 cil_log(CIL_ERR, "Improper port range specified\n");
4356 rc = SEPOL_ERR;
4357 goto exit;
4358 }
4359 } else {
4360 rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10);
4361 if (rc != SEPOL_OK) {
4362 cil_log(CIL_ERR, "Improper port specified\n");
4363 goto exit;
4364 }
4365 portcon->port_high = portcon->port_low;
4366 }
4367
4368 if (parse_current->next->next->next->cl_head == NULL ) {
4369 portcon->context_str = parse_current->next->next->next->data;
4370 } else {
4371 cil_context_init(&portcon->context);
4372
4373 rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context);
4374 if (rc != SEPOL_OK) {
4375 goto exit;
4376 }
4377 }
4378
4379 ast_node->data = portcon;
4380 ast_node->flavor = CIL_PORTCON;
4381
4382 return SEPOL_OK;
4383
4384 exit:
4385 cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration");
4386 cil_destroy_portcon(portcon);
4387 return rc;
4388 }
4389
cil_destroy_portcon(struct cil_portcon * portcon)4390 void cil_destroy_portcon(struct cil_portcon *portcon)
4391 {
4392 if (portcon == NULL) {
4393 return;
4394 }
4395
4396 if (portcon->context_str == NULL && portcon->context != NULL) {
4397 cil_destroy_context(portcon->context);
4398 }
4399
4400 free(portcon);
4401 }
4402
cil_gen_nodecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4403 int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4404 {
4405 enum cil_syntax syntax[] = {
4406 CIL_SYN_STRING,
4407 CIL_SYN_STRING | CIL_SYN_LIST,
4408 CIL_SYN_STRING | CIL_SYN_LIST,
4409 CIL_SYN_STRING | CIL_SYN_LIST,
4410 CIL_SYN_END
4411 };
4412 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4413 int rc = SEPOL_ERR;
4414 struct cil_nodecon *nodecon = NULL;
4415
4416 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4417 goto exit;
4418 }
4419
4420 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4421 if (rc != SEPOL_OK) {
4422 goto exit;
4423 }
4424
4425 cil_nodecon_init(&nodecon);
4426
4427 if (parse_current->next->cl_head) {
4428 cil_ipaddr_init(&nodecon->addr);
4429 rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr);
4430 if (rc != SEPOL_OK) {
4431 goto exit;
4432 }
4433 } else {
4434 char *addr = parse_current->next->data;
4435 if (strchr(addr, ':') || (strchr(addr, '.') && isdigit(addr[0]))) {
4436 cil_ipaddr_init(&nodecon->addr);
4437 rc = cil_fill_ipaddr(parse_current->next, nodecon->addr);
4438 if (rc != SEPOL_OK) {
4439 goto exit;
4440 }
4441 } else {
4442 nodecon->addr_str = addr;
4443 }
4444 }
4445
4446 if (parse_current->next->next->cl_head) {
4447 cil_ipaddr_init(&nodecon->mask);
4448 rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask);
4449 if (rc != SEPOL_OK) {
4450 goto exit;
4451 }
4452 } else {
4453 char *mask = parse_current->next->next->data;
4454 if (strchr(mask, ':') || (strchr(mask, '.') && isdigit(mask[0]))) {
4455 cil_ipaddr_init(&nodecon->mask);
4456 rc = cil_fill_ipaddr(parse_current->next->next, nodecon->mask);
4457 if (rc != SEPOL_OK) {
4458 goto exit;
4459 }
4460 } else {
4461 nodecon->mask_str = mask;
4462 }
4463 }
4464
4465 if (parse_current->next->next->next->cl_head == NULL ) {
4466 nodecon->context_str = parse_current->next->next->next->data;
4467 } else {
4468 cil_context_init(&nodecon->context);
4469
4470 rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context);
4471 if (rc != SEPOL_OK) {
4472 goto exit;
4473 }
4474 }
4475
4476 ast_node->data = nodecon;
4477 ast_node->flavor = CIL_NODECON;
4478
4479 return SEPOL_OK;
4480
4481 exit:
4482 cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration");
4483 cil_destroy_nodecon(nodecon);
4484 return rc;
4485 }
4486
cil_destroy_nodecon(struct cil_nodecon * nodecon)4487 void cil_destroy_nodecon(struct cil_nodecon *nodecon)
4488 {
4489 if (nodecon == NULL) {
4490 return;
4491 }
4492
4493 if (nodecon->addr_str == NULL && nodecon->addr != NULL) {
4494 cil_destroy_ipaddr(nodecon->addr);
4495 }
4496
4497 if (nodecon->mask_str == NULL && nodecon->mask != NULL) {
4498 cil_destroy_ipaddr(nodecon->mask);
4499 }
4500
4501 if (nodecon->context_str == NULL && nodecon->context != NULL) {
4502 cil_destroy_context(nodecon->context);
4503 }
4504
4505 free(nodecon);
4506 }
4507
cil_gen_genfscon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4508 int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4509 {
4510 enum cil_syntax syntax[] = {
4511 CIL_SYN_STRING,
4512 CIL_SYN_STRING,
4513 CIL_SYN_STRING,
4514 CIL_SYN_STRING | CIL_SYN_LIST,
4515 CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
4516 CIL_SYN_END
4517 };
4518 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4519 struct cil_tree_node *context_node;
4520 int rc = SEPOL_ERR;
4521 struct cil_genfscon *genfscon = NULL;
4522
4523 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4524 goto exit;
4525 }
4526
4527 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4528 if (rc != SEPOL_OK) {
4529 goto exit;
4530 }
4531
4532 cil_genfscon_init(&genfscon);
4533
4534 genfscon->fs_str = parse_current->next->data;
4535 genfscon->path_str = parse_current->next->next->data;
4536
4537 if (parse_current->next->next->next->next) {
4538 /* (genfscon <FS_STR> <PATH_STR> <FILE_TYPE> ... */
4539 char *file_type = parse_current->next->next->next->data;
4540 if (file_type == CIL_KEY_ANY) {
4541 genfscon->file_type = CIL_FILECON_ANY;
4542 } else if (file_type == CIL_KEY_FILE) {
4543 genfscon->file_type = CIL_FILECON_FILE;
4544 } else if (file_type == CIL_KEY_DIR) {
4545 genfscon->file_type = CIL_FILECON_DIR;
4546 } else if (file_type == CIL_KEY_CHAR) {
4547 genfscon->file_type = CIL_FILECON_CHAR;
4548 } else if (file_type == CIL_KEY_BLOCK) {
4549 genfscon->file_type = CIL_FILECON_BLOCK;
4550 } else if (file_type == CIL_KEY_SOCKET) {
4551 genfscon->file_type = CIL_FILECON_SOCKET;
4552 } else if (file_type == CIL_KEY_PIPE) {
4553 genfscon->file_type = CIL_FILECON_PIPE;
4554 } else if (file_type == CIL_KEY_SYMLINK) {
4555 genfscon->file_type = CIL_FILECON_SYMLINK;
4556 } else {
4557 if (parse_current->next->next->next->cl_head) {
4558 cil_log(CIL_ERR, "Expecting file type, but found a list\n");
4559 } else {
4560 cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type);
4561 }
4562 goto exit;
4563 }
4564 context_node = parse_current->next->next->next->next;
4565 } else {
4566 /* (genfscon <FS_STR> <PATH_STR> ... */
4567 context_node = parse_current->next->next->next;
4568 }
4569
4570 if (context_node->cl_head) {
4571 cil_context_init(&genfscon->context);
4572 rc = cil_fill_context(context_node->cl_head, genfscon->context);
4573 if (rc != SEPOL_OK) {
4574 goto exit;
4575 }
4576 } else {
4577 genfscon->context_str = context_node->data;
4578 }
4579
4580 ast_node->data = genfscon;
4581 ast_node->flavor = CIL_GENFSCON;
4582
4583 return SEPOL_OK;
4584
4585 exit:
4586 cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
4587 cil_destroy_genfscon(genfscon);
4588 return SEPOL_ERR;
4589 }
4590
cil_destroy_genfscon(struct cil_genfscon * genfscon)4591 void cil_destroy_genfscon(struct cil_genfscon *genfscon)
4592 {
4593 if (genfscon == NULL) {
4594 return;
4595 }
4596
4597 if (genfscon->context_str == NULL && genfscon->context != NULL) {
4598 cil_destroy_context(genfscon->context);
4599 }
4600
4601 free(genfscon);
4602 }
4603
4604
cil_gen_netifcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4605 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4606 {
4607 enum cil_syntax syntax[] = {
4608 CIL_SYN_STRING,
4609 CIL_SYN_STRING,
4610 CIL_SYN_STRING | CIL_SYN_LIST,
4611 CIL_SYN_STRING | CIL_SYN_LIST,
4612 CIL_SYN_END
4613 };
4614 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4615 int rc = SEPOL_ERR;
4616 struct cil_netifcon *netifcon = NULL;
4617
4618 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4619 goto exit;
4620 }
4621
4622 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4623 if (rc != SEPOL_OK) {
4624 goto exit;
4625 }
4626
4627 cil_netifcon_init(&netifcon);
4628
4629 netifcon->interface_str = parse_current->next->data;
4630
4631 if (parse_current->next->next->cl_head == NULL) {
4632 netifcon->if_context_str = parse_current->next->next->data;
4633 } else {
4634 cil_context_init(&netifcon->if_context);
4635
4636 rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context);
4637 if (rc != SEPOL_OK) {
4638 goto exit;
4639 }
4640 }
4641
4642 if (parse_current->next->next->next->cl_head == NULL) {
4643 netifcon->packet_context_str = parse_current->next->next->next->data;
4644 } else {
4645 cil_context_init(&netifcon->packet_context);
4646
4647 rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context);
4648 if (rc != SEPOL_OK) {
4649 goto exit;
4650 }
4651 }
4652
4653 ast_node->data = netifcon;
4654 ast_node->flavor = CIL_NETIFCON;
4655
4656 return SEPOL_OK;
4657
4658 exit:
4659 cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
4660 cil_destroy_netifcon(netifcon);
4661 return SEPOL_ERR;
4662 }
4663
cil_destroy_netifcon(struct cil_netifcon * netifcon)4664 void cil_destroy_netifcon(struct cil_netifcon *netifcon)
4665 {
4666 if (netifcon == NULL) {
4667 return;
4668 }
4669
4670 if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
4671 cil_destroy_context(netifcon->if_context);
4672 }
4673
4674 if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) {
4675 cil_destroy_context(netifcon->packet_context);
4676 }
4677
4678 free(netifcon);
4679 }
4680
cil_gen_ibendportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4681 int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4682 {
4683 enum cil_syntax syntax[] = {
4684 CIL_SYN_STRING,
4685 CIL_SYN_STRING,
4686 CIL_SYN_STRING,
4687 CIL_SYN_STRING | CIL_SYN_LIST,
4688 CIL_SYN_END
4689 };
4690 size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4691 int rc = SEPOL_ERR;
4692 struct cil_ibendportcon *ibendportcon = NULL;
4693
4694 if (!parse_current || !ast_node)
4695 goto exit;
4696
4697 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4698 if (rc != SEPOL_OK)
4699 goto exit;
4700
4701 cil_ibendportcon_init(&ibendportcon);
4702
4703 ibendportcon->dev_name_str = parse_current->next->data;
4704
4705 rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10);
4706 if (rc != SEPOL_OK) {
4707 cil_log(CIL_ERR, "Improper ibendport port specified\n");
4708 goto exit;
4709 }
4710
4711 if (!parse_current->next->next->next->cl_head) {
4712 ibendportcon->context_str = parse_current->next->next->next->data;
4713 } else {
4714 cil_context_init(&ibendportcon->context);
4715
4716 rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context);
4717 if (rc != SEPOL_OK)
4718 goto exit;
4719 }
4720
4721 ast_node->data = ibendportcon;
4722 ast_node->flavor = CIL_IBENDPORTCON;
4723
4724 return SEPOL_OK;
4725
4726 exit:
4727 cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration");
4728 cil_destroy_ibendportcon(ibendportcon);
4729 return SEPOL_ERR;
4730 }
4731
cil_destroy_ibendportcon(struct cil_ibendportcon * ibendportcon)4732 void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon)
4733 {
4734 if (!ibendportcon)
4735 return;
4736
4737 if (!ibendportcon->context_str && ibendportcon->context)
4738 cil_destroy_context(ibendportcon->context);
4739
4740 free(ibendportcon);
4741 }
4742
cil_gen_pirqcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4743 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4744 {
4745 enum cil_syntax syntax[] = {
4746 CIL_SYN_STRING,
4747 CIL_SYN_STRING,
4748 CIL_SYN_STRING | CIL_SYN_LIST,
4749 CIL_SYN_END
4750 };
4751 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4752 int rc = SEPOL_ERR;
4753 struct cil_pirqcon *pirqcon = NULL;
4754
4755 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4756 goto exit;
4757 }
4758
4759 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4760 if (rc != SEPOL_OK) {
4761 goto exit;
4762 }
4763
4764 cil_pirqcon_init(&pirqcon);
4765
4766 rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
4767 if (rc != SEPOL_OK) {
4768 goto exit;
4769 }
4770
4771 if (parse_current->next->next->cl_head == NULL) {
4772 pirqcon->context_str = parse_current->next->next->data;
4773 } else {
4774 cil_context_init(&pirqcon->context);
4775
4776 rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context);
4777 if (rc != SEPOL_OK) {
4778 goto exit;
4779 }
4780 }
4781
4782 ast_node->data = pirqcon;
4783 ast_node->flavor = CIL_PIRQCON;
4784
4785 return SEPOL_OK;
4786
4787 exit:
4788 cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
4789 cil_destroy_pirqcon(pirqcon);
4790 return rc;
4791 }
4792
cil_destroy_pirqcon(struct cil_pirqcon * pirqcon)4793 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
4794 {
4795 if (pirqcon == NULL) {
4796 return;
4797 }
4798
4799 if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
4800 cil_destroy_context(pirqcon->context);
4801 }
4802
4803 free(pirqcon);
4804 }
4805
cil_gen_iomemcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4806 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4807 {
4808 enum cil_syntax syntax[] = {
4809 CIL_SYN_STRING,
4810 CIL_SYN_STRING | CIL_SYN_LIST,
4811 CIL_SYN_STRING | CIL_SYN_LIST,
4812 CIL_SYN_END
4813 };
4814 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4815 int rc = SEPOL_ERR;
4816 struct cil_iomemcon *iomemcon = NULL;
4817
4818 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4819 goto exit;
4820 }
4821
4822 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4823 if (rc != SEPOL_OK) {
4824 goto exit;
4825 }
4826
4827 cil_iomemcon_init(&iomemcon);
4828
4829 if (parse_current->next->cl_head != NULL) {
4830 if (parse_current->next->cl_head->next != NULL &&
4831 parse_current->next->cl_head->next->next == NULL) {
4832 rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0);
4833 if (rc != SEPOL_OK) {
4834 cil_log(CIL_ERR, "Improper iomem specified\n");
4835 goto exit;
4836 }
4837 rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0);
4838 if (rc != SEPOL_OK) {
4839 cil_log(CIL_ERR, "Improper iomem specified\n");
4840 goto exit;
4841 }
4842 } else {
4843 cil_log(CIL_ERR, "Improper iomem range specified\n");
4844 rc = SEPOL_ERR;
4845 goto exit;
4846 }
4847 } else {
4848 rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0);
4849 if (rc != SEPOL_OK) {
4850 cil_log(CIL_ERR, "Improper iomem specified\n");
4851 goto exit;
4852 }
4853 iomemcon->iomem_high = iomemcon->iomem_low;
4854 }
4855
4856 if (parse_current->next->next->cl_head == NULL ) {
4857 iomemcon->context_str = parse_current->next->next->data;
4858 } else {
4859 cil_context_init(&iomemcon->context);
4860
4861 rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context);
4862 if (rc != SEPOL_OK) {
4863 goto exit;
4864 }
4865 }
4866
4867 ast_node->data = iomemcon;
4868 ast_node->flavor = CIL_IOMEMCON;
4869
4870 return SEPOL_OK;
4871
4872 exit:
4873 cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
4874 cil_destroy_iomemcon(iomemcon);
4875 return rc;
4876 }
4877
cil_destroy_iomemcon(struct cil_iomemcon * iomemcon)4878 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
4879 {
4880 if (iomemcon == NULL) {
4881 return;
4882 }
4883
4884 if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
4885 cil_destroy_context(iomemcon->context);
4886 }
4887
4888 free(iomemcon);
4889 }
4890
cil_gen_ioportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4891 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4892 {
4893 enum cil_syntax syntax[] = {
4894 CIL_SYN_STRING,
4895 CIL_SYN_STRING | CIL_SYN_LIST,
4896 CIL_SYN_STRING | CIL_SYN_LIST,
4897 CIL_SYN_END
4898 };
4899 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4900 int rc = SEPOL_ERR;
4901 struct cil_ioportcon *ioportcon = NULL;
4902
4903 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4904 goto exit;
4905 }
4906
4907 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4908 if (rc != SEPOL_OK) {
4909 goto exit;
4910 }
4911
4912 cil_ioportcon_init(&ioportcon);
4913
4914 if (parse_current->next->cl_head != NULL) {
4915 if (parse_current->next->cl_head->next != NULL &&
4916 parse_current->next->cl_head->next->next == NULL) {
4917 rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0);
4918 if (rc != SEPOL_OK) {
4919 cil_log(CIL_ERR, "Improper ioport specified\n");
4920 goto exit;
4921 }
4922 rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0);
4923 if (rc != SEPOL_OK) {
4924 cil_log(CIL_ERR, "Improper ioport specified\n");
4925 goto exit;
4926 }
4927 } else {
4928 cil_log(CIL_ERR, "Improper ioport range specified\n");
4929 rc = SEPOL_ERR;
4930 goto exit;
4931 }
4932 } else {
4933 rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0);
4934 if (rc != SEPOL_OK) {
4935 cil_log(CIL_ERR, "Improper ioport specified\n");
4936 goto exit;
4937 }
4938 ioportcon->ioport_high = ioportcon->ioport_low;
4939 }
4940
4941 if (parse_current->next->next->cl_head == NULL ) {
4942 ioportcon->context_str = parse_current->next->next->data;
4943 } else {
4944 cil_context_init(&ioportcon->context);
4945
4946 rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context);
4947 if (rc != SEPOL_OK) {
4948 goto exit;
4949 }
4950 }
4951
4952 ast_node->data = ioportcon;
4953 ast_node->flavor = CIL_IOPORTCON;
4954
4955 return SEPOL_OK;
4956
4957 exit:
4958 cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
4959 cil_destroy_ioportcon(ioportcon);
4960 return rc;
4961 }
4962
cil_destroy_ioportcon(struct cil_ioportcon * ioportcon)4963 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
4964 {
4965 if (ioportcon == NULL) {
4966 return;
4967 }
4968
4969 if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
4970 cil_destroy_context(ioportcon->context);
4971 }
4972
4973 free(ioportcon);
4974 }
4975
cil_gen_pcidevicecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4976 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4977 {
4978 enum cil_syntax syntax[] = {
4979 CIL_SYN_STRING,
4980 CIL_SYN_STRING,
4981 CIL_SYN_STRING | CIL_SYN_LIST,
4982 CIL_SYN_END
4983 };
4984 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
4985 int rc = SEPOL_ERR;
4986 struct cil_pcidevicecon *pcidevicecon = NULL;
4987
4988 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4989 goto exit;
4990 }
4991
4992 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4993 if (rc != SEPOL_OK) {
4994 goto exit;
4995 }
4996
4997 cil_pcidevicecon_init(&pcidevicecon);
4998
4999 rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
5000 if (rc != SEPOL_OK) {
5001 goto exit;
5002 }
5003
5004 if (parse_current->next->next->cl_head == NULL) {
5005 pcidevicecon->context_str = parse_current->next->next->data;
5006 } else {
5007 cil_context_init(&pcidevicecon->context);
5008
5009 rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context);
5010 if (rc != SEPOL_OK) {
5011 goto exit;
5012 }
5013 }
5014
5015 ast_node->data = pcidevicecon;
5016 ast_node->flavor = CIL_PCIDEVICECON;
5017
5018 return SEPOL_OK;
5019
5020 exit:
5021 cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
5022 cil_destroy_pcidevicecon(pcidevicecon);
5023 return rc;
5024 }
5025
cil_destroy_pcidevicecon(struct cil_pcidevicecon * pcidevicecon)5026 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
5027 {
5028 if (pcidevicecon == NULL) {
5029 return;
5030 }
5031
5032 if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) {
5033 cil_destroy_context(pcidevicecon->context);
5034 }
5035
5036 free(pcidevicecon);
5037 }
5038
cil_gen_devicetreecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5039 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5040 {
5041 enum cil_syntax syntax[] = {
5042 CIL_SYN_STRING,
5043 CIL_SYN_STRING,
5044 CIL_SYN_STRING | CIL_SYN_LIST,
5045 CIL_SYN_END
5046 };
5047 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5048 int rc = SEPOL_ERR;
5049 struct cil_devicetreecon *devicetreecon = NULL;
5050
5051 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5052 goto exit;
5053 }
5054
5055 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5056 if (rc != SEPOL_OK) {
5057 goto exit;
5058 }
5059
5060 cil_devicetreecon_init(&devicetreecon);
5061
5062 devicetreecon->path = parse_current->next->data;
5063
5064 if (parse_current->next->next->cl_head == NULL) {
5065 devicetreecon->context_str = parse_current->next->next->data;
5066 } else {
5067 cil_context_init(&devicetreecon->context);
5068
5069 rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context);
5070 if (rc != SEPOL_OK) {
5071 goto exit;
5072 }
5073 }
5074
5075 ast_node->data = devicetreecon;
5076 ast_node->flavor = CIL_DEVICETREECON;
5077
5078 return SEPOL_OK;
5079
5080 exit:
5081 cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
5082 cil_destroy_devicetreecon(devicetreecon);
5083 return rc;
5084 }
5085
cil_destroy_devicetreecon(struct cil_devicetreecon * devicetreecon)5086 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
5087 {
5088 if (devicetreecon == NULL) {
5089 return;
5090 }
5091
5092 if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) {
5093 cil_destroy_context(devicetreecon->context);
5094 }
5095
5096 free(devicetreecon);
5097 }
5098
cil_gen_fsuse(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5099 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5100 {
5101 enum cil_syntax syntax[] = {
5102 CIL_SYN_STRING,
5103 CIL_SYN_STRING,
5104 CIL_SYN_STRING,
5105 CIL_SYN_STRING | CIL_SYN_LIST,
5106 CIL_SYN_END
5107 };
5108 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5109 char *type = NULL;
5110 struct cil_fsuse *fsuse = NULL;
5111 int rc = SEPOL_ERR;
5112
5113 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5114 goto exit;
5115 }
5116
5117 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5118 if (rc != SEPOL_OK) {
5119 goto exit;
5120 }
5121
5122 type = parse_current->next->data;
5123
5124 cil_fsuse_init(&fsuse);
5125
5126 if (type == CIL_KEY_XATTR) {
5127 fsuse->type = CIL_FSUSE_XATTR;
5128 } else if (type == CIL_KEY_TASK) {
5129 fsuse->type = CIL_FSUSE_TASK;
5130 } else if (type == CIL_KEY_TRANS) {
5131 fsuse->type = CIL_FSUSE_TRANS;
5132 } else {
5133 cil_log(CIL_ERR, "Invalid fsuse type\n");
5134 goto exit;
5135 }
5136
5137 fsuse->fs_str = parse_current->next->next->data;
5138
5139 if (parse_current->next->next->next->cl_head == NULL) {
5140 fsuse->context_str = parse_current->next->next->next->data;
5141 } else {
5142 cil_context_init(&fsuse->context);
5143
5144 rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context);
5145 if (rc != SEPOL_OK) {
5146 goto exit;
5147 }
5148 }
5149
5150 ast_node->data = fsuse;
5151 ast_node->flavor = CIL_FSUSE;
5152
5153 return SEPOL_OK;
5154
5155 exit:
5156 cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
5157 cil_destroy_fsuse(fsuse);
5158 return SEPOL_ERR;
5159 }
5160
cil_destroy_fsuse(struct cil_fsuse * fsuse)5161 void cil_destroy_fsuse(struct cil_fsuse *fsuse)
5162 {
5163 if (fsuse == NULL) {
5164 return;
5165 }
5166
5167 if (fsuse->context_str == NULL && fsuse->context != NULL) {
5168 cil_destroy_context(fsuse->context);
5169 }
5170
5171 free(fsuse);
5172 }
5173
cil_destroy_param(struct cil_param * param)5174 void cil_destroy_param(struct cil_param *param)
5175 {
5176 if (param == NULL) {
5177 return;
5178 }
5179
5180 free(param);
5181 }
5182
cil_gen_macro(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5183 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5184 {
5185 int rc = SEPOL_ERR;
5186 char *key = NULL;
5187 struct cil_macro *macro = NULL;
5188 struct cil_tree_node *macro_content = NULL;
5189 struct cil_tree_node *current_item;
5190 enum cil_syntax syntax[] = {
5191 CIL_SYN_STRING,
5192 CIL_SYN_STRING,
5193 CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
5194 CIL_SYN_N_LISTS | CIL_SYN_END,
5195 CIL_SYN_END
5196 };
5197 size_t syntax_len = sizeof(syntax)/ sizeof(*syntax);
5198
5199 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5200 goto exit;
5201 }
5202
5203 rc =__cil_verify_syntax(parse_current, syntax, syntax_len);
5204 if (rc != SEPOL_OK) {
5205 goto exit;
5206 }
5207
5208 cil_macro_init(¯o);
5209
5210 key = parse_current->next->data;
5211
5212 current_item = parse_current->next->next->cl_head;
5213 while (current_item != NULL) {
5214 enum cil_syntax param_syntax[] = {
5215 CIL_SYN_STRING,
5216 CIL_SYN_STRING,
5217 CIL_SYN_END
5218 };
5219 int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
5220 char *kind = NULL;
5221 struct cil_param *param = NULL;
5222 struct cil_list_item *curr_param;
5223
5224 rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
5225 if (rc != SEPOL_OK) {
5226 goto exit;
5227 }
5228
5229 if (macro->params == NULL) {
5230 cil_list_init(¯o->params, CIL_LIST_ITEM);
5231 }
5232
5233 kind = current_item->cl_head->data;
5234 cil_param_init(¶m);
5235
5236 if (kind == CIL_KEY_TYPE) {
5237 param->flavor = CIL_TYPE;
5238 } else if (kind == CIL_KEY_ROLE) {
5239 param->flavor = CIL_ROLE;
5240 } else if (kind == CIL_KEY_USER) {
5241 param->flavor = CIL_USER;
5242 } else if (kind == CIL_KEY_SENSITIVITY) {
5243 param->flavor = CIL_SENS;
5244 } else if (kind == CIL_KEY_CATEGORY) {
5245 param->flavor = CIL_CAT;
5246 } else if (kind == CIL_KEY_CATSET) {
5247 param->flavor = CIL_CATSET;
5248 } else if (kind == CIL_KEY_LEVEL) {
5249 param->flavor = CIL_LEVEL;
5250 } else if (kind == CIL_KEY_LEVELRANGE) {
5251 param->flavor = CIL_LEVELRANGE;
5252 } else if (kind == CIL_KEY_CLASS) {
5253 param->flavor = CIL_CLASS;
5254 } else if (kind == CIL_KEY_IPADDR) {
5255 param->flavor = CIL_IPADDR;
5256 } else if (kind == CIL_KEY_MAP_CLASS) {
5257 param->flavor = CIL_MAP_CLASS;
5258 } else if (kind == CIL_KEY_CLASSPERMISSION) {
5259 param->flavor = CIL_CLASSPERMISSION;
5260 } else if (kind == CIL_KEY_BOOL) {
5261 param->flavor = CIL_BOOL;
5262 } else if (kind == CIL_KEY_STRING) {
5263 param->flavor = CIL_DECLARED_STRING;
5264 } else if (kind == CIL_KEY_NAME) {
5265 param->flavor = CIL_DECLARED_STRING;
5266 } else {
5267 cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind);
5268 cil_destroy_param(param);
5269 goto exit;
5270 }
5271
5272 param->str = current_item->cl_head->next->data;
5273
5274 rc = cil_verify_name(db, param->str, param->flavor);
5275 if (rc != SEPOL_OK) {
5276 cil_destroy_param(param);
5277 goto exit;
5278 }
5279
5280 //walk current list and check for duplicate parameters
5281 cil_list_for_each(curr_param, macro->params) {
5282 if (param->str == ((struct cil_param*)curr_param->data)->str) {
5283 cil_log(CIL_ERR, "Duplicate parameter\n");
5284 cil_destroy_param(param);
5285 goto exit;
5286 }
5287 }
5288
5289 cil_list_append(macro->params, CIL_PARAM, param);
5290
5291 current_item = current_item->next;
5292 }
5293
5294 /* 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
5295 node containing the macro name is updated to point to the start of the macro content */
5296 macro_content = parse_current->next->next->next;
5297 cil_tree_subtree_destroy(parse_current->next->next);
5298 parse_current->next->next = macro_content;
5299 if (macro_content == NULL) {
5300 /* No statements in macro and macro parameter list was last node */
5301 parse_current->parent->cl_tail = parse_current->next;
5302 }
5303
5304 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
5305 if (rc != SEPOL_OK) {
5306 goto exit;
5307 }
5308
5309 return SEPOL_OK;
5310
5311 exit:
5312 cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
5313 cil_destroy_macro(macro);
5314 cil_clear_node(ast_node);
5315 return SEPOL_ERR;
5316 }
5317
cil_destroy_macro(struct cil_macro * macro)5318 void cil_destroy_macro(struct cil_macro *macro)
5319 {
5320 if (macro == NULL) {
5321 return;
5322 }
5323
5324 cil_symtab_datum_destroy(¯o->datum);
5325 cil_symtab_array_destroy(macro->symtab);
5326
5327 if (macro->params != NULL) {
5328 cil_list_destroy(¯o->params, 1);
5329 }
5330
5331 free(macro);
5332 }
5333
cil_gen_call(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5334 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5335 {
5336 enum cil_syntax syntax[] = {
5337 CIL_SYN_STRING,
5338 CIL_SYN_STRING,
5339 CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
5340 CIL_SYN_END
5341 };
5342 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5343 struct cil_call *call = NULL;
5344 int rc = SEPOL_ERR;
5345
5346 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5347 goto exit;
5348 }
5349
5350 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5351 if (rc != SEPOL_OK) {
5352 goto exit;
5353 }
5354
5355 cil_call_init(&call);
5356
5357 call->macro_str = parse_current->next->data;
5358
5359 if (parse_current->next->next != NULL) {
5360 cil_tree_init(&call->args_tree);
5361 cil_copy_ast(db, parse_current->next->next, call->args_tree->root);
5362 }
5363
5364 ast_node->data = call;
5365 ast_node->flavor = CIL_CALL;
5366
5367 return SEPOL_OK;
5368
5369 exit:
5370 cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
5371 cil_destroy_call(call);
5372 return rc;
5373 }
5374
cil_destroy_call(struct cil_call * call)5375 void cil_destroy_call(struct cil_call *call)
5376 {
5377 if (call == NULL) {
5378 return;
5379 }
5380
5381 call->macro = NULL;
5382
5383 if (call->args_tree != NULL) {
5384 cil_tree_destroy(&call->args_tree);
5385 }
5386
5387 if (call->args != NULL) {
5388 cil_list_destroy(&call->args, 1);
5389 }
5390
5391 free(call);
5392 }
5393
cil_destroy_args(struct cil_args * args)5394 void cil_destroy_args(struct cil_args *args)
5395 {
5396 if (args == NULL) {
5397 return;
5398 }
5399
5400 if (args->arg_str != NULL) {
5401 args->arg_str = NULL;
5402 } else if (args->arg != NULL) {
5403 struct cil_tree_node *node = args->arg->nodes->head->data;
5404 switch (args->flavor) {
5405 case CIL_DECLARED_STRING:
5406 break;
5407 case CIL_CATSET:
5408 cil_destroy_catset((struct cil_catset *)args->arg);
5409 free(node);
5410 break;
5411 case CIL_LEVEL:
5412 cil_destroy_level((struct cil_level *)args->arg);
5413 free(node);
5414 break;
5415 case CIL_LEVELRANGE:
5416 cil_destroy_levelrange((struct cil_levelrange *)args->arg);
5417 free(node);
5418 break;
5419 case CIL_IPADDR:
5420 cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
5421 free(node);
5422 break;
5423 case CIL_CLASSPERMISSION:
5424 cil_destroy_classpermission((struct cil_classpermission *)args->arg);
5425 free(node);
5426 break;
5427 default:
5428 cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor);
5429 break;
5430 }
5431 }
5432
5433 args->param_str = NULL;
5434 args->arg = NULL;
5435
5436 free(args);
5437 }
5438
cil_gen_optional(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5439 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5440 {
5441 enum cil_syntax syntax[] = {
5442 CIL_SYN_STRING,
5443 CIL_SYN_STRING,
5444 CIL_SYN_N_LISTS | CIL_SYN_END,
5445 CIL_SYN_END
5446 };
5447 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5448 char *key = NULL;
5449 struct cil_optional *optional = NULL;
5450 int rc = SEPOL_ERR;
5451
5452 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5453 goto exit;
5454 }
5455
5456 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5457 if (rc != SEPOL_OK) {
5458 goto exit;
5459 }
5460
5461 cil_optional_init(&optional);
5462
5463 key = parse_current->next->data;
5464
5465 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
5466 if (rc != SEPOL_OK) {
5467 if (rc == SEPOL_EEXIST) {
5468 cil_destroy_optional(optional);
5469 optional = NULL;
5470 } else {
5471 goto exit;
5472 }
5473 }
5474
5475 return SEPOL_OK;
5476
5477 exit:
5478 cil_tree_log(parse_current, CIL_ERR, "Bad optional");
5479 cil_destroy_optional(optional);
5480 cil_clear_node(ast_node);
5481 return rc;
5482 }
5483
cil_destroy_optional(struct cil_optional * optional)5484 void cil_destroy_optional(struct cil_optional *optional)
5485 {
5486 if (optional == NULL) {
5487 return;
5488 }
5489
5490 cil_symtab_datum_destroy(&optional->datum);
5491 free(optional);
5492 }
5493
cil_gen_policycap(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5494 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5495 {
5496 enum cil_syntax syntax[] = {
5497 CIL_SYN_STRING,
5498 CIL_SYN_STRING,
5499 CIL_SYN_END
5500 };
5501 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5502 char *key = NULL;
5503 struct cil_policycap *polcap = NULL;
5504 int rc = SEPOL_ERR;
5505
5506 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5507 goto exit;
5508 }
5509
5510 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5511 if (rc != SEPOL_OK) {
5512 goto exit;
5513 }
5514
5515 cil_policycap_init(&polcap);
5516
5517 key = parse_current->next->data;
5518
5519 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP);
5520 if (rc != SEPOL_OK)
5521 goto exit;
5522
5523 return SEPOL_OK;
5524
5525 exit:
5526 cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
5527 cil_destroy_policycap(polcap);
5528 cil_clear_node(ast_node);
5529 return rc;
5530 }
5531
cil_destroy_policycap(struct cil_policycap * polcap)5532 void cil_destroy_policycap(struct cil_policycap *polcap)
5533 {
5534 if (polcap == NULL) {
5535 return;
5536 }
5537
5538 cil_symtab_datum_destroy(&polcap->datum);
5539 free(polcap);
5540 }
5541
cil_gen_ipaddr(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5542 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5543 {
5544 enum cil_syntax syntax[] = {
5545 CIL_SYN_STRING,
5546 CIL_SYN_STRING,
5547 CIL_SYN_STRING,
5548 CIL_SYN_END
5549 };
5550 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5551 char *key = NULL;
5552 struct cil_ipaddr *ipaddr = NULL;
5553 int rc = SEPOL_ERR;
5554
5555 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5556 goto exit;
5557 }
5558
5559 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5560 if (rc != SEPOL_OK) {
5561 goto exit;
5562 }
5563
5564 cil_ipaddr_init(&ipaddr);
5565
5566 key = parse_current->next->data;
5567
5568 rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
5569 if (rc != SEPOL_OK) {
5570 goto exit;
5571 }
5572
5573 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
5574 if (rc != SEPOL_OK) {
5575 goto exit;
5576 }
5577
5578 return SEPOL_OK;
5579
5580 exit:
5581 cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
5582 cil_destroy_ipaddr(ipaddr);
5583 cil_clear_node(ast_node);
5584 return rc;
5585 }
5586
cil_destroy_ipaddr(struct cil_ipaddr * ipaddr)5587 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
5588 {
5589 if (ipaddr == NULL) {
5590 return;
5591 }
5592
5593 cil_symtab_datum_destroy(&ipaddr->datum);
5594 free(ipaddr);
5595 }
5596
cil_fill_integer(struct cil_tree_node * int_node,uint32_t * integer,int base)5597 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
5598 {
5599 int rc = SEPOL_ERR;
5600
5601 if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5602 goto exit;
5603 }
5604
5605 rc = cil_string_to_uint32(int_node->data, integer, base);
5606 if (rc != SEPOL_OK) {
5607 goto exit;
5608 }
5609
5610 return SEPOL_OK;
5611
5612 exit:
5613 cil_log(CIL_ERR, "Failed to fill 32-bit integer\n");
5614 return rc;
5615 }
5616
cil_fill_integer64(struct cil_tree_node * int_node,uint64_t * integer,int base)5617 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
5618 {
5619 int rc = SEPOL_ERR;
5620
5621 if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5622 goto exit;
5623 }
5624
5625 rc = cil_string_to_uint64(int_node->data, integer, base);
5626 if (rc != SEPOL_OK) {
5627 goto exit;
5628 }
5629
5630 return SEPOL_OK;
5631
5632 exit:
5633 cil_log(CIL_ERR, "Failed to fill 64-bit integer\n");
5634 return rc;
5635 }
5636
cil_fill_ipaddr(struct cil_tree_node * addr_node,struct cil_ipaddr * addr)5637 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
5638 {
5639 int rc = SEPOL_ERR;
5640 char *addr_str;
5641
5642 if (addr_node == NULL || addr_node->data == NULL || addr == NULL) {
5643 goto exit;
5644 }
5645
5646 addr_str = addr_node->data;
5647 if (strchr(addr_str, ':')) {
5648 addr->family = AF_INET6;
5649 } else if (strchr(addr_str, '.') && isdigit(addr_str[0])) {
5650 addr->family = AF_INET;
5651 } else {
5652 goto exit;
5653 }
5654
5655 rc = inet_pton(addr->family, addr_node->data, &addr->ip);
5656 if (rc != 1) {
5657 rc = SEPOL_ERR;
5658 goto exit;
5659 }
5660
5661 return SEPOL_OK;
5662
5663 exit:
5664 cil_log(CIL_ERR, "Bad ip address or netmask: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "NULL");
5665 return rc;
5666 }
5667
cil_fill_level(struct cil_tree_node * curr,struct cil_level * level)5668 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
5669 {
5670 int rc = SEPOL_ERR;
5671 enum cil_syntax syntax[] = {
5672 CIL_SYN_STRING,
5673 CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
5674 CIL_SYN_END
5675 };
5676 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5677
5678 if (curr == NULL) {
5679 goto exit;
5680 }
5681
5682 rc = __cil_verify_syntax(curr, syntax, syntax_len);
5683 if (rc != SEPOL_OK) {
5684 goto exit;
5685 }
5686
5687 level->sens_str = curr->data;
5688 if (curr->next != NULL) {
5689 rc = cil_fill_cats(curr->next, &level->cats);
5690 if (rc != SEPOL_OK) {
5691 goto exit;
5692 }
5693 }
5694
5695 return SEPOL_OK;
5696
5697 exit:
5698 cil_log(CIL_ERR, "Bad level\n");
5699 return rc;
5700 }
5701
cil_fill_cats(struct cil_tree_node * curr,struct cil_cats ** cats)5702 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
5703 {
5704 int rc = SEPOL_ERR;
5705
5706 cil_cats_init(cats);
5707
5708 rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
5709 if (rc != SEPOL_OK) {
5710 cil_destroy_cats(*cats);
5711 *cats = NULL;
5712 }
5713
5714 return rc;
5715 }
5716
cil_destroy_cats(struct cil_cats * cats)5717 void cil_destroy_cats(struct cil_cats *cats)
5718 {
5719 if (cats == NULL) {
5720 return;
5721 }
5722
5723 cil_list_destroy(&cats->str_expr, CIL_TRUE);
5724
5725 cil_list_destroy(&cats->datum_expr, CIL_FALSE);
5726
5727 free(cats);
5728 }
cil_gen_bounds(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5729 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5730 {
5731 enum cil_syntax syntax[] = {
5732 CIL_SYN_STRING,
5733 CIL_SYN_STRING,
5734 CIL_SYN_STRING,
5735 CIL_SYN_END
5736 };
5737 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5738 struct cil_bounds *bounds = NULL;
5739 int rc = SEPOL_ERR;
5740
5741 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5742 goto exit;
5743 }
5744
5745 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5746 if (rc != SEPOL_OK) {
5747 goto exit;
5748 }
5749
5750 cil_bounds_init(&bounds);
5751
5752 bounds->parent_str = parse_current->next->data;
5753 bounds->child_str = parse_current->next->next->data;
5754
5755 ast_node->data = bounds;
5756
5757 switch (flavor) {
5758 case CIL_USER:
5759 ast_node->flavor = CIL_USERBOUNDS;
5760 break;
5761 case CIL_ROLE:
5762 ast_node->flavor = CIL_ROLEBOUNDS;
5763 break;
5764 case CIL_TYPE:
5765 ast_node->flavor = CIL_TYPEBOUNDS;
5766 break;
5767 default:
5768 break;
5769 }
5770
5771 return SEPOL_OK;
5772
5773 exit:
5774 cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
5775 cil_destroy_bounds(bounds);
5776 return rc;
5777 }
5778
cil_destroy_bounds(struct cil_bounds * bounds)5779 void cil_destroy_bounds(struct cil_bounds *bounds)
5780 {
5781 if (bounds == NULL) {
5782 return;
5783 }
5784
5785 free(bounds);
5786 }
5787
cil_gen_default(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5788 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5789 {
5790 int rc = SEPOL_ERR;
5791 struct cil_default *def = NULL;
5792 char *object;
5793 enum cil_syntax syntax[] = {
5794 CIL_SYN_STRING,
5795 CIL_SYN_STRING | CIL_SYN_LIST,
5796 CIL_SYN_STRING,
5797 CIL_SYN_END
5798 };
5799 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5800
5801 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5802 if (rc != SEPOL_OK) {
5803 goto exit;
5804 }
5805
5806 cil_default_init(&def);
5807
5808 def->flavor = flavor;
5809
5810 if (parse_current->next->cl_head == NULL) {
5811 cil_list_init(&def->class_strs, CIL_CLASS);
5812 cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5813 } else {
5814 rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5815 if (rc != SEPOL_OK) {
5816 goto exit;
5817 }
5818 }
5819
5820 object = parse_current->next->next->data;
5821 if (object == CIL_KEY_SOURCE) {
5822 def->object = CIL_DEFAULT_SOURCE;
5823 } else if (object == CIL_KEY_TARGET) {
5824 def->object = CIL_DEFAULT_TARGET;
5825 } else {
5826 cil_log(CIL_ERR,"Expected either 'source' or 'target'\n");
5827 rc = SEPOL_ERR;
5828 goto exit;
5829 }
5830
5831 ast_node->data = def;
5832 ast_node->flavor = flavor;
5833
5834 return SEPOL_OK;
5835
5836 exit:
5837 cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current));
5838 cil_destroy_default(def);
5839 return rc;
5840 }
5841
cil_destroy_default(struct cil_default * def)5842 void cil_destroy_default(struct cil_default *def)
5843 {
5844 if (def == NULL) {
5845 return;
5846 }
5847
5848 cil_list_destroy(&def->class_strs, CIL_TRUE);
5849
5850 cil_list_destroy(&def->class_datums, CIL_FALSE);
5851
5852 free(def);
5853 }
5854
cil_gen_defaultrange(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5855 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5856 {
5857 int rc = SEPOL_ERR;
5858 struct cil_defaultrange *def = NULL;
5859 char *object;
5860 char *range;
5861 enum cil_syntax syntax[] = {
5862 CIL_SYN_STRING,
5863 CIL_SYN_STRING | CIL_SYN_LIST,
5864 CIL_SYN_STRING,
5865 CIL_SYN_STRING | CIL_SYN_END,
5866 CIL_SYN_END
5867 };
5868 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5869
5870 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5871 if (rc != SEPOL_OK) {
5872 goto exit;
5873 }
5874
5875 cil_defaultrange_init(&def);
5876
5877 if (parse_current->next->cl_head == NULL) {
5878 cil_list_init(&def->class_strs, CIL_CLASS);
5879 cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5880 } else {
5881 rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5882 if (rc != SEPOL_OK) {
5883 goto exit;
5884 }
5885 }
5886
5887 object = parse_current->next->next->data;
5888 if (object == CIL_KEY_SOURCE) {
5889 if (!parse_current->next->next->next) {
5890 cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5891 rc = SEPOL_ERR;
5892 goto exit;
5893 }
5894 range = parse_current->next->next->next->data;
5895 if (range == CIL_KEY_LOW) {
5896 def->object_range = CIL_DEFAULT_SOURCE_LOW;
5897 } else if (range == CIL_KEY_HIGH) {
5898 def->object_range = CIL_DEFAULT_SOURCE_HIGH;
5899 } else if (range == CIL_KEY_LOW_HIGH) {
5900 def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
5901 } else {
5902 cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5903 rc = SEPOL_ERR;
5904 goto exit;
5905 }
5906 } else if (object == CIL_KEY_TARGET) {
5907 if (!parse_current->next->next->next) {
5908 cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n");
5909 rc = SEPOL_ERR;
5910 goto exit;
5911 }
5912 range = parse_current->next->next->next->data;
5913 if (range == CIL_KEY_LOW) {
5914 def->object_range = CIL_DEFAULT_TARGET_LOW;
5915 } else if (range == CIL_KEY_HIGH) {
5916 def->object_range = CIL_DEFAULT_TARGET_HIGH;
5917 } else if (range == CIL_KEY_LOW_HIGH) {
5918 def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
5919 } else {
5920 cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5921 rc = SEPOL_ERR;
5922 goto exit;
5923 }
5924 } else if (object == CIL_KEY_GLBLUB) {
5925 def->object_range = CIL_DEFAULT_GLBLUB;
5926 } else {
5927 cil_log(CIL_ERR,"Expected \'source\', \'target\', or \'glblub\'\n");
5928 rc = SEPOL_ERR;
5929 goto exit;
5930 }
5931
5932 ast_node->data = def;
5933 ast_node->flavor = CIL_DEFAULTRANGE;
5934
5935 return SEPOL_OK;
5936
5937 exit:
5938 cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
5939 cil_destroy_defaultrange(def);
5940 return rc;
5941 }
5942
cil_destroy_defaultrange(struct cil_defaultrange * def)5943 void cil_destroy_defaultrange(struct cil_defaultrange *def)
5944 {
5945 if (def == NULL) {
5946 return;
5947 }
5948
5949 cil_list_destroy(&def->class_strs, CIL_TRUE);
5950
5951 cil_list_destroy(&def->class_datums, CIL_FALSE);
5952
5953 free(def);
5954 }
5955
cil_gen_handleunknown(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5956 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5957 {
5958 int rc = SEPOL_ERR;
5959 enum cil_syntax syntax[] = {
5960 CIL_SYN_STRING,
5961 CIL_SYN_STRING,
5962 CIL_SYN_END
5963 };
5964 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
5965 struct cil_handleunknown *unknown = NULL;
5966 char *unknown_key;
5967
5968 if (parse_current == NULL || ast_node == NULL) {
5969 goto exit;
5970 }
5971
5972 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5973 if (rc != SEPOL_OK) {
5974 goto exit;
5975 }
5976
5977 cil_handleunknown_init(&unknown);
5978
5979 unknown_key = parse_current->next->data;
5980 if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
5981 unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
5982 } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
5983 unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
5984 } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
5985 unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
5986 } else {
5987 cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT);
5988 rc = SEPOL_ERR;
5989 goto exit;
5990 }
5991
5992 ast_node->data = unknown;
5993 ast_node->flavor = CIL_HANDLEUNKNOWN;
5994
5995 return SEPOL_OK;
5996
5997 exit:
5998 cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
5999 cil_destroy_handleunknown(unknown);
6000 return rc;
6001 }
6002
cil_destroy_handleunknown(struct cil_handleunknown * unk)6003 void cil_destroy_handleunknown(struct cil_handleunknown *unk)
6004 {
6005 free(unk);
6006 }
6007
cil_gen_mls(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6008 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6009 {
6010 int rc = SEPOL_ERR;
6011 enum cil_syntax syntax[] = {
6012 CIL_SYN_STRING,
6013 CIL_SYN_STRING,
6014 CIL_SYN_END
6015 };
6016 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6017 struct cil_mls *mls = NULL;
6018
6019 if (parse_current == NULL || ast_node == NULL) {
6020 goto exit;
6021 }
6022
6023 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6024 if (rc != SEPOL_OK) {
6025 goto exit;
6026 }
6027
6028 cil_mls_init(&mls);
6029
6030 if (parse_current->next->data == CIL_KEY_CONDTRUE) {
6031 mls->value = CIL_TRUE;
6032 } else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
6033 mls->value = CIL_FALSE;
6034 } else {
6035 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
6036 rc = SEPOL_ERR;
6037 goto exit;
6038 }
6039
6040 ast_node->data = mls;
6041 ast_node->flavor = CIL_MLS;
6042
6043 return SEPOL_OK;
6044
6045 exit:
6046 cil_tree_log(parse_current, CIL_ERR, "Bad mls");
6047 cil_destroy_mls(mls);
6048 return rc;
6049 }
6050
cil_destroy_mls(struct cil_mls * mls)6051 void cil_destroy_mls(struct cil_mls *mls)
6052 {
6053 free(mls);
6054 }
6055
cil_gen_src_info(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6056 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6057 {
6058 int rc = SEPOL_ERR;
6059 enum cil_syntax syntax[] = {
6060 CIL_SYN_STRING,
6061 CIL_SYN_STRING,
6062 CIL_SYN_STRING,
6063 CIL_SYN_STRING,
6064 CIL_SYN_N_LISTS | CIL_SYN_END,
6065 CIL_SYN_END
6066 };
6067 size_t syntax_len = sizeof(syntax)/sizeof(*syntax);
6068 struct cil_src_info *info = NULL;
6069
6070 if (parse_current == NULL || ast_node == NULL) {
6071 goto exit;
6072 }
6073
6074 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6075 if (rc != SEPOL_OK) {
6076 goto exit;
6077 }
6078
6079 cil_src_info_init(&info);
6080
6081 info->kind = parse_current->next->data;
6082 if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) {
6083 cil_log(CIL_ERR, "Invalid src info kind\n");
6084 rc = SEPOL_ERR;
6085 goto exit;
6086 }
6087
6088 rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10);
6089 if (rc != SEPOL_OK) {
6090 goto exit;
6091 }
6092
6093 info->path = parse_current->next->next->next->data;
6094
6095 ast_node->data = info;
6096 ast_node->flavor = CIL_SRC_INFO;
6097
6098 return SEPOL_OK;
6099
6100 exit:
6101 cil_tree_log(parse_current, CIL_ERR, "Bad src info");
6102 cil_destroy_src_info(info);
6103 return rc;
6104 }
6105
cil_destroy_src_info(struct cil_src_info * info)6106 void cil_destroy_src_info(struct cil_src_info *info)
6107 {
6108 free(info);
6109 }
6110
check_for_illegal_statement(struct cil_tree_node * parse_current,struct cil_args_build * args)6111 static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args)
6112 {
6113 if (args->tunif != NULL) {
6114 if (parse_current->data == CIL_KEY_TUNABLE) {
6115 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data);
6116 return SEPOL_ERR;
6117 }
6118 }
6119
6120 if (args->in != NULL) {
6121 struct cil_in *in_block = args->in->data;
6122 if (parse_current->data == CIL_KEY_TUNABLE ||
6123 parse_current->data == CIL_KEY_IN) {
6124 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data);
6125 return SEPOL_ERR;
6126 }
6127 if (in_block->is_after == CIL_TRUE) {
6128 if (parse_current->data == CIL_KEY_BLOCKINHERIT ||
6129 parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6130 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data);
6131 return SEPOL_ERR;
6132 }
6133 }
6134 }
6135
6136 if (args->macro != NULL) {
6137 if (parse_current->data == CIL_KEY_TUNABLE ||
6138 parse_current->data == CIL_KEY_IN ||
6139 parse_current->data == CIL_KEY_BLOCK ||
6140 parse_current->data == CIL_KEY_BLOCKINHERIT ||
6141 parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6142 parse_current->data == CIL_KEY_MACRO) {
6143 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data);
6144 return SEPOL_ERR;
6145 }
6146 }
6147
6148 if (args->optional != NULL) {
6149 if (parse_current->data == CIL_KEY_TUNABLE ||
6150 parse_current->data == CIL_KEY_IN ||
6151 parse_current->data == CIL_KEY_BLOCK ||
6152 parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6153 parse_current->data == CIL_KEY_MACRO) {
6154 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data);
6155 return SEPOL_ERR;
6156 }
6157 }
6158
6159 if (args->boolif != NULL) {
6160 if (parse_current->data != CIL_KEY_TUNABLEIF &&
6161 parse_current->data != CIL_KEY_CALL &&
6162 parse_current->data != CIL_KEY_CONDTRUE &&
6163 parse_current->data != CIL_KEY_CONDFALSE &&
6164 parse_current->data != CIL_KEY_ALLOW &&
6165 parse_current->data != CIL_KEY_DONTAUDIT &&
6166 parse_current->data != CIL_KEY_AUDITALLOW &&
6167 parse_current->data != CIL_KEY_TYPETRANSITION &&
6168 parse_current->data != CIL_KEY_TYPECHANGE &&
6169 parse_current->data != CIL_KEY_TYPEMEMBER) {
6170 if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) {
6171 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data);
6172 } else {
6173 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data);
6174 }
6175 return SEPOL_ERR;
6176 }
6177 }
6178
6179 return SEPOL_OK;
6180 }
6181
parse_statement(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_parent)6182 static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent)
6183 {
6184 struct cil_tree_node *new_ast_node = NULL;
6185 int rc = SEPOL_ERR;
6186
6187 cil_tree_node_init(&new_ast_node);
6188 new_ast_node->parent = ast_parent;
6189 new_ast_node->line = parse_current->line;
6190 new_ast_node->hll_offset = parse_current->hll_offset;
6191
6192 if (parse_current->data == CIL_KEY_BLOCK) {
6193 rc = cil_gen_block(db, parse_current, new_ast_node, 0);
6194 } else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
6195 rc = cil_gen_blockinherit(db, parse_current, new_ast_node);
6196 } else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6197 rc = cil_gen_blockabstract(db, parse_current, new_ast_node);
6198 } else if (parse_current->data == CIL_KEY_IN) {
6199 rc = cil_gen_in(db, parse_current, new_ast_node);
6200 } else if (parse_current->data == CIL_KEY_CLASS) {
6201 rc = cil_gen_class(db, parse_current, new_ast_node);
6202 } else if (parse_current->data == CIL_KEY_CLASSORDER) {
6203 rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CLASSORDER);
6204 } else if (parse_current->data == CIL_KEY_MAP_CLASS) {
6205 rc = cil_gen_map_class(db, parse_current, new_ast_node);
6206 } else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
6207 rc = cil_gen_classmapping(db, parse_current, new_ast_node);
6208 } else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
6209 rc = cil_gen_classpermission(db, parse_current, new_ast_node);
6210 } else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
6211 rc = cil_gen_classpermissionset(db, parse_current, new_ast_node);
6212 } else if (parse_current->data == CIL_KEY_COMMON) {
6213 rc = cil_gen_common(db, parse_current, new_ast_node);
6214 } else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
6215 rc = cil_gen_classcommon(db, parse_current, new_ast_node);
6216 } else if (parse_current->data == CIL_KEY_SID) {
6217 rc = cil_gen_sid(db, parse_current, new_ast_node);
6218 } else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
6219 rc = cil_gen_sidcontext(db, parse_current, new_ast_node);
6220 } else if (parse_current->data == CIL_KEY_SIDORDER) {
6221 rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SIDORDER);
6222 } else if (parse_current->data == CIL_KEY_USER) {
6223 rc = cil_gen_user(db, parse_current, new_ast_node);
6224 } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
6225 rc = cil_gen_userattribute(db, parse_current, new_ast_node);
6226 } else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
6227 rc = cil_gen_userattributeset(db, parse_current, new_ast_node);
6228 } else if (parse_current->data == CIL_KEY_USERLEVEL) {
6229 rc = cil_gen_userlevel(db, parse_current, new_ast_node);
6230 } else if (parse_current->data == CIL_KEY_USERRANGE) {
6231 rc = cil_gen_userrange(db, parse_current, new_ast_node);
6232 } else if (parse_current->data == CIL_KEY_USERBOUNDS) {
6233 rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER);
6234 } else if (parse_current->data == CIL_KEY_USERPREFIX) {
6235 rc = cil_gen_userprefix(db, parse_current, new_ast_node);
6236 } else if (parse_current->data == CIL_KEY_SELINUXUSER) {
6237 rc = cil_gen_selinuxuser(db, parse_current, new_ast_node);
6238 } else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
6239 rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node);
6240 } else if (parse_current->data == CIL_KEY_TYPE) {
6241 rc = cil_gen_type(db, parse_current, new_ast_node);
6242 } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
6243 rc = cil_gen_typeattribute(db, parse_current, new_ast_node);
6244 } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
6245 rc = cil_gen_typeattributeset(db, parse_current, new_ast_node);
6246 } else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
6247 rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node);
6248 } else if (parse_current->data == CIL_KEY_TYPEALIAS) {
6249 rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS);
6250 } else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
6251 rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL);
6252 } else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
6253 rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE);
6254 } else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
6255 rc = cil_gen_typepermissive(db, parse_current, new_ast_node);
6256 } else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
6257 rc = cil_gen_rangetransition(db, parse_current, new_ast_node);
6258 } else if (parse_current->data == CIL_KEY_ROLE) {
6259 rc = cil_gen_role(db, parse_current, new_ast_node);
6260 } else if (parse_current->data == CIL_KEY_USERROLE) {
6261 rc = cil_gen_userrole(db, parse_current, new_ast_node);
6262 } else if (parse_current->data == CIL_KEY_ROLETYPE) {
6263 rc = cil_gen_roletype(db, parse_current, new_ast_node);
6264 } else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
6265 rc = cil_gen_roletransition(parse_current, new_ast_node);
6266 } else if (parse_current->data == CIL_KEY_ROLEALLOW) {
6267 rc = cil_gen_roleallow(db, parse_current, new_ast_node);
6268 } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
6269 rc = cil_gen_roleattribute(db, parse_current, new_ast_node);
6270 } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
6271 rc = cil_gen_roleattributeset(db, parse_current, new_ast_node);
6272 } else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
6273 rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE);
6274 } else if (parse_current->data == CIL_KEY_BOOL) {
6275 rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE);
6276 } else if (parse_current->data == CIL_KEY_BOOLEANIF) {
6277 rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE);
6278 } else if(parse_current->data == CIL_KEY_TUNABLE) {
6279 if (db->preserve_tunables) {
6280 rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE);
6281 } else {
6282 rc = cil_gen_tunable(db, parse_current, new_ast_node);
6283 }
6284 } else if (parse_current->data == CIL_KEY_TUNABLEIF) {
6285 if (db->preserve_tunables) {
6286 rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE);
6287 } else {
6288 rc = cil_gen_tunif(db, parse_current, new_ast_node);
6289 }
6290 } else if (parse_current->data == CIL_KEY_CONDTRUE) {
6291 rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE);
6292 } else if (parse_current->data == CIL_KEY_CONDFALSE) {
6293 rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE);
6294 } else if (parse_current->data == CIL_KEY_ALLOW) {
6295 rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6296 } else if (parse_current->data == CIL_KEY_AUDITALLOW) {
6297 rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6298 } else if (parse_current->data == CIL_KEY_DONTAUDIT) {
6299 rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6300 } else if (parse_current->data == CIL_KEY_NEVERALLOW) {
6301 rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6302 } else if (parse_current->data == CIL_KEY_ALLOWX) {
6303 rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED);
6304 } else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
6305 rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW);
6306 } else if (parse_current->data == CIL_KEY_DONTAUDITX) {
6307 rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT);
6308 } else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
6309 rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW);
6310 } else if (parse_current->data == CIL_KEY_PERMISSIONX) {
6311 rc = cil_gen_permissionx(db, parse_current, new_ast_node);
6312 } else if (parse_current->data == CIL_KEY_DENY_RULE) {
6313 rc = cil_gen_deny_rule(parse_current, new_ast_node);
6314 } else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
6315 rc = cil_gen_typetransition(db, parse_current, new_ast_node);
6316 } else if (parse_current->data == CIL_KEY_TYPECHANGE) {
6317 rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE);
6318 } else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
6319 rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER);
6320 } else if (parse_current->data == CIL_KEY_SENSITIVITY) {
6321 rc = cil_gen_sensitivity(db, parse_current, new_ast_node);
6322 } else if (parse_current->data == CIL_KEY_SENSALIAS) {
6323 rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS);
6324 } else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
6325 rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL);
6326 } else if (parse_current->data == CIL_KEY_CATEGORY) {
6327 rc = cil_gen_category(db, parse_current, new_ast_node);
6328 } else if (parse_current->data == CIL_KEY_CATALIAS) {
6329 rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS);
6330 } else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
6331 rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL);
6332 } else if (parse_current->data == CIL_KEY_CATSET) {
6333 rc = cil_gen_catset(db, parse_current, new_ast_node);
6334 } else if (parse_current->data == CIL_KEY_CATORDER) {
6335 rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_CATORDER);
6336 } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
6337 rc = cil_gen_ordered(db, parse_current, new_ast_node, CIL_SENSITIVITYORDER);
6338 } else if (parse_current->data == CIL_KEY_SENSCAT) {
6339 rc = cil_gen_senscat(db, parse_current, new_ast_node);
6340 } else if (parse_current->data == CIL_KEY_LEVEL) {
6341 rc = cil_gen_level(db, parse_current, new_ast_node);
6342 } else if (parse_current->data == CIL_KEY_LEVELRANGE) {
6343 rc = cil_gen_levelrange(db, parse_current, new_ast_node);
6344 } else if (parse_current->data == CIL_KEY_CONSTRAIN) {
6345 rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN);
6346 } else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
6347 rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN);
6348 } else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
6349 rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS);
6350 } else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
6351 rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS);
6352 } else if (parse_current->data == CIL_KEY_CONTEXT) {
6353 rc = cil_gen_context(db, parse_current, new_ast_node);
6354 } else if (parse_current->data == CIL_KEY_FILECON) {
6355 rc = cil_gen_filecon(db, parse_current, new_ast_node);
6356 } else if (parse_current->data == CIL_KEY_IBPKEYCON) {
6357 rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node);
6358 } else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
6359 rc = cil_gen_ibendportcon(db, parse_current, new_ast_node);
6360 } else if (parse_current->data == CIL_KEY_PORTCON) {
6361 rc = cil_gen_portcon(db, parse_current, new_ast_node);
6362 } else if (parse_current->data == CIL_KEY_NODECON) {
6363 rc = cil_gen_nodecon(db, parse_current, new_ast_node);
6364 } else if (parse_current->data == CIL_KEY_GENFSCON) {
6365 rc = cil_gen_genfscon(db, parse_current, new_ast_node);
6366 } else if (parse_current->data == CIL_KEY_NETIFCON) {
6367 rc = cil_gen_netifcon(db, parse_current, new_ast_node);
6368 } else if (parse_current->data == CIL_KEY_PIRQCON) {
6369 rc = cil_gen_pirqcon(db, parse_current, new_ast_node);
6370 } else if (parse_current->data == CIL_KEY_IOMEMCON) {
6371 rc = cil_gen_iomemcon(db, parse_current, new_ast_node);
6372 } else if (parse_current->data == CIL_KEY_IOPORTCON) {
6373 rc = cil_gen_ioportcon(db, parse_current, new_ast_node);
6374 } else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
6375 rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node);
6376 } else if (parse_current->data == CIL_KEY_DEVICETREECON) {
6377 rc = cil_gen_devicetreecon(db, parse_current, new_ast_node);
6378 } else if (parse_current->data == CIL_KEY_FSUSE) {
6379 rc = cil_gen_fsuse(db, parse_current, new_ast_node);
6380 } else if (parse_current->data == CIL_KEY_MACRO) {
6381 rc = cil_gen_macro(db, parse_current, new_ast_node);
6382 } else if (parse_current->data == CIL_KEY_CALL) {
6383 rc = cil_gen_call(db, parse_current, new_ast_node);
6384 } else if (parse_current->data == CIL_KEY_POLICYCAP) {
6385 rc = cil_gen_policycap(db, parse_current, new_ast_node);
6386 } else if (parse_current->data == CIL_KEY_OPTIONAL) {
6387 rc = cil_gen_optional(db, parse_current, new_ast_node);
6388 } else if (parse_current->data == CIL_KEY_IPADDR) {
6389 rc = cil_gen_ipaddr(db, parse_current, new_ast_node);
6390 } else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
6391 rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER);
6392 } else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
6393 rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE);
6394 } else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
6395 rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE);
6396 } else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
6397 rc = cil_gen_defaultrange(parse_current, new_ast_node);
6398 } else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
6399 rc = cil_gen_handleunknown(parse_current, new_ast_node);
6400 } else if (parse_current->data == CIL_KEY_MLS) {
6401 rc = cil_gen_mls(parse_current, new_ast_node);
6402 } else if (parse_current->data == CIL_KEY_SRC_INFO) {
6403 rc = cil_gen_src_info(parse_current, new_ast_node);
6404 } else {
6405 cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
6406 rc = SEPOL_ERR;
6407 }
6408
6409 if (rc == SEPOL_OK) {
6410 if (ast_parent->cl_head == NULL) {
6411 ast_parent->cl_head = new_ast_node;
6412 } else {
6413 ast_parent->cl_tail->next = new_ast_node;
6414 }
6415 ast_parent->cl_tail = new_ast_node;
6416 } else {
6417 cil_tree_node_destroy(&new_ast_node);
6418 new_ast_node = NULL;
6419 }
6420
6421 return new_ast_node;
6422 }
6423
__cil_build_ast_node_helper(struct cil_tree_node * parse_current,uint32_t * finished,void * extra_args)6424 static int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
6425 {
6426 struct cil_args_build *args = extra_args;
6427 struct cil_tree_node *new_ast_node = NULL;
6428 int rc = SEPOL_ERR;
6429
6430 if (parse_current->parent->cl_head != parse_current) {
6431 /* ignore anything that isn't following a parenthesis */
6432 return SEPOL_OK;
6433 } else if (parse_current->data == NULL) {
6434 /* the only time parenthesis can immediately following parenthesis is if
6435 * the parent is the root node */
6436 if (parse_current->parent->parent == NULL) {
6437 return SEPOL_OK;
6438 } else {
6439 cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
6440 return SEPOL_ERR;
6441 }
6442 }
6443
6444 rc = check_for_illegal_statement(parse_current, args);
6445 if (rc != SEPOL_OK) {
6446 return SEPOL_ERR;
6447 }
6448
6449 new_ast_node = parse_statement(args->db, parse_current, args->ast);
6450 if (!new_ast_node) {
6451 return SEPOL_ERR;
6452 }
6453
6454 args->ast = new_ast_node;
6455
6456 if (parse_current->data != CIL_KEY_BLOCK &&
6457 parse_current->data != CIL_KEY_IN &&
6458 parse_current->data != CIL_KEY_TUNABLEIF &&
6459 parse_current->data != CIL_KEY_BOOLEANIF &&
6460 parse_current->data != CIL_KEY_CONDTRUE &&
6461 parse_current->data != CIL_KEY_CONDFALSE &&
6462 parse_current->data != CIL_KEY_MACRO &&
6463 parse_current->data != CIL_KEY_OPTIONAL &&
6464 parse_current->data != CIL_KEY_SRC_INFO) {
6465 /* Skip anything that does not contain a list of policy statements */
6466 *finished = CIL_TREE_SKIP_NEXT;
6467 }
6468
6469 return SEPOL_OK;
6470 }
6471
__cil_build_ast_first_child_helper(struct cil_tree_node * parse_current,void * extra_args)6472 static int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args)
6473 {
6474 struct cil_args_build *args = extra_args;
6475 struct cil_tree_node *ast = args->ast;
6476
6477 if (ast->flavor == CIL_TUNABLEIF) {
6478 args->tunif = ast;
6479 } else if (ast->flavor == CIL_IN) {
6480 args->in = ast;
6481 } else if (ast->flavor == CIL_MACRO) {
6482 args->macro = ast;
6483 } else if (ast->flavor == CIL_OPTIONAL) {
6484 args->optional = ast;
6485 } else if (ast->flavor == CIL_BOOLEANIF) {
6486 args->boolif = ast;
6487 }
6488
6489 return SEPOL_OK;
6490 }
6491
__cil_build_ast_last_child_helper(struct cil_tree_node * parse_current,void * extra_args)6492 static int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
6493 {
6494 struct cil_args_build *args = extra_args;
6495 struct cil_tree_node *ast = args->ast;
6496
6497 if (ast->flavor == CIL_ROOT) {
6498 return SEPOL_OK;
6499 }
6500
6501 args->ast = ast->parent;
6502
6503 if (ast->flavor == CIL_TUNABLEIF) {
6504 args->tunif = NULL;
6505 }
6506
6507 if (ast->flavor == CIL_IN) {
6508 args->in = NULL;
6509 }
6510
6511 if (ast->flavor == CIL_MACRO) {
6512 args->macro = NULL;
6513 }
6514
6515 if (ast->flavor == CIL_OPTIONAL) {
6516 struct cil_tree_node *n = ast->parent;
6517 args->optional = NULL;
6518 /* Optionals can be nested */
6519 while (n && n->flavor != CIL_ROOT) {
6520 if (n->flavor == CIL_OPTIONAL) {
6521 args->optional = n;
6522 break;
6523 }
6524 n = n->parent;
6525 }
6526 }
6527
6528 if (ast->flavor == CIL_BOOLEANIF) {
6529 args->boolif = NULL;
6530 }
6531
6532 // At this point we no longer have any need for parse_current or any of its
6533 // siblings; they have all been converted to the appropriate AST node. The
6534 // full parse tree will get deleted elsewhere, but in an attempt to
6535 // minimize memory usage (of which the parse tree uses a lot), start
6536 // deleting the parts we don't need now.
6537 cil_tree_children_destroy(parse_current->parent);
6538
6539 return SEPOL_OK;
6540 }
6541
cil_build_ast(struct cil_db * db,struct cil_tree_node * parse_tree,struct cil_tree_node * ast)6542 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
6543 {
6544 int rc = SEPOL_ERR;
6545 struct cil_args_build extra_args;
6546
6547 if (db == NULL || parse_tree == NULL || ast == NULL) {
6548 goto exit;
6549 }
6550
6551 extra_args.ast = ast;
6552 extra_args.db = db;
6553 extra_args.tunif = NULL;
6554 extra_args.in = NULL;
6555 extra_args.macro = NULL;
6556 extra_args.optional = NULL;
6557 extra_args.boolif = NULL;
6558
6559 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);
6560 if (rc != SEPOL_OK) {
6561 goto exit;
6562 }
6563
6564 return SEPOL_OK;
6565
6566 exit:
6567 return rc;
6568 }
6569