| /* |
| * Copyright 2011 Tresys Technology, LLC. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright notice, |
| * this list of conditions and the following disclaimer. |
| * |
| * 2. Redistributions in binary form must reproduce the above copyright notice, |
| * this list of conditions and the following disclaimer in the documentation |
| * and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS |
| * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF |
| * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO |
| * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE |
| * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF |
| * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| * |
| * The views and conclusions contained in the software and documentation are those |
| * of the authors and should not be interpreted as representing official policies, |
| * either expressed or implied, of Tresys Technology, LLC. |
| */ |
| |
| #include <stdlib.h> |
| #include <stdio.h> |
| #include <string.h> |
| #include <ctype.h> |
| |
| #include <sepol/policydb/conditional.h> |
| |
| #include "cil_internal.h" |
| #include "cil_flavor.h" |
| #include "cil_log.h" |
| #include "cil_mem.h" |
| #include "cil_tree.h" |
| #include "cil_list.h" |
| #include "cil_parser.h" |
| #include "cil_build_ast.h" |
| #include "cil_copy_ast.h" |
| #include "cil_verify.h" |
| #include "cil_strpool.h" |
| |
| struct cil_args_build { |
| struct cil_tree_node *ast; |
| struct cil_db *db; |
| struct cil_tree_node *tunif; |
| struct cil_tree_node *in; |
| struct cil_tree_node *macro; |
| struct cil_tree_node *optional; |
| struct cil_tree_node *boolif; |
| }; |
| |
| static int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **list) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_tree_node *curr; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_N_STRINGS, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| rc = __cil_verify_syntax(current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_list_init(list, flavor); |
| |
| for (curr = current; curr != NULL; curr = curr->next) { |
| cil_list_append(*list, CIL_STRING, curr->data); |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| return rc; |
| } |
| |
| static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new, enum cil_flavor f_old) |
| { |
| if (f_new != f_old) { |
| return CIL_FALSE; |
| } |
| |
| switch (f_new) { |
| case CIL_TYPE: |
| case CIL_TYPEATTRIBUTE: |
| if (db->multiple_decls) { |
| return CIL_TRUE; |
| } |
| break; |
| case CIL_OPTIONAL: |
| return CIL_TRUE; |
| break; |
| default: |
| break; |
| } |
| |
| return CIL_FALSE; |
| } |
| |
| int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab, hashtab_key_t key, struct cil_symtab_datum *datum, struct cil_tree_node *node) |
| { |
| int rc; |
| |
| if (symtab == NULL || datum == NULL || node == NULL) { |
| return SEPOL_ERR; |
| } |
| |
| rc = cil_symtab_insert(symtab, key, datum, node); |
| if (rc == SEPOL_EEXIST) { |
| struct cil_symtab_datum *prev; |
| rc = cil_symtab_get_datum(symtab, key, &prev); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Re-declaration of %s %s, but previous declaration could not be found\n",cil_node_to_string(node), key); |
| return SEPOL_ERR; |
| } |
| if (!cil_allow_multiple_decls(db, node->flavor, FLAVOR(prev))) { |
| /* multiple_decls not ok, ret error */ |
| struct cil_tree_node *n = NODE(prev); |
| cil_log(CIL_ERR, "Re-declaration of %s %s\n", |
| cil_node_to_string(node), key); |
| cil_tree_log(node, CIL_ERR, "Previous declaration of %s", |
| cil_node_to_string(n)); |
| return SEPOL_ERR; |
| } |
| /* multiple_decls is enabled and works for this datum type, add node */ |
| cil_list_append(prev->nodes, CIL_NODE, node); |
| node->data = prev; |
| return SEPOL_EEXIST; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor) |
| { |
| int rc = SEPOL_ERR; |
| symtab_t *symtab = NULL; |
| |
| rc = cil_verify_name(db, (const char*)key, nflavor); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_get_symtab(ast_node->parent, &symtab, sflavor); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| ast_node->data = datum; |
| ast_node->flavor = nflavor; |
| |
| rc = cil_add_decl_to_symtab(db, symtab, key, datum, ast_node); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| if (ast_node->parent->flavor == CIL_MACRO) { |
| rc = cil_verify_decl_does_not_shadow_macro_parameter(ast_node->parent->data, ast_node, key); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| return rc; |
| } |
| |
| static void cil_clear_node(struct cil_tree_node *ast_node) |
| { |
| if (ast_node == NULL) { |
| return; |
| } |
| |
| ast_node->data = NULL; |
| ast_node->flavor = CIL_NONE; |
| } |
| |
| int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint16_t is_abstract) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_N_LISTS | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_block *block = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| if (db->qualified_names) { |
| cil_log(CIL_ERR, "Blocks are not allowed when the option for qualified names is used\n"); |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_block_init(&block); |
| |
| block->is_abstract = is_abstract; |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)block, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_BLOCK); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad block declaration"); |
| cil_destroy_block(block); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_block(struct cil_block *block) |
| { |
| struct cil_list_item *item; |
| struct cil_tree_node *bi_node; |
| struct cil_blockinherit *inherit; |
| |
| if (block == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&block->datum); |
| cil_symtab_array_destroy(block->symtab); |
| if (block->bi_nodes != NULL) { |
| /* unlink blockinherit->block */ |
| cil_list_for_each(item, block->bi_nodes) { |
| bi_node = item->data; |
| /* the conditions should always be true, but better be sure */ |
| if (bi_node->flavor == CIL_BLOCKINHERIT) { |
| inherit = bi_node->data; |
| if (inherit->block == block) { |
| inherit->block = NULL; |
| } |
| } |
| } |
| cil_list_destroy(&block->bi_nodes, CIL_FALSE); |
| } |
| |
| free(block); |
| } |
| |
| int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_blockinherit *inherit = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| if (db->qualified_names) { |
| cil_log(CIL_ERR, "Block inherit rules are not allowed when the option for qualified names is used\n"); |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_blockinherit_init(&inherit); |
| |
| inherit->block_str = parse_current->next->data; |
| |
| ast_node->data = inherit; |
| ast_node->flavor = CIL_BLOCKINHERIT; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad blockinherit declaration"); |
| cil_destroy_blockinherit(inherit); |
| return rc; |
| } |
| |
| void cil_destroy_blockinherit(struct cil_blockinherit *inherit) |
| { |
| if (inherit == NULL) { |
| return; |
| } |
| |
| if (inherit->block != NULL && inherit->block->bi_nodes != NULL) { |
| struct cil_tree_node *node; |
| struct cil_list_item *item; |
| |
| cil_list_for_each(item, inherit->block->bi_nodes) { |
| node = item->data; |
| if (node->data == inherit) { |
| cil_list_remove(inherit->block->bi_nodes, CIL_NODE, node, CIL_FALSE); |
| break; |
| } |
| } |
| } |
| |
| free(inherit); |
| } |
| |
| int cil_gen_blockabstract(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_blockabstract *abstract = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| if (db->qualified_names) { |
| cil_log(CIL_ERR, "Block abstract rules are not allowed when the option for qualified names is used\n"); |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_blockabstract_init(&abstract); |
| |
| abstract->block_str = parse_current->next->data; |
| |
| ast_node->data = abstract; |
| ast_node->flavor = CIL_BLOCKABSTRACT; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad blockabstract declaration"); |
| cil_destroy_blockabstract(abstract); |
| return rc; |
| } |
| |
| void cil_destroy_blockabstract(struct cil_blockabstract *abstract) |
| { |
| if (abstract == NULL) { |
| return; |
| } |
| |
| free(abstract); |
| } |
| |
| int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_N_LISTS, |
| CIL_SYN_N_LISTS | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_in *in = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| if (db->qualified_names) { |
| cil_log(CIL_ERR, "In-statements are not allowed when the option for qualified names is used\n"); |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_in_init(&in); |
| |
| if (parse_current->next->next->data) { |
| char *is_after_str = parse_current->next->data; |
| if (is_after_str == CIL_KEY_IN_BEFORE) { |
| in->is_after = CIL_FALSE; |
| } else if (is_after_str == CIL_KEY_IN_AFTER) { |
| in->is_after = CIL_TRUE; |
| } else { |
| cil_log(CIL_ERR, "Value must be either \'before\' or \'after\'\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| in->block_str = parse_current->next->next->data; |
| } else { |
| in->is_after = CIL_FALSE; |
| in->block_str = parse_current->next->data; |
| } |
| |
| ast_node->data = in; |
| ast_node->flavor = CIL_IN; |
| |
| return SEPOL_OK; |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad in-statement"); |
| cil_destroy_in(in); |
| return rc; |
| } |
| |
| void cil_destroy_in(struct cil_in *in) |
| { |
| if (in == NULL) { |
| return; |
| } |
| |
| cil_symtab_array_destroy(in->symtab); |
| |
| free(in); |
| } |
| |
| int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_class *class = NULL; |
| struct cil_tree_node *perms = NULL; |
| int rc = SEPOL_ERR; |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_class_init(&class); |
| |
| key = parse_current->next->data; |
| if (key == CIL_KEY_UNORDERED) { |
| cil_log(CIL_ERR, "'unordered' keyword is reserved and not a valid class name.\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)class, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_CLASS); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| if (parse_current->next->next != NULL) { |
| perms = parse_current->next->next->cl_head; |
| rc = cil_gen_perm_nodes(db, perms, ast_node, CIL_PERM, &class->num_perms); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| if (class->num_perms > CIL_PERMS_PER_CLASS) { |
| cil_tree_log(parse_current, CIL_ERR, "Too many permissions in class '%s'", class->datum.name); |
| cil_tree_children_destroy(ast_node); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad class declaration"); |
| cil_destroy_class(class); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_class(struct cil_class *class) |
| { |
| if (class == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&class->datum); |
| cil_symtab_destroy(&class->perms); |
| |
| free(class); |
| } |
| |
| int cil_gen_classorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_classorder *classorder = NULL; |
| struct cil_list_item *curr = NULL; |
| struct cil_list_item *head = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_classorder_init(&classorder); |
| |
| rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASSORDER, &classorder->class_list_str); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| head = classorder->class_list_str->head; |
| cil_list_for_each(curr, classorder->class_list_str) { |
| if (curr->data == CIL_KEY_UNORDERED) { |
| if (curr == head && curr->next == NULL) { |
| cil_log(CIL_ERR, "Classorder 'unordered' keyword must be followed by one or more class.\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } else if (curr != head) { |
| cil_log(CIL_ERR, "Classorder can only use 'unordered' keyword as the first item in the list.\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } |
| } |
| |
| ast_node->data = classorder; |
| ast_node->flavor = CIL_CLASSORDER; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad classorder declaration"); |
| cil_destroy_classorder(classorder); |
| return rc; |
| } |
| |
| void cil_destroy_classorder(struct cil_classorder *classorder) |
| { |
| if (classorder == NULL) { |
| return; |
| } |
| |
| if (classorder->class_list_str != NULL) { |
| cil_list_destroy(&classorder->class_list_str, 1); |
| } |
| |
| free(classorder); |
| } |
| |
| 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) |
| { |
| char *key = NULL; |
| struct cil_perm *perm = NULL; |
| int rc = SEPOL_ERR; |
| |
| cil_perm_init(&perm); |
| |
| key = parse_current->data; |
| if (key == NULL) { |
| cil_log(CIL_ERR, "Bad permission\n"); |
| goto exit; |
| } |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)perm, (hashtab_key_t)key, CIL_SYM_PERMS, flavor); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| perm->value = *num_perms; |
| (*num_perms)++; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_destroy_perm(perm); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_perm(struct cil_perm *perm) |
| { |
| if (perm == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&perm->datum); |
| cil_list_destroy(&perm->classperms, CIL_FALSE); |
| |
| free(perm); |
| } |
| |
| 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) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_tree_node *new_ast = NULL; |
| |
| while(current_perm != NULL) { |
| if (current_perm->cl_head != NULL) { |
| |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| cil_tree_node_init(&new_ast); |
| new_ast->parent = ast_node; |
| new_ast->line = current_perm->line; |
| new_ast->hll_offset = current_perm->hll_offset; |
| |
| rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms); |
| if (rc != SEPOL_OK) { |
| cil_tree_node_destroy(&new_ast); |
| goto exit; |
| } |
| |
| if (ast_node->cl_head == NULL) { |
| ast_node->cl_head = new_ast; |
| } else { |
| ast_node->cl_tail->next = new_ast; |
| } |
| ast_node->cl_tail = new_ast; |
| |
| current_perm = current_perm->next; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Bad permissions\n"); |
| cil_tree_children_destroy(ast_node); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_gen_expr(start_perm, CIL_PERM, perms); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Bad permission list or expression\n"); |
| return rc; |
| } |
| |
| int cil_fill_classperms(struct cil_tree_node *parse_current, struct cil_classperms **cp) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_classperms_init(cp); |
| |
| (*cp)->class_str = parse_current->data; |
| |
| rc = cil_fill_perms(parse_current->next, &(*cp)->perm_strs); |
| if (rc != SEPOL_OK) { |
| cil_destroy_classperms(*cp); |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Bad class-permissions\n"); |
| *cp = NULL; |
| return rc; |
| } |
| |
| void cil_destroy_classperms(struct cil_classperms *cp) |
| { |
| if (cp == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&cp->perm_strs, CIL_TRUE); |
| cil_list_destroy(&cp->perms, CIL_FALSE); |
| |
| free(cp); |
| } |
| |
| void cil_fill_classperms_set(struct cil_tree_node *parse_current, struct cil_classperms_set **cp_set) |
| { |
| cil_classperms_set_init(cp_set); |
| (*cp_set)->set_str = parse_current->data; |
| } |
| |
| void cil_destroy_classperms_set(struct cil_classperms_set *cp_set) |
| { |
| if (cp_set == NULL) { |
| return; |
| } |
| |
| free(cp_set); |
| } |
| |
| int cil_fill_classperms_list(struct cil_tree_node *parse_current, struct cil_list **cp_list) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_tree_node *curr; |
| |
| if (parse_current == NULL || cp_list == NULL) { |
| goto exit; |
| } |
| |
| cil_list_init(cp_list, CIL_CLASSPERMS); |
| |
| curr = parse_current->cl_head; |
| |
| if (curr == NULL) { |
| /* Class-perms form: SET1 */ |
| struct cil_classperms_set *new_cp_set; |
| cil_fill_classperms_set(parse_current, &new_cp_set); |
| cil_list_append(*cp_list, CIL_CLASSPERMS_SET, new_cp_set); |
| } else if (curr->cl_head == NULL) { |
| /* Class-perms form: (CLASS1 (PERM1 ...)) */ |
| struct cil_classperms *new_cp; |
| rc = cil_fill_classperms(curr, &new_cp); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| cil_list_append(*cp_list, CIL_CLASSPERMS, new_cp); |
| } else { |
| cil_log(CIL_ERR, "Bad class-permissions list syntax\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Problem filling class-permissions list\n"); |
| cil_list_destroy(cp_list, CIL_TRUE); |
| return rc; |
| } |
| |
| void cil_destroy_classperms_list(struct cil_list **cp_list) |
| { |
| struct cil_list_item *curr; |
| |
| if (cp_list == NULL || *cp_list == NULL) { |
| return; |
| } |
| |
| cil_list_for_each(curr, *cp_list) { |
| if (curr->flavor == CIL_CLASSPERMS) { |
| cil_destroy_classperms(curr->data); |
| } else { |
| cil_destroy_classperms_set(curr->data); |
| } |
| } |
| |
| cil_list_destroy(cp_list, CIL_FALSE); |
| } |
| |
| int cil_gen_classpermission(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| int rc = SEPOL_ERR; |
| char *key = NULL; |
| struct cil_classpermission *cp = NULL; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_classpermission_init(&cp); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cp, (hashtab_key_t)key, CIL_SYM_CLASSPERMSETS, CIL_CLASSPERMISSION); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad classpermission declaration"); |
| cil_destroy_classpermission(cp); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_classpermission(struct cil_classpermission *cp) |
| { |
| if (cp == NULL) { |
| return; |
| } |
| |
| if (cp->datum.name != NULL) { |
| cil_list_destroy(&cp->classperms, CIL_FALSE); |
| } else { |
| /* anonymous classpermission from call */ |
| cil_destroy_classperms_list(&cp->classperms); |
| } |
| |
| cil_symtab_datum_destroy(&cp->datum); |
| |
| |
| free(cp); |
| } |
| |
| int cil_gen_classpermissionset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_classpermissionset *cps = NULL; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_classpermissionset_init(&cps); |
| |
| cps->set_str = parse_current->next->data; |
| |
| rc = cil_fill_classperms_list(parse_current->next->next, &cps->classperms); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| ast_node->data = cps; |
| ast_node->flavor = CIL_CLASSPERMISSIONSET; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad classpermissionset"); |
| cil_destroy_classpermissionset(cps); |
| return rc; |
| } |
| |
| void cil_destroy_classpermissionset(struct cil_classpermissionset *cps) |
| { |
| if (cps == NULL) { |
| return; |
| } |
| |
| cil_destroy_classperms_list(&cps->classperms); |
| |
| free(cps); |
| } |
| |
| int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_class *map = NULL; |
| int rc = SEPOL_ERR; |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_class_init(&map); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)map, (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_MAP_CLASS); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_MAP_PERM, &map->num_perms); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad map class declaration"); |
| cil_destroy_class(map); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_classmapping *mapping = NULL; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_classmapping_init(&mapping); |
| |
| mapping->map_class_str = parse_current->next->data; |
| mapping->map_perm_str = parse_current->next->next->data; |
| |
| rc = cil_fill_classperms_list(parse_current->next->next->next, &mapping->classperms); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| ast_node->data = mapping; |
| ast_node->flavor = CIL_CLASSMAPPING; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad classmapping declaration"); |
| cil_destroy_classmapping(mapping); |
| return rc; |
| } |
| |
| void cil_destroy_classmapping(struct cil_classmapping *mapping) |
| { |
| if (mapping == NULL) { |
| return; |
| } |
| |
| cil_destroy_classperms_list(&mapping->classperms); |
| |
| free(mapping); |
| } |
| |
| // TODO try to merge some of this with cil_gen_class (helper function for both) |
| int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_class *common = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_class_init(&common); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)common, (hashtab_key_t)key, CIL_SYM_COMMONS, CIL_COMMON); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head, ast_node, CIL_PERM, &common->num_perms); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| if (common->num_perms > CIL_PERMS_PER_CLASS) { |
| cil_tree_log(parse_current, CIL_ERR, "Too many permissions in common '%s'", common->datum.name); |
| cil_tree_children_destroy(ast_node); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad common declaration"); |
| cil_destroy_class(common); |
| cil_clear_node(ast_node); |
| return rc; |
| |
| } |
| |
| int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_classcommon *clscom = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_classcommon_init(&clscom); |
| |
| clscom->class_str = parse_current->next->data; |
| clscom->common_str = parse_current->next->next->data; |
| |
| ast_node->data = clscom; |
| ast_node->flavor = CIL_CLASSCOMMON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad classcommon declaration"); |
| cil_destroy_classcommon(clscom); |
| return rc; |
| |
| } |
| |
| void cil_destroy_classcommon(struct cil_classcommon *clscom) |
| { |
| if (clscom == NULL) { |
| return; |
| } |
| |
| free(clscom); |
| } |
| |
| int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_sid *sid = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_sid_init(&sid); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sid, (hashtab_key_t)key, CIL_SYM_SIDS, CIL_SID); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad sid declaration"); |
| cil_destroy_sid(sid); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_sid(struct cil_sid *sid) |
| { |
| if (sid == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&sid->datum); |
| free(sid); |
| } |
| |
| int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_sidcontext *sidcon = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_sidcontext_init(&sidcon); |
| |
| sidcon->sid_str = parse_current->next->data; |
| |
| if (parse_current->next->next->cl_head == NULL) { |
| sidcon->context_str = parse_current->next->next->data; |
| } else { |
| cil_context_init(&sidcon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->cl_head, sidcon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = sidcon; |
| ast_node->flavor = CIL_SIDCONTEXT; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad sidcontext declaration"); |
| cil_destroy_sidcontext(sidcon); |
| return rc; |
| } |
| |
| void cil_destroy_sidcontext(struct cil_sidcontext *sidcon) |
| { |
| if (sidcon == NULL) { |
| return; |
| } |
| |
| if (sidcon->context_str == NULL && sidcon->context != NULL) { |
| cil_destroy_context(sidcon->context); |
| } |
| |
| free(sidcon); |
| } |
| |
| int cil_gen_sidorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_sidorder *sidorder = NULL; |
| struct cil_list_item *curr = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_sidorder_init(&sidorder); |
| |
| rc = cil_fill_list(parse_current->next->cl_head, CIL_SIDORDER, &sidorder->sid_list_str); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_list_for_each(curr, sidorder->sid_list_str) { |
| if (curr->data == CIL_KEY_UNORDERED) { |
| cil_log(CIL_ERR, "Sidorder cannot be unordered.\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } |
| |
| ast_node->data = sidorder; |
| ast_node->flavor = CIL_SIDORDER; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad sidorder declaration"); |
| cil_destroy_sidorder(sidorder); |
| return rc; |
| } |
| |
| void cil_destroy_sidorder(struct cil_sidorder *sidorder) |
| { |
| if (sidorder == NULL) { |
| return; |
| } |
| |
| if (sidorder->sid_list_str != NULL) { |
| cil_list_destroy(&sidorder->sid_list_str, 1); |
| } |
| |
| free(sidorder); |
| } |
| |
| int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_user *user = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_user_init(&user); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)user, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USER); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad user declaration"); |
| cil_destroy_user(user); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_user(struct cil_user *user) |
| { |
| if (user == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&user->datum); |
| ebitmap_destroy(user->roles); |
| free(user->roles); |
| free(user); |
| } |
| |
| int cil_gen_userattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_userattribute *attr = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_userattribute_init(&attr); |
| |
| key = parse_current->next->data; |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad userattribute declaration"); |
| cil_destroy_userattribute(attr); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_userattribute(struct cil_userattribute *attr) |
| { |
| struct cil_list_item *expr = NULL; |
| struct cil_list_item *next = NULL; |
| |
| if (attr == NULL) { |
| return; |
| } |
| |
| if (attr->expr_list != NULL) { |
| /* we don't want to destroy the expression stacks (cil_list) inside |
| * this list cil_list_destroy destroys sublists, so we need to do it |
| * manually */ |
| expr = attr->expr_list->head; |
| while (expr != NULL) { |
| next = expr->next; |
| cil_list_item_destroy(&expr, CIL_FALSE); |
| expr = next; |
| } |
| free(attr->expr_list); |
| attr->expr_list = NULL; |
| } |
| |
| cil_symtab_datum_destroy(&attr->datum); |
| ebitmap_destroy(attr->users); |
| free(attr->users); |
| free(attr); |
| } |
| |
| int cil_gen_userattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_userattributeset *attrset = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_userattributeset_init(&attrset); |
| |
| attrset->attr_str = parse_current->next->data; |
| |
| rc = cil_gen_expr(parse_current->next->next, CIL_USER, &attrset->str_expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| ast_node->data = attrset; |
| ast_node->flavor = CIL_USERATTRIBUTESET; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad userattributeset declaration"); |
| cil_destroy_userattributeset(attrset); |
| |
| return rc; |
| } |
| |
| void cil_destroy_userattributeset(struct cil_userattributeset *attrset) |
| { |
| if (attrset == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&attrset->str_expr, CIL_TRUE); |
| cil_list_destroy(&attrset->datum_expr, CIL_FALSE); |
| |
| free(attrset); |
| } |
| |
| int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_userlevel *usrlvl = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_userlevel_init(&usrlvl); |
| |
| usrlvl->user_str = parse_current->next->data; |
| |
| if (parse_current->next->next->cl_head == NULL) { |
| usrlvl->level_str = parse_current->next->next->data; |
| } else { |
| cil_level_init(&usrlvl->level); |
| |
| rc = cil_fill_level(parse_current->next->next->cl_head, usrlvl->level); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = usrlvl; |
| ast_node->flavor = CIL_USERLEVEL; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad userlevel declaration"); |
| cil_destroy_userlevel(usrlvl); |
| return rc; |
| } |
| |
| void cil_destroy_userlevel(struct cil_userlevel *usrlvl) |
| { |
| if (usrlvl == NULL) { |
| return; |
| } |
| |
| if (usrlvl->level_str == NULL && usrlvl->level != NULL) { |
| cil_destroy_level(usrlvl->level); |
| } |
| |
| free(usrlvl); |
| } |
| |
| int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_userrange *userrange = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_userrange_init(&userrange); |
| |
| userrange->user_str = parse_current->next->data; |
| |
| if (parse_current->next->next->cl_head == NULL) { |
| userrange->range_str = parse_current->next->next->data; |
| } else { |
| cil_levelrange_init(&userrange->range); |
| |
| rc = cil_fill_levelrange(parse_current->next->next->cl_head, userrange->range); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = userrange; |
| ast_node->flavor = CIL_USERRANGE; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad userrange declaration"); |
| cil_destroy_userrange(userrange); |
| return rc; |
| } |
| |
| void cil_destroy_userrange(struct cil_userrange *userrange) |
| { |
| if (userrange == NULL) { |
| return; |
| } |
| |
| if (userrange->range_str == NULL && userrange->range != NULL) { |
| cil_destroy_levelrange(userrange->range); |
| } |
| |
| free(userrange); |
| } |
| |
| int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_userprefix *userprefix = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_userprefix_init(&userprefix); |
| |
| userprefix->user_str = parse_current->next->data; |
| userprefix->prefix_str = parse_current->next->next->data; |
| |
| ast_node->data = userprefix; |
| ast_node->flavor = CIL_USERPREFIX; |
| |
| return SEPOL_OK; |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad userprefix declaration"); |
| cil_destroy_userprefix(userprefix); |
| return rc; |
| } |
| |
| void cil_destroy_userprefix(struct cil_userprefix *userprefix) |
| { |
| if (userprefix == NULL) { |
| return; |
| } |
| |
| free(userprefix); |
| } |
| |
| int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_selinuxuser *selinuxuser = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_selinuxuser_init(&selinuxuser); |
| |
| selinuxuser->name_str = parse_current->next->data; |
| selinuxuser->user_str = parse_current->next->next->data; |
| |
| if (parse_current->next->next->next->cl_head == NULL) { |
| selinuxuser->range_str = parse_current->next->next->next->data; |
| } else { |
| cil_levelrange_init(&selinuxuser->range); |
| |
| rc = cil_fill_levelrange(parse_current->next->next->next->cl_head, selinuxuser->range); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = selinuxuser; |
| ast_node->flavor = CIL_SELINUXUSER; |
| |
| return SEPOL_OK; |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuser declaration"); |
| cil_destroy_selinuxuser(selinuxuser); |
| return rc; |
| } |
| |
| int cil_gen_selinuxuserdefault(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_selinuxuser *selinuxuser = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_selinuxuser_init(&selinuxuser); |
| |
| selinuxuser->name_str = cil_strpool_add("__default__"); |
| selinuxuser->user_str = parse_current->next->data; |
| |
| if (parse_current->next->next->cl_head == NULL) { |
| selinuxuser->range_str = parse_current->next->next->data; |
| } else { |
| cil_levelrange_init(&selinuxuser->range); |
| |
| rc = cil_fill_levelrange(parse_current->next->next->cl_head, selinuxuser->range); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = selinuxuser; |
| ast_node->flavor = CIL_SELINUXUSERDEFAULT; |
| |
| return SEPOL_OK; |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuserdefault declaration"); |
| cil_destroy_selinuxuser(selinuxuser); |
| return rc; |
| } |
| |
| void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser) |
| { |
| if (selinuxuser == NULL) { |
| return; |
| } |
| |
| if (selinuxuser->range_str == NULL && selinuxuser->range != NULL) { |
| cil_destroy_levelrange(selinuxuser->range); |
| } |
| |
| free(selinuxuser); |
| } |
| |
| int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_role *role = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_role_init(&role); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)role, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLE); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad role declaration"); |
| cil_destroy_role(role); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_role(struct cil_role *role) |
| { |
| if (role == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&role->datum); |
| ebitmap_destroy(role->types); |
| free(role->types); |
| free(role); |
| } |
| |
| int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_roletype *roletype = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_roletype_init(&roletype); |
| |
| roletype->role_str = parse_current->next->data; |
| roletype->type_str = parse_current->next->next->data; |
| |
| ast_node->data = roletype; |
| ast_node->flavor = CIL_ROLETYPE; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad roletype declaration"); |
| cil_destroy_roletype(roletype); |
| return rc; |
| } |
| |
| void cil_destroy_roletype(struct cil_roletype *roletype) |
| { |
| if (roletype == NULL) { |
| return; |
| } |
| |
| free(roletype); |
| } |
| |
| int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_userrole *userrole = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_userrole_init(&userrole); |
| |
| userrole->user_str = parse_current->next->data; |
| userrole->role_str = parse_current->next->next->data; |
| |
| ast_node->data = userrole; |
| ast_node->flavor = CIL_USERROLE; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad userrole declaration"); |
| cil_destroy_userrole(userrole); |
| return rc; |
| } |
| |
| void cil_destroy_userrole(struct cil_userrole *userrole) |
| { |
| if (userrole == NULL) { |
| return; |
| } |
| |
| free(userrole); |
| } |
| |
| int cil_gen_roletransition(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_roletransition *roletrans = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_roletransition_init(&roletrans); |
| |
| roletrans->src_str = parse_current->next->data; |
| roletrans->tgt_str = parse_current->next->next->data; |
| roletrans->obj_str = parse_current->next->next->next->data; |
| roletrans->result_str = parse_current->next->next->next->next->data; |
| |
| ast_node->data = roletrans; |
| ast_node->flavor = CIL_ROLETRANSITION; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad roletransition rule"); |
| cil_destroy_roletransition(roletrans); |
| return rc; |
| } |
| |
| void cil_destroy_roletransition(struct cil_roletransition *roletrans) |
| { |
| if (roletrans == NULL) { |
| return; |
| } |
| |
| free(roletrans); |
| } |
| |
| int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_roleallow *roleallow = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_roleallow_init(&roleallow); |
| |
| roleallow->src_str = parse_current->next->data; |
| roleallow->tgt_str = parse_current->next->next->data; |
| |
| ast_node->data = roleallow; |
| ast_node->flavor = CIL_ROLEALLOW; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad roleallow rule"); |
| cil_destroy_roleallow(roleallow); |
| return rc; |
| } |
| |
| void cil_destroy_roleallow(struct cil_roleallow *roleallow) |
| { |
| if (roleallow == NULL) { |
| return; |
| } |
| |
| free(roleallow); |
| } |
| |
| int cil_gen_roleattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_roleattribute *attr = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_roleattribute_init(&attr); |
| |
| key = parse_current->next->data; |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLEATTRIBUTE); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad roleattribute declaration"); |
| cil_destroy_roleattribute(attr); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_roleattribute(struct cil_roleattribute *attr) |
| { |
| if (attr == NULL) { |
| return; |
| } |
| |
| if (attr->expr_list != NULL) { |
| /* we don't want to destroy the expression stacks (cil_list) inside |
| * this list cil_list_destroy destroys sublists, so we need to do it |
| * manually */ |
| struct cil_list_item *expr = attr->expr_list->head; |
| while (expr != NULL) { |
| struct cil_list_item *next = expr->next; |
| cil_list_item_destroy(&expr, CIL_FALSE); |
| expr = next; |
| } |
| free(attr->expr_list); |
| attr->expr_list = NULL; |
| } |
| |
| cil_symtab_datum_destroy(&attr->datum); |
| ebitmap_destroy(attr->roles); |
| free(attr->roles); |
| free(attr); |
| } |
| |
| int cil_gen_roleattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_roleattributeset *attrset = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_roleattributeset_init(&attrset); |
| |
| attrset->attr_str = parse_current->next->data; |
| |
| rc = cil_gen_expr(parse_current->next->next, CIL_ROLE, &attrset->str_expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| ast_node->data = attrset; |
| ast_node->flavor = CIL_ROLEATTRIBUTESET; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad roleattributeset declaration"); |
| cil_destroy_roleattributeset(attrset); |
| |
| return rc; |
| } |
| |
| void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset) |
| { |
| if (attrset == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&attrset->str_expr, CIL_TRUE); |
| cil_list_destroy(&attrset->datum_expr, CIL_FALSE); |
| |
| free(attrset); |
| } |
| |
| int cil_gen_avrule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_avrule *rule = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_avrule_init(&rule); |
| |
| rule->is_extended = 0; |
| rule->rule_kind = rule_kind; |
| |
| rule->src_str = parse_current->next->data; |
| rule->tgt_str = parse_current->next->next->data; |
| |
| rc = cil_fill_classperms_list(parse_current->next->next->next, &rule->perms.classperms); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| ast_node->data = rule; |
| ast_node->flavor = CIL_AVRULE; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad allow rule"); |
| cil_destroy_avrule(rule); |
| return rc; |
| } |
| |
| void cil_destroy_avrule(struct cil_avrule *rule) |
| { |
| if (rule == NULL) { |
| return; |
| } |
| |
| if (!rule->is_extended) { |
| cil_destroy_classperms_list(&rule->perms.classperms); |
| } else { |
| if (rule->perms.x.permx_str == NULL && rule->perms.x.permx != NULL) { |
| cil_destroy_permissionx(rule->perms.x.permx); |
| } |
| } |
| |
| free(rule); |
| } |
| |
| static int cil_fill_permissionx(struct cil_tree_node *parse_current, struct cil_permissionx *permx) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| if (parse_current->data == CIL_KEY_IOCTL) { |
| permx->kind = CIL_PERMX_KIND_IOCTL; |
| } else { |
| cil_log(CIL_ERR, "Unknown permissionx kind, %s. Must be \"ioctl\"\n", (char *)parse_current->data); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| permx->obj_str = parse_current->next->data; |
| |
| rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX, &permx->expr_str); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content"); |
| return rc; |
| } |
| |
| int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_permissionx *permx = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_permissionx_init(&permx); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)permx, (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement"); |
| cil_destroy_permissionx(permx); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_permissionx(struct cil_permissionx *permx) |
| { |
| if (permx == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&permx->datum); |
| |
| cil_list_destroy(&permx->expr_str, CIL_TRUE); |
| ebitmap_destroy(permx->perms); |
| free(permx->perms); |
| free(permx); |
| } |
| |
| int cil_gen_avrulex(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_avrule *rule = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_avrule_init(&rule); |
| |
| rule->is_extended = 1; |
| rule->rule_kind = rule_kind; |
| rule->src_str = parse_current->next->data; |
| rule->tgt_str = parse_current->next->next->data; |
| |
| if (parse_current->next->next->next->cl_head == NULL) { |
| rule->perms.x.permx_str = parse_current->next->next->next->data; |
| } else { |
| cil_permissionx_init(&rule->perms.x.permx); |
| |
| rc = cil_fill_permissionx(parse_current->next->next->next->cl_head, rule->perms.x.permx); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = rule; |
| ast_node->flavor = CIL_AVRULEX; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule"); |
| cil_destroy_avrule(rule); |
| return rc; |
| } |
| |
| int cil_gen_type_rule(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, uint32_t rule_kind) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_type_rule *rule = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_type_rule_init(&rule); |
| |
| rule->rule_kind = rule_kind; |
| rule->src_str = parse_current->next->data; |
| rule->tgt_str = parse_current->next->next->data; |
| rule->obj_str = parse_current->next->next->next->data; |
| rule->result_str = parse_current->next->next->next->next->data; |
| |
| ast_node->data = rule; |
| ast_node->flavor = CIL_TYPE_RULE; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad type rule"); |
| cil_destroy_type_rule(rule); |
| return rc; |
| } |
| |
| void cil_destroy_type_rule(struct cil_type_rule *rule) |
| { |
| if (rule == NULL) { |
| return; |
| } |
| |
| free(rule); |
| } |
| |
| int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_type *type = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_type_init(&type); |
| |
| key = parse_current->next->data; |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)type, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE); |
| if (rc != SEPOL_OK) { |
| if (rc == SEPOL_EEXIST) { |
| cil_destroy_type(type); |
| type = NULL; |
| } else { |
| goto exit; |
| } |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad type declaration"); |
| cil_destroy_type(type); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_type(struct cil_type *type) |
| { |
| if (type == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&type->datum); |
| free(type); |
| } |
| |
| int cil_gen_typeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_typeattribute *attr = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_typeattribute_init(&attr); |
| |
| key = parse_current->next->data; |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)attr, (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE); |
| if (rc != SEPOL_OK) { |
| if (rc == SEPOL_EEXIST) { |
| cil_destroy_typeattribute(attr); |
| attr = NULL; |
| } else { |
| goto exit; |
| } |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration"); |
| cil_destroy_typeattribute(attr); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_typeattribute(struct cil_typeattribute *attr) |
| { |
| if (attr == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&attr->datum); |
| |
| if (attr->expr_list != NULL) { |
| /* we don't want to destroy the expression stacks (cil_list) inside |
| * this list cil_list_destroy destroys sublists, so we need to do it |
| * manually */ |
| struct cil_list_item *expr = attr->expr_list->head; |
| while (expr != NULL) { |
| struct cil_list_item *next = expr->next; |
| cil_list_item_destroy(&expr, CIL_FALSE); |
| expr = next; |
| } |
| free(attr->expr_list); |
| attr->expr_list = NULL; |
| } |
| ebitmap_destroy(attr->types); |
| free(attr->types); |
| free(attr); |
| } |
| |
| int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_bool *boolean = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_bool_init(&boolean); |
| |
| key = parse_current->next->data; |
| |
| if (parse_current->next->next->data == CIL_KEY_CONDTRUE) { |
| boolean->value = CIL_TRUE; |
| } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) { |
| boolean->value = CIL_FALSE; |
| } else { |
| cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)boolean, (hashtab_key_t)key, CIL_SYM_BOOLS, CIL_BOOL); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| if (tunableif) { |
| cil_tree_log(parse_current, CIL_ERR, "Bad tunable (treated as a boolean due to preserve-tunables) declaration"); |
| } else { |
| cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration"); |
| } |
| cil_destroy_bool(boolean); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_bool(struct cil_bool *boolean) |
| { |
| if (boolean == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&boolean->datum); |
| free(boolean); |
| } |
| |
| int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_tunable *tunable = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_tunable_init(&tunable); |
| |
| key = parse_current->next->data; |
| |
| if (parse_current->next->next->data == CIL_KEY_CONDTRUE) { |
| tunable->value = CIL_TRUE; |
| } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) { |
| tunable->value = CIL_FALSE; |
| } else { |
| cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)tunable, (hashtab_key_t)key, CIL_SYM_TUNABLES, CIL_TUNABLE); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration"); |
| cil_destroy_tunable(tunable); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_tunable(struct cil_tunable *tunable) |
| { |
| if (tunable == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&tunable->datum); |
| free(tunable); |
| } |
| |
| static enum cil_flavor __cil_get_expr_operator_flavor(const char *op) |
| { |
| if (op == NULL) return CIL_NONE; |
| else if (op == CIL_KEY_AND) return CIL_AND; |
| else if (op == CIL_KEY_OR) return CIL_OR; |
| else if (op == CIL_KEY_NOT) return CIL_NOT; |
| else if (op == CIL_KEY_EQ) return CIL_EQ; /* Only conditional */ |
| else if (op == CIL_KEY_NEQ) return CIL_NEQ; /* Only conditional */ |
| else if (op == CIL_KEY_XOR) return CIL_XOR; |
| else if (op == CIL_KEY_ALL) return CIL_ALL; /* Only set and permissionx */ |
| else if (op == CIL_KEY_RANGE) return CIL_RANGE; /* Only catset and permissionx */ |
| else return CIL_NONE; |
| } |
| |
| static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr); |
| |
| static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_flavor op; |
| |
| op = __cil_get_expr_operator_flavor(current->data); |
| |
| rc = cil_verify_expr_syntax(current, op, flavor); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| if (op != CIL_NONE) { |
| cil_list_append(expr, CIL_OP, (void *)op); |
| current = current->next; |
| } |
| |
| for (;current != NULL; current = current->next) { |
| rc = __cil_fill_expr(current, flavor, expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| return rc; |
| } |
| |
| static int __cil_fill_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr) |
| { |
| int rc = SEPOL_ERR; |
| |
| if (current->cl_head == NULL) { |
| enum cil_flavor op = __cil_get_expr_operator_flavor(current->data); |
| if (op != CIL_NONE) { |
| cil_log(CIL_ERR, "Operator (%s) not in an expression\n", (char*)current->data); |
| goto exit; |
| } |
| cil_list_append(expr, CIL_STRING, current->data); |
| } else { |
| struct cil_list *sub_expr; |
| cil_list_init(&sub_expr, flavor); |
| rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr); |
| if (rc != SEPOL_OK) { |
| cil_list_destroy(&sub_expr, CIL_TRUE); |
| goto exit; |
| } |
| cil_list_append(expr, CIL_LIST, sub_expr); |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| return rc; |
| } |
| |
| |
| int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) |
| { |
| int rc = SEPOL_ERR; |
| |
| cil_list_init(expr, flavor); |
| |
| if (current->cl_head == NULL) { |
| rc = __cil_fill_expr(current, flavor, *expr); |
| } else { |
| rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr); |
| } |
| |
| if (rc != SEPOL_OK) { |
| cil_list_destroy(expr, CIL_TRUE); |
| cil_log(CIL_ERR, "Bad expression\n"); |
| } |
| |
| return rc; |
| } |
| |
| static enum cil_flavor __cil_get_constraint_operator_flavor(const char *op) |
| { |
| if (op == CIL_KEY_AND) return CIL_AND; |
| else if (op == CIL_KEY_OR) return CIL_OR; |
| else if (op == CIL_KEY_NOT) return CIL_NOT; |
| else if (op == CIL_KEY_EQ) return CIL_EQ; |
| else if (op == CIL_KEY_NEQ) return CIL_NEQ; |
| else if (op == CIL_KEY_CONS_DOM) return CIL_CONS_DOM; |
| else if (op == CIL_KEY_CONS_DOMBY) return CIL_CONS_DOMBY; |
| else if (op == CIL_KEY_CONS_INCOMP) return CIL_CONS_INCOMP; |
| else return CIL_NONE; |
| } |
| |
| static enum cil_flavor __cil_get_constraint_operand_flavor(const char *operand) |
| { |
| if (operand == NULL) return CIL_LIST; |
| else if (operand == CIL_KEY_CONS_T1) return CIL_CONS_T1; |
| else if (operand == CIL_KEY_CONS_T2) return CIL_CONS_T2; |
| else if (operand == CIL_KEY_CONS_T3) return CIL_CONS_T3; |
| else if (operand == CIL_KEY_CONS_R1) return CIL_CONS_R1; |
| else if (operand == CIL_KEY_CONS_R2) return CIL_CONS_R2; |
| else if (operand == CIL_KEY_CONS_R3) return CIL_CONS_R3; |
| else if (operand == CIL_KEY_CONS_U1) return CIL_CONS_U1; |
| else if (operand == CIL_KEY_CONS_U2) return CIL_CONS_U2; |
| else if (operand == CIL_KEY_CONS_U3) return CIL_CONS_U3; |
| else if (operand == CIL_KEY_CONS_L1) return CIL_CONS_L1; |
| else if (operand == CIL_KEY_CONS_L2) return CIL_CONS_L2; |
| else if (operand == CIL_KEY_CONS_H1) return CIL_CONS_H1; |
| else if (operand == CIL_KEY_CONS_H2) return CIL_CONS_H2; |
| else return CIL_STRING; |
| } |
| |
| 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) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_flavor leaf_expr_flavor = CIL_NONE; |
| enum cil_flavor l_flavor = CIL_NONE; |
| enum cil_flavor r_flavor = CIL_NONE; |
| |
| l_flavor = __cil_get_constraint_operand_flavor(current->next->data); |
| r_flavor = __cil_get_constraint_operand_flavor(current->next->next->data); |
| |
| switch (l_flavor) { |
| case CIL_CONS_U1: |
| case CIL_CONS_U2: |
| case CIL_CONS_U3: |
| leaf_expr_flavor = CIL_USER; |
| break; |
| case CIL_CONS_R1: |
| case CIL_CONS_R2: |
| case CIL_CONS_R3: |
| leaf_expr_flavor = CIL_ROLE; |
| break; |
| case CIL_CONS_T1: |
| case CIL_CONS_T2: |
| case CIL_CONS_T3: |
| leaf_expr_flavor = CIL_TYPE; |
| break; |
| case CIL_CONS_L1: |
| case CIL_CONS_L2: |
| case CIL_CONS_H1: |
| case CIL_CONS_H2: |
| leaf_expr_flavor = CIL_LEVEL; |
| break; |
| default: |
| cil_log(CIL_ERR, "Invalid left operand (%s)\n", (char*)current->next->data); |
| goto exit; |
| } |
| |
| rc = cil_verify_constraint_leaf_expr_syntax(l_flavor, r_flavor, op, expr_flavor); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_list_init(leaf_expr, leaf_expr_flavor); |
| |
| cil_list_append(*leaf_expr, CIL_OP, (void *)op); |
| |
| cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)l_flavor); |
| |
| if (r_flavor == CIL_STRING) { |
| cil_list_append(*leaf_expr, CIL_STRING, current->next->next->data); |
| } else if (r_flavor == CIL_LIST) { |
| struct cil_list *sub_list; |
| rc = cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list); |
| if (rc != SEPOL_OK) { |
| cil_list_destroy(leaf_expr, CIL_TRUE); |
| goto exit; |
| } |
| cil_list_append(*leaf_expr, CIL_LIST, sub_list); |
| } else { |
| cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor); |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| |
| return SEPOL_ERR; |
| } |
| |
| static int __cil_fill_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_flavor op; |
| struct cil_list *lexpr; |
| struct cil_list *rexpr; |
| |
| if (current->data == NULL || current->cl_head != NULL) { |
| cil_log(CIL_ERR, "Expected a string at the start of the constraint expression\n"); |
| goto exit; |
| } |
| |
| op = __cil_get_constraint_operator_flavor(current->data); |
| |
| rc = cil_verify_constraint_expr_syntax(current, op); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| switch (op) { |
| case CIL_EQ: |
| case CIL_NEQ: |
| case CIL_CONS_DOM: |
| case CIL_CONS_DOMBY: |
| case CIL_CONS_INCOMP: |
| rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| break; |
| case CIL_NOT: |
| rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| cil_list_init(expr, flavor); |
| cil_list_append(*expr, CIL_OP, (void *)op); |
| cil_list_append(*expr, CIL_LIST, lexpr); |
| break; |
| default: |
| rc = __cil_fill_constraint_expr(current->next->cl_head, flavor, &lexpr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr); |
| if (rc != SEPOL_OK) { |
| cil_list_destroy(&lexpr, CIL_TRUE); |
| goto exit; |
| } |
| cil_list_init(expr, flavor); |
| cil_list_append(*expr, CIL_OP, (void *)op); |
| cil_list_append(*expr, CIL_LIST, lexpr); |
| cil_list_append(*expr, CIL_LIST, rexpr); |
| break; |
| } |
| |
| return SEPOL_OK; |
| exit: |
| |
| return rc; |
| } |
| |
| static int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) |
| { |
| int rc = SEPOL_ERR; |
| |
| if (current->cl_head == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| |
| cil_log(CIL_ERR, "Bad expression tree for constraint\n"); |
| return rc; |
| } |
| |
| int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, int tunableif) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_LIST, |
| CIL_SYN_LIST | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_booleanif *bif = NULL; |
| struct cil_tree_node *next = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_boolif_init(&bif); |
| bif->preserved_tunable = tunableif; |
| |
| rc = cil_gen_expr(parse_current->next, CIL_BOOL, &bif->str_expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_verify_conditional_blocks(parse_current->next->next); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| /* Destroying expr tree */ |
| next = parse_current->next->next; |
| cil_tree_subtree_destroy(parse_current->next); |
| parse_current->next = next; |
| |
| ast_node->flavor = CIL_BOOLEANIF; |
| ast_node->data = bif; |
| |
| return SEPOL_OK; |
| |
| exit: |
| if (tunableif) { |
| cil_tree_log(parse_current, CIL_ERR, "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration"); |
| } else { |
| cil_tree_log(parse_current, CIL_ERR, "Bad booleanif declaration"); |
| } |
| cil_destroy_boolif(bif); |
| return rc; |
| } |
| |
| void cil_destroy_boolif(struct cil_booleanif *bif) |
| { |
| if (bif == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&bif->str_expr, CIL_TRUE); |
| cil_list_destroy(&bif->datum_expr, CIL_FALSE); |
| |
| free(bif); |
| } |
| |
| int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_LIST, |
| CIL_SYN_LIST | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_tunableif *tif = NULL; |
| struct cil_tree_node *next = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_tunif_init(&tif); |
| |
| rc = cil_gen_expr(parse_current->next, CIL_TUNABLE, &tif->str_expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_verify_conditional_blocks(parse_current->next->next); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| /* Destroying expr tree */ |
| next = parse_current->next->next; |
| cil_tree_subtree_destroy(parse_current->next); |
| parse_current->next = next; |
| |
| ast_node->flavor = CIL_TUNABLEIF; |
| ast_node->data = tif; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration"); |
| cil_destroy_tunif(tif); |
| return rc; |
| } |
| |
| void cil_destroy_tunif(struct cil_tunableif *tif) |
| { |
| if (tif == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&tif->str_expr, CIL_TRUE); |
| cil_list_destroy(&tif->datum_expr, CIL_FALSE); |
| |
| free(tif); |
| } |
| |
| int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_N_LISTS, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_condblock *cb = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| if (ast_node->parent->flavor != CIL_BOOLEANIF && ast_node->parent->flavor != CIL_TUNABLEIF) { |
| rc = SEPOL_ERR; |
| cil_log(CIL_ERR, "Conditional statements must be a direct child of a tunableif or booleanif statement.\n"); |
| goto exit; |
| } |
| |
| ast_node->flavor = CIL_CONDBLOCK; |
| |
| cil_condblock_init(&cb); |
| cb->flavor = flavor; |
| |
| ast_node->data = cb; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration", |
| (char*)parse_current->data); |
| cil_destroy_condblock(cb); |
| return rc; |
| } |
| |
| void cil_destroy_condblock(struct cil_condblock *cb) |
| { |
| if (cb == NULL) { |
| return; |
| } |
| |
| cil_symtab_array_destroy(cb->symtab); |
| free(cb); |
| } |
| |
| int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_alias *alias = NULL; |
| enum cil_sym_index sym_index; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_alias_init(&alias); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_flavor_to_symtab_index(flavor, &sym_index); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)alias, (hashtab_key_t)key, sym_index, flavor); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", (char*)parse_current->data); |
| cil_destroy_alias(alias); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_alias(struct cil_alias *alias) |
| { |
| if (alias == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&alias->datum); |
| alias->actual = NULL; |
| |
| free(alias); |
| } |
| |
| int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_aliasactual *aliasactual = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| if ((flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) || parse_current->next->next->data == CIL_KEY_SELF) { |
| cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| cil_aliasactual_init(&aliasactual); |
| |
| aliasactual->alias_str = parse_current->next->data; |
| |
| aliasactual->actual_str = parse_current->next->next->data; |
| |
| ast_node->data = aliasactual; |
| ast_node->flavor = flavor; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad %s association", cil_node_to_string(parse_current)); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual) |
| { |
| if (aliasactual == NULL) { |
| return; |
| } |
| |
| free(aliasactual); |
| } |
| |
| int cil_gen_typeattributeset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_typeattributeset *attrset = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_typeattributeset_init(&attrset); |
| |
| attrset->attr_str = parse_current->next->data; |
| |
| rc = cil_gen_expr(parse_current->next->next, CIL_TYPE, &attrset->str_expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| ast_node->data = attrset; |
| ast_node->flavor = CIL_TYPEATTRIBUTESET; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement"); |
| cil_destroy_typeattributeset(attrset); |
| return rc; |
| } |
| |
| void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset) |
| { |
| if (attrset == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&attrset->str_expr, CIL_TRUE); |
| cil_list_destroy(&attrset->datum_expr, CIL_FALSE); |
| |
| free(attrset); |
| } |
| |
| int cil_gen_expandtypeattribute(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| char *expand_str; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_expandtypeattribute *expandattr = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_expandtypeattribute_init(&expandattr); |
| |
| if (parse_current->next->cl_head == NULL) { |
| cil_list_init(&expandattr->attr_strs, CIL_TYPE); |
| cil_list_append(expandattr->attr_strs, CIL_STRING, parse_current->next->data); |
| } else { |
| rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE, &expandattr->attr_strs); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| expand_str = parse_current->next->next->data; |
| |
| if (expand_str == CIL_KEY_CONDTRUE) { |
| expandattr->expand = CIL_TRUE; |
| } else if (expand_str == CIL_KEY_CONDFALSE) { |
| expandattr->expand = CIL_FALSE; |
| } else { |
| cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| ast_node->data = expandattr; |
| ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad expandtypeattribute statement"); |
| cil_destroy_expandtypeattribute(expandattr); |
| return rc; |
| } |
| |
| void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr) |
| { |
| if (expandattr == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&expandattr->attr_strs, CIL_TRUE); |
| |
| cil_list_destroy(&expandattr->attr_datums, CIL_FALSE); |
| |
| free(expandattr); |
| } |
| |
| int cil_gen_typepermissive(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_typepermissive *typeperm = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_typepermissive_init(&typeperm); |
| |
| typeperm->type_str = parse_current->next->data; |
| |
| ast_node->data = typeperm; |
| ast_node->flavor = CIL_TYPEPERMISSIVE; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration"); |
| cil_destroy_typepermissive(typeperm); |
| return rc; |
| } |
| |
| void cil_destroy_typepermissive(struct cil_typepermissive *typeperm) |
| { |
| if (typeperm == NULL) { |
| return; |
| } |
| |
| free(typeperm); |
| } |
| |
| int cil_gen_typetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *s1, *s2, *s3, *s4, *s5; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL ) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| s1 = parse_current->next->data; |
| s2 = parse_current->next->next->data; |
| s3 = parse_current->next->next->next->data; |
| s4 = parse_current->next->next->next->next->data; |
| s5 = NULL; |
| |
| if (parse_current->next->next->next->next->next) { |
| if (s4 == CIL_KEY_STAR) { |
| s4 = parse_current->next->next->next->next->next->data; |
| } else { |
| s5 = parse_current->next->next->next->next->next->data; |
| } |
| } |
| |
| if (s5) { |
| struct cil_nametypetransition *nametypetrans = NULL; |
| |
| cil_nametypetransition_init(&nametypetrans); |
| |
| nametypetrans->src_str = s1; |
| nametypetrans->tgt_str = s2; |
| nametypetrans->obj_str = s3; |
| nametypetrans->result_str = s5; |
| nametypetrans->name_str = s4; |
| |
| ast_node->data = nametypetrans; |
| ast_node->flavor = CIL_NAMETYPETRANSITION; |
| } else { |
| struct cil_type_rule *rule = NULL; |
| |
| cil_type_rule_init(&rule); |
| |
| rule->rule_kind = CIL_TYPE_TRANSITION; |
| rule->src_str = s1; |
| rule->tgt_str = s2; |
| rule->obj_str = s3; |
| rule->result_str = s4; |
| |
| ast_node->data = rule; |
| ast_node->flavor = CIL_TYPE_RULE; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration"); |
| return rc; |
| } |
| |
| void cil_destroy_name(struct cil_name *name) |
| { |
| if (name == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&name->datum); |
| free(name); |
| } |
| |
| void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans) |
| { |
| if (nametypetrans == NULL) { |
| return; |
| } |
| |
| free(nametypetrans); |
| } |
| |
| int cil_gen_rangetransition(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_rangetransition *rangetrans = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL ) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_rangetransition_init(&rangetrans); |
| |
| rangetrans->src_str = parse_current->next->data; |
| rangetrans->exec_str = parse_current->next->next->data; |
| rangetrans->obj_str = parse_current->next->next->next->data; |
| |
| rangetrans->range_str = NULL; |
| |
| if (parse_current->next->next->next->next->cl_head == NULL) { |
| rangetrans->range_str = parse_current->next->next->next->next->data; |
| } else { |
| cil_levelrange_init(&rangetrans->range); |
| |
| rc = cil_fill_levelrange(parse_current->next->next->next->next->cl_head, rangetrans->range); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = rangetrans; |
| ast_node->flavor = CIL_RANGETRANSITION; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration"); |
| cil_destroy_rangetransition(rangetrans); |
| return rc; |
| } |
| |
| void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans) |
| { |
| if (rangetrans == NULL) { |
| return; |
| } |
| |
| if (rangetrans->range_str == NULL && rangetrans->range != NULL) { |
| cil_destroy_levelrange(rangetrans->range); |
| } |
| |
| free(rangetrans); |
| } |
| |
| int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_sens *sens = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_sens_init(&sens); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)sens, (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration"); |
| cil_destroy_sensitivity(sens); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_sensitivity(struct cil_sens *sens) |
| { |
| if (sens == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&sens->datum); |
| |
| cil_list_destroy(&sens->cats_list, CIL_FALSE); |
| |
| free(sens); |
| } |
| |
| int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_cat *cat = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_cat_init(&cat); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)cat, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad category declaration"); |
| cil_destroy_category(cat); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_category(struct cil_cat *cat) |
| { |
| if (cat == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&cat->datum); |
| free(cat); |
| } |
| |
| static int cil_gen_catset(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_catset *catset = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_catset_init(&catset); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)catset, (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_fill_cats(parse_current->next->next, &catset->cats); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration"); |
| cil_destroy_catset(catset); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_catset(struct cil_catset *catset) |
| { |
| if (catset == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&catset->datum); |
| |
| cil_destroy_cats(catset->cats); |
| |
| free(catset); |
| } |
| |
| int cil_gen_catorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_catorder *catorder = NULL; |
| struct cil_list_item *curr = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_catorder_init(&catorder); |
| |
| rc = cil_fill_list(parse_current->next->cl_head, CIL_CATORDER, &catorder->cat_list_str); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_list_for_each(curr, catorder->cat_list_str) { |
| if (curr->data == CIL_KEY_UNORDERED) { |
| cil_log(CIL_ERR, "Category order cannot be unordered.\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } |
| |
| ast_node->data = catorder; |
| ast_node->flavor = CIL_CATORDER; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad categoryorder declaration"); |
| cil_destroy_catorder(catorder); |
| return rc; |
| } |
| |
| void cil_destroy_catorder(struct cil_catorder *catorder) |
| { |
| if (catorder == NULL) { |
| return; |
| } |
| |
| if (catorder->cat_list_str != NULL) { |
| cil_list_destroy(&catorder->cat_list_str, 1); |
| } |
| |
| free(catorder); |
| } |
| |
| int cil_gen_sensitivityorder(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_sensorder *sensorder = NULL; |
| struct cil_list_item *curr = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_sensorder_init(&sensorder); |
| |
| rc = cil_fill_list(parse_current->next->cl_head, CIL_SENSITIVITYORDER, &sensorder->sens_list_str); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_list_for_each(curr, sensorder->sens_list_str) { |
| if (curr->data == CIL_KEY_UNORDERED) { |
| cil_log(CIL_ERR, "Sensitivity order cannot be unordered.\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } |
| |
| ast_node->data = sensorder; |
| ast_node->flavor = CIL_SENSITIVITYORDER; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad sensitivityorder declaration"); |
| cil_destroy_sensitivityorder(sensorder); |
| return rc; |
| } |
| |
| void cil_destroy_sensitivityorder(struct cil_sensorder *sensorder) |
| { |
| if (sensorder == NULL) { |
| return; |
| } |
| |
| if (sensorder->sens_list_str != NULL) { |
| cil_list_destroy(&sensorder->sens_list_str, CIL_TRUE); |
| } |
| |
| free(sensorder); |
| } |
| |
| int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_senscat *senscat = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_senscat_init(&senscat); |
| |
| senscat->sens_str = parse_current->next->data; |
| |
| rc = cil_fill_cats(parse_current->next->next, &senscat->cats); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| ast_node->data = senscat; |
| ast_node->flavor = CIL_SENSCAT; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad sensitivitycategory declaration"); |
| cil_destroy_senscat(senscat); |
| return rc; |
| } |
| |
| void cil_destroy_senscat(struct cil_senscat *senscat) |
| { |
| if (senscat == NULL) { |
| return; |
| } |
| |
| cil_destroy_cats(senscat->cats); |
| |
| free(senscat); |
| } |
| |
| int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_level *level = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_level_init(&level); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)level, (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_fill_level(parse_current->next->next->cl_head, level); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad level declaration"); |
| cil_destroy_level(level); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_level(struct cil_level *level) |
| { |
| if (level == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&level->datum); |
| |
| cil_destroy_cats(level->cats); |
| |
| free(level); |
| } |
| |
| /* low should be pointing to either the name of the low level or to an open paren for an anonymous low level */ |
| int cil_fill_levelrange(struct cil_tree_node *low, struct cil_levelrange *lvlrange) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| |
| if (low == NULL || lvlrange == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(low, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| |
| goto exit; |
| } |
| |
| if (low->cl_head == NULL) { |
| lvlrange->low_str = low->data; |
| } else { |
| cil_level_init(&lvlrange->low); |
| rc = cil_fill_level(low->cl_head, lvlrange->low); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| if (low->next->cl_head == NULL) { |
| lvlrange->high_str = low->next->data; |
| } else { |
| cil_level_init(&lvlrange->high); |
| rc = cil_fill_level(low->next->cl_head, lvlrange->high); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Bad levelrange\n"); |
| return rc; |
| } |
| |
| int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_levelrange *lvlrange = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_levelrange_init(&lvlrange); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)lvlrange, (hashtab_key_t)key, CIL_SYM_LEVELRANGES, CIL_LEVELRANGE); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration"); |
| cil_destroy_levelrange(lvlrange); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_levelrange(struct cil_levelrange *lvlrange) |
| { |
| if (lvlrange == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&lvlrange->datum); |
| |
| if (lvlrange->low_str == NULL) { |
| cil_destroy_level(lvlrange->low); |
| } |
| |
| if (lvlrange->high_str == NULL) { |
| cil_destroy_level(lvlrange->high); |
| } |
| |
| free(lvlrange); |
| } |
| |
| int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_constrain *cons = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_constrain_init(&cons); |
| |
| rc = cil_fill_classperms_list(parse_current->next, &cons->classperms); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &cons->str_expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| ast_node->data = cons; |
| ast_node->flavor = flavor; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration"); |
| cil_destroy_constrain(cons); |
| return rc; |
| } |
| |
| void cil_destroy_constrain(struct cil_constrain *cons) |
| { |
| if (cons == NULL) { |
| return; |
| } |
| |
| cil_destroy_classperms_list(&cons->classperms); |
| cil_list_destroy(&cons->str_expr, CIL_TRUE); |
| cil_list_destroy(&cons->datum_expr, CIL_FALSE); |
| |
| free(cons); |
| } |
| |
| int cil_gen_validatetrans(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_validatetrans *validtrans = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_validatetrans_init(&validtrans); |
| |
| validtrans->class_str = parse_current->next->data; |
| |
| rc = cil_gen_constraint_expr(parse_current->next->next, flavor, &validtrans->str_expr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| ast_node->data = validtrans; |
| ast_node->flavor = flavor; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration"); |
| cil_destroy_validatetrans(validtrans); |
| return rc; |
| |
| |
| } |
| |
| void cil_destroy_validatetrans(struct cil_validatetrans *validtrans) |
| { |
| if (validtrans == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&validtrans->str_expr, CIL_TRUE); |
| cil_list_destroy(&validtrans->datum_expr, CIL_FALSE); |
| |
| free(validtrans); |
| } |
| |
| /* Fills in context starting from user */ |
| int cil_fill_context(struct cil_tree_node *user_node, struct cil_context *context) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| |
| if (user_node == NULL || context == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(user_node, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| context->user_str = user_node->data; |
| context->role_str = user_node->next->data; |
| context->type_str = user_node->next->next->data; |
| |
| context->range_str = NULL; |
| |
| if (user_node->next->next->next->cl_head == NULL) { |
| context->range_str = user_node->next->next->next->data; |
| } else { |
| cil_levelrange_init(&context->range); |
| |
| rc = cil_fill_levelrange(user_node->next->next->next->cl_head, context->range); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Bad context\n"); |
| return rc; |
| } |
| |
| int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_context *context = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_context_init(&context); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)context, (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_fill_context(parse_current->next->next->cl_head, context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad context declaration"); |
| cil_destroy_context(context); |
| cil_clear_node(ast_node); |
| return SEPOL_ERR; |
| } |
| |
| void cil_destroy_context(struct cil_context *context) |
| { |
| if (context == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&context->datum); |
| |
| if (context->range_str == NULL && context->range != NULL) { |
| cil_destroy_levelrange(context->range); |
| } |
| |
| free(context); |
| } |
| |
| int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_filecon *filecon = NULL; |
| char *type = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| type = parse_current->next->next->data; |
| cil_filecon_init(&filecon); |
| |
| filecon->path_str = parse_current->next->data; |
| |
| if (type == CIL_KEY_ANY) { |
| filecon->type = CIL_FILECON_ANY; |
| } else if (type == CIL_KEY_FILE) { |
| filecon->type = CIL_FILECON_FILE; |
| } else if (type == CIL_KEY_DIR) { |
| filecon->type = CIL_FILECON_DIR; |
| } else if (type == CIL_KEY_CHAR) { |
| filecon->type = CIL_FILECON_CHAR; |
| } else if (type == CIL_KEY_BLOCK) { |
| filecon->type = CIL_FILECON_BLOCK; |
| } else if (type == CIL_KEY_SOCKET) { |
| filecon->type = CIL_FILECON_SOCKET; |
| } else if (type == CIL_KEY_PIPE) { |
| filecon->type = CIL_FILECON_PIPE; |
| } else if (type == CIL_KEY_SYMLINK) { |
| filecon->type = CIL_FILECON_SYMLINK; |
| } else { |
| cil_log(CIL_ERR, "Invalid file type\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| if (parse_current->next->next->next->cl_head == NULL) { |
| filecon->context_str = parse_current->next->next->next->data; |
| } else { |
| if (parse_current->next->next->next->cl_head->next == NULL) { |
| filecon->context = NULL; |
| } else { |
| cil_context_init(&filecon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->next->cl_head, filecon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| } |
| |
| ast_node->data = filecon; |
| ast_node->flavor = CIL_FILECON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration"); |
| cil_destroy_filecon(filecon); |
| return rc; |
| } |
| |
| //TODO: Should we be checking if the pointer is NULL when passed in? |
| void cil_destroy_filecon(struct cil_filecon *filecon) |
| { |
| if (filecon == NULL) { |
| return; |
| } |
| |
| if (filecon->context_str == NULL && filecon->context != NULL) { |
| cil_destroy_context(filecon->context); |
| } |
| |
| free(filecon); |
| } |
| |
| int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax) / sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_ibpkeycon *ibpkeycon = NULL; |
| |
| if (!parse_current || !ast_node) |
| goto exit; |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) |
| goto exit; |
| |
| cil_ibpkeycon_init(&ibpkeycon); |
| |
| ibpkeycon->subnet_prefix_str = parse_current->next->data; |
| |
| if (parse_current->next->next->cl_head) { |
| if (parse_current->next->next->cl_head->next && |
| !parse_current->next->next->cl_head->next->next) { |
| rc = cil_fill_integer(parse_current->next->next->cl_head, &ibpkeycon->pkey_low, 0); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper ibpkey specified\n"); |
| goto exit; |
| } |
| rc = cil_fill_integer(parse_current->next->next->cl_head->next, &ibpkeycon->pkey_high, 0); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper ibpkey specified\n"); |
| goto exit; |
| } |
| } else { |
| cil_log(CIL_ERR, "Improper ibpkey range specified\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } else { |
| rc = cil_fill_integer(parse_current->next->next, &ibpkeycon->pkey_low, 0); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper ibpkey specified\n"); |
| goto exit; |
| } |
| ibpkeycon->pkey_high = ibpkeycon->pkey_low; |
| } |
| |
| if (!parse_current->next->next->next->cl_head) { |
| ibpkeycon->context_str = parse_current->next->next->next->data; |
| } else { |
| cil_context_init(&ibpkeycon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->next->cl_head, ibpkeycon->context); |
| if (rc != SEPOL_OK) |
| goto exit; |
| } |
| |
| ast_node->data = ibpkeycon; |
| ast_node->flavor = CIL_IBPKEYCON; |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad ibpkeycon declaration"); |
| cil_destroy_ibpkeycon(ibpkeycon); |
| |
| return rc; |
| } |
| |
| void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon) |
| { |
| if (!ibpkeycon) |
| return; |
| |
| if (!ibpkeycon->context_str && ibpkeycon->context) |
| cil_destroy_context(ibpkeycon->context); |
| |
| free(ibpkeycon); |
| } |
| |
| int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_portcon *portcon = NULL; |
| char *proto; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_portcon_init(&portcon); |
| |
| proto = parse_current->next->data; |
| if (proto == CIL_KEY_UDP) { |
| portcon->proto = CIL_PROTOCOL_UDP; |
| } else if (proto == CIL_KEY_TCP) { |
| portcon->proto = CIL_PROTOCOL_TCP; |
| } else if (proto == CIL_KEY_DCCP) { |
| portcon->proto = CIL_PROTOCOL_DCCP; |
| } else if (proto == CIL_KEY_SCTP) { |
| portcon->proto = CIL_PROTOCOL_SCTP; |
| } else { |
| cil_log(CIL_ERR, "Invalid protocol\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| if (parse_current->next->next->cl_head != NULL) { |
| if (parse_current->next->next->cl_head->next != NULL |
| && parse_current->next->next->cl_head->next->next == NULL) { |
| rc = cil_fill_integer(parse_current->next->next->cl_head, &portcon->port_low, 10); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper port specified\n"); |
| goto exit; |
| } |
| rc = cil_fill_integer(parse_current->next->next->cl_head->next, &portcon->port_high, 10); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper port specified\n"); |
| goto exit; |
| } |
| } else { |
| cil_log(CIL_ERR, "Improper port range specified\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } else { |
| rc = cil_fill_integer(parse_current->next->next, &portcon->port_low, 10); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper port specified\n"); |
| goto exit; |
| } |
| portcon->port_high = portcon->port_low; |
| } |
| |
| if (parse_current->next->next->next->cl_head == NULL ) { |
| portcon->context_str = parse_current->next->next->next->data; |
| } else { |
| cil_context_init(&portcon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->next->cl_head, portcon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = portcon; |
| ast_node->flavor = CIL_PORTCON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration"); |
| cil_destroy_portcon(portcon); |
| return rc; |
| } |
| |
| void cil_destroy_portcon(struct cil_portcon *portcon) |
| { |
| if (portcon == NULL) { |
| return; |
| } |
| |
| if (portcon->context_str == NULL && portcon->context != NULL) { |
| cil_destroy_context(portcon->context); |
| } |
| |
| free(portcon); |
| } |
| |
| int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_nodecon *nodecon = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_nodecon_init(&nodecon); |
| |
| if (parse_current->next->cl_head == NULL ) { |
| nodecon->addr_str = parse_current->next->data; |
| } else { |
| cil_ipaddr_init(&nodecon->addr); |
| |
| rc = cil_fill_ipaddr(parse_current->next->cl_head, nodecon->addr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| if (parse_current->next->next->cl_head == NULL ) { |
| nodecon->mask_str = parse_current->next->next->data; |
| } else { |
| cil_ipaddr_init(&nodecon->mask); |
| |
| rc = cil_fill_ipaddr(parse_current->next->next->cl_head, nodecon->mask); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| if (parse_current->next->next->next->cl_head == NULL ) { |
| nodecon->context_str = parse_current->next->next->next->data; |
| } else { |
| cil_context_init(&nodecon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->next->cl_head, nodecon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = nodecon; |
| ast_node->flavor = CIL_NODECON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration"); |
| cil_destroy_nodecon(nodecon); |
| return rc; |
| } |
| |
| void cil_destroy_nodecon(struct cil_nodecon *nodecon) |
| { |
| if (nodecon == NULL) { |
| return; |
| } |
| |
| if (nodecon->addr_str == NULL && nodecon->addr != NULL) { |
| cil_destroy_ipaddr(nodecon->addr); |
| } |
| |
| if (nodecon->mask_str == NULL && nodecon->mask != NULL) { |
| cil_destroy_ipaddr(nodecon->mask); |
| } |
| |
| if (nodecon->context_str == NULL && nodecon->context != NULL) { |
| cil_destroy_context(nodecon->context); |
| } |
| |
| free(nodecon); |
| } |
| |
| int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_tree_node *context_node; |
| int rc = SEPOL_ERR; |
| struct cil_genfscon *genfscon = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_genfscon_init(&genfscon); |
| |
| genfscon->fs_str = parse_current->next->data; |
| genfscon->path_str = parse_current->next->next->data; |
| |
| if (parse_current->next->next->next->next) { |
| /* (genfscon <FS_STR> <PATH_STR> <FILE_TYPE> ... */ |
| char *file_type = parse_current->next->next->next->data; |
| if (file_type == CIL_KEY_ANY) { |
| genfscon->file_type = CIL_FILECON_ANY; |
| } else if (file_type == CIL_KEY_FILE) { |
| genfscon->file_type = CIL_FILECON_FILE; |
| } else if (file_type == CIL_KEY_DIR) { |
| genfscon->file_type = CIL_FILECON_DIR; |
| } else if (file_type == CIL_KEY_CHAR) { |
| genfscon->file_type = CIL_FILECON_CHAR; |
| } else if (file_type == CIL_KEY_BLOCK) { |
| genfscon->file_type = CIL_FILECON_BLOCK; |
| } else if (file_type == CIL_KEY_SOCKET) { |
| genfscon->file_type = CIL_FILECON_SOCKET; |
| } else if (file_type == CIL_KEY_PIPE) { |
| genfscon->file_type = CIL_FILECON_PIPE; |
| } else if (file_type == CIL_KEY_SYMLINK) { |
| genfscon->file_type = CIL_FILECON_SYMLINK; |
| } else { |
| if (parse_current->next->next->next->cl_head) { |
| cil_log(CIL_ERR, "Expecting file type, but found a list\n"); |
| } else { |
| cil_log(CIL_ERR, "Invalid file type \"%s\"\n", file_type); |
| } |
| goto exit; |
| } |
| context_node = parse_current->next->next->next->next; |
| } else { |
| /* (genfscon <FS_STR> <PATH_STR> ... */ |
| context_node = parse_current->next->next->next; |
| } |
| |
| if (context_node->cl_head) { |
| cil_context_init(&genfscon->context); |
| rc = cil_fill_context(context_node->cl_head, genfscon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } else { |
| genfscon->context_str = context_node->data; |
| } |
| |
| ast_node->data = genfscon; |
| ast_node->flavor = CIL_GENFSCON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration"); |
| cil_destroy_genfscon(genfscon); |
| return SEPOL_ERR; |
| } |
| |
| void cil_destroy_genfscon(struct cil_genfscon *genfscon) |
| { |
| if (genfscon == NULL) { |
| return; |
| } |
| |
| if (genfscon->context_str == NULL && genfscon->context != NULL) { |
| cil_destroy_context(genfscon->context); |
| } |
| |
| free(genfscon); |
| } |
| |
| |
| int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_netifcon *netifcon = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_netifcon_init(&netifcon); |
| |
| netifcon->interface_str = parse_current->next->data; |
| |
| if (parse_current->next->next->cl_head == NULL) { |
| netifcon->if_context_str = parse_current->next->next->data; |
| } else { |
| cil_context_init(&netifcon->if_context); |
| |
| rc = cil_fill_context(parse_current->next->next->cl_head, netifcon->if_context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| if (parse_current->next->next->next->cl_head == NULL) { |
| netifcon->packet_context_str = parse_current->next->next->next->data; |
| } else { |
| cil_context_init(&netifcon->packet_context); |
| |
| rc = cil_fill_context(parse_current->next->next->next->cl_head, netifcon->packet_context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = netifcon; |
| ast_node->flavor = CIL_NETIFCON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration"); |
| cil_destroy_netifcon(netifcon); |
| return SEPOL_ERR; |
| } |
| |
| void cil_destroy_netifcon(struct cil_netifcon *netifcon) |
| { |
| if (netifcon == NULL) { |
| return; |
| } |
| |
| if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) { |
| cil_destroy_context(netifcon->if_context); |
| } |
| |
| if (netifcon->packet_context_str == NULL && netifcon->packet_context != NULL) { |
| cil_destroy_context(netifcon->packet_context); |
| } |
| |
| free(netifcon); |
| } |
| |
| int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax) / sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_ibendportcon *ibendportcon = NULL; |
| |
| if (!parse_current || !ast_node) |
| goto exit; |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) |
| goto exit; |
| |
| cil_ibendportcon_init(&ibendportcon); |
| |
| ibendportcon->dev_name_str = parse_current->next->data; |
| |
| rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port, 10); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper ibendport port specified\n"); |
| goto exit; |
| } |
| |
| if (!parse_current->next->next->next->cl_head) { |
| ibendportcon->context_str = parse_current->next->next->next->data; |
| } else { |
| cil_context_init(&ibendportcon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->next->cl_head, ibendportcon->context); |
| if (rc != SEPOL_OK) |
| goto exit; |
| } |
| |
| ast_node->data = ibendportcon; |
| ast_node->flavor = CIL_IBENDPORTCON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration"); |
| cil_destroy_ibendportcon(ibendportcon); |
| return SEPOL_ERR; |
| } |
| |
| void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon) |
| { |
| if (!ibendportcon) |
| return; |
| |
| if (!ibendportcon->context_str && ibendportcon->context) |
| cil_destroy_context(ibendportcon->context); |
| |
| free(ibendportcon); |
| } |
| |
| int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_pirqcon *pirqcon = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_pirqcon_init(&pirqcon); |
| |
| rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| if (parse_current->next->next->cl_head == NULL) { |
| pirqcon->context_str = parse_current->next->next->data; |
| } else { |
| cil_context_init(&pirqcon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->cl_head, pirqcon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = pirqcon; |
| ast_node->flavor = CIL_PIRQCON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration"); |
| cil_destroy_pirqcon(pirqcon); |
| return rc; |
| } |
| |
| void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon) |
| { |
| if (pirqcon == NULL) { |
| return; |
| } |
| |
| if (pirqcon->context_str == NULL && pirqcon->context != NULL) { |
| cil_destroy_context(pirqcon->context); |
| } |
| |
| free(pirqcon); |
| } |
| |
| int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_iomemcon *iomemcon = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_iomemcon_init(&iomemcon); |
| |
| if (parse_current->next->cl_head != NULL) { |
| if (parse_current->next->cl_head->next != NULL && |
| parse_current->next->cl_head->next->next == NULL) { |
| rc = cil_fill_integer64(parse_current->next->cl_head, &iomemcon->iomem_low, 0); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper iomem specified\n"); |
| goto exit; |
| } |
| rc = cil_fill_integer64(parse_current->next->cl_head->next, &iomemcon->iomem_high, 0); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper iomem specified\n"); |
| goto exit; |
| } |
| } else { |
| cil_log(CIL_ERR, "Improper iomem range specified\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } else { |
| rc = cil_fill_integer64(parse_current->next, &iomemcon->iomem_low, 0); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper iomem specified\n"); |
| goto exit; |
| } |
| iomemcon->iomem_high = iomemcon->iomem_low; |
| } |
| |
| if (parse_current->next->next->cl_head == NULL ) { |
| iomemcon->context_str = parse_current->next->next->data; |
| } else { |
| cil_context_init(&iomemcon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->cl_head, iomemcon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = iomemcon; |
| ast_node->flavor = CIL_IOMEMCON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration"); |
| cil_destroy_iomemcon(iomemcon); |
| return rc; |
| } |
| |
| void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon) |
| { |
| if (iomemcon == NULL) { |
| return; |
| } |
| |
| if (iomemcon->context_str == NULL && iomemcon->context != NULL) { |
| cil_destroy_context(iomemcon->context); |
| } |
| |
| free(iomemcon); |
| } |
| |
| int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_ioportcon *ioportcon = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_ioportcon_init(&ioportcon); |
| |
| if (parse_current->next->cl_head != NULL) { |
| if (parse_current->next->cl_head->next != NULL && |
| parse_current->next->cl_head->next->next == NULL) { |
| rc = cil_fill_integer(parse_current->next->cl_head, &ioportcon->ioport_low, 0); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper ioport specified\n"); |
| goto exit; |
| } |
| rc = cil_fill_integer(parse_current->next->cl_head->next, &ioportcon->ioport_high, 0); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper ioport specified\n"); |
| goto exit; |
| } |
| } else { |
| cil_log(CIL_ERR, "Improper ioport range specified\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } else { |
| rc = cil_fill_integer(parse_current->next, &ioportcon->ioport_low, 0); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_ERR, "Improper ioport specified\n"); |
| goto exit; |
| } |
| ioportcon->ioport_high = ioportcon->ioport_low; |
| } |
| |
| if (parse_current->next->next->cl_head == NULL ) { |
| ioportcon->context_str = parse_current->next->next->data; |
| } else { |
| cil_context_init(&ioportcon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->cl_head, ioportcon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = ioportcon; |
| ast_node->flavor = CIL_IOPORTCON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration"); |
| cil_destroy_ioportcon(ioportcon); |
| return rc; |
| } |
| |
| void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon) |
| { |
| if (ioportcon == NULL) { |
| return; |
| } |
| |
| if (ioportcon->context_str == NULL && ioportcon->context != NULL) { |
| cil_destroy_context(ioportcon->context); |
| } |
| |
| free(ioportcon); |
| } |
| |
| int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_pcidevicecon *pcidevicecon = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_pcidevicecon_init(&pcidevicecon); |
| |
| rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| if (parse_current->next->next->cl_head == NULL) { |
| pcidevicecon->context_str = parse_current->next->next->data; |
| } else { |
| cil_context_init(&pcidevicecon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->cl_head, pcidevicecon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = pcidevicecon; |
| ast_node->flavor = CIL_PCIDEVICECON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration"); |
| cil_destroy_pcidevicecon(pcidevicecon); |
| return rc; |
| } |
| |
| void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon) |
| { |
| if (pcidevicecon == NULL) { |
| return; |
| } |
| |
| if (pcidevicecon->context_str == NULL && pcidevicecon->context != NULL) { |
| cil_destroy_context(pcidevicecon->context); |
| } |
| |
| free(pcidevicecon); |
| } |
| |
| int cil_gen_devicetreecon(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| int rc = SEPOL_ERR; |
| struct cil_devicetreecon *devicetreecon = NULL; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_devicetreecon_init(&devicetreecon); |
| |
| devicetreecon->path = parse_current->next->data; |
| |
| if (parse_current->next->next->cl_head == NULL) { |
| devicetreecon->context_str = parse_current->next->next->data; |
| } else { |
| cil_context_init(&devicetreecon->context); |
| |
| rc = cil_fill_context(parse_current->next->next->cl_head, devicetreecon->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = devicetreecon; |
| ast_node->flavor = CIL_DEVICETREECON; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration"); |
| cil_destroy_devicetreecon(devicetreecon); |
| return rc; |
| } |
| |
| void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon) |
| { |
| if (devicetreecon == NULL) { |
| return; |
| } |
| |
| if (devicetreecon->context_str == NULL && devicetreecon->context != NULL) { |
| cil_destroy_context(devicetreecon->context); |
| } |
| |
| free(devicetreecon); |
| } |
| |
| int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *type = NULL; |
| struct cil_fsuse *fsuse = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| type = parse_current->next->data; |
| |
| cil_fsuse_init(&fsuse); |
| |
| if (type == CIL_KEY_XATTR) { |
| fsuse->type = CIL_FSUSE_XATTR; |
| } else if (type == CIL_KEY_TASK) { |
| fsuse->type = CIL_FSUSE_TASK; |
| } else if (type == CIL_KEY_TRANS) { |
| fsuse->type = CIL_FSUSE_TRANS; |
| } else { |
| cil_log(CIL_ERR, "Invalid fsuse type\n"); |
| goto exit; |
| } |
| |
| fsuse->fs_str = parse_current->next->next->data; |
| |
| if (parse_current->next->next->next->cl_head == NULL) { |
| fsuse->context_str = parse_current->next->next->next->data; |
| } else { |
| cil_context_init(&fsuse->context); |
| |
| rc = cil_fill_context(parse_current->next->next->next->cl_head, fsuse->context); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| ast_node->data = fsuse; |
| ast_node->flavor = CIL_FSUSE; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration"); |
| cil_destroy_fsuse(fsuse); |
| return SEPOL_ERR; |
| } |
| |
| void cil_destroy_fsuse(struct cil_fsuse *fsuse) |
| { |
| if (fsuse == NULL) { |
| return; |
| } |
| |
| if (fsuse->context_str == NULL && fsuse->context != NULL) { |
| cil_destroy_context(fsuse->context); |
| } |
| |
| free(fsuse); |
| } |
| |
| void cil_destroy_param(struct cil_param *param) |
| { |
| if (param == NULL) { |
| return; |
| } |
| |
| free(param); |
| } |
| |
| int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| int rc = SEPOL_ERR; |
| char *key = NULL; |
| struct cil_macro *macro = NULL; |
| struct cil_tree_node *macro_content = NULL; |
| struct cil_tree_node *current_item; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, |
| CIL_SYN_N_LISTS | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/ sizeof(*syntax); |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc =__cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_macro_init(¯o); |
| |
| key = parse_current->next->data; |
| |
| current_item = parse_current->next->next->cl_head; |
| while (current_item != NULL) { |
| enum cil_syntax param_syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| int param_syntax_len = sizeof(param_syntax)/sizeof(*param_syntax); |
| char *kind = NULL; |
| struct cil_param *param = NULL; |
| struct cil_list_item *curr_param; |
| |
| rc =__cil_verify_syntax(current_item->cl_head, param_syntax, param_syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| if (macro->params == NULL) { |
| cil_list_init(¯o->params, CIL_LIST_ITEM); |
| } |
| |
| kind = current_item->cl_head->data; |
| cil_param_init(¶m); |
| |
| if (kind == CIL_KEY_TYPE) { |
| param->flavor = CIL_TYPE; |
| } else if (kind == CIL_KEY_ROLE) { |
| param->flavor = CIL_ROLE; |
| } else if (kind == CIL_KEY_USER) { |
| param->flavor = CIL_USER; |
| } else if (kind == CIL_KEY_SENSITIVITY) { |
| param->flavor = CIL_SENS; |
| } else if (kind == CIL_KEY_CATEGORY) { |
| param->flavor = CIL_CAT; |
| } else if (kind == CIL_KEY_CATSET) { |
| param->flavor = CIL_CATSET; |
| } else if (kind == CIL_KEY_LEVEL) { |
| param->flavor = CIL_LEVEL; |
| } else if (kind == CIL_KEY_LEVELRANGE) { |
| param->flavor = CIL_LEVELRANGE; |
| } else if (kind == CIL_KEY_CLASS) { |
| param->flavor = CIL_CLASS; |
| } else if (kind == CIL_KEY_IPADDR) { |
| param->flavor = CIL_IPADDR; |
| } else if (kind == CIL_KEY_MAP_CLASS) { |
| param->flavor = CIL_MAP_CLASS; |
| } else if (kind == CIL_KEY_CLASSPERMISSION) { |
| param->flavor = CIL_CLASSPERMISSION; |
| } else if (kind == CIL_KEY_BOOL) { |
| param->flavor = CIL_BOOL; |
| } else if (kind == CIL_KEY_STRING) { |
| param->flavor = CIL_NAME; |
| } else if (kind == CIL_KEY_NAME) { |
| param->flavor = CIL_NAME; |
| } else { |
| cil_log(CIL_ERR, "The kind %s is not allowed as a parameter\n",kind); |
| cil_destroy_param(param); |
| goto exit; |
| } |
| |
| param->str = current_item->cl_head->next->data; |
| |
| rc = cil_verify_name(db, param->str, param->flavor); |
| if (rc != SEPOL_OK) { |
| cil_destroy_param(param); |
| goto exit; |
| } |
| |
| //walk current list and check for duplicate parameters |
| cil_list_for_each(curr_param, macro->params) { |
| if (param->str == ((struct cil_param*)curr_param->data)->str) { |
| cil_log(CIL_ERR, "Duplicate parameter\n"); |
| cil_destroy_param(param); |
| goto exit; |
| } |
| } |
| |
| cil_list_append(macro->params, CIL_PARAM, param); |
| |
| current_item = current_item->next; |
| } |
| |
| /* 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 |
| node containing the macro name is updated to point to the start of the macro content */ |
| macro_content = parse_current->next->next->next; |
| cil_tree_subtree_destroy(parse_current->next->next); |
| parse_current->next->next = macro_content; |
| if (macro_content == NULL) { |
| /* No statements in macro and macro parameter list was last node */ |
| parse_current->parent->cl_tail = parse_current->next; |
| } |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)macro, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration"); |
| cil_destroy_macro(macro); |
| cil_clear_node(ast_node); |
| return SEPOL_ERR; |
| } |
| |
| void cil_destroy_macro(struct cil_macro *macro) |
| { |
| if (macro == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(¯o->datum); |
| cil_symtab_array_destroy(macro->symtab); |
| |
| if (macro->params != NULL) { |
| cil_list_destroy(¯o->params, 1); |
| } |
| |
| free(macro); |
| } |
| |
| int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_LIST | CIL_SYN_EMPTY_LIST | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_call *call = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_call_init(&call); |
| |
| call->macro_str = parse_current->next->data; |
| |
| if (parse_current->next->next != NULL) { |
| cil_tree_init(&call->args_tree); |
| cil_copy_ast(db, parse_current->next->next, call->args_tree->root); |
| } |
| |
| ast_node->data = call; |
| ast_node->flavor = CIL_CALL; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad macro call"); |
| cil_destroy_call(call); |
| return rc; |
| } |
| |
| void cil_destroy_call(struct cil_call *call) |
| { |
| if (call == NULL) { |
| return; |
| } |
| |
| call->macro = NULL; |
| |
| if (call->args_tree != NULL) { |
| cil_tree_destroy(&call->args_tree); |
| } |
| |
| if (call->args != NULL) { |
| cil_list_destroy(&call->args, 1); |
| } |
| |
| free(call); |
| } |
| |
| void cil_destroy_args(struct cil_args *args) |
| { |
| if (args == NULL) { |
| return; |
| } |
| |
| if (args->arg_str != NULL) { |
| args->arg_str = NULL; |
| } else if (args->arg != NULL) { |
| struct cil_tree_node *node = args->arg->nodes->head->data; |
| switch (args->flavor) { |
| case CIL_NAME: |
| break; |
| case CIL_CATSET: |
| cil_destroy_catset((struct cil_catset *)args->arg); |
| free(node); |
| break; |
| case CIL_LEVEL: |
| cil_destroy_level((struct cil_level *)args->arg); |
| free(node); |
| break; |
| case CIL_LEVELRANGE: |
| cil_destroy_levelrange((struct cil_levelrange *)args->arg); |
| free(node); |
| break; |
| case CIL_IPADDR: |
| cil_destroy_ipaddr((struct cil_ipaddr *)args->arg); |
| free(node); |
| break; |
| case CIL_CLASSPERMISSION: |
| cil_destroy_classpermission((struct cil_classpermission *)args->arg); |
| free(node); |
| break; |
| default: |
| cil_log(CIL_ERR, "Destroying arg with the unexpected flavor=%d\n",args->flavor); |
| break; |
| } |
| } |
| |
| args->param_str = NULL; |
| args->arg = NULL; |
| |
| free(args); |
| } |
| |
| int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_N_LISTS | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_optional *optional = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_optional_init(&optional); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)optional, (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL); |
| if (rc != SEPOL_OK) { |
| if (rc == SEPOL_EEXIST) { |
| cil_destroy_optional(optional); |
| optional = NULL; |
| } else { |
| goto exit; |
| } |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad optional"); |
| cil_destroy_optional(optional); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_optional(struct cil_optional *optional) |
| { |
| if (optional == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&optional->datum); |
| free(optional); |
| } |
| |
| int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_policycap *polcap = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_policycap_init(&polcap); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)polcap, (hashtab_key_t)key, CIL_SYM_POLICYCAPS, CIL_POLICYCAP); |
| if (rc != SEPOL_OK) |
| goto exit; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement"); |
| cil_destroy_policycap(polcap); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_policycap(struct cil_policycap *polcap) |
| { |
| if (polcap == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&polcap->datum); |
| free(polcap); |
| } |
| |
| int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| char *key = NULL; |
| struct cil_ipaddr *ipaddr = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_ipaddr_init(&ipaddr); |
| |
| key = parse_current->next->data; |
| |
| rc = cil_fill_ipaddr(parse_current->next->next, ipaddr); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum*)ipaddr, (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement"); |
| cil_destroy_ipaddr(ipaddr); |
| cil_clear_node(ast_node); |
| return rc; |
| } |
| |
| void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr) |
| { |
| if (ipaddr == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&ipaddr->datum); |
| free(ipaddr); |
| } |
| |
| int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer, int base) |
| { |
| int rc = SEPOL_ERR; |
| |
| if (int_node == NULL || int_node->data == NULL || integer == NULL) { |
| goto exit; |
| } |
| |
| rc = cil_string_to_uint32(int_node->data, integer, base); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Failed to fill 32-bit integer\n"); |
| return rc; |
| } |
| |
| int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer, int base) |
| { |
| int rc = SEPOL_ERR; |
| |
| if (int_node == NULL || int_node->data == NULL || integer == NULL) { |
| goto exit; |
| } |
| |
| rc = cil_string_to_uint64(int_node->data, integer, base); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Failed to fill 64-bit integer\n"); |
| return rc; |
| } |
| |
| int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr) |
| { |
| int rc = SEPOL_ERR; |
| |
| if (addr_node == NULL || addr_node->data == NULL || addr == NULL) { |
| goto exit; |
| } |
| |
| if (strchr(addr_node->data, ':') != NULL) { |
| addr->family = AF_INET6; |
| } else { |
| addr->family = AF_INET; |
| } |
| |
| rc = inet_pton(addr->family, addr_node->data, &addr->ip); |
| if (rc != 1) { |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Bad ip address or netmask: %s\n", (addr_node && addr_node->data) ? (const char *)addr_node->data : "n/a"); |
| return rc; |
| } |
| |
| int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| if (curr == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(curr, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| level->sens_str = curr->data; |
| if (curr->next != NULL) { |
| rc = cil_fill_cats(curr->next, &level->cats); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Bad level\n"); |
| return rc; |
| } |
| |
| int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats) |
| { |
| int rc = SEPOL_ERR; |
| |
| cil_cats_init(cats); |
| |
| rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr); |
| if (rc != SEPOL_OK) { |
| cil_destroy_cats(*cats); |
| *cats = NULL; |
| } |
| |
| return rc; |
| } |
| |
| void cil_destroy_cats(struct cil_cats *cats) |
| { |
| if (cats == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&cats->str_expr, CIL_TRUE); |
| |
| cil_list_destroy(&cats->datum_expr, CIL_FALSE); |
| |
| free(cats); |
| } |
| int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) |
| { |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_bounds *bounds = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (db == NULL || parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_bounds_init(&bounds); |
| |
| bounds->parent_str = parse_current->next->data; |
| bounds->child_str = parse_current->next->next->data; |
| |
| ast_node->data = bounds; |
| |
| switch (flavor) { |
| case CIL_USER: |
| ast_node->flavor = CIL_USERBOUNDS; |
| break; |
| case CIL_ROLE: |
| ast_node->flavor = CIL_ROLEBOUNDS; |
| break; |
| case CIL_TYPE: |
| ast_node->flavor = CIL_TYPEBOUNDS; |
| break; |
| default: |
| break; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration"); |
| cil_destroy_bounds(bounds); |
| return rc; |
| } |
| |
| void cil_destroy_bounds(struct cil_bounds *bounds) |
| { |
| if (bounds == NULL) { |
| return; |
| } |
| |
| free(bounds); |
| } |
| |
| int cil_gen_default(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node, enum cil_flavor flavor) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_default *def = NULL; |
| char *object; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_default_init(&def); |
| |
| def->flavor = flavor; |
| |
| if (parse_current->next->cl_head == NULL) { |
| cil_list_init(&def->class_strs, CIL_CLASS); |
| cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data); |
| } else { |
| rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| object = parse_current->next->next->data; |
| if (object == CIL_KEY_SOURCE) { |
| def->object = CIL_DEFAULT_SOURCE; |
| } else if (object == CIL_KEY_TARGET) { |
| def->object = CIL_DEFAULT_TARGET; |
| } else { |
| cil_log(CIL_ERR,"Expected either 'source' or 'target'\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| ast_node->data = def; |
| ast_node->flavor = flavor; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration", cil_node_to_string(parse_current)); |
| cil_destroy_default(def); |
| return rc; |
| } |
| |
| void cil_destroy_default(struct cil_default *def) |
| { |
| if (def == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&def->class_strs, CIL_TRUE); |
| |
| cil_list_destroy(&def->class_datums, CIL_FALSE); |
| |
| free(def); |
| } |
| |
| int cil_gen_defaultrange(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_defaultrange *def = NULL; |
| char *object; |
| char *range; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_defaultrange_init(&def); |
| |
| if (parse_current->next->cl_head == NULL) { |
| cil_list_init(&def->class_strs, CIL_CLASS); |
| cil_list_append(def->class_strs, CIL_STRING, parse_current->next->data); |
| } else { |
| rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS, &def->class_strs); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| object = parse_current->next->next->data; |
| if (object == CIL_KEY_SOURCE) { |
| if (!parse_current->next->next->next) { |
| cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| range = parse_current->next->next->next->data; |
| if (range == CIL_KEY_LOW) { |
| def->object_range = CIL_DEFAULT_SOURCE_LOW; |
| } else if (range == CIL_KEY_HIGH) { |
| def->object_range = CIL_DEFAULT_SOURCE_HIGH; |
| } else if (range == CIL_KEY_LOW_HIGH) { |
| def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH; |
| } else { |
| cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } else if (object == CIL_KEY_TARGET) { |
| if (!parse_current->next->next->next) { |
| cil_log(CIL_ERR, "Missing 'low', 'high', or 'low-high'\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| range = parse_current->next->next->next->data; |
| if (range == CIL_KEY_LOW) { |
| def->object_range = CIL_DEFAULT_TARGET_LOW; |
| } else if (range == CIL_KEY_HIGH) { |
| def->object_range = CIL_DEFAULT_TARGET_HIGH; |
| } else if (range == CIL_KEY_LOW_HIGH) { |
| def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH; |
| } else { |
| cil_log(CIL_ERR,"Expected 'low', 'high', or 'low-high'\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } else if (object == CIL_KEY_GLBLUB) { |
| def->object_range = CIL_DEFAULT_GLBLUB; |
| } else { |
| cil_log(CIL_ERR,"Expected \'source\', \'target\', or \'glblub\'\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| ast_node->data = def; |
| ast_node->flavor = CIL_DEFAULTRANGE; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration"); |
| cil_destroy_defaultrange(def); |
| return rc; |
| } |
| |
| void cil_destroy_defaultrange(struct cil_defaultrange *def) |
| { |
| if (def == NULL) { |
| return; |
| } |
| |
| cil_list_destroy(&def->class_strs, CIL_TRUE); |
| |
| cil_list_destroy(&def->class_datums, CIL_FALSE); |
| |
| free(def); |
| } |
| |
| int cil_gen_handleunknown(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_handleunknown *unknown = NULL; |
| char *unknown_key; |
| |
| if (parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_handleunknown_init(&unknown); |
| |
| unknown_key = parse_current->next->data; |
| if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) { |
| unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN; |
| } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) { |
| unknown->handle_unknown = SEPOL_DENY_UNKNOWN; |
| } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) { |
| unknown->handle_unknown = SEPOL_REJECT_UNKNOWN; |
| } else { |
| cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n", CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY, CIL_KEY_HANDLEUNKNOWN_REJECT); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| ast_node->data = unknown; |
| ast_node->flavor = CIL_HANDLEUNKNOWN; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown"); |
| cil_destroy_handleunknown(unknown); |
| return rc; |
| } |
| |
| void cil_destroy_handleunknown(struct cil_handleunknown *unk) |
| { |
| free(unk); |
| } |
| |
| int cil_gen_mls(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_mls *mls = NULL; |
| |
| if (parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_mls_init(&mls); |
| |
| if (parse_current->next->data == CIL_KEY_CONDTRUE) { |
| mls->value = CIL_TRUE; |
| } else if (parse_current->next->data == CIL_KEY_CONDFALSE) { |
| mls->value = CIL_FALSE; |
| } else { |
| cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| ast_node->data = mls; |
| ast_node->flavor = CIL_MLS; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad mls"); |
| cil_destroy_mls(mls); |
| return rc; |
| } |
| |
| void cil_destroy_mls(struct cil_mls *mls) |
| { |
| free(mls); |
| } |
| |
| int cil_gen_src_info(struct cil_tree_node *parse_current, struct cil_tree_node *ast_node) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_STRING, |
| CIL_SYN_N_LISTS | CIL_SYN_END, |
| CIL_SYN_END |
| }; |
| size_t syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_src_info *info = NULL; |
| |
| if (parse_current == NULL || ast_node == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_src_info_init(&info); |
| |
| info->kind = parse_current->next->data; |
| if (info->kind != CIL_KEY_SRC_CIL && info->kind != CIL_KEY_SRC_HLL_LMS && info->kind != CIL_KEY_SRC_HLL_LMX) { |
| cil_log(CIL_ERR, "Invalid src info kind\n"); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| |
| rc = cil_string_to_uint32(parse_current->next->next->data, &info->hll_line, 10); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| info->path = parse_current->next->next->next->data; |
| |
| ast_node->data = info; |
| ast_node->flavor = CIL_SRC_INFO; |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_tree_log(parse_current, CIL_ERR, "Bad src info"); |
| cil_destroy_src_info(info); |
| return rc; |
| } |
| |
| void cil_destroy_src_info(struct cil_src_info *info) |
| { |
| free(info); |
| } |
| |
| static int check_for_illegal_statement(struct cil_tree_node *parse_current, struct cil_args_build *args) |
| { |
| if (args->tunif != NULL) { |
| if (parse_current->data == CIL_KEY_TUNABLE) { |
| cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif", (char *)parse_current->data); |
| return SEPOL_ERR; |
| } |
| } |
| |
| if (args->in != NULL) { |
| struct cil_in *in_block = args->in->data; |
| if (parse_current->data == CIL_KEY_TUNABLE || |
| parse_current->data == CIL_KEY_IN) { |
| cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in in-statement", (char *)parse_current->data); |
| return SEPOL_ERR; |
| } |
| if (in_block->is_after == CIL_TRUE) { |
| if (parse_current->data == CIL_KEY_BLOCKINHERIT || |
| parse_current->data == CIL_KEY_BLOCKABSTRACT) { |
| cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in an after in-statement", (char *)parse_current->data); |
| return SEPOL_ERR; |
| } |
| } |
| } |
| |
| if (args->macro != NULL) { |
| if (parse_current->data == CIL_KEY_TUNABLE || |
| parse_current->data == CIL_KEY_IN || |
| parse_current->data == CIL_KEY_BLOCK || |
| parse_current->data == CIL_KEY_BLOCKINHERIT || |
| parse_current->data == CIL_KEY_BLOCKABSTRACT || |
| parse_current->data == CIL_KEY_MACRO) { |
| cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in macro", (char *)parse_current->data); |
| return SEPOL_ERR; |
| } |
| } |
| |
| if (args->optional != NULL) { |
| if (parse_current->data == CIL_KEY_TUNABLE || |
| parse_current->data == CIL_KEY_IN || |
| parse_current->data == CIL_KEY_BLOCK || |
| parse_current->data == CIL_KEY_BLOCKABSTRACT || |
| parse_current->data == CIL_KEY_MACRO) { |
| cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in optional", (char *)parse_current->data); |
| return SEPOL_ERR; |
| } |
| } |
| |
| if (args->boolif != NULL) { |
| if (parse_current->data != CIL_KEY_TUNABLEIF && |
| parse_current->data != CIL_KEY_CALL && |
| parse_current->data != CIL_KEY_CONDTRUE && |
| parse_current->data != CIL_KEY_CONDFALSE && |
| parse_current->data != CIL_KEY_ALLOW && |
| parse_current->data != CIL_KEY_DONTAUDIT && |
| parse_current->data != CIL_KEY_AUDITALLOW && |
| parse_current->data != CIL_KEY_TYPETRANSITION && |
| parse_current->data != CIL_KEY_TYPECHANGE && |
| parse_current->data != CIL_KEY_TYPEMEMBER) { |
| if (((struct cil_booleanif*)args->boolif->data)->preserved_tunable) { |
| cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in tunableif being treated as a booleanif", (char *)parse_current->data); |
| } else { |
| cil_tree_log(parse_current, CIL_ERR, "%s is not allowed in booleanif", (char *)parse_current->data); |
| } |
| return SEPOL_ERR; |
| } |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| static struct cil_tree_node * parse_statement(struct cil_db *db, struct cil_tree_node *parse_current, struct cil_tree_node *ast_parent) |
| { |
| struct cil_tree_node *new_ast_node = NULL; |
| int rc = SEPOL_ERR; |
| |
| cil_tree_node_init(&new_ast_node); |
| new_ast_node->parent = ast_parent; |
| new_ast_node->line = parse_current->line; |
| new_ast_node->hll_offset = parse_current->hll_offset; |
| |
| if (parse_current->data == CIL_KEY_BLOCK) { |
| rc = cil_gen_block(db, parse_current, new_ast_node, 0); |
| } else if (parse_current->data == CIL_KEY_BLOCKINHERIT) { |
| rc = cil_gen_blockinherit(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) { |
| rc = cil_gen_blockabstract(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_IN) { |
| rc = cil_gen_in(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CLASS) { |
| rc = cil_gen_class(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CLASSORDER) { |
| rc = cil_gen_classorder(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_MAP_CLASS) { |
| rc = cil_gen_map_class(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CLASSMAPPING) { |
| rc = cil_gen_classmapping(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CLASSPERMISSION) { |
| rc = cil_gen_classpermission(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) { |
| rc = cil_gen_classpermissionset(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_COMMON) { |
| rc = cil_gen_common(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CLASSCOMMON) { |
| rc = cil_gen_classcommon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_SID) { |
| rc = cil_gen_sid(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_SIDCONTEXT) { |
| rc = cil_gen_sidcontext(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_SIDORDER) { |
| rc = cil_gen_sidorder(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_USER) { |
| rc = cil_gen_user(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) { |
| rc = cil_gen_userattribute(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) { |
| rc = cil_gen_userattributeset(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_USERLEVEL) { |
| rc = cil_gen_userlevel(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_USERRANGE) { |
| rc = cil_gen_userrange(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_USERBOUNDS) { |
| rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER); |
| } else if (parse_current->data == CIL_KEY_USERPREFIX) { |
| rc = cil_gen_userprefix(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_SELINUXUSER) { |
| rc = cil_gen_selinuxuser(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) { |
| rc = cil_gen_selinuxuserdefault(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_TYPE) { |
| rc = cil_gen_type(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) { |
| rc = cil_gen_typeattribute(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) { |
| rc = cil_gen_typeattributeset(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) { |
| rc = cil_gen_expandtypeattribute(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_TYPEALIAS) { |
| rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_TYPEALIAS); |
| } else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) { |
| rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_TYPEALIASACTUAL); |
| } else if (parse_current->data == CIL_KEY_TYPEBOUNDS) { |
| rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE); |
| } else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) { |
| rc = cil_gen_typepermissive(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_RANGETRANSITION) { |
| rc = cil_gen_rangetransition(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_ROLE) { |
| rc = cil_gen_role(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_USERROLE) { |
| rc = cil_gen_userrole(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_ROLETYPE) { |
| rc = cil_gen_roletype(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_ROLETRANSITION) { |
| rc = cil_gen_roletransition(parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_ROLEALLOW) { |
| rc = cil_gen_roleallow(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) { |
| rc = cil_gen_roleattribute(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) { |
| rc = cil_gen_roleattributeset(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_ROLEBOUNDS) { |
| rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE); |
| } else if (parse_current->data == CIL_KEY_BOOL) { |
| rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE); |
| } else if (parse_current->data == CIL_KEY_BOOLEANIF) { |
| rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE); |
| } else if(parse_current->data == CIL_KEY_TUNABLE) { |
| if (db->preserve_tunables) { |
| rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_TRUE); |
| } else { |
| rc = cil_gen_tunable(db, parse_current, new_ast_node); |
| } |
| } else if (parse_current->data == CIL_KEY_TUNABLEIF) { |
| if (db->preserve_tunables) { |
| rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_TRUE); |
| } else { |
| rc = cil_gen_tunif(db, parse_current, new_ast_node); |
| } |
| } else if (parse_current->data == CIL_KEY_CONDTRUE) { |
| rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDTRUE); |
| } else if (parse_current->data == CIL_KEY_CONDFALSE) { |
| rc = cil_gen_condblock(db, parse_current, new_ast_node, CIL_CONDFALSE); |
| } else if (parse_current->data == CIL_KEY_ALLOW) { |
| rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_ALLOWED); |
| } else if (parse_current->data == CIL_KEY_AUDITALLOW) { |
| rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW); |
| } else if (parse_current->data == CIL_KEY_DONTAUDIT) { |
| rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT); |
| } else if (parse_current->data == CIL_KEY_NEVERALLOW) { |
| rc = cil_gen_avrule(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW); |
| } else if (parse_current->data == CIL_KEY_ALLOWX) { |
| rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_ALLOWED); |
| } else if (parse_current->data == CIL_KEY_AUDITALLOWX) { |
| rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_AUDITALLOW); |
| } else if (parse_current->data == CIL_KEY_DONTAUDITX) { |
| rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_DONTAUDIT); |
| } else if (parse_current->data == CIL_KEY_NEVERALLOWX) { |
| rc = cil_gen_avrulex(parse_current, new_ast_node, CIL_AVRULE_NEVERALLOW); |
| } else if (parse_current->data == CIL_KEY_PERMISSIONX) { |
| rc = cil_gen_permissionx(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_TYPETRANSITION) { |
| rc = cil_gen_typetransition(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_TYPECHANGE) { |
| rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_CHANGE); |
| } else if (parse_current->data == CIL_KEY_TYPEMEMBER) { |
| rc = cil_gen_type_rule(parse_current, new_ast_node, CIL_TYPE_MEMBER); |
| } else if (parse_current->data == CIL_KEY_SENSITIVITY) { |
| rc = cil_gen_sensitivity(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_SENSALIAS) { |
| rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_SENSALIAS); |
| } else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) { |
| rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_SENSALIASACTUAL); |
| } else if (parse_current->data == CIL_KEY_CATEGORY) { |
| rc = cil_gen_category(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CATALIAS) { |
| rc = cil_gen_alias(db, parse_current, new_ast_node, CIL_CATALIAS); |
| } else if (parse_current->data == CIL_KEY_CATALIASACTUAL) { |
| rc = cil_gen_aliasactual(db, parse_current, new_ast_node, CIL_CATALIASACTUAL); |
| } else if (parse_current->data == CIL_KEY_CATSET) { |
| rc = cil_gen_catset(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CATORDER) { |
| rc = cil_gen_catorder(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) { |
| rc = cil_gen_sensitivityorder(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_SENSCAT) { |
| rc = cil_gen_senscat(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_LEVEL) { |
| rc = cil_gen_level(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_LEVELRANGE) { |
| rc = cil_gen_levelrange(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CONSTRAIN) { |
| rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_CONSTRAIN); |
| } else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) { |
| rc = cil_gen_constrain(db, parse_current, new_ast_node, CIL_MLSCONSTRAIN); |
| } else if (parse_current->data == CIL_KEY_VALIDATETRANS) { |
| rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_VALIDATETRANS); |
| } else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) { |
| rc = cil_gen_validatetrans(db, parse_current, new_ast_node, CIL_MLSVALIDATETRANS); |
| } else if (parse_current->data == CIL_KEY_CONTEXT) { |
| rc = cil_gen_context(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_FILECON) { |
| rc = cil_gen_filecon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_IBPKEYCON) { |
| rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_IBENDPORTCON) { |
| rc = cil_gen_ibendportcon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_PORTCON) { |
| rc = cil_gen_portcon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_NODECON) { |
| rc = cil_gen_nodecon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_GENFSCON) { |
| rc = cil_gen_genfscon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_NETIFCON) { |
| rc = cil_gen_netifcon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_PIRQCON) { |
| rc = cil_gen_pirqcon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_IOMEMCON) { |
| rc = cil_gen_iomemcon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_IOPORTCON) { |
| rc = cil_gen_ioportcon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_PCIDEVICECON) { |
| rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_DEVICETREECON) { |
| rc = cil_gen_devicetreecon(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_FSUSE) { |
| rc = cil_gen_fsuse(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_MACRO) { |
| rc = cil_gen_macro(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_CALL) { |
| rc = cil_gen_call(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_POLICYCAP) { |
| rc = cil_gen_policycap(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_OPTIONAL) { |
| rc = cil_gen_optional(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_IPADDR) { |
| rc = cil_gen_ipaddr(db, parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_DEFAULTUSER) { |
| rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTUSER); |
| } else if (parse_current->data == CIL_KEY_DEFAULTROLE) { |
| rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTROLE); |
| } else if (parse_current->data == CIL_KEY_DEFAULTTYPE) { |
| rc = cil_gen_default(parse_current, new_ast_node, CIL_DEFAULTTYPE); |
| } else if (parse_current->data == CIL_KEY_DEFAULTRANGE) { |
| rc = cil_gen_defaultrange(parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) { |
| rc = cil_gen_handleunknown(parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_MLS) { |
| rc = cil_gen_mls(parse_current, new_ast_node); |
| } else if (parse_current->data == CIL_KEY_SRC_INFO) { |
| rc = cil_gen_src_info(parse_current, new_ast_node); |
| } else { |
| cil_log(CIL_ERR, "Error: Unknown keyword %s\n", (char *)parse_current->data); |
| rc = SEPOL_ERR; |
| } |
| |
| if (rc == SEPOL_OK) { |
| if (ast_parent->cl_head == NULL) { |
| ast_parent->cl_head = new_ast_node; |
| } else { |
| ast_parent->cl_tail->next = new_ast_node; |
| } |
| ast_parent->cl_tail = new_ast_node; |
| } else { |
| cil_tree_node_destroy(&new_ast_node); |
| new_ast_node = NULL; |
| } |
| |
| return new_ast_node; |
| } |
| |
| static int __cil_build_ast_node_helper(struct cil_tree_node *parse_current, uint32_t *finished, void *extra_args) |
| { |
| struct cil_args_build *args = extra_args; |
| struct cil_tree_node *new_ast_node = NULL; |
| int rc = SEPOL_ERR; |
| |
| if (parse_current->parent->cl_head != parse_current) { |
| /* ignore anything that isn't following a parenthesis */ |
| return SEPOL_OK; |
| } else if (parse_current->data == NULL) { |
| /* the only time parenthesis can immediately following parenthesis is if |
| * the parent is the root node */ |
| if (parse_current->parent->parent == NULL) { |
| return SEPOL_OK; |
| } else { |
| cil_tree_log(parse_current, CIL_ERR, "Keyword expected after open parenthesis"); |
| return SEPOL_ERR; |
| } |
| } |
| |
| rc = check_for_illegal_statement(parse_current, args); |
| if (rc != SEPOL_OK) { |
| return SEPOL_ERR; |
| } |
| |
| new_ast_node = parse_statement(args->db, parse_current, args->ast); |
| if (!new_ast_node) { |
| return SEPOL_ERR; |
| } |
| |
| args->ast = new_ast_node; |
| |
| if (parse_current->data != CIL_KEY_BLOCK && |
| parse_current->data != CIL_KEY_IN && |
| parse_current->data != CIL_KEY_TUNABLEIF && |
| parse_current->data != CIL_KEY_BOOLEANIF && |
| parse_current->data != CIL_KEY_CONDTRUE && |
| parse_current->data != CIL_KEY_CONDFALSE && |
| parse_current->data != CIL_KEY_MACRO && |
| parse_current->data != CIL_KEY_OPTIONAL && |
| parse_current->data != CIL_KEY_SRC_INFO) { |
| /* Skip anything that does not contain a list of policy statements */ |
| *finished = CIL_TREE_SKIP_NEXT; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| static int __cil_build_ast_first_child_helper(__attribute__((unused)) struct cil_tree_node *parse_current, void *extra_args) |
| { |
| struct cil_args_build *args = extra_args; |
| struct cil_tree_node *ast = args->ast; |
| |
| if (ast->flavor == CIL_TUNABLEIF) { |
| args->tunif = ast; |
| } else if (ast->flavor == CIL_IN) { |
| args->in = ast; |
| } else if (ast->flavor == CIL_MACRO) { |
| args->macro = ast; |
| } else if (ast->flavor == CIL_OPTIONAL) { |
| args->optional = ast; |
| } else if (ast->flavor == CIL_BOOLEANIF) { |
| args->boolif = ast; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| static int __cil_build_ast_last_child_helper(struct cil_tree_node *parse_current, void *extra_args) |
| { |
| struct cil_args_build *args = extra_args; |
| struct cil_tree_node *ast = args->ast; |
| |
| if (ast->flavor == CIL_ROOT) { |
| return SEPOL_OK; |
| } |
| |
| args->ast = ast->parent; |
| |
| if (ast->flavor == CIL_TUNABLEIF) { |
| args->tunif = NULL; |
| } |
| |
| if (ast->flavor == CIL_IN) { |
| args->in = NULL; |
| } |
| |
| if (ast->flavor == CIL_MACRO) { |
| args->macro = NULL; |
| } |
| |
| if (ast->flavor == CIL_OPTIONAL) { |
| struct cil_tree_node *n = ast->parent; |
| args->optional = NULL; |
| /* Optionals can be nested */ |
| while (n && n->flavor != CIL_ROOT) { |
| if (n->flavor == CIL_OPTIONAL) { |
| args->optional = n; |
| break; |
| } |
| n = n->parent; |
| } |
| } |
| |
| if (ast->flavor == CIL_BOOLEANIF) { |
| args->boolif = NULL; |
| } |
| |
| // At this point we no longer have any need for parse_current or any of its |
| // siblings; they have all been converted to the appropriate AST node. The |
| // full parse tree will get deleted elsewhere, but in an attempt to |
| // minimize memory usage (of which the parse tree uses a lot), start |
| // deleting the parts we don't need now. |
| cil_tree_children_destroy(parse_current->parent); |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree, struct cil_tree_node *ast) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_args_build extra_args; |
| |
| if (db == NULL || parse_tree == NULL || ast == NULL) { |
| goto exit; |
| } |
| |
| extra_args.ast = ast; |
| extra_args.db = db; |
| extra_args.tunif = NULL; |
| extra_args.in = NULL; |
| extra_args.macro = NULL; |
| extra_args.optional = NULL; |
| extra_args.boolif = NULL; |
| |
| rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper, __cil_build_ast_first_child_helper, __cil_build_ast_last_child_helper, &extra_args); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| return rc; |
| } |