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/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 89 extern char *optarg; 90 extern int optind; 91 92 static policydb_t policydb; 93 static sidtab_t sidtab; 94 95 extern policydb_t *policydbp; 96 extern int mlspol; 97 98 static int handle_unknown = SEPOL_DENY_UNKNOWN; 99 static char *txtfile = "policy.conf"; 100 static char *binfile = "policy"; 101 102 unsigned int policyvers = POLICYDB_VERSION_MAX; 103 104 void 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) \ 115 if (fgets(out,size,in)==NULL) { \ 116 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,\ 117 strerror(errno)); \ 118 exit(1);\ 119 } 120 static 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 139 struct val_to_name { 140 unsigned int val; 141 char *name; 142 }; 143 144 static 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 160 static 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 196 static 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 214 static 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 225 static 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 290 extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av); 291 292 int 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 303 void 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 338 int 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 350 int 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 364 static 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 377 int main(int argc, char **argv) 378 { 379 sepol_security_class_t tclass; 380 sepol_security_id_t ssid, tsid, *sids; 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 struct policy_file pf; 399 struct option long_options[] = { 400 {"output", required_argument, NULL, 'o'}, 401 {"target", required_argument, NULL, 't'}, 402 {"binary", no_argument, NULL, 'b'}, 403 {"debug", no_argument, NULL, 'd'}, 404 {"version", no_argument, NULL, 'V'}, 405 {"handle-unknown", optional_argument, NULL, 'U'}, 406 {"mls", no_argument, NULL, 'M'}, 407 {"help", no_argument, NULL, 'h'}, 408 {NULL, 0, NULL, 0} 409 }; 410 411 while ((ch = getopt_long(argc, argv, "o:t:dbU:MVc:h", long_options, NULL)) != -1) { 412 switch (ch) { 413 case 'o': 414 outfile = optarg; 415 break; 416 case 't': 417 if (!strcasecmp(optarg, "Xen")) 418 target = SEPOL_TARGET_XEN; 419 else if (!strcasecmp(optarg, "SELinux")) 420 target = SEPOL_TARGET_SELINUX; 421 else{ 422 fprintf(stderr, "%s: Unknown target platform:" 423 "%s\n", argv[0], optarg); 424 exit(1); 425 } 426 break; 427 case 'b': 428 binary = 1; 429 file = binfile; 430 break; 431 case 'd': 432 debug = 1; 433 break; 434 case 'V': 435 show_version = 1; 436 break; 437 case 'U': 438 if (!strcasecmp(optarg, "deny")) { 439 handle_unknown = DENY_UNKNOWN; 440 break; 441 } 442 if (!strcasecmp(optarg, "allow")) { 443 handle_unknown = ALLOW_UNKNOWN; 444 break; 445 } 446 if (!strcasecmp(optarg, "reject")) { 447 handle_unknown = REJECT_UNKNOWN; 448 break; 449 } 450 usage(argv[0]); 451 case 'M': 452 mlspol = 1; 453 break; 454 case 'c':{ 455 long int n = strtol(optarg, NULL, 10); 456 if (errno) { 457 fprintf(stderr, 458 "Invalid policyvers specified: %s\n", 459 optarg); 460 usage(argv[0]); 461 exit(1); 462 } 463 if (n < POLICYDB_VERSION_MIN 464 || n > POLICYDB_VERSION_MAX) { 465 fprintf(stderr, 466 "policyvers value %ld not in range %d-%d\n", 467 n, POLICYDB_VERSION_MIN, 468 POLICYDB_VERSION_MAX); 469 usage(argv[0]); 470 exit(1); 471 } 472 if (policyvers != n) 473 policyvers = n; 474 break; 475 } 476 case 'h': 477 default: 478 usage(argv[0]); 479 } 480 } 481 482 if (show_version) { 483 printf("%d (compatibility range %d-%d)\n", policyvers, 484 POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN); 485 exit(0); 486 } 487 488 if (optind != argc) { 489 file = argv[optind++]; 490 if (optind != argc) 491 usage(argv[0]); 492 } 493 printf("%s: loading policy configuration from %s\n", argv[0], file); 494 495 /* Set policydb and sidtab used by libsepol service functions 496 to my structures, so that I can directly populate and 497 manipulate them. */ 498 sepol_set_policydb(&policydb); 499 sepol_set_sidtab(&sidtab); 500 501 if (binary) { 502 fd = open(file, O_RDONLY); 503 if (fd < 0) { 504 fprintf(stderr, "Can't open '%s': %s\n", 505 file, strerror(errno)); 506 exit(1); 507 } 508 if (fstat(fd, &sb) < 0) { 509 fprintf(stderr, "Can't stat '%s': %s\n", 510 file, strerror(errno)); 511 exit(1); 512 } 513 map = 514 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, 515 fd, 0); 516 if (map == MAP_FAILED) { 517 fprintf(stderr, "Can't map '%s': %s\n", 518 file, strerror(errno)); 519 exit(1); 520 } 521 policy_file_init(&pf); 522 pf.type = PF_USE_MEMORY; 523 pf.data = map; 524 pf.len = sb.st_size; 525 if (policydb_init(&policydb)) { 526 fprintf(stderr, "%s: policydb_init: Out of memory!\n", 527 argv[0]); 528 exit(1); 529 } 530 ret = policydb_read(&policydb, &pf, 1); 531 if (ret) { 532 fprintf(stderr, 533 "%s: error(s) encountered while parsing configuration\n", 534 argv[0]); 535 exit(1); 536 } 537 policydbp = &policydb; 538 539 /* Check Policy Consistency */ 540 if (policydbp->mls) { 541 if (!mlspol) { 542 fprintf(stderr, "%s: MLS policy, but non-MLS" 543 " is specified\n", argv[0]); 544 exit(1); 545 } 546 } else { 547 if (mlspol) { 548 fprintf(stderr, "%s: non-MLS policy, but MLS" 549 " is specified\n", argv[0]); 550 exit(1); 551 } 552 } 553 } else { 554 policydb_t parse_policy; 555 556 if (policydb_init(&parse_policy)) 557 exit(1); 558 /* We build this as a base policy first since that is all the parser understands */ 559 parse_policy.policy_type = POLICY_BASE; 560 policydb_set_target_platform(&parse_policy, target); 561 562 /* Let sepol know if we are dealing with MLS support */ 563 parse_policy.mls = mlspol; 564 parse_policy.handle_unknown = handle_unknown; 565 566 policydbp = &parse_policy; 567 568 if (read_source_policy(policydbp, file, "checkpolicy") < 0) 569 exit(1); 570 571 if (hashtab_map(policydbp->p_levels.table, check_level, NULL)) 572 exit(1); 573 574 if (policydb_init(&policydb)) { 575 fprintf(stderr, "%s: policydb_init failed\n", argv[0]); 576 exit(1); 577 } 578 579 /* Linking takes care of optional avrule blocks */ 580 if (link_modules(NULL, &parse_policy, NULL, 0, 0)) { 581 fprintf(stderr, "Error while resolving optionals\n"); 582 exit(1); 583 } 584 585 if (expand_module(NULL, &parse_policy, &policydb, 0, 1)) { 586 fprintf(stderr, "Error while expanding policy\n"); 587 exit(1); 588 } 589 policydb_destroy(&parse_policy); 590 policydbp = &policydb; 591 } 592 593 if (policydb_load_isids(&policydb, &sidtab)) 594 exit(1); 595 596 printf("%s: policy configuration loaded\n", argv[0]); 597 598 if (outfile) { 599 printf 600 ("%s: writing binary representation (version %d) to %s\n", 601 argv[0], policyvers, outfile); 602 outfp = fopen(outfile, "w"); 603 if (!outfp) { 604 perror(outfile); 605 exit(1); 606 } 607 608 policydb.policy_type = POLICY_KERN; 609 policydb.policyvers = policyvers; 610 611 policy_file_init(&pf); 612 pf.type = PF_USE_STDIO; 613 pf.fp = outfp; 614 ret = policydb_write(&policydb, &pf); 615 if (ret) { 616 fprintf(stderr, "%s: error writing %s\n", 617 argv[0], outfile); 618 exit(1); 619 } 620 fclose(outfp); 621 } 622 if (!debug) { 623 policydb_destroy(&policydb); 624 exit(0); 625 } 626 627 menu: 628 printf("\nSelect an option:\n"); 629 printf("0) Call compute_access_vector\n"); 630 printf("1) Call sid_to_context\n"); 631 printf("2) Call context_to_sid\n"); 632 printf("3) Call transition_sid\n"); 633 printf("4) Call member_sid\n"); 634 printf("5) Call change_sid\n"); 635 printf("6) Call list_sids\n"); 636 printf("7) Call load_policy\n"); 637 printf("8) Call fs_sid\n"); 638 printf("9) Call port_sid\n"); 639 printf("a) Call netif_sid\n"); 640 printf("b) Call node_sid\n"); 641 printf("c) Call fs_use\n"); 642 printf("d) Call genfs_sid\n"); 643 printf("e) Call get_user_sids\n"); 644 printf("f) display conditional bools\n"); 645 printf("g) display conditional expressions\n"); 646 printf("h) change a boolean value\n"); 647 #ifdef EQUIVTYPES 648 printf("z) Show equivalent types\n"); 649 #endif 650 printf("m) Show menu again\n"); 651 printf("q) Exit\n"); 652 while (1) { 653 printf("\nChoose: "); 654 FGETS(ans, sizeof(ans), stdin); 655 switch (ans[0]) { 656 case '0': 657 printf("source sid? "); 658 FGETS(ans, sizeof(ans), stdin); 659 ssid = atoi(ans); 660 661 printf("target sid? "); 662 FGETS(ans, sizeof(ans), stdin); 663 tsid = atoi(ans); 664 665 printf("target class? "); 666 FGETS(ans, sizeof(ans), stdin); 667 if (isdigit(ans[0])) { 668 tclass = atoi(ans); 669 if (!tclass 670 || tclass > policydb.p_classes.nprim) { 671 printf("\nNo such class.\n"); 672 break; 673 } 674 cladatum = 675 policydb.class_val_to_struct[tclass - 1]; 676 } else { 677 ans[strlen(ans) - 1] = 0; 678 cladatum = 679 (class_datum_t *) hashtab_search(policydb. 680 p_classes. 681 table, 682 ans); 683 if (!cladatum) { 684 printf("\nNo such class\n"); 685 break; 686 } 687 tclass = cladatum->s.value; 688 } 689 690 if (!cladatum->comdatum && !cladatum->permissions.nprim) { 691 printf 692 ("\nNo access vector definition for that class\n"); 693 break; 694 } 695 ret = sepol_compute_av(ssid, tsid, tclass, 0, &avd); 696 switch (ret) { 697 case 0: 698 printf("\nallowed {"); 699 for (i = 1; i <= sizeof(avd.allowed) * 8; i++) { 700 if (avd.allowed & (1 << (i - 1))) { 701 v.val = i; 702 ret = 703 hashtab_map(cladatum-> 704 permissions. 705 table, 706 find_perm, &v); 707 if (!ret && cladatum->comdatum) { 708 ret = 709 hashtab_map 710 (cladatum-> 711 comdatum-> 712 permissions.table, 713 find_perm, &v); 714 } 715 if (ret) 716 printf(" %s", v.name); 717 } 718 } 719 printf(" }\n"); 720 break; 721 case -EINVAL: 722 printf("\ninvalid sid\n"); 723 break; 724 default: 725 printf("return code 0x%x\n", ret); 726 } 727 break; 728 case '1': 729 printf("sid? "); 730 FGETS(ans, sizeof(ans), stdin); 731 ssid = atoi(ans); 732 ret = sepol_sid_to_context(ssid, 733 &scontext, &scontext_len); 734 switch (ret) { 735 case 0: 736 printf("\nscontext %s\n", scontext); 737 free(scontext); 738 break; 739 case -EINVAL: 740 printf("\ninvalid sid\n"); 741 break; 742 case -ENOMEM: 743 printf("\nout of memory\n"); 744 break; 745 default: 746 printf("return code 0x%x\n", ret); 747 } 748 break; 749 case '2': 750 printf("scontext? "); 751 FGETS(ans, sizeof(ans), stdin); 752 scontext_len = strlen(ans); 753 ans[scontext_len - 1] = 0; 754 ret = sepol_context_to_sid(ans, scontext_len, &ssid); 755 switch (ret) { 756 case 0: 757 printf("\nsid %d\n", ssid); 758 break; 759 case -EINVAL: 760 printf("\ninvalid context\n"); 761 break; 762 case -ENOMEM: 763 printf("\nout of memory\n"); 764 break; 765 default: 766 printf("return code 0x%x\n", ret); 767 } 768 break; 769 case '3': 770 case '4': 771 case '5': 772 ch = ans[0]; 773 774 printf("source sid? "); 775 FGETS(ans, sizeof(ans), stdin); 776 ssid = atoi(ans); 777 printf("target sid? "); 778 FGETS(ans, sizeof(ans), stdin); 779 tsid = atoi(ans); 780 781 printf("object class? "); 782 FGETS(ans, sizeof(ans), stdin); 783 if (isdigit(ans[0])) { 784 tclass = atoi(ans); 785 if (!tclass 786 || tclass > policydb.p_classes.nprim) { 787 printf("\nNo such class.\n"); 788 break; 789 } 790 } else { 791 ans[strlen(ans) - 1] = 0; 792 cladatum = 793 (class_datum_t *) hashtab_search(policydb. 794 p_classes. 795 table, 796 ans); 797 if (!cladatum) { 798 printf("\nNo such class\n"); 799 break; 800 } 801 tclass = cladatum->s.value; 802 } 803 804 if (ch == '3') 805 ret = 806 sepol_transition_sid(ssid, tsid, tclass, 807 &ssid); 808 else if (ch == '4') 809 ret = 810 sepol_member_sid(ssid, tsid, tclass, &ssid); 811 else 812 ret = 813 sepol_change_sid(ssid, tsid, tclass, &ssid); 814 switch (ret) { 815 case 0: 816 printf("\nsid %d\n", ssid); 817 break; 818 case -EINVAL: 819 printf("\ninvalid sid\n"); 820 break; 821 case -ENOMEM: 822 printf("\nout of memory\n"); 823 break; 824 default: 825 printf("return code 0x%x\n", ret); 826 } 827 break; 828 case '6': 829 sepol_sidtab_map(&sidtab, print_sid, 0); 830 break; 831 case '7': 832 printf("pathname? "); 833 FGETS(ans, sizeof(ans), stdin); 834 pathlen = strlen(ans); 835 ans[pathlen - 1] = 0; 836 printf("%s: loading policy configuration from %s\n", 837 argv[0], ans); 838 fd = open(ans, O_RDONLY); 839 if (fd < 0) { 840 fprintf(stderr, "Can't open '%s': %s\n", 841 ans, strerror(errno)); 842 break; 843 } 844 if (fstat(fd, &sb) < 0) { 845 fprintf(stderr, "Can't stat '%s': %s\n", 846 ans, strerror(errno)); 847 break; 848 } 849 map = 850 mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, 851 MAP_PRIVATE, fd, 0); 852 if (map == MAP_FAILED) { 853 fprintf(stderr, "Can't map '%s': %s\n", 854 ans, strerror(errno)); 855 break; 856 } 857 ret = sepol_load_policy(map, sb.st_size); 858 switch (ret) { 859 case 0: 860 printf("\nsuccess\n"); 861 break; 862 case -EINVAL: 863 printf("\ninvalid policy\n"); 864 break; 865 case -ENOMEM: 866 printf("\nout of memory\n"); 867 break; 868 default: 869 printf("return code 0x%x\n", ret); 870 } 871 break; 872 case '8': 873 printf("fs kdevname? "); 874 FGETS(ans, sizeof(ans), stdin); 875 ans[strlen(ans) - 1] = 0; 876 sepol_fs_sid(ans, &ssid, &tsid); 877 printf("fs_sid %d default_file_sid %d\n", ssid, tsid); 878 break; 879 case '9': 880 printf("protocol? "); 881 FGETS(ans, sizeof(ans), stdin); 882 ans[strlen(ans) - 1] = 0; 883 if (!strcmp(ans, "tcp") || !strcmp(ans, "TCP")) 884 protocol = IPPROTO_TCP; 885 else if (!strcmp(ans, "udp") || !strcmp(ans, "UDP")) 886 protocol = IPPROTO_UDP; 887 else { 888 printf("unknown protocol\n"); 889 break; 890 } 891 printf("port? "); 892 FGETS(ans, sizeof(ans), stdin); 893 port = atoi(ans); 894 sepol_port_sid(0, 0, protocol, port, &ssid); 895 printf("sid %d\n", ssid); 896 break; 897 case 'a': 898 printf("netif name? "); 899 FGETS(ans, sizeof(ans), stdin); 900 ans[strlen(ans) - 1] = 0; 901 sepol_netif_sid(ans, &ssid, &tsid); 902 printf("if_sid %d default_msg_sid %d\n", ssid, tsid); 903 break; 904 case 'b':{ 905 char *p; 906 int family, len; 907 struct in_addr addr4; 908 struct in6_addr addr6; 909 910 printf("protocol family? "); 911 FGETS(ans, sizeof(ans), stdin); 912 ans[strlen(ans) - 1] = 0; 913 if (!strcasecmp(ans, "ipv4")) 914 family = AF_INET; 915 else if (!strcasecmp(ans, "ipv6")) 916 family = AF_INET6; 917 else { 918 printf("unknown protocol family\n"); 919 break; 920 } 921 922 printf("node address? "); 923 FGETS(ans, sizeof(ans), stdin); 924 ans[strlen(ans) - 1] = 0; 925 926 if (family == AF_INET) { 927 p = (char *)&addr4; 928 len = sizeof(addr4); 929 } else { 930 p = (char *)&addr6; 931 len = sizeof(addr6); 932 } 933 934 if (inet_pton(family, ans, p) < 1) { 935 printf("error parsing address\n"); 936 break; 937 } 938 939 sepol_node_sid(family, p, len, &ssid); 940 printf("sid %d\n", ssid); 941 break; 942 } 943 case 'c': 944 printf("fstype? "); 945 FGETS(ans, sizeof(ans), stdin); 946 ans[strlen(ans) - 1] = 0; 947 sepol_fs_use(ans, &uret, &ssid); 948 switch (uret) { 949 case SECURITY_FS_USE_XATTR: 950 printf("use xattr\n"); 951 break; 952 case SECURITY_FS_USE_TRANS: 953 printf("use transition SIDs\n"); 954 break; 955 case SECURITY_FS_USE_TASK: 956 printf("use task SIDs\n"); 957 break; 958 case SECURITY_FS_USE_GENFS: 959 printf("use genfs\n"); 960 break; 961 case SECURITY_FS_USE_NONE: 962 printf("no labeling support\n"); 963 break; 964 } 965 printf("sid %d\n", ssid); 966 break; 967 case 'd': 968 printf("fstype? "); 969 FGETS(ans, sizeof(ans), stdin); 970 ans[strlen(ans) - 1] = 0; 971 fstype = strdup(ans); 972 printf("path? "); 973 FGETS(ans, sizeof(ans), stdin); 974 ans[strlen(ans) - 1] = 0; 975 path = strdup(ans); 976 printf("object class? "); 977 FGETS(ans, sizeof(ans), stdin); 978 if (isdigit(ans[0])) { 979 tclass = atoi(ans); 980 if (!tclass 981 || tclass > policydb.p_classes.nprim) { 982 printf("\nNo such class.\n"); 983 break; 984 } 985 } else { 986 ans[strlen(ans) - 1] = 0; 987 cladatum = 988 (class_datum_t *) hashtab_search(policydb. 989 p_classes. 990 table, 991 ans); 992 if (!cladatum) { 993 printf("\nNo such class\n"); 994 break; 995 } 996 tclass = cladatum->s.value; 997 } 998 sepol_genfs_sid(fstype, path, tclass, &ssid); 999 printf("sid %d\n", ssid); 1000 free(fstype); 1001 free(path); 1002 break; 1003 case 'e': 1004 printf("from SID? "); 1005 FGETS(ans, sizeof(ans), stdin); 1006 ans[strlen(ans) - 1] = 0; 1007 ssid = atoi(ans); 1008 1009 printf("username? "); 1010 FGETS(ans, sizeof(ans), stdin); 1011 ans[strlen(ans) - 1] = 0; 1012 1013 ret = sepol_get_user_sids(ssid, ans, &sids, &nel); 1014 switch (ret) { 1015 case 0: 1016 if (!nel) 1017 printf("\nnone\n"); 1018 for (i = 0; i < nel; i++) 1019 print_sid(sids[i], NULL, NULL); 1020 free(sids); 1021 break; 1022 case -ENOMEM: 1023 printf("\nout of memory\n"); 1024 break; 1025 case -EINVAL: 1026 printf("\ninvalid argument\n"); 1027 break; 1028 default: 1029 printf("\nerror\n"); 1030 break; 1031 } 1032 break; 1033 case 'f': 1034 display_bools(); 1035 break; 1036 case 'g': 1037 display_cond_expressions(); 1038 break; 1039 case 'h': 1040 printf("name? "); 1041 FGETS(ans, sizeof(ans), stdin); 1042 ans[strlen(ans) - 1] = 0; 1043 1044 name = malloc((strlen(ans) + 1) * sizeof(char)); 1045 if (name == NULL) { 1046 fprintf(stderr, "couldn't malloc string.\n"); 1047 break; 1048 } 1049 strcpy(name, ans); 1050 1051 printf("state? "); 1052 FGETS(ans, sizeof(ans), stdin); 1053 ans[strlen(ans) - 1] = 0; 1054 1055 if (atoi(ans)) 1056 state = 1; 1057 else 1058 state = 0; 1059 1060 change_bool(name, state); 1061 free(name); 1062 break; 1063 #ifdef EQUIVTYPES 1064 case 'z': 1065 identify_equiv_types(); 1066 break; 1067 #endif 1068 case 'm': 1069 goto menu; 1070 case 'q': 1071 exit(0); 1072 break; 1073 default: 1074 printf("\nUnknown option %s.\n", ans); 1075 } 1076 } 1077 1078 return 0; 1079 } 1080 1081 /* FLASK */ 1082