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 ? 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_DECLARED_STRING:
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 fprintf(out, "%s", datum_or_str(DATUM(arg->arg), arg->arg_str));
418 break;
419 }
420 case CIL_DECLARED_STRING: {
421 if (arg->arg) {
422 fprintf(out, "\"%s\" ", DATUM(arg->arg)->fqn);
423 } else {
424 fprintf(out, "%s ", arg->arg_str);
425 }
426 break;
427 }
428 case CIL_CATSET: {
429 if (arg->arg) {
430 struct cil_catset *catset = (struct cil_catset *)arg->arg;
431 write_cats(out, catset->cats);
432 } else {
433 fprintf(out, "%s", arg->arg_str);
434 }
435 break;
436 }
437 case CIL_LEVEL: {
438 if (arg->arg) {
439 struct cil_level *level = (struct cil_level *)arg->arg;
440 write_level(out, level, CIL_TRUE);
441 } else {
442 fprintf(out, "%s", arg->arg_str);
443 }
444 break;
445 }
446 case CIL_LEVELRANGE: {
447 if (arg->arg) {
448 struct cil_levelrange *range = (struct cil_levelrange *)arg->arg;
449 write_range(out, range, CIL_TRUE);
450 } else {
451 fprintf(out, "%s", arg->arg_str);
452 }
453 break;
454 }
455 case CIL_IPADDR: {
456 if (arg->arg) {
457 struct cil_ipaddr *addr = (struct cil_ipaddr *)arg->arg;
458 write_ipaddr(out, addr);
459 } else {
460 fprintf(out, "%s", arg->arg_str);
461 }
462 break;
463 }
464 case CIL_CLASSPERMISSION: {
465 if (arg->arg) {
466 struct cil_classpermission *cp = (struct cil_classpermission *)arg->arg;
467 if (cp->datum.name)
468 fprintf(out, "%s", datum_to_str(DATUM(cp)));
469 else
470 write_classperms_list(out, cp->classperms);
471 } else {
472 fprintf(out, "%s", arg->arg_str);
473 }
474 break;
475 }
476 default:
477 fprintf(out, "<?ARG:%s>", datum_or_str(DATUM(arg->arg), arg->arg_str));
478 break;
479 }
480 }
481 fprintf(out, ")");
482 }
483
write_call_args_tree(FILE * out,struct cil_tree_node * arg_node)484 static void write_call_args_tree(FILE *out, struct cil_tree_node *arg_node)
485 {
486 while (arg_node) {
487 if (arg_node->data) {
488 fprintf(out, "%s", (char *)arg_node->data);
489 } else if (arg_node->cl_head) {
490 fprintf(out, "(");
491 write_call_args_tree(out, arg_node->cl_head);
492 fprintf(out, ")");
493 }
494 if (arg_node->next)
495 fprintf(out, " ");
496 arg_node = arg_node->next;
497 }
498 }
499
macro_param_flavor_to_string(enum cil_flavor flavor)500 static const char *macro_param_flavor_to_string(enum cil_flavor flavor)
501 {
502 const char *str;
503 switch(flavor) {
504 case CIL_TYPE:
505 str = CIL_KEY_TYPE;
506 break;
507 case CIL_ROLE:
508 str = CIL_KEY_ROLE;
509 break;
510 case CIL_USER:
511 str = CIL_KEY_USER;
512 break;
513 case CIL_SENS:
514 str = CIL_KEY_SENSITIVITY;
515 break;
516 case CIL_CAT:
517 str = CIL_KEY_CATEGORY;
518 break;
519 case CIL_CATSET:
520 str = CIL_KEY_CATSET;
521 break;
522 case CIL_LEVEL:
523 str = CIL_KEY_LEVEL;
524 break;
525 case CIL_LEVELRANGE:
526 str = CIL_KEY_LEVELRANGE;
527 break;
528 case CIL_CLASS:
529 str = CIL_KEY_CLASS;
530 break;
531 case CIL_IPADDR:
532 str = CIL_KEY_IPADDR;
533 break;
534 case CIL_MAP_CLASS:
535 str = CIL_KEY_MAP_CLASS;
536 break;
537 case CIL_CLASSPERMISSION:
538 str = CIL_KEY_CLASSPERMISSION;
539 break;
540 case CIL_BOOL:
541 str = CIL_KEY_BOOL;
542 break;
543 case CIL_DECLARED_STRING:
544 str = CIL_KEY_STRING;
545 break;
546 default:
547 str = "<?FLAVOR>";
548 break;
549 }
550 return str;
551 }
552
cil_write_src_info_node(FILE * out,struct cil_tree_node * node)553 static void cil_write_src_info_node(FILE *out, struct cil_tree_node *node)
554 {
555 struct cil_src_info *info = node->data;
556 if (info->kind == CIL_KEY_SRC_CIL || info->kind == CIL_KEY_SRC_HLL_LMS) {
557 fprintf(out, ";;* lms %u %s\n", info->hll_line, info->path);
558 } else if (info->kind == CIL_KEY_SRC_HLL_LMX) {
559 fprintf(out, ";;* lmx %u %s\n", info->hll_line, info->path);
560 } else {
561 fprintf(out, ";;* <?SRC_INFO_KIND> %u %s\n", info->hll_line, info->path);
562 }
563 }
564
cil_write_ast_node(FILE * out,struct cil_tree_node * node)565 void cil_write_ast_node(FILE *out, struct cil_tree_node *node)
566 {
567 if (!node->data) {
568 return;
569 }
570
571 switch(node->flavor) {
572 case CIL_NODE: {
573 fprintf(out, "%s\n", (char *)node->data);
574 break;
575 }
576 case CIL_BLOCK: {
577 struct cil_block *block = node->data;
578 fprintf(out, "(block %s", datum_to_str(DATUM(block)));
579 if (!node->cl_head)
580 fprintf(out, ")");
581 fprintf(out, "\n");
582 break;
583 }
584 case CIL_BLOCKINHERIT: {
585 struct cil_blockinherit *inherit = node->data;
586 fprintf(out, "(blockinherit %s)\n", datum_or_str(DATUM(inherit->block), inherit->block_str));
587 break;
588 }
589 case CIL_IN: {
590 struct cil_in *in = node->data;
591 fprintf(out, "(in %s", datum_or_str(DATUM(in->block), in->block_str));
592 if (!node->cl_head)
593 fprintf(out, ")");
594 fprintf(out, "\n");
595 break;
596 }
597 case CIL_OPTIONAL: {
598 struct cil_optional *optional = node->data;
599 fprintf(out, "(optional %s", datum_to_str(DATUM(optional)));
600 if (!node->cl_head)
601 fprintf(out, ")");
602 fprintf(out, "\n");
603 break;
604 }
605 case CIL_BOOLEANIF: {
606 struct cil_booleanif *bif = node->data;
607 fprintf(out, "(booleanif ");
608 if (bif->datum_expr)
609 write_expr(out, bif->datum_expr);
610 else
611 write_expr(out, bif->str_expr);
612 if (!node->cl_head)
613 fprintf(out, ")");
614 fprintf(out, "\n");
615 break;
616 }
617 case CIL_TUNABLEIF: {
618 struct cil_tunableif *tif = node->data;
619 fprintf(out, "(tunableif ");
620 if (tif->datum_expr)
621 write_expr(out, tif->datum_expr);
622 else
623 write_expr(out, tif->str_expr);
624 if (!node->cl_head)
625 fprintf(out, ")");
626 fprintf(out, "\n");
627 break;
628 }
629 case CIL_CONDBLOCK: {
630 struct cil_condblock *cb = node->data;
631 fprintf(out, "(%s", cb->flavor == CIL_CONDTRUE ? "true" : "false");
632 if (!node->cl_head)
633 fprintf(out, ")");
634 fprintf(out, "\n");
635 break;
636 }
637 case CIL_MACRO: {
638 struct cil_macro *macro = node->data;
639 struct cil_list_item *curr;
640 fprintf(out, "(macro %s (", datum_to_str(DATUM(macro)));
641 if (macro->params) {
642 cil_list_for_each(curr, macro->params) {
643 struct cil_param *param = curr->data;
644 fprintf(out, "(%s %s)", macro_param_flavor_to_string(param->flavor), param->str);
645 }
646 }
647 fprintf(out, ")");
648 if (!node->cl_head)
649 fprintf(out, ")");
650 fprintf(out, "\n");
651 break;
652 }
653 case CIL_CALL: {
654 struct cil_call *call = node->data;
655 fprintf(out, "(call %s", datum_or_str(DATUM(call->macro), call->macro_str));
656 if (call->args) {
657 fprintf(out, " ");
658 write_call_args(out, call->args);
659 } else if (call->args_tree) {
660 fprintf(out, " ");
661 write_call_args_tree(out, call->args_tree->root);
662 }
663 if (!node->cl_head)
664 fprintf(out, ")");
665 fprintf(out, "\n");
666 break;
667 }
668 case CIL_BLOCKABSTRACT: {
669 struct cil_blockabstract *abstract = node->data;
670 fprintf(out, "(blockabstract %s)\n", datum_or_str(DATUM(abstract->block), abstract->block_str));
671 break;
672 }
673 case CIL_MLS: {
674 struct cil_mls *mls = node->data;
675 fprintf(out, "(mls %s)\n", mls->value ? "true" : "false");
676 break;
677 }
678 case CIL_HANDLEUNKNOWN: {
679 struct cil_handleunknown *unknown = node->data;
680 fprintf(out, "(handleunknown ");
681 if (unknown->handle_unknown == SEPOL_ALLOW_UNKNOWN)
682 fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_ALLOW);
683 else if (unknown->handle_unknown == SEPOL_DENY_UNKNOWN)
684 fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_DENY);
685 else if (unknown->handle_unknown == SEPOL_REJECT_UNKNOWN)
686 fprintf(out, "%s", CIL_KEY_HANDLEUNKNOWN_REJECT);
687 else
688 fprintf(out, "<?UNKNOWN>");
689 fprintf(out, ")\n");
690 break;
691 }
692 case CIL_DEFAULTUSER: {
693 struct cil_default *def = node->data;
694 fprintf(out, "(defaultuser ");
695 if (def->class_datums)
696 write_datum_list(out, def->class_datums);
697 else
698 write_string_list(out, def->class_strs);
699 if (def->object == CIL_DEFAULT_SOURCE)
700 fprintf(out, " source");
701 else if (def->object == CIL_DEFAULT_TARGET)
702 fprintf(out, " target");
703 else
704 fprintf(out, " <?DEFAULT>");
705 fprintf(out, ")\n");
706 break;
707 }
708 case CIL_DEFAULTROLE: {
709 struct cil_default *def = node->data;
710 fprintf(out, "(defaultrole ");
711 if (def->class_datums)
712 write_datum_list(out, def->class_datums);
713 else
714 write_string_list(out, def->class_strs);
715 if (def->object == CIL_DEFAULT_SOURCE)
716 fprintf(out, " source");
717 else if (def->object == CIL_DEFAULT_TARGET)
718 fprintf(out, " target");
719 else
720 fprintf(out, " <?DEFAULT>");
721 fprintf(out, ")\n");
722 break;
723 }
724 case CIL_DEFAULTTYPE: {
725 struct cil_default *def = node->data;
726 fprintf(out, "(defaulttype ");
727 if (def->class_datums)
728 write_datum_list(out, def->class_datums);
729 else
730 write_string_list(out, def->class_strs);
731 if (def->object == CIL_DEFAULT_SOURCE)
732 fprintf(out, " source");
733 else if (def->object == CIL_DEFAULT_TARGET)
734 fprintf(out, " target");
735 else
736 fprintf(out, " <?DEFAULT>");
737 fprintf(out, ")\n");
738 break;
739 }
740 case CIL_DEFAULTRANGE: {
741 struct cil_defaultrange *def = node->data;
742 fprintf(out, "(defaultrange ");
743 if (def->class_datums)
744 write_datum_list(out, def->class_datums);
745 else
746 write_string_list(out, def->class_strs);
747 if (def->object_range == CIL_DEFAULT_SOURCE_LOW)
748 fprintf(out, " source low");
749 else if (def->object_range == CIL_DEFAULT_SOURCE_HIGH)
750 fprintf(out, " source high");
751 else if (def->object_range == CIL_DEFAULT_SOURCE_LOW_HIGH)
752 fprintf(out, " source low-high");
753 else if (def->object_range == CIL_DEFAULT_TARGET_LOW)
754 fprintf(out, " target low");
755 else if (def->object_range == CIL_DEFAULT_TARGET_HIGH)
756 fprintf(out, " target high");
757 else if (def->object_range == CIL_DEFAULT_TARGET_LOW_HIGH)
758 fprintf(out, " target low-high");
759 else
760 fprintf(out, " <?DEFAULT>");
761 fprintf(out, ")\n");
762 break;
763 }
764 case CIL_CLASS: {
765 struct cil_class *class = node->data;
766 fprintf(out, "(class %s ", datum_to_str(DATUM(class)));
767 write_node_list(out, node->cl_head);
768 fprintf(out, ")\n");
769 break;
770 }
771 case CIL_CLASSORDER: {
772 struct cil_ordered *ordered = node->data;
773 fprintf(out, "(classorder ");
774 if (ordered->datums) {
775 write_datum_list(out, ordered->datums);
776 } else {
777 write_string_list(out, ordered->strs);
778 }
779 fprintf(out, ")\n");
780 break;
781 }
782 case CIL_COMMON: {
783 struct cil_class *common = node->data;
784 fprintf(out, "(common %s ", datum_to_str(DATUM(common)));
785 write_node_list(out, node->cl_head);
786 fprintf(out, ")\n");
787 break;
788 }
789 case CIL_CLASSCOMMON: {
790 struct cil_classcommon *cc = node->data;
791 fprintf(out, "(classcommon %s ", datum_or_str(DATUM(cc->class), cc->class_str));
792 fprintf(out, "%s", datum_or_str(DATUM(cc->common), cc->common_str));
793 fprintf(out, ")\n");
794 break;
795 }
796 case CIL_CLASSPERMISSION: {
797 struct cil_classpermission *cp = node->data;
798 fprintf(out, "(classpermission %s)\n", datum_to_str(DATUM(cp)));
799 break;
800 }
801 case CIL_CLASSPERMISSIONSET: {
802 struct cil_classpermissionset *cps = node->data;
803 fprintf(out, "(classpermissionset %s ", datum_or_str(DATUM(cps->set), cps->set_str));
804 write_classperms_list(out, cps->classperms);
805 fprintf(out, ")\n");
806 break;
807 }
808 case CIL_MAP_CLASS: {
809 struct cil_class *map = node->data;
810 fprintf(out, "(classmap %s ", datum_to_str(DATUM(map)));
811 write_node_list(out, node->cl_head);
812 fprintf(out, ")\n");
813 break;
814 }
815 case CIL_CLASSMAPPING: {
816 struct cil_classmapping *mapping = node->data;
817 fprintf(out, "(classmapping %s ", datum_or_str(DATUM(mapping->map_class), mapping->map_class_str));
818 fprintf(out, "%s ", datum_or_str(DATUM(mapping->map_perm), mapping->map_perm_str));
819 write_classperms_list(out, mapping->classperms);
820 fprintf(out, ")\n");
821 break;
822 }
823 case CIL_PERMISSIONX: {
824 struct cil_permissionx *permx = node->data;
825 fprintf(out, "(permissionx %s (", datum_to_str(DATUM(permx)));
826 fprintf(out, "%s ", permx->kind == CIL_PERMX_KIND_IOCTL ? "ioctl" : "<?KIND>");
827 fprintf(out, "%s ", datum_or_str(DATUM(permx->obj), permx->obj_str));
828 write_expr(out, permx->expr_str);
829 fprintf(out, "))\n");
830 break;
831 }
832 case CIL_SID: {
833 struct cil_sid *sid = node->data;
834 fprintf(out, "(sid %s)\n", datum_to_str(DATUM(sid)));
835 break;
836 }
837 case CIL_SIDCONTEXT: {
838 struct cil_sidcontext *sidcon = node->data;
839 fprintf(out, "(sidcontext %s ", datum_or_str(DATUM(sidcon->sid), sidcon->sid_str));
840 if (sidcon->context)
841 write_context(out, sidcon->context, CIL_TRUE);
842 else
843 fprintf(out, "%s", sidcon->context_str);
844 fprintf(out, ")\n");
845 break;
846 }
847 case CIL_SIDORDER: {
848 struct cil_ordered *ordered = node->data;
849 fprintf(out, "(sidorder ");
850 if (ordered->datums) {
851 write_datum_list(out, ordered->datums);
852 } else {
853 write_string_list(out, ordered->strs);
854 }
855 fprintf(out, ")\n");
856 break;
857 }
858 case CIL_BOOL: {
859 struct cil_bool *boolean = node->data;
860 fprintf(out, "(boolean %s %s)\n", datum_to_str(DATUM(boolean)), boolean->value ? "true" : "false");
861 break;
862 }
863 case CIL_TUNABLE: {
864 struct cil_tunable *tunable = node->data;
865 fprintf(out, "(tunable %s %s)\n", datum_to_str(DATUM(tunable)), tunable->value ? "true" : "false");
866 break;
867 }
868 case CIL_SENS: {
869 struct cil_sens *sens = node->data;
870 fprintf(out, "(sensitivity %s)\n", datum_to_str(DATUM(sens)));
871 break;
872 }
873 case CIL_SENSALIAS: {
874 struct cil_alias *alias = node->data;
875 fprintf(out, "(sensitivityalias %s)\n", datum_to_str(DATUM(alias)));
876 break;
877 }
878 case CIL_SENSALIASACTUAL: {
879 struct cil_aliasactual *aliasactual = node->data;
880 fprintf(out, "(sensitivityaliasactual %s ", datum_or_str(DATUM(aliasactual->alias), aliasactual->alias_str));
881 fprintf(out, "%s", datum_or_str(DATUM(aliasactual->actual), aliasactual->actual_str));
882 fprintf(out, ")\n");
883 break;
884 }
885 case CIL_CAT: {
886 struct cil_cat *cat = node->data;
887 fprintf(out, "(category %s)\n", datum_to_str(DATUM(cat)));
888 break;
889 }
890 case CIL_CATALIAS: {
891 struct cil_alias *alias = node->data;
892 fprintf(out, "(categoryalias %s)\n", datum_to_str(DATUM(alias)));
893 break;
894 }
895 case CIL_CATALIASACTUAL: {
896 struct cil_aliasactual *aliasactual = node->data;
897 fprintf(out, "(categoryaliasactual %s ", datum_or_str(DATUM(aliasactual->alias), aliasactual->alias_str));
898 fprintf(out, "%s", datum_or_str(DATUM(aliasactual->actual), aliasactual->actual_str));
899 fprintf(out, ")\n");
900 break;
901 }
902 case CIL_CATSET: {
903 struct cil_catset *catset = node->data;
904 fprintf(out, "(categoryset %s ", datum_to_str(DATUM(catset)));
905 write_cats(out, catset->cats);
906 fprintf(out, ")\n");
907 break;
908 }
909 case CIL_CATORDER: {
910 struct cil_ordered *ordered = node->data;
911 fprintf(out, "(categoryorder ");
912 if (ordered->datums) {
913 write_datum_list(out, ordered->datums);
914 } else {
915 write_string_list(out, ordered->strs);
916 }
917 fprintf(out, ")\n");
918 break;
919 }
920 case CIL_SENSCAT: {
921 struct cil_senscat *senscat = node->data;
922 fprintf(out, "(sensitivitycategory ");
923 fprintf(out, "%s ", datum_or_str(DATUM(senscat->sens), senscat->sens_str));
924 write_cats(out, senscat->cats);
925 fprintf(out, ")\n");
926 break;
927 }
928 case CIL_SENSITIVITYORDER: {
929 struct cil_ordered *ordered = node->data;
930 fprintf(out, "(sensitivityorder ");
931 if (ordered->datums) {
932 write_datum_list(out, ordered->datums);
933 } else {
934 write_string_list(out, ordered->strs);
935 }
936 fprintf(out, ")\n");
937 break;
938 }
939 case CIL_LEVEL: {
940 struct cil_level *level = node->data;
941 fprintf(out, "(level %s ", datum_to_str(&level->datum));
942 write_level(out, level, CIL_FALSE);
943 fprintf(out, ")\n");
944 break;
945 }
946 case CIL_LEVELRANGE: {
947 struct cil_levelrange *lvlrange = node->data;
948 fprintf(out, "(levelrange %s ", datum_to_str(DATUM(lvlrange)));
949 write_range(out, lvlrange, CIL_FALSE);
950 fprintf(out, ")\n");
951 break;
952 }
953 case CIL_USER: {
954 struct cil_user *user = node->data;
955 fprintf(out, "(user %s)\n", datum_to_str(DATUM(user)));
956 break;
957 }
958 case CIL_USERATTRIBUTE: {
959 struct cil_userattribute *attr = node->data;
960 fprintf(out, "(userattribute %s)\n", datum_to_str(DATUM(attr)));
961 break;
962 }
963 case CIL_USERATTRIBUTESET: {
964 struct cil_userattributeset *attr = node->data;
965 fprintf(out, "(userattributeset %s ", datum_or_str(DATUM(attr->attr), attr->attr_str));
966 if (attr->datum_expr)
967 write_expr(out, attr->datum_expr);
968 else
969 write_expr(out, attr->str_expr);
970 fprintf(out, ")\n");
971 break;
972 }
973 case CIL_USERROLE: {
974 struct cil_userrole *userrole = node->data;
975 fprintf(out, "(userrole ");
976 fprintf(out, "%s ", datum_or_str(DATUM(userrole->user), userrole->user_str));
977 fprintf(out, "%s", datum_or_str(DATUM(userrole->role), userrole->role_str));
978 fprintf(out, ")\n");
979 break;
980 }
981 case CIL_USERLEVEL: {
982 struct cil_userlevel *userlevel = node->data;
983 fprintf(out, "(userlevel %s ", datum_or_str(DATUM(userlevel->user), userlevel->user_str));
984 if (userlevel->level)
985 write_level(out, userlevel->level, CIL_TRUE);
986 else
987 fprintf(out, "%s", userlevel->level_str);
988 fprintf(out, ")\n");
989 break;
990 }
991 case CIL_USERRANGE: {
992 struct cil_userrange *userrange = node->data;
993 fprintf(out, "(userrange %s ", datum_or_str(DATUM(userrange->user), userrange->user_str));
994 if (userrange->range)
995 write_range(out, userrange->range, CIL_TRUE);
996 else
997 fprintf(out, "%s", userrange->range_str);
998 fprintf(out, ")\n");
999 break;
1000 }
1001 case CIL_USERBOUNDS: {
1002 struct cil_bounds *bounds = node->data;
1003 fprintf(out, "(userbounds ");
1004 fprintf(out, "%s ", datum_or_str(DATUM(bounds->parent), bounds->parent_str));
1005 fprintf(out, "%s)\n", datum_or_str(DATUM(bounds->child), bounds->child_str));
1006 break;
1007 }
1008 case CIL_USERPREFIX: {
1009 struct cil_userprefix *prefix = node->data;
1010 fprintf(out, "(userprefix ");
1011 fprintf(out, "%s ", datum_or_str(DATUM(prefix->user), prefix->user_str));
1012 fprintf(out, "%s)\n", prefix->prefix_str);
1013 break;
1014 }
1015 case CIL_SELINUXUSER: {
1016 struct cil_selinuxuser *selinuxuser = node->data;
1017 fprintf(out, "(selinuxuser %s ", selinuxuser->name_str);
1018 fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str));
1019 if (selinuxuser->range)
1020 write_range(out, selinuxuser->range, CIL_TRUE);
1021 else
1022 fprintf(out, "%s", selinuxuser->range_str);
1023 fprintf(out, ")\n");
1024 break;
1025 }
1026 case CIL_SELINUXUSERDEFAULT: {
1027 struct cil_selinuxuser *selinuxuser = node->data;
1028 fprintf(out, "(selinuxuserdefault ");
1029 fprintf(out, "%s ", datum_or_str(DATUM(selinuxuser->user), selinuxuser->user_str));
1030 if (selinuxuser->range)
1031 write_range(out, selinuxuser->range, CIL_TRUE);
1032 else
1033 fprintf(out, "%s", selinuxuser->range_str);
1034 fprintf(out, ")\n");
1035 break;
1036 }
1037 case CIL_ROLE: {
1038 fprintf(out, "(role %s)\n", datum_to_str(node->data));
1039 break;
1040 }
1041 case CIL_ROLEATTRIBUTE: {
1042 fprintf(out, "(roleattribute %s)\n", datum_to_str(node->data));
1043 break;
1044 }
1045 case CIL_ROLEATTRIBUTESET: {
1046 struct cil_roleattributeset *attr = node->data;
1047 fprintf(out, "(roleattributeset %s ", datum_or_str(DATUM(attr->attr), attr->attr_str));
1048 if (attr->datum_expr)
1049 write_expr(out, attr->datum_expr);
1050 else
1051 write_expr(out, attr->str_expr);
1052 fprintf(out, ")\n");
1053 break;
1054 }
1055 case CIL_ROLETYPE: {
1056 struct cil_roletype *roletype = node->data;
1057 fprintf(out, "(roletype ");
1058 fprintf(out, "%s ", datum_or_str(DATUM(roletype->role), roletype->role_str));
1059 fprintf(out, "%s", datum_or_str(DATUM(roletype->type), roletype->type_str));
1060 fprintf(out, ")\n");
1061 break;
1062 }
1063 case CIL_ROLEBOUNDS: {
1064 struct cil_bounds *bounds = node->data;
1065 fprintf(out, "(rolebounds ");
1066 fprintf(out, "%s ", datum_or_str(DATUM(bounds->parent), bounds->parent_str));
1067 fprintf(out, "%s)\n", datum_or_str(DATUM(bounds->child), bounds->child_str));
1068 break;
1069 }
1070 case CIL_TYPE: {
1071 fprintf(out, "(type %s)\n", datum_to_str(node->data));
1072 break;
1073 }
1074 case CIL_TYPEALIAS: {
1075 fprintf(out, "(typealias %s)\n", datum_to_str(node->data));
1076 break;
1077 }
1078 case CIL_TYPEALIASACTUAL: {
1079 struct cil_aliasactual *aliasactual = node->data;
1080 fprintf(out, "(typealiasactual %s ", datum_or_str(DATUM(aliasactual->alias), aliasactual->alias_str));
1081 fprintf(out, "%s", datum_or_str(DATUM(aliasactual->actual), aliasactual->actual_str));
1082 fprintf(out, ")\n");
1083 break;
1084 }
1085 case CIL_TYPEATTRIBUTE: {
1086 fprintf(out, "(typeattribute %s)\n", datum_to_str(node->data));
1087 break;
1088 }
1089 case CIL_TYPEATTRIBUTESET: {
1090 struct cil_typeattributeset *attr = node->data;
1091 fprintf(out, "(typeattributeset %s ", datum_or_str(DATUM(attr->attr), attr->attr_str));
1092 if (attr->datum_expr)
1093 write_expr(out, attr->datum_expr);
1094 else
1095 write_expr(out, attr->str_expr);
1096 fprintf(out, ")\n");
1097 break;
1098 }
1099 case CIL_EXPANDTYPEATTRIBUTE: {
1100 struct cil_expandtypeattribute *attr = node->data;
1101 fprintf(out, "(expandtypeattribute ");
1102 if (attr->attr_datums)
1103 write_expr(out, attr->attr_datums);
1104 else
1105 write_expr(out, attr->attr_strs);
1106 fprintf(out, " %s)\n", attr->expand ? "true" : "false");
1107 break;
1108 }
1109 case CIL_TYPEPERMISSIVE: {
1110 struct cil_typepermissive *tp = node->data;
1111 fprintf(out, "(typepermissive ");
1112 fprintf(out, "%s", datum_or_str(DATUM(tp->type), tp->type_str));
1113 fprintf(out, ")\n");
1114 break;
1115 }
1116 case CIL_TYPEBOUNDS: {
1117 struct cil_bounds *bounds = node->data;
1118 fprintf(out, "(typebounds ");
1119 fprintf(out, "%s ", datum_or_str(DATUM(bounds->parent), bounds->parent_str));
1120 fprintf(out, "%s)\n", datum_or_str(DATUM(bounds->child), bounds->child_str));
1121 break;
1122 }
1123 case CIL_ROLEALLOW: {
1124 struct cil_roleallow *roleallow = node->data;
1125 fprintf(out, "(roleallow ");
1126 fprintf(out, "%s ", datum_or_str(DATUM(roleallow->src), roleallow->src_str));
1127 fprintf(out, "%s", datum_or_str(DATUM(roleallow->tgt), roleallow->tgt_str));
1128 fprintf(out, ")\n");
1129 break;
1130 }
1131 case CIL_ROLETRANSITION: {
1132 struct cil_roletransition *roletrans = node->data;
1133 fprintf(out, "(roletransition ");
1134 fprintf(out, "%s ", datum_or_str(DATUM(roletrans->src), roletrans->src_str));
1135 fprintf(out, "%s ", datum_or_str(DATUM(roletrans->tgt), roletrans->tgt_str));
1136 fprintf(out, "%s ", datum_or_str(DATUM(roletrans->obj), roletrans->obj_str));
1137 fprintf(out, "%s", datum_or_str(DATUM(roletrans->result), roletrans->result_str));
1138 fprintf(out, ")\n");
1139 break;
1140 }
1141 case CIL_AVRULE: {
1142 struct cil_avrule *rule = node->data;
1143 if (rule->rule_kind == AVRULE_ALLOWED)
1144 fprintf(out, "(allow ");
1145 else if (rule->rule_kind == AVRULE_AUDITALLOW)
1146 fprintf(out, "(auditallow ");
1147 else if (rule->rule_kind == AVRULE_DONTAUDIT)
1148 fprintf(out, "(dontaudit ");
1149 else if (rule->rule_kind == AVRULE_NEVERALLOW)
1150 fprintf(out, "(neverallow ");
1151 else
1152 fprintf(out, "(<?AVRULE> ");
1153
1154 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1155 fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
1156 write_classperms_list(out, rule->perms.classperms);
1157 fprintf(out, ")\n");
1158 break;
1159 }
1160 case CIL_AVRULEX: {
1161 struct cil_avrule *rule = node->data;
1162 if (rule->rule_kind == AVRULE_ALLOWED)
1163 fprintf(out, "(allowx ");
1164 else if (rule->rule_kind == AVRULE_AUDITALLOW)
1165 fprintf(out, "(auditallowx ");
1166 else if (rule->rule_kind == AVRULE_DONTAUDIT)
1167 fprintf(out, "(dontauditx ");
1168 else if (rule->rule_kind == AVRULE_NEVERALLOW)
1169 fprintf(out, "(neverallowx ");
1170 else
1171 fprintf(out, "(<?AVRULEX> ");
1172 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1173 fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
1174 if (rule->perms.x.permx_str) {
1175 fprintf(out, "%s",rule->perms.x.permx_str);
1176 } else {
1177 write_permx(out, rule->perms.x.permx);
1178 }
1179 fprintf(out, ")\n");
1180 break;
1181 }
1182 case CIL_DENY_RULE: {
1183 struct cil_deny_rule *rule = node->data;
1184 fprintf(out, "(deny ");
1185
1186 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1187 fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
1188 write_classperms_list(out, rule->classperms);
1189 fprintf(out, ")\n");
1190 break;
1191 }
1192 case CIL_TYPE_RULE: {
1193 struct cil_type_rule *rule = node->data;
1194 if (rule->rule_kind == AVRULE_TRANSITION)
1195 fprintf(out, "(typetransition ");
1196 else if (rule->rule_kind == AVRULE_MEMBER)
1197 fprintf(out, "(typemember ");
1198 else if (rule->rule_kind == AVRULE_CHANGE)
1199 fprintf(out, "(typechange ");
1200 else
1201 fprintf(out, "(<?TYPERULE> ");
1202 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1203 fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
1204 fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
1205 fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str));
1206 fprintf(out, ")\n");
1207 break;
1208 }
1209 case CIL_NAMETYPETRANSITION: {
1210 struct cil_nametypetransition *rule = node->data;
1211 fprintf(out, "(typetransition ");
1212 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1213 fprintf(out, "%s ", datum_or_str(DATUM(rule->tgt), rule->tgt_str));
1214 fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
1215 if (rule->name) {
1216 fprintf(out, "\"%s\" ", DATUM(rule->name)->fqn);
1217 } else {
1218 fprintf(out, "%s ", rule->name_str);
1219 }
1220 fprintf(out, "%s", datum_or_str(DATUM(rule->result), rule->result_str));
1221 fprintf(out, ")\n");
1222 break;
1223 }
1224 case CIL_RANGETRANSITION: {
1225 struct cil_rangetransition *rule = node->data;
1226 fprintf(out, "(rangetransition ");
1227 fprintf(out, "%s ", datum_or_str(DATUM(rule->src), rule->src_str));
1228 fprintf(out, "%s ", datum_or_str(DATUM(rule->exec), rule->exec_str));
1229 fprintf(out, "%s ", datum_or_str(DATUM(rule->obj), rule->obj_str));
1230 if (rule->range)
1231 write_range(out, rule->range, CIL_TRUE);
1232 else
1233 fprintf(out, "%s", rule->range_str);
1234 fprintf(out, ")\n");
1235 break;
1236 }
1237 case CIL_CONSTRAIN: {
1238 struct cil_constrain *cons = node->data;
1239 fprintf(out, "(constrain ");
1240 write_constrain(out, cons);
1241 fprintf(out, ")\n");
1242 break;
1243 }
1244 case CIL_MLSCONSTRAIN: {
1245 struct cil_constrain *cons = node->data;
1246 fprintf(out, "(mlsconstrain ");
1247 write_constrain(out, cons);
1248 fprintf(out, ")\n");
1249 break;
1250 }
1251 case CIL_VALIDATETRANS: {
1252 struct cil_validatetrans *vt = node->data;
1253 fprintf(out, "(validatetrans ");
1254 fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str));
1255 if (vt->datum_expr)
1256 write_expr(out, vt->datum_expr);
1257 else
1258 write_expr(out, vt->str_expr);
1259 fprintf(out, ")\n");
1260 break;
1261 }
1262 case CIL_MLSVALIDATETRANS: {
1263 struct cil_validatetrans *vt = node->data;
1264 fprintf(out, "(mlsvalidatetrans ");
1265 fprintf(out, "%s ", datum_or_str(DATUM(vt->class), vt->class_str));
1266 if (vt->datum_expr)
1267 write_expr(out, vt->datum_expr);
1268 else
1269 write_expr(out, vt->str_expr);
1270 fprintf(out, ")\n");
1271 break;
1272 }
1273 case CIL_CONTEXT: {
1274 struct cil_context *context = node->data;
1275 fprintf(out, "(context %s ", datum_to_str(DATUM(context)));
1276 write_context(out, context, CIL_FALSE);
1277 fprintf(out, ")\n");
1278 break;
1279 }
1280 case CIL_FILECON: {
1281 struct cil_filecon *filecon = node->data;
1282 fprintf(out, "(filecon ");
1283 if (filecon->path) {
1284 fprintf(out, "\"%s\" ", DATUM(filecon->path)->fqn);
1285 } else {
1286 fprintf(out, "%s ", filecon->path_str);
1287 }
1288 switch (filecon->type) {
1289 case CIL_FILECON_ANY:
1290 fprintf(out, "%s ", CIL_KEY_ANY);
1291 break;
1292 case CIL_FILECON_FILE:
1293 fprintf(out, "%s ", CIL_KEY_FILE);
1294 break;
1295 case CIL_FILECON_DIR:
1296 fprintf(out, "%s ", CIL_KEY_DIR);
1297 break;
1298 case CIL_FILECON_CHAR:
1299 fprintf(out, "%s ", CIL_KEY_CHAR);
1300 break;
1301 case CIL_FILECON_BLOCK:
1302 fprintf(out, "%s ", CIL_KEY_BLOCK);
1303 break;
1304 case CIL_FILECON_SOCKET:
1305 fprintf(out, "%s ", CIL_KEY_SOCKET);
1306 break;
1307 case CIL_FILECON_PIPE:
1308 fprintf(out, "%s ", CIL_KEY_PIPE);
1309 break;
1310 case CIL_FILECON_SYMLINK:
1311 fprintf(out, "%s ", CIL_KEY_SYMLINK);
1312 break;
1313 default:
1314 fprintf(out, "<?FILETYPE> ");
1315 }
1316 if (filecon->context)
1317 write_context(out, filecon->context, CIL_TRUE);
1318 else if (filecon->context_str)
1319 fprintf(out, "%s", filecon->context_str);
1320 else
1321 fprintf(out, "()");
1322 fprintf(out, ")\n");
1323 break;
1324 }
1325 case CIL_IBPKEYCON: {
1326 struct cil_ibpkeycon *ibpkeycon = node->data;
1327 fprintf(out, "(ibpkeycon %s ", ibpkeycon->subnet_prefix_str);
1328 fprintf(out, "(%d %d) ", ibpkeycon->pkey_low, ibpkeycon->pkey_high);
1329 if (ibpkeycon->context)
1330 write_context(out, ibpkeycon->context, CIL_TRUE);
1331 else if (ibpkeycon->context_str)
1332 fprintf(out, "%s", ibpkeycon->context_str);
1333 fprintf(out, ")\n");
1334 break;
1335 }
1336 case CIL_PORTCON: {
1337 struct cil_portcon *portcon = node->data;
1338 fprintf(out, "(portcon ");
1339 if (portcon->proto == CIL_PROTOCOL_UDP)
1340 fprintf(out, " udp ");
1341 else if (portcon->proto == CIL_PROTOCOL_TCP)
1342 fprintf(out, " tcp ");
1343 else if (portcon->proto == CIL_PROTOCOL_DCCP)
1344 fprintf(out, "dccp ");
1345 else if (portcon->proto == CIL_PROTOCOL_SCTP)
1346 fprintf(out, "sctp ");
1347 else
1348 fprintf(out, "<?PROTOCOL> ");
1349 if (portcon->port_low == portcon->port_high)
1350 fprintf(out, "%d ", portcon->port_low);
1351 else
1352 fprintf(out, "(%d %d) ", portcon->port_low, portcon->port_high);
1353 if (portcon->context)
1354 write_context(out, portcon->context, CIL_TRUE);
1355 else
1356 fprintf(out, "%s", portcon->context_str);
1357 fprintf(out, ")\n");
1358 break;
1359 }
1360 case CIL_NODECON: {
1361 struct cil_nodecon *nodecon = node->data;
1362 fprintf(out, "(nodecon ");
1363 if (nodecon->addr)
1364 write_ipaddr(out, nodecon->addr);
1365 else
1366 fprintf(out, "%s ", nodecon->addr_str);
1367 fprintf(out, " ");
1368 if (nodecon->mask)
1369 write_ipaddr(out, nodecon->mask);
1370 else
1371 fprintf(out, "%s ", nodecon->mask_str);
1372 fprintf(out, " ");
1373 if (nodecon->context)
1374 write_context(out, nodecon->context, CIL_TRUE);
1375 else
1376 fprintf(out, "%s", nodecon->context_str);
1377 fprintf(out, ")\n");
1378 break;
1379 }
1380 case CIL_GENFSCON: {
1381 struct cil_genfscon *genfscon = node->data;
1382 fprintf(out, "(genfscon ");
1383 fprintf(out, "%s \"%s\" ", genfscon->fs_str, genfscon->path_str);
1384 if (genfscon->file_type != CIL_FILECON_ANY) {
1385 switch (genfscon->file_type) {
1386 case CIL_FILECON_FILE:
1387 fprintf(out, "%s ", CIL_KEY_FILE);
1388 break;
1389 case CIL_FILECON_DIR:
1390 fprintf(out, "%s ", CIL_KEY_DIR);
1391 break;
1392 case CIL_FILECON_CHAR:
1393 fprintf(out, "%s ", CIL_KEY_CHAR);
1394 break;
1395 case CIL_FILECON_BLOCK:
1396 fprintf(out, "%s ", CIL_KEY_BLOCK);
1397 break;
1398 case CIL_FILECON_SOCKET:
1399 fprintf(out, "%s ", CIL_KEY_SOCKET);
1400 break;
1401 case CIL_FILECON_PIPE:
1402 fprintf(out, "%s ", CIL_KEY_PIPE);
1403 break;
1404 case CIL_FILECON_SYMLINK:
1405 fprintf(out, "%s ", CIL_KEY_SYMLINK);
1406 break;
1407 default:
1408 fprintf(out, "<?FILETYPE> ");
1409 }
1410 }
1411 if (genfscon->context)
1412 write_context(out, genfscon->context, CIL_TRUE);
1413 else
1414 fprintf(out, "%s", genfscon->context_str);
1415 fprintf(out, ")\n");
1416 break;
1417 }
1418 case CIL_NETIFCON: {
1419 struct cil_netifcon *netifcon = node->data;
1420 fprintf(out, "(netifcon %s ", netifcon->interface_str);
1421 if (netifcon->if_context)
1422 write_context(out, netifcon->if_context, CIL_TRUE);
1423 else
1424 fprintf(out, "%s", netifcon->if_context_str);
1425 fprintf(out, " ");
1426 if (netifcon->packet_context)
1427 write_context(out, netifcon->packet_context, CIL_TRUE);
1428 else
1429 fprintf(out, "%s", netifcon->packet_context_str);
1430 fprintf(out, ")\n");
1431 break;
1432 }
1433 case CIL_IBENDPORTCON: {
1434 struct cil_ibendportcon *ibendportcon = node->data;
1435 fprintf(out, "(ibendportcon %s %u ", ibendportcon->dev_name_str, ibendportcon->port);
1436 if (ibendportcon->context)
1437 write_context(out, ibendportcon->context, CIL_TRUE);
1438 else
1439 fprintf(out, "%s", ibendportcon->context_str);
1440 fprintf(out, ")\n");
1441 break;
1442 }
1443 case CIL_PIRQCON: {
1444 struct cil_pirqcon *pirqcon = node->data;
1445 fprintf(out, "(pirqcon %d ", pirqcon->pirq);
1446 if (pirqcon->context)
1447 write_context(out, pirqcon->context, CIL_TRUE);
1448 else
1449 fprintf(out, "%s", pirqcon->context_str);
1450 fprintf(out, ")\n");
1451 break;
1452 }
1453 case CIL_IOMEMCON: {
1454 struct cil_iomemcon *iomemcon = node->data;
1455 fprintf(out, "(iomemcon (%"PRId64" %"PRId64") ", iomemcon->iomem_low, iomemcon->iomem_high);
1456 if (iomemcon->context)
1457 write_context(out, iomemcon->context, CIL_TRUE);
1458 else
1459 fprintf(out, "%s", iomemcon->context_str);
1460 fprintf(out, ")\n");
1461 break;
1462 }
1463 case CIL_IOPORTCON: {
1464 struct cil_ioportcon *ioportcon = node->data;
1465 fprintf(out, "(ioportcon ");
1466 if (ioportcon->ioport_low == ioportcon->ioport_high)
1467 fprintf(out, "%d ", ioportcon->ioport_low);
1468 else
1469 fprintf(out, "(%d %d) ", ioportcon->ioport_low, ioportcon->ioport_high);
1470
1471 if (ioportcon->context)
1472 write_context(out, ioportcon->context, CIL_TRUE);
1473 else
1474 fprintf(out, "%s", ioportcon->context_str);
1475 fprintf(out, ")\n");
1476 break;
1477 }
1478 case CIL_PCIDEVICECON: {
1479 struct cil_pcidevicecon *pcidevicecon = node->data;
1480 fprintf(out, "(pcidevicecon %d ", pcidevicecon->dev);
1481 if (pcidevicecon->context)
1482 write_context(out, pcidevicecon->context, CIL_TRUE);
1483 else
1484 fprintf(out, "%s", pcidevicecon->context_str);
1485 fprintf(out, ")\n");
1486 break;
1487 }
1488 case CIL_DEVICETREECON: {
1489 struct cil_devicetreecon *devicetreecon = node->data;
1490 fprintf(out, "(devicetreecon \"%s\" ", devicetreecon->path);
1491 if (devicetreecon->context)
1492 write_context(out, devicetreecon->context, CIL_TRUE);
1493 else
1494 fprintf(out, "%s", devicetreecon->context_str);
1495 fprintf(out, ")\n");
1496 break;
1497 }
1498 case CIL_FSUSE: {
1499 struct cil_fsuse *fsuse = node->data;
1500 fprintf(out, "(fsuse ");
1501 if (fsuse->type == CIL_FSUSE_XATTR)
1502 fprintf(out, "xattr ");
1503 else if (fsuse->type == CIL_FSUSE_TASK)
1504 fprintf(out, "task ");
1505 else if (fsuse->type == CIL_FSUSE_TRANS)
1506 fprintf(out, "trans ");
1507 else
1508 fprintf(out, "<?TYPE> ");
1509 fprintf(out, "%s ", fsuse->fs_str);
1510 if (fsuse->context)
1511 write_context(out, fsuse->context, CIL_TRUE);
1512 else
1513 fprintf(out, "%s", fsuse->context_str);
1514 fprintf(out, ")\n");
1515 break;
1516 }
1517 case CIL_POLICYCAP: {
1518 struct cil_policycap *polcap = node->data;
1519 fprintf(out, "(policycap %s)\n", polcap->datum.name);
1520 break;
1521 }
1522 case CIL_IPADDR: {
1523 struct cil_ipaddr *ipaddr = node->data;
1524 char buf[256];
1525 if (inet_ntop(ipaddr->family, &ipaddr->ip, buf, 256) == NULL)
1526 strcpy(buf, "<?IPADDR>");
1527 fprintf(out, "(ipaddr %s %s)\n", datum_to_str(&ipaddr->datum), buf);
1528 break;
1529 }
1530 default :
1531 fprintf(out, "(<?RULE:%s>)\n", cil_node_to_string(node));
1532 break;
1533 }
1534 }
1535
1536 /*
1537 * Tree walk data and helper functions for writing the AST of the various phases
1538 */
1539
1540 struct cil_write_ast_args {
1541 FILE *out;
1542 int depth;
1543 };
1544
1545 /*
1546 * Helper functions for writing the parse AST
1547 */
1548
__write_parse_ast_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1549 static int __write_parse_ast_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
1550 {
1551 struct cil_write_ast_args *args = extra_args;
1552
1553 fprintf(args->out, "%*s", args->depth*4, "");
1554 if (!node->data) {
1555 if (node->cl_head)
1556 fprintf(args->out, "(\n");
1557 else
1558 fprintf(args->out, "()\n");
1559 } else {
1560 char *str = (char *)node->data;
1561 size_t len = strlen(str);
1562 size_t i;
1563
1564 for (i = 0; i < len; i++) {
1565 if (isspace(str[i])) {
1566 fprintf(args->out, "\"%s\"\n", str);
1567 return SEPOL_OK;
1568 }
1569 }
1570
1571 fprintf(args->out, "%s\n", (char *)node->data);
1572 }
1573
1574 return SEPOL_OK;
1575 }
1576
__write_parse_ast_first_child_helper(struct cil_tree_node * node,void * extra_args)1577 static int __write_parse_ast_first_child_helper(struct cil_tree_node *node, void *extra_args)
1578 {
1579 struct cil_write_ast_args *args = extra_args;
1580 struct cil_tree_node *parent = node->parent;
1581
1582 if (parent->flavor != CIL_ROOT) {
1583 args->depth++;
1584 }
1585
1586 return SEPOL_OK;
1587 }
1588
__write_parse_ast_last_child_helper(struct cil_tree_node * node,void * extra_args)1589 static int __write_parse_ast_last_child_helper(struct cil_tree_node *node, void *extra_args)
1590 {
1591 struct cil_write_ast_args *args = extra_args;
1592 struct cil_tree_node *parent = node->parent;
1593
1594 if (parent->flavor == CIL_ROOT) {
1595 return SEPOL_OK;
1596 }
1597
1598 args->depth--;
1599 fprintf(args->out, "%*s", args->depth*4, "");
1600 fprintf(args->out, ")\n");
1601
1602 return SEPOL_OK;
1603 }
1604
1605 /*
1606 * Helper functions for writing the CIL AST for the build and resolve phases
1607 */
1608
__write_cil_ast_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1609 static int __write_cil_ast_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1610 {
1611 struct cil_write_ast_args *args = extra_args;
1612
1613 if (node->flavor == CIL_SRC_INFO) {
1614 cil_write_src_info_node(args->out, node);
1615 return SEPOL_OK;
1616 }
1617
1618 fprintf(args->out, "%*s", args->depth*4, "");
1619
1620 cil_write_ast_node(args->out, node);
1621
1622 if (node->flavor == CIL_CLASS || node->flavor == CIL_COMMON || node->flavor == CIL_MAP_CLASS) {
1623 *finished = CIL_TREE_SKIP_HEAD;
1624 }
1625
1626 return SEPOL_OK;
1627 }
1628
__write_cil_ast_first_child_helper(struct cil_tree_node * node,void * extra_args)1629 static int __write_cil_ast_first_child_helper(struct cil_tree_node *node, void *extra_args)
1630 {
1631 struct cil_write_ast_args *args = extra_args;
1632 struct cil_tree_node *parent = node->parent;
1633
1634 if (parent->flavor != CIL_SRC_INFO && parent->flavor != CIL_ROOT) {
1635 args->depth++;
1636 }
1637
1638 return SEPOL_OK;
1639 }
1640
__write_cil_ast_last_child_helper(struct cil_tree_node * node,void * extra_args)1641 static int __write_cil_ast_last_child_helper(struct cil_tree_node *node, void *extra_args)
1642 {
1643 struct cil_write_ast_args *args = extra_args;
1644 struct cil_tree_node *parent = node->parent;
1645
1646 if (parent->flavor == CIL_ROOT) {
1647 return SEPOL_OK;
1648 } else if (parent->flavor == CIL_SRC_INFO) {
1649 fprintf(args->out, ";;* lme\n");
1650 return SEPOL_OK;
1651 }
1652
1653 args->depth--;
1654 fprintf(args->out, "%*s", args->depth*4, "");
1655 fprintf(args->out, ")\n");
1656
1657 return SEPOL_OK;
1658 }
1659
cil_write_ast(FILE * out,enum cil_write_ast_phase phase,struct cil_tree_node * node)1660 int cil_write_ast(FILE *out, enum cil_write_ast_phase phase, struct cil_tree_node *node)
1661 {
1662 struct cil_write_ast_args extra_args;
1663 int rc;
1664
1665 extra_args.out = out;
1666 extra_args.depth = 0;
1667
1668 if (phase == CIL_WRITE_AST_PHASE_PARSE) {
1669 rc = cil_tree_walk(node, __write_parse_ast_node_helper, __write_parse_ast_first_child_helper, __write_parse_ast_last_child_helper, &extra_args);
1670 } else {
1671 rc = cil_tree_walk(node, __write_cil_ast_node_helper, __write_cil_ast_first_child_helper, __write_cil_ast_last_child_helper, &extra_args);
1672 }
1673
1674 if (rc != SEPOL_OK) {
1675 cil_log(CIL_ERR, "Failed to write AST\n");
1676 return SEPOL_ERR;
1677 }
1678
1679 return SEPOL_OK;
1680 }
1681