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