blob: 292f56894f306e6c43a88bafe53e9178d6621ced [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
Stephen Smalleyda752ca2012-02-23 10:14:13 -050073#ifdef DARWIN
74#include <ctype.h>
75#endif
76
Joshua Brindle13cd4c82008-08-19 15:30:36 -040077#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
89extern char *optarg;
90extern int optind;
91
92static policydb_t policydb;
93static sidtab_t sidtab;
94
95extern policydb_t *policydbp;
96extern int mlspol;
97
98static int handle_unknown = SEPOL_DENY_UNKNOWN;
99static char *txtfile = "policy.conf";
100static char *binfile = "policy";
101
102unsigned int policyvers = POLICYDB_VERSION_MAX;
103
104void usage(char *progname)
105{
106 printf
Joshua Brindlef830d962009-10-14 15:49:25 -0400107 ("usage: %s [-b] [-d] [-U handle_unknown (allow,deny,reject)] [-M]"
108 "[-c policyvers (%d-%d)] [-o output_file] [-t target_platform (selinux,xen)]"
Paul Nuzzi79d10a82009-09-29 10:06:26 -0400109 "[input_file]\n",
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400110 progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
111 exit(1);
112}
113
114#define FGETS(out, size, in) \
115if (fgets(out,size,in)==NULL) { \
116 fprintf(stderr, "fgets failed at line %d: %s\n", __LINE__,\
117 strerror(errno)); \
118 exit(1);\
119}
120static 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
139struct val_to_name {
140 unsigned int val;
141 char *name;
142};
143
144static 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
160static 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
196static 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
214static 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
225static 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
290extern char *av_to_string(uint32_t tclass, sepol_access_vector_t av);
291
292int 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
303void 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
338int 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
350int 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
364static 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
377int 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;
Paul Nuzzi79d10a82009-09-29 10:06:26 -0400390 int ret, ch, fd, target = SEPOL_TARGET_SELINUX;
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400391 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;
Guido Trentalanciabf57d232009-11-02 18:14:28 +0100399 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'},
Laurent Bigonvillef6a03f12013-07-06 14:32:33 +0200405 {"handle-unknown", required_argument, NULL, 'U'},
Guido Trentalanciabf57d232009-11-02 18:14:28 +0100406 {"mls", no_argument, NULL, 'M'},
407 {"help", no_argument, NULL, 'h'},
408 {NULL, 0, NULL, 0}
409 };
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400410
Guido Trentalanciabf57d232009-11-02 18:14:28 +0100411 while ((ch = getopt_long(argc, argv, "o:t:dbU:MVc:h", long_options, NULL)) != -1) {
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400412 switch (ch) {
413 case 'o':
414 outfile = optarg;
415 break;
Paul Nuzzi79d10a82009-09-29 10:06:26 -0400416 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;
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400427 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 }
Guido Trentalanciabf57d232009-11-02 18:14:28 +0100476 case 'h':
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400477 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;
Paul Nuzzi79d10a82009-09-29 10:06:26 -0400560 policydb_set_target_platform(&parse_policy, target);
Joshua Brindle13cd4c82008-08-19 15:30:36 -0400561
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 */