Coverage Report

Created: 2026-08-31 06:40

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/selinux/libsepol/cil/src/cil_build_ast.c
Line
Count
Source
1
/*
2
 * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3
 * 
4
 * Redistribution and use in source and binary forms, with or without
5
 * modification, are permitted provided that the following conditions are met:
6
 * 
7
 *    1. Redistributions of source code must retain the above copyright notice,
8
 *       this list of conditions and the following disclaimer.
9
 * 
10
 *    2. Redistributions in binary form must reproduce the above copyright notice,
11
 *       this list of conditions and the following disclaimer in the documentation
12
 *       and/or other materials provided with the distribution.
13
 * 
14
 * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17
 * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21
 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22
 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24
 * 
25
 * The views and conclusions contained in the software and documentation are those
26
 * of the authors and should not be interpreted as representing official policies,
27
 * either expressed or implied, of Tresys Technology, LLC.
28
 */
29
30
#include <stdlib.h>
31
#include <stdio.h>
32
#include <string.h>
33
#include <ctype.h>
34
35
#include <sepol/policydb/conditional.h>
36
37
#include "cil_internal.h"
38
#include "cil_flavor.h"
39
#include "cil_log.h"
40
#include "cil_mem.h"
41
#include "cil_tree.h"
42
#include "cil_list.h"
43
#include "cil_parser.h"
44
#include "cil_build_ast.h"
45
#include "cil_copy_ast.h"
46
#include "cil_verify.h"
47
#include "cil_strpool.h"
48
49
struct cil_args_build {
50
  struct cil_tree_node *ast;
51
  struct cil_db *db;
52
  struct cil_tree_node *tunif;
53
  struct cil_tree_node *in;
54
  struct cil_tree_node *macro;
55
  struct cil_tree_node *optional;
56
  struct cil_tree_node *boolif;
57
};
58
59
static int cil_fill_list(struct cil_tree_node *current, enum cil_flavor flavor,
60
       struct cil_list **list)
61
0
{
62
0
  int rc = SEPOL_ERR;
63
0
  struct cil_tree_node *curr;
64
0
  enum cil_syntax syntax[] = { CIL_SYN_N_STRINGS, CIL_SYN_END };
65
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
66
67
0
  rc = __cil_verify_syntax(current, syntax, syntax_len);
68
0
  if (rc != SEPOL_OK) {
69
0
    goto exit;
70
0
  }
71
72
0
  cil_list_init(list, flavor);
73
74
0
  for (curr = current; curr != NULL; curr = curr->next) {
75
0
    cil_list_append(*list, CIL_STRING, curr->data);
76
0
  }
77
78
0
  return SEPOL_OK;
79
80
0
exit:
81
0
  return rc;
82
0
}
83
84
struct cil_symtab_datum *cil_gen_declared_string(struct cil_db *db,
85
             hashtab_key_t key,
86
             struct cil_tree_node *ast_node)
87
0
{
88
0
  struct cil_tree_node *parent = ast_node->parent;
89
0
  struct cil_macro *macro = NULL;
90
0
  symtab_t *symtab;
91
0
  struct cil_symtab_datum *datum;
92
93
0
  while (parent) {
94
0
    if (parent->flavor == CIL_MACRO) {
95
      /* This condition is only reached in the build phase */
96
0
      macro = parent->data;
97
0
      break;
98
0
    } else if (parent->flavor == CIL_CALL) {
99
      /* This condition is only reached in the resolve phase */
100
0
      struct cil_call *call = parent->data;
101
0
      macro = call->macro;
102
0
      break;
103
0
    }
104
0
    parent = parent->parent;
105
0
  }
106
107
0
  if (macro && macro->params) {
108
0
    struct cil_list_item *item;
109
0
    cil_list_for_each(item, macro->params) {
110
0
      struct cil_param *param = item->data;
111
0
      if (param->flavor == CIL_DECLARED_STRING &&
112
0
          param->str == key) {
113
0
        return NULL;
114
0
      }
115
0
    }
116
0
  }
117
118
0
  symtab = &((struct cil_root *)db->ast->root->data)
119
0
        ->symtab[CIL_SYM_STRINGS];
120
0
  cil_symtab_get_datum(symtab, key, &datum);
121
0
  if (datum != NULL) {
122
0
    return datum;
123
0
  }
124
125
0
  datum = cil_malloc(sizeof(*datum));
126
0
  cil_symtab_datum_init(datum);
127
0
  cil_symtab_insert(symtab, key, datum, ast_node);
128
0
  cil_list_append(db->declared_strings, CIL_DATUM, datum);
129
0
  return datum;
130
0
}
131
132
static int cil_allow_multiple_decls(struct cil_db *db, enum cil_flavor f_new,
133
            enum cil_flavor f_old)
134
0
{
135
0
  if (f_new != f_old) {
136
0
    return CIL_FALSE;
137
0
  }
138
139
0
  switch (f_new) {
140
0
  case CIL_TYPE:
141
0
  case CIL_TYPEATTRIBUTE:
142
0
  case CIL_ROLE:
143
0
    if (db->multiple_decls) {
144
0
      return CIL_TRUE;
145
0
    }
146
0
    break;
147
0
  case CIL_OPTIONAL:
148
0
    return CIL_TRUE;
149
0
    break;
150
0
  case CIL_POLICYCAP:
151
0
    return CIL_TRUE;
152
0
    break;
153
0
  default:
154
0
    break;
155
0
  }
156
157
0
  return CIL_FALSE;
158
0
}
159
160
int cil_add_decl_to_symtab(struct cil_db *db, symtab_t *symtab,
161
         hashtab_key_t key, struct cil_symtab_datum *datum,
162
         struct cil_tree_node *node)
163
0
{
164
0
  int rc;
165
166
0
  if (symtab == NULL || datum == NULL || node == NULL) {
167
0
    return SEPOL_ERR;
168
0
  }
169
170
0
  rc = cil_symtab_insert(symtab, key, datum, node);
171
0
  if (rc == SEPOL_EEXIST) {
172
0
    struct cil_symtab_datum *prev;
173
0
    rc = cil_symtab_get_datum(symtab, key, &prev);
174
0
    if (rc != SEPOL_OK) {
175
0
      cil_log(CIL_ERR,
176
0
        "Re-declaration of %s %s, but previous declaration could not be found\n",
177
0
        cil_node_to_string(node), key);
178
0
      return SEPOL_ERR;
179
0
    }
180
0
    if (!cil_allow_multiple_decls(db, node->flavor, FLAVOR(prev))) {
181
      /* multiple_decls not ok, ret error */
182
0
      struct cil_tree_node *n = NODE(prev);
183
0
      cil_log(CIL_ERR, "Re-declaration of %s %s\n",
184
0
        cil_node_to_string(node), key);
185
0
      cil_tree_log(node, CIL_ERR,
186
0
             "Previous declaration of %s",
187
0
             cil_node_to_string(n));
188
0
      return SEPOL_ERR;
189
0
    }
190
    /* multiple_decls is enabled and works for this datum type, add node */
191
0
    cil_list_append(prev->nodes, CIL_NODE, node);
192
0
    node->data = prev;
193
0
    return SEPOL_EEXIST;
194
0
  }
195
196
0
  return SEPOL_OK;
197
0
}
198
199
int cil_gen_node(struct cil_db *db, struct cil_tree_node *ast_node,
200
     struct cil_symtab_datum *datum, hashtab_key_t key,
201
     enum cil_sym_index sflavor, enum cil_flavor nflavor)
202
0
{
203
0
  int rc = SEPOL_ERR;
204
0
  symtab_t *symtab = NULL;
205
206
0
  rc = cil_verify_name(db, (const char *)key, nflavor);
207
0
  if (rc != SEPOL_OK) {
208
0
    goto exit;
209
0
  }
210
211
0
  rc = cil_get_symtab(ast_node->parent, &symtab, sflavor);
212
0
  if (rc != SEPOL_OK) {
213
0
    goto exit;
214
0
  }
215
216
0
  ast_node->data = datum;
217
0
  ast_node->flavor = nflavor;
218
219
0
  rc = cil_add_decl_to_symtab(db, symtab, key, datum, ast_node);
220
0
  if (rc != SEPOL_OK) {
221
0
    goto exit;
222
0
  }
223
224
0
  if (ast_node->parent->flavor == CIL_MACRO) {
225
0
    rc = cil_verify_decl_does_not_shadow_macro_parameter(
226
0
      ast_node->parent->data, ast_node, key);
227
0
    if (rc != SEPOL_OK) {
228
0
      goto exit;
229
0
    }
230
0
  }
231
232
0
  return SEPOL_OK;
233
234
0
exit:
235
0
  return rc;
236
0
}
237
238
static void cil_clear_node(struct cil_tree_node *ast_node)
239
0
{
240
0
  if (ast_node == NULL) {
241
0
    return;
242
0
  }
243
244
0
  ast_node->data = NULL;
245
0
  ast_node->flavor = CIL_NONE;
246
0
}
247
248
int cil_gen_ordered(struct cil_db *db, struct cil_tree_node *parse_current,
249
        struct cil_tree_node *ast_node, enum cil_flavor flavor)
250
0
{
251
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_LIST,
252
0
             CIL_SYN_END };
253
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
254
0
  struct cil_ordered *ordered = NULL;
255
0
  struct cil_list_item *curr = NULL;
256
257
0
  int rc = SEPOL_ERR;
258
259
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
260
0
    goto exit;
261
0
  }
262
263
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
264
0
  if (rc != SEPOL_OK) {
265
0
    goto exit;
266
0
  }
267
268
0
  cil_ordered_init(&ordered);
269
270
0
  rc = cil_fill_list(parse_current->next->cl_head, flavor,
271
0
         &ordered->strs);
272
0
  if (rc != SEPOL_OK) {
273
0
    goto exit;
274
0
  }
275
276
0
  cil_list_for_each(curr, ordered->strs) {
277
0
    if (curr->data == CIL_KEY_UNORDERED) {
278
0
      if (flavor == CIL_CLASSORDER) {
279
0
        if (curr == ordered->strs->head &&
280
0
            curr->next == NULL) {
281
0
          cil_log(CIL_ERR,
282
0
            "classorder 'unordered' keyword must be followed by one or more class.\n");
283
0
          rc = SEPOL_ERR;
284
0
          goto exit;
285
0
        } else if (curr != ordered->strs->head) {
286
0
          cil_log(CIL_ERR,
287
0
            "classorder can only use 'unordered' keyword as the first item in the list.\n");
288
0
          rc = SEPOL_ERR;
289
0
          goto exit;
290
0
        }
291
0
      } else {
292
0
        cil_log(CIL_ERR,
293
0
          "The 'unordered' keyword can only be used with classorder rules.\n");
294
0
        rc = SEPOL_ERR;
295
0
        goto exit;
296
0
      }
297
0
    }
298
0
  }
299
300
0
  ast_node->data = ordered;
301
0
  ast_node->flavor = flavor;
302
303
0
  return SEPOL_OK;
304
305
0
exit:
306
0
  cil_tree_log(parse_current, CIL_ERR, "Bad ordered declaration");
307
0
  cil_destroy_ordered(ordered);
308
0
  return rc;
309
0
}
310
311
void cil_destroy_ordered(struct cil_ordered *ordered)
312
0
{
313
0
  if (ordered == NULL) {
314
0
    return;
315
0
  }
316
317
0
  if (ordered->strs != NULL) {
318
0
    cil_list_destroy(&ordered->strs, CIL_FALSE);
319
0
  }
320
0
  if (ordered->datums != NULL) {
321
0
    cil_list_destroy(&ordered->datums, CIL_FALSE);
322
0
  }
323
324
0
  free(ordered);
325
0
}
326
327
int cil_gen_block(struct cil_db *db, struct cil_tree_node *parse_current,
328
      struct cil_tree_node *ast_node, uint16_t is_abstract)
329
0
{
330
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
331
0
             CIL_SYN_N_LISTS | CIL_SYN_END,
332
0
             CIL_SYN_END };
333
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
334
0
  char *key = NULL;
335
0
  struct cil_block *block = NULL;
336
0
  int rc = SEPOL_ERR;
337
338
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
339
0
    goto exit;
340
0
  }
341
342
0
  if (db->qualified_names) {
343
0
    cil_log(CIL_ERR,
344
0
      "Blocks are not allowed when the option for qualified names is used\n");
345
0
    goto exit;
346
0
  }
347
348
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
349
0
  if (rc != SEPOL_OK) {
350
0
    goto exit;
351
0
  }
352
353
0
  cil_block_init(&block);
354
355
0
  block->is_abstract = is_abstract;
356
357
0
  key = parse_current->next->data;
358
359
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)block,
360
0
        (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_BLOCK);
361
0
  if (rc != SEPOL_OK) {
362
0
    goto exit;
363
0
  }
364
365
0
  return SEPOL_OK;
366
367
0
exit:
368
0
  cil_tree_log(parse_current, CIL_ERR, "Bad block declaration");
369
0
  cil_destroy_block(block);
370
0
  cil_clear_node(ast_node);
371
0
  return rc;
372
0
}
373
374
void cil_destroy_block(struct cil_block *block)
375
0
{
376
0
  struct cil_list_item *item;
377
0
  struct cil_tree_node *bi_node;
378
0
  struct cil_blockinherit *inherit;
379
380
0
  if (block == NULL) {
381
0
    return;
382
0
  }
383
384
0
  cil_symtab_datum_destroy(&block->datum);
385
0
  cil_symtab_array_destroy(block->symtab);
386
0
  if (block->bi_nodes != NULL) {
387
    /* unlink blockinherit->block */
388
0
    cil_list_for_each(item, block->bi_nodes) {
389
0
      bi_node = item->data;
390
      /* the conditions should always be true, but better be sure */
391
0
      if (bi_node->flavor == CIL_BLOCKINHERIT) {
392
0
        inherit = bi_node->data;
393
0
        if (inherit->block == block) {
394
0
          inherit->block = NULL;
395
0
        }
396
0
      }
397
0
    }
398
0
    cil_list_destroy(&block->bi_nodes, CIL_FALSE);
399
0
  }
400
401
0
  free(block);
402
0
}
403
404
int cil_gen_blockinherit(struct cil_db *db, struct cil_tree_node *parse_current,
405
       struct cil_tree_node *ast_node)
406
0
{
407
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
408
0
             CIL_SYN_END };
409
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
410
0
  struct cil_blockinherit *inherit = NULL;
411
0
  int rc = SEPOL_ERR;
412
413
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
414
0
    goto exit;
415
0
  }
416
417
0
  if (db->qualified_names) {
418
0
    cil_log(CIL_ERR,
419
0
      "Block inherit rules are not allowed when the option for qualified names is used\n");
420
0
    goto exit;
421
0
  }
422
423
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
424
0
  if (rc != SEPOL_OK) {
425
0
    goto exit;
426
0
  }
427
428
0
  cil_blockinherit_init(&inherit);
429
430
0
  inherit->block_str = parse_current->next->data;
431
432
0
  ast_node->data = inherit;
433
0
  ast_node->flavor = CIL_BLOCKINHERIT;
434
435
0
  return SEPOL_OK;
436
437
0
exit:
438
0
  cil_tree_log(parse_current, CIL_ERR, "Bad blockinherit declaration");
439
0
  cil_destroy_blockinherit(inherit);
440
0
  return rc;
441
0
}
442
443
void cil_destroy_blockinherit(struct cil_blockinherit *inherit)
444
0
{
445
0
  if (inherit == NULL) {
446
0
    return;
447
0
  }
448
449
0
  if (inherit->block != NULL && inherit->block->bi_nodes != NULL) {
450
0
    struct cil_tree_node *node;
451
0
    struct cil_list_item *item;
452
453
0
    cil_list_for_each(item, inherit->block->bi_nodes) {
454
0
      node = item->data;
455
0
      if (node->data == inherit) {
456
0
        cil_list_remove(inherit->block->bi_nodes,
457
0
            CIL_NODE, node, CIL_FALSE);
458
0
        break;
459
0
      }
460
0
    }
461
0
  }
462
463
0
  free(inherit);
464
0
}
465
466
int cil_gen_blockabstract(struct cil_db *db,
467
        struct cil_tree_node *parse_current,
468
        struct cil_tree_node *ast_node)
469
0
{
470
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
471
0
             CIL_SYN_END };
472
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
473
0
  struct cil_blockabstract *abstract = NULL;
474
0
  int rc = SEPOL_ERR;
475
476
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
477
0
    goto exit;
478
0
  }
479
480
0
  if (db->qualified_names) {
481
0
    cil_log(CIL_ERR,
482
0
      "Block abstract rules are not allowed when the option for qualified names is used\n");
483
0
    goto exit;
484
0
  }
485
486
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
487
0
  if (rc != SEPOL_OK) {
488
0
    goto exit;
489
0
  }
490
491
0
  cil_blockabstract_init(&abstract);
492
493
0
  abstract->block_str = parse_current->next->data;
494
495
0
  ast_node->data = abstract;
496
0
  ast_node->flavor = CIL_BLOCKABSTRACT;
497
498
0
  return SEPOL_OK;
499
500
0
exit:
501
0
  cil_tree_log(parse_current, CIL_ERR, "Bad blockabstract declaration");
502
0
  cil_destroy_blockabstract(abstract);
503
0
  return rc;
504
0
}
505
506
void cil_destroy_blockabstract(struct cil_blockabstract *abstract)
507
0
{
508
0
  if (abstract == NULL) {
509
0
    return;
510
0
  }
511
512
0
  free(abstract);
513
0
}
514
515
int cil_gen_in(struct cil_db *db, struct cil_tree_node *parse_current,
516
         struct cil_tree_node *ast_node)
517
0
{
518
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
519
0
             CIL_SYN_STRING | CIL_SYN_N_LISTS,
520
0
             CIL_SYN_N_LISTS | CIL_SYN_END,
521
0
             CIL_SYN_END };
522
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
523
0
  int rc = SEPOL_ERR;
524
0
  struct cil_in *in = NULL;
525
526
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
527
0
    goto exit;
528
0
  }
529
530
0
  if (db->qualified_names) {
531
0
    cil_log(CIL_ERR,
532
0
      "In-statements are not allowed when the option for qualified names is used\n");
533
0
    goto exit;
534
0
  }
535
536
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
537
0
  if (rc != SEPOL_OK) {
538
0
    goto exit;
539
0
  }
540
541
0
  cil_in_init(&in);
542
543
0
  if (parse_current->next->next->data) {
544
0
    char *is_after_str = parse_current->next->data;
545
0
    if (is_after_str == CIL_KEY_IN_BEFORE) {
546
0
      in->is_after = CIL_FALSE;
547
0
    } else if (is_after_str == CIL_KEY_IN_AFTER) {
548
0
      in->is_after = CIL_TRUE;
549
0
    } else {
550
0
      cil_log(CIL_ERR,
551
0
        "Value must be either \'before\' or \'after\'\n");
552
0
      rc = SEPOL_ERR;
553
0
      goto exit;
554
0
    }
555
0
    in->block_str = parse_current->next->next->data;
556
0
  } else {
557
0
    in->is_after = CIL_FALSE;
558
0
    in->block_str = parse_current->next->data;
559
0
  }
560
561
0
  ast_node->data = in;
562
0
  ast_node->flavor = CIL_IN;
563
564
0
  return SEPOL_OK;
565
0
exit:
566
0
  cil_tree_log(parse_current, CIL_ERR, "Bad in-statement");
567
0
  cil_destroy_in(in);
568
0
  return rc;
569
0
}
570
571
void cil_destroy_in(struct cil_in *in)
572
0
{
573
0
  if (in == NULL) {
574
0
    return;
575
0
  }
576
577
0
  cil_symtab_array_destroy(in->symtab);
578
579
0
  free(in);
580
0
}
581
582
int cil_gen_class(struct cil_db *db, struct cil_tree_node *parse_current,
583
      struct cil_tree_node *ast_node)
584
0
{
585
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
586
0
             CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
587
0
             CIL_SYN_END };
588
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
589
0
  char *key = NULL;
590
0
  struct cil_class *class = NULL;
591
0
  struct cil_tree_node *perms = NULL;
592
0
  int rc = SEPOL_ERR;
593
594
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
595
0
  if (rc != SEPOL_OK) {
596
0
    goto exit;
597
0
  }
598
599
0
  cil_class_init(&class);
600
601
0
  key = parse_current->next->data;
602
0
  if (key == CIL_KEY_UNORDERED) {
603
0
    cil_log(CIL_ERR,
604
0
      "'unordered' keyword is reserved and not a valid class name.\n");
605
0
    rc = SEPOL_ERR;
606
0
    goto exit;
607
0
  }
608
609
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)class,
610
0
        (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_CLASS);
611
0
  if (rc != SEPOL_OK) {
612
0
    goto exit;
613
0
  }
614
615
0
  if (parse_current->next->next != NULL) {
616
0
    perms = parse_current->next->next->cl_head;
617
0
    rc = cil_gen_perm_nodes(db, perms, ast_node, CIL_PERM,
618
0
          &class->num_perms);
619
0
    if (rc != SEPOL_OK) {
620
0
      goto exit;
621
0
    }
622
0
    if (class->num_perms > CIL_PERMS_PER_CLASS) {
623
0
      cil_tree_log(parse_current, CIL_ERR,
624
0
             "Too many permissions in class '%s'",
625
0
             class->datum.name);
626
0
      cil_tree_children_destroy(ast_node);
627
0
      rc = SEPOL_ERR;
628
0
      goto exit;
629
0
    }
630
0
  }
631
632
0
  return SEPOL_OK;
633
634
0
exit:
635
0
  cil_tree_log(parse_current, CIL_ERR, "Bad class declaration");
636
0
  cil_destroy_class(class);
637
0
  cil_clear_node(ast_node);
638
0
  return rc;
639
0
}
640
641
void cil_destroy_class(struct cil_class *class)
642
0
{
643
0
  if (class == NULL) {
644
0
    return;
645
0
  }
646
647
0
  cil_symtab_datum_destroy(&class->datum);
648
0
  cil_symtab_destroy(&class->perms);
649
650
0
  free(class);
651
0
}
652
653
int cil_gen_perm(struct cil_db *db, struct cil_tree_node *parse_current,
654
     struct cil_tree_node *ast_node, enum cil_flavor flavor,
655
     unsigned int *num_perms)
656
0
{
657
0
  char *key = NULL;
658
0
  struct cil_perm *perm = NULL;
659
0
  int rc = SEPOL_ERR;
660
661
0
  cil_perm_init(&perm);
662
663
0
  key = parse_current->data;
664
0
  if (key == NULL) {
665
0
    cil_log(CIL_ERR, "Bad permission\n");
666
0
    goto exit;
667
0
  }
668
669
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)perm,
670
0
        (hashtab_key_t)key, CIL_SYM_PERMS, flavor);
671
0
  if (rc != SEPOL_OK) {
672
0
    goto exit;
673
0
  }
674
675
0
  perm->value = *num_perms;
676
0
  (*num_perms)++;
677
678
0
  return SEPOL_OK;
679
680
0
exit:
681
0
  cil_destroy_perm(perm);
682
0
  cil_clear_node(ast_node);
683
0
  return rc;
684
0
}
685
686
void cil_destroy_perm(struct cil_perm *perm)
687
0
{
688
0
  if (perm == NULL) {
689
0
    return;
690
0
  }
691
692
0
  cil_symtab_datum_destroy(&perm->datum);
693
0
  cil_list_destroy(&perm->classperms, CIL_FALSE);
694
695
0
  free(perm);
696
0
}
697
698
int cil_gen_perm_nodes(struct cil_db *db, struct cil_tree_node *current_perm,
699
           struct cil_tree_node *ast_node, enum cil_flavor flavor,
700
           unsigned int *num_perms)
701
0
{
702
0
  int rc = SEPOL_ERR;
703
0
  struct cil_tree_node *new_ast = NULL;
704
705
0
  while (current_perm != NULL) {
706
0
    if (current_perm->cl_head != NULL) {
707
0
      rc = SEPOL_ERR;
708
0
      goto exit;
709
0
    }
710
0
    cil_tree_node_init(&new_ast);
711
0
    new_ast->parent = ast_node;
712
0
    new_ast->line = current_perm->line;
713
0
    new_ast->hll_offset = current_perm->hll_offset;
714
715
0
    rc = cil_gen_perm(db, current_perm, new_ast, flavor, num_perms);
716
0
    if (rc != SEPOL_OK) {
717
0
      cil_tree_node_destroy(&new_ast);
718
0
      goto exit;
719
0
    }
720
721
0
    if (ast_node->cl_head == NULL) {
722
0
      ast_node->cl_head = new_ast;
723
0
    } else {
724
0
      ast_node->cl_tail->next = new_ast;
725
0
    }
726
0
    ast_node->cl_tail = new_ast;
727
728
0
    current_perm = current_perm->next;
729
0
  }
730
731
0
  return SEPOL_OK;
732
733
0
exit:
734
0
  cil_log(CIL_ERR, "Bad permissions\n");
735
0
  cil_tree_children_destroy(ast_node);
736
0
  cil_clear_node(ast_node);
737
0
  return rc;
738
0
}
739
740
int cil_fill_perms(struct cil_tree_node *start_perm, struct cil_list **perms)
741
0
{
742
0
  int rc = SEPOL_ERR;
743
0
  enum cil_syntax syntax[] = { CIL_SYN_N_STRINGS | CIL_SYN_N_LISTS,
744
0
             CIL_SYN_END };
745
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
746
747
0
  rc = __cil_verify_syntax(start_perm->cl_head, syntax, syntax_len);
748
0
  if (rc != SEPOL_OK) {
749
0
    goto exit;
750
0
  }
751
752
0
  rc = cil_gen_expr(start_perm, CIL_PERM, perms);
753
0
  if (rc != SEPOL_OK) {
754
0
    goto exit;
755
0
  }
756
757
0
  return SEPOL_OK;
758
759
0
exit:
760
0
  cil_log(CIL_ERR, "Bad permission list or expression\n");
761
0
  return rc;
762
0
}
763
764
int cil_fill_classperms(struct cil_tree_node *parse_current,
765
      struct cil_classperms **cp)
766
0
{
767
0
  int rc = SEPOL_ERR;
768
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_LIST,
769
0
             CIL_SYN_END };
770
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
771
772
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
773
0
  if (rc != SEPOL_OK) {
774
0
    goto exit;
775
0
  }
776
777
0
  cil_classperms_init(cp);
778
779
0
  (*cp)->class_str = parse_current->data;
780
781
0
  rc = cil_fill_perms(parse_current->next, &(*cp)->perm_strs);
782
0
  if (rc != SEPOL_OK) {
783
0
    cil_destroy_classperms(*cp);
784
0
    goto exit;
785
0
  }
786
787
0
  return SEPOL_OK;
788
789
0
exit:
790
0
  cil_log(CIL_ERR, "Bad class-permissions\n");
791
0
  *cp = NULL;
792
0
  return rc;
793
0
}
794
795
void cil_destroy_classperms(struct cil_classperms *cp)
796
0
{
797
0
  if (cp == NULL) {
798
0
    return;
799
0
  }
800
801
0
  cil_list_destroy(&cp->perm_strs, CIL_TRUE);
802
0
  cil_list_destroy(&cp->perms, CIL_FALSE);
803
804
0
  free(cp);
805
0
}
806
807
void cil_fill_classperms_set(struct cil_tree_node *parse_current,
808
           struct cil_classperms_set **cp_set)
809
0
{
810
0
  cil_classperms_set_init(cp_set);
811
0
  (*cp_set)->set_str = parse_current->data;
812
0
}
813
814
void cil_destroy_classperms_set(struct cil_classperms_set *cp_set)
815
0
{
816
0
  if (cp_set == NULL) {
817
0
    return;
818
0
  }
819
820
0
  free(cp_set);
821
0
}
822
823
int cil_fill_classperms_list(struct cil_tree_node *parse_current,
824
           struct cil_list **cp_list)
825
0
{
826
0
  int rc = SEPOL_ERR;
827
0
  struct cil_tree_node *curr;
828
829
0
  if (parse_current == NULL || cp_list == NULL) {
830
0
    goto exit;
831
0
  }
832
833
0
  cil_list_init(cp_list, CIL_CLASSPERMS);
834
835
0
  curr = parse_current->cl_head;
836
837
0
  if (curr == NULL) {
838
    /* Class-perms form: SET1 */
839
0
    struct cil_classperms_set *new_cp_set;
840
0
    cil_fill_classperms_set(parse_current, &new_cp_set);
841
0
    cil_list_append(*cp_list, CIL_CLASSPERMS_SET, new_cp_set);
842
0
  } else if (curr->cl_head == NULL) {
843
    /* Class-perms form: (CLASS1 (PERM1 ...)) */
844
0
    struct cil_classperms *new_cp;
845
0
    rc = cil_fill_classperms(curr, &new_cp);
846
0
    if (rc != SEPOL_OK) {
847
0
      goto exit;
848
0
    }
849
0
    cil_list_append(*cp_list, CIL_CLASSPERMS, new_cp);
850
0
  } else {
851
0
    cil_log(CIL_ERR, "Bad class-permissions list syntax\n");
852
0
    rc = SEPOL_ERR;
853
0
    goto exit;
854
0
  }
855
856
0
  return SEPOL_OK;
857
858
0
exit:
859
0
  cil_log(CIL_ERR, "Problem filling class-permissions list\n");
860
0
  cil_list_destroy(cp_list, CIL_TRUE);
861
0
  return rc;
862
0
}
863
864
void cil_destroy_classperms_list(struct cil_list **cp_list)
865
0
{
866
0
  struct cil_list_item *curr;
867
868
0
  if (cp_list == NULL || *cp_list == NULL) {
869
0
    return;
870
0
  }
871
872
0
  cil_list_for_each(curr, *cp_list) {
873
0
    if (curr->flavor == CIL_CLASSPERMS) {
874
0
      cil_destroy_classperms(curr->data);
875
0
    } else {
876
0
      cil_destroy_classperms_set(curr->data);
877
0
    }
878
0
  }
879
880
0
  cil_list_destroy(cp_list, CIL_FALSE);
881
0
}
882
883
int cil_gen_classpermission(struct cil_db *db,
884
          struct cil_tree_node *parse_current,
885
          struct cil_tree_node *ast_node)
886
0
{
887
0
  int rc = SEPOL_ERR;
888
0
  char *key = NULL;
889
0
  struct cil_classpermission *cp = NULL;
890
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
891
0
             CIL_SYN_END };
892
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
893
894
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
895
0
    goto exit;
896
0
  }
897
898
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
899
0
  if (rc != SEPOL_OK) {
900
0
    goto exit;
901
0
  }
902
903
0
  cil_classpermission_init(&cp);
904
905
0
  key = parse_current->next->data;
906
907
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)cp,
908
0
        (hashtab_key_t)key, CIL_SYM_CLASSPERMSETS,
909
0
        CIL_CLASSPERMISSION);
910
0
  if (rc != SEPOL_OK) {
911
0
    goto exit;
912
0
  }
913
914
0
  return SEPOL_OK;
915
916
0
exit:
917
0
  cil_tree_log(parse_current, CIL_ERR, "Bad classpermission declaration");
918
0
  cil_destroy_classpermission(cp);
919
0
  cil_clear_node(ast_node);
920
0
  return rc;
921
0
}
922
923
void cil_destroy_classpermission(struct cil_classpermission *cp)
924
0
{
925
0
  if (cp == NULL) {
926
0
    return;
927
0
  }
928
929
0
  if (cp->datum.name != NULL) {
930
0
    cil_list_destroy(&cp->classperms, CIL_FALSE);
931
0
  } else {
932
    /* anonymous classpermission from call */
933
0
    cil_destroy_classperms_list(&cp->classperms);
934
0
  }
935
936
0
  cil_symtab_datum_destroy(&cp->datum);
937
938
0
  free(cp);
939
0
}
940
941
int cil_gen_classpermissionset(struct cil_db *db,
942
             struct cil_tree_node *parse_current,
943
             struct cil_tree_node *ast_node)
944
0
{
945
0
  int rc = SEPOL_ERR;
946
0
  struct cil_classpermissionset *cps = NULL;
947
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
948
0
             CIL_SYN_STRING | CIL_SYN_LIST,
949
0
             CIL_SYN_END };
950
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
951
952
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
953
0
    goto exit;
954
0
  }
955
956
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
957
0
  if (rc != SEPOL_OK) {
958
0
    goto exit;
959
0
  }
960
961
0
  cil_classpermissionset_init(&cps);
962
963
0
  cps->set_str = parse_current->next->data;
964
965
0
  rc = cil_fill_classperms_list(parse_current->next->next,
966
0
              &cps->classperms);
967
0
  if (rc != SEPOL_OK) {
968
0
    goto exit;
969
0
  }
970
971
0
  ast_node->data = cps;
972
0
  ast_node->flavor = CIL_CLASSPERMISSIONSET;
973
974
0
  return SEPOL_OK;
975
976
0
exit:
977
0
  cil_tree_log(parse_current, CIL_ERR, "Bad classpermissionset");
978
0
  cil_destroy_classpermissionset(cps);
979
0
  return rc;
980
0
}
981
982
void cil_destroy_classpermissionset(struct cil_classpermissionset *cps)
983
0
{
984
0
  if (cps == NULL) {
985
0
    return;
986
0
  }
987
988
0
  cil_destroy_classperms_list(&cps->classperms);
989
990
0
  free(cps);
991
0
}
992
993
int cil_gen_map_class(struct cil_db *db, struct cil_tree_node *parse_current,
994
          struct cil_tree_node *ast_node)
995
0
{
996
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
997
0
             CIL_SYN_LIST, CIL_SYN_END };
998
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
999
0
  char *key = NULL;
1000
0
  struct cil_class *map = NULL;
1001
0
  int rc = SEPOL_ERR;
1002
1003
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1004
0
  if (rc != SEPOL_OK) {
1005
0
    goto exit;
1006
0
  }
1007
1008
0
  cil_class_init(&map);
1009
1010
0
  key = parse_current->next->data;
1011
1012
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)map,
1013
0
        (hashtab_key_t)key, CIL_SYM_CLASSES, CIL_MAP_CLASS);
1014
0
  if (rc != SEPOL_OK) {
1015
0
    goto exit;
1016
0
  }
1017
1018
0
  rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head,
1019
0
        ast_node, CIL_MAP_PERM, &map->num_perms);
1020
0
  if (rc != SEPOL_OK) {
1021
0
    goto exit;
1022
0
  }
1023
1024
0
  return SEPOL_OK;
1025
1026
0
exit:
1027
0
  cil_tree_log(parse_current, CIL_ERR, "Bad map class declaration");
1028
0
  cil_destroy_class(map);
1029
0
  cil_clear_node(ast_node);
1030
0
  return rc;
1031
0
}
1032
1033
int cil_gen_classmapping(struct cil_db *db, struct cil_tree_node *parse_current,
1034
       struct cil_tree_node *ast_node)
1035
0
{
1036
0
  int rc = SEPOL_ERR;
1037
0
  struct cil_classmapping *mapping = NULL;
1038
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1039
0
             CIL_SYN_STRING,
1040
0
             CIL_SYN_STRING | CIL_SYN_LIST,
1041
0
             CIL_SYN_END };
1042
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1043
1044
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1045
0
    goto exit;
1046
0
  }
1047
1048
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1049
0
  if (rc != SEPOL_OK) {
1050
0
    goto exit;
1051
0
  }
1052
1053
0
  cil_classmapping_init(&mapping);
1054
1055
0
  mapping->map_class_str = parse_current->next->data;
1056
0
  mapping->map_perm_str = parse_current->next->next->data;
1057
1058
0
  rc = cil_fill_classperms_list(parse_current->next->next->next,
1059
0
              &mapping->classperms);
1060
0
  if (rc != SEPOL_OK) {
1061
0
    goto exit;
1062
0
  }
1063
1064
0
  ast_node->data = mapping;
1065
0
  ast_node->flavor = CIL_CLASSMAPPING;
1066
1067
0
  return SEPOL_OK;
1068
1069
0
exit:
1070
0
  cil_tree_log(parse_current, CIL_ERR, "Bad classmapping declaration");
1071
0
  cil_destroy_classmapping(mapping);
1072
0
  return rc;
1073
0
}
1074
1075
void cil_destroy_classmapping(struct cil_classmapping *mapping)
1076
0
{
1077
0
  if (mapping == NULL) {
1078
0
    return;
1079
0
  }
1080
1081
0
  cil_destroy_classperms_list(&mapping->classperms);
1082
1083
0
  free(mapping);
1084
0
}
1085
1086
// TODO try to merge some of this with cil_gen_class (helper function for both)
1087
int cil_gen_common(struct cil_db *db, struct cil_tree_node *parse_current,
1088
       struct cil_tree_node *ast_node)
1089
0
{
1090
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1091
0
             CIL_SYN_LIST, CIL_SYN_END };
1092
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1093
0
  char *key = NULL;
1094
0
  struct cil_class *common = NULL;
1095
0
  int rc = SEPOL_ERR;
1096
1097
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1098
0
    goto exit;
1099
0
  }
1100
1101
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1102
0
  if (rc != SEPOL_OK) {
1103
0
    goto exit;
1104
0
  }
1105
1106
0
  cil_class_init(&common);
1107
1108
0
  key = parse_current->next->data;
1109
1110
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)common,
1111
0
        (hashtab_key_t)key, CIL_SYM_COMMONS, CIL_COMMON);
1112
0
  if (rc != SEPOL_OK) {
1113
0
    goto exit;
1114
0
  }
1115
1116
0
  rc = cil_gen_perm_nodes(db, parse_current->next->next->cl_head,
1117
0
        ast_node, CIL_PERM, &common->num_perms);
1118
0
  if (rc != SEPOL_OK) {
1119
0
    goto exit;
1120
0
  }
1121
0
  if (common->num_perms > CIL_PERMS_PER_CLASS) {
1122
0
    cil_tree_log(parse_current, CIL_ERR,
1123
0
           "Too many permissions in common '%s'",
1124
0
           common->datum.name);
1125
0
    cil_tree_children_destroy(ast_node);
1126
0
    rc = SEPOL_ERR;
1127
0
    goto exit;
1128
0
  }
1129
1130
0
  return SEPOL_OK;
1131
1132
0
exit:
1133
0
  cil_tree_log(parse_current, CIL_ERR, "Bad common declaration");
1134
0
  cil_destroy_class(common);
1135
0
  cil_clear_node(ast_node);
1136
0
  return rc;
1137
0
}
1138
1139
int cil_gen_classcommon(struct cil_db *db, struct cil_tree_node *parse_current,
1140
      struct cil_tree_node *ast_node)
1141
0
{
1142
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1143
0
             CIL_SYN_STRING, CIL_SYN_END };
1144
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1145
0
  struct cil_classcommon *clscom = NULL;
1146
0
  int rc = SEPOL_ERR;
1147
1148
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1149
0
    goto exit;
1150
0
  }
1151
1152
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1153
0
  if (rc != SEPOL_OK) {
1154
0
    goto exit;
1155
0
  }
1156
1157
0
  cil_classcommon_init(&clscom);
1158
1159
0
  clscom->class_str = parse_current->next->data;
1160
0
  clscom->common_str = parse_current->next->next->data;
1161
1162
0
  ast_node->data = clscom;
1163
0
  ast_node->flavor = CIL_CLASSCOMMON;
1164
1165
0
  return SEPOL_OK;
1166
1167
0
exit:
1168
0
  cil_tree_log(parse_current, CIL_ERR, "Bad classcommon declaration");
1169
0
  cil_destroy_classcommon(clscom);
1170
0
  return rc;
1171
0
}
1172
1173
void cil_destroy_classcommon(struct cil_classcommon *clscom)
1174
0
{
1175
0
  if (clscom == NULL) {
1176
0
    return;
1177
0
  }
1178
1179
0
  free(clscom);
1180
0
}
1181
1182
int cil_gen_sid(struct cil_db *db, struct cil_tree_node *parse_current,
1183
    struct cil_tree_node *ast_node)
1184
0
{
1185
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1186
0
             CIL_SYN_END };
1187
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1188
0
  char *key = NULL;
1189
0
  struct cil_sid *sid = NULL;
1190
0
  int rc = SEPOL_ERR;
1191
1192
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1193
0
    goto exit;
1194
0
  }
1195
1196
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1197
0
  if (rc != SEPOL_OK) {
1198
0
    goto exit;
1199
0
  }
1200
1201
0
  cil_sid_init(&sid);
1202
1203
0
  key = parse_current->next->data;
1204
1205
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)sid,
1206
0
        (hashtab_key_t)key, CIL_SYM_SIDS, CIL_SID);
1207
0
  if (rc != SEPOL_OK) {
1208
0
    goto exit;
1209
0
  }
1210
1211
0
  return SEPOL_OK;
1212
1213
0
exit:
1214
0
  cil_tree_log(parse_current, CIL_ERR, "Bad sid declaration");
1215
0
  cil_destroy_sid(sid);
1216
0
  cil_clear_node(ast_node);
1217
0
  return rc;
1218
0
}
1219
1220
void cil_destroy_sid(struct cil_sid *sid)
1221
0
{
1222
0
  if (sid == NULL) {
1223
0
    return;
1224
0
  }
1225
1226
0
  cil_symtab_datum_destroy(&sid->datum);
1227
0
  free(sid);
1228
0
}
1229
1230
int cil_gen_sidcontext(struct cil_db *db, struct cil_tree_node *parse_current,
1231
           struct cil_tree_node *ast_node)
1232
0
{
1233
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1234
0
             CIL_SYN_STRING | CIL_SYN_LIST,
1235
0
             CIL_SYN_END };
1236
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1237
0
  struct cil_sidcontext *sidcon = NULL;
1238
0
  int rc = SEPOL_ERR;
1239
1240
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1241
0
    goto exit;
1242
0
  }
1243
1244
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1245
0
  if (rc != SEPOL_OK) {
1246
0
    goto exit;
1247
0
  }
1248
1249
0
  cil_sidcontext_init(&sidcon);
1250
1251
0
  sidcon->sid_str = parse_current->next->data;
1252
1253
0
  if (parse_current->next->next->cl_head == NULL) {
1254
0
    sidcon->context_str = parse_current->next->next->data;
1255
0
  } else {
1256
0
    cil_context_init(&sidcon->context);
1257
1258
0
    rc = cil_fill_context(parse_current->next->next->cl_head,
1259
0
              sidcon->context);
1260
0
    if (rc != SEPOL_OK) {
1261
0
      goto exit;
1262
0
    }
1263
0
  }
1264
1265
0
  ast_node->data = sidcon;
1266
0
  ast_node->flavor = CIL_SIDCONTEXT;
1267
1268
0
  return SEPOL_OK;
1269
1270
0
exit:
1271
0
  cil_tree_log(parse_current, CIL_ERR, "Bad sidcontext declaration");
1272
0
  cil_destroy_sidcontext(sidcon);
1273
0
  return rc;
1274
0
}
1275
1276
void cil_destroy_sidcontext(struct cil_sidcontext *sidcon)
1277
0
{
1278
0
  if (sidcon == NULL) {
1279
0
    return;
1280
0
  }
1281
1282
0
  if (sidcon->context_str == NULL && sidcon->context != NULL) {
1283
0
    cil_destroy_context(sidcon->context);
1284
0
  }
1285
1286
0
  free(sidcon);
1287
0
}
1288
1289
int cil_gen_user(struct cil_db *db, struct cil_tree_node *parse_current,
1290
     struct cil_tree_node *ast_node)
1291
0
{
1292
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1293
0
             CIL_SYN_END };
1294
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1295
0
  char *key = NULL;
1296
0
  struct cil_user *user = NULL;
1297
0
  int rc = SEPOL_ERR;
1298
1299
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1300
0
    goto exit;
1301
0
  }
1302
1303
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1304
0
  if (rc != SEPOL_OK) {
1305
0
    goto exit;
1306
0
  }
1307
1308
0
  cil_user_init(&user);
1309
1310
0
  key = parse_current->next->data;
1311
1312
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)user,
1313
0
        (hashtab_key_t)key, CIL_SYM_USERS, CIL_USER);
1314
0
  if (rc != SEPOL_OK) {
1315
0
    goto exit;
1316
0
  }
1317
1318
0
  return SEPOL_OK;
1319
1320
0
exit:
1321
0
  cil_tree_log(parse_current, CIL_ERR, "Bad user declaration");
1322
0
  cil_destroy_user(user);
1323
0
  cil_clear_node(ast_node);
1324
0
  return rc;
1325
0
}
1326
1327
void cil_destroy_user(struct cil_user *user)
1328
0
{
1329
0
  if (user == NULL) {
1330
0
    return;
1331
0
  }
1332
1333
0
  cil_symtab_datum_destroy(&user->datum);
1334
0
  ebitmap_destroy(user->roles);
1335
0
  free(user->roles);
1336
0
  free(user);
1337
0
}
1338
1339
int cil_gen_userattribute(struct cil_db *db,
1340
        struct cil_tree_node *parse_current,
1341
        struct cil_tree_node *ast_node)
1342
0
{
1343
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1344
0
             CIL_SYN_END };
1345
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1346
0
  char *key = NULL;
1347
0
  struct cil_userattribute *attr = NULL;
1348
0
  int rc = SEPOL_ERR;
1349
1350
0
  if (parse_current == NULL || ast_node == NULL) {
1351
0
    goto exit;
1352
0
  }
1353
1354
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1355
0
  if (rc != SEPOL_OK) {
1356
0
    goto exit;
1357
0
  }
1358
1359
0
  cil_userattribute_init(&attr);
1360
1361
0
  key = parse_current->next->data;
1362
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)attr,
1363
0
        (hashtab_key_t)key, CIL_SYM_USERS, CIL_USERATTRIBUTE);
1364
0
  if (rc != SEPOL_OK) {
1365
0
    goto exit;
1366
0
  }
1367
1368
0
  return SEPOL_OK;
1369
0
exit:
1370
0
  cil_tree_log(parse_current, CIL_ERR, "Bad userattribute declaration");
1371
0
  cil_destroy_userattribute(attr);
1372
0
  cil_clear_node(ast_node);
1373
0
  return rc;
1374
0
}
1375
1376
void cil_destroy_userattribute(struct cil_userattribute *attr)
1377
0
{
1378
0
  struct cil_list_item *expr = NULL;
1379
0
  struct cil_list_item *next = NULL;
1380
1381
0
  if (attr == NULL) {
1382
0
    return;
1383
0
  }
1384
1385
0
  if (attr->expr_list != NULL) {
1386
    /* we don't want to destroy the expression stacks (cil_list) inside
1387
     * this list cil_list_destroy destroys sublists, so we need to do it
1388
     * manually */
1389
0
    expr = attr->expr_list->head;
1390
0
    while (expr != NULL) {
1391
0
      next = expr->next;
1392
0
      cil_list_item_destroy(&expr, CIL_FALSE);
1393
0
      expr = next;
1394
0
    }
1395
0
    free(attr->expr_list);
1396
0
    attr->expr_list = NULL;
1397
0
  }
1398
1399
0
  cil_symtab_datum_destroy(&attr->datum);
1400
0
  ebitmap_destroy(attr->users);
1401
0
  free(attr->users);
1402
0
  free(attr);
1403
0
}
1404
1405
int cil_gen_userattributeset(struct cil_db *db,
1406
           struct cil_tree_node *parse_current,
1407
           struct cil_tree_node *ast_node)
1408
0
{
1409
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1410
0
             CIL_SYN_STRING | CIL_SYN_LIST,
1411
0
             CIL_SYN_END };
1412
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1413
0
  struct cil_userattributeset *attrset = NULL;
1414
0
  int rc = SEPOL_ERR;
1415
1416
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1417
0
    goto exit;
1418
0
  }
1419
1420
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1421
0
  if (rc != SEPOL_OK) {
1422
0
    goto exit;
1423
0
  }
1424
1425
0
  cil_userattributeset_init(&attrset);
1426
1427
0
  attrset->attr_str = parse_current->next->data;
1428
1429
0
  rc = cil_gen_expr(parse_current->next->next, CIL_USER,
1430
0
        &attrset->str_expr);
1431
0
  if (rc != SEPOL_OK) {
1432
0
    goto exit;
1433
0
  }
1434
0
  ast_node->data = attrset;
1435
0
  ast_node->flavor = CIL_USERATTRIBUTESET;
1436
1437
0
  return SEPOL_OK;
1438
1439
0
exit:
1440
0
  cil_tree_log(parse_current, CIL_ERR,
1441
0
         "Bad userattributeset declaration");
1442
0
  cil_destroy_userattributeset(attrset);
1443
1444
0
  return rc;
1445
0
}
1446
1447
void cil_destroy_userattributeset(struct cil_userattributeset *attrset)
1448
0
{
1449
0
  if (attrset == NULL) {
1450
0
    return;
1451
0
  }
1452
1453
0
  cil_list_destroy(&attrset->str_expr, CIL_TRUE);
1454
0
  cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
1455
1456
0
  free(attrset);
1457
0
}
1458
1459
int cil_gen_userlevel(struct cil_db *db, struct cil_tree_node *parse_current,
1460
          struct cil_tree_node *ast_node)
1461
0
{
1462
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1463
0
             CIL_SYN_STRING | CIL_SYN_LIST,
1464
0
             CIL_SYN_END };
1465
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1466
0
  struct cil_userlevel *usrlvl = NULL;
1467
0
  int rc = SEPOL_ERR;
1468
1469
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1470
0
    goto exit;
1471
0
  }
1472
1473
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1474
0
  if (rc != SEPOL_OK) {
1475
0
    goto exit;
1476
0
  }
1477
1478
0
  cil_userlevel_init(&usrlvl);
1479
1480
0
  usrlvl->user_str = parse_current->next->data;
1481
1482
0
  if (parse_current->next->next->cl_head == NULL) {
1483
0
    usrlvl->level_str = parse_current->next->next->data;
1484
0
  } else {
1485
0
    cil_level_init(&usrlvl->level);
1486
1487
0
    rc = cil_fill_level(parse_current->next->next->cl_head,
1488
0
            usrlvl->level);
1489
0
    if (rc != SEPOL_OK) {
1490
0
      goto exit;
1491
0
    }
1492
0
  }
1493
1494
0
  ast_node->data = usrlvl;
1495
0
  ast_node->flavor = CIL_USERLEVEL;
1496
1497
0
  return SEPOL_OK;
1498
1499
0
exit:
1500
0
  cil_tree_log(parse_current, CIL_ERR, "Bad userlevel declaration");
1501
0
  cil_destroy_userlevel(usrlvl);
1502
0
  return rc;
1503
0
}
1504
1505
void cil_destroy_userlevel(struct cil_userlevel *usrlvl)
1506
0
{
1507
0
  if (usrlvl == NULL) {
1508
0
    return;
1509
0
  }
1510
1511
0
  if (usrlvl->level_str == NULL && usrlvl->level != NULL) {
1512
0
    cil_destroy_level(usrlvl->level);
1513
0
  }
1514
1515
0
  free(usrlvl);
1516
0
}
1517
1518
int cil_gen_userrange(struct cil_db *db, struct cil_tree_node *parse_current,
1519
          struct cil_tree_node *ast_node)
1520
0
{
1521
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1522
0
             CIL_SYN_STRING | CIL_SYN_LIST,
1523
0
             CIL_SYN_END };
1524
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1525
0
  struct cil_userrange *userrange = NULL;
1526
0
  int rc = SEPOL_ERR;
1527
1528
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1529
0
    goto exit;
1530
0
  }
1531
1532
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1533
0
  if (rc != SEPOL_OK) {
1534
0
    goto exit;
1535
0
  }
1536
1537
0
  cil_userrange_init(&userrange);
1538
1539
0
  userrange->user_str = parse_current->next->data;
1540
1541
0
  if (parse_current->next->next->cl_head == NULL) {
1542
0
    userrange->range_str = parse_current->next->next->data;
1543
0
  } else {
1544
0
    cil_levelrange_init(&userrange->range);
1545
1546
0
    rc = cil_fill_levelrange(parse_current->next->next->cl_head,
1547
0
           userrange->range);
1548
0
    if (rc != SEPOL_OK) {
1549
0
      goto exit;
1550
0
    }
1551
0
  }
1552
1553
0
  ast_node->data = userrange;
1554
0
  ast_node->flavor = CIL_USERRANGE;
1555
1556
0
  return SEPOL_OK;
1557
1558
0
exit:
1559
0
  cil_tree_log(parse_current, CIL_ERR, "Bad userrange declaration");
1560
0
  cil_destroy_userrange(userrange);
1561
0
  return rc;
1562
0
}
1563
1564
void cil_destroy_userrange(struct cil_userrange *userrange)
1565
0
{
1566
0
  if (userrange == NULL) {
1567
0
    return;
1568
0
  }
1569
1570
0
  if (userrange->range_str == NULL && userrange->range != NULL) {
1571
0
    cil_destroy_levelrange(userrange->range);
1572
0
  }
1573
1574
0
  free(userrange);
1575
0
}
1576
1577
int cil_gen_userprefix(struct cil_db *db, struct cil_tree_node *parse_current,
1578
           struct cil_tree_node *ast_node)
1579
0
{
1580
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1581
0
             CIL_SYN_STRING, CIL_SYN_END };
1582
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1583
0
  struct cil_userprefix *userprefix = NULL;
1584
0
  int rc = SEPOL_ERR;
1585
1586
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1587
0
    goto exit;
1588
0
  }
1589
1590
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1591
0
  if (rc != SEPOL_OK) {
1592
0
    goto exit;
1593
0
  }
1594
1595
0
  cil_userprefix_init(&userprefix);
1596
1597
0
  userprefix->user_str = parse_current->next->data;
1598
0
  userprefix->prefix_str = parse_current->next->next->data;
1599
1600
0
  ast_node->data = userprefix;
1601
0
  ast_node->flavor = CIL_USERPREFIX;
1602
1603
0
  return SEPOL_OK;
1604
0
exit:
1605
0
  cil_tree_log(parse_current, CIL_ERR, "Bad userprefix declaration");
1606
0
  cil_destroy_userprefix(userprefix);
1607
0
  return rc;
1608
0
}
1609
1610
void cil_destroy_userprefix(struct cil_userprefix *userprefix)
1611
0
{
1612
0
  if (userprefix == NULL) {
1613
0
    return;
1614
0
  }
1615
1616
0
  free(userprefix);
1617
0
}
1618
1619
int cil_gen_selinuxuser(struct cil_db *db, struct cil_tree_node *parse_current,
1620
      struct cil_tree_node *ast_node)
1621
0
{
1622
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1623
0
             CIL_SYN_STRING,
1624
0
             CIL_SYN_STRING | CIL_SYN_LIST,
1625
0
             CIL_SYN_END };
1626
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1627
0
  struct cil_selinuxuser *selinuxuser = NULL;
1628
0
  int rc = SEPOL_ERR;
1629
1630
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1631
0
    goto exit;
1632
0
  }
1633
1634
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1635
0
  if (rc != SEPOL_OK) {
1636
0
    goto exit;
1637
0
  }
1638
1639
0
  cil_selinuxuser_init(&selinuxuser);
1640
1641
0
  selinuxuser->name_str = parse_current->next->data;
1642
0
  selinuxuser->user_str = parse_current->next->next->data;
1643
1644
0
  if (parse_current->next->next->next->cl_head == NULL) {
1645
0
    selinuxuser->range_str = parse_current->next->next->next->data;
1646
0
  } else {
1647
0
    cil_levelrange_init(&selinuxuser->range);
1648
1649
0
    rc = cil_fill_levelrange(
1650
0
      parse_current->next->next->next->cl_head,
1651
0
      selinuxuser->range);
1652
0
    if (rc != SEPOL_OK) {
1653
0
      goto exit;
1654
0
    }
1655
0
  }
1656
1657
0
  ast_node->data = selinuxuser;
1658
0
  ast_node->flavor = CIL_SELINUXUSER;
1659
1660
0
  return SEPOL_OK;
1661
0
exit:
1662
0
  cil_tree_log(parse_current, CIL_ERR, "Bad selinuxuser declaration");
1663
0
  cil_destroy_selinuxuser(selinuxuser);
1664
0
  return rc;
1665
0
}
1666
1667
int cil_gen_selinuxuserdefault(struct cil_db *db,
1668
             struct cil_tree_node *parse_current,
1669
             struct cil_tree_node *ast_node)
1670
0
{
1671
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1672
0
             CIL_SYN_STRING | CIL_SYN_LIST,
1673
0
             CIL_SYN_END };
1674
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1675
0
  struct cil_selinuxuser *selinuxuser = NULL;
1676
0
  int rc = SEPOL_ERR;
1677
1678
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1679
0
    goto exit;
1680
0
  }
1681
1682
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1683
0
  if (rc != SEPOL_OK) {
1684
0
    goto exit;
1685
0
  }
1686
1687
0
  cil_selinuxuser_init(&selinuxuser);
1688
1689
0
  selinuxuser->name_str = cil_strpool_add("__default__");
1690
0
  selinuxuser->user_str = parse_current->next->data;
1691
1692
0
  if (parse_current->next->next->cl_head == NULL) {
1693
0
    selinuxuser->range_str = parse_current->next->next->data;
1694
0
  } else {
1695
0
    cil_levelrange_init(&selinuxuser->range);
1696
1697
0
    rc = cil_fill_levelrange(parse_current->next->next->cl_head,
1698
0
           selinuxuser->range);
1699
0
    if (rc != SEPOL_OK) {
1700
0
      goto exit;
1701
0
    }
1702
0
  }
1703
1704
0
  ast_node->data = selinuxuser;
1705
0
  ast_node->flavor = CIL_SELINUXUSERDEFAULT;
1706
1707
0
  return SEPOL_OK;
1708
0
exit:
1709
0
  cil_tree_log(parse_current, CIL_ERR,
1710
0
         "Bad selinuxuserdefault declaration");
1711
0
  cil_destroy_selinuxuser(selinuxuser);
1712
0
  return rc;
1713
0
}
1714
1715
void cil_destroy_selinuxuser(struct cil_selinuxuser *selinuxuser)
1716
0
{
1717
0
  if (selinuxuser == NULL) {
1718
0
    return;
1719
0
  }
1720
1721
0
  if (selinuxuser->range_str == NULL && selinuxuser->range != NULL) {
1722
0
    cil_destroy_levelrange(selinuxuser->range);
1723
0
  }
1724
1725
0
  free(selinuxuser);
1726
0
}
1727
1728
int cil_gen_role(struct cil_db *db, struct cil_tree_node *parse_current,
1729
     struct cil_tree_node *ast_node)
1730
0
{
1731
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1732
0
             CIL_SYN_END };
1733
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1734
0
  char *key = NULL;
1735
0
  struct cil_role *role = NULL;
1736
0
  int rc = SEPOL_ERR;
1737
1738
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1739
0
    goto exit;
1740
0
  }
1741
1742
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1743
0
  if (rc != SEPOL_OK) {
1744
0
    goto exit;
1745
0
  }
1746
1747
0
  cil_role_init(&role);
1748
1749
0
  key = parse_current->next->data;
1750
1751
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)role,
1752
0
        (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLE);
1753
0
  if (rc != SEPOL_OK) {
1754
0
    if (rc == SEPOL_EEXIST) {
1755
0
      cil_destroy_role(role);
1756
0
      role = NULL;
1757
0
    } else {
1758
0
      goto exit;
1759
0
    }
1760
0
  }
1761
1762
0
  return SEPOL_OK;
1763
1764
0
exit:
1765
0
  cil_tree_log(parse_current, CIL_ERR, "Bad role declaration");
1766
0
  cil_destroy_role(role);
1767
0
  cil_clear_node(ast_node);
1768
0
  return rc;
1769
0
}
1770
1771
void cil_destroy_role(struct cil_role *role)
1772
0
{
1773
0
  if (role == NULL) {
1774
0
    return;
1775
0
  }
1776
1777
0
  cil_symtab_datum_destroy(&role->datum);
1778
0
  ebitmap_destroy(role->types);
1779
0
  free(role->types);
1780
0
  free(role);
1781
0
}
1782
1783
int cil_gen_roletype(struct cil_db *db, struct cil_tree_node *parse_current,
1784
         struct cil_tree_node *ast_node)
1785
0
{
1786
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1787
0
             CIL_SYN_STRING, CIL_SYN_END };
1788
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1789
0
  struct cil_roletype *roletype = NULL;
1790
0
  int rc = SEPOL_ERR;
1791
1792
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1793
0
    goto exit;
1794
0
  }
1795
1796
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1797
0
  if (rc != SEPOL_OK) {
1798
0
    goto exit;
1799
0
  }
1800
1801
0
  cil_roletype_init(&roletype);
1802
1803
0
  roletype->role_str = parse_current->next->data;
1804
0
  roletype->type_str = parse_current->next->next->data;
1805
1806
0
  ast_node->data = roletype;
1807
0
  ast_node->flavor = CIL_ROLETYPE;
1808
1809
0
  return SEPOL_OK;
1810
1811
0
exit:
1812
0
  cil_tree_log(parse_current, CIL_ERR, "Bad roletype declaration");
1813
0
  cil_destroy_roletype(roletype);
1814
0
  return rc;
1815
0
}
1816
1817
void cil_destroy_roletype(struct cil_roletype *roletype)
1818
0
{
1819
0
  if (roletype == NULL) {
1820
0
    return;
1821
0
  }
1822
1823
0
  free(roletype);
1824
0
}
1825
1826
int cil_gen_userrole(struct cil_db *db, struct cil_tree_node *parse_current,
1827
         struct cil_tree_node *ast_node)
1828
0
{
1829
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1830
0
             CIL_SYN_STRING, CIL_SYN_END };
1831
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1832
0
  struct cil_userrole *userrole = NULL;
1833
0
  int rc = SEPOL_ERR;
1834
1835
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1836
0
    goto exit;
1837
0
  }
1838
1839
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1840
0
  if (rc != SEPOL_OK) {
1841
0
    goto exit;
1842
0
  }
1843
1844
0
  cil_userrole_init(&userrole);
1845
1846
0
  userrole->user_str = parse_current->next->data;
1847
0
  userrole->role_str = parse_current->next->next->data;
1848
1849
0
  ast_node->data = userrole;
1850
0
  ast_node->flavor = CIL_USERROLE;
1851
1852
0
  return SEPOL_OK;
1853
1854
0
exit:
1855
0
  cil_tree_log(parse_current, CIL_ERR, "Bad userrole declaration");
1856
0
  cil_destroy_userrole(userrole);
1857
0
  return rc;
1858
0
}
1859
1860
void cil_destroy_userrole(struct cil_userrole *userrole)
1861
0
{
1862
0
  if (userrole == NULL) {
1863
0
    return;
1864
0
  }
1865
1866
0
  free(userrole);
1867
0
}
1868
1869
int cil_gen_roletransition(struct cil_tree_node *parse_current,
1870
         struct cil_tree_node *ast_node)
1871
0
{
1872
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1873
0
             CIL_SYN_STRING, CIL_SYN_STRING,
1874
0
             CIL_SYN_STRING, CIL_SYN_END };
1875
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1876
0
  struct cil_roletransition *roletrans = NULL;
1877
0
  int rc = SEPOL_ERR;
1878
1879
0
  if (parse_current == NULL || ast_node == NULL) {
1880
0
    goto exit;
1881
0
  }
1882
1883
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1884
0
  if (rc != SEPOL_OK) {
1885
0
    goto exit;
1886
0
  }
1887
1888
0
  cil_roletransition_init(&roletrans);
1889
1890
0
  roletrans->src_str = parse_current->next->data;
1891
0
  roletrans->tgt_str = parse_current->next->next->data;
1892
0
  roletrans->obj_str = parse_current->next->next->next->data;
1893
0
  roletrans->result_str = parse_current->next->next->next->next->data;
1894
1895
0
  ast_node->data = roletrans;
1896
0
  ast_node->flavor = CIL_ROLETRANSITION;
1897
1898
0
  return SEPOL_OK;
1899
1900
0
exit:
1901
0
  cil_tree_log(parse_current, CIL_ERR, "Bad roletransition rule");
1902
0
  cil_destroy_roletransition(roletrans);
1903
0
  return rc;
1904
0
}
1905
1906
void cil_destroy_roletransition(struct cil_roletransition *roletrans)
1907
0
{
1908
0
  if (roletrans == NULL) {
1909
0
    return;
1910
0
  }
1911
1912
0
  free(roletrans);
1913
0
}
1914
1915
int cil_gen_roleallow(struct cil_db *db, struct cil_tree_node *parse_current,
1916
          struct cil_tree_node *ast_node)
1917
0
{
1918
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1919
0
             CIL_SYN_STRING, CIL_SYN_END };
1920
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1921
0
  struct cil_roleallow *roleallow = NULL;
1922
0
  int rc = SEPOL_ERR;
1923
1924
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1925
0
    goto exit;
1926
0
  }
1927
1928
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1929
0
  if (rc != SEPOL_OK) {
1930
0
    goto exit;
1931
0
  }
1932
1933
0
  cil_roleallow_init(&roleallow);
1934
1935
0
  roleallow->src_str = parse_current->next->data;
1936
0
  roleallow->tgt_str = parse_current->next->next->data;
1937
1938
0
  ast_node->data = roleallow;
1939
0
  ast_node->flavor = CIL_ROLEALLOW;
1940
1941
0
  return SEPOL_OK;
1942
1943
0
exit:
1944
0
  cil_tree_log(parse_current, CIL_ERR, "Bad roleallow rule");
1945
0
  cil_destroy_roleallow(roleallow);
1946
0
  return rc;
1947
0
}
1948
1949
void cil_destroy_roleallow(struct cil_roleallow *roleallow)
1950
0
{
1951
0
  if (roleallow == NULL) {
1952
0
    return;
1953
0
  }
1954
1955
0
  free(roleallow);
1956
0
}
1957
1958
int cil_gen_roleattribute(struct cil_db *db,
1959
        struct cil_tree_node *parse_current,
1960
        struct cil_tree_node *ast_node)
1961
0
{
1962
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
1963
0
             CIL_SYN_END };
1964
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
1965
0
  char *key = NULL;
1966
0
  struct cil_roleattribute *attr = NULL;
1967
0
  int rc = SEPOL_ERR;
1968
1969
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
1970
0
    goto exit;
1971
0
  }
1972
1973
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
1974
0
  if (rc != SEPOL_OK) {
1975
0
    goto exit;
1976
0
  }
1977
1978
0
  cil_roleattribute_init(&attr);
1979
1980
0
  key = parse_current->next->data;
1981
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)attr,
1982
0
        (hashtab_key_t)key, CIL_SYM_ROLES, CIL_ROLEATTRIBUTE);
1983
0
  if (rc != SEPOL_OK) {
1984
0
    goto exit;
1985
0
  }
1986
1987
0
  return SEPOL_OK;
1988
0
exit:
1989
0
  cil_tree_log(parse_current, CIL_ERR, "Bad roleattribute declaration");
1990
0
  cil_destroy_roleattribute(attr);
1991
0
  cil_clear_node(ast_node);
1992
0
  return rc;
1993
0
}
1994
1995
void cil_destroy_roleattribute(struct cil_roleattribute *attr)
1996
0
{
1997
0
  if (attr == NULL) {
1998
0
    return;
1999
0
  }
2000
2001
0
  if (attr->expr_list != NULL) {
2002
    /* we don't want to destroy the expression stacks (cil_list) inside
2003
     * this list cil_list_destroy destroys sublists, so we need to do it
2004
     * manually */
2005
0
    struct cil_list_item *expr = attr->expr_list->head;
2006
0
    while (expr != NULL) {
2007
0
      struct cil_list_item *next = expr->next;
2008
0
      cil_list_item_destroy(&expr, CIL_FALSE);
2009
0
      expr = next;
2010
0
    }
2011
0
    free(attr->expr_list);
2012
0
    attr->expr_list = NULL;
2013
0
  }
2014
2015
0
  cil_symtab_datum_destroy(&attr->datum);
2016
0
  ebitmap_destroy(attr->roles);
2017
0
  free(attr->roles);
2018
0
  free(attr);
2019
0
}
2020
2021
int cil_gen_roleattributeset(struct cil_db *db,
2022
           struct cil_tree_node *parse_current,
2023
           struct cil_tree_node *ast_node)
2024
0
{
2025
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2026
0
             CIL_SYN_STRING | CIL_SYN_LIST,
2027
0
             CIL_SYN_END };
2028
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2029
0
  struct cil_roleattributeset *attrset = NULL;
2030
0
  int rc = SEPOL_ERR;
2031
2032
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
2033
0
    goto exit;
2034
0
  }
2035
2036
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2037
0
  if (rc != SEPOL_OK) {
2038
0
    goto exit;
2039
0
  }
2040
2041
0
  cil_roleattributeset_init(&attrset);
2042
2043
0
  attrset->attr_str = parse_current->next->data;
2044
2045
0
  rc = cil_gen_expr(parse_current->next->next, CIL_ROLE,
2046
0
        &attrset->str_expr);
2047
0
  if (rc != SEPOL_OK) {
2048
0
    goto exit;
2049
0
  }
2050
0
  ast_node->data = attrset;
2051
0
  ast_node->flavor = CIL_ROLEATTRIBUTESET;
2052
2053
0
  return SEPOL_OK;
2054
2055
0
exit:
2056
0
  cil_tree_log(parse_current, CIL_ERR,
2057
0
         "Bad roleattributeset declaration");
2058
0
  cil_destroy_roleattributeset(attrset);
2059
2060
0
  return rc;
2061
0
}
2062
2063
void cil_destroy_roleattributeset(struct cil_roleattributeset *attrset)
2064
0
{
2065
0
  if (attrset == NULL) {
2066
0
    return;
2067
0
  }
2068
2069
0
  cil_list_destroy(&attrset->str_expr, CIL_TRUE);
2070
0
  cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
2071
2072
0
  free(attrset);
2073
0
}
2074
2075
int cil_gen_avrule(struct cil_tree_node *parse_current,
2076
       struct cil_tree_node *ast_node, uint32_t rule_kind)
2077
0
{
2078
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2079
0
             CIL_SYN_STRING,
2080
0
             CIL_SYN_STRING | CIL_SYN_LIST,
2081
0
             CIL_SYN_END };
2082
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2083
0
  struct cil_avrule *rule = NULL;
2084
0
  int rc = SEPOL_ERR;
2085
2086
0
  if (parse_current == NULL || ast_node == NULL) {
2087
0
    goto exit;
2088
0
  }
2089
2090
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2091
0
  if (rc != SEPOL_OK) {
2092
0
    goto exit;
2093
0
  }
2094
2095
0
  cil_avrule_init(&rule);
2096
2097
0
  rule->is_extended = 0;
2098
0
  rule->rule_kind = rule_kind;
2099
2100
0
  rule->src_str = parse_current->next->data;
2101
0
  rule->tgt_str = parse_current->next->next->data;
2102
2103
0
  rc = cil_fill_classperms_list(parse_current->next->next->next,
2104
0
              &rule->perms.classperms);
2105
0
  if (rc != SEPOL_OK) {
2106
0
    goto exit;
2107
0
  }
2108
2109
0
  ast_node->data = rule;
2110
0
  ast_node->flavor = CIL_AVRULE;
2111
2112
0
  return SEPOL_OK;
2113
2114
0
exit:
2115
0
  cil_tree_log(parse_current, CIL_ERR, "Bad allow rule");
2116
0
  cil_destroy_avrule(rule);
2117
0
  return rc;
2118
0
}
2119
2120
void cil_destroy_avrule(struct cil_avrule *rule)
2121
0
{
2122
0
  if (rule == NULL) {
2123
0
    return;
2124
0
  }
2125
2126
0
  if (!rule->is_extended) {
2127
0
    cil_destroy_classperms_list(&rule->perms.classperms);
2128
0
  } else {
2129
0
    if (rule->perms.x.permx_str == NULL &&
2130
0
        rule->perms.x.permx != NULL) {
2131
0
      cil_destroy_permissionx(rule->perms.x.permx);
2132
0
    }
2133
0
  }
2134
2135
0
  free(rule);
2136
0
}
2137
2138
static int cil_fill_permissionx(struct cil_tree_node *parse_current,
2139
        struct cil_permissionx *permx)
2140
0
{
2141
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2142
0
             CIL_SYN_LIST, CIL_SYN_END };
2143
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2144
0
  int rc = SEPOL_ERR;
2145
2146
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2147
0
  if (rc != SEPOL_OK) {
2148
0
    goto exit;
2149
0
  }
2150
2151
0
  if (parse_current->data == CIL_KEY_IOCTL) {
2152
0
    permx->kind = CIL_PERMX_KIND_IOCTL;
2153
0
  } else if (parse_current->data == CIL_KEY_NLMSG) {
2154
0
    permx->kind = CIL_PERMX_KIND_NLMSG;
2155
0
  } else {
2156
0
    cil_log(CIL_ERR,
2157
0
      "Unknown permissionx kind, %s. Must be \"ioctl\" or \"nlmsg\"\n",
2158
0
      (char *)parse_current->data);
2159
0
    rc = SEPOL_ERR;
2160
0
    goto exit;
2161
0
  }
2162
2163
0
  permx->obj_str = parse_current->next->data;
2164
2165
0
  rc = cil_gen_expr(parse_current->next->next, CIL_PERMISSIONX,
2166
0
        &permx->expr_str);
2167
0
  if (rc != SEPOL_OK) {
2168
0
    goto exit;
2169
0
  }
2170
2171
0
  return SEPOL_OK;
2172
2173
0
exit:
2174
0
  cil_tree_log(parse_current, CIL_ERR, "Bad permissionx content");
2175
0
  return rc;
2176
0
}
2177
2178
int cil_gen_permissionx(struct cil_db *db, struct cil_tree_node *parse_current,
2179
      struct cil_tree_node *ast_node)
2180
0
{
2181
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2182
0
             CIL_SYN_LIST, CIL_SYN_END };
2183
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2184
0
  char *key = NULL;
2185
0
  struct cil_permissionx *permx = NULL;
2186
0
  int rc = SEPOL_ERR;
2187
2188
0
  if (parse_current == NULL || ast_node == NULL) {
2189
0
    goto exit;
2190
0
  }
2191
2192
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2193
0
  if (rc != SEPOL_OK) {
2194
0
    goto exit;
2195
0
  }
2196
2197
0
  cil_permissionx_init(&permx);
2198
2199
0
  key = parse_current->next->data;
2200
2201
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)permx,
2202
0
        (hashtab_key_t)key, CIL_SYM_PERMX, CIL_PERMISSIONX);
2203
0
  if (rc != SEPOL_OK) {
2204
0
    goto exit;
2205
0
  }
2206
2207
0
  rc = cil_fill_permissionx(parse_current->next->next->cl_head, permx);
2208
0
  if (rc != SEPOL_OK) {
2209
0
    goto exit;
2210
0
  }
2211
2212
0
  return SEPOL_OK;
2213
2214
0
exit:
2215
0
  cil_tree_log(parse_current, CIL_ERR, "Bad permissionx statement");
2216
0
  cil_destroy_permissionx(permx);
2217
0
  cil_clear_node(ast_node);
2218
0
  return rc;
2219
0
}
2220
2221
void cil_destroy_permissionx(struct cil_permissionx *permx)
2222
0
{
2223
0
  if (permx == NULL) {
2224
0
    return;
2225
0
  }
2226
2227
0
  cil_symtab_datum_destroy(&permx->datum);
2228
2229
0
  cil_list_destroy(&permx->expr_str, CIL_TRUE);
2230
0
  ebitmap_destroy(permx->perms);
2231
0
  free(permx->perms);
2232
0
  free(permx);
2233
0
}
2234
2235
int cil_gen_avrulex(struct cil_tree_node *parse_current,
2236
        struct cil_tree_node *ast_node, uint32_t rule_kind)
2237
0
{
2238
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2239
0
             CIL_SYN_STRING,
2240
0
             CIL_SYN_STRING | CIL_SYN_LIST,
2241
0
             CIL_SYN_END };
2242
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2243
0
  struct cil_avrule *rule = NULL;
2244
0
  int rc = SEPOL_ERR;
2245
2246
0
  if (parse_current == NULL || ast_node == NULL) {
2247
0
    goto exit;
2248
0
  }
2249
2250
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2251
0
  if (rc != SEPOL_OK) {
2252
0
    goto exit;
2253
0
  }
2254
2255
0
  cil_avrule_init(&rule);
2256
2257
0
  rule->is_extended = 1;
2258
0
  rule->rule_kind = rule_kind;
2259
0
  rule->src_str = parse_current->next->data;
2260
0
  rule->tgt_str = parse_current->next->next->data;
2261
2262
0
  if (parse_current->next->next->next->cl_head == NULL) {
2263
0
    rule->perms.x.permx_str = parse_current->next->next->next->data;
2264
0
  } else {
2265
0
    cil_permissionx_init(&rule->perms.x.permx);
2266
2267
0
    rc = cil_fill_permissionx(
2268
0
      parse_current->next->next->next->cl_head,
2269
0
      rule->perms.x.permx);
2270
0
    if (rc != SEPOL_OK) {
2271
0
      goto exit;
2272
0
    }
2273
0
  }
2274
2275
0
  ast_node->data = rule;
2276
0
  ast_node->flavor = CIL_AVRULEX;
2277
2278
0
  return SEPOL_OK;
2279
2280
0
exit:
2281
0
  cil_tree_log(parse_current, CIL_ERR, "Bad allowx rule");
2282
0
  cil_destroy_avrule(rule);
2283
0
  return rc;
2284
0
}
2285
2286
int cil_gen_deny_rule(struct cil_tree_node *parse_current,
2287
          struct cil_tree_node *ast_node)
2288
0
{
2289
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2290
0
             CIL_SYN_STRING,
2291
0
             CIL_SYN_STRING | CIL_SYN_LIST,
2292
0
             CIL_SYN_END };
2293
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2294
0
  struct cil_deny_rule *rule = NULL;
2295
0
  int rc = SEPOL_ERR;
2296
2297
0
  if (parse_current == NULL || ast_node == NULL) {
2298
0
    goto exit;
2299
0
  }
2300
2301
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2302
0
  if (rc != SEPOL_OK) {
2303
0
    goto exit;
2304
0
  }
2305
2306
0
  cil_deny_rule_init(&rule);
2307
2308
0
  rule->src_str = parse_current->next->data;
2309
0
  rule->tgt_str = parse_current->next->next->data;
2310
2311
0
  rc = cil_fill_classperms_list(parse_current->next->next->next,
2312
0
              &rule->classperms);
2313
0
  if (rc != SEPOL_OK) {
2314
0
    goto exit;
2315
0
  }
2316
2317
0
  ast_node->data = rule;
2318
0
  ast_node->flavor = CIL_DENY_RULE;
2319
2320
0
  return SEPOL_OK;
2321
2322
0
exit:
2323
0
  cil_tree_log(parse_current, CIL_ERR, "Bad deny rule");
2324
0
  cil_destroy_deny_rule(rule);
2325
0
  return rc;
2326
0
}
2327
2328
void cil_destroy_deny_rule(struct cil_deny_rule *rule)
2329
0
{
2330
0
  if (rule == NULL) {
2331
0
    return;
2332
0
  }
2333
2334
0
  cil_destroy_classperms_list(&rule->classperms);
2335
2336
0
  free(rule);
2337
0
}
2338
2339
int cil_gen_type_rule(struct cil_tree_node *parse_current,
2340
          struct cil_tree_node *ast_node, uint32_t rule_kind)
2341
0
{
2342
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2343
0
             CIL_SYN_STRING, CIL_SYN_STRING,
2344
0
             CIL_SYN_STRING, CIL_SYN_END };
2345
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2346
0
  struct cil_type_rule *rule = NULL;
2347
0
  int rc = SEPOL_ERR;
2348
2349
0
  if (parse_current == NULL || ast_node == NULL) {
2350
0
    goto exit;
2351
0
  }
2352
2353
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2354
0
  if (rc != SEPOL_OK) {
2355
0
    goto exit;
2356
0
  }
2357
2358
0
  cil_type_rule_init(&rule);
2359
2360
0
  rule->rule_kind = rule_kind;
2361
0
  rule->src_str = parse_current->next->data;
2362
0
  rule->tgt_str = parse_current->next->next->data;
2363
0
  rule->obj_str = parse_current->next->next->next->data;
2364
0
  rule->result_str = parse_current->next->next->next->next->data;
2365
2366
0
  ast_node->data = rule;
2367
0
  ast_node->flavor = CIL_TYPE_RULE;
2368
2369
0
  return SEPOL_OK;
2370
2371
0
exit:
2372
0
  cil_tree_log(parse_current, CIL_ERR, "Bad type rule");
2373
0
  cil_destroy_type_rule(rule);
2374
0
  return rc;
2375
0
}
2376
2377
void cil_destroy_type_rule(struct cil_type_rule *rule)
2378
0
{
2379
0
  if (rule == NULL) {
2380
0
    return;
2381
0
  }
2382
2383
0
  free(rule);
2384
0
}
2385
2386
int cil_gen_type(struct cil_db *db, struct cil_tree_node *parse_current,
2387
     struct cil_tree_node *ast_node)
2388
0
{
2389
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2390
0
             CIL_SYN_END };
2391
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2392
0
  char *key = NULL;
2393
0
  struct cil_type *type = NULL;
2394
0
  int rc = SEPOL_ERR;
2395
2396
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
2397
0
    goto exit;
2398
0
  }
2399
2400
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2401
0
  if (rc != SEPOL_OK) {
2402
0
    goto exit;
2403
0
  }
2404
2405
0
  cil_type_init(&type);
2406
2407
0
  key = parse_current->next->data;
2408
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)type,
2409
0
        (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPE);
2410
0
  if (rc != SEPOL_OK) {
2411
0
    if (rc == SEPOL_EEXIST) {
2412
0
      cil_destroy_type(type);
2413
0
      type = NULL;
2414
0
    } else {
2415
0
      goto exit;
2416
0
    }
2417
0
  }
2418
2419
0
  return SEPOL_OK;
2420
2421
0
exit:
2422
0
  cil_tree_log(parse_current, CIL_ERR, "Bad type declaration");
2423
0
  cil_destroy_type(type);
2424
0
  cil_clear_node(ast_node);
2425
0
  return rc;
2426
0
}
2427
2428
void cil_destroy_type(struct cil_type *type)
2429
0
{
2430
0
  if (type == NULL) {
2431
0
    return;
2432
0
  }
2433
2434
0
  cil_symtab_datum_destroy(&type->datum);
2435
0
  free(type);
2436
0
}
2437
2438
int cil_gen_typeattribute(struct cil_db *db,
2439
        struct cil_tree_node *parse_current,
2440
        struct cil_tree_node *ast_node)
2441
0
{
2442
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2443
0
             CIL_SYN_END };
2444
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2445
0
  char *key = NULL;
2446
0
  struct cil_typeattribute *attr = NULL;
2447
0
  int rc = SEPOL_ERR;
2448
2449
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
2450
0
    goto exit;
2451
0
  }
2452
2453
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2454
0
  if (rc != SEPOL_OK) {
2455
0
    goto exit;
2456
0
  }
2457
2458
0
  cil_typeattribute_init(&attr);
2459
2460
0
  key = parse_current->next->data;
2461
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)attr,
2462
0
        (hashtab_key_t)key, CIL_SYM_TYPES, CIL_TYPEATTRIBUTE);
2463
0
  if (rc != SEPOL_OK) {
2464
0
    if (rc == SEPOL_EEXIST) {
2465
0
      cil_destroy_typeattribute(attr);
2466
0
      attr = NULL;
2467
0
    } else {
2468
0
      goto exit;
2469
0
    }
2470
0
  }
2471
2472
0
  return SEPOL_OK;
2473
2474
0
exit:
2475
0
  cil_tree_log(parse_current, CIL_ERR, "Bad typeattribute declaration");
2476
0
  cil_destroy_typeattribute(attr);
2477
0
  cil_clear_node(ast_node);
2478
0
  return rc;
2479
0
}
2480
2481
void cil_destroy_typeattribute(struct cil_typeattribute *attr)
2482
0
{
2483
0
  if (attr == NULL) {
2484
0
    return;
2485
0
  }
2486
2487
0
  cil_symtab_datum_destroy(&attr->datum);
2488
2489
0
  if (attr->expr_list != NULL) {
2490
    /* we don't want to destroy the expression stacks (cil_list) inside
2491
     * this list cil_list_destroy destroys sublists, so we need to do it
2492
     * manually */
2493
0
    struct cil_list_item *expr = attr->expr_list->head;
2494
0
    while (expr != NULL) {
2495
0
      struct cil_list_item *next = expr->next;
2496
0
      cil_list_item_destroy(&expr, CIL_FALSE);
2497
0
      expr = next;
2498
0
    }
2499
0
    free(attr->expr_list);
2500
0
    attr->expr_list = NULL;
2501
0
  }
2502
0
  ebitmap_destroy(attr->types);
2503
0
  free(attr->types);
2504
0
  free(attr);
2505
0
}
2506
2507
int cil_gen_bool(struct cil_db *db, struct cil_tree_node *parse_current,
2508
     struct cil_tree_node *ast_node, int tunableif)
2509
0
{
2510
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2511
0
             CIL_SYN_STRING, CIL_SYN_END };
2512
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2513
0
  char *key = NULL;
2514
0
  struct cil_bool *boolean = NULL;
2515
0
  int rc = SEPOL_ERR;
2516
2517
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
2518
0
    goto exit;
2519
0
  }
2520
2521
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2522
0
  if (rc != SEPOL_OK) {
2523
0
    goto exit;
2524
0
  }
2525
2526
0
  cil_bool_init(&boolean);
2527
2528
0
  key = parse_current->next->data;
2529
2530
0
  if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
2531
0
    boolean->value = CIL_TRUE;
2532
0
  } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
2533
0
    boolean->value = CIL_FALSE;
2534
0
  } else {
2535
0
    cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
2536
0
    rc = SEPOL_ERR;
2537
0
    goto exit;
2538
0
  }
2539
2540
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)boolean,
2541
0
        (hashtab_key_t)key, CIL_SYM_BOOLS, CIL_BOOL);
2542
0
  if (rc != SEPOL_OK) {
2543
0
    goto exit;
2544
0
  }
2545
2546
0
  return SEPOL_OK;
2547
2548
0
exit:
2549
0
  if (tunableif) {
2550
0
    cil_tree_log(
2551
0
      parse_current, CIL_ERR,
2552
0
      "Bad tunable (treated as a boolean due to preserve-tunables) declaration");
2553
0
  } else {
2554
0
    cil_tree_log(parse_current, CIL_ERR, "Bad boolean declaration");
2555
0
  }
2556
0
  cil_destroy_bool(boolean);
2557
0
  cil_clear_node(ast_node);
2558
0
  return rc;
2559
0
}
2560
2561
void cil_destroy_bool(struct cil_bool *boolean)
2562
0
{
2563
0
  if (boolean == NULL) {
2564
0
    return;
2565
0
  }
2566
2567
0
  cil_symtab_datum_destroy(&boolean->datum);
2568
0
  free(boolean);
2569
0
}
2570
2571
int cil_gen_tunable(struct cil_db *db, struct cil_tree_node *parse_current,
2572
        struct cil_tree_node *ast_node)
2573
0
{
2574
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
2575
0
             CIL_SYN_STRING, CIL_SYN_END };
2576
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2577
0
  char *key = NULL;
2578
0
  struct cil_tunable *tunable = NULL;
2579
0
  int rc = SEPOL_ERR;
2580
2581
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
2582
0
    goto exit;
2583
0
  }
2584
2585
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2586
0
  if (rc != SEPOL_OK) {
2587
0
    goto exit;
2588
0
  }
2589
2590
0
  cil_tunable_init(&tunable);
2591
2592
0
  key = parse_current->next->data;
2593
2594
0
  if (parse_current->next->next->data == CIL_KEY_CONDTRUE) {
2595
0
    tunable->value = CIL_TRUE;
2596
0
  } else if (parse_current->next->next->data == CIL_KEY_CONDFALSE) {
2597
0
    tunable->value = CIL_FALSE;
2598
0
  } else {
2599
0
    cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
2600
0
    rc = SEPOL_ERR;
2601
0
    goto exit;
2602
0
  }
2603
2604
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)tunable,
2605
0
        (hashtab_key_t)key, CIL_SYM_TUNABLES, CIL_TUNABLE);
2606
0
  if (rc != SEPOL_OK) {
2607
0
    goto exit;
2608
0
  }
2609
2610
0
  return SEPOL_OK;
2611
2612
0
exit:
2613
0
  cil_tree_log(parse_current, CIL_ERR, "Bad tunable declaration");
2614
0
  cil_destroy_tunable(tunable);
2615
0
  cil_clear_node(ast_node);
2616
0
  return rc;
2617
0
}
2618
2619
void cil_destroy_tunable(struct cil_tunable *tunable)
2620
0
{
2621
0
  if (tunable == NULL) {
2622
0
    return;
2623
0
  }
2624
2625
0
  cil_symtab_datum_destroy(&tunable->datum);
2626
0
  free(tunable);
2627
0
}
2628
2629
static enum cil_flavor __cil_get_expr_operator_flavor(const char *op)
2630
0
{
2631
0
  if (op == NULL)
2632
0
    return CIL_NONE;
2633
0
  else if (op == CIL_KEY_AND)
2634
0
    return CIL_AND;
2635
0
  else if (op == CIL_KEY_OR)
2636
0
    return CIL_OR;
2637
0
  else if (op == CIL_KEY_NOT)
2638
0
    return CIL_NOT;
2639
0
  else if (op == CIL_KEY_EQ)
2640
0
    return CIL_EQ; /* Only conditional */
2641
0
  else if (op == CIL_KEY_NEQ)
2642
0
    return CIL_NEQ; /* Only conditional */
2643
0
  else if (op == CIL_KEY_XOR)
2644
0
    return CIL_XOR;
2645
0
  else if (op == CIL_KEY_ALL)
2646
0
    return CIL_ALL; /* Only set and permissionx */
2647
0
  else if (op == CIL_KEY_RANGE)
2648
0
    return CIL_RANGE; /* Only catset and permissionx */
2649
0
  else
2650
0
    return CIL_NONE;
2651
0
}
2652
2653
static int __cil_fill_expr(struct cil_tree_node *current,
2654
         enum cil_flavor flavor, struct cil_list *expr);
2655
2656
static int __cil_fill_expr_helper(struct cil_tree_node *current,
2657
          enum cil_flavor flavor, struct cil_list *expr)
2658
0
{
2659
0
  int rc = SEPOL_ERR;
2660
0
  enum cil_flavor op;
2661
2662
0
  op = __cil_get_expr_operator_flavor(current->data);
2663
2664
0
  rc = cil_verify_expr_syntax(current, op, flavor);
2665
0
  if (rc != SEPOL_OK) {
2666
0
    goto exit;
2667
0
  }
2668
2669
0
  if (op != CIL_NONE) {
2670
0
    cil_list_append(expr, CIL_OP, (void *)op);
2671
0
    current = current->next;
2672
0
  }
2673
2674
0
  for (; current != NULL; current = current->next) {
2675
0
    rc = __cil_fill_expr(current, flavor, expr);
2676
0
    if (rc != SEPOL_OK) {
2677
0
      goto exit;
2678
0
    }
2679
0
  }
2680
2681
0
  return SEPOL_OK;
2682
2683
0
exit:
2684
0
  return rc;
2685
0
}
2686
2687
static int __cil_fill_expr(struct cil_tree_node *current,
2688
         enum cil_flavor flavor, struct cil_list *expr)
2689
0
{
2690
0
  int rc = SEPOL_ERR;
2691
2692
0
  if (current->cl_head == NULL) {
2693
0
    enum cil_flavor op =
2694
0
      __cil_get_expr_operator_flavor(current->data);
2695
0
    if (op != CIL_NONE) {
2696
0
      cil_log(CIL_ERR, "Operator (%s) not in an expression\n",
2697
0
        (char *)current->data);
2698
0
      goto exit;
2699
0
    }
2700
0
    cil_list_append(expr, CIL_STRING, current->data);
2701
0
  } else {
2702
0
    struct cil_list *sub_expr;
2703
0
    cil_list_init(&sub_expr, flavor);
2704
0
    rc = __cil_fill_expr_helper(current->cl_head, flavor, sub_expr);
2705
0
    if (rc != SEPOL_OK) {
2706
0
      cil_list_destroy(&sub_expr, CIL_TRUE);
2707
0
      goto exit;
2708
0
    }
2709
0
    cil_list_append(expr, CIL_LIST, sub_expr);
2710
0
  }
2711
2712
0
  return SEPOL_OK;
2713
2714
0
exit:
2715
0
  return rc;
2716
0
}
2717
2718
int cil_gen_expr(struct cil_tree_node *current, enum cil_flavor flavor,
2719
     struct cil_list **expr)
2720
0
{
2721
0
  int rc = SEPOL_ERR;
2722
2723
0
  cil_list_init(expr, flavor);
2724
2725
0
  if (current->cl_head == NULL) {
2726
0
    rc = __cil_fill_expr(current, flavor, *expr);
2727
0
  } else {
2728
0
    rc = __cil_fill_expr_helper(current->cl_head, flavor, *expr);
2729
0
  }
2730
2731
0
  if (rc != SEPOL_OK) {
2732
0
    cil_list_destroy(expr, CIL_TRUE);
2733
0
    cil_log(CIL_ERR, "Bad expression\n");
2734
0
  }
2735
2736
0
  return rc;
2737
0
}
2738
2739
static enum cil_flavor __cil_get_constraint_operator_flavor(const char *op)
2740
0
{
2741
0
  if (op == CIL_KEY_AND)
2742
0
    return CIL_AND;
2743
0
  else if (op == CIL_KEY_OR)
2744
0
    return CIL_OR;
2745
0
  else if (op == CIL_KEY_NOT)
2746
0
    return CIL_NOT;
2747
0
  else if (op == CIL_KEY_EQ)
2748
0
    return CIL_EQ;
2749
0
  else if (op == CIL_KEY_NEQ)
2750
0
    return CIL_NEQ;
2751
0
  else if (op == CIL_KEY_CONS_DOM)
2752
0
    return CIL_CONS_DOM;
2753
0
  else if (op == CIL_KEY_CONS_DOMBY)
2754
0
    return CIL_CONS_DOMBY;
2755
0
  else if (op == CIL_KEY_CONS_INCOMP)
2756
0
    return CIL_CONS_INCOMP;
2757
0
  else
2758
0
    return CIL_NONE;
2759
0
}
2760
2761
static enum cil_flavor __cil_get_constraint_operand_flavor(const char *operand)
2762
0
{
2763
0
  if (operand == NULL)
2764
0
    return CIL_LIST;
2765
0
  else if (operand == CIL_KEY_CONS_T1)
2766
0
    return CIL_CONS_T1;
2767
0
  else if (operand == CIL_KEY_CONS_T2)
2768
0
    return CIL_CONS_T2;
2769
0
  else if (operand == CIL_KEY_CONS_T3)
2770
0
    return CIL_CONS_T3;
2771
0
  else if (operand == CIL_KEY_CONS_R1)
2772
0
    return CIL_CONS_R1;
2773
0
  else if (operand == CIL_KEY_CONS_R2)
2774
0
    return CIL_CONS_R2;
2775
0
  else if (operand == CIL_KEY_CONS_R3)
2776
0
    return CIL_CONS_R3;
2777
0
  else if (operand == CIL_KEY_CONS_U1)
2778
0
    return CIL_CONS_U1;
2779
0
  else if (operand == CIL_KEY_CONS_U2)
2780
0
    return CIL_CONS_U2;
2781
0
  else if (operand == CIL_KEY_CONS_U3)
2782
0
    return CIL_CONS_U3;
2783
0
  else if (operand == CIL_KEY_CONS_L1)
2784
0
    return CIL_CONS_L1;
2785
0
  else if (operand == CIL_KEY_CONS_L2)
2786
0
    return CIL_CONS_L2;
2787
0
  else if (operand == CIL_KEY_CONS_H1)
2788
0
    return CIL_CONS_H1;
2789
0
  else if (operand == CIL_KEY_CONS_H2)
2790
0
    return CIL_CONS_H2;
2791
0
  else
2792
0
    return CIL_STRING;
2793
0
}
2794
2795
static int __cil_fill_constraint_leaf_expr(struct cil_tree_node *current,
2796
             enum cil_flavor expr_flavor,
2797
             enum cil_flavor op,
2798
             struct cil_list **leaf_expr)
2799
0
{
2800
0
  int rc = SEPOL_ERR;
2801
0
  enum cil_flavor leaf_expr_flavor = CIL_NONE;
2802
0
  enum cil_flavor l_flavor = CIL_NONE;
2803
0
  enum cil_flavor r_flavor = CIL_NONE;
2804
2805
0
  l_flavor = __cil_get_constraint_operand_flavor(current->next->data);
2806
0
  r_flavor =
2807
0
    __cil_get_constraint_operand_flavor(current->next->next->data);
2808
2809
0
  switch (l_flavor) {
2810
0
  case CIL_CONS_U1:
2811
0
  case CIL_CONS_U2:
2812
0
  case CIL_CONS_U3:
2813
0
    leaf_expr_flavor = CIL_USER;
2814
0
    break;
2815
0
  case CIL_CONS_R1:
2816
0
  case CIL_CONS_R2:
2817
0
  case CIL_CONS_R3:
2818
0
    leaf_expr_flavor = CIL_ROLE;
2819
0
    break;
2820
0
  case CIL_CONS_T1:
2821
0
  case CIL_CONS_T2:
2822
0
  case CIL_CONS_T3:
2823
0
    leaf_expr_flavor = CIL_TYPE;
2824
0
    break;
2825
0
  case CIL_CONS_L1:
2826
0
  case CIL_CONS_L2:
2827
0
  case CIL_CONS_H1:
2828
0
  case CIL_CONS_H2:
2829
0
    leaf_expr_flavor = CIL_LEVEL;
2830
0
    break;
2831
0
  default:
2832
0
    cil_log(CIL_ERR, "Invalid left operand (%s)\n",
2833
0
      (char *)current->next->data);
2834
0
    goto exit;
2835
0
  }
2836
2837
0
  rc = cil_verify_constraint_leaf_expr_syntax(l_flavor, r_flavor, op,
2838
0
                expr_flavor);
2839
0
  if (rc != SEPOL_OK) {
2840
0
    goto exit;
2841
0
  }
2842
2843
0
  cil_list_init(leaf_expr, leaf_expr_flavor);
2844
2845
0
  cil_list_append(*leaf_expr, CIL_OP, (void *)op);
2846
2847
0
  cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)l_flavor);
2848
2849
0
  if (r_flavor == CIL_STRING) {
2850
0
    cil_list_append(*leaf_expr, CIL_STRING,
2851
0
        current->next->next->data);
2852
0
  } else if (r_flavor == CIL_LIST) {
2853
0
    struct cil_list *sub_list;
2854
0
    rc = cil_fill_list(current->next->next->cl_head,
2855
0
           leaf_expr_flavor, &sub_list);
2856
0
    if (rc != SEPOL_OK) {
2857
0
      cil_list_destroy(leaf_expr, CIL_TRUE);
2858
0
      goto exit;
2859
0
    }
2860
0
    cil_list_append(*leaf_expr, CIL_LIST, sub_list);
2861
0
  } else {
2862
0
    cil_list_append(*leaf_expr, CIL_CONS_OPERAND, (void *)r_flavor);
2863
0
  }
2864
2865
0
  return SEPOL_OK;
2866
2867
0
exit:
2868
2869
0
  return SEPOL_ERR;
2870
0
}
2871
2872
static int __cil_fill_constraint_expr(struct cil_tree_node *current,
2873
              enum cil_flavor flavor,
2874
              struct cil_list **expr)
2875
0
{
2876
0
  int rc = SEPOL_ERR;
2877
0
  enum cil_flavor op;
2878
0
  struct cil_list *lexpr;
2879
0
  struct cil_list *rexpr;
2880
2881
0
  if (current->data == NULL || current->cl_head != NULL) {
2882
0
    cil_log(CIL_ERR,
2883
0
      "Expected a string at the start of the constraint expression\n");
2884
0
    goto exit;
2885
0
  }
2886
2887
0
  op = __cil_get_constraint_operator_flavor(current->data);
2888
2889
0
  rc = cil_verify_constraint_expr_syntax(current, op);
2890
0
  if (rc != SEPOL_OK) {
2891
0
    goto exit;
2892
0
  }
2893
2894
0
  switch (op) {
2895
0
  case CIL_EQ:
2896
0
  case CIL_NEQ:
2897
0
  case CIL_CONS_DOM:
2898
0
  case CIL_CONS_DOMBY:
2899
0
  case CIL_CONS_INCOMP:
2900
0
    rc = __cil_fill_constraint_leaf_expr(current, flavor, op, expr);
2901
0
    if (rc != SEPOL_OK) {
2902
0
      goto exit;
2903
0
    }
2904
0
    break;
2905
0
  case CIL_NOT:
2906
0
    rc = __cil_fill_constraint_expr(current->next->cl_head, flavor,
2907
0
            &lexpr);
2908
0
    if (rc != SEPOL_OK) {
2909
0
      goto exit;
2910
0
    }
2911
0
    cil_list_init(expr, flavor);
2912
0
    cil_list_append(*expr, CIL_OP, (void *)op);
2913
0
    cil_list_append(*expr, CIL_LIST, lexpr);
2914
0
    break;
2915
0
  default:
2916
0
    rc = __cil_fill_constraint_expr(current->next->cl_head, flavor,
2917
0
            &lexpr);
2918
0
    if (rc != SEPOL_OK) {
2919
0
      goto exit;
2920
0
    }
2921
0
    rc = __cil_fill_constraint_expr(current->next->next->cl_head,
2922
0
            flavor, &rexpr);
2923
0
    if (rc != SEPOL_OK) {
2924
0
      cil_list_destroy(&lexpr, CIL_TRUE);
2925
0
      goto exit;
2926
0
    }
2927
0
    cil_list_init(expr, flavor);
2928
0
    cil_list_append(*expr, CIL_OP, (void *)op);
2929
0
    cil_list_append(*expr, CIL_LIST, lexpr);
2930
0
    cil_list_append(*expr, CIL_LIST, rexpr);
2931
0
    break;
2932
0
  }
2933
2934
0
  return SEPOL_OK;
2935
0
exit:
2936
2937
0
  return rc;
2938
0
}
2939
2940
static int cil_gen_constraint_expr(struct cil_tree_node *current,
2941
           enum cil_flavor flavor,
2942
           struct cil_list **expr)
2943
0
{
2944
0
  int rc = SEPOL_ERR;
2945
2946
0
  if (current->cl_head == NULL) {
2947
0
    goto exit;
2948
0
  }
2949
2950
0
  rc = __cil_fill_constraint_expr(current->cl_head, flavor, expr);
2951
0
  if (rc != SEPOL_OK) {
2952
0
    goto exit;
2953
0
  }
2954
2955
0
  return SEPOL_OK;
2956
2957
0
exit:
2958
2959
0
  cil_log(CIL_ERR, "Bad expression tree for constraint\n");
2960
0
  return rc;
2961
0
}
2962
2963
int cil_gen_boolif(struct cil_db *db, struct cil_tree_node *parse_current,
2964
       struct cil_tree_node *ast_node, int tunableif)
2965
0
{
2966
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
2967
0
             CIL_SYN_STRING | CIL_SYN_LIST,
2968
0
             CIL_SYN_LIST, CIL_SYN_LIST | CIL_SYN_END,
2969
0
             CIL_SYN_END };
2970
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
2971
0
  struct cil_booleanif *bif = NULL;
2972
0
  struct cil_tree_node *next = NULL;
2973
0
  int rc = SEPOL_ERR;
2974
2975
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
2976
0
    goto exit;
2977
0
  }
2978
2979
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
2980
0
  if (rc != SEPOL_OK) {
2981
0
    goto exit;
2982
0
  }
2983
2984
0
  cil_boolif_init(&bif);
2985
0
  bif->preserved_tunable = tunableif;
2986
2987
0
  rc = cil_gen_expr(parse_current->next, CIL_BOOL, &bif->str_expr);
2988
0
  if (rc != SEPOL_OK) {
2989
0
    goto exit;
2990
0
  }
2991
2992
0
  rc = cil_verify_conditional_blocks(parse_current->next->next);
2993
0
  if (rc != SEPOL_OK) {
2994
0
    goto exit;
2995
0
  }
2996
2997
  /* Destroying expr tree */
2998
0
  next = parse_current->next->next;
2999
0
  cil_tree_subtree_destroy(parse_current->next);
3000
0
  parse_current->next = next;
3001
3002
0
  ast_node->flavor = CIL_BOOLEANIF;
3003
0
  ast_node->data = bif;
3004
3005
0
  return SEPOL_OK;
3006
3007
0
exit:
3008
0
  if (tunableif) {
3009
0
    cil_tree_log(
3010
0
      parse_current, CIL_ERR,
3011
0
      "Bad tunableif (treated as a booleanif due to preserve-tunables) declaration");
3012
0
  } else {
3013
0
    cil_tree_log(parse_current, CIL_ERR,
3014
0
           "Bad booleanif declaration");
3015
0
  }
3016
0
  cil_destroy_boolif(bif);
3017
0
  return rc;
3018
0
}
3019
3020
void cil_destroy_boolif(struct cil_booleanif *bif)
3021
0
{
3022
0
  if (bif == NULL) {
3023
0
    return;
3024
0
  }
3025
3026
0
  cil_list_destroy(&bif->str_expr, CIL_TRUE);
3027
0
  cil_list_destroy(&bif->datum_expr, CIL_FALSE);
3028
3029
0
  free(bif);
3030
0
}
3031
3032
int cil_gen_tunif(struct cil_db *db, struct cil_tree_node *parse_current,
3033
      struct cil_tree_node *ast_node)
3034
0
{
3035
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
3036
0
             CIL_SYN_STRING | CIL_SYN_LIST,
3037
0
             CIL_SYN_LIST, CIL_SYN_LIST | CIL_SYN_END,
3038
0
             CIL_SYN_END };
3039
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3040
0
  struct cil_tunableif *tif = NULL;
3041
0
  struct cil_tree_node *next = NULL;
3042
0
  int rc = SEPOL_ERR;
3043
3044
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3045
0
    goto exit;
3046
0
  }
3047
3048
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3049
0
  if (rc != SEPOL_OK) {
3050
0
    goto exit;
3051
0
  }
3052
3053
0
  cil_tunif_init(&tif);
3054
3055
0
  rc = cil_gen_expr(parse_current->next, CIL_TUNABLE, &tif->str_expr);
3056
0
  if (rc != SEPOL_OK) {
3057
0
    goto exit;
3058
0
  }
3059
3060
0
  rc = cil_verify_conditional_blocks(parse_current->next->next);
3061
0
  if (rc != SEPOL_OK) {
3062
0
    goto exit;
3063
0
  }
3064
3065
  /* Destroying expr tree */
3066
0
  next = parse_current->next->next;
3067
0
  cil_tree_subtree_destroy(parse_current->next);
3068
0
  parse_current->next = next;
3069
3070
0
  ast_node->flavor = CIL_TUNABLEIF;
3071
0
  ast_node->data = tif;
3072
3073
0
  return SEPOL_OK;
3074
3075
0
exit:
3076
0
  cil_tree_log(parse_current, CIL_ERR, "Bad tunableif declaration");
3077
0
  cil_destroy_tunif(tif);
3078
0
  return rc;
3079
0
}
3080
3081
void cil_destroy_tunif(struct cil_tunableif *tif)
3082
0
{
3083
0
  if (tif == NULL) {
3084
0
    return;
3085
0
  }
3086
3087
0
  cil_list_destroy(&tif->str_expr, CIL_TRUE);
3088
0
  cil_list_destroy(&tif->datum_expr, CIL_FALSE);
3089
3090
0
  free(tif);
3091
0
}
3092
3093
int cil_gen_condblock(struct cil_db *db, struct cil_tree_node *parse_current,
3094
          struct cil_tree_node *ast_node, enum cil_flavor flavor)
3095
0
{
3096
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_N_LISTS,
3097
0
             CIL_SYN_END };
3098
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3099
0
  int rc = SEPOL_ERR;
3100
0
  struct cil_condblock *cb = NULL;
3101
3102
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3103
0
    goto exit;
3104
0
  }
3105
3106
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3107
0
  if (rc != SEPOL_OK) {
3108
0
    goto exit;
3109
0
  }
3110
3111
0
  if (ast_node->parent->flavor != CIL_BOOLEANIF &&
3112
0
      ast_node->parent->flavor != CIL_TUNABLEIF) {
3113
0
    rc = SEPOL_ERR;
3114
0
    cil_log(CIL_ERR,
3115
0
      "Conditional statements must be a direct child of a tunableif or booleanif statement.\n");
3116
0
    goto exit;
3117
0
  }
3118
3119
0
  ast_node->flavor = CIL_CONDBLOCK;
3120
3121
0
  cil_condblock_init(&cb);
3122
0
  cb->flavor = flavor;
3123
3124
0
  ast_node->data = cb;
3125
3126
0
  return SEPOL_OK;
3127
3128
0
exit:
3129
0
  cil_tree_log(parse_current, CIL_ERR, "Bad %s condition declaration",
3130
0
         (char *)parse_current->data);
3131
0
  cil_destroy_condblock(cb);
3132
0
  return rc;
3133
0
}
3134
3135
void cil_destroy_condblock(struct cil_condblock *cb)
3136
0
{
3137
0
  if (cb == NULL) {
3138
0
    return;
3139
0
  }
3140
3141
0
  cil_symtab_array_destroy(cb->symtab);
3142
0
  free(cb);
3143
0
}
3144
3145
int cil_gen_alias(struct cil_db *db, struct cil_tree_node *parse_current,
3146
      struct cil_tree_node *ast_node, enum cil_flavor flavor)
3147
0
{
3148
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3149
0
             CIL_SYN_END };
3150
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3151
0
  char *key = NULL;
3152
0
  struct cil_alias *alias = NULL;
3153
0
  enum cil_sym_index sym_index;
3154
0
  int rc = SEPOL_ERR;
3155
3156
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3157
0
    goto exit;
3158
0
  }
3159
3160
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3161
0
  if (rc != SEPOL_OK) {
3162
0
    goto exit;
3163
0
  }
3164
3165
0
  cil_alias_init(&alias);
3166
3167
0
  key = parse_current->next->data;
3168
3169
0
  rc = cil_flavor_to_symtab_index(flavor, &sym_index);
3170
0
  if (rc != SEPOL_OK) {
3171
0
    goto exit;
3172
0
  }
3173
3174
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)alias,
3175
0
        (hashtab_key_t)key, sym_index, flavor);
3176
0
  if (rc != SEPOL_OK) {
3177
0
    goto exit;
3178
0
  }
3179
3180
0
  return SEPOL_OK;
3181
3182
0
exit:
3183
0
  cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration",
3184
0
         (char *)parse_current->data);
3185
0
  cil_destroy_alias(alias);
3186
0
  cil_clear_node(ast_node);
3187
0
  return rc;
3188
0
}
3189
3190
void cil_destroy_alias(struct cil_alias *alias)
3191
0
{
3192
0
  if (alias == NULL) {
3193
0
    return;
3194
0
  }
3195
3196
0
  cil_symtab_datum_destroy(&alias->datum);
3197
0
  alias->actual = NULL;
3198
3199
0
  free(alias);
3200
0
}
3201
3202
int cil_gen_aliasactual(struct cil_db *db, struct cil_tree_node *parse_current,
3203
      struct cil_tree_node *ast_node, enum cil_flavor flavor)
3204
0
{
3205
0
  int rc = SEPOL_ERR;
3206
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3207
0
             CIL_SYN_STRING, CIL_SYN_END };
3208
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3209
0
  struct cil_aliasactual *aliasactual = NULL;
3210
3211
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3212
0
    goto exit;
3213
0
  }
3214
3215
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3216
0
  if (rc != SEPOL_OK) {
3217
0
    goto exit;
3218
0
  }
3219
3220
0
  cil_aliasactual_init(&aliasactual);
3221
3222
0
  aliasactual->alias_str = parse_current->next->data;
3223
3224
0
  aliasactual->actual_str = parse_current->next->next->data;
3225
3226
0
  ast_node->data = aliasactual;
3227
0
  ast_node->flavor = flavor;
3228
3229
0
  return SEPOL_OK;
3230
3231
0
exit:
3232
0
  cil_tree_log(parse_current, CIL_ERR, "Bad %s association",
3233
0
         cil_node_to_string(parse_current));
3234
0
  cil_clear_node(ast_node);
3235
0
  return rc;
3236
0
}
3237
3238
void cil_destroy_aliasactual(struct cil_aliasactual *aliasactual)
3239
0
{
3240
0
  if (aliasactual == NULL) {
3241
0
    return;
3242
0
  }
3243
3244
0
  free(aliasactual);
3245
0
}
3246
3247
int cil_gen_typeattributeset(struct cil_db *db,
3248
           struct cil_tree_node *parse_current,
3249
           struct cil_tree_node *ast_node)
3250
0
{
3251
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3252
0
             CIL_SYN_STRING | CIL_SYN_LIST,
3253
0
             CIL_SYN_END };
3254
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3255
0
  struct cil_typeattributeset *attrset = NULL;
3256
0
  int rc = SEPOL_ERR;
3257
3258
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3259
0
    goto exit;
3260
0
  }
3261
3262
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3263
0
  if (rc != SEPOL_OK) {
3264
0
    goto exit;
3265
0
  }
3266
3267
0
  cil_typeattributeset_init(&attrset);
3268
3269
0
  attrset->attr_str = parse_current->next->data;
3270
3271
0
  rc = cil_gen_expr(parse_current->next->next, CIL_TYPE,
3272
0
        &attrset->str_expr);
3273
0
  if (rc != SEPOL_OK) {
3274
0
    goto exit;
3275
0
  }
3276
0
  ast_node->data = attrset;
3277
0
  ast_node->flavor = CIL_TYPEATTRIBUTESET;
3278
3279
0
  return SEPOL_OK;
3280
3281
0
exit:
3282
0
  cil_tree_log(parse_current, CIL_ERR, "Bad typeattributeset statement");
3283
0
  cil_destroy_typeattributeset(attrset);
3284
0
  return rc;
3285
0
}
3286
3287
void cil_destroy_typeattributeset(struct cil_typeattributeset *attrset)
3288
0
{
3289
0
  if (attrset == NULL) {
3290
0
    return;
3291
0
  }
3292
3293
0
  cil_list_destroy(&attrset->str_expr, CIL_TRUE);
3294
0
  cil_list_destroy(&attrset->datum_expr, CIL_FALSE);
3295
3296
0
  free(attrset);
3297
0
}
3298
3299
int cil_gen_expandtypeattribute(struct cil_db *db,
3300
        struct cil_tree_node *parse_current,
3301
        struct cil_tree_node *ast_node)
3302
0
{
3303
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
3304
0
             CIL_SYN_STRING | CIL_SYN_LIST,
3305
0
             CIL_SYN_STRING, CIL_SYN_END };
3306
0
  char *expand_str;
3307
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3308
0
  struct cil_expandtypeattribute *expandattr = NULL;
3309
0
  int rc = SEPOL_ERR;
3310
3311
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3312
0
    goto exit;
3313
0
  }
3314
3315
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3316
0
  if (rc != SEPOL_OK) {
3317
0
    goto exit;
3318
0
  }
3319
3320
0
  cil_expandtypeattribute_init(&expandattr);
3321
3322
0
  if (parse_current->next->cl_head == NULL) {
3323
0
    cil_list_init(&expandattr->attr_strs, CIL_TYPE);
3324
0
    cil_list_append(expandattr->attr_strs, CIL_STRING,
3325
0
        parse_current->next->data);
3326
0
  } else {
3327
0
    rc = cil_fill_list(parse_current->next->cl_head, CIL_TYPE,
3328
0
           &expandattr->attr_strs);
3329
0
    if (rc != SEPOL_OK) {
3330
0
      goto exit;
3331
0
    }
3332
0
  }
3333
3334
0
  expand_str = parse_current->next->next->data;
3335
3336
0
  if (expand_str == CIL_KEY_CONDTRUE) {
3337
0
    expandattr->expand = CIL_TRUE;
3338
0
  } else if (expand_str == CIL_KEY_CONDFALSE) {
3339
0
    expandattr->expand = CIL_FALSE;
3340
0
  } else {
3341
0
    cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
3342
0
    rc = SEPOL_ERR;
3343
0
    goto exit;
3344
0
  }
3345
3346
0
  ast_node->data = expandattr;
3347
0
  ast_node->flavor = CIL_EXPANDTYPEATTRIBUTE;
3348
3349
0
  return SEPOL_OK;
3350
3351
0
exit:
3352
0
  cil_tree_log(parse_current, CIL_ERR,
3353
0
         "Bad expandtypeattribute statement");
3354
0
  cil_destroy_expandtypeattribute(expandattr);
3355
0
  return rc;
3356
0
}
3357
3358
void cil_destroy_expandtypeattribute(struct cil_expandtypeattribute *expandattr)
3359
0
{
3360
0
  if (expandattr == NULL) {
3361
0
    return;
3362
0
  }
3363
3364
0
  cil_list_destroy(&expandattr->attr_strs, CIL_TRUE);
3365
3366
0
  cil_list_destroy(&expandattr->attr_datums, CIL_FALSE);
3367
3368
0
  free(expandattr);
3369
0
}
3370
3371
int cil_gen_typepermissive(struct cil_db *db,
3372
         struct cil_tree_node *parse_current,
3373
         struct cil_tree_node *ast_node)
3374
0
{
3375
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3376
0
             CIL_SYN_END };
3377
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3378
0
  struct cil_typepermissive *typeperm = NULL;
3379
0
  int rc = SEPOL_ERR;
3380
3381
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3382
0
    goto exit;
3383
0
  }
3384
3385
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3386
0
  if (rc != SEPOL_OK) {
3387
0
    goto exit;
3388
0
  }
3389
3390
0
  cil_typepermissive_init(&typeperm);
3391
3392
0
  typeperm->type_str = parse_current->next->data;
3393
3394
0
  ast_node->data = typeperm;
3395
0
  ast_node->flavor = CIL_TYPEPERMISSIVE;
3396
3397
0
  return SEPOL_OK;
3398
3399
0
exit:
3400
0
  cil_tree_log(parse_current, CIL_ERR, "Bad typepermissive declaration");
3401
0
  cil_destroy_typepermissive(typeperm);
3402
0
  return rc;
3403
0
}
3404
3405
void cil_destroy_typepermissive(struct cil_typepermissive *typeperm)
3406
0
{
3407
0
  if (typeperm == NULL) {
3408
0
    return;
3409
0
  }
3410
3411
0
  free(typeperm);
3412
0
}
3413
3414
int cil_gen_typeneveraudit(struct cil_db *db,
3415
         struct cil_tree_node *parse_current,
3416
         struct cil_tree_node *ast_node)
3417
0
{
3418
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3419
0
             CIL_SYN_END };
3420
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3421
0
  struct cil_typeneveraudit *typeperm = NULL;
3422
0
  int rc = SEPOL_ERR;
3423
3424
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3425
0
    goto exit;
3426
0
  }
3427
3428
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3429
0
  if (rc != SEPOL_OK) {
3430
0
    goto exit;
3431
0
  }
3432
3433
0
  cil_typeneveraudit_init(&typeperm);
3434
3435
0
  typeperm->type_str = parse_current->next->data;
3436
3437
0
  ast_node->data = typeperm;
3438
0
  ast_node->flavor = CIL_TYPENEVERAUDIT;
3439
3440
0
  return SEPOL_OK;
3441
3442
0
exit:
3443
0
  cil_tree_log(parse_current, CIL_ERR, "Bad typeneveraudit declaration");
3444
0
  cil_destroy_typeneveraudit(typeperm);
3445
0
  return rc;
3446
0
}
3447
3448
void cil_destroy_typeneveraudit(struct cil_typeneveraudit *typeperm)
3449
0
{
3450
0
  if (typeperm == NULL) {
3451
0
    return;
3452
0
  }
3453
3454
0
  free(typeperm);
3455
0
}
3456
3457
int cil_gen_typetransition(struct cil_db *db,
3458
         struct cil_tree_node *parse_current,
3459
         struct cil_tree_node *ast_node)
3460
0
{
3461
0
  int rc = SEPOL_ERR;
3462
0
  enum cil_syntax syntax[] = {
3463
0
    CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING,
3464
0
    CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_END,
3465
0
    CIL_SYN_END
3466
0
  };
3467
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3468
0
  char *s1, *s2, *s3, *s4, *s5;
3469
3470
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3471
0
    goto exit;
3472
0
  }
3473
3474
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3475
0
  if (rc != SEPOL_OK) {
3476
0
    goto exit;
3477
0
  }
3478
3479
0
  s1 = parse_current->next->data;
3480
0
  s2 = parse_current->next->next->data;
3481
0
  s3 = parse_current->next->next->next->data;
3482
0
  s4 = parse_current->next->next->next->next->data;
3483
0
  s5 = NULL;
3484
3485
0
  if (parse_current->next->next->next->next->next) {
3486
0
    if (s4 == CIL_KEY_STAR) {
3487
0
      s4 = parse_current->next->next->next->next->next->data;
3488
0
    } else {
3489
0
      s5 = parse_current->next->next->next->next->next->data;
3490
0
    }
3491
0
  }
3492
3493
0
  if (s5) {
3494
0
    struct cil_nametypetransition *nametypetrans = NULL;
3495
0
    cil_nametypetransition_init(&nametypetrans);
3496
3497
0
    ast_node->data = nametypetrans;
3498
0
    ast_node->flavor = CIL_NAMETYPETRANSITION;
3499
3500
0
    nametypetrans->src_str = s1;
3501
0
    nametypetrans->tgt_str = s2;
3502
0
    nametypetrans->obj_str = s3;
3503
0
    nametypetrans->name_str = s4;
3504
0
    nametypetrans->name = cil_gen_declared_string(db, s4, ast_node);
3505
0
    nametypetrans->result_str = s5;
3506
0
  } else {
3507
0
    struct cil_type_rule *rule = NULL;
3508
0
    cil_type_rule_init(&rule);
3509
3510
0
    ast_node->data = rule;
3511
0
    ast_node->flavor = CIL_TYPE_RULE;
3512
3513
0
    rule->rule_kind = CIL_TYPE_TRANSITION;
3514
0
    rule->src_str = s1;
3515
0
    rule->tgt_str = s2;
3516
0
    rule->obj_str = s3;
3517
0
    rule->result_str = s4;
3518
0
  }
3519
3520
0
  return SEPOL_OK;
3521
3522
0
exit:
3523
0
  cil_tree_log(parse_current, CIL_ERR, "Bad typetransition declaration");
3524
0
  return rc;
3525
0
}
3526
3527
void cil_destroy_typetransition(struct cil_nametypetransition *nametypetrans)
3528
0
{
3529
0
  if (nametypetrans == NULL) {
3530
0
    return;
3531
0
  }
3532
3533
0
  free(nametypetrans);
3534
0
}
3535
3536
int cil_gen_rangetransition(struct cil_db *db,
3537
          struct cil_tree_node *parse_current,
3538
          struct cil_tree_node *ast_node)
3539
0
{
3540
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
3541
0
             CIL_SYN_STRING,
3542
0
             CIL_SYN_STRING,
3543
0
             CIL_SYN_STRING,
3544
0
             CIL_SYN_STRING | CIL_SYN_LIST,
3545
0
             CIL_SYN_END };
3546
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3547
0
  struct cil_rangetransition *rangetrans = NULL;
3548
0
  int rc = SEPOL_ERR;
3549
3550
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3551
0
    goto exit;
3552
0
  }
3553
3554
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3555
0
  if (rc != SEPOL_OK) {
3556
0
    goto exit;
3557
0
  }
3558
3559
0
  cil_rangetransition_init(&rangetrans);
3560
3561
0
  rangetrans->src_str = parse_current->next->data;
3562
0
  rangetrans->exec_str = parse_current->next->next->data;
3563
0
  rangetrans->obj_str = parse_current->next->next->next->data;
3564
3565
0
  rangetrans->range_str = NULL;
3566
3567
0
  if (parse_current->next->next->next->next->cl_head == NULL) {
3568
0
    rangetrans->range_str =
3569
0
      parse_current->next->next->next->next->data;
3570
0
  } else {
3571
0
    cil_levelrange_init(&rangetrans->range);
3572
3573
0
    rc = cil_fill_levelrange(
3574
0
      parse_current->next->next->next->next->cl_head,
3575
0
      rangetrans->range);
3576
0
    if (rc != SEPOL_OK) {
3577
0
      goto exit;
3578
0
    }
3579
0
  }
3580
3581
0
  ast_node->data = rangetrans;
3582
0
  ast_node->flavor = CIL_RANGETRANSITION;
3583
3584
0
  return SEPOL_OK;
3585
3586
0
exit:
3587
0
  cil_tree_log(parse_current, CIL_ERR, "Bad rangetransition declaration");
3588
0
  cil_destroy_rangetransition(rangetrans);
3589
0
  return rc;
3590
0
}
3591
3592
void cil_destroy_rangetransition(struct cil_rangetransition *rangetrans)
3593
0
{
3594
0
  if (rangetrans == NULL) {
3595
0
    return;
3596
0
  }
3597
3598
0
  if (rangetrans->range_str == NULL && rangetrans->range != NULL) {
3599
0
    cil_destroy_levelrange(rangetrans->range);
3600
0
  }
3601
3602
0
  free(rangetrans);
3603
0
}
3604
3605
int cil_gen_sensitivity(struct cil_db *db, struct cil_tree_node *parse_current,
3606
      struct cil_tree_node *ast_node)
3607
0
{
3608
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3609
0
             CIL_SYN_END };
3610
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3611
0
  char *key = NULL;
3612
0
  struct cil_sens *sens = NULL;
3613
0
  int rc = SEPOL_ERR;
3614
3615
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3616
0
    goto exit;
3617
0
  }
3618
3619
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3620
0
  if (rc != SEPOL_OK) {
3621
0
    goto exit;
3622
0
  }
3623
3624
0
  cil_sens_init(&sens);
3625
3626
0
  key = parse_current->next->data;
3627
3628
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)sens,
3629
0
        (hashtab_key_t)key, CIL_SYM_SENS, CIL_SENS);
3630
0
  if (rc != SEPOL_OK) {
3631
0
    goto exit;
3632
0
  }
3633
3634
0
  return SEPOL_OK;
3635
3636
0
exit:
3637
0
  cil_tree_log(parse_current, CIL_ERR, "Bad sensitivity declaration");
3638
0
  cil_destroy_sensitivity(sens);
3639
0
  cil_clear_node(ast_node);
3640
0
  return rc;
3641
0
}
3642
3643
void cil_destroy_sensitivity(struct cil_sens *sens)
3644
0
{
3645
0
  if (sens == NULL) {
3646
0
    return;
3647
0
  }
3648
3649
0
  cil_symtab_datum_destroy(&sens->datum);
3650
3651
0
  cil_list_destroy(&sens->cats_list, CIL_FALSE);
3652
3653
0
  free(sens);
3654
0
}
3655
3656
int cil_gen_category(struct cil_db *db, struct cil_tree_node *parse_current,
3657
         struct cil_tree_node *ast_node)
3658
0
{
3659
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3660
0
             CIL_SYN_END };
3661
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3662
0
  char *key = NULL;
3663
0
  struct cil_cat *cat = NULL;
3664
0
  int rc = SEPOL_ERR;
3665
3666
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3667
0
    goto exit;
3668
0
  }
3669
3670
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3671
0
  if (rc != SEPOL_OK) {
3672
0
    goto exit;
3673
0
  }
3674
3675
0
  cil_cat_init(&cat);
3676
3677
0
  key = parse_current->next->data;
3678
3679
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)cat,
3680
0
        (hashtab_key_t)key, CIL_SYM_CATS, CIL_CAT);
3681
0
  if (rc != SEPOL_OK) {
3682
0
    goto exit;
3683
0
  }
3684
3685
0
  return SEPOL_OK;
3686
3687
0
exit:
3688
0
  cil_tree_log(parse_current, CIL_ERR, "Bad category declaration");
3689
0
  cil_destroy_category(cat);
3690
0
  cil_clear_node(ast_node);
3691
0
  return rc;
3692
0
}
3693
3694
void cil_destroy_category(struct cil_cat *cat)
3695
0
{
3696
0
  if (cat == NULL) {
3697
0
    return;
3698
0
  }
3699
3700
0
  cil_symtab_datum_destroy(&cat->datum);
3701
0
  free(cat);
3702
0
}
3703
3704
static int cil_gen_catset(struct cil_db *db,
3705
        struct cil_tree_node *parse_current,
3706
        struct cil_tree_node *ast_node)
3707
0
{
3708
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3709
0
             CIL_SYN_LIST, CIL_SYN_END };
3710
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3711
0
  char *key = NULL;
3712
0
  struct cil_catset *catset = NULL;
3713
0
  int rc = SEPOL_ERR;
3714
3715
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3716
0
    goto exit;
3717
0
  }
3718
3719
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3720
0
  if (rc != SEPOL_OK) {
3721
0
    goto exit;
3722
0
  }
3723
3724
0
  cil_catset_init(&catset);
3725
3726
0
  key = parse_current->next->data;
3727
3728
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)catset,
3729
0
        (hashtab_key_t)key, CIL_SYM_CATS, CIL_CATSET);
3730
0
  if (rc != SEPOL_OK) {
3731
0
    goto exit;
3732
0
  }
3733
3734
0
  rc = cil_fill_cats(parse_current->next->next, &catset->cats);
3735
0
  if (rc != SEPOL_OK) {
3736
0
    goto exit;
3737
0
  }
3738
3739
0
  return SEPOL_OK;
3740
3741
0
exit:
3742
0
  cil_tree_log(parse_current, CIL_ERR, "Bad categoryset declaration");
3743
0
  cil_destroy_catset(catset);
3744
0
  cil_clear_node(ast_node);
3745
0
  return rc;
3746
0
}
3747
3748
void cil_destroy_catset(struct cil_catset *catset)
3749
0
{
3750
0
  if (catset == NULL) {
3751
0
    return;
3752
0
  }
3753
3754
0
  cil_symtab_datum_destroy(&catset->datum);
3755
3756
0
  cil_destroy_cats(catset->cats);
3757
3758
0
  free(catset);
3759
0
}
3760
3761
int cil_gen_senscat(struct cil_db *db, struct cil_tree_node *parse_current,
3762
        struct cil_tree_node *ast_node)
3763
0
{
3764
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3765
0
             CIL_SYN_STRING | CIL_SYN_LIST,
3766
0
             CIL_SYN_END };
3767
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3768
0
  struct cil_senscat *senscat = NULL;
3769
0
  int rc = SEPOL_ERR;
3770
3771
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3772
0
    goto exit;
3773
0
  }
3774
3775
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3776
0
  if (rc != SEPOL_OK) {
3777
0
    goto exit;
3778
0
  }
3779
3780
0
  cil_senscat_init(&senscat);
3781
3782
0
  senscat->sens_str = parse_current->next->data;
3783
3784
0
  rc = cil_fill_cats(parse_current->next->next, &senscat->cats);
3785
0
  if (rc != SEPOL_OK) {
3786
0
    goto exit;
3787
0
  }
3788
3789
0
  ast_node->data = senscat;
3790
0
  ast_node->flavor = CIL_SENSCAT;
3791
3792
0
  return SEPOL_OK;
3793
3794
0
exit:
3795
0
  cil_tree_log(parse_current, CIL_ERR,
3796
0
         "Bad sensitivitycategory declaration");
3797
0
  cil_destroy_senscat(senscat);
3798
0
  return rc;
3799
0
}
3800
3801
void cil_destroy_senscat(struct cil_senscat *senscat)
3802
0
{
3803
0
  if (senscat == NULL) {
3804
0
    return;
3805
0
  }
3806
3807
0
  cil_destroy_cats(senscat->cats);
3808
3809
0
  free(senscat);
3810
0
}
3811
3812
int cil_gen_level(struct cil_db *db, struct cil_tree_node *parse_current,
3813
      struct cil_tree_node *ast_node)
3814
0
{
3815
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3816
0
             CIL_SYN_LIST, CIL_SYN_END };
3817
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3818
0
  char *key = NULL;
3819
0
  struct cil_level *level = NULL;
3820
0
  int rc = SEPOL_ERR;
3821
3822
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3823
0
    goto exit;
3824
0
  }
3825
3826
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3827
0
  if (rc != SEPOL_OK) {
3828
0
    goto exit;
3829
0
  }
3830
3831
0
  cil_level_init(&level);
3832
3833
0
  key = parse_current->next->data;
3834
3835
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)level,
3836
0
        (hashtab_key_t)key, CIL_SYM_LEVELS, CIL_LEVEL);
3837
0
  if (rc != SEPOL_OK) {
3838
0
    goto exit;
3839
0
  }
3840
3841
0
  rc = cil_fill_level(parse_current->next->next->cl_head, level);
3842
0
  if (rc != SEPOL_OK) {
3843
0
    goto exit;
3844
0
  }
3845
3846
0
  return SEPOL_OK;
3847
3848
0
exit:
3849
0
  cil_tree_log(parse_current, CIL_ERR, "Bad level declaration");
3850
0
  cil_destroy_level(level);
3851
0
  cil_clear_node(ast_node);
3852
0
  return rc;
3853
0
}
3854
3855
void cil_destroy_level(struct cil_level *level)
3856
0
{
3857
0
  if (level == NULL) {
3858
0
    return;
3859
0
  }
3860
3861
0
  cil_symtab_datum_destroy(&level->datum);
3862
3863
0
  cil_destroy_cats(level->cats);
3864
3865
0
  free(level);
3866
0
}
3867
3868
/* low should be pointing to either the name of the low level or to an open paren for an anonymous low level */
3869
int cil_fill_levelrange(struct cil_tree_node *low,
3870
      struct cil_levelrange *lvlrange)
3871
0
{
3872
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING | CIL_SYN_LIST,
3873
0
             CIL_SYN_STRING | CIL_SYN_LIST,
3874
0
             CIL_SYN_END };
3875
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3876
0
  int rc = SEPOL_ERR;
3877
3878
0
  if (low == NULL || lvlrange == NULL) {
3879
0
    goto exit;
3880
0
  }
3881
3882
0
  rc = __cil_verify_syntax(low, syntax, syntax_len);
3883
0
  if (rc != SEPOL_OK) {
3884
0
    goto exit;
3885
0
  }
3886
3887
0
  if (low->cl_head == NULL) {
3888
0
    lvlrange->low_str = low->data;
3889
0
  } else {
3890
0
    cil_level_init(&lvlrange->low);
3891
0
    rc = cil_fill_level(low->cl_head, lvlrange->low);
3892
0
    if (rc != SEPOL_OK) {
3893
0
      goto exit;
3894
0
    }
3895
0
  }
3896
3897
0
  if (low->next->cl_head == NULL) {
3898
0
    lvlrange->high_str = low->next->data;
3899
0
  } else {
3900
0
    cil_level_init(&lvlrange->high);
3901
0
    rc = cil_fill_level(low->next->cl_head, lvlrange->high);
3902
0
    if (rc != SEPOL_OK) {
3903
0
      goto exit;
3904
0
    }
3905
0
  }
3906
3907
0
  return SEPOL_OK;
3908
3909
0
exit:
3910
0
  cil_log(CIL_ERR, "Bad levelrange\n");
3911
0
  return rc;
3912
0
}
3913
3914
int cil_gen_levelrange(struct cil_db *db, struct cil_tree_node *parse_current,
3915
           struct cil_tree_node *ast_node)
3916
0
{
3917
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
3918
0
             CIL_SYN_LIST, CIL_SYN_END };
3919
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3920
0
  char *key = NULL;
3921
0
  struct cil_levelrange *lvlrange = NULL;
3922
0
  int rc = SEPOL_ERR;
3923
3924
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3925
0
    goto exit;
3926
0
  }
3927
3928
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3929
0
  if (rc != SEPOL_OK) {
3930
0
    goto exit;
3931
0
  }
3932
3933
0
  cil_levelrange_init(&lvlrange);
3934
3935
0
  key = parse_current->next->data;
3936
3937
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)lvlrange,
3938
0
        (hashtab_key_t)key, CIL_SYM_LEVELRANGES,
3939
0
        CIL_LEVELRANGE);
3940
0
  if (rc != SEPOL_OK) {
3941
0
    goto exit;
3942
0
  }
3943
3944
0
  rc = cil_fill_levelrange(parse_current->next->next->cl_head, lvlrange);
3945
0
  if (rc != SEPOL_OK) {
3946
0
    goto exit;
3947
0
  }
3948
3949
0
  return SEPOL_OK;
3950
3951
0
exit:
3952
0
  cil_tree_log(parse_current, CIL_ERR, "Bad levelrange declaration");
3953
0
  cil_destroy_levelrange(lvlrange);
3954
0
  cil_clear_node(ast_node);
3955
0
  return rc;
3956
0
}
3957
3958
void cil_destroy_levelrange(struct cil_levelrange *lvlrange)
3959
0
{
3960
0
  if (lvlrange == NULL) {
3961
0
    return;
3962
0
  }
3963
3964
0
  cil_symtab_datum_destroy(&lvlrange->datum);
3965
3966
0
  if (lvlrange->low_str == NULL) {
3967
0
    cil_destroy_level(lvlrange->low);
3968
0
  }
3969
3970
0
  if (lvlrange->high_str == NULL) {
3971
0
    cil_destroy_level(lvlrange->high);
3972
0
  }
3973
3974
0
  free(lvlrange);
3975
0
}
3976
3977
int cil_gen_constrain(struct cil_db *db, struct cil_tree_node *parse_current,
3978
          struct cil_tree_node *ast_node, enum cil_flavor flavor)
3979
0
{
3980
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
3981
0
             CIL_SYN_STRING | CIL_SYN_LIST,
3982
0
             CIL_SYN_LIST, CIL_SYN_END };
3983
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
3984
0
  struct cil_constrain *cons = NULL;
3985
0
  int rc = SEPOL_ERR;
3986
3987
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
3988
0
    goto exit;
3989
0
  }
3990
3991
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
3992
0
  if (rc != SEPOL_OK) {
3993
0
    goto exit;
3994
0
  }
3995
3996
0
  cil_constrain_init(&cons);
3997
3998
0
  rc = cil_fill_classperms_list(parse_current->next, &cons->classperms);
3999
0
  if (rc != SEPOL_OK) {
4000
0
    goto exit;
4001
0
  }
4002
4003
0
  rc = cil_gen_constraint_expr(parse_current->next->next, flavor,
4004
0
             &cons->str_expr);
4005
0
  if (rc != SEPOL_OK) {
4006
0
    goto exit;
4007
0
  }
4008
4009
0
  ast_node->data = cons;
4010
0
  ast_node->flavor = flavor;
4011
4012
0
  return SEPOL_OK;
4013
4014
0
exit:
4015
0
  cil_tree_log(parse_current, CIL_ERR, "Bad constrain declaration");
4016
0
  cil_destroy_constrain(cons);
4017
0
  return rc;
4018
0
}
4019
4020
void cil_destroy_constrain(struct cil_constrain *cons)
4021
0
{
4022
0
  if (cons == NULL) {
4023
0
    return;
4024
0
  }
4025
4026
0
  cil_destroy_classperms_list(&cons->classperms);
4027
0
  cil_list_destroy(&cons->str_expr, CIL_TRUE);
4028
0
  cil_list_destroy(&cons->datum_expr, CIL_FALSE);
4029
4030
0
  free(cons);
4031
0
}
4032
4033
int cil_gen_validatetrans(struct cil_db *db,
4034
        struct cil_tree_node *parse_current,
4035
        struct cil_tree_node *ast_node,
4036
        enum cil_flavor flavor)
4037
0
{
4038
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
4039
0
             CIL_SYN_LIST, CIL_SYN_END };
4040
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4041
0
  struct cil_validatetrans *validtrans = NULL;
4042
0
  int rc = SEPOL_ERR;
4043
4044
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4045
0
    goto exit;
4046
0
  }
4047
4048
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4049
0
  if (rc != SEPOL_OK) {
4050
0
    goto exit;
4051
0
  }
4052
4053
0
  cil_validatetrans_init(&validtrans);
4054
4055
0
  validtrans->class_str = parse_current->next->data;
4056
4057
0
  rc = cil_gen_constraint_expr(parse_current->next->next, flavor,
4058
0
             &validtrans->str_expr);
4059
0
  if (rc != SEPOL_OK) {
4060
0
    goto exit;
4061
0
  }
4062
4063
0
  ast_node->data = validtrans;
4064
0
  ast_node->flavor = flavor;
4065
4066
0
  return SEPOL_OK;
4067
4068
0
exit:
4069
0
  cil_tree_log(parse_current, CIL_ERR, "Bad validatetrans declaration");
4070
0
  cil_destroy_validatetrans(validtrans);
4071
0
  return rc;
4072
0
}
4073
4074
void cil_destroy_validatetrans(struct cil_validatetrans *validtrans)
4075
0
{
4076
0
  if (validtrans == NULL) {
4077
0
    return;
4078
0
  }
4079
4080
0
  cil_list_destroy(&validtrans->str_expr, CIL_TRUE);
4081
0
  cil_list_destroy(&validtrans->datum_expr, CIL_FALSE);
4082
4083
0
  free(validtrans);
4084
0
}
4085
4086
/* Fills in context starting from user */
4087
int cil_fill_context(struct cil_tree_node *user_node,
4088
         struct cil_context *context)
4089
0
{
4090
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
4091
0
             CIL_SYN_STRING,
4092
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4093
0
             CIL_SYN_END };
4094
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4095
0
  int rc = SEPOL_ERR;
4096
4097
0
  if (user_node == NULL || context == NULL) {
4098
0
    goto exit;
4099
0
  }
4100
4101
0
  rc = __cil_verify_syntax(user_node, syntax, syntax_len);
4102
0
  if (rc != SEPOL_OK) {
4103
0
    goto exit;
4104
0
  }
4105
4106
0
  context->user_str = user_node->data;
4107
0
  context->role_str = user_node->next->data;
4108
0
  context->type_str = user_node->next->next->data;
4109
4110
0
  context->range_str = NULL;
4111
4112
0
  if (user_node->next->next->next->cl_head == NULL) {
4113
0
    context->range_str = user_node->next->next->next->data;
4114
0
  } else {
4115
0
    cil_levelrange_init(&context->range);
4116
4117
0
    rc = cil_fill_levelrange(user_node->next->next->next->cl_head,
4118
0
           context->range);
4119
0
    if (rc != SEPOL_OK) {
4120
0
      goto exit;
4121
0
    }
4122
0
  }
4123
4124
0
  return SEPOL_OK;
4125
4126
0
exit:
4127
0
  cil_log(CIL_ERR, "Bad context\n");
4128
0
  return rc;
4129
0
}
4130
4131
int cil_gen_context(struct cil_db *db, struct cil_tree_node *parse_current,
4132
        struct cil_tree_node *ast_node)
4133
0
{
4134
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
4135
0
             CIL_SYN_LIST, CIL_SYN_END };
4136
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4137
0
  char *key = NULL;
4138
0
  struct cil_context *context = NULL;
4139
0
  int rc = SEPOL_ERR;
4140
4141
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4142
0
    goto exit;
4143
0
  }
4144
4145
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4146
0
  if (rc != SEPOL_OK) {
4147
0
    goto exit;
4148
0
  }
4149
4150
0
  cil_context_init(&context);
4151
4152
0
  key = parse_current->next->data;
4153
4154
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)context,
4155
0
        (hashtab_key_t)key, CIL_SYM_CONTEXTS, CIL_CONTEXT);
4156
0
  if (rc != SEPOL_OK) {
4157
0
    goto exit;
4158
0
  }
4159
4160
0
  rc = cil_fill_context(parse_current->next->next->cl_head, context);
4161
0
  if (rc != SEPOL_OK) {
4162
0
    goto exit;
4163
0
  }
4164
4165
0
  return SEPOL_OK;
4166
4167
0
exit:
4168
0
  cil_tree_log(parse_current, CIL_ERR, "Bad context declaration");
4169
0
  cil_destroy_context(context);
4170
0
  cil_clear_node(ast_node);
4171
0
  return SEPOL_ERR;
4172
0
}
4173
4174
void cil_destroy_context(struct cil_context *context)
4175
0
{
4176
0
  if (context == NULL) {
4177
0
    return;
4178
0
  }
4179
4180
0
  cil_symtab_datum_destroy(&context->datum);
4181
4182
0
  if (context->range_str == NULL && context->range != NULL) {
4183
0
    cil_destroy_levelrange(context->range);
4184
0
  }
4185
4186
0
  free(context);
4187
0
}
4188
4189
int cil_gen_filecon(struct cil_db *db, struct cil_tree_node *parse_current,
4190
        struct cil_tree_node *ast_node)
4191
0
{
4192
0
  enum cil_syntax syntax[] = {
4193
0
    CIL_SYN_STRING, CIL_SYN_STRING, CIL_SYN_STRING,
4194
0
    CIL_SYN_STRING | CIL_SYN_LIST | CIL_SYN_EMPTY_LIST, CIL_SYN_END
4195
0
  };
4196
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4197
0
  int rc = SEPOL_ERR;
4198
0
  struct cil_filecon *filecon = NULL;
4199
0
  char *type = NULL;
4200
4201
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4202
0
    goto exit;
4203
0
  }
4204
4205
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4206
0
  if (rc != SEPOL_OK) {
4207
0
    goto exit;
4208
0
  }
4209
4210
0
  type = parse_current->next->next->data;
4211
0
  cil_filecon_init(&filecon);
4212
4213
0
  ast_node->data = filecon;
4214
0
  ast_node->flavor = CIL_FILECON;
4215
4216
0
  filecon->path_str = parse_current->next->data;
4217
  /* filecon->path will be NULL if in a macro and the path is an argument */
4218
0
  filecon->path =
4219
0
    cil_gen_declared_string(db, filecon->path_str, ast_node);
4220
4221
0
  if (type == CIL_KEY_ANY) {
4222
0
    filecon->type = CIL_FILECON_ANY;
4223
0
  } else if (type == CIL_KEY_FILE) {
4224
0
    filecon->type = CIL_FILECON_FILE;
4225
0
  } else if (type == CIL_KEY_DIR) {
4226
0
    filecon->type = CIL_FILECON_DIR;
4227
0
  } else if (type == CIL_KEY_CHAR) {
4228
0
    filecon->type = CIL_FILECON_CHAR;
4229
0
  } else if (type == CIL_KEY_BLOCK) {
4230
0
    filecon->type = CIL_FILECON_BLOCK;
4231
0
  } else if (type == CIL_KEY_SOCKET) {
4232
0
    filecon->type = CIL_FILECON_SOCKET;
4233
0
  } else if (type == CIL_KEY_PIPE) {
4234
0
    filecon->type = CIL_FILECON_PIPE;
4235
0
  } else if (type == CIL_KEY_SYMLINK) {
4236
0
    filecon->type = CIL_FILECON_SYMLINK;
4237
0
  } else {
4238
0
    cil_log(CIL_ERR, "Invalid file type\n");
4239
0
    rc = SEPOL_ERR;
4240
0
    goto exit;
4241
0
  }
4242
4243
0
  if (parse_current->next->next->next->cl_head == NULL) {
4244
0
    filecon->context_str = parse_current->next->next->next->data;
4245
0
  } else {
4246
0
    if (parse_current->next->next->next->cl_head->next == NULL) {
4247
0
      filecon->context = NULL;
4248
0
    } else {
4249
0
      cil_context_init(&filecon->context);
4250
4251
0
      rc = cil_fill_context(
4252
0
        parse_current->next->next->next->cl_head,
4253
0
        filecon->context);
4254
0
      if (rc != SEPOL_OK) {
4255
0
        goto exit;
4256
0
      }
4257
0
    }
4258
0
  }
4259
4260
0
  return SEPOL_OK;
4261
4262
0
exit:
4263
0
  cil_tree_log(parse_current, CIL_ERR, "Bad filecon declaration");
4264
0
  cil_destroy_filecon(filecon);
4265
0
  cil_clear_node(ast_node);
4266
0
  return rc;
4267
0
}
4268
4269
//TODO: Should we be checking if the pointer is NULL when passed in?
4270
void cil_destroy_filecon(struct cil_filecon *filecon)
4271
0
{
4272
0
  if (filecon == NULL) {
4273
0
    return;
4274
0
  }
4275
4276
0
  if (filecon->context_str == NULL && filecon->context != NULL) {
4277
0
    cil_destroy_context(filecon->context);
4278
0
  }
4279
4280
0
  free(filecon);
4281
0
}
4282
4283
int cil_gen_ibpkeycon(__attribute__((unused)) struct cil_db *db,
4284
          struct cil_tree_node *parse_current,
4285
          struct cil_tree_node *ast_node)
4286
0
{
4287
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
4288
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4289
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4290
0
             CIL_SYN_END };
4291
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4292
0
  int rc = SEPOL_ERR;
4293
0
  struct cil_ibpkeycon *ibpkeycon = NULL;
4294
4295
0
  if (!parse_current || !ast_node)
4296
0
    goto exit;
4297
4298
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4299
0
  if (rc != SEPOL_OK)
4300
0
    goto exit;
4301
4302
0
  cil_ibpkeycon_init(&ibpkeycon);
4303
4304
0
  ibpkeycon->subnet_prefix_str = parse_current->next->data;
4305
4306
0
  if (parse_current->next->next->cl_head) {
4307
0
    if (parse_current->next->next->cl_head->next &&
4308
0
        !parse_current->next->next->cl_head->next->next) {
4309
0
      rc = cil_fill_integer(
4310
0
        parse_current->next->next->cl_head,
4311
0
        &ibpkeycon->pkey_low, 0);
4312
0
      if (rc != SEPOL_OK) {
4313
0
        cil_log(CIL_ERR, "Improper ibpkey specified\n");
4314
0
        goto exit;
4315
0
      }
4316
0
      rc = cil_fill_integer(
4317
0
        parse_current->next->next->cl_head->next,
4318
0
        &ibpkeycon->pkey_high, 0);
4319
0
      if (rc != SEPOL_OK) {
4320
0
        cil_log(CIL_ERR, "Improper ibpkey specified\n");
4321
0
        goto exit;
4322
0
      }
4323
0
    } else {
4324
0
      cil_log(CIL_ERR, "Improper ibpkey range specified\n");
4325
0
      rc = SEPOL_ERR;
4326
0
      goto exit;
4327
0
    }
4328
0
  } else {
4329
0
    rc = cil_fill_integer(parse_current->next->next,
4330
0
              &ibpkeycon->pkey_low, 0);
4331
0
    if (rc != SEPOL_OK) {
4332
0
      cil_log(CIL_ERR, "Improper ibpkey specified\n");
4333
0
      goto exit;
4334
0
    }
4335
0
    ibpkeycon->pkey_high = ibpkeycon->pkey_low;
4336
0
  }
4337
4338
0
  if (!parse_current->next->next->next->cl_head) {
4339
0
    ibpkeycon->context_str = parse_current->next->next->next->data;
4340
0
  } else {
4341
0
    cil_context_init(&ibpkeycon->context);
4342
4343
0
    rc = cil_fill_context(parse_current->next->next->next->cl_head,
4344
0
              ibpkeycon->context);
4345
0
    if (rc != SEPOL_OK)
4346
0
      goto exit;
4347
0
  }
4348
4349
0
  ast_node->data = ibpkeycon;
4350
0
  ast_node->flavor = CIL_IBPKEYCON;
4351
0
  return SEPOL_OK;
4352
4353
0
exit:
4354
0
  cil_tree_log(parse_current, CIL_ERR, "Bad ibpkeycon declaration");
4355
0
  cil_destroy_ibpkeycon(ibpkeycon);
4356
4357
0
  return rc;
4358
0
}
4359
4360
void cil_destroy_ibpkeycon(struct cil_ibpkeycon *ibpkeycon)
4361
0
{
4362
0
  if (!ibpkeycon)
4363
0
    return;
4364
4365
0
  if (!ibpkeycon->context_str && ibpkeycon->context)
4366
0
    cil_destroy_context(ibpkeycon->context);
4367
4368
0
  free(ibpkeycon);
4369
0
}
4370
4371
int cil_gen_portcon(struct cil_db *db, struct cil_tree_node *parse_current,
4372
        struct cil_tree_node *ast_node)
4373
0
{
4374
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
4375
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4376
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4377
0
             CIL_SYN_END };
4378
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4379
0
  int rc = SEPOL_ERR;
4380
0
  struct cil_portcon *portcon = NULL;
4381
0
  char *proto;
4382
4383
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4384
0
    goto exit;
4385
0
  }
4386
4387
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4388
0
  if (rc != SEPOL_OK) {
4389
0
    goto exit;
4390
0
  }
4391
4392
0
  cil_portcon_init(&portcon);
4393
4394
0
  proto = parse_current->next->data;
4395
0
  if (proto == CIL_KEY_UDP) {
4396
0
    portcon->proto = CIL_PROTOCOL_UDP;
4397
0
  } else if (proto == CIL_KEY_TCP) {
4398
0
    portcon->proto = CIL_PROTOCOL_TCP;
4399
0
  } else if (proto == CIL_KEY_DCCP) {
4400
0
    portcon->proto = CIL_PROTOCOL_DCCP;
4401
0
  } else if (proto == CIL_KEY_SCTP) {
4402
0
    portcon->proto = CIL_PROTOCOL_SCTP;
4403
0
  } else {
4404
0
    cil_log(CIL_ERR, "Invalid protocol\n");
4405
0
    rc = SEPOL_ERR;
4406
0
    goto exit;
4407
0
  }
4408
4409
0
  if (parse_current->next->next->cl_head != NULL) {
4410
0
    if (parse_current->next->next->cl_head->next != NULL &&
4411
0
        parse_current->next->next->cl_head->next->next == NULL) {
4412
0
      rc = cil_fill_integer(
4413
0
        parse_current->next->next->cl_head,
4414
0
        &portcon->port_low, 10);
4415
0
      if (rc != SEPOL_OK) {
4416
0
        cil_log(CIL_ERR, "Improper port specified\n");
4417
0
        goto exit;
4418
0
      }
4419
0
      rc = cil_fill_integer(
4420
0
        parse_current->next->next->cl_head->next,
4421
0
        &portcon->port_high, 10);
4422
0
      if (rc != SEPOL_OK) {
4423
0
        cil_log(CIL_ERR, "Improper port specified\n");
4424
0
        goto exit;
4425
0
      }
4426
0
    } else {
4427
0
      cil_log(CIL_ERR, "Improper port range specified\n");
4428
0
      rc = SEPOL_ERR;
4429
0
      goto exit;
4430
0
    }
4431
0
  } else {
4432
0
    rc = cil_fill_integer(parse_current->next->next,
4433
0
              &portcon->port_low, 10);
4434
0
    if (rc != SEPOL_OK) {
4435
0
      cil_log(CIL_ERR, "Improper port specified\n");
4436
0
      goto exit;
4437
0
    }
4438
0
    portcon->port_high = portcon->port_low;
4439
0
  }
4440
4441
0
  if (parse_current->next->next->next->cl_head == NULL) {
4442
0
    portcon->context_str = parse_current->next->next->next->data;
4443
0
  } else {
4444
0
    cil_context_init(&portcon->context);
4445
4446
0
    rc = cil_fill_context(parse_current->next->next->next->cl_head,
4447
0
              portcon->context);
4448
0
    if (rc != SEPOL_OK) {
4449
0
      goto exit;
4450
0
    }
4451
0
  }
4452
4453
0
  ast_node->data = portcon;
4454
0
  ast_node->flavor = CIL_PORTCON;
4455
4456
0
  return SEPOL_OK;
4457
4458
0
exit:
4459
0
  cil_tree_log(parse_current, CIL_ERR, "Bad portcon declaration");
4460
0
  cil_destroy_portcon(portcon);
4461
0
  return rc;
4462
0
}
4463
4464
void cil_destroy_portcon(struct cil_portcon *portcon)
4465
0
{
4466
0
  if (portcon == NULL) {
4467
0
    return;
4468
0
  }
4469
4470
0
  if (portcon->context_str == NULL && portcon->context != NULL) {
4471
0
    cil_destroy_context(portcon->context);
4472
0
  }
4473
4474
0
  free(portcon);
4475
0
}
4476
4477
int cil_gen_nodecon(struct cil_db *db, struct cil_tree_node *parse_current,
4478
        struct cil_tree_node *ast_node)
4479
0
{
4480
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
4481
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4482
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4483
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4484
0
             CIL_SYN_END };
4485
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4486
0
  int rc = SEPOL_ERR;
4487
0
  struct cil_nodecon *nodecon = NULL;
4488
4489
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4490
0
    goto exit;
4491
0
  }
4492
4493
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4494
0
  if (rc != SEPOL_OK) {
4495
0
    goto exit;
4496
0
  }
4497
4498
0
  cil_nodecon_init(&nodecon);
4499
4500
0
  if (parse_current->next->cl_head) {
4501
0
    cil_ipaddr_init(&nodecon->addr);
4502
0
    rc = cil_fill_ipaddr(parse_current->next->cl_head,
4503
0
             nodecon->addr);
4504
0
    if (rc != SEPOL_OK) {
4505
0
      goto exit;
4506
0
    }
4507
0
  } else {
4508
0
    char *addr = parse_current->next->data;
4509
0
    if (strchr(addr, ':') ||
4510
0
        (strchr(addr, '.') && isdigit((unsigned char)addr[0]))) {
4511
0
      cil_ipaddr_init(&nodecon->addr);
4512
0
      rc = cil_fill_ipaddr(parse_current->next,
4513
0
               nodecon->addr);
4514
0
      if (rc != SEPOL_OK) {
4515
0
        goto exit;
4516
0
      }
4517
0
    } else {
4518
0
      nodecon->addr_str = addr;
4519
0
    }
4520
0
  }
4521
4522
0
  if (parse_current->next->next->cl_head) {
4523
0
    cil_ipaddr_init(&nodecon->mask);
4524
0
    rc = cil_fill_ipaddr(parse_current->next->next->cl_head,
4525
0
             nodecon->mask);
4526
0
    if (rc != SEPOL_OK) {
4527
0
      goto exit;
4528
0
    }
4529
0
  } else {
4530
0
    char *mask = parse_current->next->next->data;
4531
0
    if (strchr(mask, ':') ||
4532
0
        (strchr(mask, '.') && isdigit((unsigned char)mask[0]))) {
4533
0
      cil_ipaddr_init(&nodecon->mask);
4534
0
      rc = cil_fill_ipaddr(parse_current->next->next,
4535
0
               nodecon->mask);
4536
0
      if (rc != SEPOL_OK) {
4537
0
        goto exit;
4538
0
      }
4539
0
    } else {
4540
0
      nodecon->mask_str = mask;
4541
0
    }
4542
0
  }
4543
4544
0
  if (parse_current->next->next->next->cl_head == NULL) {
4545
0
    nodecon->context_str = parse_current->next->next->next->data;
4546
0
  } else {
4547
0
    cil_context_init(&nodecon->context);
4548
4549
0
    rc = cil_fill_context(parse_current->next->next->next->cl_head,
4550
0
              nodecon->context);
4551
0
    if (rc != SEPOL_OK) {
4552
0
      goto exit;
4553
0
    }
4554
0
  }
4555
4556
0
  ast_node->data = nodecon;
4557
0
  ast_node->flavor = CIL_NODECON;
4558
4559
0
  return SEPOL_OK;
4560
4561
0
exit:
4562
0
  cil_tree_log(parse_current, CIL_ERR, "Bad nodecon declaration");
4563
0
  cil_destroy_nodecon(nodecon);
4564
0
  return rc;
4565
0
}
4566
4567
void cil_destroy_nodecon(struct cil_nodecon *nodecon)
4568
0
{
4569
0
  if (nodecon == NULL) {
4570
0
    return;
4571
0
  }
4572
4573
0
  if (nodecon->addr_str == NULL && nodecon->addr != NULL) {
4574
0
    cil_destroy_ipaddr(nodecon->addr);
4575
0
  }
4576
4577
0
  if (nodecon->mask_str == NULL && nodecon->mask != NULL) {
4578
0
    cil_destroy_ipaddr(nodecon->mask);
4579
0
  }
4580
4581
0
  if (nodecon->context_str == NULL && nodecon->context != NULL) {
4582
0
    cil_destroy_context(nodecon->context);
4583
0
  }
4584
4585
0
  free(nodecon);
4586
0
}
4587
4588
int cil_gen_genfscon(struct cil_db *db, struct cil_tree_node *parse_current,
4589
         struct cil_tree_node *ast_node)
4590
0
{
4591
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
4592
0
             CIL_SYN_STRING,
4593
0
             CIL_SYN_STRING,
4594
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4595
0
             CIL_SYN_STRING | CIL_SYN_LIST |
4596
0
               CIL_SYN_END,
4597
0
             CIL_SYN_END };
4598
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4599
0
  struct cil_tree_node *context_node;
4600
0
  int rc = SEPOL_ERR;
4601
0
  struct cil_genfscon *genfscon = NULL;
4602
4603
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4604
0
    goto exit;
4605
0
  }
4606
4607
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4608
0
  if (rc != SEPOL_OK) {
4609
0
    goto exit;
4610
0
  }
4611
4612
0
  cil_genfscon_init(&genfscon);
4613
4614
0
  genfscon->fs_str = parse_current->next->data;
4615
0
  genfscon->path_str = parse_current->next->next->data;
4616
4617
0
  if (parse_current->next->next->next->next) {
4618
    /* (genfscon <FS_STR> <PATH_STR> <FILE_TYPE> ... */
4619
0
    char *file_type = parse_current->next->next->next->data;
4620
0
    if (file_type == CIL_KEY_ANY) {
4621
0
      genfscon->file_type = CIL_FILECON_ANY;
4622
0
    } else if (file_type == CIL_KEY_FILE) {
4623
0
      genfscon->file_type = CIL_FILECON_FILE;
4624
0
    } else if (file_type == CIL_KEY_DIR) {
4625
0
      genfscon->file_type = CIL_FILECON_DIR;
4626
0
    } else if (file_type == CIL_KEY_CHAR) {
4627
0
      genfscon->file_type = CIL_FILECON_CHAR;
4628
0
    } else if (file_type == CIL_KEY_BLOCK) {
4629
0
      genfscon->file_type = CIL_FILECON_BLOCK;
4630
0
    } else if (file_type == CIL_KEY_SOCKET) {
4631
0
      genfscon->file_type = CIL_FILECON_SOCKET;
4632
0
    } else if (file_type == CIL_KEY_PIPE) {
4633
0
      genfscon->file_type = CIL_FILECON_PIPE;
4634
0
    } else if (file_type == CIL_KEY_SYMLINK) {
4635
0
      genfscon->file_type = CIL_FILECON_SYMLINK;
4636
0
    } else {
4637
0
      if (parse_current->next->next->next->cl_head) {
4638
0
        cil_log(CIL_ERR,
4639
0
          "Expecting file type, but found a list\n");
4640
0
      } else {
4641
0
        cil_log(CIL_ERR, "Invalid file type \"%s\"\n",
4642
0
          file_type);
4643
0
      }
4644
0
      goto exit;
4645
0
    }
4646
0
    context_node = parse_current->next->next->next->next;
4647
0
  } else {
4648
    /* (genfscon <FS_STR> <PATH_STR> ... */
4649
0
    context_node = parse_current->next->next->next;
4650
0
  }
4651
4652
0
  if (context_node->cl_head) {
4653
0
    cil_context_init(&genfscon->context);
4654
0
    rc = cil_fill_context(context_node->cl_head, genfscon->context);
4655
0
    if (rc != SEPOL_OK) {
4656
0
      goto exit;
4657
0
    }
4658
0
  } else {
4659
0
    genfscon->context_str = context_node->data;
4660
0
  }
4661
4662
0
  ast_node->data = genfscon;
4663
0
  ast_node->flavor = CIL_GENFSCON;
4664
4665
0
  return SEPOL_OK;
4666
4667
0
exit:
4668
0
  cil_tree_log(parse_current, CIL_ERR, "Bad genfscon declaration");
4669
0
  cil_destroy_genfscon(genfscon);
4670
0
  return SEPOL_ERR;
4671
0
}
4672
4673
void cil_destroy_genfscon(struct cil_genfscon *genfscon)
4674
0
{
4675
0
  if (genfscon == NULL) {
4676
0
    return;
4677
0
  }
4678
4679
0
  if (genfscon->context_str == NULL && genfscon->context != NULL) {
4680
0
    cil_destroy_context(genfscon->context);
4681
0
  }
4682
4683
0
  free(genfscon);
4684
0
}
4685
4686
int cil_gen_netifcon(struct cil_db *db, struct cil_tree_node *parse_current,
4687
         struct cil_tree_node *ast_node)
4688
0
{
4689
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
4690
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4691
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4692
0
             CIL_SYN_END };
4693
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4694
0
  int rc = SEPOL_ERR;
4695
0
  struct cil_netifcon *netifcon = NULL;
4696
4697
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4698
0
    goto exit;
4699
0
  }
4700
4701
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4702
0
  if (rc != SEPOL_OK) {
4703
0
    goto exit;
4704
0
  }
4705
4706
0
  cil_netifcon_init(&netifcon);
4707
4708
0
  netifcon->interface_str = parse_current->next->data;
4709
4710
0
  if (parse_current->next->next->cl_head == NULL) {
4711
0
    netifcon->if_context_str = parse_current->next->next->data;
4712
0
  } else {
4713
0
    cil_context_init(&netifcon->if_context);
4714
4715
0
    rc = cil_fill_context(parse_current->next->next->cl_head,
4716
0
              netifcon->if_context);
4717
0
    if (rc != SEPOL_OK) {
4718
0
      goto exit;
4719
0
    }
4720
0
  }
4721
4722
0
  if (parse_current->next->next->next->cl_head == NULL) {
4723
0
    netifcon->packet_context_str =
4724
0
      parse_current->next->next->next->data;
4725
0
  } else {
4726
0
    cil_context_init(&netifcon->packet_context);
4727
4728
0
    rc = cil_fill_context(parse_current->next->next->next->cl_head,
4729
0
              netifcon->packet_context);
4730
0
    if (rc != SEPOL_OK) {
4731
0
      goto exit;
4732
0
    }
4733
0
  }
4734
4735
0
  ast_node->data = netifcon;
4736
0
  ast_node->flavor = CIL_NETIFCON;
4737
4738
0
  return SEPOL_OK;
4739
4740
0
exit:
4741
0
  cil_tree_log(parse_current, CIL_ERR, "Bad netifcon declaration");
4742
0
  cil_destroy_netifcon(netifcon);
4743
0
  return SEPOL_ERR;
4744
0
}
4745
4746
void cil_destroy_netifcon(struct cil_netifcon *netifcon)
4747
0
{
4748
0
  if (netifcon == NULL) {
4749
0
    return;
4750
0
  }
4751
4752
0
  if (netifcon->if_context_str == NULL && netifcon->if_context != NULL) {
4753
0
    cil_destroy_context(netifcon->if_context);
4754
0
  }
4755
4756
0
  if (netifcon->packet_context_str == NULL &&
4757
0
      netifcon->packet_context != NULL) {
4758
0
    cil_destroy_context(netifcon->packet_context);
4759
0
  }
4760
4761
0
  free(netifcon);
4762
0
}
4763
4764
int cil_gen_ibendportcon(__attribute__((unused)) struct cil_db *db,
4765
       struct cil_tree_node *parse_current,
4766
       struct cil_tree_node *ast_node)
4767
0
{
4768
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
4769
0
             CIL_SYN_STRING,
4770
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4771
0
             CIL_SYN_END };
4772
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4773
0
  int rc = SEPOL_ERR;
4774
0
  struct cil_ibendportcon *ibendportcon = NULL;
4775
4776
0
  if (!parse_current || !ast_node)
4777
0
    goto exit;
4778
4779
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4780
0
  if (rc != SEPOL_OK)
4781
0
    goto exit;
4782
4783
0
  cil_ibendportcon_init(&ibendportcon);
4784
4785
0
  ibendportcon->dev_name_str = parse_current->next->data;
4786
4787
0
  rc = cil_fill_integer(parse_current->next->next, &ibendportcon->port,
4788
0
            10);
4789
0
  if (rc != SEPOL_OK) {
4790
0
    cil_log(CIL_ERR, "Improper ibendport port specified\n");
4791
0
    goto exit;
4792
0
  }
4793
4794
0
  if (!parse_current->next->next->next->cl_head) {
4795
0
    ibendportcon->context_str =
4796
0
      parse_current->next->next->next->data;
4797
0
  } else {
4798
0
    cil_context_init(&ibendportcon->context);
4799
4800
0
    rc = cil_fill_context(parse_current->next->next->next->cl_head,
4801
0
              ibendportcon->context);
4802
0
    if (rc != SEPOL_OK)
4803
0
      goto exit;
4804
0
  }
4805
4806
0
  ast_node->data = ibendportcon;
4807
0
  ast_node->flavor = CIL_IBENDPORTCON;
4808
4809
0
  return SEPOL_OK;
4810
4811
0
exit:
4812
0
  cil_tree_log(parse_current, CIL_ERR, "Bad ibendportcon declaration");
4813
0
  cil_destroy_ibendportcon(ibendportcon);
4814
0
  return SEPOL_ERR;
4815
0
}
4816
4817
void cil_destroy_ibendportcon(struct cil_ibendportcon *ibendportcon)
4818
0
{
4819
0
  if (!ibendportcon)
4820
0
    return;
4821
4822
0
  if (!ibendportcon->context_str && ibendportcon->context)
4823
0
    cil_destroy_context(ibendportcon->context);
4824
4825
0
  free(ibendportcon);
4826
0
}
4827
4828
int cil_gen_pirqcon(struct cil_db *db, struct cil_tree_node *parse_current,
4829
        struct cil_tree_node *ast_node)
4830
0
{
4831
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
4832
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4833
0
             CIL_SYN_END };
4834
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4835
0
  int rc = SEPOL_ERR;
4836
0
  struct cil_pirqcon *pirqcon = NULL;
4837
4838
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4839
0
    goto exit;
4840
0
  }
4841
4842
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4843
0
  if (rc != SEPOL_OK) {
4844
0
    goto exit;
4845
0
  }
4846
4847
0
  cil_pirqcon_init(&pirqcon);
4848
4849
0
  rc = cil_fill_integer(parse_current->next, &pirqcon->pirq, 10);
4850
0
  if (rc != SEPOL_OK) {
4851
0
    goto exit;
4852
0
  }
4853
4854
0
  if (parse_current->next->next->cl_head == NULL) {
4855
0
    pirqcon->context_str = parse_current->next->next->data;
4856
0
  } else {
4857
0
    cil_context_init(&pirqcon->context);
4858
4859
0
    rc = cil_fill_context(parse_current->next->next->cl_head,
4860
0
              pirqcon->context);
4861
0
    if (rc != SEPOL_OK) {
4862
0
      goto exit;
4863
0
    }
4864
0
  }
4865
4866
0
  ast_node->data = pirqcon;
4867
0
  ast_node->flavor = CIL_PIRQCON;
4868
4869
0
  return SEPOL_OK;
4870
4871
0
exit:
4872
0
  cil_tree_log(parse_current, CIL_ERR, "Bad pirqcon declaration");
4873
0
  cil_destroy_pirqcon(pirqcon);
4874
0
  return rc;
4875
0
}
4876
4877
void cil_destroy_pirqcon(struct cil_pirqcon *pirqcon)
4878
0
{
4879
0
  if (pirqcon == NULL) {
4880
0
    return;
4881
0
  }
4882
4883
0
  if (pirqcon->context_str == NULL && pirqcon->context != NULL) {
4884
0
    cil_destroy_context(pirqcon->context);
4885
0
  }
4886
4887
0
  free(pirqcon);
4888
0
}
4889
4890
int cil_gen_iomemcon(struct cil_db *db, struct cil_tree_node *parse_current,
4891
         struct cil_tree_node *ast_node)
4892
0
{
4893
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
4894
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4895
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4896
0
             CIL_SYN_END };
4897
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4898
0
  int rc = SEPOL_ERR;
4899
0
  struct cil_iomemcon *iomemcon = NULL;
4900
4901
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4902
0
    goto exit;
4903
0
  }
4904
4905
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4906
0
  if (rc != SEPOL_OK) {
4907
0
    goto exit;
4908
0
  }
4909
4910
0
  cil_iomemcon_init(&iomemcon);
4911
4912
0
  if (parse_current->next->cl_head != NULL) {
4913
0
    if (parse_current->next->cl_head->next != NULL &&
4914
0
        parse_current->next->cl_head->next->next == NULL) {
4915
0
      rc = cil_fill_integer64(parse_current->next->cl_head,
4916
0
            &iomemcon->iomem_low, 0);
4917
0
      if (rc != SEPOL_OK) {
4918
0
        cil_log(CIL_ERR, "Improper iomem specified\n");
4919
0
        goto exit;
4920
0
      }
4921
0
      rc = cil_fill_integer64(
4922
0
        parse_current->next->cl_head->next,
4923
0
        &iomemcon->iomem_high, 0);
4924
0
      if (rc != SEPOL_OK) {
4925
0
        cil_log(CIL_ERR, "Improper iomem specified\n");
4926
0
        goto exit;
4927
0
      }
4928
0
    } else {
4929
0
      cil_log(CIL_ERR, "Improper iomem range specified\n");
4930
0
      rc = SEPOL_ERR;
4931
0
      goto exit;
4932
0
    }
4933
0
  } else {
4934
0
    rc = cil_fill_integer64(parse_current->next,
4935
0
          &iomemcon->iomem_low, 0);
4936
0
    if (rc != SEPOL_OK) {
4937
0
      cil_log(CIL_ERR, "Improper iomem specified\n");
4938
0
      goto exit;
4939
0
    }
4940
0
    iomemcon->iomem_high = iomemcon->iomem_low;
4941
0
  }
4942
4943
0
  if (parse_current->next->next->cl_head == NULL) {
4944
0
    iomemcon->context_str = parse_current->next->next->data;
4945
0
  } else {
4946
0
    cil_context_init(&iomemcon->context);
4947
4948
0
    rc = cil_fill_context(parse_current->next->next->cl_head,
4949
0
              iomemcon->context);
4950
0
    if (rc != SEPOL_OK) {
4951
0
      goto exit;
4952
0
    }
4953
0
  }
4954
4955
0
  ast_node->data = iomemcon;
4956
0
  ast_node->flavor = CIL_IOMEMCON;
4957
4958
0
  return SEPOL_OK;
4959
4960
0
exit:
4961
0
  cil_tree_log(parse_current, CIL_ERR, "Bad iomemcon declaration");
4962
0
  cil_destroy_iomemcon(iomemcon);
4963
0
  return rc;
4964
0
}
4965
4966
void cil_destroy_iomemcon(struct cil_iomemcon *iomemcon)
4967
0
{
4968
0
  if (iomemcon == NULL) {
4969
0
    return;
4970
0
  }
4971
4972
0
  if (iomemcon->context_str == NULL && iomemcon->context != NULL) {
4973
0
    cil_destroy_context(iomemcon->context);
4974
0
  }
4975
4976
0
  free(iomemcon);
4977
0
}
4978
4979
int cil_gen_ioportcon(struct cil_db *db, struct cil_tree_node *parse_current,
4980
          struct cil_tree_node *ast_node)
4981
0
{
4982
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
4983
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4984
0
             CIL_SYN_STRING | CIL_SYN_LIST,
4985
0
             CIL_SYN_END };
4986
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
4987
0
  int rc = SEPOL_ERR;
4988
0
  struct cil_ioportcon *ioportcon = NULL;
4989
4990
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
4991
0
    goto exit;
4992
0
  }
4993
4994
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
4995
0
  if (rc != SEPOL_OK) {
4996
0
    goto exit;
4997
0
  }
4998
4999
0
  cil_ioportcon_init(&ioportcon);
5000
5001
0
  if (parse_current->next->cl_head != NULL) {
5002
0
    if (parse_current->next->cl_head->next != NULL &&
5003
0
        parse_current->next->cl_head->next->next == NULL) {
5004
0
      rc = cil_fill_integer(parse_current->next->cl_head,
5005
0
                &ioportcon->ioport_low, 0);
5006
0
      if (rc != SEPOL_OK) {
5007
0
        cil_log(CIL_ERR, "Improper ioport specified\n");
5008
0
        goto exit;
5009
0
      }
5010
0
      rc = cil_fill_integer(
5011
0
        parse_current->next->cl_head->next,
5012
0
        &ioportcon->ioport_high, 0);
5013
0
      if (rc != SEPOL_OK) {
5014
0
        cil_log(CIL_ERR, "Improper ioport specified\n");
5015
0
        goto exit;
5016
0
      }
5017
0
    } else {
5018
0
      cil_log(CIL_ERR, "Improper ioport range specified\n");
5019
0
      rc = SEPOL_ERR;
5020
0
      goto exit;
5021
0
    }
5022
0
  } else {
5023
0
    rc = cil_fill_integer(parse_current->next,
5024
0
              &ioportcon->ioport_low, 0);
5025
0
    if (rc != SEPOL_OK) {
5026
0
      cil_log(CIL_ERR, "Improper ioport specified\n");
5027
0
      goto exit;
5028
0
    }
5029
0
    ioportcon->ioport_high = ioportcon->ioport_low;
5030
0
  }
5031
5032
0
  if (parse_current->next->next->cl_head == NULL) {
5033
0
    ioportcon->context_str = parse_current->next->next->data;
5034
0
  } else {
5035
0
    cil_context_init(&ioportcon->context);
5036
5037
0
    rc = cil_fill_context(parse_current->next->next->cl_head,
5038
0
              ioportcon->context);
5039
0
    if (rc != SEPOL_OK) {
5040
0
      goto exit;
5041
0
    }
5042
0
  }
5043
5044
0
  ast_node->data = ioportcon;
5045
0
  ast_node->flavor = CIL_IOPORTCON;
5046
5047
0
  return SEPOL_OK;
5048
5049
0
exit:
5050
0
  cil_tree_log(parse_current, CIL_ERR, "Bad ioportcon declaration");
5051
0
  cil_destroy_ioportcon(ioportcon);
5052
0
  return rc;
5053
0
}
5054
5055
void cil_destroy_ioportcon(struct cil_ioportcon *ioportcon)
5056
0
{
5057
0
  if (ioportcon == NULL) {
5058
0
    return;
5059
0
  }
5060
5061
0
  if (ioportcon->context_str == NULL && ioportcon->context != NULL) {
5062
0
    cil_destroy_context(ioportcon->context);
5063
0
  }
5064
5065
0
  free(ioportcon);
5066
0
}
5067
5068
int cil_gen_pcidevicecon(struct cil_db *db, struct cil_tree_node *parse_current,
5069
       struct cil_tree_node *ast_node)
5070
0
{
5071
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
5072
0
             CIL_SYN_STRING | CIL_SYN_LIST,
5073
0
             CIL_SYN_END };
5074
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5075
0
  int rc = SEPOL_ERR;
5076
0
  struct cil_pcidevicecon *pcidevicecon = NULL;
5077
5078
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
5079
0
    goto exit;
5080
0
  }
5081
5082
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5083
0
  if (rc != SEPOL_OK) {
5084
0
    goto exit;
5085
0
  }
5086
5087
0
  cil_pcidevicecon_init(&pcidevicecon);
5088
5089
0
  rc = cil_fill_integer(parse_current->next, &pcidevicecon->dev, 0);
5090
0
  if (rc != SEPOL_OK) {
5091
0
    goto exit;
5092
0
  }
5093
5094
0
  if (parse_current->next->next->cl_head == NULL) {
5095
0
    pcidevicecon->context_str = parse_current->next->next->data;
5096
0
  } else {
5097
0
    cil_context_init(&pcidevicecon->context);
5098
5099
0
    rc = cil_fill_context(parse_current->next->next->cl_head,
5100
0
              pcidevicecon->context);
5101
0
    if (rc != SEPOL_OK) {
5102
0
      goto exit;
5103
0
    }
5104
0
  }
5105
5106
0
  ast_node->data = pcidevicecon;
5107
0
  ast_node->flavor = CIL_PCIDEVICECON;
5108
5109
0
  return SEPOL_OK;
5110
5111
0
exit:
5112
0
  cil_tree_log(parse_current, CIL_ERR, "Bad pcidevicecon declaration");
5113
0
  cil_destroy_pcidevicecon(pcidevicecon);
5114
0
  return rc;
5115
0
}
5116
5117
void cil_destroy_pcidevicecon(struct cil_pcidevicecon *pcidevicecon)
5118
0
{
5119
0
  if (pcidevicecon == NULL) {
5120
0
    return;
5121
0
  }
5122
5123
0
  if (pcidevicecon->context_str == NULL &&
5124
0
      pcidevicecon->context != NULL) {
5125
0
    cil_destroy_context(pcidevicecon->context);
5126
0
  }
5127
5128
0
  free(pcidevicecon);
5129
0
}
5130
5131
int cil_gen_devicetreecon(struct cil_db *db,
5132
        struct cil_tree_node *parse_current,
5133
        struct cil_tree_node *ast_node)
5134
0
{
5135
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
5136
0
             CIL_SYN_STRING | CIL_SYN_LIST,
5137
0
             CIL_SYN_END };
5138
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5139
0
  int rc = SEPOL_ERR;
5140
0
  struct cil_devicetreecon *devicetreecon = NULL;
5141
5142
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
5143
0
    goto exit;
5144
0
  }
5145
5146
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5147
0
  if (rc != SEPOL_OK) {
5148
0
    goto exit;
5149
0
  }
5150
5151
0
  cil_devicetreecon_init(&devicetreecon);
5152
5153
0
  devicetreecon->path = parse_current->next->data;
5154
5155
0
  if (parse_current->next->next->cl_head == NULL) {
5156
0
    devicetreecon->context_str = parse_current->next->next->data;
5157
0
  } else {
5158
0
    cil_context_init(&devicetreecon->context);
5159
5160
0
    rc = cil_fill_context(parse_current->next->next->cl_head,
5161
0
              devicetreecon->context);
5162
0
    if (rc != SEPOL_OK) {
5163
0
      goto exit;
5164
0
    }
5165
0
  }
5166
5167
0
  ast_node->data = devicetreecon;
5168
0
  ast_node->flavor = CIL_DEVICETREECON;
5169
5170
0
  return SEPOL_OK;
5171
5172
0
exit:
5173
0
  cil_tree_log(parse_current, CIL_ERR, "Bad devicetreecon declaration");
5174
0
  cil_destroy_devicetreecon(devicetreecon);
5175
0
  return rc;
5176
0
}
5177
5178
void cil_destroy_devicetreecon(struct cil_devicetreecon *devicetreecon)
5179
0
{
5180
0
  if (devicetreecon == NULL) {
5181
0
    return;
5182
0
  }
5183
5184
0
  if (devicetreecon->context_str == NULL &&
5185
0
      devicetreecon->context != NULL) {
5186
0
    cil_destroy_context(devicetreecon->context);
5187
0
  }
5188
5189
0
  free(devicetreecon);
5190
0
}
5191
5192
int cil_gen_fsuse(struct cil_db *db, struct cil_tree_node *parse_current,
5193
      struct cil_tree_node *ast_node)
5194
0
{
5195
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
5196
0
             CIL_SYN_STRING,
5197
0
             CIL_SYN_STRING | CIL_SYN_LIST,
5198
0
             CIL_SYN_END };
5199
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5200
0
  char *type = NULL;
5201
0
  struct cil_fsuse *fsuse = NULL;
5202
0
  int rc = SEPOL_ERR;
5203
5204
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
5205
0
    goto exit;
5206
0
  }
5207
5208
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5209
0
  if (rc != SEPOL_OK) {
5210
0
    goto exit;
5211
0
  }
5212
5213
0
  type = parse_current->next->data;
5214
5215
0
  cil_fsuse_init(&fsuse);
5216
5217
0
  if (type == CIL_KEY_XATTR) {
5218
0
    fsuse->type = CIL_FSUSE_XATTR;
5219
0
  } else if (type == CIL_KEY_TASK) {
5220
0
    fsuse->type = CIL_FSUSE_TASK;
5221
0
  } else if (type == CIL_KEY_TRANS) {
5222
0
    fsuse->type = CIL_FSUSE_TRANS;
5223
0
  } else {
5224
0
    cil_log(CIL_ERR, "Invalid fsuse type\n");
5225
0
    goto exit;
5226
0
  }
5227
5228
0
  fsuse->fs_str = parse_current->next->next->data;
5229
5230
0
  if (parse_current->next->next->next->cl_head == NULL) {
5231
0
    fsuse->context_str = parse_current->next->next->next->data;
5232
0
  } else {
5233
0
    cil_context_init(&fsuse->context);
5234
5235
0
    rc = cil_fill_context(parse_current->next->next->next->cl_head,
5236
0
              fsuse->context);
5237
0
    if (rc != SEPOL_OK) {
5238
0
      goto exit;
5239
0
    }
5240
0
  }
5241
5242
0
  ast_node->data = fsuse;
5243
0
  ast_node->flavor = CIL_FSUSE;
5244
5245
0
  return SEPOL_OK;
5246
5247
0
exit:
5248
0
  cil_tree_log(parse_current, CIL_ERR, "Bad fsuse declaration");
5249
0
  cil_destroy_fsuse(fsuse);
5250
0
  return SEPOL_ERR;
5251
0
}
5252
5253
void cil_destroy_fsuse(struct cil_fsuse *fsuse)
5254
0
{
5255
0
  if (fsuse == NULL) {
5256
0
    return;
5257
0
  }
5258
5259
0
  if (fsuse->context_str == NULL && fsuse->context != NULL) {
5260
0
    cil_destroy_context(fsuse->context);
5261
0
  }
5262
5263
0
  free(fsuse);
5264
0
}
5265
5266
void cil_destroy_param(struct cil_param *param)
5267
0
{
5268
0
  if (param == NULL) {
5269
0
    return;
5270
0
  }
5271
5272
0
  free(param);
5273
0
}
5274
5275
int cil_gen_macro(struct cil_db *db, struct cil_tree_node *parse_current,
5276
      struct cil_tree_node *ast_node)
5277
0
{
5278
0
  int rc = SEPOL_ERR;
5279
0
  char *key = NULL;
5280
0
  struct cil_macro *macro = NULL;
5281
0
  struct cil_tree_node *macro_content = NULL;
5282
0
  struct cil_tree_node *current_item;
5283
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
5284
0
             CIL_SYN_LIST | CIL_SYN_EMPTY_LIST,
5285
0
             CIL_SYN_N_LISTS | CIL_SYN_END,
5286
0
             CIL_SYN_END };
5287
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5288
5289
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
5290
0
    goto exit;
5291
0
  }
5292
5293
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5294
0
  if (rc != SEPOL_OK) {
5295
0
    goto exit;
5296
0
  }
5297
5298
0
  cil_macro_init(&macro);
5299
5300
0
  key = parse_current->next->data;
5301
5302
0
  current_item = parse_current->next->next->cl_head;
5303
0
  while (current_item != NULL) {
5304
0
    enum cil_syntax param_syntax[] = { CIL_SYN_STRING,
5305
0
               CIL_SYN_STRING,
5306
0
               CIL_SYN_END };
5307
0
    int param_syntax_len =
5308
0
      sizeof(param_syntax) / sizeof(*param_syntax);
5309
0
    char *kind = NULL;
5310
0
    struct cil_param *param = NULL;
5311
0
    struct cil_list_item *curr_param;
5312
5313
0
    rc = __cil_verify_syntax(current_item->cl_head, param_syntax,
5314
0
           param_syntax_len);
5315
0
    if (rc != SEPOL_OK) {
5316
0
      goto exit;
5317
0
    }
5318
5319
0
    if (macro->params == NULL) {
5320
0
      cil_list_init(&macro->params, CIL_LIST_ITEM);
5321
0
    }
5322
5323
0
    kind = current_item->cl_head->data;
5324
0
    cil_param_init(&param);
5325
5326
0
    if (kind == CIL_KEY_TYPE) {
5327
0
      param->flavor = CIL_TYPE;
5328
0
    } else if (kind == CIL_KEY_ROLE) {
5329
0
      param->flavor = CIL_ROLE;
5330
0
    } else if (kind == CIL_KEY_USER) {
5331
0
      param->flavor = CIL_USER;
5332
0
    } else if (kind == CIL_KEY_SENSITIVITY) {
5333
0
      param->flavor = CIL_SENS;
5334
0
    } else if (kind == CIL_KEY_CATEGORY) {
5335
0
      param->flavor = CIL_CAT;
5336
0
    } else if (kind == CIL_KEY_CATSET) {
5337
0
      param->flavor = CIL_CATSET;
5338
0
    } else if (kind == CIL_KEY_LEVEL) {
5339
0
      param->flavor = CIL_LEVEL;
5340
0
    } else if (kind == CIL_KEY_LEVELRANGE) {
5341
0
      param->flavor = CIL_LEVELRANGE;
5342
0
    } else if (kind == CIL_KEY_CLASS) {
5343
0
      param->flavor = CIL_CLASS;
5344
0
    } else if (kind == CIL_KEY_IPADDR) {
5345
0
      param->flavor = CIL_IPADDR;
5346
0
    } else if (kind == CIL_KEY_MAP_CLASS) {
5347
0
      param->flavor = CIL_MAP_CLASS;
5348
0
    } else if (kind == CIL_KEY_CLASSPERMISSION) {
5349
0
      param->flavor = CIL_CLASSPERMISSION;
5350
0
    } else if (kind == CIL_KEY_BOOL) {
5351
0
      param->flavor = CIL_BOOL;
5352
0
    } else if (kind == CIL_KEY_STRING) {
5353
0
      param->flavor = CIL_DECLARED_STRING;
5354
0
    } else if (kind == CIL_KEY_NAME) {
5355
0
      param->flavor = CIL_DECLARED_STRING;
5356
0
    } else {
5357
0
      cil_log(CIL_ERR,
5358
0
        "The kind %s is not allowed as a parameter\n",
5359
0
        kind);
5360
0
      cil_destroy_param(param);
5361
0
      goto exit;
5362
0
    }
5363
5364
0
    param->str = current_item->cl_head->next->data;
5365
5366
0
    rc = cil_verify_name(db, param->str, param->flavor);
5367
0
    if (rc != SEPOL_OK) {
5368
0
      cil_destroy_param(param);
5369
0
      goto exit;
5370
0
    }
5371
5372
    //walk current list and check for duplicate parameters
5373
0
    cil_list_for_each(curr_param, macro->params) {
5374
0
      if (param->str ==
5375
0
          ((struct cil_param *)curr_param->data)->str) {
5376
0
        cil_log(CIL_ERR, "Duplicate parameter\n");
5377
0
        cil_destroy_param(param);
5378
0
        goto exit;
5379
0
      }
5380
0
    }
5381
5382
0
    cil_list_append(macro->params, CIL_PARAM, param);
5383
5384
0
    current_item = current_item->next;
5385
0
  }
5386
5387
  /* we don't want the tree walker to walk the macro parameters (they were just handled above), so the subtree is deleted, and the next pointer of the
5388
           node containing the macro name is updated to point to the start of the macro content */
5389
0
  macro_content = parse_current->next->next->next;
5390
0
  cil_tree_subtree_destroy(parse_current->next->next);
5391
0
  parse_current->next->next = macro_content;
5392
0
  if (macro_content == NULL) {
5393
    /* No statements in macro and macro parameter list was last node */
5394
0
    parse_current->parent->cl_tail = parse_current->next;
5395
0
  }
5396
5397
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)macro,
5398
0
        (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_MACRO);
5399
0
  if (rc != SEPOL_OK) {
5400
0
    goto exit;
5401
0
  }
5402
5403
0
  return SEPOL_OK;
5404
5405
0
exit:
5406
0
  cil_tree_log(parse_current, CIL_ERR, "Bad macro declaration");
5407
0
  cil_destroy_macro(macro);
5408
0
  cil_clear_node(ast_node);
5409
0
  return SEPOL_ERR;
5410
0
}
5411
5412
void cil_destroy_macro(struct cil_macro *macro)
5413
0
{
5414
0
  if (macro == NULL) {
5415
0
    return;
5416
0
  }
5417
5418
0
  cil_symtab_datum_destroy(&macro->datum);
5419
0
  cil_symtab_array_destroy(macro->symtab);
5420
5421
0
  if (macro->params != NULL) {
5422
0
    cil_list_destroy(&macro->params, 1);
5423
0
  }
5424
5425
0
  free(macro);
5426
0
}
5427
5428
int cil_gen_call(struct cil_db *db, struct cil_tree_node *parse_current,
5429
     struct cil_tree_node *ast_node)
5430
0
{
5431
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
5432
0
             CIL_SYN_LIST | CIL_SYN_EMPTY_LIST |
5433
0
               CIL_SYN_END,
5434
0
             CIL_SYN_END };
5435
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5436
0
  struct cil_call *call = NULL;
5437
0
  int rc = SEPOL_ERR;
5438
5439
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
5440
0
    goto exit;
5441
0
  }
5442
5443
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5444
0
  if (rc != SEPOL_OK) {
5445
0
    goto exit;
5446
0
  }
5447
5448
0
  cil_call_init(&call);
5449
5450
0
  call->macro_str = parse_current->next->data;
5451
5452
0
  if (parse_current->next->next != NULL) {
5453
0
    cil_tree_init(&call->args_tree);
5454
0
    cil_copy_ast(db, parse_current->next->next,
5455
0
           call->args_tree->root);
5456
0
  }
5457
5458
0
  ast_node->data = call;
5459
0
  ast_node->flavor = CIL_CALL;
5460
5461
0
  return SEPOL_OK;
5462
5463
0
exit:
5464
0
  cil_tree_log(parse_current, CIL_ERR, "Bad macro call");
5465
0
  cil_destroy_call(call);
5466
0
  return rc;
5467
0
}
5468
5469
void cil_destroy_call(struct cil_call *call)
5470
0
{
5471
0
  if (call == NULL) {
5472
0
    return;
5473
0
  }
5474
5475
0
  call->macro = NULL;
5476
5477
0
  if (call->args_tree != NULL) {
5478
0
    cil_tree_destroy(&call->args_tree);
5479
0
  }
5480
5481
0
  if (call->args != NULL) {
5482
0
    cil_list_destroy(&call->args, 1);
5483
0
  }
5484
5485
0
  free(call);
5486
0
}
5487
5488
void cil_destroy_args(struct cil_args *args)
5489
0
{
5490
0
  if (args == NULL) {
5491
0
    return;
5492
0
  }
5493
5494
0
  if (args->arg_str != NULL) {
5495
0
    args->arg_str = NULL;
5496
0
  } else if (args->arg != NULL) {
5497
0
    struct cil_tree_node *node = args->arg->nodes->head->data;
5498
0
    switch (args->flavor) {
5499
0
    case CIL_DECLARED_STRING:
5500
0
      break;
5501
0
    case CIL_CATSET:
5502
0
      cil_destroy_catset((struct cil_catset *)args->arg);
5503
0
      free(node);
5504
0
      break;
5505
0
    case CIL_LEVEL:
5506
0
      cil_destroy_level((struct cil_level *)args->arg);
5507
0
      free(node);
5508
0
      break;
5509
0
    case CIL_LEVELRANGE:
5510
0
      cil_destroy_levelrange(
5511
0
        (struct cil_levelrange *)args->arg);
5512
0
      free(node);
5513
0
      break;
5514
0
    case CIL_IPADDR:
5515
0
      cil_destroy_ipaddr((struct cil_ipaddr *)args->arg);
5516
0
      free(node);
5517
0
      break;
5518
0
    case CIL_CLASSPERMISSION:
5519
0
      cil_destroy_classpermission(
5520
0
        (struct cil_classpermission *)args->arg);
5521
0
      free(node);
5522
0
      break;
5523
0
    default:
5524
0
      cil_log(CIL_ERR,
5525
0
        "Destroying arg with the unexpected flavor=%d\n",
5526
0
        args->flavor);
5527
0
      break;
5528
0
    }
5529
0
  }
5530
5531
0
  args->param_str = NULL;
5532
0
  args->arg = NULL;
5533
5534
0
  free(args);
5535
0
}
5536
5537
int cil_gen_optional(struct cil_db *db, struct cil_tree_node *parse_current,
5538
         struct cil_tree_node *ast_node)
5539
0
{
5540
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
5541
0
             CIL_SYN_N_LISTS | CIL_SYN_END,
5542
0
             CIL_SYN_END };
5543
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5544
0
  char *key = NULL;
5545
0
  struct cil_optional *optional = NULL;
5546
0
  int rc = SEPOL_ERR;
5547
5548
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
5549
0
    goto exit;
5550
0
  }
5551
5552
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5553
0
  if (rc != SEPOL_OK) {
5554
0
    goto exit;
5555
0
  }
5556
5557
0
  cil_optional_init(&optional);
5558
5559
0
  key = parse_current->next->data;
5560
5561
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)optional,
5562
0
        (hashtab_key_t)key, CIL_SYM_BLOCKS, CIL_OPTIONAL);
5563
0
  if (rc != SEPOL_OK) {
5564
0
    if (rc == SEPOL_EEXIST) {
5565
0
      cil_destroy_optional(optional);
5566
0
      optional = NULL;
5567
0
    } else {
5568
0
      goto exit;
5569
0
    }
5570
0
  }
5571
5572
0
  return SEPOL_OK;
5573
5574
0
exit:
5575
0
  cil_tree_log(parse_current, CIL_ERR, "Bad optional");
5576
0
  cil_destroy_optional(optional);
5577
0
  cil_clear_node(ast_node);
5578
0
  return rc;
5579
0
}
5580
5581
void cil_destroy_optional(struct cil_optional *optional)
5582
0
{
5583
0
  if (optional == NULL) {
5584
0
    return;
5585
0
  }
5586
5587
0
  cil_symtab_datum_destroy(&optional->datum);
5588
0
  free(optional);
5589
0
}
5590
5591
int cil_gen_policycap(struct cil_db *db, struct cil_tree_node *parse_current,
5592
          struct cil_tree_node *ast_node)
5593
0
{
5594
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
5595
0
             CIL_SYN_END };
5596
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5597
0
  char *key = NULL;
5598
0
  struct cil_policycap *polcap = NULL;
5599
0
  int rc = SEPOL_ERR;
5600
5601
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
5602
0
    goto exit;
5603
0
  }
5604
5605
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5606
0
  if (rc != SEPOL_OK) {
5607
0
    goto exit;
5608
0
  }
5609
5610
0
  cil_policycap_init(&polcap);
5611
5612
0
  key = parse_current->next->data;
5613
5614
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)polcap,
5615
0
        (hashtab_key_t)key, CIL_SYM_POLICYCAPS,
5616
0
        CIL_POLICYCAP);
5617
0
  if (rc != SEPOL_OK) {
5618
0
    if (rc == SEPOL_EEXIST) {
5619
0
      cil_destroy_policycap(polcap);
5620
0
      polcap = NULL;
5621
0
    } else {
5622
0
      goto exit;
5623
0
    }
5624
0
  }
5625
5626
0
  return SEPOL_OK;
5627
5628
0
exit:
5629
0
  cil_tree_log(parse_current, CIL_ERR, "Bad policycap statement");
5630
0
  cil_destroy_policycap(polcap);
5631
0
  cil_clear_node(ast_node);
5632
0
  return rc;
5633
0
}
5634
5635
void cil_destroy_policycap(struct cil_policycap *polcap)
5636
0
{
5637
0
  if (polcap == NULL) {
5638
0
    return;
5639
0
  }
5640
5641
0
  cil_symtab_datum_destroy(&polcap->datum);
5642
0
  free(polcap);
5643
0
}
5644
5645
int cil_gen_ipaddr(struct cil_db *db, struct cil_tree_node *parse_current,
5646
       struct cil_tree_node *ast_node)
5647
0
{
5648
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
5649
0
             CIL_SYN_STRING, CIL_SYN_END };
5650
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5651
0
  char *key = NULL;
5652
0
  struct cil_ipaddr *ipaddr = NULL;
5653
0
  int rc = SEPOL_ERR;
5654
5655
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
5656
0
    goto exit;
5657
0
  }
5658
5659
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5660
0
  if (rc != SEPOL_OK) {
5661
0
    goto exit;
5662
0
  }
5663
5664
0
  cil_ipaddr_init(&ipaddr);
5665
5666
0
  key = parse_current->next->data;
5667
5668
0
  rc = cil_fill_ipaddr(parse_current->next->next, ipaddr);
5669
0
  if (rc != SEPOL_OK) {
5670
0
    goto exit;
5671
0
  }
5672
5673
0
  rc = cil_gen_node(db, ast_node, (struct cil_symtab_datum *)ipaddr,
5674
0
        (hashtab_key_t)key, CIL_SYM_IPADDRS, CIL_IPADDR);
5675
0
  if (rc != SEPOL_OK) {
5676
0
    goto exit;
5677
0
  }
5678
5679
0
  return SEPOL_OK;
5680
5681
0
exit:
5682
0
  cil_tree_log(parse_current, CIL_ERR, "Bad ipaddr statement");
5683
0
  cil_destroy_ipaddr(ipaddr);
5684
0
  cil_clear_node(ast_node);
5685
0
  return rc;
5686
0
}
5687
5688
void cil_destroy_ipaddr(struct cil_ipaddr *ipaddr)
5689
0
{
5690
0
  if (ipaddr == NULL) {
5691
0
    return;
5692
0
  }
5693
5694
0
  cil_symtab_datum_destroy(&ipaddr->datum);
5695
0
  free(ipaddr);
5696
0
}
5697
5698
int cil_fill_integer(struct cil_tree_node *int_node, uint32_t *integer,
5699
         int base)
5700
0
{
5701
0
  int rc = SEPOL_ERR;
5702
5703
0
  if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5704
0
    goto exit;
5705
0
  }
5706
5707
0
  rc = cil_string_to_uint32(int_node->data, integer, base);
5708
0
  if (rc != SEPOL_OK) {
5709
0
    goto exit;
5710
0
  }
5711
5712
0
  return SEPOL_OK;
5713
5714
0
exit:
5715
0
  cil_log(CIL_ERR, "Failed to fill 32-bit integer\n");
5716
0
  return rc;
5717
0
}
5718
5719
int cil_fill_integer64(struct cil_tree_node *int_node, uint64_t *integer,
5720
           int base)
5721
0
{
5722
0
  int rc = SEPOL_ERR;
5723
5724
0
  if (int_node == NULL || int_node->data == NULL || integer == NULL) {
5725
0
    goto exit;
5726
0
  }
5727
5728
0
  rc = cil_string_to_uint64(int_node->data, integer, base);
5729
0
  if (rc != SEPOL_OK) {
5730
0
    goto exit;
5731
0
  }
5732
5733
0
  return SEPOL_OK;
5734
5735
0
exit:
5736
0
  cil_log(CIL_ERR, "Failed to fill 64-bit integer\n");
5737
0
  return rc;
5738
0
}
5739
5740
int cil_fill_ipaddr(struct cil_tree_node *addr_node, struct cil_ipaddr *addr)
5741
0
{
5742
0
  int rc = SEPOL_ERR;
5743
0
  char *addr_str;
5744
5745
0
  if (addr_node == NULL || addr_node->data == NULL || addr == NULL) {
5746
0
    goto exit;
5747
0
  }
5748
5749
0
  addr_str = addr_node->data;
5750
0
  if (strchr(addr_str, ':')) {
5751
0
    addr->family = AF_INET6;
5752
0
  } else if (strchr(addr_str, '.') &&
5753
0
       isdigit((unsigned char)addr_str[0])) {
5754
0
    addr->family = AF_INET;
5755
0
  } else {
5756
0
    goto exit;
5757
0
  }
5758
5759
0
  rc = inet_pton(addr->family, addr_node->data, &addr->ip);
5760
0
  if (rc != 1) {
5761
0
    rc = SEPOL_ERR;
5762
0
    goto exit;
5763
0
  }
5764
5765
0
  return SEPOL_OK;
5766
5767
0
exit:
5768
0
  cil_log(CIL_ERR, "Bad ip address or netmask: %s\n",
5769
0
    (addr_node && addr_node->data) ? (const char *)addr_node->data :
5770
0
             "NULL");
5771
0
  return rc;
5772
0
}
5773
5774
int cil_fill_level(struct cil_tree_node *curr, struct cil_level *level)
5775
0
{
5776
0
  int rc = SEPOL_ERR;
5777
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
5778
0
             CIL_SYN_STRING | CIL_SYN_LIST |
5779
0
               CIL_SYN_END,
5780
0
             CIL_SYN_END };
5781
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5782
5783
0
  if (curr == NULL) {
5784
0
    goto exit;
5785
0
  }
5786
5787
0
  rc = __cil_verify_syntax(curr, syntax, syntax_len);
5788
0
  if (rc != SEPOL_OK) {
5789
0
    goto exit;
5790
0
  }
5791
5792
0
  level->sens_str = curr->data;
5793
0
  if (curr->next != NULL) {
5794
0
    rc = cil_fill_cats(curr->next, &level->cats);
5795
0
    if (rc != SEPOL_OK) {
5796
0
      goto exit;
5797
0
    }
5798
0
  }
5799
5800
0
  return SEPOL_OK;
5801
5802
0
exit:
5803
0
  cil_log(CIL_ERR, "Bad level\n");
5804
0
  return rc;
5805
0
}
5806
5807
int cil_fill_cats(struct cil_tree_node *curr, struct cil_cats **cats)
5808
0
{
5809
0
  int rc = SEPOL_ERR;
5810
5811
0
  cil_cats_init(cats);
5812
5813
0
  rc = cil_gen_expr(curr, CIL_CAT, &(*cats)->str_expr);
5814
0
  if (rc != SEPOL_OK) {
5815
0
    cil_destroy_cats(*cats);
5816
0
    *cats = NULL;
5817
0
  }
5818
5819
0
  return rc;
5820
0
}
5821
5822
void cil_destroy_cats(struct cil_cats *cats)
5823
0
{
5824
0
  if (cats == NULL) {
5825
0
    return;
5826
0
  }
5827
5828
0
  cil_list_destroy(&cats->str_expr, CIL_TRUE);
5829
5830
0
  cil_list_destroy(&cats->datum_expr, CIL_FALSE);
5831
5832
0
  free(cats);
5833
0
}
5834
int cil_gen_bounds(struct cil_db *db, struct cil_tree_node *parse_current,
5835
       struct cil_tree_node *ast_node, enum cil_flavor flavor)
5836
0
{
5837
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
5838
0
             CIL_SYN_STRING, CIL_SYN_END };
5839
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5840
0
  struct cil_bounds *bounds = NULL;
5841
0
  int rc = SEPOL_ERR;
5842
5843
0
  if (db == NULL || parse_current == NULL || ast_node == NULL) {
5844
0
    goto exit;
5845
0
  }
5846
5847
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5848
0
  if (rc != SEPOL_OK) {
5849
0
    goto exit;
5850
0
  }
5851
5852
0
  cil_bounds_init(&bounds);
5853
5854
0
  bounds->parent_str = parse_current->next->data;
5855
0
  bounds->child_str = parse_current->next->next->data;
5856
5857
0
  ast_node->data = bounds;
5858
5859
0
  switch (flavor) {
5860
0
  case CIL_USER:
5861
0
    ast_node->flavor = CIL_USERBOUNDS;
5862
0
    break;
5863
0
  case CIL_ROLE:
5864
0
    ast_node->flavor = CIL_ROLEBOUNDS;
5865
0
    break;
5866
0
  case CIL_TYPE:
5867
0
    ast_node->flavor = CIL_TYPEBOUNDS;
5868
0
    break;
5869
0
  default:
5870
0
    break;
5871
0
  }
5872
5873
0
  return SEPOL_OK;
5874
5875
0
exit:
5876
0
  cil_tree_log(parse_current, CIL_ERR, "Bad bounds declaration");
5877
0
  cil_destroy_bounds(bounds);
5878
0
  return rc;
5879
0
}
5880
5881
void cil_destroy_bounds(struct cil_bounds *bounds)
5882
0
{
5883
0
  if (bounds == NULL) {
5884
0
    return;
5885
0
  }
5886
5887
0
  free(bounds);
5888
0
}
5889
5890
int cil_gen_default(struct cil_tree_node *parse_current,
5891
        struct cil_tree_node *ast_node, enum cil_flavor flavor)
5892
0
{
5893
0
  int rc = SEPOL_ERR;
5894
0
  struct cil_default *def = NULL;
5895
0
  char *object;
5896
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
5897
0
             CIL_SYN_STRING | CIL_SYN_LIST,
5898
0
             CIL_SYN_STRING, CIL_SYN_END };
5899
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5900
5901
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5902
0
  if (rc != SEPOL_OK) {
5903
0
    goto exit;
5904
0
  }
5905
5906
0
  cil_default_init(&def);
5907
5908
0
  def->flavor = flavor;
5909
5910
0
  if (parse_current->next->cl_head == NULL) {
5911
0
    cil_list_init(&def->class_strs, CIL_CLASS);
5912
0
    cil_list_append(def->class_strs, CIL_STRING,
5913
0
        parse_current->next->data);
5914
0
  } else {
5915
0
    rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS,
5916
0
           &def->class_strs);
5917
0
    if (rc != SEPOL_OK) {
5918
0
      goto exit;
5919
0
    }
5920
0
  }
5921
5922
0
  object = parse_current->next->next->data;
5923
0
  if (object == CIL_KEY_SOURCE) {
5924
0
    def->object = CIL_DEFAULT_SOURCE;
5925
0
  } else if (object == CIL_KEY_TARGET) {
5926
0
    def->object = CIL_DEFAULT_TARGET;
5927
0
  } else {
5928
0
    cil_log(CIL_ERR, "Expected either 'source' or 'target'\n");
5929
0
    rc = SEPOL_ERR;
5930
0
    goto exit;
5931
0
  }
5932
5933
0
  ast_node->data = def;
5934
0
  ast_node->flavor = flavor;
5935
5936
0
  return SEPOL_OK;
5937
5938
0
exit:
5939
0
  cil_tree_log(parse_current, CIL_ERR, "Bad %s declaration",
5940
0
         cil_node_to_string(parse_current));
5941
0
  cil_destroy_default(def);
5942
0
  return rc;
5943
0
}
5944
5945
void cil_destroy_default(struct cil_default *def)
5946
0
{
5947
0
  if (def == NULL) {
5948
0
    return;
5949
0
  }
5950
5951
0
  cil_list_destroy(&def->class_strs, CIL_TRUE);
5952
5953
0
  cil_list_destroy(&def->class_datums, CIL_FALSE);
5954
5955
0
  free(def);
5956
0
}
5957
5958
int cil_gen_defaultrange(struct cil_tree_node *parse_current,
5959
       struct cil_tree_node *ast_node)
5960
0
{
5961
0
  int rc = SEPOL_ERR;
5962
0
  struct cil_defaultrange *def = NULL;
5963
0
  char *object;
5964
0
  char *range;
5965
0
  enum cil_syntax syntax[] = {
5966
0
    CIL_SYN_STRING, CIL_SYN_STRING | CIL_SYN_LIST, CIL_SYN_STRING,
5967
0
    CIL_SYN_STRING | CIL_SYN_END, CIL_SYN_END
5968
0
  };
5969
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
5970
5971
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
5972
0
  if (rc != SEPOL_OK) {
5973
0
    goto exit;
5974
0
  }
5975
5976
0
  cil_defaultrange_init(&def);
5977
5978
0
  if (parse_current->next->cl_head == NULL) {
5979
0
    cil_list_init(&def->class_strs, CIL_CLASS);
5980
0
    cil_list_append(def->class_strs, CIL_STRING,
5981
0
        parse_current->next->data);
5982
0
  } else {
5983
0
    rc = cil_fill_list(parse_current->next->cl_head, CIL_CLASS,
5984
0
           &def->class_strs);
5985
0
    if (rc != SEPOL_OK) {
5986
0
      goto exit;
5987
0
    }
5988
0
  }
5989
5990
0
  object = parse_current->next->next->data;
5991
0
  if (object == CIL_KEY_SOURCE) {
5992
0
    if (!parse_current->next->next->next) {
5993
0
      cil_log(CIL_ERR,
5994
0
        "Missing 'low', 'high', or 'low-high'\n");
5995
0
      rc = SEPOL_ERR;
5996
0
      goto exit;
5997
0
    }
5998
0
    range = parse_current->next->next->next->data;
5999
0
    if (range == CIL_KEY_LOW) {
6000
0
      def->object_range = CIL_DEFAULT_SOURCE_LOW;
6001
0
    } else if (range == CIL_KEY_HIGH) {
6002
0
      def->object_range = CIL_DEFAULT_SOURCE_HIGH;
6003
0
    } else if (range == CIL_KEY_LOW_HIGH) {
6004
0
      def->object_range = CIL_DEFAULT_SOURCE_LOW_HIGH;
6005
0
    } else {
6006
0
      cil_log(CIL_ERR,
6007
0
        "Expected 'low', 'high', or 'low-high'\n");
6008
0
      rc = SEPOL_ERR;
6009
0
      goto exit;
6010
0
    }
6011
0
  } else if (object == CIL_KEY_TARGET) {
6012
0
    if (!parse_current->next->next->next) {
6013
0
      cil_log(CIL_ERR,
6014
0
        "Missing 'low', 'high', or 'low-high'\n");
6015
0
      rc = SEPOL_ERR;
6016
0
      goto exit;
6017
0
    }
6018
0
    range = parse_current->next->next->next->data;
6019
0
    if (range == CIL_KEY_LOW) {
6020
0
      def->object_range = CIL_DEFAULT_TARGET_LOW;
6021
0
    } else if (range == CIL_KEY_HIGH) {
6022
0
      def->object_range = CIL_DEFAULT_TARGET_HIGH;
6023
0
    } else if (range == CIL_KEY_LOW_HIGH) {
6024
0
      def->object_range = CIL_DEFAULT_TARGET_LOW_HIGH;
6025
0
    } else {
6026
0
      cil_log(CIL_ERR,
6027
0
        "Expected 'low', 'high', or 'low-high'\n");
6028
0
      rc = SEPOL_ERR;
6029
0
      goto exit;
6030
0
    }
6031
0
  } else if (object == CIL_KEY_GLBLUB) {
6032
0
    def->object_range = CIL_DEFAULT_GLBLUB;
6033
0
  } else {
6034
0
    cil_log(CIL_ERR,
6035
0
      "Expected \'source\', \'target\', or \'glblub\'\n");
6036
0
    rc = SEPOL_ERR;
6037
0
    goto exit;
6038
0
  }
6039
6040
0
  ast_node->data = def;
6041
0
  ast_node->flavor = CIL_DEFAULTRANGE;
6042
6043
0
  return SEPOL_OK;
6044
6045
0
exit:
6046
0
  cil_tree_log(parse_current, CIL_ERR, "Bad defaultrange declaration");
6047
0
  cil_destroy_defaultrange(def);
6048
0
  return rc;
6049
0
}
6050
6051
void cil_destroy_defaultrange(struct cil_defaultrange *def)
6052
0
{
6053
0
  if (def == NULL) {
6054
0
    return;
6055
0
  }
6056
6057
0
  cil_list_destroy(&def->class_strs, CIL_TRUE);
6058
6059
0
  cil_list_destroy(&def->class_datums, CIL_FALSE);
6060
6061
0
  free(def);
6062
0
}
6063
6064
int cil_gen_handleunknown(struct cil_tree_node *parse_current,
6065
        struct cil_tree_node *ast_node)
6066
0
{
6067
0
  int rc = SEPOL_ERR;
6068
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
6069
0
             CIL_SYN_END };
6070
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
6071
0
  struct cil_handleunknown *unknown = NULL;
6072
0
  char *unknown_key;
6073
6074
0
  if (parse_current == NULL || ast_node == NULL) {
6075
0
    goto exit;
6076
0
  }
6077
6078
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6079
0
  if (rc != SEPOL_OK) {
6080
0
    goto exit;
6081
0
  }
6082
6083
0
  cil_handleunknown_init(&unknown);
6084
6085
0
  unknown_key = parse_current->next->data;
6086
0
  if (unknown_key == CIL_KEY_HANDLEUNKNOWN_ALLOW) {
6087
0
    unknown->handle_unknown = SEPOL_ALLOW_UNKNOWN;
6088
0
  } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_DENY) {
6089
0
    unknown->handle_unknown = SEPOL_DENY_UNKNOWN;
6090
0
  } else if (unknown_key == CIL_KEY_HANDLEUNKNOWN_REJECT) {
6091
0
    unknown->handle_unknown = SEPOL_REJECT_UNKNOWN;
6092
0
  } else {
6093
0
    cil_log(CIL_ERR, "Expected either \'%s\', \'%s\', or \'%s\'\n",
6094
0
      CIL_KEY_HANDLEUNKNOWN_ALLOW, CIL_KEY_HANDLEUNKNOWN_DENY,
6095
0
      CIL_KEY_HANDLEUNKNOWN_REJECT);
6096
0
    rc = SEPOL_ERR;
6097
0
    goto exit;
6098
0
  }
6099
6100
0
  ast_node->data = unknown;
6101
0
  ast_node->flavor = CIL_HANDLEUNKNOWN;
6102
6103
0
  return SEPOL_OK;
6104
6105
0
exit:
6106
0
  cil_tree_log(parse_current, CIL_ERR, "Bad handleunknown");
6107
0
  cil_destroy_handleunknown(unknown);
6108
0
  return rc;
6109
0
}
6110
6111
void cil_destroy_handleunknown(struct cil_handleunknown *unk)
6112
0
{
6113
0
  free(unk);
6114
0
}
6115
6116
int cil_gen_mls(struct cil_tree_node *parse_current,
6117
    struct cil_tree_node *ast_node)
6118
0
{
6119
0
  int rc = SEPOL_ERR;
6120
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING, CIL_SYN_STRING,
6121
0
             CIL_SYN_END };
6122
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
6123
0
  struct cil_mls *mls = NULL;
6124
6125
0
  if (parse_current == NULL || ast_node == NULL) {
6126
0
    goto exit;
6127
0
  }
6128
6129
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6130
0
  if (rc != SEPOL_OK) {
6131
0
    goto exit;
6132
0
  }
6133
6134
0
  cil_mls_init(&mls);
6135
6136
0
  if (parse_current->next->data == CIL_KEY_CONDTRUE) {
6137
0
    mls->value = CIL_TRUE;
6138
0
  } else if (parse_current->next->data == CIL_KEY_CONDFALSE) {
6139
0
    mls->value = CIL_FALSE;
6140
0
  } else {
6141
0
    cil_log(CIL_ERR, "Value must be either \'true\' or \'false\'");
6142
0
    rc = SEPOL_ERR;
6143
0
    goto exit;
6144
0
  }
6145
6146
0
  ast_node->data = mls;
6147
0
  ast_node->flavor = CIL_MLS;
6148
6149
0
  return SEPOL_OK;
6150
6151
0
exit:
6152
0
  cil_tree_log(parse_current, CIL_ERR, "Bad mls");
6153
0
  cil_destroy_mls(mls);
6154
0
  return rc;
6155
0
}
6156
6157
void cil_destroy_mls(struct cil_mls *mls)
6158
0
{
6159
0
  free(mls);
6160
0
}
6161
6162
int cil_gen_src_info(struct cil_tree_node *parse_current,
6163
         struct cil_tree_node *ast_node)
6164
0
{
6165
0
  int rc = SEPOL_ERR;
6166
0
  enum cil_syntax syntax[] = { CIL_SYN_STRING,
6167
0
             CIL_SYN_STRING,
6168
0
             CIL_SYN_STRING,
6169
0
             CIL_SYN_STRING,
6170
0
             CIL_SYN_N_LISTS | CIL_SYN_END,
6171
0
             CIL_SYN_END };
6172
0
  size_t syntax_len = sizeof(syntax) / sizeof(*syntax);
6173
0
  struct cil_src_info *info = NULL;
6174
6175
0
  if (parse_current == NULL || ast_node == NULL) {
6176
0
    goto exit;
6177
0
  }
6178
6179
0
  rc = __cil_verify_syntax(parse_current, syntax, syntax_len);
6180
0
  if (rc != SEPOL_OK) {
6181
0
    goto exit;
6182
0
  }
6183
6184
0
  cil_src_info_init(&info);
6185
6186
0
  info->kind = parse_current->next->data;
6187
0
  if (info->kind != CIL_KEY_SRC_CIL &&
6188
0
      info->kind != CIL_KEY_SRC_HLL_LMS &&
6189
0
      info->kind != CIL_KEY_SRC_HLL_LMX) {
6190
0
    cil_log(CIL_ERR, "Invalid src info kind\n");
6191
0
    rc = SEPOL_ERR;
6192
0
    goto exit;
6193
0
  }
6194
6195
0
  rc = cil_string_to_uint32(parse_current->next->next->data,
6196
0
          &info->hll_line, 10);
6197
0
  if (rc != SEPOL_OK) {
6198
0
    goto exit;
6199
0
  }
6200
6201
0
  info->path = parse_current->next->next->next->data;
6202
6203
0
  ast_node->data = info;
6204
0
  ast_node->flavor = CIL_SRC_INFO;
6205
6206
0
  return SEPOL_OK;
6207
6208
0
exit:
6209
0
  cil_tree_log(parse_current, CIL_ERR, "Bad src info");
6210
0
  cil_destroy_src_info(info);
6211
0
  return rc;
6212
0
}
6213
6214
void cil_destroy_src_info(struct cil_src_info *info)
6215
0
{
6216
0
  free(info);
6217
0
}
6218
6219
static int check_for_illegal_statement(struct cil_tree_node *parse_current,
6220
               struct cil_args_build *args)
6221
0
{
6222
0
  if (args->tunif != NULL) {
6223
0
    if (parse_current->data == CIL_KEY_TUNABLE) {
6224
0
      cil_tree_log(parse_current, CIL_ERR,
6225
0
             "%s is not allowed in tunableif",
6226
0
             (char *)parse_current->data);
6227
0
      return SEPOL_ERR;
6228
0
    }
6229
0
  }
6230
6231
0
  if (args->in != NULL) {
6232
0
    struct cil_in *in_block = args->in->data;
6233
0
    if (parse_current->data == CIL_KEY_TUNABLE ||
6234
0
        parse_current->data == CIL_KEY_IN) {
6235
0
      cil_tree_log(parse_current, CIL_ERR,
6236
0
             "%s is not allowed in in-statement",
6237
0
             (char *)parse_current->data);
6238
0
      return SEPOL_ERR;
6239
0
    }
6240
0
    if (in_block->is_after == CIL_TRUE) {
6241
0
      if (parse_current->data == CIL_KEY_BLOCKINHERIT ||
6242
0
          parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6243
0
        cil_tree_log(
6244
0
          parse_current, CIL_ERR,
6245
0
          "%s is not allowed in an after in-statement",
6246
0
          (char *)parse_current->data);
6247
0
        return SEPOL_ERR;
6248
0
      }
6249
0
    }
6250
0
  }
6251
6252
0
  if (args->macro != NULL) {
6253
0
    if (parse_current->data == CIL_KEY_TUNABLE ||
6254
0
        parse_current->data == CIL_KEY_IN ||
6255
0
        parse_current->data == CIL_KEY_BLOCK ||
6256
0
        parse_current->data == CIL_KEY_BLOCKINHERIT ||
6257
0
        parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6258
0
        parse_current->data == CIL_KEY_MACRO) {
6259
0
      cil_tree_log(parse_current, CIL_ERR,
6260
0
             "%s is not allowed in macro",
6261
0
             (char *)parse_current->data);
6262
0
      return SEPOL_ERR;
6263
0
    }
6264
0
  }
6265
6266
0
  if (args->optional != NULL) {
6267
0
    if (parse_current->data == CIL_KEY_TUNABLE ||
6268
0
        parse_current->data == CIL_KEY_IN ||
6269
0
        parse_current->data == CIL_KEY_BLOCK ||
6270
0
        parse_current->data == CIL_KEY_BLOCKABSTRACT ||
6271
0
        parse_current->data == CIL_KEY_MACRO) {
6272
0
      cil_tree_log(parse_current, CIL_ERR,
6273
0
             "%s is not allowed in optional",
6274
0
             (char *)parse_current->data);
6275
0
      return SEPOL_ERR;
6276
0
    }
6277
0
  }
6278
6279
0
  if (args->boolif != NULL) {
6280
0
    if (parse_current->data != CIL_KEY_TUNABLEIF &&
6281
0
        parse_current->data != CIL_KEY_CALL &&
6282
0
        parse_current->data != CIL_KEY_CONDTRUE &&
6283
0
        parse_current->data != CIL_KEY_CONDFALSE &&
6284
0
        parse_current->data != CIL_KEY_ALLOW &&
6285
0
        parse_current->data != CIL_KEY_DONTAUDIT &&
6286
0
        parse_current->data != CIL_KEY_AUDITALLOW &&
6287
0
        parse_current->data != CIL_KEY_TYPETRANSITION &&
6288
0
        parse_current->data != CIL_KEY_TYPECHANGE &&
6289
0
        parse_current->data != CIL_KEY_SRC_INFO &&
6290
0
        parse_current->data != CIL_KEY_TYPEMEMBER &&
6291
0
        ((args->db->policy_version < POLICYDB_VERSION_COND_XPERMS) ||
6292
0
         (parse_current->data != CIL_KEY_ALLOWX &&
6293
0
          parse_current->data != CIL_KEY_DONTAUDITX &&
6294
0
          parse_current->data != CIL_KEY_AUDITALLOWX))) {
6295
0
      if (((struct cil_booleanif *)args->boolif->data)
6296
0
            ->preserved_tunable) {
6297
0
        cil_tree_log(
6298
0
          parse_current, CIL_ERR,
6299
0
          "%s is not allowed in tunableif being treated as a booleanif",
6300
0
          (char *)parse_current->data);
6301
0
      } else {
6302
0
        cil_tree_log(parse_current, CIL_ERR,
6303
0
               "%s is not allowed in booleanif",
6304
0
               (char *)parse_current->data);
6305
0
      }
6306
0
      return SEPOL_ERR;
6307
0
    }
6308
0
  }
6309
6310
0
  return SEPOL_OK;
6311
0
}
6312
6313
static struct cil_tree_node *
6314
parse_statement(struct cil_db *db, struct cil_tree_node *parse_current,
6315
    struct cil_tree_node *ast_parent)
6316
0
{
6317
0
  struct cil_tree_node *new_ast_node = NULL;
6318
0
  int rc = SEPOL_ERR;
6319
6320
0
  cil_tree_node_init(&new_ast_node);
6321
0
  new_ast_node->parent = ast_parent;
6322
0
  new_ast_node->line = parse_current->line;
6323
0
  new_ast_node->hll_offset = parse_current->hll_offset;
6324
6325
0
  if (parse_current->data == CIL_KEY_BLOCK) {
6326
0
    rc = cil_gen_block(db, parse_current, new_ast_node, 0);
6327
0
  } else if (parse_current->data == CIL_KEY_BLOCKINHERIT) {
6328
0
    rc = cil_gen_blockinherit(db, parse_current, new_ast_node);
6329
0
  } else if (parse_current->data == CIL_KEY_BLOCKABSTRACT) {
6330
0
    rc = cil_gen_blockabstract(db, parse_current, new_ast_node);
6331
0
  } else if (parse_current->data == CIL_KEY_IN) {
6332
0
    rc = cil_gen_in(db, parse_current, new_ast_node);
6333
0
  } else if (parse_current->data == CIL_KEY_CLASS) {
6334
0
    rc = cil_gen_class(db, parse_current, new_ast_node);
6335
0
  } else if (parse_current->data == CIL_KEY_CLASSORDER) {
6336
0
    rc = cil_gen_ordered(db, parse_current, new_ast_node,
6337
0
             CIL_CLASSORDER);
6338
0
  } else if (parse_current->data == CIL_KEY_MAP_CLASS) {
6339
0
    rc = cil_gen_map_class(db, parse_current, new_ast_node);
6340
0
  } else if (parse_current->data == CIL_KEY_CLASSMAPPING) {
6341
0
    rc = cil_gen_classmapping(db, parse_current, new_ast_node);
6342
0
  } else if (parse_current->data == CIL_KEY_CLASSPERMISSION) {
6343
0
    rc = cil_gen_classpermission(db, parse_current, new_ast_node);
6344
0
  } else if (parse_current->data == CIL_KEY_CLASSPERMISSIONSET) {
6345
0
    rc = cil_gen_classpermissionset(db, parse_current,
6346
0
            new_ast_node);
6347
0
  } else if (parse_current->data == CIL_KEY_COMMON) {
6348
0
    rc = cil_gen_common(db, parse_current, new_ast_node);
6349
0
  } else if (parse_current->data == CIL_KEY_CLASSCOMMON) {
6350
0
    rc = cil_gen_classcommon(db, parse_current, new_ast_node);
6351
0
  } else if (parse_current->data == CIL_KEY_SID) {
6352
0
    rc = cil_gen_sid(db, parse_current, new_ast_node);
6353
0
  } else if (parse_current->data == CIL_KEY_SIDCONTEXT) {
6354
0
    rc = cil_gen_sidcontext(db, parse_current, new_ast_node);
6355
0
  } else if (parse_current->data == CIL_KEY_SIDORDER) {
6356
0
    rc = cil_gen_ordered(db, parse_current, new_ast_node,
6357
0
             CIL_SIDORDER);
6358
0
  } else if (parse_current->data == CIL_KEY_USER) {
6359
0
    rc = cil_gen_user(db, parse_current, new_ast_node);
6360
0
  } else if (parse_current->data == CIL_KEY_USERATTRIBUTE) {
6361
0
    rc = cil_gen_userattribute(db, parse_current, new_ast_node);
6362
0
  } else if (parse_current->data == CIL_KEY_USERATTRIBUTESET) {
6363
0
    rc = cil_gen_userattributeset(db, parse_current, new_ast_node);
6364
0
  } else if (parse_current->data == CIL_KEY_USERLEVEL) {
6365
0
    rc = cil_gen_userlevel(db, parse_current, new_ast_node);
6366
0
  } else if (parse_current->data == CIL_KEY_USERRANGE) {
6367
0
    rc = cil_gen_userrange(db, parse_current, new_ast_node);
6368
0
  } else if (parse_current->data == CIL_KEY_USERBOUNDS) {
6369
0
    rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_USER);
6370
0
  } else if (parse_current->data == CIL_KEY_USERPREFIX) {
6371
0
    rc = cil_gen_userprefix(db, parse_current, new_ast_node);
6372
0
  } else if (parse_current->data == CIL_KEY_SELINUXUSER) {
6373
0
    rc = cil_gen_selinuxuser(db, parse_current, new_ast_node);
6374
0
  } else if (parse_current->data == CIL_KEY_SELINUXUSERDEFAULT) {
6375
0
    rc = cil_gen_selinuxuserdefault(db, parse_current,
6376
0
            new_ast_node);
6377
0
  } else if (parse_current->data == CIL_KEY_TYPE) {
6378
0
    rc = cil_gen_type(db, parse_current, new_ast_node);
6379
0
  } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTE) {
6380
0
    rc = cil_gen_typeattribute(db, parse_current, new_ast_node);
6381
0
  } else if (parse_current->data == CIL_KEY_TYPEATTRIBUTESET) {
6382
0
    rc = cil_gen_typeattributeset(db, parse_current, new_ast_node);
6383
0
  } else if (parse_current->data == CIL_KEY_EXPANDTYPEATTRIBUTE) {
6384
0
    rc = cil_gen_expandtypeattribute(db, parse_current,
6385
0
             new_ast_node);
6386
0
  } else if (parse_current->data == CIL_KEY_TYPEALIAS) {
6387
0
    rc = cil_gen_alias(db, parse_current, new_ast_node,
6388
0
           CIL_TYPEALIAS);
6389
0
  } else if (parse_current->data == CIL_KEY_TYPEALIASACTUAL) {
6390
0
    rc = cil_gen_aliasactual(db, parse_current, new_ast_node,
6391
0
           CIL_TYPEALIASACTUAL);
6392
0
  } else if (parse_current->data == CIL_KEY_TYPEBOUNDS) {
6393
0
    rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_TYPE);
6394
0
  } else if (parse_current->data == CIL_KEY_TYPEPERMISSIVE) {
6395
0
    rc = cil_gen_typepermissive(db, parse_current, new_ast_node);
6396
0
  } else if (parse_current->data == CIL_KEY_TYPENEVERAUDIT) {
6397
0
    rc = cil_gen_typeneveraudit(db, parse_current, new_ast_node);
6398
0
  } else if (parse_current->data == CIL_KEY_RANGETRANSITION) {
6399
0
    rc = cil_gen_rangetransition(db, parse_current, new_ast_node);
6400
0
  } else if (parse_current->data == CIL_KEY_ROLE) {
6401
0
    rc = cil_gen_role(db, parse_current, new_ast_node);
6402
0
  } else if (parse_current->data == CIL_KEY_USERROLE) {
6403
0
    rc = cil_gen_userrole(db, parse_current, new_ast_node);
6404
0
  } else if (parse_current->data == CIL_KEY_ROLETYPE) {
6405
0
    rc = cil_gen_roletype(db, parse_current, new_ast_node);
6406
0
  } else if (parse_current->data == CIL_KEY_ROLETRANSITION) {
6407
0
    rc = cil_gen_roletransition(parse_current, new_ast_node);
6408
0
  } else if (parse_current->data == CIL_KEY_ROLEALLOW) {
6409
0
    rc = cil_gen_roleallow(db, parse_current, new_ast_node);
6410
0
  } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTE) {
6411
0
    rc = cil_gen_roleattribute(db, parse_current, new_ast_node);
6412
0
  } else if (parse_current->data == CIL_KEY_ROLEATTRIBUTESET) {
6413
0
    rc = cil_gen_roleattributeset(db, parse_current, new_ast_node);
6414
0
  } else if (parse_current->data == CIL_KEY_ROLEBOUNDS) {
6415
0
    rc = cil_gen_bounds(db, parse_current, new_ast_node, CIL_ROLE);
6416
0
  } else if (parse_current->data == CIL_KEY_BOOL) {
6417
0
    rc = cil_gen_bool(db, parse_current, new_ast_node, CIL_FALSE);
6418
0
  } else if (parse_current->data == CIL_KEY_BOOLEANIF) {
6419
0
    rc = cil_gen_boolif(db, parse_current, new_ast_node, CIL_FALSE);
6420
0
  } else if (parse_current->data == CIL_KEY_TUNABLE) {
6421
0
    if (db->preserve_tunables) {
6422
0
      rc = cil_gen_bool(db, parse_current, new_ast_node,
6423
0
            CIL_TRUE);
6424
0
    } else {
6425
0
      rc = cil_gen_tunable(db, parse_current, new_ast_node);
6426
0
    }
6427
0
  } else if (parse_current->data == CIL_KEY_TUNABLEIF) {
6428
0
    if (db->preserve_tunables) {
6429
0
      rc = cil_gen_boolif(db, parse_current, new_ast_node,
6430
0
              CIL_TRUE);
6431
0
    } else {
6432
0
      rc = cil_gen_tunif(db, parse_current, new_ast_node);
6433
0
    }
6434
0
  } else if (parse_current->data == CIL_KEY_CONDTRUE) {
6435
0
    rc = cil_gen_condblock(db, parse_current, new_ast_node,
6436
0
               CIL_CONDTRUE);
6437
0
  } else if (parse_current->data == CIL_KEY_CONDFALSE) {
6438
0
    rc = cil_gen_condblock(db, parse_current, new_ast_node,
6439
0
               CIL_CONDFALSE);
6440
0
  } else if (parse_current->data == CIL_KEY_ALLOW) {
6441
0
    rc = cil_gen_avrule(parse_current, new_ast_node,
6442
0
            CIL_AVRULE_ALLOWED);
6443
0
  } else if (parse_current->data == CIL_KEY_AUDITALLOW) {
6444
0
    rc = cil_gen_avrule(parse_current, new_ast_node,
6445
0
            CIL_AVRULE_AUDITALLOW);
6446
0
  } else if (parse_current->data == CIL_KEY_DONTAUDIT) {
6447
0
    rc = cil_gen_avrule(parse_current, new_ast_node,
6448
0
            CIL_AVRULE_DONTAUDIT);
6449
0
  } else if (parse_current->data == CIL_KEY_NEVERALLOW) {
6450
0
    rc = cil_gen_avrule(parse_current, new_ast_node,
6451
0
            CIL_AVRULE_NEVERALLOW);
6452
0
  } else if (parse_current->data == CIL_KEY_ALLOWX) {
6453
0
    rc = cil_gen_avrulex(parse_current, new_ast_node,
6454
0
             CIL_AVRULE_ALLOWED);
6455
0
  } else if (parse_current->data == CIL_KEY_AUDITALLOWX) {
6456
0
    rc = cil_gen_avrulex(parse_current, new_ast_node,
6457
0
             CIL_AVRULE_AUDITALLOW);
6458
0
  } else if (parse_current->data == CIL_KEY_DONTAUDITX) {
6459
0
    rc = cil_gen_avrulex(parse_current, new_ast_node,
6460
0
             CIL_AVRULE_DONTAUDIT);
6461
0
  } else if (parse_current->data == CIL_KEY_NEVERALLOWX) {
6462
0
    rc = cil_gen_avrulex(parse_current, new_ast_node,
6463
0
             CIL_AVRULE_NEVERALLOW);
6464
0
  } else if (parse_current->data == CIL_KEY_PERMISSIONX) {
6465
0
    rc = cil_gen_permissionx(db, parse_current, new_ast_node);
6466
0
  } else if (parse_current->data == CIL_KEY_DENY_RULE) {
6467
0
    rc = cil_gen_deny_rule(parse_current, new_ast_node);
6468
0
  } else if (parse_current->data == CIL_KEY_TYPETRANSITION) {
6469
0
    rc = cil_gen_typetransition(db, parse_current, new_ast_node);
6470
0
  } else if (parse_current->data == CIL_KEY_TYPECHANGE) {
6471
0
    rc = cil_gen_type_rule(parse_current, new_ast_node,
6472
0
               CIL_TYPE_CHANGE);
6473
0
  } else if (parse_current->data == CIL_KEY_TYPEMEMBER) {
6474
0
    rc = cil_gen_type_rule(parse_current, new_ast_node,
6475
0
               CIL_TYPE_MEMBER);
6476
0
  } else if (parse_current->data == CIL_KEY_SENSITIVITY) {
6477
0
    rc = cil_gen_sensitivity(db, parse_current, new_ast_node);
6478
0
  } else if (parse_current->data == CIL_KEY_SENSALIAS) {
6479
0
    rc = cil_gen_alias(db, parse_current, new_ast_node,
6480
0
           CIL_SENSALIAS);
6481
0
  } else if (parse_current->data == CIL_KEY_SENSALIASACTUAL) {
6482
0
    rc = cil_gen_aliasactual(db, parse_current, new_ast_node,
6483
0
           CIL_SENSALIASACTUAL);
6484
0
  } else if (parse_current->data == CIL_KEY_CATEGORY) {
6485
0
    rc = cil_gen_category(db, parse_current, new_ast_node);
6486
0
  } else if (parse_current->data == CIL_KEY_CATALIAS) {
6487
0
    rc = cil_gen_alias(db, parse_current, new_ast_node,
6488
0
           CIL_CATALIAS);
6489
0
  } else if (parse_current->data == CIL_KEY_CATALIASACTUAL) {
6490
0
    rc = cil_gen_aliasactual(db, parse_current, new_ast_node,
6491
0
           CIL_CATALIASACTUAL);
6492
0
  } else if (parse_current->data == CIL_KEY_CATSET) {
6493
0
    rc = cil_gen_catset(db, parse_current, new_ast_node);
6494
0
  } else if (parse_current->data == CIL_KEY_CATORDER) {
6495
0
    rc = cil_gen_ordered(db, parse_current, new_ast_node,
6496
0
             CIL_CATORDER);
6497
0
  } else if (parse_current->data == CIL_KEY_SENSITIVITYORDER) {
6498
0
    rc = cil_gen_ordered(db, parse_current, new_ast_node,
6499
0
             CIL_SENSITIVITYORDER);
6500
0
  } else if (parse_current->data == CIL_KEY_SENSCAT) {
6501
0
    rc = cil_gen_senscat(db, parse_current, new_ast_node);
6502
0
  } else if (parse_current->data == CIL_KEY_LEVEL) {
6503
0
    rc = cil_gen_level(db, parse_current, new_ast_node);
6504
0
  } else if (parse_current->data == CIL_KEY_LEVELRANGE) {
6505
0
    rc = cil_gen_levelrange(db, parse_current, new_ast_node);
6506
0
  } else if (parse_current->data == CIL_KEY_CONSTRAIN) {
6507
0
    rc = cil_gen_constrain(db, parse_current, new_ast_node,
6508
0
               CIL_CONSTRAIN);
6509
0
  } else if (parse_current->data == CIL_KEY_MLSCONSTRAIN) {
6510
0
    rc = cil_gen_constrain(db, parse_current, new_ast_node,
6511
0
               CIL_MLSCONSTRAIN);
6512
0
  } else if (parse_current->data == CIL_KEY_VALIDATETRANS) {
6513
0
    rc = cil_gen_validatetrans(db, parse_current, new_ast_node,
6514
0
             CIL_VALIDATETRANS);
6515
0
  } else if (parse_current->data == CIL_KEY_MLSVALIDATETRANS) {
6516
0
    rc = cil_gen_validatetrans(db, parse_current, new_ast_node,
6517
0
             CIL_MLSVALIDATETRANS);
6518
0
  } else if (parse_current->data == CIL_KEY_CONTEXT) {
6519
0
    rc = cil_gen_context(db, parse_current, new_ast_node);
6520
0
  } else if (parse_current->data == CIL_KEY_FILECON) {
6521
0
    rc = cil_gen_filecon(db, parse_current, new_ast_node);
6522
0
  } else if (parse_current->data == CIL_KEY_IBPKEYCON) {
6523
0
    rc = cil_gen_ibpkeycon(db, parse_current, new_ast_node);
6524
0
  } else if (parse_current->data == CIL_KEY_IBENDPORTCON) {
6525
0
    rc = cil_gen_ibendportcon(db, parse_current, new_ast_node);
6526
0
  } else if (parse_current->data == CIL_KEY_PORTCON) {
6527
0
    rc = cil_gen_portcon(db, parse_current, new_ast_node);
6528
0
  } else if (parse_current->data == CIL_KEY_NODECON) {
6529
0
    rc = cil_gen_nodecon(db, parse_current, new_ast_node);
6530
0
  } else if (parse_current->data == CIL_KEY_GENFSCON) {
6531
0
    rc = cil_gen_genfscon(db, parse_current, new_ast_node);
6532
0
  } else if (parse_current->data == CIL_KEY_NETIFCON) {
6533
0
    rc = cil_gen_netifcon(db, parse_current, new_ast_node);
6534
0
  } else if (parse_current->data == CIL_KEY_PIRQCON) {
6535
0
    rc = cil_gen_pirqcon(db, parse_current, new_ast_node);
6536
0
  } else if (parse_current->data == CIL_KEY_IOMEMCON) {
6537
0
    rc = cil_gen_iomemcon(db, parse_current, new_ast_node);
6538
0
  } else if (parse_current->data == CIL_KEY_IOPORTCON) {
6539
0
    rc = cil_gen_ioportcon(db, parse_current, new_ast_node);
6540
0
  } else if (parse_current->data == CIL_KEY_PCIDEVICECON) {
6541
0
    rc = cil_gen_pcidevicecon(db, parse_current, new_ast_node);
6542
0
  } else if (parse_current->data == CIL_KEY_DEVICETREECON) {
6543
0
    rc = cil_gen_devicetreecon(db, parse_current, new_ast_node);
6544
0
  } else if (parse_current->data == CIL_KEY_FSUSE) {
6545
0
    rc = cil_gen_fsuse(db, parse_current, new_ast_node);
6546
0
  } else if (parse_current->data == CIL_KEY_MACRO) {
6547
0
    rc = cil_gen_macro(db, parse_current, new_ast_node);
6548
0
  } else if (parse_current->data == CIL_KEY_CALL) {
6549
0
    rc = cil_gen_call(db, parse_current, new_ast_node);
6550
0
  } else if (parse_current->data == CIL_KEY_POLICYCAP) {
6551
0
    rc = cil_gen_policycap(db, parse_current, new_ast_node);
6552
0
  } else if (parse_current->data == CIL_KEY_OPTIONAL) {
6553
0
    rc = cil_gen_optional(db, parse_current, new_ast_node);
6554
0
  } else if (parse_current->data == CIL_KEY_IPADDR) {
6555
0
    rc = cil_gen_ipaddr(db, parse_current, new_ast_node);
6556
0
  } else if (parse_current->data == CIL_KEY_DEFAULTUSER) {
6557
0
    rc = cil_gen_default(parse_current, new_ast_node,
6558
0
             CIL_DEFAULTUSER);
6559
0
  } else if (parse_current->data == CIL_KEY_DEFAULTROLE) {
6560
0
    rc = cil_gen_default(parse_current, new_ast_node,
6561
0
             CIL_DEFAULTROLE);
6562
0
  } else if (parse_current->data == CIL_KEY_DEFAULTTYPE) {
6563
0
    rc = cil_gen_default(parse_current, new_ast_node,
6564
0
             CIL_DEFAULTTYPE);
6565
0
  } else if (parse_current->data == CIL_KEY_DEFAULTRANGE) {
6566
0
    rc = cil_gen_defaultrange(parse_current, new_ast_node);
6567
0
  } else if (parse_current->data == CIL_KEY_HANDLEUNKNOWN) {
6568
0
    rc = cil_gen_handleunknown(parse_current, new_ast_node);
6569
0
  } else if (parse_current->data == CIL_KEY_MLS) {
6570
0
    rc = cil_gen_mls(parse_current, new_ast_node);
6571
0
  } else if (parse_current->data == CIL_KEY_SRC_INFO) {
6572
0
    rc = cil_gen_src_info(parse_current, new_ast_node);
6573
0
  } else {
6574
0
    cil_log(CIL_ERR, "Error: Unknown keyword %s\n",
6575
0
      (char *)parse_current->data);
6576
0
    rc = SEPOL_ERR;
6577
0
  }
6578
6579
0
  if (rc == SEPOL_OK) {
6580
0
    if (ast_parent->cl_head == NULL) {
6581
0
      ast_parent->cl_head = new_ast_node;
6582
0
    } else {
6583
0
      ast_parent->cl_tail->next = new_ast_node;
6584
0
    }
6585
0
    ast_parent->cl_tail = new_ast_node;
6586
0
  } else {
6587
0
    cil_tree_node_destroy(&new_ast_node);
6588
0
    new_ast_node = NULL;
6589
0
  }
6590
6591
0
  return new_ast_node;
6592
0
}
6593
6594
static int __cil_build_ast_node_helper(struct cil_tree_node *parse_current,
6595
               uint32_t *finished, void *extra_args)
6596
0
{
6597
0
  struct cil_args_build *args = extra_args;
6598
0
  struct cil_tree_node *new_ast_node = NULL;
6599
0
  int rc = SEPOL_ERR;
6600
6601
0
  if (parse_current->parent->cl_head != parse_current) {
6602
    /* ignore anything that isn't following a parenthesis */
6603
0
    return SEPOL_OK;
6604
0
  } else if (parse_current->data == NULL) {
6605
    /* the only time parenthesis can immediately following parenthesis is if
6606
     * the parent is the root node */
6607
0
    if (parse_current->parent->parent == NULL) {
6608
0
      return SEPOL_OK;
6609
0
    } else {
6610
0
      cil_tree_log(parse_current, CIL_ERR,
6611
0
             "Keyword expected after open parenthesis");
6612
0
      return SEPOL_ERR;
6613
0
    }
6614
0
  }
6615
6616
0
  rc = check_for_illegal_statement(parse_current, args);
6617
0
  if (rc != SEPOL_OK) {
6618
0
    return SEPOL_ERR;
6619
0
  }
6620
6621
0
  new_ast_node = parse_statement(args->db, parse_current, args->ast);
6622
0
  if (!new_ast_node) {
6623
0
    return SEPOL_ERR;
6624
0
  }
6625
6626
0
  args->ast = new_ast_node;
6627
6628
0
  if (parse_current->data != CIL_KEY_BLOCK &&
6629
0
      parse_current->data != CIL_KEY_IN &&
6630
0
      parse_current->data != CIL_KEY_TUNABLEIF &&
6631
0
      parse_current->data != CIL_KEY_BOOLEANIF &&
6632
0
      parse_current->data != CIL_KEY_CONDTRUE &&
6633
0
      parse_current->data != CIL_KEY_CONDFALSE &&
6634
0
      parse_current->data != CIL_KEY_MACRO &&
6635
0
      parse_current->data != CIL_KEY_OPTIONAL &&
6636
0
      parse_current->data != CIL_KEY_SRC_INFO) {
6637
    /* Skip anything that does not contain a list of policy statements */
6638
0
    *finished = CIL_TREE_SKIP_NEXT;
6639
0
  }
6640
6641
0
  return SEPOL_OK;
6642
0
}
6643
6644
static int __cil_build_ast_first_child_helper(
6645
  __attribute__((unused)) struct cil_tree_node *parse_current,
6646
  void *extra_args)
6647
0
{
6648
0
  struct cil_args_build *args = extra_args;
6649
0
  struct cil_tree_node *ast = args->ast;
6650
6651
0
  if (ast->flavor == CIL_TUNABLEIF) {
6652
0
    args->tunif = ast;
6653
0
  } else if (ast->flavor == CIL_IN) {
6654
0
    args->in = ast;
6655
0
  } else if (ast->flavor == CIL_MACRO) {
6656
0
    args->macro = ast;
6657
0
  } else if (ast->flavor == CIL_OPTIONAL) {
6658
0
    args->optional = ast;
6659
0
  } else if (ast->flavor == CIL_BOOLEANIF) {
6660
0
    args->boolif = ast;
6661
0
  }
6662
6663
0
  return SEPOL_OK;
6664
0
}
6665
6666
static int
6667
__cil_build_ast_last_child_helper(struct cil_tree_node *parse_current,
6668
          void *extra_args)
6669
0
{
6670
0
  struct cil_args_build *args = extra_args;
6671
0
  struct cil_tree_node *ast = args->ast;
6672
6673
0
  if (ast->flavor == CIL_ROOT) {
6674
0
    return SEPOL_OK;
6675
0
  }
6676
6677
0
  args->ast = ast->parent;
6678
6679
0
  if (ast->flavor == CIL_TUNABLEIF) {
6680
0
    args->tunif = NULL;
6681
0
  }
6682
6683
0
  if (ast->flavor == CIL_IN) {
6684
0
    args->in = NULL;
6685
0
  }
6686
6687
0
  if (ast->flavor == CIL_MACRO) {
6688
0
    args->macro = NULL;
6689
0
  }
6690
6691
0
  if (ast->flavor == CIL_OPTIONAL) {
6692
0
    struct cil_tree_node *n = ast->parent;
6693
0
    args->optional = NULL;
6694
    /* Optionals can be nested */
6695
0
    while (n && n->flavor != CIL_ROOT) {
6696
0
      if (n->flavor == CIL_OPTIONAL) {
6697
0
        args->optional = n;
6698
0
        break;
6699
0
      }
6700
0
      n = n->parent;
6701
0
    }
6702
0
  }
6703
6704
0
  if (ast->flavor == CIL_BOOLEANIF) {
6705
0
    args->boolif = NULL;
6706
0
  }
6707
6708
  // At this point we no longer have any need for parse_current or any of its
6709
  // siblings; they have all been converted to the appropriate AST node. The
6710
  // full parse tree will get deleted elsewhere, but in an attempt to
6711
  // minimize memory usage (of which the parse tree uses a lot), start
6712
  // deleting the parts we don't need now.
6713
0
  cil_tree_children_destroy(parse_current->parent);
6714
6715
0
  return SEPOL_OK;
6716
0
}
6717
6718
int cil_build_ast(struct cil_db *db, struct cil_tree_node *parse_tree,
6719
      struct cil_tree_node *ast)
6720
0
{
6721
0
  int rc = SEPOL_ERR;
6722
0
  struct cil_args_build extra_args;
6723
6724
0
  if (db == NULL || parse_tree == NULL || ast == NULL) {
6725
0
    goto exit;
6726
0
  }
6727
6728
0
  extra_args.ast = ast;
6729
0
  extra_args.db = db;
6730
0
  extra_args.tunif = NULL;
6731
0
  extra_args.in = NULL;
6732
0
  extra_args.macro = NULL;
6733
0
  extra_args.optional = NULL;
6734
0
  extra_args.boolif = NULL;
6735
6736
0
  rc = cil_tree_walk(parse_tree, __cil_build_ast_node_helper,
6737
0
         __cil_build_ast_first_child_helper,
6738
0
         __cil_build_ast_last_child_helper, &extra_args);
6739
0
  if (rc != SEPOL_OK) {
6740
0
    goto exit;
6741
0
  }
6742
6743
0
  return SEPOL_OK;
6744
6745
0
exit:
6746
0
  return rc;
6747
0
}