1 #include <stdlib.h>
2
3 #include "cil_flavor.h"
4 #include "cil_internal.h"
5 #include "cil_log.h"
6 #include "cil_tree.h"
7
8 struct cil_args_write {
9 FILE *cil_out;
10 struct cil_db *db;
11 };
12
13 static int cil_unfill_expr(struct cil_list *expr_str, char **out_str, int paren);
14 static int cil_unfill_classperms_list(struct cil_list *classperms, char **out_str, int paren);
15 static int __cil_write_first_child_helper(struct cil_tree_node *node, void *extra_args);
16 static int __cil_write_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args);
17 static int __cil_write_last_child_helper(struct cil_tree_node *node, void *extra_args);
18
__cil_strlist_concat(struct cil_list * str_list,char ** out_str,int paren)19 static int __cil_strlist_concat(struct cil_list *str_list, char **out_str, int paren) {
20 size_t len = paren ? 3 : 1;
21 size_t num_elems = 0;
22 char *p = NULL;
23 struct cil_list_item *curr;
24
25 /* get buffer size */
26 cil_list_for_each(curr, str_list) {
27 len += strlen((char *)curr->data);
28 num_elems++;
29 }
30 if (num_elems != 0) {
31 /* add spaces between elements */
32 len += num_elems - 1;
33 }
34 *out_str = cil_malloc(len);
35 p = *out_str;
36 if (paren)
37 *p++ = '(';
38 cil_list_for_each(curr, str_list) {
39 size_t src_len = strlen((char *)curr->data);
40 memcpy(p, curr->data, src_len);
41 p += src_len;
42 if (curr->next != NULL)
43 *p++ = ' ';
44 }
45 if (paren)
46 *p++ = ')';
47 *p++ = '\0';
48 return SEPOL_OK;
49 }
50
__cil_unfill_expr_helper(struct cil_list_item * curr,struct cil_list_item ** next,char ** out_str,int paren)51 static int __cil_unfill_expr_helper(struct cil_list_item *curr,
52 struct cil_list_item **next, char **out_str, int paren) {
53 int rc = SEPOL_ERR;
54 char *str = NULL;
55 char *operand1 = NULL;
56 char *operand2 = NULL;
57
58 switch(curr->flavor) {
59 case CIL_LIST:
60 rc = cil_unfill_expr((struct cil_list *)curr->data, &str, paren);
61 if (rc != SEPOL_OK)
62 goto exit;
63 *out_str = str;
64 *next = curr->next;
65 break;
66 case CIL_STRING:
67 str = strdup((char *)curr->data);
68 if (!str) {
69 cil_log(CIL_ERR, "OOM. Unable to copy string.\n");
70 rc = SEPOL_ERR;
71 goto exit;
72 }
73 *out_str = str;
74 *next = curr->next;
75 break;
76 case CIL_DATUM:
77 str = strdup(((struct cil_symtab_datum *)curr->data)->name);
78 if (!str) {
79 cil_log(CIL_ERR, "OOM. Unable to copy string.\n");
80 rc = SEPOL_ERR;
81 goto exit;
82 }
83 *out_str = str;
84 *next = curr->next;
85 break;
86 case CIL_OP: {
87 char *op_str = NULL;
88 size_t len = 0;
89 enum cil_flavor op_flavor = (enum cil_flavor)curr->data;
90 switch (op_flavor) {
91 case CIL_AND:
92 op_str = CIL_KEY_AND;
93 break;
94 case CIL_OR:
95 op_str = CIL_KEY_OR;
96 break;
97 case CIL_NOT:
98 op_str = CIL_KEY_NOT;
99 break;
100 case CIL_ALL:
101 op_str = CIL_KEY_ALL;
102 break;
103 case CIL_EQ:
104 op_str = CIL_KEY_EQ;
105 break;
106 case CIL_NEQ:
107 op_str = CIL_KEY_NEQ;
108 break;
109 case CIL_RANGE:
110 op_str = CIL_KEY_RANGE;
111 break;
112 case CIL_XOR:
113 op_str = CIL_KEY_XOR;
114 break;
115 case CIL_CONS_DOM:
116 op_str = CIL_KEY_CONS_DOM;
117 break;
118 case CIL_CONS_DOMBY:
119 op_str = CIL_KEY_CONS_DOMBY;
120 break;
121 case CIL_CONS_INCOMP:
122 op_str = CIL_KEY_CONS_INCOMP;
123 break;
124 default:
125 cil_log(CIL_ERR, "Unknown operator in expression: %d\n", op_flavor);
126 goto exit;
127 break;
128 }
129 /* all operands take two args except for 'all' and 'not', which take
130 * one and two, respectively */
131 len = strlen(op_str) + 3;
132 if (op_flavor == CIL_ALL) {
133 *out_str = cil_malloc(len);
134 sprintf(*out_str, "(%s)", op_str);
135 *next = curr->next;
136 } else if (op_flavor == CIL_NOT) {
137 rc = __cil_unfill_expr_helper(curr->next, next, &operand1, paren);
138 if (rc != SEPOL_OK)
139 goto exit;
140 len += strlen(operand1) + 1;
141 *out_str = cil_malloc(len);
142 sprintf(*out_str, "(%s %s)", op_str, operand1);
143 // *next already set by recursive call
144 } else {
145 rc = __cil_unfill_expr_helper(curr->next, next, &operand1, paren);
146 if (rc != SEPOL_OK)
147 goto exit;
148 len += strlen(operand1) + 1;
149 // *next contains operand2, but keep track of next after that
150 rc = __cil_unfill_expr_helper(*next, next, &operand2, paren);
151 if (rc != SEPOL_OK)
152 goto exit;
153 len += strlen(operand2) + 1;
154 *out_str = cil_malloc(len);
155 sprintf(*out_str, "(%s %s %s)", op_str, operand1, operand2);
156 // *next already set by recursive call
157 }
158 }
159 break;
160 case CIL_CONS_OPERAND: {
161 enum cil_flavor operand_flavor = (enum cil_flavor)curr->data;
162 char *operand_str = NULL;
163 switch (operand_flavor) {
164 case CIL_CONS_U1:
165 operand_str = CIL_KEY_CONS_U1;
166 break;
167 case CIL_CONS_U2:
168 operand_str = CIL_KEY_CONS_U2;
169 break;
170 case CIL_CONS_U3:
171 operand_str = CIL_KEY_CONS_U3;
172 break;
173 case CIL_CONS_T1:
174 operand_str = CIL_KEY_CONS_T1;
175 break;
176 case CIL_CONS_T2:
177 operand_str = CIL_KEY_CONS_T2;
178 break;
179 case CIL_CONS_T3:
180 operand_str = CIL_KEY_CONS_T3;
181 break;
182 case CIL_CONS_R1:
183 operand_str = CIL_KEY_CONS_R1;
184 break;
185 case CIL_CONS_R2:
186 operand_str = CIL_KEY_CONS_R2;
187 break;
188 case CIL_CONS_R3:
189 operand_str = CIL_KEY_CONS_R3;
190 break;
191 case CIL_CONS_L1:
192 operand_str = CIL_KEY_CONS_L1;
193 break;
194 case CIL_CONS_L2:
195 operand_str = CIL_KEY_CONS_L2;
196 break;
197 case CIL_CONS_H1:
198 operand_str = CIL_KEY_CONS_H1;
199 break;
200 case CIL_CONS_H2:
201 operand_str = CIL_KEY_CONS_H2;
202 break;
203 default:
204 cil_log(CIL_ERR, "Unknown operand in expression\n");
205 goto exit;
206 break;
207 }
208 str = strdup(operand_str);
209 if (!str) {
210 cil_log(CIL_ERR, "OOM. Unable to copy string.\n");
211 rc = SEPOL_ERR;
212 goto exit;
213 }
214 *out_str = str;
215 *next = curr->next;
216 }
217 break;
218 default:
219 cil_log(CIL_ERR, "Unknown flavor in expression\n");
220 goto exit;
221 break;
222 }
223 rc = SEPOL_OK;
224 exit:
225 free(operand1);
226 free(operand2);
227 return rc;
228 }
229
cil_unfill_expr(struct cil_list * expr_str,char ** out_str,int paren)230 static int cil_unfill_expr(struct cil_list *expr_str, char **out_str, int paren) {
231 int rc = SEPOL_ERR;
232
233 /* reuse cil_list to keep track of strings */
234 struct cil_list *str_list = NULL;
235 struct cil_list_item *curr = NULL;
236
237 cil_list_init(&str_list, CIL_NONE);
238
239 /* iterate through cil_list, grabbing elements as needed */
240 curr = expr_str->head;
241 while(curr != NULL) {
242 char *str = NULL;
243 struct cil_list_item *next = NULL;
244
245 rc = __cil_unfill_expr_helper(curr, &next, &str, paren);
246 if (rc != SEPOL_OK)
247 goto exit;
248 cil_list_append(str_list, CIL_STRING, (void *) str);
249 str = NULL;
250 curr = next;
251 }
252 rc = __cil_strlist_concat(str_list, out_str, paren);
253 if (rc != SEPOL_OK)
254 goto exit;
255 rc = SEPOL_OK;
256 exit:
257 cil_list_for_each(curr, str_list) {
258 free(curr->data);
259 }
260 cil_list_destroy(&str_list, 0);
261 return rc;
262 }
263
cil_unfill_cats(struct cil_cats * cats,char ** out_str)264 static int cil_unfill_cats(struct cil_cats *cats, char **out_str) {
265 return cil_unfill_expr(cats->str_expr, out_str, 0);
266 }
267
cil_unfill_level(struct cil_level * lvl,char ** out_str)268 static int cil_unfill_level(struct cil_level *lvl, char **out_str) {
269 int rc = SEPOL_ERR;
270 size_t len = 0;
271 char *sens, *cats = NULL;
272 sens = lvl->sens_str;
273 len = strlen(sens) + 3; // '()\0'
274 if (lvl->cats != NULL) {
275 rc = cil_unfill_cats(lvl->cats, &cats);
276 if (rc != SEPOL_OK)
277 goto exit;
278 len += strlen(cats) + 1;
279 }
280 *out_str = cil_malloc(len);
281 if (cats == NULL) {
282 if (sprintf(*out_str, "(%s)", sens) < 0) {
283 cil_log(CIL_ERR, "Error unpacking and writing level\n");
284 rc = SEPOL_ERR;
285 goto exit;
286 }
287 } else {
288 if (sprintf(*out_str, "(%s %s)", sens, cats) < 0) {
289 cil_log(CIL_ERR, "Error unpacking and writing level\n");
290 rc = SEPOL_ERR;
291 goto exit;
292 }
293 }
294 rc = SEPOL_OK;
295 exit:
296 free(cats);
297 return rc;
298 }
299
cil_unfill_levelrange(struct cil_levelrange * lvlrnge,char ** out_str)300 static int cil_unfill_levelrange(struct cil_levelrange *lvlrnge, char **out_str) {
301 int rc = SEPOL_ERR;
302 size_t len = 0;
303 char *low = NULL, *high = NULL;
304 if (lvlrnge->low_str != NULL) {
305 low = strdup(lvlrnge->low_str);
306 if (low == NULL) {
307 cil_log(CIL_ERR, "OOM. Unable to copy level string.\n");
308 rc = SEPOL_ERR;
309 goto exit;
310 }
311 } else {
312 rc = cil_unfill_level(lvlrnge->low, &low);
313 if (rc != SEPOL_OK)
314 goto exit;
315 }
316 if (lvlrnge->high_str != NULL) {
317 high = strdup(lvlrnge->high_str);
318 if (high == NULL) {
319 cil_log(CIL_ERR, "OOM. Unable to copy level string.\n");
320 rc = SEPOL_ERR;
321 goto exit;
322 }
323 } else {
324 rc = cil_unfill_level(lvlrnge->high, &high);
325 if (rc != SEPOL_OK)
326 goto exit;
327 }
328 len = strlen(low) + strlen(high) + 4;
329 *out_str = cil_malloc(len);
330 if (sprintf(*out_str, "(%s %s)", low, high) < 0) {
331 cil_log(CIL_ERR, "Error unpacking and writing levelrange\n");
332 rc = SEPOL_ERR;
333 goto exit;
334 }
335 rc = SEPOL_OK;
336 exit:
337 free(low);
338 free(high);
339 return rc;
340 }
341
cil_unfill_context(struct cil_context * context,char ** out_str)342 static int cil_unfill_context(struct cil_context *context, char **out_str) {
343 int rc = SEPOL_ERR;
344 size_t len = 0;
345 char *user_str, *role_str, *type_str;
346 char *range_str = NULL;
347
348 user_str = context->user_str;
349 role_str = context->role_str;
350 type_str = context->type_str;
351 if (context->range_str != NULL) {
352 range_str = strdup(context->range_str);
353 if (range_str == NULL) {
354 cil_log(CIL_ERR, "OOM. Unable to copy range string.\n");
355 rc = SEPOL_ERR;
356 goto exit;
357 }
358 } else {
359 rc = cil_unfill_levelrange(context->range, &range_str);
360 if (rc != SEPOL_OK)
361 goto exit;
362 }
363 len = strlen(user_str) + strlen(role_str) + strlen(type_str)
364 + strlen(range_str) + 6;
365 *out_str = cil_malloc(len);
366 if (sprintf(*out_str, "(%s %s %s %s)", user_str, role_str, type_str, range_str) < 0) {
367 cil_log(CIL_ERR, "Error unpacking and writing context\n");
368 rc = SEPOL_ERR;
369 goto exit;
370 }
371 rc = SEPOL_OK;
372 exit:
373 free(range_str);
374 return rc;
375 }
376
cil_unfill_permx(struct cil_permissionx * permx,char ** out_str)377 static int cil_unfill_permx(struct cil_permissionx *permx, char **out_str) {
378 size_t len = 3;
379 int rc = SEPOL_ERR;
380 char *kind, *obj;
381 char *expr = NULL;
382
383 switch (permx->kind) {
384 case CIL_PERMX_KIND_IOCTL:
385 kind = CIL_KEY_IOCTL;
386 break;
387 default:
388 cil_log(CIL_ERR, "Unknown permissionx kind: %d\n", permx->kind);
389 rc = SEPOL_ERR;
390 goto exit;
391 break;
392 }
393 obj = permx->obj_str;
394 rc = cil_unfill_expr(permx->expr_str, &expr, 1);
395 if (rc != SEPOL_OK)
396 goto exit;
397 len += strlen(kind) + strlen(obj) + strlen(expr) + 2;
398 *out_str = cil_malloc(len);
399 if (sprintf(*out_str, "(%s %s %s)", kind, obj, expr) < 0) {
400 cil_log(CIL_ERR, "Error writing xperm\n");
401 rc = SEPOL_ERR;
402 goto exit;
403 }
404 rc = SEPOL_OK;
405 exit:
406 free(expr);
407 return rc;
408 }
409
410 #define cil_write_unsupported(flavor) _cil_write_unsupported(flavor, __LINE__)
_cil_write_unsupported(const char * flavor,int line)411 static int _cil_write_unsupported(const char *flavor, int line) {
412 cil_log(CIL_ERR,
413 "flavor \"%s\" is not supported, look in file \"%s\""
414 " on line %d to add support.\n", flavor, __FILE__, line);
415 return SEPOL_ENOTSUP;
416 }
417
cil_write_policycap(struct cil_tree_node * node,FILE * cil_out)418 static int cil_write_policycap(struct cil_tree_node *node, FILE *cil_out) {
419 struct cil_policycap *polcap = (struct cil_policycap *)node->data;
420 fprintf(cil_out, "(%s %s)\n", CIL_KEY_POLICYCAP, polcap->datum.name);
421 return SEPOL_OK;
422 }
423
cil_write_perm(struct cil_tree_node * node,FILE * cil_out)424 static int cil_write_perm(struct cil_tree_node *node, FILE *cil_out) {
425 struct cil_perm *perm = (struct cil_perm *)node->data;
426 fprintf(cil_out, "%s", perm->datum.name);
427 if (node->next != NULL)
428 fprintf(cil_out, " ");
429 return SEPOL_OK;
430 }
431
432
cil_write_class(struct cil_tree_node * node,uint32_t * finished,struct cil_args_write * extra_args)433 static int cil_write_class(struct cil_tree_node *node, uint32_t *finished,
434 struct cil_args_write *extra_args) {
435 int rc = SEPOL_ERR;
436 FILE *cil_out = extra_args->cil_out;
437 struct cil_symtab_datum *datum = (struct cil_symtab_datum *)node->data;
438 char *class_type = (node->flavor == CIL_CLASS) ? CIL_KEY_CLASS : CIL_KEY_COMMON;
439
440 /* print preamble */
441 fprintf(cil_out, "(%s %s ", class_type, datum->name);
442
443 if (node->cl_head == NULL) {
444 /* no associated perms in this part of tree */
445 fprintf(cil_out, "()");
446 } else {
447
448 /* visit subtree (perms) */
449 rc = cil_tree_walk(node, __cil_write_node_helper,
450 __cil_write_first_child_helper,
451 __cil_write_last_child_helper,
452 extra_args);
453 if (rc != SEPOL_OK)
454 goto exit;
455 }
456
457 /* postamble (trailing paren) */
458 fprintf(cil_out, ")\n");
459 *finished = CIL_TREE_SKIP_HEAD;
460 rc = SEPOL_OK;
461 exit:
462 return rc;
463 }
464
cil_write_classorder(struct cil_tree_node * node,FILE * cil_out)465 static int cil_write_classorder(struct cil_tree_node *node, FILE *cil_out) {
466 int rc = SEPOL_ERR;
467 char *ord_str = NULL;
468 struct cil_classorder *classord = (struct cil_classorder *)node->data;
469
470 /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */
471 rc = cil_unfill_expr(classord->class_list_str, &ord_str, 1);
472 if (rc != SEPOL_OK)
473 goto exit;
474 fprintf(cil_out, "(%s %s)\n", CIL_KEY_CLASSORDER, ord_str);
475 rc = SEPOL_OK;
476 exit:
477 free(ord_str);
478 return rc;
479 }
480
cil_write_classcommon(struct cil_tree_node * node,FILE * cil_out)481 static int cil_write_classcommon(struct cil_tree_node *node, FILE *cil_out) {
482 struct cil_classcommon *classcommon = (struct cil_classcommon *)node->data;
483 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_CLASSCOMMON, classcommon->class_str,
484 classcommon->common_str);
485 return SEPOL_OK;
486 }
487
cil_write_sid(struct cil_tree_node * node,FILE * cil_out)488 static int cil_write_sid(struct cil_tree_node *node, FILE *cil_out) {
489 struct cil_sid *sid = (struct cil_sid *)node->data;
490 fprintf(cil_out, "(%s %s)\n", CIL_KEY_SID, sid->datum.name);
491 return SEPOL_OK;
492 }
493
cil_write_sidcontext(struct cil_tree_node * node,FILE * cil_out)494 static int cil_write_sidcontext(struct cil_tree_node *node, FILE *cil_out) {
495 int rc = SEPOL_ERR;
496 char *sid;
497 char *ctx_str = NULL;
498 struct cil_sidcontext *sidcon = (struct cil_sidcontext *)node->data;
499
500 sid = sidcon->sid_str;
501 if (sidcon->context_str != NULL) {
502 ctx_str = strdup(sidcon->context_str);
503 if (ctx_str == NULL) {
504 cil_log(CIL_ERR, "OOM. Unable to copy context string.\n");
505 rc = SEPOL_ERR;
506 goto exit;
507 }
508 } else {
509 rc = cil_unfill_context(sidcon->context, &ctx_str);
510 if (rc != SEPOL_OK)
511 goto exit;
512 }
513 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_SIDCONTEXT, sid, ctx_str);
514 rc = SEPOL_OK;
515 exit:
516 free(ctx_str);
517 return rc;
518 }
519
cil_write_sidorder(struct cil_tree_node * node,FILE * cil_out)520 static int cil_write_sidorder(struct cil_tree_node *node, FILE *cil_out) {
521 int rc = SEPOL_ERR;
522 char *ord_str = NULL;
523 struct cil_sidorder *sidord = (struct cil_sidorder *)node->data;
524
525 /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */
526 rc = cil_unfill_expr(sidord->sid_list_str, &ord_str, 1);
527 if (rc != SEPOL_OK)
528 goto exit;
529 fprintf(cil_out, "(%s %s)\n", CIL_KEY_SIDORDER, ord_str);
530 rc = SEPOL_OK;
531 exit:
532 free(ord_str);
533 return rc;
534 }
535
cil_write_user(struct cil_tree_node * node,FILE * cil_out)536 static int cil_write_user(struct cil_tree_node *node, FILE *cil_out) {
537 struct cil_user *user = (struct cil_user *)node->data;
538 fprintf(cil_out, "(%s %s)\n", CIL_KEY_USER, user->datum.name);
539 return SEPOL_OK;
540 }
541
cil_write_userrole(struct cil_tree_node * node,FILE * cil_out)542 static int cil_write_userrole(struct cil_tree_node *node, FILE *cil_out) {
543 struct cil_userrole *userrole = (struct cil_userrole *)node->data;
544 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERROLE, userrole->user_str,
545 userrole->role_str);
546 return SEPOL_OK;
547 }
548
cil_write_userlevel(struct cil_tree_node * node,FILE * cil_out)549 static int cil_write_userlevel(struct cil_tree_node *node, FILE *cil_out) {
550 struct cil_userlevel *usrlvl = (struct cil_userlevel *)node->data;
551 int rc = SEPOL_ERR;
552 char *usr;
553 char *lvl = NULL;
554
555 usr = usrlvl->user_str;
556 if (usrlvl->level_str != NULL) {
557 lvl = strdup(usrlvl->level_str);
558 if (lvl == NULL) {
559 cil_log(CIL_ERR, "OOM. Unable to copy level string.\n");
560 rc = SEPOL_ERR;
561 goto exit;
562 }
563 } else {
564 rc = cil_unfill_level(usrlvl->level, &lvl);
565 if (rc != SEPOL_OK)
566 goto exit;
567 }
568 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERLEVEL, usr, lvl);
569 rc = SEPOL_OK;
570 exit:
571 free(lvl);
572 return rc;
573 }
574
cil_write_userrange(struct cil_tree_node * node,FILE * cil_out)575 static int cil_write_userrange(struct cil_tree_node *node, FILE *cil_out) {
576 struct cil_userrange *usrrng = (struct cil_userrange *)node->data;
577 int rc = SEPOL_ERR;
578 char *usr;
579 char *range = NULL;
580
581 usr = usrrng->user_str;
582 if (usrrng->range_str != NULL) {
583 range = strdup(usrrng->range_str);
584 if (range == NULL) {
585 cil_log(CIL_ERR, "OOM. Unable to copy levelrange string.\n");
586 rc = SEPOL_ERR;
587 goto exit;
588 }
589 } else {
590 rc = cil_unfill_levelrange(usrrng->range, &range);
591 if (rc != SEPOL_OK)
592 goto exit;
593 }
594 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_USERRANGE, usr, range);
595 rc = SEPOL_OK;
596 exit:
597 free(range);
598 return rc;
599 }
600
cil_write_role(struct cil_tree_node * node,FILE * cil_out)601 static int cil_write_role(struct cil_tree_node *node, FILE *cil_out) {
602 struct cil_role *role = (struct cil_role *)node->data;
603 fprintf(cil_out, "(%s %s)\n", CIL_KEY_ROLE, role->datum.name);
604 return SEPOL_OK;
605 }
606
cil_write_roletype(struct cil_tree_node * node,FILE * cil_out)607 static int cil_write_roletype(struct cil_tree_node *node, FILE *cil_out) {
608 struct cil_roletype *roletype = (struct cil_roletype *)node->data;
609 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_ROLETYPE, roletype->role_str, roletype->type_str);
610 return SEPOL_OK;
611 }
612
cil_write_roleattribute(struct cil_tree_node * node,FILE * cil_out)613 static int cil_write_roleattribute(struct cil_tree_node *node, FILE *cil_out) {
614 struct cil_roleattribute *roleattr = (struct cil_roleattribute *)node->data;
615 fprintf(cil_out, "(%s %s)\n", CIL_KEY_ROLEATTRIBUTE, roleattr->datum.name);
616 return SEPOL_OK;
617 }
618
cil_write_type(struct cil_tree_node * node,FILE * cil_out)619 static int cil_write_type(struct cil_tree_node *node, FILE *cil_out) {
620 struct cil_type *type = (struct cil_type *)node->data;
621 fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPE, type->datum.name);
622 return SEPOL_OK;
623 }
624
cil_write_typepermissive(struct cil_tree_node * node,FILE * cil_out)625 static int cil_write_typepermissive(struct cil_tree_node *node, FILE *cil_out) {
626 struct cil_typepermissive *type = (struct cil_typepermissive *)node->data;
627 fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPEPERMISSIVE, type->type_str);
628 return SEPOL_OK;
629 }
630
cil_write_typeattribute(struct cil_tree_node * node,FILE * cil_out)631 static int cil_write_typeattribute(struct cil_tree_node *node, FILE *cil_out) {
632 struct cil_typeattribute *typeattr = (struct cil_typeattribute *)node->data;
633 fprintf(cil_out, "(%s %s)\n", CIL_KEY_TYPEATTRIBUTE, typeattr->datum.name);
634 return SEPOL_OK;
635 }
636
cil_write_typeattributeset(struct cil_tree_node * node,FILE * cil_out)637 static int cil_write_typeattributeset(struct cil_tree_node *node, FILE *cil_out) {
638 int rc = SEPOL_ERR;
639 char *typeattr;
640 char *set_str = NULL;
641 struct cil_typeattributeset *typeattrset = (struct cil_typeattributeset *)node->data;
642
643 typeattr = typeattrset->attr_str;
644 rc = cil_unfill_expr(typeattrset->str_expr, &set_str, 1);
645 if (rc != SEPOL_OK)
646 goto exit;
647
648 fprintf(cil_out, "(%s %s %s)\n", CIL_KEY_TYPEATTRIBUTESET, typeattr, set_str);
649 rc = SEPOL_OK;
650 exit:
651 free(set_str);
652 return rc;
653 }
654
cil_write_alias(struct cil_tree_node * node,FILE * cil_out)655 static int cil_write_alias(struct cil_tree_node *node, FILE *cil_out) {
656 int rc = SEPOL_ERR;
657 char *type;
658 struct cil_alias *alias = (struct cil_alias *)node->data;
659
660 switch (node->flavor) {
661 case CIL_TYPEALIAS:
662 type = CIL_KEY_TYPEALIAS;
663 break;
664 case CIL_SENSALIAS:
665 type = CIL_KEY_SENSALIAS;
666 break;
667 case CIL_CATALIAS:
668 type = CIL_KEY_CATALIAS;
669 break;
670 default:
671 cil_log(CIL_ERR, "Unknown alias type: %d\n", node->flavor);
672 rc = SEPOL_ERR;
673 goto exit;
674 break;
675 }
676 fprintf(cil_out, "(%s %s)\n", type, alias->datum.name);
677 rc = SEPOL_OK;
678 exit:
679 return rc;
680 }
681
cil_write_aliasactual(struct cil_tree_node * node,FILE * cil_out)682 static int cil_write_aliasactual(struct cil_tree_node *node, FILE *cil_out) {
683 int rc = SEPOL_ERR;
684 char *type, *alias, *actual;
685 struct cil_aliasactual *aliasact = (struct cil_aliasactual *)node->data;
686
687 switch (node->flavor) {
688 case CIL_TYPEALIASACTUAL:
689 type = CIL_KEY_TYPEALIASACTUAL;
690 break;
691 case CIL_SENSALIASACTUAL:
692 type = CIL_KEY_SENSALIASACTUAL;
693 break;
694 case CIL_CATALIASACTUAL:
695 type = CIL_KEY_CATALIASACTUAL;
696 break;
697 default:
698 cil_log(CIL_ERR, "Unknown alias type: %d\n", node->flavor);
699 rc = SEPOL_ERR;
700 goto exit;
701 break;
702 }
703 alias = aliasact->alias_str;
704 actual = aliasact->actual_str;
705 fprintf(cil_out, "(%s %s %s)\n", type, alias, actual);
706 rc = SEPOL_OK;
707 exit:
708 return rc;
709 }
710
cil_write_nametypetransition(struct cil_tree_node * node,FILE * cil_out)711 static int cil_write_nametypetransition(struct cil_tree_node *node, FILE *cil_out) {
712 char *src, *tgt, *obj, *res, *name;
713 struct cil_nametypetransition *ntrans = (struct cil_nametypetransition *)node->data;
714
715 src = ntrans->src_str;
716 tgt = ntrans->tgt_str;
717 obj = ntrans->obj_str;
718 res = ntrans->result_str;
719 name = ntrans->name_str;
720 fprintf(cil_out, "(%s %s %s %s \"%s\" %s)\n", CIL_KEY_TYPETRANSITION,
721 src, tgt, obj, name, res);
722 return SEPOL_OK;
723 }
724
cil_write_avrule_x(struct cil_avrule * avrule,FILE * cil_out)725 static int cil_write_avrule_x(struct cil_avrule *avrule, FILE *cil_out) {
726 int rc = SEPOL_ERR;
727 char *rulekind, *src, *tgt;
728 char *xperms = NULL;
729
730 switch (avrule->rule_kind) {
731 case CIL_AVRULE_ALLOWED:
732 rulekind = CIL_KEY_ALLOWX;
733 break;
734 case CIL_AVRULE_AUDITALLOW:
735 rulekind = CIL_KEY_AUDITALLOWX;
736 break;
737 case CIL_AVRULE_DONTAUDIT:
738 rulekind = CIL_KEY_DONTAUDITX;
739 break;
740 case CIL_AVRULE_NEVERALLOW:
741 rulekind = CIL_KEY_NEVERALLOWX;
742 break;
743 default:
744 cil_log(CIL_ERR, "Unknown AVRULE type: %d\n", avrule->rule_kind);
745 rc = SEPOL_ERR;
746 goto exit;
747 break;
748 }
749 src = avrule->src_str;
750 tgt = avrule->tgt_str;
751
752 if (avrule->perms.x.permx_str != NULL) {
753 xperms = strdup(avrule->perms.x.permx_str);
754 if (xperms == NULL) {
755 cil_log(CIL_ERR, "OOM. Unable to copy xperms string.\n");
756 rc = SEPOL_ERR;
757 goto exit;
758 }
759 } else {
760 rc = cil_unfill_permx(avrule->perms.x.permx, &xperms);
761 if (rc != SEPOL_OK)
762 goto exit;
763 }
764 fprintf(cil_out, "(%s %s %s %s)\n", rulekind, src, tgt, xperms);
765 rc = SEPOL_OK;
766 exit:
767 free(xperms);
768 return rc;
769 }
770
cil_write_avrule_orig(struct cil_avrule * avrule,FILE * cil_out)771 static int cil_write_avrule_orig(struct cil_avrule *avrule, FILE *cil_out) {
772 int rc = SEPOL_ERR;
773 char *rulekind, *src, *tgt;
774 char *classperms = NULL;
775
776 switch (avrule->rule_kind) {
777 case CIL_AVRULE_ALLOWED:
778 rulekind = CIL_KEY_ALLOW;
779 break;
780 case CIL_AVRULE_AUDITALLOW:
781 rulekind = CIL_KEY_AUDITALLOW;
782 break;
783 case CIL_AVRULE_DONTAUDIT:
784 rulekind = CIL_KEY_DONTAUDIT;
785 break;
786 case CIL_AVRULE_NEVERALLOW:
787 rulekind = CIL_KEY_NEVERALLOW;
788 break;
789 default:
790 cil_log(CIL_ERR, "Unknown AVRULE type: %d\n", avrule->rule_kind);
791 rc = SEPOL_ERR;
792 goto exit;
793 break;
794 }
795 src = avrule->src_str;
796 tgt = avrule->tgt_str;
797
798 rc = cil_unfill_classperms_list(avrule->perms.classperms, &classperms, 0);
799 if (rc != SEPOL_OK)
800 goto exit;
801 fprintf(cil_out, "(%s %s %s %s)\n", rulekind, src, tgt, classperms);
802 rc = SEPOL_OK;
803 exit:
804 free(classperms);
805 return rc;
806 }
807
cil_write_avrule(struct cil_tree_node * node,FILE * cil_out)808 static int cil_write_avrule(struct cil_tree_node *node, FILE *cil_out) {
809 int rc = SEPOL_ERR;
810 struct cil_avrule *avrule = (struct cil_avrule *)node->data;
811
812 if (avrule->is_extended)
813 rc = cil_write_avrule_x(avrule, cil_out);
814 else
815 rc = cil_write_avrule_orig(avrule, cil_out);
816 return rc;
817 }
818
cil_write_type_rule(struct cil_tree_node * node,FILE * cil_out)819 static int cil_write_type_rule(struct cil_tree_node *node, FILE *cil_out) {
820 int rc = SEPOL_ERR;
821 char *type, *src, *tgt, *obj, *res;
822 struct cil_type_rule *typerule = (struct cil_type_rule *)node->data;
823
824 switch (typerule->rule_kind) {
825 case CIL_TYPE_TRANSITION:
826 type = CIL_KEY_TYPETRANSITION;
827 break;
828 case CIL_TYPE_MEMBER:
829 type = CIL_KEY_TYPEMEMBER;
830 break;
831 case CIL_TYPE_CHANGE:
832 type = CIL_KEY_TYPECHANGE;
833 break;
834 default:
835 cil_log(CIL_ERR, "Unknown TYPERULE type: %d\n", typerule->rule_kind);
836 rc = SEPOL_ERR;
837 goto exit;
838 break;
839 }
840 src = typerule->src_str;
841 tgt = typerule->tgt_str;
842 obj = typerule->obj_str;
843 res = typerule->result_str;
844 fprintf(cil_out, "(%s %s %s %s %s)\n", type, src, tgt, obj, res);
845 rc = SEPOL_OK;
846 exit:
847 return rc;
848 }
849
cil_write_sens(struct cil_tree_node * node,FILE * cil_out)850 static int cil_write_sens(struct cil_tree_node *node, FILE *cil_out) {
851 struct cil_sens *sens = (struct cil_sens *)node->data;
852 fprintf(cil_out, "(%s %s)\n", CIL_KEY_SENSITIVITY, sens->datum.name);
853 return SEPOL_OK;
854 }
855
cil_write_cat(struct cil_tree_node * node,FILE * cil_out)856 static int cil_write_cat(struct cil_tree_node *node, FILE *cil_out) {
857 struct cil_cat *cat = (struct cil_cat *)node->data;
858 fprintf(cil_out, "(%s %s)\n", CIL_KEY_CATEGORY, cat->datum.name);
859 return SEPOL_OK;
860 }
861
cil_write_senscat(struct cil_tree_node * node,FILE * cil_out)862 static int cil_write_senscat(struct cil_tree_node *node, FILE *cil_out) {
863 int rc = SEPOL_ERR;
864 char *sens;
865 char *cats = NULL;
866 struct cil_senscat *senscat = (struct cil_senscat *)node->data;
867
868 sens = senscat->sens_str;
869 rc = cil_unfill_cats(senscat->cats, &cats);
870 if (rc != SEPOL_OK)
871 goto exit;
872 /* TODO: deal with extra/missing parens */
873 fprintf(cil_out, "(%s %s (%s))\n", CIL_KEY_SENSCAT, sens, cats);
874 rc = SEPOL_OK;
875 exit:
876 free(cats);
877 return rc;
878 }
879
cil_write_catorder(struct cil_tree_node * node,FILE * cil_out)880 static int cil_write_catorder(struct cil_tree_node *node, FILE *cil_out) {
881 int rc = SEPOL_ERR;
882 char *ord_str = NULL;
883 struct cil_catorder *catord = (struct cil_catorder *)node->data;
884
885 /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */
886 rc = cil_unfill_expr(catord->cat_list_str, &ord_str, 1);
887 if (rc != SEPOL_OK)
888 goto exit;
889 fprintf(cil_out, "(%s %s)\n", CIL_KEY_CATORDER, ord_str);
890 rc = SEPOL_OK;
891 exit:
892 free(ord_str);
893 return rc;
894 }
895
cil_write_sensorder(struct cil_tree_node * node,FILE * cil_out)896 static int cil_write_sensorder(struct cil_tree_node *node, FILE *cil_out) {
897 int rc = SEPOL_ERR;
898 char *ord_str = NULL;
899 struct cil_sensorder *sensord = (struct cil_sensorder *)node->data;
900
901 /* cil_unfill_expr() has logic to stringify a cil_list, reuse that. */
902 rc = cil_unfill_expr(sensord->sens_list_str, &ord_str, 1);
903 if (rc != SEPOL_OK)
904 goto exit;
905 fprintf(cil_out, "(%s %s)\n", CIL_KEY_SENSITIVITYORDER, ord_str);
906 rc = SEPOL_OK;
907 exit:
908 free(ord_str);
909 return rc;
910 }
911
cil_write_genfscon(struct cil_tree_node * node,FILE * cil_out)912 static int cil_write_genfscon(struct cil_tree_node *node, FILE *cil_out) {
913 int rc = SEPOL_ERR;
914 char *ctx_str = NULL;
915
916 struct cil_genfscon *genfscon = (struct cil_genfscon *)node->data;
917 if (genfscon->context_str != NULL) {
918 ctx_str = strdup(genfscon->context_str);
919 if (ctx_str == NULL) {
920 cil_log(CIL_ERR, "OOM. Unable to copy context string.\n");
921 rc = SEPOL_ERR;
922 goto exit;
923 }
924 } else {
925 rc = cil_unfill_context(genfscon->context, &ctx_str);
926 if (rc != SEPOL_OK)
927 goto exit;
928 }
929 fprintf(cil_out, "(%s %s %s %s)\n", CIL_KEY_GENFSCON, genfscon->fs_str,
930 genfscon->path_str, ctx_str);
931 rc = SEPOL_OK;
932 exit:
933 free(ctx_str);
934 return rc;
935 }
936
cil_unfill_classperms(struct cil_list_item * curr,char ** out_str)937 static int cil_unfill_classperms(struct cil_list_item *curr, char **out_str) {
938 int rc = SEPOL_ERR;
939 size_t len = 3;
940 char *class_str;
941 char *perms_str = NULL;
942 struct cil_classperms *cp = (struct cil_classperms *)curr->data;
943
944 class_str = cp->class_str;
945 len += strlen(class_str) + 1;
946
947 /* fill_perms just calls gen_expr */
948 rc = cil_unfill_expr(cp->perm_strs, &perms_str, 1);
949 if (rc != SEPOL_OK)
950 goto exit;
951 len += strlen(perms_str);
952 *out_str = cil_malloc(len);
953 sprintf(*out_str, "(%s %s)", class_str, perms_str);
954 rc = SEPOL_OK;
955 exit:
956 free(perms_str);
957 return rc;
958 }
959
cil_unfill_classperms_list(struct cil_list * classperms,char ** out_str,int paren)960 static int cil_unfill_classperms_list(struct cil_list *classperms, char **out_str, int paren) {
961 int rc = SEPOL_ERR;
962 struct cil_list_item *curr;
963 char *str = NULL;
964
965 /* reuse cil_list to keep track of strings */
966 struct cil_list *str_list = NULL;
967 cil_list_init(&str_list, CIL_NONE);
968 cil_list_for_each(curr, classperms) {
969 switch (curr->flavor) {
970 case CIL_CLASSPERMS_SET:
971 str = strdup(((struct cil_classperms_set *)curr->data)->set_str);
972 if (str == NULL) {
973 cil_log(CIL_ERR, "OOM. Unable to copy classpermset.\n");
974 rc = SEPOL_ERR;
975 goto exit;
976 }
977 break;
978 case CIL_CLASSPERMS:
979 rc = cil_unfill_classperms(curr, &str);
980 if (rc != SEPOL_OK)
981 goto exit;
982 break;
983 default:
984 cil_log(CIL_ERR, "Unrecognized classperms flavor\n.");
985 goto exit;
986 }
987 cil_list_append(str_list, CIL_STRING, (void *) str);
988 str = NULL;
989 }
990 rc = __cil_strlist_concat(str_list, out_str, paren);
991 if (rc != SEPOL_OK)
992 goto exit;
993 rc = SEPOL_OK;
994 exit:
995 cil_list_for_each(curr, str_list) {
996 free(curr->data);
997 }
998 cil_list_destroy(&str_list, 0);
999 return rc;
1000 }
1001
cil_write_fsuse(struct cil_tree_node * node,FILE * cil_out)1002 static int cil_write_fsuse(struct cil_tree_node *node, FILE *cil_out) {
1003 int rc = SEPOL_ERR;
1004 struct cil_fsuse *fsuse = (struct cil_fsuse *)node->data;
1005 char *type, *fsname;
1006 char *ctx_str = NULL;
1007
1008 switch(fsuse->type) {
1009 case CIL_FSUSE_XATTR:
1010 type = CIL_KEY_XATTR;
1011 break;
1012 case CIL_FSUSE_TASK:
1013 type = CIL_KEY_TASK;
1014 break;
1015 case CIL_FSUSE_TRANS:
1016 type = CIL_KEY_TRANS;
1017 break;
1018 default:
1019 cil_log(CIL_ERR, "Unrecognized fsuse type\n");
1020 rc = SEPOL_ERR;
1021 goto exit;
1022 break;
1023 }
1024
1025 fsname = fsuse->fs_str;
1026 if (fsuse->context_str != NULL) {
1027 ctx_str = strdup(fsuse->context_str);
1028 if (ctx_str == NULL) {
1029 cil_log(CIL_ERR, "OOM. Unable to copy context string.\n");
1030 rc = SEPOL_ERR;
1031 goto exit;
1032 }
1033 } else {
1034 rc = cil_unfill_context(fsuse->context, &ctx_str);
1035 if (rc != SEPOL_OK)
1036 goto exit;
1037 }
1038 fprintf(cil_out, "(%s %s %s %s)\n", CIL_KEY_FSUSE, type, fsname, ctx_str);
1039 exit:
1040 free(ctx_str);
1041 return rc;
1042 }
1043
cil_write_constrain(struct cil_tree_node * node,FILE * cil_out)1044 static int cil_write_constrain(struct cil_tree_node *node, FILE *cil_out) {
1045 int rc = SEPOL_ERR;
1046 struct cil_constrain *cons = (struct cil_constrain *)node->data;
1047 char *flav;
1048 char *classperms = NULL;
1049 char *expr = NULL;
1050
1051 flav = (node->flavor == CIL_CONSTRAIN) ? CIL_KEY_CONSTRAIN : CIL_KEY_MLSCONSTRAIN;
1052
1053 rc = cil_unfill_classperms_list(cons->classperms, &classperms, 0);
1054 if (rc != SEPOL_OK)
1055 goto exit;
1056
1057 rc = cil_unfill_expr(cons->str_expr, &expr, 0);
1058 if (rc != SEPOL_OK)
1059 goto exit;
1060
1061 fprintf(cil_out, "(%s %s %s)\n", flav, classperms, expr);
1062 exit:
1063 free(classperms);
1064 free(expr);
1065 return rc;
1066 }
1067
cil_write_handleunknown(struct cil_tree_node * node,FILE * cil_out)1068 static int cil_write_handleunknown(struct cil_tree_node *node, FILE *cil_out) {
1069 int rc = SEPOL_OK;
1070 struct cil_handleunknown *handunknown = (struct cil_handleunknown *)node->data;
1071 char *val = NULL;
1072 switch (handunknown->handle_unknown) {
1073 case SEPOL_ALLOW_UNKNOWN:
1074 val = CIL_KEY_HANDLEUNKNOWN_ALLOW;
1075 break;
1076 case SEPOL_DENY_UNKNOWN:
1077 val = CIL_KEY_HANDLEUNKNOWN_DENY;
1078 break;
1079 case SEPOL_REJECT_UNKNOWN:
1080 val = CIL_KEY_HANDLEUNKNOWN_REJECT;
1081 break;
1082 default:
1083 cil_log(CIL_ERR, "Unknown handleunknown value: %d.\n",
1084 handunknown->handle_unknown);
1085 rc = SEPOL_ERR;
1086 goto exit;
1087 break;
1088 }
1089 fprintf(cil_out, "(%s %s)\n", CIL_KEY_HANDLEUNKNOWN, val);
1090 exit:
1091 return rc;
1092 }
1093
cil_write_mls(struct cil_tree_node * node,FILE * cil_out)1094 static int cil_write_mls(struct cil_tree_node *node, FILE *cil_out) {
1095 int rc = SEPOL_OK;
1096 struct cil_mls *mls = (struct cil_mls *)node->data;
1097 char *val = NULL;
1098 switch (mls->value) {
1099 case CIL_TRUE:
1100 val = CIL_KEY_CONDTRUE;
1101 break;
1102 case CIL_FALSE:
1103 val = CIL_KEY_CONDFALSE;
1104 break;
1105 default:
1106 cil_log(CIL_ERR, "Unknown mls value: %d.\n", mls->value);
1107 rc = SEPOL_ERR;
1108 goto exit;
1109 break;
1110 }
1111 fprintf(cil_out, "(%s %s)\n", CIL_KEY_MLS, val);
1112 exit:
1113 return rc;
1114 }
1115
__cil_write_first_child_helper(struct cil_tree_node * node,void * extra_args)1116 static int __cil_write_first_child_helper(struct cil_tree_node *node, void *extra_args)
1117 {
1118 int rc = SEPOL_ERR;
1119 struct cil_args_write *args = (struct cil_args_write *) extra_args;
1120 FILE *cil_out = NULL;
1121
1122 if (node == NULL || extra_args == NULL) {
1123 goto exit;
1124 }
1125
1126 cil_out = args->cil_out;
1127
1128 if (node->parent && node->parent->flavor != CIL_ROOT && node->parent->flavor != CIL_SRC_INFO)
1129 fprintf(cil_out,"(");
1130 rc = SEPOL_OK;
1131 exit:
1132 return rc;
1133 }
1134
__cil_write_node_helper(struct cil_tree_node * node,uint32_t * finished,void * extra_args)1135 static int __cil_write_node_helper(struct cil_tree_node *node, uint32_t *finished, void *extra_args)
1136 {
1137 int rc = SEPOL_OK;
1138 struct cil_db *db = NULL;
1139 struct cil_args_write *args = NULL;
1140 FILE *cil_out = NULL;
1141
1142 if (node == NULL || extra_args == NULL) {
1143 goto exit;
1144 }
1145
1146 args = extra_args;
1147 db = args->db;
1148 cil_out = args->cil_out;
1149
1150 switch (node->flavor) {
1151 case CIL_BLOCK:
1152 rc = cil_write_unsupported("CIL_BLOCK");
1153 break;
1154 case CIL_BLOCKABSTRACT:
1155 rc = cil_write_unsupported("CIL_BLOCKABSTRACT");
1156 break;
1157 case CIL_BLOCKINHERIT:
1158 rc = cil_write_unsupported("CIL_BLOCKINHERIT");
1159 break;
1160 case CIL_IN:
1161 rc = cil_write_unsupported("CIL_IN");
1162 break;
1163 case CIL_POLICYCAP:
1164 cil_write_policycap(node, cil_out);
1165 break;
1166 case CIL_PERM:
1167 rc = cil_write_perm(node, cil_out);
1168 break;
1169 case CIL_MAP_PERM:
1170 rc = cil_write_unsupported("CIL_MAP_PERM");
1171 break;
1172 case CIL_CLASSMAPPING:
1173 rc = cil_write_unsupported("CIL_CLASSMAPPING");
1174 break;
1175 case CIL_CLASS:
1176 rc = cil_write_class(node, finished, extra_args);
1177 break;
1178 case CIL_COMMON:
1179 rc = cil_write_class(node, finished, extra_args);
1180 break;
1181 case CIL_MAP_CLASS:
1182 rc = cil_write_unsupported("CIL_MAP_CLASS");
1183 break;
1184 case CIL_CLASSORDER:
1185 rc = cil_write_classorder(node, cil_out);
1186 break;
1187 case CIL_CLASSPERMISSION:
1188 rc = cil_write_unsupported("CIL_CLASSPERMISSION");
1189 break;
1190 case CIL_CLASSPERMISSIONSET:
1191 rc = cil_write_unsupported("CIL_CLASSPERMISSIONSET");
1192 break;
1193 case CIL_CLASSCOMMON:
1194 rc = cil_write_classcommon(node, cil_out);
1195 break;
1196 case CIL_SID:
1197 rc = cil_write_sid(node, cil_out);
1198 break;
1199 case CIL_SIDCONTEXT:
1200 rc = cil_write_sidcontext(node, cil_out);
1201 break;
1202 case CIL_SIDORDER:
1203 rc = cil_write_sidorder(node, cil_out);
1204 break;
1205 case CIL_USER:
1206 rc = cil_write_user(node, cil_out);
1207 break;
1208 case CIL_USERATTRIBUTE:
1209 rc = cil_write_unsupported("CIL_USERATTRIBUTE");
1210 break;
1211 case CIL_USERATTRIBUTESET:
1212 rc = cil_write_unsupported("CIL_USERATTRIBUTESET");
1213 break;
1214 case CIL_USERROLE:
1215 rc = cil_write_userrole(node, cil_out);
1216 break;
1217 case CIL_USERLEVEL:
1218 rc = cil_write_userlevel(node, cil_out);
1219 break;
1220 case CIL_USERRANGE:
1221 rc = cil_write_userrange(node, cil_out);
1222 break;
1223 case CIL_USERBOUNDS:
1224 rc = cil_write_unsupported("CIL_USERBOUNDS");
1225 break;
1226 case CIL_USERPREFIX:
1227 rc = cil_write_unsupported("CIL_USERPREFIX");
1228 break;
1229 case CIL_ROLE:
1230 rc = cil_write_role(node, cil_out);
1231 break;
1232 case CIL_ROLETYPE:
1233 rc = cil_write_roletype(node, cil_out);
1234 break;
1235 case CIL_ROLEBOUNDS:
1236 rc = cil_write_unsupported("CIL_ROLEBOUNDS");
1237 break;
1238 case CIL_ROLEATTRIBUTE:
1239 cil_write_roleattribute(node, cil_out);
1240 break;
1241 case CIL_ROLEATTRIBUTESET:
1242 rc = cil_write_unsupported("CIL_ROLEATTRIBUTESET");
1243 break;
1244 case CIL_ROLEALLOW:
1245 rc = cil_write_unsupported("CIL_ROLEALLOW");
1246 break;
1247 case CIL_TYPE:
1248 rc = cil_write_type(node, cil_out);
1249 break;
1250 case CIL_TYPEBOUNDS:
1251 rc = cil_write_unsupported("CIL_TYPEBOUNDS");
1252 break;
1253 case CIL_TYPEPERMISSIVE:
1254 rc = cil_write_typepermissive(node, cil_out);
1255 break;
1256 case CIL_TYPEATTRIBUTE:
1257 rc = cil_write_typeattribute(node, cil_out);
1258 break;
1259 case CIL_TYPEATTRIBUTESET:
1260 rc = cil_write_typeattributeset(node, cil_out);
1261 break;
1262 case CIL_TYPEALIAS:
1263 rc = cil_write_alias(node, cil_out);
1264 break;
1265 case CIL_TYPEALIASACTUAL:
1266 rc = cil_write_aliasactual(node, cil_out);
1267 break;
1268 case CIL_ROLETRANSITION:
1269 rc = cil_write_unsupported("CIL_ROLETRANSITION");
1270 break;
1271 case CIL_NAMETYPETRANSITION:
1272 rc = cil_write_nametypetransition(node, cil_out);
1273 break;
1274 case CIL_RANGETRANSITION:
1275 rc = cil_write_unsupported("CIL_RANGETRANSITION");
1276 break;
1277 case CIL_TUNABLE:
1278 rc = cil_write_unsupported("CIL_TUNABLE");
1279 break;
1280 case CIL_BOOL:
1281 rc = cil_write_unsupported("CIL_BOOL");
1282 break;
1283 case CIL_AVRULE:
1284 case CIL_AVRULEX:
1285 rc = cil_write_avrule(node, cil_out);
1286 break;
1287 case CIL_PERMISSIONX:
1288 rc = cil_write_unsupported("CIL_PERMISSIONX");
1289 break;
1290 case CIL_TYPE_RULE:
1291 cil_write_type_rule(node, cil_out);
1292 break;
1293 case CIL_SENS:
1294 rc = cil_write_sens(node, cil_out);
1295 break;
1296 case CIL_SENSALIAS:
1297 rc = cil_write_alias(node, cil_out);
1298 break;
1299 case CIL_SENSALIASACTUAL:
1300 rc = cil_write_aliasactual(node, cil_out);
1301 break;
1302 case CIL_CAT:
1303 rc = cil_write_cat(node, cil_out);
1304 break;
1305 case CIL_CATALIAS:
1306 rc = cil_write_alias(node, cil_out);
1307 break;
1308 case CIL_CATALIASACTUAL:
1309 rc = cil_write_aliasactual(node, cil_out);
1310 break;
1311 case CIL_CATSET:
1312 rc = cil_write_unsupported("CIL_CATSET");
1313 break;
1314 case CIL_SENSCAT:
1315 rc = cil_write_senscat(node, cil_out);
1316 break;
1317 case CIL_CATORDER:
1318 rc = cil_write_catorder(node, cil_out);
1319 break;
1320 case CIL_SENSITIVITYORDER:
1321 rc = cil_write_sensorder(node, cil_out);
1322 break;
1323 case CIL_LEVEL:
1324 rc = cil_write_unsupported("CIL_LEVEL");
1325 break;
1326 case CIL_LEVELRANGE:
1327 rc = cil_write_unsupported("CIL_LEVELRANGE");
1328 break;
1329 case CIL_CONTEXT:
1330 rc = cil_write_unsupported("CIL_CONTEXT");
1331 break;
1332 case CIL_NETIFCON:
1333 rc = cil_write_unsupported("CIL_NETIFCON");
1334 break;
1335 case CIL_GENFSCON:
1336 rc = cil_write_genfscon(node, cil_out);
1337 break;
1338 case CIL_FILECON:
1339 rc = cil_write_unsupported("CIL_FILECON");
1340 break;
1341 case CIL_NODECON:
1342 rc = cil_write_unsupported("CIL_NODECON");
1343 break;
1344 case CIL_PORTCON:
1345 rc = cil_write_unsupported("CIL_PORTCON");
1346 break;
1347 case CIL_PIRQCON:
1348 rc = cil_write_unsupported("CIL_PIRQCON");
1349 break;
1350 case CIL_IOMEMCON:
1351 rc = cil_write_unsupported("CIL_IOMEMCON");
1352 break;
1353 case CIL_IOPORTCON:
1354 rc = cil_write_unsupported("CIL_IOPORTCON");
1355 break;
1356 case CIL_PCIDEVICECON:
1357 rc = cil_write_unsupported("CIL_PCIDEVICECON");
1358 break;
1359 case CIL_DEVICETREECON:
1360 rc = cil_write_unsupported("CIL_DEVICETREECON");
1361 break;
1362 case CIL_FSUSE:
1363 rc = cil_write_fsuse(node, cil_out);
1364 break;
1365 case CIL_CONSTRAIN:
1366 rc = cil_write_unsupported("CIL_CONSTRAIN");
1367 break;
1368 case CIL_MLSCONSTRAIN:
1369 rc = cil_write_constrain(node, cil_out);
1370 break;
1371 case CIL_VALIDATETRANS:
1372 rc = cil_write_unsupported("CIL_VALIDATETRANS");
1373 break;
1374 case CIL_MLSVALIDATETRANS:
1375 rc = cil_write_unsupported("CIL_MLSVALIDATETRANS");
1376 break;
1377 case CIL_CALL:
1378 rc = cil_write_unsupported("CIL_CALL");
1379 break;
1380 case CIL_MACRO:
1381 rc = cil_write_unsupported("CIL_MACRO");
1382 break;
1383 case CIL_NODE:
1384 rc = cil_write_unsupported("CIL_NODE");
1385 break;
1386 case CIL_OPTIONAL:
1387 rc = cil_write_unsupported("CIL_OPTIONAL");
1388 break;
1389 case CIL_IPADDR:
1390 rc = cil_write_unsupported("CIL_IPADDR");
1391 break;
1392 case CIL_CONDBLOCK:
1393 rc = cil_write_unsupported("CIL_CONDBLOCK");
1394 break;
1395 case CIL_BOOLEANIF:
1396 rc = cil_write_unsupported("CIL_BOOLEANIF");
1397 break;
1398 case CIL_TUNABLEIF:
1399 rc = cil_write_unsupported("CIL_TUNABLEIF");
1400 break;
1401 case CIL_DEFAULTUSER:
1402 rc = cil_write_unsupported("CIL_DEFAULTUSER");
1403 break;
1404 case CIL_DEFAULTROLE:
1405 rc = cil_write_unsupported("CIL_DEFAULTROLE");
1406 break;
1407 case CIL_DEFAULTTYPE:
1408 rc = cil_write_unsupported("CIL_DEFAULTTYPE");
1409 break;
1410 case CIL_DEFAULTRANGE:
1411 rc = cil_write_unsupported("CIL_DEFAULTRANGE");
1412 break;
1413 case CIL_SELINUXUSER:
1414 rc = cil_write_unsupported("CIL_SELINUXUSER");
1415 break;
1416 case CIL_SELINUXUSERDEFAULT:
1417 rc = cil_write_unsupported("CIL_SELINUXUSERDEFAULT");
1418 break;
1419 case CIL_HANDLEUNKNOWN:
1420 rc = cil_write_handleunknown(node, cil_out);
1421 break;
1422 case CIL_MLS:
1423 rc = cil_write_mls(node, cil_out);
1424 break;
1425 case CIL_SRC_INFO:
1426 break;
1427 case CIL_NONE:
1428 // TODO: add proper removal support
1429 *finished = CIL_TREE_SKIP_HEAD;
1430 break;
1431 default:
1432 cil_log(CIL_ERR, "Unknown AST flavor: %d.\n", node->flavor);
1433 rc = SEPOL_ERR;
1434 goto exit;
1435 break;
1436 }
1437 exit:
1438 return rc;
1439 }
1440
__cil_write_last_child_helper(struct cil_tree_node * node,void * extra_args)1441 static int __cil_write_last_child_helper(struct cil_tree_node *node, void *extra_args)
1442 {
1443 int rc = SEPOL_ERR;
1444 struct cil_db *db = NULL;
1445 struct cil_args_write *args = NULL;
1446 FILE *cil_out = NULL;
1447
1448 if (node == NULL || extra_args == NULL) {
1449 goto exit;
1450 }
1451
1452 args = extra_args;
1453 db = args->db;
1454 cil_out = args->cil_out;
1455
1456 if (node->parent && node->parent->flavor != CIL_ROOT && node->parent->flavor != CIL_SRC_INFO) {
1457 fprintf(cil_out,")");
1458 }
1459 rc = SEPOL_OK;
1460 exit:
1461 return rc;
1462 }
1463
1464 /* main exported function */
cil_write_ast(struct cil_db * db,const char * path)1465 int cil_write_ast(struct cil_db *db, const char* path) {
1466 int rc = SEPOL_ERR;
1467 struct cil_args_write extra_args;
1468 FILE *cil_out = NULL;
1469
1470 cil_out = fopen(path, "we");
1471 if (cil_out == NULL) {
1472 cil_log(CIL_ERR, "Failure opening output file for writing AST\n");
1473 rc = SEPOL_ERR;
1474 goto exit;
1475 }
1476
1477 extra_args.cil_out = cil_out;
1478 extra_args.db = db;
1479 rc = cil_tree_walk(db->ast->root, __cil_write_node_helper,
1480 __cil_write_first_child_helper,
1481 __cil_write_last_child_helper,
1482 &extra_args);
1483 if (rc != SEPOL_OK) {
1484 cil_log(CIL_INFO, "cil_tree_walk failed, rc: %d\n", rc);
1485 goto exit;
1486 }
1487
1488 exit:
1489 fclose(cil_out);
1490 cil_out = NULL;
1491 return rc;
1492 }
1493