| /* |
| * 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 <stdio.h> |
| #include <stdarg.h> |
| #include <inttypes.h> |
| |
| #include <sepol/policydb/conditional.h> |
| |
| #include "cil_internal.h" |
| #include "cil_flavor.h" |
| #include "cil_log.h" |
| #include "cil_tree.h" |
| #include "cil_list.h" |
| #include "cil_parser.h" |
| #include "cil_strpool.h" |
| |
| void cil_tree_print_perms_list(struct cil_tree_node *current_perm); |
| void cil_tree_print_classperms(struct cil_classperms *cp); |
| void cil_tree_print_level(struct cil_level *level); |
| void cil_tree_print_levelrange(struct cil_levelrange *lvlrange); |
| void cil_tree_print_context(struct cil_context *context); |
| void cil_tree_print_expr_tree(struct cil_tree_node *expr_root); |
| void cil_tree_print_constrain(struct cil_constrain *cons); |
| void cil_tree_print_node(struct cil_tree_node *node); |
| |
| __attribute__((noreturn)) __attribute__((format (printf, 1, 2))) void cil_tree_error(const char* msg, ...) |
| { |
| va_list ap; |
| va_start(ap, msg); |
| cil_vlog(CIL_ERR, msg, ap); |
| va_end(ap); |
| exit(1); |
| } |
| |
| int cil_tree_init(struct cil_tree **tree) |
| { |
| struct cil_tree *new_tree = cil_malloc(sizeof(*new_tree)); |
| |
| cil_tree_node_init(&new_tree->root); |
| |
| *tree = new_tree; |
| |
| return SEPOL_OK; |
| } |
| |
| void cil_tree_destroy(struct cil_tree **tree) |
| { |
| if (tree == NULL || *tree == NULL) { |
| return; |
| } |
| |
| cil_tree_subtree_destroy((*tree)->root); |
| free(*tree); |
| *tree = NULL; |
| } |
| |
| void cil_tree_subtree_destroy(struct cil_tree_node *node) |
| { |
| cil_tree_children_destroy(node); |
| cil_tree_node_destroy(&node); |
| } |
| |
| void cil_tree_children_destroy(struct cil_tree_node *node) |
| { |
| struct cil_tree_node *start_node = node; |
| struct cil_tree_node *next = NULL; |
| |
| if (node == NULL) { |
| return; |
| } |
| |
| if (node->cl_head != NULL) { |
| node = node->cl_head; |
| } |
| |
| while (node != start_node) { |
| if (node->cl_head != NULL){ |
| next = node->cl_head; |
| } else { |
| if (node->next == NULL) { |
| next = node->parent; |
| if (node->parent != NULL) { |
| node->parent->cl_head = NULL; |
| } |
| cil_tree_node_destroy(&node); |
| } else { |
| next = node->next; |
| cil_tree_node_destroy(&node); |
| } |
| } |
| node = next; |
| } |
| } |
| |
| void cil_tree_node_init(struct cil_tree_node **node) |
| { |
| struct cil_tree_node *new_node = cil_malloc(sizeof(*new_node)); |
| new_node->cl_head = NULL; |
| new_node->cl_tail = NULL; |
| new_node->parent = NULL; |
| new_node->data = NULL; |
| new_node->next = NULL; |
| new_node->flavor = CIL_ROOT; |
| new_node->line = 0; |
| new_node->path = NULL; |
| |
| *node = new_node; |
| } |
| |
| void cil_tree_node_destroy(struct cil_tree_node **node) |
| { |
| struct cil_symtab_datum *datum; |
| |
| if (node == NULL || *node == NULL) { |
| return; |
| } |
| |
| if ((*node)->flavor >= CIL_MIN_DECLARATIVE) { |
| datum = (*node)->data; |
| cil_symtab_datum_remove_node(datum, *node); |
| if (datum->nodes == NULL) { |
| cil_destroy_data(&(*node)->data, (*node)->flavor); |
| } |
| } else { |
| cil_destroy_data(&(*node)->data, (*node)->flavor); |
| } |
| free(*node); |
| *node = NULL; |
| } |
| |
| /* Perform depth-first walk of the tree |
| Parameters: |
| start_node: root node to start walking from |
| process_node: function to call when visiting a node |
| Takes parameters: |
| node: node being visited |
| finished: boolean indicating to the tree walker that it should move on from this branch |
| extra_args: additional data |
| first_child: Function to call before entering list of children |
| Takes parameters: |
| node: node of first child |
| extra args: additional data |
| last_child: Function to call when finished with the last child of a node's children |
| extra_args: any additional data to be passed to the helper functions |
| */ |
| |
| int cil_tree_walk_core(struct cil_tree_node *node, |
| int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args), |
| int (*first_child)(struct cil_tree_node *node, void *extra_args), |
| int (*last_child)(struct cil_tree_node *node, void *extra_args), |
| void *extra_args) |
| { |
| int rc = SEPOL_ERR; |
| |
| while (node) { |
| uint32_t finished = CIL_TREE_SKIP_NOTHING; |
| |
| if (process_node != NULL) { |
| rc = (*process_node)(node, &finished, extra_args); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_INFO, "Problem at line %d of %s\n", node->line, node->path); |
| return rc; |
| } |
| } |
| |
| if (finished & CIL_TREE_SKIP_NEXT) { |
| return SEPOL_OK; |
| } |
| |
| if (node->cl_head != NULL && !(finished & CIL_TREE_SKIP_HEAD)) { |
| rc = cil_tree_walk(node, process_node, first_child, last_child, extra_args); |
| if (rc != SEPOL_OK) { |
| return rc; |
| } |
| } |
| |
| node = node->next; |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| int cil_tree_walk(struct cil_tree_node *node, |
| int (*process_node)(struct cil_tree_node *node, uint32_t *finished, void *extra_args), |
| int (*first_child)(struct cil_tree_node *node, void *extra_args), |
| int (*last_child)(struct cil_tree_node *node, void *extra_args), |
| void *extra_args) |
| { |
| int rc = SEPOL_ERR; |
| |
| if (!node || !node->cl_head) { |
| return SEPOL_OK; |
| } |
| |
| if (first_child != NULL) { |
| rc = (*first_child)(node->cl_head, extra_args); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_INFO, "Problem at line %d of %s\n", node->line, node->path); |
| return rc; |
| } |
| } |
| |
| rc = cil_tree_walk_core(node->cl_head, process_node, first_child, last_child, extra_args); |
| if (rc != SEPOL_OK) { |
| return rc; |
| } |
| |
| if (last_child != NULL) { |
| rc = (*last_child)(node->cl_tail, extra_args); |
| if (rc != SEPOL_OK) { |
| cil_log(CIL_INFO, "Problem at line %d of %s\n",node->line, node->path); |
| return rc; |
| } |
| } |
| |
| return SEPOL_OK; |
| } |
| |
| |
| /* Copied from cil_policy.c, but changed to prefix -- Need to refactor */ |
| static int cil_expr_to_string(struct cil_list *expr, char **out) |
| { |
| int rc = SEPOL_ERR; |
| struct cil_list_item *curr; |
| char *stack[COND_EXPR_MAXDEPTH] = {}; |
| int pos = 0; |
| |
| cil_list_for_each(curr, expr) { |
| if (pos > COND_EXPR_MAXDEPTH) { |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| switch (curr->flavor) { |
| case CIL_LIST: |
| rc = cil_expr_to_string(curr->data, &stack[pos]); |
| if (rc != SEPOL_OK) { |
| goto exit; |
| } |
| pos++; |
| break; |
| case CIL_STRING: |
| stack[pos] = curr->data; |
| pos++; |
| break; |
| case CIL_DATUM: |
| stack[pos] = ((struct cil_symtab_datum *)curr->data)->name; |
| pos++; |
| break; |
| case CIL_OP: { |
| int len; |
| char *expr_str; |
| enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data); |
| char *op_str = NULL; |
| |
| if (pos == 0) { |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| switch (op_flavor) { |
| case CIL_AND: |
| op_str = CIL_KEY_AND; |
| break; |
| case CIL_OR: |
| op_str = CIL_KEY_OR; |
| break; |
| case CIL_NOT: |
| op_str = CIL_KEY_NOT; |
| break; |
| case CIL_ALL: |
| op_str = CIL_KEY_ALL; |
| break; |
| case CIL_EQ: |
| op_str = CIL_KEY_EQ; |
| break; |
| case CIL_NEQ: |
| op_str = CIL_KEY_NEQ; |
| break; |
| case CIL_XOR: |
| op_str = CIL_KEY_XOR; |
| break; |
| case CIL_RANGE: |
| op_str = CIL_KEY_RANGE; |
| break; |
| case CIL_CONS_DOM: |
| op_str = CIL_KEY_CONS_DOM; |
| break; |
| case CIL_CONS_DOMBY: |
| op_str = CIL_KEY_CONS_DOMBY; |
| break; |
| case CIL_CONS_INCOMP: |
| op_str = CIL_KEY_CONS_INCOMP; |
| break; |
| default: |
| cil_log(CIL_ERR, "Unknown operator in expression\n"); |
| goto exit; |
| break; |
| } |
| if (op_flavor == CIL_NOT) { |
| len = strlen(stack[pos-1]) + strlen(op_str) + 4; |
| expr_str = cil_malloc(len); |
| snprintf(expr_str, len, "(%s %s)", op_str, stack[pos-1]); |
| free(stack[pos-1]); |
| stack[pos-1] = NULL; |
| pos--; |
| } else { |
| if (pos < 2) { |
| rc = SEPOL_ERR; |
| goto exit; |
| } |
| len = strlen(stack[pos-1]) + strlen(stack[pos-2]) + strlen(op_str) + 5; |
| expr_str = cil_malloc(len); |
| snprintf(expr_str, len, "(%s %s %s)", op_str, stack[pos-1], stack[pos-2]); |
| free(stack[pos-2]); |
| free(stack[pos-1]); |
| stack[pos-2] = NULL; |
| stack[pos-1] = NULL; |
| pos -= 2; |
| } |
| stack[pos] = expr_str; |
| pos++; |
| break; |
| } |
| case CIL_CONS_OPERAND: { |
| enum cil_flavor operand_flavor = *((enum cil_flavor *)curr->data); |
| char *operand_str = NULL; |
| switch (operand_flavor) { |
| case CIL_CONS_U1: |
| operand_str = CIL_KEY_CONS_U1; |
| break; |
| case CIL_CONS_U2: |
| operand_str = CIL_KEY_CONS_U2; |
| break; |
| case CIL_CONS_U3: |
| operand_str = CIL_KEY_CONS_U3; |
| break; |
| case CIL_CONS_T1: |
| operand_str = CIL_KEY_CONS_T1; |
| break; |
| case CIL_CONS_T2: |
| operand_str = CIL_KEY_CONS_T2; |
| break; |
| case CIL_CONS_T3: |
| operand_str = CIL_KEY_CONS_T3; |
| break; |
| case CIL_CONS_R1: |
| operand_str = CIL_KEY_CONS_R1; |
| break; |
| case CIL_CONS_R2: |
| operand_str = CIL_KEY_CONS_R2; |
| break; |
| case CIL_CONS_R3: |
| operand_str = CIL_KEY_CONS_R3; |
| break; |
| case CIL_CONS_L1: |
| operand_str = CIL_KEY_CONS_L1; |
| break; |
| case CIL_CONS_L2: |
| operand_str = CIL_KEY_CONS_L2; |
| break; |
| case CIL_CONS_H1: |
| operand_str = CIL_KEY_CONS_H1; |
| break; |
| case CIL_CONS_H2: |
| operand_str = CIL_KEY_CONS_H2; |
| break; |
| default: |
| cil_log(CIL_ERR, "Unknown operand in expression\n"); |
| goto exit; |
| break; |
| } |
| stack[pos] = operand_str; |
| pos++; |
| break; |
| } |
| default: |
| cil_log(CIL_ERR, "Unknown flavor in expression\n"); |
| goto exit; |
| break; |
| } |
| } |
| |
| *out = stack[0]; |
| |
| return SEPOL_OK; |
| |
| exit: |
| return rc; |
| } |
| |
| void cil_tree_print_expr(struct cil_list *datum_expr, struct cil_list *str_expr) |
| { |
| char *expr_str; |
| |
| cil_log(CIL_INFO, "("); |
| |
| if (datum_expr != NULL) { |
| cil_expr_to_string(datum_expr, &expr_str); |
| } else { |
| cil_expr_to_string(str_expr, &expr_str); |
| } |
| |
| cil_log(CIL_INFO, "%s)", expr_str); |
| free(expr_str); |
| } |
| |
| void cil_tree_print_perms_list(struct cil_tree_node *current_perm) |
| { |
| while (current_perm != NULL) { |
| if (current_perm->flavor == CIL_PERM) { |
| cil_log(CIL_INFO, " %s", ((struct cil_perm *)current_perm->data)->datum.name); |
| } else if (current_perm->flavor == CIL_MAP_PERM) { |
| cil_log(CIL_INFO, " %s", ((struct cil_perm*)current_perm->data)->datum.name); |
| } else { |
| cil_log(CIL_INFO, "\n\n perms list contained unexpected data type: %d\n", current_perm->flavor); |
| break; |
| } |
| current_perm = current_perm->next; |
| } |
| } |
| |
| void cil_tree_print_cats(struct cil_cats *cats) |
| { |
| cil_tree_print_expr(cats->datum_expr, cats->str_expr); |
| } |
| |
| void cil_tree_print_perm_strs(struct cil_list *perm_strs) |
| { |
| struct cil_list_item *curr; |
| |
| if (perm_strs == NULL) { |
| return; |
| } |
| |
| cil_log(CIL_INFO, " ("); |
| |
| cil_list_for_each(curr, perm_strs) { |
| cil_log(CIL_INFO, " %s", (char*)curr->data); |
| } |
| |
| cil_log(CIL_INFO, " )"); |
| } |
| |
| |
| void cil_tree_print_classperms(struct cil_classperms *cp) |
| { |
| if (cp == NULL) { |
| return; |
| } |
| |
| cil_log(CIL_INFO, " class: %s", cp->class_str); |
| cil_log(CIL_INFO, ", perm_strs:"); |
| cil_tree_print_perm_strs(cp->perm_strs); |
| } |
| |
| void cil_tree_print_classperms_set(struct cil_classperms_set *cp_set) |
| { |
| if (cp_set == NULL) { |
| return; |
| } |
| |
| cil_log(CIL_INFO, " %s", cp_set->set_str); |
| } |
| |
| void cil_tree_print_classperms_list(struct cil_list *cp_list) |
| { |
| struct cil_list_item *i; |
| |
| if (cp_list == NULL) { |
| return; |
| } |
| |
| cil_list_for_each(i, cp_list) { |
| if (i->flavor == CIL_CLASSPERMS) { |
| cil_tree_print_classperms(i->data); |
| } else { |
| cil_tree_print_classperms_set(i->data); |
| } |
| } |
| } |
| |
| void cil_tree_print_level(struct cil_level *level) |
| { |
| if (level->sens != NULL) { |
| cil_log(CIL_INFO, " %s", level->sens->datum.name); |
| } else if (level->sens_str != NULL) { |
| cil_log(CIL_INFO, " %s", level->sens_str); |
| } |
| |
| cil_tree_print_cats(level->cats); |
| |
| return; |
| } |
| |
| void cil_tree_print_levelrange(struct cil_levelrange *lvlrange) |
| { |
| cil_log(CIL_INFO, " ("); |
| if (lvlrange->low != NULL) { |
| cil_log(CIL_INFO, " ("); |
| cil_tree_print_level(lvlrange->low); |
| cil_log(CIL_INFO, " )"); |
| } else if (lvlrange->low_str != NULL) { |
| cil_log(CIL_INFO, " %s", lvlrange->low_str); |
| } |
| |
| if (lvlrange->high != NULL) { |
| cil_log(CIL_INFO, " ("); |
| cil_tree_print_level(lvlrange->high); |
| cil_log(CIL_INFO, " )"); |
| } else if (lvlrange->high_str != NULL) { |
| cil_log(CIL_INFO, " %s", lvlrange->high_str); |
| } |
| cil_log(CIL_INFO, " )"); |
| } |
| |
| void cil_tree_print_context(struct cil_context *context) |
| { |
| cil_log(CIL_INFO, " ("); |
| if (context->user != NULL) { |
| cil_log(CIL_INFO, " %s", context->user->datum.name); |
| } else if (context->user_str != NULL) { |
| cil_log(CIL_INFO, " %s", context->user_str); |
| } |
| |
| if (context->role != NULL) { |
| cil_log(CIL_INFO, " %s", context->role->datum.name); |
| } else if (context->role_str != NULL) { |
| cil_log(CIL_INFO, " %s", context->role_str); |
| } |
| |
| if (context->type != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)context->type)->name); |
| } else if (context->type_str != NULL) { |
| cil_log(CIL_INFO, " %s", context->type_str); |
| } |
| |
| if (context->range != NULL) { |
| cil_tree_print_levelrange(context->range); |
| } else if (context->range_str != NULL) { |
| cil_log(CIL_INFO, " %s", context->range_str); |
| } |
| |
| cil_log(CIL_INFO, " )"); |
| |
| return; |
| } |
| |
| void cil_tree_print_constrain(struct cil_constrain *cons) |
| { |
| cil_tree_print_classperms_list(cons->classperms); |
| |
| cil_tree_print_expr(cons->datum_expr, cons->str_expr); |
| |
| cil_log(CIL_INFO, "\n"); |
| } |
| |
| void cil_tree_print_node(struct cil_tree_node *node) |
| { |
| if (node->data == NULL) { |
| cil_log(CIL_INFO, "FLAVOR: %d", node->flavor); |
| return; |
| } else { |
| switch( node->flavor ) { |
| case CIL_BLOCK: { |
| struct cil_block *block = node->data; |
| cil_log(CIL_INFO, "BLOCK: %s\n", block->datum.name); |
| return; |
| } |
| case CIL_BLOCKINHERIT: { |
| struct cil_blockinherit *inherit = node->data; |
| cil_log(CIL_INFO, "BLOCKINHERIT: %s\n", inherit->block_str); |
| return; |
| } |
| case CIL_BLOCKABSTRACT: { |
| struct cil_blockabstract *abstract = node->data; |
| cil_log(CIL_INFO, "BLOCKABSTRACT: %s\n", abstract->block_str); |
| return; |
| } |
| case CIL_IN: { |
| struct cil_in *in = node->data; |
| cil_log(CIL_INFO, "IN: %s\n", in->block_str); |
| return; |
| } |
| case CIL_USER: { |
| struct cil_user *user = node->data; |
| cil_log(CIL_INFO, "USER: %s\n", user->datum.name); |
| return; |
| } |
| case CIL_TYPE: { |
| struct cil_type *type = node->data; |
| cil_log(CIL_INFO, "TYPE: %s\n", type->datum.name); |
| return; |
| } |
| case CIL_TYPEATTRIBUTESET: { |
| struct cil_typeattributeset *attr = node->data; |
| |
| cil_log(CIL_INFO, "(TYPEATTRIBUTESET %s ", attr->attr_str); |
| |
| cil_tree_print_expr(attr->datum_expr, attr->str_expr); |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_TYPEATTRIBUTE: { |
| struct cil_typeattribute *attr = node->data; |
| cil_log(CIL_INFO, "TYPEATTRIBUTE: %s\n", attr->datum.name); |
| return; |
| } |
| case CIL_ROLE: { |
| struct cil_role *role = node->data; |
| cil_log(CIL_INFO, "ROLE: %s\n", role->datum.name); |
| return; |
| } |
| case CIL_USERROLE: { |
| struct cil_userrole *userrole = node->data; |
| cil_log(CIL_INFO, "USERROLE:"); |
| |
| if (userrole->user != NULL) { |
| cil_log(CIL_INFO, " %s", userrole->user->datum.name); |
| } else if (userrole->user_str != NULL) { |
| cil_log(CIL_INFO, " %s", userrole->user_str); |
| } |
| |
| if (userrole->role != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)userrole->role)->name); |
| } else if (userrole->role_str != NULL) { |
| cil_log(CIL_INFO, " %s", userrole->role_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_USERLEVEL: { |
| struct cil_userlevel *usrlvl = node->data; |
| cil_log(CIL_INFO, "USERLEVEL:"); |
| |
| if (usrlvl->user_str != NULL) { |
| cil_log(CIL_INFO, " %s", usrlvl->user_str); |
| } |
| |
| if (usrlvl->level != NULL) { |
| cil_log(CIL_INFO, " ("); |
| cil_tree_print_level(usrlvl->level); |
| cil_log(CIL_INFO, " )"); |
| } else if (usrlvl->level_str != NULL) { |
| cil_log(CIL_INFO, " %s", usrlvl->level_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_USERRANGE: { |
| struct cil_userrange *userrange = node->data; |
| cil_log(CIL_INFO, "USERRANGE:"); |
| |
| if (userrange->user_str != NULL) { |
| cil_log(CIL_INFO, " %s", userrange->user_str); |
| } |
| |
| if (userrange->range != NULL) { |
| cil_log(CIL_INFO, " ("); |
| cil_tree_print_levelrange(userrange->range); |
| cil_log(CIL_INFO, " )"); |
| } else if (userrange->range_str != NULL) { |
| cil_log(CIL_INFO, " %s", userrange->range_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_USERBOUNDS: { |
| struct cil_bounds *bnds = node->data; |
| cil_log(CIL_INFO, "USERBOUNDS: user: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); |
| return; |
| } |
| case CIL_ROLETYPE: { |
| struct cil_roletype *roletype = node->data; |
| struct cil_symtab_datum *datum = NULL; |
| cil_log(CIL_INFO, "ROLETYPE:"); |
| |
| if (roletype->role != NULL) { |
| datum = roletype->role; |
| cil_log(CIL_INFO, " %s", datum->name); |
| } else if (roletype->role_str != NULL) { |
| cil_log(CIL_INFO, " %s", roletype->role_str); |
| } |
| |
| if (roletype->type != NULL) { |
| datum = roletype->type; |
| cil_log(CIL_INFO, " %s", datum->name); |
| } else if (roletype->type_str != NULL) { |
| cil_log(CIL_INFO, " %s", roletype->type_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_ROLETRANSITION: { |
| struct cil_roletransition *roletrans = node->data; |
| cil_log(CIL_INFO, "ROLETRANSITION:"); |
| |
| if (roletrans->src != NULL) { |
| cil_log(CIL_INFO, " %s", roletrans->src->datum.name); |
| } else { |
| cil_log(CIL_INFO, " %s", roletrans->src_str); |
| } |
| |
| if (roletrans->tgt != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)roletrans->tgt)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", roletrans->tgt_str); |
| } |
| |
| if (roletrans->obj != NULL) { |
| cil_log(CIL_INFO, " %s", roletrans->obj->datum.name); |
| } else { |
| cil_log(CIL_INFO, " %s", roletrans->obj_str); |
| } |
| |
| if (roletrans->result != NULL) { |
| cil_log(CIL_INFO, " %s\n", roletrans->result->datum.name); |
| } else { |
| cil_log(CIL_INFO, " %s\n", roletrans->result_str); |
| } |
| |
| return; |
| } |
| case CIL_ROLEALLOW: { |
| struct cil_roleallow *roleallow = node->data; |
| cil_log(CIL_INFO, "ROLEALLOW:"); |
| |
| if (roleallow->src != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->src)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", roleallow->src_str); |
| } |
| |
| if (roleallow->tgt != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)roleallow->tgt)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", roleallow->tgt_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_ROLEATTRIBUTESET: { |
| struct cil_roleattributeset *attr = node->data; |
| |
| cil_log(CIL_INFO, "(ROLEATTRIBUTESET %s ", attr->attr_str); |
| |
| cil_tree_print_expr(attr->datum_expr, attr->str_expr); |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_ROLEATTRIBUTE: { |
| struct cil_roleattribute *attr = node->data; |
| cil_log(CIL_INFO, "ROLEATTRIBUTE: %s\n", attr->datum.name); |
| return; |
| } |
| case CIL_ROLEBOUNDS: { |
| struct cil_bounds *bnds = node->data; |
| cil_log(CIL_INFO, "ROLEBOUNDS: role: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); |
| return; |
| } |
| case CIL_CLASS: { |
| struct cil_class *cls = node->data; |
| cil_log(CIL_INFO, "CLASS: %s ", cls->datum.name); |
| |
| if (cls->common != NULL) { |
| cil_log(CIL_INFO, "inherits: %s ", cls->common->datum.name); |
| } |
| cil_log(CIL_INFO, "("); |
| |
| cil_tree_print_perms_list(node->cl_head); |
| |
| cil_log(CIL_INFO, " )"); |
| return; |
| } |
| case CIL_CLASSORDER: { |
| struct cil_classorder *classorder = node->data; |
| struct cil_list_item *class; |
| |
| if (classorder->class_list_str == NULL) { |
| cil_log(CIL_INFO, "CLASSORDER: ()\n"); |
| return; |
| } |
| |
| cil_log(CIL_INFO, "CLASSORDER: ("); |
| cil_list_for_each(class, classorder->class_list_str) { |
| cil_log(CIL_INFO, " %s", (char*)class->data); |
| } |
| cil_log(CIL_INFO, " )\n"); |
| return; |
| } |
| case CIL_COMMON: { |
| struct cil_class *common = node->data; |
| cil_log(CIL_INFO, "COMMON: %s (", common->datum.name); |
| |
| cil_tree_print_perms_list(node->cl_head); |
| |
| cil_log(CIL_INFO, " )"); |
| return; |
| } |
| case CIL_CLASSCOMMON: { |
| struct cil_classcommon *clscom = node->data; |
| |
| cil_log(CIL_INFO, "CLASSCOMMON: class: %s, common: %s\n", clscom->class_str, clscom->common_str); |
| |
| return; |
| } |
| case CIL_CLASSPERMISSION: { |
| struct cil_classpermission *cp = node->data; |
| |
| cil_log(CIL_INFO, "CLASSPERMISSION: %s", cp->datum.name); |
| |
| cil_log(CIL_INFO, "\n"); |
| |
| return; |
| } |
| case CIL_CLASSPERMISSIONSET: { |
| struct cil_classpermissionset *cps = node->data; |
| |
| cil_log(CIL_INFO, "CLASSPERMISSIONSET: %s", cps->set_str); |
| |
| cil_tree_print_classperms_list(cps->classperms); |
| |
| cil_log(CIL_INFO, "\n"); |
| |
| return; |
| } |
| case CIL_MAP_CLASS: { |
| struct cil_class *cm = node->data; |
| cil_log(CIL_INFO, "MAP_CLASS: %s", cm->datum.name); |
| |
| cil_log(CIL_INFO, " ("); |
| cil_tree_print_perms_list(node->cl_head); |
| cil_log(CIL_INFO, " )\n"); |
| |
| return; |
| } |
| case CIL_MAP_PERM: { |
| struct cil_perm *cmp = node->data; |
| |
| cil_log(CIL_INFO, "MAP_PERM: %s", cmp->datum.name); |
| |
| if (cmp->classperms == NULL) { |
| cil_log(CIL_INFO, " perms: ()"); |
| return; |
| } |
| |
| cil_log(CIL_INFO, " kernel class perms: ("); |
| |
| cil_tree_print_classperms_list(cmp->classperms); |
| |
| cil_log(CIL_INFO, " )\n"); |
| |
| return; |
| } |
| case CIL_CLASSMAPPING: { |
| struct cil_classmapping *mapping = node->data; |
| |
| cil_log(CIL_INFO, "CLASSMAPPING: map class: %s, map perm: %s,", mapping->map_class_str, mapping->map_perm_str); |
| |
| cil_log(CIL_INFO, " ("); |
| |
| cil_tree_print_classperms_list(mapping->classperms); |
| |
| cil_log(CIL_INFO, " )\n"); |
| return; |
| } |
| case CIL_BOOL: { |
| struct cil_bool *boolean = node->data; |
| cil_log(CIL_INFO, "BOOL: %s, value: %d\n", boolean->datum.name, boolean->value); |
| return; |
| } |
| case CIL_TUNABLE: { |
| struct cil_tunable *tunable = node->data; |
| cil_log(CIL_INFO, "TUNABLE: %s, value: %d\n", tunable->datum.name, tunable->value); |
| return; |
| } |
| case CIL_BOOLEANIF: { |
| struct cil_booleanif *bif = node->data; |
| |
| cil_log(CIL_INFO, "(BOOLEANIF "); |
| |
| cil_tree_print_expr(bif->datum_expr, bif->str_expr); |
| |
| cil_log(CIL_INFO, " )\n"); |
| return; |
| } |
| case CIL_TUNABLEIF: { |
| struct cil_tunableif *tif = node->data; |
| |
| cil_log(CIL_INFO, "(TUNABLEIF "); |
| |
| cil_tree_print_expr(tif->datum_expr, tif->str_expr); |
| |
| cil_log(CIL_INFO, " )\n"); |
| return; |
| } |
| case CIL_CONDBLOCK: { |
| struct cil_condblock *cb = node->data; |
| if (cb->flavor == CIL_CONDTRUE) { |
| cil_log(CIL_INFO, "true\n"); |
| } else if (cb->flavor == CIL_CONDFALSE) { |
| cil_log(CIL_INFO, "false\n"); |
| } |
| return; |
| } |
| case CIL_ALL: |
| cil_log(CIL_INFO, "all"); |
| return; |
| case CIL_AND: |
| cil_log(CIL_INFO, "&&"); |
| return; |
| case CIL_OR: |
| cil_log(CIL_INFO, "|| "); |
| return; |
| case CIL_NOT: |
| cil_log(CIL_INFO, "!"); |
| return; |
| case CIL_EQ: |
| cil_log(CIL_INFO, "=="); |
| return; |
| case CIL_NEQ: |
| cil_log(CIL_INFO, "!="); |
| return; |
| case CIL_TYPEALIAS: { |
| struct cil_alias *alias = node->data; |
| cil_log(CIL_INFO, "TYPEALIAS: %s\n", alias->datum.name); |
| return; |
| } |
| case CIL_TYPEALIASACTUAL: { |
| struct cil_aliasactual *aliasactual = node->data; |
| cil_log(CIL_INFO, "TYPEALIASACTUAL: type: %s, alias: %s\n", aliasactual->alias_str, aliasactual->actual_str); |
| return; |
| } |
| case CIL_TYPEBOUNDS: { |
| struct cil_bounds *bnds = node->data; |
| cil_log(CIL_INFO, "TYPEBOUNDS: type: %s, bounds: %s\n", bnds->parent_str, bnds->child_str); |
| return; |
| } |
| case CIL_TYPEPERMISSIVE: { |
| struct cil_typepermissive *typeperm = node->data; |
| |
| if (typeperm->type != NULL) { |
| cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", ((struct cil_symtab_datum *)typeperm->type)->name); |
| } else { |
| cil_log(CIL_INFO, "TYPEPERMISSIVE: %s\n", typeperm->type_str); |
| } |
| |
| return; |
| } |
| case CIL_NAMETYPETRANSITION: { |
| struct cil_nametypetransition *nametypetrans = node->data; |
| cil_log(CIL_INFO, "TYPETRANSITION:"); |
| |
| if (nametypetrans->src != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->src)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", nametypetrans->src_str); |
| } |
| |
| if (nametypetrans->tgt != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->tgt)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", nametypetrans->tgt_str); |
| } |
| |
| if (nametypetrans->obj != NULL) { |
| cil_log(CIL_INFO, " %s", nametypetrans->obj->datum.name); |
| } else { |
| cil_log(CIL_INFO, " %s", nametypetrans->obj_str); |
| } |
| |
| cil_log(CIL_INFO, " %s\n", nametypetrans->name_str); |
| |
| if (nametypetrans->result != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)nametypetrans->result)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", nametypetrans->result_str); |
| } |
| |
| return; |
| } |
| case CIL_RANGETRANSITION: { |
| struct cil_rangetransition *rangetrans = node->data; |
| cil_log(CIL_INFO, "RANGETRANSITION:"); |
| |
| if (rangetrans->src != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->src)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", rangetrans->src_str); |
| } |
| |
| if (rangetrans->exec != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rangetrans->exec)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", rangetrans->exec_str); |
| } |
| |
| if (rangetrans->obj != NULL) { |
| cil_log(CIL_INFO, " %s", rangetrans->obj->datum.name); |
| } else { |
| cil_log(CIL_INFO, " %s", rangetrans->obj_str); |
| } |
| |
| if (rangetrans->range != NULL) { |
| cil_log(CIL_INFO, " ("); |
| cil_tree_print_levelrange(rangetrans->range); |
| cil_log(CIL_INFO, " )"); |
| } else { |
| cil_log(CIL_INFO, " %s", rangetrans->range_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_AVRULE: { |
| struct cil_avrule *rule = node->data; |
| switch (rule->rule_kind) { |
| case CIL_AVRULE_ALLOWED: |
| cil_log(CIL_INFO, "ALLOW:"); |
| break; |
| case CIL_AVRULE_AUDITALLOW: |
| cil_log(CIL_INFO, "AUDITALLOW:"); |
| break; |
| case CIL_AVRULE_DONTAUDIT: |
| cil_log(CIL_INFO, "DONTAUDIT:"); |
| break; |
| case CIL_AVRULE_NEVERALLOW: |
| cil_log(CIL_INFO, "NEVERALLOW:"); |
| break; |
| } |
| |
| if (rule->src != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->src)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", rule->src_str); |
| } |
| |
| if (rule->tgt != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum*)rule->tgt)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", rule->tgt_str); |
| } |
| |
| cil_tree_print_classperms_list(rule->classperms); |
| |
| cil_log(CIL_INFO, "\n"); |
| |
| return; |
| } |
| case CIL_TYPE_RULE: { |
| struct cil_type_rule *rule = node->data; |
| switch (rule->rule_kind) { |
| case CIL_TYPE_TRANSITION: |
| cil_log(CIL_INFO, "TYPETRANSITION:"); |
| break; |
| case CIL_TYPE_MEMBER: |
| cil_log(CIL_INFO, "TYPEMEMBER:"); |
| break; |
| case CIL_TYPE_CHANGE: |
| cil_log(CIL_INFO, "TYPECHANGE:"); |
| break; |
| } |
| |
| if (rule->src != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->src)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", rule->src_str); |
| } |
| |
| if (rule->tgt != NULL) { |
| cil_log(CIL_INFO, " %s", ((struct cil_symtab_datum *)rule->tgt)->name); |
| } else { |
| cil_log(CIL_INFO, " %s", rule->tgt_str); |
| } |
| |
| if (rule->obj != NULL) { |
| cil_log(CIL_INFO, " %s", rule->obj->datum.name); |
| } else { |
| cil_log(CIL_INFO, " %s", rule->obj_str); |
| } |
| |
| if (rule->result != NULL) { |
| cil_log(CIL_INFO, " %s\n", ((struct cil_symtab_datum *)rule->result)->name); |
| } else { |
| cil_log(CIL_INFO, " %s\n", rule->result_str); |
| } |
| |
| return; |
| } |
| case CIL_SENS: { |
| struct cil_sens *sens = node->data; |
| cil_log(CIL_INFO, "SENSITIVITY: %s\n", sens->datum.name); |
| return; |
| } |
| case CIL_SENSALIAS: { |
| struct cil_alias *alias = node->data; |
| cil_log(CIL_INFO, "SENSITIVITYALIAS: %s\n", alias->datum.name); |
| return; |
| } |
| case CIL_SENSALIASACTUAL: { |
| struct cil_aliasactual *aliasactual = node->data; |
| cil_log(CIL_INFO, "SENSITIVITYALIAS: alias: %s, sensitivity: %s\n", aliasactual->alias_str, aliasactual->actual_str); |
| |
| return; |
| } |
| case CIL_CAT: { |
| struct cil_cat *cat = node->data; |
| cil_log(CIL_INFO, "CATEGORY: %s\n", cat->datum.name); |
| return; |
| } |
| case CIL_CATALIAS: { |
| struct cil_alias *alias = node->data; |
| cil_log(CIL_INFO, "CATEGORYALIAS: %s\n", alias->datum.name); |
| return; |
| } |
| case CIL_CATALIASACTUAL: { |
| struct cil_aliasactual *aliasactual = node->data; |
| cil_log(CIL_INFO, "CATEGORYALIAS: alias %s, category: %s\n", aliasactual->alias_str, aliasactual->actual_str); |
| return; |
| } |
| case CIL_CATSET: { |
| struct cil_catset *catset = node->data; |
| |
| cil_log(CIL_INFO, "CATSET: %s ",catset->datum.name); |
| |
| cil_tree_print_cats(catset->cats); |
| |
| return; |
| } |
| case CIL_CATORDER: { |
| struct cil_catorder *catorder = node->data; |
| struct cil_list_item *cat; |
| |
| if (catorder->cat_list_str == NULL) { |
| cil_log(CIL_INFO, "CATORDER: ()\n"); |
| return; |
| } |
| |
| cil_log(CIL_INFO, "CATORDER: ("); |
| cil_list_for_each(cat, catorder->cat_list_str) { |
| cil_log(CIL_INFO, " %s", (char*)cat->data); |
| } |
| cil_log(CIL_INFO, " )\n"); |
| return; |
| } |
| case CIL_SENSCAT: { |
| struct cil_senscat *senscat = node->data; |
| |
| cil_log(CIL_INFO, "SENSCAT: sens:"); |
| |
| if (senscat->sens_str != NULL) { |
| cil_log(CIL_INFO, " %s ", senscat->sens_str); |
| } else { |
| cil_log(CIL_INFO, " [processed]"); |
| } |
| |
| cil_tree_print_cats(senscat->cats); |
| |
| return; |
| } |
| case CIL_SENSITIVITYORDER: { |
| struct cil_sensorder *sensorder = node->data; |
| struct cil_list_item *sens; |
| |
| cil_log(CIL_INFO, "SENSITIVITYORDER: ("); |
| |
| if (sensorder->sens_list_str != NULL) { |
| cil_list_for_each(sens, sensorder->sens_list_str) { |
| if (sens->flavor == CIL_LIST) { |
| struct cil_list_item *sub; |
| cil_log(CIL_INFO, " ("); |
| cil_list_for_each(sub, (struct cil_list*)sens->data) { |
| cil_log(CIL_INFO, " %s", (char*)sub->data); |
| } |
| cil_log(CIL_INFO, " )"); |
| } else { |
| cil_log(CIL_INFO, " %s", (char*)sens->data); |
| } |
| } |
| } |
| |
| cil_log(CIL_INFO, " )\n"); |
| return; |
| } |
| case CIL_LEVEL: { |
| struct cil_level *level = node->data; |
| cil_log(CIL_INFO, "LEVEL %s:", level->datum.name); |
| cil_tree_print_level(level); |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_LEVELRANGE: { |
| struct cil_levelrange *lvlrange = node->data; |
| cil_log(CIL_INFO, "LEVELRANGE %s:", lvlrange->datum.name); |
| cil_tree_print_levelrange(lvlrange); |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_CONSTRAIN: { |
| struct cil_constrain *cons = node->data; |
| cil_log(CIL_INFO, "CONSTRAIN: ("); |
| cil_tree_print_constrain(cons); |
| return; |
| } |
| case CIL_MLSCONSTRAIN: { |
| struct cil_constrain *cons = node->data; |
| cil_log(CIL_INFO, "MLSCONSTRAIN: ("); |
| cil_tree_print_constrain(cons); |
| return; |
| } |
| case CIL_VALIDATETRANS: { |
| struct cil_validatetrans *vt = node->data; |
| |
| cil_log(CIL_INFO, "(VALIDATETRANS "); |
| |
| if (vt->class != NULL) { |
| cil_log(CIL_INFO, "%s ", vt->class->datum.name); |
| } else if (vt->class_str != NULL) { |
| cil_log(CIL_INFO, "%s ", vt->class_str); |
| } |
| |
| cil_tree_print_expr(vt->datum_expr, vt->str_expr); |
| |
| cil_log(CIL_INFO, ")\n"); |
| return; |
| } |
| case CIL_MLSVALIDATETRANS: { |
| struct cil_validatetrans *vt = node->data; |
| |
| cil_log(CIL_INFO, "(MLSVALIDATETRANS "); |
| |
| if (vt->class != NULL) { |
| cil_log(CIL_INFO, "%s ", vt->class->datum.name); |
| } else if (vt->class_str != NULL) { |
| cil_log(CIL_INFO, "%s ", vt->class_str); |
| } |
| |
| cil_tree_print_expr(vt->datum_expr, vt->str_expr); |
| |
| cil_log(CIL_INFO, ")\n"); |
| return; |
| } |
| case CIL_CONTEXT: { |
| struct cil_context *context = node->data; |
| cil_log(CIL_INFO, "CONTEXT %s:", context->datum.name); |
| cil_tree_print_context(context); |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_FILECON: { |
| struct cil_filecon *filecon = node->data; |
| cil_log(CIL_INFO, "FILECON:"); |
| cil_log(CIL_INFO, " %s %d", filecon->path_str, filecon->type); |
| |
| if (filecon->context_str != NULL) { |
| cil_log(CIL_INFO, " %s", filecon->context_str); |
| } else if (filecon->context != NULL) { |
| cil_tree_print_context(filecon->context); |
| } else if (filecon->context_str != NULL) { |
| cil_log(CIL_INFO, " %s", filecon->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| |
| } |
| case CIL_PORTCON: { |
| struct cil_portcon *portcon = node->data; |
| cil_log(CIL_INFO, "PORTCON:"); |
| if (portcon->proto == CIL_PROTOCOL_UDP) { |
| cil_log(CIL_INFO, " udp"); |
| } else if (portcon->proto == CIL_PROTOCOL_TCP) { |
| cil_log(CIL_INFO, " tcp"); |
| } |
| cil_log(CIL_INFO, " (%d %d)", portcon->port_low, portcon->port_high); |
| |
| if (portcon->context != NULL) { |
| cil_tree_print_context(portcon->context); |
| } else if (portcon->context_str != NULL) { |
| cil_log(CIL_INFO, " %s", portcon->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_NODECON: { |
| struct cil_nodecon *nodecon = node->data; |
| char buf[256]; |
| |
| cil_log(CIL_INFO, "NODECON:"); |
| |
| if (nodecon->addr) { |
| inet_ntop(nodecon->addr->family, &nodecon->addr->ip, buf, 256); |
| cil_log(CIL_INFO, " %s", buf); |
| } else { |
| cil_log(CIL_INFO, " %s", nodecon->addr_str); |
| } |
| |
| if (nodecon->mask) { |
| inet_ntop(nodecon->mask->family, &nodecon->mask->ip, buf, 256); |
| cil_log(CIL_INFO, " %s", buf); |
| } else { |
| cil_log(CIL_INFO, " %s", nodecon->mask_str); |
| } |
| |
| if (nodecon->context != NULL) { |
| cil_tree_print_context(nodecon->context); |
| } else if (nodecon->context_str != NULL) { |
| cil_log(CIL_INFO, " %s", nodecon->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_GENFSCON: { |
| struct cil_genfscon *genfscon = node->data; |
| cil_log(CIL_INFO, "GENFSCON:"); |
| cil_log(CIL_INFO, " %s %s", genfscon->fs_str, genfscon->path_str); |
| |
| if (genfscon->context != NULL) { |
| cil_tree_print_context(genfscon->context); |
| } else if (genfscon->context_str != NULL) { |
| cil_log(CIL_INFO, " %s", genfscon->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_NETIFCON: { |
| struct cil_netifcon *netifcon = node->data; |
| cil_log(CIL_INFO, "NETIFCON %s", netifcon->interface_str); |
| |
| if (netifcon->if_context != NULL) { |
| cil_tree_print_context(netifcon->if_context); |
| } else if (netifcon->if_context_str != NULL) { |
| cil_log(CIL_INFO, " %s", netifcon->if_context_str); |
| } |
| |
| if (netifcon->packet_context != NULL) { |
| cil_tree_print_context(netifcon->packet_context); |
| } else if (netifcon->packet_context_str != NULL) { |
| cil_log(CIL_INFO, " %s", netifcon->packet_context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_PIRQCON: { |
| struct cil_pirqcon *pirqcon = node->data; |
| |
| cil_log(CIL_INFO, "PIRQCON %d", pirqcon->pirq); |
| if (pirqcon->context != NULL) { |
| cil_tree_print_context(pirqcon->context); |
| } else { |
| cil_log(CIL_INFO, " %s", pirqcon->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_IOMEMCON: { |
| struct cil_iomemcon *iomemcon = node->data; |
| |
| cil_log(CIL_INFO, "IOMEMCON ( %"PRId64" %"PRId64" )", iomemcon->iomem_low, iomemcon->iomem_high); |
| if (iomemcon->context != NULL) { |
| cil_tree_print_context(iomemcon->context); |
| } else { |
| cil_log(CIL_INFO, " %s", iomemcon->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_IOPORTCON: { |
| struct cil_ioportcon *ioportcon = node->data; |
| |
| cil_log(CIL_INFO, "IOPORTCON ( %d %d )", ioportcon->ioport_low, ioportcon->ioport_high); |
| if (ioportcon->context != NULL) { |
| cil_tree_print_context(ioportcon->context); |
| } else { |
| cil_log(CIL_INFO, " %s", ioportcon->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_PCIDEVICECON: { |
| struct cil_pcidevicecon *pcidevicecon = node->data; |
| |
| cil_log(CIL_INFO, "PCIDEVICECON %d", pcidevicecon->dev); |
| if (pcidevicecon->context != NULL) { |
| cil_tree_print_context(pcidevicecon->context); |
| } else { |
| cil_log(CIL_INFO, " %s", pcidevicecon->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_FSUSE: { |
| struct cil_fsuse *fsuse = node->data; |
| cil_log(CIL_INFO, "FSUSE: "); |
| |
| if (fsuse->type == CIL_FSUSE_XATTR) { |
| cil_log(CIL_INFO, "xattr "); |
| } else if (fsuse->type == CIL_FSUSE_TASK) { |
| cil_log(CIL_INFO, "task "); |
| } else if (fsuse->type == CIL_FSUSE_TRANS) { |
| cil_log(CIL_INFO, "trans "); |
| } else { |
| cil_log(CIL_INFO, "unknown "); |
| } |
| |
| cil_log(CIL_INFO, "%s ", fsuse->fs_str); |
| |
| if (fsuse->context != NULL) { |
| cil_tree_print_context(fsuse->context); |
| } else { |
| cil_log(CIL_INFO, " %s", fsuse->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_SID: { |
| struct cil_sid *sid = node->data; |
| cil_log(CIL_INFO, "SID: %s\n", sid->datum.name); |
| return; |
| } |
| case CIL_SIDCONTEXT: { |
| struct cil_sidcontext *sidcon = node->data; |
| cil_log(CIL_INFO, "SIDCONTEXT: %s", sidcon->sid_str); |
| |
| if (sidcon->context != NULL) { |
| cil_tree_print_context(sidcon->context); |
| } else { |
| cil_log(CIL_INFO, " %s", sidcon->context_str); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_SIDORDER: { |
| struct cil_sidorder *sidorder = node->data; |
| struct cil_list_item *sid; |
| |
| if (sidorder->sid_list_str == NULL) { |
| cil_log(CIL_INFO, "SIDORDER: ()\n"); |
| return; |
| } |
| |
| cil_log(CIL_INFO, "SIDORDER: ("); |
| cil_list_for_each(sid, sidorder->sid_list_str) { |
| cil_log(CIL_INFO, " %s", (char*)sid->data); |
| } |
| cil_log(CIL_INFO, " )\n"); |
| return; |
| } |
| case CIL_POLICYCAP: { |
| struct cil_policycap *polcap = node->data; |
| cil_log(CIL_INFO, "POLICYCAP: %s\n", polcap->datum.name); |
| return; |
| } |
| case CIL_MACRO: { |
| struct cil_macro *macro = node->data; |
| cil_log(CIL_INFO, "MACRO %s:", macro->datum.name); |
| |
| if (macro->params != NULL && macro->params->head != NULL) { |
| struct cil_list_item *curr_param; |
| cil_log(CIL_INFO, " parameters: ("); |
| cil_list_for_each(curr_param, macro->params) { |
| cil_log(CIL_INFO, " flavor: %d, string: %s;", ((struct cil_param*)curr_param->data)->flavor, ((struct cil_param*)curr_param->data)->str); |
| |
| } |
| cil_log(CIL_INFO, " )"); |
| } |
| cil_log(CIL_INFO, "\n"); |
| |
| return; |
| } |
| case CIL_CALL: { |
| struct cil_call *call = node->data; |
| cil_log(CIL_INFO, "CALL: macro name:"); |
| |
| if (call->macro != NULL) { |
| cil_log(CIL_INFO, " %s", call->macro->datum.name); |
| } else { |
| cil_log(CIL_INFO, " %s", call->macro_str); |
| } |
| |
| if (call->args != NULL) { |
| cil_log(CIL_INFO, ", args: ( "); |
| struct cil_list_item *item; |
| cil_list_for_each(item, call->args) { |
| struct cil_symtab_datum *datum = ((struct cil_args*)item->data)->arg; |
| if (datum != NULL) { |
| if (datum->nodes != NULL && datum->nodes->head != NULL) { |
| cil_tree_print_node((struct cil_tree_node*)datum->nodes->head->data); |
| } |
| } else if (((struct cil_args*)item->data)->arg_str != NULL) { |
| switch (item->flavor) { |
| case CIL_TYPE: cil_log(CIL_INFO, "type:"); break; |
| case CIL_USER: cil_log(CIL_INFO, "user:"); break; |
| case CIL_ROLE: cil_log(CIL_INFO, "role:"); break; |
| case CIL_SENS: cil_log(CIL_INFO, "sensitivity:"); break; |
| case CIL_CAT: cil_log(CIL_INFO, "category:"); break; |
| case CIL_CATSET: cil_log(CIL_INFO, "categoryset:"); break; |
| case CIL_LEVEL: cil_log(CIL_INFO, "level:"); break; |
| case CIL_CLASS: cil_log(CIL_INFO, "class:"); break; |
| default: break; |
| } |
| cil_log(CIL_INFO, "%s ", ((struct cil_args*)item->data)->arg_str); |
| } |
| } |
| cil_log(CIL_INFO, ")"); |
| } |
| |
| cil_log(CIL_INFO, "\n"); |
| return; |
| } |
| case CIL_OPTIONAL: { |
| struct cil_optional *optional = node->data; |
| cil_log(CIL_INFO, "OPTIONAL: %s\n", optional->datum.name); |
| return; |
| } |
| case CIL_IPADDR: { |
| struct cil_ipaddr *ipaddr = node->data; |
| char buf[256]; |
| |
| inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256); |
| cil_log(CIL_INFO, "IPADDR %s: %s\n", ipaddr->datum.name, buf); |
| |
| break; |
| } |
| default : { |
| cil_log(CIL_INFO, "CIL FLAVOR: %d\n", node->flavor); |
| return; |
| } |
| } |
| } |
| } |
| |
| void cil_tree_print(struct cil_tree_node *tree, uint32_t depth) |
| { |
| struct cil_tree_node *current = NULL; |
| current = tree; |
| uint32_t x = 0; |
| |
| if (current != NULL) { |
| if (current->cl_head == NULL) { |
| if (current->flavor == CIL_NODE) { |
| if (current->parent->cl_head == current) { |
| cil_log(CIL_INFO, "%s", (char*)current->data); |
| } else { |
| cil_log(CIL_INFO, " %s", (char*)current->data); |
| } |
| } else if (current->flavor != CIL_PERM) { |
| for (x = 0; x<depth; x++) { |
| cil_log(CIL_INFO, "\t"); |
| } |
| cil_tree_print_node(current); |
| } |
| } else { |
| if (current->parent != NULL) { |
| cil_log(CIL_INFO, "\n"); |
| for (x = 0; x<depth; x++) { |
| cil_log(CIL_INFO, "\t"); |
| } |
| cil_log(CIL_INFO, "("); |
| |
| if (current->flavor != CIL_NODE) { |
| cil_tree_print_node(current); |
| } |
| } |
| cil_tree_print(current->cl_head, depth + 1); |
| } |
| |
| if (current->next == NULL) { |
| if ((current->parent != NULL) && (current->parent->cl_tail == current) && (current->parent->parent != NULL)) { |
| if (current->flavor == CIL_PERM) { |
| cil_log(CIL_INFO, ")\n"); |
| } else if (current->flavor != CIL_NODE) { |
| for (x = 0; x<depth-1; x++) { |
| cil_log(CIL_INFO, "\t"); |
| } |
| cil_log(CIL_INFO, ")\n"); |
| } else { |
| cil_log(CIL_INFO, ")"); |
| } |
| } |
| |
| if ((current->parent != NULL) && (current->parent->parent == NULL)) |
| cil_log(CIL_INFO, "\n\n"); |
| } else { |
| cil_tree_print(current->next, depth); |
| } |
| } else { |
| cil_log(CIL_INFO, "Tree is NULL\n"); |
| } |
| } |