1 /*
2 SSSD
3
4 selinux.c
5
6 Copyright (C) Jakub Hrozek <jhrozek@redhat.com> 2010
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 3 of the License, or
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20 */
21
22 #include "config.h"
23
24 #define _GNU_SOURCE
25 #include <stdio.h>
26
27 #ifdef HAVE_SELINUX
28 #include <selinux/selinux.h>
29 #endif
30
31 #ifdef HAVE_SEMANAGE
32 #include <semanage/semanage.h>
33 #endif
34
35 #include "util/util.h"
36
37 #ifndef DEFAULT_SERANGE
38 #define DEFAULT_SERANGE "s0"
39 #endif
40
41 #ifdef HAVE_SELINUX
42 /*
43 * selinux_file_context - Set the security context before any file or
44 * directory creation.
45 *
46 * selinux_file_context () should be called before any creation of file,
47 * symlink, directory, ...
48 *
49 * Callers may have to Reset SELinux to create files with default
50 * contexts:
51 * reset_selinux_file_context();
52 */
53 int selinux_file_context(const char *dst_name)
54 {
55 security_context_t scontext = NULL;
56
57 if (is_selinux_enabled() == 1) {
58 /* Get the default security context for this file */
59 if (matchpathcon(dst_name, 0, &scontext) < 0) {
60 if (security_getenforce () != 0) {
61 return 1;
62 }
63 }
64 /* Set the security context for the next created file */
65 if (setfscreatecon(scontext) < 0) {
66 if (security_getenforce() != 0) {
67 return 1;
68 }
69 }
70 freecon(scontext);
71 }
72
73 return 0;
74 }
75
76 int reset_selinux_file_context(void)
77 {
78 setfscreatecon(NULL);
79 return EOK;
80 }
81
82 #else /* HAVE_SELINUX */
83 int selinux_file_context(const char *dst_name)
84 {
85 return EOK;
86 }
87
88 int reset_selinux_file_context(void)
89 {
90 return EOK;
91 }
92 #endif /* HAVE_SELINUX */
93
94 #ifdef HAVE_SEMANAGE
95 /* turn libselinux messages into SSSD DEBUG() calls */
96 static void sss_semanage_error_callback(void *varg,
97 semanage_handle_t *handle,
98 const char *fmt, ...)
99 {
100 int level = -1;
101 int ret;
102 char * message = NULL;
103 va_list ap;
104
105 switch (semanage_msg_get_level(handle)) {
106 case SEMANAGE_MSG_ERR:
107 level = 1;
108 break;
109 case SEMANAGE_MSG_WARN:
110 level = 4;
111 break;
112 case SEMANAGE_MSG_INFO:
113 level = 6;
114 break;
115 }
116
Event va_init: Initializing va_list "ap".
Also see events: [missing_va_end] | |
117 va_start(ap, fmt);
118 ret = vasprintf(&message, fmt, ap);
At conditional (1): "ret < 0": Taking true branch.
|
119 if (ret < 0) {
120 /* ENOMEM */
Event missing_va_end: va_end was not called for "ap".
Also see events: [va_init] | |
121 return;
122 }
123 va_end(ap);
124
125 if (level <= debug_level) {
126 if (debug_timestamps) {
127 time_t rightnow = time(NULL);
128 char stamp[25];
129 memcpy(stamp, ctime(&rightnow), 24);
130 stamp[24] = '\0';
131 debug_fn("(%s) [%s] [libsemanage] (%d): %s\n",
132 stamp, debug_prg_name, level, message);
133 } else {
134 debug_fn("[%s] [libsemanage] (%d): %s\n",
135 debug_prg_name, level, message);
136 }
137 }
138 free(message);
139 }
140
141 static semanage_handle_t *sss_semanage_init(void)
142 {
143 int ret;
144 semanage_handle_t *handle = NULL;
145
146 handle = semanage_handle_create();
147 if (!handle) {
148 DEBUG(1, ("Cannot create SELinux management handle\n"));
149 return NULL;
150 }
151
152 semanage_msg_set_callback(handle,
153 sss_semanage_error_callback,
154 NULL);
155
156 ret = semanage_is_managed(handle);
157 if (ret != 1) {
158 DEBUG(1, ("SELinux policy not managed\n"));
159 goto fail;
160 }
161
162 ret = semanage_access_check(handle);
163 if (ret < SEMANAGE_CAN_READ) {
164 DEBUG(1, ("Cannot read SELinux policy store\n"));
165 goto fail;
166 }
167
168 ret = semanage_connect(handle);
169 if (ret != 0) {
170 DEBUG(1, ("Cannot estabilish SELinux management connection\n"));
171 goto fail;
172 }
173
174 ret = semanage_begin_transaction(handle);
175 if (ret != 0) {
176 DEBUG(1, ("Cannot begin SELinux transaction\n"));
177 goto fail;
178 }
179
180 return handle;
181 fail:
182 semanage_handle_destroy(handle);
183 return NULL;
184 }
185
186 static int sss_semanage_user_add(semanage_handle_t *handle,
187 semanage_seuser_key_t *key,
188 const char *login_name,
189 const char *seuser_name)
190 {
191 int ret;
192 semanage_seuser_t *seuser = NULL;
193
194 ret = semanage_seuser_create(handle, &seuser);
195 if (ret != 0) {
196 DEBUG(1, ("Cannot create SELinux login mapping for %s\n", login_name));
197 ret = EIO;
198 goto done;
199 }
200
201 ret = semanage_seuser_set_name(handle, seuser, login_name);
202 if (ret != 0) {
203 DEBUG(1, ("Could not set name for %s\n", login_name));
204 ret = EIO;
205 goto done;
206 }
207
208 ret = semanage_seuser_set_mlsrange(handle, seuser, DEFAULT_SERANGE);
209 if (ret != 0) {
210 DEBUG(1, ("Could not set serange for %s\n", login_name));
211 ret = EIO;
212 goto done;
213 }
214
215 ret = semanage_seuser_set_sename(handle, seuser, seuser_name);
216 if (ret != 0) {
217 DEBUG(1, ("Could not set SELinux user for %s\n", login_name));
218 ret = EIO;
219 goto done;
220 }
221
222 ret = semanage_seuser_modify_local(handle, key, seuser);
223 if (ret != 0) {
224 DEBUG(1, ("Could not add login mapping for %s\n", login_name));
225 ret = EIO;
226 goto done;
227 }
228
229 ret = EOK;
230 done:
231 semanage_seuser_free(seuser);
232 return ret;
233 }
234
235 static int sss_semanage_user_mod(semanage_handle_t *handle,
236 semanage_seuser_key_t *key,
237 const char *login_name,
238 const char *seuser_name)
239 {
240 int ret;
241 semanage_seuser_t *seuser = NULL;
242
243 semanage_seuser_query(handle, key, &seuser);
244 if (seuser == NULL) {
245 DEBUG(1, ("Could not query seuser for %s\n", login_name));
246 ret = EIO;
247 goto done;
248 }
249
250 ret = semanage_seuser_set_mlsrange(handle, seuser, DEFAULT_SERANGE);
251 if (ret != 0) {
252 DEBUG(1, ("Could not set serange for %s\n", login_name));
253 ret = EIO;
254 goto done;
255 }
256
257 ret = semanage_seuser_set_sename(handle, seuser, seuser_name);
258 if (ret != 0) {
259 DEBUG(1, ("Could not set sename for %s\n", login_name));
260 ret = EIO;
261 goto done;
262 }
263
264 ret = semanage_seuser_modify_local(handle, key, seuser);
265 if (ret != 0) {
266 DEBUG(1, (("Could not modify login mapping for %s\n"), login_name));
267 ret = EIO;
268 goto done;
269 }
270
271 ret = EOK;
272 done:
273 semanage_seuser_free(seuser);
274 return ret;
275 }
276
277 int set_seuser(const char *login_name, const char *seuser_name)
278 {
279 semanage_handle_t *handle = NULL;
280 semanage_seuser_key_t *key = NULL;
281 int ret;
282 int seuser_exists = 0;
283
284 if (seuser_name == NULL) {
285 /* don't care, just let system pick the defaults */
286 return EOK;
287 }
288
289 handle = sss_semanage_init();
290 if (!handle) {
291 DEBUG(1, ("Cannot init SELinux management\n"));
292 ret = EIO;
293 goto done;
294 }
295
296 ret = semanage_seuser_key_create(handle, login_name, &key);
297 if (ret != 0) {
298 DEBUG(1, ("Cannot create SELinux user key\n"));
299 ret = EIO;
300 goto done;
301 }
302
303 ret = semanage_seuser_exists(handle, key, &seuser_exists);
304 if (ret < 0) {
305 DEBUG(1, ("Cannot verify the SELinux user\n"));
306 ret = EIO;
307 goto done;
308 }
309
310 if (seuser_exists) {
311 ret = sss_semanage_user_mod(handle, key, login_name, seuser_name);
312 if (ret != 0) {
313 DEBUG(1, ("Cannot modify SELinux user mapping\n"));
314 ret = EIO;
315 goto done;
316 }
317 } else {
318 ret = sss_semanage_user_add(handle, key, login_name, seuser_name);
319 if (ret != 0) {
320 DEBUG(1, ("Cannot add SELinux user mapping\n"));
321 ret = EIO;
322 goto done;
323 }
324 }
325
326 ret = semanage_commit(handle);
327 if (ret != 0) {
328 DEBUG(1, ("Cannot commit SELinux transaction\n"));
329 ret = EIO;
330 goto done;
331 }
332
333 ret = EOK;
334 done:
335 semanage_seuser_key_free(key);
336 semanage_handle_destroy(handle);
337 return ret;
338 }
339
340 int del_seuser(const char *login_name)
341 {
342 semanage_handle_t *handle = NULL;
343 semanage_seuser_key_t *key = NULL;
344 int ret;
345 int exists = 0;
346
347 handle = sss_semanage_init();
348 if (!handle) {
349 DEBUG(1, ("Cannot init SELinux management\n"));
350 ret = EIO;
351 goto done;
352 }
353
354 ret = semanage_seuser_key_create(handle, login_name, &key);
355 if (ret != 0) {
356 DEBUG(1, ("Cannot create SELinux user key\n"));
357 ret = EIO;
358 goto done;
359 }
360
361 ret = semanage_seuser_exists(handle, key, &exists);
362 if (ret < 0) {
363 DEBUG(1, ("Cannot verify the SELinux user\n"));
364 ret = EIO;
365 goto done;
366 }
367
368 if (!exists) {
369 DEBUG(5, ("Login mapping for %s is not defined, OK if default mapping "
370 "was used\n", login_name));
371 ret = EOK; /* probably default mapping */
372 goto done;
373 }
374
375 ret = semanage_seuser_exists_local(handle, key, &exists);
376 if (ret < 0) {
377 DEBUG(1, ("Cannot verify the SELinux user\n"));
378 ret = EIO;
379 goto done;
380 }
381
382 if (!exists) {
383 DEBUG(1, ("Login mapping for %s is defined in policy, "
384 "cannot be deleted", login_name));
385 ret = ENOENT;
386 goto done;
387 }
388
389 ret = semanage_seuser_del_local(handle, key);
390 if (ret != 0) {
391 DEBUG(1, ("Could not delete login mapping for %s", login_name));
392 ret = EIO;
393 goto done;
394 }
395
396 ret = semanage_commit(handle);
397 if (ret != 0) {
398 DEBUG(1, ("Cannot commit SELinux transaction\n"));
399 ret = EIO;
400 goto done;
401 }
402
403 ret = EOK;
404 done:
405 semanage_handle_destroy(handle);
406 return ret;
407 }
408
409 #else /* HAVE_SEMANAGE */
410 int set_seuser(const char *login_name, const char *seuser_name)
411 {
412 return EOK;
413 }
414
415 int del_seuser(const char *login_name)
416 {
417 return EOK;
418 }
419 #endif /* HAVE_SEMANAGE */