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