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