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