1 /* Authors: Frank Mayer <[email protected]> and Karl MacMillan <[email protected]>
2 *
3 * Copyright (C) 2003 Tresys Technology, LLC
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, version 2.
7 */
8
9 /*
10 * displaypol.c
11 *
12 * Test program to the contents of a binary policy in text
13 * form. This program currently only displays the
14 * avtab (including conditional avtab) rules.
15 *
16 * displaypol binary_pol_file
17 */
18
19 #include <sepol/policydb/policydb.h>
20 #include <sepol/policydb/avtab.h>
21 #include <sepol/policydb/services.h>
22 #include <sepol/policydb/conditional.h>
23 #include <sepol/policydb/util.h>
24 #include <sepol/policydb/polcaps.h>
25 #include <getopt.h>
26 #include <assert.h>
27 #include <unistd.h>
28 #include <stdlib.h>
29 #include <sys/stat.h>
30 #include <sys/types.h>
31 #include <sys/mman.h>
32 #include <errno.h>
33 #include <stdio.h>
34 #include <fcntl.h>
35
36 static const struct command {
37 enum {
38 EOL = 0,
39 HEADER = 1,
40 CMD = 1 << 1,
41 NOOPT = 1 << 2,
42 } meta;
43 char cmd;
44 const char *desc;
45 } commands[] = {
46 {HEADER, 0, "\nSelect a command:"},
47 {CMD, '1', "display unconditional AVTAB" },
48 {CMD, '2', "display conditional AVTAB (entirely)"},
49 {CMD, '3', "display conditional AVTAB (only ENABLED rules)"},
50 {CMD, '4', "display conditional AVTAB (only DISABLED rules)"},
51 {CMD, '5', "display booleans"},
52 {CMD, '6', "display conditional expressions"},
53 {CMD|NOOPT, '7', "change a boolean value"},
54 {CMD, '8', "display role transitions"},
55 {HEADER, 0, ""},
56 {CMD, 'c', "display policy capabilities"},
57 {CMD, 'C', "display classes"},
58 {CMD, 'u', "display users"},
59 {CMD, 'r', "display roles"},
60 {CMD, 't', "display types"},
61 {CMD, 'a', "display type attributes"},
62 {CMD, 'p', "display the list of permissive types"},
63 {CMD, 'U', "display unknown handling setting"},
64 {CMD, 'F', "display filename_trans rules"},
65 {HEADER, 0, ""},
66 {CMD|NOOPT, 'f', "set output file"},
67 {CMD|NOOPT, 'm', "display menu"},
68 {CMD|NOOPT, 'q', "quit"},
69 {EOL, 0, "" },
70 };
71
usage(const char * progname)72 static __attribute__((__noreturn__)) void usage(const char *progname)
73 {
74 puts("Usage:");
75 printf(" %s [OPTIONS] binary_pol_file\n\n", progname);
76 puts("Options:");
77 puts(" -h, --help print this help message");
78 puts(" -a, --actions ACTIONS run non-interactively");
79 puts("");
80 puts("Actions:");
81 for (unsigned int i = 0; commands[i].meta != EOL; i++) {
82 if (commands[i].meta == HEADER
83 || commands[i].meta & NOOPT)
84 continue;
85 printf(" %c %s\n", commands[i].cmd, commands[i].desc);
86 }
87 puts("");
88 exit(1);
89 }
90
render_access_mask(uint32_t mask,avtab_key_t * key,policydb_t * p,FILE * fp)91 static int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
92 FILE * fp)
93 {
94 char *perm = sepol_av_to_string(p, key->target_class, mask);
95 fprintf(fp, "{");
96 fprintf(fp, "%s ", perm ?: "<format-failure>");
97 fprintf(fp, "}");
98 free(perm);
99 return 0;
100 }
101
render_type(uint32_t type,policydb_t * p,FILE * fp)102 static int render_type(uint32_t type, policydb_t * p, FILE * fp)
103 {
104 fprintf(fp, "%s", p->p_type_val_to_name[type - 1]);
105 return 0;
106 }
107
render_key(avtab_key_t * key,policydb_t * p,FILE * fp)108 static int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
109 {
110 char *stype, *ttype, *tclass;
111 stype = p->p_type_val_to_name[key->source_type - 1];
112 ttype = p->p_type_val_to_name[key->target_type - 1];
113 tclass = p->p_class_val_to_name[key->target_class - 1];
114 if (stype && ttype)
115 fprintf(fp, "%s %s : %s ", stype, ttype, tclass);
116 else if (stype)
117 fprintf(fp, "%s %u : %s ", stype, key->target_type, tclass);
118 else if (ttype)
119 fprintf(fp, "%u %s : %s ", key->source_type, ttype, tclass);
120 else
121 fprintf(fp, "%u %u : %s ", key->source_type, key->target_type,
122 tclass);
123 return 0;
124 }
125
126 /* 'what' values for this function */
127 #define RENDER_UNCONDITIONAL 0x0001 /* render all regardless of enabled state */
128 #define RENDER_ENABLED 0x0002
129 #define RENDER_DISABLED 0x0004
130 #define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED)
131
render_av_rule(avtab_key_t * key,avtab_datum_t * datum,uint32_t what,policydb_t * p,FILE * fp)132 static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
133 policydb_t * p, FILE * fp)
134 {
135 if (!(what & RENDER_UNCONDITIONAL)) {
136 if (what != RENDER_CONDITIONAL && (((what & RENDER_ENABLED)
137 && !(key->
138 specified &
139 AVTAB_ENABLED))
140 || ((what & RENDER_DISABLED)
141 && (key->
142 specified &
143 AVTAB_ENABLED)))) {
144 return 0; /* doesn't match selection criteria */
145 }
146 }
147
148 if (!(what & RENDER_UNCONDITIONAL)) {
149 if (key->specified & AVTAB_ENABLED)
150 fprintf(fp, "[enabled] ");
151 else if (!(key->specified & AVTAB_ENABLED))
152 fprintf(fp, "[disabled] ");
153 }
154
155 if (key->specified & AVTAB_AV) {
156 if (key->specified & AVTAB_ALLOWED) {
157 fprintf(fp, "allow ");
158 render_key(key, p, fp);
159 render_access_mask(datum->data, key, p, fp);
160 fprintf(fp, ";\n");
161 }
162 if (key->specified & AVTAB_AUDITALLOW) {
163 fprintf(fp, "auditallow ");
164 render_key(key, p, fp);
165 render_access_mask(datum->data, key, p, fp);
166 fprintf(fp, ";\n");
167 }
168 if (key->specified & AVTAB_AUDITDENY) {
169 fprintf(fp, "dontaudit ");
170 render_key(key, p, fp);
171 /* We inverse the mask for dontaudit since the mask is internally stored
172 * as a auditdeny mask */
173 render_access_mask(~datum->data, key, p, fp);
174 fprintf(fp, ";\n");
175 }
176 } else if (key->specified & AVTAB_TYPE) {
177 if (key->specified & AVTAB_TRANSITION) {
178 fprintf(fp, "type_transition ");
179 render_key(key, p, fp);
180 render_type(datum->data, p, fp);
181 fprintf(fp, ";\n");
182 }
183 if (key->specified & AVTAB_MEMBER) {
184 fprintf(fp, "type_member ");
185 render_key(key, p, fp);
186 render_type(datum->data, p, fp);
187 fprintf(fp, ";\n");
188 }
189 if (key->specified & AVTAB_CHANGE) {
190 fprintf(fp, "type_change ");
191 render_key(key, p, fp);
192 render_type(datum->data, p, fp);
193 fprintf(fp, ";\n");
194 }
195 } else if (key->specified & AVTAB_XPERMS) {
196 char *perms;
197
198 if (key->specified & AVTAB_XPERMS_ALLOWED)
199 fprintf(fp, "allowxperm ");
200 else if (key->specified & AVTAB_XPERMS_AUDITALLOW)
201 fprintf(fp, "auditallowxperm ");
202 else if (key->specified & AVTAB_XPERMS_DONTAUDIT)
203 fprintf(fp, "dontauditxperm ");
204 render_key(key, p, fp);
205 perms = sepol_extended_perms_to_string(datum->xperms);
206 if (!perms) {
207 fprintf(fp, " ERROR: failed to format xperms\n");
208 return -1;
209 }
210 fprintf(fp, "%s;\n", perms);
211 free(perms);
212 } else {
213 fprintf(fp, " ERROR: no valid rule type specified\n");
214 return -1;
215 }
216 return 0;
217 }
218
display_avtab(avtab_t * a,uint32_t what,policydb_t * p,FILE * fp)219 static int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
220 {
221 unsigned int i;
222 avtab_ptr_t cur;
223
224 /* hmm...should have used avtab_map. */
225 for (i = 0; i < a->nslot; i++) {
226 for (cur = a->htable[i]; cur; cur = cur->next) {
227 render_av_rule(&cur->key, &cur->datum, what, p, fp);
228 }
229 }
230 fprintf(fp, "\n");
231 return 0;
232 }
233
display_expr(policydb_t * p,cond_expr_t * exp,FILE * fp)234 static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
235 {
236
237 cond_expr_t *cur;
238 for (cur = exp; cur != NULL; cur = cur->next) {
239 switch (cur->expr_type) {
240 case COND_BOOL:
241 fprintf(fp, "%s ",
242 p->p_bool_val_to_name[cur->boolean - 1]);
243 break;
244 case COND_NOT:
245 fprintf(fp, "! ");
246 break;
247 case COND_OR:
248 fprintf(fp, "|| ");
249 break;
250 case COND_AND:
251 fprintf(fp, "&& ");
252 break;
253 case COND_XOR:
254 fprintf(fp, "^ ");
255 break;
256 case COND_EQ:
257 fprintf(fp, "== ");
258 break;
259 case COND_NEQ:
260 fprintf(fp, "!= ");
261 break;
262 default:
263 fprintf(fp, "error!");
264 break;
265 }
266 }
267 }
268
display_cond_expressions(policydb_t * p,FILE * fp)269 static int display_cond_expressions(policydb_t * p, FILE * fp)
270 {
271 cond_node_t *cur;
272 cond_av_list_t *av_cur;
273
274 for (cur = p->cond_list; cur != NULL; cur = cur->next) {
275 fprintf(fp, "expression: ");
276 display_expr(p, cur->expr, fp);
277 fprintf(fp, "current state: %d\n", cur->cur_state);
278 fprintf(fp, "True list:\n");
279 for (av_cur = cur->true_list; av_cur != NULL; av_cur = av_cur->next) {
280 fprintf(fp, "\t");
281 render_av_rule(&av_cur->node->key, &av_cur->node->datum,
282 RENDER_CONDITIONAL, p, fp);
283 }
284 fprintf(fp, "False list:\n");
285 for (av_cur = cur->false_list; av_cur != NULL; av_cur = av_cur->next) {
286 fprintf(fp, "\t");
287 render_av_rule(&av_cur->node->key, &av_cur->node->datum,
288 RENDER_CONDITIONAL, p, fp);
289 }
290 }
291 return 0;
292 }
293
display_handle_unknown(policydb_t * p,FILE * out_fp)294 static int display_handle_unknown(policydb_t * p, FILE * out_fp)
295 {
296 if (p->handle_unknown == ALLOW_UNKNOWN)
297 fprintf(out_fp, "Allow unknown classes and permissions\n");
298 else if (p->handle_unknown == DENY_UNKNOWN)
299 fprintf(out_fp, "Deny unknown classes and permissions\n");
300 else if (p->handle_unknown == REJECT_UNKNOWN)
301 fprintf(out_fp, "Reject unknown classes and permissions\n");
302 else
303 fprintf(out_fp, "<INVALID SETTING!>\n");
304 return 0;
305 }
306
change_bool(char * name,int state,policydb_t * p,FILE * fp)307 static int change_bool(char *name, int state, policydb_t * p, FILE * fp)
308 {
309 cond_bool_datum_t *boolean;
310
311 boolean = hashtab_search(p->p_bools.table, name);
312 if (boolean == NULL) {
313 fprintf(fp, "Could not find bool %s\n", name);
314 return -1;
315 }
316 boolean->state = state;
317 evaluate_conds(p);
318 return 0;
319 }
320
display_booleans(policydb_t * p,FILE * fp)321 static int display_booleans(policydb_t * p, FILE *fp)
322 {
323 uint32_t i;
324
325 fprintf(fp, "booleans (#%u):\n", p->p_bools.table->nel);
326 for (i = 0; i < p->p_bools.nprim; i++) {
327 fprintf(fp, "\t%s : %d\n", p->p_bool_val_to_name[i],
328 p->bool_val_to_struct[i]->state);
329 }
330 return 0;
331 }
332
display_policycaps(policydb_t * p,FILE * fp)333 static void display_policycaps(policydb_t * p, FILE * fp)
334 {
335 ebitmap_node_t *node;
336 const char *capname;
337 char buf[64];
338 unsigned int i;
339
340 fprintf(fp, "policy capabilities:\n");
341 ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
342 capname = sepol_polcap_getname(i);
343 if (capname == NULL) {
344 snprintf(buf, sizeof(buf), "unknown (%u)", i);
345 capname = buf;
346 }
347 fprintf(fp, "\t%s\n", capname);
348 }
349 }
350
display_classes(policydb_t * p,FILE * fp)351 static int display_classes(policydb_t * p, FILE *fp)
352 {
353 uint32_t i;
354
355 fprintf(fp, "classes (#%u):\n", p->p_classes.table->nel);
356 for (i = 0; i < p->p_classes.nprim; i++) {
357 if (!p->p_class_val_to_name[i])
358 continue;
359
360 fprintf(fp, "\t%s\n", p->p_class_val_to_name[i]);
361 }
362 return 0;
363 }
364
display_id(policydb_t * p,FILE * fp,uint32_t symbol_type,uint32_t symbol_value,const char * prefix)365 static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type,
366 uint32_t symbol_value, const char *prefix)
367 {
368 const char *id = p->sym_val_to_name[symbol_type][symbol_value];
369 fprintf(fp, " %s%s", prefix, id);
370 }
371
display_permissive(policydb_t * p,FILE * fp)372 static void display_permissive(policydb_t *p, FILE *fp)
373 {
374 ebitmap_node_t *node;
375 unsigned int i;
376
377 fprintf(fp, "permissive sids (#%u):\n", ebitmap_cardinality(&p->permissive_map));
378 ebitmap_for_each_positive_bit(&p->permissive_map, node, i) {
379 fprintf(fp, "\t");
380 display_id(p, fp, SYM_TYPES, i - 1, "");
381 fprintf(fp, "\n");
382 }
383 }
384
display_users(policydb_t * p,FILE * fp)385 static int display_users(policydb_t * p, FILE *fp)
386 {
387 uint32_t i;
388
389 fprintf(fp, "users (#%u):\n", p->p_users.table->nel);
390 for (i = 0; i < p->p_users.nprim; i++) {
391 if (!p->p_user_val_to_name[i])
392 continue;
393
394 fprintf(fp, "\t%s\n", p->p_user_val_to_name[i]);
395 }
396 return 0;
397 }
398
display_roles(policydb_t * p,FILE * fp)399 static int display_roles(policydb_t * p, FILE *fp)
400 {
401 uint32_t i;
402
403 fprintf(fp, "roles (#%u):\n", p->p_roles.table->nel);
404 for (i = 0; i < p->p_roles.nprim; i++) {
405 if (!p->p_role_val_to_name[i])
406 continue;
407
408 fprintf(fp, "\t%s\n", p->p_role_val_to_name[i]);
409 }
410 return 0;
411 }
412
display_types(policydb_t * p,FILE * fp)413 static int display_types(policydb_t * p, FILE *fp)
414 {
415 uint32_t i;
416
417 fprintf(fp, "types (out of #%u):\n", p->p_types.table->nel);
418 for (i = 0; i < p->p_types.nprim; i++) {
419 if (!p->p_type_val_to_name[i])
420 continue;
421
422 if (p->type_val_to_struct[i]->flavor == TYPE_ATTRIB)
423 continue;
424
425 fprintf(fp, "\t%s\n", p->p_type_val_to_name[i]);
426 }
427 return 0;
428 }
429
display_attributes(policydb_t * p,FILE * fp)430 static int display_attributes(policydb_t * p, FILE *fp)
431 {
432 uint32_t i;
433
434 fprintf(fp, "attributes (out of #%u):\n", p->p_types.table->nel);
435 for (i = 0; i < p->p_types.nprim; i++) {
436 if (!p->p_type_val_to_name[i])
437 continue;
438
439 if (p->type_val_to_struct[i]->flavor != TYPE_ATTRIB)
440 continue;
441
442 fprintf(fp, "\t%s\n", p->p_type_val_to_name[i]);
443 }
444 return 0;
445 }
446
display_role_trans(policydb_t * p,FILE * fp)447 static void display_role_trans(policydb_t *p, FILE *fp)
448 {
449 role_trans_t *rt;
450
451 fprintf(fp, "role_trans rules:\n");
452 for (rt = p->role_tr; rt; rt = rt->next) {
453 display_id(p, fp, SYM_ROLES, rt->role - 1, "");
454 display_id(p, fp, SYM_TYPES, rt->type - 1, "");
455 display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":");
456 display_id(p, fp, SYM_ROLES, rt->new_role - 1, "");
457 fprintf(fp, "\n");
458 }
459 }
460
461 struct filenametr_display_args {
462 policydb_t *p;
463 FILE *fp;
464 };
465
filenametr_display(hashtab_key_t key,hashtab_datum_t datum,void * ptr)466 static int filenametr_display(hashtab_key_t key,
467 hashtab_datum_t datum,
468 void *ptr)
469 {
470 struct filename_trans_key *ft = (struct filename_trans_key *)key;
471 struct filename_trans_datum *ftdatum = datum;
472 struct filenametr_display_args *args = ptr;
473 policydb_t *p = args->p;
474 FILE *fp = args->fp;
475 ebitmap_node_t *node;
476 uint32_t bit;
477
478 do {
479 ebitmap_for_each_positive_bit(&ftdatum->stypes, node, bit) {
480 display_id(p, fp, SYM_TYPES, bit, "");
481 display_id(p, fp, SYM_TYPES, ft->ttype - 1, "");
482 display_id(p, fp, SYM_CLASSES, ft->tclass - 1, ":");
483 display_id(p, fp, SYM_TYPES, ftdatum->otype - 1, "");
484 fprintf(fp, " %s\n", ft->name);
485 }
486 ftdatum = ftdatum->next;
487 } while (ftdatum);
488
489 return 0;
490 }
491
492
display_filename_trans(policydb_t * p,FILE * fp)493 static void display_filename_trans(policydb_t *p, FILE *fp)
494 {
495 struct filenametr_display_args args;
496
497 fprintf(fp, "filename_trans rules:\n");
498 args.p = p;
499 args.fp = fp;
500 hashtab_map(p->filename_trans, filenametr_display, &args);
501 }
502
menu(void)503 static int menu(void)
504 {
505 unsigned int i;
506 for (i = 0; commands[i].meta != EOL; i++) {
507 if (commands[i].meta == HEADER)
508 printf("%s\n", commands[i].desc);
509 else if (commands[i].meta & CMD)
510 printf("%c) %s\n", commands[i].cmd, commands[i].desc);
511 }
512 return 0;
513 }
514
main(int argc,char ** argv)515 int main(int argc, char **argv)
516 {
517 char *ops = NULL;
518 char *bpol;
519 FILE *out_fp = stdout;
520 char ans[81], OutfileName[121];
521 int fd, ret;
522 struct stat sb;
523 void *map;
524 char *name;
525 int state;
526 struct policy_file pf;
527 policydb_t policydb;
528
529 if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
530 usage(argv[0]);
531
532 bpol = argv[1];
533 if (strcmp (bpol, "--actions") == 0 || strcmp (bpol, "-a") == 0) {
534 if (argc != 4) {
535 fprintf(stderr, "%s: unexpected number of arguments\n", argv[0]);
536 usage(argv[0]);
537 }
538 ops = argv[2];
539 bpol = argv[3];
540 } else if (bpol[0] == '-') {
541 fprintf(stderr, "%s: unknown option: %s\n", argv[0], bpol);
542 usage(argv[0]);
543 }
544
545 fd = open(bpol, O_RDONLY);
546 if (fd < 0) {
547 fprintf(stderr, "Can't open '%s': %s\n",
548 bpol, strerror(errno));
549 exit(1);
550 }
551 if (fstat(fd, &sb) < 0) {
552 fprintf(stderr, "Can't stat '%s': %s\n",
553 bpol, strerror(errno));
554 exit(1);
555 }
556 map =
557 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
558 if (map == MAP_FAILED) {
559 fprintf(stderr, "Can't map '%s': %s\n",
560 bpol, strerror(errno));
561 exit(1);
562 }
563
564 /* read the binary policy */
565 if (!ops)
566 fprintf(out_fp, "Reading policy...\n");
567 policy_file_init(&pf);
568 pf.type = PF_USE_MEMORY;
569 pf.data = map;
570 pf.len = sb.st_size;
571 if (policydb_init(&policydb)) {
572 fprintf(stderr, "%s: Out of memory!\n", argv[0]);
573 exit(1);
574 }
575 ret = policydb_read(&policydb, &pf, ops? 0: 1);
576 if (ret) {
577 fprintf(stderr,
578 "%s: error(s) encountered while parsing configuration\n",
579 argv[0]);
580 exit(1);
581 }
582
583 if (!ops)
584 fprintf(stdout, "binary policy file loaded\n\n");
585 close(fd);
586
587 if (!ops)
588 menu();
589 for (;;) {
590 if (ops) {
591 puts("");
592 ans[0] = *ops? *ops++: 'q';
593 ans[1] = '\0';
594 } else {
595 printf("\nCommand (\'m\' for menu): ");
596 if (fgets(ans, sizeof(ans), stdin) == NULL) {
597 if (feof(stdin))
598 break;
599 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
600 strerror(errno));
601 continue;
602 }
603 }
604 switch (ans[0]) {
605
606 case '1':
607 display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL,
608 &policydb, out_fp);
609 break;
610 case '2':
611 display_avtab(&policydb.te_cond_avtab,
612 RENDER_CONDITIONAL, &policydb, out_fp);
613 break;
614 case '3':
615 display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED,
616 &policydb, out_fp);
617 break;
618 case '4':
619 display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED,
620 &policydb, out_fp);
621 break;
622 case '5':
623 display_booleans(&policydb, out_fp);
624 break;
625 case '6':
626 display_cond_expressions(&policydb, out_fp);
627 break;
628 case '7':
629 printf("name? ");
630 if (fgets(ans, sizeof(ans), stdin) == NULL) {
631 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
632 strerror(errno));
633 break;
634 }
635 ans[strlen(ans) - 1] = 0;
636
637 name = strdup(ans);
638 if (name == NULL) {
639 fprintf(stderr, "couldn't strdup string.\n");
640 break;
641 }
642
643 printf("state? ");
644 if (fgets(ans, sizeof(ans), stdin) == NULL) {
645 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
646 strerror(errno));
647 break;
648 }
649 ans[strlen(ans) - 1] = 0;
650
651 if (atoi(ans))
652 state = 1;
653 else
654 state = 0;
655
656 change_bool(name, state, &policydb, out_fp);
657 free(name);
658 break;
659 case '8':
660 display_role_trans(&policydb, out_fp);
661 break;
662 case 'a':
663 display_attributes(&policydb, out_fp);
664 break;
665 case 'c':
666 display_policycaps(&policydb, out_fp);
667 break;
668 case 'C':
669 display_classes(&policydb, out_fp);
670 break;
671 case 'p':
672 display_permissive(&policydb, out_fp);
673 break;
674 case 'r':
675 display_roles(&policydb, out_fp);
676 break;
677 case 't':
678 display_types(&policydb, out_fp);
679 break;
680 case 'u':
681 display_users(&policydb, out_fp);
682 break;
683 case 'U':
684 display_handle_unknown(&policydb, out_fp);
685 break;
686 case 'f':
687 printf
688 ("\nFilename for output (<CR> for screen output): ");
689 if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
690 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
691 strerror(errno));
692 break;
693 }
694 OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */
695 if (strlen(OutfileName) == 0)
696 out_fp = stdout;
697 else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
698 fprintf(stderr, "Cannot open output file %s\n",
699 OutfileName);
700 out_fp = stdout;
701 }
702 if (out_fp != stdout)
703 printf("\nOutput to file: %s\n", OutfileName);
704 break;
705 case 'F':
706 display_filename_trans(&policydb, out_fp);
707 break;
708 case 'q':
709 policydb_destroy(&policydb);
710 exit(0);
711 break;
712 case 'm':
713 menu();
714 break;
715 default:
716 printf("\nInvalid choice\n");
717 menu();
718 break;
719
720 }
721 }
722 }
723
724 /* FLASK */
725