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