16cd6a6acSopenharmony_ci
26cd6a6acSopenharmony_ci/*
36cd6a6acSopenharmony_ci * Author : Stephen Smalley, <sds@tycho.nsa.gov>
46cd6a6acSopenharmony_ci */
56cd6a6acSopenharmony_ci
66cd6a6acSopenharmony_ci/*
76cd6a6acSopenharmony_ci * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com>
86cd6a6acSopenharmony_ci *
96cd6a6acSopenharmony_ci *	Support for enhanced MLS infrastructure.
106cd6a6acSopenharmony_ci *
116cd6a6acSopenharmony_ci * Updated: Karl MacMillan <kmacmillan@tresys.com>
126cd6a6acSopenharmony_ci *
136cd6a6acSopenharmony_ci * 	Added conditional policy language extensions
146cd6a6acSopenharmony_ci *
156cd6a6acSopenharmony_ci * Updated: James Morris <jmorris@intercode.com.au>
166cd6a6acSopenharmony_ci *
176cd6a6acSopenharmony_ci *	Added IPv6 support.
186cd6a6acSopenharmony_ci *
196cd6a6acSopenharmony_ci * Updated: Joshua Brindle <jbrindle@tresys.com>
206cd6a6acSopenharmony_ci *	    Karl MacMillan <kmacmillan@tresys.com>
216cd6a6acSopenharmony_ci *          Jason Tang     <jtang@tresys.com>
226cd6a6acSopenharmony_ci *
236cd6a6acSopenharmony_ci *	Policy Module support.
246cd6a6acSopenharmony_ci *
256cd6a6acSopenharmony_ci * Copyright (C) 2017 Mellanox Technologies Inc.
266cd6a6acSopenharmony_ci * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc.
276cd6a6acSopenharmony_ci * Copyright (C) 2003 - 2005 Tresys Technology, LLC
286cd6a6acSopenharmony_ci * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
296cd6a6acSopenharmony_ci *	This program is free software; you can redistribute it and/or modify
306cd6a6acSopenharmony_ci *  	it under the terms of the GNU General Public License as published by
316cd6a6acSopenharmony_ci *	the Free Software Foundation, version 2.
326cd6a6acSopenharmony_ci */
336cd6a6acSopenharmony_ci
346cd6a6acSopenharmony_ci/* FLASK */
356cd6a6acSopenharmony_ci
366cd6a6acSopenharmony_ci/*
376cd6a6acSopenharmony_ci * checkpolicy
386cd6a6acSopenharmony_ci *
396cd6a6acSopenharmony_ci * Load and check a policy configuration.
406cd6a6acSopenharmony_ci *
416cd6a6acSopenharmony_ci * A policy configuration is created in a text format,
426cd6a6acSopenharmony_ci * and then compiled into a binary format for use by
436cd6a6acSopenharmony_ci * the security server.  By default, checkpolicy reads
446cd6a6acSopenharmony_ci * the text format.   If '-b' is specified, then checkpolicy
456cd6a6acSopenharmony_ci * reads the binary format instead.
466cd6a6acSopenharmony_ci *
476cd6a6acSopenharmony_ci * If '-o output_file' is specified, then checkpolicy
486cd6a6acSopenharmony_ci * writes the binary format version of the configuration
496cd6a6acSopenharmony_ci * to the specified output file.
506cd6a6acSopenharmony_ci *
516cd6a6acSopenharmony_ci * If '-d' is specified, then checkpolicy permits the user
526cd6a6acSopenharmony_ci * to interactively test the security server functions with
536cd6a6acSopenharmony_ci * the loaded policy configuration.
546cd6a6acSopenharmony_ci *
556cd6a6acSopenharmony_ci * If '-c' is specified, then the supplied parameter is used to
566cd6a6acSopenharmony_ci * determine which policy version to use for generating binary
576cd6a6acSopenharmony_ci * policy.  This is for compatibility with older kernels. If any
586cd6a6acSopenharmony_ci * booleans or conditional rules are thrown away a warning is printed.
596cd6a6acSopenharmony_ci */
606cd6a6acSopenharmony_ci
616cd6a6acSopenharmony_ci#include <ctype.h>
626cd6a6acSopenharmony_ci#include <getopt.h>
636cd6a6acSopenharmony_ci#include <unistd.h>
646cd6a6acSopenharmony_ci#include <stdlib.h>
656cd6a6acSopenharmony_ci#include <sys/types.h>
666cd6a6acSopenharmony_ci#include <sys/stat.h>
676cd6a6acSopenharmony_ci#include <sys/socket.h>
686cd6a6acSopenharmony_ci#include <netinet/in.h>
696cd6a6acSopenharmony_ci#ifndef IPPROTO_DCCP
706cd6a6acSopenharmony_ci#define IPPROTO_DCCP 33
716cd6a6acSopenharmony_ci#endif
726cd6a6acSopenharmony_ci#ifndef IPPROTO_SCTP
736cd6a6acSopenharmony_ci#define IPPROTO_SCTP 132
746cd6a6acSopenharmony_ci#endif
756cd6a6acSopenharmony_ci#include <arpa/inet.h>
766cd6a6acSopenharmony_ci#include <fcntl.h>
776cd6a6acSopenharmony_ci#include <stdio.h>
786cd6a6acSopenharmony_ci#include <errno.h>
796cd6a6acSopenharmony_ci#include <sys/mman.h>
806cd6a6acSopenharmony_ci
816cd6a6acSopenharmony_ci#include <sepol/module_to_cil.h>
826cd6a6acSopenharmony_ci#include <sepol/kernel_to_cil.h>
836cd6a6acSopenharmony_ci#include <sepol/kernel_to_conf.h>
846cd6a6acSopenharmony_ci#include <sepol/policydb/policydb.h>
856cd6a6acSopenharmony_ci#include <sepol/policydb/services.h>
866cd6a6acSopenharmony_ci#include <sepol/policydb/conditional.h>
876cd6a6acSopenharmony_ci#include <sepol/policydb/hierarchy.h>
886cd6a6acSopenharmony_ci#include <sepol/policydb/expand.h>
896cd6a6acSopenharmony_ci#include <sepol/policydb/link.h>
906cd6a6acSopenharmony_ci
916cd6a6acSopenharmony_ci#include "queue.h"
926cd6a6acSopenharmony_ci#include "checkpolicy.h"
936cd6a6acSopenharmony_ci#include "parse_util.h"
946cd6a6acSopenharmony_ci
956cd6a6acSopenharmony_cistatic policydb_t policydb;
966cd6a6acSopenharmony_cistatic sidtab_t sidtab;
976cd6a6acSopenharmony_ci
986cd6a6acSopenharmony_ciextern policydb_t *policydbp;
996cd6a6acSopenharmony_ciextern int mlspol;
1006cd6a6acSopenharmony_ciextern int werror;
1016cd6a6acSopenharmony_ci
1026cd6a6acSopenharmony_cistatic int handle_unknown = SEPOL_DENY_UNKNOWN;
1036cd6a6acSopenharmony_cistatic const char *txtfile = "policy.conf";
1046cd6a6acSopenharmony_cistatic const char *binfile = "policy";
1056cd6a6acSopenharmony_ci
1066cd6a6acSopenharmony_ciunsigned int policyvers = 0;
1076cd6a6acSopenharmony_ci
1086cd6a6acSopenharmony_cistatic __attribute__((__noreturn__)) void usage(const char *progname)
1096cd6a6acSopenharmony_ci{
1106cd6a6acSopenharmony_ci	printf
1116cd6a6acSopenharmony_ci	    ("usage:  %s [-b[F]] [-C] [-d] [-U handle_unknown (allow,deny,reject)] [-M] "
1126cd6a6acSopenharmony_ci	     "[-c policyvers (%d-%d)] [-o output_file|-] [-S] [-O] "
1136cd6a6acSopenharmony_ci	     "[-t target_platform (selinux,xen)] [-E] [-V] [input_file]\n",
1146cd6a6acSopenharmony_ci	     progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
1156cd6a6acSopenharmony_ci	exit(1);
1166cd6a6acSopenharmony_ci}
1176cd6a6acSopenharmony_ci
1186cd6a6acSopenharmony_ci#define FGETS(out, size, in) \
1196cd6a6acSopenharmony_cido { \
1206cd6a6acSopenharmony_ci	if (fgets(out,size,in)==NULL) {	\
1216cd6a6acSopenharmony_ci		fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__, \
1226cd6a6acSopenharmony_ci			strerror(errno)); \
1236cd6a6acSopenharmony_ci		exit(1);\
1246cd6a6acSopenharmony_ci	} \
1256cd6a6acSopenharmony_ci} while (0)
1266cd6a6acSopenharmony_ci
1276cd6a6acSopenharmony_cistatic int print_sid(sepol_security_id_t sid,
1286cd6a6acSopenharmony_ci		     context_struct_t * context
1296cd6a6acSopenharmony_ci		     __attribute__ ((unused)), void *data
1306cd6a6acSopenharmony_ci		     __attribute__ ((unused)))
1316cd6a6acSopenharmony_ci{
1326cd6a6acSopenharmony_ci	sepol_security_context_t scontext;
1336cd6a6acSopenharmony_ci	size_t scontext_len;
1346cd6a6acSopenharmony_ci	int rc;
1356cd6a6acSopenharmony_ci
1366cd6a6acSopenharmony_ci	rc = sepol_sid_to_context(sid, &scontext, &scontext_len);
1376cd6a6acSopenharmony_ci	if (rc)
1386cd6a6acSopenharmony_ci		printf("sid %d -> error %d\n", sid, rc);
1396cd6a6acSopenharmony_ci	else {
1406cd6a6acSopenharmony_ci		printf("sid %d -> scontext %s\n", sid, scontext);
1416cd6a6acSopenharmony_ci		free(scontext);
1426cd6a6acSopenharmony_ci	}
1436cd6a6acSopenharmony_ci	return 0;
1446cd6a6acSopenharmony_ci}
1456cd6a6acSopenharmony_ci
1466cd6a6acSopenharmony_cistruct val_to_name {
1476cd6a6acSopenharmony_ci	unsigned int val;
1486cd6a6acSopenharmony_ci	char *name;
1496cd6a6acSopenharmony_ci};
1506cd6a6acSopenharmony_ci
1516cd6a6acSopenharmony_cistatic int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *p)
1526cd6a6acSopenharmony_ci{
1536cd6a6acSopenharmony_ci	struct val_to_name *v = p;
1546cd6a6acSopenharmony_ci	perm_datum_t *perdatum;
1556cd6a6acSopenharmony_ci
1566cd6a6acSopenharmony_ci	perdatum = (perm_datum_t *) datum;
1576cd6a6acSopenharmony_ci
1586cd6a6acSopenharmony_ci	if (v->val == perdatum->s.value) {
1596cd6a6acSopenharmony_ci		v->name = key;
1606cd6a6acSopenharmony_ci		return 1;
1616cd6a6acSopenharmony_ci	}
1626cd6a6acSopenharmony_ci
1636cd6a6acSopenharmony_ci	return 0;
1646cd6a6acSopenharmony_ci}
1656cd6a6acSopenharmony_ci
1666cd6a6acSopenharmony_ci#ifdef EQUIVTYPES
1676cd6a6acSopenharmony_cistatic int insert_type_rule(avtab_key_t * k, avtab_datum_t * d,
1686cd6a6acSopenharmony_ci			    struct avtab_node *type_rules)
1696cd6a6acSopenharmony_ci{
1706cd6a6acSopenharmony_ci	struct avtab_node *p, *c, *n;
1716cd6a6acSopenharmony_ci
1726cd6a6acSopenharmony_ci	for (p = type_rules, c = type_rules->next; c; p = c, c = c->next) {
1736cd6a6acSopenharmony_ci		/*
1746cd6a6acSopenharmony_ci		 * Find the insertion point, keeping the list
1756cd6a6acSopenharmony_ci		 * ordered by source type, then target type, then
1766cd6a6acSopenharmony_ci		 * target class.
1776cd6a6acSopenharmony_ci		 */
1786cd6a6acSopenharmony_ci		if (k->source_type < c->key.source_type)
1796cd6a6acSopenharmony_ci			break;
1806cd6a6acSopenharmony_ci		if (k->source_type == c->key.source_type &&
1816cd6a6acSopenharmony_ci		    k->target_type < c->key.target_type)
1826cd6a6acSopenharmony_ci			break;
1836cd6a6acSopenharmony_ci		if (k->source_type == c->key.source_type &&
1846cd6a6acSopenharmony_ci		    k->target_type == c->key.target_type &&
1856cd6a6acSopenharmony_ci		    k->target_class < c->key.target_class)
1866cd6a6acSopenharmony_ci			break;
1876cd6a6acSopenharmony_ci	}
1886cd6a6acSopenharmony_ci
1896cd6a6acSopenharmony_ci	/* Insert the rule */
1906cd6a6acSopenharmony_ci	n = malloc(sizeof(struct avtab_node));
1916cd6a6acSopenharmony_ci	if (!n) {
1926cd6a6acSopenharmony_ci		fprintf(stderr, "out of memory\n");
1936cd6a6acSopenharmony_ci		exit(1);
1946cd6a6acSopenharmony_ci	}
1956cd6a6acSopenharmony_ci
1966cd6a6acSopenharmony_ci	n->key = *k;
1976cd6a6acSopenharmony_ci	n->datum = *d;
1986cd6a6acSopenharmony_ci	n->next = p->next;
1996cd6a6acSopenharmony_ci	p->next = n;
2006cd6a6acSopenharmony_ci	return 0;
2016cd6a6acSopenharmony_ci}
2026cd6a6acSopenharmony_ci
2036cd6a6acSopenharmony_cistatic int create_type_rules(avtab_key_t * k, avtab_datum_t * d, void *args)
2046cd6a6acSopenharmony_ci{
2056cd6a6acSopenharmony_ci	struct avtab_node *type_rules = args;
2066cd6a6acSopenharmony_ci
2076cd6a6acSopenharmony_ci	if (d->specified & AVTAB_ALLOWED) {
2086cd6a6acSopenharmony_ci		/*
2096cd6a6acSopenharmony_ci		 * Insert the rule into the lists for both
2106cd6a6acSopenharmony_ci		 * the source type and the target type.
2116cd6a6acSopenharmony_ci		 */
2126cd6a6acSopenharmony_ci		if (insert_type_rule(k, d, &type_rules[k->source_type - 1]))
2136cd6a6acSopenharmony_ci			return -1;
2146cd6a6acSopenharmony_ci		if (insert_type_rule(k, d, &type_rules[k->target_type - 1]))
2156cd6a6acSopenharmony_ci			return -1;
2166cd6a6acSopenharmony_ci	}
2176cd6a6acSopenharmony_ci
2186cd6a6acSopenharmony_ci	return 0;
2196cd6a6acSopenharmony_ci}
2206cd6a6acSopenharmony_ci
2216cd6a6acSopenharmony_cistatic void free_type_rules(struct avtab_node *l)
2226cd6a6acSopenharmony_ci{
2236cd6a6acSopenharmony_ci	struct avtab_node *tmp;
2246cd6a6acSopenharmony_ci
2256cd6a6acSopenharmony_ci	while (l) {
2266cd6a6acSopenharmony_ci		tmp = l;
2276cd6a6acSopenharmony_ci		l = l->next;
2286cd6a6acSopenharmony_ci		free(tmp);
2296cd6a6acSopenharmony_ci	}
2306cd6a6acSopenharmony_ci}
2316cd6a6acSopenharmony_ci
2326cd6a6acSopenharmony_cistatic int identify_equiv_types(void)
2336cd6a6acSopenharmony_ci{
2346cd6a6acSopenharmony_ci	struct avtab_node *type_rules, *l1, *l2;
2356cd6a6acSopenharmony_ci	int i, j;
2366cd6a6acSopenharmony_ci
2376cd6a6acSopenharmony_ci	/*
2386cd6a6acSopenharmony_ci	 * Create a list of access vector rules for each type
2396cd6a6acSopenharmony_ci	 * from the access vector table.
2406cd6a6acSopenharmony_ci	 */
2416cd6a6acSopenharmony_ci	type_rules = malloc(sizeof(struct avtab_node) * policydb.p_types.nprim);
2426cd6a6acSopenharmony_ci	if (!type_rules) {
2436cd6a6acSopenharmony_ci		fprintf(stderr, "out of memory\n");
2446cd6a6acSopenharmony_ci		exit(1);
2456cd6a6acSopenharmony_ci	}
2466cd6a6acSopenharmony_ci	memset(type_rules, 0,
2476cd6a6acSopenharmony_ci	       sizeof(struct avtab_node) * policydb.p_types.nprim);
2486cd6a6acSopenharmony_ci	if (avtab_map(&policydb.te_avtab, create_type_rules, type_rules))
2496cd6a6acSopenharmony_ci		exit(1);
2506cd6a6acSopenharmony_ci
2516cd6a6acSopenharmony_ci	/*
2526cd6a6acSopenharmony_ci	 * Compare the type lists and identify equivalent types.
2536cd6a6acSopenharmony_ci	 */
2546cd6a6acSopenharmony_ci	for (i = 0; i < policydb.p_types.nprim - 1; i++) {
2556cd6a6acSopenharmony_ci		if (!type_rules[i].next)
2566cd6a6acSopenharmony_ci			continue;
2576cd6a6acSopenharmony_ci		for (j = i + 1; j < policydb.p_types.nprim; j++) {
2586cd6a6acSopenharmony_ci			for (l1 = type_rules[i].next, l2 = type_rules[j].next;
2596cd6a6acSopenharmony_ci			     l1 && l2; l1 = l1->next, l2 = l2->next) {
2606cd6a6acSopenharmony_ci				if (l2->key.source_type == (j + 1)) {
2616cd6a6acSopenharmony_ci					if (l1->key.source_type != (i + 1))
2626cd6a6acSopenharmony_ci						break;
2636cd6a6acSopenharmony_ci				} else {
2646cd6a6acSopenharmony_ci					if (l1->key.source_type !=
2656cd6a6acSopenharmony_ci					    l2->key.source_type)
2666cd6a6acSopenharmony_ci						break;
2676cd6a6acSopenharmony_ci				}
2686cd6a6acSopenharmony_ci				if (l2->key.target_type == (j + 1)) {
2696cd6a6acSopenharmony_ci					if (l1->key.target_type != (i + 1))
2706cd6a6acSopenharmony_ci						break;
2716cd6a6acSopenharmony_ci				} else {
2726cd6a6acSopenharmony_ci					if (l1->key.target_type !=
2736cd6a6acSopenharmony_ci					    l2->key.target_type)
2746cd6a6acSopenharmony_ci						break;
2756cd6a6acSopenharmony_ci				}
2766cd6a6acSopenharmony_ci				if (l1->key.target_class != l2->key.target_class
2776cd6a6acSopenharmony_ci				    || l1->datum.allowed != l2->datum.allowed)
2786cd6a6acSopenharmony_ci					break;
2796cd6a6acSopenharmony_ci			}
2806cd6a6acSopenharmony_ci			if (l1 || l2)
2816cd6a6acSopenharmony_ci				continue;
2826cd6a6acSopenharmony_ci			free_type_rules(type_rules[j].next);
2836cd6a6acSopenharmony_ci			type_rules[j].next = NULL;
2846cd6a6acSopenharmony_ci			printf("Types %s and %s are equivalent.\n",
2856cd6a6acSopenharmony_ci			       policydb.p_type_val_to_name[i],
2866cd6a6acSopenharmony_ci			       policydb.p_type_val_to_name[j]);
2876cd6a6acSopenharmony_ci		}
2886cd6a6acSopenharmony_ci		free_type_rules(type_rules[i].next);
2896cd6a6acSopenharmony_ci		type_rules[i].next = NULL;
2906cd6a6acSopenharmony_ci	}
2916cd6a6acSopenharmony_ci
2926cd6a6acSopenharmony_ci	free(type_rules);
2936cd6a6acSopenharmony_ci	return 0;
2946cd6a6acSopenharmony_ci}
2956cd6a6acSopenharmony_ci#endif
2966cd6a6acSopenharmony_ci
2976cd6a6acSopenharmony_cistatic int display_bools(void)
2986cd6a6acSopenharmony_ci{
2996cd6a6acSopenharmony_ci	uint32_t i;
3006cd6a6acSopenharmony_ci
3016cd6a6acSopenharmony_ci	for (i = 0; i < policydbp->p_bools.nprim; i++) {
3026cd6a6acSopenharmony_ci		printf("%s : %d\n", policydbp->p_bool_val_to_name[i],
3036cd6a6acSopenharmony_ci		       policydbp->bool_val_to_struct[i]->state);
3046cd6a6acSopenharmony_ci	}
3056cd6a6acSopenharmony_ci	return 0;
3066cd6a6acSopenharmony_ci}
3076cd6a6acSopenharmony_ci
3086cd6a6acSopenharmony_cistatic void display_expr(const cond_expr_t * exp)
3096cd6a6acSopenharmony_ci{
3106cd6a6acSopenharmony_ci
3116cd6a6acSopenharmony_ci	const cond_expr_t *cur;
3126cd6a6acSopenharmony_ci	for (cur = exp; cur != NULL; cur = cur->next) {
3136cd6a6acSopenharmony_ci		switch (cur->expr_type) {
3146cd6a6acSopenharmony_ci		case COND_BOOL:
3156cd6a6acSopenharmony_ci			printf("%s ",
3166cd6a6acSopenharmony_ci			       policydbp->p_bool_val_to_name[cur->bool - 1]);
3176cd6a6acSopenharmony_ci			break;
3186cd6a6acSopenharmony_ci		case COND_NOT:
3196cd6a6acSopenharmony_ci			printf("! ");
3206cd6a6acSopenharmony_ci			break;
3216cd6a6acSopenharmony_ci		case COND_OR:
3226cd6a6acSopenharmony_ci			printf("|| ");
3236cd6a6acSopenharmony_ci			break;
3246cd6a6acSopenharmony_ci		case COND_AND:
3256cd6a6acSopenharmony_ci			printf("&& ");
3266cd6a6acSopenharmony_ci			break;
3276cd6a6acSopenharmony_ci		case COND_XOR:
3286cd6a6acSopenharmony_ci			printf("^ ");
3296cd6a6acSopenharmony_ci			break;
3306cd6a6acSopenharmony_ci		case COND_EQ:
3316cd6a6acSopenharmony_ci			printf("== ");
3326cd6a6acSopenharmony_ci			break;
3336cd6a6acSopenharmony_ci		case COND_NEQ:
3346cd6a6acSopenharmony_ci			printf("!= ");
3356cd6a6acSopenharmony_ci			break;
3366cd6a6acSopenharmony_ci		default:
3376cd6a6acSopenharmony_ci			printf("error!");
3386cd6a6acSopenharmony_ci			break;
3396cd6a6acSopenharmony_ci		}
3406cd6a6acSopenharmony_ci	}
3416cd6a6acSopenharmony_ci}
3426cd6a6acSopenharmony_ci
3436cd6a6acSopenharmony_cistatic int display_cond_expressions(void)
3446cd6a6acSopenharmony_ci{
3456cd6a6acSopenharmony_ci	const cond_node_t *cur;
3466cd6a6acSopenharmony_ci
3476cd6a6acSopenharmony_ci	for (cur = policydbp->cond_list; cur != NULL; cur = cur->next) {
3486cd6a6acSopenharmony_ci		printf("expression: ");
3496cd6a6acSopenharmony_ci		display_expr(cur->expr);
3506cd6a6acSopenharmony_ci		printf("current state: %d\n", cur->cur_state);
3516cd6a6acSopenharmony_ci	}
3526cd6a6acSopenharmony_ci	return 0;
3536cd6a6acSopenharmony_ci}
3546cd6a6acSopenharmony_ci
3556cd6a6acSopenharmony_cistatic int change_bool(const char *name, int state)
3566cd6a6acSopenharmony_ci{
3576cd6a6acSopenharmony_ci	cond_bool_datum_t *bool;
3586cd6a6acSopenharmony_ci
3596cd6a6acSopenharmony_ci	bool = hashtab_search(policydbp->p_bools.table, name);
3606cd6a6acSopenharmony_ci	if (bool == NULL) {
3616cd6a6acSopenharmony_ci		printf("Could not find bool %s\n", name);
3626cd6a6acSopenharmony_ci		return -1;
3636cd6a6acSopenharmony_ci	}
3646cd6a6acSopenharmony_ci	bool->state = state;
3656cd6a6acSopenharmony_ci	evaluate_conds(policydbp);
3666cd6a6acSopenharmony_ci	return 0;
3676cd6a6acSopenharmony_ci}
3686cd6a6acSopenharmony_ci
3696cd6a6acSopenharmony_cistatic int check_level(hashtab_key_t key, hashtab_datum_t datum, void *arg __attribute__ ((unused)))
3706cd6a6acSopenharmony_ci{
3716cd6a6acSopenharmony_ci	level_datum_t *levdatum = (level_datum_t *) datum;
3726cd6a6acSopenharmony_ci
3736cd6a6acSopenharmony_ci	if (!levdatum->isalias && !levdatum->defined) {
3746cd6a6acSopenharmony_ci		fprintf(stderr,
3756cd6a6acSopenharmony_ci			"Error:  sensitivity %s was not used in a level definition!\n",
3766cd6a6acSopenharmony_ci			key);
3776cd6a6acSopenharmony_ci		return -1;
3786cd6a6acSopenharmony_ci	}
3796cd6a6acSopenharmony_ci	return 0;
3806cd6a6acSopenharmony_ci}
3816cd6a6acSopenharmony_ci
3826cd6a6acSopenharmony_ciint main(int argc, char **argv)
3836cd6a6acSopenharmony_ci{
3846cd6a6acSopenharmony_ci	policydb_t parse_policy;
3856cd6a6acSopenharmony_ci	sepol_security_class_t tclass;
3866cd6a6acSopenharmony_ci	sepol_security_id_t ssid, tsid, *sids, oldsid, newsid, tasksid;
3876cd6a6acSopenharmony_ci	sepol_security_context_t scontext;
3886cd6a6acSopenharmony_ci	struct sepol_av_decision avd;
3896cd6a6acSopenharmony_ci	class_datum_t *cladatum;
3906cd6a6acSopenharmony_ci	const char *file = txtfile;
3916cd6a6acSopenharmony_ci	char ans[80 + 1], *path, *fstype;
3926cd6a6acSopenharmony_ci	const char *outfile = NULL;
3936cd6a6acSopenharmony_ci	size_t scontext_len, pathlen;
3946cd6a6acSopenharmony_ci	unsigned int i;
3956cd6a6acSopenharmony_ci	unsigned int protocol, port;
3966cd6a6acSopenharmony_ci	unsigned int binary = 0, debug = 0, sort = 0, cil = 0, conf = 0, optimize = 0;
3976cd6a6acSopenharmony_ci	struct val_to_name v;
3986cd6a6acSopenharmony_ci	int ret, ch, fd, target = SEPOL_TARGET_SELINUX;
3996cd6a6acSopenharmony_ci	unsigned int nel, uret;
4006cd6a6acSopenharmony_ci	struct stat sb;
4016cd6a6acSopenharmony_ci	void *map;
4026cd6a6acSopenharmony_ci	FILE *outfp = NULL;
4036cd6a6acSopenharmony_ci	char *name;
4046cd6a6acSopenharmony_ci	int state;
4056cd6a6acSopenharmony_ci	int show_version = 0;
4066cd6a6acSopenharmony_ci	char *reason_buf = NULL;
4076cd6a6acSopenharmony_ci	unsigned int reason;
4086cd6a6acSopenharmony_ci	int flags;
4096cd6a6acSopenharmony_ci	struct policy_file pf;
4106cd6a6acSopenharmony_ci	const struct option long_options[] = {
4116cd6a6acSopenharmony_ci		{"output", required_argument, NULL, 'o'},
4126cd6a6acSopenharmony_ci		{"target", required_argument, NULL, 't'},
4136cd6a6acSopenharmony_ci		{"binary", no_argument, NULL, 'b'},
4146cd6a6acSopenharmony_ci		{"debug", no_argument, NULL, 'd'},
4156cd6a6acSopenharmony_ci		{"version", no_argument, NULL, 'V'},
4166cd6a6acSopenharmony_ci		{"handle-unknown", required_argument, NULL, 'U'},
4176cd6a6acSopenharmony_ci		{"mls", no_argument, NULL, 'M'},
4186cd6a6acSopenharmony_ci		{"cil", no_argument, NULL, 'C'},
4196cd6a6acSopenharmony_ci		{"conf",no_argument, NULL, 'F'},
4206cd6a6acSopenharmony_ci		{"sort", no_argument, NULL, 'S'},
4216cd6a6acSopenharmony_ci		{"optimize", no_argument, NULL, 'O'},
4226cd6a6acSopenharmony_ci		{"werror", no_argument, NULL, 'E'},
4236cd6a6acSopenharmony_ci		{"help", no_argument, NULL, 'h'},
4246cd6a6acSopenharmony_ci		{NULL, 0, NULL, 0}
4256cd6a6acSopenharmony_ci	};
4266cd6a6acSopenharmony_ci
4276cd6a6acSopenharmony_ci	while ((ch = getopt_long(argc, argv, "o:t:dbU:MCFSVc:OEh", long_options, NULL)) != -1) {
4286cd6a6acSopenharmony_ci		switch (ch) {
4296cd6a6acSopenharmony_ci		case 'o':
4306cd6a6acSopenharmony_ci			outfile = optarg;
4316cd6a6acSopenharmony_ci			break;
4326cd6a6acSopenharmony_ci		case 't':
4336cd6a6acSopenharmony_ci			if (!strcasecmp(optarg, "Xen"))
4346cd6a6acSopenharmony_ci				target = SEPOL_TARGET_XEN;
4356cd6a6acSopenharmony_ci			else if (!strcasecmp(optarg, "SELinux"))
4366cd6a6acSopenharmony_ci				target = SEPOL_TARGET_SELINUX;
4376cd6a6acSopenharmony_ci			else{
4386cd6a6acSopenharmony_ci				fprintf(stderr, "%s:  Unknown target platform:"
4396cd6a6acSopenharmony_ci					"%s\n", argv[0], optarg);
4406cd6a6acSopenharmony_ci				exit(1);
4416cd6a6acSopenharmony_ci			}
4426cd6a6acSopenharmony_ci			break;
4436cd6a6acSopenharmony_ci		case 'b':
4446cd6a6acSopenharmony_ci			binary = 1;
4456cd6a6acSopenharmony_ci			file = binfile;
4466cd6a6acSopenharmony_ci			break;
4476cd6a6acSopenharmony_ci		case 'd':
4486cd6a6acSopenharmony_ci			debug = 1;
4496cd6a6acSopenharmony_ci			break;
4506cd6a6acSopenharmony_ci		case 'V':
4516cd6a6acSopenharmony_ci			show_version = 1;
4526cd6a6acSopenharmony_ci			break;
4536cd6a6acSopenharmony_ci		case 'U':
4546cd6a6acSopenharmony_ci			if (!strcasecmp(optarg, "deny")) {
4556cd6a6acSopenharmony_ci				handle_unknown = DENY_UNKNOWN;
4566cd6a6acSopenharmony_ci				break;
4576cd6a6acSopenharmony_ci			}
4586cd6a6acSopenharmony_ci			if (!strcasecmp(optarg, "allow")) {
4596cd6a6acSopenharmony_ci				handle_unknown = ALLOW_UNKNOWN;
4606cd6a6acSopenharmony_ci				break;
4616cd6a6acSopenharmony_ci			}
4626cd6a6acSopenharmony_ci			if (!strcasecmp(optarg, "reject")) {
4636cd6a6acSopenharmony_ci				handle_unknown = REJECT_UNKNOWN;
4646cd6a6acSopenharmony_ci				break;
4656cd6a6acSopenharmony_ci			}
4666cd6a6acSopenharmony_ci			usage(argv[0]);
4676cd6a6acSopenharmony_ci		case 'S':
4686cd6a6acSopenharmony_ci			sort = 1;
4696cd6a6acSopenharmony_ci			break;
4706cd6a6acSopenharmony_ci		case 'O':
4716cd6a6acSopenharmony_ci			optimize = 1;
4726cd6a6acSopenharmony_ci			break;
4736cd6a6acSopenharmony_ci		case 'M':
4746cd6a6acSopenharmony_ci			mlspol = 1;
4756cd6a6acSopenharmony_ci			break;
4766cd6a6acSopenharmony_ci		case 'C':
4776cd6a6acSopenharmony_ci			cil = 1;
4786cd6a6acSopenharmony_ci			break;
4796cd6a6acSopenharmony_ci		case 'F':
4806cd6a6acSopenharmony_ci			conf = 1;
4816cd6a6acSopenharmony_ci			break;
4826cd6a6acSopenharmony_ci		case 'c':{
4836cd6a6acSopenharmony_ci				long int n;
4846cd6a6acSopenharmony_ci				errno = 0;
4856cd6a6acSopenharmony_ci				n = strtol(optarg, NULL, 10);
4866cd6a6acSopenharmony_ci				if (errno) {
4876cd6a6acSopenharmony_ci					fprintf(stderr,
4886cd6a6acSopenharmony_ci						"Invalid policyvers specified: %s\n",
4896cd6a6acSopenharmony_ci						optarg);
4906cd6a6acSopenharmony_ci					usage(argv[0]);
4916cd6a6acSopenharmony_ci					exit(1);
4926cd6a6acSopenharmony_ci				}
4936cd6a6acSopenharmony_ci				if (n < POLICYDB_VERSION_MIN
4946cd6a6acSopenharmony_ci				    || n > POLICYDB_VERSION_MAX) {
4956cd6a6acSopenharmony_ci					fprintf(stderr,
4966cd6a6acSopenharmony_ci						"policyvers value %ld not in range %d-%d\n",
4976cd6a6acSopenharmony_ci						n, POLICYDB_VERSION_MIN,
4986cd6a6acSopenharmony_ci						POLICYDB_VERSION_MAX);
4996cd6a6acSopenharmony_ci					usage(argv[0]);
5006cd6a6acSopenharmony_ci					exit(1);
5016cd6a6acSopenharmony_ci				}
5026cd6a6acSopenharmony_ci				policyvers = n;
5036cd6a6acSopenharmony_ci				break;
5046cd6a6acSopenharmony_ci			}
5056cd6a6acSopenharmony_ci		case 'E':
5066cd6a6acSopenharmony_ci			 werror = 1;
5076cd6a6acSopenharmony_ci			 break;
5086cd6a6acSopenharmony_ci		case 'h':
5096cd6a6acSopenharmony_ci		default:
5106cd6a6acSopenharmony_ci			usage(argv[0]);
5116cd6a6acSopenharmony_ci		}
5126cd6a6acSopenharmony_ci	}
5136cd6a6acSopenharmony_ci
5146cd6a6acSopenharmony_ci	if (show_version) {
5156cd6a6acSopenharmony_ci		printf("%d (compatibility range %d-%d)\n",
5166cd6a6acSopenharmony_ci			   policyvers ? policyvers : POLICYDB_VERSION_MAX ,
5176cd6a6acSopenharmony_ci		       POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN);
5186cd6a6acSopenharmony_ci		exit(0);
5196cd6a6acSopenharmony_ci	}
5206cd6a6acSopenharmony_ci
5216cd6a6acSopenharmony_ci	if (optind != argc) {
5226cd6a6acSopenharmony_ci		file = argv[optind++];
5236cd6a6acSopenharmony_ci		if (optind != argc)
5246cd6a6acSopenharmony_ci			usage(argv[0]);
5256cd6a6acSopenharmony_ci	}
5266cd6a6acSopenharmony_ci	/* Set policydb and sidtab used by libsepol service functions
5276cd6a6acSopenharmony_ci	   to my structures, so that I can directly populate and
5286cd6a6acSopenharmony_ci	   manipulate them. */
5296cd6a6acSopenharmony_ci	sepol_set_policydb(&policydb);
5306cd6a6acSopenharmony_ci	sepol_set_sidtab(&sidtab);
5316cd6a6acSopenharmony_ci
5326cd6a6acSopenharmony_ci	if (cil && conf) {
5336cd6a6acSopenharmony_ci		fprintf(stderr, "Can't convert to CIL and policy.conf at the same time\n");
5346cd6a6acSopenharmony_ci		exit(1);
5356cd6a6acSopenharmony_ci	}
5366cd6a6acSopenharmony_ci
5376cd6a6acSopenharmony_ci	if (binary) {
5386cd6a6acSopenharmony_ci		fd = open(file, O_RDONLY);
5396cd6a6acSopenharmony_ci		if (fd < 0) {
5406cd6a6acSopenharmony_ci			fprintf(stderr, "Can't open '%s':  %s\n",
5416cd6a6acSopenharmony_ci				file, strerror(errno));
5426cd6a6acSopenharmony_ci			exit(1);
5436cd6a6acSopenharmony_ci		}
5446cd6a6acSopenharmony_ci		if (fstat(fd, &sb) < 0) {
5456cd6a6acSopenharmony_ci			fprintf(stderr, "Can't stat '%s':  %s\n",
5466cd6a6acSopenharmony_ci				file, strerror(errno));
5476cd6a6acSopenharmony_ci			exit(1);
5486cd6a6acSopenharmony_ci		}
5496cd6a6acSopenharmony_ci		map =
5506cd6a6acSopenharmony_ci		    mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE,
5516cd6a6acSopenharmony_ci			 fd, 0);
5526cd6a6acSopenharmony_ci		if (map == MAP_FAILED) {
5536cd6a6acSopenharmony_ci			fprintf(stderr, "Can't map '%s':  %s\n",
5546cd6a6acSopenharmony_ci				file, strerror(errno));
5556cd6a6acSopenharmony_ci			exit(1);
5566cd6a6acSopenharmony_ci		}
5576cd6a6acSopenharmony_ci		policy_file_init(&pf);
5586cd6a6acSopenharmony_ci		pf.type = PF_USE_MEMORY;
5596cd6a6acSopenharmony_ci		pf.data = map;
5606cd6a6acSopenharmony_ci		pf.len = sb.st_size;
5616cd6a6acSopenharmony_ci		if (policydb_init(&policydb)) {
5626cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  policydb_init:  Out of memory!\n",
5636cd6a6acSopenharmony_ci				argv[0]);
5646cd6a6acSopenharmony_ci			exit(1);
5656cd6a6acSopenharmony_ci		}
5666cd6a6acSopenharmony_ci		ret = policydb_read(&policydb, &pf, 1);
5676cd6a6acSopenharmony_ci		if (ret) {
5686cd6a6acSopenharmony_ci			fprintf(stderr,
5696cd6a6acSopenharmony_ci				"%s:  error(s) encountered while parsing configuration\n",
5706cd6a6acSopenharmony_ci				argv[0]);
5716cd6a6acSopenharmony_ci			exit(1);
5726cd6a6acSopenharmony_ci		}
5736cd6a6acSopenharmony_ci		policydbp = &policydb;
5746cd6a6acSopenharmony_ci
5756cd6a6acSopenharmony_ci		/* Check Policy Consistency */
5766cd6a6acSopenharmony_ci		if (policydbp->mls) {
5776cd6a6acSopenharmony_ci			if (!mlspol) {
5786cd6a6acSopenharmony_ci				fprintf(stderr, "%s:  MLS policy, but non-MLS"
5796cd6a6acSopenharmony_ci					" is specified\n", argv[0]);
5806cd6a6acSopenharmony_ci				exit(1);
5816cd6a6acSopenharmony_ci			}
5826cd6a6acSopenharmony_ci		} else {
5836cd6a6acSopenharmony_ci			if (mlspol) {
5846cd6a6acSopenharmony_ci				fprintf(stderr, "%s:  non-MLS policy, but MLS"
5856cd6a6acSopenharmony_ci					" is specified\n", argv[0]);
5866cd6a6acSopenharmony_ci				exit(1);
5876cd6a6acSopenharmony_ci			}
5886cd6a6acSopenharmony_ci		}
5896cd6a6acSopenharmony_ci
5906cd6a6acSopenharmony_ci		if (policydbp->policyvers <= POLICYDB_VERSION_PERMISSIVE) {
5916cd6a6acSopenharmony_ci			if (policyvers > policydbp->policyvers) {
5926cd6a6acSopenharmony_ci				fprintf(stderr, "Binary policies with version <= %u cannot be upgraded\n", POLICYDB_VERSION_PERMISSIVE);
5936cd6a6acSopenharmony_ci			} else if (policyvers) {
5946cd6a6acSopenharmony_ci				policydbp->policyvers = policyvers;
5956cd6a6acSopenharmony_ci			}
5966cd6a6acSopenharmony_ci		} else {
5976cd6a6acSopenharmony_ci			policydbp->policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX;
5986cd6a6acSopenharmony_ci		}
5996cd6a6acSopenharmony_ci	} else {
6006cd6a6acSopenharmony_ci		if (conf) {
6016cd6a6acSopenharmony_ci			fprintf(stderr, "Can only generate policy.conf from binary policy\n");
6026cd6a6acSopenharmony_ci			exit(1);
6036cd6a6acSopenharmony_ci		}
6046cd6a6acSopenharmony_ci		if (policydb_init(&parse_policy))
6056cd6a6acSopenharmony_ci			exit(1);
6066cd6a6acSopenharmony_ci		/* We build this as a base policy first since that is all the parser understands */
6076cd6a6acSopenharmony_ci		parse_policy.policy_type = POLICY_BASE;
6086cd6a6acSopenharmony_ci		policydb_set_target_platform(&parse_policy, target);
6096cd6a6acSopenharmony_ci
6106cd6a6acSopenharmony_ci		/* Let sepol know if we are dealing with MLS support */
6116cd6a6acSopenharmony_ci		parse_policy.mls = mlspol;
6126cd6a6acSopenharmony_ci		parse_policy.handle_unknown = handle_unknown;
6136cd6a6acSopenharmony_ci
6146cd6a6acSopenharmony_ci		policydbp = &parse_policy;
6156cd6a6acSopenharmony_ci
6166cd6a6acSopenharmony_ci		if (read_source_policy(policydbp, file, "checkpolicy") < 0)
6176cd6a6acSopenharmony_ci			exit(1);
6186cd6a6acSopenharmony_ci
6196cd6a6acSopenharmony_ci		if (hashtab_map(policydbp->p_levels.table, check_level, NULL))
6206cd6a6acSopenharmony_ci			exit(1);
6216cd6a6acSopenharmony_ci
6226cd6a6acSopenharmony_ci		/* Linking takes care of optional avrule blocks */
6236cd6a6acSopenharmony_ci		if (link_modules(NULL, policydbp, NULL, 0, 0)) {
6246cd6a6acSopenharmony_ci			fprintf(stderr, "Error while resolving optionals\n");
6256cd6a6acSopenharmony_ci			exit(1);
6266cd6a6acSopenharmony_ci		}
6276cd6a6acSopenharmony_ci
6286cd6a6acSopenharmony_ci		if (!cil) {
6296cd6a6acSopenharmony_ci			if (policydb_init(&policydb)) {
6306cd6a6acSopenharmony_ci				fprintf(stderr, "%s:  policydb_init failed\n", argv[0]);
6316cd6a6acSopenharmony_ci				exit(1);
6326cd6a6acSopenharmony_ci			}
6336cd6a6acSopenharmony_ci			if (expand_module(NULL, policydbp, &policydb, 0, 1)) {
6346cd6a6acSopenharmony_ci				fprintf(stderr, "Error while expanding policy\n");
6356cd6a6acSopenharmony_ci				exit(1);
6366cd6a6acSopenharmony_ci			}
6376cd6a6acSopenharmony_ci			policydb_destroy(policydbp);
6386cd6a6acSopenharmony_ci			policydbp = &policydb;
6396cd6a6acSopenharmony_ci		}
6406cd6a6acSopenharmony_ci
6416cd6a6acSopenharmony_ci		policydbp->policyvers = policyvers ? policyvers : POLICYDB_VERSION_MAX;
6426cd6a6acSopenharmony_ci	}
6436cd6a6acSopenharmony_ci
6446cd6a6acSopenharmony_ci	if (policydb_load_isids(&policydb, &sidtab))
6456cd6a6acSopenharmony_ci		exit(1);
6466cd6a6acSopenharmony_ci
6476cd6a6acSopenharmony_ci	if (optimize && policydbp->policy_type == POLICY_KERN) {
6486cd6a6acSopenharmony_ci		ret = policydb_optimize(policydbp);
6496cd6a6acSopenharmony_ci		if (ret) {
6506cd6a6acSopenharmony_ci			fprintf(stderr, "%s:  error optimizing policy\n", argv[0]);
6516cd6a6acSopenharmony_ci			exit(1);
6526cd6a6acSopenharmony_ci		}
6536cd6a6acSopenharmony_ci	}
6546cd6a6acSopenharmony_ci
6556cd6a6acSopenharmony_ci	if (outfile) {
6566cd6a6acSopenharmony_ci		if (!strcmp(outfile, "-")) {
6576cd6a6acSopenharmony_ci			outfp = stdout;
6586cd6a6acSopenharmony_ci			outfile = "<STDOUT>";
6596cd6a6acSopenharmony_ci		} else {
6606cd6a6acSopenharmony_ci			outfp = fopen(outfile, "w");
6616cd6a6acSopenharmony_ci			if (!outfp) {
6626cd6a6acSopenharmony_ci				perror(outfile);
6636cd6a6acSopenharmony_ci				exit(1);
6646cd6a6acSopenharmony_ci			}
6656cd6a6acSopenharmony_ci		}
6666cd6a6acSopenharmony_ci
6676cd6a6acSopenharmony_ci		if (!cil) {
6686cd6a6acSopenharmony_ci			if (!conf) {
6696cd6a6acSopenharmony_ci				policydb.policy_type = POLICY_KERN;
6706cd6a6acSopenharmony_ci
6716cd6a6acSopenharmony_ci				policy_file_init(&pf);
6726cd6a6acSopenharmony_ci				pf.type = PF_USE_STDIO;
6736cd6a6acSopenharmony_ci				pf.fp = outfp;
6746cd6a6acSopenharmony_ci				if (sort) {
6756cd6a6acSopenharmony_ci					ret = policydb_sort_ocontexts(&policydb);
6766cd6a6acSopenharmony_ci					if (ret) {
6776cd6a6acSopenharmony_ci						fprintf(stderr, "%s:  error sorting ocontexts\n",
6786cd6a6acSopenharmony_ci						argv[0]);
6796cd6a6acSopenharmony_ci						exit(1);
6806cd6a6acSopenharmony_ci					}
6816cd6a6acSopenharmony_ci				}
6826cd6a6acSopenharmony_ci				ret = policydb_write(&policydb, &pf);
6836cd6a6acSopenharmony_ci			} else {
6846cd6a6acSopenharmony_ci				ret = sepol_kernel_policydb_to_conf(outfp, policydbp);
6856cd6a6acSopenharmony_ci			}
6866cd6a6acSopenharmony_ci			if (ret) {
6876cd6a6acSopenharmony_ci				fprintf(stderr, "%s:  error writing %s\n",
6886cd6a6acSopenharmony_ci						argv[0], outfile);
6896cd6a6acSopenharmony_ci				exit(1);
6906cd6a6acSopenharmony_ci			}
6916cd6a6acSopenharmony_ci		} else {
6926cd6a6acSopenharmony_ci			if (binary) {
6936cd6a6acSopenharmony_ci				ret = sepol_kernel_policydb_to_cil(outfp, policydbp);
6946cd6a6acSopenharmony_ci			} else {
6956cd6a6acSopenharmony_ci				ret = sepol_module_policydb_to_cil(outfp, policydbp, 1);
6966cd6a6acSopenharmony_ci			}
6976cd6a6acSopenharmony_ci			if (ret) {
6986cd6a6acSopenharmony_ci				fprintf(stderr, "%s:  error writing %s\n", argv[0], outfile);
6996cd6a6acSopenharmony_ci				exit(1);
7006cd6a6acSopenharmony_ci			}
7016cd6a6acSopenharmony_ci		}
7026cd6a6acSopenharmony_ci
7036cd6a6acSopenharmony_ci		if (outfp != stdout) {
7046cd6a6acSopenharmony_ci			if(fclose(outfp)) {
7056cd6a6acSopenharmony_ci				fprintf(stderr, "%s:  error closing %s:  %s\n", argv[0], outfile, strerror(errno));
7066cd6a6acSopenharmony_ci				exit(1);
7076cd6a6acSopenharmony_ci			}
7086cd6a6acSopenharmony_ci		}
7096cd6a6acSopenharmony_ci	} else if (cil) {
7106cd6a6acSopenharmony_ci		fprintf(stderr, "%s:  No file to write CIL was specified\n", argv[0]);
7116cd6a6acSopenharmony_ci		exit(1);
7126cd6a6acSopenharmony_ci	}
7136cd6a6acSopenharmony_ci
7146cd6a6acSopenharmony_ci	if (!debug) {
7156cd6a6acSopenharmony_ci		policydb_destroy(&policydb);
7166cd6a6acSopenharmony_ci		sepol_sidtab_destroy(&sidtab);
7176cd6a6acSopenharmony_ci		exit(0);
7186cd6a6acSopenharmony_ci	}
7196cd6a6acSopenharmony_ci
7206cd6a6acSopenharmony_ci      menu:
7216cd6a6acSopenharmony_ci	printf("\nSelect an option:\n");
7226cd6a6acSopenharmony_ci	printf("0)  Call compute_access_vector\n");
7236cd6a6acSopenharmony_ci	printf("1)  Call sid_to_context\n");
7246cd6a6acSopenharmony_ci	printf("2)  Call context_to_sid\n");
7256cd6a6acSopenharmony_ci	printf("3)  Call transition_sid\n");
7266cd6a6acSopenharmony_ci	printf("4)  Call member_sid\n");
7276cd6a6acSopenharmony_ci	printf("5)  Call change_sid\n");
7286cd6a6acSopenharmony_ci	printf("6)  Call list_sids\n");
7296cd6a6acSopenharmony_ci	printf("7)  Call load_policy\n");
7306cd6a6acSopenharmony_ci	printf("8)  Call fs_sid\n");
7316cd6a6acSopenharmony_ci	printf("9)  Call port_sid\n");
7326cd6a6acSopenharmony_ci	printf("a)  Call netif_sid\n");
7336cd6a6acSopenharmony_ci	printf("b)  Call node_sid\n");
7346cd6a6acSopenharmony_ci	printf("c)  Call fs_use\n");
7356cd6a6acSopenharmony_ci	printf("d)  Call genfs_sid\n");
7366cd6a6acSopenharmony_ci	printf("e)  Call get_user_sids\n");
7376cd6a6acSopenharmony_ci	printf("f)  display conditional bools\n");
7386cd6a6acSopenharmony_ci	printf("g)  display conditional expressions\n");
7396cd6a6acSopenharmony_ci	printf("h)  change a boolean value\n");
7406cd6a6acSopenharmony_ci	printf("i)  display constraint expressions\n");
7416cd6a6acSopenharmony_ci	printf("j)  display validatetrans expressions\n");
7426cd6a6acSopenharmony_ci	printf("k)  Call ibpkey_sid\n");
7436cd6a6acSopenharmony_ci	printf("l)  Call ibendport_sid\n");
7446cd6a6acSopenharmony_ci#ifdef EQUIVTYPES
7456cd6a6acSopenharmony_ci	printf("z)  Show equivalent types\n");
7466cd6a6acSopenharmony_ci#endif
7476cd6a6acSopenharmony_ci	printf("m)  Show menu again\n");
7486cd6a6acSopenharmony_ci	printf("q)  Exit\n");
7496cd6a6acSopenharmony_ci	while (1) {
7506cd6a6acSopenharmony_ci		printf("\nChoose:  ");
7516cd6a6acSopenharmony_ci		FGETS(ans, sizeof(ans), stdin);
7526cd6a6acSopenharmony_ci		switch (ans[0]) {
7536cd6a6acSopenharmony_ci		case '0':
7546cd6a6acSopenharmony_ci			printf("source sid?  ");
7556cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
7566cd6a6acSopenharmony_ci			ssid = atoi(ans);
7576cd6a6acSopenharmony_ci
7586cd6a6acSopenharmony_ci			printf("target sid?  ");
7596cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
7606cd6a6acSopenharmony_ci			tsid = atoi(ans);
7616cd6a6acSopenharmony_ci
7626cd6a6acSopenharmony_ci			printf("target class?  ");
7636cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
7646cd6a6acSopenharmony_ci			if (isdigit(ans[0])) {
7656cd6a6acSopenharmony_ci				tclass = atoi(ans);
7666cd6a6acSopenharmony_ci				if (!tclass
7676cd6a6acSopenharmony_ci				    || tclass > policydb.p_classes.nprim) {
7686cd6a6acSopenharmony_ci					printf("\nNo such class.\n");
7696cd6a6acSopenharmony_ci					break;
7706cd6a6acSopenharmony_ci				}
7716cd6a6acSopenharmony_ci				cladatum =
7726cd6a6acSopenharmony_ci				    policydb.class_val_to_struct[tclass - 1];
7736cd6a6acSopenharmony_ci			} else {
7746cd6a6acSopenharmony_ci				ans[strlen(ans) - 1] = 0;
7756cd6a6acSopenharmony_ci				cladatum =
7766cd6a6acSopenharmony_ci				    (class_datum_t *) hashtab_search(policydb.
7776cd6a6acSopenharmony_ci								     p_classes.
7786cd6a6acSopenharmony_ci								     table,
7796cd6a6acSopenharmony_ci								     ans);
7806cd6a6acSopenharmony_ci				if (!cladatum) {
7816cd6a6acSopenharmony_ci					printf("\nNo such class\n");
7826cd6a6acSopenharmony_ci					break;
7836cd6a6acSopenharmony_ci				}
7846cd6a6acSopenharmony_ci				tclass = cladatum->s.value;
7856cd6a6acSopenharmony_ci			}
7866cd6a6acSopenharmony_ci
7876cd6a6acSopenharmony_ci			if (!cladatum->comdatum && !cladatum->permissions.nprim) {
7886cd6a6acSopenharmony_ci				printf
7896cd6a6acSopenharmony_ci				    ("\nNo access vector definition for that class\n");
7906cd6a6acSopenharmony_ci				break;
7916cd6a6acSopenharmony_ci			}
7926cd6a6acSopenharmony_ci			ret = sepol_compute_av(ssid, tsid, tclass, 0, &avd);
7936cd6a6acSopenharmony_ci			switch (ret) {
7946cd6a6acSopenharmony_ci			case 0:
7956cd6a6acSopenharmony_ci				printf("\nallowed {");
7966cd6a6acSopenharmony_ci				for (i = 1; i <= sizeof(avd.allowed) * 8; i++) {
7976cd6a6acSopenharmony_ci					if (avd.allowed & (UINT32_C(1) << (i - 1))) {
7986cd6a6acSopenharmony_ci						v.val = i;
7996cd6a6acSopenharmony_ci						ret =
8006cd6a6acSopenharmony_ci						    hashtab_map(cladatum->
8016cd6a6acSopenharmony_ci								permissions.
8026cd6a6acSopenharmony_ci								table,
8036cd6a6acSopenharmony_ci								find_perm, &v);
8046cd6a6acSopenharmony_ci						if (!ret && cladatum->comdatum) {
8056cd6a6acSopenharmony_ci							ret =
8066cd6a6acSopenharmony_ci							    hashtab_map
8076cd6a6acSopenharmony_ci							    (cladatum->
8086cd6a6acSopenharmony_ci							     comdatum->
8096cd6a6acSopenharmony_ci							     permissions.table,
8106cd6a6acSopenharmony_ci							     find_perm, &v);
8116cd6a6acSopenharmony_ci						}
8126cd6a6acSopenharmony_ci						if (ret)
8136cd6a6acSopenharmony_ci							printf(" %s", v.name);
8146cd6a6acSopenharmony_ci					}
8156cd6a6acSopenharmony_ci				}
8166cd6a6acSopenharmony_ci				printf(" }\n");
8176cd6a6acSopenharmony_ci				break;
8186cd6a6acSopenharmony_ci			case -EINVAL:
8196cd6a6acSopenharmony_ci				printf("\ninvalid sid\n");
8206cd6a6acSopenharmony_ci				break;
8216cd6a6acSopenharmony_ci			default:
8226cd6a6acSopenharmony_ci				printf("return code 0x%x\n", ret);
8236cd6a6acSopenharmony_ci			}
8246cd6a6acSopenharmony_ci			break;
8256cd6a6acSopenharmony_ci		case '1':
8266cd6a6acSopenharmony_ci			printf("sid?  ");
8276cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
8286cd6a6acSopenharmony_ci			ssid = atoi(ans);
8296cd6a6acSopenharmony_ci			ret = sepol_sid_to_context(ssid,
8306cd6a6acSopenharmony_ci						   &scontext, &scontext_len);
8316cd6a6acSopenharmony_ci			switch (ret) {
8326cd6a6acSopenharmony_ci			case 0:
8336cd6a6acSopenharmony_ci				printf("\nscontext %s\n", scontext);
8346cd6a6acSopenharmony_ci				free(scontext);
8356cd6a6acSopenharmony_ci				break;
8366cd6a6acSopenharmony_ci			case -EINVAL:
8376cd6a6acSopenharmony_ci				printf("\ninvalid sid\n");
8386cd6a6acSopenharmony_ci				break;
8396cd6a6acSopenharmony_ci			case -ENOMEM:
8406cd6a6acSopenharmony_ci				printf("\nout of memory\n");
8416cd6a6acSopenharmony_ci				break;
8426cd6a6acSopenharmony_ci			default:
8436cd6a6acSopenharmony_ci				printf("return code 0x%x\n", ret);
8446cd6a6acSopenharmony_ci			}
8456cd6a6acSopenharmony_ci			break;
8466cd6a6acSopenharmony_ci		case '2':
8476cd6a6acSopenharmony_ci			printf("scontext?  ");
8486cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
8496cd6a6acSopenharmony_ci			scontext_len = strlen(ans);
8506cd6a6acSopenharmony_ci			ans[scontext_len - 1] = 0;
8516cd6a6acSopenharmony_ci			ret = sepol_context_to_sid(ans, scontext_len, &ssid);
8526cd6a6acSopenharmony_ci			switch (ret) {
8536cd6a6acSopenharmony_ci			case 0:
8546cd6a6acSopenharmony_ci				printf("\nsid %d\n", ssid);
8556cd6a6acSopenharmony_ci				break;
8566cd6a6acSopenharmony_ci			case -EINVAL:
8576cd6a6acSopenharmony_ci				printf("\ninvalid context\n");
8586cd6a6acSopenharmony_ci				break;
8596cd6a6acSopenharmony_ci			case -ENOMEM:
8606cd6a6acSopenharmony_ci				printf("\nout of memory\n");
8616cd6a6acSopenharmony_ci				break;
8626cd6a6acSopenharmony_ci			default:
8636cd6a6acSopenharmony_ci				printf("return code 0x%x\n", ret);
8646cd6a6acSopenharmony_ci			}
8656cd6a6acSopenharmony_ci			break;
8666cd6a6acSopenharmony_ci		case '3':
8676cd6a6acSopenharmony_ci		case '4':
8686cd6a6acSopenharmony_ci		case '5':
8696cd6a6acSopenharmony_ci			ch = ans[0];
8706cd6a6acSopenharmony_ci
8716cd6a6acSopenharmony_ci			printf("source sid?  ");
8726cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
8736cd6a6acSopenharmony_ci			ssid = atoi(ans);
8746cd6a6acSopenharmony_ci			printf("target sid?  ");
8756cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
8766cd6a6acSopenharmony_ci			tsid = atoi(ans);
8776cd6a6acSopenharmony_ci
8786cd6a6acSopenharmony_ci			printf("object class?  ");
8796cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
8806cd6a6acSopenharmony_ci			if (isdigit(ans[0])) {
8816cd6a6acSopenharmony_ci				tclass = atoi(ans);
8826cd6a6acSopenharmony_ci				if (!tclass
8836cd6a6acSopenharmony_ci				    || tclass > policydb.p_classes.nprim) {
8846cd6a6acSopenharmony_ci					printf("\nNo such class.\n");
8856cd6a6acSopenharmony_ci					break;
8866cd6a6acSopenharmony_ci				}
8876cd6a6acSopenharmony_ci			} else {
8886cd6a6acSopenharmony_ci				ans[strlen(ans) - 1] = 0;
8896cd6a6acSopenharmony_ci				cladatum =
8906cd6a6acSopenharmony_ci				    (class_datum_t *) hashtab_search(policydb.
8916cd6a6acSopenharmony_ci								     p_classes.
8926cd6a6acSopenharmony_ci								     table,
8936cd6a6acSopenharmony_ci								     ans);
8946cd6a6acSopenharmony_ci				if (!cladatum) {
8956cd6a6acSopenharmony_ci					printf("\nNo such class\n");
8966cd6a6acSopenharmony_ci					break;
8976cd6a6acSopenharmony_ci				}
8986cd6a6acSopenharmony_ci				tclass = cladatum->s.value;
8996cd6a6acSopenharmony_ci			}
9006cd6a6acSopenharmony_ci
9016cd6a6acSopenharmony_ci			if (ch == '3')
9026cd6a6acSopenharmony_ci				ret =
9036cd6a6acSopenharmony_ci				    sepol_transition_sid(ssid, tsid, tclass,
9046cd6a6acSopenharmony_ci							 &ssid);
9056cd6a6acSopenharmony_ci			else if (ch == '4')
9066cd6a6acSopenharmony_ci				ret =
9076cd6a6acSopenharmony_ci				    sepol_member_sid(ssid, tsid, tclass, &ssid);
9086cd6a6acSopenharmony_ci			else
9096cd6a6acSopenharmony_ci				ret =
9106cd6a6acSopenharmony_ci				    sepol_change_sid(ssid, tsid, tclass, &ssid);
9116cd6a6acSopenharmony_ci			switch (ret) {
9126cd6a6acSopenharmony_ci			case 0:
9136cd6a6acSopenharmony_ci				printf("\nsid %d\n", ssid);
9146cd6a6acSopenharmony_ci				break;
9156cd6a6acSopenharmony_ci			case -EINVAL:
9166cd6a6acSopenharmony_ci				printf("\ninvalid sid\n");
9176cd6a6acSopenharmony_ci				break;
9186cd6a6acSopenharmony_ci			case -ENOMEM:
9196cd6a6acSopenharmony_ci				printf("\nout of memory\n");
9206cd6a6acSopenharmony_ci				break;
9216cd6a6acSopenharmony_ci			default:
9226cd6a6acSopenharmony_ci				printf("return code 0x%x\n", ret);
9236cd6a6acSopenharmony_ci			}
9246cd6a6acSopenharmony_ci			break;
9256cd6a6acSopenharmony_ci		case '6':
9266cd6a6acSopenharmony_ci			sepol_sidtab_map(&sidtab, print_sid, 0);
9276cd6a6acSopenharmony_ci			break;
9286cd6a6acSopenharmony_ci		case '7':
9296cd6a6acSopenharmony_ci			printf("pathname?  ");
9306cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
9316cd6a6acSopenharmony_ci			pathlen = strlen(ans);
9326cd6a6acSopenharmony_ci			ans[pathlen - 1] = 0;
9336cd6a6acSopenharmony_ci			fd = open(ans, O_RDONLY);
9346cd6a6acSopenharmony_ci			if (fd < 0) {
9356cd6a6acSopenharmony_ci				fprintf(stderr, "Can't open '%s':  %s\n",
9366cd6a6acSopenharmony_ci					ans, strerror(errno));
9376cd6a6acSopenharmony_ci				break;
9386cd6a6acSopenharmony_ci			}
9396cd6a6acSopenharmony_ci			if (fstat(fd, &sb) < 0) {
9406cd6a6acSopenharmony_ci				fprintf(stderr, "Can't stat '%s':  %s\n",
9416cd6a6acSopenharmony_ci					ans, strerror(errno));
9426cd6a6acSopenharmony_ci				break;
9436cd6a6acSopenharmony_ci			}
9446cd6a6acSopenharmony_ci			map =
9456cd6a6acSopenharmony_ci			    mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE,
9466cd6a6acSopenharmony_ci				 MAP_PRIVATE, fd, 0);
9476cd6a6acSopenharmony_ci			if (map == MAP_FAILED) {
9486cd6a6acSopenharmony_ci				fprintf(stderr, "Can't map '%s':  %s\n",
9496cd6a6acSopenharmony_ci					ans, strerror(errno));
9506cd6a6acSopenharmony_ci				break;
9516cd6a6acSopenharmony_ci			}
9526cd6a6acSopenharmony_ci			ret = sepol_load_policy(map, sb.st_size);
9536cd6a6acSopenharmony_ci			switch (ret) {
9546cd6a6acSopenharmony_ci			case 0:
9556cd6a6acSopenharmony_ci				printf("\nsuccess\n");
9566cd6a6acSopenharmony_ci				break;
9576cd6a6acSopenharmony_ci			case -EINVAL:
9586cd6a6acSopenharmony_ci				printf("\ninvalid policy\n");
9596cd6a6acSopenharmony_ci				break;
9606cd6a6acSopenharmony_ci			case -ENOMEM:
9616cd6a6acSopenharmony_ci				printf("\nout of memory\n");
9626cd6a6acSopenharmony_ci				break;
9636cd6a6acSopenharmony_ci			default:
9646cd6a6acSopenharmony_ci				printf("return code 0x%x\n", ret);
9656cd6a6acSopenharmony_ci			}
9666cd6a6acSopenharmony_ci			break;
9676cd6a6acSopenharmony_ci		case '8':
9686cd6a6acSopenharmony_ci			printf("fs kdevname?  ");
9696cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
9706cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
9716cd6a6acSopenharmony_ci			ret = sepol_fs_sid(ans, &ssid, &tsid);
9726cd6a6acSopenharmony_ci			if (ret) {
9736cd6a6acSopenharmony_ci				printf("unknown fs kdevname\n");
9746cd6a6acSopenharmony_ci			} else {
9756cd6a6acSopenharmony_ci				printf("fs_sid %d default_file_sid %d\n", ssid, tsid);
9766cd6a6acSopenharmony_ci			}
9776cd6a6acSopenharmony_ci			break;
9786cd6a6acSopenharmony_ci		case '9':
9796cd6a6acSopenharmony_ci			printf("protocol?  ");
9806cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
9816cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
9826cd6a6acSopenharmony_ci			if (!strcmp(ans, "tcp") || !strcmp(ans, "TCP"))
9836cd6a6acSopenharmony_ci				protocol = IPPROTO_TCP;
9846cd6a6acSopenharmony_ci			else if (!strcmp(ans, "udp") || !strcmp(ans, "UDP"))
9856cd6a6acSopenharmony_ci				protocol = IPPROTO_UDP;
9866cd6a6acSopenharmony_ci			else if (!strcmp(ans, "dccp") || !strcmp(ans, "DCCP"))
9876cd6a6acSopenharmony_ci				protocol = IPPROTO_DCCP;
9886cd6a6acSopenharmony_ci			else if (!strcmp(ans, "sctp") || !strcmp(ans, "SCTP"))
9896cd6a6acSopenharmony_ci				protocol = IPPROTO_SCTP;
9906cd6a6acSopenharmony_ci			else {
9916cd6a6acSopenharmony_ci				printf("unknown protocol\n");
9926cd6a6acSopenharmony_ci				break;
9936cd6a6acSopenharmony_ci			}
9946cd6a6acSopenharmony_ci			printf("port? ");
9956cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
9966cd6a6acSopenharmony_ci			port = atoi(ans);
9976cd6a6acSopenharmony_ci			sepol_port_sid(0, 0, protocol, port, &ssid);
9986cd6a6acSopenharmony_ci			printf("sid %d\n", ssid);
9996cd6a6acSopenharmony_ci			break;
10006cd6a6acSopenharmony_ci		case 'a':
10016cd6a6acSopenharmony_ci			printf("netif name?  ");
10026cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
10036cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
10046cd6a6acSopenharmony_ci			ret = sepol_netif_sid(ans, &ssid, &tsid);
10056cd6a6acSopenharmony_ci			if (ret) {
10066cd6a6acSopenharmony_ci				printf("unknown name\n");
10076cd6a6acSopenharmony_ci			} else {
10086cd6a6acSopenharmony_ci				printf("if_sid %d default_msg_sid %d\n", ssid, tsid);
10096cd6a6acSopenharmony_ci			}
10106cd6a6acSopenharmony_ci			break;
10116cd6a6acSopenharmony_ci		case 'b':{
10126cd6a6acSopenharmony_ci				char *p;
10136cd6a6acSopenharmony_ci				int family, len;
10146cd6a6acSopenharmony_ci				struct in_addr addr4;
10156cd6a6acSopenharmony_ci				struct in6_addr addr6;
10166cd6a6acSopenharmony_ci
10176cd6a6acSopenharmony_ci				printf("protocol family? ");
10186cd6a6acSopenharmony_ci				FGETS(ans, sizeof(ans), stdin);
10196cd6a6acSopenharmony_ci				ans[strlen(ans) - 1] = 0;
10206cd6a6acSopenharmony_ci				if (!strcasecmp(ans, "ipv4"))
10216cd6a6acSopenharmony_ci					family = AF_INET;
10226cd6a6acSopenharmony_ci				else if (!strcasecmp(ans, "ipv6"))
10236cd6a6acSopenharmony_ci					family = AF_INET6;
10246cd6a6acSopenharmony_ci				else {
10256cd6a6acSopenharmony_ci					printf("unknown protocol family\n");
10266cd6a6acSopenharmony_ci					break;
10276cd6a6acSopenharmony_ci				}
10286cd6a6acSopenharmony_ci
10296cd6a6acSopenharmony_ci				printf("node address?  ");
10306cd6a6acSopenharmony_ci				FGETS(ans, sizeof(ans), stdin);
10316cd6a6acSopenharmony_ci				ans[strlen(ans) - 1] = 0;
10326cd6a6acSopenharmony_ci
10336cd6a6acSopenharmony_ci				if (family == AF_INET) {
10346cd6a6acSopenharmony_ci					p = (char *)&addr4;
10356cd6a6acSopenharmony_ci					len = sizeof(addr4);
10366cd6a6acSopenharmony_ci				} else {
10376cd6a6acSopenharmony_ci					p = (char *)&addr6;
10386cd6a6acSopenharmony_ci					len = sizeof(addr6);
10396cd6a6acSopenharmony_ci				}
10406cd6a6acSopenharmony_ci
10416cd6a6acSopenharmony_ci				if (inet_pton(family, ans, p) < 1) {
10426cd6a6acSopenharmony_ci					printf("error parsing address\n");
10436cd6a6acSopenharmony_ci					break;
10446cd6a6acSopenharmony_ci				}
10456cd6a6acSopenharmony_ci
10466cd6a6acSopenharmony_ci				sepol_node_sid(family, p, len, &ssid);
10476cd6a6acSopenharmony_ci				printf("sid %d\n", ssid);
10486cd6a6acSopenharmony_ci				break;
10496cd6a6acSopenharmony_ci			}
10506cd6a6acSopenharmony_ci		case 'c':
10516cd6a6acSopenharmony_ci			printf("fstype?  ");
10526cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
10536cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
10546cd6a6acSopenharmony_ci			sepol_fs_use(ans, &uret, &ssid);
10556cd6a6acSopenharmony_ci			switch (uret) {
10566cd6a6acSopenharmony_ci			case SECURITY_FS_USE_XATTR:
10576cd6a6acSopenharmony_ci				printf("use xattr\n");
10586cd6a6acSopenharmony_ci				break;
10596cd6a6acSopenharmony_ci			case SECURITY_FS_USE_TRANS:
10606cd6a6acSopenharmony_ci				printf("use transition SIDs\n");
10616cd6a6acSopenharmony_ci				break;
10626cd6a6acSopenharmony_ci			case SECURITY_FS_USE_TASK:
10636cd6a6acSopenharmony_ci				printf("use task SIDs\n");
10646cd6a6acSopenharmony_ci				break;
10656cd6a6acSopenharmony_ci			case SECURITY_FS_USE_GENFS:
10666cd6a6acSopenharmony_ci				printf("use genfs\n");
10676cd6a6acSopenharmony_ci				break;
10686cd6a6acSopenharmony_ci			case SECURITY_FS_USE_NONE:
10696cd6a6acSopenharmony_ci				printf("no labeling support\n");
10706cd6a6acSopenharmony_ci				break;
10716cd6a6acSopenharmony_ci			}
10726cd6a6acSopenharmony_ci			printf("sid %d\n", ssid);
10736cd6a6acSopenharmony_ci			break;
10746cd6a6acSopenharmony_ci		case 'd':
10756cd6a6acSopenharmony_ci			printf("fstype?  ");
10766cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
10776cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
10786cd6a6acSopenharmony_ci			fstype = strdup(ans);
10796cd6a6acSopenharmony_ci			printf("path?  ");
10806cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
10816cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
10826cd6a6acSopenharmony_ci			path = strdup(ans);
10836cd6a6acSopenharmony_ci			printf("object class?  ");
10846cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
10856cd6a6acSopenharmony_ci			if (isdigit(ans[0])) {
10866cd6a6acSopenharmony_ci				tclass = atoi(ans);
10876cd6a6acSopenharmony_ci				if (!tclass
10886cd6a6acSopenharmony_ci				    || tclass > policydb.p_classes.nprim) {
10896cd6a6acSopenharmony_ci					printf("\nNo such class.\n");
10906cd6a6acSopenharmony_ci					break;
10916cd6a6acSopenharmony_ci				}
10926cd6a6acSopenharmony_ci			} else {
10936cd6a6acSopenharmony_ci				ans[strlen(ans) - 1] = 0;
10946cd6a6acSopenharmony_ci				cladatum =
10956cd6a6acSopenharmony_ci				    (class_datum_t *) hashtab_search(policydb.
10966cd6a6acSopenharmony_ci								     p_classes.
10976cd6a6acSopenharmony_ci								     table,
10986cd6a6acSopenharmony_ci								     ans);
10996cd6a6acSopenharmony_ci				if (!cladatum) {
11006cd6a6acSopenharmony_ci					printf("\nNo such class\n");
11016cd6a6acSopenharmony_ci					break;
11026cd6a6acSopenharmony_ci				}
11036cd6a6acSopenharmony_ci				tclass = cladatum->s.value;
11046cd6a6acSopenharmony_ci			}
11056cd6a6acSopenharmony_ci			sepol_genfs_sid(fstype, path, tclass, &ssid);
11066cd6a6acSopenharmony_ci			printf("sid %d\n", ssid);
11076cd6a6acSopenharmony_ci			free(fstype);
11086cd6a6acSopenharmony_ci			free(path);
11096cd6a6acSopenharmony_ci			break;
11106cd6a6acSopenharmony_ci		case 'e':
11116cd6a6acSopenharmony_ci			printf("from SID?  ");
11126cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
11136cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
11146cd6a6acSopenharmony_ci			ssid = atoi(ans);
11156cd6a6acSopenharmony_ci
11166cd6a6acSopenharmony_ci			printf("username?  ");
11176cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
11186cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
11196cd6a6acSopenharmony_ci
11206cd6a6acSopenharmony_ci			ret = sepol_get_user_sids(ssid, ans, &sids, &nel);
11216cd6a6acSopenharmony_ci			switch (ret) {
11226cd6a6acSopenharmony_ci			case 0:
11236cd6a6acSopenharmony_ci				if (!nel)
11246cd6a6acSopenharmony_ci					printf("\nnone\n");
11256cd6a6acSopenharmony_ci				for (i = 0; i < nel; i++)
11266cd6a6acSopenharmony_ci					print_sid(sids[i], NULL, NULL);
11276cd6a6acSopenharmony_ci				free(sids);
11286cd6a6acSopenharmony_ci				break;
11296cd6a6acSopenharmony_ci			case -ENOMEM:
11306cd6a6acSopenharmony_ci				printf("\nout of memory\n");
11316cd6a6acSopenharmony_ci				break;
11326cd6a6acSopenharmony_ci			case -EINVAL:
11336cd6a6acSopenharmony_ci				printf("\ninvalid argument\n");
11346cd6a6acSopenharmony_ci				break;
11356cd6a6acSopenharmony_ci			default:
11366cd6a6acSopenharmony_ci				printf("\nerror\n");
11376cd6a6acSopenharmony_ci				break;
11386cd6a6acSopenharmony_ci			}
11396cd6a6acSopenharmony_ci			break;
11406cd6a6acSopenharmony_ci		case 'f':
11416cd6a6acSopenharmony_ci			display_bools();
11426cd6a6acSopenharmony_ci			break;
11436cd6a6acSopenharmony_ci		case 'g':
11446cd6a6acSopenharmony_ci			display_cond_expressions();
11456cd6a6acSopenharmony_ci			break;
11466cd6a6acSopenharmony_ci		case 'h':
11476cd6a6acSopenharmony_ci			printf("name? ");
11486cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
11496cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
11506cd6a6acSopenharmony_ci
11516cd6a6acSopenharmony_ci			name = strdup(ans);
11526cd6a6acSopenharmony_ci			if (name == NULL) {
11536cd6a6acSopenharmony_ci				fprintf(stderr, "couldn't strdup string.\n");
11546cd6a6acSopenharmony_ci				break;
11556cd6a6acSopenharmony_ci			}
11566cd6a6acSopenharmony_ci
11576cd6a6acSopenharmony_ci			printf("state? ");
11586cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
11596cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
11606cd6a6acSopenharmony_ci
11616cd6a6acSopenharmony_ci			if (atoi(ans))
11626cd6a6acSopenharmony_ci				state = 1;
11636cd6a6acSopenharmony_ci			else
11646cd6a6acSopenharmony_ci				state = 0;
11656cd6a6acSopenharmony_ci
11666cd6a6acSopenharmony_ci			change_bool(name, state);
11676cd6a6acSopenharmony_ci			free(name);
11686cd6a6acSopenharmony_ci			break;
11696cd6a6acSopenharmony_ci		case 'i':
11706cd6a6acSopenharmony_ci			printf("source sid?  ");
11716cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
11726cd6a6acSopenharmony_ci			ssid = atoi(ans);
11736cd6a6acSopenharmony_ci
11746cd6a6acSopenharmony_ci			printf("target sid?  ");
11756cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
11766cd6a6acSopenharmony_ci			tsid = atoi(ans);
11776cd6a6acSopenharmony_ci
11786cd6a6acSopenharmony_ci			printf("target class?  ");
11796cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
11806cd6a6acSopenharmony_ci			if (isdigit(ans[0])) {
11816cd6a6acSopenharmony_ci				tclass = atoi(ans);
11826cd6a6acSopenharmony_ci				if (!tclass
11836cd6a6acSopenharmony_ci				    || tclass > policydb.p_classes.nprim) {
11846cd6a6acSopenharmony_ci					printf("\nNo such class.\n");
11856cd6a6acSopenharmony_ci					break;
11866cd6a6acSopenharmony_ci				}
11876cd6a6acSopenharmony_ci			} else {
11886cd6a6acSopenharmony_ci				ans[strlen(ans) - 1] = 0;
11896cd6a6acSopenharmony_ci				cladatum =
11906cd6a6acSopenharmony_ci				    (class_datum_t *) hashtab_search(policydb.
11916cd6a6acSopenharmony_ci								     p_classes.
11926cd6a6acSopenharmony_ci								     table,
11936cd6a6acSopenharmony_ci								     ans);
11946cd6a6acSopenharmony_ci				if (!cladatum) {
11956cd6a6acSopenharmony_ci					printf("\nNo such class\n");
11966cd6a6acSopenharmony_ci					break;
11976cd6a6acSopenharmony_ci				}
11986cd6a6acSopenharmony_ci				tclass = cladatum->s.value;
11996cd6a6acSopenharmony_ci			}
12006cd6a6acSopenharmony_ci
12016cd6a6acSopenharmony_ci			flags = SHOW_GRANTED;
12026cd6a6acSopenharmony_ci			if (sepol_compute_av_reason_buffer(ssid, tsid,
12036cd6a6acSopenharmony_ci					tclass, 0, &avd, &reason,
12046cd6a6acSopenharmony_ci					&reason_buf, flags)) {
12056cd6a6acSopenharmony_ci				printf("\nconstraint error\n");
12066cd6a6acSopenharmony_ci				break;
12076cd6a6acSopenharmony_ci			}
12086cd6a6acSopenharmony_ci			if (reason_buf) {
12096cd6a6acSopenharmony_ci				printf("\nConstraint expressions:\n%s",
12106cd6a6acSopenharmony_ci						reason_buf);
12116cd6a6acSopenharmony_ci				free(reason_buf);
12126cd6a6acSopenharmony_ci			} else {
12136cd6a6acSopenharmony_ci				printf("\nNo constraints found.\n");
12146cd6a6acSopenharmony_ci			}
12156cd6a6acSopenharmony_ci			break;
12166cd6a6acSopenharmony_ci		case 'j':
12176cd6a6acSopenharmony_ci			printf("old sid?  ");
12186cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
12196cd6a6acSopenharmony_ci			oldsid = atoi(ans);
12206cd6a6acSopenharmony_ci
12216cd6a6acSopenharmony_ci			printf("new sid?  ");
12226cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
12236cd6a6acSopenharmony_ci			newsid = atoi(ans);
12246cd6a6acSopenharmony_ci
12256cd6a6acSopenharmony_ci			printf("task sid?  ");
12266cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
12276cd6a6acSopenharmony_ci			tasksid = atoi(ans);
12286cd6a6acSopenharmony_ci
12296cd6a6acSopenharmony_ci			printf("target class?  ");
12306cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
12316cd6a6acSopenharmony_ci			if (isdigit(ans[0])) {
12326cd6a6acSopenharmony_ci				tclass = atoi(ans);
12336cd6a6acSopenharmony_ci				if (!tclass
12346cd6a6acSopenharmony_ci				    || tclass > policydb.p_classes.nprim) {
12356cd6a6acSopenharmony_ci					printf("\nNo such class.\n");
12366cd6a6acSopenharmony_ci					break;
12376cd6a6acSopenharmony_ci				}
12386cd6a6acSopenharmony_ci			} else {
12396cd6a6acSopenharmony_ci				ans[strlen(ans) - 1] = 0;
12406cd6a6acSopenharmony_ci				cladatum =
12416cd6a6acSopenharmony_ci				    (class_datum_t *) hashtab_search(policydb.
12426cd6a6acSopenharmony_ci								     p_classes.
12436cd6a6acSopenharmony_ci								     table,
12446cd6a6acSopenharmony_ci								     ans);
12456cd6a6acSopenharmony_ci				if (!cladatum) {
12466cd6a6acSopenharmony_ci					printf("\nNo such class\n");
12476cd6a6acSopenharmony_ci					break;
12486cd6a6acSopenharmony_ci				}
12496cd6a6acSopenharmony_ci				tclass = cladatum->s.value;
12506cd6a6acSopenharmony_ci			}
12516cd6a6acSopenharmony_ci
12526cd6a6acSopenharmony_ci			flags = SHOW_GRANTED;
12536cd6a6acSopenharmony_ci			if (sepol_validate_transition_reason_buffer(oldsid,
12546cd6a6acSopenharmony_ci						newsid, tasksid, tclass,
12556cd6a6acSopenharmony_ci						&reason_buf, flags)) {
12566cd6a6acSopenharmony_ci				printf("\nvalidatetrans error\n");
12576cd6a6acSopenharmony_ci				break;
12586cd6a6acSopenharmony_ci			}
12596cd6a6acSopenharmony_ci			if (reason_buf) {
12606cd6a6acSopenharmony_ci				printf("\nValidatetrans expressions:\n%s",
12616cd6a6acSopenharmony_ci						reason_buf);
12626cd6a6acSopenharmony_ci				free(reason_buf);
12636cd6a6acSopenharmony_ci			} else {
12646cd6a6acSopenharmony_ci				printf(
12656cd6a6acSopenharmony_ci				    "\nNo validatetrans expressions found.\n");
12666cd6a6acSopenharmony_ci			}
12676cd6a6acSopenharmony_ci			break;
12686cd6a6acSopenharmony_ci		case 'k':
12696cd6a6acSopenharmony_ci			{
12706cd6a6acSopenharmony_ci				char *p;
12716cd6a6acSopenharmony_ci				struct in6_addr addr6;
12726cd6a6acSopenharmony_ci				uint64_t subnet_prefix;
12736cd6a6acSopenharmony_ci				unsigned int pkey;
12746cd6a6acSopenharmony_ci
12756cd6a6acSopenharmony_ci				printf("subnet prefix?  ");
12766cd6a6acSopenharmony_ci				FGETS(ans, sizeof(ans), stdin);
12776cd6a6acSopenharmony_ci				ans[strlen(ans) - 1] = 0;
12786cd6a6acSopenharmony_ci				p = (char *)&addr6;
12796cd6a6acSopenharmony_ci
12806cd6a6acSopenharmony_ci				if (inet_pton(AF_INET6, ans, p) < 1) {
12816cd6a6acSopenharmony_ci					printf("error parsing subnet prefix\n");
12826cd6a6acSopenharmony_ci					break;
12836cd6a6acSopenharmony_ci				}
12846cd6a6acSopenharmony_ci
12856cd6a6acSopenharmony_ci				memcpy(&subnet_prefix, p, sizeof(subnet_prefix));
12866cd6a6acSopenharmony_ci				printf("pkey? ");
12876cd6a6acSopenharmony_ci				FGETS(ans, sizeof(ans), stdin);
12886cd6a6acSopenharmony_ci				pkey = atoi(ans);
12896cd6a6acSopenharmony_ci				sepol_ibpkey_sid(subnet_prefix, pkey, &ssid);
12906cd6a6acSopenharmony_ci				printf("sid %d\n", ssid);
12916cd6a6acSopenharmony_ci			}
12926cd6a6acSopenharmony_ci			break;
12936cd6a6acSopenharmony_ci		case 'l':
12946cd6a6acSopenharmony_ci			printf("device name (eg. mlx4_0)?  ");
12956cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
12966cd6a6acSopenharmony_ci			ans[strlen(ans) - 1] = 0;
12976cd6a6acSopenharmony_ci
12986cd6a6acSopenharmony_ci			name = strdup(ans);
12996cd6a6acSopenharmony_ci			if (!name) {
13006cd6a6acSopenharmony_ci				fprintf(stderr, "couldn't strdup string.\n");
13016cd6a6acSopenharmony_ci				break;
13026cd6a6acSopenharmony_ci			}
13036cd6a6acSopenharmony_ci
13046cd6a6acSopenharmony_ci			printf("port? ");
13056cd6a6acSopenharmony_ci			FGETS(ans, sizeof(ans), stdin);
13066cd6a6acSopenharmony_ci			port = atoi(ans);
13076cd6a6acSopenharmony_ci			sepol_ibendport_sid(name, port, &ssid);
13086cd6a6acSopenharmony_ci			printf("sid %d\n", ssid);
13096cd6a6acSopenharmony_ci			free(name);
13106cd6a6acSopenharmony_ci			break;
13116cd6a6acSopenharmony_ci#ifdef EQUIVTYPES
13126cd6a6acSopenharmony_ci		case 'z':
13136cd6a6acSopenharmony_ci			identify_equiv_types();
13146cd6a6acSopenharmony_ci			break;
13156cd6a6acSopenharmony_ci#endif
13166cd6a6acSopenharmony_ci		case 'm':
13176cd6a6acSopenharmony_ci			goto menu;
13186cd6a6acSopenharmony_ci		case 'q':
13196cd6a6acSopenharmony_ci			exit(0);
13206cd6a6acSopenharmony_ci			break;
13216cd6a6acSopenharmony_ci		default:
13226cd6a6acSopenharmony_ci			printf("\nUnknown option %s.\n", ans);
13236cd6a6acSopenharmony_ci		}
13246cd6a6acSopenharmony_ci	}
13256cd6a6acSopenharmony_ci
13266cd6a6acSopenharmony_ci	return 0;
13276cd6a6acSopenharmony_ci}
13286cd6a6acSopenharmony_ci
13296cd6a6acSopenharmony_ci/* FLASK */
1330