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