source: trunk/packages/xen-common/xen-common/tools/security/secpol_xml2bin.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 43.3 KB
Line 
1/****************************************************************
2 * secpol_xml2bin.c
3 *
4 * Copyright (C) 2005 IBM Corporation
5 *
6 * Author: Reiner Sailer <sailer@us.ibm.com>
7 *
8 * Maintained:
9 * Reiner Sailer <sailer@us.ibm.com>
10 * Ray Valdez <rvaldez@us.ibm.com>
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License as
14 * published by the Free Software Foundation, version 2 of the
15 * License.
16 *
17 * sHype policy translation tool. This tool takes an XML
18 * policy specification as input and produces a binary
19 * policy file that can be loaded into Xen through the
20 * ACM operations (xensec_tool loadpolicy) interface or at
21 * boot time (grub module parameter)
22 *
23 * indent -i4 -kr -nut
24 */
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <errno.h>
29#include <libgen.h>
30#include <fcntl.h>
31#include <unistd.h>
32#include <sys/types.h>
33#include <sys/stat.h>
34#include <sys/queue.h>
35#include <netinet/in.h>
36#include <libxml/xmlschemas.h>
37#include <libxml/parser.h>
38#include <libxml/tree.h>
39#include <libxml/xmlreader.h>
40#include <stdint.h>
41#include <xen/acm.h>
42
43#include "secpol_xml2bin.h"
44
45#define DEBUG    0
46
47#define NULL_LABEL_NAME "__NULL_LABEL__"
48
49#define ROUND8(x)   ((x + 7) & ~7)
50
51/* primary / secondary policy component setting */
52enum policycomponent { CHWALL, STE, NULLPOLICY }
53    primary = NULLPOLICY, secondary = NULLPOLICY;
54
55/* general list element for ste and chwall type queues */
56struct type_entry {
57    TAILQ_ENTRY(type_entry) entries;
58    char *name;                 /* name of type from xml file */
59    type_t mapping;             /* type mapping into 16bit */
60};
61
62TAILQ_HEAD(tailhead, type_entry) ste_head, chwall_head;
63
64/* general list element for all label queues */
65enum label_type { VM, RES, ANY };
66struct ssid_entry {
67    TAILQ_ENTRY(ssid_entry) entries;
68    char *name;                 /* label name */
69    enum label_type type;       /* type: VM / RESOURCE LABEL */
70    u_int32_t num;              /* ssid or referenced ssid */
71    int is_ref;                 /* if this entry references earlier ssid number */
72    unsigned char *row;         /* index of types (if not a reference) */
73};
74
75TAILQ_HEAD(tailhead_ssid, ssid_entry) ste_ssid_head, chwall_ssid_head,
76    conflictsets_head;
77struct ssid_entry *current_chwall_ssid_p = NULL;
78struct ssid_entry *current_ste_ssid_p = NULL;
79struct ssid_entry *current_conflictset_p = NULL;
80
81/* which label to assign to dom0 during boot */
82char *bootstrap_label;
83
84u_int32_t max_ste_ssids = 0;
85u_int32_t max_chwall_ssids = 0;
86u_int32_t max_chwall_labels = 0;
87u_int32_t max_ste_labels = 0;
88u_int32_t max_conflictsets = 0;
89
90char *current_ssid_name;        /* store name until structure is allocated */
91char *current_conflictset_name; /* store name until structure is allocated */
92
93/* dynamic list of type mappings for STE */
94u_int32_t max_ste_types = 0;
95
96/* dynamic list of type mappings for CHWALL */
97u_int32_t max_chwall_types = 0;
98
99/* dynamic list of conflict sets */
100int max_conflict_set = 0;
101
102/* which policies are defined */
103int have_ste = 0;
104int have_chwall = 0;
105
106/* input/output file names */
107char *policy_filename = NULL,
108    *binary_filename = NULL,
109    *mapping_filename = NULL, *schema_filename = NULL;
110
111char *policy_reference_name = NULL;
112
113char *policy_version_string = NULL;
114
115void walk_labels(xmlNode * start, xmlDocPtr doc, unsigned long state);
116
117void usage(char *prg)
118{
119    printf(
120    "Usage: %s [OPTIONS] POLICYNAME\n"
121    "POLICYNAME is the directory name within the policy directory\n"
122    "that contains the policy files.  The default policy directory\n"
123    "is '%s' (see the '-d' option below to change it)\n"
124    "The policy files contained in the POLICYNAME directory must be named:\n"
125    "\tPOLICYNAME-security_policy.xml\n"
126    "\tPOLICYNAME-security_label_template.xml\n\n"
127    "OPTIONS:\n"
128    "\t-d POLICYDIR\n"
129    "\t\tUse POLICYDIR as the policy directory. This directory must \n"
130    "\t\tcontain the policy schema file 'security_policy.xsd'\n",
131    prg, POLICY_DIR);
132    exit(EXIT_FAILURE);
133}
134
135
136/***************** policy-related parsing *********************/
137
138char *type_by_mapping(struct tailhead *head, u_int32_t mapping)
139{
140    struct type_entry *np;
141    for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next)
142        if (np->mapping == mapping)
143            return np->name;
144    return NULL;
145}
146
147
148struct type_entry *lookup(struct tailhead *head, char *name)
149{
150    struct type_entry *np;
151    for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next)
152        if (!(strcmp(np->name, name)))
153            return np;
154    return NULL;
155}
156
157/* enforces single-entry lists */
158int add_entry(struct tailhead *head, char *name, type_t mapping)
159{
160    struct type_entry *e;
161    if (lookup(head, name)) {
162        printf("Error: Type >%s< defined more than once.\n", name);
163        return -EFAULT;         /* already in the list */
164    }
165    if (!(e = malloc(sizeof(struct type_entry))))
166        return -ENOMEM;
167
168    e->name = name;
169    e->mapping = mapping;
170    TAILQ_INSERT_TAIL(head, e, entries);
171    return 0;
172}
173
174int totoken(char *tok)
175{
176    int i;
177    for (i = 0; token[i] != NULL; i++)
178        if (!strcmp(token[i], tok))
179            return i;
180    return -EFAULT;
181}
182
183/* conflictsets use the same data structure as ssids; since
184 * they are similar in structure (set of types)
185 */
186int init_next_conflictset(void)
187{
188    struct ssid_entry *conflictset = malloc(sizeof(struct ssid_entry));
189
190    if (!conflictset)
191        return -ENOMEM;
192
193    conflictset->name = current_conflictset_name;
194    conflictset->num = max_conflictsets++;
195    conflictset->is_ref = 0;    /* n/a for conflictsets */
196        /**
197         *  row: allocate one byte per type;
198         *  [i] != 0 --> mapped type >i< is part of the conflictset
199         */
200    conflictset->row = malloc(max_chwall_types);
201    if (!conflictset->row)
202        return -ENOMEM;
203
204    memset(conflictset->row, 0, max_chwall_types);
205    TAILQ_INSERT_TAIL(&conflictsets_head, conflictset, entries);
206    current_conflictset_p = conflictset;
207    return 0;
208}
209
210int register_type(xmlNode * cur_node, xmlDocPtr doc, unsigned long state)
211{
212    xmlChar *text;
213    struct type_entry *e;
214
215
216    text = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
217    if (!text) {
218        printf("Error reading type name!\n");
219        return -EFAULT;
220    }
221
222    switch (state) {
223    case XML2BIN_stetype_S:
224        if (add_entry(&ste_head, (char *) text, max_ste_types)) {
225            xmlFree(text);
226            return -EFAULT;
227        }
228        max_ste_types++;
229        break;
230
231    case XML2BIN_chwalltype_S:
232        if (add_entry(&chwall_head, (char *) text, max_chwall_types)) {
233            xmlFree(text);
234            return -EFAULT;
235        }
236        max_chwall_types++;
237        break;
238
239    case XML2BIN_conflictsettype_S:
240        /* a) search the type in the chwall_type list */
241        e = lookup(&chwall_head, (char *) text);
242        if (e == NULL) {
243            printf("CS type >%s< not a CHWALL type.\n", text);
244            xmlFree(text);
245            return -EFAULT;
246        }
247        /* b) add type entry to the current cs set */
248        if (current_conflictset_p->row[e->mapping]) {
249            printf
250                ("ERROR: Double entry of type >%s< in conflict set %d.\n",
251                 text, current_conflictset_p->num);
252            xmlFree(text);
253            return -EFAULT;
254        }
255        current_conflictset_p->row[e->mapping] = 1;
256        break;
257
258    default:
259        printf("Incorrect type environment (state = %lx, text = %s).\n",
260               state, text);
261        xmlFree(text);
262        return -EFAULT;
263    }
264    return 0;
265}
266
267void set_component_type(xmlNode * cur_node, enum policycomponent pc)
268{
269    xmlChar *order;
270
271    if ((order =
272         xmlGetProp(cur_node, (xmlChar *) PRIMARY_COMPONENT_ATTR_NAME))) {
273        if (strcmp((char *) order, PRIMARY_COMPONENT)) {
274            printf("ERROR: Illegal attribut value >order=%s<.\n",
275                   (char *) order);
276            xmlFree(order);
277            exit(EXIT_FAILURE);
278        }
279        if (primary != NULLPOLICY) {
280            printf("ERROR: Primary Policy Component set twice!\n");
281            exit(EXIT_FAILURE);
282        }
283        primary = pc;
284        xmlFree(order);
285    }
286}
287
288void walk_policy(xmlNode * start, xmlDocPtr doc, unsigned long state)
289{
290    xmlNode *cur_node = NULL;
291    int code;
292
293    for (cur_node = start; cur_node; cur_node = cur_node->next) {
294        if ((code = totoken((char *) cur_node->name)) < 0) {
295            printf("Unknown token: >%s<. Aborting.\n", cur_node->name);
296            exit(EXIT_FAILURE);
297        }
298        switch (code) {         /* adjust state to new state */
299        case XML2BIN_SECPOL:
300        case XML2BIN_STETYPES:
301        case XML2BIN_CHWALLTYPES:
302        case XML2BIN_CONFLICTSETS:
303        case XML2BIN_POLICYHEADER:
304        case XML2BIN_FROMPOLICY:
305            walk_policy(cur_node->children, doc, state | (1 << code));
306            break;
307
308        case XML2BIN_POLICYNAME:       /* get policy reference name .... */
309            if (state != XML2BIN_PN_S &&
310                state != XML2BIN_PN_frompolicy_S) {
311                printf("ERROR: >Url< >%s< out of context.\n",
312                       (char *) xmlNodeListGetString(doc,
313                                                     cur_node->
314                                                     xmlChildrenNode, 1));
315                exit(EXIT_FAILURE);
316            }
317            if (state == XML2BIN_PN_S) {
318                policy_reference_name = (char *)
319                    xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
320                if (!policy_reference_name) {
321                    printf("ERROR: empty >policy reference name (Url)<!\n");
322                    exit(EXIT_FAILURE);
323                } else
324                    printf("Policy Reference name (Url): %s\n",
325                           policy_reference_name);
326            }
327            break;
328
329        case XML2BIN_VERSION:         /* get policy version number .... */
330            if (state != XML2BIN_PN_S &&
331                state != XML2BIN_PN_frompolicy_S) {
332                printf("ERROR: >Url< >%s< out of context.\n",
333                       (char *) xmlNodeListGetString(doc,
334                                                     cur_node->
335                                                     xmlChildrenNode, 1));
336                exit(EXIT_FAILURE);
337            }
338            if (state == XML2BIN_PN_S) {
339                policy_version_string = (char *)
340                    xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
341                if (!policy_version_string) {
342                    printf("ERROR: empty >policy version string <!\n");
343                    exit(EXIT_FAILURE);
344                } else
345                    printf("Policy version string: %s\n",
346                           policy_version_string);
347            }
348            break;
349
350        case XML2BIN_STE:
351            if (WRITTEN_AGAINST_ACM_STE_VERSION != ACM_STE_VERSION) {
352                printf
353                    ("ERROR: This program was written against another STE version.\n");
354                exit(EXIT_FAILURE);
355            }
356            have_ste = 1;
357            set_component_type(cur_node, STE);
358            walk_policy(cur_node->children, doc, state | (1 << code));
359            break;
360
361        case XML2BIN_CHWALL:
362            if (WRITTEN_AGAINST_ACM_CHWALL_VERSION != ACM_CHWALL_VERSION) {
363                printf
364                    ("ERROR: This program was written against another CHWALL version.\n");
365                exit(EXIT_FAILURE);
366            }
367            have_chwall = 1;
368            set_component_type(cur_node, CHWALL);
369            walk_policy(cur_node->children, doc, state | (1 << code));
370            break;
371
372        case XML2BIN_CSTYPE:
373            current_conflictset_name =
374                (char *) xmlGetProp(cur_node, (xmlChar *) "name");
375            if (!current_conflictset_name)
376                current_conflictset_name = "";
377
378            if (init_next_conflictset()) {
379                printf
380                    ("ERROR: creating new conflictset structure failed.\n");
381                exit(EXIT_FAILURE);
382            }
383            walk_policy(cur_node->children, doc, state | (1 << code));
384            break;
385
386        case XML2BIN_TYPE:
387            if (register_type(cur_node, doc, state))
388                exit(EXIT_FAILURE);
389            /* type leaf */
390            break;
391
392        case XML2BIN_LABELTEMPLATE:    /* handle in second pass */
393        case XML2BIN_TEXT:
394        case XML2BIN_COMMENT:
395        case XML2BIN_DATE:
396        case XML2BIN_REFERENCE:
397        case XML2BIN_NSURL:    /* for future use: where to find global label / type name mappings */
398        case XML2BIN_URL:      /* for future use: where to find policy */
399            /* leaf - nothing to do */
400            break;
401
402        default:
403            printf("Unkonwn token Error (%d) in Policy\n", code);
404            exit(EXIT_FAILURE);
405        }
406
407    }
408    return;
409}
410
411void init_type_mapping(void)
412{
413    printf("Creating ssid mappings ...\n");
414
415    /* initialize the ste and chwall type lists */
416    TAILQ_INIT(&ste_head);
417    TAILQ_INIT(&chwall_head);
418    TAILQ_INIT(&conflictsets_head);
419}
420
421void post_type_mapping(void)
422{
423    struct type_entry *te;
424    struct ssid_entry *se;
425    int i;
426
427    /* determine primary/secondary policy component orders */
428    if ((primary == NULLPOLICY) && have_chwall)
429        primary = CHWALL;       /* default if not set */
430    else if ((primary == NULLPOLICY) && have_ste)
431        primary = STE;
432
433    switch (primary) {
434
435    case CHWALL:
436        if (have_ste)
437            secondary = STE;
438        /* else default = NULLPOLICY */
439        break;
440
441    case STE:
442        if (have_chwall)
443            secondary = CHWALL;
444        /* else default = NULLPOLICY */
445        break;
446
447    default:
448        /* NULL/NULL policy */
449        break;
450    }
451
452    if (!DEBUG)
453        return;
454
455    /* print queues */
456    if (have_ste) {
457        printf("STE-Type queue (%s):\n",
458               (primary == STE) ? "PRIMARY" : "SECONDARY");
459        for (te = ste_head.tqh_first; te != NULL;
460             te = te->entries.tqe_next)
461            printf("name=%22s, map=%x\n", te->name, te->mapping);
462    }
463    if (have_chwall) {
464        printf("CHWALL-Type queue (%s):\n",
465               (primary == CHWALL) ? "PRIMARY" : "SECONDARY");
466        for (te = chwall_head.tqh_first; te != NULL;
467             te = te->entries.tqe_next)
468            printf("name=%s, map=%x\n", te->name, te->mapping);
469
470        printf("Conflictset queue (max=%d):\n", max_conflictsets);
471        for (se = conflictsets_head.tqh_first; se != NULL;
472             se = se->entries.tqe_next) {
473            printf("conflictset name >%s<\n",
474                   se->name ? se->name : "NONAME");
475            for (i = 0; i < max_chwall_types; i++)
476                if (se->row[i])
477                    printf("#%x ", i);
478            printf("\n");
479        }
480    }
481}
482
483
484/***************** template-related parsing *********************/
485
486/* add default ssid at head of ssid queues */
487int init_ssid_queues(void)
488{
489    struct ssid_entry *default_ssid_chwall, *default_ssid_ste;
490
491    default_ssid_chwall = malloc(sizeof(struct ssid_entry));
492    default_ssid_ste = malloc(sizeof(struct ssid_entry));
493
494    if ((!default_ssid_chwall) || (!default_ssid_ste))
495        return -ENOMEM;
496
497    /* default chwall ssid */
498    default_ssid_chwall->name = NULL_LABEL_NAME;
499    default_ssid_chwall->num = max_chwall_ssids++;
500    default_ssid_chwall->is_ref = 0;
501    default_ssid_chwall->type = ANY;
502
503    default_ssid_chwall->row = malloc(max_chwall_types);
504
505    if (!default_ssid_chwall->row)
506        return -ENOMEM;
507
508    memset(default_ssid_chwall->row, 0, max_chwall_types);
509
510    TAILQ_INSERT_TAIL(&chwall_ssid_head, default_ssid_chwall, entries);
511    current_chwall_ssid_p = default_ssid_chwall;
512    max_chwall_labels++;
513
514    /* default ste ssid */
515    default_ssid_ste->name = NULL_LABEL_NAME;
516    default_ssid_ste->num = max_ste_ssids++;
517    default_ssid_ste->is_ref = 0;
518    default_ssid_ste->type = ANY;
519
520    default_ssid_ste->row = malloc(max_ste_types);
521
522    if (!default_ssid_ste->row)
523        return -ENOMEM;
524
525    memset(default_ssid_ste->row, 0, max_ste_types);
526
527    TAILQ_INSERT_TAIL(&ste_ssid_head, default_ssid_ste, entries);
528    current_ste_ssid_p = default_ssid_ste;
529    max_ste_labels++;
530    return 0;
531}
532
533int init_next_chwall_ssid(unsigned long state)
534{
535    struct ssid_entry *ssid = malloc(sizeof(struct ssid_entry));
536
537    if (!ssid)
538        return -ENOMEM;
539
540    ssid->name = current_ssid_name;
541    ssid->num = max_chwall_ssids++;
542    ssid->is_ref = 0;
543
544    if (state & (1 << XML2BIN_VM))
545        ssid->type = VM;
546    else
547        ssid->type = RES;
548        /**
549         *  row: allocate one byte per type;
550         *  [i] != 0 --> mapped type >i< is part of the ssid
551         */
552    ssid->row = malloc(max_chwall_types);
553    if (!ssid->row)
554        return -ENOMEM;
555
556    memset(ssid->row, 0, max_chwall_types);
557    TAILQ_INSERT_TAIL(&chwall_ssid_head, ssid, entries);
558    current_chwall_ssid_p = ssid;
559    max_chwall_labels++;
560    return 0;
561}
562
563int init_next_ste_ssid(unsigned long state)
564{
565    struct ssid_entry *ssid = malloc(sizeof(struct ssid_entry));
566
567    if (!ssid)
568        return -ENOMEM;
569
570    ssid->name = current_ssid_name;
571    ssid->num = max_ste_ssids++;
572    ssid->is_ref = 0;
573
574    if (state & (1 << XML2BIN_VM))
575        ssid->type = VM;
576    else
577        ssid->type = RES;
578
579        /**
580         *  row: allocate one byte per type;
581         *  [i] != 0 --> mapped type >i< is part of the ssid
582         */
583    ssid->row = malloc(max_ste_types);
584    if (!ssid->row)
585        return -ENOMEM;
586
587    memset(ssid->row, 0, max_ste_types);
588    TAILQ_INSERT_TAIL(&ste_ssid_head, ssid, entries);
589    current_ste_ssid_p = ssid;
590    max_ste_labels++;
591
592    return 0;
593}
594
595
596/* adds a type to the current ssid */
597int add_type(xmlNode * cur_node, xmlDocPtr doc, unsigned long state)
598{
599    xmlChar *text;
600    struct type_entry *e;
601
602    text = xmlNodeListGetString(doc, cur_node->xmlChildrenNode, 1);
603    if (!text) {
604        printf("Error reading type name!\n");
605        return -EFAULT;
606    }
607    /* same for all: 1. lookup type mapping, 2. mark type in ssid */
608    switch (state) {
609    case XML2BIN_VM_STE_S:
610    case XML2BIN_RES_STE_S:
611        /* lookup the type mapping and include the type mapping into the array */
612        if (!(e = lookup(&ste_head, (char *) text))) {
613            printf("ERROR: unknown VM STE type >%s<.\n", text);
614            exit(EXIT_FAILURE);
615        }
616        if (current_ste_ssid_p->row[e->mapping])
617            printf("Warning: double entry of VM STE type >%s<.\n", text);
618
619        current_ste_ssid_p->row[e->mapping] = 1;
620        break;
621
622    case XML2BIN_VM_CHWALL_S:
623        /* lookup the type mapping and include the type mapping into the array */
624        if (!(e = lookup(&chwall_head, (char *) text))) {
625            printf("ERROR: unknown VM CHWALL type >%s<.\n", text);
626            exit(EXIT_FAILURE);
627        }
628        if (current_chwall_ssid_p->row[e->mapping])
629            printf("Warning: double entry of VM CHWALL type >%s<.\n",
630                   text);
631
632        current_chwall_ssid_p->row[e->mapping] = 1;
633        break;
634
635    default:
636        printf("Incorrect type environment (state = %lx, text = %s).\n",
637               state, text);
638        xmlFree(text);
639        return -EFAULT;
640    }
641    return 0;
642}
643
644void set_bootstrap_label(xmlNode * cur_node)
645{
646    xmlChar *order;
647
648    if ((order =
649         xmlGetProp(cur_node, (xmlChar *) BOOTSTRAP_LABEL_ATTR_NAME)))
650        bootstrap_label = (char *) order;
651    else {
652        printf("ERROR: No bootstrap label defined!\n");
653        exit(EXIT_FAILURE);
654    }
655}
656
657void walk_labels(xmlNode * start, xmlDocPtr doc, unsigned long state)
658{
659    xmlNode *cur_node = NULL;
660    int code;
661
662    for (cur_node = start; cur_node; cur_node = cur_node->next) {
663        if ((code = totoken((char *) cur_node->name)) < 0) {
664            printf("Unkonwn token: >%s<. Aborting.\n", cur_node->name);
665            exit(EXIT_FAILURE);
666        }
667        switch (code) {         /* adjust state to new state */
668        case XML2BIN_SUBJECTS:
669            set_bootstrap_label(cur_node);
670            /* fall through */
671        case XML2BIN_SECPOL:
672        case XML2BIN_LABELTEMPLATE:
673        case XML2BIN_VM:
674        case XML2BIN_RES:
675        case XML2BIN_OBJECTS:
676            walk_labels(cur_node->children, doc, state | (1 << code));
677            break;
678
679        case XML2BIN_STETYPES:
680            /* create new ssid entry to use and point current to it */
681            if (init_next_ste_ssid(state)) {
682                printf("ERROR: creating new ste ssid structure failed.\n");
683                exit(EXIT_FAILURE);
684            }
685            walk_labels(cur_node->children, doc, state | (1 << code));
686            break;
687
688        case XML2BIN_CHWALLTYPES:
689            /* create new ssid entry to use and point current to it */
690            if (init_next_chwall_ssid(state)) {
691                printf
692                    ("ERROR: creating new chwall ssid structure failed.\n");
693                exit(EXIT_FAILURE);
694            }
695            walk_labels(cur_node->children, doc, state | (1 << code));
696            break;
697
698        case XML2BIN_TYPE:
699            /* add type to current ssid */
700            if (add_type(cur_node, doc, state))
701                exit(EXIT_FAILURE);
702            break;
703
704        case XML2BIN_NAME:
705            if ((state == XML2BIN_VM_S) || (state == XML2BIN_RES_S)) {
706                current_ssid_name = (char *)
707                    xmlNodeListGetString(doc, cur_node->xmlChildrenNode,
708                                         1);
709                if (!current_ssid_name) {
710                    printf("ERROR: empty >vm/res name<!\n");
711                    exit(EXIT_FAILURE);
712                }
713            } else {
714                printf
715                    ("ERROR: >name< >%s< out of context (state = 0x%lx.\n",
716                     (char *) xmlNodeListGetString(doc,
717                                                   cur_node->
718                                                   xmlChildrenNode, 1),
719                     state);
720                exit(EXIT_FAILURE);
721            }
722            break;
723
724        case XML2BIN_TEXT:
725        case XML2BIN_COMMENT:
726        case XML2BIN_POLICYHEADER:
727        case XML2BIN_STE:
728        case XML2BIN_CHWALL:
729            break;
730
731        default:
732            printf("Unkonwn token Error (%d) in Label Template\n", code);
733            exit(EXIT_FAILURE);
734        }
735    }
736    return;
737}
738
739/*
740 * will go away as soon as we have non-static bootstrap ssidref for dom0
741 */
742void fixup_bootstrap_label(struct tailhead_ssid *head,
743                           u_int32_t max_types, u_int32_t * max_ssids)
744{
745    struct ssid_entry *np;
746    int i;
747
748    /* should not happen if xml / xsd checks work */
749    if (!bootstrap_label) {
750        printf("ERROR: No bootstrap label defined.\n");
751        exit(EXIT_FAILURE);
752    }
753
754    /* search bootstrap_label */
755    for (np = head->tqh_first; np != NULL; np = np->entries.tqe_next) {
756        if (!strcmp(np->name, bootstrap_label)) {
757            break;
758        }
759    }
760
761    if (!np) {
762        /* bootstrap label not found */
763        printf("ERROR: Bootstrap label >%s< not found.\n",
764               bootstrap_label);
765        exit(EXIT_FAILURE);
766    }
767
768    /* move this entry ahead in the list right after the default entry so it
769     * receives ssidref 1/1 */
770    TAILQ_REMOVE(head, np, entries);
771    TAILQ_INSERT_AFTER(head, head->tqh_first, np, entries);
772
773    /* renumber the ssids (we could also just switch places with 1st element) */
774    for (np = head->tqh_first, i = 0; np != NULL;
775         np = np->entries.tqe_next, i++)
776        np->num = i;
777
778}
779
780void init_label_mapping(void)
781{
782
783    printf("Creating label mappings ...\n");
784    /* initialize the ste and chwall type lists */
785    TAILQ_INIT(&chwall_ssid_head);
786    TAILQ_INIT(&ste_ssid_head);
787
788    /* init with default ssids */
789    if (init_ssid_queues()) {
790        printf("ERROR adding default ssids.\n");
791        exit(EXIT_FAILURE);
792    }
793}
794
795void post_label_mapping(void)
796{
797    struct ssid_entry *np;
798    int i;
799
800    /*
801     * now sort bootstrap label to the head of the list
802     * (for now), dom0 assumes its label in the first
803     * defined ssidref (1/1). 0/0 is the default non-Label
804     */
805    if (have_chwall)
806        fixup_bootstrap_label(&chwall_ssid_head, max_chwall_types,
807                              &max_chwall_ssids);
808    if (have_ste)
809        fixup_bootstrap_label(&ste_ssid_head, max_ste_types,
810                              &max_ste_ssids);
811
812    if (!DEBUG)
813        return;
814
815    /* print queues */
816    if (have_chwall) {
817        printf("CHWALL SSID queue (max ssidrefs=%d):\n", max_chwall_ssids);
818        np = NULL;
819        for (np = chwall_ssid_head.tqh_first; np != NULL;
820             np = np->entries.tqe_next) {
821            printf("SSID #%02u (Label=%s)\n", np->num, np->name);
822            if (np->is_ref)
823                printf("REFERENCE");
824            else
825                for (i = 0; i < max_chwall_types; i++)
826                    if (np->row[i])
827                        printf("#%02d ", i);
828            printf("\n\n");
829        }
830    }
831    if (have_ste) {
832        printf("STE SSID queue (max ssidrefs=%d):\n", max_ste_ssids);
833        np = NULL;
834        for (np = ste_ssid_head.tqh_first; np != NULL;
835             np = np->entries.tqe_next) {
836            printf("SSID #%02u (Label=%s)\n", np->num, np->name);
837            if (np->is_ref)
838                printf("REFERENCE");
839            else
840                for (i = 0; i < max_ste_types; i++)
841                    if (np->row[i])
842                        printf("#%02d ", i);
843            printf("\n\n");
844        }
845    }
846}
847
848void create_mappings(xmlDocPtr doc)
849{
850    xmlNode *doc_root_node = xmlDocGetRootElement(doc);
851
852    /* walk the XML policy tree and fill in types and labels */
853    init_type_mapping();
854    walk_policy(doc_root_node, doc, XML2BIN_NULL);      /* first pass: types */
855    post_type_mapping();
856    init_label_mapping();
857    walk_labels(doc_root_node, doc, XML2BIN_NULL);      /* second pass: labels */
858    post_label_mapping();
859}
860
861/***************** writing the binary policy *********************/
862
863/*
864 * the mapping file is ascii-based since it will likely be used from
865 * within scripts (using awk, grep, etc.);
866 *
867 * We print from high-level to low-level information so that with one
868 * pass, any symbol can be resolved (e.g. Label -> types)
869 */
870int write_mapping(char *filename)
871{
872
873    struct ssid_entry *e;
874    struct type_entry *t;
875    int i;
876    FILE *file;
877
878    if ((file = fopen(filename, "w")) == NULL)
879        return -EIO;
880
881    fprintf(file, "POLICYREFERENCENAME    %s\n", policy_reference_name);
882    fprintf(file, "MAGIC                  %08x\n", ACM_MAGIC);
883    fprintf(file, "POLICY FILE            %s\n", policy_filename);
884    fprintf(file, "BINARY FILE            %s\n", binary_filename);
885    if (have_chwall) {
886        fprintf(file, "MAX-CHWALL-TYPES       %08x\n", max_chwall_types);
887        fprintf(file, "MAX-CHWALL-SSIDS       %08x\n", max_chwall_ssids);
888        fprintf(file, "MAX-CHWALL-LABELS      %08x\n", max_chwall_labels);
889    }
890    if (have_ste) {
891        fprintf(file, "MAX-STE-TYPES          %08x\n", max_ste_types);
892        fprintf(file, "MAX-STE-SSIDS          %08x\n", max_ste_ssids);
893        fprintf(file, "MAX-STE-LABELS         %08x\n", max_ste_labels);
894    }
895    fprintf(file, "\n");
896
897    /* primary / secondary order for combined ssid synthesis/analysis
898     * if no primary is named, then chwall is primary */
899    switch (primary) {
900    case CHWALL:
901        fprintf(file, "PRIMARY                CHWALL\n");
902        break;
903
904    case STE:
905        fprintf(file, "PRIMARY                STE\n");
906        break;
907
908    default:
909        fprintf(file, "PRIMARY                NULL\n");
910        break;
911    }
912
913    switch (secondary) {
914    case CHWALL:
915        fprintf(file, "SECONDARY              CHWALL\n");
916        break;
917
918    case STE:
919        fprintf(file, "SECONDARY              STE\n");
920        break;
921
922    default:
923        fprintf(file, "SECONDARY              NULL\n");
924        break;
925    }
926    fprintf(file, "\n");
927
928    /* first labels to ssid mappings */
929    if (have_chwall) {
930        for (e = chwall_ssid_head.tqh_first; e != NULL;
931             e = e->entries.tqe_next) {
932            fprintf(file, "LABEL->SSID %s CHWALL %-25s %8x\n",
933                    (e->type ==
934                     VM) ? "VM " : ((e->type == RES) ? "RES" : "ANY"),
935                    e->name, e->num);
936        }
937        fprintf(file, "\n");
938    }
939    if (have_ste) {
940        for (e = ste_ssid_head.tqh_first; e != NULL;
941             e = e->entries.tqe_next) {
942            fprintf(file, "LABEL->SSID %s STE    %-25s %8x\n",
943                    (e->type ==
944                     VM) ? "VM " : ((e->type == RES) ? "RES" : "ANY"),
945                    e->name, e->num);
946        }
947        fprintf(file, "\n");
948    }
949
950    /* second ssid to type mappings */
951    if (have_chwall) {
952        for (e = chwall_ssid_head.tqh_first; e != NULL;
953             e = e->entries.tqe_next) {
954            if (e->is_ref)
955                continue;
956
957            fprintf(file, "SSID->TYPE CHWALL      %08x", e->num);
958
959            for (i = 0; i < max_chwall_types; i++)
960                if (e->row[i])
961                    fprintf(file, " %s", type_by_mapping(&chwall_head, i));
962
963            fprintf(file, "\n");
964        }
965        fprintf(file, "\n");
966    }
967    if (have_ste) {
968        for (e = ste_ssid_head.tqh_first; e != NULL;
969             e = e->entries.tqe_next) {
970            if (e->is_ref)
971                continue;
972
973            fprintf(file, "SSID->TYPE STE         %08x", e->num);
974
975            for (i = 0; i < max_ste_types; i++)
976                if (e->row[i])
977                    fprintf(file, " %s", type_by_mapping(&ste_head, i));
978
979            fprintf(file, "\n");
980        }
981        fprintf(file, "\n");
982    }
983    /* third type mappings */
984    if (have_chwall) {
985        for (t = chwall_head.tqh_first; t != NULL; t = t->entries.tqe_next) {
986            fprintf(file, "TYPE CHWALL            %-25s %8x\n",
987                    t->name, t->mapping);
988        }
989        fprintf(file, "\n");
990    }
991    if (have_ste) {
992        for (t = ste_head.tqh_first; t != NULL; t = t->entries.tqe_next) {
993            fprintf(file, "TYPE STE               %-25s %8x\n",
994                    t->name, t->mapping);
995        }
996        fprintf(file, "\n");
997    }
998    fclose(file);
999    return 0;
1000}
1001
1002
1003unsigned char *write_policy_reference_binary(u_int32_t * len_pr)
1004{
1005    unsigned char *buf, *ptr;
1006    struct acm_policy_reference_buffer *pr_header;
1007    u_int32_t len;
1008    u_int32_t name_len;
1009
1010    if (policy_reference_name == NULL) {
1011        printf("ERROR: No policy reference name found.\n");
1012        exit(EXIT_FAILURE);
1013    }
1014    name_len = strlen(policy_reference_name) + 1; /* strend '\0' */
1015    len = sizeof(struct acm_policy_reference_buffer) + name_len;
1016    len = (len + 7) & ~7; /* Alignment.  */
1017    buf = malloc(len);
1018    ptr = buf;
1019
1020    if (!buf) {
1021        printf
1022            ("ERROR: out of memory allocating label reference buffer.\n");
1023        exit(EXIT_FAILURE);
1024    }
1025    memset (buf, 0, len);
1026    pr_header = (struct acm_policy_reference_buffer *) buf;
1027    pr_header->len = htonl(name_len);
1028    ptr += sizeof(struct acm_policy_reference_buffer);
1029    strcpy((char *) ptr, policy_reference_name);
1030
1031    (*len_pr) = len;
1032    return buf;
1033}
1034
1035
1036unsigned char *write_chwall_binary(u_int32_t * len_chwall)
1037{
1038    unsigned char *buf, *ptr;
1039    struct acm_chwall_policy_buffer *chwall_header;
1040    u_int32_t len;
1041    struct ssid_entry *e;
1042    int i;
1043
1044    if (!have_chwall)
1045        return NULL;
1046
1047    len = sizeof(struct acm_chwall_policy_buffer) +
1048        sizeof(type_t) * max_chwall_types * max_chwall_ssids +
1049        sizeof(type_t) * max_chwall_types * max_conflictsets;
1050
1051    buf = malloc(len);
1052    ptr = buf;
1053
1054    if (!buf) {
1055        printf("ERROR: out of memory allocating chwall buffer.\n");
1056        exit(EXIT_FAILURE);
1057    }
1058    /* chwall has 3 parts : header, types, conflictsets */
1059
1060    chwall_header = (struct acm_chwall_policy_buffer *) buf;
1061    chwall_header->chwall_max_types = htonl(max_chwall_types);
1062    chwall_header->chwall_max_ssidrefs = htonl(max_chwall_ssids);
1063    chwall_header->policy_code = htonl(ACM_CHINESE_WALL_POLICY);
1064    chwall_header->policy_version = htonl(ACM_CHWALL_VERSION);
1065    chwall_header->chwall_ssid_offset =
1066        htonl(sizeof(struct acm_chwall_policy_buffer));
1067    chwall_header->chwall_max_conflictsets = htonl(max_conflictsets);
1068    chwall_header->chwall_conflict_sets_offset =
1069        htonl(ntohl(chwall_header->chwall_ssid_offset) +
1070              sizeof(domaintype_t) * max_chwall_ssids * max_chwall_types);
1071    chwall_header->chwall_running_types_offset = 0;
1072    chwall_header->chwall_conflict_aggregate_offset = 0;
1073    ptr += sizeof(struct acm_chwall_policy_buffer);
1074
1075    /* types */
1076    for (e = chwall_ssid_head.tqh_first; e != NULL;
1077         e = e->entries.tqe_next) {
1078        if (e->is_ref)
1079            continue;
1080
1081        for (i = 0; i < max_chwall_types; i++)
1082            ((type_t *) ptr)[i] = htons((type_t) e->row[i]);
1083
1084        ptr += sizeof(type_t) * max_chwall_types;
1085    }
1086
1087    /* conflictsets */
1088    for (e = conflictsets_head.tqh_first; e != NULL;
1089         e = e->entries.tqe_next) {
1090        for (i = 0; i < max_chwall_types; i++)
1091            ((type_t *) ptr)[i] = htons((type_t) e->row[i]);
1092
1093        ptr += sizeof(type_t) * max_chwall_types;
1094    }
1095
1096    if ((ptr - buf) != len) {
1097        printf("ERROR: wrong lengths in %s.\n", __func__);
1098        exit(EXIT_FAILURE);
1099    }
1100
1101    (*len_chwall) = len;
1102    return buf;
1103}
1104
1105unsigned char *write_ste_binary(u_int32_t * len_ste)
1106{
1107    unsigned char *buf, *ptr;
1108    struct acm_ste_policy_buffer *ste_header;
1109    struct ssid_entry *e;
1110    u_int32_t len;
1111    int i;
1112
1113    if (!have_ste)
1114        return NULL;
1115
1116    len = sizeof(struct acm_ste_policy_buffer) +
1117        sizeof(type_t) * max_ste_types * max_ste_ssids;
1118
1119    buf = malloc(len);
1120    ptr = buf;
1121
1122    if (!buf) {
1123        printf("ERROR: out of memory allocating chwall buffer.\n");
1124        exit(EXIT_FAILURE);
1125    }
1126
1127    /* fill buffer */
1128    ste_header = (struct acm_ste_policy_buffer *) buf;
1129    ste_header->policy_version = htonl(ACM_STE_VERSION);
1130    ste_header->policy_code = htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
1131    ste_header->ste_max_types = htonl(max_ste_types);
1132    ste_header->ste_max_ssidrefs = htonl(max_ste_ssids);
1133    ste_header->ste_ssid_offset =
1134        htonl(sizeof(struct acm_ste_policy_buffer));
1135
1136    ptr += sizeof(struct acm_ste_policy_buffer);
1137
1138    /* types */
1139    for (e = ste_ssid_head.tqh_first; e != NULL; e = e->entries.tqe_next) {
1140        if (e->is_ref)
1141            continue;
1142
1143        for (i = 0; i < max_ste_types; i++)
1144            ((type_t *) ptr)[i] = htons((type_t) e->row[i]);
1145
1146        ptr += sizeof(type_t) * max_ste_types;
1147    }
1148
1149    if ((ptr - buf) != len) {
1150        printf("ERROR: wrong lengths in %s.\n", __func__);
1151        exit(EXIT_FAILURE);
1152    }
1153    (*len_ste) = len;
1154    return buf;                 /* for now */
1155}
1156
1157static ssize_t write_padded(int fd, const void *buf, size_t count)
1158{
1159    int rc;
1160    static const char padding[7] = {0,0,0,0,0,0,0};
1161    unsigned int len = ROUND8(count) - count;
1162
1163    rc = write(fd, buf, count);
1164    if (rc == count && len > 0) {
1165        write(fd, padding, len);
1166    }
1167    return rc;
1168}
1169
1170int write_binary(char *filename)
1171{
1172    struct acm_policy_buffer header;
1173    unsigned char *ste_buffer = NULL, *chwall_buffer =
1174        NULL, *policy_reference_buffer = NULL;
1175    u_int32_t len;
1176    int fd, ret = 0;
1177    uint32_t major = 0, minor = 0;
1178
1179    u_int32_t len_ste = 0, len_chwall = 0, len_pr = 0;  /* length of policy components */
1180
1181    if (policy_version_string)
1182        sscanf(policy_version_string,"%d.%d", &major, &minor);
1183
1184    /* open binary file */
1185    if ((fd =
1186         open(filename, O_WRONLY | O_CREAT | O_TRUNC,
1187              S_IRUSR | S_IWUSR)) <= 0) {
1188        ret = -EIO;
1189        goto out1;
1190    }
1191    policy_reference_buffer = write_policy_reference_binary(&len_pr);
1192    ste_buffer = write_ste_binary(&len_ste);
1193    chwall_buffer = write_chwall_binary(&len_chwall);
1194
1195    /* determine primary component (default chwall) */
1196    header.policy_version = htonl(ACM_POLICY_VERSION);
1197    header.magic = htonl(ACM_MAGIC);
1198    header.xml_pol_version.major = htonl(major);
1199    header.xml_pol_version.minor = htonl(minor);
1200
1201    len = ROUND8(sizeof(struct acm_policy_buffer));
1202    if (have_chwall)
1203        len += ROUND8(len_chwall);
1204    if (have_ste)
1205        len += ROUND8(len_ste);
1206    len += ROUND8(len_pr);           /* policy reference is mandatory */
1207    header.len = htonl(len);
1208
1209    header.policy_reference_offset =
1210        htonl(ROUND8(sizeof(struct acm_policy_buffer)));
1211
1212    header.primary_buffer_offset =
1213        htonl(ROUND8(sizeof(struct acm_policy_buffer)) +
1214              ROUND8(len_pr));
1215    if (primary == CHWALL) {
1216        header.primary_policy_code = htonl(ACM_CHINESE_WALL_POLICY);
1217        header.secondary_buffer_offset =
1218            htonl(ROUND8(sizeof(struct acm_policy_buffer)) +
1219                  ROUND8(len_pr) +
1220                  ROUND8(len_chwall));
1221    } else if (primary == STE) {
1222        header.primary_policy_code =
1223            htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
1224        header.secondary_buffer_offset =
1225            htonl(ROUND8(sizeof(struct acm_policy_buffer)) +
1226                  ROUND8(len_pr) +
1227                  ROUND8(len_ste));
1228    } else {
1229        /* null policy */
1230        header.primary_policy_code = htonl(ACM_NULL_POLICY);
1231        header.secondary_buffer_offset = header.primary_buffer_offset;
1232    }
1233
1234    if (secondary == CHWALL)
1235        header.secondary_policy_code = htonl(ACM_CHINESE_WALL_POLICY);
1236    else if (secondary == STE)
1237        header.secondary_policy_code =
1238            htonl(ACM_SIMPLE_TYPE_ENFORCEMENT_POLICY);
1239    else
1240        header.secondary_policy_code = htonl(ACM_NULL_POLICY);
1241
1242    if (write_padded(fd, (void *) &header, sizeof(struct acm_policy_buffer))
1243        != sizeof(struct acm_policy_buffer)) {
1244        ret = -EIO;
1245        goto out1;
1246    }
1247
1248    /* write label reference name */
1249    if (write_padded(fd, policy_reference_buffer, len_pr) != len_pr) {
1250        ret = -EIO;
1251        goto out1;
1252    }
1253    /* write primary policy component */
1254    if (primary == CHWALL) {
1255        if (write_padded(fd, chwall_buffer, len_chwall) != len_chwall) {
1256            ret = -EIO;
1257            goto out1;
1258        }
1259    } else if (primary == STE) {
1260        if (write_padded(fd, ste_buffer, len_ste) != len_ste) {
1261            ret = -EIO;
1262            goto out1;
1263        }
1264    } else;                     /* NULL POLICY has no policy data */
1265
1266    /* write secondary policy component */
1267    if (secondary == CHWALL) {
1268        if (write_padded(fd, chwall_buffer, len_chwall) != len_chwall) {
1269            ret = -EIO;
1270            goto out1;
1271        }
1272    } else if (secondary == STE) {
1273        if (write_padded(fd, ste_buffer, len_ste) != len_ste) {
1274            ret = -EIO;
1275            goto out1;
1276        }
1277    } else;                     /* NULL POLICY has no policy data */
1278
1279  out1:
1280    /* cleanup */
1281    if (policy_reference_buffer)
1282        free(policy_reference_buffer);
1283    if (chwall_buffer)
1284        free(chwall_buffer);
1285    if (ste_buffer)
1286        free(ste_buffer);
1287    close(fd);
1288    return ret;
1289}
1290
1291int is_valid(xmlDocPtr doc)
1292{
1293    int err = 0;
1294    xmlSchemaPtr schema_ctxt = NULL;
1295    xmlSchemaParserCtxtPtr schemaparser_ctxt = NULL;
1296    xmlSchemaValidCtxtPtr schemavalid_ctxt = NULL;
1297
1298    schemaparser_ctxt = xmlSchemaNewParserCtxt(schema_filename);
1299    schema_ctxt = xmlSchemaParse(schemaparser_ctxt);
1300    schemavalid_ctxt = xmlSchemaNewValidCtxt(schema_ctxt);
1301
1302#ifdef VALIDATE_SCHEMA
1303    /* only tested to be available from libxml2-2.6.20 upwards */
1304    if ((err = xmlSchemaIsValid(schemavalid_ctxt)) != 1) {
1305        printf("ERROR: Invalid schema file %s (err=%d)\n",
1306               schema_filename, err);
1307        err = -EIO;
1308        goto out;
1309    } else
1310        printf("XML Schema %s valid.\n", schema_filename);
1311#endif
1312    if ((err = xmlSchemaValidateDoc(schemavalid_ctxt, doc))) {
1313        err = -EIO;
1314        goto out;
1315    }
1316  out:
1317    xmlSchemaFreeValidCtxt(schemavalid_ctxt);
1318    xmlSchemaFreeParserCtxt(schemaparser_ctxt);
1319    xmlSchemaFree(schema_ctxt);
1320    return (err != 0) ? 0 : 1;
1321}
1322
1323int main(int argc, char **argv)
1324{
1325    xmlDocPtr policydoc = NULL;
1326
1327    int err = EXIT_FAILURE;
1328
1329    char *file_prefix;
1330    int prefix_len;
1331
1332    int opt_char;
1333    char *policy_dir = POLICY_DIR;
1334
1335    if (ACM_POLICY_VERSION != WRITTEN_AGAINST_ACM_POLICY_VERSION) {
1336        printf
1337            ("ERROR: This program was written against an older ACM version.\n");
1338        printf("ERROR: ACM_POLICY_VERSION=%d, WRITTEN AGAINST= %d.\n",
1339               ACM_POLICY_VERSION, WRITTEN_AGAINST_ACM_POLICY_VERSION);
1340        exit(EXIT_FAILURE);
1341    }
1342
1343    while ((opt_char = getopt(argc, argv, "d:")) != -1) {
1344        switch (opt_char) {
1345        case 'd':
1346            policy_dir = malloc(strlen(optarg) + 2);    /* null terminator and possibly "/" */
1347            if (!policy_dir) {
1348                printf("ERROR allocating directory name memory.\n");
1349                exit(EXIT_FAILURE);
1350            }
1351            strcpy(policy_dir, optarg);
1352            if (policy_dir[strlen(policy_dir) - 1] != '/')
1353                strcat(policy_dir, "/");
1354            break;
1355
1356        default:
1357            usage(basename(argv[0]));
1358        }
1359    }
1360
1361    if ((argc - optind) != 1)
1362        usage(basename(argv[0]));
1363
1364    printf("arg=%s\n", argv[optind]);
1365
1366    prefix_len =
1367        strlen(policy_dir) + strlen(argv[optind]) +
1368        1 /* null terminator */ ;
1369
1370    file_prefix = malloc(prefix_len);
1371    policy_filename = malloc(prefix_len + strlen(POLICY_EXTENSION));
1372    binary_filename = malloc(prefix_len + strlen(BINARY_EXTENSION));
1373    mapping_filename = malloc(prefix_len + strlen(MAPPING_EXTENSION));
1374    schema_filename =
1375        malloc(strlen(policy_dir) + strlen(SCHEMA_FILENAME) + 1);
1376
1377    if (!file_prefix || !policy_filename ||
1378        !binary_filename || !mapping_filename || !schema_filename) {
1379        printf("ERROR allocating file name memory.\n");
1380        goto out2;
1381    }
1382
1383    /* create input/output filenames out of prefix */
1384    strcpy(file_prefix, policy_dir);
1385    strcat(file_prefix, argv[optind]);
1386
1387    strcpy(policy_filename, file_prefix);
1388    strcpy(binary_filename, file_prefix);
1389    strcpy(mapping_filename, file_prefix);
1390
1391    strcat(policy_filename, POLICY_EXTENSION);
1392    strcat(binary_filename, BINARY_EXTENSION);
1393    strcat(mapping_filename, MAPPING_EXTENSION);
1394
1395    strcpy(schema_filename, policy_dir);
1396    strcat(schema_filename, SCHEMA_FILENAME);
1397
1398    policydoc = xmlParseFile(policy_filename);
1399
1400    if (policydoc == NULL) {
1401        printf("Error: could not parse file %s.\n", argv[optind]);
1402        goto out;
1403    }
1404
1405    printf("Validating policy file %s...\n", policy_filename);
1406
1407    if (!is_valid(policydoc)) {
1408        printf("ERROR: Failed schema-validation for file %s (err=%d)\n",
1409               policy_filename, err);
1410        goto out;
1411    }
1412
1413    /* create mappings */
1414    create_mappings(policydoc);
1415
1416    /* write label mapping file */
1417    if (write_mapping(mapping_filename)) {
1418        printf("ERROR: writing mapping file %s.\n", mapping_filename);
1419        goto out;
1420    }
1421
1422    /* write binary file */
1423    if (write_binary(binary_filename)) {
1424        printf("ERROR: writing binary file %s.\n", binary_filename);
1425        goto out;
1426    }
1427    err = EXIT_SUCCESS;
1428    /* write stats */
1429    if (have_chwall) {
1430        printf("Max chwall labels:  %u\n", max_chwall_labels);
1431        printf("Max chwall-types:   %u\n", max_chwall_types);
1432        printf("Max chwall-ssids:   %u\n", max_chwall_ssids);
1433    }
1434
1435    if (have_ste) {
1436        printf("Max ste labels:     %u\n", max_ste_labels);
1437        printf("Max ste-types:      %u\n", max_ste_types);
1438        printf("Max ste-ssids:      %u\n", max_ste_ssids);
1439    }
1440    /* cleanup */
1441  out:
1442    xmlFreeDoc(policydoc);
1443  out2:
1444    xmlCleanupParser();
1445    return err;
1446}
1447
1448/*
1449 * Local variables:
1450 * mode: C
1451 * c-set-style: "BSD"
1452 * c-basic-offset: 4
1453 * tab-width: 4
1454 * indent-tabs-mode: nil
1455 * End:
1456 */
Note: See TracBrowser for help on using the repository browser.