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