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 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 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 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 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 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 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 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 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__) 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 */ 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