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