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