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