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 /* FALLTHRU */ 604 case SEMANAGE_MODULE_PATH_CIL: 605 if (file == NULL) file = "cil"; 606 /* FALLTHRU */ 607 case SEMANAGE_MODULE_PATH_LANG_EXT: 608 if (file == NULL) file = "lang_ext"; 609 610 /* verify priority and name */ 611 ret = semanage_module_validate_priority(modinfo->priority); 612 if (ret < 0) { 613 errno = 0; 614 ERR(sh, 615 "Priority %d is invalid.", 616 modinfo->priority); 617 status = -1; 618 goto cleanup; 619 } 620 621 ret = semanage_module_validate_name(modinfo->name); 622 if (ret < 0) { 623 errno = 0; 624 ERR(sh, "Name %s is invalid.", modinfo->name); 625 status = -1; 626 goto cleanup; 627 } 628 629 ret = snprintf(path, 630 len, 631 "%s/%03u/%s/%s", 632 modules_path, 633 modinfo->priority, 634 modinfo->name, 635 file); 636 if (ret < 0 || (size_t)ret >= len) { 637 ERR(sh, 638 "Unable to compose path for %s file.", 639 file); 640 status = -1; 641 goto cleanup; 642 } 643 break; 644 case SEMANAGE_MODULE_PATH_DISABLED: 645 /* verify name */ 646 ret = semanage_module_validate_name(modinfo->name); 647 if (ret < 0) { 648 errno = 0; 649 ERR(sh, "Name %s is invalid.", modinfo->name); 650 status = -1; 651 goto cleanup; 652 } 653 654 ret = snprintf(path, 655 len, 656 "%s/disabled/%s", 657 modules_path, 658 modinfo->name); 659 if (ret < 0 || (size_t)ret >= len) { 660 ERR(sh, 661 "Unable to compose disabled status path."); 662 status = -1; 663 goto cleanup; 664 } 665 break; 666 default: 667 ERR(sh, "Invalid module path type %d.", type); 668 status = -1; 669 goto cleanup; 670 } 671 672 cleanup: 673 return status; 674 } 675 676 int semanage_module_key_create(semanage_handle_t *sh, 677 semanage_module_key_t **modkey) 678 { 679 assert(sh); 680 assert(modkey); 681 682 *modkey = malloc(sizeof(semanage_module_key_t)); 683 if (*modkey == NULL) return -1; 684 685 return semanage_module_key_init(sh, *modkey); 686 } 687 688 hidden_def(semanage_module_key_create) 689 690 int semanage_module_key_destroy(semanage_handle_t *sh, 691 semanage_module_key_t *modkey) 692 { 693 assert(sh); 694 695 if (!modkey) { 696 return 0; 697 } 698 699 free(modkey->name); 700 701 return semanage_module_key_init(sh, modkey); 702 } 703 704 hidden_def(semanage_module_key_destroy) 705 706 int semanage_module_key_init(semanage_handle_t *sh, 707 semanage_module_key_t *modkey) 708 { 709 assert(sh); 710 assert(modkey); 711 712 modkey->name = NULL; 713 modkey->priority = 0; 714 715 return 0; 716 } 717 718 int semanage_module_key_get_name(semanage_handle_t *sh, 719 semanage_module_key_t *modkey, 720 const char **name) 721 { 722 assert(sh); 723 assert(modkey); 724 assert(name); 725 726 *name = modkey->name; 727 728 return 0; 729 } 730 731 hidden_def(semanage_module_key_get_name) 732 733 int semanage_module_key_get_priority(semanage_handle_t *sh, 734 semanage_module_key_t *modkey, 735 uint16_t *priority) 736 { 737 assert(sh); 738 assert(modkey); 739 assert(priority); 740 741 *priority = modkey->priority; 742 743 return 0; 744 } 745 746 hidden_def(semanage_module_key_get_priority) 747 748 int semanage_module_key_set_name(semanage_handle_t *sh, 749 semanage_module_key_t *modkey, 750 const char *name) 751 { 752 assert(sh); 753 assert(modkey); 754 assert(name); 755 756 int status = 0; 757 char *tmp = NULL; 758 759 if (semanage_module_validate_name(name) < 0) { 760 errno = 0; 761 ERR(sh, "Name %s is invalid.", name); 762 return -1; 763 } 764 765 tmp = strdup(name); 766 if (tmp == NULL) { 767 ERR(sh, "No memory available for strdup"); 768 status = -1; 769 goto cleanup; 770 } 771 772 free(modkey->name); 773 modkey->name = tmp; 774 775 cleanup: 776 return status; 777 } 778 779 hidden_def(semanage_module_key_set_name) 780 781 int semanage_module_key_set_priority(semanage_handle_t *sh, 782 semanage_module_key_t *modkey, 783 uint16_t priority) 784 { 785 assert(sh); 786 assert(modkey); 787 788 if (semanage_module_validate_priority(priority) < 0) { 789 errno = 0; 790 ERR(sh, "Priority %d is invalid.", priority); 791 return -1; 792 } 793 794 modkey->priority = priority; 795 796 return 0; 797 } 798 799 hidden_def(semanage_module_key_set_priority) 800 801 int semanage_module_get_enabled_1_1(semanage_handle_t *sh, 802 const semanage_module_key_t *modkey, 803 int *enabled) 804 { 805 assert(sh); 806 assert(modkey); 807 assert(enabled); 808 809 if (sh->funcs->get_enabled == NULL) { 810 ERR(sh, 811 "No get_enabled function defined for this connection type."); 812 return -1; 813 } else if (!sh->is_connected) { 814 ERR(sh, "Not connected."); 815 return -1; 816 } 817 818 return sh->funcs->get_enabled(sh, modkey, enabled); 819 } 820 821 int semanage_module_get_enabled_1_0(semanage_module_info_t *modinfo) 822 { 823 return modinfo->enabled; 824 } 825 826 int semanage_module_set_enabled(semanage_handle_t *sh, 827 const semanage_module_key_t *modkey, 828 int enabled) 829 { 830 assert(sh); 831 assert(modkey); 832 833 if (sh->funcs->set_enabled == NULL) { 834 ERR(sh, 835 "No set_enabled function defined for this connection type."); 836 return -1; 837 } else if (!sh->is_connected) { 838 ERR(sh, "Not connected."); 839 return -1; 840 } else if (!sh->is_in_transaction) { 841 if (semanage_begin_transaction(sh) < 0) { 842 return -1; 843 } 844 } 845 846 sh->modules_modified = 1; 847 return sh->funcs->set_enabled(sh, modkey, enabled); 848 } 849 850 hidden_def(semanage_module_set_enabled) 851 852 /* This function exists only for ABI compatability. It has been deprecated and 853 * should not be used. Instead, use semanage_module_set_enabled() */ 854 int semanage_module_enable(semanage_handle_t *sh, char *module_name) 855 { 856 int rc = -1; 857 semanage_module_key_t *modkey = NULL; 858 859 rc = semanage_module_key_create(sh, &modkey); 860 if (rc != 0) 861 goto exit; 862 863 rc = semanage_module_key_set_name(sh, modkey, module_name); 864 if (rc != 0) 865 goto exit; 866 867 rc = semanage_module_set_enabled(sh, modkey, 1); 868 if (rc != 0) 869 goto exit; 870 871 rc = 0; 872 873 exit: 874 semanage_module_key_destroy(sh, modkey); 875 free(modkey); 876 877 return rc; 878 } 879 880 /* This function exists only for ABI compatability. It has been deprecated and 881 * should not be used. Instead, use semanage_module_set_enabled() */ 882 int semanage_module_disable(semanage_handle_t *sh, char *module_name) 883 { 884 int rc = -1; 885 semanage_module_key_t *modkey = NULL; 886 887 rc = semanage_module_key_create(sh, &modkey); 888 if (rc != 0) 889 goto exit; 890 891 rc = semanage_module_key_set_name(sh, modkey, module_name); 892 if (rc != 0) 893 goto exit; 894 895 rc = semanage_module_set_enabled(sh, modkey, 0); 896 if (rc != 0) 897 goto exit; 898 899 rc = 0; 900 901 exit: 902 semanage_module_key_destroy(sh, modkey); 903 free(modkey); 904 905 return rc; 906 } 907 908 /* Converts a string to a priority 909 * 910 * returns -1 if str is not a valid priority. 911 * returns 0 and sets priority if str is a valid priority 912 */ 913 int semanage_string_to_priority(const char *str, uint16_t *priority) 914 { 915 unsigned long val; 916 char *endptr = NULL; 917 int status = -1; 918 919 if (str == NULL || priority == NULL) { 920 goto exit; 921 } 922 923 errno = 0; 924 925 val = strtoul(str, &endptr, 10); 926 927 if (errno != 0 || endptr == str || *endptr != '\0' || val > UINT16_MAX) { 928 goto exit; 929 } 930 931 if (semanage_module_validate_priority((uint16_t)val) < 0) { 932 goto exit; 933 } 934 935 *priority = val; 936 status = 0; 937 938 exit: 939 return status; 940 } 941 942 /* Validates a module info struct. 943 * 944 * Returns -1 if module is invalid, 0 otherwise. 945 */ 946 int semanage_module_info_validate(const semanage_module_info_t *modinfo) 947 { 948 if (semanage_module_validate_priority(modinfo->priority) != 0 || 949 semanage_module_validate_name(modinfo->name) != 0 || 950 semanage_module_validate_lang_ext(modinfo->lang_ext) != 0 || 951 semanage_module_validate_enabled(modinfo->enabled) != 0) { 952 return -1; 953 } 954 return 0; 955 } 956 957 #define PRIORITY_MIN 1 958 #define PRIORITY_MAX 999 959 960 /* Validates priority. 961 * 962 * returns -1 if priority is not in the valid range, returns 0 otherwise 963 */ 964 int semanage_module_validate_priority(uint16_t priority) 965 { 966 if (priority >= PRIORITY_MIN && priority <= PRIORITY_MAX) { 967 return 0; 968 } 969 970 return -1; 971 } 972 973 /* Validates module name. 974 * 975 * A module name must match one of the following regular expressions 976 * to be considered valid: 977 * 978 * ^[a-zA-Z](\.?[a-zA-Z0-9_-])*$ 979 * 980 * returns -1 if name is not valid, returns 0 otherwise 981 */ 982 int semanage_module_validate_name(const char * name) 983 { 984 int status = 0; 985 986 if (name == NULL) { 987 status = -1; 988 goto exit; 989 } 990 991 if (!isalpha(*name)) { 992 status = -1; 993 goto exit; 994 } 995 996 #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-') 997 998 for (name++; *name; name++) { 999 if (ISVALIDCHAR(*name)) { 1000 continue; 1001 } 1002 if (*name == '.' && name++ && ISVALIDCHAR(*name)) { 1003 continue; 1004 } 1005 status = -1; 1006 goto exit; 1007 } 1008 1009 #undef ISVALIDCHAR 1010 1011 exit: 1012 return status; 1013 } 1014 1015 /* Validates module enabled status. 1016 * 1017 * Valid enabled values are 1, 0, and -1. 1018 * 1019 * returns 0 if enabled is a valid value, returns -1 otherwise. 1020 */ 1021 int semanage_module_validate_enabled(int enabled) 1022 { 1023 if (enabled == 1 || enabled == 0 || enabled == -1) { 1024 return 0; 1025 } 1026 1027 return -1; 1028 } 1029 1030 /* Validate extension. 1031 * 1032 * An extension must match the following regular expression to be 1033 * considered valid: 1034 * 1035 * ^[a-zA-Z0-9][a-zA-Z0-9_-]*$ 1036 * 1037 * returns 0 if ext is a valid value, returns -1 otherwise. 1038 */ 1039 int semanage_module_validate_lang_ext(const char *ext) 1040 { 1041 int status = 0; 1042 1043 if (ext == NULL) { 1044 status = -1; 1045 goto exit; 1046 } 1047 1048 if (!isalnum(*ext)) { 1049 status = -1; 1050 goto exit; 1051 } 1052 1053 #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-') 1054 1055 for (ext++; *ext; ext++) { 1056 if (ISVALIDCHAR(*ext)) { 1057 continue; 1058 } 1059 status = -1; 1060 goto exit; 1061 } 1062 1063 #undef ISVALIDCHAR 1064 1065 exit: 1066 return status; 1067 } 1068 1069 int semanage_module_get_module_info(semanage_handle_t *sh, 1070 const semanage_module_key_t *modkey, 1071 semanage_module_info_t **modinfo) 1072 { 1073 assert(sh); 1074 assert(modkey); 1075 assert(modinfo); 1076 1077 if (sh->funcs->get_module_info == NULL) { 1078 ERR(sh, 1079 "No get module info function defined for this connection type."); 1080 return -1; 1081 } else if (!sh->is_connected) { 1082 ERR(sh, "Not connected."); 1083 return -1; 1084 } 1085 1086 return sh->funcs->get_module_info(sh, modkey, modinfo); 1087 } 1088 1089 int semanage_module_list_all(semanage_handle_t *sh, 1090 semanage_module_info_t **modinfos, 1091 int *modinfos_len) 1092 { 1093 assert(sh); 1094 assert(modinfos); 1095 assert(modinfos_len); 1096 1097 if (sh->funcs->list_all == NULL) { 1098 ERR(sh, 1099 "No list all function defined for this connection type."); 1100 return -1; 1101 } else if (!sh->is_connected) { 1102 ERR(sh, "Not connected."); 1103 return -1; 1104 } 1105 1106 return sh->funcs->list_all(sh, modinfos, modinfos_len); 1107 } 1108 1109 int semanage_module_install_info(semanage_handle_t *sh, 1110 const semanage_module_info_t *modinfo, 1111 char *data, 1112 size_t data_len) 1113 { 1114 if (sh->funcs->install_info == NULL) { 1115 ERR(sh, 1116 "No install info function defined for this connection type."); 1117 return -1; 1118 } else if (!sh->is_connected) { 1119 ERR(sh, "Not connected."); 1120 return -1; 1121 } else if (!sh->is_in_transaction) { 1122 if (semanage_begin_transaction(sh) < 0) { 1123 return -1; 1124 } 1125 } 1126 sh->modules_modified = 1; 1127 return sh->funcs->install_info(sh, modinfo, data, data_len); 1128 } 1129 1130 int semanage_module_remove_key(semanage_handle_t *sh, 1131 const semanage_module_key_t *modkey) 1132 { 1133 if (sh->funcs->remove_key== NULL) { 1134 ERR(sh, 1135 "No remove key function defined for this connection type."); 1136 return -1; 1137 } else if (!sh->is_connected) { 1138 ERR(sh, "Not connected."); 1139 return -1; 1140 } else if (!sh->is_in_transaction) { 1141 if (semanage_begin_transaction(sh) < 0) { 1142 return -1; 1143 } 1144 } 1145 sh->modules_modified = 1; 1146 return sh->funcs->remove_key(sh, modkey); 1147 } 1148 1149