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