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