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