xref: /aosp_15_r20/external/selinux/libsemanage/src/handle.c (revision 2d543d20722ada2425b5bdab9d0d1d29470e7bba)
1 /* Author: Joshua Brindle <[email protected]
2  *	   Jason Tang	  <[email protected]>
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 
semanage_root(void)52 const char * semanage_root(void)
53 {
54 	if (private_semanage_root == NULL) {
55 		return "";
56 	}
57 	return private_semanage_root;
58 }
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 	sh->commit_err = 0;
90 
91 	/* By default always reload policy after commit if SELinux is enabled. */
92 	sh->do_reload = (is_selinux_enabled() > 0);
93 
94 	/* By default always check the file contexts file. */
95 	sh->do_check_contexts = 1;
96 
97 	/* By default do not create store */
98 	sh->create_store = 0;
99 
100 	/* Set timeout: some default value for now, later use config */
101 	sh->timeout = SEMANAGE_COMMIT_READ_WAIT;
102 
103 	/* Set callback */
104 	sh->msg_callback = semanage_msg_default_handler;
105 	sh->msg_callback_arg = NULL;
106 
107 	free(conf_name);
108 
109 	return sh;
110 
111       err:
112 	free(conf_name);
113 	semanage_handle_destroy(sh);
114 	return NULL;
115 }
116 
semanage_set_rebuild(semanage_handle_t * sh,int do_rebuild)117 void semanage_set_rebuild(semanage_handle_t * sh, int do_rebuild)
118 {
119 	assert(sh != NULL);
120 
121 	sh->do_rebuild = do_rebuild;
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 	assert(sh != NULL);
127 
128 	sh->do_reload = do_reload;
129 }
130 
semanage_set_check_ext_changes(semanage_handle_t * sh,int do_check)131 void semanage_set_check_ext_changes(semanage_handle_t * sh, int do_check)
132 {
133 	assert(sh != NULL);
134 
135 	sh->check_ext_changes = do_check;
136 }
137 
semanage_get_hll_compiler_path(semanage_handle_t * sh,char * lang_ext,char ** compiler_path)138 int semanage_get_hll_compiler_path(semanage_handle_t *sh,
139 				char *lang_ext,
140 				char **compiler_path)
141 {
142 	assert(sh != NULL);
143 	assert(lang_ext != NULL);
144 
145 	int i;
146 	int status = 0;
147 	int num_printed = 0;
148 	size_t len;
149 	char *compiler = NULL;
150 	char *lower_lang_ext = NULL;
151 
152 	lower_lang_ext = strdup(lang_ext);
153 	if (lower_lang_ext == NULL) {
154 		ERR(sh, "Could not create copy of lang_ext. Out of memory.\n");
155 		status = -1;
156 		goto cleanup;
157 	}
158 	/* Set lang_ext to lowercase in case a file with a mixed case extension was passed to libsemanage */
159 	for (i = 0; lower_lang_ext[i] != '\0'; i++) {
160 		lower_lang_ext[i] = tolower(lower_lang_ext[i]);
161 	}
162 
163 	len = strlen(sh->conf->compiler_directory_path) + strlen("/") + strlen(lower_lang_ext) + 1;
164 
165 	compiler = malloc(len * sizeof(*compiler));
166 	if (compiler == NULL) {
167 		ERR(sh, "Error allocating space for compiler path.");
168 		status = -1;
169 		goto cleanup;
170 	}
171 
172 	num_printed = snprintf(compiler, len, "%s/%s", sh->conf->compiler_directory_path, lower_lang_ext);
173 	if (num_printed < 0 || (int)num_printed >= (int)len) {
174 		ERR(sh, "Error creating compiler path.");
175 		status = -1;
176 		goto cleanup;
177 	}
178 
179 	*compiler_path = compiler;
180 	status = 0;
181 
182 cleanup:
183 	free(lower_lang_ext);
184 	if (status != 0) {
185 		free(compiler);
186 	}
187 
188 	return status;
189 }
190 
semanage_set_create_store(semanage_handle_t * sh,int create_store)191 void semanage_set_create_store(semanage_handle_t * sh, int create_store)
192 {
193 
194 	assert(sh != NULL);
195 
196 	sh->create_store = create_store;
197 	return;
198 }
199 
semanage_get_disable_dontaudit(semanage_handle_t * sh)200 int semanage_get_disable_dontaudit(semanage_handle_t * sh)
201 {
202 	assert(sh != NULL);
203 
204 	return sepol_get_disable_dontaudit(sh->sepolh);
205 }
206 
semanage_set_disable_dontaudit(semanage_handle_t * sh,int disable_dontaudit)207 void semanage_set_disable_dontaudit(semanage_handle_t * sh, int disable_dontaudit)
208 {
209 	assert(sh != NULL);
210 
211 	sepol_set_disable_dontaudit(sh->sepolh, disable_dontaudit);
212 	return;
213 }
214 
semanage_get_preserve_tunables(semanage_handle_t * sh)215 int semanage_get_preserve_tunables(semanage_handle_t * sh)
216 {
217 	assert(sh != NULL);
218 	return sepol_get_preserve_tunables(sh->sepolh);
219 }
220 
semanage_set_preserve_tunables(semanage_handle_t * sh,int preserve_tunables)221 void semanage_set_preserve_tunables(semanage_handle_t * sh,
222 				    int preserve_tunables)
223 {
224 	assert(sh != NULL);
225 	sepol_set_preserve_tunables(sh->sepolh, preserve_tunables);
226 }
227 
semanage_get_ignore_module_cache(semanage_handle_t * sh)228 int semanage_get_ignore_module_cache(semanage_handle_t *sh)
229 {
230 	assert(sh != NULL);
231 	return sh->conf->ignore_module_cache;
232 }
233 
semanage_set_ignore_module_cache(semanage_handle_t * sh,int ignore_module_cache)234 void semanage_set_ignore_module_cache(semanage_handle_t *sh,
235 				    int ignore_module_cache)
236 {
237 	assert(sh != NULL);
238 	sh->conf->ignore_module_cache = ignore_module_cache;
239 }
240 
semanage_set_check_contexts(semanage_handle_t * sh,int do_check_contexts)241 void semanage_set_check_contexts(semanage_handle_t * sh, int do_check_contexts)
242 {
243 
244 	assert(sh != NULL);
245 
246 	sh->do_check_contexts = do_check_contexts;
247 	return;
248 }
249 
semanage_get_default_priority(semanage_handle_t * sh)250 uint16_t semanage_get_default_priority(semanage_handle_t *sh)
251 {
252 	assert(sh != NULL);
253 	return sh->priority;
254 }
255 
semanage_set_default_priority(semanage_handle_t * sh,uint16_t priority)256 int semanage_set_default_priority(semanage_handle_t *sh, uint16_t priority)
257 {
258 	assert(sh != NULL);
259 
260 	/* Verify priority */
261 	if (semanage_module_validate_priority(priority) < 0) {
262 		ERR(sh, "Priority %d is invalid.", priority);
263 		return -1;
264 	}
265 
266 	sh->priority = priority;
267 	return 0;
268 }
269 
semanage_is_connected(semanage_handle_t * sh)270 int semanage_is_connected(semanage_handle_t * sh)
271 {
272 	assert(sh != NULL);
273 	return sh->is_connected;
274 }
275 
semanage_select_store(semanage_handle_t * sh,char * storename,enum semanage_connect_type storetype)276 void semanage_select_store(semanage_handle_t * sh, char *storename,
277 			   enum semanage_connect_type storetype)
278 {
279 
280 	assert(sh != NULL);
281 
282 	/* This just sets the storename to what the user requests, no
283 	   verification of existence will be done until connect */
284 	free(sh->conf->store_path);
285 	sh->conf->store_path = strdup(storename);
286 	assert(sh->conf->store_path); /* no way to return failure */
287 	sh->conf->store_type = storetype;
288 
289 	return;
290 }
291 
semanage_set_store_root(semanage_handle_t * sh,const char * store_root)292 void semanage_set_store_root(semanage_handle_t *sh, const char *store_root)
293 {
294 	assert(sh != NULL);
295 
296 	free(sh->conf->store_root_path);
297 	sh->conf->store_root_path = strdup(store_root);
298 	assert(sh->conf->store_root_path); /* no way to return failure */
299 
300 	return;
301 }
302 
semanage_is_managed(semanage_handle_t * sh)303 int semanage_is_managed(semanage_handle_t * sh)
304 {
305 	assert(sh != NULL);
306 	if (sh->is_connected) {
307 		ERR(sh, "Already connected.");
308 		return -1;
309 	}
310 	switch (sh->conf->store_type) {
311 	case SEMANAGE_CON_DIRECT:
312 		return semanage_direct_is_managed(sh);
313 	default:
314 		ERR(sh,
315 		    "The connection type specified within your semanage.conf file has not been implemented yet.");
316 		/* fall through */
317 	}
318 	return -1;
319 }
320 
semanage_mls_enabled(semanage_handle_t * sh)321 int semanage_mls_enabled(semanage_handle_t * sh)
322 {
323 	assert(sh != NULL);
324 	switch (sh->conf->store_type) {
325 	case SEMANAGE_CON_DIRECT:
326 		return semanage_direct_mls_enabled(sh);
327 	default:
328 		ERR(sh,
329 		    "The connection type specified within your semanage.conf file has not been implemented yet.");
330 		/* fall through */
331 	}
332 	return -1;
333 }
334 
semanage_connect(semanage_handle_t * sh)335 int semanage_connect(semanage_handle_t * sh)
336 {
337 	assert(sh != NULL);
338 	switch (sh->conf->store_type) {
339 	case SEMANAGE_CON_DIRECT:{
340 			if (semanage_direct_connect(sh) < 0) {
341 				return -1;
342 			}
343 			break;
344 		}
345 	default:{
346 			ERR(sh,
347 			    "The connection type specified within your semanage.conf file has not been implemented yet.");
348 			return -1;
349 		}
350 	}
351 	sh->is_connected = 1;
352 	return 0;
353 }
354 
semanage_access_check(semanage_handle_t * sh)355 int semanage_access_check(semanage_handle_t * sh)
356 {
357 	assert(sh != NULL);
358 	switch (sh->conf->store_type) {
359 	case SEMANAGE_CON_DIRECT:
360 		return semanage_direct_access_check(sh);
361 	default:
362 		return -1;
363 	}
364 
365 	return -1;		/* unreachable */
366 }
367 
368 
semanage_disconnect(semanage_handle_t * sh)369 int semanage_disconnect(semanage_handle_t * sh)
370 {
371 	assert(sh != NULL && sh->funcs != NULL
372 	       && sh->funcs->disconnect != NULL);
373 	if (!sh->is_connected) {
374 		return 0;
375 	}
376 	if (sh->funcs->disconnect(sh) < 0) {
377 		return -1;
378 	}
379 	sh->is_in_transaction = 0;
380 	sh->is_connected = 0;
381 	sh->modules_modified = 0;
382 	return 0;
383 }
384 
semanage_handle_destroy(semanage_handle_t * sh)385 void semanage_handle_destroy(semanage_handle_t * sh)
386 {
387 	if (sh == NULL)
388 		return;
389 
390 	if (sh->funcs != NULL && sh->funcs->destroy != NULL)
391 		sh->funcs->destroy(sh);
392 	semanage_conf_destroy(sh->conf);
393 	sepol_handle_destroy(sh->sepolh);
394 	free(sh);
395 }
396 
397 
398 /********************* public transaction functions *********************/
semanage_begin_transaction(semanage_handle_t * sh)399 int semanage_begin_transaction(semanage_handle_t * sh)
400 {
401 	assert(sh != NULL && sh->funcs != NULL
402 	       && sh->funcs->begin_trans != NULL);
403 	if (!sh->is_connected) {
404 		ERR(sh, "Not connected.");
405 		return -1;
406 	}
407 	if (sh->is_in_transaction) {
408 		return 0;
409 	}
410 
411 	if (sh->funcs->begin_trans(sh) < 0) {
412 		return -1;
413 	}
414 	sh->is_in_transaction = 1;
415 	return 0;
416 }
417 
418 
semanage_commit(semanage_handle_t * sh)419 int semanage_commit(semanage_handle_t * sh)
420 {
421 	int retval;
422 	assert(sh != NULL && sh->funcs != NULL && sh->funcs->commit != NULL);
423 	if (!sh->is_in_transaction) {
424 		ERR(sh,
425 		    "Will not commit because caller does not have a transaction lock yet.");
426 		return -1;
427 	}
428 	retval = sh->funcs->commit(sh);
429 	sh->is_in_transaction = 0;
430 	sh->modules_modified = 0;
431 	return retval;
432 }
433