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