dismod.c revision f1b004bf7d2453bda1a8076270f5c56b7ad90f56
1
2/* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
3 *
4 * Copyright (C) 2003,2004,2005 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 * dismod.c
12 *
13 * Test program to the contents of a binary policy in text
14 * form.
15 *
16 * 	dismod binary_mod_file
17 */
18
19#include <getopt.h>
20#include <assert.h>
21#include <sys/stat.h>
22#include <sys/types.h>
23#include <sys/mman.h>
24#include <errno.h>
25#include <stdio.h>
26#include <fcntl.h>
27#include <stdlib.h>
28#include <unistd.h>
29
30#include <sepol/policydb/policydb.h>
31#include <sepol/policydb/services.h>
32#include <sepol/policydb/conditional.h>
33#include <sepol/policydb/flask.h>
34#include <sepol/policydb/link.h>
35#include <sepol/policydb/module.h>
36#include <sepol/policydb/util.h>
37#include <sepol/policydb/polcaps.h>
38
39#include <byteswap.h>
40#include <endian.h>
41
42#if __BYTE_ORDER == __LITTLE_ENDIAN
43#define le32_to_cpu(x) (x)
44#else
45#define le32_to_cpu(x) bswap_32(x)
46#endif
47
48#define DISPLAY_AVBLOCK_COND_AVTAB	0
49#define DISPLAY_AVBLOCK_UNCOND_AVTAB	1
50#define DISPLAY_AVBLOCK_ROLE_TYPE_NODE	2 /* unused? */
51#define DISPLAY_AVBLOCK_ROLE_TRANS	3
52#define DISPLAY_AVBLOCK_ROLE_ALLOW	4
53#define DISPLAY_AVBLOCK_REQUIRES	5
54#define DISPLAY_AVBLOCK_DECLARES	6
55#define DISPLAY_AVBLOCK_FILENAME_TRANS	7
56
57static policydb_t policydb;
58extern unsigned int ss_initialized;
59
60int policyvers = MOD_POLICYDB_VERSION_BASE;
61
62static const char *symbol_labels[9] = {
63	"commons",
64	"classes", "roles  ", "types  ", "users  ", "bools  ",
65	"levels ", "cats   ", "attribs"
66};
67
68void usage(char *progname)
69{
70	printf("usage:  %s binary_pol_file\n\n", progname);
71	exit(1);
72}
73
74static void render_access_mask(uint32_t mask, uint32_t class, policydb_t * p,
75			       FILE * fp)
76{
77	char *perm;
78	fprintf(fp, "{");
79	perm = sepol_av_to_string(p, class, mask);
80	if (perm)
81		fprintf(fp, "%s ", perm);
82	fprintf(fp, "}");
83}
84
85static void render_access_bitmap(ebitmap_t * map, uint32_t class,
86				 policydb_t * p, FILE * fp)
87{
88	unsigned int i;
89	char *perm;
90	fprintf(fp, "{");
91	for (i = ebitmap_startbit(map); i < ebitmap_length(map); i++) {
92		if (ebitmap_get_bit(map, i)) {
93			perm = sepol_av_to_string(p, class, 1 << i);
94			if (perm)
95				fprintf(fp, " %s", perm);
96		}
97	}
98	fprintf(fp, " }");
99}
100
101static void display_id(policydb_t * p, FILE * fp, uint32_t symbol_type,
102		       uint32_t symbol_value, char *prefix)
103{
104	char *id = p->sym_val_to_name[symbol_type][symbol_value];
105	scope_datum_t *scope =
106	    (scope_datum_t *) hashtab_search(p->scope[symbol_type].table, id);
107	assert(scope != NULL);
108	if (scope->scope == SCOPE_REQ) {
109		fprintf(fp, " [%s%s]", prefix, id);
110	} else {
111		fprintf(fp, " %s%s", prefix, id);
112	}
113}
114
115int display_type_set(type_set_t * set, uint32_t flags, policydb_t * policy,
116		     FILE * fp)
117{
118	int i, num_types;
119
120	if (set->flags & TYPE_STAR) {
121		fprintf(fp, " * ");
122		return 0;
123	} else if (set->flags & TYPE_COMP) {
124		fprintf(fp, " ~");
125	}
126
127	num_types = 0;
128	if (flags & RULE_SELF) {
129		num_types++;
130	}
131
132	for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
133	     i++) {
134		if (!ebitmap_get_bit(&set->types, i))
135			continue;
136		num_types++;
137		if (num_types > 1)
138			break;
139	}
140
141	if (num_types <= 1) {
142		for (i = ebitmap_startbit(&set->negset);
143		     i < ebitmap_length(&set->negset); i++) {
144			if (!ebitmap_get_bit(&set->negset, i))
145				continue;
146			num_types++;
147			if (num_types > 1)
148				break;
149		}
150	}
151
152	if (num_types > 1)
153		fprintf(fp, "{");
154
155	for (i = ebitmap_startbit(&set->types); i < ebitmap_length(&set->types);
156	     i++) {
157		if (!ebitmap_get_bit(&set->types, i))
158			continue;
159		display_id(policy, fp, SYM_TYPES, i, "");
160	}
161
162	for (i = ebitmap_startbit(&set->negset);
163	     i < ebitmap_length(&set->negset); i++) {
164		if (!ebitmap_get_bit(&set->negset, i))
165			continue;
166		display_id(policy, fp, SYM_TYPES, i, "-");
167	}
168
169	if (flags & RULE_SELF) {
170		fprintf(fp, " self");
171	}
172
173	if (num_types > 1)
174		fprintf(fp, " }");
175
176	return 0;
177}
178
179int display_mod_role_set(role_set_t * roles, policydb_t * p, FILE * fp)
180{
181	int i, num = 0;
182
183	if (roles->flags & ROLE_STAR) {
184		fprintf(fp, " * ");
185		return 0;
186	} else if (roles->flags & ROLE_COMP) {
187		fprintf(fp, " ~");
188	}
189
190	for (i = ebitmap_startbit(&roles->roles);
191	     i < ebitmap_length(&roles->roles); i++) {
192		if (!ebitmap_get_bit(&roles->roles, i))
193			continue;
194		num++;
195		if (num > 1) {
196			fprintf(fp, "{");
197			break;
198		}
199	}
200
201	for (i = ebitmap_startbit(&roles->roles);
202	     i < ebitmap_length(&roles->roles); i++) {
203		if (ebitmap_get_bit(&roles->roles, i))
204			display_id(p, fp, SYM_ROLES, i, "");
205	}
206
207	if (num > 1)
208		fprintf(fp, " }");
209
210	return 0;
211
212}
213
214/* 'what' values for this function */
215#define	RENDER_UNCONDITIONAL	0x0001	/* render all regardless of enabled state */
216#define RENDER_ENABLED		0x0002
217#define RENDER_DISABLED		0x0004
218#define RENDER_CONDITIONAL	(RENDER_ENABLED|RENDER_DISABLED)
219
220int display_avrule(avrule_t * avrule, uint32_t what, policydb_t * policy,
221		   FILE * fp)
222{
223	class_perm_node_t *cur;
224	int num_classes;
225
226	if (avrule == NULL) {
227		fprintf(fp, "  <empty>\n");
228		return 0;
229	}
230	if (avrule->specified & AVRULE_AV) {
231		if (avrule->specified & AVRULE_ALLOWED) {
232			fprintf(fp, "  allow");
233		}
234		if (avrule->specified & AVRULE_AUDITALLOW) {
235			fprintf(fp, "  auditallow ");
236		}
237		if (avrule->specified & AVRULE_DONTAUDIT) {
238			fprintf(fp, "  dontaudit");
239		}
240	} else if (avrule->specified & AVRULE_TYPE) {
241		if (avrule->specified & AVRULE_TRANSITION) {
242			fprintf(fp, "  type_transition");
243		}
244		if (avrule->specified & AVRULE_MEMBER) {
245			fprintf(fp, "  type_member");
246		}
247		if (avrule->specified & AVRULE_CHANGE) {
248			fprintf(fp, "  type_change");
249		}
250	} else if (avrule->specified & AVRULE_NEVERALLOW) {
251		fprintf(fp, "  neverallow");
252	} else {
253		fprintf(fp, "     ERROR: no valid rule type specified\n");
254		return -1;
255	}
256
257	if (display_type_set(&avrule->stypes, 0, policy, fp))
258		return -1;
259
260	if (display_type_set(&avrule->ttypes, avrule->flags, policy, fp))
261		return -1;
262
263	fprintf(fp, " :");
264	cur = avrule->perms;
265	num_classes = 0;
266	while (cur) {
267		num_classes++;
268		if (num_classes > 1)
269			break;
270		cur = cur->next;
271	}
272
273	if (num_classes > 1)
274		fprintf(fp, " {");
275
276	cur = avrule->perms;
277	while (cur) {
278		display_id(policy, fp, SYM_CLASSES, cur->class - 1, "");
279		cur = cur->next;
280	}
281
282	if (num_classes > 1)
283		fprintf(fp, " }");
284	fprintf(fp, " ");
285
286	if (avrule->specified & (AVRULE_AV | AVRULE_NEVERALLOW)) {
287		render_access_mask(avrule->perms->data, avrule->perms->class,
288				   policy, fp);
289	} else if (avrule->specified & AVRULE_TYPE) {
290		display_id(policy, fp, SYM_TYPES, avrule->perms->data - 1, "");
291	}
292
293	fprintf(fp, ";\n");
294
295	return 0;
296}
297
298int display_type_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
299{
300	type_datum_t *type;
301	FILE *fp;
302	int i, first_attrib = 1;
303
304	type = (type_datum_t *) datum;
305	fp = (FILE *) data;
306
307	if (type->primary) {
308		display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
309		fprintf(fp, " [%d]: ", type->s.value);
310	} else {
311		/* as that aliases have no value of their own and that
312		 * they can never be required by a module, use this
313		 * alternative way of displaying a name */
314		fprintf(fp, " %s [%d]: ", (char *)key, type->s.value);
315	}
316	if (type->flavor == TYPE_ATTRIB) {
317		fprintf(fp, "attribute for types");
318		for (i = ebitmap_startbit(&type->types);
319		     i < ebitmap_length(&type->types); i++) {
320			if (!ebitmap_get_bit(&type->types, i))
321				continue;
322			if (first_attrib) {
323				first_attrib = 0;
324			} else {
325				fprintf(fp, ",");
326			}
327			display_id(&policydb, fp, SYM_TYPES, i, "");
328		}
329	} else if (type->primary) {
330		fprintf(fp, "type");
331	} else {
332		fprintf(fp, "alias for type");
333		display_id(&policydb, fp, SYM_TYPES, type->s.value - 1, "");
334	}
335	fprintf(fp, " flags:%x\n", type->flags);
336
337	return 0;
338}
339
340int display_types(policydb_t * p, FILE * fp)
341{
342	if (hashtab_map(p->p_types.table, display_type_callback, fp))
343		return -1;
344	return 0;
345}
346
347int display_users(policydb_t * p, FILE * fp)
348{
349	int i, j;
350	ebitmap_t *bitmap;
351	for (i = 0; i < p->p_users.nprim; i++) {
352		display_id(p, fp, SYM_USERS, i, "");
353		fprintf(fp, ":");
354		bitmap = &(p->user_val_to_struct[i]->roles.roles);
355		for (j = ebitmap_startbit(bitmap); j < ebitmap_length(bitmap);
356		     j++) {
357			if (ebitmap_get_bit(bitmap, j)) {
358				display_id(p, fp, SYM_ROLES, j, "");
359			}
360		}
361		fprintf(fp, "\n");
362	}
363	return 0;
364}
365
366int display_bools(policydb_t * p, FILE * fp)
367{
368	int i;
369
370	for (i = 0; i < p->p_bools.nprim; i++) {
371		display_id(p, fp, SYM_BOOLS, i, "");
372		fprintf(fp, " : %d\n", p->bool_val_to_struct[i]->state);
373	}
374	return 0;
375}
376
377void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
378{
379
380	cond_expr_t *cur;
381	for (cur = exp; cur != NULL; cur = cur->next) {
382		switch (cur->expr_type) {
383		case COND_BOOL:
384			fprintf(fp, "%s ",
385				p->p_bool_val_to_name[cur->bool - 1]);
386			break;
387		case COND_NOT:
388			fprintf(fp, "! ");
389			break;
390		case COND_OR:
391			fprintf(fp, "|| ");
392			break;
393		case COND_AND:
394			fprintf(fp, "&& ");
395			break;
396		case COND_XOR:
397			fprintf(fp, "^ ");
398			break;
399		case COND_EQ:
400			fprintf(fp, "== ");
401			break;
402		case COND_NEQ:
403			fprintf(fp, "!= ");
404			break;
405		default:
406			fprintf(fp, "error!");
407			break;
408		}
409	}
410}
411
412void display_policycon(policydb_t * p, FILE * fp)
413{
414#if 0
415	int i;
416	ocontext_t *cur;
417	char *name;
418
419	for (i = 0; i < POLICYCON_NUM; i++) {
420		fprintf(fp, "%s:", symbol_labels[i]);
421		for (cur = p->policycon[i].head; cur != NULL; cur = cur->next) {
422			if (*(cur->u.name) == '\0') {
423				name = "{default}";
424			} else {
425				name = cur->u.name;
426			}
427			fprintf(fp, "\n%16s - %s:%s:%s", name,
428				p->p_user_val_to_name[cur->context[0].user - 1],
429				p->p_role_val_to_name[cur->context[0].role - 1],
430				p->p_type_val_to_name[cur->context[0].type -
431						      1]);
432		}
433		fprintf(fp, "\n");
434	}
435#endif
436}
437
438void display_initial_sids(policydb_t * p, FILE * fp)
439{
440	ocontext_t *cur;
441	char *user, *role, *type;
442
443	fprintf(fp, "Initial SIDs:\n");
444	for (cur = p->ocontexts[OCON_ISID]; cur != NULL; cur = cur->next) {
445		user = p->p_user_val_to_name[cur->context[0].user - 1];
446		role = p->p_role_val_to_name[cur->context[0].role - 1];
447		type = p->p_type_val_to_name[cur->context[0].type - 1];
448		fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
449			cur->u.name, cur->sid[0], user, role, type);
450	}
451#if 0
452	fprintf(fp, "Policy Initial SIDs:\n");
453	for (cur = p->ocontexts[OCON_POLICYISID]; cur != NULL; cur = cur->next) {
454		user = p->p_user_val_to_name[cur->context[0].user - 1];
455		role = p->p_role_val_to_name[cur->context[0].role - 1];
456		type = p->p_type_val_to_name[cur->context[0].type - 1];
457		fprintf(fp, "\t%s: sid %d, context %s:%s:%s\n",
458			cur->u.name, cur->sid[0], user, role, type);
459	}
460#endif
461}
462
463void display_class_set(ebitmap_t *classes, policydb_t *p, FILE *fp)
464{
465	int i, num = 0;
466
467	for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
468		if (!ebitmap_get_bit(classes, i))
469			continue;
470		num++;
471		if (num > 1) {
472			fprintf(fp, "{");
473			break;
474		}
475	}
476
477	for (i = ebitmap_startbit(classes); i < ebitmap_length(classes); i++) {
478		if (ebitmap_get_bit(classes, i))
479			display_id(p, fp, SYM_CLASSES, i, "");
480	}
481
482	if (num > 1)
483		fprintf(fp, " }");
484}
485
486void display_role_trans(role_trans_rule_t * tr, policydb_t * p, FILE * fp)
487{
488	for (; tr; tr = tr->next) {
489		fprintf(fp, "role transition ");
490		display_mod_role_set(&tr->roles, p, fp);
491		display_type_set(&tr->types, 0, p, fp);
492		fprintf(fp, " :");
493		display_class_set(&tr->classes, p, fp);
494		display_id(p, fp, SYM_ROLES, tr->new_role - 1, "");
495		fprintf(fp, "\n");
496	}
497}
498
499void display_role_allow(role_allow_rule_t * ra, policydb_t * p, FILE * fp)
500{
501	for (; ra; ra = ra->next) {
502		fprintf(fp, "role allow ");
503		display_mod_role_set(&ra->roles, p, fp);
504		display_mod_role_set(&ra->new_roles, p, fp);
505		fprintf(fp, "\n");
506	}
507}
508
509static void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
510{
511	fprintf(fp, "filename transition");
512	for (; tr; tr = tr->next) {
513		display_type_set(&tr->stypes, 0, p, fp);
514		display_type_set(&tr->ttypes, 0, p, fp);
515		display_id(p, fp, SYM_CLASSES, tr->tclass - 1, ":");
516		display_id(p, fp, SYM_TYPES, tr->otype - 1, "");
517		fprintf(fp, " %s\n", tr->name);
518	}
519}
520
521int role_display_callback(hashtab_key_t key, hashtab_datum_t datum, void *data)
522{
523	role_datum_t *role;
524	FILE *fp;
525
526	role = (role_datum_t *) datum;
527	fp = (FILE *) data;
528
529	fprintf(fp, "role:");
530	display_id(&policydb, fp, SYM_ROLES, role->s.value - 1, "");
531	fprintf(fp, " types: ");
532	display_type_set(&role->types, 0, &policydb, fp);
533	fprintf(fp, "\n");
534
535	return 0;
536}
537
538static int display_scope_index(scope_index_t * indices, policydb_t * p,
539			       FILE * out_fp)
540{
541	int i;
542	for (i = 0; i < SYM_NUM; i++) {
543		int any_found = 0, j;
544		fprintf(out_fp, "%s:", symbol_labels[i]);
545		for (j = ebitmap_startbit(&indices->scope[i]);
546		     j < ebitmap_length(&indices->scope[i]); j++) {
547			if (ebitmap_get_bit(&indices->scope[i], j)) {
548				any_found = 1;
549				fprintf(out_fp, " %s",
550					p->sym_val_to_name[i][j]);
551				if (i == SYM_CLASSES) {
552					if (j < indices->class_perms_len) {
553						render_access_bitmap(indices->
554								     class_perms_map
555								     + j, j + 1,
556								     p, out_fp);
557					} else {
558						fprintf(out_fp,
559							"<no perms known>");
560					}
561				}
562			}
563		}
564		if (!any_found) {
565			fprintf(out_fp, " <empty>");
566		}
567		fprintf(out_fp, "\n");
568	}
569	return 0;
570}
571
572#if 0
573int display_cond_expressions(policydb_t * p, FILE * fp)
574{
575	cond_node_t *cur;
576	cond_av_list_t *av_cur;
577	for (cur = p->cond_list; cur != NULL; cur = cur->next) {
578		fprintf(fp, "expression: ");
579		display_expr(p, cur->expr, fp);
580		fprintf(fp, "current state: %d\n", cur->cur_state);
581		fprintf(fp, "True list:\n");
582		for (av_cur = cur->true_list; av_cur != NULL;
583		     av_cur = av_cur->next) {
584			fprintf(fp, "\t");
585			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
586				       RENDER_CONDITIONAL, p, fp);
587		}
588		fprintf(fp, "False list:\n");
589		for (av_cur = cur->false_list; av_cur != NULL;
590		     av_cur = av_cur->next) {
591			fprintf(fp, "\t");
592			render_av_rule(&av_cur->node->key, &av_cur->node->datum,
593				       RENDER_CONDITIONAL, p, fp);
594		}
595	}
596	return 0;
597}
598
599int change_bool(char *name, int state, policydb_t * p, FILE * fp)
600{
601	cond_bool_datum_t *bool;
602
603	bool = hashtab_search(p->p_bools.table, name);
604	if (bool == NULL) {
605		fprintf(fp, "Could not find bool %s\n", name);
606		return -1;
607	}
608	bool->state = state;
609	evaluate_conds(p);
610	return 0;
611}
612#endif
613
614int display_avdecl(avrule_decl_t * decl, int field, uint32_t what,
615		   policydb_t * policy, FILE * out_fp)
616{
617	fprintf(out_fp, "decl %u:%s\n", decl->decl_id,
618		(decl->enabled ? " [enabled]" : ""));
619	switch (field) {
620	case DISPLAY_AVBLOCK_COND_AVTAB:{
621			cond_list_t *cond = decl->cond_list;
622			avrule_t *avrule;
623			while (cond) {
624				fprintf(out_fp, "expression: ");
625				display_expr(&policydb, cond->expr, out_fp);
626				fprintf(out_fp, "current state: %d\n",
627					cond->cur_state);
628				fprintf(out_fp, "True list:\n");
629				avrule = cond->avtrue_list;
630				while (avrule) {
631					display_avrule(avrule,
632						       RENDER_UNCONDITIONAL,
633						       &policydb, out_fp);
634					avrule = avrule->next;
635				}
636				fprintf(out_fp, "False list:\n");
637				avrule = cond->avfalse_list;
638				while (avrule) {
639					display_avrule(avrule,
640						       RENDER_UNCONDITIONAL,
641						       &policydb, out_fp);
642					avrule = avrule->next;
643				}
644				cond = cond->next;
645			}
646			break;
647		}
648	case DISPLAY_AVBLOCK_UNCOND_AVTAB:{
649			avrule_t *avrule = decl->avrules;
650			if (avrule == NULL) {
651				fprintf(out_fp, "  <empty>\n");
652			}
653			while (avrule != NULL) {
654				if (display_avrule
655				    (avrule, what, policy, out_fp)) {
656					return -1;
657				}
658				avrule = avrule->next;
659			}
660			break;
661		}
662	case DISPLAY_AVBLOCK_ROLE_TYPE_NODE:{	/* role_type_node */
663			break;
664		}
665	case DISPLAY_AVBLOCK_ROLE_TRANS:{
666			display_role_trans(decl->role_tr_rules, policy, out_fp);
667			break;
668		}
669	case DISPLAY_AVBLOCK_ROLE_ALLOW:{
670			display_role_allow(decl->role_allow_rules, policy,
671					   out_fp);
672			break;
673		}
674	case DISPLAY_AVBLOCK_REQUIRES:{
675			if (display_scope_index
676			    (&decl->required, policy, out_fp)) {
677				return -1;
678			}
679			break;
680		}
681	case DISPLAY_AVBLOCK_DECLARES:{
682			if (display_scope_index
683			    (&decl->declared, policy, out_fp)) {
684				return -1;
685			}
686			break;
687		}
688	case DISPLAY_AVBLOCK_FILENAME_TRANS:
689		display_filename_trans(decl->filename_trans_rules, policy,
690				       out_fp);
691		break;
692	default:{
693			assert(0);
694		}
695	}
696	return 0;		/* should never get here */
697}
698
699int display_avblock(int field, uint32_t what, policydb_t * policy,
700		    FILE * out_fp)
701{
702	avrule_block_t *block = policydb.global;
703	while (block != NULL) {
704		fprintf(out_fp, "--- begin avrule block ---\n");
705		avrule_decl_t *decl = block->branch_list;
706		while (decl != NULL) {
707			if (display_avdecl(decl, field, what, policy, out_fp)) {
708				return -1;
709			}
710			decl = decl->next;
711		}
712		block = block->next;
713	}
714	return 0;
715}
716
717int display_handle_unknown(policydb_t * p, FILE * out_fp)
718{
719	if (p->handle_unknown == ALLOW_UNKNOWN)
720		fprintf(out_fp, "Allow unknown classes and perms\n");
721	else if (p->handle_unknown == DENY_UNKNOWN)
722		fprintf(out_fp, "Deny unknown classes and perms\n");
723	else if (p->handle_unknown == REJECT_UNKNOWN)
724		fprintf(out_fp, "Reject unknown classes and perms\n");
725	return 0;
726}
727
728static int read_policy(char *filename, policydb_t * policy)
729{
730	FILE *in_fp;
731	struct policy_file f;
732	int retval;
733	uint32_t buf[1];
734
735	if ((in_fp = fopen(filename, "rb")) == NULL) {
736		fprintf(stderr, "Can't open '%s':  %s\n",
737			filename, strerror(errno));
738		exit(1);
739	}
740	policy_file_init(&f);
741	f.type = PF_USE_STDIO;
742	f.fp = in_fp;
743
744	/* peek at the first byte.  if they are indicative of a
745	   package use the package reader, otherwise use the normal
746	   policy reader */
747	if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) {
748		fprintf(stderr, "Could not read from policy.\n");
749		exit(1);
750	}
751	rewind(in_fp);
752	if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) {
753		sepol_module_package_t *package;
754		if (sepol_module_package_create(&package)) {
755			fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
756			exit(1);
757		}
758		package->policy = (sepol_policydb_t *) policy;
759		package->file_contexts = NULL;
760		retval =
761		    sepol_module_package_read(package,
762					      (sepol_policy_file_t *) & f, 1);
763		free(package->file_contexts);
764	} else {
765		if (policydb_init(policy)) {
766			fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
767			exit(1);
768		}
769		retval = policydb_read(policy, &f, 1);
770	}
771	fclose(in_fp);
772	return retval;
773}
774
775static void link_module(policydb_t * base, FILE * out_fp)
776{
777	char module_name[80] = { 0 };
778	int ret;
779	policydb_t module, *mods = &module;
780
781	if (base->policy_type != POLICY_BASE) {
782		printf("Can only link if initial file was a base policy.\n");
783		return;
784	}
785	printf("\nModule filename: ");
786	fgets(module_name, sizeof(module_name), stdin);
787	module_name[strlen(module_name) - 1] = '\0';	/* remove LF */
788	if (module_name[0] == '\0') {
789		return;
790	}
791
792	/* read the binary policy */
793	fprintf(out_fp, "Reading module...\n");
794	if (read_policy(module_name, mods)) {
795		fprintf(stderr,
796			"%s:  error(s) encountered while loading policy\n",
797			module_name);
798		exit(1);
799	}
800	if (module.policy_type != POLICY_MOD) {
801		fprintf(stderr, "This file is not a loadable policy module.\n");
802		exit(1);
803	}
804	if (policydb_index_classes(&module) ||
805	    policydb_index_others(NULL, &module, 0)) {
806		fprintf(stderr, "Could not index module.\n");
807		exit(1);
808	}
809	ret = link_modules(NULL, base, &mods, 1, 0);
810	if (ret != 0) {
811		printf("Link failed (error %d)\n", ret);
812		printf("(You will probably need to restart dismod.)\n");
813	}
814	policydb_destroy(&module);
815	return;
816}
817
818static void display_policycaps(policydb_t * p, FILE * fp)
819{
820	ebitmap_node_t *node;
821	const char *capname;
822	char buf[64];
823	int i;
824
825	fprintf(fp, "policy capabilities:\n");
826	ebitmap_for_each_bit(&p->policycaps, node, i) {
827		if (ebitmap_node_get_bit(node, i)) {
828			capname = sepol_polcap_getname(i);
829			if (capname == NULL) {
830				snprintf(buf, sizeof(buf), "unknown (%d)", i);
831				capname = buf;
832			}
833			fprintf(fp, "\t%s\n", capname);
834		}
835	}
836}
837
838int menu()
839{
840	printf("\nSelect a command:\n");
841	printf("1)  display unconditional AVTAB\n");
842	printf("2)  display conditional AVTAB\n");
843	printf("3)  display users\n");
844	printf("4)  display bools\n");
845	printf("5)  display roles\n");
846	printf("6)  display types, attributes, and aliases\n");
847	printf("7)  display role transitions\n");
848	printf("8)  display role allows\n");
849	printf("9)  Display policycon\n");
850	printf("0)  Display initial SIDs\n");
851	printf("\n");
852	printf("a)  Display avrule requirements\n");
853	printf("b)  Display avrule declarations\n");
854	printf("c)  Display policy capabilities\n");
855	printf("l)  Link in a module\n");
856	printf("u)  Display the unknown handling setting\n");
857	printf("F)  Display filename_trans rules\n");
858	printf("\n");
859	printf("f)  set output file\n");
860	printf("m)  display menu\n");
861	printf("q)  quit\n");
862	return 0;
863}
864
865int main(int argc, char **argv)
866{
867	FILE *out_fp = stdout;
868	char ans[81], OutfileName[121];
869
870	if (argc != 2)
871		usage(argv[0]);
872
873	/* read the binary policy */
874	fprintf(out_fp, "Reading policy...\n");
875	policydb_init(&policydb);
876	if (read_policy(argv[1], &policydb)) {
877		fprintf(stderr,
878			"%s:  error(s) encountered while loading policy\n",
879			argv[0]);
880		exit(1);
881	}
882
883	if (policydb.policy_type != POLICY_BASE &&
884	    policydb.policy_type != POLICY_MOD) {
885		fprintf(stderr,
886			"This file is neither a base nor loadable policy module.\n");
887		exit(1);
888	}
889
890	if (policydb_index_classes(&policydb)) {
891		fprintf(stderr, "Error indexing classes\n");
892		exit(1);
893	}
894
895	if (policydb_index_others(NULL, &policydb, 1)) {
896		fprintf(stderr, "Error indexing others\n");
897		exit(1);
898	}
899
900	if (policydb.policy_type == POLICY_BASE) {
901		printf("Binary base policy file loaded.\n\n");
902	} else {
903		printf("Binary policy module file loaded.\n");
904		printf("Module name: %s\n", policydb.name);
905		printf("Module version: %s\n", policydb.version);
906		printf("\n");
907	}
908
909	menu();
910	for (;;) {
911		printf("\nCommand (\'m\' for menu):  ");
912		fgets(ans, sizeof(ans), stdin);
913		switch (ans[0]) {
914
915		case '1':
916			fprintf(out_fp, "unconditional avtab:\n");
917			display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB,
918					RENDER_UNCONDITIONAL, &policydb,
919					out_fp);
920			break;
921		case '2':
922			fprintf(out_fp, "conditional avtab:\n");
923			display_avblock(DISPLAY_AVBLOCK_COND_AVTAB,
924					RENDER_UNCONDITIONAL, &policydb,
925					out_fp);
926			break;
927		case '3':
928			display_users(&policydb, out_fp);
929			break;
930		case '4':
931			display_bools(&policydb, out_fp);
932			break;
933		case '5':
934			if (hashtab_map
935			    (policydb.p_roles.table, role_display_callback,
936			     out_fp))
937				exit(1);
938			break;
939		case '6':
940			if (display_types(&policydb, out_fp)) {
941				fprintf(stderr, "Error displaying types\n");
942				exit(1);
943			}
944			break;
945		case '7':
946			fprintf(out_fp, "role transitions:\n");
947			display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS, 0,
948					&policydb, out_fp);
949			break;
950		case '8':
951			fprintf(out_fp, "role allows:\n");
952			display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW, 0,
953					&policydb, out_fp);
954			break;
955		case '9':
956			display_policycon(&policydb, out_fp);
957			break;
958		case '0':
959			display_initial_sids(&policydb, out_fp);
960			break;
961		case 'a':
962			fprintf(out_fp, "avrule block requirements:\n");
963			display_avblock(DISPLAY_AVBLOCK_REQUIRES, 0,
964					&policydb, out_fp);
965			break;
966		case 'b':
967			fprintf(out_fp, "avrule block declarations:\n");
968			display_avblock(DISPLAY_AVBLOCK_DECLARES, 0,
969					&policydb, out_fp);
970			break;
971		case 'c':
972			display_policycaps(&policydb, out_fp);
973			break;
974		case 'u':
975		case 'U':
976			display_handle_unknown(&policydb, out_fp);
977			break;
978		case 'f':
979			printf
980			    ("\nFilename for output (<CR> for screen output): ");
981			fgets(OutfileName, sizeof(OutfileName), stdin);
982			OutfileName[strlen(OutfileName) - 1] = '\0';	/* fix_string (remove LF) */
983			if (strlen(OutfileName) == 0)
984				out_fp = stdout;
985			else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
986				fprintf(stderr, "Cannot open output file %s\n",
987					OutfileName);
988				out_fp = stdout;
989			}
990			if (out_fp != stdout)
991				printf("\nOutput to file: %s\n", OutfileName);
992			break;
993		case 'F':
994			fprintf(out_fp, "filename_trans rules:\n");
995			display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
996					0, &policydb, out_fp);
997			break;
998		case 'l':
999			link_module(&policydb, out_fp);
1000			break;
1001		case 'q':
1002			policydb_destroy(&policydb);
1003			exit(0);
1004			break;
1005		case 'm':
1006			menu();
1007			break;
1008		default:
1009			printf("\nInvalid choice\n");
1010			menu();
1011			break;
1012
1013		}
1014	}
1015	exit(EXIT_SUCCESS);
1016}
1017