1 /* Copyright (C) 2005 Red Hat, Inc. */
2
3 struct semanage_seuser;
4 struct semanage_seuser_key;
5 typedef struct semanage_seuser_key record_key_t;
6 typedef struct semanage_seuser record_t;
7 #define DBASE_RECORD_DEFINED
8
9 #include <sepol/policydb.h>
10 #include <sepol/context.h>
11 #include <libaudit.h>
12 #include <errno.h>
13 #include "user_internal.h"
14 #include "seuser_internal.h"
15 #include "handle.h"
16 #include "database.h"
17 #include "debug.h"
18 #include "string.h"
19 #include <stdlib.h>
20
semanage_user_roles(semanage_handle_t * handle,const char * sename)21 static char *semanage_user_roles(semanage_handle_t * handle, const char *sename) {
22 char *roles = NULL;
23 unsigned int num_roles;
24 size_t i;
25 size_t size = 0;
26 const char **roles_arr;
27 semanage_user_key_t *key = NULL;
28 semanage_user_t * user;
29 if (semanage_user_key_create(handle, sename, &key) >= 0) {
30 if (semanage_user_query(handle, key, &user) >= 0) {
31 if (semanage_user_get_roles(handle,
32 user,
33 &roles_arr,
34 &num_roles) >= 0) {
35 for (i = 0; i<num_roles; i++) {
36 size += (strlen(roles_arr[i]) + 1);
37 }
38 roles = malloc(size);
39 if (roles) {
40 strcpy(roles,roles_arr[0]);
41 for (i = 1; i<num_roles; i++) {
42 strcat(roles,",");
43 strcat(roles,roles_arr[i]);
44 }
45 }
46 }
47 semanage_user_free(user);
48 }
49 semanage_user_key_free(key);
50 }
51 return roles;
52 }
53
semanage_seuser_audit(semanage_handle_t * handle,const semanage_seuser_t * seuser,const semanage_seuser_t * previous,int audit_type,int success)54 static int semanage_seuser_audit(semanage_handle_t * handle,
55 const semanage_seuser_t * seuser,
56 const semanage_seuser_t * previous,
57 int audit_type,
58 int success) {
59 const char *name = NULL;
60 const char *sename = NULL;
61 char *roles = NULL;
62 const char *mls = NULL;
63 const char *psename = NULL;
64 const char *pmls = NULL;
65 char *proles = NULL;
66 char msg[1024];
67 const char *sep = "-";
68 int rc = -1;
69 strcpy(msg, "login");
70 if (seuser) {
71 name = semanage_seuser_get_name(seuser);
72 sename = semanage_seuser_get_sename(seuser);
73 mls = semanage_seuser_get_mlsrange(seuser);
74 roles = semanage_user_roles(handle, sename);
75 }
76 if (previous) {
77 psename = semanage_seuser_get_sename(previous);
78 pmls = semanage_seuser_get_mlsrange(previous);
79 proles = semanage_user_roles(handle, psename);
80 }
81 if (audit_type != AUDIT_ROLE_REMOVE) {
82 if (sename && (!psename || strcmp(psename, sename) != 0)) {
83 strcat(msg,sep);
84 strcat(msg,"sename");
85 sep = ",";
86 }
87 if (roles && (!proles || strcmp(proles, roles) != 0)) {
88 strcat(msg,sep);
89 strcat(msg,"role");
90 sep = ",";
91 }
92 if (mls && (!pmls || strcmp(pmls, mls) != 0)) {
93 strcat(msg,sep);
94 strcat(msg,"range");
95 }
96 }
97
98 int fd = audit_open();
99 if (fd < 0)
100 {
101 /* If kernel doesn't support audit, bail out */
102 if (errno == EINVAL || errno == EPROTONOSUPPORT || errno == EAFNOSUPPORT) {
103 rc = 0;
104 goto err;
105 }
106 rc = fd;
107 goto err;
108 }
109 audit_log_semanage_message(fd, audit_type, NULL, msg, name, 0, sename, roles, mls, psename, proles, pmls, NULL, NULL,NULL, success);
110 rc = 0;
111 err:
112 audit_close(fd);
113 free(roles);
114 free(proles);
115 return rc;
116 }
117
semanage_seuser_modify_local(semanage_handle_t * handle,const semanage_seuser_key_t * key,const semanage_seuser_t * data)118 int semanage_seuser_modify_local(semanage_handle_t * handle,
119 const semanage_seuser_key_t * key,
120 const semanage_seuser_t * data)
121 {
122 int rc;
123 void *callback = (void *) handle->msg_callback;
124 dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
125 const char *sename = semanage_seuser_get_sename(data);
126 const char *mls_range = semanage_seuser_get_mlsrange(data);
127 semanage_seuser_t *previous = NULL;
128 semanage_seuser_t *new = NULL;
129
130 if (!sename) {
131 errno=EINVAL;
132 return -1;
133 }
134 rc = semanage_seuser_clone(handle, data, &new);
135 if (rc < 0) {
136 goto err;
137 }
138
139 if (!mls_range && semanage_mls_enabled(handle)) {
140 semanage_user_key_t *ukey = NULL;
141 semanage_user_t *u = NULL;
142 rc = semanage_user_key_create(handle, sename, &ukey);
143 if (rc < 0)
144 goto err;
145
146 rc = semanage_user_query(handle, ukey, &u);
147 semanage_user_key_free(ukey);
148 if (rc >= 0 ) {
149 mls_range = semanage_user_get_mlsrange(u);
150 rc = semanage_seuser_set_mlsrange(handle, new, mls_range);
151 semanage_user_free(u);
152 }
153 if (rc < 0)
154 goto err;
155 }
156
157 handle->msg_callback = NULL;
158 (void) semanage_seuser_query(handle, key, &previous);
159 handle->msg_callback = callback;
160 rc = dbase_modify(handle, dconfig, key, new);
161 if (semanage_seuser_audit(handle, new, previous, AUDIT_ROLE_ASSIGN, rc == 0) < 0)
162 rc = -1;
163 err:
164 if (previous)
165 semanage_seuser_free(previous);
166 semanage_seuser_free(new);
167 return rc;
168 }
169
semanage_seuser_del_local(semanage_handle_t * handle,const semanage_seuser_key_t * key)170 int semanage_seuser_del_local(semanage_handle_t * handle,
171 const semanage_seuser_key_t * key)
172 {
173 int rc;
174 semanage_seuser_t *seuser = NULL;
175 dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
176 rc = dbase_del(handle, dconfig, key);
177 semanage_seuser_query(handle, key, &seuser);
178 if (semanage_seuser_audit(handle, NULL, seuser, AUDIT_ROLE_REMOVE, rc == 0) < 0)
179 rc = -1;
180 if (seuser)
181 semanage_seuser_free(seuser);
182 return rc;
183 }
184
semanage_seuser_query_local(semanage_handle_t * handle,const semanage_seuser_key_t * key,semanage_seuser_t ** response)185 int semanage_seuser_query_local(semanage_handle_t * handle,
186 const semanage_seuser_key_t * key,
187 semanage_seuser_t ** response)
188 {
189
190 dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
191 return dbase_query(handle, dconfig, key, response);
192 }
193
semanage_seuser_exists_local(semanage_handle_t * handle,const semanage_seuser_key_t * key,int * response)194 int semanage_seuser_exists_local(semanage_handle_t * handle,
195 const semanage_seuser_key_t * key,
196 int *response)
197 {
198
199 dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
200 return dbase_exists(handle, dconfig, key, response);
201 }
202
semanage_seuser_count_local(semanage_handle_t * handle,unsigned int * response)203 int semanage_seuser_count_local(semanage_handle_t * handle,
204 unsigned int *response)
205 {
206
207 dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
208 return dbase_count(handle, dconfig, response);
209 }
210
semanage_seuser_iterate_local(semanage_handle_t * handle,int (* handler)(const semanage_seuser_t * record,void * varg),void * handler_arg)211 int semanage_seuser_iterate_local(semanage_handle_t * handle,
212 int (*handler) (const semanage_seuser_t *
213 record, void *varg),
214 void *handler_arg)
215 {
216
217 dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
218 return dbase_iterate(handle, dconfig, handler, handler_arg);
219 }
220
hidden_def(semanage_seuser_iterate_local)221 hidden_def(semanage_seuser_iterate_local)
222
223 int semanage_seuser_list_local(semanage_handle_t * handle,
224 semanage_seuser_t *** records,
225 unsigned int *count)
226 {
227
228 dbase_config_t *dconfig = semanage_seuser_dbase_local(handle);
229 return dbase_list(handle, dconfig, records, count);
230 }
231
232 struct validate_handler_arg {
233 semanage_handle_t *handle;
234 const sepol_policydb_t *policydb;
235 };
236
validate_handler(const semanage_seuser_t * seuser,void * varg)237 static int validate_handler(const semanage_seuser_t * seuser, void *varg)
238 {
239
240 semanage_user_t *user = NULL;
241 semanage_user_key_t *key = NULL;
242 int exists, mls_ok;
243
244 /* Unpack varg */
245 struct validate_handler_arg *arg = (struct validate_handler_arg *)varg;
246 semanage_handle_t *handle = arg->handle;
247 const sepol_policydb_t *policydb = arg->policydb;
248
249 /* Unpack seuser */
250 const char *name = semanage_seuser_get_name(seuser);
251 const char *sename = semanage_seuser_get_sename(seuser);
252 const char *mls_range = semanage_seuser_get_mlsrange(seuser);
253 const char *user_mls_range;
254
255 /* Make sure the (SElinux) user exists */
256 if (semanage_user_key_create(handle, sename, &key) < 0)
257 goto err;
258 if (semanage_user_exists(handle, key, &exists) < 0)
259 goto err;
260 if (!exists) {
261 ERR(handle, "selinux user %s does not exist", sename);
262 goto invalid;
263 }
264
265 /* Verify that the mls range is valid, and that it's contained
266 * within the (SELinux) user mls range. This range is optional */
267 if (mls_range && sepol_policydb_mls_enabled(policydb)) {
268
269 if (semanage_user_query(handle, key, &user) < 0)
270 goto err;
271 user_mls_range = semanage_user_get_mlsrange(user);
272
273 if (sepol_mls_check(handle->sepolh, policydb, mls_range) < 0)
274 goto invalid;
275 if (sepol_mls_contains(handle->sepolh, policydb,
276 user_mls_range, mls_range, &mls_ok) < 0)
277 goto err;
278
279 if (!mls_ok) {
280 ERR(handle, "MLS range %s for Unix user %s "
281 "exceeds allowed range %s for SELinux user %s",
282 mls_range, name, user_mls_range, sename);
283 goto invalid;
284 }
285
286 } else if (mls_range) {
287 ERR(handle, "MLS is disabled, but MLS range %s "
288 "was found for Unix user %s", mls_range, name);
289 goto invalid;
290 }
291
292 semanage_user_key_free(key);
293 semanage_user_free(user);
294 return 0;
295
296 err:
297 ERR(handle, "could not check if seuser mapping for %s is valid", name);
298 semanage_user_key_free(key);
299 semanage_user_free(user);
300 return -1;
301
302 invalid:
303 if (mls_range)
304 ERR(handle, "seuser mapping [%s -> (%s, %s)] is invalid",
305 name, sename, mls_range);
306 else
307 ERR(handle, "seuser mapping [%s -> %s] is invalid",
308 name, sename);
309 semanage_user_key_free(key);
310 semanage_user_free(user);
311 return -1;
312 }
313
314 /* This function may not be called outside a transaction, or
315 * it will (1) deadlock, because iterate is not reentrant outside
316 * a transaction, and (2) be racy, because it makes multiple dbase calls */
317
semanage_seuser_validate_local(semanage_handle_t * handle,const sepol_policydb_t * policydb)318 int hidden semanage_seuser_validate_local(semanage_handle_t * handle,
319 const sepol_policydb_t * policydb)
320 {
321
322 struct validate_handler_arg arg;
323 arg.handle = handle;
324 arg.policydb = policydb;
325 return semanage_seuser_iterate_local(handle, validate_handler, &arg);
326 }
327