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