Home | History | Annotate | Download | only in setsebool
      1 #include <unistd.h>
      2 #include <stdlib.h>
      3 #include <stdio.h>
      4 #include <string.h>
      5 #include <sys/stat.h>
      6 #include <fcntl.h>
      7 #include <errno.h>
      8 #include <syslog.h>
      9 #include <getopt.h>
     10 #include <pwd.h>
     11 #include <selinux/selinux.h>
     12 #include <semanage/handle.h>
     13 #include <semanage/debug.h>
     14 #include <semanage/booleans_policy.h>
     15 #include <semanage/booleans_local.h>
     16 #include <semanage/booleans_active.h>
     17 #include <semanage/boolean_record.h>
     18 #include <errno.h>
     19 
     20 int permanent = 0;
     21 int reload = 1;
     22 int verbose = 0;
     23 
     24 int setbool(char **list, size_t start, size_t end);
     25 
     26 static __attribute__((__noreturn__)) void usage(void)
     27 {
     28 	fputs
     29 	    ("\nUsage:  setsebool [ -NPV ] boolean value | bool1=val1 bool2=val2...\n\n",
     30 	     stderr);
     31 	exit(1);
     32 }
     33 
     34 int main(int argc, char **argv)
     35 {
     36 	size_t rc;
     37 	int clflag;		/* holds codes for command line flags */
     38 	if (argc < 2)
     39 		usage();
     40 
     41 	if (is_selinux_enabled() <= 0) {
     42 		fputs("setsebool:  SELinux is disabled.\n", stderr);
     43 		return 1;
     44 	}
     45 
     46 	while (1) {
     47 		clflag = getopt(argc, argv, "PNV");
     48 		if (clflag == -1)
     49 			break;
     50 
     51 		switch (clflag) {
     52 		case 'P':
     53 			permanent = 1;
     54 			break;
     55 		case 'N':
     56 			reload = 0;
     57 			break;
     58 		case 'V':
     59 			verbose = 1;
     60 			break;
     61 		default:
     62 			usage();
     63 			break;
     64 		}
     65 	}
     66 
     67 	if (argc - optind < 1) {
     68 		fprintf(stderr, "Error: boolean name required\n");
     69 		usage();
     70 	}
     71 
     72 	/* Check to see which way we are being called. If a '=' is passed,
     73 	   we'll enforce the list syntax. If not we'll enforce the original
     74 	   syntax for backward compatibility. */
     75 	if (strchr(argv[optind], '=') == 0) {
     76 		int len;
     77 		char *bool_list[1];
     78 
     79 		if ((argc - optind) != 2)
     80 			usage();
     81 
     82 		/* Add 1 for the '=' */
     83 		len = strlen(argv[optind]) + strlen(argv[optind + 1]) + 2;
     84 		bool_list[0] = (char *)malloc(len);
     85 		if (bool_list[0] == 0) {
     86 			fputs("Out of memory - aborting\n", stderr);
     87 			return 1;
     88 		}
     89 		snprintf(bool_list[0], len, "%s=%s", argv[optind],
     90 			 argv[optind + 1]);
     91 		rc = setbool(bool_list, 0, 1);
     92 		free(bool_list[0]);
     93 	} else
     94 		rc = setbool(argv, optind, argc);
     95 
     96 	return rc;
     97 }
     98 
     99 /* Apply temporal boolean changes to policy via libselinux */
    100 static int selinux_set_boolean_list(size_t boolcnt,
    101 				    SELboolean * boollist)
    102 {
    103 
    104 	if (security_set_boolean_list(boolcnt, boollist, 0)) {
    105 		if (errno == ENOENT)
    106 			fprintf(stderr, "Could not change active booleans: "
    107 				"Invalid boolean\n");
    108 		else if (errno) {
    109 			if (getuid() == 0) {
    110 				perror("Could not change active booleans");
    111 			} else {
    112 				perror("Could not change active booleans. Please try as root");
    113 			}
    114 		}
    115 
    116 		return -1;
    117 	}
    118 
    119 	return 0;
    120 }
    121 
    122 /* Apply permanent boolean changes to policy via libsemanage */
    123 static int semanage_set_boolean_list(size_t boolcnt,
    124 				     SELboolean * boollist)
    125 {
    126 
    127 	size_t j;
    128 	semanage_handle_t *handle = NULL;
    129 	semanage_bool_t *boolean = NULL;
    130 	semanage_bool_key_t *bool_key = NULL;
    131 	int managed;
    132 	int result;
    133 
    134 	handle = semanage_handle_create();
    135 	if (handle == NULL) {
    136 		fprintf(stderr, "Could not create semanage library handle\n");
    137 		goto err;
    138 	}
    139 
    140 	if (! verbose) {
    141 		semanage_msg_set_callback(handle,NULL, NULL);
    142 	}
    143 
    144 	managed = semanage_is_managed(handle);
    145 	if (managed < 0) {
    146 		fprintf(stderr,
    147 			"Error when checking whether policy is managed\n");
    148 		goto err;
    149 
    150 	} else if (managed == 0) {
    151 		if (getuid() == 0) {
    152 			fprintf(stderr,
    153 				"Cannot set persistent booleans without managed policy.\n");
    154 		} else {
    155 			fprintf(stderr,
    156 				"Cannot set persistent booleans, please try as root.\n");
    157 		}
    158 		goto err;
    159 	}
    160 
    161 	if (semanage_connect(handle) < 0)
    162 		goto err;
    163 
    164 	if (semanage_begin_transaction(handle) < 0)
    165 		goto err;
    166 
    167 	for (j = 0; j < boolcnt; j++) {
    168 
    169 		if (semanage_bool_create(handle, &boolean) < 0)
    170 			goto err;
    171 
    172 		if (semanage_bool_set_name(handle, boolean, boollist[j].name) <
    173 		    0)
    174 			goto err;
    175 
    176 		semanage_bool_set_value(boolean, boollist[j].value);
    177 
    178 		if (semanage_bool_key_extract(handle, boolean, &bool_key) < 0)
    179 			goto err;
    180 
    181 		semanage_bool_exists(handle, bool_key, &result);
    182 		if ( !result ) {
    183 			semanage_bool_exists_local(handle, bool_key, &result);
    184 			if ( !result ) {
    185 				fprintf(stderr, "Boolean %s is not defined\n", boollist[j].name);
    186 				goto err;
    187 			}
    188 		}
    189 
    190 		if (semanage_bool_modify_local(handle, bool_key,
    191 						  boolean) < 0)
    192 			goto err;
    193 
    194 		if (semanage_bool_set_active(handle, bool_key, boolean) < 0) {
    195 			fprintf(stderr, "Failed to change boolean %s: %m\n",
    196 				boollist[j].name);
    197 			goto err;
    198 		}
    199 		semanage_bool_key_free(bool_key);
    200 		semanage_bool_free(boolean);
    201 		bool_key = NULL;
    202 		boolean = NULL;
    203 	}
    204 
    205 	semanage_set_reload(handle, reload);
    206 	if (semanage_commit(handle) < 0)
    207 		goto err;
    208 
    209 	semanage_disconnect(handle);
    210 	semanage_handle_destroy(handle);
    211 	return 0;
    212 
    213       err:
    214 	semanage_bool_key_free(bool_key);
    215 	semanage_bool_free(boolean);
    216 	semanage_handle_destroy(handle);
    217 	return -1;
    218 }
    219 
    220 /* Given an array of strings in the form "boolname=value", a start index,
    221    and a finish index...walk the list and set the bool. */
    222 int setbool(char **list, size_t start, size_t end)
    223 {
    224 	char *name, *value_ptr;
    225 	int j = 0, value;
    226 	size_t i = start;
    227 	size_t boolcnt = end - start;
    228 	struct passwd *pwd;
    229 	SELboolean *vallist = calloc(boolcnt, sizeof(SELboolean));
    230 	if (!vallist)
    231 		goto omem;
    232 
    233 	while (i < end) {
    234 		name = list[i];
    235 		value_ptr = strchr(list[i], '=');
    236 		if (value_ptr == 0) {
    237 			fprintf(stderr,
    238 				"setsebool: '=' not found in boolean expression %s\n",
    239 				list[i]);
    240 			goto err;
    241 		}
    242 		*value_ptr = 0;
    243 		value_ptr++;
    244 		if (strcmp(value_ptr, "1") == 0 ||
    245 		    strcasecmp(value_ptr, "true") == 0 ||
    246 		    strcasecmp(value_ptr, "on") == 0)
    247 			value = 1;
    248 		else if (strcmp(value_ptr, "0") == 0 ||
    249 			 strcasecmp(value_ptr, "false") == 0 ||
    250 			 strcasecmp(value_ptr, "off") == 0)
    251 			value = 0;
    252 		else {
    253 			fprintf(stderr, "setsebool: illegal value "
    254 				"%s for boolean %s\n", value_ptr, name);
    255 			goto err;
    256 		}
    257 
    258 		vallist[j].value = value;
    259 		vallist[j].name = strdup(name);
    260 		if (!vallist[j].name)
    261 			goto omem;
    262 		i++;
    263 		j++;
    264 
    265 		/* Now put it back */
    266 		value_ptr--;
    267 		*value_ptr = '=';
    268 	}
    269 
    270 	if (permanent) {
    271 		if (semanage_set_boolean_list(boolcnt, vallist) < 0)
    272 			goto err;
    273 	} else {
    274 		if (selinux_set_boolean_list(boolcnt, vallist) < 0)
    275 			goto err;
    276 	}
    277 
    278 	/* Now log what was done */
    279 	pwd = getpwuid(getuid());
    280 	i = start;
    281 	while (i < end) {
    282 		name = list[i];
    283 		value_ptr = strchr(name, '=');
    284 		*value_ptr = 0;
    285 		value_ptr++;
    286 		if (pwd && pwd->pw_name)
    287 			syslog(LOG_NOTICE,
    288 			       "The %s policy boolean was changed to %s by %s",
    289 			       name, value_ptr, pwd->pw_name);
    290 		else
    291 			syslog(LOG_NOTICE,
    292 			       "The %s policy boolean was changed to %s by uid:%d",
    293 			       name, value_ptr, getuid());
    294 		i++;
    295 	}
    296 
    297 	for (i = 0; i < boolcnt; i++)
    298 		free(vallist[i].name);
    299 	free(vallist);
    300 	return 0;
    301 
    302       omem:
    303 	fprintf(stderr, "setsebool: out of memory");
    304 
    305       err:
    306 	if (vallist) {
    307 		for (i = 0; i < boolcnt; i++)
    308 			free(vallist[i].name);
    309 		free(vallist);
    310 	}
    311 	return -1;
    312 }
    313