dispol.c revision cd88c5c44f93ca14828bdae024fae6e0287ba71d
1
2/* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
3 *
4 * Copyright (C) 2003 Tresys Technology, LLC
5 *	This program is free software; you can redistribute it and/or modify
6 *  	it under the terms of the GNU General Public License as published by
7 *	the Free Software Foundation, version 2.
8 */
9
10/*
11 * displaypol.c
12 *
13 * Test program to the contents of a binary policy in text
14 * form.  This program currently only displays the
15 * avtab (including conditional avtab) rules.
16 *
17 * 	displaypol binary_pol_file
18 */
19
20#include <sepol/policydb/policydb.h>
21#include <sepol/policydb/avtab.h>
22#include <sepol/policydb/services.h>
23#include <sepol/policydb/conditional.h>
24#include <sepol/policydb/expand.h>
25#include <sepol/policydb/util.h>
26#include <sepol/policydb/polcaps.h>
27#include <getopt.h>
28#include <assert.h>
29#include <unistd.h>
30#include <stdlib.h>
31#include <sys/stat.h>
32#include <sys/types.h>
33#include <sys/mman.h>
34#include <errno.h>
35#include <stdio.h>
36#include <fcntl.h>
37
38static policydb_t policydb;
39
40void usage(char *progname)
41{
42	printf("usage:  %s binary_pol_file\n\n", progname);
43	exit(1);
44}
45
46int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
47		       FILE * fp)
48{
49	char *perm;
50	fprintf(fp, "{");
51	perm = sepol_av_to_string(p, key->target_class, mask);
52	if (perm)
53		fprintf(fp, "%s ", perm);
54	fprintf(fp, "}");
55	return 0;
56}
57
58int render_type(uint32_t type, policydb_t * p, FILE * fp)
59{
60	fprintf(fp, "%s", p->p_type_val_to_name[type - 1]);
61	return 0;
62}
63
64int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
65{
66	char *stype, *ttype, *tclass;
67	stype = p->p_type_val_to_name[key->source_type - 1];
68	ttype = p->p_type_val_to_name[key->target_type - 1];
69	tclass = p->p_class_val_to_name[key->target_class - 1];
70	if (stype && ttype)
71		fprintf(fp, "%s %s : %s ", stype, ttype, tclass);
72	else if (stype)
73		fprintf(fp, "%s %u : %s ", stype, key->target_type, tclass);
74	else if (ttype)
75		fprintf(fp, "%u %s : %s ", key->source_type, ttype, tclass);
76	else
77		fprintf(fp, "%u %u : %s ", key->source_type, key->target_type,
78			tclass);
79	return 0;
80}
81
82/* 'what' values for this function */
83#define	RENDER_UNCONDITIONAL	0x0001	/* render all regardless of enabled state */
84#define RENDER_ENABLED		0x0002
85#define RENDER_DISABLED		0x0004
86#define RENDER_CONDITIONAL	(RENDER_ENABLED|RENDER_DISABLED)
87
88int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
89		   policydb_t * p, FILE * fp)
90{
91	if (!(what & RENDER_UNCONDITIONAL)) {
92		if (what != RENDER_CONDITIONAL && (((what & RENDER_ENABLED)
93						    && !(key->
94							 specified &
95							 AVTAB_ENABLED))
96						   || ((what & RENDER_DISABLED)
97						       && (key->
98							   specified &
99							   AVTAB_ENABLED)))) {
100			return 0;	/* doesn't match selection criteria */
101		}
102	}
103
104	if (!(what & RENDER_UNCONDITIONAL)) {
105		if (key->specified & AVTAB_ENABLED)
106			fprintf(fp, "[enabled] ");
107		else if (!(key->specified & AVTAB_ENABLED))
108			fprintf(fp, "[disabled] ");
109	}
110
111	if (key->specified & AVTAB_AV) {
112		if (key->specified & AVTAB_ALLOWED) {
113			fprintf(fp, "allow ");
114			render_key(key, p, fp);
115			render_access_mask(datum->data, key, p, fp);
116			fprintf(fp, ";\n");
117		}
118		if (key->specified & AVTAB_AUDITALLOW) {
119			fprintf(fp, "auditallow ");
120			render_key(key, p, fp);
121			render_access_mask(datum->data, key, p, fp);
122			fprintf(fp, ";\n");
123		}
124		if (key->specified & AVTAB_AUDITDENY) {
125			fprintf(fp, "dontaudit ");
126			render_key(key, p, fp);
127			/* We inverse the mask for dontaudit since the mask is internally stored
128			 * as a auditdeny mask */
129			render_access_mask(~datum->data, key, p, fp);
130			fprintf(fp, ";\n");
131		}
132	} else if (key->specified & AVTAB_TYPE) {
133		if (key->specified & AVTAB_TRANSITION) {
134			fprintf(fp, "type_transition ");
135			render_key(key, p, fp);
136			render_type(datum->data, p, fp);
137			fprintf(fp, ";\n");
138		}
139		if (key->specified & AVTAB_MEMBER) {
140			fprintf(fp, "type_member ");
141			render_key(key, p, fp);
142			render_type(datum->data, p, fp);
143			fprintf(fp, ";\n");
144		}
145		if (key->specified & AVTAB_CHANGE) {
146			fprintf(fp, "type_change ");
147			render_key(key, p, fp);
148			render_type(datum->data, p, fp);
149			fprintf(fp, ";\n");
150		}
151	} else {
152		fprintf(fp, "     ERROR: no valid rule type specified\n");
153		return -1;
154	}
155	return 0;
156}
157
158int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
159{
160	unsigned int i;
161	avtab_ptr_t cur;
162	avtab_t expa;
163
164	if (avtab_init(&expa))
165		goto oom;
166	if (expand_avtab(p, a, &expa)) {
167		avtab_destroy(&expa);
168		goto oom;
169	}
170
171	/* hmm...should have used avtab_map. */
172	for (i = 0; i < expa.nslot; i++) {
173		for (cur = expa.htable[i]; cur; cur = cur->next) {
174			render_av_rule(&cur->key, &cur->datum, what, p, fp);
175		}
176	}
177	avtab_destroy(&expa);
178	fprintf(fp, "\n");
179	return 0;
180      oom:
181	fprintf(stderr, "out of memory\n");
182	return 1;
183}
184
185int display_bools(policydb_t * p, FILE * fp)
186{
187	unsigned int i;
188
189	for (i = 0; i < p->p_bools.nprim; i++) {
190		fprintf(fp, "%s : %d\n", p->p_bool_val_to_name[i],
191			p->bool_val_to_struct[i]->state);
192	}
193	return 0;
194}
195
196void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
197{
198
199	cond_expr_t *cur;
200	for (cur = exp; cur != NULL; cur = cur->next) {
201		switch (cur->expr_type) {
202		case COND_BOOL:
203			fprintf(fp, "%s ",
204				p->p_bool_val_to_name[cur->bool - 1]);
205			break;
206		case COND_NOT:
207			fprintf(fp, "! ");
208			break;
209		case COND_OR:
210			fprintf(fp, "|| ");
211			break;
212		case COND_AND:
213			fprintf(fp, "&& ");
214			break;
215		case COND_XOR:
216			fprintf(fp, "^ ");
217			break;
218		case COND_EQ:
219			fprintf(fp, "== ");
220			break;
221		case COND_NEQ:
222			fprintf(fp, "!= ");
223			break;
224		default:
225			fprintf(fp, "error!");
226			break;
227		}
228	}
229}
230
231int display_cond_expressions(policydb_t * p, FILE * fp)
232{
233	cond_node_t *cur;
234	cond_av_list_t *av_cur, *expl = NULL;
235	avtab_t expa;
236
237	for (cur = p->cond_list; cur != NULL; cur = cur->next) {
238		fprintf(fp, "expression: ");
239		display_expr(p, cur->expr, fp);
240		fprintf(fp, "current state: %d\n", cur->cur_state);
241		fprintf(fp, "True list:\n");
242		if (avtab_init(&expa))
243			goto oom;
244		if (expand_cond_av_list(p, cur->true_list, &expl, &expa)) {
245			avtab_destroy(&expa);
246			goto oom;
247		}
248		for (av_cur = expl; av_cur != NULL; av_cur = av_cur->next) {
249			fprintf(fp, "\t");
250			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
251				       RENDER_CONDITIONAL, p, fp);
252		}
253		cond_av_list_destroy(expl);
254		avtab_destroy(&expa);
255		fprintf(fp, "False list:\n");
256		if (avtab_init(&expa))
257			goto oom;
258		if (expand_cond_av_list(p, cur->false_list, &expl, &expa)) {
259			avtab_destroy(&expa);
260			goto oom;
261		}
262		for (av_cur = expl; av_cur != NULL; av_cur = av_cur->next) {
263			fprintf(fp, "\t");
264			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
265				       RENDER_CONDITIONAL, p, fp);
266		}
267		cond_av_list_destroy(expl);
268		avtab_destroy(&expa);
269	}
270	return 0;
271
272      oom:
273	fprintf(stderr, "out of memory\n");
274	return 1;
275}
276
277int display_handle_unknown(policydb_t * p, FILE * out_fp)
278{
279	if (p->handle_unknown == ALLOW_UNKNOWN)
280		fprintf(out_fp, "Allow unknown classes and permisions\n");
281	else if (p->handle_unknown == DENY_UNKNOWN)
282		fprintf(out_fp, "Deny unknown classes and permisions\n");
283	else if (p->handle_unknown == REJECT_UNKNOWN)
284		fprintf(out_fp, "Reject unknown classes and permisions\n");
285	return 0;
286}
287
288int change_bool(char *name, int state, policydb_t * p, FILE * fp)
289{
290	cond_bool_datum_t *bool;
291
292	bool = hashtab_search(p->p_bools.table, name);
293	if (bool == NULL) {
294		fprintf(fp, "Could not find bool %s\n", name);
295		return -1;
296	}
297	bool->state = state;
298	evaluate_conds(p);
299	return 0;
300}
301
302static void display_policycaps(policydb_t * p, FILE * fp)
303{
304	ebitmap_node_t *node;
305	const char *capname;
306	char buf[64];
307	unsigned int i;
308
309	fprintf(fp, "policy capabilities:\n");
310	ebitmap_for_each_bit(&p->policycaps, node, i) {
311		if (ebitmap_node_get_bit(node, i)) {
312			capname = sepol_polcap_getname(i);
313			if (capname == NULL) {
314				snprintf(buf, sizeof(buf), "unknown (%d)", i);
315				capname = buf;
316			}
317			fprintf(fp, "\t%s\n", capname);
318		}
319	}
320}
321
322static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type,
323		       uint32_t symbol_value, char *prefix)
324{
325	char *id = p->sym_val_to_name[symbol_type][symbol_value];
326	fprintf(fp, " %s%s", prefix, id);
327}
328
329static void display_permissive(policydb_t *p, FILE *fp)
330{
331	ebitmap_node_t *node;
332	unsigned int i;
333
334	fprintf(fp, "permissive sids:\n");
335	ebitmap_for_each_bit(&p->permissive_map, node, i) {
336		if (ebitmap_node_get_bit(node, i)) {
337			fprintf(fp, "\t");
338			display_id(p, fp, SYM_TYPES, i - 1, "");
339			fprintf(fp, "\n");
340		}
341	}
342}
343
344static void display_role_trans(policydb_t *p, FILE *fp)
345{
346	role_trans_t *rt;
347
348	fprintf(fp, "role_trans rules:\n");
349	for (rt = p->role_tr; rt; rt = rt->next) {
350		display_id(p, fp, SYM_ROLES, rt->role - 1, "");
351		display_id(p, fp, SYM_TYPES, rt->type - 1, "");
352		display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":");
353		display_id(p, fp, SYM_ROLES, rt->new_role - 1, "");
354		fprintf(fp, "\n");
355	}
356}
357
358static void display_filename_trans(policydb_t *p, FILE *fp)
359{
360	filename_trans_t *ft;
361
362	fprintf(fp, "filename_trans rules:\n");
363	for (ft = p->filename_trans; ft; ft = ft->next) {
364		display_id(p, fp, SYM_TYPES, ft->stype - 1, "");
365		display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
366		display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
367		display_id(p, fp, SYM_TYPES, ft->otype - 1, "");
368		fprintf(fp, " %s\n", ft->name);
369	}
370}
371
372int menu()
373{
374	printf("\nSelect a command:\n");
375	printf("1)  display unconditional AVTAB\n");
376	printf("2)  display conditional AVTAB (entirely)\n");
377	printf("3)  display conditional AVTAG (only ENABLED rules)\n");
378	printf("4)  display conditional AVTAB (only DISABLED rules)\n");
379	printf("5)  display conditional bools\n");
380	printf("6)  display conditional expressions\n");
381	printf("7)  change a boolean value\n");
382	printf("8)  display role transitions\n");
383	printf("\n");
384	printf("c)  display policy capabilities\n");
385	printf("p)  display the list of permissive types\n");
386	printf("u)  display unknown handling setting\n");
387	printf("F)  display filename_trans rules\n");
388	printf("\n");
389	printf("f)  set output file\n");
390	printf("m)  display menu\n");
391	printf("q)  quit\n");
392	return 0;
393}
394
395int main(int argc, char **argv)
396{
397	FILE *out_fp = stdout;
398	char ans[81], OutfileName[121];
399	int fd, ret;
400	struct stat sb;
401	void *map;
402	char *name;
403	int state;
404	struct policy_file pf;
405
406	if (argc != 2)
407		usage(argv[0]);
408
409	fd = open(argv[1], O_RDONLY);
410	if (fd < 0) {
411		fprintf(stderr, "Can't open '%s':  %s\n",
412			argv[1], strerror(errno));
413		exit(1);
414	}
415	if (fstat(fd, &sb) < 0) {
416		fprintf(stderr, "Can't stat '%s':  %s\n",
417			argv[1], strerror(errno));
418		exit(1);
419	}
420	map =
421	    mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
422	if (map == MAP_FAILED) {
423		fprintf(stderr, "Can't map '%s':  %s\n",
424			argv[1], strerror(errno));
425		exit(1);
426	}
427
428	/* read the binary policy */
429	fprintf(out_fp, "Reading policy...\n");
430	policy_file_init(&pf);
431	pf.type = PF_USE_MEMORY;
432	pf.data = map;
433	pf.len = sb.st_size;
434	if (policydb_init(&policydb)) {
435		fprintf(stderr, "%s:  Out of memory!\n", argv[0]);
436		exit(1);
437	}
438	ret = policydb_read(&policydb, &pf, 1);
439	if (ret) {
440		fprintf(stderr,
441			"%s:  error(s) encountered while parsing configuration\n",
442			argv[0]);
443		exit(1);
444	}
445
446	fprintf(stdout, "binary policy file loaded\n\n");
447	close(fd);
448
449	menu();
450	for (;;) {
451		printf("\nCommand (\'m\' for menu):  ");
452		fgets(ans, sizeof(ans), stdin);
453		switch (ans[0]) {
454
455		case '1':
456			display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL,
457				      &policydb, out_fp);
458			break;
459		case '2':
460			display_avtab(&policydb.te_cond_avtab,
461				      RENDER_CONDITIONAL, &policydb, out_fp);
462			break;
463		case '3':
464			display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED,
465				      &policydb, out_fp);
466			break;
467		case '4':
468			display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED,
469				      &policydb, out_fp);
470			break;
471		case '5':
472			display_bools(&policydb, out_fp);
473			break;
474		case '6':
475			display_cond_expressions(&policydb, out_fp);
476			break;
477		case '7':
478			printf("name? ");
479			fgets(ans, sizeof(ans), stdin);
480			ans[strlen(ans) - 1] = 0;
481
482			name = malloc((strlen(ans) + 1) * sizeof(char));
483			if (name == NULL) {
484				fprintf(stderr, "couldn't malloc string.\n");
485				break;
486			}
487			strcpy(name, ans);
488
489			printf("state? ");
490			fgets(ans, sizeof(ans), stdin);
491			ans[strlen(ans) - 1] = 0;
492
493			if (atoi(ans))
494				state = 1;
495			else
496				state = 0;
497
498			change_bool(name, state, &policydb, out_fp);
499			free(name);
500			break;
501		case '8':
502			display_role_trans(&policydb, out_fp);
503			break;
504		case 'c':
505			display_policycaps(&policydb, out_fp);
506			break;
507		case 'p':
508			display_permissive(&policydb, out_fp);
509			break;
510		case 'u':
511		case 'U':
512			display_handle_unknown(&policydb, out_fp);
513			break;
514		case 'f':
515			printf
516			    ("\nFilename for output (<CR> for screen output): ");
517			fgets(OutfileName, sizeof(OutfileName), stdin);
518			OutfileName[strlen(OutfileName) - 1] = '\0';	/* fix_string (remove LF) */
519			if (strlen(OutfileName) == 0)
520				out_fp = stdout;
521			else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
522				fprintf(stderr, "Cannot open output file %s\n",
523					OutfileName);
524				out_fp = stdout;
525			}
526			if (out_fp != stdout)
527				printf("\nOutput to file: %s\n", OutfileName);
528			break;
529		case 'F':
530			display_filename_trans(&policydb, out_fp);
531			break;
532		case 'q':
533			policydb_destroy(&policydb);
534			exit(0);
535			break;
536		case 'm':
537			menu();
538			break;
539		default:
540			printf("\nInvalid choice\n");
541			menu();
542			break;
543
544		}
545	}
546}
547
548/* FLASK */
549