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