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