summaryrefslogtreecommitdiff
path: root/checkpolicy.c
diff options
context:
space:
mode:
Diffstat (limited to 'checkpolicy.c')
-rw-r--r--checkpolicy.c1077
1 files changed, 1077 insertions, 0 deletions
diff --git a/checkpolicy.c b/checkpolicy.c
new file mode 100644
index 0000000..a35a749
--- /dev/null
+++ b/checkpolicy.c
@@ -0,0 +1,1077 @@
+
+/*
+ * Author : Stephen Smalley, <sds@epoch.ncsc.mil>
+ */
+
+/*
+ * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
+ *
+ * Support for enhanced MLS infrastructure.
+ *
+ * Updated: Karl MacMillan <kmacmillan@tresys.com>
+ *
+ * Added conditional policy language extensions
+ *
+ * Updated: James Morris <jmorris@intercode.com.au>
+ *
+ * Added IPv6 support.
+ *
+ * Updated: Joshua Brindle <jbrindle@tresys.com>
+ * Karl MacMillan <kmacmillan@tresys.com>
+ * Jason Tang <jtang@tresys.com>
+ *
+ * Policy Module support.
+ *
+ * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
+ * Copyright (C) 2003 - 2005 Tresys Technology, LLC
+ * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.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.
+ */
+
+/* FLASK */
+
+/*
+ * checkpolicy
+ *
+ * Load and check a policy configuration.
+ *
+ * A policy configuration is created in a text format,
+ * and then compiled into a binary format for use by
+ * the security server. By default, checkpolicy reads
+ * the text format. If '-b' is specified, then checkpolicy
+ * reads the binary format instead.
+ *
+ * If '-o output_file' is specified, then checkpolicy
+ * writes the binary format version of the configuration
+ * to the specified output file.
+ *
+ * If '-d' is specified, then checkpolicy permits the user
+ * to interactively test the security server functions with
+ * the loaded policy configuration.
+ *
+ * If '-c' is specified, then the supplied parameter is used to
+ * determine which policy version to use for generating binary
+ * policy. This is for compatibility with older kernels. If any
+ * booleans or conditional rules are thrown away a warning is printed.
+ */
+
+#include <getopt.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/mman.h>
+
+#include <sepol/policydb/policydb.h>
+#include <sepol/policydb/services.h>
+#include <sepol/policydb/conditional.h>
+#include <sepol/policydb/hierarchy.h>
+#include <sepol/policydb/flask.h>
+#include <sepol/policydb/expand.h>
+#include <sepol/policydb/link.h>
+
+#include "queue.h"
+#include "checkpolicy.h"
+#include "parse_util.h"
+
+extern char *optarg;
+extern int optind;
+
+static policydb_t policydb;
+static sidtab_t sidtab;
+
+extern policydb_t *policydbp;
+extern int mlspol;
+
+static int handle_unknown = SEPOL_DENY_UNKNOWN;
+static char *txtfile = "policy.conf";
+static char *binfile = "policy";
+
+unsigned int policyvers = POLICYDB_VERSION_MAX;
+
+void usage(char *progname)
+{
+ printf
+ ("usage: %s [-b] [-d] [-U handle_unknown (allow,deny,reject)] [-M]"
+ "[-c policyvers (%d-%d)] [-o output_file] [-t target_platform (selinux,xen)]"
+ "[input_file]\n",
+ progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
+ exit(1);
+}
+
+#define FGETS(out, size, in) \
+if (fgets(out,size,in)==NULL) { \
+ fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,\
+ strerror(errno)); \
+ exit(1);\
+}
+static int print_sid(sepol_security_id_t sid,
+ context_struct_t * context
+ __attribute__ ((unused)), void *data
+ __attribute__ ((unused)))
+{
+ sepol_security_context_t scontext;
+ size_t scontext_len;
+ int rc;
+
+ rc = sepol_sid_to_context(sid, &scontext, &scontext_len);
+ if (rc)
+ printf("sid %d -> error %d\n", sid, rc);
+ else {
+ printf("sid %d -> scontext %s\n", sid, scontext);
+ free(scontext);
+ }
+ return 0;
+}
+
+struct val_to_name {
+ unsigned int val;
+ char *name;
+};
+
+static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *p)
+{
+ struct val_to_name *v = p;
+ perm_datum_t *perdatum;
+
+ perdatum = (perm_datum_t *) datum;
+
+ if (v->val == perdatum->s.value) {
+ v->name = key;
+ return 1;
+ }
+
+ return 0;
+}
+
+#ifdef EQUIVTYPES
+static int insert_type_rule(avtab_key_t * k, avtab_datum_t * d,
+ struct avtab_node *type_rules)
+{
+ struct avtab_node *p, *c, *n;
+
+ for (p = type_rules, c = type_rules->next; c; p = c, c = c->next) {
+ /*
+ * Find the insertion point, keeping the list
+ * ordered by source type, then target type, then
+ * target class.
+ */
+ if (k->source_type < c->key.source_type)
+ break;
+ if (k->source_type == c->key.source_type &&
+ k->target_type < c->key.target_type)
+ break;
+ if (k->source_type == c->key.source_type &&
+ k->target_type == c->key.target_type &&
+ k->target_class < c->key.target_class)
+ break;
+ }
+
+ /* Insert the rule */
+ n = malloc(sizeof(struct avtab_node));
+ if (!n) {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+
+ n->key = *k;
+ n->datum = *d;
+ n->next = p->next;
+ p->next = n;
+ return 0;
+}
+
+static int create_type_rules(avtab_key_t * k, avtab_datum_t * d, void *args)
+{
+ struct avtab_node *type_rules = args;
+
+ if (d->specified & AVTAB_ALLOWED) {
+ /*
+ * Insert the rule into the lists for both
+ * the source type and the target type.
+ */
+ if (insert_type_rule(k, d, &type_rules[k->source_type - 1]))
+ return -1;
+ if (insert_type_rule(k, d, &type_rules[k->target_type - 1]))
+ return -1;
+ }
+
+ return 0;
+}
+
+static void free_type_rules(struct avtab_node *l)
+{
+ struct avtab_node *tmp;
+
+ while (l) {
+ tmp = l;
+ l = l->next;
+ free(tmp);
+ }
+}
+
+static int identify_equiv_types(void)
+{
+ struct avtab_node *type_rules, *l1, *l2;
+ int i, j;
+
+ /*
+ * Create a list of access vector rules for each type
+ * from the access vector table.
+ */
+ type_rules = malloc(sizeof(struct avtab_node) * policydb.p_types.nprim);
+ if (!type_rules) {
+ fprintf(stderr, "out of memory\n");
+ exit(1);
+ }
+ memset(type_rules, 0,
+ sizeof(struct avtab_node) * policydb.p_types.nprim);
+ if (avtab_map(&policydb.te_avtab, create_type_rules, type_rules))
+ exit(1);
+
+ /*
+ * Compare the type lists and identify equivalent types.
+ */
+ for (i = 0; i < policydb.p_types.nprim - 1; i++) {
+ if (!type_rules[i].next)
+ continue;
+ for (j = i + 1; j < policydb.p_types.nprim; j++) {
+ for (l1 = type_rules[i].next, l2 = type_rules[j].next;
+ l1 && l2; l1 = l1->next, l2 = l2->next) {
+ if (l2->key.source_type == (j + 1)) {
+ if (l1->key.source_type != (i + 1))
+ break;
+ } else {
+ if (l1->key.source_type !=
+ l2->key.source_type)
+ break;
+ }
+ if (l2->key.target_type == (j + 1)) {
+ if (l1->key.target_type != (i + 1))
+ break;
+ } else {
+ if (l1->key.target_type !=
+ l2->key.target_type)
+ break;
+ }
+ if (l1->key.target_class != l2->key.target_class
+ || l1->datum.allowed != l2->datum.allowed)
+ break;
+ }
+ if (l1 || l2)
+ continue;
+ free_type_rules(type_rules[j].next);
+ type_rules[j].next = NULL;
+ printf("Types %s and %s are equivalent.\n",
+ policydb.p_type_val_to_name[i],
+ policydb.p_type_val_to_name[j]);
+ }
+ free_type_rules(type_rules[i].next);
+ type_rules[i].next = NULL;
+ }
+
+ free(type_rules);
+ return 0;
+}
+#endif
+
+extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av);
+
+int display_bools()
+{
+ int i;
+
+ for (i = 0; i < policydbp->p_bools.nprim; i++) {
+ printf("%s : %d\n", policydbp->p_bool_val_to_name[i],
+ policydbp->bool_val_to_struct[i]->state);
+ }
+ return 0;
+}
+
+void display_expr(cond_expr_t * exp)
+{
+
+ cond_expr_t *cur;
+ for (cur = exp; cur != NULL; cur = cur->next) {
+ switch (cur->expr_type) {
+ case COND_BOOL:
+ printf("%s ",
+ policydbp->p_bool_val_to_name[cur->bool - 1]);
+ break;
+ case COND_NOT:
+ printf("! ");
+ break;
+ case COND_OR:
+ printf("|| ");
+ break;
+ case COND_AND:
+ printf("&& ");
+ break;
+ case COND_XOR:
+ printf("^ ");
+ break;
+ case COND_EQ:
+ printf("== ");
+ break;
+ case COND_NEQ:
+ printf("!= ");
+ break;
+ default:
+ printf("error!");
+ break;
+ }
+ }
+}
+
+int display_cond_expressions()
+{
+ cond_node_t *cur;
+
+ for (cur = policydbp->cond_list; cur != NULL; cur = cur->next) {
+ printf("expression: ");
+ display_expr(cur->expr);
+ printf("current state: %d\n", cur->cur_state);
+ }
+ return 0;
+}
+
+int change_bool(char *name, int state)
+{
+ cond_bool_datum_t *bool;
+
+ bool = hashtab_search(policydbp->p_bools.table, name);
+ if (bool == NULL) {
+ printf("Could not find bool %s\n", name);
+ return -1;
+ }
+ bool->state = state;
+ evaluate_conds(policydbp);
+ return 0;
+}
+
+static int check_level(hashtab_key_t key, hashtab_datum_t datum, void *arg)
+{
+ level_datum_t *levdatum = (level_datum_t *) datum;
+
+ if (!levdatum->isalias && !levdatum->defined) {
+ fprintf(stderr,
+ "Error: sensitivity %s was not used in a level definition!\n",
+ key);
+ return -1;
+ }
+ return 0;
+}
+
+int main(int argc, char **argv)
+{
+ sepol_security_class_t tclass;
+ sepol_security_id_t ssid, tsid, *sids;
+ sepol_security_context_t scontext;
+ struct sepol_av_decision avd;
+ class_datum_t *cladatum;
+ char ans[80 + 1], *file = txtfile, *outfile = NULL, *path, *fstype;
+ size_t scontext_len, pathlen;
+ unsigned int i;
+ unsigned int protocol, port;
+ unsigned int binary = 0, debug = 0;
+ struct val_to_name v;
+ int ret, ch, fd, target = SEPOL_TARGET_SELINUX;
+ unsigned int nel, uret;
+ struct stat sb;
+ void *map;
+ FILE *outfp = NULL;
+ char *name;
+ int state;
+ int show_version = 0;
+ struct policy_file pf;
+ struct option long_options[] = {
+ {"output", required_argument, NULL, 'o'},
+ {"target", required_argument, NULL, 't'},
+ {"binary", no_argument, NULL, 'b'},
+ {"debug", no_argument, NULL, 'd'},
+ {"version", no_argument, NULL, 'V'},
+ {"handle-unknown", optional_argument, NULL, 'U'},
+ {"mls", no_argument, NULL, 'M'},
+ {"help", no_argument, NULL, 'h'},
+ {NULL, 0, NULL, 0}
+ };
+
+ while ((ch = getopt_long(argc, argv, "o:t:dbU:MVc:h", long_options, NULL)) != -1) {
+ switch (ch) {
+ case 'o':
+ outfile = optarg;
+ break;
+ case 't':
+ if (!strcasecmp(optarg, "Xen"))
+ target = SEPOL_TARGET_XEN;
+ else if (!strcasecmp(optarg, "SELinux"))
+ target = SEPOL_TARGET_SELINUX;
+ else{
+ fprintf(stderr, "%s: Unknown target platform:"
+ "%s\n", argv[0], optarg);
+ exit(1);
+ }
+ break;
+ case 'b':
+ binary = 1;
+ file = binfile;
+ break;
+ case 'd':
+ debug = 1;
+ break;
+ case 'V':
+ show_version = 1;
+ break;
+ case 'U':
+ if (!strcasecmp(optarg, "deny")) {
+ handle_unknown = DENY_UNKNOWN;
+ break;
+ }
+ if (!strcasecmp(optarg, "allow")) {
+ handle_unknown = ALLOW_UNKNOWN;
+ break;
+ }
+ if (!strcasecmp(optarg, "reject")) {
+ handle_unknown = REJECT_UNKNOWN;
+ break;
+ }
+ usage(argv[0]);
+ case 'M':
+ mlspol = 1;
+ break;
+ case 'c':{
+ long int n = strtol(optarg, NULL, 10);
+ if (errno) {
+ fprintf(stderr,
+ "Invalid policyvers specified: %s\n",
+ optarg);
+ usage(argv[0]);
+ exit(1);
+ }
+ if (n < POLICYDB_VERSION_MIN
+ || n > POLICYDB_VERSION_MAX) {
+ fprintf(stderr,
+ "policyvers value %ld not in range %d-%d\n",
+ n, POLICYDB_VERSION_MIN,
+ POLICYDB_VERSION_MAX);
+ usage(argv[0]);
+ exit(1);
+ }
+ if (policyvers != n)
+ policyvers = n;
+ break;
+ }
+ case 'h':
+ default:
+ usage(argv[0]);
+ }
+ }
+
+ if (show_version) {
+ printf("%d (compatibility range %d-%d)\n", policyvers,
+ POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN);
+ exit(0);
+ }
+
+ if (optind != argc) {
+ file = argv[optind++];
+ if (optind != argc)
+ usage(argv[0]);
+ }
+ printf("%s: loading policy configuration from %s\n", argv[0], file);
+
+ /* Set policydb and sidtab used by libsepol service functions
+ to my structures, so that I can directly populate and
+ manipulate them. */
+ sepol_set_policydb(&policydb);
+ sepol_set_sidtab(&sidtab);
+
+ if (binary) {
+ fd = open(file, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Can't open '%s': %s\n",
+ file, strerror(errno));
+ exit(1);
+ }
+ if (fstat(fd, &sb) < 0) {
+ fprintf(stderr, "Can't stat '%s': %s\n",
+ file, strerror(errno));
+ exit(1);
+ }
+ map =
+ mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
+ fd, 0);
+ if (map == MAP_FAILED) {
+ fprintf(stderr, "Can't map '%s': %s\n",
+ file, strerror(errno));
+ exit(1);
+ }
+ policy_file_init(&pf);
+ pf.type = PF_USE_MEMORY;
+ pf.data = map;
+ pf.len = sb.st_size;
+ if (policydb_init(&policydb)) {
+ fprintf(stderr, "%s: policydb_init: Out of memory!\n",
+ argv[0]);
+ exit(1);
+ }
+ ret = policydb_read(&policydb, &pf, 1);
+ if (ret) {
+ fprintf(stderr,
+ "%s: error(s) encountered while parsing configuration\n",
+ argv[0]);
+ exit(1);
+ }
+ policydbp = &policydb;
+
+ /* Check Policy Consistency */
+ if (policydbp->mls) {
+ if (!mlspol) {
+ fprintf(stderr, "%s: MLS policy, but non-MLS"
+ " is specified\n", argv[0]);
+ exit(1);
+ }
+ } else {
+ if (mlspol) {
+ fprintf(stderr, "%s: non-MLS policy, but MLS"
+ " is specified\n", argv[0]);
+ exit(1);
+ }
+ }
+ } else {
+ policydb_t parse_policy;
+
+ if (policydb_init(&parse_policy))
+ exit(1);
+ /* We build this as a base policy first since that is all the parser understands */
+ parse_policy.policy_type = POLICY_BASE;
+ policydb_set_target_platform(&parse_policy, target);
+
+ /* Let sepol know if we are dealing with MLS support */
+ parse_policy.mls = mlspol;
+ parse_policy.handle_unknown = handle_unknown;
+
+ policydbp = &parse_policy;
+
+ if (read_source_policy(policydbp, file, "checkpolicy") < 0)
+ exit(1);
+
+ if (hashtab_map(policydbp->p_levels.table, check_level, NULL))
+ exit(1);
+
+ if (policydb_init(&policydb)) {
+ fprintf(stderr, "%s: policydb_init failed\n", argv[0]);
+ exit(1);
+ }
+
+ /* Linking takes care of optional avrule blocks */
+ if (link_modules(NULL, &parse_policy, NULL, 0, 0)) {
+ fprintf(stderr, "Error while resolving optionals\n");
+ exit(1);
+ }
+
+ if (expand_module(NULL, &parse_policy, &policydb, 0, 1)) {
+ fprintf(stderr, "Error while expanding policy\n");
+ exit(1);
+ }
+ policydb_destroy(&parse_policy);
+ policydbp = &policydb;
+ }
+
+ if (policydb_load_isids(&policydb, &sidtab))
+ exit(1);
+
+ printf("%s: policy configuration loaded\n", argv[0]);
+
+ if (outfile) {
+ printf
+ ("%s: writing binary representation (version %d) to %s\n",
+ argv[0], policyvers, outfile);
+ outfp = fopen(outfile, "w");
+ if (!outfp) {
+ perror(outfile);
+ exit(1);
+ }
+
+ policydb.policy_type = POLICY_KERN;
+ policydb.policyvers = policyvers;
+
+ policy_file_init(&pf);
+ pf.type = PF_USE_STDIO;
+ pf.fp = outfp;
+ ret = policydb_write(&policydb, &pf);
+ if (ret) {
+ fprintf(stderr, "%s: error writing %s\n",
+ argv[0], outfile);
+ exit(1);
+ }
+ fclose(outfp);
+ }
+ if (!debug) {
+ policydb_destroy(&policydb);
+ exit(0);
+ }
+
+ menu:
+ printf("\nSelect an option:\n");
+ printf("0) Call compute_access_vector\n");
+ printf("1) Call sid_to_context\n");
+ printf("2) Call context_to_sid\n");
+ printf("3) Call transition_sid\n");
+ printf("4) Call member_sid\n");
+ printf("5) Call change_sid\n");
+ printf("6) Call list_sids\n");
+ printf("7) Call load_policy\n");
+ printf("8) Call fs_sid\n");
+ printf("9) Call port_sid\n");
+ printf("a) Call netif_sid\n");
+ printf("b) Call node_sid\n");
+ printf("c) Call fs_use\n");
+ printf("d) Call genfs_sid\n");
+ printf("e) Call get_user_sids\n");
+ printf("f) display conditional bools\n");
+ printf("g) display conditional expressions\n");
+ printf("h) change a boolean value\n");
+#ifdef EQUIVTYPES
+ printf("z) Show equivalent types\n");
+#endif
+ printf("m) Show menu again\n");
+ printf("q) Exit\n");
+ while (1) {
+ printf("\nChoose: ");
+ FGETS(ans, sizeof(ans), stdin);
+ switch (ans[0]) {
+ case '0':
+ printf("source sid? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ssid = atoi(ans);
+
+ printf("target sid? ");
+ FGETS(ans, sizeof(ans), stdin);
+ tsid = atoi(ans);
+
+ printf("target class? ");
+ FGETS(ans, sizeof(ans), stdin);
+ if (isdigit(ans[0])) {
+ tclass = atoi(ans);
+ if (!tclass
+ || tclass > policydb.p_classes.nprim) {
+ printf("\nNo such class.\n");
+ break;
+ }
+ cladatum =
+ policydb.class_val_to_struct[tclass - 1];
+ } else {
+ ans[strlen(ans) - 1] = 0;
+ cladatum =
+ (class_datum_t *) hashtab_search(policydb.
+ p_classes.
+ table,
+ ans);
+ if (!cladatum) {
+ printf("\nNo such class\n");
+ break;
+ }
+ tclass = cladatum->s.value;
+ }
+
+ if (!cladatum->comdatum && !cladatum->permissions.nprim) {
+ printf
+ ("\nNo access vector definition for that class\n");
+ break;
+ }
+ ret = sepol_compute_av(ssid, tsid, tclass, 0, &avd);
+ switch (ret) {
+ case 0:
+ printf("\nallowed {");
+ for (i = 1; i <= sizeof(avd.allowed) * 8; i++) {
+ if (avd.allowed & (1 << (i - 1))) {
+ v.val = i;
+ ret =
+ hashtab_map(cladatum->
+ permissions.
+ table,
+ find_perm, &v);
+ if (!ret && cladatum->comdatum) {
+ ret =
+ hashtab_map
+ (cladatum->
+ comdatum->
+ permissions.table,
+ find_perm, &v);
+ }
+ if (ret)
+ printf(" %s", v.name);
+ }
+ }
+ printf(" }\n");
+ break;
+ case -EINVAL:
+ printf("\ninvalid sid\n");
+ break;
+ default:
+ printf("return code 0x%x\n", ret);
+ }
+ break;
+ case '1':
+ printf("sid? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ssid = atoi(ans);
+ ret = sepol_sid_to_context(ssid,
+ &scontext, &scontext_len);
+ switch (ret) {
+ case 0:
+ printf("\nscontext %s\n", scontext);
+ free(scontext);
+ break;
+ case -EINVAL:
+ printf("\ninvalid sid\n");
+ break;
+ case -ENOMEM:
+ printf("\nout of memory\n");
+ break;
+ default:
+ printf("return code 0x%x\n", ret);
+ }
+ break;
+ case '2':
+ printf("scontext? ");
+ FGETS(ans, sizeof(ans), stdin);
+ scontext_len = strlen(ans);
+ ans[scontext_len - 1] = 0;
+ ret = sepol_context_to_sid(ans, scontext_len, &ssid);
+ switch (ret) {
+ case 0:
+ printf("\nsid %d\n", ssid);
+ break;
+ case -EINVAL:
+ printf("\ninvalid context\n");
+ break;
+ case -ENOMEM:
+ printf("\nout of memory\n");
+ break;
+ default:
+ printf("return code 0x%x\n", ret);
+ }
+ break;
+ case '3':
+ case '4':
+ case '5':
+ ch = ans[0];
+
+ printf("source sid? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ssid = atoi(ans);
+ printf("target sid? ");
+ FGETS(ans, sizeof(ans), stdin);
+ tsid = atoi(ans);
+
+ printf("object class? ");
+ FGETS(ans, sizeof(ans), stdin);
+ if (isdigit(ans[0])) {
+ tclass = atoi(ans);
+ if (!tclass
+ || tclass > policydb.p_classes.nprim) {
+ printf("\nNo such class.\n");
+ break;
+ }
+ } else {
+ ans[strlen(ans) - 1] = 0;
+ cladatum =
+ (class_datum_t *) hashtab_search(policydb.
+ p_classes.
+ table,
+ ans);
+ if (!cladatum) {
+ printf("\nNo such class\n");
+ break;
+ }
+ tclass = cladatum->s.value;
+ }
+
+ if (ch == '3')
+ ret =
+ sepol_transition_sid(ssid, tsid, tclass,
+ &ssid);
+ else if (ch == '4')
+ ret =
+ sepol_member_sid(ssid, tsid, tclass, &ssid);
+ else
+ ret =
+ sepol_change_sid(ssid, tsid, tclass, &ssid);
+ switch (ret) {
+ case 0:
+ printf("\nsid %d\n", ssid);
+ break;
+ case -EINVAL:
+ printf("\ninvalid sid\n");
+ break;
+ case -ENOMEM:
+ printf("\nout of memory\n");
+ break;
+ default:
+ printf("return code 0x%x\n", ret);
+ }
+ break;
+ case '6':
+ sepol_sidtab_map(&sidtab, print_sid, 0);
+ break;
+ case '7':
+ printf("pathname? ");
+ FGETS(ans, sizeof(ans), stdin);
+ pathlen = strlen(ans);
+ ans[pathlen - 1] = 0;
+ printf("%s: loading policy configuration from %s\n",
+ argv[0], ans);
+ fd = open(ans, O_RDONLY);
+ if (fd < 0) {
+ fprintf(stderr, "Can't open '%s': %s\n",
+ ans, strerror(errno));
+ break;
+ }
+ if (fstat(fd, &sb) < 0) {
+ fprintf(stderr, "Can't stat '%s': %s\n",
+ ans, strerror(errno));
+ break;
+ }
+ map =
+ mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE, fd, 0);
+ if (map == MAP_FAILED) {
+ fprintf(stderr, "Can't map '%s': %s\n",
+ ans, strerror(errno));
+ break;
+ }
+ ret = sepol_load_policy(map, sb.st_size);
+ switch (ret) {
+ case 0:
+ printf("\nsuccess\n");
+ break;
+ case -EINVAL:
+ printf("\ninvalid policy\n");
+ break;
+ case -ENOMEM:
+ printf("\nout of memory\n");
+ break;
+ default:
+ printf("return code 0x%x\n", ret);
+ }
+ break;
+ case '8':
+ printf("fs kdevname? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+ sepol_fs_sid(ans, &ssid, &tsid);
+ printf("fs_sid %d default_file_sid %d\n", ssid, tsid);
+ break;
+ case '9':
+ printf("protocol? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+ if (!strcmp(ans, "tcp") || !strcmp(ans, "TCP"))
+ protocol = IPPROTO_TCP;
+ else if (!strcmp(ans, "udp") || !strcmp(ans, "UDP"))
+ protocol = IPPROTO_UDP;
+ else {
+ printf("unknown protocol\n");
+ break;
+ }
+ printf("port? ");
+ FGETS(ans, sizeof(ans), stdin);
+ port = atoi(ans);
+ sepol_port_sid(0, 0, protocol, port, &ssid);
+ printf("sid %d\n", ssid);
+ break;
+ case 'a':
+ printf("netif name? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+ sepol_netif_sid(ans, &ssid, &tsid);
+ printf("if_sid %d default_msg_sid %d\n", ssid, tsid);
+ break;
+ case 'b':{
+ char *p;
+ int family, len;
+ struct in_addr addr4;
+ struct in6_addr addr6;
+
+ printf("protocol family? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+ if (!strcasecmp(ans, "ipv4"))
+ family = AF_INET;
+ else if (!strcasecmp(ans, "ipv6"))
+ family = AF_INET6;
+ else {
+ printf("unknown protocol family\n");
+ break;
+ }
+
+ printf("node address? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+
+ if (family == AF_INET) {
+ p = (char *)&addr4;
+ len = sizeof(addr4);
+ } else {
+ p = (char *)&addr6;
+ len = sizeof(addr6);
+ }
+
+ if (inet_pton(family, ans, p) < 1) {
+ printf("error parsing address\n");
+ break;
+ }
+
+ sepol_node_sid(family, p, len, &ssid);
+ printf("sid %d\n", ssid);
+ break;
+ }
+ case 'c':
+ printf("fstype? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+ sepol_fs_use(ans, &uret, &ssid);
+ switch (uret) {
+ case SECURITY_FS_USE_XATTR:
+ printf("use xattr\n");
+ break;
+ case SECURITY_FS_USE_TRANS:
+ printf("use transition SIDs\n");
+ break;
+ case SECURITY_FS_USE_TASK:
+ printf("use task SIDs\n");
+ break;
+ case SECURITY_FS_USE_GENFS:
+ printf("use genfs\n");
+ break;
+ case SECURITY_FS_USE_NONE:
+ printf("no labeling support\n");
+ break;
+ }
+ printf("sid %d\n", ssid);
+ break;
+ case 'd':
+ printf("fstype? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+ fstype = strdup(ans);
+ printf("path? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+ path = strdup(ans);
+ printf("object class? ");
+ FGETS(ans, sizeof(ans), stdin);
+ if (isdigit(ans[0])) {
+ tclass = atoi(ans);
+ if (!tclass
+ || tclass > policydb.p_classes.nprim) {
+ printf("\nNo such class.\n");
+ break;
+ }
+ } else {
+ ans[strlen(ans) - 1] = 0;
+ cladatum =
+ (class_datum_t *) hashtab_search(policydb.
+ p_classes.
+ table,
+ ans);
+ if (!cladatum) {
+ printf("\nNo such class\n");
+ break;
+ }
+ tclass = cladatum->s.value;
+ }
+ sepol_genfs_sid(fstype, path, tclass, &ssid);
+ printf("sid %d\n", ssid);
+ free(fstype);
+ free(path);
+ break;
+ case 'e':
+ printf("from SID? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+ ssid = atoi(ans);
+
+ printf("username? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+
+ ret = sepol_get_user_sids(ssid, ans, &sids, &nel);
+ switch (ret) {
+ case 0:
+ if (!nel)
+ printf("\nnone\n");
+ for (i = 0; i < nel; i++)
+ print_sid(sids[i], NULL, NULL);
+ free(sids);
+ break;
+ case -ENOMEM:
+ printf("\nout of memory\n");
+ break;
+ case -EINVAL:
+ printf("\ninvalid argument\n");
+ break;
+ default:
+ printf("\nerror\n");
+ break;
+ }
+ break;
+ case 'f':
+ display_bools();
+ break;
+ case 'g':
+ display_cond_expressions();
+ break;
+ case 'h':
+ printf("name? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+
+ name = malloc((strlen(ans) + 1) * sizeof(char));
+ if (name == NULL) {
+ fprintf(stderr, "couldn't malloc string.\n");
+ break;
+ }
+ strcpy(name, ans);
+
+ printf("state? ");
+ FGETS(ans, sizeof(ans), stdin);
+ ans[strlen(ans) - 1] = 0;
+
+ if (atoi(ans))
+ state = 1;
+ else
+ state = 0;
+
+ change_bool(name, state);
+ free(name);
+ break;
+#ifdef EQUIVTYPES
+ case 'z':
+ identify_equiv_types();
+ break;
+#endif
+ case 'm':
+ goto menu;
+ case 'q':
+ exit(0);
+ break;
+ default:
+ printf("\nUnknown option %s.\n", ans);
+ }
+ }
+
+ return 0;
+}
+
+/* FLASK */