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