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