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