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