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