Home | History | Annotate | Download | only in src
      1 /* Author: Joshua Brindle <jbrindle (at) tresys.co
      2  *	   Jason Tang	  <jtang (at) tresys.com>
      3  *
      4  * Copyright (C) 2004-2005 Tresys Technology, LLC
      5  * Copyright (C) 2005 Red Hat, Inc.
      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 handle functions to libsemanage. */
     23 
     24 #include <selinux/selinux.h>
     25 
     26 #include <ctype.h>
     27 #include <stdarg.h>
     28 #include <assert.h>
     29 #include <stdlib.h>
     30 #include <stdio.h>
     31 #include <string.h>
     32 #include <sys/time.h>
     33 
     34 #include "direct_api.h"
     35 #include "handle.h"
     36 #include "debug.h"
     37 #include "semanage_conf.h"
     38 #include "semanage_store.h"
     39 
     40 #define SEMANAGE_COMMIT_READ_WAIT 5
     41 
     42 static char *private_semanage_root = NULL;
     43 
     44 int semanage_set_root(const char *root)
     45 {
     46 	free(private_semanage_root);
     47 	private_semanage_root = strdup(root);
     48 	return 0;
     49 }
     50 
     51 hidden_def(semanage_set_root);
     52 
     53 const char * semanage_root(void)
     54 {
     55 	if (private_semanage_root == NULL) {
     56 		return "";
     57 	}
     58 	return private_semanage_root;
     59 }
     60 
     61 semanage_handle_t *semanage_handle_create(void)
     62 {
     63 	semanage_handle_t *sh = NULL;
     64 	char *conf_name = NULL;
     65 
     66 	/* Allocate handle */
     67 	if ((sh = calloc(1, sizeof(semanage_handle_t))) == NULL)
     68 		goto err;
     69 
     70 	if ((conf_name = semanage_conf_path()) == NULL)
     71 		goto err;
     72 
     73 	if ((sh->conf = semanage_conf_parse(conf_name)) == NULL)
     74 		goto err;
     75 
     76 	/* Link to sepol handle */
     77 	sh->sepolh = sepol_handle_create();
     78 	if (!sh->sepolh)
     79 		goto err;
     80 	sepol_msg_set_callback(sh->sepolh, semanage_msg_relay_handler, sh);
     81 
     82 	/* Default priority is 400 */
     83 	sh->priority = 400;
     84 
     85 	/* By default do not rebuild the policy on commit
     86 	 * If any changes are made, this flag is ignored */
     87 	sh->do_rebuild = 0;
     88 
     89 	/* By default always reload policy after commit if SELinux is enabled. */
     90 	sh->do_reload = (is_selinux_enabled() > 0);
     91 
     92 	/* By default always check the file contexts file. */
     93 	sh->do_check_contexts = 1;
     94 
     95 	/* By default do not create store */
     96 	sh->create_store = 0;
     97 
     98 	/* Set timeout: some default value for now, later use config */
     99 	sh->timeout = SEMANAGE_COMMIT_READ_WAIT;
    100 
    101 	/* Set callback */
    102 	sh->msg_callback = semanage_msg_default_handler;
    103 	sh->msg_callback_arg = NULL;
    104 
    105 	free(conf_name);
    106 
    107 	return sh;
    108 
    109       err:
    110 	free(conf_name);
    111 	semanage_handle_destroy(sh);
    112 	return NULL;
    113 }
    114 
    115 void semanage_set_rebuild(semanage_handle_t * sh, int do_rebuild)
    116 {
    117 
    118 	assert(sh != NULL);
    119 
    120 	sh->do_rebuild = do_rebuild;
    121 	return;
    122 }
    123 
    124 void semanage_set_reload(semanage_handle_t * sh, int do_reload)
    125 {
    126 
    127 	assert(sh != NULL);
    128 
    129 	sh->do_reload = do_reload;
    130 	return;
    131 }
    132 
    133 int semanage_get_hll_compiler_path(semanage_handle_t *sh,
    134 				char *lang_ext,
    135 				char **compiler_path)
    136 {
    137 	assert(sh != NULL);
    138 	assert(lang_ext != NULL);
    139 
    140 	int i;
    141 	int status = 0;
    142 	int num_printed = 0;
    143 	size_t len;
    144 	char *compiler = NULL;
    145 	char *lower_lang_ext = NULL;
    146 
    147 	lower_lang_ext = strdup(lang_ext);
    148 	if (lower_lang_ext == NULL) {
    149 		ERR(sh, "Could not create copy of lang_ext. Out of memory.\n");
    150 		status = -1;
    151 		goto cleanup;
    152 	}
    153 	/* Set lang_ext to lowercase in case a file with a mixed case extension was passed to libsemanage */
    154 	for (i = 0; lower_lang_ext[i] != '\0'; i++) {
    155 		lower_lang_ext[i] = tolower(lower_lang_ext[i]);
    156 	}
    157 
    158 	len = strlen(sh->conf->compiler_directory_path) + strlen("/") + strlen(lower_lang_ext) + 1;
    159 
    160 	compiler = malloc(len * sizeof(*compiler));
    161 	if (compiler == NULL) {
    162 		ERR(sh, "Error allocating space for compiler path.");
    163 		status = -1;
    164 		goto cleanup;
    165 	}
    166 
    167 	num_printed = snprintf(compiler, len, "%s/%s", sh->conf->compiler_directory_path, lower_lang_ext);
    168 	if (num_printed < 0 || (int)num_printed >= (int)len) {
    169 		ERR(sh, "Error creating compiler path.");
    170 		status = -1;
    171 		goto cleanup;
    172 	}
    173 
    174 	*compiler_path = compiler;
    175 	status = 0;
    176 
    177 cleanup:
    178 	free(lower_lang_ext);
    179 	if (status != 0) {
    180 		free(compiler);
    181 	}
    182 
    183 	return status;
    184 }
    185 
    186 void semanage_set_create_store(semanage_handle_t * sh, int create_store)
    187 {
    188 
    189 	assert(sh != NULL);
    190 
    191 	sh->create_store = create_store;
    192 	return;
    193 }
    194 
    195 int semanage_get_disable_dontaudit(semanage_handle_t * sh)
    196 {
    197 	assert(sh != NULL);
    198 
    199 	return sepol_get_disable_dontaudit(sh->sepolh);
    200 }
    201 
    202 void semanage_set_disable_dontaudit(semanage_handle_t * sh, int disable_dontaudit)
    203 {
    204 	assert(sh != NULL);
    205 
    206 	sepol_set_disable_dontaudit(sh->sepolh, disable_dontaudit);
    207 	return;
    208 }
    209 
    210 int semanage_get_preserve_tunables(semanage_handle_t * sh)
    211 {
    212 	assert(sh != NULL);
    213 	return sepol_get_preserve_tunables(sh->sepolh);
    214 }
    215 
    216 void semanage_set_preserve_tunables(semanage_handle_t * sh,
    217 				    int preserve_tunables)
    218 {
    219 	assert(sh != NULL);
    220 	sepol_set_preserve_tunables(sh->sepolh, preserve_tunables);
    221 }
    222 
    223 int semanage_get_ignore_module_cache(semanage_handle_t *sh)
    224 {
    225 	assert(sh != NULL);
    226 	return sh->conf->ignore_module_cache;
    227 }
    228 
    229 void semanage_set_ignore_module_cache(semanage_handle_t *sh,
    230 				    int ignore_module_cache)
    231 {
    232 	assert(sh != NULL);
    233 	sh->conf->ignore_module_cache = ignore_module_cache;
    234 }
    235 
    236 void semanage_set_check_contexts(semanage_handle_t * sh, int do_check_contexts)
    237 {
    238 
    239 	assert(sh != NULL);
    240 
    241 	sh->do_check_contexts = do_check_contexts;
    242 	return;
    243 }
    244 
    245 uint16_t semanage_get_default_priority(semanage_handle_t *sh)
    246 {
    247 	assert(sh != NULL);
    248 	return sh->priority;
    249 }
    250 
    251 int semanage_set_default_priority(semanage_handle_t *sh, uint16_t priority)
    252 {
    253 	assert(sh != NULL);
    254 
    255 	/* Verify priority */
    256 	if (semanage_module_validate_priority(priority) < 0) {
    257 		ERR(sh, "Priority %d is invalid.", priority);
    258 		return -1;
    259 	}
    260 
    261 	sh->priority = priority;
    262 	return 0;
    263 }
    264 
    265 int semanage_is_connected(semanage_handle_t * sh)
    266 {
    267 	assert(sh != NULL);
    268 	return sh->is_connected;
    269 }
    270 
    271 void semanage_select_store(semanage_handle_t * sh, char *storename,
    272 			   enum semanage_connect_type storetype)
    273 {
    274 
    275 	assert(sh != NULL);
    276 
    277 	/* This just sets the storename to what the user requests, no
    278 	   verification of existance will be done until connect */
    279 	free(sh->conf->store_path);
    280 	sh->conf->store_path = strdup(storename);
    281 	assert(sh->conf->store_path); /* no way to return failure */
    282 	sh->conf->store_type = storetype;
    283 
    284 	return;
    285 }
    286 
    287 void semanage_set_store_root(semanage_handle_t *sh, const char *store_root)
    288 {
    289 	assert(sh != NULL);
    290 
    291 	free(sh->conf->store_root_path);
    292 	sh->conf->store_root_path = strdup(store_root);
    293 	assert(sh->conf->store_root_path); /* no way to return failure */
    294 
    295 	return;
    296 }
    297 
    298 int semanage_is_managed(semanage_handle_t * sh)
    299 {
    300 	assert(sh != NULL);
    301 	if (sh->is_connected) {
    302 		ERR(sh, "Already connected.");
    303 		return -1;
    304 	}
    305 	switch (sh->conf->store_type) {
    306 	case SEMANAGE_CON_DIRECT:
    307 		return semanage_direct_is_managed(sh);
    308 	default:
    309 		ERR(sh,
    310 		    "The connection type specified within your semanage.conf file has not been implemented yet.");
    311 		/* fall through */
    312 	}
    313 	return -1;
    314 }
    315 
    316 int semanage_mls_enabled(semanage_handle_t * sh)
    317 {
    318 	assert(sh != NULL);
    319 	switch (sh->conf->store_type) {
    320 	case SEMANAGE_CON_DIRECT:
    321 		return semanage_direct_mls_enabled(sh);
    322 	default:
    323 		ERR(sh,
    324 		    "The connection type specified within your semanage.conf file has not been implemented yet.");
    325 		/* fall through */
    326 	}
    327 	return -1;
    328 }
    329 
    330 int semanage_connect(semanage_handle_t * sh)
    331 {
    332 	assert(sh != NULL);
    333 	switch (sh->conf->store_type) {
    334 	case SEMANAGE_CON_DIRECT:{
    335 			if (semanage_direct_connect(sh) < 0) {
    336 				return -1;
    337 			}
    338 			break;
    339 		}
    340 	default:{
    341 			ERR(sh,
    342 			    "The connection type specified within your semanage.conf file has not been implemented yet.");
    343 			return -1;
    344 		}
    345 	}
    346 	sh->is_connected = 1;
    347 	return 0;
    348 }
    349 
    350 int semanage_access_check(semanage_handle_t * sh)
    351 {
    352 	assert(sh != NULL);
    353 	switch (sh->conf->store_type) {
    354 	case SEMANAGE_CON_DIRECT:
    355 		return semanage_direct_access_check(sh);
    356 	default:
    357 		return -1;
    358 	}
    359 
    360 	return -1;		/* unreachable */
    361 }
    362 
    363 hidden_def(semanage_access_check)
    364 
    365 int semanage_disconnect(semanage_handle_t * sh)
    366 {
    367 	assert(sh != NULL && sh->funcs != NULL
    368 	       && sh->funcs->disconnect != NULL);
    369 	if (!sh->is_connected) {
    370 		return 0;
    371 	}
    372 	if (sh->funcs->disconnect(sh) < 0) {
    373 		return -1;
    374 	}
    375 	sh->is_in_transaction = 0;
    376 	sh->is_connected = 0;
    377 	sh->modules_modified = 0;
    378 	return 0;
    379 }
    380 
    381 void semanage_handle_destroy(semanage_handle_t * sh)
    382 {
    383 	if (sh == NULL)
    384 		return;
    385 
    386 	if (sh->funcs != NULL && sh->funcs->destroy != NULL)
    387 		sh->funcs->destroy(sh);
    388 	semanage_conf_destroy(sh->conf);
    389 	sepol_handle_destroy(sh->sepolh);
    390 	free(sh);
    391 }
    392 
    393 hidden_def(semanage_handle_destroy)
    394 
    395 /********************* public transaction functions *********************/
    396 int semanage_begin_transaction(semanage_handle_t * sh)
    397 {
    398 	assert(sh != NULL && sh->funcs != NULL
    399 	       && sh->funcs->begin_trans != NULL);
    400 	if (!sh->is_connected) {
    401 		ERR(sh, "Not connected.");
    402 		return -1;
    403 	}
    404 	if (sh->is_in_transaction) {
    405 		return 0;
    406 	}
    407 
    408 	if (sh->funcs->begin_trans(sh) < 0) {
    409 		return -1;
    410 	}
    411 	sh->is_in_transaction = 1;
    412 	return 0;
    413 }
    414 
    415 hidden_def(semanage_begin_transaction)
    416 
    417 int semanage_commit(semanage_handle_t * sh)
    418 {
    419 	int retval;
    420 	assert(sh != NULL && sh->funcs != NULL && sh->funcs->commit != NULL);
    421 	if (!sh->is_in_transaction) {
    422 		ERR(sh,
    423 		    "Will not commit because caller does not have a transaction lock yet.");
    424 		return -1;
    425 	}
    426 	retval = sh->funcs->commit(sh);
    427 	sh->is_in_transaction = 0;
    428 	sh->modules_modified = 0;
    429 	return retval;
    430 }
    431