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