1 /* Author: Joshua Brindle <jbrindle@tresys.co
2 * Jason Tang <jtang@tresys.com>
3 * Caleb Case <ccase@tresys.com>
4 *
5 * Copyright (C) 2004-2005,2009 Tresys Technology, LLC
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 module functions to libsemanage. */
23
24 #include "direct_api.h"
25 #include "semanage_conf.h"
26 #include "semanage_store.h"
27
28 #include <stdarg.h>
29 #include <assert.h>
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33 #include <limits.h>
34 #include <fcntl.h>
35 #include <sys/types.h>
36 #include <sys/stat.h>
37 #include <errno.h>
38 #include <ctype.h>
39
40 #include "handle.h"
41 #include "modules.h"
42 #include "debug.h"
43
44 asm(".symver semanage_module_get_enabled_1_1,semanage_module_get_enabled@@LIBSEMANAGE_1.1");
45 asm(".symver semanage_module_get_enabled_1_0,semanage_module_get_enabled@LIBSEMANAGE_1.0");
46 asm(".symver semanage_module_install_pp,semanage_module_install@LIBSEMANAGE_1.0");
47 asm(".symver semanage_module_install_hll,semanage_module_install@@LIBSEMANAGE_1.1");
48
49 /* Takes a module stored in 'module_data' and parses its headers.
50 * Sets reference variables 'module_name' to module's name and
51 * 'version' to module's version. The caller is responsible for
52 * free()ing 'module_name' and 'version'; they will be
53 * set to NULL upon entering this function. Returns 0 on success, -1
54 * if out of memory, or -2 if data did not represent a module.
55 */
parse_module_headers(semanage_handle_t * sh,char * module_data,size_t data_len,char ** module_name,char ** version)56 static int parse_module_headers(semanage_handle_t * sh, char *module_data,
57 size_t data_len, char **module_name, char **version)
58 {
59 struct sepol_policy_file *pf;
60 int file_type;
61 *version = NULL;
62
63 if (sepol_policy_file_create(&pf)) {
64 ERR(sh, "Out of memory!");
65 return -1;
66 }
67 sepol_policy_file_set_mem(pf, module_data, data_len);
68 sepol_policy_file_set_handle(pf, sh->sepolh);
69 if (module_data == NULL ||
70 data_len == 0 ||
71 sepol_module_package_info(pf, &file_type, module_name, version) == -1) {
72 sepol_policy_file_free(pf);
73 ERR(sh, "Could not parse module data.");
74 return -2;
75 }
76 sepol_policy_file_free(pf);
77 if (file_type != SEPOL_POLICY_MOD) {
78 ERR(sh, "Data did not represent a pp module. Please upgrade to the latest version of libsemanage to support hll modules.");
79 return -2;
80 }
81
82 return 0;
83 }
84
85 /* This function is used to preserve ABI compatibility with
86 * versions of semodule using LIBSEMANAGE_1.0
87 */
semanage_module_install_pp(semanage_handle_t * sh,char * module_data,size_t data_len)88 int semanage_module_install_pp(semanage_handle_t * sh,
89 char *module_data, size_t data_len)
90 {
91 char *name = NULL;
92 char *version = NULL;
93 int status;
94
95 if ((status = parse_module_headers(sh, module_data, data_len, &name, &version)) != 0) {
96 goto cleanup;
97 }
98
99 status = semanage_module_install_hll(sh, module_data, data_len, name, "pp");
100
101 cleanup:
102 free(name);
103 free(version);
104 return status;
105 }
106
semanage_module_install_hll(semanage_handle_t * sh,char * module_data,size_t data_len,const char * name,const char * ext_lang)107 int semanage_module_install_hll(semanage_handle_t * sh,
108 char *module_data, size_t data_len, const char *name, const char *ext_lang)
109 {
110 if (sh->funcs->install == NULL) {
111 ERR(sh,
112 "No install function defined for this connection type.");
113 return -1;
114 } else if (!sh->is_connected) {
115 ERR(sh, "Not connected.");
116 return -1;
117 } else if (!sh->is_in_transaction) {
118 if (semanage_begin_transaction(sh) < 0) {
119 return -1;
120 }
121 }
122 sh->modules_modified = 1;
123 return sh->funcs->install(sh, module_data, data_len, name, ext_lang);
124 }
125
semanage_module_install_file(semanage_handle_t * sh,const char * module_name)126 int semanage_module_install_file(semanage_handle_t * sh,
127 const char *module_name) {
128
129 if (sh->funcs->install_file == NULL) {
130 ERR(sh,
131 "No install function defined for this connection type.");
132 return -1;
133 } else if (!sh->is_connected) {
134 ERR(sh, "Not connected.");
135 return -1;
136 } else if (!sh->is_in_transaction) {
137 if (semanage_begin_transaction(sh) < 0) {
138 return -1;
139 }
140 }
141 sh->modules_modified = 1;
142 return sh->funcs->install_file(sh, module_name);
143 }
144
145 /* Legacy function that remains to preserve ABI
146 * compatibility. Please use semanage_module_install instead.
147 */
semanage_module_upgrade(semanage_handle_t * sh,char * module_data,size_t data_len)148 int semanage_module_upgrade(semanage_handle_t * sh,
149 char *module_data, size_t data_len)
150 {
151 return semanage_module_install_pp(sh, module_data, data_len);
152
153 }
154
155 /* Legacy function that remains to preserve ABI
156 * compatibility. Please use semanage_module_install_file instead.
157 */
semanage_module_upgrade_file(semanage_handle_t * sh,const char * module_name)158 int semanage_module_upgrade_file(semanage_handle_t * sh,
159 const char *module_name)
160 {
161 return semanage_module_install_file(sh, module_name);
162 }
163
164 /* Legacy function that remains to preserve ABI
165 * compatibility. Please use semanage_module_install instead.
166 */
semanage_module_install_base(semanage_handle_t * sh,char * module_data,size_t data_len)167 int semanage_module_install_base(semanage_handle_t * sh,
168 char *module_data, size_t data_len)
169 {
170 return semanage_module_install_pp(sh, module_data, data_len);
171 }
172
173 /* Legacy function that remains to preserve ABI
174 * compatibility. Please use semanage_module_install_file instead.
175 */
semanage_module_install_base_file(semanage_handle_t * sh,const char * module_name)176 int semanage_module_install_base_file(semanage_handle_t * sh,
177 const char *module_name)
178 {
179 return semanage_module_install_file(sh, module_name);
180 }
181
semanage_module_remove(semanage_handle_t * sh,char * module_name)182 int semanage_module_remove(semanage_handle_t * sh, char *module_name)
183 {
184 if (sh->funcs->remove == NULL) {
185 ERR(sh, "No remove function defined for this connection type.");
186 return -1;
187 } else if (!sh->is_connected) {
188 ERR(sh, "Not connected.");
189 return -1;
190 } else if (!sh->is_in_transaction) {
191 if (semanage_begin_transaction(sh) < 0) {
192 return -1;
193 }
194 }
195 sh->modules_modified = 1;
196 return sh->funcs->remove(sh, module_name);
197 }
198
semanage_module_list(semanage_handle_t * sh,semanage_module_info_t ** modinfo,int * num_modules)199 int semanage_module_list(semanage_handle_t * sh,
200 semanage_module_info_t ** modinfo, int *num_modules)
201 {
202 if (sh->funcs->list == NULL) {
203 ERR(sh, "No list function defined for this connection type.");
204 return -1;
205 } else if (!sh->is_connected) {
206 ERR(sh, "Not connected.");
207 return -1;
208 }
209 return sh->funcs->list(sh, modinfo, num_modules);
210 }
211
semanage_module_info_datum_destroy(semanage_module_info_t * modinfo)212 void semanage_module_info_datum_destroy(semanage_module_info_t * modinfo)
213 {
214 if (modinfo != NULL) {
215 modinfo->priority = 0;
216
217 free(modinfo->name);
218 modinfo->name = NULL;
219
220 free(modinfo->lang_ext);
221 modinfo->lang_ext = NULL;
222
223 modinfo->enabled = -1;
224 }
225 }
226
hidden_def(semanage_module_info_datum_destroy)227 hidden_def(semanage_module_info_datum_destroy)
228
229 semanage_module_info_t *semanage_module_list_nth(semanage_module_info_t * list,
230 int n)
231 {
232 return list + n;
233 }
234
hidden_def(semanage_module_list_nth)235 hidden_def(semanage_module_list_nth)
236
237 const char *semanage_module_get_name(semanage_module_info_t * modinfo)
238 {
239 return modinfo->name;
240 }
241
hidden_def(semanage_module_get_name)242 hidden_def(semanage_module_get_name)
243
244 /* Legacy function that remains to preserve ABI
245 * compatibility.
246 */
247 const char *semanage_module_get_version(semanage_module_info_t * modinfo
248 __attribute__ ((unused)))
249 {
250 return "";
251 }
252
semanage_module_info_create(semanage_handle_t * sh,semanage_module_info_t ** modinfo)253 int semanage_module_info_create(semanage_handle_t *sh,
254 semanage_module_info_t **modinfo)
255 {
256 assert(sh);
257 assert(modinfo);
258
259 *modinfo = malloc(sizeof(semanage_module_info_t));
260 if (*modinfo == NULL) return -1;
261
262 return semanage_module_info_init(sh, *modinfo);
263 }
264
hidden_def(semanage_module_info_create)265 hidden_def(semanage_module_info_create)
266
267 int semanage_module_info_destroy(semanage_handle_t *sh,
268 semanage_module_info_t *modinfo)
269 {
270 assert(sh);
271
272 if (!modinfo) {
273 return 0;
274 }
275
276 free(modinfo->name);
277 free(modinfo->lang_ext);
278
279 return semanage_module_info_init(sh, modinfo);
280 }
281
hidden_def(semanage_module_info_destroy)282 hidden_def(semanage_module_info_destroy)
283
284 int semanage_module_info_init(semanage_handle_t *sh,
285 semanage_module_info_t *modinfo)
286 {
287 assert(sh);
288 assert(modinfo);
289
290 modinfo->priority = 0;
291 modinfo->name = NULL;
292 modinfo->lang_ext = NULL;
293 modinfo->enabled = -1;
294
295 return 0;
296 }
297
semanage_module_info_clone(semanage_handle_t * sh,const semanage_module_info_t * source,semanage_module_info_t * target)298 int semanage_module_info_clone(semanage_handle_t *sh,
299 const semanage_module_info_t *source,
300 semanage_module_info_t *target)
301 {
302 assert(sh);
303 assert(source);
304 assert(target);
305
306 int status = 0;
307 int ret = 0;
308
309 ret = semanage_module_info_destroy(sh, target);
310 if (ret != 0) {
311 status = -1;
312 goto cleanup;
313 }
314
315 ret = semanage_module_info_set_priority(sh, target, source->priority);
316 if (ret != 0) {
317 status = -1;
318 goto cleanup;
319 }
320
321 ret = semanage_module_info_set_name(sh, target, source->name);
322 if (ret != 0) {
323 status = -1;
324 goto cleanup;
325 }
326
327 ret = semanage_module_info_set_lang_ext(sh, target, source->lang_ext);
328 if (ret != 0) {
329 status = -1;
330 goto cleanup;
331 }
332
333 ret = semanage_module_info_set_enabled(sh, target, source->enabled);
334 if (ret != 0) {
335 status = -1;
336 goto cleanup;
337 }
338
339 cleanup:
340 if (status != 0) semanage_module_info_destroy(sh, target);
341 return status;
342 }
343
semanage_module_info_get_priority(semanage_handle_t * sh,semanage_module_info_t * modinfo,uint16_t * priority)344 int semanage_module_info_get_priority(semanage_handle_t *sh,
345 semanage_module_info_t *modinfo,
346 uint16_t *priority)
347 {
348 assert(sh);
349 assert(modinfo);
350 assert(priority);
351
352 *priority = modinfo->priority;
353
354 return 0;
355 }
356
hidden_def(semanage_module_info_get_priority)357 hidden_def(semanage_module_info_get_priority)
358
359 int semanage_module_info_get_name(semanage_handle_t *sh,
360 semanage_module_info_t *modinfo,
361 const char **name)
362 {
363 assert(sh);
364 assert(modinfo);
365 assert(name);
366
367 *name = modinfo->name;
368
369 return 0;
370 }
371
hidden_def(semanage_module_info_get_name)372 hidden_def(semanage_module_info_get_name)
373
374 int semanage_module_info_get_lang_ext(semanage_handle_t *sh,
375 semanage_module_info_t *modinfo,
376 const char **lang_ext)
377 {
378 assert(sh);
379 assert(modinfo);
380 assert(lang_ext);
381
382 *lang_ext = modinfo->lang_ext;
383
384 return 0;
385 }
386
hidden_def(semanage_module_info_get_lang_ext)387 hidden_def(semanage_module_info_get_lang_ext)
388
389 int semanage_module_info_get_enabled(semanage_handle_t *sh,
390 semanage_module_info_t *modinfo,
391 int *enabled)
392 {
393 assert(sh);
394 assert(modinfo);
395 assert(enabled);
396
397 *enabled = modinfo->enabled;
398
399 return 0;
400 }
401
hidden_def(semanage_module_info_get_enabled)402 hidden_def(semanage_module_info_get_enabled)
403
404 int semanage_module_info_set_priority(semanage_handle_t *sh,
405 semanage_module_info_t *modinfo,
406 uint16_t priority)
407 {
408 assert(sh);
409 assert(modinfo);
410
411 /* Verify priority */
412 if (semanage_module_validate_priority(priority) < 0) {
413 errno = 0;
414 ERR(sh, "Priority %d is invalid.", priority);
415 return -1;
416 }
417
418 modinfo->priority = priority;
419
420 return 0;
421 }
422
hidden_def(semanage_module_info_set_priority)423 hidden_def(semanage_module_info_set_priority)
424
425 int semanage_module_info_set_name(semanage_handle_t *sh,
426 semanage_module_info_t *modinfo,
427 const char *name)
428 {
429 assert(sh);
430 assert(modinfo);
431 assert(name);
432
433 char * tmp;
434
435 /* Verify name */
436 if (semanage_module_validate_name(name) < 0) {
437 errno = 0;
438 ERR(sh, "Name %s is invalid.", name);
439 return -1;
440 }
441
442 tmp = strdup(name);
443 if (!tmp) {
444 ERR(sh, "No memory available for strdup");
445 return -1;
446 }
447
448 free(modinfo->name);
449 modinfo->name = tmp;
450
451 return 0;
452 }
453
hidden_def(semanage_module_info_set_name)454 hidden_def(semanage_module_info_set_name)
455
456 int semanage_module_info_set_lang_ext(semanage_handle_t *sh,
457 semanage_module_info_t *modinfo,
458 const char *lang_ext)
459 {
460 assert(sh);
461 assert(modinfo);
462 assert(lang_ext);
463
464 char * tmp;
465
466 /* Verify extension */
467 if (semanage_module_validate_lang_ext(lang_ext) < 0) {
468 errno = 0;
469 ERR(sh, "Language extensions %s is invalid.", lang_ext);
470 return -1;
471 }
472
473 tmp = strdup(lang_ext);
474 if (!tmp) {
475 ERR(sh, "No memory available for strdup");
476 return -1;
477 }
478
479 free(modinfo->lang_ext);
480 modinfo->lang_ext = tmp;
481
482 return 0;
483 }
484
hidden_def(semanage_module_info_set_lang_ext)485 hidden_def(semanage_module_info_set_lang_ext)
486
487 int semanage_module_info_set_enabled(semanage_handle_t *sh,
488 semanage_module_info_t *modinfo,
489 int enabled)
490 {
491 assert(sh);
492 assert(modinfo);
493
494 /* Verify enabled */
495 if (semanage_module_validate_enabled(enabled) < 0) {
496 errno = 0;
497 ERR(sh, "Enabled status %d is invalid.", enabled);
498 return -1;
499 }
500
501 modinfo->enabled = enabled;
502
503 return 0;
504 }
505
hidden_def(semanage_module_info_set_enabled)506 hidden_def(semanage_module_info_set_enabled)
507
508 int semanage_module_get_path(semanage_handle_t *sh,
509 const semanage_module_info_t *modinfo,
510 enum semanage_module_path_type type,
511 char *path,
512 size_t len)
513 {
514 assert(sh);
515 assert(modinfo);
516 assert(path);
517
518 int status = 0;
519 int ret = 0;
520
521 const char *modules_path = NULL;
522 const char *file = NULL;
523
524 modules_path = sh->is_in_transaction ?
525 semanage_path(SEMANAGE_TMP, SEMANAGE_MODULES):
526 semanage_path(SEMANAGE_ACTIVE, SEMANAGE_MODULES);
527
528 switch (type) {
529 case SEMANAGE_MODULE_PATH_PRIORITY:
530 /* verify priority */
531 ret = semanage_module_validate_priority(modinfo->priority);
532 if (ret < 0) {
533 errno = 0;
534 ERR(sh,
535 "Priority %d is invalid.",
536 modinfo->priority);
537 status = ret;
538 goto cleanup;
539 }
540
541 ret = snprintf(path,
542 len,
543 "%s/%03u",
544 modules_path,
545 modinfo->priority);
546 if (ret < 0 || (size_t)ret >= len) {
547 ERR(sh, "Unable to compose priority path.");
548 status = -1;
549 goto cleanup;
550 }
551 break;
552 case SEMANAGE_MODULE_PATH_NAME:
553 /* verify priority and name */
554 ret = semanage_module_validate_priority(modinfo->priority);
555 if (ret < 0) {
556 errno = 0;
557 ERR(sh,
558 "Priority %d is invalid.",
559 modinfo->priority);
560 status = -1;
561 goto cleanup;
562 }
563
564 ret = semanage_module_validate_name(modinfo->name);
565 if (ret < 0) {
566 errno = 0;
567 ERR(sh, "Name %s is invalid.", modinfo->name);
568 status = -1;
569 goto cleanup;
570 }
571
572 ret = snprintf(path,
573 len,
574 "%s/%03u/%s",
575 modules_path,
576 modinfo->priority,
577 modinfo->name);
578 if (ret < 0 || (size_t)ret >= len) {
579 ERR(sh, "Unable to compose name path.");
580 status = -1;
581 goto cleanup;
582 }
583 break;
584 case SEMANAGE_MODULE_PATH_HLL:
585 if (file == NULL) file = "hll";
586 case SEMANAGE_MODULE_PATH_CIL:
587 if (file == NULL) file = "cil";
588 case SEMANAGE_MODULE_PATH_LANG_EXT:
589 if (file == NULL) file = "lang_ext";
590
591 /* verify priority and name */
592 ret = semanage_module_validate_priority(modinfo->priority);
593 if (ret < 0) {
594 errno = 0;
595 ERR(sh,
596 "Priority %d is invalid.",
597 modinfo->priority);
598 status = -1;
599 goto cleanup;
600 }
601
602 ret = semanage_module_validate_name(modinfo->name);
603 if (ret < 0) {
604 errno = 0;
605 ERR(sh, "Name %s is invalid.", modinfo->name);
606 status = -1;
607 goto cleanup;
608 }
609
610 ret = snprintf(path,
611 len,
612 "%s/%03u/%s/%s",
613 modules_path,
614 modinfo->priority,
615 modinfo->name,
616 file);
617 if (ret < 0 || (size_t)ret >= len) {
618 ERR(sh,
619 "Unable to compose path for %s file.",
620 file);
621 status = -1;
622 goto cleanup;
623 }
624 break;
625 case SEMANAGE_MODULE_PATH_DISABLED:
626 /* verify name */
627 ret = semanage_module_validate_name(modinfo->name);
628 if (ret < 0) {
629 errno = 0;
630 ERR(sh, "Name %s is invalid.", modinfo->name);
631 status = -1;
632 goto cleanup;
633 }
634
635 ret = snprintf(path,
636 len,
637 "%s/disabled/%s",
638 modules_path,
639 modinfo->name);
640 if (ret < 0 || (size_t)ret >= len) {
641 ERR(sh,
642 "Unable to compose disabled status path.");
643 status = -1;
644 goto cleanup;
645 }
646 break;
647 default:
648 ERR(sh, "Invalid module path type %d.", type);
649 status = -1;
650 goto cleanup;
651 }
652
653 cleanup:
654 return status;
655 }
656
semanage_module_key_create(semanage_handle_t * sh,semanage_module_key_t ** modkey)657 int semanage_module_key_create(semanage_handle_t *sh,
658 semanage_module_key_t **modkey)
659 {
660 assert(sh);
661 assert(modkey);
662
663 *modkey = malloc(sizeof(semanage_module_key_t));
664 if (*modkey == NULL) return -1;
665
666 return semanage_module_key_init(sh, *modkey);
667 }
668
hidden_def(semanage_module_key_create)669 hidden_def(semanage_module_key_create)
670
671 int semanage_module_key_destroy(semanage_handle_t *sh,
672 semanage_module_key_t *modkey)
673 {
674 assert(sh);
675
676 if (modkey) {
677 free(modkey->name);
678 }
679
680 return semanage_module_key_init(sh, modkey);
681 }
682
hidden_def(semanage_module_key_destroy)683 hidden_def(semanage_module_key_destroy)
684
685 int semanage_module_key_init(semanage_handle_t *sh,
686 semanage_module_key_t *modkey)
687 {
688 assert(sh);
689 assert(modkey);
690
691 modkey->name = NULL;
692 modkey->priority = 0;
693
694 return 0;
695 }
696
semanage_module_key_get_name(semanage_handle_t * sh,semanage_module_key_t * modkey,const char ** name)697 int semanage_module_key_get_name(semanage_handle_t *sh,
698 semanage_module_key_t *modkey,
699 const char **name)
700 {
701 assert(sh);
702 assert(modkey);
703 assert(name);
704
705 *name = modkey->name;
706
707 return 0;
708 }
709
hidden_def(semanage_module_key_get_name)710 hidden_def(semanage_module_key_get_name)
711
712 int semanage_module_key_get_priority(semanage_handle_t *sh,
713 semanage_module_key_t *modkey,
714 uint16_t *priority)
715 {
716 assert(sh);
717 assert(modkey);
718 assert(priority);
719
720 *priority = modkey->priority;
721
722 return 0;
723 }
724
hidden_def(semanage_module_key_get_priority)725 hidden_def(semanage_module_key_get_priority)
726
727 int semanage_module_key_set_name(semanage_handle_t *sh,
728 semanage_module_key_t *modkey,
729 const char *name)
730 {
731 assert(sh);
732 assert(modkey);
733 assert(name);
734
735 int status = 0;
736 char *tmp = NULL;
737
738 if (semanage_module_validate_name(name) < 0) {
739 errno = 0;
740 ERR(sh, "Name %s is invalid.", name);
741 return -1;
742 }
743
744 tmp = strdup(name);
745 if (tmp == NULL) {
746 ERR(sh, "No memory available for strdup");
747 status = -1;
748 goto cleanup;
749 }
750
751 free(modkey->name);
752 modkey->name = tmp;
753
754 cleanup:
755 return status;
756 }
757
hidden_def(semanage_module_key_set_name)758 hidden_def(semanage_module_key_set_name)
759
760 int semanage_module_key_set_priority(semanage_handle_t *sh,
761 semanage_module_key_t *modkey,
762 uint16_t priority)
763 {
764 assert(sh);
765 assert(modkey);
766
767 if (semanage_module_validate_priority(priority) < 0) {
768 errno = 0;
769 ERR(sh, "Priority %d is invalid.", priority);
770 return -1;
771 }
772
773 modkey->priority = priority;
774
775 return 0;
776 }
777
hidden_def(semanage_module_key_set_priority)778 hidden_def(semanage_module_key_set_priority)
779
780 int semanage_module_get_enabled_1_1(semanage_handle_t *sh,
781 const semanage_module_key_t *modkey,
782 int *enabled)
783 {
784 assert(sh);
785 assert(modkey);
786 assert(enabled);
787
788 if (sh->funcs->get_enabled == NULL) {
789 ERR(sh,
790 "No get_enabled function defined for this connection type.");
791 return -1;
792 } else if (!sh->is_connected) {
793 ERR(sh, "Not connected.");
794 return -1;
795 }
796
797 return sh->funcs->get_enabled(sh, modkey, enabled);
798 }
799
semanage_module_get_enabled_1_0(semanage_module_info_t * modinfo)800 int semanage_module_get_enabled_1_0(semanage_module_info_t *modinfo)
801 {
802 return modinfo->enabled;
803 }
804
semanage_module_set_enabled(semanage_handle_t * sh,const semanage_module_key_t * modkey,int enabled)805 int semanage_module_set_enabled(semanage_handle_t *sh,
806 const semanage_module_key_t *modkey,
807 int enabled)
808 {
809 assert(sh);
810 assert(modkey);
811
812 if (sh->funcs->set_enabled == NULL) {
813 ERR(sh,
814 "No set_enabled function defined for this connection type.");
815 return -1;
816 } else if (!sh->is_connected) {
817 ERR(sh, "Not connected.");
818 return -1;
819 } else if (!sh->is_in_transaction) {
820 if (semanage_begin_transaction(sh) < 0) {
821 return -1;
822 }
823 }
824
825 sh->modules_modified = 1;
826 return sh->funcs->set_enabled(sh, modkey, enabled);
827 }
828
hidden_def(semanage_module_set_enabled)829 hidden_def(semanage_module_set_enabled)
830
831 /* This function exists only for ABI compatability. It has been deprecated and
832 * should not be used. Instead, use semanage_module_set_enabled() */
833 int semanage_module_enable(semanage_handle_t *sh, char *module_name)
834 {
835 int rc = -1;
836 semanage_module_key_t *modkey = NULL;
837
838 rc = semanage_module_key_create(sh, &modkey);
839 if (rc != 0)
840 goto exit;
841
842 rc = semanage_module_key_set_name(sh, modkey, module_name);
843 if (rc != 0)
844 goto exit;
845
846 rc = semanage_module_set_enabled(sh, modkey, 1);
847 if (rc != 0)
848 goto exit;
849
850 rc = 0;
851
852 exit:
853 semanage_module_key_destroy(sh, modkey);
854 free(modkey);
855
856 return rc;
857 }
858
859 /* This function exists only for ABI compatability. It has been deprecated and
860 * should not be used. Instead, use semanage_module_set_enabled() */
semanage_module_disable(semanage_handle_t * sh,char * module_name)861 int semanage_module_disable(semanage_handle_t *sh, char *module_name)
862 {
863 int rc = -1;
864 semanage_module_key_t *modkey = NULL;
865
866 rc = semanage_module_key_create(sh, &modkey);
867 if (rc != 0)
868 goto exit;
869
870 rc = semanage_module_key_set_name(sh, modkey, module_name);
871 if (rc != 0)
872 goto exit;
873
874 rc = semanage_module_set_enabled(sh, modkey, 0);
875 if (rc != 0)
876 goto exit;
877
878 rc = 0;
879
880 exit:
881 semanage_module_key_destroy(sh, modkey);
882 free(modkey);
883
884 return rc;
885 }
886
887 /* Converts a string to a priority
888 *
889 * returns -1 if str is not a valid priority.
890 * returns 0 and sets priority if str is a valid priority
891 */
semanage_string_to_priority(const char * str,uint16_t * priority)892 int semanage_string_to_priority(const char *str, uint16_t *priority)
893 {
894 unsigned long val;
895 char *endptr = NULL;
896 int status = -1;
897
898 if (str == NULL || priority == NULL) {
899 goto exit;
900 }
901
902 errno = 0;
903
904 val = strtoul(str, &endptr, 10);
905
906 if (errno != 0 || endptr == str || *endptr != '\0' || val > UINT16_MAX) {
907 goto exit;
908 }
909
910 if (semanage_module_validate_priority((uint16_t)val) < 0) {
911 goto exit;
912 }
913
914 *priority = val;
915 status = 0;
916
917 exit:
918 return status;
919 }
920
921 /* Validates a module info struct.
922 *
923 * Returns -1 if module is invalid, 0 otherwise.
924 */
semanage_module_info_validate(const semanage_module_info_t * modinfo)925 int semanage_module_info_validate(const semanage_module_info_t *modinfo)
926 {
927 if (semanage_module_validate_priority(modinfo->priority) != 0 ||
928 semanage_module_validate_name(modinfo->name) != 0 ||
929 semanage_module_validate_lang_ext(modinfo->lang_ext) != 0 ||
930 semanage_module_validate_enabled(modinfo->enabled) != 0) {
931 return -1;
932 }
933 return 0;
934 }
935
936 #define PRIORITY_MIN 1
937 #define PRIORITY_MAX 999
938
939 /* Validates priority.
940 *
941 * returns -1 if priority is not in the valid range, returns 0 otherwise
942 */
semanage_module_validate_priority(uint16_t priority)943 int semanage_module_validate_priority(uint16_t priority)
944 {
945 if (priority >= PRIORITY_MIN && priority <= PRIORITY_MAX) {
946 return 0;
947 }
948
949 return -1;
950 }
951
952 /* Validates module name.
953 *
954 * A module name must match one of the following regular expressions
955 * to be considered valid:
956 *
957 * ^[a-zA-Z](\.?[a-zA-Z0-9_-])*$
958 *
959 * returns -1 if name is not valid, returns 0 otherwise
960 */
semanage_module_validate_name(const char * name)961 int semanage_module_validate_name(const char * name)
962 {
963 int status = 0;
964
965 if (name == NULL) {
966 status = -1;
967 goto exit;
968 }
969
970 if (!isalpha(*name)) {
971 status = -1;
972 goto exit;
973 }
974
975 #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-')
976
977 for (name++; *name; name++) {
978 if (ISVALIDCHAR(*name)) {
979 continue;
980 }
981 if (*name == '.' && name++ && ISVALIDCHAR(*name)) {
982 continue;
983 }
984 status = -1;
985 goto exit;
986 }
987
988 #undef ISVALIDCHAR
989
990 exit:
991 return status;
992 }
993
994 /* Validates module enabled status.
995 *
996 * Valid enabled values are 1, 0, and -1.
997 *
998 * returns 0 if enabled is a valid value, returns -1 otherwise.
999 */
semanage_module_validate_enabled(int enabled)1000 int semanage_module_validate_enabled(int enabled)
1001 {
1002 if (enabled == 1 || enabled == 0 || enabled == -1) {
1003 return 0;
1004 }
1005
1006 return -1;
1007 }
1008
1009 /* Validate extension.
1010 *
1011 * An extension must match the following regular expression to be
1012 * considered valid:
1013 *
1014 * ^[a-zA-Z0-9][a-zA-Z0-9_-]*$
1015 *
1016 * returns 0 if ext is a valid value, returns -1 otherwise.
1017 */
semanage_module_validate_lang_ext(const char * ext)1018 int semanage_module_validate_lang_ext(const char *ext)
1019 {
1020 int status = 0;
1021
1022 if (ext == NULL) {
1023 status = -1;
1024 goto exit;
1025 }
1026
1027 if (!isalnum(*ext)) {
1028 status = -1;
1029 goto exit;
1030 }
1031
1032 #define ISVALIDCHAR(c) (isalnum(c) || c == '_' || c == '-')
1033
1034 for (ext++; *ext; ext++) {
1035 if (ISVALIDCHAR(*ext)) {
1036 continue;
1037 }
1038 status = -1;
1039 goto exit;
1040 }
1041
1042 #undef ISVALIDCHAR
1043
1044 exit:
1045 return status;
1046 }
1047
semanage_module_get_module_info(semanage_handle_t * sh,const semanage_module_key_t * modkey,semanage_module_info_t ** modinfo)1048 int semanage_module_get_module_info(semanage_handle_t *sh,
1049 const semanage_module_key_t *modkey,
1050 semanage_module_info_t **modinfo)
1051 {
1052 assert(sh);
1053 assert(modkey);
1054 assert(modinfo);
1055
1056 if (sh->funcs->get_module_info == NULL) {
1057 ERR(sh,
1058 "No get module info function defined for this connection type.");
1059 return -1;
1060 } else if (!sh->is_connected) {
1061 ERR(sh, "Not connected.");
1062 return -1;
1063 }
1064
1065 return sh->funcs->get_module_info(sh, modkey, modinfo);
1066 }
1067
semanage_module_list_all(semanage_handle_t * sh,semanage_module_info_t ** modinfos,int * modinfos_len)1068 int semanage_module_list_all(semanage_handle_t *sh,
1069 semanage_module_info_t **modinfos,
1070 int *modinfos_len)
1071 {
1072 assert(sh);
1073 assert(modinfos);
1074 assert(modinfos_len);
1075
1076 if (sh->funcs->list_all == NULL) {
1077 ERR(sh,
1078 "No list all function defined for this connection type.");
1079 return -1;
1080 } else if (!sh->is_connected) {
1081 ERR(sh, "Not connected.");
1082 return -1;
1083 }
1084
1085 return sh->funcs->list_all(sh, modinfos, modinfos_len);
1086 }
1087
semanage_module_install_info(semanage_handle_t * sh,const semanage_module_info_t * modinfo,char * data,size_t data_len)1088 int semanage_module_install_info(semanage_handle_t *sh,
1089 const semanage_module_info_t *modinfo,
1090 char *data,
1091 size_t data_len)
1092 {
1093 if (sh->funcs->install_info == NULL) {
1094 ERR(sh,
1095 "No install info function defined for this connection type.");
1096 return -1;
1097 } else if (!sh->is_connected) {
1098 ERR(sh, "Not connected.");
1099 return -1;
1100 } else if (!sh->is_in_transaction) {
1101 if (semanage_begin_transaction(sh) < 0) {
1102 return -1;
1103 }
1104 }
1105 sh->modules_modified = 1;
1106 return sh->funcs->install_info(sh, modinfo, data, data_len);
1107 }
1108
semanage_module_remove_key(semanage_handle_t * sh,const semanage_module_key_t * modkey)1109 int semanage_module_remove_key(semanage_handle_t *sh,
1110 const semanage_module_key_t *modkey)
1111 {
1112 if (sh->funcs->remove_key== NULL) {
1113 ERR(sh,
1114 "No remove key function defined for this connection type.");
1115 return -1;
1116 } else if (!sh->is_connected) {
1117 ERR(sh, "Not connected.");
1118 return -1;
1119 } else if (!sh->is_in_transaction) {
1120 if (semanage_begin_transaction(sh) < 0) {
1121 return -1;
1122 }
1123 }
1124 sh->modules_modified = 1;
1125 return sh->funcs->remove_key(sh, modkey);
1126 }
1127
1128