mirror of
https://github.com/SELinuxProject/selinux
synced 2025-01-05 04:59:42 +00:00
1174483d29
Currently, filename type transitions support only exact name matching. However, in practice, the names contain variable parts. This leads to many duplicated rules in the policy that differ only in the part of the name, or it is even impossible to cover all possible combinations. This patch extends the filename type transitions structures to include new types of filename transitions - prefix and suffix filename transitions. It also implements the reading and writing of those rules in the kernel binary policy format together with increasing its version. Reviewed-by: Ondrej Mosnacek <omosnace@redhat.com> Signed-off-by: Juraj Marcin <juraj@jurajmarcin.com> Acked-by: James Carter <jwcart2@gmail.com>
721 lines
17 KiB
C
721 lines
17 KiB
C
/* Authors: Frank Mayer <mayerf@tresys.com> and Karl MacMillan <kmacmillan@tresys.com>
|
|
*
|
|
* Copyright (C) 2003 Tresys Technology, LLC
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation, version 2.
|
|
*/
|
|
|
|
/*
|
|
* displaypol.c
|
|
*
|
|
* Test program to the contents of a binary policy in text
|
|
* form. This program currently only displays the
|
|
* avtab (including conditional avtab) rules.
|
|
*
|
|
* displaypol binary_pol_file
|
|
*/
|
|
|
|
#include <sepol/policydb/policydb.h>
|
|
#include <sepol/policydb/avtab.h>
|
|
#include <sepol/policydb/services.h>
|
|
#include <sepol/policydb/conditional.h>
|
|
#include <sepol/policydb/util.h>
|
|
#include <sepol/policydb/polcaps.h>
|
|
#include <getopt.h>
|
|
#include <assert.h>
|
|
#include <unistd.h>
|
|
#include <stdlib.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <sys/mman.h>
|
|
#include <errno.h>
|
|
#include <stdio.h>
|
|
#include <fcntl.h>
|
|
|
|
static policydb_t policydb;
|
|
|
|
static struct command {
|
|
enum {
|
|
EOL = 0,
|
|
HEADER = 1,
|
|
CMD = 1 << 1,
|
|
NOOPT = 1 << 2,
|
|
} meta;
|
|
char cmd;
|
|
const char *desc;
|
|
} commands[] = {
|
|
{HEADER, 0, "\nSelect a command:"},
|
|
{CMD, '1', "display unconditional AVTAB" },
|
|
{CMD, '2', "display conditional AVTAB (entirely)"},
|
|
{CMD, '3', "display conditional AVTAB (only ENABLED rules)"},
|
|
{CMD, '4', "display conditional AVTAB (only DISABLED rules)"},
|
|
{CMD, '5', "display conditional bools"},
|
|
{CMD, '6', "display conditional expressions"},
|
|
{CMD|NOOPT, '7', "change a boolean value"},
|
|
{CMD, '8', "display role transitions"},
|
|
{HEADER, 0, ""},
|
|
{CMD, 'c', "display policy capabilities"},
|
|
{CMD, 'b', "display booleans"},
|
|
{CMD, 'C', "display classes"},
|
|
{CMD, 'r', "display roles"},
|
|
{CMD, 't', "display types"},
|
|
{CMD, 'a', "display type attributes"},
|
|
{CMD, 'p', "display the list of permissive types"},
|
|
{CMD, 'u', "display unknown handling setting"},
|
|
{HEADER, 0, ""},
|
|
{CMD|NOOPT, 'f', "set output file"},
|
|
{CMD|NOOPT, 'm', "display menu"},
|
|
{CMD|NOOPT, 'q', "quit"},
|
|
{EOL, 0, "" },
|
|
};
|
|
|
|
static __attribute__((__noreturn__)) void usage(const char *progname)
|
|
{
|
|
puts("Usage:");
|
|
printf(" %s [OPTIONS] binary_pol_file\n\n", progname);
|
|
puts("Options:");
|
|
puts(" -h, --help print this help message");
|
|
puts(" -a, --actions ACTIONS run non-interactively");
|
|
puts("");
|
|
puts("Actions:");
|
|
for (unsigned int i = 0; commands[i].meta != EOL; i++) {
|
|
if (commands[i].meta == HEADER
|
|
|| commands[i].meta & NOOPT)
|
|
continue;
|
|
printf(" %c %s\n", commands[i].cmd, commands[i].desc);
|
|
}
|
|
puts("");
|
|
exit(1);
|
|
}
|
|
|
|
static int render_access_mask(uint32_t mask, avtab_key_t * key, policydb_t * p,
|
|
FILE * fp)
|
|
{
|
|
char *perm;
|
|
fprintf(fp, "{");
|
|
perm = sepol_av_to_string(p, key->target_class, mask);
|
|
if (perm)
|
|
fprintf(fp, "%s ", perm);
|
|
fprintf(fp, "}");
|
|
return 0;
|
|
}
|
|
|
|
static int render_type(uint32_t type, policydb_t * p, FILE * fp)
|
|
{
|
|
fprintf(fp, "%s", p->p_type_val_to_name[type - 1]);
|
|
return 0;
|
|
}
|
|
|
|
static int render_key(avtab_key_t * key, policydb_t * p, FILE * fp)
|
|
{
|
|
char *stype, *ttype, *tclass;
|
|
stype = p->p_type_val_to_name[key->source_type - 1];
|
|
ttype = p->p_type_val_to_name[key->target_type - 1];
|
|
tclass = p->p_class_val_to_name[key->target_class - 1];
|
|
if (stype && ttype)
|
|
fprintf(fp, "%s %s : %s ", stype, ttype, tclass);
|
|
else if (stype)
|
|
fprintf(fp, "%s %u : %s ", stype, key->target_type, tclass);
|
|
else if (ttype)
|
|
fprintf(fp, "%u %s : %s ", key->source_type, ttype, tclass);
|
|
else
|
|
fprintf(fp, "%u %u : %s ", key->source_type, key->target_type,
|
|
tclass);
|
|
return 0;
|
|
}
|
|
|
|
typedef struct {
|
|
avtab_key_t *key;
|
|
policydb_t *p;
|
|
FILE *fp;
|
|
name_trans_match_t match;
|
|
} render_name_trans_args_t;
|
|
|
|
static int render_name_trans_helper(hashtab_key_t k, hashtab_datum_t d, void *a)
|
|
{
|
|
char *name = k;
|
|
uint32_t *otype = d;
|
|
render_name_trans_args_t *args = a;
|
|
|
|
fprintf(args->fp, "type_transition ");
|
|
render_key(args->key, args->p, args->fp);
|
|
render_type(*otype, args->p, args->fp);
|
|
const char *match_str = "";
|
|
switch (args->match) {
|
|
case NAME_TRANS_MATCH_EXACT:
|
|
match_str = "";
|
|
break;
|
|
case NAME_TRANS_MATCH_PREFIX:
|
|
match_str = " PREFIX";
|
|
break;
|
|
case NAME_TRANS_MATCH_SUFFIX:
|
|
match_str = " SUFFIX";
|
|
break;
|
|
default:
|
|
fprintf(args->fp, " ERROR: no valid name match type specified\n");
|
|
return -1;
|
|
}
|
|
fprintf(args->fp, " \"%s\"%s;\n", name, match_str);
|
|
|
|
return 0;
|
|
}
|
|
|
|
/* 'what' values for this function */
|
|
#define RENDER_UNCONDITIONAL 0x0001 /* render all regardless of enabled state */
|
|
#define RENDER_ENABLED 0x0002
|
|
#define RENDER_DISABLED 0x0004
|
|
#define RENDER_CONDITIONAL (RENDER_ENABLED|RENDER_DISABLED)
|
|
|
|
static int render_av_rule(avtab_key_t * key, avtab_datum_t * datum, uint32_t what,
|
|
policydb_t * p, FILE * fp)
|
|
{
|
|
if (!(what & RENDER_UNCONDITIONAL)) {
|
|
if (what != RENDER_CONDITIONAL && (((what & RENDER_ENABLED)
|
|
&& !(key->
|
|
specified &
|
|
AVTAB_ENABLED))
|
|
|| ((what & RENDER_DISABLED)
|
|
&& (key->
|
|
specified &
|
|
AVTAB_ENABLED)))) {
|
|
return 0; /* doesn't match selection criteria */
|
|
}
|
|
}
|
|
|
|
if (!(what & RENDER_UNCONDITIONAL)) {
|
|
if (key->specified & AVTAB_ENABLED)
|
|
fprintf(fp, "[enabled] ");
|
|
else if (!(key->specified & AVTAB_ENABLED))
|
|
fprintf(fp, "[disabled] ");
|
|
}
|
|
|
|
if (key->specified & AVTAB_AV) {
|
|
if (key->specified & AVTAB_ALLOWED) {
|
|
fprintf(fp, "allow ");
|
|
render_key(key, p, fp);
|
|
render_access_mask(datum->data, key, p, fp);
|
|
fprintf(fp, ";\n");
|
|
}
|
|
if (key->specified & AVTAB_AUDITALLOW) {
|
|
fprintf(fp, "auditallow ");
|
|
render_key(key, p, fp);
|
|
render_access_mask(datum->data, key, p, fp);
|
|
fprintf(fp, ";\n");
|
|
}
|
|
if (key->specified & AVTAB_AUDITDENY) {
|
|
fprintf(fp, "dontaudit ");
|
|
render_key(key, p, fp);
|
|
/* We inverse the mask for dontaudit since the mask is internally stored
|
|
* as a auditdeny mask */
|
|
render_access_mask(~datum->data, key, p, fp);
|
|
fprintf(fp, ";\n");
|
|
}
|
|
} else if (key->specified & AVTAB_TYPE) {
|
|
if (key->specified & AVTAB_TRANSITION) {
|
|
if (datum->trans->otype) {
|
|
fprintf(fp, "type_transition ");
|
|
render_key(key, p, fp);
|
|
render_type(datum->trans->otype, p, fp);
|
|
fprintf(fp, ";\n");
|
|
}
|
|
render_name_trans_args_t args = {
|
|
.key = key,
|
|
.p = p,
|
|
.fp = fp,
|
|
.match = NAME_TRANS_MATCH_EXACT,
|
|
};
|
|
hashtab_map(datum->trans->name_trans.table,
|
|
render_name_trans_helper, &args);
|
|
args.match = NAME_TRANS_MATCH_PREFIX;
|
|
hashtab_map(datum->trans->prefix_trans.table,
|
|
render_name_trans_helper, &args);
|
|
args.match = NAME_TRANS_MATCH_SUFFIX;
|
|
hashtab_map(datum->trans->suffix_trans.table,
|
|
render_name_trans_helper, &args);
|
|
}
|
|
if (key->specified & AVTAB_MEMBER) {
|
|
fprintf(fp, "type_member ");
|
|
render_key(key, p, fp);
|
|
render_type(datum->data, p, fp);
|
|
fprintf(fp, ";\n");
|
|
}
|
|
if (key->specified & AVTAB_CHANGE) {
|
|
fprintf(fp, "type_change ");
|
|
render_key(key, p, fp);
|
|
render_type(datum->data, p, fp);
|
|
fprintf(fp, ";\n");
|
|
}
|
|
} else if (key->specified & AVTAB_XPERMS) {
|
|
if (key->specified & AVTAB_XPERMS_ALLOWED)
|
|
fprintf(fp, "allowxperm ");
|
|
else if (key->specified & AVTAB_XPERMS_AUDITALLOW)
|
|
fprintf(fp, "auditallowxperm ");
|
|
else if (key->specified & AVTAB_XPERMS_DONTAUDIT)
|
|
fprintf(fp, "dontauditxperm ");
|
|
render_key(key, p, fp);
|
|
fprintf(fp, "%s;\n", sepol_extended_perms_to_string(datum->xperms));
|
|
} else {
|
|
fprintf(fp, " ERROR: no valid rule type specified\n");
|
|
return -1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int display_avtab(avtab_t * a, uint32_t what, policydb_t * p, FILE * fp)
|
|
{
|
|
unsigned int i;
|
|
avtab_ptr_t cur;
|
|
|
|
/* hmm...should have used avtab_map. */
|
|
for (i = 0; i < a->nslot; i++) {
|
|
for (cur = a->htable[i]; cur; cur = cur->next) {
|
|
render_av_rule(&cur->key, &cur->datum, what, p, fp);
|
|
}
|
|
}
|
|
fprintf(fp, "\n");
|
|
return 0;
|
|
}
|
|
|
|
static int display_bools(policydb_t * p, FILE * fp)
|
|
{
|
|
unsigned int i;
|
|
|
|
for (i = 0; i < p->p_bools.nprim; i++) {
|
|
fprintf(fp, "%s : %d\n", p->p_bool_val_to_name[i],
|
|
p->bool_val_to_struct[i]->state);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void display_expr(policydb_t * p, cond_expr_t * exp, FILE * fp)
|
|
{
|
|
|
|
cond_expr_t *cur;
|
|
for (cur = exp; cur != NULL; cur = cur->next) {
|
|
switch (cur->expr_type) {
|
|
case COND_BOOL:
|
|
fprintf(fp, "%s ",
|
|
p->p_bool_val_to_name[cur->boolean - 1]);
|
|
break;
|
|
case COND_NOT:
|
|
fprintf(fp, "! ");
|
|
break;
|
|
case COND_OR:
|
|
fprintf(fp, "|| ");
|
|
break;
|
|
case COND_AND:
|
|
fprintf(fp, "&& ");
|
|
break;
|
|
case COND_XOR:
|
|
fprintf(fp, "^ ");
|
|
break;
|
|
case COND_EQ:
|
|
fprintf(fp, "== ");
|
|
break;
|
|
case COND_NEQ:
|
|
fprintf(fp, "!= ");
|
|
break;
|
|
default:
|
|
fprintf(fp, "error!");
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int display_cond_expressions(policydb_t * p, FILE * fp)
|
|
{
|
|
cond_node_t *cur;
|
|
cond_av_list_t *av_cur;
|
|
|
|
for (cur = p->cond_list; cur != NULL; cur = cur->next) {
|
|
fprintf(fp, "expression: ");
|
|
display_expr(p, cur->expr, fp);
|
|
fprintf(fp, "current state: %d\n", cur->cur_state);
|
|
fprintf(fp, "True list:\n");
|
|
for (av_cur = cur->true_list; av_cur != NULL; av_cur = av_cur->next) {
|
|
fprintf(fp, "\t");
|
|
render_av_rule(&av_cur->node->key, &av_cur->node->datum,
|
|
RENDER_CONDITIONAL, p, fp);
|
|
}
|
|
fprintf(fp, "False list:\n");
|
|
for (av_cur = cur->false_list; av_cur != NULL; av_cur = av_cur->next) {
|
|
fprintf(fp, "\t");
|
|
render_av_rule(&av_cur->node->key, &av_cur->node->datum,
|
|
RENDER_CONDITIONAL, p, fp);
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int display_handle_unknown(policydb_t * p, FILE * out_fp)
|
|
{
|
|
if (p->handle_unknown == ALLOW_UNKNOWN)
|
|
fprintf(out_fp, "Allow unknown classes and permissions\n");
|
|
else if (p->handle_unknown == DENY_UNKNOWN)
|
|
fprintf(out_fp, "Deny unknown classes and permissions\n");
|
|
else if (p->handle_unknown == REJECT_UNKNOWN)
|
|
fprintf(out_fp, "Reject unknown classes and permissions\n");
|
|
return 0;
|
|
}
|
|
|
|
static int change_bool(char *name, int state, policydb_t * p, FILE * fp)
|
|
{
|
|
cond_bool_datum_t *boolean;
|
|
|
|
boolean = hashtab_search(p->p_bools.table, name);
|
|
if (boolean == NULL) {
|
|
fprintf(fp, "Could not find bool %s\n", name);
|
|
return -1;
|
|
}
|
|
boolean->state = state;
|
|
evaluate_conds(p);
|
|
return 0;
|
|
}
|
|
|
|
static int display_booleans(policydb_t * p, FILE *fp)
|
|
{
|
|
uint32_t i;
|
|
|
|
fprintf(fp, "booleans:\n");
|
|
for (i = 0; i < p->p_bools.nprim; i++) {
|
|
fprintf(fp, "\t%s : %d\n", p->p_bool_val_to_name[i],
|
|
p->bool_val_to_struct[i]->state);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void display_policycaps(policydb_t * p, FILE * fp)
|
|
{
|
|
ebitmap_node_t *node;
|
|
const char *capname;
|
|
char buf[64];
|
|
unsigned int i;
|
|
|
|
fprintf(fp, "policy capabilities:\n");
|
|
ebitmap_for_each_positive_bit(&p->policycaps, node, i) {
|
|
capname = sepol_polcap_getname(i);
|
|
if (capname == NULL) {
|
|
snprintf(buf, sizeof(buf), "unknown (%u)", i);
|
|
capname = buf;
|
|
}
|
|
fprintf(fp, "\t%s\n", capname);
|
|
}
|
|
}
|
|
|
|
static int display_classes(policydb_t * p, FILE *fp)
|
|
{
|
|
uint32_t i;
|
|
|
|
fprintf(fp, "classes:\n");
|
|
for (i = 0; i < p->p_classes.nprim; i++) {
|
|
if (!p->p_class_val_to_name[i])
|
|
continue;
|
|
|
|
fprintf(fp, "\t%s\n", p->p_class_val_to_name[i]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void display_id(policydb_t *p, FILE *fp, uint32_t symbol_type,
|
|
uint32_t symbol_value, const char *prefix)
|
|
{
|
|
const char *id = p->sym_val_to_name[symbol_type][symbol_value];
|
|
fprintf(fp, " %s%s", prefix, id);
|
|
}
|
|
|
|
static void display_permissive(policydb_t *p, FILE *fp)
|
|
{
|
|
ebitmap_node_t *node;
|
|
unsigned int i;
|
|
|
|
fprintf(fp, "permissive sids:\n");
|
|
ebitmap_for_each_positive_bit(&p->permissive_map, node, i) {
|
|
fprintf(fp, "\t");
|
|
display_id(p, fp, SYM_TYPES, i - 1, "");
|
|
fprintf(fp, "\n");
|
|
}
|
|
}
|
|
|
|
static int display_roles(policydb_t * p, FILE *fp)
|
|
{
|
|
uint32_t i;
|
|
|
|
fprintf(fp, "roles:\n");
|
|
for (i = 0; i < p->p_roles.nprim; i++) {
|
|
if (!p->p_role_val_to_name[i])
|
|
continue;
|
|
|
|
fprintf(fp, "\t%s\n", p->p_role_val_to_name[i]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int display_types(policydb_t * p, FILE *fp)
|
|
{
|
|
uint32_t i;
|
|
|
|
fprintf(fp, "types:\n");
|
|
for (i = 0; i < p->p_types.nprim; i++) {
|
|
if (!p->p_type_val_to_name[i])
|
|
continue;
|
|
|
|
if (p->type_val_to_struct[i]->flavor == TYPE_ATTRIB)
|
|
continue;
|
|
|
|
fprintf(fp, "\t%s\n", p->p_type_val_to_name[i]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int display_attributes(policydb_t * p, FILE *fp)
|
|
{
|
|
uint32_t i;
|
|
|
|
fprintf(fp, "attributes:\n");
|
|
for (i = 0; i < p->p_types.nprim; i++) {
|
|
if (!p->p_type_val_to_name[i])
|
|
continue;
|
|
|
|
if (p->type_val_to_struct[i]->flavor != TYPE_ATTRIB)
|
|
continue;
|
|
|
|
fprintf(fp, "\t%s\n", p->p_type_val_to_name[i]);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static void display_role_trans(policydb_t *p, FILE *fp)
|
|
{
|
|
role_trans_t *rt;
|
|
|
|
fprintf(fp, "role_trans rules:\n");
|
|
for (rt = p->role_tr; rt; rt = rt->next) {
|
|
display_id(p, fp, SYM_ROLES, rt->role - 1, "");
|
|
display_id(p, fp, SYM_TYPES, rt->type - 1, "");
|
|
display_id(p, fp, SYM_CLASSES, rt->tclass - 1, ":");
|
|
display_id(p, fp, SYM_ROLES, rt->new_role - 1, "");
|
|
fprintf(fp, "\n");
|
|
}
|
|
}
|
|
|
|
static int menu(void)
|
|
{
|
|
unsigned int i;
|
|
for (i = 0; commands[i].meta != EOL; i++) {
|
|
if (commands[i].meta == HEADER)
|
|
printf("%s\n", commands[i].desc);
|
|
else if (commands[i].meta & CMD)
|
|
printf("%c) %s\n", commands[i].cmd, commands[i].desc);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char **argv)
|
|
{
|
|
char *ops = NULL;
|
|
char *bpol;
|
|
FILE *out_fp = stdout;
|
|
char ans[81], OutfileName[121];
|
|
int fd, ret;
|
|
struct stat sb;
|
|
void *map;
|
|
char *name;
|
|
int state;
|
|
struct policy_file pf;
|
|
|
|
if (argc < 2 || strcmp(argv[1], "-h") == 0 || strcmp(argv[1], "--help") == 0)
|
|
usage(argv[0]);
|
|
|
|
bpol = argv[1];
|
|
if (strcmp (bpol, "--actions") == 0 || strcmp (bpol, "-a") == 0) {
|
|
if (argc != 4) {
|
|
fprintf(stderr, "%s: unexpected number of arguments\n", argv[0]);
|
|
usage(argv[0]);
|
|
}
|
|
ops = argv[2];
|
|
bpol = argv[3];
|
|
} else if (bpol[0] == '-') {
|
|
fprintf(stderr, "%s: unknown option: %s\n", argv[0], bpol);
|
|
usage(argv[0]);
|
|
}
|
|
|
|
fd = open(bpol, O_RDONLY);
|
|
if (fd < 0) {
|
|
fprintf(stderr, "Can't open '%s': %s\n",
|
|
bpol, strerror(errno));
|
|
exit(1);
|
|
}
|
|
if (fstat(fd, &sb) < 0) {
|
|
fprintf(stderr, "Can't stat '%s': %s\n",
|
|
bpol, strerror(errno));
|
|
exit(1);
|
|
}
|
|
map =
|
|
mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
|
|
if (map == MAP_FAILED) {
|
|
fprintf(stderr, "Can't map '%s': %s\n",
|
|
bpol, strerror(errno));
|
|
exit(1);
|
|
}
|
|
|
|
/* read the binary policy */
|
|
if (!ops)
|
|
fprintf(out_fp, "Reading policy...\n");
|
|
policy_file_init(&pf);
|
|
pf.type = PF_USE_MEMORY;
|
|
pf.data = map;
|
|
pf.len = sb.st_size;
|
|
if (policydb_init(&policydb)) {
|
|
fprintf(stderr, "%s: Out of memory!\n", argv[0]);
|
|
exit(1);
|
|
}
|
|
ret = policydb_read(&policydb, &pf, ops? 0: 1);
|
|
if (ret) {
|
|
fprintf(stderr,
|
|
"%s: error(s) encountered while parsing configuration\n",
|
|
argv[0]);
|
|
exit(1);
|
|
}
|
|
|
|
if (!ops)
|
|
fprintf(stdout, "binary policy file loaded\n\n");
|
|
close(fd);
|
|
|
|
if (!ops)
|
|
menu();
|
|
for (;;) {
|
|
if (ops) {
|
|
puts("");
|
|
ans[0] = *ops? *ops++: 'q';
|
|
ans[1] = '\0';
|
|
} else {
|
|
printf("\nCommand (\'m\' for menu): ");
|
|
if (fgets(ans, sizeof(ans), stdin) == NULL) {
|
|
if (feof(stdin))
|
|
break;
|
|
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
|
|
strerror(errno));
|
|
continue;
|
|
}
|
|
}
|
|
switch (ans[0]) {
|
|
|
|
case '1':
|
|
display_avtab(&policydb.te_avtab, RENDER_UNCONDITIONAL,
|
|
&policydb, out_fp);
|
|
break;
|
|
case '2':
|
|
display_avtab(&policydb.te_cond_avtab,
|
|
RENDER_CONDITIONAL, &policydb, out_fp);
|
|
break;
|
|
case '3':
|
|
display_avtab(&policydb.te_cond_avtab, RENDER_ENABLED,
|
|
&policydb, out_fp);
|
|
break;
|
|
case '4':
|
|
display_avtab(&policydb.te_cond_avtab, RENDER_DISABLED,
|
|
&policydb, out_fp);
|
|
break;
|
|
case '5':
|
|
display_bools(&policydb, out_fp);
|
|
break;
|
|
case '6':
|
|
display_cond_expressions(&policydb, out_fp);
|
|
break;
|
|
case '7':
|
|
printf("name? ");
|
|
if (fgets(ans, sizeof(ans), stdin) == NULL) {
|
|
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
|
|
strerror(errno));
|
|
break;
|
|
}
|
|
ans[strlen(ans) - 1] = 0;
|
|
|
|
name = strdup(ans);
|
|
if (name == NULL) {
|
|
fprintf(stderr, "couldn't strdup string.\n");
|
|
break;
|
|
}
|
|
|
|
printf("state? ");
|
|
if (fgets(ans, sizeof(ans), stdin) == NULL) {
|
|
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
|
|
strerror(errno));
|
|
break;
|
|
}
|
|
ans[strlen(ans) - 1] = 0;
|
|
|
|
if (atoi(ans))
|
|
state = 1;
|
|
else
|
|
state = 0;
|
|
|
|
change_bool(name, state, &policydb, out_fp);
|
|
free(name);
|
|
break;
|
|
case '8':
|
|
display_role_trans(&policydb, out_fp);
|
|
break;
|
|
case 'a':
|
|
display_attributes(&policydb, out_fp);
|
|
break;
|
|
case 'b':
|
|
display_booleans(&policydb, out_fp);
|
|
break;
|
|
case 'c':
|
|
display_policycaps(&policydb, out_fp);
|
|
break;
|
|
case 'C':
|
|
display_classes(&policydb, out_fp);
|
|
break;
|
|
case 'p':
|
|
display_permissive(&policydb, out_fp);
|
|
break;
|
|
case 'r':
|
|
display_roles(&policydb, out_fp);
|
|
break;
|
|
case 't':
|
|
display_types(&policydb, out_fp);
|
|
break;
|
|
case 'u':
|
|
case 'U':
|
|
display_handle_unknown(&policydb, out_fp);
|
|
break;
|
|
case 'f':
|
|
printf
|
|
("\nFilename for output (<CR> for screen output): ");
|
|
if (fgets(OutfileName, sizeof(OutfileName), stdin) == NULL) {
|
|
fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,
|
|
strerror(errno));
|
|
break;
|
|
}
|
|
OutfileName[strlen(OutfileName) - 1] = '\0'; /* fix_string (remove LF) */
|
|
if (strlen(OutfileName) == 0)
|
|
out_fp = stdout;
|
|
else if ((out_fp = fopen(OutfileName, "w")) == NULL) {
|
|
fprintf(stderr, "Cannot open output file %s\n",
|
|
OutfileName);
|
|
out_fp = stdout;
|
|
}
|
|
if (out_fp != stdout)
|
|
printf("\nOutput to file: %s\n", OutfileName);
|
|
break;
|
|
case 'q':
|
|
policydb_destroy(&policydb);
|
|
exit(0);
|
|
break;
|
|
case 'm':
|
|
menu();
|
|
break;
|
|
default:
|
|
printf("\nInvalid choice\n");
|
|
menu();
|
|
break;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
/* FLASK */
|