]> granicus.if.org Git - shadow/blob - lib/selinux.c
* src/usermod.c, man/usermod.8.xml: usermod -Z "" removes the
[shadow] / lib / selinux.c
1 /*
2  * Copyright (c) 2010       , Jakub Hrozek <jhrozek@redhat.com>
3  * Copyright (c) 2011       , Peter Vrabec <pvrabec@redhat.com>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  * 3. The name of the copyright holders or contributors may not be used to
15  *    endorse or promote products derived from this software without
16  *    specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
21  * PARTICULAR PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT
22  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29  */
30
31 #include <config.h>
32
33 #ifdef WITH_SELINUX
34
35 #include "defines.h"
36
37 #define _GNU_SOURCE
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <selinux/selinux.h>
41 #include <semanage/semanage.h>
42
43
44 #ifndef DEFAULT_SERANGE
45 #define DEFAULT_SERANGE "s0"
46 #endif
47
48
49 static void semanage_error_callback (void *varg,
50                                      semanage_handle_t *handle,
51                                      const char *fmt, ...)
52 {
53         int ret;
54         char * message = NULL;
55         va_list ap;
56
57
58         va_start (ap, fmt);
59         ret = vasprintf (&message, fmt, ap);
60         va_end (ap);
61         if (ret < 0) {
62                 /* ENOMEM */
63                 return;
64         }
65
66         switch (semanage_msg_get_level (handle)) {
67         case SEMANAGE_MSG_ERR:
68         case SEMANAGE_MSG_WARN:
69                 fprintf (stderr, _("[libsemanage]: %s\n"), message);
70                 break;
71         case SEMANAGE_MSG_INFO:
72                 /* nop */
73                 break;
74         }
75
76         free (message);
77 }
78
79
80 static semanage_handle_t *semanage_init (void)
81 {
82         int ret;
83         semanage_handle_t *handle = NULL;
84
85         handle = semanage_handle_create ();
86         if (NULL == handle) {
87                 fprintf (stderr,
88                          _("Cannot create SELinux management handle\n"));
89                 return NULL;
90         }
91
92         semanage_msg_set_callback (handle, semanage_error_callback, NULL);
93
94         ret = semanage_is_managed (handle);
95         if (ret != 1) {
96                 fprintf (stderr, _("SELinux policy not managed\n"));
97                 goto fail;
98         }
99
100         ret = semanage_access_check (handle);
101         if (ret < SEMANAGE_CAN_READ) {
102                 fprintf (stderr, _("Cannot read SELinux policy store\n"));
103                 goto fail;
104         }
105
106         ret = semanage_connect (handle);
107         if (ret != 0) {
108                 fprintf (stderr,
109                          _("Cannot establish SELinux management connection\n"));
110                 goto fail;
111         }
112
113         ret = semanage_begin_transaction (handle);
114         if (ret != 0) {
115                 fprintf (stderr, _("Cannot begin SELinux transaction\n"));
116                 goto fail;
117         }
118
119         return handle;
120
121 fail:
122         semanage_handle_destroy (handle);
123         return NULL;
124 }
125
126
127 static int semanage_user_mod (semanage_handle_t *handle,
128                               semanage_seuser_key_t *key,
129                               const char *login_name,
130                               const char *seuser_name)
131 {
132         int ret;
133         semanage_seuser_t *seuser = NULL;
134
135         semanage_seuser_query (handle, key, &seuser);
136         if (NULL == seuser) {
137                 fprintf (stderr,
138                          _("Could not query seuser for %s\n"), login_name);
139                 ret = 1;
140                 goto done;
141         }
142
143         ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
144         if (ret != 0) {
145                 fprintf (stderr,
146                          _("Could not set serange for %s\n"), login_name);
147                 ret = 1;
148                 goto done;
149         }
150
151         ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
152         if (ret != 0) {
153                 fprintf (stderr,
154                          _("Could not set sename for %s\n"),
155                          login_name);
156                 ret = 1;
157                 goto done;
158         }
159
160         ret = semanage_seuser_modify_local (handle, key, seuser);
161         if (ret != 0) {
162                 fprintf (stderr,
163                          _("Could not modify login mapping for %s\n"),
164                          login_name);
165                 ret = 1;
166                 goto done;
167         }
168
169         ret = 0;
170 done:
171         semanage_seuser_free (seuser);
172         return ret;
173 }
174
175
176 static int semanage_user_add (semanage_handle_t *handle,
177                              semanage_seuser_key_t *key,
178                              const char *login_name,
179                              const char *seuser_name)
180 {
181         int ret;
182         semanage_seuser_t *seuser = NULL;
183
184         ret = semanage_seuser_create (handle, &seuser);
185         if (ret != 0) {
186                 fprintf (stderr,
187                          _("Cannot create SELinux login mapping for %s\n"),
188                          login_name);
189                 ret = 1;
190                 goto done;
191         }
192
193         ret = semanage_seuser_set_name (handle, seuser, login_name);
194         if (ret != 0) {
195                 fprintf (stderr, _("Could not set name for %s\n"), login_name);
196                 ret = 1;
197                 goto done;
198         }
199
200         ret = semanage_seuser_set_mlsrange (handle, seuser, DEFAULT_SERANGE);
201         if (ret != 0) {
202                 fprintf (stderr,
203                          _("Could not set serange for %s\n"),
204                          login_name);
205                 ret = 1;
206                 goto done;
207         }
208
209         ret = semanage_seuser_set_sename (handle, seuser, seuser_name);
210         if (ret != 0) {
211                 fprintf (stderr,
212                          _("Could not set SELinux user for %s\n"),
213                          login_name);
214                 ret = 1;
215                 goto done;
216         }
217
218         ret = semanage_seuser_modify_local (handle, key, seuser);
219         if (ret != 0) {
220                 fprintf (stderr,
221                          _("Could not add login mapping for %s\n"),
222                          login_name);
223                 ret = 1;
224                 goto done;
225         }
226
227         ret = 0;
228 done:
229         semanage_seuser_free (seuser);
230         return ret;
231 }
232
233
234 int set_seuser (const char *login_name, const char *seuser_name)
235 {
236         semanage_handle_t *handle = NULL;
237         semanage_seuser_key_t *key = NULL;
238         int ret;
239         int seuser_exists = 0;
240
241         if (NULL == seuser_name) {
242                 /* don't care, just let system pick the defaults */
243                 return 0;
244         }
245
246         handle = semanage_init ();
247         if (NULL == handle) {
248                 fprintf (stderr, _("Cannot init SELinux management\n"));
249                 ret = 1;
250                 goto done;
251         }
252
253         ret = semanage_seuser_key_create (handle, login_name, &key);
254         if (ret != 0) {
255                 fprintf (stderr, _("Cannot create SELinux user key\n"));
256                 ret = 1;
257                 goto done;
258         }
259
260         ret = semanage_seuser_exists (handle, key, &seuser_exists);
261         if (ret < 0) {
262                 fprintf (stderr, _("Cannot verify the SELinux user\n"));
263                 ret = 1;
264                 goto done;
265         }
266
267         if (0 != seuser_exists) {
268                 ret = semanage_user_mod (handle, key, login_name, seuser_name);
269                 if (ret != 0) {
270                         fprintf (stderr,
271                                  _("Cannot modify SELinux user mapping\n"));
272                         ret = 1;
273                         goto done;
274                 }
275         } else {
276                 ret = semanage_user_add (handle, key, login_name, seuser_name);
277                 if (ret != 0) {
278                         fprintf (stderr,
279                                  _("Cannot add SELinux user mapping\n"));
280                         ret = 1;
281                         goto done;
282                 }
283         }
284
285         ret = semanage_commit (handle);
286         if (ret < 0) {
287                 fprintf (stderr, _("Cannot commit SELinux transaction\n"));
288                 ret = 1;
289                 goto done;
290         }
291
292         ret = 0;
293
294 done:
295         semanage_seuser_key_free (key);
296         semanage_handle_destroy (handle);
297         return ret;
298 }
299
300
301 int del_seuser (const char *login_name)
302 {
303         semanage_handle_t *handle = NULL;
304         semanage_seuser_key_t *key = NULL;
305         int ret;
306         int exists = 0;
307
308         handle = semanage_init ();
309         if (NULL == handle) {
310                 fprintf (stderr, _("Cannot init SELinux management\n"));
311                 ret = 1;
312                 goto done;
313         }
314
315         ret = semanage_seuser_key_create (handle, login_name, &key);
316         if (ret != 0) {
317                 fprintf (stderr, _("Cannot create SELinux user key\n"));
318                 ret = 1;
319                 goto done;
320         }
321
322         ret = semanage_seuser_exists (handle, key, &exists);
323         if (ret < 0) {
324                 fprintf (stderr, _("Cannot verify the SELinux user\n"));
325                 ret = 1;
326                 goto done;
327         }
328
329         if (0 == exists) {
330                 fprintf (stderr,
331                          _("Login mapping for %s is not defined, OK if default mapping was used\n"), 
332                          login_name);
333                 ret = 0;  /* probably default mapping */
334                 goto done;
335         }
336
337         ret = semanage_seuser_exists_local (handle, key, &exists);
338         if (ret < 0) {
339                 fprintf (stderr, _("Cannot verify the SELinux user\n"));
340                 ret = 1;
341                 goto done;
342         }
343
344         if (0 == exists) {
345                 fprintf (stderr,
346                          _("Login mapping for %s is defined in policy, cannot be deleted\n"), 
347                          login_name);
348                 ret = 0; /* Login mapping defined in policy can't be deleted */
349                 goto done;
350         }
351
352         ret = semanage_seuser_del_local (handle, key);
353         if (ret != 0) {
354                 fprintf (stderr,
355                          _("Could not delete login mapping for %s"),
356                          login_name);
357                 ret = 1;
358                 goto done;
359         }
360
361         ret = semanage_commit (handle);
362         if (ret < 0) {
363                 fprintf (stderr, _("Cannot commit SELinux transaction\n"));
364                 ret = 1;
365                 goto done;
366         }
367
368         ret = 0;
369 done:
370         semanage_handle_destroy (handle);
371         return ret;
372 }
373 #else                           /* !WITH_SELINUX */
374 extern int errno;               /* warning: ANSI C forbids an empty source file */
375 #endif                          /* !WITH_SELINUX */