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 {
4409 cil_log(CIL_ERR, "Invalid protocol\n");
4410 rc = SEPOL_ERR;
4411 goto exit;
4412 }
4413
4414 if (parse_current->next->next->cl_head != NULL) {
4415 if (parse_current->next->next->cl_head->next != NULL
4416 && parse_current->next->next->cl_head->next->next == NULL) {
4417 rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10);
4418 if (rc != SEPOL_OK) {
4419 cil_log(CIL_ERR, "Improper port specified\n");
4420 goto exit;
4421 }
4422 rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10);
4423 if (rc != SEPOL_OK) {
4424 cil_log(CIL_ERR, "Improper port specified\n");
4425 goto exit;
4426 }
4427 } else {
4428 cil_log(CIL_ERR, "Improper port range specified\n");
4429 rc = SEPOL_ERR;
4430 goto exit;
4431 }
4432 } else {
4433 rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10);
4434 if (rc != SEPOL_OK) {
4435 cil_log(CIL_ERR, "Improper port specified\n");
4436 goto exit;
4437 }
4438 portcon->port_high = portcon->port_low;
4439 }
4440
4441 if (parse_current->next->next->next->cl_head == NULL ) {
4442 portcon->context_str = parse_current->next->next->next->data;
4443 } else {
4444 cil_context_init(&portcon->context);
4445
4446 rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context);
4447 if (rc != SEPOL_OK) {
4448 goto exit;
4449 }
4450 }
4451
4452 ast_node->data = portcon;
4453 ast_node->flavor = CIL_PORTCON;
4454
4455 return SEPOL_OK;
4456
4457 exit:
4458 cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration");
4459 cil_destroy_portcon(portcon);
4460 return rc;
4461 }
4462
cil_destroy_portcon(struct cil_portcon * portcon)4463 void cil_destroy_portcon(struct cil_portcon *portcon)
4464 {
4465 if (portcon == NULL) {
4466 return;
4467 }
4468
4469 if (portcon->context_str == NULL && portcon->context != NULL) {
4470 cil_destroy_context(portcon->context);
4471 }
4472
4473 free(portcon);
4474 }
4475
cil_gen_nodecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4476 int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4477 {
4478 enum cil_syntax syntax[] = {
4479 CIL_SYN_STRING,
4480 CIL_SYN_STRING | CIL_SYN_LIST,
4481 CIL_SYN_STRING | CIL_SYN_LIST,
4482 CIL_SYN_STRING | CIL_SYN_LIST,
4483 CIL_SYN_END
4484 };
4485 int syntax_len = sizeof(syntax)/sizeof(*syntax);
4486 int rc = SEPOL_ERR;
4487 struct cil_nodecon *nodecon = NULL;
4488
4489 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4490 goto exit;
4491 }
4492
4493 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4494 if (rc != SEPOL_OK) {
4495 goto exit;
4496 }
4497
4498 cil_nodecon_init(&nodecon);
4499
4500 if (parse_current->next->cl_head == NULL ) {
4501 nodecon->addr_str = parse_current->next->data;
4502 } else {
4503 cil_ipaddr_init(&nodecon->addr);
4504
4505 rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr);
4506 if (rc != SEPOL_OK) {
4507 goto exit;
4508 }
4509 }
4510
4511 if (parse_current->next->next->cl_head == NULL ) {
4512 nodecon->mask_str = parse_current->next->next->data;
4513 } else {
4514 cil_ipaddr_init(&nodecon->mask);
4515
4516 rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask);
4517 if (rc != SEPOL_OK) {
4518 goto exit;
4519 }
4520 }
4521
4522 if (parse_current->next->next->next->cl_head == NULL ) {
4523 nodecon->context_str = parse_current->next->next->next->data;
4524 } else {
4525 cil_context_init(&nodecon->context);
4526
4527 rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context);
4528 if (rc != SEPOL_OK) {
4529 goto exit;
4530 }
4531 }
4532
4533 ast_node->data = nodecon;
4534 ast_node->flavor = CIL_NODECON;
4535
4536 return SEPOL_OK;
4537
4538 exit:
4539 cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration");
4540 cil_destroy_nodecon(nodecon);
4541 return rc;
4542 }
4543
cil_destroy_nodecon(struct cil_nodecon * nodecon)4544 void cil_destroy_nodecon(struct cil_nodecon *nodecon)
4545 {
4546 if (nodecon == NULL) {
4547 return;
4548 }
4549
4550 if (nodecon->addr_str == NULL && nodecon->addr != NULL) {
4551 cil_destroy_ipaddr(nodecon->addr);
4552 }
4553
4554 if (nodecon->mask_str == NULL && nodecon->mask != NULL) {
4555 cil_destroy_ipaddr(nodecon->mask);
4556 }
4557
4558 if (nodecon->context_str == NULL && nodecon->context != NULL) {
4559 cil_destroy_context(nodecon->context);
4560 }
4561
4562 free(nodecon);
4563 }
4564
cil_gen_genfscon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4565 int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4566 {
4567 enum cil_syntax syntax[] = {
4568 CIL_SYN_STRING,
4569 CIL_SYN_STRING,
4570 CIL_SYN_STRING,
4571 CIL_SYN_STRING | CIL_SYN_LIST,
4572 CIL_SYN_END
4573 };
4574 int syntax_len = sizeof(syntax)/sizeof(*syntax);
4575 int rc = SEPOL_ERR;
4576 struct cil_genfscon *genfscon = NULL;
4577
4578 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4579 goto exit;
4580 }
4581
4582 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4583 if (rc != SEPOL_OK) {
4584 goto exit;
4585 }
4586
4587 cil_genfscon_init(&genfscon);
4588
4589 genfscon->fs_str = parse_current->next->data;
4590 genfscon->path_str = parse_current->next->next->data;
4591
4592 if (parse_current->next->next->next->cl_head == NULL ) {
4593 genfscon->context_str = parse_current->next->next->next->data;
4594 } else {
4595 cil_context_init(&genfscon->context);
4596
4597 rc = cil_fill_context(parse_current->next->next->next->cl_head, genfscon->context);
4598 if (rc != SEPOL_OK) {
4599 goto exit;
4600 }
4601 }
4602
4603 ast_node->data = genfscon;
4604 ast_node->flavor = CIL_GENFSCON;
4605
4606 return SEPOL_OK;
4607
4608 exit:
4609 cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
4610 cil_destroy_genfscon(genfscon);
4611 return SEPOL_ERR;
4612 }
4613
cil_destroy_genfscon(struct cil_genfscon * genfscon)4614 void cil_destroy_genfscon(struct cil_genfscon *genfscon)
4615 {
4616 if (genfscon == NULL) {
4617 return;
4618 }
4619
4620 if (genfscon->context_str == NULL && genfscon->context != NULL) {
4621 cil_destroy_context(genfscon->context);
4622 }
4623
4624 free(genfscon);
4625 }
4626
4627
cil_gen_netifcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4628 int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4629 {
4630 enum cil_syntax syntax[] = {
4631 CIL_SYN_STRING,
4632 CIL_SYN_STRING,
4633 CIL_SYN_STRING | CIL_SYN_LIST,
4634 CIL_SYN_STRING | CIL_SYN_LIST,
4635 CIL_SYN_END
4636 };
4637 int syntax_len = sizeof(syntax)/sizeof(*syntax);
4638 int rc = SEPOL_ERR;
4639 struct cil_netifcon *netifcon = NULL;
4640
4641 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4642 goto exit;
4643 }
4644
4645 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4646 if (rc != SEPOL_OK) {
4647 goto exit;
4648 }
4649
4650 cil_netifcon_init(&netifcon);
4651
4652 netifcon->interface_str = parse_current->next->data;
4653
4654 if (parse_current->next->next->cl_head == NULL) {
4655 netifcon->if_context_str = parse_current->next->next->data;
4656 } else {
4657 cil_context_init(&netifcon->if_context);
4658
4659 rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context);
4660 if (rc != SEPOL_OK) {
4661 goto exit;
4662 }
4663 }
4664
4665 if (parse_current->next->next->next->cl_head == NULL) {
4666 netifcon->packet_context_str = parse_current->next->next->next->data;
4667 } else {
4668 cil_context_init(&netifcon->packet_context);
4669
4670 rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context);
4671 if (rc != SEPOL_OK) {
4672 goto exit;
4673 }
4674 }
4675
4676 ast_node->data = netifcon;
4677 ast_node->flavor = CIL_NETIFCON;
4678
4679 return SEPOL_OK;
4680
4681 exit:
4682 cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
4683 cil_destroy_netifcon(netifcon);
4684 return SEPOL_ERR;
4685 }
4686
cil_destroy_netifcon(struct cil_netifcon * netifcon)4687 void cil_destroy_netifcon(struct cil_netifcon *netifcon)
4688 {
4689 if (netifcon == NULL) {
4690 return;
4691 }
4692
4693 if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
4694 cil_destroy_context(netifcon->if_context);
4695 }
4696
4697 if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) {
4698 cil_destroy_context(netifcon->packet_context);
4699 }
4700
4701 free(netifcon);
4702 }
4703
cil_gen_ibendportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4704 int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4705 {
4706 enum cil_syntax syntax[] = {
4707 CIL_SYN_STRING,
4708 CIL_SYN_STRING,
4709 CIL_SYN_STRING,
4710 CIL_SYN_STRING | CIL_SYN_LIST,
4711 CIL_SYN_END
4712 };
4713 int syntax_len = sizeof(syntax) / sizeof(*syntax);
4714 int rc = SEPOL_ERR;
4715 struct cil_ibendportcon *ibendportcon = NULL;
4716
4717 if (!parse_current || !ast_node)
4718 goto exit;
4719
4720 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4721 if (rc != SEPOL_OK)
4722 goto exit;
4723
4724 cil_ibendportcon_init(&ibendportcon);
4725
4726 ibendportcon->dev_name_str = parse_current->next->data;
4727
4728 rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10);
4729 if (rc != SEPOL_OK) {
4730 cil_log(CIL_ERR, "Improper ibendport port specified\n");
4731 goto exit;
4732 }
4733
4734 if (!parse_current->next->next->next->cl_head) {
4735 ibendportcon->context_str = parse_current->next->next->next->data;
4736 } else {
4737 cil_context_init(&ibendportcon->context);
4738
4739 rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context);
4740 if (rc != SEPOL_OK)
4741 goto exit;
4742 }
4743
4744 ast_node->data = ibendportcon;
4745 ast_node->flavor = CIL_IBENDPORTCON;
4746
4747 return SEPOL_OK;
4748
4749 exit:
4750 cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration");
4751 cil_destroy_ibendportcon(ibendportcon);
4752 return SEPOL_ERR;
4753 }
4754
cil_destroy_ibendportcon(struct cil_ibendportcon * ibendportcon)4755 void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon)
4756 {
4757 if (!ibendportcon)
4758 return;
4759
4760 if (!ibendportcon->context_str && ibendportcon->context)
4761 cil_destroy_context(ibendportcon->context);
4762
4763 free(ibendportcon);
4764 }
4765
cil_gen_pirqcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4766 int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4767 {
4768 enum cil_syntax syntax[] = {
4769 CIL_SYN_STRING,
4770 CIL_SYN_STRING,
4771 CIL_SYN_STRING | CIL_SYN_LIST,
4772 CIL_SYN_END
4773 };
4774 int syntax_len = sizeof(syntax)/sizeof(*syntax);
4775 int rc = SEPOL_ERR;
4776 struct cil_pirqcon *pirqcon = NULL;
4777
4778 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4779 goto exit;
4780 }
4781
4782 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4783 if (rc != SEPOL_OK) {
4784 goto exit;
4785 }
4786
4787 cil_pirqcon_init(&pirqcon);
4788
4789 rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
4790 if (rc != SEPOL_OK) {
4791 goto exit;
4792 }
4793
4794 if (parse_current->next->next->cl_head == NULL) {
4795 pirqcon->context_str = parse_current->next->next->data;
4796 } else {
4797 cil_context_init(&pirqcon->context);
4798
4799 rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context);
4800 if (rc != SEPOL_OK) {
4801 goto exit;
4802 }
4803 }
4804
4805 ast_node->data = pirqcon;
4806 ast_node->flavor = CIL_PIRQCON;
4807
4808 return SEPOL_OK;
4809
4810 exit:
4811 cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
4812 cil_destroy_pirqcon(pirqcon);
4813 return rc;
4814 }
4815
cil_destroy_pirqcon(struct cil_pirqcon * pirqcon)4816 void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
4817 {
4818 if (pirqcon == NULL) {
4819 return;
4820 }
4821
4822 if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
4823 cil_destroy_context(pirqcon->context);
4824 }
4825
4826 free(pirqcon);
4827 }
4828
cil_gen_iomemcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4829 int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4830 {
4831 enum cil_syntax syntax[] = {
4832 CIL_SYN_STRING,
4833 CIL_SYN_STRING | CIL_SYN_LIST,
4834 CIL_SYN_STRING | CIL_SYN_LIST,
4835 CIL_SYN_END
4836 };
4837 int syntax_len = sizeof(syntax)/sizeof(*syntax);
4838 int rc = SEPOL_ERR;
4839 struct cil_iomemcon *iomemcon = NULL;
4840
4841 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4842 goto exit;
4843 }
4844
4845 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4846 if (rc != SEPOL_OK) {
4847 goto exit;
4848 }
4849
4850 cil_iomemcon_init(&iomemcon);
4851
4852 if (parse_current->next->cl_head != NULL) {
4853 if (parse_current->next->cl_head->next != NULL &&
4854 parse_current->next->cl_head->next->next == NULL) {
4855 rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0);
4856 if (rc != SEPOL_OK) {
4857 cil_log(CIL_ERR, "Improper iomem specified\n");
4858 goto exit;
4859 }
4860 rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0);
4861 if (rc != SEPOL_OK) {
4862 cil_log(CIL_ERR, "Improper iomem specified\n");
4863 goto exit;
4864 }
4865 } else {
4866 cil_log(CIL_ERR, "Improper iomem range specified\n");
4867 rc = SEPOL_ERR;
4868 goto exit;
4869 }
4870 } else {
4871 rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0);
4872 if (rc != SEPOL_OK) {
4873 cil_log(CIL_ERR, "Improper iomem specified\n");
4874 goto exit;
4875 }
4876 iomemcon->iomem_high = iomemcon->iomem_low;
4877 }
4878
4879 if (parse_current->next->next->cl_head == NULL ) {
4880 iomemcon->context_str = parse_current->next->next->data;
4881 } else {
4882 cil_context_init(&iomemcon->context);
4883
4884 rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context);
4885 if (rc != SEPOL_OK) {
4886 goto exit;
4887 }
4888 }
4889
4890 ast_node->data = iomemcon;
4891 ast_node->flavor = CIL_IOMEMCON;
4892
4893 return SEPOL_OK;
4894
4895 exit:
4896 cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
4897 cil_destroy_iomemcon(iomemcon);
4898 return rc;
4899 }
4900
cil_destroy_iomemcon(struct cil_iomemcon * iomemcon)4901 void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
4902 {
4903 if (iomemcon == NULL) {
4904 return;
4905 }
4906
4907 if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
4908 cil_destroy_context(iomemcon->context);
4909 }
4910
4911 free(iomemcon);
4912 }
4913
cil_gen_ioportcon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4914 int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
4915 {
4916 enum cil_syntax syntax[] = {
4917 CIL_SYN_STRING,
4918 CIL_SYN_STRING | CIL_SYN_LIST,
4919 CIL_SYN_STRING | CIL_SYN_LIST,
4920 CIL_SYN_END
4921 };
4922 int syntax_len = sizeof(syntax)/sizeof(*syntax);
4923 int rc = SEPOL_ERR;
4924 struct cil_ioportcon *ioportcon = NULL;
4925
4926 if (db == NULL || parse_current == NULL || ast_node == NULL) {
4927 goto exit;
4928 }
4929
4930 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4931 if (rc != SEPOL_OK) {
4932 goto exit;
4933 }
4934
4935 cil_ioportcon_init(&ioportcon);
4936
4937 if (parse_current->next->cl_head != NULL) {
4938 if (parse_current->next->cl_head->next != NULL &&
4939 parse_current->next->cl_head->next->next == NULL) {
4940 rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0);
4941 if (rc != SEPOL_OK) {
4942 cil_log(CIL_ERR, "Improper ioport specified\n");
4943 goto exit;
4944 }
4945 rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0);
4946 if (rc != SEPOL_OK) {
4947 cil_log(CIL_ERR, "Improper ioport specified\n");
4948 goto exit;
4949 }
4950 } else {
4951 cil_log(CIL_ERR, "Improper ioport range specified\n");
4952 rc = SEPOL_ERR;
4953 goto exit;
4954 }
4955 } else {
4956 rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0);
4957 if (rc != SEPOL_OK) {
4958 cil_log(CIL_ERR, "Improper ioport specified\n");
4959 goto exit;
4960 }
4961 ioportcon->ioport_high = ioportcon->ioport_low;
4962 }
4963
4964 if (parse_current->next->next->cl_head == NULL ) {
4965 ioportcon->context_str = parse_current->next->next->data;
4966 } else {
4967 cil_context_init(&ioportcon->context);
4968
4969 rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context);
4970 if (rc != SEPOL_OK) {
4971 goto exit;
4972 }
4973 }
4974
4975 ast_node->data = ioportcon;
4976 ast_node->flavor = CIL_IOPORTCON;
4977
4978 return SEPOL_OK;
4979
4980 exit:
4981 cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
4982 cil_destroy_ioportcon(ioportcon);
4983 return rc;
4984 }
4985
cil_destroy_ioportcon(struct cil_ioportcon * ioportcon)4986 void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
4987 {
4988 if (ioportcon == NULL) {
4989 return;
4990 }
4991
4992 if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
4993 cil_destroy_context(ioportcon->context);
4994 }
4995
4996 free(ioportcon);
4997 }
4998
cil_gen_pcidevicecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)4999 int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5000 {
5001 enum cil_syntax syntax[] = {
5002 CIL_SYN_STRING,
5003 CIL_SYN_STRING,
5004 CIL_SYN_STRING | CIL_SYN_LIST,
5005 CIL_SYN_END
5006 };
5007 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5008 int rc = SEPOL_ERR;
5009 struct cil_pcidevicecon *pcidevicecon = NULL;
5010
5011 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5012 goto exit;
5013 }
5014
5015 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5016 if (rc != SEPOL_OK) {
5017 goto exit;
5018 }
5019
5020 cil_pcidevicecon_init(&pcidevicecon);
5021
5022 rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
5023 if (rc != SEPOL_OK) {
5024 goto exit;
5025 }
5026
5027 if (parse_current->next->next->cl_head == NULL) {
5028 pcidevicecon->context_str = parse_current->next->next->data;
5029 } else {
5030 cil_context_init(&pcidevicecon->context);
5031
5032 rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context);
5033 if (rc != SEPOL_OK) {
5034 goto exit;
5035 }
5036 }
5037
5038 ast_node->data = pcidevicecon;
5039 ast_node->flavor = CIL_PCIDEVICECON;
5040
5041 return SEPOL_OK;
5042
5043 exit:
5044 cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
5045 cil_destroy_pcidevicecon(pcidevicecon);
5046 return rc;
5047 }
5048
cil_destroy_pcidevicecon(struct cil_pcidevicecon * pcidevicecon)5049 void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
5050 {
5051 if (pcidevicecon == NULL) {
5052 return;
5053 }
5054
5055 if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) {
5056 cil_destroy_context(pcidevicecon->context);
5057 }
5058
5059 free(pcidevicecon);
5060 }
5061
cil_gen_devicetreecon(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5062 int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5063 {
5064 enum cil_syntax syntax[] = {
5065 CIL_SYN_STRING,
5066 CIL_SYN_STRING,
5067 CIL_SYN_STRING | CIL_SYN_LIST,
5068 CIL_SYN_END
5069 };
5070 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5071 int rc = SEPOL_ERR;
5072 struct cil_devicetreecon *devicetreecon = NULL;
5073
5074 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5075 goto exit;
5076 }
5077
5078 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5079 if (rc != SEPOL_OK) {
5080 goto exit;
5081 }
5082
5083 cil_devicetreecon_init(&devicetreecon);
5084
5085 devicetreecon->path = parse_current->next->data;
5086
5087 if (parse_current->next->next->cl_head == NULL) {
5088 devicetreecon->context_str = parse_current->next->next->data;
5089 } else {
5090 cil_context_init(&devicetreecon->context);
5091
5092 rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context);
5093 if (rc != SEPOL_OK) {
5094 goto exit;
5095 }
5096 }
5097
5098 ast_node->data = devicetreecon;
5099 ast_node->flavor = CIL_DEVICETREECON;
5100
5101 return SEPOL_OK;
5102
5103 exit:
5104 cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
5105 cil_destroy_devicetreecon(devicetreecon);
5106 return rc;
5107 }
5108
cil_destroy_devicetreecon(struct cil_devicetreecon * devicetreecon)5109 void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
5110 {
5111 if (devicetreecon == NULL) {
5112 return;
5113 }
5114
5115 if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) {
5116 cil_destroy_context(devicetreecon->context);
5117 }
5118
5119 free(devicetreecon);
5120 }
5121
cil_gen_fsuse(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5122 int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5123 {
5124 enum cil_syntax syntax[] = {
5125 CIL_SYN_STRING,
5126 CIL_SYN_STRING,
5127 CIL_SYN_STRING,
5128 CIL_SYN_STRING | CIL_SYN_LIST,
5129 CIL_SYN_END
5130 };
5131 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5132 char *type = NULL;
5133 struct cil_fsuse *fsuse = NULL;
5134 int rc = SEPOL_ERR;
5135
5136 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5137 goto exit;
5138 }
5139
5140 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5141 if (rc != SEPOL_OK) {
5142 goto exit;
5143 }
5144
5145 type = parse_current->next->data;
5146
5147 cil_fsuse_init(&fsuse);
5148
5149 if (type == CIL_KEY_XATTR) {
5150 fsuse->type = CIL_FSUSE_XATTR;
5151 } else if (type == CIL_KEY_TASK) {
5152 fsuse->type = CIL_FSUSE_TASK;
5153 } else if (type == CIL_KEY_TRANS) {
5154 fsuse->type = CIL_FSUSE_TRANS;
5155 } else {
5156 cil_log(CIL_ERR, "Invalid fsuse type\n");
5157 goto exit;
5158 }
5159
5160 fsuse->fs_str = parse_current->next->next->data;
5161
5162 if (parse_current->next->next->next->cl_head == NULL) {
5163 fsuse->context_str = parse_current->next->next->next->data;
5164 } else {
5165 cil_context_init(&fsuse->context);
5166
5167 rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context);
5168 if (rc != SEPOL_OK) {
5169 goto exit;
5170 }
5171 }
5172
5173 ast_node->data = fsuse;
5174 ast_node->flavor = CIL_FSUSE;
5175
5176 return SEPOL_OK;
5177
5178 exit:
5179 cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
5180 cil_destroy_fsuse(fsuse);
5181 return SEPOL_ERR;
5182 }
5183
cil_destroy_fsuse(struct cil_fsuse * fsuse)5184 void cil_destroy_fsuse(struct cil_fsuse *fsuse)
5185 {
5186 if (fsuse == NULL) {
5187 return;
5188 }
5189
5190 if (fsuse->context_str == NULL && fsuse->context != NULL) {
5191 cil_destroy_context(fsuse->context);
5192 }
5193
5194 free(fsuse);
5195 }
5196
cil_destroy_param(struct cil_param * param)5197 void cil_destroy_param(struct cil_param *param)
5198 {
5199 if (param == NULL) {
5200 return;
5201 }
5202
5203 free(param);
5204 }
5205
cil_gen_macro(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5206 int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5207 {
5208 int rc = SEPOL_ERR;
5209 char *key = NULL;
5210 struct cil_macro *macro = NULL;
5211 struct cil_tree_node *macro_content = NULL;
5212 enum cil_syntax syntax[] = {
5213 CIL_SYN_STRING,
5214 CIL_SYN_STRING,
5215 CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
5216 CIL_SYN_N_LISTS | CIL_SYN_END,
5217 CIL_SYN_END
5218 };
5219 int syntax_len = sizeof(syntax)/ sizeof(*syntax);
5220
5221 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5222 goto exit;
5223 }
5224
5225 rc =__cil_verify_syntax(parse_current, syntax, syntax_len);
5226 if (rc != SEPOL_OK) {
5227 goto exit;
5228 }
5229
5230 cil_macro_init(¯o);
5231
5232 key = parse_current->next->data;
5233
5234 struct cil_tree_node *current_item = parse_current->next->next->cl_head;
5235 while (current_item != NULL) {
5236 enum cil_syntax param_syntax[] = {
5237 CIL_SYN_STRING,
5238 CIL_SYN_STRING,
5239 CIL_SYN_END
5240 };
5241 int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax);
5242 char *kind = NULL;
5243 struct cil_param *param = NULL;
5244
5245 rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len);
5246 if (rc != SEPOL_OK) {
5247 goto exit;
5248 }
5249
5250 if (macro->params == NULL) {
5251 cil_list_init(¯o->params, CIL_LIST_ITEM);
5252 }
5253
5254 kind = current_item->cl_head->data;
5255 cil_param_init(¶m);
5256
5257 if (kind == CIL_KEY_TYPE) {
5258 param->flavor = CIL_TYPE;
5259 } else if (kind == CIL_KEY_ROLE) {
5260 param->flavor = CIL_ROLE;
5261 } else if (kind == CIL_KEY_USER) {
5262 param->flavor = CIL_USER;
5263 } else if (kind == CIL_KEY_SENSITIVITY) {
5264 param->flavor = CIL_SENS;
5265 } else if (kind == CIL_KEY_CATEGORY) {
5266 param->flavor = CIL_CAT;
5267 } else if (kind == CIL_KEY_CATSET) {
5268 param->flavor = CIL_CATSET;
5269 } else if (kind == CIL_KEY_LEVEL) {
5270 param->flavor = CIL_LEVEL;
5271 } else if (kind == CIL_KEY_LEVELRANGE) {
5272 param->flavor = CIL_LEVELRANGE;
5273 } else if (kind == CIL_KEY_CLASS) {
5274 param->flavor = CIL_CLASS;
5275 } else if (kind == CIL_KEY_IPADDR) {
5276 param->flavor = CIL_IPADDR;
5277 } else if (kind == CIL_KEY_MAP_CLASS) {
5278 param->flavor = CIL_MAP_CLASS;
5279 } else if (kind == CIL_KEY_CLASSPERMISSION) {
5280 param->flavor = CIL_CLASSPERMISSION;
5281 } else if (kind == CIL_KEY_BOOL) {
5282 param->flavor = CIL_BOOL;
5283 } else if (kind == CIL_KEY_STRING) {
5284 param->flavor = CIL_NAME;
5285 } else if (kind == CIL_KEY_NAME) {
5286 param->flavor = CIL_NAME;
5287 } else {
5288 cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind);
5289 cil_destroy_param(param);
5290 goto exit;
5291 }
5292
5293 param->str = current_item->cl_head->next->data;
5294
5295 rc = __cil_verify_name(param->str);
5296 if (rc != SEPOL_OK) {
5297 cil_destroy_param(param);
5298 goto exit;
5299 }
5300
5301 //walk current list and check for duplicate parameters
5302 struct cil_list_item *curr_param;
5303 cil_list_for_each(curr_param, macro->params) {
5304 if (param->str == ((struct cil_param*)curr_param->data)->str) {
5305 if (param->flavor == ((struct cil_param*)curr_param->data)->flavor) {
5306 cil_log(CIL_ERR, "Duplicate parameter\n");
5307 cil_destroy_param(param);
5308 goto exit;
5309 }
5310 }
5311 }
5312
5313 cil_list_append(macro->params, CIL_PARAM, param);
5314
5315 current_item = current_item->next;
5316 }
5317
5318 /* 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
5319 node containing the macro name is updated to point to the start of the macro content */
5320 macro_content = parse_current->next->next->next;
5321 cil_tree_subtree_destroy(parse_current->next->next);
5322 parse_current->next->next = macro_content;
5323 if (macro_content == NULL) {
5324 /* No statements in macro and macro parameter list was last node */
5325 parse_current->parent->cl_tail = parse_current->next;
5326 }
5327
5328 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
5329 if (rc != SEPOL_OK) {
5330 goto exit;
5331 }
5332
5333 return SEPOL_OK;
5334
5335 exit:
5336 cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
5337 cil_destroy_macro(macro);
5338 cil_clear_node(ast_node);
5339 return SEPOL_ERR;
5340 }
5341
cil_destroy_macro(struct cil_macro * macro)5342 void cil_destroy_macro(struct cil_macro *macro)
5343 {
5344 if (macro == NULL) {
5345 return;
5346 }
5347
5348 cil_symtab_datum_destroy(¯o->datum);
5349 cil_symtab_array_destroy(macro->symtab);
5350
5351 if (macro->params != NULL) {
5352 cil_list_destroy(¯o->params, 1);
5353 }
5354
5355 free(macro);
5356 }
5357
cil_gen_call(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5358 int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5359 {
5360 enum cil_syntax syntax[] = {
5361 CIL_SYN_STRING,
5362 CIL_SYN_STRING,
5363 CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END,
5364 CIL_SYN_END
5365 };
5366 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5367 struct cil_call *call = NULL;
5368 int rc = SEPOL_ERR;
5369
5370 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5371 goto exit;
5372 }
5373
5374 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5375 if (rc != SEPOL_OK) {
5376 goto exit;
5377 }
5378
5379 cil_call_init(&call);
5380
5381 call->macro_str = parse_current->next->data;
5382
5383 if (parse_current->next->next != NULL) {
5384 cil_tree_init(&call->args_tree);
5385 cil_copy_ast(db, parse_current->next->next, call->args_tree->root);
5386 }
5387
5388 ast_node->data = call;
5389 ast_node->flavor = CIL_CALL;
5390
5391 return SEPOL_OK;
5392
5393 exit:
5394 cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
5395 cil_destroy_call(call);
5396 return rc;
5397 }
5398
cil_destroy_call(struct cil_call * call)5399 void cil_destroy_call(struct cil_call *call)
5400 {
5401 if (call == NULL) {
5402 return;
5403 }
5404
5405 call->macro = NULL;
5406
5407 if (call->args_tree != NULL) {
5408 cil_tree_destroy(&call->args_tree);
5409 }
5410
5411 if (call->args != NULL) {
5412 cil_list_destroy(&call->args, 1);
5413 }
5414
5415 free(call);
5416 }
5417
cil_destroy_args(struct cil_args * args)5418 void cil_destroy_args(struct cil_args *args)
5419 {
5420 if (args == NULL) {
5421 return;
5422 }
5423
5424 if (args->arg_str != NULL) {
5425 args->arg_str = NULL;
5426 } else if (args->arg != NULL) {
5427 struct cil_tree_node *node = args->arg->nodes->head->data;
5428 switch (args->flavor) {
5429 case CIL_NAME:
5430 break;
5431 case CIL_CATSET:
5432 cil_destroy_catset((struct cil_catset *)args->arg);
5433 free(node);
5434 break;
5435 case CIL_LEVEL:
5436 cil_destroy_level((struct cil_level *)args->arg);
5437 free(node);
5438 break;
5439 case CIL_LEVELRANGE:
5440 cil_destroy_levelrange((struct cil_levelrange *)args->arg);
5441 free(node);
5442 break;
5443 case CIL_IPADDR:
5444 cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
5445 free(node);
5446 break;
5447 case CIL_CLASSPERMISSION:
5448 cil_destroy_classpermission((struct cil_classpermission *)args->arg);
5449 free(node);
5450 break;
5451 default:
5452 cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor);
5453 break;
5454 }
5455 }
5456
5457 args->param_str = NULL;
5458 args->arg = NULL;
5459
5460 free(args);
5461 }
5462
cil_gen_optional(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5463 int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5464 {
5465 enum cil_syntax syntax[] = {
5466 CIL_SYN_STRING,
5467 CIL_SYN_STRING,
5468 CIL_SYN_N_LISTS | CIL_SYN_END,
5469 CIL_SYN_END
5470 };
5471 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5472 char *key = NULL;
5473 struct cil_optional *optional = NULL;
5474 int rc = SEPOL_ERR;
5475
5476 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5477 goto exit;
5478 }
5479
5480 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5481 if (rc != SEPOL_OK) {
5482 goto exit;
5483 }
5484
5485 cil_optional_init(&optional);
5486
5487 key = parse_current->next->data;
5488
5489 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
5490 if (rc != SEPOL_OK)
5491 goto exit;
5492
5493 return SEPOL_OK;
5494
5495 exit:
5496 cil_tree_log(parse_current, CIL_ERR, "Bad optional");
5497 cil_destroy_optional(optional);
5498 cil_clear_node(ast_node);
5499 return rc;
5500 }
5501
cil_destroy_optional(struct cil_optional * optional)5502 void cil_destroy_optional(struct cil_optional *optional)
5503 {
5504 if (optional == NULL) {
5505 return;
5506 }
5507
5508 cil_symtab_datum_destroy(&optional->datum);
5509 free(optional);
5510 }
5511
cil_gen_policycap(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5512 int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5513 {
5514 enum cil_syntax syntax[] = {
5515 CIL_SYN_STRING,
5516 CIL_SYN_STRING,
5517 CIL_SYN_END
5518 };
5519 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5520 char *key = NULL;
5521 struct cil_policycap *polcap = NULL;
5522 int rc = SEPOL_ERR;
5523
5524 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5525 goto exit;
5526 }
5527
5528 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5529 if (rc != SEPOL_OK) {
5530 goto exit;
5531 }
5532
5533 cil_policycap_init(&polcap);
5534
5535 key = parse_current->next->data;
5536
5537 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP);
5538 if (rc != SEPOL_OK)
5539 goto exit;
5540
5541 return SEPOL_OK;
5542
5543 exit:
5544 cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
5545 cil_destroy_policycap(polcap);
5546 cil_clear_node(ast_node);
5547 return rc;
5548 }
5549
cil_destroy_policycap(struct cil_policycap * polcap)5550 void cil_destroy_policycap(struct cil_policycap *polcap)
5551 {
5552 if (polcap == NULL) {
5553 return;
5554 }
5555
5556 cil_symtab_datum_destroy(&polcap->datum);
5557 free(polcap);
5558 }
5559
cil_gen_ipaddr(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5560 int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5561 {
5562 enum cil_syntax syntax[] = {
5563 CIL_SYN_STRING,
5564 CIL_SYN_STRING,
5565 CIL_SYN_STRING,
5566 CIL_SYN_END
5567 };
5568 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5569 char *key = NULL;
5570 struct cil_ipaddr *ipaddr = NULL;
5571 int rc = SEPOL_ERR;
5572
5573 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5574 goto exit;
5575 }
5576
5577 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5578 if (rc != SEPOL_OK) {
5579 goto exit;
5580 }
5581
5582 cil_ipaddr_init(&ipaddr);
5583
5584 key = parse_current->next->data;
5585
5586 rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
5587 if (rc != SEPOL_OK) {
5588 goto exit;
5589 }
5590
5591 rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
5592 if (rc != SEPOL_OK) {
5593 goto exit;
5594 }
5595
5596 return SEPOL_OK;
5597
5598 exit:
5599 cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
5600 cil_destroy_ipaddr(ipaddr);
5601 cil_clear_node(ast_node);
5602 return rc;
5603 }
5604
cil_destroy_ipaddr(struct cil_ipaddr * ipaddr)5605 void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
5606 {
5607 if (ipaddr == NULL) {
5608 return;
5609 }
5610
5611 cil_symtab_datum_destroy(&ipaddr->datum);
5612 free(ipaddr);
5613 }
5614
cil_fill_integer(struct cil_tree_node * int_node,uint32_t * integer,int base)5615 int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base)
5616 {
5617 int rc = SEPOL_ERR;
5618 char *endptr = NULL;
5619 int val;
5620
5621 if (int_node == NULL || integer == NULL) {
5622 goto exit;
5623 }
5624
5625 errno = 0;
5626 val = strtol(int_node->data, &endptr, base);
5627 if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
5628 rc = SEPOL_ERR;
5629 goto exit;
5630 }
5631
5632 *integer = val;
5633
5634 return SEPOL_OK;
5635
5636 exit:
5637 cil_log(CIL_ERR, "Failed to create integer from string\n");
5638 return rc;
5639 }
5640
cil_fill_integer64(struct cil_tree_node * int_node,uint64_t * integer,int base)5641 int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base)
5642 {
5643 int rc = SEPOL_ERR;
5644 char *endptr = NULL;
5645 uint64_t val;
5646
5647 if (int_node == NULL || integer == NULL) {
5648 goto exit;
5649 }
5650
5651 errno = 0;
5652 val = strtoull(int_node->data, &endptr, base);
5653 if (errno != 0 || endptr == int_node->data || *endptr != '\0') {
5654 rc = SEPOL_ERR;
5655 goto exit;
5656 }
5657
5658 *integer = val;
5659
5660 return SEPOL_OK;
5661
5662 exit:
5663 cil_log(CIL_ERR, "Failed to create integer from string\n");
5664 return rc;
5665 }
5666
cil_fill_ipaddr(struct cil_tree_node * addr_node,struct cil_ipaddr * addr)5667 int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
5668 {
5669 int rc = SEPOL_ERR;
5670
5671 if (addr_node == NULL || addr == NULL) {
5672 goto exit;
5673 }
5674
5675 if (addr_node->cl_head != NULL || addr_node->next != NULL) {
5676 goto exit;
5677 }
5678
5679 if (strchr(addr_node->data, '.') != NULL) {
5680 addr->family = AF_INET;
5681 } else {
5682 addr->family = AF_INET6;
5683 }
5684
5685 rc = inet_pton(addr->family, addr_node->data, &addr->ip);
5686 if (rc != 1) {
5687 rc = SEPOL_ERR;
5688 goto exit;
5689 }
5690
5691 return SEPOL_OK;
5692
5693 exit:
5694 cil_log(CIL_ERR, "Bad ip address or netmask\n");
5695 return rc;
5696 }
5697
cil_fill_level(struct cil_tree_node * curr,struct cil_level * level)5698 int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
5699 {
5700 int rc = SEPOL_ERR;
5701 enum cil_syntax syntax[] = {
5702 CIL_SYN_STRING,
5703 CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END,
5704 CIL_SYN_END
5705 };
5706 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5707
5708 if (curr == NULL) {
5709 goto exit;
5710 }
5711
5712 rc = __cil_verify_syntax(curr, syntax, syntax_len);
5713 if (rc != SEPOL_OK) {
5714 goto exit;
5715 }
5716
5717 level->sens_str = curr->data;
5718 if (curr->next != NULL) {
5719 rc = cil_fill_cats(curr->next, &level->cats);
5720 if (rc != SEPOL_OK) {
5721 goto exit;
5722 }
5723 }
5724
5725 return SEPOL_OK;
5726
5727 exit:
5728 cil_log(CIL_ERR, "Bad level\n");
5729 return rc;
5730 }
5731
cil_fill_cats(struct cil_tree_node * curr,struct cil_cats ** cats)5732 int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
5733 {
5734 int rc = SEPOL_ERR;
5735
5736 cil_cats_init(cats);
5737
5738 rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
5739 if (rc != SEPOL_OK) {
5740 cil_destroy_cats(*cats);
5741 *cats = NULL;
5742 }
5743
5744 return rc;
5745 }
5746
cil_destroy_cats(struct cil_cats * cats)5747 void cil_destroy_cats(struct cil_cats *cats)
5748 {
5749 if (cats == NULL) {
5750 return;
5751 }
5752
5753 cil_list_destroy(&cats->str_expr, CIL_TRUE);
5754
5755 cil_list_destroy(&cats->datum_expr, CIL_FALSE);
5756
5757 free(cats);
5758 }
cil_gen_bounds(struct cil_db * db,struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5759 int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5760 {
5761 enum cil_syntax syntax[] = {
5762 CIL_SYN_STRING,
5763 CIL_SYN_STRING,
5764 CIL_SYN_STRING,
5765 CIL_SYN_END
5766 };
5767 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5768 struct cil_bounds *bounds = NULL;
5769 int rc = SEPOL_ERR;
5770
5771 if (db == NULL || parse_current == NULL || ast_node == NULL) {
5772 goto exit;
5773 }
5774
5775 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5776 if (rc != SEPOL_OK) {
5777 goto exit;
5778 }
5779
5780 cil_bounds_init(&bounds);
5781
5782 bounds->parent_str = parse_current->next->data;
5783 bounds->child_str = parse_current->next->next->data;
5784
5785 ast_node->data = bounds;
5786
5787 switch (flavor) {
5788 case CIL_USER:
5789 ast_node->flavor = CIL_USERBOUNDS;
5790 break;
5791 case CIL_ROLE:
5792 ast_node->flavor = CIL_ROLEBOUNDS;
5793 break;
5794 case CIL_TYPE:
5795 ast_node->flavor = CIL_TYPEBOUNDS;
5796 break;
5797 default:
5798 break;
5799 }
5800
5801 return SEPOL_OK;
5802
5803 exit:
5804 cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
5805 cil_destroy_bounds(bounds);
5806 return rc;
5807 }
5808
cil_destroy_bounds(struct cil_bounds * bounds)5809 void cil_destroy_bounds(struct cil_bounds *bounds)
5810 {
5811 if (bounds == NULL) {
5812 return;
5813 }
5814
5815 free(bounds);
5816 }
5817
cil_gen_default(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node,enum cil_flavor flavor)5818 int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor)
5819 {
5820 int rc = SEPOL_ERR;
5821 struct cil_default *def = NULL;
5822 char *object;
5823 enum cil_syntax syntax[] = {
5824 CIL_SYN_STRING,
5825 CIL_SYN_STRING | CIL_SYN_LIST,
5826 CIL_SYN_STRING,
5827 CIL_SYN_END
5828 };
5829 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5830
5831 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5832 if (rc != SEPOL_OK) {
5833 goto exit;
5834 }
5835
5836 cil_default_init(&def);
5837
5838 def->flavor = flavor;
5839
5840 if (parse_current->next->cl_head == NULL) {
5841 cil_list_init(&def->class_strs, CIL_CLASS);
5842 cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5843 } else {
5844 rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5845 if (rc != SEPOL_OK) {
5846 goto exit;
5847 }
5848 }
5849
5850 object = parse_current->next->next->data;
5851 if (object == CIL_KEY_SOURCE) {
5852 def->object = CIL_DEFAULT_SOURCE;
5853 } else if (object == CIL_KEY_TARGET) {
5854 def->object = CIL_DEFAULT_TARGET;
5855 } else {
5856 cil_log(CIL_ERR,"Expected either 'source' or 'target'\n");
5857 rc = SEPOL_ERR;
5858 goto exit;
5859 }
5860
5861 ast_node->data = def;
5862 ast_node->flavor = flavor;
5863
5864 return SEPOL_OK;
5865
5866 exit:
5867 cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current));
5868 cil_destroy_default(def);
5869 return rc;
5870 }
5871
cil_destroy_default(struct cil_default * def)5872 void cil_destroy_default(struct cil_default *def)
5873 {
5874 if (def == NULL) {
5875 return;
5876 }
5877
5878 cil_list_destroy(&def->class_strs, CIL_TRUE);
5879
5880 cil_list_destroy(&def->class_datums, CIL_FALSE);
5881
5882 free(def);
5883 }
5884
cil_gen_defaultrange(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5885 int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5886 {
5887 int rc = SEPOL_ERR;
5888 struct cil_defaultrange *def = NULL;
5889 char *object;
5890 char *range;
5891 enum cil_syntax syntax[] = {
5892 CIL_SYN_STRING,
5893 CIL_SYN_STRING | CIL_SYN_LIST,
5894 CIL_SYN_STRING,
5895 CIL_SYN_STRING,
5896 CIL_SYN_END
5897 };
5898 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5899
5900 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5901 if (rc != SEPOL_OK) {
5902 goto exit;
5903 }
5904
5905 cil_defaultrange_init(&def);
5906
5907 if (parse_current->next->cl_head == NULL) {
5908 cil_list_init(&def->class_strs, CIL_CLASS);
5909 cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data);
5910 } else {
5911 rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs);
5912 if (rc != SEPOL_OK) {
5913 goto exit;
5914 }
5915 }
5916
5917 object = parse_current->next->next->data;
5918 range = parse_current->next->next->next->data;
5919 if (object == CIL_KEY_SOURCE) {
5920 if (range == CIL_KEY_LOW) {
5921 def->object_range = CIL_DEFAULT_SOURCE_LOW;
5922 } else if (range == CIL_KEY_HIGH) {
5923 def->object_range = CIL_DEFAULT_SOURCE_HIGH;
5924 } else if (range == CIL_KEY_LOW_HIGH) {
5925 def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
5926 } else {
5927 cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5928 rc = SEPOL_ERR;
5929 goto exit;
5930 }
5931 } else if (parse_current->next->next->data == CIL_KEY_TARGET) {
5932 if (range == CIL_KEY_LOW) {
5933 def->object_range = CIL_DEFAULT_TARGET_LOW;
5934 } else if (range == CIL_KEY_HIGH) {
5935 def->object_range = CIL_DEFAULT_TARGET_HIGH;
5936 } else if (range == CIL_KEY_LOW_HIGH) {
5937 def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
5938 } else {
5939 cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n");
5940 rc = SEPOL_ERR;
5941 goto exit;
5942 }
5943 } else {
5944 cil_log(CIL_ERR,"Expected either \'source\' or \'target\'\n");
5945 rc = SEPOL_ERR;
5946 goto exit;
5947 }
5948
5949 ast_node->data = def;
5950 ast_node->flavor = CIL_DEFAULTRANGE;
5951
5952 return SEPOL_OK;
5953
5954 exit:
5955 cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
5956 cil_destroy_defaultrange(def);
5957 return rc;
5958 }
5959
cil_destroy_defaultrange(struct cil_defaultrange * def)5960 void cil_destroy_defaultrange(struct cil_defaultrange *def)
5961 {
5962 if (def == NULL) {
5963 return;
5964 }
5965
5966 cil_list_destroy(&def->class_strs, CIL_TRUE);
5967
5968 cil_list_destroy(&def->class_datums, CIL_FALSE);
5969
5970 free(def);
5971 }
5972
cil_gen_handleunknown(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)5973 int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
5974 {
5975 int rc = SEPOL_ERR;
5976 enum cil_syntax syntax[] = {
5977 CIL_SYN_STRING,
5978 CIL_SYN_STRING,
5979 CIL_SYN_END
5980 };
5981 int syntax_len = sizeof(syntax)/sizeof(*syntax);
5982 struct cil_handleunknown *unknown = NULL;
5983 char *unknown_key;
5984
5985 if (parse_current == NULL || ast_node == NULL) {
5986 goto exit;
5987 }
5988
5989 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5990 if (rc != SEPOL_OK) {
5991 goto exit;
5992 }
5993
5994 cil_handleunknown_init(&unknown);
5995
5996 unknown_key = parse_current->next->data;
5997 if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
5998 unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
5999 } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
6000 unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
6001 } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
6002 unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
6003 } else {
6004 cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT);
6005 rc = SEPOL_ERR;
6006 goto exit;
6007 }
6008
6009 ast_node->data = unknown;
6010 ast_node->flavor = CIL_HANDLEUNKNOWN;
6011
6012 return SEPOL_OK;
6013
6014 exit:
6015 cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
6016 cil_destroy_handleunknown(unknown);
6017 return rc;
6018 }
6019
cil_destroy_handleunknown(struct cil_handleunknown * unk)6020 void cil_destroy_handleunknown(struct cil_handleunknown *unk)
6021 {
6022 free(unk);
6023 }
6024
cil_gen_mls(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6025 int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6026 {
6027 int rc = SEPOL_ERR;
6028 enum cil_syntax syntax[] = {
6029 CIL_SYN_STRING,
6030 CIL_SYN_STRING,
6031 CIL_SYN_END
6032 };
6033 int syntax_len = sizeof(syntax)/sizeof(*syntax);
6034 struct cil_mls *mls = NULL;
6035
6036 if (parse_current == NULL || ast_node == NULL) {
6037 goto exit;
6038 }
6039
6040 rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6041 if (rc != SEPOL_OK) {
6042 goto exit;
6043 }
6044
6045 cil_mls_init(&mls);
6046
6047 if (parse_current->next->data == CIL_KEY_CONDTRUE) {
6048 mls->value = CIL_TRUE;
6049 } else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
6050 mls->value = CIL_FALSE;
6051 } else {
6052 cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
6053 rc = SEPOL_ERR;
6054 goto exit;
6055 }
6056
6057 ast_node->data = mls;
6058 ast_node->flavor = CIL_MLS;
6059
6060 return SEPOL_OK;
6061
6062 exit:
6063 cil_tree_log(parse_current, CIL_ERR, "Bad mls");
6064 cil_destroy_mls(mls);
6065 return rc;
6066 }
6067
cil_destroy_mls(struct cil_mls * mls)6068 void cil_destroy_mls(struct cil_mls *mls)
6069 {
6070 free(mls);
6071 }
6072
cil_gen_src_info(struct cil_tree_node * parse_current,struct cil_tree_node * ast_node)6073 int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node)
6074 {
6075 /* No need to check syntax, because this is auto generated */
6076 struct cil_src_info *info = NULL;
6077
6078 cil_src_info_init(&info);
6079
6080 info->is_cil = (parse_current->next->data == CIL_KEY_SRC_CIL) ? CIL_TRUE : CIL_FALSE;
6081 info->path = parse_current->next->next->data;
6082
6083 ast_node->data = info;
6084 ast_node->flavor = CIL_SRC_INFO;
6085
6086 return SEPOL_OK;
6087 }
6088
cil_destroy_src_info(struct cil_src_info * info)6089 void cil_destroy_src_info(struct cil_src_info *info)
6090 {
6091 free(info);
6092 }
6093
__cil_build_ast_node_helper(struct cil_tree_node * parse_current,uint32_t * finished,void * extra_args)6094 int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args)
6095 {
6096 struct cil_args_build *args = NULL;
6097 struct cil_tree_node *ast_current = NULL;
6098 struct cil_db *db = NULL;
6099 struct cil_tree_node *ast_node = NULL;
6100 struct cil_tree_node *macro = NULL;
6101 struct cil_tree_node *boolif = NULL;
6102 struct cil_tree_node *tunif = NULL;
6103 struct cil_tree_node *in = NULL;
6104 int rc = SEPOL_ERR;
6105
6106 if (parse_current == NULL || finished == NULL || extra_args == NULL) {
6107 goto exit;
6108 }
6109
6110 args = extra_args;
6111 ast_current = args->ast;
6112 db = args->db;
6113 macro = args->macro;
6114 boolif = args->boolif;
6115 tunif = args->tunif;
6116 in = args->in;
6117
6118 if (parse_current->parent->cl_head != parse_current) {
6119 /* ignore anything that isn't following a parenthesis */
6120 rc = SEPOL_OK;
6121 goto exit;
6122 } else if (parse_current->data == NULL) {
6123 /* the only time parenthsis can immediately following parenthesis is if
6124 * the parent is the root node */
6125 if (parse_current->parent->parent == NULL) {
6126 rc = SEPOL_OK;
6127 } else {
6128 cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis");
6129 }
6130 goto exit;
6131 }
6132
6133 if (macro != NULL) {
6134 if (parse_current->data == CIL_KEY_MACRO ||
6135 parse_current->data == CIL_KEY_TUNABLE ||
6136 parse_current->data == CIL_KEY_IN ||
6137 parse_current->data == CIL_KEY_BLOCK ||
6138 parse_current->data == CIL_KEY_BLOCKINHERIT ||
6139 parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6140 rc = SEPOL_ERR;
6141 cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macros", (char *)parse_current->data);
6142 goto exit;
6143 }
6144 }
6145
6146 if (boolif != NULL) {
6147 if (parse_current->data != CIL_KEY_CONDTRUE &&
6148 parse_current->data != CIL_KEY_CONDFALSE &&
6149 parse_current->data != CIL_KEY_AUDITALLOW &&
6150 parse_current->data != CIL_KEY_TUNABLEIF &&
6151 parse_current->data != CIL_KEY_ALLOW &&
6152 parse_current->data != CIL_KEY_DONTAUDIT &&
6153 parse_current->data != CIL_KEY_TYPETRANSITION &&
6154 parse_current->data != CIL_KEY_TYPECHANGE &&
6155 parse_current->data != CIL_KEY_CALL) {
6156 rc = SEPOL_ERR;
6157 cil_tree_log(parse_current, CIL_ERR, "Found %s", (char*)parse_current->data);
6158 if (((struct cil_booleanif*)boolif->data)->preserved_tunable) {
6159 cil_log(CIL_ERR, "%s cannot be defined within tunableif statement (treated as a booleanif due to preserve-tunables)\n",
6160 (char*)parse_current->data);
6161 } else {
6162 cil_log(CIL_ERR, "%s cannot be defined within booleanif statement\n",
6163 (char*)parse_current->data);
6164 }
6165 goto exit;
6166 }
6167 }
6168
6169 if (tunif != NULL) {
6170 if (parse_current->data == CIL_KEY_TUNABLE) {
6171 rc = SEPOL_ERR;
6172 cil_tree_log(parse_current, CIL_ERR, "Found tunable");
6173 cil_log(CIL_ERR, "Tunables cannot be defined within tunableif statement\n");
6174 goto exit;
6175 }
6176 }
6177
6178 if (in != NULL) {
6179 if (parse_current->data == CIL_KEY_IN) {
6180 rc = SEPOL_ERR;
6181 cil_tree_log(parse_current, CIL_ERR, "Found in-statement");
6182 cil_log(CIL_ERR, "in-statements cannot be defined within in-statements\n");
6183 goto exit;
6184 }
6185 }
6186
6187 cil_tree_node_init(&ast_node);
6188
6189 ast_node->parent = ast_current;
6190 ast_node->line = parse_current->line;
6191 ast_node->hll_line = parse_current->hll_line;
6192
6193 if (parse_current->data == CIL_KEY_BLOCK) {
6194 rc = cil_gen_block(db, parse_current, ast_node, 0);
6195 } else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
6196 rc = cil_gen_blockinherit(db, parse_current, ast_node);
6197 } else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6198 rc = cil_gen_blockabstract(db, parse_current, ast_node);
6199 } else if (parse_current->data == CIL_KEY_IN) {
6200 rc = cil_gen_in(db, parse_current, ast_node);
6201 } else if (parse_current->data == CIL_KEY_CLASS) {
6202 rc = cil_gen_class(db, parse_current, ast_node);
6203 // To avoid parsing list of perms again
6204 *finished = CIL_TREE_SKIP_NEXT;
6205 } else if (parse_current->data == CIL_KEY_CLASSORDER) {
6206 rc = cil_gen_classorder(db, parse_current, ast_node);
6207 *finished = CIL_TREE_SKIP_NEXT;
6208 } else if (parse_current->data == CIL_KEY_MAP_CLASS) {
6209 rc = cil_gen_map_class(db, parse_current, ast_node);
6210 *finished = CIL_TREE_SKIP_NEXT;
6211 } else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
6212 rc = cil_gen_classmapping(db, parse_current, ast_node);
6213 *finished = CIL_TREE_SKIP_NEXT;
6214 } else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
6215 rc = cil_gen_classpermission(db, parse_current, ast_node);
6216 *finished = CIL_TREE_SKIP_NEXT;
6217 } else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
6218 rc = cil_gen_classpermissionset(db, parse_current, ast_node);
6219 *finished = CIL_TREE_SKIP_NEXT;
6220 } else if (parse_current->data == CIL_KEY_COMMON) {
6221 rc = cil_gen_common(db, parse_current, ast_node);
6222 *finished = CIL_TREE_SKIP_NEXT;
6223 } else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
6224 rc = cil_gen_classcommon(db, parse_current, ast_node);
6225 } else if (parse_current->data == CIL_KEY_SID) {
6226 rc = cil_gen_sid(db, parse_current, ast_node);
6227 *finished = CIL_TREE_SKIP_NEXT;
6228 } else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
6229 rc = cil_gen_sidcontext(db, parse_current, ast_node);
6230 *finished = CIL_TREE_SKIP_NEXT;
6231 } else if (parse_current->data == CIL_KEY_SIDORDER) {
6232 rc = cil_gen_sidorder(db, parse_current, ast_node);
6233 *finished = CIL_TREE_SKIP_NEXT;
6234 } else if (parse_current->data == CIL_KEY_USER) {
6235 rc = cil_gen_user(db, parse_current, ast_node);
6236 } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
6237 rc = cil_gen_userattribute(db, parse_current, ast_node);
6238 } else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
6239 rc = cil_gen_userattributeset(db, parse_current, ast_node);
6240 *finished = CIL_TREE_SKIP_NEXT;
6241 } else if (parse_current->data == CIL_KEY_USERLEVEL) {
6242 rc = cil_gen_userlevel(db, parse_current, ast_node);
6243 *finished = CIL_TREE_SKIP_NEXT;
6244 } else if (parse_current->data == CIL_KEY_USERRANGE) {
6245 rc = cil_gen_userrange(db, parse_current, ast_node);
6246 *finished = CIL_TREE_SKIP_NEXT;
6247 } else if (parse_current->data == CIL_KEY_USERBOUNDS) {
6248 rc = cil_gen_bounds(db, parse_current, ast_node, CIL_USER);
6249 } else if (parse_current->data == CIL_KEY_USERPREFIX) {
6250 rc = cil_gen_userprefix(db, parse_current, ast_node);
6251 } else if (parse_current->data == CIL_KEY_SELINUXUSER) {
6252 rc = cil_gen_selinuxuser(db, parse_current, ast_node);
6253 *finished = CIL_TREE_SKIP_NEXT;
6254 } else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
6255 rc = cil_gen_selinuxuserdefault(db, parse_current, ast_node);
6256 *finished = CIL_TREE_SKIP_NEXT;
6257 } else if (parse_current->data == CIL_KEY_TYPE) {
6258 rc = cil_gen_type(db, parse_current, ast_node);
6259 } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
6260 rc = cil_gen_typeattribute(db, parse_current, ast_node);
6261 } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
6262 rc = cil_gen_typeattributeset(db, parse_current, ast_node);
6263 *finished = CIL_TREE_SKIP_NEXT;
6264 } else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
6265 rc = cil_gen_expandtypeattribute(db, parse_current, ast_node);
6266 *finished = CIL_TREE_SKIP_NEXT;
6267 } else if (parse_current->data == CIL_KEY_TYPEALIAS) {
6268 rc = cil_gen_alias(db, parse_current, ast_node, CIL_TYPEALIAS);
6269 } else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
6270 rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_TYPEALIASACTUAL);
6271 } else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
6272 rc = cil_gen_bounds(db, parse_current, ast_node, CIL_TYPE);
6273 } else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
6274 rc = cil_gen_typepermissive(db, parse_current, ast_node);
6275 } else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
6276 rc = cil_gen_rangetransition(db, parse_current, ast_node);
6277 *finished = CIL_TREE_SKIP_NEXT;
6278 } else if (parse_current->data == CIL_KEY_ROLE) {
6279 rc = cil_gen_role(db, parse_current, ast_node);
6280 } else if (parse_current->data == CIL_KEY_USERROLE) {
6281 rc = cil_gen_userrole(db, parse_current, ast_node);
6282 } else if (parse_current->data == CIL_KEY_ROLETYPE) {
6283 rc = cil_gen_roletype(db, parse_current, ast_node);
6284 } else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
6285 rc = cil_gen_roletransition(parse_current, ast_node);
6286 } else if (parse_current->data == CIL_KEY_ROLEALLOW) {
6287 rc = cil_gen_roleallow(db, parse_current, ast_node);
6288 } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
6289 rc = cil_gen_roleattribute(db, parse_current, ast_node);
6290 } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
6291 rc = cil_gen_roleattributeset(db, parse_current, ast_node);
6292 *finished = CIL_TREE_SKIP_NEXT;
6293 } else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
6294 rc = cil_gen_bounds(db, parse_current, ast_node, CIL_ROLE);
6295 } else if (parse_current->data == CIL_KEY_BOOL) {
6296 rc = cil_gen_bool(db, parse_current, ast_node, CIL_FALSE);
6297 } else if (parse_current->data == CIL_KEY_BOOLEANIF) {
6298 rc = cil_gen_boolif(db, parse_current, ast_node, CIL_FALSE);
6299 } else if(parse_current->data == CIL_KEY_TUNABLE) {
6300 if (db->preserve_tunables) {
6301 rc = cil_gen_bool(db, parse_current, ast_node, CIL_TRUE);
6302 } else {
6303 rc = cil_gen_tunable(db, parse_current, ast_node);
6304 }
6305 } else if (parse_current->data == CIL_KEY_TUNABLEIF) {
6306 if (db->preserve_tunables) {
6307 rc = cil_gen_boolif(db, parse_current, ast_node, CIL_TRUE);
6308 } else {
6309 rc = cil_gen_tunif(db, parse_current, ast_node);
6310 }
6311 } else if (parse_current->data == CIL_KEY_CONDTRUE) {
6312 rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDTRUE);
6313 } else if (parse_current->data == CIL_KEY_CONDFALSE) {
6314 rc = cil_gen_condblock(db, parse_current, ast_node, CIL_CONDFALSE);
6315 } else if (parse_current->data == CIL_KEY_ALLOW) {
6316 rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_ALLOWED);
6317 // So that the object and perms lists do not get parsed again
6318 *finished = CIL_TREE_SKIP_NEXT;
6319 } else if (parse_current->data == CIL_KEY_AUDITALLOW) {
6320 rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
6321 *finished = CIL_TREE_SKIP_NEXT;
6322 } else if (parse_current->data == CIL_KEY_DONTAUDIT) {
6323 rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
6324 *finished = CIL_TREE_SKIP_NEXT;
6325 } else if (parse_current->data == CIL_KEY_NEVERALLOW) {
6326 rc = cil_gen_avrule(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
6327 *finished = CIL_TREE_SKIP_NEXT;
6328 } else if (parse_current->data == CIL_KEY_ALLOWX) {
6329 rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_ALLOWED);
6330 *finished = CIL_TREE_SKIP_NEXT;
6331 } else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
6332 rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_AUDITALLOW);
6333 *finished = CIL_TREE_SKIP_NEXT;
6334 } else if (parse_current->data == CIL_KEY_DONTAUDITX) {
6335 rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_DONTAUDIT);
6336 *finished = CIL_TREE_SKIP_NEXT;
6337 } else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
6338 rc = cil_gen_avrulex(parse_current, ast_node, CIL_AVRULE_NEVERALLOW);
6339 *finished = CIL_TREE_SKIP_NEXT;
6340 } else if (parse_current->data == CIL_KEY_PERMISSIONX) {
6341 rc = cil_gen_permissionx(db, parse_current, ast_node);
6342 *finished = CIL_TREE_SKIP_NEXT;
6343 } else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
6344 rc = cil_gen_typetransition(db, parse_current, ast_node);
6345 } else if (parse_current->data == CIL_KEY_TYPECHANGE) {
6346 rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_CHANGE);
6347 } else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
6348 rc = cil_gen_type_rule(parse_current, ast_node, CIL_TYPE_MEMBER);
6349 } else if (parse_current->data == CIL_KEY_SENSITIVITY) {
6350 rc = cil_gen_sensitivity(db, parse_current, ast_node);
6351 } else if (parse_current->data == CIL_KEY_SENSALIAS) {
6352 rc = cil_gen_alias(db, parse_current, ast_node, CIL_SENSALIAS);
6353 } else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
6354 rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_SENSALIASACTUAL);
6355 } else if (parse_current->data == CIL_KEY_CATEGORY) {
6356 rc = cil_gen_category(db, parse_current, ast_node);
6357 } else if (parse_current->data == CIL_KEY_CATALIAS) {
6358 rc = cil_gen_alias(db, parse_current, ast_node, CIL_CATALIAS);
6359 } else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
6360 rc = cil_gen_aliasactual(db, parse_current, ast_node, CIL_CATALIASACTUAL);
6361 } else if (parse_current->data == CIL_KEY_CATSET) {
6362 rc = cil_gen_catset(db, parse_current, ast_node);
6363 *finished = CIL_TREE_SKIP_NEXT;
6364 } else if (parse_current->data == CIL_KEY_CATORDER) {
6365 rc = cil_gen_catorder(db, parse_current, ast_node);
6366 *finished = CIL_TREE_SKIP_NEXT;
6367 } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
6368 rc = cil_gen_sensitivityorder(db, parse_current, ast_node);
6369 *finished = CIL_TREE_SKIP_NEXT;
6370 } else if (parse_current->data == CIL_KEY_SENSCAT) {
6371 rc = cil_gen_senscat(db, parse_current, ast_node);
6372 *finished = CIL_TREE_SKIP_NEXT;
6373 } else if (parse_current->data == CIL_KEY_LEVEL) {
6374 rc = cil_gen_level(db, parse_current, ast_node);
6375 *finished = CIL_TREE_SKIP_NEXT;
6376 } else if (parse_current->data == CIL_KEY_LEVELRANGE) {
6377 rc = cil_gen_levelrange(db, parse_current, ast_node);
6378 *finished = CIL_TREE_SKIP_NEXT;
6379 } else if (parse_current->data == CIL_KEY_CONSTRAIN) {
6380 rc = cil_gen_constrain(db, parse_current, ast_node, CIL_CONSTRAIN);
6381 *finished = CIL_TREE_SKIP_NEXT;
6382 } else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
6383 rc = cil_gen_constrain(db, parse_current, ast_node, CIL_MLSCONSTRAIN);
6384 *finished = CIL_TREE_SKIP_NEXT;
6385 } else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
6386 rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_VALIDATETRANS);
6387 *finished = CIL_TREE_SKIP_NEXT;
6388 } else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
6389 rc = cil_gen_validatetrans(db, parse_current, ast_node, CIL_MLSVALIDATETRANS);
6390 *finished = CIL_TREE_SKIP_NEXT;
6391 } else if (parse_current->data == CIL_KEY_CONTEXT) {
6392 rc = cil_gen_context(db, parse_current, ast_node);
6393 *finished = CIL_TREE_SKIP_NEXT;
6394 } else if (parse_current->data == CIL_KEY_FILECON) {
6395 rc = cil_gen_filecon(db, parse_current, ast_node);
6396 *finished = CIL_TREE_SKIP_NEXT;
6397 } else if (parse_current->data == CIL_KEY_IBPKEYCON) {
6398 rc = cil_gen_ibpkeycon(db, parse_current, ast_node);
6399 *finished = CIL_TREE_SKIP_NEXT;
6400 } else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
6401 rc = cil_gen_ibendportcon(db, parse_current, ast_node);
6402 *finished = CIL_TREE_SKIP_NEXT;
6403 } else if (parse_current->data == CIL_KEY_PORTCON) {
6404 rc = cil_gen_portcon(db, parse_current, ast_node);
6405 *finished = CIL_TREE_SKIP_NEXT;
6406 } else if (parse_current->data == CIL_KEY_NODECON) {
6407 rc = cil_gen_nodecon(db, parse_current, ast_node);
6408 *finished = CIL_TREE_SKIP_NEXT;
6409 } else if (parse_current->data == CIL_KEY_GENFSCON) {
6410 rc = cil_gen_genfscon(db, parse_current, ast_node);
6411 *finished = CIL_TREE_SKIP_NEXT;
6412 } else if (parse_current->data == CIL_KEY_NETIFCON) {
6413 rc = cil_gen_netifcon(db, parse_current, ast_node);
6414 *finished = CIL_TREE_SKIP_NEXT;
6415 } else if (parse_current->data == CIL_KEY_PIRQCON) {
6416 rc = cil_gen_pirqcon(db, parse_current, ast_node);
6417 *finished = CIL_TREE_SKIP_NEXT;
6418 } else if (parse_current->data == CIL_KEY_IOMEMCON) {
6419 rc = cil_gen_iomemcon(db, parse_current, ast_node);
6420 *finished = CIL_TREE_SKIP_NEXT;
6421 } else if (parse_current->data == CIL_KEY_IOPORTCON) {
6422 rc = cil_gen_ioportcon(db, parse_current, ast_node);
6423 *finished = CIL_TREE_SKIP_NEXT;
6424 } else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
6425 rc = cil_gen_pcidevicecon(db, parse_current, ast_node);
6426 *finished = CIL_TREE_SKIP_NEXT;
6427 } else if (parse_current->data == CIL_KEY_DEVICETREECON) {
6428 rc = cil_gen_devicetreecon(db, parse_current, ast_node);
6429 *finished = CIL_TREE_SKIP_NEXT;
6430 } else if (parse_current->data == CIL_KEY_FSUSE) {
6431 rc = cil_gen_fsuse(db, parse_current, ast_node);
6432 *finished = CIL_TREE_SKIP_NEXT;
6433 } else if (parse_current->data == CIL_KEY_MACRO) {
6434 rc = cil_gen_macro(db, parse_current, ast_node);
6435 } else if (parse_current->data == CIL_KEY_CALL) {
6436 rc = cil_gen_call(db, parse_current, ast_node);
6437 *finished = 1;
6438 } else if (parse_current->data == CIL_KEY_POLICYCAP) {
6439 rc = cil_gen_policycap(db, parse_current, ast_node);
6440 *finished = 1;
6441 } else if (parse_current->data == CIL_KEY_OPTIONAL) {
6442 rc = cil_gen_optional(db, parse_current, ast_node);
6443 } else if (parse_current->data == CIL_KEY_IPADDR) {
6444 rc = cil_gen_ipaddr(db, parse_current, ast_node);
6445 } else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
6446 rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTUSER);
6447 *finished = CIL_TREE_SKIP_NEXT;
6448 } else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
6449 rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTROLE);
6450 *finished = CIL_TREE_SKIP_NEXT;
6451 } else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
6452 rc = cil_gen_default(parse_current, ast_node, CIL_DEFAULTTYPE);
6453 *finished = CIL_TREE_SKIP_NEXT;
6454 } else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
6455 rc = cil_gen_defaultrange(parse_current, ast_node);
6456 *finished = CIL_TREE_SKIP_NEXT;
6457 } else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
6458 rc = cil_gen_handleunknown(parse_current, ast_node);
6459 *finished = CIL_TREE_SKIP_NEXT;
6460 } else if (parse_current->data == CIL_KEY_MLS) {
6461 rc = cil_gen_mls(parse_current, ast_node);
6462 *finished = CIL_TREE_SKIP_NEXT;
6463 } else if (parse_current->data == CIL_KEY_SRC_INFO) {
6464 rc = cil_gen_src_info(parse_current, ast_node);
6465 } else {
6466 cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data);
6467 rc = SEPOL_ERR;
6468 }
6469
6470 if (rc == SEPOL_OK) {
6471 if (ast_current->cl_head == NULL) {
6472 if (ast_current->flavor == CIL_MACRO) {
6473 args->macro = ast_current;
6474 }
6475
6476 if (ast_current->flavor == CIL_BOOLEANIF) {
6477 args->boolif = ast_current;
6478 }
6479
6480 if (ast_current->flavor == CIL_TUNABLEIF) {
6481 args->tunif = ast_current;
6482 }
6483
6484 if (ast_current->flavor == CIL_IN) {
6485 args->in = ast_current;
6486 }
6487
6488 ast_current->cl_head = ast_node;
6489 } else {
6490 ast_current->cl_tail->next = ast_node;
6491 }
6492 ast_current->cl_tail = ast_node;
6493 ast_current = ast_node;
6494 args->ast = ast_current;
6495 } else {
6496 cil_tree_node_destroy(&ast_node);
6497 }
6498
6499 exit:
6500 return rc;
6501 }
6502
__cil_build_ast_last_child_helper(struct cil_tree_node * parse_current,void * extra_args)6503 int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args)
6504 {
6505 int rc = SEPOL_ERR;
6506 struct cil_tree_node *ast = NULL;
6507 struct cil_args_build *args = NULL;
6508
6509 if (extra_args == NULL) {
6510 goto exit;
6511 }
6512
6513 args = extra_args;
6514 ast = args->ast;
6515
6516 if (ast->flavor == CIL_ROOT) {
6517 rc = SEPOL_OK;
6518 goto exit;
6519 }
6520
6521 args->ast = ast->parent;
6522
6523 if (ast->flavor == CIL_MACRO) {
6524 args->macro = NULL;
6525 }
6526
6527 if (ast->flavor == CIL_BOOLEANIF) {
6528 args->boolif = NULL;
6529 }
6530
6531 if (ast->flavor == CIL_TUNABLEIF) {
6532 args->tunif = NULL;
6533 }
6534
6535 if (ast->flavor == CIL_IN) {
6536 args->in = NULL;
6537 }
6538
6539 // At this point we no longer have any need for parse_current or any of its
6540 // siblings; they have all been converted to the appropriate AST node. The
6541 // full parse tree will get deleted elsewhere, but in an attempt to
6542 // minimize memory useage (of which the parse tree uses alot), start
6543 // deleting the parts we don't need now.
6544 cil_tree_children_destroy(parse_current->parent);
6545
6546 return SEPOL_OK;
6547
6548 exit:
6549 return rc;
6550 }
6551
cil_build_ast(struct cil_db * db,struct cil_tree_node * parse_tree,struct cil_tree_node * ast)6552 int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast)
6553 {
6554 int rc = SEPOL_ERR;
6555 struct cil_args_build extra_args;
6556
6557 if (db == NULL || parse_tree == NULL || ast == NULL) {
6558 goto exit;
6559 }
6560
6561 extra_args.ast = ast;
6562 extra_args.db = db;
6563 extra_args.macro = NULL;
6564 extra_args.boolif = NULL;
6565 extra_args.tunif = NULL;
6566 extra_args.in = NULL;
6567
6568 rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, NULL, __cil_build_ast_last_child_helper, &extra_args);
6569 if (rc != SEPOL_OK) {
6570 goto exit;
6571 }
6572
6573 return SEPOL_OK;
6574
6575 exit:
6576 return rc;
6577 }
6578