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