16cd6a6acSopenharmony_ci#include <unistd.h>
26cd6a6acSopenharmony_ci#include <stdio.h>
36cd6a6acSopenharmony_ci#include <stdlib.h>
46cd6a6acSopenharmony_ci#include <libgen.h>
56cd6a6acSopenharmony_ci#include <errno.h>
66cd6a6acSopenharmony_ci#include <selinux/selinux.h>
76cd6a6acSopenharmony_ci#include <syslog.h>
86cd6a6acSopenharmony_ci#include <pwd.h>
96cd6a6acSopenharmony_ci#include <string.h>
106cd6a6acSopenharmony_ci
116cd6a6acSopenharmony_ci/* Attempt to rollback the transaction. No need to check error
126cd6a6acSopenharmony_ci   codes since this is rolling back something that blew up. */
136cd6a6acSopenharmony_cistatic __attribute__ ((__noreturn__)) void rollback(int argc, char **argv)
146cd6a6acSopenharmony_ci{
156cd6a6acSopenharmony_ci	int i;
166cd6a6acSopenharmony_ci
176cd6a6acSopenharmony_ci	for (i = 1; i < argc; i++)
186cd6a6acSopenharmony_ci		security_set_boolean(argv[i],
196cd6a6acSopenharmony_ci				     security_get_boolean_active(argv[i]));
206cd6a6acSopenharmony_ci	exit(1);
216cd6a6acSopenharmony_ci}
226cd6a6acSopenharmony_ci
236cd6a6acSopenharmony_ciint main(int argc, char **argv)
246cd6a6acSopenharmony_ci{
256cd6a6acSopenharmony_ci
266cd6a6acSopenharmony_ci	int rc, i, commit = 0;
276cd6a6acSopenharmony_ci
286cd6a6acSopenharmony_ci	if (is_selinux_enabled() <= 0) {
296cd6a6acSopenharmony_ci		fprintf(stderr, "%s:  SELinux is disabled\n", argv[0]);
306cd6a6acSopenharmony_ci		return 1;
316cd6a6acSopenharmony_ci	}
326cd6a6acSopenharmony_ci
336cd6a6acSopenharmony_ci	if (argc < 2) {
346cd6a6acSopenharmony_ci		printf("Usage:  %s boolname1 [boolname2 ...]\n",
356cd6a6acSopenharmony_ci		       basename(argv[0]));
366cd6a6acSopenharmony_ci		return 1;
376cd6a6acSopenharmony_ci	}
386cd6a6acSopenharmony_ci
396cd6a6acSopenharmony_ci	for (i = 1; i < argc; i++) {
406cd6a6acSopenharmony_ci		printf("%s: ", argv[i]);
416cd6a6acSopenharmony_ci		rc = security_get_boolean_active(argv[i]);
426cd6a6acSopenharmony_ci		switch (rc) {
436cd6a6acSopenharmony_ci		case 1:
446cd6a6acSopenharmony_ci			if (security_set_boolean(argv[i], 0) >= 0) {
456cd6a6acSopenharmony_ci				printf("inactive\n");
466cd6a6acSopenharmony_ci				commit++;
476cd6a6acSopenharmony_ci			} else {
486cd6a6acSopenharmony_ci				printf("%s - rolling back all changes\n",
496cd6a6acSopenharmony_ci				       strerror(errno));
506cd6a6acSopenharmony_ci				rollback(i, argv);
516cd6a6acSopenharmony_ci			}
526cd6a6acSopenharmony_ci			break;
536cd6a6acSopenharmony_ci		case 0:
546cd6a6acSopenharmony_ci			if (security_set_boolean(argv[i], 1) >= 0) {
556cd6a6acSopenharmony_ci				printf("active\n");
566cd6a6acSopenharmony_ci				commit++;
576cd6a6acSopenharmony_ci			} else {
586cd6a6acSopenharmony_ci				printf("%s - rolling back all changes\n",
596cd6a6acSopenharmony_ci				       strerror(errno));
606cd6a6acSopenharmony_ci				rollback(i, argv);
616cd6a6acSopenharmony_ci			}
626cd6a6acSopenharmony_ci			break;
636cd6a6acSopenharmony_ci		default:
646cd6a6acSopenharmony_ci			if (errno == ENOENT)
656cd6a6acSopenharmony_ci				printf
666cd6a6acSopenharmony_ci				    ("Boolean does not exist - rolling back all changes.\n");
676cd6a6acSopenharmony_ci			else
686cd6a6acSopenharmony_ci				printf("%s - rolling back all changes.\n",
696cd6a6acSopenharmony_ci				       strerror(errno));
706cd6a6acSopenharmony_ci			rollback(i, argv);
716cd6a6acSopenharmony_ci			break;	/* Not reached. */
726cd6a6acSopenharmony_ci		}
736cd6a6acSopenharmony_ci	}
746cd6a6acSopenharmony_ci
756cd6a6acSopenharmony_ci	if (commit > 0) {
766cd6a6acSopenharmony_ci		if (security_commit_booleans() < 0) {
776cd6a6acSopenharmony_ci			printf("Commit failed. (%s)  No change to booleans.\n",
786cd6a6acSopenharmony_ci			       strerror(errno));
796cd6a6acSopenharmony_ci		} else {
806cd6a6acSopenharmony_ci			/* syslog all the changes */
816cd6a6acSopenharmony_ci			struct passwd *pwd = getpwuid(getuid());
826cd6a6acSopenharmony_ci			for (i = 1; i < argc; i++) {
836cd6a6acSopenharmony_ci				if (pwd && pwd->pw_name)
846cd6a6acSopenharmony_ci					syslog(LOG_NOTICE,
856cd6a6acSopenharmony_ci					       "The %s policy boolean was toggled by %s",
866cd6a6acSopenharmony_ci					       argv[i], pwd->pw_name);
876cd6a6acSopenharmony_ci				else
886cd6a6acSopenharmony_ci					syslog(LOG_NOTICE,
896cd6a6acSopenharmony_ci					       "The %s policy boolean was toggled by uid:%u",
906cd6a6acSopenharmony_ci					       argv[i], getuid());
916cd6a6acSopenharmony_ci
926cd6a6acSopenharmony_ci			}
936cd6a6acSopenharmony_ci			return 0;
946cd6a6acSopenharmony_ci		}
956cd6a6acSopenharmony_ci	}
966cd6a6acSopenharmony_ci	return 1;
976cd6a6acSopenharmony_ci}
98