~ubuntu-branches/ubuntu/gutsy/checkpolicy/gutsy

« back to all changes in this revision

Viewing changes to checkpolicy.c

  • Committer: Bazaar Package Importer
  • Author(s): Russell Coker
  • Date: 2004-05-20 04:32:00 UTC
  • Revision ID: james.westby@ubuntu.com-20040520043200-w4lzkx37dmmc3wt9
Tags: upstream-1.10
ImportĀ upstreamĀ versionĀ 1.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
 
 
2
/*
 
3
 * Author : Stephen Smalley, <sds@epoch.ncsc.mil> 
 
4
 */
 
5
 
 
6
/* Updated: Karl MacMillan <kmacmillan@tresys.com>
 
7
 *
 
8
 *      Added conditional policy language extensions
 
9
 *
 
10
 * Updated: James Morris <jmorris@intercode.com.au>
 
11
 *
 
12
 *      Added IPv6 support.
 
13
 *
 
14
 * Copyright (C) 2003 - 2004 Tresys Technology, LLC
 
15
 * Copyright (C) 2003 Red Hat, Inc., James Morris <jmorris@redhat.com>
 
16
 *      This program is free software; you can redistribute it and/or modify
 
17
 *      it under the terms of the GNU General Public License as published by
 
18
 *      the Free Software Foundation, version 2.
 
19
 */
 
20
 
 
21
/* FLASK */
 
22
 
 
23
/* 
 
24
 * checkpolicy
 
25
 *
 
26
 * Load and check a policy configuration.
 
27
 *
 
28
 * A policy configuration is created in a text format,
 
29
 * and then compiled into a binary format for use by
 
30
 * the security server.  By default, checkpolicy reads
 
31
 * the text format.   If '-b' is specified, then checkpolicy
 
32
 * reads the binary format instead.
 
33
 * 
 
34
 * If '-o output_file' is specified, then checkpolicy 
 
35
 * writes the binary format version of the configuration
 
36
 * to the specified output file.  
 
37
 * 
 
38
 * If '-d' is specified, then checkpolicy permits the user 
 
39
 * to interactively test the security server functions with 
 
40
 * the loaded policy configuration.
 
41
 *
 
42
 * If '-c' is specified, then the supplied parameter is used to
 
43
 * determine which policy version to use for generating binary
 
44
 * policy.  This is for compatibility with older kernels. If any
 
45
 * booleans or conditional rules are thrown away a warning is printed.
 
46
 */
 
47
 
 
48
#include "policydb.h"
 
49
#include "services.h"
 
50
#include "queue.h"
 
51
#include "checkpolicy.h"
 
52
#include "conditional.h"
 
53
#include <getopt.h>
 
54
#include <unistd.h>
 
55
#include <sys/types.h>
 
56
#include <sys/stat.h>
 
57
#include <fcntl.h>
 
58
#include <stdio.h>
 
59
#include <errno.h>
 
60
#include <sys/mman.h>
 
61
extern char *optarg;
 
62
extern int optind;
 
63
 
 
64
extern policydb_t *policydbp;
 
65
extern queue_t id_queue;
 
66
extern unsigned int policydb_errors;
 
67
extern unsigned long policydb_lineno;
 
68
extern unsigned long source_lineno;
 
69
extern char source_file[];
 
70
extern unsigned int pass;
 
71
extern unsigned int ss_initialized;
 
72
 
 
73
extern int policydb_write(policydb_t * p, FILE * fp);
 
74
 
 
75
extern FILE *yyin;
 
76
extern int yyparse(void);
 
77
extern void yyrestart(FILE *);
 
78
 
 
79
char *txtfile = "policy.conf";
 
80
char *binfile = "policy";
 
81
 
 
82
int policyvers = POLICYDB_VERSION_MAX;
 
83
 
 
84
int avc_ss_reset(__u32 seqno __attribute__ ((unused)))
 
85
{
 
86
        return 0;
 
87
}
 
88
 
 
89
void usage(char *progname)
 
90
{
 
91
        printf("usage:  %s [-b] [-d] [-c policyvers (%d-%d)] [-o output_file] [input_file]\n",
 
92
                progname, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
 
93
        exit(1);
 
94
}
 
95
 
 
96
static int print_sid(security_id_t sid,
 
97
                     context_struct_t * context __attribute__ ((unused)), void *data __attribute__ ((unused)))
 
98
{
 
99
        security_context_t scontext;
 
100
        size_t scontext_len;
 
101
        int rc;
 
102
 
 
103
        rc = security_sid_to_context(sid, &scontext, &scontext_len);
 
104
        if (rc)
 
105
                printf("sid %d -> error %d\n", sid, rc);
 
106
        else {
 
107
                printf("sid %d -> scontext %s\n", sid, scontext);
 
108
                free(scontext);
 
109
        }
 
110
        return 0;
 
111
}
 
112
 
 
113
struct val_to_name {
 
114
        unsigned int val;
 
115
        char *name;
 
116
};
 
117
 
 
118
static int find_perm(hashtab_key_t key, hashtab_datum_t datum, void *p)
 
119
{
 
120
        struct val_to_name *v = p;
 
121
        perm_datum_t *perdatum;
 
122
 
 
123
        perdatum = (perm_datum_t *) datum;
 
124
 
 
125
        if (v->val == perdatum->value) {
 
126
                v->name = key;
 
127
                return 1;
 
128
        }
 
129
 
 
130
        return 0;
 
131
}
 
132
 
 
133
static int type_attr_remove(hashtab_key_t key __attribute__ ((unused)), hashtab_datum_t datum, void *p __attribute__ ((unused)))
 
134
{
 
135
        type_datum_t *typdatum;
 
136
 
 
137
        typdatum = (type_datum_t *) datum;
 
138
        if (typdatum->isattr)
 
139
                return 1;
 
140
        return 0;
 
141
}
 
142
 
 
143
#ifdef EQUIVTYPES
 
144
static int insert_type_rule(avtab_key_t *k, avtab_datum_t *d, 
 
145
                            struct avtab_node *type_rules)
 
146
{
 
147
        struct avtab_node *p, *c, *n;
 
148
 
 
149
        for (p = type_rules, c = type_rules->next; c; p = c, c = c->next) {
 
150
                /* 
 
151
                 * Find the insertion point, keeping the list
 
152
                 * ordered by source type, then target type, then
 
153
                 * target class.
 
154
                 */
 
155
                if (k->source_type < c->key.source_type)
 
156
                        break;
 
157
                if (k->source_type == c->key.source_type && 
 
158
                    k->target_type < c->key.target_type)
 
159
                        break;
 
160
                if (k->source_type == c->key.source_type && 
 
161
                    k->target_type == c->key.target_type &&
 
162
                    k->target_class < c->key.target_class)
 
163
                        break;
 
164
        }
 
165
 
 
166
        /* Insert the rule */
 
167
        n = malloc(sizeof(struct avtab_node));
 
168
        if (!n) {
 
169
                fprintf(stderr, "out of memory\n");
 
170
                exit(1);
 
171
        }
 
172
 
 
173
        n->key = *k;
 
174
        n->datum = *d;
 
175
        n->next = p->next;
 
176
        p->next = n;
 
177
        return 0;
 
178
}
 
179
 
 
180
static int create_type_rules(avtab_key_t *k, avtab_datum_t *d, void *args)
 
181
{
 
182
        struct avtab_node *type_rules = args;
 
183
 
 
184
        if (d->specified & AVTAB_ALLOWED) {
 
185
                /* 
 
186
                 * Insert the rule into the lists for both 
 
187
                 * the source type and the target type.
 
188
                 */
 
189
                if (insert_type_rule(k, d, &type_rules[k->source_type-1])) return -1;
 
190
                if (insert_type_rule(k, d, &type_rules[k->target_type-1])) return -1;
 
191
        }
 
192
 
 
193
        return 0;
 
194
}
 
195
 
 
196
static void free_type_rules(struct avtab_node *l)
 
197
{
 
198
        struct avtab_node *tmp;
 
199
 
 
200
        while (l) {
 
201
                tmp = l;
 
202
                l = l->next;
 
203
                free(tmp);
 
204
        }
 
205
}
 
206
 
 
207
static int identify_equiv_types(void) 
 
208
{
 
209
        struct avtab_node *type_rules, *l1, *l2;
 
210
        int i, j;
 
211
 
 
212
        /*
 
213
         * Create a list of access vector rules for each type
 
214
         * from the access vector table.
 
215
         */
 
216
        type_rules = malloc(sizeof(struct avtab_node)*policydb.p_types.nprim);
 
217
        if (!type_rules) {
 
218
                fprintf(stderr, "out of memory\n");
 
219
                exit(1);
 
220
        }
 
221
        memset(type_rules, 0, sizeof(struct avtab_node)*policydb.p_types.nprim);
 
222
        if (avtab_map(&policydb.te_avtab, create_type_rules, type_rules))
 
223
                exit(1);
 
224
        
 
225
 
 
226
        /*
 
227
         * Compare the type lists and identify equivalent types.
 
228
         */
 
229
        for (i = 0; i < policydb.p_types.nprim - 1; i++) {
 
230
                if (!type_rules[i].next)
 
231
                        continue;
 
232
                for (j = i + 1; j < policydb.p_types.nprim; j++) {
 
233
                        for (l1 = type_rules[i].next, l2 = type_rules[j].next; l1 && l2;
 
234
                             l1 = l1->next, l2 = l2->next) {
 
235
                                if (l2->key.source_type == (j+1)) {
 
236
                                        if (l1->key.source_type != (i+1))
 
237
                                                break;
 
238
                                } else {
 
239
                                        if (l1->key.source_type != l2->key.source_type)
 
240
                                                break;
 
241
                                }
 
242
                                if (l2->key.target_type == (j+1)) {
 
243
                                        if (l1->key.target_type != (i+1))
 
244
                                                break;
 
245
                                } else {
 
246
                                        if (l1->key.target_type != l2->key.target_type)
 
247
                                                break;
 
248
                                }
 
249
                                if (l1->key.target_class != l2->key.target_class || 
 
250
                                    l1->datum.allowed != l2->datum.allowed)
 
251
                                        break;
 
252
                        }
 
253
                        if (l1 || l2) 
 
254
                                continue;
 
255
                        free_type_rules(type_rules[j].next);
 
256
                        type_rules[j].next = NULL;
 
257
                        printf("Types %s and %s are equivalent.\n",
 
258
                               policydb.p_type_val_to_name[i],
 
259
                               policydb.p_type_val_to_name[j]);
 
260
                }
 
261
                free_type_rules(type_rules[i].next);            
 
262
                type_rules[i].next = NULL;
 
263
        }
 
264
 
 
265
        free(type_rules);       
 
266
        return 0;
 
267
}
 
268
#endif 
 
269
 
 
270
static void cond_check_type_rules_list(cond_av_list_t *list)
 
271
{
 
272
        cond_av_list_t *cur = list;
 
273
 
 
274
        while (cur) {
 
275
                if (cur->node->datum.specified & AVTAB_TYPE) {
 
276
                        if (avtab_search(&policydbp->te_avtab, &cur->node->key, AVTAB_TYPE)) {
 
277
                                fprintf(stderr, "conditional type rule for (%s, %s : %s) conflicts with entry in base policy; "
 
278
                                        "conditional rule discarded.\n", policydbp->p_type_val_to_name[cur->node->key.source_type],
 
279
                                        policydbp->p_type_val_to_name[cur->node->key.target_type],
 
280
                                        policydbp->p_class_val_to_name[cur->node->key.target_class]);
 
281
                                cur->node->parse_context = (void*)0;
 
282
                        } else {
 
283
                                cur->node->parse_context = (void*)1;
 
284
                        }
 
285
                } else {
 
286
                        cur->node->parse_context = (void*)1;
 
287
                }
 
288
                cur = cur->next;
 
289
        }
 
290
}
 
291
 
 
292
/* check for duplicate type rules - this has to be done after all of
 
293
 * the parsing is finished because the conditional and base type rules
 
294
 * are collected in the same pass */
 
295
static void cond_check_type_rules(void)
 
296
{
 
297
        cond_list_t *node;
 
298
 
 
299
        for (node = policydbp->cond_list; node != NULL; node = node->next) {
 
300
                cond_check_type_rules_list(node->true_list);
 
301
                cond_check_type_rules_list(node->false_list);
 
302
        }
 
303
}
 
304
 
 
305
extern char *av_to_string(__u32 tclass, access_vector_t av);
 
306
 
 
307
void check_assertion_helper(unsigned int stype, unsigned int ttype, ebitmap_t *tclasses, 
 
308
                            access_vector_t *avp, unsigned long line) 
 
309
{
 
310
        avtab_key_t avkey;
 
311
        avtab_datum_t *avdatump;
 
312
        unsigned int k;
 
313
        
 
314
 
 
315
        for (k = ebitmap_startbit(tclasses); k < ebitmap_length(tclasses); k++) {
 
316
                if (!ebitmap_get_bit(tclasses, k)) 
 
317
                        continue;
 
318
                avkey.source_type = stype + 1;
 
319
                avkey.target_type = ttype + 1;
 
320
                avkey.target_class = k + 1;
 
321
                avdatump = avtab_search(&policydb.te_avtab, &avkey, AVTAB_AV);
 
322
                if (!avdatump) 
 
323
                        continue;
 
324
 
 
325
                if ((avdatump->specified & AVTAB_ALLOWED) &&
 
326
                    (avtab_allowed(avdatump) & avp[k])) {
 
327
                        fprintf(stderr, "assertion on line %ld violated by allow %s %s:%s {%s };\n", line, policydb.p_type_val_to_name[stype], policydb.p_type_val_to_name[ttype], policydb.p_class_val_to_name[k], 
 
328
                                av_to_string(k+1,
 
329
                                             avtab_allowed(avdatump) & avp[k]));
 
330
                        policydb_errors++;
 
331
                }
 
332
        }
 
333
}
 
334
 
 
335
void check_assertions(void) 
 
336
{
 
337
        te_assert_t *a, *tmp;
 
338
        unsigned int i, j;
 
339
 
 
340
        a = te_assertions;
 
341
        while (a) {
 
342
                for (i = ebitmap_startbit(&a->stypes); i < ebitmap_length(&a->stypes); i++) {
 
343
                        if (!ebitmap_get_bit(&a->stypes, i))
 
344
                                continue;
 
345
                        if (a->self) {
 
346
                                check_assertion_helper(i, i, &a->tclasses, a->avp, a->line);
 
347
                        }
 
348
                        for (j = ebitmap_startbit(&a->ttypes); j < ebitmap_length(&a->ttypes); j++) {
 
349
                                if (!ebitmap_get_bit(&a->ttypes, j)) 
 
350
                                        continue;
 
351
                                check_assertion_helper(i, j, &a->tclasses, a->avp, a->line);
 
352
                        }
 
353
                }
 
354
                tmp = a;
 
355
                a = a->next;
 
356
                ebitmap_destroy(&tmp->stypes);
 
357
                ebitmap_destroy(&tmp->ttypes);
 
358
                ebitmap_destroy(&tmp->tclasses);
 
359
                free(tmp->avp);
 
360
                free(tmp);
 
361
        }
 
362
}
 
363
 
 
364
int display_bools()
 
365
{
 
366
        int i;
 
367
 
 
368
        for (i = 0; i < policydbp->p_bools.nprim; i++) {
 
369
                printf("%s : %d\n", policydbp->p_bool_val_to_name[i],
 
370
                        policydbp->bool_val_to_struct[i]->state);
 
371
        }
 
372
        return 0;
 
373
}
 
374
 
 
375
void display_expr(cond_expr_t *exp)
 
376
{
 
377
 
 
378
        cond_expr_t *cur;
 
379
        for (cur = exp; cur != NULL; cur = cur->next) {
 
380
                switch (cur->expr_type) {
 
381
                case COND_BOOL:
 
382
                        printf("%s ", policydbp->p_bool_val_to_name[cur->bool - 1]);
 
383
                        break;
 
384
                case COND_NOT:
 
385
                        printf("! ");
 
386
                        break;
 
387
                case COND_OR:
 
388
                        printf("|| ");
 
389
                        break;
 
390
                case COND_AND:
 
391
                        printf("&& ");
 
392
                        break;
 
393
                case COND_XOR:
 
394
                        printf("^ ");
 
395
                        break;
 
396
                case COND_EQ:
 
397
                        printf("== ");
 
398
                        break;
 
399
                case COND_NEQ:
 
400
                        printf("!= ");
 
401
                        break;
 
402
                default:
 
403
                        printf("error!");
 
404
                        break;
 
405
                }
 
406
        }
 
407
}
 
408
 
 
409
int display_cond_expressions()
 
410
{
 
411
        cond_node_t *cur;
 
412
 
 
413
        for (cur = policydbp->cond_list; cur != NULL; cur = cur->next) {
 
414
                printf("expression: ");
 
415
                display_expr(cur->expr);
 
416
                printf("current state: %d\n", cur->cur_state);
 
417
        }
 
418
        return 0;
 
419
}
 
420
 
 
421
int change_bool(char *name, int state)
 
422
{
 
423
        cond_bool_datum_t *bool;
 
424
 
 
425
        bool = hashtab_search(policydbp->p_bools.table, name);
 
426
        if (bool == NULL) {
 
427
                printf("Could not find bool %s\n", name);
 
428
                return -1;
 
429
        }
 
430
        bool->state = state;
 
431
        evaluate_conds(policydbp);
 
432
        return 0;
 
433
}
 
434
 
 
435
int main(int argc, char **argv)
 
436
{
 
437
        security_class_t tclass;
 
438
        security_id_t ssid, tsid, *sids;
 
439
        security_context_t scontext;
 
440
        struct av_decision avd;
 
441
        class_datum_t *cladatum;
 
442
        char ans[80 + 1], *file = txtfile, *outfile = NULL, *path, *fstype;
 
443
        size_t scontext_len, pathlen;
 
444
        unsigned int i;
 
445
        unsigned int protocol, port;
 
446
        unsigned int binary = 0, debug = 0;
 
447
        struct val_to_name v;
 
448
        int ret, ch, fd;
 
449
        unsigned int nel;
 
450
        struct stat sb;
 
451
        void *map;
 
452
        FILE *outfp = NULL;
 
453
        char *name;
 
454
        int state;
 
455
        int show_version = 0;
 
456
 
 
457
 
 
458
        while ((ch = getopt(argc, argv, "o:dbVc:")) != EOF) {
 
459
                switch (ch) {
 
460
                case 'o':
 
461
                        outfile = optarg;
 
462
                        break;
 
463
                case 'b':
 
464
                        binary = 1;
 
465
                        file = binfile;
 
466
                        break;
 
467
                case 'd':
 
468
                        debug = 1;
 
469
                        break;
 
470
                case 'V':
 
471
                        show_version = 1;
 
472
                        break;
 
473
                case 'c': {
 
474
                        long int n = strtol(optarg, NULL, 10);
 
475
                        if (errno) {
 
476
                                fprintf(stderr, "Invalid policyvers specified: %s\n", optarg);
 
477
                                usage(argv[0]);
 
478
                                exit(1);
 
479
                        }
 
480
                        if (n < POLICYDB_VERSION_MIN || n > POLICYDB_VERSION_MAX) {
 
481
                                fprintf(stderr, "policyvers value %ld not in range %d-%d\n",
 
482
                                        n, POLICYDB_VERSION_MIN, POLICYDB_VERSION_MAX);
 
483
                                usage(argv[0]);
 
484
                                exit(1);
 
485
                        }
 
486
                        if (policyvers != n)
 
487
                                policyvers = n;
 
488
                        break;
 
489
                }
 
490
                default:
 
491
                        usage(argv[0]);
 
492
                }
 
493
        }
 
494
 
 
495
        if (show_version) {
 
496
#ifdef CONFIG_SECURITY_SELINUX_MLS      
 
497
                printf("%d-mls (compatibility range %d-%d)\n", policyvers, POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN);
 
498
#else
 
499
                printf("%d (compatibility range %d-%d)\n", policyvers, POLICYDB_VERSION_MAX, POLICYDB_VERSION_MIN);
 
500
#endif
 
501
                exit(0);
 
502
        }
 
503
 
 
504
        if (optind != argc) {
 
505
                file = argv[optind++];
 
506
                if (optind != argc)
 
507
                        usage(argv[0]);
 
508
        }
 
509
        printf("%s:  loading policy configuration from %s\n", argv[0],
 
510
               file);
 
511
 
 
512
        if (binary) {
 
513
                fd = open(file, O_RDONLY);
 
514
                if (fd < 0) {
 
515
                        fprintf(stderr, "Can't open '%s':  %s\n",
 
516
                                file, strerror(errno));
 
517
                        exit(1);
 
518
                }
 
519
                if (fstat(fd, &sb) < 0) {
 
520
                        fprintf(stderr, "Can't stat '%s':  %s\n",
 
521
                                file, strerror(errno));
 
522
                        exit(1);
 
523
                }
 
524
                map = mmap(NULL, sb.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
 
525
                if (map == MAP_FAILED) {
 
526
                        fprintf(stderr, "Can't map '%s':  %s\n",
 
527
                                file, strerror(errno));
 
528
                        exit(1);
 
529
                }
 
530
                ret = security_load_policy(map,sb.st_size);
 
531
                if (ret) {
 
532
                        fprintf(stderr, "%s:  error(s) encountered while parsing configuration\n", argv[0]);
 
533
                        exit(1);
 
534
                }
 
535
                policydbp = &policydb;
 
536
        } else {
 
537
                yyin = fopen(file, "r");
 
538
                if (!yyin) {
 
539
                        fprintf(stderr, "%s:  unable to open %s\n", argv[0], 
 
540
                                file);
 
541
                        exit(1);
 
542
                }
 
543
 
 
544
                if (policydb_init(&policydb))
 
545
                        exit(1);
 
546
 
 
547
                id_queue = queue_create();
 
548
                if (!id_queue) {
 
549
                        fprintf(stderr, "%s:  out of memory\n", argv[0]);
 
550
                        exit(1);
 
551
                }
 
552
                policydbp = &policydb;
 
553
                policydb_errors = 0;
 
554
                pass = 1;
 
555
                if (yyparse() || policydb_errors) {
 
556
                        fprintf(stderr, "%s:  error(s) encountered while parsing configuration\n", argv[0]);
 
557
                        exit(1);
 
558
                }
 
559
                rewind(yyin);
 
560
                policydb_lineno = 1;
 
561
                source_file[0] = '\0';
 
562
                source_lineno = 1;
 
563
                yyrestart(yyin);
 
564
                pass = 2;
 
565
                if (yyparse() || policydb_errors) {
 
566
                        fprintf(stderr, "%s:  error(s) encountered while parsing configuration\n", argv[0]);
 
567
                        exit(1);
 
568
                }
 
569
                queue_destroy(id_queue);
 
570
 
 
571
                cond_check_type_rules();
 
572
                cond_optimize_lists(policydb.cond_list);
 
573
 
 
574
                check_assertions();
 
575
                if (policydb_errors) 
 
576
                        exit(1);
 
577
 
 
578
                /* remove type attributes */
 
579
                hashtab_map_remove_on_error(policydb.p_types.table, 
 
580
                                            type_attr_remove, 0, 0);
 
581
                fclose(yyin);
 
582
        }
 
583
 
 
584
        if (policydb_load_isids(&policydb, &sidtab))
 
585
                exit(1);
 
586
 
 
587
        printf("%s:  policy configuration loaded\n", argv[0]);
 
588
 
 
589
        if (outfile) {
 
590
                printf("%s:  writing binary representation (version %d) to %s\n",
 
591
                       argv[0], policyvers, outfile);
 
592
                outfp = fopen(outfile, "w");
 
593
                if (!outfp) {
 
594
                        perror(outfile);
 
595
                        exit(1);
 
596
                }
 
597
                ret = policydb_write(&policydb, outfp);
 
598
                if (ret) {
 
599
                        fprintf(stderr, "%s:  error writing %s\n",
 
600
                                argv[0], outfile);
 
601
                        exit(1);
 
602
                }
 
603
                fclose(outfp);
 
604
        }
 
605
        if (!debug)
 
606
                exit(0);
 
607
 
 
608
        ss_initialized = 1;
 
609
 
 
610
      menu:
 
611
        printf("\nSelect an option:\n");
 
612
        printf("0)  Call compute_access_vector\n");
 
613
        printf("1)  Call sid_to_context\n");
 
614
        printf("2)  Call context_to_sid\n");
 
615
        printf("3)  Call transition_sid\n");
 
616
        printf("4)  Call member_sid\n");
 
617
        printf("5)  Call change_sid\n");
 
618
        printf("6)  Call list_sids\n");
 
619
        printf("7)  Call load_policy\n");
 
620
        printf("8)  Call fs_sid\n");
 
621
        printf("9)  Call port_sid\n");
 
622
        printf("a)  Call netif_sid\n");
 
623
        printf("b)  Call node_sid\n");
 
624
        printf("c)  Call fs_use\n");
 
625
        printf("d)  Call genfs_sid\n");
 
626
        printf("e)  Call get_user_sids\n");
 
627
        printf("f)  display conditional bools\n");
 
628
        printf("g)  display conditional expressions\n");
 
629
        printf("h)  change a boolean value\n");
 
630
#ifdef EQUIVTYPES
 
631
        printf("z)  Show equivalent types\n");
 
632
#endif
 
633
        printf("m)  Show menu again\n");
 
634
        printf("q)  Exit\n");
 
635
        while (1) {
 
636
                printf("\nChoose:  ");
 
637
                fgets(ans, sizeof(ans), stdin);
 
638
                switch (ans[0]) {
 
639
                case '0':
 
640
                        printf("source sid?  ");
 
641
                        fgets(ans, sizeof(ans), stdin);
 
642
                        ssid = atoi(ans);
 
643
 
 
644
                        printf("target sid?  ");
 
645
                        fgets(ans, sizeof(ans), stdin);
 
646
                        tsid = atoi(ans);
 
647
 
 
648
                        printf("target class?  ");
 
649
                        fgets(ans, sizeof(ans), stdin);
 
650
                        if (isdigit(ans[0])) {
 
651
                                tclass = atoi(ans);
 
652
                                if (!tclass || tclass > policydb.p_classes.nprim) {
 
653
                                        printf("\nNo such class.\n");
 
654
                                        break;
 
655
                                }
 
656
                                cladatum = policydb.class_val_to_struct[tclass - 1];
 
657
                        } else {
 
658
                                ans[strlen(ans) - 1] = 0;
 
659
                                cladatum = (class_datum_t *) hashtab_search(policydb.p_classes.table,
 
660
                                                                    ans);
 
661
                                if (!cladatum) {
 
662
                                        printf("\nNo such class\n");
 
663
                                        break;
 
664
                                }
 
665
                                tclass = cladatum->value;
 
666
                        }
 
667
 
 
668
                        if (!cladatum->comdatum && !cladatum->permissions.nprim) {
 
669
                                printf("\nNo access vector definition for that class\n");
 
670
                                break;
 
671
                        }
 
672
                        ret = security_compute_av(ssid, tsid, tclass, 0,
 
673
                                                  &avd);
 
674
                        switch (ret) {
 
675
                        case 0:
 
676
                                printf("\nallowed {");
 
677
                                for (i = 1; i <= sizeof(avd.allowed) * 8; i++) {
 
678
                                        if (avd.allowed & (1 << (i - 1))) {
 
679
                                                v.val = i;
 
680
                                                ret = hashtab_map(cladatum->permissions.table,
 
681
                                                                   find_perm, &v);
 
682
                                                if (!ret && cladatum->comdatum) {
 
683
                                                        ret = hashtab_map(cladatum->comdatum->permissions.table,
 
684
                                                                         find_perm, &v);
 
685
                                                }
 
686
                                                if (ret)
 
687
                                                        printf(" %s", v.name);
 
688
                                        }
 
689
                                }
 
690
                                printf(" }\n");
 
691
                                break;
 
692
                        case -EINVAL:
 
693
                                printf("\ninvalid sid\n");
 
694
                                break;
 
695
                        default:
 
696
                                printf("return code 0x%x\n", ret);
 
697
                        }
 
698
                        break;
 
699
                case '1':
 
700
                        printf("sid?  ");
 
701
                        fgets(ans, sizeof(ans), stdin);
 
702
                        ssid = atoi(ans);
 
703
                        ret = security_sid_to_context(ssid,
 
704
                                               &scontext, &scontext_len);
 
705
                        switch (ret) {
 
706
                        case 0:
 
707
                                printf("\nscontext %s\n", scontext);
 
708
                                free(scontext);
 
709
                                break;
 
710
                        case -EINVAL:
 
711
                                printf("\ninvalid sid\n");
 
712
                                break;
 
713
                        case -ENOMEM:
 
714
                                printf("\nout of memory\n");
 
715
                                break;
 
716
                        default:
 
717
                                printf("return code 0x%x\n", ret);
 
718
                        }
 
719
                        break;
 
720
                case '2':
 
721
                        printf("scontext?  ");
 
722
                        fgets(ans, sizeof(ans), stdin);
 
723
                        scontext_len = strlen(ans);
 
724
                        ans[scontext_len - 1] = 0;
 
725
                        ret = security_context_to_sid(ans, scontext_len,
 
726
                                                      &ssid);
 
727
                        switch (ret) {
 
728
                        case 0:
 
729
                                printf("\nsid %d\n", ssid);
 
730
                                break;
 
731
                        case -EINVAL:
 
732
                                printf("\ninvalid context\n");
 
733
                                break;
 
734
                        case -ENOMEM:
 
735
                                printf("\nout of memory\n");
 
736
                                break;
 
737
                        default:
 
738
                                printf("return code 0x%x\n", ret);
 
739
                        }
 
740
                        break;
 
741
                case '3':
 
742
                case '4':
 
743
                case '5':
 
744
                        ch = ans[0];
 
745
 
 
746
                        printf("source sid?  ");
 
747
                        fgets(ans, sizeof(ans), stdin);
 
748
                        ssid = atoi(ans);
 
749
                        printf("target sid?  ");
 
750
                        fgets(ans, sizeof(ans), stdin);
 
751
                        tsid = atoi(ans);
 
752
 
 
753
                        printf("object class?  ");
 
754
                        fgets(ans, sizeof(ans), stdin);
 
755
                        if (isdigit(ans[0])) {
 
756
                                tclass = atoi(ans);
 
757
                                if (!tclass || tclass > policydb.p_classes.nprim) {
 
758
                                        printf("\nNo such class.\n");
 
759
                                        break;
 
760
                                }
 
761
                        } else {
 
762
                                ans[strlen(ans) - 1] = 0;
 
763
                                cladatum = (class_datum_t *) hashtab_search(policydb.p_classes.table,
 
764
                                                                    ans);
 
765
                                if (!cladatum) {
 
766
                                        printf("\nNo such class\n");
 
767
                                        break;
 
768
                                }
 
769
                                tclass = cladatum->value;
 
770
                        }
 
771
 
 
772
                        if (ch == '3')
 
773
                                ret = security_transition_sid(ssid, tsid, tclass, &ssid);
 
774
                        else if (ch == '4')
 
775
                                ret = security_member_sid(ssid, tsid, tclass, &ssid);
 
776
                        else 
 
777
                                ret = security_change_sid(ssid, tsid, tclass, &ssid);
 
778
                        switch (ret) {
 
779
                        case 0:
 
780
                                printf("\nsid %d\n", ssid);
 
781
                                break;
 
782
                        case -EINVAL:
 
783
                                printf("\ninvalid sid\n");
 
784
                                break;
 
785
                        case -ENOMEM:
 
786
                                printf("\nout of memory\n");
 
787
                                break;
 
788
                        default:
 
789
                                printf("return code 0x%x\n", ret);
 
790
                        }
 
791
                        break;
 
792
                case '6':
 
793
                        sidtab_map(&sidtab, print_sid, 0);
 
794
                        break;
 
795
                case '7':
 
796
                        printf("pathname?  ");
 
797
                        fgets(ans, sizeof(ans), stdin);
 
798
                        pathlen = strlen(ans);
 
799
                        ans[pathlen - 1] = 0;
 
800
                        printf("%s:  loading policy configuration from %s\n", argv[0], ans);
 
801
                        fd = open(ans, O_RDONLY);
 
802
                        if (fd < 0) {
 
803
                                fprintf(stderr, "Can't open '%s':  %s\n",
 
804
                                        ans, strerror(errno));
 
805
                                break;
 
806
                        }
 
807
                        if (fstat(fd, &sb) < 0) {
 
808
                                fprintf(stderr, "Can't stat '%s':  %s\n",
 
809
                                        ans, strerror(errno));
 
810
                                break;
 
811
                        }
 
812
                        map = mmap(NULL, sb.st_size, PROT_READ, MAP_SHARED, fd, 0);
 
813
                        if (map == MAP_FAILED) {
 
814
                                fprintf(stderr, "Can't map '%s':  %s\n",
 
815
                                        ans, strerror(errno));
 
816
                                break;
 
817
                        }
 
818
                        ret = security_load_policy(map,sb.st_size);
 
819
                        switch (ret) {
 
820
                        case 0:
 
821
                                printf("\nsuccess\n");
 
822
                                break;
 
823
                        case -EINVAL:
 
824
                                printf("\ninvalid policy\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 '8':
 
834
                        printf("fs kdevname?  ");
 
835
                        fgets(ans, sizeof(ans), stdin);
 
836
                        ans[strlen(ans) - 1] = 0;
 
837
                        security_fs_sid(ans, &ssid, &tsid);
 
838
                        printf("fs_sid %d default_file_sid %d\n",
 
839
                               ssid, tsid);
 
840
                        break;
 
841
                case '9':
 
842
                        printf("protocol?  ");
 
843
                        fgets(ans, sizeof(ans), stdin);
 
844
                        ans[strlen(ans) - 1] = 0;
 
845
                        if (!strcmp(ans, "tcp") || !strcmp(ans, "TCP"))
 
846
                                protocol = IPPROTO_TCP;
 
847
                        else if (!strcmp(ans, "udp") || !strcmp(ans, "UDP"))
 
848
                                protocol = IPPROTO_UDP;
 
849
                        else {
 
850
                                printf("unknown protocol\n");
 
851
                                break;
 
852
                        }
 
853
                        printf("port? ");
 
854
                        fgets(ans, sizeof(ans), stdin);
 
855
                        port = atoi(ans);
 
856
                        security_port_sid(0, 0, protocol, port, &ssid);
 
857
                        printf("sid %d\n", ssid);
 
858
                        break;
 
859
                case 'a':
 
860
                        printf("netif name?  ");
 
861
                        fgets(ans, sizeof(ans), stdin);
 
862
                        ans[strlen(ans) - 1] = 0;
 
863
                        security_netif_sid(ans, &ssid, &tsid);
 
864
                        printf("if_sid %d default_msg_sid %d\n",
 
865
                               ssid, tsid);
 
866
                        break;
 
867
                case 'b': {
 
868
                        char *p;
 
869
                        int family, len;
 
870
                        struct in_addr addr4;
 
871
                        struct in6_addr addr6;
 
872
                        
 
873
                        printf("protocol family? ");
 
874
                        fgets(ans, sizeof(ans), stdin);
 
875
                        ans[strlen(ans) - 1] = 0;
 
876
                        if (!strcasecmp(ans, "ipv4"))
 
877
                                family = AF_INET;
 
878
                        else if (!strcasecmp(ans, "ipv6"))
 
879
                                family = AF_INET6;
 
880
                        else {
 
881
                                printf("unknown protocol family\n");
 
882
                                break;
 
883
                        }
 
884
                        
 
885
                        printf("node address?  ");
 
886
                        fgets(ans, sizeof(ans), stdin);
 
887
                        ans[strlen(ans) - 1] = 0;
 
888
                        
 
889
                        if (family == AF_INET) {
 
890
                                p = (char *)&addr4;
 
891
                                len = sizeof(addr4);
 
892
                        } else {
 
893
                                p = (char *)&addr6;
 
894
                                len = sizeof(addr6);
 
895
                        }
 
896
                        
 
897
                        if (inet_pton(family, ans, p) < 1) {
 
898
                                printf("error parsing address\n");
 
899
                                break;
 
900
                        }
 
901
 
 
902
                        security_node_sid(family, p, len, &ssid);
 
903
                        printf("sid %d\n", ssid);
 
904
                        break;
 
905
                }       
 
906
                case 'c':
 
907
                        printf("fstype?  ");
 
908
                        fgets(ans, sizeof(ans), stdin);
 
909
                        ans[strlen(ans) - 1] = 0;
 
910
                        security_fs_use(ans, &ret, &ssid);
 
911
                        switch (ret) {
 
912
                        case SECURITY_FS_USE_XATTR:
 
913
                                printf("use xattr\n");
 
914
                                break;
 
915
                        case SECURITY_FS_USE_TRANS:
 
916
                                printf("use transition SIDs\n");
 
917
                                break;
 
918
                        case SECURITY_FS_USE_TASK:
 
919
                                printf("use task SIDs\n");
 
920
                                break;
 
921
                        case SECURITY_FS_USE_GENFS:
 
922
                                printf("use genfs\n");
 
923
                                break;
 
924
                        case SECURITY_FS_USE_NONE:
 
925
                                printf("no labeling support\n");
 
926
                                break;
 
927
                        }
 
928
                        printf("sid %d\n", ssid);
 
929
                        break;
 
930
                case 'd':
 
931
                        printf("fstype?  ");
 
932
                        fgets(ans, sizeof(ans), stdin);
 
933
                        ans[strlen(ans) - 1] = 0;
 
934
                        fstype = strdup(ans);
 
935
                        printf("path?  ");
 
936
                        fgets(ans, sizeof(ans), stdin);
 
937
                        ans[strlen(ans) - 1] = 0;
 
938
                        path = strdup(ans);
 
939
                        printf("object class?  ");
 
940
                        fgets(ans, sizeof(ans), stdin);
 
941
                        if (isdigit(ans[0])) {
 
942
                                tclass = atoi(ans);
 
943
                                if (!tclass || tclass > policydb.p_classes.nprim) {
 
944
                                        printf("\nNo such class.\n");
 
945
                                        break;
 
946
                                }
 
947
                        } else {
 
948
                                ans[strlen(ans) - 1] = 0;
 
949
                                cladatum = (class_datum_t *) hashtab_search(policydb.p_classes.table,
 
950
                                                                    ans);
 
951
                                if (!cladatum) {
 
952
                                        printf("\nNo such class\n");
 
953
                                        break;
 
954
                                }
 
955
                                tclass = cladatum->value;
 
956
                        }
 
957
                        security_genfs_sid(fstype, path, tclass, &ssid);
 
958
                        printf("sid %d\n", ssid);
 
959
                        free(fstype);
 
960
                        free(path);
 
961
                        break;
 
962
                case 'e':
 
963
                        printf("from SID?  ");
 
964
                        fgets(ans, sizeof(ans), stdin);
 
965
                        ans[strlen(ans) - 1] = 0;
 
966
                        ssid = atoi(ans);
 
967
 
 
968
                        printf("username?  ");
 
969
                        fgets(ans, sizeof(ans), stdin);
 
970
                        ans[strlen(ans) - 1] = 0;
 
971
 
 
972
                        ret = security_get_user_sids(ssid, ans, &sids, &nel);
 
973
                        switch (ret) {
 
974
                        case 0:
 
975
                                if (!nel)
 
976
                                        printf("\nnone\n");
 
977
                                for (i = 0; i < nel; i++)
 
978
                                        print_sid(sids[i],NULL,NULL);
 
979
                                free(sids);
 
980
                                break;
 
981
                        case -ENOMEM:
 
982
                                printf("\nout of memory\n");
 
983
                                break;
 
984
                        case -EINVAL:
 
985
                                printf("\ninvalid argument\n");
 
986
                                break;
 
987
                        default:
 
988
                                printf("\nerror\n");
 
989
                                break;
 
990
                        }
 
991
                        break;
 
992
                case 'f':
 
993
                        display_bools();
 
994
                        break;
 
995
                case 'g':
 
996
                        display_cond_expressions();
 
997
                        break;
 
998
                case 'h':
 
999
                        printf("name? ");
 
1000
                        fgets(ans, sizeof(ans), stdin);
 
1001
                        ans[strlen(ans) - 1] = 0;
 
1002
                        
 
1003
                        name = malloc((strlen(ans) + 1) * sizeof(char));
 
1004
                        if (name == NULL) {
 
1005
                                fprintf(stderr, "couldn't malloc string.\n");
 
1006
                                break;
 
1007
                        }
 
1008
                        strcpy(name, ans);
 
1009
 
 
1010
 
 
1011
                        printf("state? ");
 
1012
                        fgets(ans, sizeof(ans), stdin);
 
1013
                        ans[strlen(ans) - 1] = 0;
 
1014
 
 
1015
                        if (atoi(ans))
 
1016
                                state = 1;
 
1017
                        else
 
1018
                                state = 0;
 
1019
 
 
1020
                        change_bool(name, state);
 
1021
                        free(name);
 
1022
                        break;
 
1023
#ifdef EQUIVTYPES
 
1024
                case 'z':
 
1025
                        identify_equiv_types();
 
1026
                        break;
 
1027
#endif
 
1028
                case 'm':
 
1029
                        goto menu;
 
1030
                case 'q':
 
1031
                        exit(0);
 
1032
                        break;
 
1033
                default:
 
1034
                        printf("\nUnknown option %s.\n", ans);
 
1035
                }
 
1036
        }
 
1037
 
 
1038
        return 0;
 
1039
}
 
1040
 
 
1041
/* FLASK */
 
1042