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