| /* |
| * 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 *macro; |
| struct cil_tree_node *boolif; |
| struct cil_tree_node *tunif; |
| struct cil_tree_node *in; |
| }; |
| |
| 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 |
| }; |
| int 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; |
| } |
| |
| int cil_gen_node(__attribute__((unused)) struct cil_db *db, struct cil_tree_node *ast_node, struct cil_symtab_datum *datum, hashtab_key_t key, enum cil_sym_index sflavor, enum cil_flavor nflavor) |
| { |
| int rc = SEPOL_ERR; |
| symtab_t *symtab = NULL; |
| |
| rc = __cil_verify_name((const char*)key); |
| 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; |
| |
| if (symtab != NULL) { |
| rc = cil_symtab_insert(symtab, (hashtab_key_t)key, datum, ast_node); |
| if (rc == SEPOL_EEXIST) { |
| cil_log(CIL_ERR, "Re-declaration of %s %s\n", |
| cil_node_to_string(ast_node), key); |
| if (cil_symtab_get_datum(symtab, key, &datum) == SEPOL_OK) { |
| if (sflavor == CIL_SYM_BLOCKS) { |
| struct cil_tree_node *node = datum->nodes->head->data; |
| cil_tree_log(node, CIL_ERR, "Previous declaration"); |
| } |
| } |
| goto exit; |
| } |
| } |
| |
| if (ast_node->flavor >= CIL_MIN_DECLARATIVE && ast_node->parent->flavor == CIL_MACRO) { |
| struct cil_list_item *item; |
| struct cil_list *param_list = ((struct cil_macro*)ast_node->parent->data)->params; |
| if (param_list != NULL) { |
| cil_list_for_each(item, param_list) { |
| struct cil_param *param = item->data; |
| if (param->flavor == ast_node->flavor) { |
| if (param->str == key) { |
| cil_log(CIL_ERR, "%s %s shadows a macro parameter in macro declaration\n", cil_node_to_string(ast_node), key); |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| } |
| } |
| } |
| } |
| |
| return SEPOL_OK; |
| |
| exit: |
| cil_log(CIL_ERR, "Failed to create node\n"); |
| return rc; |
| } |
| |
| 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 |
| }; |
| int 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; |
| } |
| |
| 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) |
| { |
| if (block == NULL) { |
| return; |
| } |
| |
| cil_symtab_datum_destroy(&block->datum); |
| cil_symtab_array_destroy(block->symtab); |
| 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 |
| }; |
| int 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; |
| } |
| |
| 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; |
| } |
| |
| 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 |
| }; |
| int 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; |
| } |
| |
| 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_N_LISTS, |
| CIL_SYN_END |
| }; |
| int 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; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| |
| cil_in_init(&in); |
| |
| 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 |
| }; |
| int 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; |
| } |
| } |
| |
| 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 |
| }; |
| int 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; |
| |
| 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_line = current_perm->hll_line; |
| |
| rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms); |
| if (rc != SEPOL_OK) { |
| 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"); |
| 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 |
| }; |
| int 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 |
| }; |
| int 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; |
| enum cil_syntax syntax[] = { |
| CIL_SYN_STRING | CIL_SYN_LIST, |
| }; |
| int syntax_len = sizeof(syntax)/sizeof(*syntax); |
| |
| if (parse_current == NULL || cp_list == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_verify_syntax(parse_current, syntax, syntax_len); |
| if (rc != SEPOL_OK) { |
| 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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; |
| } |
| |
| 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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; |
| } |
| |
| if (parse_current->next->data == CIL_KEY_SELF) { |
| cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); |
| rc = SEPOL_ERR; |
| 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 |
| }; |
| int 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 |
| }; |
| int 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); |
| } |
| |
| 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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 |
| }; |
| int 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; |
| } |
| |
| if (parse_current->next->data == CIL_KEY_SELF) { |
| cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); |
| rc = SEPOL_ERR; |
| 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) { |
| 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 |
| }; |
| int 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; |
| } |
| |
| if (parse_current->next->data == CIL_KEY_SELF) { |
| cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); |
| rc = SEPOL_ERR; |
| 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) { |
| 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 |
| }; |
| int 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 |
| }; |
| int 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, int *depth); |
| |
| static int __cil_fill_expr_helper(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list *expr, int *depth) |
| { |
| int rc = SEPOL_ERR; |
| enum cil_flavor op; |
| |
| if (flavor == CIL_BOOL && *depth > COND_EXPR_MAXDEPTH) { |
| cil_log(CIL_ERR, "Max depth of %d exceeded for boolean expression\n", COND_EXPR_MAXDEPTH); |
| goto exit; |
| } |
| |
| 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; |
| } |
| |
| if (op == CIL_NONE || op == CIL_ALL) { |
| (*depth)++; |
| } |
| |
| for (;current != NULL; current = current->next) { |
| rc = __cil_fill_expr(current, flavor, expr, depth); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| } |
| |
| (*depth)--; |
| |
| 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 *depth) |
| { |
| 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, depth); |
| if (rc != SEPOL_OK) { |
| 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; |
| int depth = 0; |
| |
| cil_list_init(expr, flavor); |
| |
| if (current->cl_head == NULL) { |
| rc = __cil_fill_expr(current, flavor, *expr, &depth); |
| } else { |
| rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr, &depth); |
| } |
| |
| 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; |
| cil_fill_list(current->next->next->cl_head, leaf_expr_flavor, &sub_list); |
| 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 *depth) |
| { |
| 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; |
| } |
| |
| if (*depth > CEXPR_MAXDEPTH) { |
| cil_log(CIL_ERR, "Max depth of %d exceeded for constraint expression\n", CEXPR_MAXDEPTH); |
| rc = SEPOL_ERR; |
| 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: |
| (*depth)++; |
| 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, depth); |
| 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, depth); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| rc = __cil_fill_constraint_expr(current->next->next->cl_head, flavor, &rexpr, depth); |
| 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); |
| cil_list_append(*expr, CIL_LIST, rexpr); |
| break; |
| } |
| |
| (*depth)--; |
| |
| return SEPOL_OK; |
| exit: |
| |
| return rc; |
| } |
| |
| int cil_gen_constraint_expr(struct cil_tree_node *current, enum cil_flavor flavor, struct cil_list **expr) |
| { |
| int rc = SEPOL_ERR; |
| int depth = 0; |
| |
| if (current->cl_head == NULL) { |
| goto exit; |
| } |
| |
| rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr, &depth); |
| 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 |
| }; |
| int syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_booleanif *bif = NULL; |
| struct cil_tree_node *next = NULL; |
| struct cil_tree_node *cond = 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; |
| } |
| |
| cond = parse_current->next->next; |
| |
| /* Destroying expr tree after stack is created*/ |
| if (cond->cl_head->data != CIL_KEY_CONDTRUE && |
| cond->cl_head->data != CIL_KEY_CONDFALSE) { |
| rc = SEPOL_ERR; |
| cil_log(CIL_ERR, "Conditional neither true nor false\n"); |
| goto exit; |
| } |
| |
| if (cond->next != NULL) { |
| cond = cond->next; |
| if (cond->cl_head->data != CIL_KEY_CONDTRUE && |
| cond->cl_head->data != CIL_KEY_CONDFALSE) { |
| rc = SEPOL_ERR; |
| cil_log(CIL_ERR, "Conditional neither true nor false\n"); |
| goto exit; |
| } |
| } |
| |
| |
| 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 |
| }; |
| int syntax_len = sizeof(syntax)/sizeof(*syntax); |
| struct cil_tunableif *tif = NULL; |
| struct cil_tree_node *next = NULL; |
| struct cil_tree_node *cond = 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; |
| } |
| |
| cond = parse_current->next->next; |
| |
| if (cond->cl_head->data != CIL_KEY_CONDTRUE && |
| cond->cl_head->data != CIL_KEY_CONDFALSE) { |
| rc = SEPOL_ERR; |
| cil_log(CIL_ERR, "Conditional neither true nor false\n"); |
| goto exit; |
| } |
| |
| if (cond->next != NULL) { |
| cond = cond->next; |
| |
| if (cond->cl_head->data != CIL_KEY_CONDTRUE && |
| cond->cl_head->data != CIL_KEY_CONDFALSE) { |
| rc = SEPOL_ERR; |
| cil_log(CIL_ERR, "Conditional neither true nor false\n"); |
| goto exit; |
| } |
| } |
| |
| /* Destroying expr tree after stack is created*/ |
| 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 |
| }; |
| int 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 |
| }; |
| int 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; |
| } |
| |
| if (flavor == CIL_TYPEALIAS && parse_current->next->data == CIL_KEY_SELF) { |
| cil_log(CIL_ERR, "The keyword '%s' is reserved\n", CIL_KEY_SELF); |
| rc = SEPOL_ERR; |
| 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 |
| }; |
| int 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) |
| |