1 #include <errno.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "user_internal.h"
6 #include "debug.h"
7 #include "private.h"
8
9 struct sepol_user {
10 /* This user's name */
11 char *name;
12
13 /* This user's mls level (only required for mls) */
14 char *mls_level;
15
16 /* This user's mls range (only required for mls) */
17 char *mls_range;
18
19 /* The role array */
20 char **roles;
21
22 /* The number of roles */
23 unsigned int num_roles;
24 };
25
26 struct sepol_user_key {
27 /* This user's name */
28 char *name;
29 };
30
sepol_user_key_create(sepol_handle_t * handle,const char * name,sepol_user_key_t ** key_ptr)31 int sepol_user_key_create(sepol_handle_t * handle,
32 const char *name, sepol_user_key_t ** key_ptr)
33 {
34
35 sepol_user_key_t *tmp_key =
36 (sepol_user_key_t *) malloc(sizeof(sepol_user_key_t));
37
38 if (!tmp_key) {
39 ERR(handle, "out of memory, "
40 "could not create selinux user key");
41 return STATUS_ERR;
42 }
43
44 tmp_key->name = strdup(name);
45 if (!tmp_key->name) {
46 ERR(handle, "out of memory, could not create selinux user key");
47 free(tmp_key);
48 return STATUS_ERR;
49 }
50
51 *key_ptr = tmp_key;
52 return STATUS_SUCCESS;
53 }
54
55
sepol_user_key_unpack(const sepol_user_key_t * key,const char ** name)56 void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name)
57 {
58
59 *name = key->name;
60 }
61
62
sepol_user_key_extract(sepol_handle_t * handle,const sepol_user_t * user,sepol_user_key_t ** key_ptr)63 int sepol_user_key_extract(sepol_handle_t * handle,
64 const sepol_user_t * user,
65 sepol_user_key_t ** key_ptr)
66 {
67
68 if (sepol_user_key_create(handle, user->name, key_ptr) < 0) {
69 ERR(handle, "could not extract key from user %s", user->name);
70 return STATUS_ERR;
71 }
72
73 return STATUS_SUCCESS;
74 }
75
sepol_user_key_free(sepol_user_key_t * key)76 void sepol_user_key_free(sepol_user_key_t * key)
77 {
78 if (!key)
79 return;
80 free(key->name);
81 free(key);
82 }
83
sepol_user_compare(const sepol_user_t * user,const sepol_user_key_t * key)84 int sepol_user_compare(const sepol_user_t * user, const sepol_user_key_t * key)
85 {
86
87 return strcmp(user->name, key->name);
88 }
89
sepol_user_compare2(const sepol_user_t * user,const sepol_user_t * user2)90 int sepol_user_compare2(const sepol_user_t * user, const sepol_user_t * user2)
91 {
92
93 return strcmp(user->name, user2->name);
94 }
95
96 /* Name */
sepol_user_get_name(const sepol_user_t * user)97 const char *sepol_user_get_name(const sepol_user_t * user)
98 {
99
100 return user->name;
101 }
102
sepol_user_set_name(sepol_handle_t * handle,sepol_user_t * user,const char * name)103 int sepol_user_set_name(sepol_handle_t * handle,
104 sepol_user_t * user, const char *name)
105 {
106
107 char *tmp_name = strdup(name);
108 if (!tmp_name) {
109 ERR(handle, "out of memory, could not set name");
110 return STATUS_ERR;
111 }
112 free(user->name);
113 user->name = tmp_name;
114 return STATUS_SUCCESS;
115 }
116
117
118 /* MLS */
sepol_user_get_mlslevel(const sepol_user_t * user)119 const char *sepol_user_get_mlslevel(const sepol_user_t * user)
120 {
121
122 return user->mls_level;
123 }
124
125
sepol_user_set_mlslevel(sepol_handle_t * handle,sepol_user_t * user,const char * mls_level)126 int sepol_user_set_mlslevel(sepol_handle_t * handle,
127 sepol_user_t * user, const char *mls_level)
128 {
129
130 char *tmp_mls_level = strdup(mls_level);
131 if (!tmp_mls_level) {
132 ERR(handle, "out of memory, "
133 "could not set MLS default level");
134 return STATUS_ERR;
135 }
136 free(user->mls_level);
137 user->mls_level = tmp_mls_level;
138 return STATUS_SUCCESS;
139 }
140
141
sepol_user_get_mlsrange(const sepol_user_t * user)142 const char *sepol_user_get_mlsrange(const sepol_user_t * user)
143 {
144
145 return user->mls_range;
146 }
147
148
sepol_user_set_mlsrange(sepol_handle_t * handle,sepol_user_t * user,const char * mls_range)149 int sepol_user_set_mlsrange(sepol_handle_t * handle,
150 sepol_user_t * user, const char *mls_range)
151 {
152
153 char *tmp_mls_range = strdup(mls_range);
154 if (!tmp_mls_range) {
155 ERR(handle, "out of memory, "
156 "could not set MLS allowed range");
157 return STATUS_ERR;
158 }
159 free(user->mls_range);
160 user->mls_range = tmp_mls_range;
161 return STATUS_SUCCESS;
162 }
163
164
165 /* Roles */
sepol_user_get_num_roles(const sepol_user_t * user)166 int sepol_user_get_num_roles(const sepol_user_t * user)
167 {
168
169 return user->num_roles;
170 }
171
sepol_user_add_role(sepol_handle_t * handle,sepol_user_t * user,const char * role)172 int sepol_user_add_role(sepol_handle_t * handle,
173 sepol_user_t * user, const char *role)
174 {
175
176 char *role_cp;
177 char **roles_realloc = NULL;
178
179 if (sepol_user_has_role(user, role))
180 return STATUS_SUCCESS;
181
182 role_cp = strdup(role);
183 if (!role_cp)
184 goto omem;
185
186 roles_realloc = reallocarray(user->roles,
187 user->num_roles + 1,
188 sizeof(char *));
189 if (!roles_realloc)
190 goto omem;
191
192 user->num_roles++;
193 user->roles = roles_realloc;
194 user->roles[user->num_roles - 1] = role_cp;
195
196 return STATUS_SUCCESS;
197
198 omem:
199 ERR(handle, "out of memory, could not add role %s", role);
200 free(role_cp);
201 free(roles_realloc);
202 return STATUS_ERR;
203 }
204
205
sepol_user_has_role(const sepol_user_t * user,const char * role)206 int sepol_user_has_role(const sepol_user_t * user, const char *role)
207 {
208
209 unsigned int i;
210
211 for (i = 0; i < user->num_roles; i++)
212 if (!strcmp(user->roles[i], role))
213 return 1;
214 return 0;
215 }
216
217
sepol_user_set_roles(sepol_handle_t * handle,sepol_user_t * user,const char ** roles_arr,unsigned int num_roles)218 int sepol_user_set_roles(sepol_handle_t * handle,
219 sepol_user_t * user,
220 const char **roles_arr, unsigned int num_roles)
221 {
222
223 unsigned int i;
224 char **tmp_roles = NULL;
225
226 if (num_roles > 0) {
227
228 /* First, make a copy */
229 tmp_roles = (char **)calloc(1, sizeof(char *) * num_roles);
230 if (!tmp_roles)
231 goto omem;
232
233 for (i = 0; i < num_roles; i++) {
234 tmp_roles[i] = strdup(roles_arr[i]);
235 if (!tmp_roles[i])
236 goto omem;
237 }
238 }
239
240 /* Apply other changes */
241 for (i = 0; i < user->num_roles; i++)
242 free(user->roles[i]);
243 free(user->roles);
244 user->roles = tmp_roles;
245 user->num_roles = num_roles;
246 return STATUS_SUCCESS;
247
248 omem:
249 ERR(handle, "out of memory, could not allocate roles array for"
250 "user %s", user->name);
251
252 if (tmp_roles) {
253 for (i = 0; i < num_roles; i++) {
254 if (!tmp_roles[i])
255 break;
256 free(tmp_roles[i]);
257 }
258 }
259 free(tmp_roles);
260 return STATUS_ERR;
261 }
262
sepol_user_get_roles(sepol_handle_t * handle,const sepol_user_t * user,const char *** roles_arr,unsigned int * num_roles)263 int sepol_user_get_roles(sepol_handle_t * handle,
264 const sepol_user_t * user,
265 const char ***roles_arr, unsigned int *num_roles)
266 {
267
268 unsigned int i;
269 const char **tmp_roles =
270 (const char **)calloc(user->num_roles, sizeof(char *));
271 if (!tmp_roles)
272 goto omem;
273
274 for (i = 0; i < user->num_roles; i++)
275 tmp_roles[i] = user->roles[i];
276
277 *roles_arr = tmp_roles;
278 *num_roles = user->num_roles;
279 return STATUS_SUCCESS;
280
281 omem:
282 ERR(handle, "out of memory, could not "
283 "allocate roles array for user %s", user->name);
284 free(tmp_roles);
285 return STATUS_ERR;
286 }
287
288
sepol_user_del_role(sepol_user_t * user,const char * role)289 void sepol_user_del_role(sepol_user_t * user, const char *role)
290 {
291
292 unsigned int i;
293 for (i = 0; i < user->num_roles; i++) {
294 if (!strcmp(user->roles[i], role)) {
295 free(user->roles[i]);
296 user->roles[i] = NULL;
297 user->roles[i] = user->roles[user->num_roles - 1];
298 user->num_roles--;
299 }
300 }
301 }
302
303 /* Create */
sepol_user_create(sepol_handle_t * handle,sepol_user_t ** user_ptr)304 int sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr)
305 {
306
307 sepol_user_t *user = (sepol_user_t *) malloc(sizeof(sepol_user_t));
308
309 if (!user) {
310 ERR(handle, "out of memory, "
311 "could not create selinux user record");
312 return STATUS_ERR;
313 }
314
315 user->roles = NULL;
316 user->num_roles = 0;
317 user->name = NULL;
318 user->mls_level = NULL;
319 user->mls_range = NULL;
320
321 *user_ptr = user;
322 return STATUS_SUCCESS;
323 }
324
325
326 /* Deep copy clone */
sepol_user_clone(sepol_handle_t * handle,const sepol_user_t * user,sepol_user_t ** user_ptr)327 int sepol_user_clone(sepol_handle_t * handle,
328 const sepol_user_t * user, sepol_user_t ** user_ptr)
329 {
330
331 sepol_user_t *new_user = NULL;
332 unsigned int i;
333
334 if (sepol_user_create(handle, &new_user) < 0)
335 goto err;
336
337 if (sepol_user_set_name(handle, new_user, user->name) < 0)
338 goto err;
339
340 for (i = 0; i < user->num_roles; i++) {
341 if (sepol_user_add_role(handle, new_user, user->roles[i]) < 0)
342 goto err;
343 }
344
345 if (user->mls_level &&
346 (sepol_user_set_mlslevel(handle, new_user, user->mls_level) < 0))
347 goto err;
348
349 if (user->mls_range &&
350 (sepol_user_set_mlsrange(handle, new_user, user->mls_range) < 0))
351 goto err;
352
353 *user_ptr = new_user;
354 return STATUS_SUCCESS;
355
356 err:
357 ERR(handle, "could not clone selinux user record");
358 sepol_user_free(new_user);
359 return STATUS_ERR;
360 }
361
362 /* Destroy */
sepol_user_free(sepol_user_t * user)363 void sepol_user_free(sepol_user_t * user)
364 {
365
366 unsigned int i;
367
368 if (!user)
369 return;
370
371 free(user->name);
372 for (i = 0; i < user->num_roles; i++)
373 free(user->roles[i]);
374 free(user->roles);
375 free(user->mls_level);
376 free(user->mls_range);
377 free(user);
378 }
379
380