15a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris/* Authors: Frank Mayer <mayerf@tresys.com>
25a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *   and Karl MacMillan <kmacmillan@tresys.com>
35a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *
45a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris * Copyright (C) 2003,2010 Tresys Technology, LLC
55a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *
65a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *	This program is free software; you can redistribute it and/or
75a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *  	modify it under the terms of the GNU General Public License as
85a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *  	published by the Free Software Foundation, version 2.
95a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *
105a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris * Adapted from dispol.c.
115a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *
125a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris * This program is used by sepolgen-ifgen to get the access for all of
135a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris * the attributes in the policy so that it can resolve the
145a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris * typeattribute statements in the interfaces.
155a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *
165a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris * It outputs the attribute access in a similar format to what sepolgen
175a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris * uses to store interface vectors:
185a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *   [Attribute sandbox_x_domain]
195a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *   sandbox_x_domain,samba_var_t,file,ioctl,read,getattr,lock,open
205a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *   sandbox_x_domain,samba_var_t,dir,getattr,search,open
215a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *   sandbox_x_domain,initrc_var_run_t,file,ioctl,read,getattr,lock,open
225a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris *
235a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris */
245a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
255a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris#include <sepol/policydb/policydb.h>
265a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris#include <sepol/policydb/avtab.h>
275a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris#include <sepol/policydb/util.h>
285a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
295a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris#include <stdio.h>
305a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris#include <sys/types.h>
315a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris#include <sys/stat.h>
325a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris#include <fcntl.h>
335a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris#include <sys/mman.h>
345a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris#include <unistd.h>
355a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
365a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisstruct val_to_name {
375a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	unsigned int val;
385a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	char *name;
395a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris};
405a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
415a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisstatic int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data)
425a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris{
435a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	struct val_to_name *v = data;
445a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	perm_datum_t *perdatum;
455a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
465a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	perdatum = (perm_datum_t *) datum;
475a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
485a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (v->val == perdatum->s.value) {
495a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		v->name = key;
505a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return 1;
515a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
525a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
535a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	return 0;
545a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris}
555a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
565a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisint render_access_mask(uint32_t av, avtab_key_t *key, policydb_t *policydbp,
575a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		       FILE *fp)
585a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris{
595a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	struct val_to_name v;
605a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	class_datum_t *cladatum;
615a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	char *perm = NULL;
625a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	unsigned int i;
635a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	int rc;
645a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	uint32_t tclass = key->target_class;
655a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
665a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	cladatum = policydbp->class_val_to_struct[tclass - 1];
675a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	for (i = 0; i < cladatum->permissions.nprim; i++) {
685a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		if (av & (1 << i)) {
695a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			v.val = i + 1;
705a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			rc = hashtab_map(cladatum->permissions.table,
715a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris					 perm_name, &v);
725a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			if (!rc && cladatum->comdatum) {
735a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris				rc = hashtab_map(cladatum->comdatum->
745a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris						 permissions.table, perm_name,
755a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris						 &v);
765a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			}
775a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			if (rc)
785a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris				perm = v.name;
795a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			if (perm) {
805a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris				fprintf(fp, ",%s", perm);
815a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			}
825a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		}
835a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
845a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
855a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	return 0;
865a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris}
875a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
885a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisstatic int render_key(avtab_key_t *key, policydb_t *p, FILE *fp)
895a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris{
905a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	char *stype, *ttype, *tclass;
915a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	stype = p->p_type_val_to_name[key->source_type - 1];
925a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	ttype = p->p_type_val_to_name[key->target_type - 1];
935a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	tclass = p->p_class_val_to_name[key->target_class - 1];
945a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (stype && ttype) {
955a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		fprintf(fp, "%s,%s,%s", stype, ttype, tclass);
965a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	} else {
975a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		fprintf(stderr, "error rendering key\n");
985a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		exit(1);
995a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
1005a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1015a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	return 0;
1025a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris}
1035a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1045a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisstruct callback_data
1055a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris{
1065a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	uint32_t attr;
1075a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	policydb_t *policy;
1085a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	FILE *fp;
1095a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris};
1105a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1115a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisint output_avrule(avtab_key_t *key, avtab_datum_t *datum, void *args)
1125a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris{
1135a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	struct callback_data *cb_data = (struct callback_data *)args;
1145a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1155a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (key->source_type != cb_data->attr)
1165a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return 0;
1175a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1185a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (!(key->specified & AVTAB_AV && key->specified & AVTAB_ALLOWED))
1195a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return 0;
1205a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1215a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	render_key(key, cb_data->policy, cb_data->fp);
1225a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	render_access_mask(datum->data, key, cb_data->policy, cb_data->fp);
1235a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	fprintf(cb_data->fp, "\n");
1245a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1255a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	return 0;
1265a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris}
1275a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1285a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisstatic int attribute_callback(hashtab_key_t key, hashtab_datum_t datum, void *datap)
1295a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris{
1305a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	struct callback_data *cb_data = (struct callback_data *)datap;
1315a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	type_datum_t *t = (type_datum_t *)datum;
1325a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1335a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (t->flavor == TYPE_ATTRIB) {
1345a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		fprintf(cb_data->fp, "[Attribute %s]\n", key);
1355a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		cb_data->attr = t->s.value;
1365a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		if (avtab_map(&cb_data->policy->te_avtab, output_avrule, cb_data) < 0)
1375a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			return -1;
1385a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		if (avtab_map(&cb_data->policy->te_cond_avtab, output_avrule, cb_data) < 0)
1395a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			return -1;
1405a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
1415a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1425a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	return 0;
1435a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris}
1445a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1455a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisstatic policydb_t *load_policy(const char *filename)
1465a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris{
1475a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	policydb_t *policydb;
1485a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	struct policy_file pf;
1495a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	FILE *fp;
1505a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	int ret;
1515a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1525a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	fp = fopen(filename, "r");
1535a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (fp == NULL) {
1545a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		fprintf(stderr, "Can't open '%s':  %s\n",
1555a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			filename, strerror(errno));
1565a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return NULL;
1575a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
1585a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1595a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	policy_file_init(&pf);
1605a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	pf.type = PF_USE_STDIO;
1615a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	pf.fp = fp;
1625a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1635a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	policydb = malloc(sizeof(policydb_t));
1645a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (policydb == NULL) {
1655a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		fprintf(stderr, "Out of memory!\n");
1665a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return NULL;
1675a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
1685a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1695a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (policydb_init(policydb)) {
1705a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		fprintf(stderr, "Out of memory!\n");
1715a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		free(policydb);
1725a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return NULL;
1735a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
1745a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1755a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	ret = policydb_read(policydb, &pf, 1);
1765a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (ret) {
1775a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		fprintf(stderr,
1785a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris			"error(s) encountered while parsing configuration\n");
1795a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		free(policydb);
1805a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return NULL;
1815a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
1825a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1835a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	fclose(fp);
1845a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1855a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	return policydb;
1865a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1875a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris}
1885a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1895a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisvoid usage(char *progname)
1905a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris{
1915a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	printf("usage: %s policy_file out_file\n", progname);
1925a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris}
1935a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
1945a2173519c4210e4b99b08bc08006dfb872442d2Eric Parisint main(int argc, char **argv)
1955a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris{
1965a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	policydb_t *p;
1975a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	struct callback_data cb_data;
1985a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	FILE *fp;
1995a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
2005a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (argc != 3) {
2015a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		usage(argv[0]);
2025a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return -1;
2035a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
2045a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
2055a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	/* Open the policy. */
2065a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	p = load_policy(argv[1]);
2075a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (p == NULL)
2085a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return -1;
2095a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
2105a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	/* Open the output policy. */
2115a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	fp = fopen(argv[2], "w");
2125a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (fp == NULL) {
2135a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		fprintf(stderr, "error opening output file\n");
2145a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		policydb_destroy(p);
2155a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		free(p);
2165a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		return -1;
2175a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
2185a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
2195a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	/* Find all of the attributes and output their access. */
2205a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	cb_data.policy = p;
2215a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	cb_data.fp = fp;
2225a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
2235a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	if (hashtab_map(p->p_types.table, attribute_callback, &cb_data)) {
2245a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris		printf("error finding attributes\n");
2255a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	}
2265a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
2275a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	policydb_destroy(p);
2285a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	free(p);
2295a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	fclose(fp);
2305a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris
2315a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris	return 0;
2325a2173519c4210e4b99b08bc08006dfb872442d2Eric Paris}
233