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_log.h"
43 #include "cil_mem.h"
44 #include "cil_tree.h"
45 #include "cil_list.h"
46 #include "cil_policy.h"
47 #include "cil_symtab.h"
48 #include "cil_strpool.h"
49 
50 #define SEPOL_DONE			555
51 
52 #define CLASS_DECL			0
53 #define ISIDS				1
54 #define COMMONS				2
55 #define CLASSES				3
56 #define INTERFACES			4
57 #define SENS				5
58 #define CATS				6
59 #define LEVELS				7
60 #define CONSTRAINS			8
61 #define TYPEATTRTYPES			9
62 #define ALIASES				10
63 #define ALLOWS				11
64 #define CONDS				12
65 #define USERROLES			13
66 #define SIDS				14
67 #define NETIFCONS			15
68 
69 #define BUFFER				1024
70 #define NUM_POLICY_FILES		16
71 
72 struct cil_args_genpolicy {
73 	struct cil_list *users;
74 	struct cil_list *sens;
75 	struct cil_list *cats;
76 	FILE **file_arr;
77 };
78 
79 struct cil_args_booleanif {
80 	FILE **file_arr;
81 	uint32_t *file_index;
82 };
83 
84 
85 int cil_expr_to_policy(FILE **file_arr, uint32_t file_index, struct cil_list *expr);
86 
cil_combine_policy(FILE ** file_arr,FILE * policy_file)87 int cil_combine_policy(FILE **file_arr, FILE *policy_file)
88 {
89 	char temp[BUFFER];
90 	int i, rc, rc_read, rc_write;
91 
92 	for(i=0; i<NUM_POLICY_FILES; i++) {
93 		fseek(file_arr[i], 0, SEEK_SET);
94 		while (!feof(file_arr[i])) {
95 			rc_read = fread(temp, 1, BUFFER, file_arr[i]);
96 			if (rc_read == 0 && ferror(file_arr[i])) {
97 				cil_log(CIL_ERR, "Error reading temp policy file\n");
98 				return SEPOL_ERR;
99 			}
100 			rc_write = 0;
101 			while (rc_read > rc_write) {
102 				rc = fwrite(temp+rc_write, 1, rc_read-rc_write, policy_file);
103 				rc_write += rc;
104 				if (rc == 0 && ferror(file_arr[i])) {
105 					cil_log(CIL_ERR, "Error writing to policy.conf\n");
106 					return SEPOL_ERR;
107 				}
108 			}
109 		}
110 	}
111 
112 	return SEPOL_OK;
113 }
114 
cil_portcon_to_policy(FILE ** file_arr,struct cil_sort * sort)115 int cil_portcon_to_policy(FILE **file_arr, struct cil_sort *sort)
116 {
117 	uint32_t i = 0;
118 
119 	for (i=0; i<sort->count; i++) {
120 		struct cil_portcon *portcon = (struct cil_portcon*)sort->array[i];
121 		fprintf(file_arr[NETIFCONS], "portcon ");
122 		if (portcon->proto == CIL_PROTOCOL_UDP) {
123 			fprintf(file_arr[NETIFCONS], "udp ");
124 		} else if (portcon->proto == CIL_PROTOCOL_TCP) {
125 			fprintf(file_arr[NETIFCONS], "tcp ");
126 		}
127 		fprintf(file_arr[NETIFCONS], "%d ", portcon->port_low);
128 		fprintf(file_arr[NETIFCONS], "%d ", portcon->port_high);
129 		cil_context_to_policy(file_arr, NETIFCONS, portcon->context);
130 		fprintf(file_arr[NETIFCONS], ";\n");
131 	}
132 
133 	return SEPOL_OK;
134 }
135 
cil_genfscon_to_policy(FILE ** file_arr,struct cil_sort * sort)136 int cil_genfscon_to_policy(FILE **file_arr, struct cil_sort *sort)
137 {
138 	uint32_t i = 0;
139 
140 	for (i=0; i<sort->count; i++) {
141 		struct cil_genfscon *genfscon = (struct cil_genfscon*)sort->array[i];
142 		fprintf(file_arr[NETIFCONS], "genfscon %s ", genfscon->fs_str);
143 		fprintf(file_arr[NETIFCONS], "%s ", genfscon->path_str);
144 		cil_context_to_policy(file_arr, NETIFCONS, genfscon->context);
145 		fprintf(file_arr[NETIFCONS], ";\n");
146 	}
147 
148 	return SEPOL_OK;
149 }
150 
cil_netifcon_to_policy(FILE ** file_arr,struct cil_sort * sort)151 int cil_netifcon_to_policy(FILE **file_arr, struct cil_sort *sort)
152 {
153 	uint32_t i = 0;
154 
155 	for (i=0; i<sort->count; i++) {
156 		struct cil_netifcon *netifcon = (struct cil_netifcon*)sort->array[i];
157 		fprintf(file_arr[NETIFCONS], "netifcon %s ", netifcon->interface_str);
158 		cil_context_to_policy(file_arr, NETIFCONS, netifcon->if_context);
159 		fprintf(file_arr[NETIFCONS], " ");
160 		cil_context_to_policy(file_arr, NETIFCONS, netifcon->packet_context);
161 		fprintf(file_arr[NETIFCONS], ";\n");
162 	}
163 
164 	return SEPOL_OK;
165 }
166 
cil_nodecon_to_policy(FILE ** file_arr,struct cil_sort * sort)167 int cil_nodecon_to_policy(FILE **file_arr, struct cil_sort *sort)
168 {
169 	uint32_t i = 0;
170 	int rc = SEPOL_ERR;
171 
172 	for (i=0; i<sort->count; i++) {
173 		struct cil_nodecon *nodecon = (struct cil_nodecon*)sort->array[i];
174 		char *buf = NULL;
175 		errno = 0;
176 		if (nodecon->addr->family == AF_INET) {
177 			buf = cil_malloc(INET_ADDRSTRLEN);
178 			inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v4, buf, INET_ADDRSTRLEN);
179 		} else if (nodecon->addr->family == AF_INET6) {
180 			buf = cil_malloc(INET6_ADDRSTRLEN);
181 			inet_ntop(nodecon->addr->family, &nodecon->addr->ip.v6, buf, INET6_ADDRSTRLEN);
182 		}
183 
184 		if (errno != 0) {
185 			cil_log(CIL_INFO, "Failed to convert ip address to string\n");
186 			rc = SEPOL_ERR;
187 			goto exit;
188 		}
189 
190 		fprintf(file_arr[NETIFCONS], "nodecon %s ", buf);
191 		free(buf);
192 
193 		if (nodecon->mask->family == AF_INET) {
194 			buf = cil_malloc(INET_ADDRSTRLEN);
195 			inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v4, buf, INET_ADDRSTRLEN);
196 		} else if (nodecon->mask->family == AF_INET6) {
197 			buf = cil_malloc(INET6_ADDRSTRLEN);
198 			inet_ntop(nodecon->mask->family, &nodecon->mask->ip.v6, buf, INET6_ADDRSTRLEN);
199 		}
200 
201 		if (errno != 0) {
202 			cil_log(CIL_INFO, "Failed to convert mask to string\n");
203 			rc = SEPOL_ERR;
204 			goto exit;
205 		}
206 
207 		fprintf(file_arr[NETIFCONS], "%s ", buf);
208 		free(buf);
209 
210 		cil_context_to_policy(file_arr, NETIFCONS, nodecon->context);
211 		fprintf(file_arr[NETIFCONS], ";\n");
212 	}
213 
214 	return SEPOL_OK;
215 
216 exit:
217 	return rc;
218 }
219 
220 
cil_pirqcon_to_policy(FILE ** file_arr,struct cil_sort * sort)221 int cil_pirqcon_to_policy(FILE **file_arr, struct cil_sort *sort)
222 {
223 	uint32_t i = 0;
224 
225 	for (i = 0; i < sort->count; i++) {
226 		struct cil_pirqcon *pirqcon = (struct cil_pirqcon*)sort->array[i];
227 		fprintf(file_arr[NETIFCONS], "pirqcon %d ", pirqcon->pirq);
228 		cil_context_to_policy(file_arr, NETIFCONS, pirqcon->context);
229 		fprintf(file_arr[NETIFCONS], ";\n");
230 	}
231 
232 	return SEPOL_OK;
233 }
cil_iomemcon_to_policy(FILE ** file_arr,struct cil_sort * sort)234 int cil_iomemcon_to_policy(FILE **file_arr, struct cil_sort *sort)
235 {
236 	uint32_t i = 0;
237 
238 	for (i = 0; i < sort->count; i++) {
239 		struct cil_iomemcon *iomemcon = (struct cil_iomemcon*)sort->array[i];
240 		fprintf(file_arr[NETIFCONS], "iomemcon %"PRId64"-%"PRId64" ", iomemcon->iomem_low, iomemcon->iomem_high);
241 		cil_context_to_policy(file_arr, NETIFCONS, iomemcon->context);
242 		fprintf(file_arr[NETIFCONS], ";\n");
243 	}
244 
245 	return SEPOL_OK;
246 }
247 
cil_ioportcon_to_policy(FILE ** file_arr,struct cil_sort * sort)248 int cil_ioportcon_to_policy(FILE **file_arr, struct cil_sort *sort)
249 {
250 	uint32_t i = 0;
251 
252 	for (i = 0; i < sort->count; i++) {
253 		struct cil_ioportcon *ioportcon = (struct cil_ioportcon*)sort->array[i];
254 		fprintf(file_arr[NETIFCONS], "ioportcon %d-%d ", ioportcon->ioport_low, ioportcon->ioport_high);
255 		cil_context_to_policy(file_arr, NETIFCONS, ioportcon->context);
256 		fprintf(file_arr[NETIFCONS], ";\n");
257 	}
258 
259 	return SEPOL_OK;
260 }
261 
cil_pcidevicecon_to_policy(FILE ** file_arr,struct cil_sort * sort)262 int cil_pcidevicecon_to_policy(FILE **file_arr, struct cil_sort *sort)
263 {
264 	uint32_t i = 0;
265 
266 	for (i = 0; i < sort->count; i++) {
267 		struct cil_pcidevicecon *pcidevicecon = (struct cil_pcidevicecon*)sort->array[i];
268 		fprintf(file_arr[NETIFCONS], "pcidevicecon %d ", pcidevicecon->dev);
269 		cil_context_to_policy(file_arr, NETIFCONS, pcidevicecon->context);
270 		fprintf(file_arr[NETIFCONS], ";\n");
271 	}
272 
273 	return SEPOL_OK;
274 }
275 
cil_fsuse_to_policy(FILE ** file_arr,struct cil_sort * sort)276 int cil_fsuse_to_policy(FILE **file_arr, struct cil_sort *sort)
277 {
278 	uint32_t i = 0;
279 
280 	for (i=0; i<sort->count; i++) {
281 		struct cil_fsuse *fsuse = (struct cil_fsuse*)sort->array[i];
282 		if (fsuse->type == CIL_FSUSE_XATTR) {
283 			fprintf(file_arr[NETIFCONS], "fs_use_xattr ");
284 		} else if (fsuse->type == CIL_FSUSE_TASK) {
285 			fprintf(file_arr[NETIFCONS], "fs_use_task ");
286 		} else if (fsuse->type == CIL_FSUSE_TRANS) {
287 			fprintf(file_arr[NETIFCONS], "fs_use_trans ");
288 		} else {
289 			return SEPOL_ERR;
290 		}
291 		fprintf(file_arr[NETIFCONS], "%s ", fsuse->fs_str);
292 		cil_context_to_policy(file_arr, NETIFCONS, fsuse->context);
293 		fprintf(file_arr[NETIFCONS], ";\n");
294 	}
295 
296 	return SEPOL_OK;
297 }
298 
cil_multimap_insert(struct cil_list * list,struct cil_symtab_datum * key,struct cil_symtab_datum * value,uint32_t key_flavor,uint32_t val_flavor)299 int cil_multimap_insert(struct cil_list *list, struct cil_symtab_datum *key, struct cil_symtab_datum *value, uint32_t key_flavor, uint32_t val_flavor)
300 {
301 	struct cil_list_item *curr_key;
302 	struct cil_multimap_item *new_data;
303 
304 	if (list == NULL || key == NULL) {
305 		return SEPOL_ERR;
306 	}
307 
308 	cil_list_for_each(curr_key, list) {
309 		struct cil_multimap_item *curr_multimap_item = curr_key->data;
310 		if (curr_multimap_item != NULL) {
311 			if (curr_multimap_item->key != NULL && curr_multimap_item->key == key) {
312 				struct cil_list_item *curr_value;
313 				cil_list_for_each(curr_value, curr_multimap_item->values) {
314 					if (curr_value == (struct cil_list_item*)value) {
315 						return SEPOL_OK;;
316 					}
317 				}
318 				cil_list_append(curr_multimap_item->values, val_flavor, value);
319 			}
320 		} else {
321 			cil_log(CIL_INFO, "No data in list item\n");
322 			return SEPOL_ERR;
323 		}
324 	}
325 
326 	new_data = cil_malloc(sizeof(*new_data));
327 	new_data->key = key;
328 	cil_list_init(&new_data->values, CIL_LIST_ITEM);
329 	if (value != NULL) {
330 		cil_list_append(new_data->values, val_flavor, value);
331 	}
332 	cil_list_append(list, key_flavor, new_data);
333 
334 	return SEPOL_OK;
335 }
336 
cil_userrole_to_policy(FILE ** file_arr,struct cil_list * userroles)337 int cil_userrole_to_policy(FILE **file_arr, struct cil_list *userroles)
338 {
339 	struct cil_list_item *current_user;
340 
341 	if (userroles == NULL) {
342 		return SEPOL_OK;
343 	}
344 
345 	cil_list_for_each(current_user, userroles) {
346 		struct cil_multimap_item *user_multimap_item = current_user->data;
347 		struct cil_list_item *current_role;
348 		if (user_multimap_item->values->head == NULL) {
349 			cil_log(CIL_INFO, "No roles associated with user %s\n",
350 					user_multimap_item->key->name);
351 			return SEPOL_ERR;
352 		}
353 
354 		fprintf(file_arr[USERROLES], "user %s roles {", user_multimap_item->key->name);
355 
356 		cil_list_for_each(current_role, user_multimap_item->values) {
357 			fprintf(file_arr[USERROLES], " %s", ((struct cil_role*)current_role->data)->datum.name);
358 		}
359 		fprintf(file_arr[USERROLES], " };\n");
360 	}
361 
362 	return SEPOL_OK;
363 }
364 
cil_cat_to_policy(FILE ** file_arr,struct cil_list * cats)365 int cil_cat_to_policy(FILE **file_arr, struct cil_list *cats)
366 {
367 	struct cil_list_item *curr_cat;
368 
369 	if (cats == NULL) {
370 		return SEPOL_OK;
371 	}
372 
373 	cil_list_for_each(curr_cat, cats) {
374 		struct cil_multimap_item *cat_multimap_item = curr_cat->data;
375 		fprintf(file_arr[CATS], "category %s", cat_multimap_item->key->name);
376 		if (cat_multimap_item->values->head == NULL) {
377 			fprintf(file_arr[CATS], ";\n");
378 		} else {
379 			struct cil_list_item *curr_catalias;
380 			fprintf(file_arr[CATS], " alias");
381 			cil_list_for_each(curr_catalias, cat_multimap_item->values) {
382 				fprintf(file_arr[CATS], " %s", ((struct cil_cat*)curr_catalias->data)->datum.name);
383 			}
384 			fprintf(file_arr[CATS], ";\n");
385 		}
386 	}
387 
388 	return SEPOL_OK;
389 }
390 
cil_sens_to_policy(FILE ** file_arr,struct cil_list * sens)391 int cil_sens_to_policy(FILE **file_arr, struct cil_list *sens)
392 {
393 	struct cil_list_item *curr_sens;
394 
395 	if (sens == NULL) {
396 		return SEPOL_OK;
397 	}
398 
399 	cil_list_for_each(curr_sens, sens) {
400 		struct cil_multimap_item *sens_multimap_item = curr_sens->data;
401 		fprintf(file_arr[SENS], "sensitivity %s", sens_multimap_item->key->name);
402 		if (sens_multimap_item->values->head == NULL)
403 			fprintf(file_arr[SENS], ";\n");
404 		else {
405 			struct cil_list_item *curr_sensalias;
406 			fprintf(file_arr[SENS], " alias");
407 			cil_list_for_each(curr_sensalias, sens_multimap_item->values) {
408 				fprintf(file_arr[SENS], " %s", ((struct cil_sens*)curr_sensalias->data)->datum.name);
409 			}
410 			fprintf(file_arr[SENS], ";\n");
411 		}
412 	}
413 
414 	return SEPOL_OK;
415 }
416 
cil_cats_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_cats * cats)417 void cil_cats_to_policy(FILE **file_arr, uint32_t file_index, struct cil_cats *cats)
418 {
419 	cil_expr_to_policy(file_arr, file_index, cats->datum_expr);
420 }
421 
cil_level_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_level * level)422 void cil_level_to_policy(FILE **file_arr, uint32_t file_index, struct cil_level *level)
423 {
424 	char *sens_str = level->sens->datum.name;
425 
426 	fprintf(file_arr[file_index], "%s", sens_str);
427 	if (level->cats != NULL) {
428 		fprintf(file_arr[file_index], ":");
429 		cil_cats_to_policy(file_arr, file_index, level->cats);
430 	}
431 }
432 
cil_levelrange_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_levelrange * lvlrange)433 void cil_levelrange_to_policy(FILE **file_arr, uint32_t file_index, struct cil_levelrange *lvlrange)
434 {
435 	struct cil_level *low = lvlrange->low;
436 	struct cil_level *high = lvlrange->high;
437 
438 	cil_level_to_policy(file_arr, file_index, low);
439 	fprintf(file_arr[file_index], "-");
440 	cil_level_to_policy(file_arr, file_index, high);
441 }
442 
cil_context_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_context * context)443 void cil_context_to_policy(FILE **file_arr, uint32_t file_index, struct cil_context *context)
444 {
445 	char *user_str = ((struct cil_symtab_datum*)context->user)->name;
446 	char *role_str = ((struct cil_symtab_datum*)context->role)->name;
447 	char *type_str = ((struct cil_symtab_datum*)context->type)->name;
448 	struct cil_levelrange *lvlrange = context->range;
449 
450 	fprintf(file_arr[file_index], "%s:%s:%s:", user_str, role_str, type_str);
451 	cil_levelrange_to_policy(file_arr, file_index, lvlrange);
452 }
453 
cil_perms_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_list * list)454 void cil_perms_to_policy(FILE **file_arr, uint32_t file_index, struct cil_list *list)
455 {
456 	struct cil_list_item *curr;
457 
458 	fprintf(file_arr[file_index], " {");
459 	cil_list_for_each(curr, list) {
460 		switch (curr->flavor) {
461 		case CIL_LIST:
462 			cil_perms_to_policy(file_arr, file_index, curr->data);
463 			break;
464 		case CIL_STRING:
465 			fprintf(file_arr[file_index], " %s", (char *)curr->data);
466 			break;
467 		case CIL_DATUM:
468 			fprintf(file_arr[file_index], " %s", ((struct cil_symtab_datum *)curr->data)->name);
469 			break;
470 		case CIL_OP: {
471 			enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data);
472 			char *op_str = NULL;
473 
474 			switch (op_flavor) {
475 			case CIL_AND:
476 				op_str = CIL_KEY_AND;
477 				break;
478 			case CIL_OR:
479 				op_str = CIL_KEY_OR;
480 				break;
481 			case CIL_NOT:
482 				op_str = CIL_KEY_NOT;
483 				break;
484 			case CIL_ALL:
485 				op_str = CIL_KEY_ALL;
486 				break;
487 			case CIL_XOR:
488 				op_str = CIL_KEY_XOR;
489 				break;
490 			default:
491 				cil_log(CIL_ERR, "Unknown operator in expression\n");
492 				break;
493 			}
494 			fprintf(file_arr[file_index], " %s", op_str);
495 			break;
496 		}
497 		default:
498 			cil_log(CIL_ERR, "Unknown flavor in expression\n");
499 			break;
500 		}
501 	}
502 	fprintf(file_arr[file_index], " }");
503 }
504 
cil_constrain_to_policy_helper(FILE ** file_arr,char * kind,struct cil_list * classperms,struct cil_list * expr)505 void cil_constrain_to_policy_helper(FILE **file_arr, char *kind, struct cil_list *classperms, struct cil_list *expr)
506 {
507 	struct cil_list_item *curr;
508 
509 	cil_list_for_each(curr, classperms) {
510 		if (curr->flavor == CIL_CLASSPERMS) {
511 			struct cil_classperms *cp = curr->data;
512 			if (FLAVOR(cp->class) == CIL_CLASS) {
513 				fprintf(file_arr[CONSTRAINS], "%s %s", kind, cp->class->datum.name);
514 				cil_perms_to_policy(file_arr, CONSTRAINS, cp->perms);
515 				fprintf(file_arr[CONSTRAINS], "\n\t");
516 				cil_expr_to_policy(file_arr, CONSTRAINS, expr);
517 				fprintf(file_arr[CONSTRAINS], ";\n");
518 			} else { /* MAP */
519 				struct cil_list_item *i = NULL;
520 				cil_list_for_each(i, cp->perms) {
521 					struct cil_perm *cmp = i->data;
522 					cil_constrain_to_policy_helper(file_arr, kind, cmp->classperms, expr);
523 				}
524 			}
525 		} else { /* SET */
526 			struct cil_classperms_set *cp_set = curr->data;
527 			struct cil_classpermission *cp = cp_set->set;
528 			cil_constrain_to_policy_helper(file_arr, kind, cp->classperms, expr);
529 		}
530 	}
531 }
532 
cil_constrain_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_constrain * cons,enum cil_flavor flavor)533 void cil_constrain_to_policy(FILE **file_arr, __attribute__((unused)) uint32_t file_index, struct cil_constrain *cons, enum cil_flavor flavor)
534 {
535 	char *kind = NULL;
536 
537 	if (flavor == CIL_CONSTRAIN) {
538 		kind = CIL_KEY_CONSTRAIN;
539 	} else if (flavor == CIL_MLSCONSTRAIN) {
540 		kind = CIL_KEY_MLSCONSTRAIN;
541 	}
542 
543 	cil_constrain_to_policy_helper(file_arr, kind, cons->classperms, cons->datum_expr);
544 }
545 
cil_avrule_to_policy_helper(FILE ** file_arr,uint32_t file_index,const char * kind,const char * src,const char * tgt,struct cil_list * classperms)546 void cil_avrule_to_policy_helper(FILE **file_arr, uint32_t file_index, const char *kind, const char *src, const char *tgt, struct cil_list *classperms)
547 {
548 	struct cil_list_item *i;
549 
550 	cil_list_for_each(i, classperms) {
551 		if (i->flavor == CIL_CLASSPERMS) {
552 			struct cil_classperms *cp = i->data;
553 			if (FLAVOR(cp->class) == CIL_CLASS) {
554 				fprintf(file_arr[file_index], "%s %s %s: %s", kind, src, tgt, cp->class->datum.name);
555 				cil_perms_to_policy(file_arr, file_index, cp->perms);
556 				fprintf(file_arr[file_index], ";\n");
557 			} else { /* MAP */
558 				struct cil_list_item *j = NULL;
559 				cil_list_for_each(j, cp->perms) {
560 					struct cil_perm *cmp = j->data;
561 					cil_avrule_to_policy_helper(file_arr, file_index, kind, src, tgt, cmp->classperms);
562 				}
563 			}
564 		} else { /* SET */
565 			struct cil_list_item *j;
566 			struct cil_classperms_set *cp_set = i->data;
567 			struct cil_classpermission *cp = cp_set->set;
568 			cil_list_for_each(j, cp->classperms) {
569 				cil_avrule_to_policy_helper(file_arr, file_index, kind, src, tgt, j->data);
570 			}
571 		}
572 	}
573 }
574 
cil_avrule_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_avrule * rule)575 int cil_avrule_to_policy(FILE **file_arr, uint32_t file_index, struct cil_avrule *rule)
576 {
577 	const char *kind_str = NULL;
578 	const char *src_str = DATUM(rule->src)->name;
579 	const char *tgt_str = DATUM(rule->tgt)->name;
580 
581 
582 	switch (rule->rule_kind) {
583 	case CIL_AVRULE_ALLOWED:
584 		kind_str = "allow";
585 		break;
586 	case CIL_AVRULE_AUDITALLOW:
587 		kind_str = "auditallow";
588 		break;
589 	case CIL_AVRULE_DONTAUDIT:
590 		kind_str = "dontaudit";
591 		break;
592 	case CIL_AVRULE_NEVERALLOW:
593 		kind_str = "neverallow";
594 		break;
595 	default :
596 		cil_log(CIL_INFO, "Unknown avrule with kind=%d src=%s tgt=%s\n",
597 				rule->rule_kind, src_str, tgt_str);
598 		return SEPOL_ERR;
599 	}
600 
601 	cil_avrule_to_policy_helper(file_arr, file_index, kind_str, src_str, tgt_str, rule->classperms);
602 
603 	return SEPOL_OK;
604 }
605 
cil_typerule_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_type_rule * rule)606 int cil_typerule_to_policy(FILE **file_arr, __attribute__((unused)) uint32_t file_index, struct cil_type_rule *rule)
607 {
608 	char *src_str = ((struct cil_symtab_datum*)rule->src)->name;
609 	char *tgt_str = ((struct cil_symtab_datum*)rule->tgt)->name;
610 	char *obj_str = ((struct cil_symtab_datum*)rule->obj)->name;
611 	char *result_str = ((struct cil_symtab_datum*)rule->result)->name;
612 
613 	switch (rule->rule_kind) {
614 	case CIL_TYPE_TRANSITION:
615 		fprintf(file_arr[ALLOWS], "type_transition %s %s : %s %s;\n", src_str, tgt_str, obj_str, result_str);
616 		break;
617 	case CIL_TYPE_CHANGE:
618 		fprintf(file_arr[ALLOWS], "type_change %s %s : %s %s\n;", src_str, tgt_str, obj_str, result_str);
619 		break;
620 	case CIL_TYPE_MEMBER:
621 		fprintf(file_arr[ALLOWS], "type_member %s %s : %s %s;\n", src_str, tgt_str, obj_str, result_str);
622 		break;
623 	default:
624 		cil_log(CIL_INFO, "Unknown type_rule\n");
625 		return SEPOL_ERR;
626 	}
627 
628 	return SEPOL_OK;
629 }
630 
cil_nametypetransition_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_nametypetransition * nametypetrans)631 int cil_nametypetransition_to_policy(FILE **file_arr, uint32_t file_index, struct cil_nametypetransition *nametypetrans)
632 {
633 	char *src_str = ((struct cil_symtab_datum*)nametypetrans->src)->name;
634 	char *tgt_str = ((struct cil_symtab_datum*)nametypetrans->tgt)->name;
635 	char *obj_str = ((struct cil_symtab_datum*)nametypetrans->obj)->name;
636 	char *result_str = ((struct cil_symtab_datum*)nametypetrans->result)->name;
637 
638 	fprintf(file_arr[file_index], "type_transition %s %s : %s %s %s;\n", src_str, tgt_str, obj_str, result_str, nametypetrans->name_str);
639 	return SEPOL_OK;
640 }
641 
cil_expr_to_string(struct cil_list * expr,char ** out)642 static int cil_expr_to_string(struct cil_list *expr, char **out)
643 {
644 	int rc = SEPOL_ERR;
645 	struct cil_list_item *curr;
646 	char *stack[COND_EXPR_MAXDEPTH] = {};
647 	int pos = 0;
648 	int i;
649 
650 	cil_list_for_each(curr, expr) {
651 		if (pos > COND_EXPR_MAXDEPTH) {
652 			rc = SEPOL_ERR;
653 			goto exit;
654 		}
655 		switch (curr->flavor) {
656 		case CIL_LIST:
657 			rc = cil_expr_to_string(curr->data, &stack[pos]);
658 			if (rc != SEPOL_OK) {
659 				goto exit;
660 			}
661 			pos++;
662 			break;
663 		case CIL_STRING:
664 			stack[pos] = curr->data;
665 			pos++;
666 			break;
667 		case CIL_DATUM:
668 			stack[pos] = ((struct cil_symtab_datum *)curr->data)->name;
669 			pos++;
670 			break;
671 		case CIL_OP: {
672 			int len;
673 			char *expr_str;
674 			enum cil_flavor op_flavor = *((enum cil_flavor *)curr->data);
675 			char *op_str = NULL;
676 
677 			if (pos == 0) {
678 				rc = SEPOL_ERR;
679 				goto exit;
680 			}
681 			switch (op_flavor) {
682 			case CIL_AND:
683 				op_str = CIL_KEY_AND;
684 				break;
685 			case CIL_OR:
686 				op_str = CIL_KEY_OR;
687 				break;
688 			case CIL_NOT:
689 				op_str = CIL_KEY_NOT;
690 				break;
691 			case CIL_ALL:
692 				op_str = CIL_KEY_ALL;
693 				break;
694 			case CIL_EQ:
695 				op_str = CIL_KEY_EQ;
696 				break;
697 			case CIL_NEQ:
698 				op_str = CIL_KEY_NEQ;
699 				break;
700 			case CIL_XOR:
701 				op_str = CIL_KEY_XOR;
702 				break;
703 			case CIL_CONS_DOM:
704 				op_str = CIL_KEY_CONS_DOM;
705 				break;
706 			case CIL_CONS_DOMBY:
707 				op_str = CIL_KEY_CONS_DOMBY;
708 				break;
709 			case CIL_CONS_INCOMP:
710 				op_str = CIL_KEY_CONS_INCOMP;
711 				break;
712 			default:
713 				cil_log(CIL_ERR, "Unknown operator in expression\n");
714 				goto exit;
715 				break;
716 			}
717 			if (op_flavor == CIL_NOT) {
718 				len = strlen(stack[pos-1]) + strlen(op_str) + 4;
719 				expr_str = cil_malloc(len);
720 				snprintf(expr_str, len, "(%s %s)", op_str, stack[pos-1]);
721 				free(stack[pos-1]);
722 				stack[pos-1] = NULL;
723 				pos--;
724 			} else {
725 				if (pos < 2) {
726 					rc = SEPOL_ERR;
727 					goto exit;
728 				}
729 				len = strlen(stack[pos-1]) + strlen(stack[pos-2]) + strlen(op_str) + 5;
730 				expr_str = cil_malloc(len);
731 				snprintf(expr_str, len, "(%s %s %s)", stack[pos-1], op_str, stack[pos-2]);
732 				free(stack[pos-2]);
733 				free(stack[pos-1]);
734 				stack[pos-2] = NULL;
735 				stack[pos-1] = NULL;
736 				pos -= 2;
737 			}
738 			stack[pos] = expr_str;
739 			pos++;
740 			break;
741 		}
742 		case CIL_CONS_OPERAND: {
743 			enum cil_flavor operand_flavor = *((enum cil_flavor *)curr->data);
744 			char *operand_str = NULL;
745 			switch (operand_flavor) {
746 			case CIL_CONS_U1:
747 				operand_str = CIL_KEY_CONS_U1;
748 				break;
749 			case CIL_CONS_U2:
750 				operand_str = CIL_KEY_CONS_U2;
751 				break;
752 			case CIL_CONS_U3:
753 				operand_str = CIL_KEY_CONS_U3;
754 				break;
755 			case CIL_CONS_T1:
756 				operand_str = CIL_KEY_CONS_T1;
757 				break;
758 			case CIL_CONS_T2:
759 				operand_str = CIL_KEY_CONS_T2;
760 				break;
761 			case CIL_CONS_T3:
762 				operand_str = CIL_KEY_CONS_T3;
763 				break;
764 			case CIL_CONS_R1:
765 				operand_str = CIL_KEY_CONS_R1;
766 				break;
767 			case CIL_CONS_R2:
768 				operand_str = CIL_KEY_CONS_R2;
769 				break;
770 			case CIL_CONS_R3:
771 				operand_str = CIL_KEY_CONS_R3;
772 				break;
773 			case CIL_CONS_L1:
774 				operand_str = CIL_KEY_CONS_L1;
775 				break;
776 			case CIL_CONS_L2:
777 				operand_str = CIL_KEY_CONS_L2;
778 				break;
779 			case CIL_CONS_H1:
780 				operand_str = CIL_KEY_CONS_H1;
781 				break;
782 			case CIL_CONS_H2:
783 				operand_str = CIL_KEY_CONS_H2;
784 				break;
785 			default:
786 				cil_log(CIL_ERR, "Unknown operand in expression\n");
787 				goto exit;
788 				break;
789 			}
790 			stack[pos] = operand_str;
791 			pos++;
792 			break;
793 		}
794 		default:
795 			cil_log(CIL_ERR, "Unknown flavor in expression\n");
796 			goto exit;
797 			break;
798 		}
799 	}
800 
801 	*out = stack[0];
802 
803 	return SEPOL_OK;
804 
805 exit:
806 	for (i = 0; i < pos; i++) {
807 		free(stack[i]);
808 	}
809 	return rc;
810 }
811 
cil_expr_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_list * expr)812 int cil_expr_to_policy(FILE **file_arr, uint32_t file_index, struct cil_list *expr)
813 {
814 	int rc = SEPOL_ERR;
815 	char *str_out;
816 
817 	rc = cil_expr_to_string(expr, &str_out);
818 	if (rc != SEPOL_OK) {
819 		goto out;
820 	}
821 	fprintf(file_arr[file_index], "%s", str_out);
822 	free(str_out);
823 
824 	return SEPOL_OK;
825 
826 out:
827 	return rc;
828 }
829 
__cil_booleanif_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)830 int __cil_booleanif_node_helper(struct cil_tree_node *node, __attribute__((unused)) uint32_t *finished, void *extra_args)
831 {
832 	int rc = SEPOL_ERR;
833 	struct cil_args_booleanif *args;
834 	FILE **file_arr;
835 	uint32_t *file_index;
836 
837 	args = extra_args;
838 	file_arr = args->file_arr;
839 	file_index = args->file_index;
840 
841 	switch (node->flavor) {
842 	case CIL_AVRULE:
843 		rc = cil_avrule_to_policy(file_arr, *file_index, (struct cil_avrule*)node->data);
844 		if (rc != SEPOL_OK) {
845 			cil_log(CIL_INFO, "cil_avrule_to_policy failed, rc: %d\n", rc);
846 			return rc;
847 		}
848 		break;
849 	case CIL_TYPE_RULE:
850 		rc = cil_typerule_to_policy(file_arr, *file_index, (struct cil_type_rule*)node->data);
851 		if (rc != SEPOL_OK) {
852 			cil_log(CIL_INFO, "cil_typerule_to_policy failed, rc: %d\n", rc);
853 			return rc;
854 		}
855 		break;
856 	case CIL_FALSE:
857 		fprintf(file_arr[*file_index], "else {\n");
858 		break;
859 	case CIL_TRUE:
860 		break;
861 	default:
862 		return SEPOL_ERR;
863 	}
864 
865 	return SEPOL_OK;
866 }
867 
__cil_booleanif_last_child_helper(struct cil_tree_node * node,void * extra_args)868 int __cil_booleanif_last_child_helper(struct cil_tree_node *node, void *extra_args)
869 {
870 	struct cil_args_booleanif *args;
871 	FILE **file_arr;
872 	uint32_t *file_index;
873 
874 	args = extra_args;
875 	file_arr = args->file_arr;
876 	file_index = args->file_index;
877 
878 	if (node->parent->flavor == CIL_FALSE) {
879 		fprintf(file_arr[*file_index], "}\n");
880 	}
881 
882 	return SEPOL_OK;
883 }
884 
cil_booleanif_to_policy(FILE ** file_arr,uint32_t file_index,struct cil_tree_node * node)885 int cil_booleanif_to_policy(FILE **file_arr, uint32_t file_index, struct cil_tree_node *node)
886 {
887 	int rc = SEPOL_ERR;
888 	struct cil_booleanif *bif = node->data;
889 	struct cil_list *expr = bif->datum_expr;
890 	struct cil_args_booleanif extra_args;
891 	struct cil_tree_node *true_node = NULL;
892 	struct cil_tree_node *false_node = NULL;
893 	struct cil_condblock *cb = NULL;
894 
895 	extra_args.file_arr = file_arr;
896 	extra_args.file_index = &file_index;;
897 
898 	fprintf(file_arr[file_index], "if ");
899 
900 	rc = cil_expr_to_policy(file_arr, file_index, expr);
901 	if (rc != SEPOL_OK) {
902 		cil_log(CIL_ERR, "Failed to write expression\n");
903 		return rc;
904 	}
905 
906 	if (node->cl_head != NULL && node->cl_head->flavor == CIL_CONDBLOCK) {
907 		cb = node->cl_head->data;
908 		if (cb->flavor == CIL_CONDTRUE) {
909 			true_node = node->cl_head;
910 		} else if (cb->flavor == CIL_CONDFALSE) {
911 			false_node = node->cl_head;
912 		}
913 	}
914 
915 	if (node->cl_head != NULL && node->cl_head->next != NULL && node->cl_head->next->flavor == CIL_CONDBLOCK) {
916 		cb = node->cl_head->next->data;
917 		if (cb->flavor == CIL_CONDTRUE) {
918 			true_node = node->cl_head->next;
919 		} else if (cb->flavor == CIL_CONDFALSE) {
920 			false_node = node->cl_head->next;
921 		}
922 	}
923 
924 	fprintf(file_arr[file_index], "{\n");
925 	if (true_node != NULL) {
926 		rc = cil_tree_walk(true_node, __cil_booleanif_node_helper, __cil_booleanif_last_child_helper, NULL, &extra_args);
927 		if (rc != SEPOL_OK) {
928 			cil_log(CIL_INFO, "Failed to write booleanif content to file, rc: %d\n", rc);
929 			return rc;
930 		}
931 	}
932 	fprintf(file_arr[file_index], "}\n");
933 
934 	if (false_node != NULL) {
935 		fprintf(file_arr[file_index], "else {\n");
936 		rc = cil_tree_walk(false_node, __cil_booleanif_node_helper, __cil_booleanif_last_child_helper, NULL, &extra_args);
937 		if (rc != SEPOL_OK) {
938 			cil_log(CIL_INFO, "Failed to write booleanif false content to file, rc: %d\n", rc);
939 			return rc;
940 		}
941 		fprintf(file_arr[file_index], "}\n");
942 	}
943 
944 	return SEPOL_OK;
945 }
946 
cil_name_to_policy(FILE ** file_arr,struct cil_tree_node * current)947 int cil_name_to_policy(FILE **file_arr, struct cil_tree_node *current)
948 {
949 	uint32_t flavor = current->flavor;
950 	int rc = SEPOL_ERR;
951 
952 	switch(flavor) {
953 	case CIL_TYPEATTRIBUTE:
954 		fprintf(file_arr[TYPEATTRTYPES], "attribute %s;\n", ((struct cil_symtab_datum*)current->data)->name);
955 		break;
956 	case CIL_TYPE:
957 		fprintf(file_arr[TYPEATTRTYPES], "type %s;\n", ((struct cil_symtab_datum*)current->data)->name);
958 		break;
959 	case CIL_TYPEALIAS: {
960 		struct cil_alias *alias = current->data;
961 		fprintf(file_arr[ALIASES], "typealias %s alias %s;\n", ((struct cil_symtab_datum*)alias->actual)->name, ((struct cil_symtab_datum*)current->data)->name);
962 		break;
963 	}
964 	case CIL_TYPEBOUNDS: {
965 		struct cil_bounds *bnds = current->data;
966 		fprintf(file_arr[ALLOWS], "typebounds %s %s;\n", bnds->parent_str, bnds->child_str);
967 		break;
968 	}
969 	case CIL_TYPEPERMISSIVE: {
970 		struct cil_typepermissive *typeperm = (struct cil_typepermissive*)current->data;
971 		fprintf(file_arr[TYPEATTRTYPES], "permissive %s;\n", ((struct cil_symtab_datum*)typeperm->type)->name);
972 		break;
973 	}
974 	case CIL_ROLE:
975 		fprintf(file_arr[TYPEATTRTYPES], "role %s;\n", ((struct cil_symtab_datum*)current->data)->name);
976 		break;
977 	case CIL_BOOL: {
978 		const char *boolean = ((struct cil_bool*)current->data)->value ? "true" : "false";
979 		fprintf(file_arr[TYPEATTRTYPES], "bool %s %s;\n", ((struct cil_symtab_datum*)current->data)->name, boolean);
980 		break;
981 	}
982 	case CIL_COMMON:
983 		fprintf(file_arr[COMMONS], "common %s", ((struct cil_symtab_datum*)current->data)->name);
984 
985 		if (current->cl_head != NULL) {
986 			current = current->cl_head;
987 			fprintf(file_arr[COMMONS], " {");
988 		} else {
989 			cil_log(CIL_INFO, "No permissions given\n");
990 			return SEPOL_ERR;
991 		}
992 
993 		while (current != NULL) {
994 			if (current->flavor == CIL_PERM) {
995 				fprintf(file_arr[COMMONS], "%s ", ((struct cil_symtab_datum*)current->data)->name);
996 			} else {
997 				cil_log(CIL_INFO, "Improper data type found in common permissions: %d\n", current->flavor);
998 				return SEPOL_ERR;
999 			}
1000 			current = current->next;
1001 		}
1002 		fprintf(file_arr[COMMONS], "}\n");
1003 
1004 		return SEPOL_DONE;
1005 	case CIL_AVRULE: {
1006 		struct cil_avrule *avrule = (struct cil_avrule*)current->data;
1007 		rc = cil_avrule_to_policy(file_arr, ALLOWS, avrule);
1008 		if (rc != SEPOL_OK) {
1009 			cil_log(CIL_INFO, "Failed to write avrule to policy\n");
1010 			return rc;
1011 		}
1012 		break;
1013 	}
1014 	case CIL_TYPE_RULE: {
1015 		struct cil_type_rule *rule = (struct cil_type_rule*)current->data;
1016 		rc = cil_typerule_to_policy(file_arr, ALLOWS, rule);
1017 		if (rc != SEPOL_OK) {
1018 			cil_log(CIL_INFO, "Failed to write type rule to policy\n");
1019 			return rc;
1020 		}
1021 		break;
1022 	}
1023 	case CIL_NAMETYPETRANSITION: {
1024 		struct cil_nametypetransition *nametypetrans = (struct cil_nametypetransition*)current->data;
1025 		rc = cil_nametypetransition_to_policy(file_arr, ALLOWS, nametypetrans);
1026 		if (rc != SEPOL_OK) {
1027 			cil_log(CIL_INFO, "Failed to write nametypetransition to policy\n");
1028 			return rc;
1029 		}
1030 	}
1031 	case CIL_ROLETRANSITION: {
1032 		struct cil_roletransition *roletrans = (struct cil_roletransition*)current->data;
1033 		char *src_str = ((struct cil_symtab_datum*)roletrans->src)->name;
1034 		char *tgt_str = ((struct cil_symtab_datum*)roletrans->tgt)->name;
1035 		char *obj_str = ((struct cil_symtab_datum*)roletrans->obj)->name;
1036 		char *result_str = ((struct cil_symtab_datum*)roletrans->result)->name;
1037 
1038 		fprintf(file_arr[ALLOWS], "role_transition %s %s:%s %s;\n", src_str, tgt_str, obj_str, result_str);
1039 		break;
1040 	}
1041 	case CIL_ROLEALLOW: {
1042 		struct cil_roleallow *roleallow = (struct cil_roleallow*)current->data;
1043 		char *src_str = ((struct cil_symtab_datum*)roleallow->src)->name;
1044 		char *tgt_str = ((struct cil_symtab_datum*)roleallow->tgt)->name;
1045 
1046 		fprintf(file_arr[ALLOWS], "roleallow %s %s;\n", src_str, tgt_str);
1047 		break;
1048 	}
1049 	case CIL_ROLETYPE: {
1050 		struct cil_roletype *roletype = (struct cil_roletype*)current->data;
1051 		char *role_str = ((struct cil_symtab_datum*)roletype->role)->name;
1052 		char *type_str = ((struct cil_symtab_datum*)roletype->type)->name;
1053 
1054 		fprintf(file_arr[ALIASES], "role %s types %s\n", role_str, type_str);
1055 		break;
1056 	}
1057 	case CIL_LEVEL:
1058 		fprintf(file_arr[LEVELS], "level ");
1059 		cil_level_to_policy(file_arr, LEVELS, (struct cil_level*)current->data);
1060 			fprintf(file_arr[LEVELS], ";\n");
1061 			break;
1062 	case CIL_CONSTRAIN:
1063 		cil_constrain_to_policy(file_arr, CONSTRAINS, (struct cil_constrain*)current->data, flavor);
1064 		break;
1065 	case CIL_MLSCONSTRAIN:
1066 		cil_constrain_to_policy(file_arr, CONSTRAINS, (struct cil_constrain*)current->data, flavor);
1067 		break;
1068 	case CIL_VALIDATETRANS: {
1069 		struct cil_validatetrans *vt = current->data;
1070 		fprintf(file_arr[CONSTRAINS], "validatetrans");
1071 		fprintf(file_arr[CONSTRAINS], " %s ", ((struct cil_class*)vt->class)->datum.name);
1072 		cil_expr_to_policy(file_arr, CONSTRAINS, vt->datum_expr);
1073 		fprintf(file_arr[CONSTRAINS], ";\n");
1074 		break;
1075 	}
1076 	case CIL_MLSVALIDATETRANS: {
1077 		struct cil_validatetrans *vt = current->data;
1078 		fprintf(file_arr[CONSTRAINS], "mlsvalidatetrans");
1079 		fprintf(file_arr[CONSTRAINS], " %s " , ((struct cil_class*)vt->class)->datum.name);
1080 		cil_expr_to_policy(file_arr, CONSTRAINS, vt->datum_expr);
1081 		fprintf(file_arr[CONSTRAINS], ";\n");
1082 		break;
1083 	}
1084 	case CIL_SID:
1085 		fprintf(file_arr[ISIDS], "sid %s\n", ((struct cil_symtab_datum*)current->data)->name);
1086 		break;
1087 	case CIL_SIDCONTEXT: {
1088 		struct cil_sidcontext *sidcon = (struct cil_sidcontext*)current->data;
1089 		fprintf(file_arr[SIDS], "sid %s ", sidcon->sid_str);
1090 		cil_context_to_policy(file_arr, SIDS, sidcon->context);
1091 		fprintf(file_arr[SIDS], "\n");
1092 		break;
1093 	}
1094 	case CIL_POLICYCAP:
1095 		fprintf(file_arr[TYPEATTRTYPES], "policycap %s;\n", ((struct cil_symtab_datum*)current->data)->name);
1096 		break;
1097 	default:
1098 		break;
1099 	}
1100 
1101 	return SEPOL_OK;
1102 }
1103 
__cil_gen_policy_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1104 int __cil_gen_policy_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1105 {
1106 	int rc = SEPOL_ERR;
1107 	struct cil_args_genpolicy *args = NULL;
1108 	struct cil_list *users = NULL;
1109 	struct cil_list *sens = NULL;
1110 	struct cil_list *cats = NULL;
1111 	FILE **file_arr = NULL;
1112 
1113 	if (extra_args == NULL) {
1114 		return SEPOL_ERR;
1115 	}
1116 
1117 	*finished = CIL_TREE_SKIP_NOTHING;
1118 
1119 	args = extra_args;
1120 	users = args->users;
1121 	sens = args->sens;
1122 	cats = args->cats;
1123 	file_arr = args->file_arr;
1124 
1125 	if (node->cl_head != NULL) {
1126 		if (node->flavor == CIL_MACRO) {
1127 			*finished = CIL_TREE_SKIP_HEAD;
1128 			return SEPOL_OK;
1129 		}
1130 
1131 		if (node->flavor == CIL_BOOLEANIF) {
1132 			rc = cil_booleanif_to_policy(file_arr, CONDS, node);
1133 			if (rc != SEPOL_OK) {
1134 				cil_log(CIL_INFO, "Failed to write booleanif contents to file\n");
1135 				return rc;
1136 			}
1137 			*finished = CIL_TREE_SKIP_HEAD;
1138 			return SEPOL_OK;
1139 		}
1140 
1141 		if (node->flavor == CIL_BLOCK && ((struct cil_block*)node->data)->is_abstract == CIL_TRUE) {
1142 			*finished = CIL_TREE_SKIP_HEAD;
1143 			return SEPOL_OK;
1144 		}
1145 
1146 		if (node->flavor != CIL_ROOT) {
1147 			rc = cil_name_to_policy(file_arr, node);
1148 			if (rc != SEPOL_OK && rc != SEPOL_DONE) {
1149 				cil_log(CIL_ERR, "Error converting node to policy %d\n", node->flavor);
1150 				return SEPOL_ERR;
1151 			}
1152 		}
1153 	} else {
1154 		switch (node->flavor) {
1155 		case CIL_USER:
1156 			cil_multimap_insert(users, node->data, NULL, CIL_USERROLE, CIL_NONE);
1157 			break;
1158 		case CIL_USERROLE: {
1159 			struct cil_userrole *userrole = node->data;
1160 			cil_multimap_insert(users, &userrole->user->datum, (struct cil_symtab_datum *)userrole->role, CIL_USERROLE, CIL_ROLE);
1161 		}
1162 			break;
1163 		case CIL_CATALIAS: {
1164 			struct cil_alias *alias = node->data;
1165 			struct cil_symtab_datum *datum = alias->actual;
1166 			cil_multimap_insert(cats, datum, node->data, CIL_CAT, CIL_CATALIAS);
1167 		}
1168 			break;
1169 		case CIL_SENSALIAS: {
1170 			struct cil_alias *alias = node->data;
1171 			struct cil_symtab_datum *datum = alias->actual;
1172 			cil_multimap_insert(sens, datum, node->data, CIL_SENS, CIL_SENSALIAS);
1173 		}
1174 			break;
1175 		default:
1176 			rc = cil_name_to_policy(file_arr, node);
1177 			if (rc != SEPOL_OK && rc != SEPOL_DONE) {
1178 				cil_log(CIL_ERR, "Error converting node to policy %d\n", rc);
1179 				return SEPOL_ERR;
1180 			}
1181 			break;
1182 		}
1183 	}
1184 
1185 	return SEPOL_OK;
1186 }
1187 
cil_gen_policy(struct cil_db * db)1188 int cil_gen_policy(struct cil_db *db)
1189 {
1190 	struct cil_tree_node *curr = db->ast->root;
1191 	struct cil_list_item *item;
1192 	int rc = SEPOL_ERR;
1193 	FILE *policy_file;
1194 	FILE **file_arr = cil_malloc(sizeof(FILE*) * NUM_POLICY_FILES);
1195 	char *file_path_arr[NUM_POLICY_FILES];
1196 	char temp[32];
1197 
1198 	struct cil_list *users = NULL;
1199 	struct cil_list *cats = NULL;
1200 	struct cil_list *sens = NULL;
1201 	struct cil_args_genpolicy extra_args;
1202 
1203 	cil_list_init(&users, CIL_LIST_ITEM);
1204 	cil_list_init(&cats, CIL_LIST_ITEM);
1205 	cil_list_init(&sens, CIL_LIST_ITEM);
1206 
1207 	strcpy(temp, "/tmp/cil_classdecl-XXXXXX");
1208 	file_arr[CLASS_DECL] = fdopen(mkstemp(temp), "w+");
1209 	file_path_arr[CLASS_DECL] = cil_strpool_add(temp);
1210 
1211 	strcpy(temp, "/tmp/cil_isids-XXXXXX");
1212 	file_arr[ISIDS] = fdopen(mkstemp(temp), "w+");
1213 	file_path_arr[ISIDS] = cil_strpool_add(temp);
1214 
1215 	strcpy(temp,"/tmp/cil_common-XXXXXX");
1216 	file_arr[COMMONS] = fdopen(mkstemp(temp), "w+");
1217 	file_path_arr[COMMONS] = cil_strpool_add(temp);
1218 
1219 	strcpy(temp, "/tmp/cil_class-XXXXXX");
1220 	file_arr[CLASSES] = fdopen(mkstemp(temp), "w+");
1221 	file_path_arr[CLASSES] = cil_strpool_add(temp);
1222 
1223 	strcpy(temp, "/tmp/cil_interf-XXXXXX");
1224 	file_arr[INTERFACES] = fdopen(mkstemp(temp), "w+");
1225 	file_path_arr[INTERFACES] = cil_strpool_add(temp);
1226 
1227 	strcpy(temp, "/tmp/cil_sens-XXXXXX");
1228 	file_arr[SENS] = fdopen(mkstemp(temp), "w+");
1229 	file_path_arr[SENS] = cil_strpool_add(temp);
1230 
1231 	strcpy(temp, "/tmp/cil_cats-XXXXXX");
1232 	file_arr[CATS] = fdopen(mkstemp(temp), "w+");
1233 	file_path_arr[CATS] = cil_strpool_add(temp);
1234 
1235 	strcpy(temp, "/tmp/cil_levels-XXXXXX");
1236 	file_arr[LEVELS] = fdopen(mkstemp(temp), "w+");
1237 	file_path_arr[LEVELS] = cil_strpool_add(temp);
1238 
1239 	strcpy(temp, "/tmp/cil_mlscon-XXXXXX");
1240 	file_arr[CONSTRAINS] = fdopen(mkstemp(temp), "w+");
1241 	file_path_arr[CONSTRAINS] = cil_strpool_add(temp);
1242 
1243 	strcpy(temp, "/tmp/cil_attrtypes-XXXXXX");
1244 	file_arr[TYPEATTRTYPES] = fdopen(mkstemp(temp), "w+");
1245 	file_path_arr[TYPEATTRTYPES] = cil_strpool_add(temp);
1246 
1247 	strcpy(temp, "/tmp/cil_aliases-XXXXXX");
1248 	file_arr[ALIASES] = fdopen(mkstemp(temp), "w+");
1249 	file_path_arr[ALIASES] = cil_strpool_add(temp);
1250 
1251 	strcpy(temp, "/tmp/cil_allows-XXXXXX");
1252 	file_arr[ALLOWS] = fdopen(mkstemp(temp), "w+");
1253 	file_path_arr[ALLOWS] = cil_strpool_add(temp);
1254 
1255 	strcpy(temp, "/tmp/cil_conds-XXXXXX");
1256 	file_arr[CONDS] = fdopen(mkstemp(temp), "w+");
1257 	file_path_arr[CONDS] = cil_strpool_add(temp);
1258 
1259 	strcpy(temp, "/tmp/cil_userroles-XXXXXX");
1260 	file_arr[USERROLES] = fdopen(mkstemp(temp), "w+");
1261 	file_path_arr[USERROLES] = cil_strpool_add(temp);
1262 
1263 	strcpy(temp, "/tmp/cil_sids-XXXXXX");
1264 	file_arr[SIDS] = fdopen(mkstemp(temp), "w+");
1265 	file_path_arr[SIDS] = cil_strpool_add(temp);
1266 
1267 	strcpy(temp, "/tmp/cil_netifcons-XXXXXX");
1268 	file_arr[NETIFCONS] = fdopen(mkstemp(temp), "w+");
1269 	file_path_arr[NETIFCONS] = cil_strpool_add(temp);
1270 
1271 	policy_file = fopen("policy.conf", "w+");
1272 
1273 	cil_list_for_each(item, db->sidorder) {
1274 		fprintf(file_arr[ISIDS], "sid %s ", ((struct cil_sid*)item->data)->datum.name);
1275 	}
1276 
1277 	cil_list_for_each(item, db->classorder) {
1278 		struct cil_class *class = item->data;
1279 		struct cil_tree_node *node = class->datum.nodes->head->data;
1280 
1281 		fprintf(file_arr[CLASS_DECL], "class %s\n", class->datum.name);
1282 
1283 		fprintf(file_arr[CLASSES], "class %s ", class->datum.name);
1284 		if (class->common != NULL) {
1285 			fprintf(file_arr[CLASSES], "inherits %s ", class->common->datum.name);
1286 		}
1287 		if (node->cl_head != NULL) {
1288 			struct cil_tree_node *curr_perm = node->cl_head;
1289 			fprintf(file_arr[CLASSES], "{ ");
1290 			while (curr_perm != NULL) {
1291 				fprintf(file_arr[CLASSES], "%s ", ((struct cil_symtab_datum*)curr_perm->data)->name);
1292 				curr_perm = curr_perm->next;
1293 			}
1294 			fprintf(file_arr[CLASSES], "}");
1295 		}
1296 		fprintf(file_arr[CLASSES], "\n");
1297 	}
1298 
1299 	if (db->catorder->head != NULL) {
1300 		cil_list_for_each(item, db->catorder) {
1301 			cil_multimap_insert(cats, item->data, NULL, CIL_CAT, 0);
1302 		}
1303 	}
1304 
1305 	if (db->sensitivityorder->head != NULL) {
1306 		fprintf(file_arr[SENS], "sensitivityorder { ");
1307 		cil_list_for_each(item, db->sensitivityorder) {
1308 			fprintf(file_arr[SENS], "%s ", ((struct cil_sens*)item->data)->datum.name);
1309 		}
1310 		fprintf(file_arr[SENS], "};\n");
1311 	}
1312 
1313 	extra_args.users = users;
1314 	extra_args.sens = sens;
1315 	extra_args.cats = cats;
1316 	extra_args.file_arr= file_arr;
1317 
1318 	rc = cil_tree_walk(curr, __cil_gen_policy_node_helper, NULL, NULL, &extra_args);
1319 	if (rc != SEPOL_OK) {
1320 		cil_log(CIL_ERR, "Error walking tree\n");
1321 		return rc;
1322 	}
1323 
1324 	rc = cil_netifcon_to_policy(file_arr, db->netifcon);
1325 	if (rc != SEPOL_OK) {
1326 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1327 		return rc;
1328 	}
1329 
1330 	rc = cil_genfscon_to_policy(file_arr, db->genfscon);
1331 	if (rc != SEPOL_OK) {
1332 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1333 		return rc;
1334 	}
1335 
1336 	rc = cil_portcon_to_policy(file_arr, db->portcon);
1337 	if (rc != SEPOL_OK) {
1338 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1339 		return rc;
1340 	}
1341 
1342 	rc = cil_nodecon_to_policy(file_arr, db->nodecon);
1343 	if (rc != SEPOL_OK) {
1344 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1345 		return rc;
1346 	}
1347 
1348 	rc = cil_fsuse_to_policy(file_arr, db->fsuse);
1349 	if (rc != SEPOL_OK) {
1350 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1351 		return rc;
1352 	}
1353 
1354 	rc = cil_pirqcon_to_policy(file_arr, db->pirqcon);
1355 	if (rc != SEPOL_OK) {
1356 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1357 		return rc;
1358 	}
1359 
1360 	rc = cil_iomemcon_to_policy(file_arr, db->iomemcon);
1361 	if (rc != SEPOL_OK) {
1362 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1363 		return rc;
1364 	}
1365 
1366 	rc = cil_ioportcon_to_policy(file_arr, db->ioportcon);
1367 	if (rc != SEPOL_OK) {
1368 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1369 		return rc;
1370 	}
1371 
1372 	rc = cil_pcidevicecon_to_policy(file_arr, db->pcidevicecon);
1373 	if (rc != SEPOL_OK) {
1374 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1375 		return rc;
1376 	}
1377 
1378 	rc = cil_userrole_to_policy(file_arr, users);
1379 	if (rc != SEPOL_OK) {
1380 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1381 		return SEPOL_ERR;
1382 	}
1383 
1384 	rc = cil_sens_to_policy(file_arr, sens);
1385 	if (rc != SEPOL_OK) {
1386 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1387 		return SEPOL_ERR;
1388 	}
1389 
1390 	rc = cil_cat_to_policy(file_arr, cats);
1391 	if (rc != SEPOL_OK) {
1392 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1393 		return SEPOL_ERR;
1394 	}
1395 
1396 	rc = cil_combine_policy(file_arr, policy_file);
1397 	if (rc != SEPOL_OK) {
1398 		cil_log(CIL_ERR, "Error creating policy.conf\n");
1399 		return SEPOL_ERR;
1400 	}
1401 
1402 	// Remove temp files
1403 	int i;
1404 	for (i=0; i<NUM_POLICY_FILES; i++) {
1405 		rc = fclose(file_arr[i]);
1406 		if (rc != 0) {
1407 			cil_log(CIL_ERR, "Error closing temporary file\n");
1408 			return SEPOL_ERR;
1409 		}
1410 		rc = unlink(file_path_arr[i]);
1411 		if (rc != 0) {
1412 			cil_log(CIL_ERR, "Error unlinking temporary files\n");
1413 			return SEPOL_ERR;
1414 		}
1415 	}
1416 
1417 	rc = fclose(policy_file);
1418 	if (rc != 0) {
1419 		cil_log(CIL_ERR, "Error closing policy.conf\n");
1420 		return SEPOL_ERR;
1421 	}
1422 	free(file_arr);
1423 
1424 	cil_list_destroy(&users, CIL_FALSE);
1425 	cil_list_destroy(&cats, CIL_FALSE);
1426 	cil_list_destroy(&sens, CIL_FALSE);
1427 
1428 	return SEPOL_OK;
1429 }
1430