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