1/* Authors: Frank Mayer <mayerf@tresys.com>
2 *   and Karl MacMillan <kmacmillan@tresys.com>
3 *
4 * Copyright (C) 2003,2010 Tresys Technology, LLC
5 *
6 *	This program is free software; you can redistribute it and/or
7 *  	modify it under the terms of the GNU General Public License as
8 *  	published by the Free Software Foundation, version 2.
9 *
10 * Adapted from dispol.c.
11 *
12 * This program is used by sepolgen-ifgen to get the access for all of
13 * the attributes in the policy so that it can resolve the
14 * typeattribute statements in the interfaces.
15 *
16 * It outputs the attribute access in a similar format to what sepolgen
17 * uses to store interface vectors:
18 *   [Attribute sandbox_x_domain]
19 *   sandbox_x_domain,samba_var_t,file,ioctl,read,getattr,lock,open
20 *   sandbox_x_domain,samba_var_t,dir,getattr,search,open
21 *   sandbox_x_domain,initrc_var_run_t,file,ioctl,read,getattr,lock,open
22 *
23 */
24
25#include <sepol/policydb/policydb.h>
26#include <sepol/policydb/avtab.h>
27#include <sepol/policydb/util.h>
28
29#include <stdio.h>
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <fcntl.h>
33#include <sys/mman.h>
34#include <unistd.h>
35
36struct val_to_name {
37	unsigned int val;
38	char *name;
39};
40
41static int perm_name(hashtab_key_t key, hashtab_datum_t datum, void *data)
42{
43	struct val_to_name *v = data;
44	perm_datum_t *perdatum;
45
46	perdatum = (perm_datum_t *) datum;
47
48	if (v->val == perdatum->s.value) {
49		v->name = key;
50		return 1;
51	}
52
53	return 0;
54}
55
56int render_access_mask(uint32_t av, avtab_key_t *key, policydb_t *policydbp,
57		       FILE *fp)
58{
59	struct val_to_name v;
60	class_datum_t *cladatum;
61	char *perm = NULL;
62	unsigned int i;
63	int rc;
64	uint32_t tclass = key->target_class;
65
66	cladatum = policydbp->class_val_to_struct[tclass - 1];
67	for (i = 0; i < cladatum->permissions.nprim; i++) {
68		if (av & (1 << i)) {
69			v.val = i + 1;
70			rc = hashtab_map(cladatum->permissions.table,
71					 perm_name, &v);
72			if (!rc && cladatum->comdatum) {
73				rc = hashtab_map(cladatum->comdatum->
74						 permissions.table, perm_name,
75						 &v);
76			}
77			if (rc)
78				perm = v.name;
79			if (perm) {
80				fprintf(fp, ",%s", perm);
81			}
82		}
83	}
84
85	return 0;
86}
87
88static int render_key(avtab_key_t *key, policydb_t *p, FILE *fp)
89{
90	char *stype, *ttype, *tclass;
91	stype = p->p_type_val_to_name[key->source_type - 1];
92	ttype = p->p_type_val_to_name[key->target_type - 1];
93	tclass = p->p_class_val_to_name[key->target_class - 1];
94	if (stype && ttype) {
95		fprintf(fp, "%s,%s,%s", stype, ttype, tclass);
96	} else {
97		fprintf(stderr, "error rendering key\n");
98		exit(1);
99	}
100
101	return 0;
102}
103
104struct callback_data
105{
106	uint32_t attr;
107	policydb_t *policy;
108	FILE *fp;
109};
110
111int output_avrule(avtab_key_t *key, avtab_datum_t *datum, void *args)
112{
113	struct callback_data *cb_data = (struct callback_data *)args;
114
115	if (key->source_type != cb_data->attr)
116		return 0;
117
118	if (!(key->specified & AVTAB_AV && key->specified & AVTAB_ALLOWED))
119		return 0;
120
121	render_key(key, cb_data->policy, cb_data->fp);
122	render_access_mask(datum->data, key, cb_data->policy, cb_data->fp);
123	fprintf(cb_data->fp, "\n");
124
125	return 0;
126}
127
128static int attribute_callback(hashtab_key_t key, hashtab_datum_t datum, void *datap)
129{
130	struct callback_data *cb_data = (struct callback_data *)datap;
131	type_datum_t *t = (type_datum_t *)datum;
132
133	if (t->flavor == TYPE_ATTRIB) {
134		fprintf(cb_data->fp, "[Attribute %s]\n", key);
135		cb_data->attr = t->s.value;
136		if (avtab_map(&cb_data->policy->te_avtab, output_avrule, cb_data) < 0)
137			return -1;
138		if (avtab_map(&cb_data->policy->te_cond_avtab, output_avrule, cb_data) < 0)
139			return -1;
140	}
141
142	return 0;
143}
144
145static policydb_t *load_policy(const char *filename)
146{
147	policydb_t *policydb;
148	struct policy_file pf;
149	FILE *fp;
150	int ret;
151
152	fp = fopen(filename, "r");
153	if (fp == NULL) {
154		fprintf(stderr, "Can't open '%s':  %s\n",
155			filename, strerror(errno));
156		return NULL;
157	}
158
159	policy_file_init(&pf);
160	pf.type = PF_USE_STDIO;
161	pf.fp = fp;
162
163	policydb = malloc(sizeof(policydb_t));
164	if (policydb == NULL) {
165		fprintf(stderr, "Out of memory!\n");
166		return NULL;
167	}
168
169	if (policydb_init(policydb)) {
170		fprintf(stderr, "Out of memory!\n");
171		free(policydb);
172		return NULL;
173	}
174
175	ret = policydb_read(policydb, &pf, 1);
176	if (ret) {
177		fprintf(stderr,
178			"error(s) encountered while parsing configuration\n");
179		free(policydb);
180		return NULL;
181	}
182
183	fclose(fp);
184
185	return policydb;
186
187}
188
189void usage(char *progname)
190{
191	printf("usage: %s policy_file out_file\n", progname);
192}
193
194int main(int argc, char **argv)
195{
196	policydb_t *p;
197	struct callback_data cb_data;
198	FILE *fp;
199
200	if (argc != 3) {
201		usage(argv[0]);
202		return -1;
203	}
204
205	/* Open the policy. */
206	p = load_policy(argv[1]);
207	if (p == NULL)
208		return -1;
209
210	/* Open the output policy. */
211	fp = fopen(argv[2], "w");
212	if (fp == NULL) {
213		fprintf(stderr, "error opening output file\n");
214		policydb_destroy(p);
215		free(p);
216		return -1;
217	}
218
219	/* Find all of the attributes and output their access. */
220	cb_data.policy = p;
221	cb_data.fp = fp;
222
223	if (hashtab_map(p->p_types.table, attribute_callback, &cb_data)) {
224		printf("error finding attributes\n");
225	}
226
227	policydb_destroy(p);
228	free(p);
229	fclose(fp);
230
231	return 0;
232}
233