checkpolicy.c revision ab9cbb1f8ef92f1db9dfac2ca7354acaf01fde83
1 2/* 3 * Author : Stephen Smalley, <sds@epoch.ncsc.mil> 4 */ 5 6/* 7 * Updated: Trusted Computer Solutions, Inc. <dgoeddel@trustedcs.com> 8 * 9 * Support for enhanced MLS infrastructure. 10 * 11 * Updated: Karl MacMillan <kmacmillan@tresys.com> 12 * 13 * Added conditional policy language extensions 14 * 15 * Updated: James Morris <jmorris@intercode.com.au> 16 * 17 * Added IPv6 support. 18 * 19 * Updated: Joshua Brindle <jbrindle@tresys.com> 20 * Karl MacMillan <kmacmillan@tresys.com> 21 * Jason Tang <jtang@tresys.com> 22 * 23 * Policy Module support. 24 * 25 * Copyright (C) 2004-2005 Trusted Computer Solutions, Inc. 26 * Copyright (C) 2003 - 2005 Tresys Technology, LLC 27 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com> 28 * This program is free software; you can redistribute it and/or modify 29 * it under the terms of the GNU General Public License as published by 30 * the Free Software Foundation, version 2. 31 */ 32 33/* FLASK */ 34 35/* 36 * checkpolicy 37 * 38 * Load and check a policy configuration. 39 * 40 * A policy configuration is created in a text format, 41 * and then compiled into a binary format for use by 42 * the security server. By default, checkpolicy reads 43 * the text format. If '-b' is specified, then checkpolicy 44 * reads the binary format instead. 45 * 46 * If '-o output_file' is specified, then checkpolicy 47 * writes the binary format version of the configuration 48 * to the specified output file. 49 * 50 * If '-d' is specified, then checkpolicy permits the user 51 * to interactively test the security server functions with 52 * the loaded policy configuration. 53 * 54 * If '-c' is specified, then the supplied parameter is used to 55 * determine which policy version to use for generating binary 56 * policy. This is for compatibility with older kernels. If any 57 * booleans or conditional rules are thrown away a warning is printed. 58 */ 59 60#include <getopt.h> 61#include <unistd.h> 62#include <stdlib.h> 63#include <sys/types.h> 64#include <sys/stat.h> 65#include <sys/socket.h> 66#include <netinet/in.h> 67#include <arpa/inet.h> 68#include <fcntl.h> 69#include <stdio.h> 70#include <errno.h> 71#include <sys/mman.h> 72 73#ifdef DARWIN 74#include <ctype.h> 75#endif 76 77#include <sepol/policydb/policydb.h> 78#include <sepol/policydb/services.h> 79#include <sepol/policydb/conditional.h> 80#include <sepol/policydb/hierarchy.h> 81#include <sepol/policydb/flask.h> 82#include <sepol/policydb/expand.h> 83#include <sepol/policydb/link.h> 84 85#include "queue.h" 86#include "checkpolicy.h" 87#include "parse_util.h" 88 89extern char *optarg; 90extern int optind; 91 92static policydb_t policydb; 93static sidtab_t sidtab; 94 95extern policydb_t *policydbp; 96extern int mlspol; 97 98static int handle_unknown = SEPOL_DENY_UNKNOWN; 99static char *txtfile = "policy.conf"; 100static char *binfile = "policy"; 101 102unsigned int policyvers = POLICYDB_VERSION_MAX; 103 104void usage(char *progname) 105{ 106 printf 107 ("usage: %s [-b] [-d] [-U handle_unknown (allow,deny,reject)] [-M]" 108 "[-c policyvers (%d-%d)] [-o output_file] [-t target_platform (selinux,xen)]" 109 "[input_file]\n", 110 progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX); 111 exit(1); 112} 113 114#define FGETS(out, size, in) \ 115if (fgets(out,size,in)==NULL) { \ 116 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,\ 117 strerror(errno)); \ 118 exit(1);\ 119} 120static int print_sid(sepol_security_id_t sid, 121 context_struct_t * context 122 __attribute__ ((unused)), void *data 123 __attribute__ ((unused))) 124{ 125 sepol_security_context_t scontext; 126 size_t scontext_len; 127 int rc; 128 129 rc = sepol_sid_to_context(sid, &scontext, &scontext_len); 130 if (rc) 131 printf("sid %d -> error %d\n", sid, rc); 132 else { 133 printf("sid %d -> scontext %s\n", sid, scontext); 134 free(scontext); 135 } 136 return 0; 137} 138 139struct val_to_name { 140 unsigned int val; 141 char *name; 142}; 143 144static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *p) 145{ 146 struct val_to_name *v = p; 147 perm_datum_t *perdatum; 148 149 perdatum = (perm_datum_t *) datum; 150 151 if (v->val == perdatum->s.value) { 152 v->name = key; 153 return 1; 154 } 155 156 return 0; 157} 158 159#ifdef EQUIVTYPES 160static int insert_type_rule(avtab_key_t * k, avtab_datum_t * d, 161 struct avtab_node *type_rules) 162{ 163 struct avtab_node *p, *c, *n; 164 165 for (p = type_rules, c = type_rules->next; c; p = c, c = c->next) { 166 /* 167 * Find the insertion point, keeping the list 168 * ordered by source type, then target type, then 169 * target class. 170 */ 171 if (k->source_type < c->key.source_type) 172 break; 173 if (k->source_type == c->key.source_type && 174 k->target_type < c->key.target_type) 175 break; 176 if (k->source_type == c->key.source_type && 177 k->target_type == c->key.target_type && 178 k->target_class < c->key.target_class) 179 break; 180 } 181 182 /* Insert the rule */ 183 n = malloc(sizeof(struct avtab_node)); 184 if (!n) { 185 fprintf(stderr, "out of memory\n"); 186 exit(1); 187 } 188 189 n->key = *k; 190 n->datum = *d; 191 n->next = p->next; 192 p->next = n; 193 return 0; 194} 195 196static int create_type_rules(avtab_key_t * k, avtab_datum_t * d, void *args) 197{ 198 struct avtab_node *type_rules = args; 199 200 if (d->specified & AVTAB_ALLOWED) { 201 /* 202 * Insert the rule into the lists for both 203 * the source type and the target type. 204 */ 205 if (insert_type_rule(k, d, &type_rules[k->source_type - 1])) 206 return -1; 207 if (insert_type_rule(k, d, &type_rules[k->target_type - 1])) 208 return -1; 209 } 210 211 return 0; 212} 213 214static void free_type_rules(struct avtab_node *l) 215{ 216 struct avtab_node *tmp; 217 218 while (l) { 219 tmp = l; 220 l = l->next; 221 free(tmp); 222 } 223} 224 225static int identify_equiv_types(void) 226{ 227 struct avtab_node *type_rules, *l1, *l2; 228 int i, j; 229 230 /* 231 * Create a list of access vector rules for each type 232 * from the access vector table. 233 */ 234 type_rules = malloc(sizeof(struct avtab_node) * policydb.p_types.nprim); 235 if (!type_rules) { 236 fprintf(stderr, "out of memory\n"); 237 exit(1); 238 } 239 memset(type_rules, 0, 240 sizeof(struct avtab_node) * policydb.p_types.nprim); 241 if (avtab_map(&policydb.te_avtab, create_type_rules, type_rules)) 242 exit(1); 243 244 /* 245 * Compare the type lists and identify equivalent types. 246 */ 247 for (i = 0; i < policydb.p_types.nprim - 1; i++) { 248 if (!type_rules[i].next) 249 continue; 250 for (j = i + 1; j < policydb.p_types.nprim; j++) { 251 for (l1 = type_rules[i].next, l2 = type_rules[j].next; 252 l1 && l2; l1 = l1->next, l2 = l2->next) { 253 if (l2->key.source_type == (j + 1)) { 254 if (l1->key.source_type != (i + 1)) 255 break; 256 } else { 257 if (l1->key.source_type != 258 l2->key.source_type) 259 break; 260 } 261 if (l2->key.target_type == (j + 1)) { 262 if (l1->key.target_type != (i + 1)) 263 break; 264 } else { 265 if (l1->key.target_type != 266 l2->key.target_type) 267 break; 268 } 269 if (l1->key.target_class != l2->key.target_class 270 || l1->datum.allowed != l2->datum.allowed) 271 break; 272 } 273 if (l1 || l2) 274 continue; 275 free_type_rules(type_rules[j].next); 276 type_rules[j].next = NULL; 277 printf("Types %s and %s are equivalent.\n", 278 policydb.p_type_val_to_name[i], 279 policydb.p_type_val_to_name[j]); 280 } 281 free_type_rules(type_rules[i].next); 282 type_rules[i].next = NULL; 283 } 284 285 free(type_rules); 286 return 0; 287} 288#endif 289 290extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av); 291 292int display_bools() 293{ 294 int i; 295 296 for (i = 0; i < policydbp->p_bools.nprim; i++) { 297 printf("%s : %d\n", policydbp->p_bool_val_to_name[i], 298 policydbp->bool_val_to_struct[i]->state); 299 } 300 return 0; 301} 302 303void display_expr(cond_expr_t * exp) 304{ 305 306 cond_expr_t *cur; 307 for (cur = exp; cur != NULL; cur = cur->next) { 308 switch (cur->expr_type) { 309 case COND_BOOL: 310 printf("%s ", 311 policydbp->p_bool_val_to_name[cur->bool - 1]); 312 break; 313 case COND_NOT: 314 printf("! "); 315 break; 316 case COND_OR: 317 printf("|| "); 318 break; 319 case COND_AND: 320 printf("&& "); 321 break; 322 case COND_XOR: 323 printf("^ "); 324 break; 325 case COND_EQ: 326 printf("== "); 327 break; 328 case COND_NEQ: 329 printf("!= "); 330 break; 331 default: 332 printf("error!"); 333 break; 334 } 335 } 336} 337 338int display_cond_expressions() 339{ 340 cond_node_t *cur; 341 342 for (cur = policydbp->cond_list; cur != NULL; cur = cur->next) { 343 printf("expression: "); 344 display_expr(cur->expr); 345 printf("current state: %d\n", cur->cur_state); 346 } 347 return 0; 348} 349 350int change_bool(char *name, int state) 351{ 352 cond_bool_datum_t *bool; 353 354 bool = hashtab_search(policydbp->p_bools.table, name); 355 if (bool == NULL) { 356 printf("Could not find bool %s\n", name); 357 return -1; 358 } 359 bool->state = state; 360 evaluate_conds(policydbp); 361 return 0; 362} 363 364static int check_level(hashtab_key_t key, hashtab_datum_t datum, void *arg) 365{ 366 level_datum_t *levdatum = (level_datum_t *) datum; 367 368 if (!levdatum->isalias && !levdatum->defined) { 369 fprintf(stderr, 370 "Error: sensitivity %s was not used in a level definition!\n", 371 key); 372 return -1; 373 } 374 return 0; 375} 376 377int main(int argc, char **argv) 378{ 379 sepol_security_class_t tclass; 380 sepol_security_id_t ssid, tsid, *sids, oldsid, newsid, tasksid; 381 sepol_security_context_t scontext; 382 struct sepol_av_decision avd; 383 class_datum_t *cladatum; 384 char ans[80 + 1], *file = txtfile, *outfile = NULL, *path, *fstype; 385 size_t scontext_len, pathlen; 386 unsigned int i; 387 unsigned int protocol, port; 388 unsigned int binary = 0, debug = 0; 389 struct val_to_name v; 390 int ret, ch, fd, target = SEPOL_TARGET_SELINUX; 391 unsigned int nel, uret; 392 struct stat sb; 393 void *map; 394 FILE *outfp = NULL; 395 char *name; 396 int state; 397 int show_version = 0; 398 char *reason_buf = NULL; 399 unsigned int reason; 400 int flags; 401 struct policy_file pf; 402 struct option long_options[] = { 403 {"output", required_argument, NULL, 'o'}, 404 {"target", required_argument, NULL, 't'}, 405 {"binary", no_argument, NULL, 'b'}, 406 {"debug", no_argument, NULL, 'd'}, 407 {"version", no_argument, NULL, 'V'}, 408 {"handle-unknown", required_argument, NULL, 'U'}, 409 {"mls", no_argument, NULL, 'M'}, 410 {"help", no_argument, NULL, 'h'}, 411 {NULL, 0, NULL, 0} 412 }; 413 414 while ((ch = getopt_long(argc, argv, "o:t:dbU:MVc:h", long_options, NULL)) != -1) { 415 switch (ch) { 416 case 'o': 417 outfile = optarg; 418 break; 419 case 't': 420 if (!strcasecmp(optarg, "Xen")) 421 target = SEPOL_TARGET_XEN; 422 else if (!strcasecmp(optarg, "SELinux")) 423 target = SEPOL_TARGET_SELINUX; 424 else{ 425 fprintf(stderr, "%s: Unknown target platform:" 426 "%s\n", argv[0], optarg); 427 exit(1); 428 } 429 break; 430 case 'b': 431 binary = 1; 432 file = binfile; 433 break; 434 case 'd': 435 debug = 1; 436 break; 437 case 'V': 438 show_version = 1; 439 break; 440 case 'U': 441 if (!strcasecmp(optarg, "deny")) { 442 handle_unknown = DENY_UNKNOWN; 443 break; 444 } 445 if (!strcasecmp(optarg, "allow")) { 446 handle_unknown = ALLOW_UNKNOWN; 447 break; 448 } 449 if (!strcasecmp(optarg, "reject")) { 450 handle_unknown = REJECT_UNKNOWN; 451 break; 452 } 453 usage(argv[0]); 454 case 'M': 455 mlspol = 1; 456 break; 457 case 'c':{ 458 long int n = strtol(optarg, NULL, 10); 459 if (errno) { 460 fprintf(stderr, 461 "Invalid policyvers specified: %s\n", 462 optarg); 463 usage(argv[0]); 464 exit(1); 465 } 466 if (n < POLICYDB_VERSION_MIN 467 || n > POLICYDB_VERSION_MAX) { 468 fprintf(stderr, 469 "policyvers value %ld not in range %d-%d\n", 470 n, POLICYDB_VERSION_MIN, 471 POLICYDB_VERSION_MAX); 472 usage(argv[0]); 473 exit(1); 474 } 475 if (policyvers != n) 476 policyvers = n; 477 break; 478 } 479 case 'h': 480 default: 481 usage(argv[0]); 482 } 483 } 484 485 if (show_version) { 486 printf("%d (compatibility range %d-%d)\n", policyvers, 487 POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN); 488 exit(0); 489 } 490 491 if (optind != argc) { 492 file = argv[optind++]; 493 if (optind != argc) 494 usage(argv[0]); 495 } 496 printf("%s: loading policy configuration from %s\n", argv[0], file); 497 498 /* Set policydb and sidtab used by libsepol service functions 499 to my structures, so that I can directly populate and 500 manipulate them. */ 501 sepol_set_policydb(&policydb); 502 sepol_set_sidtab(&sidtab); 503 504 if (binary) { 505 fd = open(file, O_RDONLY); 506 if (fd < 0) { 507 fprintf(stderr, "Can't open '%s': %s\n", 508 file, strerror(errno)); 509 exit(1); 510 } 511 if (fstat(fd, &sb) < 0) { 512 fprintf(stderr, "Can't stat '%s': %s\n", 513 file, strerror(errno)); 514 exit(1); 515 } 516 map = 517 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, 518 fd, 0); 519 if (map == MAP_FAILED) { 520 fprintf(stderr, "Can't map '%s': %s\n", 521 file, strerror(errno)); 522 exit(1); 523 } 524 policy_file_init(&pf); 525 pf.type = PF_USE_MEMORY; 526 pf.data = map; 527 pf.len = sb.st_size; 528 if (policydb_init(&policydb)) { 529 fprintf(stderr, "%s: policydb_init: Out of memory!\n", 530 argv[0]); 531 exit(1); 532 } 533 ret = policydb_read(&policydb, &pf, 1); 534 if (ret) { 535 fprintf(stderr, 536 "%s: error(s) encountered while parsing configuration\n", 537 argv[0]); 538 exit(1); 539 } 540 policydbp = &policydb; 541 542 /* Check Policy Consistency */ 543 if (policydbp->mls) { 544 if (!mlspol) { 545 fprintf(stderr, "%s: MLS policy, but non-MLS" 546 " is specified\n", argv[0]); 547 exit(1); 548 } 549 } else { 550 if (mlspol) { 551 fprintf(stderr, "%s: non-MLS policy, but MLS" 552 " is specified\n", argv[0]); 553 exit(1); 554 } 555 } 556 } else { 557 policydb_t parse_policy; 558 559 if (policydb_init(&parse_policy)) 560 exit(1); 561 /* We build this as a base policy first since that is all the parser understands */ 562 parse_policy.policy_type = POLICY_BASE; 563 policydb_set_target_platform(&parse_policy, target); 564 565 /* Let sepol know if we are dealing with MLS support */ 566 parse_policy.mls = mlspol; 567 parse_policy.handle_unknown = handle_unknown; 568 569 policydbp = &parse_policy; 570 571 if (read_source_policy(policydbp, file, "checkpolicy") < 0) 572 exit(1); 573 574 if (hashtab_map(policydbp->p_levels.table, check_level, NULL)) 575 exit(1); 576 577 if (policydb_init(&policydb)) { 578 fprintf(stderr, "%s: policydb_init failed\n", argv[0]); 579 exit(1); 580 } 581 582 /* Linking takes care of optional avrule blocks */ 583 if (link_modules(NULL, &parse_policy, NULL, 0, 0)) { 584 fprintf(stderr, "Error while resolving optionals\n"); 585 exit(1); 586 } 587 588 if (expand_module(NULL, &parse_policy, &policydb, 0, 1)) { 589 fprintf(stderr, "Error while expanding policy\n"); 590 exit(1); 591 } 592 policydb_destroy(&parse_policy); 593 policydbp = &policydb; 594 } 595 596 if (policydb_load_isids(&policydb, &sidtab)) 597 exit(1); 598 599 printf("%s: policy configuration loaded\n", argv[0]); 600 601 if (outfile) { 602 printf 603 ("%s: writing binary representation (version %d) to %s\n", 604 argv[0], policyvers, outfile); 605 outfp = fopen(outfile, "w"); 606 if (!outfp) { 607 perror(outfile); 608 exit(1); 609 } 610 611 policydb.policy_type = POLICY_KERN; 612 policydb.policyvers = policyvers; 613 614 policy_file_init(&pf); 615 pf.type = PF_USE_STDIO; 616 pf.fp = outfp; 617 ret = policydb_write(&policydb, &pf); 618 if (ret) { 619 fprintf(stderr, "%s: error writing %s\n", 620 argv[0], outfile); 621 exit(1); 622 } 623 fclose(outfp); 624 } 625 if (!debug) { 626 policydb_destroy(&policydb); 627 exit(0); 628 } 629 630 menu: 631 printf("\nSelect an option:\n"); 632 printf("0) Call compute_access_vector\n"); 633 printf("1) Call sid_to_context\n"); 634 printf("2) Call context_to_sid\n"); 635 printf("3) Call transition_sid\n"); 636 printf("4) Call member_sid\n"); 637 printf("5) Call change_sid\n"); 638 printf("6) Call list_sids\n"); 639 printf("7) Call load_policy\n"); 640 printf("8) Call fs_sid\n"); 641 printf("9) Call port_sid\n"); 642 printf("a) Call netif_sid\n"); 643 printf("b) Call node_sid\n"); 644 printf("c) Call fs_use\n"); 645 printf("d) Call genfs_sid\n"); 646 printf("e) Call get_user_sids\n"); 647 printf("f) display conditional bools\n"); 648 printf("g) display conditional expressions\n"); 649 printf("h) change a boolean value\n"); 650 printf("i) display constraint expressions\n"); 651 printf("j) display validatetrans expressions\n"); 652#ifdef EQUIVTYPES 653 printf("z) Show equivalent types\n"); 654#endif 655 printf("m) Show menu again\n"); 656 printf("q) Exit\n"); 657 while (1) { 658 printf("\nChoose: "); 659 FGETS(ans, sizeof(ans), stdin); 660 switch (ans[0]) { 661 case '0': 662 printf("source sid? "); 663 FGETS(ans, sizeof(ans), stdin); 664 ssid = atoi(ans); 665 666 printf("target sid? "); 667 FGETS(ans, sizeof(ans), stdin); 668 tsid = atoi(ans); 669 670 printf("target class? "); 671 FGETS(ans, sizeof(ans), stdin); 672 if (isdigit(ans[0])) { 673 tclass = atoi(ans); 674 if (!tclass 675 || tclass > policydb.p_classes.nprim) { 676 printf("\nNo such class.\n"); 677 break; 678 } 679 cladatum = 680 policydb.class_val_to_struct[tclass - 1]; 681 } else { 682 ans[strlen(ans) - 1] = 0; 683 cladatum = 684 (class_datum_t *) hashtab_search(policydb. 685 p_classes. 686 table, 687 ans); 688 if (!cladatum) { 689 printf("\nNo such class\n"); 690 break; 691 } 692 tclass = cladatum->s.value; 693 } 694 695 if (!cladatum->comdatum && !cladatum->permissions.nprim) { 696 printf 697 ("\nNo access vector definition for that class\n"); 698 break; 699 } 700 ret = sepol_compute_av(ssid, tsid, tclass, 0, &avd); 701 switch (ret) { 702 case 0: 703 printf("\nallowed {"); 704 for (i = 1; i <= sizeof(avd.allowed) * 8; i++) { 705 if (avd.allowed & (1 << (i - 1))) { 706 v.val = i; 707 ret = 708 hashtab_map(cladatum-> 709 permissions. 710 table, 711 find_perm, &v); 712 if (!ret && cladatum->comdatum) { 713 ret = 714 hashtab_map 715 (cladatum-> 716 comdatum-> 717 permissions.table, 718 find_perm, &v); 719 } 720 if (ret) 721 printf(" %s", v.name); 722 } 723 } 724 printf(" }\n"); 725 break; 726 case -EINVAL: 727 printf("\ninvalid sid\n"); 728 break; 729 default: 730 printf("return code 0x%x\n", ret); 731 } 732 break; 733 case '1': 734 printf("sid? "); 735 FGETS(ans, sizeof(ans), stdin); 736 ssid = atoi(ans); 737 ret = sepol_sid_to_context(ssid, 738 &scontext, &scontext_len); 739 switch (ret) { 740 case 0: 741 printf("\nscontext %s\n", scontext); 742 free(scontext); 743 break; 744 case -EINVAL: 745 printf("\ninvalid sid\n"); 746 break; 747 case -ENOMEM: 748 printf("\nout of memory\n"); 749 break; 750 default: 751 printf("return code 0x%x\n", ret); 752 } 753 break; 754 case '2': 755 printf("scontext? "); 756 FGETS(ans, sizeof(ans), stdin); 757 scontext_len = strlen(ans); 758 ans[scontext_len - 1] = 0; 759 ret = sepol_context_to_sid(ans, scontext_len, &ssid); 760 switch (ret) { 761 case 0: 762 printf("\nsid %d\n", ssid); 763 break; 764 case -EINVAL: 765 printf("\ninvalid context\n"); 766 break; 767 case -ENOMEM: 768 printf("\nout of memory\n"); 769 break; 770 default: 771 printf("return code 0x%x\n", ret); 772 } 773 break; 774 case '3': 775 case '4': 776 case '5': 777 ch = ans[0]; 778 779 printf("source sid? "); 780 FGETS(ans, sizeof(ans), stdin); 781 ssid = atoi(ans); 782 printf("target sid? "); 783 FGETS(ans, sizeof(ans), stdin); 784 tsid = atoi(ans); 785 786 printf("object class? "); 787 FGETS(ans, sizeof(ans), stdin); 788 if (isdigit(ans[0])) { 789 tclass = atoi(ans); 790 if (!tclass 791 || tclass > policydb.p_classes.nprim) { 792 printf("\nNo such class.\n"); 793 break; 794 } 795 } else { 796 ans[strlen(ans) - 1] = 0; 797 cladatum = 798 (class_datum_t *) hashtab_search(policydb. 799 p_classes. 800 table, 801 ans); 802 if (!cladatum) { 803 printf("\nNo such class\n"); 804 break; 805 } 806 tclass = cladatum->s.value; 807 } 808 809 if (ch == '3') 810 ret = 811 sepol_transition_sid(ssid, tsid, tclass, 812 &ssid); 813 else if (ch == '4') 814 ret = 815 sepol_member_sid(ssid, tsid, tclass, &ssid); 816 else 817 ret = 818 sepol_change_sid(ssid, tsid, tclass, &ssid); 819 switch (ret) { 820 case 0: 821 printf("\nsid %d\n", ssid); 822 break; 823 case -EINVAL: 824 printf("\ninvalid sid\n"); 825 break; 826 case -ENOMEM: 827 printf("\nout of memory\n"); 828 break; 829 default: 830 printf("return code 0x%x\n", ret); 831 } 832 break; 833 case '6': 834 sepol_sidtab_map(&sidtab, print_sid, 0); 835 break; 836 case '7': 837 printf("pathname? "); 838 FGETS(ans, sizeof(ans), stdin); 839 pathlen = strlen(ans); 840 ans[pathlen - 1] = 0; 841 printf("%s: loading policy configuration from %s\n", 842 argv[0], ans); 843 fd = open(ans, O_RDONLY); 844 if (fd < 0) { 845 fprintf(stderr, "Can't open '%s': %s\n", 846 ans, strerror(errno)); 847 break; 848 } 849 if (fstat(fd, &sb) < 0) { 850 fprintf(stderr, "Can't stat '%s': %s\n", 851 ans, strerror(errno)); 852 break; 853 } 854 map = 855 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, 856 MAP_PRIVATE, fd, 0); 857 if (map == MAP_FAILED) { 858 fprintf(stderr, "Can't map '%s': %s\n", 859 ans, strerror(errno)); 860 break; 861 } 862 ret = sepol_load_policy(map, sb.st_size); 863 switch (ret) { 864 case 0: 865 printf("\nsuccess\n"); 866 break; 867 case -EINVAL: 868 printf("\ninvalid policy\n"); 869 break; 870 case -ENOMEM: 871 printf("\nout of memory\n"); 872 break; 873 default: 874 printf("return code 0x%x\n", ret); 875 } 876 break; 877 case '8': 878 printf("fs kdevname? "); 879 FGETS(ans, sizeof(ans), stdin); 880 ans[strlen(ans) - 1] = 0; 881 sepol_fs_sid(ans, &ssid, &tsid); 882 printf("fs_sid %d default_file_sid %d\n", ssid, tsid); 883 break; 884 case '9': 885 printf("protocol? "); 886 FGETS(ans, sizeof(ans), stdin); 887 ans[strlen(ans) - 1] = 0; 888 if (!strcmp(ans, "tcp") || !strcmp(ans, "TCP")) 889 protocol = IPPROTO_TCP; 890 else if (!strcmp(ans, "udp") || !strcmp(ans, "UDP")) 891 protocol = IPPROTO_UDP; 892 else { 893 printf("unknown protocol\n"); 894 break; 895 } 896 printf("port? "); 897 FGETS(ans, sizeof(ans), stdin); 898 port = atoi(ans); 899 sepol_port_sid(0, 0, protocol, port, &ssid); 900 printf("sid %d\n", ssid); 901 break; 902 case 'a': 903 printf("netif name? "); 904 FGETS(ans, sizeof(ans), stdin); 905 ans[strlen(ans) - 1] = 0; 906 sepol_netif_sid(ans, &ssid, &tsid); 907 printf("if_sid %d default_msg_sid %d\n", ssid, tsid); 908 break; 909 case 'b':{ 910 char *p; 911 int family, len; 912 struct in_addr addr4; 913 struct in6_addr addr6; 914 915 printf("protocol family? "); 916 FGETS(ans, sizeof(ans), stdin); 917 ans[strlen(ans) - 1] = 0; 918 if (!strcasecmp(ans, "ipv4")) 919 family = AF_INET; 920 else if (!strcasecmp(ans, "ipv6")) 921 family = AF_INET6; 922 else { 923 printf("unknown protocol family\n"); 924 break; 925 } 926 927 printf("node address? "); 928 FGETS(ans, sizeof(ans), stdin); 929 ans[strlen(ans) - 1] = 0; 930 931 if (family == AF_INET) { 932 p = (char *)&addr4; 933 len = sizeof(addr4); 934 } else { 935 p = (char *)&addr6; 936 len = sizeof(addr6); 937 } 938 939 if (inet_pton(family, ans, p) < 1) { 940 printf("error parsing address\n"); 941 break; 942 } 943 944 sepol_node_sid(family, p, len, &ssid); 945 printf("sid %d\n", ssid); 946 break; 947 } 948 case 'c': 949 printf("fstype? "); 950 FGETS(ans, sizeof(ans), stdin); 951 ans[strlen(ans) - 1] = 0; 952 sepol_fs_use(ans, &uret, &ssid); 953 switch (uret) { 954 case SECURITY_FS_USE_XATTR: 955 printf("use xattr\n"); 956 break; 957 case SECURITY_FS_USE_TRANS: 958 printf("use transition SIDs\n"); 959 break; 960 case SECURITY_FS_USE_TASK: 961 printf("use task SIDs\n"); 962 break; 963 case SECURITY_FS_USE_GENFS: 964 printf("use genfs\n"); 965 break; 966 case SECURITY_FS_USE_NONE: 967 printf("no labeling support\n"); 968 break; 969 } 970 printf("sid %d\n", ssid); 971 break; 972 case 'd': 973 printf("fstype? "); 974 FGETS(ans, sizeof(ans), stdin); 975 ans[strlen(ans) - 1] = 0; 976 fstype = strdup(ans); 977 printf("path? "); 978 FGETS(ans, sizeof(ans), stdin); 979 ans[strlen(ans) - 1] = 0; 980 path = strdup(ans); 981 printf("object class? "); 982 FGETS(ans, sizeof(ans), stdin); 983 if (isdigit(ans[0])) { 984 tclass = atoi(ans); 985 if (!tclass 986 || tclass > policydb.p_classes.nprim) { 987 printf("\nNo such class.\n"); 988 break; 989 } 990 } else { 991 ans[strlen(ans) - 1] = 0; 992 cladatum = 993 (class_datum_t *) hashtab_search(policydb. 994 p_classes. 995 table, 996 ans); 997 if (!cladatum) { 998 printf("\nNo such class\n"); 999 break; 1000 } 1001 tclass = cladatum->s.value; 1002 } 1003 sepol_genfs_sid(fstype, path, tclass, &ssid); 1004 printf("sid %d\n", ssid); 1005 free(fstype); 1006 free(path); 1007 break; 1008 case 'e': 1009 printf("from SID? "); 1010 FGETS(ans, sizeof(ans), stdin); 1011 ans[strlen(ans) - 1] = 0; 1012 ssid = atoi(ans); 1013 1014 printf("username? "); 1015 FGETS(ans, sizeof(ans), stdin); 1016 ans[strlen(ans) - 1] = 0; 1017 1018 ret = sepol_get_user_sids(ssid, ans, &sids, &nel); 1019 switch (ret) { 1020 case 0: 1021 if (!nel) 1022 printf("\nnone\n"); 1023 for (i = 0; i < nel; i++) 1024 print_sid(sids[i], NULL, NULL); 1025 free(sids); 1026 break; 1027 case -ENOMEM: 1028 printf("\nout of memory\n"); 1029 break; 1030 case -EINVAL: 1031 printf("\ninvalid argument\n"); 1032 break; 1033 default: 1034 printf("\nerror\n"); 1035 break; 1036 } 1037 break; 1038 case 'f': 1039 display_bools(); 1040 break; 1041 case 'g': 1042 display_cond_expressions(); 1043 break; 1044 case 'h': 1045 printf("name? "); 1046 FGETS(ans, sizeof(ans), stdin); 1047 ans[strlen(ans) - 1] = 0; 1048 1049 name = malloc((strlen(ans) + 1) * sizeof(char)); 1050 if (name == NULL) { 1051 fprintf(stderr, "couldn't malloc string.\n"); 1052 break; 1053 } 1054 strcpy(name, ans); 1055 1056 printf("state? "); 1057 FGETS(ans, sizeof(ans), stdin); 1058 ans[strlen(ans) - 1] = 0; 1059 1060 if (atoi(ans)) 1061 state = 1; 1062 else 1063 state = 0; 1064 1065 change_bool(name, state); 1066 free(name); 1067 break; 1068 case 'i': 1069 printf("source sid? "); 1070 FGETS(ans, sizeof(ans), stdin); 1071 ssid = atoi(ans); 1072 1073 printf("target sid? "); 1074 FGETS(ans, sizeof(ans), stdin); 1075 tsid = atoi(ans); 1076 1077 printf("target class? "); 1078 FGETS(ans, sizeof(ans), stdin); 1079 if (isdigit(ans[0])) { 1080 tclass = atoi(ans); 1081 if (!tclass 1082 || tclass > policydb.p_classes.nprim) { 1083 printf("\nNo such class.\n"); 1084 break; 1085 } 1086 cladatum = 1087 policydb.class_val_to_struct[tclass - 1]; 1088 } else { 1089 ans[strlen(ans) - 1] = 0; 1090 cladatum = 1091 (class_datum_t *) hashtab_search(policydb. 1092 p_classes. 1093 table, 1094 ans); 1095 if (!cladatum) { 1096 printf("\nNo such class\n"); 1097 break; 1098 } 1099 tclass = cladatum->s.value; 1100 } 1101 1102 flags = SHOW_GRANTED; 1103 if (sepol_compute_av_reason_buffer(ssid, tsid, 1104 tclass, 0, &avd, &reason, 1105 &reason_buf, flags)) { 1106 printf("\nconstraint error\n"); 1107 break; 1108 } 1109 if (reason_buf) { 1110 printf("\nConstraint expressions:\n%s", 1111 reason_buf); 1112 free(reason_buf); 1113 } else { 1114 printf("\nNo constraints found.\n"); 1115 } 1116 break; 1117 case 'j': 1118 printf("old sid? "); 1119 FGETS(ans, sizeof(ans), stdin); 1120 oldsid = atoi(ans); 1121 1122 printf("new sid? "); 1123 FGETS(ans, sizeof(ans), stdin); 1124 newsid = atoi(ans); 1125 1126 printf("task sid? "); 1127 FGETS(ans, sizeof(ans), stdin); 1128 tasksid = atoi(ans); 1129 1130 printf("target class? "); 1131 FGETS(ans, sizeof(ans), stdin); 1132 if (isdigit(ans[0])) { 1133 tclass = atoi(ans); 1134 if (!tclass 1135 || tclass > policydb.p_classes.nprim) { 1136 printf("\nNo such class.\n"); 1137 break; 1138 } 1139 cladatum = 1140 policydb.class_val_to_struct[tclass - 1]; 1141 } else { 1142 ans[strlen(ans) - 1] = 0; 1143 cladatum = 1144 (class_datum_t *) hashtab_search(policydb. 1145 p_classes. 1146 table, 1147 ans); 1148 if (!cladatum) { 1149 printf("\nNo such class\n"); 1150 break; 1151 } 1152 tclass = cladatum->s.value; 1153 } 1154 1155 flags = SHOW_GRANTED; 1156 if (sepol_validate_transition_reason_buffer(oldsid, 1157 newsid, tasksid, tclass, 1158 &reason_buf, flags)) { 1159 printf("\nvalidatetrans error\n"); 1160 break; 1161 } 1162 if (reason_buf) { 1163 printf("\nValidatetrans expressions:\n%s", 1164 reason_buf); 1165 free(reason_buf); 1166 } else { 1167 printf( 1168 "\nNo validatetrans expressions found.\n"); 1169 } 1170 break; 1171#ifdef EQUIVTYPES 1172 case 'z': 1173 identify_equiv_types(); 1174 break; 1175#endif 1176 case 'm': 1177 goto menu; 1178 case 'q': 1179 exit(0); 1180 break; 1181 default: 1182 printf("\nUnknown option %s.\n", ans); 1183 } 1184 } 1185 1186 return 0; 1187} 1188 1189/* FLASK */ 1190