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