1 /* Author: Joshua Brindle <jbrindle (at) tresys.co 2 * Jason Tang <jtang (at) tresys.com> 3 * Caleb Case <ccase (at) tresys.com> 4 * 5 * Copyright (C) 2004-2005,2009 Tresys Technology, LLC 6 * 7 * This library is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * This library is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with this library; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22 /* This file implements only the publicly-visible module functions to libsemanage. */ 23 24 #include "direct_api.h" 25 #include "semanage_conf.h" 26 #include "semanage_store.h" 27 28 #include <stdarg.h> 29 #include <assert.h> 30 #include <stdlib.h> 31 #include <stdio.h> 32 #include <string.h> 33 #include <limits.h> 34 #include <fcntl.h> 35 #include <sys/types.h> 36 #include <sys/stat.h> 37 #include <errno.h> 38 #include <ctype.h> 39 40 #include "handle.h" 41 #include "modules.h" 42 #include "debug.h" 43 44 asm(".symver semanage_module_get_enabled_1_1,semanage_module_get_enabled@@LIBSEMANAGE_1.1"); 45 asm(".symver semanage_module_get_enabled_1_0,semanage_module_get_enabled (at) LIBSEMANAGE_1.0"); 46 asm(".symver semanage_module_install_pp,semanage_module_install (at) LIBSEMANAGE_1.0"); 47 asm(".symver semanage_module_install_hll,semanage_module_install@@LIBSEMANAGE_1.1"); 48 49 /* Takes a module stored in 'module_data' and parses its headers. 50 * Sets reference variables 'module_name' to module's name and 51 * 'version' to module's version. The caller is responsible for 52 * free()ing 'module_name' and 'version'; they will be 53 * set to NULL upon entering this function. Returns 0 on success, -1 54 * if out of memory, or -2 if data did not represent a module. 55 */ 56 static int parse_module_headers(semanage_handle_t * sh, char *module_data, 57 size_t data_len, char **module_name, char **version) 58 { 59 struct sepol_policy_file *pf; 60 int file_type; 61 *version = NULL; 62 63 if (sepol_policy_file_create(&pf)) { 64 ERR(sh, "Out of memory!"); 65 return -1; 66 } 67 sepol_policy_file_set_mem(pf, module_data, data_len); 68 sepol_policy_file_set_handle(pf, sh->sepolh); 69 if (module_data == NULL || 70 data_len == 0 || 71 sepol_module_package_info(pf, &file_type, module_name, version) == -1) { 72 sepol_policy_file_free(pf); 73 ERR(sh, "Could not parse module data."); 74 return -2; 75 } 76 sepol_policy_file_free(pf); 77 if (file_type != SEPOL_POLICY_MOD) { 78 ERR(sh, "Data did not represent a pp module. Please upgrade to the latest version of libsemanage to support hll modules."); 79 return -2; 80 } 81 82 return 0; 83 } 84 85 /* This function is used to preserve ABI compatibility with 86 * versions of semodule using LIBSEMANAGE_1.0 87 */ 88 int semanage_module_install_pp(semanage_handle_t * sh, 89 char *module_data, size_t data_len) 90 { 91 char *name = NULL; 92 char *version = NULL; 93 int status; 94 95 if ((status = parse_module_headers(sh, module_data, data_len, &name, &version)) != 0) { 96 goto cleanup; 97 } 98 99 status = semanage_module_install_hll(sh, module_data, data_len, name, "pp"); 100 101 cleanup: 102 free(name); 103 free(version); 104 return status; 105 } 106 107 int semanage_module_install_hll(semanage_handle_t * sh, 108 char *module_data, size_t data_len, const char *name, const char *ext_lang) 109 { 110 if (sh->funcs->install == NULL) { 111 ERR(sh, 112 "No install function defined for this connection type."); 113 return -1; 114 } else if (!sh->is_connected) { 115 ERR(sh, "Not connected."); 116 return -1; 117 } else if (!sh->is_in_transaction) { 118 if (semanage_begin_transaction(sh) < 0) { 119 return -1; 120 } 121 } 122 sh->modules_modified = 1; 123 return sh->funcs->install(sh, module_data, data_len, name, ext_lang); 124 } 125 126 int semanage_module_install_file(semanage_handle_t * sh, 127 const char *module_name) { 128 129 if (sh->funcs->install_file == NULL) { 130 ERR(sh, 131 "No install function defined for this connection type."); 132 return -1; 133 } else if (!sh->is_connected) { 134 ERR(sh, "Not connected."); 135 return -1; 136 } else if (!sh->is_in_transaction) { 137 if (semanage_begin_transaction(sh) < 0) { 138 return -1; 139 } 140 } 141 sh->modules_modified = 1; 142 return sh->funcs->install_file(sh, module_name); 143 } 144 145 int semanage_module_extract(semanage_handle_t * sh, 146 semanage_module_key_t *modkey, 147 int extract_cil, 148 void **mapped_data, 149 size_t *data_len, 150 semanage_module_info_t **modinfo) { 151 if (sh->funcs->extract == NULL) { 152 ERR(sh, 153 "No get function defined for this connection type."); 154 return -1; 155 } else if (!sh->is_connected) { 156 ERR(sh, "Not connected."); 157 return -1; 158 } 159 return sh->funcs->extract(sh, modkey, extract_cil, mapped_data, data_len, modinfo); 160 } 161 162 /* Legacy function that remains to preserve ABI 163 * compatibility. Please use semanage_module_install instead. 164 */ 165 int semanage_module_upgrade(semanage_handle_t * sh, 166 char *module_data, size_t data_len) 167 { 168 return semanage_module_install_pp(sh, module_data, data_len); 169 170 } 171 172 /* Legacy function that remains to preserve ABI 173 * compatibility. Please use semanage_module_install_file instead. 174 */ 175 int semanage_module_upgrade_file(semanage_handle_t * sh, 176 const char *module_name) 177 { 178 return semanage_module_install_file(sh, module_name); 179 } 180 181 /* Legacy function that remains to preserve ABI 182 * compatibility. Please use semanage_module_install instead. 183 */ 184 int semanage_module_install_base(semanage_handle_t * sh, 185 char *module_data, size_t data_len) 186 { 187 return semanage_module_install_pp(sh, module_data, data_len); 188 } 189 190 /* Legacy function that remains to preserve ABI 191 * compatibility. Please use semanage_module_install_file instead. 192 */ 193 int semanage_module_install_base_file(semanage_handle_t * sh, 194 const char *module_name) 195 { 196 return semanage_module_install_file(sh, module_name); 197 } 198 199 int semanage_module_remove(semanage_handle_t * sh, char *module_name) 200 { 201 if (sh->funcs->remove == NULL) { 202 ERR(sh, "No remove function defined for this connection type."); 203 return -1; 204 } else if (!sh->is_connected) { 205 ERR(sh, "Not connected."); 206 return -1; 207 } else if (!sh->is_in_transaction) { 208 if (semanage_begin_transaction(sh) < 0) { 209 return -1; 210 } 211 } 212 sh->modules_modified = 1; 213 return sh->funcs->remove(sh, module_name); 214 } 215 216 int semanage_module_list(semanage_handle_t * sh, 217 semanage_module_info_t ** modinfo, int *num_modules) 218 { 219 if (sh->funcs->list == NULL) { 220 ERR(sh, "No list function defined for this connection type."); 221 return -1; 222 } else if (!sh->is_connected) { 223 ERR(sh, "Not connected."); 224 return -1; 225 } 226 return sh->funcs->list(sh, modinfo, num_modules); 227 } 228 229 void semanage_module_info_datum_destroy(semanage_module_info_t * modinfo) 230 { 231 if (modinfo != NULL) { 232 modinfo->priority = 0; 233 234 free(modinfo->name); 235 modinfo->name = NULL; 236 237 free(modinfo->lang_ext); 238 modinfo->lang_ext = NULL; 239 240 modinfo->enabled = -1; 241 } 242 } 243 244 hidden_def(semanage_module_info_datum_destroy) 245 246 semanage_module_info_t *semanage_module_list_nth(semanage_module_info_t * list, 247 int n) 248 { 249 return list + n; 250 } 251 252 hidden_def(semanage_module_list_nth) 253 254 const char *semanage_module_get_name(semanage_module_info_t * modinfo) 255 { 256 return modinfo->name; 257 } 258 259 hidden_def(semanage_module_get_name) 260 261 /* Legacy function that remains to preserve ABI 262 * compatibility. 263 */ 264 const char *semanage_module_get_version(semanage_module_info_t * modinfo 265 __attribute__ ((unused))) 266 { 267 return ""; 268 } 269 270 int semanage_module_info_create(semanage_handle_t *sh, 271 semanage_module_info_t **modinfo) 272 { 273 assert(sh); 274 assert(modinfo); 275 276 *modinfo = malloc(sizeof(semanage_module_info_t)); 277 if (*modinfo == NULL) return -1; 278 279 return semanage_module_info_init(sh, *modinfo); 280 } 281 282 hidden_def(semanage_module_info_create) 283 284 int semanage_module_info_destroy(semanage_handle_t *sh, 285 semanage_module_info_t *modinfo) 286 { 287 assert(sh); 288 289 if (!modinfo) { 290 return 0; 291 } 292 293 free(modinfo->name); 294 free(modinfo->lang_ext); 295 296 return semanage_module_info_init(sh, modinfo); 297 } 298 299 hidden_def(semanage_module_info_destroy) 300 301 int semanage_module_info_init(semanage_handle_t *sh, 302 semanage_module_info_t *modinfo) 303 { 304 assert(sh); 305 assert(modinfo); 306 307 modinfo->priority = 0; 308 modinfo->name = NULL; 309 modinfo->lang_ext = NULL; 310 modinfo->enabled = -1; 311 312 return 0; 313 } 314 315 int semanage_module_info_clone(semanage_handle_t *sh, 316 const semanage_module_info_t *source, 317 semanage_module_info_t *target) 318 { 319 assert(sh); 320 assert(source); 321 assert(target); 322 323 int status = 0; 324 int ret = 0; 325 326 ret = semanage_module_info_destroy(sh, target); 327 if (ret != 0) { 328 status = -1; 329 goto cleanup; 330 } 331 332 ret = semanage_module_info_set_priority(sh, target, source->priority); 333 if (ret != 0) { 334 status = -1; 335 goto cleanup; 336 } 337 338 ret = semanage_module_info_set_name(sh, target, source->name); 339 if (ret != 0) { 340 status = -1; 341 goto cleanup; 342 } 343 344 ret = semanage_module_info_set_lang_ext(sh, target, source->lang_ext); 345 if (ret != 0) { 346 status = -1; 347 goto cleanup; 348 } 349 350 ret = semanage_module_info_set_enabled(sh, target, source->enabled); 351 if (ret != 0) { 352 status = -1; 353 goto cleanup; 354 } 355 356 cleanup: 357 if (status != 0) semanage_module_info_destroy(sh, target); 358 return status; 359 } 360 361 int semanage_module_info_get_priority(semanage_handle_t *sh, 362 semanage_module_info_t *modinfo, 363 uint16_t *priority) 364 { 365 assert(sh); 366 assert(modinfo); 367 assert(priority); 368 369 *priority = modinfo->priority; 370 371 return 0; 372 } 373 374 hidden_def(semanage_module_info_get_priority) 375 376 int semanage_module_info_get_name(semanage_handle_t *sh, 377 semanage_module_info_t *modinfo, 378 const char **name) 379 { 380 assert(sh); 381 assert(modinfo); 382 assert(name); 383 384 *name = modinfo->name; 385 386 return 0; 387 } 388 389 hidden_def(semanage_module_info_get_name) 390 391 int semanage_module_info_get_lang_ext(semanage_handle_t *sh, 392 semanage_module_info_t *modinfo, 393 const char **lang_ext) 394 { 395 assert(sh); 396 assert(modinfo); 397 assert(lang_ext); 398 399 *lang_ext = modinfo->lang_ext; 400 401 return 0; 402 } 403 404 hidden_def(semanage_module_info_get_lang_ext) 405 406 int semanage_module_info_get_enabled(semanage_handle_t *sh, 407 semanage_module_info_t *modinfo, 408 int *enabled) 409 { 410 assert(sh); 411 assert(modinfo); 412 assert(enabled); 413 414 *enabled = modinfo->enabled; 415 416 return 0; 417 } 418 419 hidden_def(semanage_module_info_get_enabled) 420 421 int semanage_module_info_set_priority(semanage_handle_t *sh, 422 semanage_module_info_t *modinfo, 423 uint16_t priority) 424 { 425 assert(sh); 426 assert(modinfo); 427 428 /* Verify priority */ 429 if (semanage_module_validate_priority(priority) < 0) { 430 errno = 0; 431 ERR(sh, "Priority %d is invalid.", priority); 432 return -1; 433 } 434 435 modinfo->priority = priority; 436 437 return 0; 438 } 439 440 hidden_def(semanage_module_info_set_priority) 441 442 int semanage_module_info_set_name(semanage_handle_t *sh, 443 semanage_module_info_t *modinfo, 444 const char *name) 445 { 446 assert(sh); 447 assert(modinfo); 448 assert(name); 449 450 char * tmp; 451 452 /* Verify name */ 453 if (semanage_module_validate_name(name) < 0) { 454 errno = 0; 455 ERR(sh, "Name %s is invalid.", name); 456 return -1; 457 } 458 459 tmp = strdup(name); 460 if (!tmp) { 461 ERR(sh, "No memory available for strdup"); 462 return -1; 463 } 464 465 free(modinfo->name); 466 modinfo->name = tmp; 467 468 return 0; 469 } 470 471 hidden_def(semanage_module_info_set_name) 472 473 int semanage_module_info_set_lang_ext(semanage_handle_t *sh, 474 semanage_module_info_t *modinfo, 475 const char *lang_ext) 476 { 477 assert(sh); 478 assert(modinfo); 479 assert(lang_ext); 480 481 char * tmp; 482 483 /* Verify extension */ 484 if (semanage_module_validate_lang_ext(lang_ext) < 0) { 485 errno = 0; 486 ERR(sh, "Language extensions %s is invalid.", lang_ext); 487 return -1; 488 } 489 490 tmp = strdup(lang_ext); 491 if (!tmp) { 492 ERR(sh, "No memory available for strdup"); 493 return -1; 494 } 495 496 free(modinfo->lang_ext); 497 modinfo->lang_ext = tmp; 498 499 return 0; 500 } 501 502 hidden_def(semanage_module_info_set_lang_ext) 503 504 int semanage_module_info_set_enabled(semanage_handle_t *sh, 505 semanage_module_info_t *modinfo, 506 int enabled) 507 { 508 assert(sh); 509 assert(modinfo); 510 511 /* Verify enabled */ 512 if (semanage_module_validate_enabled(enabled) < 0) { 513 errno = 0; 514 ERR(sh, "Enabled status %d is invalid.", enabled); 515 return -1; 516 } 517 518 modinfo->enabled = enabled; 519 520 return 0; 521 } 522 523 hidden_def(semanage_module_info_set_enabled) 524 525 int semanage_module_get_path(semanage_handle_t *sh, 526 const semanage_module_info_t *modinfo, 527 enum semanage_module_path_type type, 528 char *path, 529 size_t len) 530 { 531 assert(sh); 532 assert(modinfo); 533 assert(path); 534 535 int status = 0; 536 int ret = 0; 537 538 const char *modules_path = NULL; 539 const char *file = NULL; 540 541 modules_path = sh->is_in_transaction ? 542 semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES): 543 semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES); 544 545 switch (type) { 546 case SEMANAGE_MODULE_PATH_PRIORITY: 547 /* verify priority */ 548 ret = semanage_module_validate_priority(modinfo->priority); 549 if (ret < 0) { 550 errno = 0; 551 ERR(sh, 552 "Priority %d is invalid.", 553 modinfo->priority); 554 status = ret; 555 goto cleanup; 556 } 557 558 ret = snprintf(path, 559 len, 560 "%s/%03u", 561 modules_path, 562 modinfo->priority); 563 if (ret < 0 || (size_t)ret >= len) { 564 ERR(sh, "Unable to compose priority path."); 565 status = -1; 566 goto cleanup; 567 } 568 break; 569 case SEMANAGE_MODULE_PATH_NAME: 570 /* verify priority and name */ 571 ret = semanage_module_validate_priority(modinfo->priority); 572 if (ret < 0) { 573 errno = 0; 574 ERR(sh, 575 "Priority %d is invalid.", 576 modinfo->priority); 577 status = -1; 578 goto cleanup; 579 } 580 581 ret = semanage_module_validate_name(modinfo->name); 582 if (ret < 0) { 583 errno = 0; 584 ERR(sh, "Name %s is invalid.", modinfo->name); 585 status = -1; 586 goto cleanup; 587 } 588 589 ret = snprintf(path, 590 len, 591 "%s/%03u/%s", 592 modules_path, 593 modinfo->priority, 594 modinfo->name); 595 if (ret < 0 || (size_t)ret >= len) { 596 ERR(sh, "Unable to compose name path."); 597 status = -1; 598 goto cleanup; 599 } 600 break; 601 case SEMANAGE_MODULE_PATH_HLL: 602 if (file == NULL) file = "hll"; 603 case SEMANAGE_MODULE_PATH_CIL: 604 if (file == NULL) file = "cil"; 605 case SEMANAGE_MODULE_PATH_LANG_EXT: 606 if (file == NULL) file = "lang_ext"; 607 608 /* verify priority and name */ 609 ret = semanage_module_validate_priority(modinfo->priority); 610 if (ret < 0) { 611 errno = 0; 612 ERR(sh, 613 "Priority %d is invalid.", 614 modinfo->priority); 615 status = -1; 616 goto cleanup; 617 } 618 619 ret = semanage_module_validate_name(modinfo->name); 620 if (ret < 0) { 621 errno = 0; 622 ERR(sh, "Name %s is invalid.", modinfo->name); 623 status = -1; 624 goto cleanup; 625 } 626 627 ret = snprintf(path, 628 len, 629 "%s/%03u/%s/%s", 630 modules_path, 631 modinfo->priority, 632 modinfo->name, 633 file); 634 if (ret < 0 || (size_t)ret >= len) { 635 ERR(sh, 636 "Unable to compose path for %s file.", 637 file); 638 status = -1; 639 goto cleanup; 640 } 641 break; 642 case SEMANAGE_MODULE_PATH_DISABLED: 643 /* verify name */ 644 ret = semanage_module_validate_name(modinfo->name); 645 if (ret < 0) { 646 errno = 0; 647 ERR(sh, "Name %s is invalid.", modinfo->name); 648 status = -1; 649 goto cleanup; 650 } 651 652 ret = snprintf(path, 653 len, 654 "%s/disabled/%s", 655 modules_path, 656 modinfo->name); 657 if (ret < 0 || (size_t)ret >= len) { 658 ERR(sh, 659 "Unable to compose disabled status path."); 660 status = -1; 661 goto cleanup; 662 } 663 break; 664 default: 665 ERR(sh, "Invalid module path type %d.", type); 666 status = -1; 667 goto cleanup; 668 } 669 670 cleanup: 671 return status; 672 } 673 674 int semanage_module_key_create(semanage_handle_t *sh, 675 semanage_module_key_t **modkey) 676 { 677 assert(sh); 678 assert(modkey); 679 680 *modkey = malloc(sizeof(semanage_module_key_t)); 681 if (*modkey == NULL) return -1; 682 683 return semanage_module_key_init(sh, *modkey); 684 } 685 686 hidden_def(semanage_module_key_create) 687 688 int semanage_module_key_destroy(semanage_handle_t *sh, 689 semanage_module_key_t *modkey) 690 { 691 assert(sh); 692 693 if (!modkey) { 694 return 0; 695 } 696 697 free(modkey->name); 698 699 return semanage_module_key_init(sh, modkey); 700 } 701 702 hidden_def(semanage_module_key_destroy) 703 704 int semanage_module_key_init(semanage_handle_t *sh, 705 semanage_module_key_t *modkey) 706 { 707 assert(sh); 708 assert(modkey); 709 710 modkey->name = NULL; 711 modkey->priority = 0; 712 713 return 0; 714 } 715 716 int semanage_module_key_get_name(semanage_handle_t *sh, 717 semanage_module_key_t *modkey, 718 const char **name) 719 { 720 assert(sh); 721 assert(modkey); 722 assert(name); 723 724 *name = modkey->name; 725 726 return 0; 727 } 728 729 hidden_def(semanage_module_key_get_name) 730 731 int semanage_module_key_get_priority(semanage_handle_t *sh, 732 semanage_module_key_t *modkey, 733 uint16_t *priority) 734 { 735 assert(sh); 736 assert(modkey); 737 assert(priority); 738 739 *priority = modkey->priority; 740 741 return 0; 742 } 743 744 hidden_def(semanage_module_key_get_priority) 745 746 int semanage_module_key_set_name(semanage_handle_t *sh, 747 semanage_module_key_t *modkey, 748 const char *name) 749 { 750 assert(sh); 751 assert(modkey); 752 assert(name); 753 754 int status = 0; 755 char *tmp = NULL; 756 757 if (semanage_module_validate_name(name) < 0) { 758 errno = 0; 759 ERR(sh, "Name %s is invalid.", name); 760 return -1; 761 } 762 763 tmp = strdup(name); 764 if (tmp == NULL) { 765 ERR(sh, "No memory available for strdup"); 766 status = -1; 767 goto cleanup; 768 } 769 770 free(modkey->name); 771 modkey->name = tmp; 772 773 cleanup: 774 return status; 775 } 776 777 hidden_def(semanage_module_key_set_name) 778 779 int semanage_module_key_set_priority(semanage_handle_t *sh, 780 semanage_module_key_t *modkey, 781 uint16_t priority) 782 { 783 assert(sh); 784 assert(modkey); 785 786 if (semanage_module_validate_priority(priority) < 0) { 787 errno = 0; 788 ERR(sh, "Priority %d is invalid.", priority); 789 return -1; 790 } 791 792 modkey->priority = priority; 793 794 return 0; 795 } 796 797 hidden_def(semanage_module_key_set_priority) 798 799 int semanage_module_get_enabled_1_1(semanage_handle_t *sh, 800 const semanage_module_key_t *modkey, 801 int *enabled) 802 { 803 assert(sh); 804 assert(modkey); 805 assert(enabled); 806 807 if (sh->funcs->get_enabled == NULL) { 808 ERR(sh, 809 "No get_enabled function defined for this connection type."); 810 return -1; 811 } else if (!sh->is_connected) { 812 ERR(sh, "Not connected."); 813 return -1; 814 } 815 816 return sh->funcs->get_enabled(sh, modkey, enabled); 817 } 818 819 int semanage_module_get_enabled_1_0(semanage_module_info_t *modinfo) 820 { 821 return modinfo->enabled; 822 } 823 824 int semanage_module_set_enabled(semanage_handle_t *sh, 825 const semanage_module_key_t *modkey, 826 int enabled) 827 { 828 assert(sh); 829 assert(modkey); 830 831 if (sh->funcs->set_enabled == NULL) { 832 ERR(sh, 833 "No set_enabled function defined for this connection type."); 834 return -1; 835 } else if (!sh->is_connected) { 836 ERR(sh, "Not connected."); 837 return -1; 838 } else if (!sh->is_in_transaction) { 839 if (semanage_begin_transaction(sh) < 0) { 840 return -1; 841 } 842 } 843 844 sh->modules_modified = 1; 845 return sh->funcs->set_enabled(sh, modkey, enabled); 846 } 847 848 hidden_def(semanage_module_set_enabled) 849 850 /* This function exists only for ABI compatability. It has been deprecated and 851 * should not be used. Instead, use semanage_module_set_enabled() */ 852 int semanage_module_enable(semanage_handle_t *sh, char *module_name) 853 { 854 int rc = -1; 855 semanage_module_key_t *modkey = NULL; 856 857 rc = semanage_module_key_create(sh, &modkey); 858 if (rc != 0) 859 goto exit; 860 861 rc = semanage_module_key_set_name(sh, modkey, module_name); 862 if (rc != 0) 863 goto exit; 864 865 rc = semanage_module_set_enabled(sh, modkey, 1); 866 if (rc != 0) 867 goto exit; 868 869 rc = 0; 870 871 exit: 872 semanage_module_key_destroy(sh, modkey); 873 free(modkey); 874 875 return rc; 876 } 877 878 /* This function exists only for ABI compatability. It has been deprecated and 879 * should not be used. Instead, use semanage_module_set_enabled() */ 880 int semanage_module_disable(semanage_handle_t *sh, char *module_name) 881 { 882 int rc = -1; 883 semanage_module_key_t *modkey = NULL; 884 885 rc = semanage_module_key_create(sh, &modkey); 886 if (rc != 0) 887 goto exit; 888 889 rc = semanage_module_key_set_name(sh, modkey, module_name); 890 if (rc != 0) 891 goto exit; 892 893 rc = semanage_module_set_enabled(sh, modkey, 0); 894 if (rc != 0) 895 goto exit; 896 897 rc = 0; 898 899 exit: 900 semanage_module_key_destroy(sh, modkey); 901 free(modkey); 902 903 return rc; 904 } 905 906 /* Converts a string to a priority 907 * 908 * returns -1 if str is not a valid priority. 909 * returns 0 and sets priority if str is a valid priority 910 */ 911 int semanage_string_to_priority(const char *str, uint16_t *priority) 912 { 913 unsigned long val; 914 char *endptr = NULL; 915 int status = -1; 916 917 if (str == NULL || priority == NULL) { 918 goto exit; 919 } 920 921 errno = 0; 922 923 val = strtoul(str, &endptr, 10); 924 925 if (errno != 0 || endptr == str || *endptr != '\0' || val > UINT16_MAX) { 926 goto exit; 927 } 928 929 if (semanage_module_validate_priority((uint16_t)val) < 0) { 930 goto exit; 931 } 932 933 *priority = val; 934 status = 0; 935 936 exit: 937 return status; 938 } 939 940 /* Validates a module info struct. 941 * 942 * Returns -1 if module is invalid, 0 otherwise. 943 */ 944 int semanage_module_info_validate(const semanage_module_info_t *modinfo) 945 { 946 if (semanage_module_validate_priority(modinfo->priority) != 0 || 947 semanage_module_validate_name(modinfo->name) != 0 || 948 semanage_module_validate_lang_ext(modinfo->lang_ext) != 0 || 949 semanage_module_validate_enabled(modinfo->enabled) != 0) { 950 return -1; 951 } 952 return 0; 953 } 954 955 #define PRIORITY_MIN 1 956 #define PRIORITY_MAX 999 957 958 /* Validates priority. 959 * 960 * returns -1 if priority is not in the valid range, returns 0 otherwise 961 */ 962 int semanage_module_validate_priority(uint16_t priority) 963 { 964 if (priority >= PRIORITY_MIN && priority <= PRIORITY_MAX) { 965 return 0; 966 } 967 968 return -1; 969 } 970 971 /* Validates module name. 972 * 973 * A module name must match one of the following regular expressions 974 * to be considered valid: 975 * 976 * ^[a-zA-Z](\.?[a-zA-Z0-9_-])*$ 977 * 978 * returns -1 if name is not valid, returns 0 otherwise 979 */ 980 int semanage_module_validate_name(const char * name) 981 { 982 int status = 0; 983 984 if (name == NULL) { 985 status = -1; 986 goto exit; 987 } 988 989 if (!isalpha(*name)) { 990 status = -1; 991 goto exit; 992 } 993 994 #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-') 995 996 for (name++; *name; name++) { 997 if (ISVALIDCHAR(*name)) { 998 continue; 999 } 1000 if (*name == '.' && name++ && ISVALIDCHAR(*name)) { 1001 continue; 1002 } 1003 status = -1; 1004 goto exit; 1005 } 1006 1007 #undef ISVALIDCHAR 1008 1009 exit: 1010 return status; 1011 } 1012 1013 /* Validates module enabled status. 1014 * 1015 * Valid enabled values are 1, 0, and -1. 1016 * 1017 * returns 0 if enabled is a valid value, returns -1 otherwise. 1018 */ 1019 int semanage_module_validate_enabled(int enabled) 1020 { 1021 if (enabled == 1 || enabled == 0 || enabled == -1) { 1022 return 0; 1023 } 1024 1025 return -1; 1026 } 1027 1028 /* Validate extension. 1029 * 1030 * An extension must match the following regular expression to be 1031 * considered valid: 1032 * 1033 * ^[a-zA-Z0-9][a-zA-Z0-9_-]*$ 1034 * 1035 * returns 0 if ext is a valid value, returns -1 otherwise. 1036 */ 1037 int semanage_module_validate_lang_ext(const char *ext) 1038 { 1039 int status = 0; 1040 1041 if (ext == NULL) { 1042 status = -1; 1043 goto exit; 1044 } 1045 1046 if (!isalnum(*ext)) { 1047 status = -1; 1048 goto exit; 1049 } 1050 1051 #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-') 1052 1053 for (ext++; *ext; ext++) { 1054 if (ISVALIDCHAR(*ext)) { 1055 continue; 1056 } 1057 status = -1; 1058 goto exit; 1059 } 1060 1061 #undef ISVALIDCHAR 1062 1063 exit: 1064 return status; 1065 } 1066 1067 int semanage_module_get_module_info(semanage_handle_t *sh, 1068 const semanage_module_key_t *modkey, 1069 semanage_module_info_t **modinfo) 1070 { 1071 assert(sh); 1072 assert(modkey); 1073 assert(modinfo); 1074 1075 if (sh->funcs->get_module_info == NULL) { 1076 ERR(sh, 1077 "No get module info function defined for this connection type."); 1078 return -1; 1079 } else if (!sh->is_connected) { 1080 ERR(sh, "Not connected."); 1081 return -1; 1082 } 1083 1084 return sh->funcs->get_module_info(sh, modkey, modinfo); 1085 } 1086 1087 int semanage_module_list_all(semanage_handle_t *sh, 1088 semanage_module_info_t **modinfos, 1089 int *modinfos_len) 1090 { 1091 assert(sh); 1092 assert(modinfos); 1093 assert(modinfos_len); 1094 1095 if (sh->funcs->list_all == NULL) { 1096 ERR(sh, 1097 "No list all function defined for this connection type."); 1098 return -1; 1099 } else if (!sh->is_connected) { 1100 ERR(sh, "Not connected."); 1101 return -1; 1102 } 1103 1104 return sh->funcs->list_all(sh, modinfos, modinfos_len); 1105 } 1106 1107 int semanage_module_install_info(semanage_handle_t *sh, 1108 const semanage_module_info_t *modinfo, 1109 char *data, 1110 size_t data_len) 1111 { 1112 if (sh->funcs->install_info == NULL) { 1113 ERR(sh, 1114 "No install info function defined for this connection type."); 1115 return -1; 1116 } else if (!sh->is_connected) { 1117 ERR(sh, "Not connected."); 1118 return -1; 1119 } else if (!sh->is_in_transaction) { 1120 if (semanage_begin_transaction(sh) < 0) { 1121 return -1; 1122 } 1123 } 1124 sh->modules_modified = 1; 1125 return sh->funcs->install_info(sh, modinfo, data, data_len); 1126 } 1127 1128 int semanage_module_remove_key(semanage_handle_t *sh, 1129 const semanage_module_key_t *modkey) 1130 { 1131 if (sh->funcs->remove_key== NULL) { 1132 ERR(sh, 1133 "No remove key function defined for this connection type."); 1134 return -1; 1135 } else if (!sh->is_connected) { 1136 ERR(sh, "Not connected."); 1137 return -1; 1138 } else if (!sh->is_in_transaction) { 1139 if (semanage_begin_transaction(sh) < 0) { 1140 return -1; 1141 } 1142 } 1143 sh->modules_modified = 1; 1144 return sh->funcs->remove_key(sh, modkey); 1145 } 1146 1147