1 /* Authors: Karl MacMillan <kmacmillan@tresys.com>
2 * Joshua Brindle <jbrindle@tresys.com>
3 * Jason Tang <jtang@tresys.com>
4 *
5 * Copyright (C) 2004-2005 Tresys Technology, LLC
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation, version 2.
9 */
10
11 #include <fcntl.h>
12 #include <getopt.h>
13 #include <signal.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <errno.h>
17 #include <string.h>
18 #include <unistd.h>
19 #include <sys/mman.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <libgen.h>
23 #include <limits.h>
24
25 #include <sepol/cil/cil.h>
26 #include <semanage/modules.h>
27
28 enum client_modes {
29 NO_MODE, INSTALL_M, REMOVE_M, EXTRACT_M, CIL_M, HLL_M,
30 LIST_M, RELOAD, PRIORITY_M, ENABLE_M, DISABLE_M
31 };
32 /* list of modes in which one ought to commit afterwards */
33 static const int do_commit[] = {
34 0, 1, 1, 0, 0, 0,
35 0, 0, 0, 1, 1,
36 };
37
38 struct command {
39 enum client_modes mode;
40 char *arg;
41 };
42 static struct command *commands = NULL;
43 static int num_commands = 0;
44
45 /* options given on command line */
46 static int verbose;
47 static int reload;
48 static int no_reload;
49 static int build;
50 static int check_ext_changes;
51 static int disable_dontaudit;
52 static int preserve_tunables;
53 static int ignore_module_cache;
54 static uint16_t priority;
55 static int priority_set = 0;
56
57 static semanage_handle_t *sh = NULL;
58 static char *store;
59 static char *store_root;
60 int extract_cil = 0;
61 static int checksum = 0;
62
63 extern char *optarg;
64 extern int optind;
65
cleanup(void)66 static void cleanup(void)
67 {
68 while (--num_commands >= 0) {
69 free(commands[num_commands].arg);
70 }
71 free(commands);
72 }
73
74 /* Signal handlers. */
handle_signal(int sig_num)75 static void handle_signal(int sig_num)
76 {
77 if (sig_num == SIGINT || sig_num == SIGQUIT || sig_num == SIGTERM) {
78 /* catch these signals, and then drop them */
79 }
80 }
81
set_store(char * storename)82 static void set_store(char *storename)
83 {
84 /* For now this only supports a store name, later on this
85 * should support an address for a remote connection */
86
87 if ((store = strdup(storename)) == NULL) {
88 fprintf(stderr, "Out of memory!\n");
89 goto bad;
90 }
91
92 return;
93
94 bad:
95 cleanup();
96 exit(1);
97 }
98
set_store_root(char * path)99 static void set_store_root(char *path)
100 {
101 if ((store_root = strdup(path)) == NULL) {
102 fprintf(stderr, "Out of memory!\n");
103 goto bad;
104 }
105
106 return;
107
108 bad:
109 cleanup();
110 exit(1);
111 }
112
113 /* Establish signal handlers for the process. */
create_signal_handlers(void)114 static void create_signal_handlers(void)
115 {
116 if (signal(SIGINT, handle_signal) == SIG_ERR ||
117 signal(SIGQUIT, handle_signal) == SIG_ERR ||
118 signal(SIGTERM, handle_signal) == SIG_ERR) {
119 fprintf(stderr, "Could not set up signal handler.\n");
120 exit(255);
121 }
122 }
123
usage(char * progname)124 static void usage(char *progname)
125 {
126 printf("usage: %s [option]... MODE...\n", progname);
127 printf("Manage SELinux policy modules.\n");
128 printf("MODES:\n");
129 printf(" -R, --reload reload policy\n");
130 printf(" -B, --build build and reload policy\n");
131 printf(" -D,--disable_dontaudit Remove dontaudits from policy\n");
132 printf(" -i,--install=MODULE_PKG install a new module\n");
133 printf(" -r,--remove=MODULE_NAME remove existing module at desired priority\n");
134 printf(" -l[KIND],--list-modules[=KIND] display list of installed modules\n");
135 printf(" KIND: standard list highest priority, enabled modules\n");
136 printf(" full list all modules\n");
137 printf(" -X,--priority=PRIORITY set priority for following operations (1-999)\n");
138 printf(" -e,--enable=MODULE_NAME enable module\n");
139 printf(" -d,--disable=MODULE_NAME disable module\n");
140 printf(" -E,--extract=MODULE_NAME extract module\n");
141 printf("Options:\n");
142 printf(" -s,--store name of the store to operate on\n");
143 printf(" -N,-n,--noreload do not reload policy after commit\n");
144 printf(" -h,--help print this message and quit\n");
145 printf(" -v,--verbose be verbose\n");
146 printf(" -P,--preserve_tunables Preserve tunables in policy\n");
147 printf(" -C,--ignore-module-cache Rebuild CIL modules compiled from HLL files\n");
148 printf(" -p,--path use an alternate path for the policy root\n");
149 printf(" -S,--store-path use an alternate path for the policy store root\n");
150 printf(" -c, --cil extract module as cil. This only affects module extraction.\n");
151 printf(" -H, --hll extract module as hll. This only affects module extraction.\n");
152 printf(" -m, --checksum print module checksum (SHA256).\n");
153 printf(" --rebuild-if-modules-changed\n"
154 " force policy rebuild if module content changed since\n"
155 " last rebuild (based on checksum)\n");
156 }
157
158 /* Sets the global mode variable to new_mode, but only if no other
159 * mode has been given. */
set_mode(enum client_modes new_mode,char * arg)160 static void set_mode(enum client_modes new_mode, char *arg)
161 {
162 struct command *c;
163 char *s;
164 if ((c = realloc(commands, sizeof(*c) * (num_commands + 1))) == NULL) {
165 fprintf(stderr, "Out of memory!\n");
166 cleanup();
167 exit(1);
168 }
169 commands = c;
170 commands[num_commands].mode = new_mode;
171 commands[num_commands].arg = NULL;
172 num_commands++;
173 if (arg != NULL) {
174 if ((s = strdup(arg)) == NULL) {
175 fprintf(stderr, "Out of memory!\n");
176 cleanup();
177 exit(1);
178 }
179 commands[num_commands - 1].arg = s;
180 }
181 }
182
183 /* Parse command line and set global options. */
parse_command_line(int argc,char ** argv)184 static void parse_command_line(int argc, char **argv)
185 {
186 static struct option opts[] = {
187 {"rebuild-if-modules-changed", 0, NULL, '\0'},
188 {"store", required_argument, NULL, 's'},
189 {"base", required_argument, NULL, 'b'},
190 {"help", 0, NULL, 'h'},
191 {"install", required_argument, NULL, 'i'},
192 {"extract", required_argument, NULL, 'E'},
193 {"cil", 0, NULL, 'c'},
194 {"hll", 0, NULL, 'H'},
195 {"list-modules", optional_argument, NULL, 'l'},
196 {"verbose", 0, NULL, 'v'},
197 {"remove", required_argument, NULL, 'r'},
198 {"upgrade", required_argument, NULL, 'u'},
199 {"reload", 0, NULL, 'R'},
200 {"noreload", 0, NULL, 'n'},
201 {"build", 0, NULL, 'B'},
202 {"disable_dontaudit", 0, NULL, 'D'},
203 {"preserve_tunables", 0, NULL, 'P'},
204 {"ignore-module-cache", 0, NULL, 'C'},
205 {"priority", required_argument, NULL, 'X'},
206 {"enable", required_argument, NULL, 'e'},
207 {"disable", required_argument, NULL, 'd'},
208 {"path", required_argument, NULL, 'p'},
209 {"store-path", required_argument, NULL, 'S'},
210 {"checksum", 0, NULL, 'm'},
211 {NULL, 0, NULL, 0}
212 };
213 int extract_selected = 0;
214 int cil_hll_set = 0;
215 int i, longind;
216 verbose = 0;
217 reload = 0;
218 no_reload = 0;
219 check_ext_changes = 0;
220 priority = 400;
221 while ((i =
222 getopt_long(argc, argv, "s:b:hi:l::vr:u:RnNBDCPX:e:d:p:S:E:cHm",
223 opts, &longind)) != -1) {
224 switch (i) {
225 case '\0':
226 switch(longind) {
227 case 0: /* --rebuild-if-modules-changed */
228 check_ext_changes = 1;
229 break;
230 default:
231 usage(argv[0]);
232 exit(1);
233 }
234 break;
235 case 'b':
236 fprintf(stderr, "The --base option is deprecated. Use --install instead.\n");
237 set_mode(INSTALL_M, optarg);
238 break;
239 case 'h':
240 usage(argv[0]);
241 exit(0);
242 case 'i':
243 set_mode(INSTALL_M, optarg);
244 break;
245 case 'E':
246 set_mode(EXTRACT_M, optarg);
247 extract_selected = 1;
248 break;
249 case 'c':
250 set_mode(CIL_M, NULL);
251 cil_hll_set = 1;
252 break;
253 case 'H':
254 set_mode(HLL_M, NULL);
255 cil_hll_set = 1;
256 break;
257 case 'l':
258 set_mode(LIST_M, optarg);
259 break;
260 case 'v':
261 verbose++;
262 break;
263 case 'r':
264 set_mode(REMOVE_M, optarg);
265 break;
266 case 'u':
267 fprintf(stderr, "The --upgrade option is deprecated. Use --install instead.\n");
268 set_mode(INSTALL_M, optarg);
269 break;
270 case 's':
271 set_store(optarg);
272 break;
273 case 'p':
274 semanage_set_root(optarg);
275 break;
276 case 'S':
277 set_store_root(optarg);
278 break;
279 case 'R':
280 reload = 1;
281 break;
282 case 'n':
283 no_reload = 1;
284 break;
285 case 'N':
286 no_reload = 1;
287 break;
288 case 'B':
289 build = 1;
290 break;
291 case 'D':
292 disable_dontaudit = 1;
293 break;
294 case 'P':
295 preserve_tunables = 1;
296 break;
297 case 'C':
298 ignore_module_cache = 1;
299 break;
300 case 'X':
301 set_mode(PRIORITY_M, optarg);
302 break;
303 case 'e':
304 set_mode(ENABLE_M, optarg);
305 break;
306 case 'd':
307 set_mode(DISABLE_M, optarg);
308 break;
309 case 'm':
310 checksum = 1;
311 break;
312 case '?':
313 default:{
314 usage(argv[0]);
315 exit(1);
316 }
317 }
318 }
319 if ((build || reload || check_ext_changes) && num_commands) {
320 fprintf(stderr,
321 "build or reload should not be used with other commands\n");
322 usage(argv[0]);
323 exit(1);
324 }
325 if (num_commands == 0 && reload == 0 && build == 0 && check_ext_changes == 0) {
326 fprintf(stderr, "At least one mode must be specified.\n");
327 usage(argv[0]);
328 exit(1);
329 }
330 if (extract_selected == 0 && cil_hll_set == 1) {
331 fprintf(stderr, "--cil and --hll require a module to export with the --extract option.\n");
332 usage(argv[0]);
333 exit(1);
334 }
335
336 if (optind < argc) {
337 int mode = commands ? (int) commands[num_commands - 1].mode : -1;
338 /* if -i/u/r/E was the last command treat any remaining
339 * arguments as args. Will allow 'semodule -i *.pp' to
340 * work as expected.
341 */
342
343 switch (mode) {
344 case INSTALL_M:
345 case REMOVE_M:
346 case EXTRACT_M:
347 case ENABLE_M:
348 case DISABLE_M:
349 while (optind < argc)
350 set_mode(mode, argv[optind++]);
351 break;
352 default:
353 fprintf(stderr, "unknown additional arguments:\n");
354 while (optind < argc)
355 fprintf(stderr, " %s", argv[optind++]);
356 fprintf(stderr, "\n\n");
357 usage(argv[0]);
358 exit(1);
359 }
360 }
361 }
362
363 /* Get module checksum */
hash_module_data(const char * module_name,const int prio)364 static char *hash_module_data(const char *module_name, const int prio) {
365 semanage_module_key_t *modkey = NULL;
366 char *hash_str = NULL;
367 void *hash = NULL;
368 size_t hash_len = 0;
369 int result;
370
371 result = semanage_module_key_create(sh, &modkey);
372 if (result != 0) {
373 goto cleanup;
374 }
375
376 result = semanage_module_key_set_name(sh, modkey, module_name);
377 if (result != 0) {
378 goto cleanup;
379 }
380
381 result = semanage_module_key_set_priority(sh, modkey, prio);
382 if (result != 0) {
383 goto cleanup;
384 }
385
386 result = semanage_module_compute_checksum(sh, modkey, 1, &hash_str,
387 &hash_len);
388 if (result != 0) {
389 goto cleanup;
390 }
391
392 cleanup:
393 free(hash);
394 semanage_module_key_destroy(sh, modkey);
395 free(modkey);
396 return hash_str;
397 }
398
main(int argc,char * argv[])399 int main(int argc, char *argv[])
400 {
401 int i, commit = 0;
402 int result;
403 int status = EXIT_FAILURE;
404 const char *genhomedirconargv[] = { "genhomedircon", "-B", "-n" };
405 create_signal_handlers();
406 if (strcmp(basename(argv[0]), "genhomedircon") == 0) {
407 argc = 3;
408 argv = (char **)genhomedirconargv;
409 }
410 parse_command_line(argc, argv);
411
412 cil_set_log_level(CIL_ERR + verbose);
413
414 if (build || check_ext_changes)
415 commit = 1;
416
417 sh = semanage_handle_create();
418 if (!sh) {
419 fprintf(stderr, "%s: Could not create semanage handle\n",
420 argv[0]);
421 goto cleanup_nohandle;
422 }
423
424 if (store) {
425 /* Set the store we want to connect to, before connecting.
426 * this will always set a direct connection now, an additional
427 * option will need to be used later to specify a policy server
428 * location */
429 semanage_select_store(sh, store, SEMANAGE_CON_DIRECT);
430 }
431
432 if (store_root) {
433 semanage_set_store_root(sh, store_root);
434 }
435
436 /* create store if necessary, for bootstrapping */
437 semanage_set_create_store(sh, 1);
438
439 if ((result = semanage_connect(sh)) < 0) {
440 fprintf(stderr, "%s: Could not connect to policy handler\n",
441 argv[0]);
442 goto cleanup;
443 }
444
445 if (reload) {
446 if ((result = semanage_reload_policy(sh)) < 0) {
447 fprintf(stderr, "%s: Could not reload policy\n",
448 argv[0]);
449 goto cleanup;
450 }
451 }
452
453 if (build || check_ext_changes) {
454 if ((result = semanage_begin_transaction(sh)) < 0) {
455 fprintf(stderr, "%s: Could not begin transaction: %s\n",
456 argv[0], errno ? strerror(errno) : "");
457 goto cleanup;
458 }
459 }
460
461 if ((result = semanage_set_default_priority(sh, priority)) != 0) {
462 fprintf(stderr,
463 "%s: Invalid priority %d (needs to be between 1 and 999)\n",
464 argv[0],
465 priority);
466 goto cleanup;
467 }
468
469 for (i = 0; i < num_commands; i++) {
470 enum client_modes mode = commands[i].mode;
471 char *mode_arg = commands[i].arg;
472
473 switch (mode) {
474 case INSTALL_M:{
475 if (verbose) {
476 printf
477 ("Attempting to install module '%s':\n",
478 mode_arg);
479 }
480 result =
481 semanage_module_install_file(sh, mode_arg);
482 break;
483 }
484 case EXTRACT_M:{
485 semanage_module_info_t *extract_info = NULL;
486 semanage_module_key_t *modkey = NULL;
487 uint16_t curr_priority;
488 void *data = NULL;
489 size_t data_len = 0;
490 char output_path[PATH_MAX];
491 const char *output_name = NULL;
492 const char *lang_ext = NULL;
493 int rlen;
494 FILE *output_fd = NULL;
495
496 result = semanage_module_key_create(sh, &modkey);
497 if (result != 0) {
498 goto cleanup_extract;
499 }
500
501 result = semanage_module_key_set_name(sh, modkey, mode_arg);
502 if (result != 0) {
503 goto cleanup_extract;
504 }
505
506 if (priority_set == 0) {
507 result = semanage_module_get_module_info(sh, modkey, &extract_info);
508 if (result != 0) {
509 goto cleanup_extract;
510 }
511
512 semanage_module_info_get_priority(sh, extract_info, &curr_priority);
513 printf("Extracting at highest existing priority '%d'.\n", curr_priority);
514 priority = curr_priority;
515 }
516
517 result = semanage_module_key_set_priority(sh, modkey, priority);
518 if (result != 0) {
519 goto cleanup_extract;
520 }
521
522 if (verbose) {
523 printf
524 ("Attempting to extract module '%s':\n",
525 mode_arg);
526 }
527 result = semanage_module_extract(sh, modkey, extract_cil, &data, &data_len, &extract_info);
528 if (result != 0) {
529 goto cleanup_extract;
530 }
531
532 if (extract_cil) {
533 lang_ext = "cil";
534 } else {
535 result = semanage_module_info_get_lang_ext(sh, extract_info, &lang_ext);
536 if (result != 0) {
537 goto cleanup_extract;
538 }
539 }
540
541 result = semanage_module_info_get_name(sh, extract_info, &output_name);
542 if (result != 0) {
543 goto cleanup_extract;
544 }
545
546 rlen = snprintf(output_path, PATH_MAX, "%s.%s", output_name, lang_ext);
547 if (rlen < 0 || rlen >= PATH_MAX) {
548 fprintf(stderr, "%s: Failed to generate output path.\n", argv[0]);
549 result = -1;
550 goto cleanup_extract;
551 }
552
553 if (access(output_path, F_OK) == 0) {
554 fprintf(stderr, "%s: %s is already extracted with extension %s.\n", argv[0], mode_arg, lang_ext);
555 result = -1;
556 goto cleanup_extract;
557 }
558
559 output_fd = fopen(output_path, "w");
560 if (output_fd == NULL) {
561 fprintf(stderr, "%s: Unable to open %s\n", argv[0], output_path);
562 result = -1;
563 goto cleanup_extract;
564 }
565
566 if (fwrite(data, 1, data_len, output_fd) < data_len) {
567 fprintf(stderr, "%s: Unable to write to %s\n", argv[0], output_path);
568 result = -1;
569 goto cleanup_extract;
570 }
571 cleanup_extract:
572 if (output_fd != NULL) {
573 fclose(output_fd);
574 }
575 if (data_len > 0) {
576 munmap(data, data_len);
577 }
578 semanage_module_info_destroy(sh, extract_info);
579 free(extract_info);
580 semanage_module_key_destroy(sh, modkey);
581 free(modkey);
582 break;
583 }
584 case CIL_M:
585 extract_cil = 1;
586 break;
587 case HLL_M:
588 extract_cil = 0;
589 break;
590 case REMOVE_M:{
591 if (verbose) {
592 printf
593 ("Attempting to remove module '%s':\n",
594 mode_arg);
595 }
596 result = semanage_module_remove(sh, mode_arg);
597 if ( result == -2 ) {
598 continue;
599 }
600 break;
601 }
602 case LIST_M:{
603 semanage_module_info_t *modinfos = NULL;
604 int modinfos_len = 0;
605 semanage_module_info_t *m = NULL;
606 int j = 0;
607 char *module_checksum = NULL;
608 uint16_t pri = 0;
609
610 if (verbose) {
611 printf
612 ("Attempting to list active modules:\n");
613 }
614
615 if (mode_arg == NULL || strcmp(mode_arg, "standard") == 0) {
616 result = semanage_module_list(sh,
617 &modinfos,
618 &modinfos_len);
619 if (result < 0) goto cleanup_list;
620
621 if (modinfos_len == 0) {
622 printf("No modules.\n");
623 }
624
625 const char *name = NULL;
626
627 for (j = 0; j < modinfos_len; j++) {
628 m = semanage_module_list_nth(modinfos, j);
629
630 result = semanage_module_info_get_name(sh, m, &name);
631 if (result != 0) goto cleanup_list;
632
633 result = semanage_module_info_get_priority(sh, m, &pri);
634 if (result != 0) goto cleanup_list;
635
636 printf("%s", name);
637 if (checksum) {
638 module_checksum = hash_module_data(name, pri);
639 if (module_checksum) {
640 printf(" %s", module_checksum);
641 free(module_checksum);
642 }
643 }
644 printf("\n");
645 }
646 }
647 else if (strcmp(mode_arg, "full") == 0) {
648 /* get the modules */
649 result = semanage_module_list_all(sh,
650 &modinfos,
651 &modinfos_len);
652 if (result != 0) goto cleanup_list;
653
654 if (modinfos_len == 0) {
655 printf("No modules.\n");
656 }
657
658 /* calculate column widths */
659 size_t column[5] = { 0, 0, 0, 0, 0 };
660
661 /* fixed width columns */
662 column[0] = sizeof("000") - 1;
663 column[3] = sizeof("disabled") - 1;
664
665 result = semanage_module_compute_checksum(sh, NULL, 0, NULL,
666 &column[4]);
667 if (result != 0) goto cleanup_list;
668
669 /* variable width columns */
670 const char *tmp = NULL;
671 size_t size;
672 for (j = 0; j < modinfos_len; j++) {
673 m = semanage_module_list_nth(modinfos, j);
674
675 result = semanage_module_info_get_name(sh, m, &tmp);
676 if (result != 0) goto cleanup_list;
677
678 size = strlen(tmp);
679 if (size > column[1]) column[1] = size;
680
681 result = semanage_module_info_get_lang_ext(sh, m, &tmp);
682 if (result != 0) goto cleanup_list;
683
684 size = strlen(tmp);
685 if (size > column[2]) column[2] = size;
686 }
687
688 /* print out each module */
689 for (j = 0; j < modinfos_len; j++) {
690 const char *name = NULL;
691 int enabled = 0;
692 const char *lang_ext = NULL;
693
694 m = semanage_module_list_nth(modinfos, j);
695
696 result = semanage_module_info_get_priority(sh, m, &pri);
697 if (result != 0) goto cleanup_list;
698
699 result = semanage_module_info_get_name(sh, m, &name);
700 if (result != 0) goto cleanup_list;
701
702 result = semanage_module_info_get_enabled(sh, m, &enabled);
703 if (result != 0) goto cleanup_list;
704
705 result = semanage_module_info_get_lang_ext(sh, m, &lang_ext);
706 if (result != 0) goto cleanup_list;
707
708 printf("%0*u %-*s %-*s %-*s",
709 (int)column[0], pri,
710 (int)column[1], name,
711 (int)column[2], lang_ext,
712 (int)column[3], enabled ? "" : "disabled");
713 if (checksum) {
714 module_checksum = hash_module_data(name, pri);
715 if (module_checksum) {
716 printf(" %-*s", (int)column[4], module_checksum);
717 free(module_checksum);
718 }
719 }
720 printf("\n");
721
722 }
723 }
724 else {
725 result = -1;
726 }
727
728 cleanup_list:
729 for (j = 0; j < modinfos_len; j++) {
730 m = semanage_module_list_nth(modinfos, j);
731 semanage_module_info_destroy(sh, m);
732 }
733
734 free(modinfos);
735
736 break;
737 }
738 case PRIORITY_M:{
739 char *endptr = NULL;
740 priority = (uint16_t)strtoul(mode_arg, &endptr, 10);
741 priority_set = 1;
742
743 if ((result = semanage_set_default_priority(sh, priority)) != 0) {
744 fprintf(stderr,
745 "%s: Invalid priority %d (needs to be between 1 and 999)\n",
746 argv[0],
747 priority);
748 goto cleanup;
749 }
750
751 break;
752 }
753 case ENABLE_M:{
754 if (verbose) {
755 printf
756 ("Attempting to enable module '%s':\n",
757 mode_arg);
758 }
759
760 semanage_module_key_t *modkey = NULL;
761
762 result = semanage_module_key_create(sh, &modkey);
763 if (result != 0) goto cleanup_enable;
764
765 result = semanage_module_key_set_name(sh, modkey, mode_arg);
766 if (result != 0) goto cleanup_enable;
767
768 result = semanage_module_set_enabled(sh, modkey, 1);
769 if (result != 0) goto cleanup_enable;
770
771 cleanup_enable:
772 semanage_module_key_destroy(sh, modkey);
773 free(modkey);
774
775 break;
776 }
777 case DISABLE_M:{
778 if (verbose) {
779 printf
780 ("Attempting to disable module '%s':\n",
781 mode_arg);
782 }
783
784 semanage_module_key_t *modkey = NULL;
785
786 result = semanage_module_key_create(sh, &modkey);
787 if (result != 0) goto cleanup_disable;
788
789 result = semanage_module_key_set_name(sh, modkey, mode_arg);
790 if (result != 0) goto cleanup_disable;
791
792 result = semanage_module_set_enabled(sh, modkey, 0);
793 if (result != 0) goto cleanup_disable;
794
795 cleanup_disable:
796 semanage_module_key_destroy(sh, modkey);
797 free(modkey);
798
799 break;
800 }
801 default:{
802 fprintf(stderr,
803 "%s: Unknown mode specified.\n",
804 argv[0]);
805 usage(argv[0]);
806 goto cleanup;
807 }
808 }
809 commit += do_commit[mode];
810 if (result < 0) {
811 fprintf(stderr, "%s: Failed on %s!\n", argv[0],
812 mode_arg ? : "list");
813 goto cleanup;
814 } else if (verbose) {
815 printf("Ok: return value of %d.\n", result);
816 }
817 }
818
819 if (commit) {
820 if (verbose)
821 printf("Committing changes:\n");
822 if (no_reload)
823 semanage_set_reload(sh, 0);
824 if (build)
825 semanage_set_rebuild(sh, 1);
826 if (check_ext_changes)
827 semanage_set_check_ext_changes(sh, 1);
828 if (disable_dontaudit)
829 semanage_set_disable_dontaudit(sh, 1);
830 else if (build)
831 semanage_set_disable_dontaudit(sh, 0);
832 if (preserve_tunables)
833 semanage_set_preserve_tunables(sh, 1);
834 if (ignore_module_cache)
835 semanage_set_ignore_module_cache(sh, 1);
836
837 result = semanage_commit(sh);
838 }
839
840 if (result < 0) {
841 fprintf(stderr, "%s: Failed!\n", argv[0]);
842 goto cleanup;
843 } else if (commit && verbose) {
844 printf("Ok: transaction number %d.\n", result);
845 }
846
847 if (semanage_disconnect(sh) < 0) {
848 fprintf(stderr, "%s: Error disconnecting\n", argv[0]);
849 goto cleanup;
850 }
851 status = EXIT_SUCCESS;
852
853 cleanup:
854 if (semanage_is_connected(sh)) {
855 if (semanage_disconnect(sh) < 0) {
856 fprintf(stderr, "%s: Error disconnecting\n", argv[0]);
857 }
858 }
859 semanage_handle_destroy(sh);
860
861 cleanup_nohandle:
862 cleanup();
863 exit(status);
864 }
865