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