diff options
Diffstat (limited to 'tools/security/secpol_xml2bin.c')
-rw-r--r-- | tools/security/secpol_xml2bin.c | 1457 |
1 files changed, 0 insertions, 1457 deletions
diff --git a/tools/security/secpol_xml2bin.c b/tools/security/secpol_xml2bin.c deleted file mode 100644 index 0fbe8efcbd..0000000000 --- a/tools/security/secpol_xml2bin.c +++ /dev/null @@ -1,1457 +0,0 @@ -/**************************************************************** - * secpol_xml2bin.c - * - * Copyright (C) 2005 IBM Corporation - * - * Author: Reiner Sailer <sailer@us.ibm.com> - * - * Maintained: - * Reiner Sailer <sailer@us.ibm.com> - * Ray Valdez <rvaldez@us.ibm.com> - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation, version 2 of the - * License. - * - * sHype policy translation tool. This tool takes an XML - * policy specification as input and produces a binary - * policy file that can be loaded into Xen through the - * ACM operations (xensec_tool loadpolicy) interface or at - * boot time (grub module parameter) - * - * indent -i4 -kr -nut - */ - -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <errno.h> -#include <libgen.h> -#include <fcntl.h> -#include <unistd.h> -#include <sys/types.h> -#include <sys/stat.h> -#include <sys/queue.h> -#include <netinet/in.h> -#include <libxml/xmlschemas.h> -#include <libxml/parser.h> -#include <libxml/tree.h> -#include <libxml/xmlreader.h> -#include <stdint.h> -#include <xen/xsm/acm.h> - -#include "secpol_xml2bin.h" - -#define DEBUG 0 - -#define NULL_LABEL_NAME "__NULL_LABEL__" - -#define ROUND8(x) ((x + 7) & ~7) - -/* primary / secondary policy component setting */ -enum policycomponent { CHWALL, STE, NULLPOLICY } - primary = NULLPOLICY, secondary = NULLPOLICY; - -/* general list element for ste and chwall type queues */ -struct type_entry { - TAILQ_ENTRY(type_entry) entries; - char *name; /* name of type from xml file */ - type_t mapping; /* type mapping into 16bit */ -}; - -TAILQ_HEAD(tailhead, type_entry) ste_head, chwall_head; - -/* general list element for all label queues */ -enum label_type { VM, RES, ANY }; -struct ssid_entry { - TAILQ_ENTRY(ssid_entry) entries; - char *name; /* label name */ - enum label_type type; /* type: VM / RESOURCE LABEL */ - u_int32_t num; /* ssid or referenced ssid */ - int is_ref; /* if this entry references earlier ssid number */ - unsigned char *row; /* index of types (if not a reference) */ -}; - -TAILQ_HEAD(tailhead_ssid, ssid_entry) ste_ssid_head, chwall_ssid_head, - conflictsets_head; -struct ssid_entry *current_chwall_ssid_p = NULL; -struct ssid_entry *current_ste_ssid_p = NULL; -struct ssid_entry *current_conflictset_p = NULL; - -/* which label to assign to dom0 during boot */ -char *bootstrap_label; - -u_int32_t max_ste_ssids = 0; -u_int32_t max_chwall_ssids = 0; -u_int32_t max_chwall_labels = 0; -u_int32_t max_ste_labels = 0; -u_int32_t max_conflictsets = 0; - -char *current_ssid_name; /* store name until structure is allocated */ -char *current_conflictset_name; /* store name until structure is allocated */ - -/* dynamic list of type mappings for STE */ -u_int32_t max_ste_types = 0; - -/* dynamic list of type mappings for CHWALL */ -u_int32_t max_chwall_types = 0; - -/* dynamic list of conflict sets */ -int max_conflict_set = 0; - -/* which policies are defined */ -int have_ste = 0; -int have_chwall = 0; - -/* input/output file names */ -char *policy_filename = NULL, - *binary_filename = NULL, - *mapping_filename = NULL, *schema_filename = NULL; - -char *policy_reference_name = NULL; - -char *policy_version_string = NULL; - -void walk_labels(xmlNode * start, xmlDocPtr doc, unsigned long state); - -void usage(char *prg) -{ - printf( - "Usage: %s [OPTIONS] POLICYNAME\n" - "POLICYNAME is the directory name within the policy directory\n" - "that contains the policy files. The default policy directory\n" - "is '%s' (see the '-d' option below to change it)\n" - "The policy files contained in the POLICYNAME directory must be named:\n" - "\tPOLICYNAME-security_policy.xml\n" - "\tPOLICYNAME-security_label_template.xml\n\n" - "OPTIONS:\n" - "\t-d POLICYDIR\n" - "\t\tUse POLICYDIR as the policy directory. This directory must \n" - "\t\tcontain the policy schema file 'security_policy.xsd'\n", - prg, POLICY_DIR); - exit(EXIT_FAILURE); -} - - -/***************** policy-related parsing *********************/ - -char *type_by_mapping(struct tailhead *head, u_int32_t mapping) -{ - struct type_entry *np; - for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) - if (np->mapping == mapping) - return np->name; - return NULL; -} - - -struct type_entry *lookup(struct tailhead *head, char *name) -{ - struct type_entry *np; - for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) - if (!(strcmp(np->name, name))) - return np; - return NULL; -} - -/* enforces single-entry lists */ -int add_entry(struct tailhead *head, char *name, type_t mapping) -{ - struct type_entry *e; - if (lookup(head, name)) { - printf("Error: Type >%s< defined more than once.\n", name); - return -EFAULT; /* already in the list */ - } - if (!(e = malloc(sizeof(struct type_entry)))) - return -ENOMEM; - - e->name = name; - e->mapping = mapping; - TAILQ_INSERT_TAIL(head, e, entries); - return 0; -} - -int totoken(char *tok) -{ - int i; - for (i = 0; token[i] != NULL; i++) - if (!strcmp(token[i], tok)) - return i; - return -EFAULT; -} - -/* conflictsets use the same data structure as ssids; since - * they are similar in structure (set of types) - */ -int init_next_conflictset(void) -{ - struct ssid_entry *conflictset = malloc(sizeof(struct ssid_entry)); - - if (!conflictset) - return -ENOMEM; - - conflictset->name = current_conflictset_name; - conflictset->num = max_conflictsets++; - conflictset->is_ref = 0; /* n/a for conflictsets */ - /** - * row: allocate one byte per type; - * [i] != 0 --> mapped type >i< is part of the conflictset - */ - conflictset->row = malloc(max_chwall_types); - if (!conflictset->row) - return -ENOMEM; - - memset(conflictset->row, 0, max_chwall_types); - TAILQ_INSERT_TAIL(&conflictsets_head, conflictset, entries); - current_conflictset_p = conflictset; - return 0; -} - -int register_type(xmlNode * cur_node, xmlDocPtr doc, unsigned long state) -{ - xmlChar *text; - struct type_entry *e; - - - text = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - if (!text) { - printf("Error reading type name!\n"); - return -EFAULT; - } - - switch (state) { - case XML2BIN_stetype_S: - if (add_entry(&ste_head, (char *) text, max_ste_types)) { - xmlFree(text); - return -EFAULT; - } - max_ste_types++; - break; - - case XML2BIN_chwalltype_S: - if (add_entry(&chwall_head, (char *) text, max_chwall_types)) { - xmlFree(text); - return -EFAULT; - } - max_chwall_types++; - break; - - case XML2BIN_conflictsettype_S: - /* a) search the type in the chwall_type list */ - e = lookup(&chwall_head, (char *) text); - if (e == NULL) { - printf("CS type >%s< not a CHWALL type.\n", text); - xmlFree(text); - return -EFAULT; - } - /* b) add type entry to the current cs set */ - if (current_conflictset_p->row[e->mapping]) { - printf - ("ERROR: Double entry of type >%s< in conflict set %d.\n", - text, current_conflictset_p->num); - xmlFree(text); - return -EFAULT; - } - current_conflictset_p->row[e->mapping] = 1; - break; - - default: - printf("Incorrect type environment (state = %lx, text = %s).\n", - state, text); - xmlFree(text); - return -EFAULT; - } - return 0; -} - -void set_component_type(xmlNode * cur_node, enum policycomponent pc) -{ - xmlChar *order; - - if ((order = - xmlGetProp(cur_node, (xmlChar *) PRIMARY_COMPONENT_ATTR_NAME))) { - if (strcmp((char *) order, PRIMARY_COMPONENT)) { - printf("ERROR: Illegal attribut value >order=%s<.\n", - (char *) order); - xmlFree(order); - exit(EXIT_FAILURE); - } - if (primary != NULLPOLICY) { - printf("ERROR: Primary Policy Component set twice!\n"); - exit(EXIT_FAILURE); - } - primary = pc; - xmlFree(order); - } -} - -void walk_policy(xmlNode * start, xmlDocPtr doc, unsigned long state) -{ - xmlNode *cur_node = NULL; - int code; - - for (cur_node = start; cur_node; cur_node = cur_node->next) { - if ((code = totoken((char *) cur_node->name)) < 0) { - printf("Unknown token: >%s<. Aborting.\n", cur_node->name); - exit(EXIT_FAILURE); - } - switch (code) { /* adjust state to new state */ - case XML2BIN_SECPOL: - case XML2BIN_STETYPES: - case XML2BIN_CHWALLTYPES: - case XML2BIN_CONFLICTSETS: - case XML2BIN_POLICYHEADER: - case XML2BIN_FROMPOLICY: - walk_policy(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_POLICYNAME: /* get policy reference name .... */ - if (state != XML2BIN_PN_S && - state != XML2BIN_PN_frompolicy_S) { - printf("ERROR: >Url< >%s< out of context.\n", - (char *) xmlNodeListGetString(doc, - cur_node-> - xmlChildrenNode, 1)); - exit(EXIT_FAILURE); - } - if (state == XML2BIN_PN_S) { - policy_reference_name = (char *) - xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - if (!policy_reference_name) { - printf("ERROR: empty >policy reference name (Url)<!\n"); - exit(EXIT_FAILURE); - } else - printf("Policy Reference name (Url): %s\n", - policy_reference_name); - } - break; - - case XML2BIN_VERSION: /* get policy version number .... */ - if (state != XML2BIN_PN_S && - state != XML2BIN_PN_frompolicy_S) { - printf("ERROR: >Url< >%s< out of context.\n", - (char *) xmlNodeListGetString(doc, - cur_node-> - xmlChildrenNode, 1)); - exit(EXIT_FAILURE); - } - if (state == XML2BIN_PN_S) { - policy_version_string = (char *) - xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - if (!policy_version_string) { - printf("ERROR: empty >policy version string <!\n"); - exit(EXIT_FAILURE); - } else - printf("Policy version string: %s\n", - policy_version_string); - } - break; - - case XML2BIN_STE: - if (WRITTEN_AGAINST_ACM_STE_VERSION != ACM_STE_VERSION) { - printf - ("ERROR: This program was written against another STE version.\n"); - exit(EXIT_FAILURE); - } - have_ste = 1; - set_component_type(cur_node, STE); - walk_policy(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_CHWALL: - if (WRITTEN_AGAINST_ACM_CHWALL_VERSION != ACM_CHWALL_VERSION) { - printf - ("ERROR: This program was written against another CHWALL version.\n"); - exit(EXIT_FAILURE); - } - have_chwall = 1; - set_component_type(cur_node, CHWALL); - walk_policy(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_CSTYPE: - current_conflictset_name = - (char *) xmlGetProp(cur_node, (xmlChar *) "name"); - if (!current_conflictset_name) - current_conflictset_name = ""; - - if (init_next_conflictset()) { - printf - ("ERROR: creating new conflictset structure failed.\n"); - exit(EXIT_FAILURE); - } - walk_policy(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_TYPE: - if (register_type(cur_node, doc, state)) - exit(EXIT_FAILURE); - /* type leaf */ - break; - - case XML2BIN_LABELTEMPLATE: /* handle in second pass */ - case XML2BIN_TEXT: - case XML2BIN_COMMENT: - case XML2BIN_DATE: - case XML2BIN_REFERENCE: - case XML2BIN_NSURL: /* for future use: where to find global label / type name mappings */ - case XML2BIN_URL: /* for future use: where to find policy */ - /* leaf - nothing to do */ - break; - - default: - printf("Unkonwn token Error (%d) in Policy\n", code); - exit(EXIT_FAILURE); - } - - } - return; -} - -void init_type_mapping(void) -{ - printf("Creating ssid mappings ...\n"); - - /* initialize the ste and chwall type lists */ - TAILQ_INIT(&ste_head); - TAILQ_INIT(&chwall_head); - TAILQ_INIT(&conflictsets_head); -} - -void post_type_mapping(void) -{ - struct type_entry *te; - struct ssid_entry *se; - int i; - - /* determine primary/secondary policy component orders */ - if ((primary == NULLPOLICY) && have_chwall) - primary = CHWALL; /* default if not set */ - else if ((primary == NULLPOLICY) && have_ste) - primary = STE; - - switch (primary) { - - case CHWALL: - if (have_ste) - secondary = STE; - /* else default = NULLPOLICY */ - break; - - case STE: - if (have_chwall) - secondary = CHWALL; - /* else default = NULLPOLICY */ - break; - - default: - /* NULL/NULL policy */ - break; - } - - if (!DEBUG) - return; - - /* print queues */ - if (have_ste) { - printf("STE-Type queue (%s):\n", - (primary == STE) ? "PRIMARY" : "SECONDARY"); - for (te = ste_head.tqh_first; te != NULL; - te = te->entries.tqe_next) - printf("name=%22s, map=%x\n", te->name, te->mapping); - } - if (have_chwall) { - printf("CHWALL-Type queue (%s):\n", - (primary == CHWALL) ? "PRIMARY" : "SECONDARY"); - for (te = chwall_head.tqh_first; te != NULL; - te = te->entries.tqe_next) - printf("name=%s, map=%x\n", te->name, te->mapping); - - printf("Conflictset queue (max=%d):\n", max_conflictsets); - for (se = conflictsets_head.tqh_first; se != NULL; - se = se->entries.tqe_next) { - printf("conflictset name >%s<\n", - se->name ? se->name : "NONAME"); - for (i = 0; i < max_chwall_types; i++) - if (se->row[i]) - printf("#%x ", i); - printf("\n"); - } - } -} - - -/***************** template-related parsing *********************/ - -/* add default ssid at head of ssid queues */ -int init_ssid_queues(void) -{ - struct ssid_entry *default_ssid_chwall, *default_ssid_ste; - - default_ssid_chwall = malloc(sizeof(struct ssid_entry)); - default_ssid_ste = malloc(sizeof(struct ssid_entry)); - - if ((!default_ssid_chwall) || (!default_ssid_ste)) - return -ENOMEM; - - /* default chwall ssid */ - default_ssid_chwall->name = NULL_LABEL_NAME; - default_ssid_chwall->num = max_chwall_ssids++; - default_ssid_chwall->is_ref = 0; - default_ssid_chwall->type = ANY; - - default_ssid_chwall->row = malloc(max_chwall_types); - - if (!default_ssid_chwall->row) - return -ENOMEM; - - memset(default_ssid_chwall->row, 0, max_chwall_types); - - TAILQ_INSERT_TAIL(&chwall_ssid_head, default_ssid_chwall, entries); - current_chwall_ssid_p = default_ssid_chwall; - max_chwall_labels++; - - /* default ste ssid */ - default_ssid_ste->name = NULL_LABEL_NAME; - default_ssid_ste->num = max_ste_ssids++; - default_ssid_ste->is_ref = 0; - default_ssid_ste->type = ANY; - - default_ssid_ste->row = malloc(max_ste_types); - - if (!default_ssid_ste->row) - return -ENOMEM; - - memset(default_ssid_ste->row, 0, max_ste_types); - - TAILQ_INSERT_TAIL(&ste_ssid_head, default_ssid_ste, entries); - current_ste_ssid_p = default_ssid_ste; - max_ste_labels++; - return 0; -} - -int init_next_chwall_ssid(unsigned long state) -{ - struct ssid_entry *ssid = malloc(sizeof(struct ssid_entry)); - - if (!ssid) - return -ENOMEM; - - ssid->name = current_ssid_name; - ssid->num = max_chwall_ssids++; - ssid->is_ref = 0; - - if (state & (1 << XML2BIN_VM)) - ssid->type = VM; - else - ssid->type = RES; - /** - * row: allocate one byte per type; - * [i] != 0 --> mapped type >i< is part of the ssid - */ - ssid->row = malloc(max_chwall_types); - if (!ssid->row) - return -ENOMEM; - - memset(ssid->row, 0, max_chwall_types); - TAILQ_INSERT_TAIL(&chwall_ssid_head, ssid, entries); - current_chwall_ssid_p = ssid; - max_chwall_labels++; - return 0; -} - -int init_next_ste_ssid(unsigned long state) -{ - struct ssid_entry *ssid = malloc(sizeof(struct ssid_entry)); - - if (!ssid) - return -ENOMEM; - - ssid->name = current_ssid_name; - ssid->num = max_ste_ssids++; - ssid->is_ref = 0; - - if (state & (1 << XML2BIN_VM)) - ssid->type = VM; - else - ssid->type = RES; - - /** - * row: allocate one byte per type; - * [i] != 0 --> mapped type >i< is part of the ssid - */ - ssid->row = malloc(max_ste_types); - if (!ssid->row) - return -ENOMEM; - - memset(ssid->row, 0, max_ste_types); - TAILQ_INSERT_TAIL(&ste_ssid_head, ssid, entries); - current_ste_ssid_p = ssid; - max_ste_labels++; - - return 0; -} - - -/* adds a type to the current ssid */ -int add_type(xmlNode * cur_node, xmlDocPtr doc, unsigned long state) -{ - xmlChar *text; - struct type_entry *e; - - text = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1); - if (!text) { - printf("Error reading type name!\n"); - return -EFAULT; - } - /* same for all: 1. lookup type mapping, 2. mark type in ssid */ - switch (state) { - case XML2BIN_VM_STE_S: - case XML2BIN_RES_STE_S: - /* lookup the type mapping and include the type mapping into the array */ - if (!(e = lookup(&ste_head, (char *) text))) { - printf("ERROR: unknown VM STE type >%s<.\n", text); - exit(EXIT_FAILURE); - } - if (current_ste_ssid_p->row[e->mapping]) - printf("Warning: double entry of VM STE type >%s<.\n", text); - - current_ste_ssid_p->row[e->mapping] = 1; - break; - - case XML2BIN_VM_CHWALL_S: - /* lookup the type mapping and include the type mapping into the array */ - if (!(e = lookup(&chwall_head, (char *) text))) { - printf("ERROR: unknown VM CHWALL type >%s<.\n", text); - exit(EXIT_FAILURE); - } - if (current_chwall_ssid_p->row[e->mapping]) - printf("Warning: double entry of VM CHWALL type >%s<.\n", - text); - - current_chwall_ssid_p->row[e->mapping] = 1; - break; - - default: - printf("Incorrect type environment (state = %lx, text = %s).\n", - state, text); - xmlFree(text); - return -EFAULT; - } - return 0; -} - -void set_bootstrap_label(xmlNode * cur_node) -{ - xmlChar *order; - - if ((order = - xmlGetProp(cur_node, (xmlChar *) BOOTSTRAP_LABEL_ATTR_NAME))) - bootstrap_label = (char *) order; - else { - printf("ERROR: No bootstrap label defined!\n"); - exit(EXIT_FAILURE); - } -} - -void walk_labels(xmlNode * start, xmlDocPtr doc, unsigned long state) -{ - xmlNode *cur_node = NULL; - int code; - - for (cur_node = start; cur_node; cur_node = cur_node->next) { - if ((code = totoken((char *) cur_node->name)) < 0) { - printf("Unkonwn token: >%s<. Aborting.\n", cur_node->name); - exit(EXIT_FAILURE); - } - switch (code) { /* adjust state to new state */ - case XML2BIN_SUBJECTS: - set_bootstrap_label(cur_node); - /* fall through */ - case XML2BIN_SECPOL: - case XML2BIN_LABELTEMPLATE: - case XML2BIN_VM: - case XML2BIN_RES: - case XML2BIN_OBJECTS: - walk_labels(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_STETYPES: - /* create new ssid entry to use and point current to it */ - if (init_next_ste_ssid(state)) { - printf("ERROR: creating new ste ssid structure failed.\n"); - exit(EXIT_FAILURE); - } - walk_labels(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_CHWALLTYPES: - /* create new ssid entry to use and point current to it */ - if (init_next_chwall_ssid(state)) { - printf - ("ERROR: creating new chwall ssid structure failed.\n"); - exit(EXIT_FAILURE); - } - walk_labels(cur_node->children, doc, state | (1 << code)); - break; - - case XML2BIN_TYPE: - /* add type to current ssid */ - if (add_type(cur_node, doc, state)) - exit(EXIT_FAILURE); - break; - - case XML2BIN_NAME: - if ((state == XML2BIN_VM_S) || (state == XML2BIN_RES_S)) { - current_ssid_name = (char *) - xmlNodeListGetString(doc, cur_node->xmlChildrenNode, - 1); - if (!current_ssid_name) { - printf("ERROR: empty >vm/res name<!\n"); - exit(EXIT_FAILURE); - } - } else { - printf - ("ERROR: >name< >%s< out of context (state = 0x%lx.\n", - (char *) xmlNodeListGetString(doc, - cur_node-> - xmlChildrenNode, 1), - state); - exit(EXIT_FAILURE); - } - break; - - case XML2BIN_TEXT: - case XML2BIN_COMMENT: - case XML2BIN_POLICYHEADER: - case XML2BIN_STE: - case XML2BIN_CHWALL: - break; - - default: - printf("Unkonwn token Error (%d) in Label Template\n", code); - exit(EXIT_FAILURE); - } - } - return; -} - -/* - * will go away as soon as we have non-static bootstrap ssidref for dom0 - */ -void fixup_bootstrap_label(struct tailhead_ssid *head, - u_int32_t max_types, u_int32_t * max_ssids) -{ - struct ssid_entry *np; - int i; - - /* should not happen if xml / xsd checks work */ - if (!bootstrap_label) { - printf("ERROR: No bootstrap label defined.\n"); - exit(EXIT_FAILURE); - } - - /* search bootstrap_label */ - for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) { - if (!strcmp(np->name, bootstrap_label)) { - break; - } - } - - if (!np) { - /* bootstrap label not found */ - printf("ERROR: Bootstrap label >%s< not found.\n", - bootstrap_label); - exit(EXIT_FAILURE); - } - - /* move this entry ahead in the list right after the default entry so it - * receives ssidref 1/1 */ - TAILQ_REMOVE(head, np, entries); - TAILQ_INSERT_AFTER(head, head->tqh_first, np, entries); - - /* renumber the ssids (we could also just switch places with 1st element) */ - for (np = head->tqh_first, i = 0; np != NULL; - np = np->entries.tqe_next, i++) - np->num = i; - -} - -void init_label_mapping(void) -{ - - printf("Creating label mappings ...\n"); - /* initialize the ste and chwall type lists */ - TAILQ_INIT(&chwall_ssid_head); - TAILQ_INIT(&ste_ssid_head); - - /* init with default ssids */ - if (init_ssid_queues()) { - printf("ERROR adding default ssids.\n"); - exit(EXIT_FAILURE); - } -} - -void post_label_mapping(void) -{ - struct ssid_entry *np; - int i; - - /* - * now sort bootstrap label to the head of the list - * (for now), dom0 assumes its label in the first - * defined ssidref (1/1). 0/0 is the default non-Label - */ - if (have_chwall) - fixup_bootstrap_label(&chwall_ssid_head, max_chwall_types, - &max_chwall_ssids); - if (have_ste) - fixup_bootstrap_label(&ste_ssid_head, max_ste_types, - &max_ste_ssids); - - if (!DEBUG) - return; - - /* print queues */ - if (have_chwall) { - printf("CHWALL SSID queue (max ssidrefs=%d):\n", max_chwall_ssids); - np = NULL; - for (np = chwall_ssid_head.tqh_first; np != NULL; - np = np->entries.tqe_next) { - printf("SSID #%02u (Label=%s)\n", np->num, np->name); - if (np->is_ref) - printf("REFERENCE"); - else - for (i = 0; i < max_chwall_types; i++) - if (np->row[i]) - printf("#%02d ", i); - printf("\n\n"); - } - } - if (have_ste) { - printf("STE SSID queue (max ssidrefs=%d):\n", max_ste_ssids); - np = NULL; - for (np = ste_ssid_head.tqh_first; np != NULL; - np = np->entries.tqe_next) { - printf("SSID #%02u (Label=%s)\n", np->num, np->name); - if (np->is_ref) - printf("REFERENCE"); - else - for (i = 0; i < max_ste_types; i++) - if (np->row[i]) - printf("#%02d ", i); - printf("\n\n"); - } - } -} - -void create_mappings(xmlDocPtr doc) -{ - xmlNode *doc_root_node = xmlDocGetRootElement(doc); - - /* walk the XML policy tree and fill in types and labels */ - init_type_mapping(); - walk_policy(doc_root_node, doc, XML2BIN_NULL); /* first pass: types */ - post_type_mapping(); - init_label_mapping(); - walk_labels(doc_root_node, doc, XML2BIN_NULL); /* second pass: labels */ - post_label_mapping(); -} - -/***************** writing the binary policy *********************/ - -/* - * the mapping file is ascii-based since it will likely be used from - * within scripts (using awk, grep, etc.); - * - * We print from high-level to low-level information so that with one - * pass, any symbol can be resolved (e.g. Label -> types) - */ -int write_mapping(char *filename) -{ - - struct ssid_entry *e; - struct type_entry *t; - int i; - FILE *file; - - if ((file = fopen(filename, "w")) == NULL) - return -EIO; - - fprintf(file, "POLICYREFERENCENAME %s\n", policy_reference_name); - fprintf(file, "MAGIC %08x\n", ACM_MAGIC); - fprintf(file, "POLICY FILE %s\n", policy_filename); - fprintf(file, "BINARY FILE %s\n", binary_filename); - if (have_chwall) { - fprintf(file, "MAX-CHWALL-TYPES %08x\n", max_chwall_types); - fprintf(file, "MAX-CHWALL-SSIDS %08x\n", max_chwall_ssids); - fprintf(file, "MAX-CHWALL-LABELS %08x\n", max_chwall_labels); - } - if (have_ste) { - fprintf(file, "MAX-STE-TYPES %08x\n", max_ste_types); - fprintf(file, "MAX-STE-SSIDS %08x\n", max_ste_ssids); - fprintf(file, "MAX-STE-LABELS %08x\n", max_ste_labels); - } - fprintf(file, "\n"); - - /* primary / secondary order for combined ssid synthesis/analysis - * if no primary is named, then chwall is primary */ - switch (primary) { - case CHWALL: - fprintf(file, "PRIMARY CHWALL\n"); - break; - - case STE: - fprintf(file, "PRIMARY STE\n"); - break; - - default: - fprintf(file, "PRIMARY NULL\n"); - break; - } - - switch (secondary) { - case CHWALL: - fprintf(file, "SECONDARY CHWALL\n"); - break; - - case STE: - fprintf(file, "SECONDARY STE\n"); - break; - - default: - fprintf(file, "SECONDARY NULL\n"); - break; - } - fprintf(file, "\n"); - - /* first labels to ssid mappings */ - if (have_chwall) { - for (e = chwall_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - fprintf(file, "LABEL->SSID %s CHWALL %-25s %8x\n", - (e->type == - VM) ? "VM " : ((e->type == RES) ? "RES" : "ANY"), - e->name, e->num); - } - fprintf(file, "\n"); - } - if (have_ste) { - for (e = ste_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - fprintf(file, "LABEL->SSID %s STE %-25s %8x\n", - (e->type == - VM) ? "VM " : ((e->type == RES) ? "RES" : "ANY"), - e->name, e->num); - } - fprintf(file, "\n"); - } - - /* second ssid to type mappings */ - if (have_chwall) { - for (e = chwall_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - if (e->is_ref) - continue; - - fprintf(file, "SSID->TYPE CHWALL %08x", e->num); - - for (i = 0; i < max_chwall_types; i++) - if (e->row[i]) - fprintf(file, " %s", type_by_mapping(&chwall_head, i)); - - fprintf(file, "\n"); - } - fprintf(file, "\n"); - } - if (have_ste) { - for (e = ste_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - if (e->is_ref) - continue; - - fprintf(file, "SSID->TYPE STE %08x", e->num); - - for (i = 0; i < max_ste_types; i++) - if (e->row[i]) - fprintf(file, " %s", type_by_mapping(&ste_head, i)); - - fprintf(file, "\n"); - } - fprintf(file, "\n"); - } - /* third type mappings */ - if (have_chwall) { - for (t = chwall_head.tqh_first; t != NULL; t = t->entries.tqe_next) { - fprintf(file, "TYPE CHWALL %-25s %8x\n", - t->name, t->mapping); - } - fprintf(file, "\n"); - } - if (have_ste) { - for (t = ste_head.tqh_first; t != NULL; t = t->entries.tqe_next) { - fprintf(file, "TYPE STE %-25s %8x\n", - t->name, t->mapping); - } - fprintf(file, "\n"); - } - fclose(file); - return 0; -} - - -unsigned char *write_policy_reference_binary(u_int32_t * len_pr) -{ - unsigned char *buf, *ptr; - struct acm_policy_reference_buffer *pr_header; - u_int32_t len; - u_int32_t name_len; - - if (policy_reference_name == NULL) { - printf("ERROR: No policy reference name found.\n"); - exit(EXIT_FAILURE); - } - name_len = strlen(policy_reference_name) + 1; /* strend '\0' */ - len = sizeof(struct acm_policy_reference_buffer) + name_len; - len = (len + 7) & ~7; /* Alignment. */ - buf = malloc(len); - ptr = buf; - - if (!buf) { - printf - ("ERROR: out of memory allocating label reference buffer.\n"); - exit(EXIT_FAILURE); - } - memset (buf, 0, len); - pr_header = (struct acm_policy_reference_buffer *) buf; - pr_header->len = htonl(name_len); - ptr += sizeof(struct acm_policy_reference_buffer); - strcpy((char *) ptr, policy_reference_name); - - (*len_pr) = len; - return buf; -} - - -unsigned char *write_chwall_binary(u_int32_t * len_chwall) -{ - unsigned char *buf, *ptr; - struct acm_chwall_policy_buffer *chwall_header; - u_int32_t len; - struct ssid_entry *e; - int i; - - if (!have_chwall) - return NULL; - - len = sizeof(struct acm_chwall_policy_buffer) + - sizeof(type_t) * max_chwall_types * max_chwall_ssids + - sizeof(type_t) * max_chwall_types * max_conflictsets; - - buf = malloc(len); - ptr = buf; - - if (!buf) { - printf("ERROR: out of memory allocating chwall buffer.\n"); - exit(EXIT_FAILURE); - } - /* chwall has 3 parts : header, types, conflictsets */ - - chwall_header = (struct acm_chwall_policy_buffer *) buf; - chwall_header->chwall_max_types = htonl(max_chwall_types); - chwall_header->chwall_max_ssidrefs = htonl(max_chwall_ssids); - chwall_header->policy_code = htonl(ACM_CHINESE_WALL_POLICY); - chwall_header->policy_version = htonl(ACM_CHWALL_VERSION); - chwall_header->chwall_ssid_offset = - htonl(sizeof(struct acm_chwall_policy_buffer)); - chwall_header->chwall_max_conflictsets = htonl(max_conflictsets); - chwall_header->chwall_conflict_sets_offset = - htonl(ntohl(chwall_header->chwall_ssid_offset) + - sizeof(domaintype_t) * max_chwall_ssids * max_chwall_types); - chwall_header->chwall_running_types_offset = 0; - chwall_header->chwall_conflict_aggregate_offset = 0; - ptr += sizeof(struct acm_chwall_policy_buffer); - - /* types */ - for (e = chwall_ssid_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - if (e->is_ref) - continue; - - for (i = 0; i < max_chwall_types; i++) - ((type_t *) ptr)[i] = htons((type_t) e->row[i]); - - ptr += sizeof(type_t) * max_chwall_types; - } - - /* conflictsets */ - for (e = conflictsets_head.tqh_first; e != NULL; - e = e->entries.tqe_next) { - for (i = 0; i < max_chwall_types; i++) - ((type_t *) ptr)[i] = htons((type_t) e->row[i]); - - ptr += sizeof(type_t) * max_chwall_types; - } - - if ((ptr - buf) != len) { - printf("ERROR: wrong lengths in %s.\n", __func__); - exit(EXIT_FAILURE); - } - - (*len_chwall) = len; - return buf; -} - -unsigned char *write_ste_binary(u_int32_t * len_ste) -{ - unsigned char *buf, *ptr; - struct acm_ste_policy_buffer *ste_header; - struct ssid_entry *e; - u_int32_t len; - int i; - - if (!have_ste) - return NULL; - - len = sizeof(struct acm_ste_policy_buffer) + - sizeof(type_t) * max_ste_types * max_ste_ssids; - - buf = malloc(len); - ptr = buf; - - if (!buf) { - printf("ERROR: out of memory allocating chwall buffer.\n"); - exit(EXIT_FAILURE); - } - - /* fill buffer */ - ste_header = (struct acm_ste_policy_buffer *) buf; - ste_header->policy_version = htonl(ACM_STE_VERSION); - ste_header->policy_code = htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); - ste_header->ste_max_types = htonl(max_ste_types); - ste_header->ste_max_ssidrefs = htonl(max_ste_ssids); - ste_header->ste_ssid_offset = - htonl(sizeof(struct acm_ste_policy_buffer)); - - ptr += sizeof(struct acm_ste_policy_buffer); - - /* types */ - for (e = ste_ssid_head.tqh_first; e != NULL; e = e->entries.tqe_next) { - if (e->is_ref) - continue; - - for (i = 0; i < max_ste_types; i++) - ((type_t *) ptr)[i] = htons((type_t) e->row[i]); - - ptr += sizeof(type_t) * max_ste_types; - } - - if ((ptr - buf) != len) { - printf("ERROR: wrong lengths in %s.\n", __func__); - exit(EXIT_FAILURE); - } - (*len_ste) = len; - return buf; /* for now */ -} - -static ssize_t write_padded(int fd, const void *buf, size_t count) -{ - int rc; - static const char padding[7] = {0,0,0,0,0,0,0}; - unsigned int len = ROUND8(count) - count; - - rc = write(fd, buf, count); - if (rc == count && len > 0) { - write(fd, padding, len); - } - return rc; -} - -int write_binary(char *filename) -{ - struct acm_policy_buffer header; - unsigned char *ste_buffer = NULL, *chwall_buffer = - NULL, *policy_reference_buffer = NULL; - u_int32_t len; - int fd, ret = 0; - uint32_t major = 0, minor = 0; - - u_int32_t len_ste = 0, len_chwall = 0, len_pr = 0; /* length of policy components */ - - if (policy_version_string) - sscanf(policy_version_string,"%d.%d", &major, &minor); - - /* open binary file */ - if ((fd = - open(filename, O_WRONLY | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR)) <= 0) { - ret = -EIO; - goto out1; - } - policy_reference_buffer = write_policy_reference_binary(&len_pr); - ste_buffer = write_ste_binary(&len_ste); - chwall_buffer = write_chwall_binary(&len_chwall); - - /* determine primary component (default chwall) */ - header.policy_version = htonl(ACM_POLICY_VERSION); - header.magic = htonl(ACM_MAGIC); - header.xml_pol_version.major = htonl(major); - header.xml_pol_version.minor = htonl(minor); - - len = ROUND8(sizeof(struct acm_policy_buffer)); - if (have_chwall) - len += ROUND8(len_chwall); - if (have_ste) - len += ROUND8(len_ste); - len += ROUND8(len_pr); /* policy reference is mandatory */ - header.len = htonl(len); - - header.policy_reference_offset = - htonl(ROUND8(sizeof(struct acm_policy_buffer))); - - header.primary_buffer_offset = - htonl(ROUND8(sizeof(struct acm_policy_buffer)) + - ROUND8(len_pr)); - if (primary == CHWALL) { - header.primary_policy_code = htonl(ACM_CHINESE_WALL_POLICY); - header.secondary_buffer_offset = - htonl(ROUND8(sizeof(struct acm_policy_buffer)) + - ROUND8(len_pr) + - ROUND8(len_chwall)); - } else if (primary == STE) { - header.primary_policy_code = - htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); - header.secondary_buffer_offset = - htonl(ROUND8(sizeof(struct acm_policy_buffer)) + - ROUND8(len_pr) + - ROUND8(len_ste)); - } else { - /* null policy */ - header.primary_policy_code = htonl(ACM_NULL_POLICY); - header.secondary_buffer_offset = header.primary_buffer_offset; - } - - if (secondary == CHWALL) - header.secondary_policy_code = htonl(ACM_CHINESE_WALL_POLICY); - else if (secondary == STE) - header.secondary_policy_code = - htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY); - else - header.secondary_policy_code = htonl(ACM_NULL_POLICY); - - if (write_padded(fd, (void *) &header, sizeof(struct acm_policy_buffer)) - != sizeof(struct acm_policy_buffer)) { - ret = -EIO; - goto out1; - } - - /* write label reference name */ - if (write_padded(fd, policy_reference_buffer, len_pr) != len_pr) { - ret = -EIO; - goto out1; - } - /* write primary policy component */ - if (primary == CHWALL) { - if (write_padded(fd, chwall_buffer, len_chwall) != len_chwall) { - ret = -EIO; - goto out1; - } - } else if (primary == STE) { - if (write_padded(fd, ste_buffer, len_ste) != len_ste) { - ret = -EIO; - goto out1; - } - } else; /* NULL POLICY has no policy data */ - - /* write secondary policy component */ - if (secondary == CHWALL) { - if (write_padded(fd, chwall_buffer, len_chwall) != len_chwall) { - ret = -EIO; - goto out1; - } - } else if (secondary == STE) { - if (write_padded(fd, ste_buffer, len_ste) != len_ste) { - ret = -EIO; - goto out1; - } - } else; /* NULL POLICY has no policy data */ - - out1: - /* cleanup */ - if (policy_reference_buffer) - free(policy_reference_buffer); - if (chwall_buffer) - free(chwall_buffer); - if (ste_buffer) - free(ste_buffer); - close(fd); - return ret; -} - -int is_valid(xmlDocPtr doc) -{ - int err = 0; - xmlSchemaPtr schema_ctxt = NULL; - xmlSchemaParserCtxtPtr schemaparser_ctxt = NULL; - xmlSchemaValidCtxtPtr schemavalid_ctxt = NULL; - - schemaparser_ctxt = xmlSchemaNewParserCtxt(schema_filename); - schema_ctxt = xmlSchemaParse(schemaparser_ctxt); - schemavalid_ctxt = xmlSchemaNewValidCtxt(schema_ctxt); - -#ifdef VALIDATE_SCHEMA - /* only tested to be available from libxml2-2.6.20 upwards */ - if ((err = xmlSchemaIsValid(schemavalid_ctxt)) != 1) { - printf("ERROR: Invalid schema file %s (err=%d)\n", - schema_filename, err); - err = -EIO; - goto out; - } else - printf("XML Schema %s valid.\n", schema_filename); -#endif - if ((err = xmlSchemaValidateDoc(schemavalid_ctxt, doc))) { - err = -EIO; - goto out; - } - out: - xmlSchemaFreeValidCtxt(schemavalid_ctxt); - xmlSchemaFreeParserCtxt(schemaparser_ctxt); - xmlSchemaFree(schema_ctxt); - return (err != 0) ? 0 : 1; -} - -int main(int argc, char **argv) -{ - xmlDocPtr policydoc = NULL; - - int err = EXIT_FAILURE; - - char *file_prefix; - int prefix_len; - - int opt_char; - char *policy_dir = POLICY_DIR; - - if (ACM_POLICY_VERSION != WRITTEN_AGAINST_ACM_POLICY_VERSION) { - printf - ("ERROR: This program was written against an older ACM version.\n"); - printf("ERROR: ACM_POLICY_VERSION=%d, WRITTEN AGAINST= %d.\n", - ACM_POLICY_VERSION, WRITTEN_AGAINST_ACM_POLICY_VERSION); - exit(EXIT_FAILURE); - } - - while ((opt_char = getopt(argc, argv, "d:")) != -1) { - switch (opt_char) { - case 'd': - policy_dir = malloc(strlen(optarg) + 2); /* null terminator and possibly "/" */ - if (!policy_dir) { - printf("ERROR allocating directory name memory.\n"); - exit(EXIT_FAILURE); - } - strcpy(policy_dir, optarg); - if (policy_dir[strlen(policy_dir) - 1] != '/') - strcat(policy_dir, "/"); - break; - - default: - usage(basename(argv[0])); - } - } - - if ((argc - optind) != 1) - usage(basename(argv[0])); - - printf("arg=%s\n", argv[optind]); - - prefix_len = - strlen(policy_dir) + strlen(argv[optind]) + - 1 /* null terminator */ ; - - file_prefix = malloc(prefix_len); - policy_filename = malloc(prefix_len + strlen(POLICY_EXTENSION)); - binary_filename = malloc(prefix_len + strlen(BINARY_EXTENSION)); - mapping_filename = malloc(prefix_len + strlen(MAPPING_EXTENSION)); - schema_filename = - malloc(strlen(policy_dir) + strlen(SCHEMA_FILENAME) + 1); - - if (!file_prefix || !policy_filename || - !binary_filename || !mapping_filename || !schema_filename) { - printf("ERROR allocating file name memory.\n"); - goto out2; - } - - /* create input/output filenames out of prefix */ - strcpy(file_prefix, policy_dir); - strcat(file_prefix, argv[optind]); - - strcpy(policy_filename, file_prefix); - strcpy(binary_filename, file_prefix); - strcpy(mapping_filename, file_prefix); - - strcat(policy_filename, POLICY_EXTENSION); - strcat(binary_filename, BINARY_EXTENSION); - strcat(mapping_filename, MAPPING_EXTENSION); - - strcpy(schema_filename, policy_dir); - strcat(schema_filename, SCHEMA_FILENAME); - - policydoc = xmlParseFile(policy_filename); - - if (policydoc == NULL) { - printf("Error: could not parse file %s.\n", argv[optind]); - goto out; - } - - printf("Validating policy file %s...\n", policy_filename); - - if (!is_valid(policydoc)) { - printf("ERROR: Failed schema-validation for file %s (err=%d)\n", - policy_filename, err); - goto out; - } - - /* create mappings */ - create_mappings(policydoc); - - /* write label mapping file */ - if (write_mapping(mapping_filename)) { - printf("ERROR: writing mapping file %s.\n", mapping_filename); - goto out; - } - - /* write binary file */ - if (write_binary(binary_filename)) { - printf("ERROR: writing binary file %s.\n", binary_filename); - goto out; - } - err = EXIT_SUCCESS; - /* write stats */ - if (have_chwall) { - printf("Max chwall labels: %u\n", max_chwall_labels); - printf("Max chwall-types: %u\n", max_chwall_types); - printf("Max chwall-ssids: %u\n", max_chwall_ssids); - } - - if (have_ste) { - printf("Max ste labels: %u\n", max_ste_labels); - printf("Max ste-types: %u\n", max_ste_types); - printf("Max ste-ssids: %u\n", max_ste_ssids); - } - /* cleanup */ - out: - xmlFreeDoc(policydoc); - out2: - xmlCleanupParser(); - return err; -} - -/* - * Local variables: - * mode: C - * c-set-style: "BSD" - * c-basic-offset: 4 - * tab-width: 4 - * indent-tabs-mode: nil - * End: - */ |