dismod.c revision 8c48de15b1afeb1cd01a753195a29b1a7811dbfe
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
509void display_filename_trans(filename_trans_rule_t * tr, policydb_t * p, FILE * fp)
510{
511	for (; tr; tr = tr->next) {
512		fprintf(fp, "filename transition %s", tr->name);
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, "\n");
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			return -1;
692		break;
693	default:{
694			assert(0);
695		}
696	}
697	return 0;		/* should never get here */
698}
699
700int display_avblock(int field, uint32_t what, policydb_t * policy,
701		    FILE * out_fp)
702{
703	avrule_block_t *block = policydb.global;
704	while (block != NULL) {
705		fprintf(out_fp, "--- begin avrule block ---\n");
706		avrule_decl_t *decl = block->branch_list;
707		while (decl != NULL) {
708			if (display_avdecl(decl, field, what, policy, out_fp)) {
709				return -1;
710			}
711			decl = decl->next;
712		}
713		block = block->next;
714	}
715	return 0;
716}
717
718int display_handle_unknown(policydb_t * p, FILE * out_fp)
719{
720	if (p->handle_unknown == ALLOW_UNKNOWN)
721		fprintf(out_fp, "Allow unknown classes and perms\n");
722	else if (p->handle_unknown == DENY_UNKNOWN)
723		fprintf(out_fp, "Deny unknown classes and perms\n");
724	else if (p->handle_unknown == REJECT_UNKNOWN)
725		fprintf(out_fp, "Reject unknown classes and perms\n");
726	return 0;
727}
728
729static int read_policy(char *filename, policydb_t * policy)
730{
731	FILE *in_fp;
732	struct policy_file f;
733	int retval;
734	uint32_t buf[1];
735
736	if ((in_fp = fopen(filename, "rb")) == NULL) {
737		fprintf(stderr, "Can't open '%s':  %s\n",
738			filename, strerror(errno));
739		exit(1);
740	}
741	policy_file_init(&f);
742	f.type = PF_USE_STDIO;
743	f.fp = in_fp;
744
745	/* peek at the first byte.  if they are indicative of a
746	   package use the package reader, otherwise use the normal
747	   policy reader */
748	if (fread(buf, sizeof(uint32_t), 1, in_fp) != 1) {
749		fprintf(stderr, "Could not read from policy.\n");
750		exit(1);
751	}
752	rewind(in_fp);
753	if (le32_to_cpu(buf[0]) == SEPOL_MODULE_PACKAGE_MAGIC) {
754		sepol_module_package_t *package;
755		if (sepol_module_package_create(&package)) {
756			fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
757			exit(1);
758		}
759		package->policy = (sepol_policydb_t *) policy;
760		package->file_contexts = NULL;
761		retval =
762		    sepol_module_package_read(package,
763					      (sepol_policy_file_t *) & f, 1);
764		free(package->file_contexts);
765	} else {
766		if (policydb_init(policy)) {
767			fprintf(stderr, "%s:  Out of memory!\n", __FUNCTION__);
768			exit(1);
769		}
770		retval = policydb_read(policy, &f, 1);
771	}
772	fclose(in_fp);
773	return retval;
774}
775
776static void link_module(policydb_t * base, FILE * out_fp)
777{
778	char module_name[80] = { 0 };
779	int ret;
780	policydb_t module, *mods = &module;
781
782	if (base->policy_type != POLICY_BASE) {
783		printf("Can only link if initial file was a base policy.\n");
784		return;
785	}
786	printf("\nModule filename: ");
787	fgets(module_name, sizeof(module_name), stdin);
788	module_name[strlen(module_name) - 1] = '\0';	/* remove LF */
789	if (module_name[0] == '\0') {
790		return;
791	}
792
793	/* read the binary policy */
794	fprintf(out_fp, "Reading module...\n");
795	if (read_policy(module_name, mods)) {
796		fprintf(stderr,
797			"%s:  error(s) encountered while loading policy\n",
798			module_name);
799		exit(1);
800	}
801	if (module.policy_type != POLICY_MOD) {
802		fprintf(stderr, "This file is not a loadable policy module.\n");
803		exit(1);
804	}
805	if (policydb_index_classes(&module) ||
806	    policydb_index_others(NULL, &module, 0)) {
807		fprintf(stderr, "Could not index module.\n");
808		exit(1);
809	}
810	ret = link_modules(NULL, base, &mods, 1, 0);
811	if (ret != 0) {
812		printf("Link failed (error %d)\n", ret);
813		printf("(You will probably need to restart dismod.)\n");
814	}
815	policydb_destroy(&module);
816	return;
817}
818
819static void display_policycaps(policydb_t * p, FILE * fp)
820{
821	ebitmap_node_t *node;
822	const char *capname;
823	char buf[64];
824	int i;
825
826	fprintf(fp, "policy capabilities:\n");
827	ebitmap_for_each_bit(&p->policycaps, node, i) {
828		if (ebitmap_node_get_bit(node, i)) {
829			capname = sepol_polcap_getname(i);
830			if (capname == NULL) {
831				snprintf(buf, sizeof(buf), "unknown (%d)", i);
832				capname = buf;
833			}
834			fprintf(fp, "\t%s\n", capname);
835		}
836	}
837}
838
839int menu()
840{
841	printf("\nSelect a command:\n");
842	printf("1)  display unconditional AVTAB\n");
843	printf("2)  display conditional AVTAB\n");
844	printf("3)  display users\n");
845	printf("4)  display bools\n");
846	printf("5)  display roles\n");
847	printf("6)  display types, attributes, and aliases\n");
848	printf("7)  display role transitions\n");
849	printf("8)  display role allows\n");
850	printf("9)  Display policycon\n");
851	printf("0)  Display initial SIDs\n");
852	printf("\n");
853	printf("a)  Display avrule requirements\n");
854	printf("b)  Display avrule declarations\n");
855	printf("c)  Display policy capabilities\n");
856	printf("l)  Link in a module\n");
857	printf("u)  Display the unknown handling setting\n");
858	printf("F)  Display filename_trans rules\n");
859	printf("\n");
860	printf("f)  set output file\n");
861	printf("m)  display menu\n");
862	printf("q)  quit\n");
863	return 0;
864}
865
866int main(int argc, char **argv)
867{
868	FILE *out_fp = stdout;
869	char ans[81], OutfileName[121];
870
871	if (argc != 2)
872		usage(argv[0]);
873
874	/* read the binary policy */
875	fprintf(out_fp, "Reading policy...\n");
876	policydb_init(&policydb);
877	if (read_policy(argv[1], &policydb)) {
878		fprintf(stderr,
879			"%s:  error(s) encountered while loading policy\n",
880			argv[0]);
881		exit(1);
882	}
883
884	if (policydb.policy_type != POLICY_BASE &&
885	    policydb.policy_type != POLICY_MOD) {
886		fprintf(stderr,
887			"This file is neither a base nor loadable policy module.\n");
888		exit(1);
889	}
890
891	if (policydb_index_classes(&policydb)) {
892		fprintf(stderr, "Error indexing classes\n");
893		exit(1);
894	}
895
896	if (policydb_index_others(NULL, &policydb, 1)) {
897		fprintf(stderr, "Error indexing others\n");
898		exit(1);
899	}
900
901	if (policydb.policy_type == POLICY_BASE) {
902		printf("Binary base policy file loaded.\n\n");
903	} else {
904		printf("Binary policy module file loaded.\n");
905		printf("Module name: %s\n", policydb.name);
906		printf("Module version: %s\n", policydb.version);
907		printf("\n");
908	}
909
910	menu();
911	for (;;) {
912		printf("\nCommand (\'m\' for menu):  ");
913		fgets(ans, sizeof(ans), stdin);
914		switch (ans[0]) {
915
916		case '1':
917			fprintf(out_fp, "unconditional avtab:\n");
918			display_avblock(DISPLAY_AVBLOCK_UNCOND_AVTAB,
919					RENDER_UNCONDITIONAL, &policydb,
920					out_fp);
921			break;
922		case '2':
923			fprintf(out_fp, "conditional avtab:\n");
924			display_avblock(DISPLAY_AVBLOCK_COND_AVTAB,
925					RENDER_UNCONDITIONAL, &policydb,
926					out_fp);
927			break;
928		case '3':
929			display_users(&policydb, out_fp);
930			break;
931		case '4':
932			display_bools(&policydb, out_fp);
933			break;
934		case '5':
935			if (hashtab_map
936			    (policydb.p_roles.table, role_display_callback,
937			     out_fp))
938				exit(1);
939			break;
940		case '6':
941			if (display_types(&policydb, out_fp)) {
942				fprintf(stderr, "Error displaying types\n");
943				exit(1);
944			}
945			break;
946		case '7':
947			fprintf(out_fp, "role transitions:\n");
948			display_avblock(DISPLAY_AVBLOCK_ROLE_TRANS, 0,
949					&policydb, out_fp);
950			break;
951		case '8':
952			fprintf(out_fp, "role allows:\n");
953			display_avblock(DISPLAY_AVBLOCK_ROLE_ALLOW, 0,
954					&policydb, out_fp);
955			break;
956		case '9':
957			display_policycon(&policydb, out_fp);
958			break;
959		case '0':
960			display_initial_sids(&policydb, out_fp);
961			break;
962		case 'a':
963			fprintf(out_fp, "avrule block requirements:\n");
964			display_avblock(DISPLAY_AVBLOCK_REQUIRES, 0,
965					&policydb, out_fp);
966			break;
967		case 'b':
968			fprintf(out_fp, "avrule block declarations:\n");
969			display_avblock(DISPLAY_AVBLOCK_DECLARES, 0,
970					&policydb, out_fp);
971			break;
972		case 'c':
973			display_policycaps(&policydb, out_fp);
974			break;
975		case 'u':
976		case 'U':
977			display_handle_unknown(&policydb, out_fp);
978			break;
979		case 'f':
980			printf
981			    ("\nFilename for output (<CR> for screen output): ");
982			fgets(OutfileName, sizeof(OutfileName), stdin);
983			OutfileName[strlen(OutfileName) - 1] = '\0';	/* fix_string (remove LF) */
984			if (strlen(OutfileName) == 0)
985				out_fp = stdout;
986			else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
987				fprintf(stderr, "Cannot open output file %s\n",
988					OutfileName);
989				out_fp = stdout;
990			}
991			if (out_fp != stdout)
992				printf("\nOutput to file: %s\n", OutfileName);
993			break;
994		case 'F':
995			fprintf(out_fp, "filename_trans rules:\n");
996			display_avblock(DISPLAY_AVBLOCK_FILENAME_TRANS,
997					0, &policydb, out_fp);
998			break;
999		case 'l':
1000			link_module(&policydb, out_fp);
1001			break;
1002		case 'q':
1003			policydb_destroy(&policydb);
1004			exit(0);
1005			break;
1006		case 'm':
1007			menu();
1008			break;
1009		default:
1010			printf("\nInvalid choice\n");
1011			menu();
1012			break;
1013
1014		}
1015	}
1016	exit(EXIT_SUCCESS);
1017}
1018