1 /* Author: Joshua Brindle <jbrindle@tresys.co
2  *	   Jason Tang	  <jtang@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 
semanage_set_root(const char * root)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 
semanage_root(void)53 const char * semanage_root(void)
54 {
55 	if (private_semanage_root == NULL) {
56 		return "";
57 	}
58 	return private_semanage_root;
59 }
60 
semanage_handle_create(void)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 
semanage_set_rebuild(semanage_handle_t * sh,int do_rebuild)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 
semanage_set_reload(semanage_handle_t * sh,int do_reload)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 
semanage_get_hll_compiler_path(semanage_handle_t * sh,char * lang_ext,char ** compiler_path)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 
semanage_set_create_store(semanage_handle_t * sh,int create_store)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 
semanage_get_disable_dontaudit(semanage_handle_t * sh)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 
semanage_set_disable_dontaudit(semanage_handle_t * sh,int disable_dontaudit)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 
semanage_get_preserve_tunables(semanage_handle_t * sh)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 
semanage_set_preserve_tunables(semanage_handle_t * sh,int preserve_tunables)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 
semanage_get_ignore_module_cache(semanage_handle_t * sh)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 
semanage_set_ignore_module_cache(semanage_handle_t * sh,int ignore_module_cache)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 
semanage_set_check_contexts(semanage_handle_t * sh,int do_check_contexts)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 
semanage_get_default_priority(semanage_handle_t * sh)245 uint16_t semanage_get_default_priority(semanage_handle_t *sh)
246 {
247 	assert(sh != NULL);
248 	return sh->priority;
249 }
250 
semanage_set_default_priority(semanage_handle_t * sh,uint16_t priority)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 
semanage_is_connected(semanage_handle_t * sh)265 int semanage_is_connected(semanage_handle_t * sh)
266 {
267 	assert(sh != NULL);
268 	return sh->is_connected;
269 }
270 
semanage_select_store(semanage_handle_t * sh,char * storename,enum semanage_connect_type storetype)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 
semanage_set_store_root(semanage_handle_t * sh,const char * store_root)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 
semanage_is_managed(semanage_handle_t * sh)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 
semanage_mls_enabled(semanage_handle_t * sh)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 
semanage_connect(semanage_handle_t * sh)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 
semanage_access_check(semanage_handle_t * sh)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 
hidden_def(semanage_access_check)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 
semanage_handle_destroy(semanage_handle_t * sh)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 
hidden_def(semanage_handle_destroy)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 
hidden_def(semanage_begin_transaction)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