aboutsummaryrefslogtreecommitdiffstats
path: root/tools/security/secpol_xml2bin.c
diff options
context:
space:
mode:
Diffstat (limited to 'tools/security/secpol_xml2bin.c')
-rw-r--r--tools/security/secpol_xml2bin.c1457
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:
- */