Home | History | Annotate | Download | only in src
      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