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 <stdio.h>
31 #include <stdint.h>
32 #include <inttypes.h>
33 #include <ctype.h>
34
35 #include "cil_internal.h"
36 #include "cil_flavor.h"
37 #include "cil_list.h"
38 #include "cil_log.h"
39 #include "cil_symtab.h"
40 #include "cil_tree.h"
41 #include "cil_write_ast.h"
42
43
datum_or_str(struct cil_symtab_datum * datum,const char * str)44 static inline const char *datum_or_str(struct cil_symtab_datum *datum, const char *str)
45 {
46 return datum ? datum->fqn : str;
47 }
48
datum_to_str(struct cil_symtab_datum * datum)49 static inline const char *datum_to_str(struct cil_symtab_datum *datum)
50 {
51 return datum ? datum->fqn : "<?DATUM>";
52 }
53
write_expr(FILE * out,struct cil_list * expr)54 static void write_expr(FILE *out, struct cil_list *expr)
55 {
56 struct cil_list_item *curr;
57 int notfirst = 0;
58
59 fprintf(out, "(");
60 cil_list_for_each(curr, expr) {
61 if (notfirst)
62 fprintf(out, " ");
63 else
64 notfirst = 1;
65 switch (curr->flavor) {
66 case CIL_LIST:
67 write_expr(out, curr->data);
68 break;
69 case CIL_STRING:
70 fprintf(out, "%s", (char *)curr->data);
71 break;
72 case CIL_DATUM:
73 case CIL_TYPE:
74 case CIL_ROLE:
75 case CIL_USER:
76 case CIL_SENS:
77 case CIL_CAT:
78 case CIL_BOOL:
79 case CIL_CLASS:
80 case CIL_MAP_CLASS:
81 case CIL_NAME:
82 fprintf(out, "%s", datum_to_str(curr->data));
83 break;
84 case CIL_OP: {
85 const char *op_str;
86 enum cil_flavor op_flavor = (enum cil_flavor)(uintptr_t)curr->data;
87 switch (op_flavor) {
88 case CIL_AND:
89 op_str = CIL_KEY_AND;
90 break;
91 case CIL_OR:
92 op_str = CIL_KEY_OR;
93 break;
94 case CIL_NOT:
95 op_str = CIL_KEY_NOT;
96 break;
97 case CIL_ALL:
98 op_str = CIL_KEY_ALL;
99 break;
100 case CIL_EQ:
101 op_str = CIL_KEY_EQ;
102 break;
103 case CIL_NEQ:
104 op_str = CIL_KEY_NEQ;
105 break;
106 case CIL_XOR:
107 op_str = CIL_KEY_XOR;
108 break;
109 case CIL_RANGE:
110 op_str = CIL_KEY_RANGE;
111 break;
112 case CIL_CONS_DOM:
113 op_str = CIL_KEY_CONS_DOM;
114 break;
115 case CIL_CONS_DOMBY:
116 op_str = CIL_KEY_CONS_DOMBY;
117 break;
118 case CIL_CONS_INCOMP:
119 op_str = CIL_KEY_CONS_INCOMP;
120 break;
121 default:
122 op_str = "<?OP>";
123 break;
124 }
125 fprintf(out, "%s", op_str);
126 break;
127 }
128 case CIL_CONS_OPERAND: {
129 const char *operand_str;
130 enum cil_flavor operand_flavor = (enum cil_flavor)(uintptr_t)curr->data;
131 switch (operand_flavor) {
132 case CIL_CONS_U1:
133 operand_str = CIL_KEY_CONS_U1;
134 break;
135 case CIL_CONS_U2:
136 operand_str = CIL_KEY_CONS_U2;
137 break;
138 case CIL_CONS_U3:
139 operand_str = CIL_KEY_CONS_U3;
140 break;
141 case CIL_CONS_T1:
142 operand_str = CIL_KEY_CONS_T1;
143 break;
144 case CIL_CONS_T2:
145 operand_str = CIL_KEY_CONS_T2;
146 break;
147 case CIL_CONS_T3:
148 operand_str = CIL_KEY_CONS_T3;
149 break;
150 case CIL_CONS_R1:
151 operand_str = CIL_KEY_CONS_R1;
152 break;
153 case CIL_CONS_R2:
154 operand_str = CIL_KEY_CONS_R2;
155 break;
156 case CIL_CONS_R3:
157 operand_str = CIL_KEY_CONS_R3;
158 break;
159 case CIL_CONS_L1:
160 operand_str = CIL_KEY_CONS_L1;
161 break;
162 case CIL_CONS_L2:
163 operand_str = CIL_KEY_CONS_L2;
164 break;
165 case CIL_CONS_H1:
166 operand_str = CIL_KEY_CONS_H1;
167 break;
168 case CIL_CONS_H2:
169 operand_str = CIL_KEY_CONS_H2;
170 break;
171 default:
172 operand_str = "<?OPERAND>";
173 break;
174 }
175 fprintf(out, "%s", operand_str);
176 break;
177 }
178 default:
179 fprintf(out, "<?FLAVOR>");
180 break;
181 }
182 }
183 fprintf(out, ")");
184 }
185
write_node_list(FILE * out,struct cil_tree_node * current)186 static void write_node_list(FILE *out, struct cil_tree_node *current)
187 {
188 int notfirst = 0;
189
190 fprintf(out, "(");
191 while (current) {
192 if (notfirst)
193 fprintf(out, " ");
194 else
195 notfirst = 1;
196
197 fprintf(out, "%s", datum_to_str(current->data));
198 current = current->next;
199 }
200 fprintf(out, ")");
201 }
202
write_string_list(FILE * out,struct cil_list * list)203 static void write_string_list(FILE *out, struct cil_list *list)
204 {
205 struct cil_list_item *curr;
206 int notfirst = 0;
207
208 if (!list) {
209 fprintf(out, "()");
210 return;
211 }
212
213 fprintf(out, "(");
214 cil_list_for_each(curr, list) {
215 if (notfirst)
216 fprintf(out, " ");
217 else
218 notfirst = 1;
219 fprintf(out, "%s", (char*)curr->data);
220 }
221 fprintf(out, ")");
222 }
223
write_datum_list(FILE * out,struct cil_list * list)224 static void write_datum_list(FILE *out, struct cil_list *list)
225 {
226 struct cil_list_item *curr;
227 int notfirst = 0;
228
229 if (!list) {
230 fprintf(out, "()");
231 return;
232 }
233
234 fprintf(out, "(");
235 cil_list_for_each(curr, list) {
236 if (notfirst)
237 fprintf(out, " ");
238 else
239 notfirst = 1;
240 fprintf(out, "%s", datum_to_str(curr->data));
241 }
242 fprintf(out, ")");
243 }
244
write_classperms(FILE * out,struct cil_classperms * cp)245 static void write_classperms(FILE *out, struct cil_classperms *cp)
246 {
247 if (!cp) {
248 fprintf(out, "()");
249 return;
250 }
251
252 fprintf(out, "(%s ", datum_or_str(DATUM(cp->class), cp->class_str));
253 if (cp->perms)
254 write_expr(out, cp->perms);
255 else
256 write_expr(out, cp->perm_strs);
257 fprintf(out, ")");
258 }
259
write_classperms_list(FILE * out,struct cil_list * cp_list)260 static void write_classperms_list(FILE *out, struct cil_list *cp_list)
261 {
262 struct cil_list_item *curr;
263 int notfirst = 0;
264 int num = 0;
265
266 if (!cp_list) {
267 fprintf(out, "()");
268 return;
269 }
270
271 cil_list_for_each(curr, cp_list) {
272 num++;
273 }
274 if (num > 1)
275 fprintf(out, "(");
276 cil_list_for_each(curr, cp_list) {
277 if (notfirst)
278 fprintf(out, " ");
279 else
280 notfirst = 1;
281 if (curr->flavor == CIL_CLASSPERMS) {
282 write_classperms(out, curr->data);
283 } else {
284 struct cil_classperms_set *cp_set = curr->data;
285 struct cil_classpermission *cp = cp_set->set;
286 if (cp) {
287 if (cp->datum.name)
288 fprintf(out, "%s", datum_to_str(DATUM(cp)));
289 else
290 write_classperms_list(out,cp->classperms);
291 } else {
292 fprintf(out, "%s", cp_set->set_str);
293 }
294 }
295 }
296 if (num > 1)
297 fprintf(out, ")");
298 }
299
write_permx(FILE * out,struct cil_permissionx * permx)300 static void write_permx(FILE *out, struct cil_permissionx *permx)
301 {
302 if (permx->datum.name) {
303 fprintf(out, "%s", datum_to_str(DATUM(permx)));
304 } else {
305 fprintf(out, "(");
306 fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : "<?KIND>");
307 fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str));
308 write_expr(out, permx->expr_str);
309 fprintf(out, ")");
310 }
311 }
312
write_cats(FILE * out,struct cil_cats * cats)313 static void write_cats(FILE *out, struct cil_cats *cats)
314 {
315 if (cats->datum_expr) {
316 write_expr(out, cats->datum_expr);
317 } else {
318 write_expr(out, cats->str_expr);
319 }
320 }
321
write_level(FILE * out,struct cil_level * level,int print_name)322 static void write_level(FILE *out, struct cil_level *level, int print_name)
323 {
324 if (print_name && level->datum.name) {
325 fprintf(out, "%s", datum_to_str(DATUM(level)));
326 } else {
327 fprintf(out, "(");
328 fprintf(out, "%s", datum_or_str(DATUM(level->sens), level->sens_str));
329 if (level->cats) {
330 fprintf(out, " ");
331 write_cats(out, level->cats);
332 }
333 fprintf(out, ")");
334 }
335 }
336
write_range(FILE * out,struct cil_levelrange * range,int print_name)337 static void write_range(FILE *out, struct cil_levelrange *range, int print_name)
338 {
339 if (print_name && range->datum.name) {
340 fprintf(out, "%s", datum_to_str(DATUM(range)));
341 } else {
342 fprintf(out, "(");
343 if (range->low)
344 write_level(out, range->low, CIL_TRUE);
345 else
346 fprintf(out, "%s", range->low_str);
347 fprintf(out, " ");
348 if (range->high)
349 write_level(out, range->high, CIL_TRUE);
350 else
351 fprintf(out, "%s", range->high_str);
352 fprintf(out, ")");
353 }
354 }
355
write_context(FILE * out,struct cil_context * context,int print_name)356 static void write_context(FILE *out, struct cil_context *context, int print_name)
357 {
358 if (print_name && context->datum.name) {
359 fprintf(out, "%s", datum_to_str(DATUM(context)));
360 } else {
361 fprintf(out, "(");
362 fprintf(out, "%s ", datum_or_str(DATUM(context->user), context->user_str));
363 fprintf(out, "%s ", datum_or_str(DATUM(context->role), context->role_str));
364 fprintf(out, "%s ", datum_or_str(DATUM(context->type), context->type_str));
365 if (context->range)
366 write_range(out, context->range, CIL_TRUE);
367 else
368 fprintf(out, "%s", context->range_str);
369 fprintf(out, ")");
370 }
371 }
372
write_ipaddr(FILE * out,struct cil_ipaddr * ipaddr)373 static void write_ipaddr(FILE *out, struct cil_ipaddr *ipaddr)
374 {
375 if (ipaddr->datum.name) {
376 fprintf(out, "%s", datum_to_str(DATUM(ipaddr)));
377 } else {
378 char buf[256];
379 if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL)
380 strcpy(buf, "<?IPADDR>");
381 fprintf(out, "(%s)", buf);
382 }
383 }
384
write_constrain(FILE * out,struct cil_constrain * cons)385 static void write_constrain(FILE *out, struct cil_constrain *cons)
386 {
387 write_classperms_list(out, cons->classperms);
388 fprintf(out, " ");
389 if (cons->datum_expr)
390 write_expr(out, cons->datum_expr);
391 else
392 write_expr(out, cons->str_expr);
393 }
394
write_call_args(FILE * out,struct cil_list * args)395 static void write_call_args(FILE *out, struct cil_list *args)
396 {
397 struct cil_list_item *item;
398 int notfirst = 0;
399
400 fprintf(out, "(");
401 cil_list_for_each(item, args) {
402 struct cil_args* arg = item->data;
403 enum cil_flavor arg_flavor = arg->flavor;
404 if (notfirst)
405 fprintf(out, " ");
406 else
407 notfirst = 1;
408 switch (arg_flavor) {
409 case CIL_TYPE:
410 case CIL_ROLE:
411 case CIL_USER:
412 case CIL_SENS:
413 case CIL_CAT:
414 case CIL_BOOL:
415 case CIL_CLASS:
416 case CIL_MAP_CLASS:
417 case CIL_NAME: {
418 fprintf(out, "%s", datum_or_str(arg->arg, arg->arg_str));
419 break;
420 }
421 case CIL_CATSET: {
422 if (arg->arg) {
423 struct cil_catset *catset = (struct cil_catset *)arg->arg;
424 write_cats(out, catset->cats);
425 } else {
426 fprintf(out, "%s", arg->arg_str);
427 }
428 break;
429 }
430 case CIL_LEVEL: {
431 if (arg->arg) {
432 struct cil_level *level = (struct cil_level *)arg->arg;
433 write_level(out, level, CIL_TRUE);
434 } else {
435 fprintf(out, "%s", arg->arg_str);
436 }
437 break;
438 }
439 case CIL_LEVELRANGE: {
440 if (arg->arg) {
441 struct cil_levelrange *range = (struct cil_levelrange *)arg->arg;
442 write_range(out, range, CIL_TRUE);
443 } else {
444 fprintf(out, "%s", arg->arg_str);
445 }
446 break;
447 }
448 case CIL_IPADDR: {
449 if (arg->arg) {
450 struct cil_ipaddr *addr = (struct cil_ipaddr *)arg->arg;
451 write_ipaddr(out, addr);
452 } else {
453 fprintf(out, "%s", arg->arg_str);
454 }
455 break;
456 }
457 case CIL_CLASSPERMISSION: {
458 if (arg->arg) {
459 struct cil_classpermission *cp = (struct cil_classpermission *)arg->arg;
460 if (cp->datum.name)
461 fprintf(out, "%s", datum_to_str(DATUM(cp)));
462 else
463 write_classperms_list(out, cp->classperms);
464 } else {
465 fprintf(out, "%s", arg->arg_str);
466 }
467 break;
468 }
469 default:
470 fprintf(out, "<?ARG:%s>", datum_or_str(arg->arg, arg->arg_str));
471 break;
472 }
473 }
474 fprintf(out, ")");
475 }
476
write_call_args_tree(FILE * out,struct cil_tree_node * arg_node)477 static void write_call_args_tree(FILE *out, struct cil_tree_node *arg_node)
478 {
479 while (arg_node) {
480 if (arg_node->data) {
481 fprintf(out, "%s", (char *)arg_node->data);
482 } else if (arg_node->cl_head) {
483 fprintf(out, "(");
484 write_call_args_tree(out, arg_node->cl_head);
485 fprintf(out, ")");
486 }
487 if (arg_node->next)
488 fprintf(out, " ");
489 arg_node = arg_node->next;
490 }
491 }
492
macro_param_flavor_to_string(enum cil_flavor flavor)493 static const char *macro_param_flavor_to_string(enum cil_flavor flavor)
494 {
495 const char *str;
496 switch(flavor) {
497 case CIL_TYPE:
498 str = CIL_KEY_TYPE;
499 break;
500 case CIL_ROLE:
501 str = CIL_KEY_ROLE;
502 break;
503 case CIL_USER:
504 str = CIL_KEY_USER;
505 break;
506 case CIL_SENS:
507 str = CIL_KEY_SENSITIVITY;
508 break;
509 case CIL_CAT:
510 str = CIL_KEY_CATEGORY;
511 break;
512 case CIL_CATSET:
513 str = CIL_KEY_CATSET;
514 break;
515 case CIL_LEVEL:
516 str = CIL_KEY_LEVEL;
517 break;
518 case CIL_LEVELRANGE:
519 str = CIL_KEY_LEVELRANGE;
520 break;
521 case CIL_CLASS:
522 str = CIL_KEY_CLASS;
523 break;
524 case CIL_IPADDR:
525 str = CIL_KEY_IPADDR;
526 break;
527 case CIL_MAP_CLASS:
528 str = CIL_KEY_MAP_CLASS;
529 break;
530 case CIL_CLASSPERMISSION:
531 str = CIL_KEY_CLASSPERMISSION;
532 break;
533 case CIL_BOOL:
534 str = CIL_KEY_BOOL;
535 break;
536 case CIL_STRING:
537 str = CIL_KEY_STRING;
538 break;
539 case CIL_NAME:
540 str = CIL_KEY_NAME;
541 break;
542 default:
543 str = "<?FLAVOR>";
544 break;
545 }
546 return str;
547 }
548
cil_write_src_info_node(FILE * out,struct cil_tree_node * node)549 void cil_write_src_info_node(FILE *out, struct cil_tree_node *node)
550 {
551 struct cil_src_info *info = node->data;
552 if (info->kind == CIL_KEY_SRC_CIL || info->kind == CIL_KEY_SRC_HLL_LMS) {
553 fprintf(out, ";;* lms %u %s\n", info->hll_line, info->path);
554 } else if (info->kind == CIL_KEY_SRC_HLL_LMX) {
555 fprintf(out, ";;* lmx %u %s\n", info->hll_line, info->path);
556 } else {
557 fprintf(out, ";;* <?SRC_INFO_KIND> %u %s\n", info->hll_line, info->path);
558 }
559 }
560
cil_write_ast_node(FILE * out,struct cil_tree_node * node)561 void cil_write_ast_node(FILE *out, struct cil_tree_node *node)
562 {
563 if (!node->data) {
564 return;
565 }
566
567 switch(node->flavor) {
568 case CIL_NODE: {
569 fprintf(out, "%s\n", (char *)node->data);
570 break;
571 }
572 case CIL_BLOCK: {
573 struct cil_block *block = node->data;
574 fprintf(out, "(block %s", datum_to_str(DATUM(block)));
575 if (!node->cl_head)
576 fprintf(out, ")");
577 fprintf(out, "\n");
578 break;
579 }
580 case CIL_BLOCKINHERIT: {
581 struct cil_blockinherit *inherit = node->data;
582 fprintf(out, "(blockinherit %s)\n", datum_or_str(DATUM(inherit->block), inherit->block_str));
583 break;
584 }
585 case CIL_IN: {
586 struct cil_in *in = node->data;
587 fprintf(out, "(in %s", in->block_str);
588 if (!node->cl_head)
589 fprintf(out, ")");
590 fprintf(out, "\n");
591 break;
592 }
593 case CIL_OPTIONAL: {
594 struct cil_optional *optional = node->data;
595 fprintf(out, "(optional %s", datum_to_str(DATUM(optional)));
596 if (!node->cl_head)
597 fprintf(out, ")");
598 fprintf(out, "\n");
599 break;
600 }
601 case CIL_BOOLEANIF: {
602 struct cil_booleanif *bif = node->data;
603 fprintf(out, "(booleanif ");
604 if (bif->datum_expr)
605 write_expr(out, bif->datum_expr);
606 else
607 write_expr(out, bif->str_expr);
608 if (!node->cl_head)
609 fprintf(out, ")");
610 fprintf(out, "\n");
611 break;
612 }
613 case CIL_TUNABLEIF: {
614 struct cil_tunableif *tif = node->data;
615 fprintf(out, "(tunableif ");
616 if (tif->datum_expr)
617 write_expr(out, tif->datum_expr);
618 else
619 write_expr(out, tif->str_expr);
620 if (!node->cl_head)
621 fprintf(out, ")");
622 fprintf(out, "\n");
623 break;
624 }
625 case CIL_CONDBLOCK: {
626 struct cil_condblock *cb = node->data;
627 fprintf(out, "(%s", cb->flavor == CIL_CONDTRUE ? "true" : "false");
628 if (!node->cl_head)
629 fprintf(out, ")");
630 fprintf(out, "\n");
631 break;
632 }
633 case CIL_MACRO: {
634 struct cil_macro *macro = node->data;
635 struct cil_list_item *curr;
636 fprintf(out, "(macro %s (", datum_to_str(DATUM(macro)));
637 if (macro->params) {
638 cil_list_for_each(curr, macro->params) {
639 struct cil_param *param = curr->data;
640 fprintf(out, "(%s %s)", macro_param_flavor_to_string(param->flavor), param->str);
641 }
642 }
643 fprintf(out, ")");
644 if (!node->cl_head)
645 fprintf(out, ")");
646 fprintf(out, "\n");
647 break;
648 }
649 case CIL_CALL: {
650 struct cil_call *call = node->data;
651 fprintf(out, "(call %s", datum_or_str(DATUM(call->macro), call->macro_str));
652 if (call->args) {
653 fprintf(out, " ");
654 write_call_args(out, call->args);
655 } else if (call->args_tree) {
656 fprintf(out, " ");
657 write_call_args_tree(out, call->args_tree->root);
658 }
659 if (!node->cl_head)
660 fprintf(out, ")");
661 fprintf(out, "\n");
662 break;
663 }
664 case CIL_BLOCKABSTRACT: {
665 struct cil_blockabstract *abstract = node->data;
666 fprintf(out, "(blockabstract %s)\n", abstract->block_str);
667 break;
668 }
669 case CIL_MLS: {
670 struct cil_mls *mls = node->data;
671 fprintf(out, "(mls %s)\n", mls->value ? "true" : "false");
672 break;
673 }
674 case CIL_HANDLEUNKNOWN: {
675 struct cil_handleunknown *unknown = node->data;
676 fprintf(out, "(handleunknown ");
677 if (unknown->handle_unknown == SEPOL_ALLOW_UNKNOWN)
678 fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_ALLOW);
679 else if (unknown->handle_unknown == SEPOL_DENY_UNKNOWN)
680 fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_DENY);
681 else if (unknown->handle_unknown == SEPOL_REJECT_UNKNOWN)
682 fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_REJECT);
683 else
684 fprintf(out, "<?UNKNOWN>");
685 fprintf(out, ")\n");
686 break;
687 }
688 case CIL_DEFAULTUSER: {
689 struct cil_default *def = node->data;
690 fprintf(out, "(defaultuser ");
691 if (def->class_datums)
692 write_datum_list(out, def->class_datums);
693 else
694 write_string_list(out, def->class_strs);
695 if (def->object == CIL_DEFAULT_SOURCE)
696 fprintf(out, " source");
697 else if (def->object == CIL_DEFAULT_TARGET)
698 fprintf(out, " target");
699 else
700 fprintf(out, " <?DEFAULT>");
701 fprintf(out, ")\n");
702 break;
703 }
704 case CIL_DEFAULTROLE: {
705 struct cil_default *def = node->data;
706 fprintf(out, "(defaultrole ");
707 if (def->class_datums)
708 write_datum_list(out, def->class_datums);
709 else
710 write_string_list(out, def->class_strs);
711 if (def->object == CIL_DEFAULT_SOURCE)
712 fprintf(out, " source");
713 else if (def->object == CIL_DEFAULT_TARGET)
714 fprintf(out, " target");
715 else
716 fprintf(out, " <?DEFAULT>");
717 fprintf(out, ")\n");
718 break;
719 }
720 case CIL_DEFAULTTYPE: {
721 struct cil_default *def = node->data;
722 fprintf(out, "(defaulttype ");
723 if (def->class_datums)
724 write_datum_list(out, def->class_datums);
725 else
726 write_string_list(out, def->class_strs);
727 if (def->object == CIL_DEFAULT_SOURCE)
728 fprintf(out, " source");
729 else if (def->object == CIL_DEFAULT_TARGET)
730 fprintf(out, " target");
731 else
732 fprintf(out, " <?DEFAULT>");
733 fprintf(out, ")\n");
734 break;
735 }
736 case CIL_DEFAULTRANGE: {
737 struct cil_defaultrange *def = node->data;
738 fprintf(out, "(defaultrange ");
739 if (def->class_datums)
740 write_datum_list(out, def->class_datums);
741 else
742 write_string_list(out, def->class_strs);
743 if (def->object_range == CIL_DEFAULT_SOURCE_LOW)
744 fprintf(out, " source low");
745 else if (def->object_range == CIL_DEFAULT_SOURCE_HIGH)
746 fprintf(out, " source high");
747 else if (def->object_range == CIL_DEFAULT_SOURCE_LOW_HIGH)
748 fprintf(out, " source low-high");
749 else if (def->object_range == CIL_DEFAULT_TARGET_LOW)
750 fprintf(out, " target low");
751 else if (def->object_range == CIL_DEFAULT_TARGET_HIGH)
752 fprintf(out, " target high");
753 else if (def->object_range == CIL_DEFAULT_TARGET_LOW_HIGH)
754 fprintf(out, " target low-high");
755 else
756 fprintf(out, " <?DEFAULT>");
757 fprintf(out, ")\n");
758 break;
759 }
760 case CIL_CLASS: {
761 struct cil_class *class = node->data;
762 fprintf(out, "(class %s ", datum_to_str(DATUM(class)));
763 write_node_list(out, node->cl_head);
764 fprintf(out, ")\n");
765 break;
766 }
767 case CIL_CLASSORDER: {
768 struct cil_classorder *classorder = node->data;
769 fprintf(out, "(classorder ");
770 write_string_list(out, classorder->class_list_str);
771 fprintf(out, ")\n");
772 break;
773 }
774 case CIL_COMMON: {
775 struct cil_class *common = node->data;
776 fprintf(out, "(common %s ", datum_to_str(DATUM(common)));
777 write_node_list(out, node->cl_head);
778 fprintf(out, ")\n");
779 break;
780 }
781 case CIL_CLASSCOMMON: {
782 struct cil_classcommon *cc = node->data;
783 fprintf(out, "(classcommon %s %s)\n", cc->class_str, cc->common_str);
784 break;
785 }
786 case CIL_CLASSPERMISSION: {
787 struct cil_classpermission *cp = node->data;
788 fprintf(out, "(classpermission %s)\n", datum_to_str(DATUM(cp)));
789 break;
790 }
791 case CIL_CLASSPERMISSIONSET: {
792 struct cil_classpermissionset *cps = node->data;
793 fprintf(out, "(classpermissionset %s ", cps->set_str);
794 write_classperms_list(out, cps->classperms);
795 fprintf(out, ")\n");
796 break;
797 }
798 case CIL_MAP_CLASS: {
799 struct cil_class *map = node->data;
800 fprintf(out, "(classmap %s ", datum_to_str(DATUM(map)));
801 write_node_list(out, node->cl_head);
802 fprintf(out, ")\n");
803 break;
804 }
805 case CIL_CLASSMAPPING: {
806 struct cil_classmapping *mapping = node->data;
807 fprintf(out, "(classmapping %s %s ", mapping->map_class_str, mapping->map_perm_str);
808 write_classperms_list(out, mapping->classperms);
809 fprintf(out, ")\n");
810 break;
811 }
812 case CIL_PERMISSIONX: {
813 struct cil_permissionx *permx = node->data;
814 fprintf(out, "(permissionx %s (", datum_to_str(DATUM(permx)));
815 fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : "<?KIND>");
816 fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str));
817 write_expr(out, permx->expr_str);
818 fprintf(out, "))\n");
819 break;
820 }
821 case CIL_SID: {
822 struct cil_sid *sid = node->data;
823 fprintf(out, "(sid %s)\n", datum_to_str(DATUM(sid)));
824 break;
825 }
826 case CIL_SIDCONTEXT: {
827 struct cil_sidcontext *sidcon = node->data;
828 fprintf(out, "(sidcontext %s ", sidcon->sid_str);
829 if (sidcon->context)
830 write_context(out, sidcon->context, CIL_TRUE);
831 else
832 fprintf(out, "%s", sidcon->context_str);
833 fprintf(out, ")\n");
834 break;
835 }
836 case CIL_SIDORDER: {
837 struct cil_sidorder *sidorder = node->data;
838 fprintf(out, "(sidorder ");
839 write_string_list(out, sidorder->sid_list_str);
840 fprintf(out, ")\n");
841 break;
842 }
843 case CIL_BOOL: {
844 struct cil_bool *boolean = node->data;
845 fprintf(out, "(boolean %s %s)\n", datum_to_str(DATUM(boolean)), boolean->value ? "true" : "false");
846 break;
847 }
848 case CIL_TUNABLE: {
849 struct cil_tunable *tunable = node->data;
850 fprintf(out, "(tunable %s %s)\n", datum_to_str(DATUM(tunable)), tunable->value ? "true" : "false");
851 break;
852 }
853 case CIL_SENS: {
854 struct cil_sens *sens = node->data;
855 fprintf(out, "(sensitivity %s)\n", datum_to_str(DATUM(sens)));
856 break;
857 }
858 case CIL_SENSALIAS: {
859 struct cil_alias *alias = node->data;
860 fprintf(out, "(sensitivityalias %s)\n", datum_to_str(DATUM(alias)));
861 break;
862 }
863 case CIL_SENSALIASACTUAL: {
864 struct cil_aliasactual *aliasactual = node->data;
865 fprintf(out, "(sensitivityaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str);
866 break;
867 }
868 case CIL_CAT: {
869 struct cil_cat *cat = node->data;
870 fprintf(out, "(category %s)\n", datum_to_str(DATUM(cat)));
871 break;
872 }
873 case CIL_CATALIAS: {
874 struct cil_alias *alias = node->data;
875 fprintf(out, "(categoryalias %s)\n", datum_to_str(DATUM(alias)));
876 break;
877 }
878 case CIL_CATALIASACTUAL: {
879 struct cil_aliasactual *aliasactual = node->data;
880 fprintf(out, "(categoryaliasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str);
881 break;
882 }
883 case CIL_CATSET: {
884 struct cil_catset *catset = node->data;
885 fprintf(out, "(categoryset %s ", datum_to_str(DATUM(catset)));
886 write_cats(out, catset->cats);
887 fprintf(out, ")\n");
888 break;
889 }
890 case CIL_CATORDER: {
891 struct cil_catorder *catorder = node->data;
892 fprintf(out, "(categoryorder ");
893 write_string_list(out, catorder->cat_list_str);
894 fprintf(out, ")\n");
895 break;
896 }
897 case CIL_SENSCAT: {
898 struct cil_senscat *senscat = node->data;
899 fprintf(out, "(sensitivitycategory ");
900 fprintf(out, "%s ", senscat->sens_str);
901 write_cats(out, senscat->cats);
902 fprintf(out, ")\n");
903 break;
904 }
905 case CIL_SENSITIVITYORDER: {
906 struct cil_sensorder *sensorder = node->data;
907 fprintf(out, "(sensitivityorder ");
908 write_string_list(out, sensorder->sens_list_str);
909 fprintf(out, ")\n");
910 break;
911 }
912 case CIL_LEVEL: {
913 struct cil_level *level = node->data;
914 fprintf(out, "(level %s ", datum_to_str(&level->datum));
915 write_level(out, level, CIL_FALSE);
916 fprintf(out, ")\n");
917 break;
918 }
919 case CIL_LEVELRANGE: {
920 struct cil_levelrange *lvlrange = node->data;
921 fprintf(out, "(levelrange %s ", datum_to_str(DATUM(lvlrange)));
922 write_range(out, lvlrange, CIL_FALSE);
923 fprintf(out, ")\n");
924 break;
925 }
926 case CIL_USER: {
927 struct cil_user *user = node->data;
928 fprintf(out, "(user %s)\n", datum_to_str(DATUM(user)));
929 break;
930 }
931 case CIL_USERATTRIBUTE: {
932 struct cil_userattribute *attr = node->data;
933 fprintf(out, "(userattribute %s)\n", datum_to_str(DATUM(attr)));
934 break;
935 }
936 case CIL_USERATTRIBUTESET: {
937 struct cil_userattributeset *attr = node->data;
938 fprintf(out, "(userattributeset %s ", attr->attr_str);
939 if (attr->datum_expr)
940 write_expr(out, attr->datum_expr);
941 else
942 write_expr(out, attr->str_expr);
943 fprintf(out, ")\n");
944 break;
945 }
946 case CIL_USERROLE: {
947 struct cil_userrole *userrole = node->data;
948 fprintf(out, "(userrole ");
949 fprintf(out, "%s ", datum_or_str(userrole->user, userrole->user_str));
950 fprintf(out, "%s", datum_or_str(userrole->role, userrole->role_str));
951 fprintf(out, ")\n");
952 break;
953 }
954 case CIL_USERLEVEL: {
955 struct cil_userlevel *userlevel = node->data;
956 fprintf(out, "(userlevel %s ", userlevel->user_str);
957 if (userlevel->level)
958 write_level(out, userlevel->level, CIL_TRUE);
959 else
960 fprintf(out, "%s", userlevel->level_str);
961 fprintf(out, ")\n");
962 break;
963 }
964 case CIL_USERRANGE: {
965 struct cil_userrange *userrange = node->data;
966 fprintf(out, "(userrange %s ", userrange->user_str);
967 if (userrange->range)
968 write_range(out, userrange->range, CIL_TRUE);
969 else
970 fprintf(out, "%s", userrange->range_str);
971 fprintf(out, ")\n");
972 break;
973 }
974 case CIL_USERBOUNDS: {
975 struct cil_bounds *bounds = node->data;
976 fprintf(out, "(userbounds %s %s)\n", bounds->parent_str, bounds->child_str);
977 break;
978 }
979 case CIL_USERPREFIX: {
980 struct cil_userprefix *prefix = node->data;
981 fprintf(out, "(userprefix ");
982 fprintf(out, "%s ", datum_or_str(DATUM(prefix->user), prefix->user_str));
983 fprintf(out, "%s)\n", prefix->prefix_str);
984 break;
985 }
986 case CIL_SELINUXUSER: {
987 struct cil_selinuxuser *selinuxuser = node->data;
988 fprintf(out, "(selinuxuser %s ", selinuxuser->name_str);
989 fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str));
990 if (selinuxuser->range)
991 write_range(out, selinuxuser->range, CIL_TRUE);
992 else
993 fprintf(out, "%s", selinuxuser->range_str);
994 fprintf(out, ")\n");
995 break;
996 }
997 case CIL_SELINUXUSERDEFAULT: {
998 struct cil_selinuxuser *selinuxuser = node->data;
999 fprintf(out, "(selinuxuserdefault ");
1000 fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str));
1001 if (selinuxuser->range)
1002 write_range(out, selinuxuser->range, CIL_TRUE);
1003 else
1004 fprintf(out, "%s", selinuxuser->range_str);
1005 fprintf(out, ")\n");
1006 break;
1007 }
1008 case CIL_ROLE: {
1009 fprintf(out, "(role %s)\n", datum_to_str(node->data));
1010 break;
1011 }
1012 case CIL_ROLEATTRIBUTE: {
1013 fprintf(out, "(roleattribute %s)\n", datum_to_str(node->data));
1014 break;
1015 }
1016 case CIL_ROLEATTRIBUTESET: {
1017 struct cil_roleattributeset *attr = node->data;
1018 fprintf(out, "(roleattributeset %s ", attr->attr_str);
1019 if (attr->datum_expr)
1020 write_expr(out, attr->datum_expr);
1021 else
1022 write_expr(out, attr->str_expr);
1023 fprintf(out, ")\n");
1024 break;
1025 }
1026 case CIL_ROLETYPE: {
1027 struct cil_roletype *roletype = node->data;
1028 fprintf(out, "(roletype ");
1029 fprintf(out, "%s ", datum_or_str(DATUM(roletype->role), roletype->role_str));
1030 fprintf(out, "%s", datum_or_str(DATUM(roletype->type), roletype->type_str));
1031 fprintf(out, ")\n");
1032 break;
1033 }
1034 case CIL_ROLEBOUNDS: {
1035 struct cil_bounds *bnds = node->data;
1036 fprintf(out, "(rolebounds %s %s)\n", bnds->parent_str, bnds->child_str);
1037 break;
1038 }
1039 case CIL_TYPE: {
1040 fprintf(out, "(type %s)\n", datum_to_str(node->data));
1041 break;
1042 }
1043 case CIL_TYPEALIAS: {
1044 fprintf(out, "(typealias %s)\n", datum_to_str(node->data));
1045 break;
1046 }
1047 case CIL_TYPEALIASACTUAL: {
1048 struct cil_aliasactual *aliasactual = node->data;
1049 fprintf(out, "(typealiasactual %s %s)\n", aliasactual->alias_str, aliasactual->actual_str);
1050 break;
1051 }
1052 case CIL_TYPEATTRIBUTE: {
1053 fprintf(out, "(typeattribute %s)\n", datum_to_str(node->data));
1054 break;
1055 }
1056 case CIL_TYPEATTRIBUTESET: {
1057 struct cil_typeattributeset *attr = node->data;
1058 fprintf(out, "(typeattributeset %s ", attr->attr_str);
1059 if (attr->datum_expr)
1060 write_expr(out, attr->datum_expr);
1061 else
1062 write_expr(out, attr->str_expr);
1063 fprintf(out, ")\n");
1064 break;
1065 }
1066 case CIL_EXPANDTYPEATTRIBUTE: {
1067 struct cil_expandtypeattribute *attr = node->data;
1068 fprintf(out, "(expandtypeattribute ");
1069 if (attr->attr_datums)
1070 write_expr(out, attr->attr_datums);
1071 else
1072 write_expr(out, attr->attr_strs);
1073 fprintf(out, " %s)\n", attr->expand ? "true" : "false");
1074 break;
1075 }
1076 case CIL_TYPEPERMISSIVE: {
1077 struct cil_typepermissive *tp = node->data;
1078 fprintf(out, "(typepermissive ");
1079 fprintf(out, "%s", datum_or_str(DATUM(tp->type), tp->type_str));
1080 fprintf(out, ")\n");
1081 break;
1082 }
1083 case CIL_TYPEBOUNDS: {
1084 struct cil_bounds *bounds = node->data;
1085 fprintf(out, "(typebounds %s %s)\n", bounds->parent_str, bounds->child_str);
1086 break;
1087 }
1088 case CIL_ROLEALLOW: {
1089 struct cil_roleallow *roleallow = node->data;
1090 fprintf(out, "(roleallow ");
1091 fprintf(out, "%s ", datum_or_str(DATUM(roleallow->src), roleallow->src_str));
1092 fprintf(out, "%s", datum_or_str(DATUM(roleallow->tgt), roleallow->tgt_str));
1093 fprintf(out, ")\n");
1094 break;
1095 }
1096 case CIL_ROLETRANSITION: {
1097 struct cil_roletransition *roletrans = node->data;
1098 fprintf(out, "(roletransition ");
1099 fprintf(out, "%s ", datum_or_str(DATUM(roletrans->src), roletrans->src_str));
1100 fprintf(out, "%s ", datum_or_str(DATUM(roletrans->tgt), roletrans->tgt_str));
1101 fprintf(out, "%s ", datum_or_str(DATUM(roletrans->obj), roletrans->obj_str));
1102 fprintf(out, "%s", datum_or_str(DATUM(roletrans->result), roletrans->result_str));
1103 fprintf(out, ")\n");
1104 break;
1105 }
1106 case CIL_AVRULE: {
1107 struct cil_avrule *rule = node->data;
1108 if (rule->rule_kind == AVRULE_ALLOWED)
1109 fprintf(out, "(allow ");
1110 else if (rule->rule_kind == AVRULE_AUDITALLOW)
1111 fprintf(out, "(auditallow ");
1112 else if (rule->rule_kind == AVRULE_DONTAUDIT)
1113 fprintf(out, "(dontaudit ");
1114 else if (rule->rule_kind == AVRULE_NEVERALLOW)
1115 fprintf(out, "(neverallow ");
1116 else
1117 fprintf(out, "(<?AVRULE> ");
1118
1119 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1120 fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
1121 write_classperms_list(out, rule->perms.classperms);
1122 fprintf(out, ")\n");
1123 break;
1124 }
1125 case CIL_AVRULEX: {
1126 struct cil_avrule *rule = node->data;
1127 if (rule->rule_kind == AVRULE_ALLOWED)
1128 fprintf(out, "(allowx ");
1129 else if (rule->rule_kind == AVRULE_AUDITALLOW)
1130 fprintf(out, "(auditallowx ");
1131 else if (rule->rule_kind == AVRULE_DONTAUDIT)
1132 fprintf(out, "(dontauditx ");
1133 else if (rule->rule_kind == AVRULE_NEVERALLOW)
1134 fprintf(out, "(neverallowx ");
1135 else
1136 fprintf(out, "(<?AVRULEX> ");
1137 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1138 fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
1139 if (rule->perms.x.permx_str) {
1140 fprintf(out, "%s",rule->perms.x.permx_str);
1141 } else {
1142 write_permx(out, rule->perms.x.permx);
1143 }
1144 fprintf(out, ")\n");
1145 break;
1146 }
1147 case CIL_TYPE_RULE: {
1148 struct cil_type_rule *rule = node->data;
1149 if (rule->rule_kind == AVRULE_TRANSITION)
1150 fprintf(out, "(typetransition ");
1151 else if (rule->rule_kind == AVRULE_MEMBER)
1152 fprintf(out, "(typemember ");
1153 else if (rule->rule_kind == AVRULE_CHANGE)
1154 fprintf(out, "(typechange ");
1155 else
1156 fprintf(out, "(<?TYPERULE> ");
1157 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1158 fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
1159 fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
1160 fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str));
1161 fprintf(out, ")\n");
1162 break;
1163 }
1164 case CIL_NAMETYPETRANSITION: {
1165 struct cil_nametypetransition *rule = node->data;
1166 fprintf(out, "(typetransition ");
1167 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1168 fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
1169 fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
1170 fprintf(out, "\"%s\" ", datum_or_str(DATUM(rule->name), rule->name_str));
1171 fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str));
1172 fprintf(out, ")\n");
1173 break;
1174 }
1175 case CIL_RANGETRANSITION: {
1176 struct cil_rangetransition *rule = node->data;
1177 fprintf(out, "(rangetransition ");
1178 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1179 fprintf(out, "%s ", datum_or_str(DATUM(rule->exec), rule->exec_str));
1180 fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
1181 if (rule->range)
1182 write_range(out, rule->range, CIL_TRUE);
1183 else
1184 fprintf(out, "%s", rule->range_str);
1185 fprintf(out, ")\n");
1186 break;
1187 }
1188 case CIL_CONSTRAIN: {
1189 struct cil_constrain *cons = node->data;
1190 fprintf(out, "(constrain ");
1191 write_constrain(out, cons);
1192 fprintf(out, ")\n");
1193 break;
1194 }
1195 case CIL_MLSCONSTRAIN: {
1196 struct cil_constrain *cons = node->data;
1197 fprintf(out, "(mlsconstrain ");
1198 write_constrain(out, cons);
1199 fprintf(out, ")\n");
1200 break;
1201 }
1202 case CIL_VALIDATETRANS: {
1203 struct cil_validatetrans *vt = node->data;
1204 fprintf(out, "(validatetrans ");
1205 fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str));
1206 if (vt->datum_expr)
1207 write_expr(out, vt->datum_expr);
1208 else
1209 write_expr(out, vt->str_expr);
1210 fprintf(out, ")\n");
1211 break;
1212 }
1213 case CIL_MLSVALIDATETRANS: {
1214 struct cil_validatetrans *vt = node->data;
1215 fprintf(out, "(mlsvalidatetrans ");
1216 fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str));
1217 if (vt->datum_expr)
1218 write_expr(out, vt->datum_expr);
1219 else
1220 write_expr(out, vt->str_expr);
1221 fprintf(out, ")\n");
1222 break;
1223 }
1224 case CIL_CONTEXT: {
1225 struct cil_context *context = node->data;
1226 fprintf(out, "(context %s ", datum_to_str(DATUM(context)));
1227 write_context(out, context, CIL_FALSE);
1228 fprintf(out, ")\n");
1229 break;
1230 }
1231 case CIL_FILECON: {
1232 struct cil_filecon *filecon = node->data;
1233 fprintf(out, "(filecon ");
1234 fprintf(out, "\"%s\" ", filecon->path_str);
1235 if (filecon->type == CIL_FILECON_FILE)
1236 fprintf(out, "%s ", CIL_KEY_FILE);
1237 else if (filecon->type == CIL_FILECON_DIR)
1238 fprintf(out, "%s ", CIL_KEY_DIR);
1239 else if (filecon->type == CIL_FILECON_CHAR)
1240 fprintf(out, "%s ", CIL_KEY_CHAR);
1241 else if (filecon->type == CIL_FILECON_BLOCK)
1242 fprintf(out, "%s ", CIL_KEY_BLOCK);
1243 else if (filecon->type == CIL_FILECON_SOCKET)
1244 fprintf(out, "%s ", CIL_KEY_SOCKET);
1245 else if (filecon->type == CIL_FILECON_PIPE)
1246 fprintf(out, "%s ", CIL_KEY_PIPE);
1247 else if (filecon->type == CIL_FILECON_SYMLINK)
1248 fprintf(out, "%s ", CIL_KEY_SYMLINK);
1249 else if (filecon->type == CIL_FILECON_ANY)
1250 fprintf(out, "%s ", CIL_KEY_ANY);
1251 else
1252 fprintf(out, "<?FILETYPE> ");
1253 if (filecon->context)
1254 write_context(out, filecon->context, CIL_TRUE);
1255 else if (filecon->context_str)
1256 fprintf(out, "%s", filecon->context_str);
1257 else
1258 fprintf(out, "()");
1259 fprintf(out, ")\n");
1260 break;
1261 }
1262 case CIL_IBPKEYCON: {
1263 struct cil_ibpkeycon *ibpkeycon = node->data;
1264 fprintf(out, "(ibpkeycon %s ", ibpkeycon->subnet_prefix_str);
1265 fprintf(out, "(%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high);
1266 if (ibpkeycon->context)
1267 write_context(out, ibpkeycon->context, CIL_TRUE);
1268 else if (ibpkeycon->context_str)
1269 fprintf(out, "%s", ibpkeycon->context_str);
1270 fprintf(out, ")\n");
1271 break;
1272 }
1273 case CIL_PORTCON: {
1274 struct cil_portcon *portcon = node->data;
1275 fprintf(out, "(portcon ");
1276 if (portcon->proto == CIL_PROTOCOL_UDP)
1277 fprintf(out, " udp ");
1278 else if (portcon->proto == CIL_PROTOCOL_TCP)
1279 fprintf(out, " tcp ");
1280 else if (portcon->proto == CIL_PROTOCOL_DCCP)
1281 fprintf(out, "dccp ");
1282 else if (portcon->proto == CIL_PROTOCOL_SCTP)
1283 fprintf(out, "sctp ");
1284 else
1285 fprintf(out, "<?PROTOCOL> ");
1286 if (portcon->port_low == portcon->port_high)
1287 fprintf(out, "%d ", portcon->port_low);
1288 else
1289 fprintf(out, "(%d %d) ", portcon->port_low, portcon->port_high);
1290 if (portcon->context)
1291 write_context(out, portcon->context, CIL_TRUE);
1292 else
1293 fprintf(out, "%s", portcon->context_str);
1294 fprintf(out, ")\n");
1295 break;
1296 }
1297 case CIL_NODECON: {
1298 struct cil_nodecon *nodecon = node->data;
1299 fprintf(out, "(nodecon ");
1300 if (nodecon->addr)
1301 write_ipaddr(out, nodecon->addr);
1302 else
1303 fprintf(out, "%s ", nodecon->addr_str);
1304 fprintf(out, " ");
1305 if (nodecon->mask)
1306 write_ipaddr(out, nodecon->mask);
1307 else
1308 fprintf(out, "%s ", nodecon->mask_str);
1309 fprintf(out, " ");
1310 if (nodecon->context)
1311 write_context(out, nodecon->context, CIL_TRUE);
1312 else
1313 fprintf(out, "%s", nodecon->context_str);
1314 fprintf(out, ")\n");
1315 break;
1316 }
1317 case CIL_GENFSCON: {
1318 struct cil_genfscon *genfscon = node->data;
1319 fprintf(out, "(genfscon ");
1320 fprintf(out, "%s \"%s\" ", genfscon->fs_str, genfscon->path_str);
1321 if (genfscon->context)
1322 write_context(out, genfscon->context, CIL_TRUE);
1323 else
1324 fprintf(out, "%s", genfscon->context_str);
1325 fprintf(out, ")\n");
1326 break;
1327 }
1328 case CIL_NETIFCON: {
1329 struct cil_netifcon *netifcon = node->data;
1330 fprintf(out, "(netifcon %s ", netifcon->interface_str);
1331 if (netifcon->if_context)
1332 write_context(out, netifcon->if_context, CIL_TRUE);
1333 else
1334 fprintf(out, "%s", netifcon->if_context_str);
1335 fprintf(out, " ");
1336 if (netifcon->packet_context)
1337 write_context(out, netifcon->packet_context, CIL_TRUE);
1338 else
1339 fprintf(out, "%s", netifcon->packet_context_str);
1340 fprintf(out, ")\n");
1341 break;
1342 }
1343 case CIL_IBENDPORTCON: {
1344 struct cil_ibendportcon *ibendportcon = node->data;
1345 fprintf(out, "(ibendportcon %s %u ", ibendportcon->dev_name_str, ibendportcon->port);
1346 if (ibendportcon->context)
1347 write_context(out, ibendportcon->context, CIL_TRUE);
1348 else
1349 fprintf(out, "%s", ibendportcon->context_str);
1350 fprintf(out, ")\n");
1351 break;
1352 }
1353 case CIL_PIRQCON: {
1354 struct cil_pirqcon *pirqcon = node->data;
1355 fprintf(out, "(pirqcon %d ", pirqcon->pirq);
1356 if (pirqcon->context)
1357 write_context(out, pirqcon->context, CIL_TRUE);
1358 else
1359 fprintf(out, "%s", pirqcon->context_str);
1360 fprintf(out, ")\n");
1361 break;
1362 }
1363 case CIL_IOMEMCON: {
1364 struct cil_iomemcon *iomemcon = node->data;
1365 fprintf(out, "(iomemcon (%"PRId64" %"PRId64") ", iomemcon->iomem_low, iomemcon->iomem_high);
1366 if (iomemcon->context)
1367 write_context(out, iomemcon->context, CIL_TRUE);
1368 else
1369 fprintf(out, "%s", iomemcon->context_str);
1370 fprintf(out, ")\n");
1371 break;
1372 }
1373 case CIL_IOPORTCON: {
1374 struct cil_ioportcon *ioportcon = node->data;
1375 fprintf(out, "(ioportcon ");
1376 if (ioportcon->ioport_low == ioportcon->ioport_high)
1377 fprintf(out, "%d ", ioportcon->ioport_low);
1378 else
1379 fprintf(out, "(%d %d) ", ioportcon->ioport_low, ioportcon->ioport_high);
1380
1381 if (ioportcon->context)
1382 write_context(out, ioportcon->context, CIL_TRUE);
1383 else
1384 fprintf(out, "%s", ioportcon->context_str);
1385 fprintf(out, ")\n");
1386 break;
1387 }
1388 case CIL_PCIDEVICECON: {
1389 struct cil_pcidevicecon *pcidevicecon = node->data;
1390 fprintf(out, "(pcidevicecon %d ", pcidevicecon->dev);
1391 if (pcidevicecon->context)
1392 write_context(out, pcidevicecon->context, CIL_TRUE);
1393 else
1394 fprintf(out, "%s", pcidevicecon->context_str);
1395 fprintf(out, ")\n");
1396 break;
1397 }
1398 case CIL_DEVICETREECON: {
1399 struct cil_devicetreecon *devicetreecon = node->data;
1400 fprintf(out, "(devicetreecon \"%s\" ", devicetreecon->path);
1401 if (devicetreecon->context)
1402 write_context(out, devicetreecon->context, CIL_TRUE);
1403 else
1404 fprintf(out, "%s", devicetreecon->context_str);
1405 fprintf(out, ")\n");
1406 break;
1407 }
1408 case CIL_FSUSE: {
1409 struct cil_fsuse *fsuse = node->data;
1410 fprintf(out, "(fsuse ");
1411 if (fsuse->type == CIL_FSUSE_XATTR)
1412 fprintf(out, "xattr ");
1413 else if (fsuse->type == CIL_FSUSE_TASK)
1414 fprintf(out, "task ");
1415 else if (fsuse->type == CIL_FSUSE_TRANS)
1416 fprintf(out, "trans ");
1417 else
1418 fprintf(out, "<?TYPE> ");
1419 fprintf(out, "%s ", fsuse->fs_str);
1420 if (fsuse->context)
1421 write_context(out, fsuse->context, CIL_TRUE);
1422 else
1423 fprintf(out, "%s", fsuse->context_str);
1424 fprintf(out, ")\n");
1425 break;
1426 }
1427 case CIL_POLICYCAP: {
1428 struct cil_policycap *polcap = node->data;
1429 fprintf(out, "(policycap %s)\n", polcap->datum.name);
1430 break;
1431 }
1432 case CIL_IPADDR: {
1433 struct cil_ipaddr *ipaddr = node->data;
1434 char buf[256];
1435 if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL)
1436 strcpy(buf, "<?IPADDR>");
1437 fprintf(out, "(ipaddr %s %s)\n", datum_to_str(&ipaddr->datum), buf);
1438 break;
1439 }
1440 default :
1441 fprintf(out, "(<?RULE:%s>)\n", cil_node_to_string(node));
1442 break;
1443 }
1444 }
1445
1446 /*
1447 * Tree walk data and helper functions for writing the AST of the various phases
1448 */
1449
1450 struct cil_write_ast_args {
1451 FILE *out;
1452 int depth;
1453 };
1454
1455 /*
1456 * Helper functions for writing the parse AST
1457 */
1458
__write_parse_ast_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1459 static int __write_parse_ast_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
1460 {
1461 struct cil_write_ast_args *args = extra_args;
1462
1463 fprintf(args->out, "%*s", args->depth*4, "");
1464 if (!node->data) {
1465 if (node->cl_head)
1466 fprintf(args->out, "(\n");
1467 else
1468 fprintf(args->out, "()\n");
1469 } else {
1470 char *str = (char *)node->data;
1471 size_t len = strlen(str);
1472 size_t i;
1473
1474 for (i = 0; i < len; i++) {
1475 if (isspace(str[i])) {
1476 fprintf(args->out, "\"%s\"\n", str);
1477 return SEPOL_OK;
1478 }
1479 }
1480
1481 fprintf(args->out, "%s\n", (char *)node->data);
1482 }
1483
1484 return SEPOL_OK;
1485 }
1486
__write_parse_ast_first_child_helper(struct cil_tree_node * node,void * extra_args)1487 static int __write_parse_ast_first_child_helper(struct cil_tree_node *node, void *extra_args)
1488 {
1489 struct cil_write_ast_args *args = extra_args;
1490 struct cil_tree_node *parent = node->parent;
1491
1492 if (parent->flavor != CIL_ROOT) {
1493 args->depth++;
1494 }
1495
1496 return SEPOL_OK;
1497 }
1498
__write_parse_ast_last_child_helper(struct cil_tree_node * node,void * extra_args)1499 static int __write_parse_ast_last_child_helper(struct cil_tree_node *node, void *extra_args)
1500 {
1501 struct cil_write_ast_args *args = extra_args;
1502 struct cil_tree_node *parent = node->parent;
1503
1504 if (parent->flavor == CIL_ROOT) {
1505 return SEPOL_OK;
1506 }
1507
1508 args->depth--;
1509 fprintf(args->out, "%*s", args->depth*4, "");
1510 fprintf(args->out, ")\n");
1511
1512 return SEPOL_OK;
1513 }
1514
1515 /*
1516 * Helper functions for writing the CIL AST for the build and resolve phases
1517 */
1518
__write_cil_ast_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1519 static int __write_cil_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1520 {
1521 struct cil_write_ast_args *args = extra_args;
1522
1523 if (node->flavor == CIL_SRC_INFO) {
1524 cil_write_src_info_node(args->out, node);
1525 return SEPOL_OK;
1526 }
1527
1528 fprintf(args->out, "%*s", args->depth*4, "");
1529
1530 cil_write_ast_node(args->out, node);
1531
1532 if (node->flavor == CIL_CLASS || node->flavor == CIL_COMMON || node->flavor == CIL_MAP_CLASS) {
1533 *finished = CIL_TREE_SKIP_HEAD;
1534 }
1535
1536 return SEPOL_OK;
1537 }
1538
__write_cil_ast_first_child_helper(struct cil_tree_node * node,void * extra_args)1539 static int __write_cil_ast_first_child_helper(struct cil_tree_node *node, void *extra_args)
1540 {
1541 struct cil_write_ast_args *args = extra_args;
1542 struct cil_tree_node *parent = node->parent;
1543
1544 if (parent->flavor != CIL_SRC_INFO && parent->flavor != CIL_ROOT) {
1545 args->depth++;
1546 }
1547
1548 return SEPOL_OK;
1549 }
1550
__write_cil_ast_last_child_helper(struct cil_tree_node * node,void * extra_args)1551 static int __write_cil_ast_last_child_helper(struct cil_tree_node *node, void *extra_args)
1552 {
1553 struct cil_write_ast_args *args = extra_args;
1554 struct cil_tree_node *parent = node->parent;
1555
1556 if (parent->flavor == CIL_ROOT) {
1557 return SEPOL_OK;
1558 } else if (parent->flavor == CIL_SRC_INFO) {
1559 fprintf(args->out, ";;* lme\n");
1560 return SEPOL_OK;
1561 }
1562
1563 args->depth--;
1564 fprintf(args->out, "%*s", args->depth*4, "");
1565 fprintf(args->out, ")\n");
1566
1567 return SEPOL_OK;
1568 }
1569
cil_write_ast(FILE * out,enum cil_write_ast_phase phase,struct cil_tree_node * node)1570 int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node)
1571 {
1572 struct cil_write_ast_args extra_args;
1573 int rc;
1574
1575 extra_args.out = out;
1576 extra_args.depth = 0;
1577
1578 if (phase == CIL_WRITE_AST_PHASE_PARSE) {
1579 rc = cil_tree_walk(node, __write_parse_ast_node_helper, __write_parse_ast_first_child_helper, __write_parse_ast_last_child_helper, &extra_args);
1580 } else {
1581 rc = cil_tree_walk(node, __write_cil_ast_node_helper, __write_cil_ast_first_child_helper, __write_cil_ast_last_child_helper, &extra_args);
1582 }
1583
1584 if (rc != SEPOL_OK) {
1585 cil_log(CIL_ERR, "Failed to write AST\n");
1586 return SEPOL_ERR;
1587 }
1588
1589 return SEPOL_OK;
1590 }
1591