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