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