Home | History | Annotate | Download | only in test
      1 
      2 /* Authors: Frank Mayer <mayerf (at) tresys.com> and Karl MacMillan <kmacmillan (at) 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 
     38 static policydb_t policydb;
     39 
     40 void usage(char *progname)
     41 {
     42 	printf("usage:  %s binary_pol_file\n\n", progname);
     43 	exit(1);
     44 }
     45 
     46 int 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 
     58 int 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 
     64 int 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 
     88 int 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 
    158 int 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 
    185 int 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 
    196 void 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 
    231 int 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 
    277 int 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 
    288 int 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 
    302 static 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 
    322 static 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 
    329 static 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 
    344 static 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 
    358 static 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 
    372 int 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 
    395 int 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