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