• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2011 Tresys Technology, LLC. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are met:
6  *
7  *    1. Redistributions of source code must retain the above copyright notice,
8  *       this list of conditions and the following disclaimer.
9  *
10  *    2. Redistributions in binary form must reproduce the above copyright notice,
11  *       this list of conditions and the following disclaimer in the documentation
12  *       and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY TRESYS TECHNOLOGY, LLC ``AS IS'' AND ANY EXPRESS
15  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
16  * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
17  * EVENT SHALL TRESYS TECHNOLOGY, LLC OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
18  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
19  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
20  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
21  * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
22  * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
23  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  *
25  * The views and conclusions contained in the software and documentation are those
26  * of the authors and should not be interpreted as representing official policies,
27  * either expressed or implied, of Tresys Technology, LLC.
28  */
29 
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdint.h>
34 #include <unistd.h>
35 #include <inttypes.h>
36 
37 #include <sepol/policydb/conditional.h>
38 #include <sepol/errcodes.h>
39 
40 #include "cil_internal.h"
41 #include "cil_flavor.h"
42 #include "cil_find.h"
43 #include "cil_mem.h"
44 #include "cil_tree.h"
45 #include "cil_list.h"
46 #include "cil_symtab.h"
47 
48 
49 enum cil_statement_list {
50 	CIL_LIST_COMMON = 1,
51 	CIL_LIST_DEFAULT_USER,
52 	CIL_LIST_DEFAULT_ROLE,
53 	CIL_LIST_DEFAULT_TYPE,
54 	CIL_LIST_DEFAULT_RANGE,
55 	CIL_LIST_SENSALIAS,
56 	CIL_LIST_CATALIAS,
57 	CIL_LIST_MLSCONSTRAIN,
58 	CIL_LIST_MLSVALIDATETRANS,
59 	CIL_LIST_POLICYCAP,
60 	CIL_LIST_TYPEATTRIBUTE,
61 	CIL_LIST_ROLEATTRIBUTE,
62 	CIL_LIST_BOOL,
63 	CIL_LIST_TYPE,
64 	CIL_LIST_TYPEALIAS,
65 	CIL_LIST_ROLE,
66 	CIL_LIST_ROLEALLOW,
67 	CIL_LIST_ROLETRANSITION,
68 	CIL_LIST_USER,
69 	CIL_LIST_CONSTRAINT,
70 	CIL_LIST_VALIDATETRANS,
71 	CIL_LIST_NUM_LISTS
72 };
73 
__cil_gather_statements_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)74 static int __cil_gather_statements_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
75 {
76 	struct cil_list **lists;
77 	int kind = 0;
78 
79 	lists = (struct cil_list **)extra_args;
80 
81 	switch (node->flavor) {
82 	case CIL_BLOCK: {
83 		struct cil_block *blk = node->data;
84 		if (blk->is_abstract == CIL_TRUE) {
85 			*finished = CIL_TREE_SKIP_HEAD;
86 		}
87 		break;
88 	}
89 	case CIL_MACRO:
90 		*finished = CIL_TREE_SKIP_HEAD;
91 		break;
92 	case CIL_BOOLEANIF:
93 		*finished = CIL_TREE_SKIP_HEAD;
94 		break;
95 	case CIL_COMMON:
96 		kind = CIL_LIST_COMMON;
97 		break;
98 	case CIL_DEFAULTUSER:
99 		kind = CIL_LIST_DEFAULT_USER;
100 		break;
101 	case CIL_DEFAULTROLE:
102 		kind = CIL_LIST_DEFAULT_ROLE;
103 		break;
104 	case CIL_DEFAULTTYPE:
105 		kind = CIL_LIST_DEFAULT_TYPE;
106 		break;
107 	case CIL_DEFAULTRANGE:
108 		kind = CIL_LIST_DEFAULT_RANGE;
109 		break;
110 	case CIL_SENSALIAS:
111 		kind = CIL_LIST_SENSALIAS;
112 		break;
113 	case CIL_CATALIAS:
114 		kind = CIL_LIST_CATALIAS;
115 		break;
116 	case CIL_MLSCONSTRAIN:
117 		kind = CIL_LIST_MLSCONSTRAIN;
118 		break;
119 	case CIL_MLSVALIDATETRANS:
120 		kind = CIL_LIST_MLSVALIDATETRANS;
121 		break;
122 	case CIL_POLICYCAP:
123 		kind = CIL_LIST_POLICYCAP;
124 		break;
125 	case CIL_TYPEATTRIBUTE: {
126 		struct cil_typeattribute *attr = node->data;
127 		if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) {
128 			kind = CIL_LIST_TYPEATTRIBUTE;
129 		}
130 		break;
131 	}
132 	case CIL_ROLEATTRIBUTE: {
133 		struct cil_roleattribute *attr = node->data;
134 		if (strcmp(attr->datum.fqn, "cil_gen_require") != 0) {
135 			kind = CIL_LIST_ROLEATTRIBUTE;
136 		}
137 		break;
138 	}
139 	case CIL_BOOL:
140 		kind = CIL_LIST_BOOL;
141 		break;
142 	case CIL_TYPE:
143 		kind = CIL_LIST_TYPE;
144 		break;
145 	case CIL_TYPEALIAS:
146 		kind = CIL_LIST_TYPEALIAS;
147 		break;
148 	case CIL_ROLE: {
149 		struct cil_role *role = node->data;
150 		if (strcmp(role->datum.fqn, "object_r") != 0) {
151 			kind = CIL_LIST_ROLE;
152 		}
153 		break;
154 	}
155 	case CIL_ROLEALLOW:
156 		kind = CIL_LIST_ROLEALLOW;
157 		break;
158 	case CIL_ROLETRANSITION:
159 		kind = CIL_LIST_ROLETRANSITION;
160 		break;
161 	case CIL_USER:
162 		kind = CIL_LIST_USER;
163 		break;
164 	case CIL_CONSTRAIN:
165 		kind = CIL_LIST_CONSTRAINT;
166 		break;
167 	case CIL_VALIDATETRANS:
168 		kind = CIL_LIST_VALIDATETRANS;
169 		break;
170 	default:
171 		break;
172 	}
173 
174 	if (kind > 0) {
175 		cil_list_append(lists[kind], node->flavor, node->data);
176 	}
177 
178 	return SEPOL_OK;
179 }
180 
cil_gather_statements(struct cil_tree_node * start,struct cil_list * lists[])181 static void cil_gather_statements(struct cil_tree_node *start, struct cil_list *lists[])
182 {
183 	cil_tree_walk(start, __cil_gather_statements_helper, NULL, NULL, lists);
184 }
185 
cil_simple_rules_to_policy(FILE * out,struct cil_list * rules,const char * kind)186 static void cil_simple_rules_to_policy(FILE *out, struct cil_list *rules, const char *kind)
187 {
188 	struct cil_list_item *i1;
189 
190 	cil_list_for_each(i1, rules) {
191 		fprintf(out, "%s %s;\n", kind, DATUM(i1->data)->fqn);
192 	}
193 }
194 
cil_cats_to_policy(FILE * out,struct cil_cats * cats)195 static void cil_cats_to_policy(FILE *out, struct cil_cats *cats)
196 {
197 	const char *lead = "";
198 	struct cil_cat *first = NULL, *last = NULL, *cat;
199 	struct cil_list_item *i1;
200 
201 	cil_list_for_each(i1, cats->datum_expr) {
202 		cat = i1->data;
203 		if (first == NULL) {
204 			first = cat;
205 		} else if (last == NULL) {
206 			if (cat->value == first->value + 1) {
207 				last = cat;
208 			} else {
209 				fprintf(out, "%s%s", lead, DATUM(first)->fqn);
210 				lead = ",";
211 				first = cat;
212 			}
213 		} else if (cat->value == last->value + 1) {
214 			last = cat;
215 		} else {
216 			fprintf(out, "%s%s", lead, DATUM(first)->fqn);
217 			lead = ",";
218 			if (last->value >= first->value + 1) {
219 				fprintf(out, ".");
220 			} else {
221 				fprintf(out, ",");
222 			}
223 			fprintf(out, "%s", DATUM(last)->fqn);
224 			first = cat;
225 			last = NULL;
226 		}
227 	}
228 	if (first) {
229 		fprintf(out, "%s%s", lead, DATUM(first)->fqn);
230 		if (last != NULL) {
231 			if (last->value >= first->value + 1) {
232 				fprintf(out, ".");
233 			} else {
234 				fprintf(out, ",");
235 			}
236 			fprintf(out, "%s", DATUM(last)->fqn);
237 		}
238 	}
239 }
240 
cil_level_to_policy(FILE * out,struct cil_level * level)241 static void cil_level_to_policy(FILE *out, struct cil_level *level)
242 {
243 	fprintf(out, "%s", DATUM(level->sens)->fqn);
244 	if (level->cats != NULL) {
245 		fprintf(out, ":");
246 		cil_cats_to_policy(out, level->cats);
247 	}
248 }
249 
cil_levels_simple_and_equal(struct cil_level * l1,struct cil_level * l2)250 static int cil_levels_simple_and_equal(struct cil_level *l1, struct cil_level *l2)
251 {
252 	/* Mostly just want to detect s0 - s0 ranges */
253 	if (l1 == l2)
254 		return CIL_TRUE;
255 
256 	if (l1->sens == l2->sens && (l1->cats == NULL && l2->cats == NULL))
257 		return CIL_TRUE;
258 
259 	return CIL_FALSE;
260 }
261 
cil_levelrange_to_policy(FILE * out,struct cil_levelrange * lvlrange)262 static void cil_levelrange_to_policy(FILE *out, struct cil_levelrange *lvlrange)
263 {
264 	cil_level_to_policy(out, lvlrange->low);
265 	if (cil_levels_simple_and_equal(lvlrange->low, lvlrange->high) == CIL_FALSE) {
266 		fprintf(out, " - ");
267 		cil_level_to_policy(out, lvlrange->high);
268 	}
269 }
270 
cil_context_to_policy(FILE * out,struct cil_context * context,int mls)271 static void cil_context_to_policy(FILE *out, struct cil_context *context, int mls)
272 {
273 	fprintf(out, "%s:", DATUM(context->user)->fqn);
274 	fprintf(out, "%s:", DATUM(context->role)->fqn);
275 	fprintf(out, "%s", DATUM(context->type)->fqn);
276 	if (mls) {
277 		fprintf(out, ":");
278 		cil_levelrange_to_policy(out, context->range);
279 	}
280 }
281 
cil_cond_expr_to_policy(FILE * out,struct cil_list * expr,int first)282 static void cil_cond_expr_to_policy(FILE *out, struct cil_list *expr, int first)
283 {
284 	struct cil_list_item *i1 = expr->head;
285 
286 	if (i1->flavor == CIL_OP) {
287 		enum cil_flavor op = (enum cil_flavor)i1->data;
288 		fprintf(out, "(");
289 		switch (op) {
290 		case CIL_NOT:
291 			fprintf(out, "! ");
292 			cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
293 			break;
294 		case CIL_OR:
295 			cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
296 			fprintf(out, " || ");
297 			cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
298 			break;
299 		case CIL_AND:
300 			cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
301 			fprintf(out, " && ");
302 			cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
303 			break;
304 		case CIL_XOR:
305 			cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
306 			fprintf(out, " ^ ");
307 			cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
308 			break;
309 		case CIL_EQ:
310 			cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
311 			fprintf(out, " == ");
312 			cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
313 			break;
314 		case CIL_NEQ:
315 			cil_cond_expr_to_policy(out, i1->next->data, CIL_FALSE);
316 			fprintf(out, " != ");
317 			cil_cond_expr_to_policy(out, i1->next->next->data, CIL_FALSE);
318 			break;
319 		default:
320 			fprintf(out, "???");
321 			break;
322 		}
323 		fprintf(out, ")");
324 	} else if (i1->flavor == CIL_DATUM) {
325 		if (first == CIL_TRUE) {
326 			fprintf(out, "(");
327 		}
328 		fprintf(out, "%s", DATUM(i1->data)->fqn);
329 		if (first == CIL_TRUE) {
330 			fprintf(out, ")");
331 		}
332 	} else if (i1->flavor == CIL_LIST) {
333 		cil_cond_expr_to_policy(out, i1->data, CIL_FALSE);
334 	} else {
335 		fprintf(out, "???");
336 	}
337 }
338 
__cil_userattribute_len(struct cil_db * db,struct cil_userattribute * attr)339 static size_t __cil_userattribute_len(struct cil_db *db, struct cil_userattribute *attr)
340 {
341 	ebitmap_node_t *unode;
342 	unsigned int i;
343 	size_t len = 0;
344 
345 	ebitmap_for_each_bit(attr->users, unode, i) {
346 		if (!ebitmap_get_bit(attr->users, i))
347 			continue;
348 		len += strlen(DATUM(db->val_to_user[i])->fqn);
349 		len++;
350 	}
351 
352 	return len;
353 }
354 
__cil_cons_leaf_operand_len(struct cil_db * db,struct cil_list_item * operand)355 static size_t __cil_cons_leaf_operand_len(struct cil_db *db, struct cil_list_item *operand)
356 {
357 	struct cil_list_item *i1;
358 	enum cil_flavor flavor = operand->flavor;
359 	size_t len = 0;
360 
361 	if (flavor == CIL_CONS_OPERAND) {
362 		len = 2;
363 	} else if (flavor == CIL_DATUM) {
364 		struct cil_tree_node *node = NODE(operand->data);
365 		if (node->flavor == CIL_USERATTRIBUTE) {
366 			len = __cil_userattribute_len(db, operand->data);
367 			len++; /* "{" */
368 		} else {
369 			len = strlen(DATUM(operand->data)->fqn);
370 		}
371 	} else if (flavor == CIL_LIST) {
372 		len = 1; /* "{" */
373 		cil_list_for_each(i1, (struct cil_list *)operand->data) {
374 			struct cil_tree_node *node = NODE(operand->data);
375 			if (node->flavor == CIL_USERATTRIBUTE) {
376 				len = __cil_userattribute_len(db, operand->data);
377 			} else {
378 				len += strlen(DATUM(operand->data)->fqn);
379 				len++; /* " " or "}" */
380 			}
381 		}
382 	}
383 
384 	return len;
385 }
386 
__cil_cons_leaf_op_len(struct cil_list_item * op)387 static size_t __cil_cons_leaf_op_len(struct cil_list_item *op)
388 {
389 	enum cil_flavor flavor = (enum cil_flavor)op->data;
390 	size_t len;
391 
392 	switch (flavor) {
393 	case CIL_EQ:
394 		len = 4; /* " == " */
395 		break;
396 	case CIL_NEQ:
397 		len = 4; /* " != " */
398 		break;
399 	case CIL_CONS_DOM:
400 		len = 5; /* " dom " */
401 		break;
402 	case CIL_CONS_DOMBY:
403 		len = 7; /* " domby " */
404 		break;
405 	case CIL_CONS_INCOMP:
406 		len = 8; /* " incomp " */
407 		break;
408 	default:
409 		/* Should be impossible to be here */
410 		len = 5; /* " ??? " */
411 	}
412 
413 	return len;
414 }
415 
cil_cons_expr_len(struct cil_db * db,struct cil_list * cons_expr)416 static size_t cil_cons_expr_len(struct cil_db *db, struct cil_list *cons_expr)
417 {
418 	struct cil_list_item *i1;
419 	enum cil_flavor op;
420 	size_t len;
421 
422 	i1 = cons_expr->head;
423 
424 	op = (enum cil_flavor)i1->data;
425 	switch (op) {
426 	case CIL_NOT:
427 		len = 6; /* "(not )" */
428 		len += cil_cons_expr_len(db, i1->next->data);
429 		break;
430 	case CIL_AND:
431 		len = 7; /* "( and )" */
432 		len += cil_cons_expr_len(db, i1->next->data);
433 		len += cil_cons_expr_len(db, i1->next->next->data);
434 		break;
435 	case CIL_OR:
436 		len = 6; /* "( or )" */
437 		len += cil_cons_expr_len(db, i1->next->data);
438 		len += cil_cons_expr_len(db, i1->next->next->data);
439 		break;
440 	default:
441 		len = 2; /* "()" */
442 		len += __cil_cons_leaf_operand_len(db, i1->next);
443 		len += __cil_cons_leaf_op_len(i1);
444 		len += __cil_cons_leaf_operand_len(db, i1->next->next);
445 	}
446 
447 	return len;
448 }
449 
__cil_userattribute_to_string(struct cil_db * db,struct cil_userattribute * attr,char * new)450 static char *__cil_userattribute_to_string(struct cil_db *db, struct cil_userattribute *attr, char *new)
451 {
452 	ebitmap_node_t *unode;
453 	unsigned int i;
454 	char *str;
455 	size_t len;
456 
457 	ebitmap_for_each_bit(attr->users, unode, i) {
458 		if (!ebitmap_get_bit(attr->users, i))
459 			continue;
460 		str = DATUM(db->val_to_user[i])->fqn;
461 		len = strlen(str);
462 		memcpy(new, str, len);
463 		new += len;
464 		*new++ = ' ';
465 	}
466 
467 	return new;
468 }
469 
__cil_cons_leaf_operand_to_string(struct cil_db * db,struct cil_list_item * operand,char * new)470 static char *__cil_cons_leaf_operand_to_string(struct cil_db *db, struct cil_list_item *operand, char *new)
471 {
472 	struct cil_list_item *i1;
473 	enum cil_flavor flavor = operand->flavor;
474 	const char *o_str;
475 	size_t o_len;
476 
477 	if (flavor == CIL_CONS_OPERAND) {
478 		enum cil_flavor o_flavor = (enum cil_flavor)operand->data;
479 		switch (o_flavor) {
480 		case CIL_CONS_U1:
481 			o_str = "u1";
482 			break;
483 		case CIL_CONS_U2:
484 			o_str = "u2";
485 			break;
486 		case CIL_CONS_U3:
487 			o_str = "u3";
488 			break;
489 		case CIL_CONS_R1:
490 			o_str = "r1";
491 			break;
492 		case CIL_CONS_R2:
493 			o_str = "r2";
494 			break;
495 		case CIL_CONS_R3:
496 			o_str = "r3";
497 			break;
498 		case CIL_CONS_T1:
499 			o_str = "t1";
500 			break;
501 		case CIL_CONS_T2:
502 			o_str = "t2";
503 			break;
504 		case CIL_CONS_T3:
505 			o_str = "t3";
506 			break;
507 		case CIL_CONS_L1:
508 			o_str = "l1";
509 			break;
510 		case CIL_CONS_L2:
511 			o_str = "l2";
512 			break;
513 		case CIL_CONS_H1:
514 			o_str = "h1";
515 			break;
516 		case CIL_CONS_H2:
517 			o_str = "h2";
518 			break;
519 		default:
520 			/* Impossible */
521 			o_str = "??";
522 		}
523 		strcpy(new, o_str);
524 		new += 2;
525 	} else if (flavor == CIL_DATUM) {
526 		struct cil_tree_node *node = NODE(operand->data);
527 		if (node->flavor == CIL_USERATTRIBUTE) {
528 			*new++ = '{';
529 			new = __cil_userattribute_to_string(db, operand->data, new);
530 			new--;
531 			*new++ = '}';
532 		} else {
533 			o_str = DATUM(operand->data)->fqn;
534 			o_len = strlen(o_str);
535 			memcpy(new, o_str, o_len);
536 			new += o_len;
537 		}
538 	} else if (flavor == CIL_LIST) {
539 		*new++ = '{';
540 		cil_list_for_each(i1, (struct cil_list *)operand->data) {
541 			struct cil_tree_node *node = NODE(operand->data);
542 			if (node->flavor == CIL_USERATTRIBUTE) {
543 				new = __cil_userattribute_to_string(db, operand->data, new);
544 			} else {
545 				o_str = DATUM(operand->data)->fqn;
546 				o_len = strlen(o_str);
547 				memcpy(new, o_str, o_len);
548 				new += o_len;
549 				*new++ = ' ';
550 			}
551 		}
552 		new--;
553 		*new++ = '}';
554 	}
555 
556 	return new;
557 }
558 
__cil_cons_leaf_op_to_string(struct cil_list_item * op,char * new)559 static char *__cil_cons_leaf_op_to_string(struct cil_list_item *op, char *new)
560 {
561 	enum cil_flavor flavor = (enum cil_flavor)op->data;
562 	const char *op_str;
563 	size_t len;
564 
565 	switch (flavor) {
566 	case CIL_EQ:
567 		op_str = " == ";
568 		len = 4;
569 		break;
570 	case CIL_NEQ:
571 		op_str = " != ";
572 		len = 4;
573 		break;
574 	case CIL_CONS_DOM:
575 		op_str = " dom ";
576 		len = 5;
577 		break;
578 	case CIL_CONS_DOMBY:
579 		op_str = " domby ";
580 		len = 7;
581 		break;
582 	case CIL_CONS_INCOMP:
583 		op_str = " incomp ";
584 		len = 8;
585 		break;
586 	default:
587 		/* Should be impossible to be here */
588 		op_str = " ??? ";
589 		len = 5;
590 	}
591 
592 	strcpy(new, op_str);
593 	new += len;
594 
595 	return new;
596 }
597 
__cil_cons_expr_to_string(struct cil_db * db,struct cil_list * cons_expr,char * new)598 static char *__cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr, char *new)
599 {
600 	struct cil_list_item *i1;
601 	enum cil_flavor op;
602 
603 	i1 = cons_expr->head;
604 
605 	op = (enum cil_flavor)i1->data;
606 	switch (op) {
607 	case CIL_NOT:
608 		*new++ = '(';
609 		strcpy(new, "not ");
610 		new += 4;
611 		new = __cil_cons_expr_to_string(db, i1->next->data, new);
612 		*new++ = ')';
613 		break;
614 	case CIL_AND:
615 		*new++ = '(';
616 		new = __cil_cons_expr_to_string(db, i1->next->data, new);
617 		strcpy(new, " and ");
618 		new += 5;
619 		new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
620 		*new++ = ')';
621 		break;
622 	case CIL_OR:
623 		*new++ = '(';
624 		new = __cil_cons_expr_to_string(db, i1->next->data, new);
625 		strcpy(new, " or ");
626 		new += 4;
627 		new = __cil_cons_expr_to_string(db, i1->next->next->data, new);
628 		*new++ = ')';
629 		break;
630 	default:
631 		*new++ = '(';
632 		new = __cil_cons_leaf_operand_to_string(db, i1->next, new);
633 		new = __cil_cons_leaf_op_to_string(i1, new);
634 		new = __cil_cons_leaf_operand_to_string(db, i1->next->next, new);
635 		*new++ = ')';
636 	}
637 
638 	return new;
639 }
640 
cil_cons_expr_to_string(struct cil_db * db,struct cil_list * cons_expr)641 static char *cil_cons_expr_to_string(struct cil_db *db, struct cil_list *cons_expr)
642 {
643 	char *new, *tail;
644 	size_t len = cil_cons_expr_len(db, cons_expr);
645 
646 	new = cil_malloc(len+1);
647 	tail = __cil_cons_expr_to_string(db, cons_expr, new);
648 	*tail = '\0';
649 
650 	return new;
651 }
652 
cil_classperms_to_string(struct cil_classperms * classperms,struct cil_list * classperms_strs)653 static void cil_classperms_to_string(struct cil_classperms *classperms, struct cil_list *classperms_strs)
654 {
655 	struct cil_list_item *i1;
656 	size_t len = 0;
657 	char *new, *curr;
658 
659 	len += strlen(DATUM(classperms->class)->fqn) + 1;
660 	cil_list_for_each(i1, classperms->perms) {
661 		len += strlen(DATUM(i1->data)->fqn) + 1;
662 	}
663 	len += 4; /* for "{ " and " }" */
664 
665 	new = cil_malloc(len);
666 	curr = new;
667 
668 	curr[len-1] = '\0';
669 
670 	len = strlen(DATUM(classperms->class)->fqn);
671 	memcpy(curr, DATUM(classperms->class)->fqn, len);
672 	curr += len;
673 	*curr++ = ' ';
674 
675 	*curr++ = '{';
676 	*curr++ = ' ';
677 	cil_list_for_each(i1, classperms->perms) {
678 		len = strlen(DATUM(i1->data)->fqn);
679 		memcpy(curr, DATUM(i1->data)->fqn, len);
680 		curr += len;
681 		*curr++ = ' ';
682 	}
683 	*curr++ = '}';
684 
685 	cil_list_append(classperms_strs, CIL_STRING, new);
686 }
687 
cil_classperms_to_strings(struct cil_list * classperms,struct cil_list * classperms_strs)688 static void cil_classperms_to_strings(struct cil_list *classperms, struct cil_list *classperms_strs)
689 {
690 	struct cil_list_item *i1;
691 
692 	cil_list_for_each(i1, classperms) {
693 		if (i1->flavor == CIL_CLASSPERMS) {
694 			struct cil_classperms *cp = i1->data;
695 			if (FLAVOR(cp->class) == CIL_CLASS) {
696 				cil_classperms_to_string(cp, classperms_strs);
697 			} else { /* MAP */
698 				struct cil_list_item *i2 = NULL;
699 				cil_list_for_each(i2, cp->perms) {
700 					struct cil_perm *cmp = i2->data;
701 					cil_classperms_to_strings(cmp->classperms, classperms_strs);
702 				}
703 			}
704 		} else { /* SET */
705 			struct cil_classperms_set *cp_set = i1->data;
706 			struct cil_classpermission *cp = cp_set->set;
707 			cil_classperms_to_strings(cp->classperms, classperms_strs);
708 		}
709 	}
710 }
711 
cil_class_decls_to_policy(FILE * out,struct cil_list * classorder)712 static void cil_class_decls_to_policy(FILE *out, struct cil_list *classorder)
713 {
714 	struct cil_list_item *i1;
715 
716 	cil_list_for_each(i1, classorder) {
717 		fprintf(out, "class %s\n", DATUM(i1->data)->fqn);
718 	}
719 }
720 
cil_sid_decls_to_policy(FILE * out,struct cil_list * sidorder)721 static void cil_sid_decls_to_policy(FILE *out, struct cil_list *sidorder)
722 {
723 	struct cil_list_item *i1;
724 
725 	cil_list_for_each(i1, sidorder) {
726 		fprintf(out, "sid %s\n", DATUM(i1->data)->fqn);
727 	}
728 }
729 
cil_commons_to_policy(FILE * out,struct cil_list * commons)730 static void cil_commons_to_policy(FILE *out, struct cil_list *commons)
731 {
732 	struct cil_list_item *i1;
733 	struct cil_class* common;
734 	struct cil_tree_node *node;
735 	struct cil_tree_node *perm;
736 
737 	cil_list_for_each(i1, commons) {
738 		common = i1->data;
739 		node = NODE(&common->datum);
740 		perm = node->cl_head;
741 
742 		fprintf(out, "common %s {", common->datum.fqn);
743 		while (perm != NULL) {
744 			fprintf(out, "%s ", DATUM(perm->data)->fqn);
745 			perm = perm->next;
746 		}
747 		fprintf(out, "}\n");
748 	}
749 }
750 
cil_classes_to_policy(FILE * out,struct cil_list * classorder)751 static void cil_classes_to_policy(FILE *out, struct cil_list *classorder)
752 {
753 	struct cil_list_item *i1;
754 	struct cil_class *class;
755 	struct cil_tree_node *node;
756 
757 	cil_list_for_each(i1, classorder) {
758 		class = i1->data;
759 		node = NODE(&class->datum);
760 
761 		fprintf(out, "class %s", class->datum.fqn);
762 		if (class->common != NULL) {
763 			fprintf(out, " inherits %s", class->common->datum.fqn);
764 		}
765 		if (node->cl_head != NULL) {
766 			struct cil_tree_node *perm = node->cl_head;
767 			fprintf(out, " {");
768 			while (perm != NULL) {
769 				fprintf(out, " %s", DATUM(perm->data)->fqn);
770 				perm = perm->next;
771 			}
772 			fprintf(out, " }");
773 		}
774 		fprintf(out, "\n");
775 	}
776 }
777 
cil_defaults_to_policy(FILE * out,struct cil_list * defaults,const char * kind)778 static void cil_defaults_to_policy(FILE *out, struct cil_list *defaults, const char *kind)
779 {
780 	struct cil_list_item *i1, *i2, *i3;
781 	struct cil_default *def;
782 	struct cil_list *class_list;
783 
784 	cil_list_for_each(i1, defaults) {
785 		def = i1->data;
786 		fprintf(out, "%s {",kind);
787 		cil_list_for_each(i2, def->class_datums) {
788 			class_list = cil_expand_class(i2->data);
789 			cil_list_for_each(i3, class_list) {
790 				fprintf(out, " %s", DATUM(i3->data)->fqn);
791 			}
792 			cil_list_destroy(&class_list, CIL_FALSE);
793 		}
794 		fprintf(out, " }");
795 		if (def->object == CIL_DEFAULT_SOURCE) {
796 			fprintf(out," %s",CIL_KEY_SOURCE);
797 		} else if (def->object == CIL_DEFAULT_TARGET) {
798 			fprintf(out," %s",CIL_KEY_TARGET);
799 		}
800 		fprintf(out,";\n");
801 	}
802 }
803 
cil_default_ranges_to_policy(FILE * out,struct cil_list * defaults)804 static void cil_default_ranges_to_policy(FILE *out, struct cil_list *defaults)
805 {
806 	struct cil_list_item *i1, *i2, *i3;
807 	struct cil_defaultrange *def;
808 	struct cil_list *class_list;
809 
810 	cil_list_for_each(i1, defaults) {
811 		def = i1->data;
812 		fprintf(out, "default_range {");
813 		cil_list_for_each(i2, def->class_datums) {
814 			class_list = cil_expand_class(i2->data);
815 			cil_list_for_each(i3, class_list) {
816 				fprintf(out, " %s", DATUM(i3->data)->fqn);
817 			}
818 			cil_list_destroy(&class_list, CIL_FALSE);
819 		}
820 		fprintf(out, " }");
821 
822 		switch (def->object_range) {
823 		case CIL_DEFAULT_SOURCE_LOW:
824 			fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW);
825 			break;
826 		case CIL_DEFAULT_SOURCE_HIGH:
827 			fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_HIGH);
828 			break;
829 		case CIL_DEFAULT_SOURCE_LOW_HIGH:
830 			fprintf(out," %s %s", CIL_KEY_SOURCE, CIL_KEY_LOW_HIGH);
831 			break;
832 		case CIL_DEFAULT_TARGET_LOW:
833 			fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW);
834 			break;
835 		case CIL_DEFAULT_TARGET_HIGH:
836 			fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_HIGH);
837 			break;
838 		case CIL_DEFAULT_TARGET_LOW_HIGH:
839 			fprintf(out," %s %s", CIL_KEY_TARGET, CIL_KEY_LOW_HIGH);
840 			break;
841 		default:
842 			break;
843 		}
844 		fprintf(out,";\n");
845 	}
846 }
847 
cil_sensitivities_to_policy(FILE * out,struct cil_list * sensorder,struct cil_list * all_aliases)848 static void cil_sensitivities_to_policy(FILE *out, struct cil_list *sensorder, struct cil_list *all_aliases)
849 {
850 	struct cil_list_item *i1, *i2;
851 	struct cil_sens *sens;
852 	struct cil_list *aliases = NULL;
853 	struct cil_alias *alias;
854 	struct cil_sens *actual;
855 	int num_aliases;
856 
857 	cil_list_for_each(i1, sensorder) {
858 		sens = i1->data;
859 		num_aliases = 0;
860 		cil_list_for_each(i2, all_aliases) {
861 			alias = i2->data;
862 			actual = alias->actual;
863 			if (sens == actual) {
864 				if (num_aliases == 0) {
865 					cil_list_init(&aliases, CIL_LIST);
866 				}
867 				cil_list_append(aliases, CIL_SENSALIAS, alias);
868 				num_aliases++;
869 			}
870 		}
871 		fprintf(out, "sensitivity %s", sens->datum.fqn);
872 		if (num_aliases > 0) {
873 			fprintf(out, " alias");
874 			if (num_aliases > 1) {
875 				fprintf(out, " {");
876 			}
877 			cil_list_for_each(i2, aliases) {
878 				alias = i2->data;
879 				fprintf(out, " %s", alias->datum.fqn);
880 			}
881 			if (num_aliases > 1) {
882 				fprintf(out, " }");
883 			}
884 			cil_list_destroy(&aliases, CIL_FALSE);
885 		}
886 		fprintf(out, ";\n");
887 	}
888 }
889 
cil_dominance_to_policy(FILE * out,struct cil_list * sensorder)890 static void cil_dominance_to_policy(FILE *out, struct cil_list *sensorder)
891 {
892 	struct cil_list_item *item;
893 	struct cil_sens *sens;
894 
895 	fprintf(out, "dominance {");
896 	cil_list_for_each(item, sensorder) {
897 		sens = item->data;
898 		fprintf(out, " %s", sens->datum.fqn);
899 	}
900 	fprintf(out, " }\n");
901 }
902 
cil_categories_to_policy(FILE * out,struct cil_list * catorder,struct cil_list * all_aliases)903 static void cil_categories_to_policy(FILE *out, struct cil_list *catorder, struct cil_list *all_aliases)
904 {
905 	struct cil_list_item *i1, *i2;
906 	struct cil_sens *cat;
907 	struct cil_list *aliases = NULL;
908 	struct cil_alias *alias;
909 	struct cil_sens *actual;
910 	int num_aliases;
911 
912 	cil_list_for_each(i1, catorder) {
913 		cat = i1->data;
914 		num_aliases = 0;
915 		cil_list_for_each(i2, all_aliases) {
916 			alias = i2->data;
917 			actual = alias->actual;
918 			if (cat == actual) {
919 				if (num_aliases == 0) {
920 					cil_list_init(&aliases, CIL_LIST);
921 				}
922 				cil_list_append(aliases, CIL_CATALIAS, alias);
923 				num_aliases++;
924 			}
925 		}
926 		fprintf(out, "category %s",cat->datum.fqn);
927 		if (num_aliases > 0) {
928 			fprintf(out, " alias");
929 			if (num_aliases > 1) {
930 				fprintf(out, " { ");
931 			}
932 			cil_list_for_each(i2, aliases) {
933 				alias = i2->data;
934 				fprintf(out, " %s", alias->datum.fqn);
935 			}
936 			if (num_aliases > 1) {
937 				fprintf(out, " }");
938 			}
939 			cil_list_destroy(&aliases, CIL_FALSE);
940 		}
941 		fprintf(out, ";\n");
942 	}
943 }
944 
cil_levels_to_policy(FILE * out,struct cil_list * sensorder)945 static void cil_levels_to_policy(FILE *out, struct cil_list *sensorder)
946 {
947 	struct cil_list_item *i1, *i2;
948 	struct cil_sens *sens;
949 
950 	cil_list_for_each(i1, sensorder) {
951 		sens = i1->data;
952 		if (sens->cats_list) {
953 			cil_list_for_each(i2, sens->cats_list) {
954 				fprintf(out, "level %s:",sens->datum.fqn);
955 				cil_cats_to_policy(out, i2->data);
956 				fprintf(out,";\n");
957 			}
958 		} else {
959 			fprintf(out, "level %s;\n",sens->datum.fqn);
960 		}
961 	}
962 }
963 
cil_mlsconstrains_to_policy(FILE * out,struct cil_db * db,struct cil_list * mlsconstrains)964 static void cil_mlsconstrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *mlsconstrains)
965 {
966 	struct cil_list_item *i1, *i2;
967 	struct cil_constrain *cons;
968 	struct cil_list *classperms_strs;
969 	char *cp_str;
970 	char *expr_str;
971 
972 	cil_list_for_each(i1, mlsconstrains) {
973 		cons = i1->data;
974 		cil_list_init(&classperms_strs, CIL_LIST);
975 		cil_classperms_to_strings(cons->classperms, classperms_strs);
976 		expr_str = cil_cons_expr_to_string(db, cons->datum_expr);
977 		cil_list_for_each(i2, classperms_strs) {
978 			cp_str = i2->data;
979 			fprintf(out, "mlsconstrain %s %s;\n", cp_str, expr_str);
980 			free(cp_str);
981 		}
982 		free(expr_str);
983 		cil_list_destroy(&classperms_strs, CIL_FALSE);
984 	}
985 }
986 
cil_validatetrans_to_policy(FILE * out,struct cil_db * db,struct cil_list * validatetrans,char * kind)987 static void cil_validatetrans_to_policy(FILE *out, struct cil_db *db, struct cil_list *validatetrans, char *kind)
988 {
989 	struct cil_list_item *i1, *i2;
990 	struct cil_validatetrans *trans;
991 	struct cil_list *class_list;
992 	struct cil_class *class;
993 	char *expr_str;
994 
995 	cil_list_for_each(i1, validatetrans) {
996 		trans = i1->data;
997 		class_list = cil_expand_class(trans->class);
998 		expr_str = cil_cons_expr_to_string(db, trans->datum_expr);
999 		cil_list_for_each(i2, class_list) {
1000 			class = i2->data;
1001 			fprintf(out, "%s %s %s;\n", kind, class->datum.fqn, expr_str);
1002 		}
1003 		free(expr_str);
1004 		cil_list_destroy(&class_list, CIL_FALSE);
1005 	}
1006 }
1007 
cil_bools_to_policy(FILE * out,struct cil_list * bools)1008 static void cil_bools_to_policy(FILE *out, struct cil_list *bools)
1009 {
1010 	struct cil_list_item *i1;
1011 	struct cil_bool *bool;
1012 	const char *value;
1013 
1014 	cil_list_for_each(i1, bools) {
1015 		bool = i1->data;
1016 		value = bool->value ? "true" : "false";
1017 		fprintf(out, "bool %s %s;\n", bool->datum.fqn, value);
1018 	}
1019 }
1020 
cil_typealiases_to_policy(FILE * out,struct cil_list * types,struct cil_list * all_aliases)1021 static void cil_typealiases_to_policy(FILE *out, struct cil_list *types, struct cil_list *all_aliases)
1022 {
1023 	struct cil_list_item *i1, *i2;
1024 	struct cil_type *type;
1025 	struct cil_list *aliases = NULL;
1026 	struct cil_alias *alias;
1027 	struct cil_type *actual;
1028 	int num_aliases;
1029 
1030 	cil_list_for_each(i1, types) {
1031 		type = i1->data;
1032 		num_aliases = 0;
1033 		cil_list_for_each(i2, all_aliases) {
1034 			alias = i2->data;
1035 			actual = alias->actual;
1036 			if (type == actual) {
1037 				if (num_aliases == 0) {
1038 					cil_list_init(&aliases, CIL_LIST);
1039 				}
1040 				cil_list_append(aliases, CIL_TYPEALIAS, alias);
1041 				num_aliases++;
1042 			}
1043 		}
1044 		if (num_aliases > 0) {
1045 			fprintf(out, "typealias %s alias", type->datum.fqn);
1046 			if (num_aliases > 1) {
1047 				fprintf(out, " {");
1048 			}
1049 			cil_list_for_each(i2, aliases) {
1050 				alias = i2->data;
1051 				fprintf(out, " %s", alias->datum.fqn);
1052 			}
1053 			if (num_aliases > 1) {
1054 				fprintf(out, " }");
1055 			}
1056 			fprintf(out, ";\n");
1057 			cil_list_destroy(&aliases, CIL_FALSE);
1058 		}
1059 	}
1060 }
1061 
cil_typebounds_to_policy(FILE * out,struct cil_list * types)1062 static void cil_typebounds_to_policy(FILE *out, struct cil_list *types)
1063 {
1064 	struct cil_list_item *i1;
1065 	struct cil_type *child;
1066 	struct cil_type *parent;
1067 
1068 	cil_list_for_each(i1, types) {
1069 		child = i1->data;
1070 		if (child->bounds != NULL) {
1071 			parent = child->bounds;
1072 			fprintf(out, "typebounds %s %s;\n", parent->datum.fqn, child->datum.fqn);
1073 		}
1074 	}
1075 }
1076 
cil_typeattributes_to_policy(FILE * out,struct cil_list * types,struct cil_list * attributes)1077 static void cil_typeattributes_to_policy(FILE *out, struct cil_list *types, struct cil_list *attributes)
1078 {
1079 	struct cil_list_item *i1, *i2;
1080 	struct cil_type *type;
1081 	struct cil_typeattribute *attribute;
1082 	int first = CIL_TRUE;
1083 
1084 	cil_list_for_each(i1, types) {
1085 		type = i1->data;
1086 		cil_list_for_each(i2, attributes) {
1087 			attribute = i2->data;
1088 			if (!attribute->keep)
1089 				continue;
1090 			if (ebitmap_get_bit(attribute->types, type->value)) {
1091 				if (first) {
1092 					fprintf(out, "typeattribute %s %s", type->datum.fqn, attribute->datum.fqn);
1093 					first = CIL_FALSE;
1094 				} else {
1095 					fprintf(out, ", %s", attribute->datum.fqn);
1096 				}
1097 			}
1098 		}
1099 		if (!first) {
1100 			fprintf(out, ";\n");
1101 			first = CIL_TRUE;
1102 		}
1103 	}
1104 }
1105 
cil_xperms_to_policy(FILE * out,struct cil_permissionx * permx)1106 static void cil_xperms_to_policy(FILE *out, struct cil_permissionx *permx)
1107 {
1108 	ebitmap_node_t *node;
1109 	unsigned int i, first = 0, last = 0;
1110 	int need_first = CIL_TRUE, need_last = CIL_TRUE;
1111 	const char *kind;
1112 
1113 	if (permx->kind == CIL_PERMX_KIND_IOCTL) {
1114 		kind = "ioctl";
1115 	} else {
1116 		kind = "???";
1117 	}
1118 
1119 	fprintf(out, "%s %s {", DATUM(permx->obj)->fqn, kind);
1120 
1121 	ebitmap_for_each_bit(permx->perms, node, i) {
1122 		if (!ebitmap_get_bit(permx->perms, i))
1123 			continue;
1124 		if (need_first == CIL_TRUE) {
1125 			first = i;
1126 			need_first = CIL_FALSE;
1127 		} else if (need_last == CIL_TRUE) {
1128 			if (i == first+1) {
1129 				last = i;
1130 				need_last = CIL_FALSE;
1131 			} else {
1132 				fprintf(out, " 0x%x", first);
1133 				first = i;
1134 			}
1135 		} else if (i == last+1) {
1136 			last = i;
1137 		} else {
1138 			if (last > first+1) {
1139 				fprintf(out, " 0x%x-0x%x", first, last);
1140 			} else {
1141 				fprintf(out, " 0x%x 0x%x", first, last);
1142 			}
1143 			first = i;
1144 			need_last = CIL_TRUE;
1145 		}
1146 	}
1147 	if (need_first == CIL_FALSE) {
1148 		if (need_last == CIL_FALSE) {
1149 			fprintf(out, " 0x%x-0x%x", first, last);
1150 		} else {
1151 			fprintf(out, " 0x%x", first);
1152 		}
1153 	}
1154 	fprintf(out," }");
1155 }
1156 
cil_av_rulex_to_policy(FILE * out,struct cil_avrule * rule)1157 static void cil_av_rulex_to_policy(FILE *out, struct cil_avrule *rule)
1158 {
1159 	const char *kind;
1160 	struct cil_symtab_datum *src, *tgt;
1161 
1162 	src = rule->src;
1163 	tgt = rule->tgt;
1164 
1165 	switch (rule->rule_kind) {
1166 	case CIL_AVRULE_ALLOWED:
1167 		kind = "allowxperm";
1168 		break;
1169 	case CIL_AVRULE_AUDITALLOW:
1170 		kind = "auditallowxperm";
1171 		break;
1172 	case CIL_AVRULE_DONTAUDIT:
1173 		kind = "dontauditxperm";
1174 		break;
1175 	case CIL_AVRULE_NEVERALLOW:
1176 		kind = "neverallowxperm";
1177 		break;
1178 	default:
1179 		kind = "???";
1180 		break;
1181 	}
1182 
1183 	fprintf(out, "%s %s %s : ", kind, src->fqn, tgt->fqn);
1184 	cil_xperms_to_policy(out, rule->perms.x.permx);
1185 	fprintf(out, ";\n");
1186 }
1187 
cil_av_rule_to_policy(FILE * out,struct cil_avrule * rule)1188 static void cil_av_rule_to_policy(FILE *out, struct cil_avrule *rule)
1189 {
1190 	const char *kind;
1191 	struct cil_symtab_datum *src, *tgt;
1192 	struct cil_list *classperms_strs;
1193 	struct cil_list_item *i1;
1194 
1195 	src = rule->src;
1196 	tgt = rule->tgt;
1197 
1198 	switch (rule->rule_kind) {
1199 	case CIL_AVRULE_ALLOWED:
1200 		kind = "allow";
1201 		break;
1202 	case CIL_AVRULE_AUDITALLOW:
1203 		kind = "auditallow";
1204 		break;
1205 	case CIL_AVRULE_DONTAUDIT:
1206 		kind = "dontaudit";
1207 		break;
1208 	case CIL_AVRULE_NEVERALLOW:
1209 		kind = "neverallow";
1210 		break;
1211 	default:
1212 		kind = "???";
1213 		break;
1214 	}
1215 
1216 	cil_list_init(&classperms_strs, CIL_LIST);
1217 	cil_classperms_to_strings(rule->perms.classperms, classperms_strs);
1218 	cil_list_for_each(i1, classperms_strs) {
1219 		char *cp_str = i1->data;
1220 		fprintf(out, "%s %s %s : %s;\n", kind, src->fqn, tgt->fqn, cp_str);
1221 		free(cp_str);
1222 	}
1223 	cil_list_destroy(&classperms_strs, CIL_FALSE);
1224 }
1225 
cil_type_rule_to_policy(FILE * out,struct cil_type_rule * rule)1226 static void cil_type_rule_to_policy(FILE *out, struct cil_type_rule *rule)
1227 {
1228 	const char *kind;
1229 	struct cil_symtab_datum *src, *tgt, *res;
1230 	struct cil_list *class_list;
1231 	struct cil_list_item *i1;
1232 
1233 	src = rule->src;
1234 	tgt = rule->tgt;
1235 	res = rule->result;
1236 
1237 	switch (rule->rule_kind) {
1238 	case CIL_TYPE_TRANSITION:
1239 		kind = "type_transition";
1240 		break;
1241 	case CIL_TYPE_MEMBER:
1242 		kind = "type_member";
1243 		break;
1244 	case CIL_TYPE_CHANGE:
1245 		kind = "type_change";
1246 		break;
1247 	default:
1248 		kind = "???";
1249 		break;
1250 	}
1251 
1252 	class_list = cil_expand_class(rule->obj);
1253 	cil_list_for_each(i1, class_list) {
1254 		fprintf(out, "%s %s %s : %s %s;\n", kind, src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn);
1255 	}
1256 	cil_list_destroy(&class_list, CIL_FALSE);
1257 }
1258 
cil_nametypetransition_to_policy(FILE * out,struct cil_nametypetransition * trans)1259 static void cil_nametypetransition_to_policy(FILE *out, struct cil_nametypetransition *trans)
1260 {
1261 	struct cil_symtab_datum *src, *tgt, *res;
1262 	struct cil_name *name;
1263 	struct cil_list *class_list;
1264 	struct cil_list_item *i1;
1265 
1266 	src = trans->src;
1267 	tgt = trans->tgt;
1268 	name = trans->name;
1269 	res = trans->result;
1270 
1271 	class_list = cil_expand_class(trans->obj);
1272 	cil_list_for_each(i1, class_list) {
1273 		fprintf(out, "type_transition %s %s : %s %s \"%s\";\n", src->fqn, tgt->fqn, DATUM(i1->data)->fqn, res->fqn, name->datum.fqn);
1274 	}
1275 	cil_list_destroy(&class_list, CIL_FALSE);
1276 }
1277 
cil_rangetransition_to_policy(FILE * out,struct cil_rangetransition * trans)1278 static void cil_rangetransition_to_policy(FILE *out, struct cil_rangetransition *trans)
1279 {
1280 	struct cil_symtab_datum *src, *exec;
1281 	struct cil_list *class_list;
1282 	struct cil_list_item *i1;
1283 
1284 	src = trans->src;
1285 	exec = trans->exec;
1286 
1287 	class_list = cil_expand_class(trans->obj);
1288 	cil_list_for_each(i1, class_list) {
1289 		fprintf(out, "range_transition %s %s : %s ", src->fqn, exec->fqn, DATUM(i1->data)->fqn);
1290 		cil_levelrange_to_policy(out, trans->range);
1291 		fprintf(out, ";\n");
1292 	}
1293 	cil_list_destroy(&class_list, CIL_FALSE);
1294 }
1295 
cil_typepermissive_to_policy(FILE * out,struct cil_typepermissive * rule)1296 static void cil_typepermissive_to_policy(FILE *out, struct cil_typepermissive *rule)
1297 {
1298 	fprintf(out, "permissive %s;\n", DATUM(rule->type)->fqn);
1299 }
1300 
1301 struct block_te_rules_extra {
1302 	FILE *out;
1303 	enum cil_flavor flavor;
1304 	uint32_t rule_kind;
1305 };
1306 
__cil_block_te_rules_to_policy_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1307 static int __cil_block_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1308 {
1309 	struct block_te_rules_extra *args = extra_args;
1310 
1311 	switch (node->flavor) {
1312 	case CIL_BLOCK: {
1313 		struct cil_block *blk = node->data;
1314 		if (blk->is_abstract == CIL_TRUE) {
1315 			*finished = CIL_TREE_SKIP_HEAD;
1316 		}
1317 		break;
1318 	}
1319 	case CIL_MACRO:
1320 		*finished = CIL_TREE_SKIP_HEAD;
1321 		break;
1322 	case CIL_BOOLEANIF:
1323 		*finished = CIL_TREE_SKIP_HEAD;
1324 		break;
1325 	case CIL_AVRULE:
1326 	case CIL_AVRULEX:
1327 		if (args->flavor == node->flavor) {
1328 			struct cil_avrule *rule = node->data;
1329 			if (args->rule_kind == rule->rule_kind) {
1330 				if (rule->is_extended) {
1331 					cil_av_rulex_to_policy(args->out, rule);
1332 				} else {
1333 					cil_av_rule_to_policy(args->out, rule);
1334 				}
1335 			}
1336 		}
1337 		break;
1338 	case CIL_TYPE_RULE:
1339 		if (args->flavor == node->flavor) {
1340 			struct cil_type_rule *rule = node->data;
1341 			if (args->rule_kind == rule->rule_kind) {
1342 				cil_type_rule_to_policy(args->out, rule);
1343 			}
1344 		}
1345 
1346 		break;
1347 	case CIL_NAMETYPETRANSITION:
1348 		if (args->flavor == node->flavor) {
1349 			cil_nametypetransition_to_policy(args->out, node->data);
1350 		}
1351 		break;
1352 	case CIL_RANGETRANSITION:
1353 		if (args->flavor == node->flavor) {
1354 			cil_rangetransition_to_policy(args->out, node->data);
1355 		}
1356 
1357 		break;
1358 	case CIL_TYPEPERMISSIVE:
1359 		if (args->flavor == node->flavor) {
1360 			cil_typepermissive_to_policy(args->out, node->data);
1361 		}
1362 		break;
1363 	default:
1364 		break;
1365 	}
1366 
1367 	return SEPOL_OK;
1368 }
1369 
cil_block_te_rules_to_policy(FILE * out,struct cil_tree_node * start,int mls)1370 static void cil_block_te_rules_to_policy(FILE *out, struct cil_tree_node *start, int mls)
1371 {
1372 	struct block_te_rules_extra args;
1373 
1374 	args.out = out;
1375 
1376 	args.flavor = CIL_TYPEPERMISSIVE;
1377 	args.rule_kind = 0;
1378 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1379 
1380 	args.flavor = CIL_AVRULE;
1381 	args.rule_kind = CIL_AVRULE_ALLOWED;
1382 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1383 	args.rule_kind = CIL_AVRULE_AUDITALLOW;
1384 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1385 	args.rule_kind = CIL_AVRULE_DONTAUDIT;
1386 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1387 	args.rule_kind = CIL_AVRULE_NEVERALLOW;
1388 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1389 
1390 	args.flavor = CIL_AVRULEX;
1391 	args.rule_kind = CIL_AVRULE_ALLOWED;
1392 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1393 	args.rule_kind = CIL_AVRULE_AUDITALLOW;
1394 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1395 	args.rule_kind = CIL_AVRULE_DONTAUDIT;
1396 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1397 	args.rule_kind = CIL_AVRULE_NEVERALLOW;
1398 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1399 
1400 	args.flavor = CIL_TYPE_RULE;
1401 	args.rule_kind = CIL_TYPE_TRANSITION;
1402 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1403 	args.rule_kind = CIL_TYPE_MEMBER;
1404 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1405 	args.rule_kind = CIL_TYPE_CHANGE;
1406 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1407 	args.rule_kind = CIL_AVRULE_TYPE;
1408 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1409 
1410 	args.flavor = CIL_NAMETYPETRANSITION;
1411 	args.rule_kind = 0;
1412 	cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1413 
1414 	if (mls == CIL_TRUE) {
1415 		args.flavor = CIL_RANGETRANSITION;
1416 		args.rule_kind = 0;
1417 		cil_tree_walk(start, __cil_block_te_rules_to_policy_helper, NULL, NULL, &args);
1418 	}
1419 }
1420 
1421 struct te_rules_extra {
1422 	FILE *out;
1423 	int mls;
1424 };
1425 
__cil_te_rules_to_policy_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1426 static int __cil_te_rules_to_policy_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1427 {
1428 	struct te_rules_extra *args = extra_args;
1429 
1430 	switch (node->flavor) {
1431 	case CIL_BLOCK: {
1432 		struct cil_block *blk = node->data;
1433 		if (blk->is_abstract == CIL_TRUE) {
1434 			*finished = CIL_TREE_SKIP_HEAD;
1435 		}
1436 		break;
1437 	}
1438 	case CIL_MACRO:
1439 		*finished = CIL_TREE_SKIP_HEAD;
1440 		break;
1441 	case CIL_BOOLEANIF: {
1442 		struct cil_booleanif *bool = node->data;
1443 		struct cil_tree_node *n;
1444 		struct cil_condblock *cb;
1445 
1446 		fprintf(args->out, "if ");
1447 		cil_cond_expr_to_policy(args->out, bool->datum_expr, CIL_TRUE);
1448 		fprintf(args->out," {\n");
1449 		n = node->cl_head;
1450 		cb = n != NULL ? n->data : NULL;
1451 		if (cb && cb->flavor == CIL_CONDTRUE) {
1452 			cil_block_te_rules_to_policy(args->out, n, args->mls);
1453 			n = n->next;
1454 			cb = n != NULL ? n->data : NULL;
1455 		}
1456 		if (cb && cb->flavor == CIL_CONDFALSE) {
1457 			fprintf(args->out,"} else {\n");
1458 			cil_block_te_rules_to_policy(args->out, n, args->mls);
1459 		}
1460 		fprintf(args->out,"}\n");
1461 		*finished = CIL_TREE_SKIP_HEAD;
1462 		break;
1463 	}
1464 	default:
1465 		break;
1466 	}
1467 
1468 	return SEPOL_OK;
1469 }
1470 
cil_te_rules_to_policy(FILE * out,struct cil_tree_node * head,int mls)1471 static void cil_te_rules_to_policy(FILE *out, struct cil_tree_node *head, int mls)
1472 {
1473 	struct te_rules_extra args;
1474 
1475 	args.out = out;
1476 	args.mls = mls;
1477 
1478 	cil_block_te_rules_to_policy(out, head, mls);
1479 	cil_tree_walk(head, __cil_te_rules_to_policy_helper, NULL, NULL, &args);
1480 }
1481 
cil_roles_to_policy(FILE * out,struct cil_list * rules)1482 static void cil_roles_to_policy(FILE *out, struct cil_list *rules)
1483 {
1484 	struct cil_list_item *i1;
1485 	struct cil_role *role;
1486 
1487 	cil_list_for_each(i1, rules) {
1488 		role = i1->data;
1489 		if (strcmp(role->datum.fqn,"object_r") == 0)
1490 			continue;
1491 		fprintf(out, "role %s;\n", role->datum.fqn);
1492 	}
1493 }
1494 
cil_role_types_to_policy(FILE * out,struct cil_list * roles,struct cil_list * types)1495 static void cil_role_types_to_policy(FILE *out, struct cil_list *roles, struct cil_list *types)
1496 {
1497 	struct cil_list_item *i1, *i2;
1498 	struct cil_role *role;
1499 	struct cil_type *type;
1500 	int first = CIL_TRUE;
1501 
1502 	cil_list_for_each(i1, roles) {
1503 		role = i1->data;
1504 		if (strcmp(role->datum.fqn,"object_r") == 0)
1505 			continue;
1506 		if (role->types) {
1507 			cil_list_for_each(i2, types) {
1508 				type = i2->data;
1509 				if (ebitmap_get_bit(role->types, type->value)) {
1510 					if (first) {
1511 						fprintf(out, "role %s types { %s", role->datum.fqn, type->datum.fqn);
1512 						first = CIL_FALSE;
1513 					} else {
1514 						fprintf(out, " %s", type->datum.fqn);
1515 					}
1516 				}
1517 			}
1518 			if (!first) {
1519 				fprintf(out, " }");
1520 				first = CIL_TRUE;
1521 			}
1522 			fprintf(out, ";\n");
1523 		}
1524 	}
1525 }
1526 
cil_roleattributes_to_policy(FILE * out,struct cil_list * roles,struct cil_list * attributes)1527 static void cil_roleattributes_to_policy(FILE *out, struct cil_list *roles, struct cil_list *attributes)
1528 {
1529 	struct cil_list_item *i1, *i2;
1530 	struct cil_role *role;
1531 	struct cil_roleattribute *attribute;
1532 	int first = CIL_TRUE;
1533 
1534 	cil_list_for_each(i1, roles) {
1535 		role = i1->data;
1536 		if (strcmp(role->datum.fqn,"object_r") == 0)
1537 			continue;
1538 		cil_list_for_each(i2, attributes) {
1539 			attribute = i2->data;
1540 			if (ebitmap_get_bit(attribute->roles, role->value)) {
1541 				if (first) {
1542 					fprintf(out, "roleattribute %s %s", role->datum.fqn, attribute->datum.fqn);
1543 					first = CIL_FALSE;
1544 				} else {
1545 					fprintf(out, ", %s", attribute->datum.fqn);
1546 				}
1547 			}
1548 		}
1549 		if (!first) {
1550 			fprintf(out, ";\n");
1551 			first = CIL_TRUE;
1552 		}
1553 	}
1554 }
1555 
cil_roleallows_to_policy(FILE * out,struct cil_list * roleallows)1556 static void cil_roleallows_to_policy(FILE *out, struct cil_list *roleallows)
1557 {
1558 	struct cil_list_item *i1;
1559 	struct cil_roleallow *allow;
1560 
1561 	cil_list_for_each(i1, roleallows) {
1562 		allow = i1->data;
1563 		fprintf(out, "allow %s %s;\n", DATUM(allow->src)->fqn, DATUM(allow->tgt)->fqn);
1564 	}
1565 }
1566 
cil_roletransitions_to_policy(FILE * out,struct cil_list * roletransitions)1567 static void cil_roletransitions_to_policy(FILE *out, struct cil_list *roletransitions)
1568 {
1569 	struct cil_list_item *i1, *i2;
1570 	struct cil_list *class_list;
1571 	struct cil_roletransition *trans;
1572 
1573 
1574 	cil_list_for_each(i1, roletransitions) {
1575 		trans = i1->data;
1576 		class_list = cil_expand_class(trans->obj);
1577 		cil_list_for_each(i2, class_list) {
1578 			fprintf(out, "role_transition %s %s : %s %s;\n", DATUM(trans->src)->fqn, DATUM(trans->tgt)->fqn, DATUM(i2->data)->fqn, DATUM(trans->result)->fqn);
1579 		}
1580 		cil_list_destroy(&class_list, CIL_FALSE);
1581 	}
1582 }
1583 
cil_users_to_policy(FILE * out,int mls,struct cil_list * users,struct cil_list * all_roles)1584 static void cil_users_to_policy(FILE *out, int mls, struct cil_list *users, struct cil_list *all_roles)
1585 {
1586 	struct cil_list_item *i1, *i2;
1587 	struct cil_user *user;
1588 	struct cil_list *roles = NULL;
1589 	struct cil_role *role;
1590 	int num_roles;
1591 
1592 	cil_list_for_each(i1, users) {
1593 		user = i1->data;
1594 		num_roles = 0;
1595 		fprintf(out, "user %s",user->datum.fqn);
1596 		cil_list_for_each(i2, all_roles) {
1597 			role = i2->data;
1598 			if (ebitmap_get_bit(user->roles, role->value)) {
1599 				if (num_roles == 0) {
1600 					cil_list_init(&roles, CIL_LIST);
1601 				}
1602 				cil_list_append(roles, CIL_ROLE, role);
1603 				num_roles++;
1604 			}
1605 		}
1606 		if (num_roles > 0) {
1607 			fprintf(out, " roles");
1608 			if (num_roles > 1) {
1609 				fprintf(out, " {");
1610 			}
1611 			cil_list_for_each(i2, roles) {
1612 				role = i2->data;
1613 				fprintf(out, " %s", role->datum.fqn);
1614 			}
1615 			if (num_roles > 1) {
1616 				fprintf(out, " }");
1617 			}
1618 			cil_list_destroy(&roles, CIL_FALSE);
1619 		}
1620 
1621 		if (mls == CIL_TRUE && user->dftlevel != NULL) {
1622 			fprintf(out, " level ");
1623 			cil_level_to_policy(out, user->dftlevel);
1624 		}
1625 
1626 		if (mls == CIL_TRUE && user->range != NULL) {
1627 			fprintf(out, " range ");
1628 			cil_levelrange_to_policy(out, user->range);
1629 		}
1630 
1631 		fprintf(out,";\n");
1632 	}
1633 }
1634 
cil_constrains_to_policy(FILE * out,struct cil_db * db,struct cil_list * constrains)1635 static void cil_constrains_to_policy(FILE *out, struct cil_db *db, struct cil_list *constrains)
1636 {
1637 	struct cil_list_item *i1, *i2;
1638 	struct cil_constrain *cons;
1639 	struct cil_list *classperms_strs;
1640 	char *cp_str;
1641 	char *expr_str;
1642 
1643 	cil_list_for_each(i1, constrains) {
1644 		cons = i1->data;
1645 		cil_list_init(&classperms_strs, CIL_LIST);
1646 		cil_classperms_to_strings(cons->classperms, classperms_strs);
1647 		expr_str = cil_cons_expr_to_string(db, cons->datum_expr);
1648 		cil_list_for_each(i2, classperms_strs) {
1649 			cp_str = i2->data;
1650 			fprintf(out, "constrain %s %s;\n",cp_str, expr_str);
1651 			free(cp_str);
1652 		}
1653 		free(expr_str);
1654 		cil_list_destroy(&classperms_strs, CIL_FALSE);
1655 	}
1656 }
1657 
cil_sid_contexts_to_policy(FILE * out,struct cil_list * sids,int mls)1658 static void cil_sid_contexts_to_policy(FILE *out, struct cil_list *sids, int mls)
1659 {
1660 	struct cil_list_item *i1;
1661 	struct cil_sid *sid;
1662 
1663 	cil_list_for_each(i1, sids) {
1664 		sid = i1->data;
1665 		fprintf(out, "sid %s ", sid->datum.fqn);
1666 		cil_context_to_policy(out, sid->context, mls);
1667 		fprintf(out,"\n");
1668 	}
1669 }
1670 
cil_fsuses_to_policy(FILE * out,struct cil_sort * fsuses,int mls)1671 static void cil_fsuses_to_policy(FILE *out, struct cil_sort *fsuses, int mls)
1672 {
1673 	unsigned i;
1674 	struct cil_fsuse *fsuse;
1675 
1676 	for (i=0; i<fsuses->count; i++) {
1677 		fsuse = fsuses->array[i];
1678 		if (fsuse->type == CIL_FSUSE_XATTR) {
1679 			fprintf(out, "fs_use_xattr %s ", fsuse->fs_str);
1680 			cil_context_to_policy(out, fsuse->context, mls);
1681 			fprintf(out,";\n");
1682 		}
1683 	}
1684 
1685 	for (i=0; i<fsuses->count; i++) {
1686 		fsuse = fsuses->array[i];
1687 		if (fsuse->type == CIL_FSUSE_TASK) {
1688 			fprintf(out, "fs_use_task %s ", fsuse->fs_str);
1689 			cil_context_to_policy(out, fsuse->context, mls);
1690 			fprintf(out,";\n");
1691 		}
1692 	}
1693 
1694 	for (i=0; i<fsuses->count; i++) {
1695 		fsuse = fsuses->array[i];
1696 		if (fsuse->type == CIL_FSUSE_TRANS) {
1697 			fprintf(out, "fs_use_trans %s ", fsuse->fs_str);
1698 			cil_context_to_policy(out, fsuse->context, mls);
1699 			fprintf(out,";\n");
1700 		}
1701 	}
1702 }
1703 
cil_genfscons_to_policy(FILE * out,struct cil_sort * genfscons,int mls)1704 static void cil_genfscons_to_policy(FILE *out, struct cil_sort *genfscons, int mls)
1705 {
1706 	unsigned i;
1707 	struct cil_genfscon *genfscon;
1708 
1709 	for (i=0; i<genfscons->count; i++) {
1710 		genfscon = genfscons->array[i];
1711 		fprintf(out, "genfscon %s %s ", genfscon->fs_str, genfscon->path_str);
1712 		cil_context_to_policy(out, genfscon->context, mls);
1713 		fprintf(out, "\n");
1714 	}
1715 }
1716 
cil_ibpkeycons_to_policy(FILE * out,struct cil_sort * ibpkeycons,int mls)1717 static void cil_ibpkeycons_to_policy(FILE *out, struct cil_sort *ibpkeycons, int mls)
1718 {
1719 	uint32_t i = 0;
1720 
1721 	for (i = 0; i < ibpkeycons->count; i++) {
1722 		struct cil_ibpkeycon *ibpkeycon = (struct cil_ibpkeycon *)ibpkeycons->array[i];
1723 
1724 		fprintf(out, "ibpkeycon %s ", ibpkeycon->subnet_prefix_str);
1725 		fprintf(out, "%d ", ibpkeycon->pkey_low);
1726 		fprintf(out, "%d ", ibpkeycon->pkey_high);
1727 		cil_context_to_policy(out, ibpkeycon->context, mls);
1728 		fprintf(out, "\n");
1729 	}
1730 }
1731 
cil_ibendportcons_to_policy(FILE * out,struct cil_sort * ibendportcons,int mls)1732 static void cil_ibendportcons_to_policy(FILE *out, struct cil_sort *ibendportcons, int mls)
1733 {
1734 	uint32_t i;
1735 
1736 	for (i = 0; i < ibendportcons->count; i++) {
1737 		struct cil_ibendportcon *ibendportcon = (struct cil_ibendportcon *)ibendportcons->array[i];
1738 
1739 		fprintf(out, "ibendportcon %s ", ibendportcon->dev_name_str);
1740 		fprintf(out, "%u ", ibendportcon->port);
1741 		cil_context_to_policy(out, ibendportcon->context, mls);
1742 		fprintf(out, "\n");
1743 	}
1744 }
1745 
cil_portcons_to_policy(FILE * out,struct cil_sort * portcons,int mls)1746 static void cil_portcons_to_policy(FILE *out, struct cil_sort *portcons, int mls)
1747 {
1748 	unsigned i;
1749 	struct cil_portcon *portcon;
1750 
1751 	for (i=0; i<portcons->count; i++) {
1752 		portcon = portcons->array[i];
1753 		fprintf(out, "portcon ");
1754 		if (portcon->proto == CIL_PROTOCOL_UDP) {
1755 			fprintf(out, "udp ");
1756 		} else if (portcon->proto == CIL_PROTOCOL_TCP) {
1757 			fprintf(out, "tcp ");
1758 		} else if (portcon->proto == CIL_PROTOCOL_DCCP) {
1759 			fprintf(out, "dccp ");
1760 		}
1761 		if (portcon->port_low == portcon->port_high) {
1762 			fprintf(out, "%d ", portcon->port_low);
1763 		} else {
1764 			fprintf(out, "%d-%d ", portcon->port_low, portcon->port_high);
1765 		}
1766 		cil_context_to_policy(out, portcon->context, mls);
1767 		fprintf(out, "\n");
1768 	}
1769 }
1770 
cil_netifcons_to_policy(FILE * out,struct cil_sort * netifcons,int mls)1771 static void cil_netifcons_to_policy(FILE *out, struct cil_sort *netifcons, int mls)
1772 {
1773 	unsigned i;
1774 	struct cil_netifcon *netifcon;
1775 
1776 	for (i=0; i<netifcons->count; i++) {
1777 		netifcon = netifcons->array[i];
1778 		fprintf(out, "netifcon %s ", netifcon->interface_str);
1779 		cil_context_to_policy(out, netifcon->if_context, mls);
1780 		fprintf(out, " ");
1781 		cil_context_to_policy(out, netifcon->packet_context, mls);
1782 		fprintf(out, "\n");
1783 	}
1784 }
1785 
cil_nodecons_to_policy(FILE * out,struct cil_sort * nodecons,int mls)1786 static void cil_nodecons_to_policy(FILE *out, struct cil_sort *nodecons, int mls)
1787 {
1788 	unsigned i;
1789 	struct cil_nodecon *nodecon;
1790 	char *addr, *mask;
1791 
1792 	for (i=0; i<nodecons->count; i++) {
1793 		nodecon = nodecons->array[i];
1794 		fprintf(out, "nodecon ");
1795 
1796 		if (nodecon->addr->family == AF_INET) {
1797 			errno = 0;
1798 			addr = cil_malloc(INET_ADDRSTRLEN);
1799 			inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, addr, INET_ADDRSTRLEN);
1800 			if (errno == 0) {
1801 				fprintf(out, "%s ",addr);
1802 			} else {
1803 				fprintf(out, "[INVALID] ");
1804 			}
1805 			free(addr);
1806 
1807 			errno = 0;
1808 			mask = cil_malloc(INET_ADDRSTRLEN);
1809 			inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, mask, INET_ADDRSTRLEN);
1810 			if (errno == 0) {
1811 				fprintf(out, "%s ",mask);
1812 			} else {
1813 				fprintf(out, "[INVALID] ");
1814 			}
1815 			free(mask);
1816 		} else {
1817 			errno = 0;
1818 			addr = cil_malloc(INET6_ADDRSTRLEN);
1819 			inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, addr, INET6_ADDRSTRLEN);
1820 			if (errno == 0) {
1821 				fprintf(out, "%s ",addr);
1822 			} else {
1823 				fprintf(out, "[INVALID] ");
1824 			}
1825 			free(addr);
1826 
1827 			errno = 0;
1828 			mask = cil_malloc(INET6_ADDRSTRLEN);
1829 			inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, mask, INET6_ADDRSTRLEN);
1830 			if (errno == 0) {
1831 				fprintf(out, "%s ",mask);
1832 			} else {
1833 				fprintf(out, "[INVALID] ");
1834 			}
1835 			free(mask);
1836 		}
1837 
1838 		cil_context_to_policy(out, nodecon->context, mls);
1839 		fprintf(out, "\n");
1840 	}
1841 }
1842 
cil_pirqcons_to_policy(FILE * out,struct cil_sort * pirqcons,int mls)1843 static void cil_pirqcons_to_policy(FILE *out, struct cil_sort *pirqcons, int mls)
1844 {
1845 	unsigned i;
1846 	struct cil_pirqcon *pirqcon;
1847 
1848 	for (i = 0; i<pirqcons->count; i++) {
1849 		pirqcon = pirqcons->array[i];
1850 		fprintf(out, "pirqcon %d ", pirqcon->pirq);
1851 		cil_context_to_policy(out, pirqcon->context, mls);
1852 		fprintf(out, ";\n");
1853 	}
1854 }
1855 
cil_iomemcons_to_policy(FILE * out,struct cil_sort * iomemcons,int mls)1856 static void cil_iomemcons_to_policy(FILE *out, struct cil_sort *iomemcons, int mls)
1857 {
1858 	unsigned i;
1859 	struct cil_iomemcon *iomemcon;
1860 
1861 	for (i = 0; i<iomemcons->count; i++) {
1862 		iomemcon = iomemcons->array[i];
1863 		if (iomemcon->iomem_low == iomemcon->iomem_high) {
1864 			fprintf(out, "iomemcon %"PRIx64" ", iomemcon->iomem_low);
1865 		} else {
1866 			fprintf(out, "iomemcon %"PRIx64"-%"PRIx64" ", iomemcon->iomem_low, iomemcon->iomem_high);
1867 		}
1868 		cil_context_to_policy(out, iomemcon->context, mls);
1869 		fprintf(out, ";\n");
1870 	}
1871 }
1872 
cil_ioportcons_to_policy(FILE * out,struct cil_sort * ioportcons,int mls)1873 static void cil_ioportcons_to_policy(FILE *out, struct cil_sort *ioportcons, int mls)
1874 {
1875 	unsigned i;
1876 	struct cil_ioportcon *ioportcon;
1877 
1878 	for (i = 0; i < ioportcons->count; i++) {
1879 		ioportcon = ioportcons->array[i];
1880 		fprintf(out, "ioportcon 0x%x-0x%x ", ioportcon->ioport_low, ioportcon->ioport_high);
1881 		cil_context_to_policy(out, ioportcon->context, mls);
1882 		fprintf(out, ";\n");
1883 	}
1884 }
1885 
cil_pcidevicecons_to_policy(FILE * out,struct cil_sort * pcidevicecons,int mls)1886 static void cil_pcidevicecons_to_policy(FILE *out, struct cil_sort *pcidevicecons, int mls)
1887 {
1888 	unsigned i;
1889 	struct cil_pcidevicecon *pcidevicecon;
1890 
1891 	for (i = 0; i < pcidevicecons->count; i++) {
1892 		pcidevicecon = pcidevicecons->array[i];
1893 		fprintf(out, "pcidevicecon 0x%x ", pcidevicecon->dev);
1894 		cil_context_to_policy(out, pcidevicecon->context, mls);
1895 		fprintf(out, ";\n");
1896 	}
1897 }
1898 
cil_devicetreecons_to_policy(FILE * out,struct cil_sort * devicetreecons,int mls)1899 static void cil_devicetreecons_to_policy(FILE *out, struct cil_sort *devicetreecons, int mls)
1900 {
1901 	unsigned i;
1902 	struct cil_devicetreecon *devicetreecon;
1903 
1904 	for (i = 0; i < devicetreecons->count; i++) {
1905 		devicetreecon = devicetreecons->array[i];
1906 		fprintf(out, "devicetreecon %s ", devicetreecon->path);
1907 		cil_context_to_policy(out, devicetreecon->context, mls);
1908 		fprintf(out, ";\n");
1909 	}
1910 }
1911 
cil_gen_policy(FILE * out,struct cil_db * db)1912 void cil_gen_policy(FILE *out, struct cil_db *db)
1913 {
1914 	unsigned i;
1915 	struct cil_tree_node *head = db->ast->root;
1916 	struct cil_list *lists[CIL_LIST_NUM_LISTS];
1917 
1918 	for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
1919 		cil_list_init(&lists[i], CIL_LIST);
1920 	}
1921 
1922 	cil_gather_statements(head, lists);
1923 
1924 	cil_class_decls_to_policy(out, db->classorder);
1925 
1926 	cil_sid_decls_to_policy(out, db->sidorder);
1927 
1928 	cil_commons_to_policy(out, lists[CIL_LIST_COMMON]);
1929 	cil_classes_to_policy(out, db->classorder);
1930 
1931 	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_USER], "default_user");
1932 	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_ROLE], "default_role");
1933 	cil_defaults_to_policy(out, lists[CIL_LIST_DEFAULT_TYPE], "default_type");
1934 
1935 	if (db->mls == CIL_TRUE) {
1936 		cil_default_ranges_to_policy(out, lists[CIL_LIST_DEFAULT_RANGE]);
1937 		cil_sensitivities_to_policy(out, db->sensitivityorder, lists[CIL_LIST_SENSALIAS]);
1938 		cil_dominance_to_policy(out, db->sensitivityorder);
1939 		cil_categories_to_policy(out, db->catorder, lists[CIL_LIST_CATALIAS]);
1940 		cil_levels_to_policy(out, db->sensitivityorder);
1941 		cil_mlsconstrains_to_policy(out, db, lists[CIL_LIST_MLSCONSTRAIN]);
1942 		cil_validatetrans_to_policy(out, db, lists[CIL_LIST_MLSVALIDATETRANS], CIL_KEY_MLSVALIDATETRANS);
1943 	}
1944 
1945 	cil_simple_rules_to_policy(out, lists[CIL_LIST_POLICYCAP], CIL_KEY_POLICYCAP);
1946 
1947 	cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPEATTRIBUTE], "attribute");
1948 	cil_simple_rules_to_policy(out, lists[CIL_LIST_ROLEATTRIBUTE], "attribute_role");
1949 
1950 	cil_bools_to_policy(out, lists[CIL_LIST_BOOL]);
1951 
1952 	cil_simple_rules_to_policy(out, lists[CIL_LIST_TYPE], "type");
1953 	cil_typealiases_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEALIAS]);
1954 	cil_typebounds_to_policy(out, lists[CIL_LIST_TYPE]);
1955 	cil_typeattributes_to_policy(out, lists[CIL_LIST_TYPE], lists[CIL_LIST_TYPEATTRIBUTE]);
1956 	cil_te_rules_to_policy(out, head, db->mls);
1957 
1958 	cil_roles_to_policy(out, lists[CIL_LIST_ROLE]);
1959 	cil_role_types_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_TYPE]);
1960 	cil_roleattributes_to_policy(out, lists[CIL_LIST_ROLE], lists[CIL_LIST_ROLEATTRIBUTE]);
1961 	cil_roleallows_to_policy(out, lists[CIL_LIST_ROLEALLOW]);
1962 	cil_roletransitions_to_policy(out, lists[CIL_LIST_ROLETRANSITION]);
1963 
1964 	cil_users_to_policy(out, db->mls, lists[CIL_LIST_USER], lists[CIL_LIST_ROLE]);
1965 
1966 	cil_constrains_to_policy(out, db, lists[CIL_LIST_CONSTRAINT]);
1967 	cil_validatetrans_to_policy(out, db, lists[CIL_LIST_VALIDATETRANS], CIL_KEY_VALIDATETRANS);
1968 
1969 	cil_sid_contexts_to_policy(out, db->sidorder, db->mls);
1970 	cil_fsuses_to_policy(out, db->fsuse, db->mls);
1971 	cil_genfscons_to_policy(out, db->genfscon, db->mls);
1972 	cil_portcons_to_policy(out, db->portcon, db->mls);
1973 	cil_netifcons_to_policy(out, db->netifcon, db->mls);
1974 	cil_ibpkeycons_to_policy(out, db->ibpkeycon, db->mls);
1975 	cil_ibendportcons_to_policy(out, db->ibendportcon, db->mls);
1976 	cil_nodecons_to_policy(out, db->nodecon, db->mls);
1977 	cil_pirqcons_to_policy(out, db->pirqcon, db->mls);
1978 	cil_iomemcons_to_policy(out, db->iomemcon, db->mls);
1979 	cil_ioportcons_to_policy(out, db->ioportcon, db->mls);
1980 	cil_pcidevicecons_to_policy(out, db->pcidevicecon, db->mls);
1981 	cil_devicetreecons_to_policy(out, db->devicetreecon, db->mls);
1982 
1983 	for (i=0; i<CIL_LIST_NUM_LISTS; i++) {
1984 		cil_list_destroy(&lists[i], CIL_FALSE);
1985 	}
1986 
1987 }
1988