| #include <errno.h> |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #include "user_internal.h" |
| #include "debug.h" |
| |
| struct sepol_user { |
| /* This user's name */ |
| char *name; |
| |
| /* This user's mls level (only required for mls) */ |
| char *mls_level; |
| |
| /* This user's mls range (only required for mls) */ |
| char *mls_range; |
| |
| /* The role array */ |
| char **roles; |
| |
| /* The number of roles */ |
| unsigned int num_roles; |
| }; |
| |
| struct sepol_user_key { |
| /* This user's name */ |
| const char *name; |
| }; |
| |
| int sepol_user_key_create(sepol_handle_t * handle, |
| const char *name, sepol_user_key_t ** key_ptr) |
| { |
| |
| sepol_user_key_t *tmp_key = |
| (sepol_user_key_t *) malloc(sizeof(sepol_user_key_t)); |
| |
| if (!tmp_key) { |
| ERR(handle, "out of memory, " |
| "could not create selinux user key"); |
| return STATUS_ERR; |
| } |
| |
| tmp_key->name = name; |
| |
| *key_ptr = tmp_key; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_user_key_create) |
| |
| void sepol_user_key_unpack(const sepol_user_key_t * key, const char **name) |
| { |
| |
| *name = key->name; |
| } |
| |
| hidden_def(sepol_user_key_unpack) |
| |
| int sepol_user_key_extract(sepol_handle_t * handle, |
| const sepol_user_t * user, |
| sepol_user_key_t ** key_ptr) |
| { |
| |
| if (sepol_user_key_create(handle, user->name, key_ptr) < 0) { |
| ERR(handle, "could not extract key from user %s", user->name); |
| return STATUS_ERR; |
| } |
| |
| return STATUS_SUCCESS; |
| } |
| |
| void sepol_user_key_free(sepol_user_key_t * key) |
| { |
| free(key); |
| } |
| |
| int sepol_user_compare(const sepol_user_t * user, const sepol_user_key_t * key) |
| { |
| |
| return strcmp(user->name, key->name); |
| } |
| |
| int sepol_user_compare2(const sepol_user_t * user, const sepol_user_t * user2) |
| { |
| |
| return strcmp(user->name, user2->name); |
| } |
| |
| /* Name */ |
| const char *sepol_user_get_name(const sepol_user_t * user) |
| { |
| |
| return user->name; |
| } |
| |
| int sepol_user_set_name(sepol_handle_t * handle, |
| sepol_user_t * user, const char *name) |
| { |
| |
| char *tmp_name = strdup(name); |
| if (!tmp_name) { |
| ERR(handle, "out of memory, could not set name"); |
| return STATUS_ERR; |
| } |
| free(user->name); |
| user->name = tmp_name; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_user_set_name) |
| |
| /* MLS */ |
| const char *sepol_user_get_mlslevel(const sepol_user_t * user) |
| { |
| |
| return user->mls_level; |
| } |
| |
| hidden_def(sepol_user_get_mlslevel) |
| |
| int sepol_user_set_mlslevel(sepol_handle_t * handle, |
| sepol_user_t * user, const char *mls_level) |
| { |
| |
| char *tmp_mls_level = strdup(mls_level); |
| if (!tmp_mls_level) { |
| ERR(handle, "out of memory, " |
| "could not set MLS default level"); |
| return STATUS_ERR; |
| } |
| free(user->mls_level); |
| user->mls_level = tmp_mls_level; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_user_set_mlslevel) |
| |
| const char *sepol_user_get_mlsrange(const sepol_user_t * user) |
| { |
| |
| return user->mls_range; |
| } |
| |
| hidden_def(sepol_user_get_mlsrange) |
| |
| int sepol_user_set_mlsrange(sepol_handle_t * handle, |
| sepol_user_t * user, const char *mls_range) |
| { |
| |
| char *tmp_mls_range = strdup(mls_range); |
| if (!tmp_mls_range) { |
| ERR(handle, "out of memory, " |
| "could not set MLS allowed range"); |
| return STATUS_ERR; |
| } |
| free(user->mls_range); |
| user->mls_range = tmp_mls_range; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_user_set_mlsrange) |
| |
| /* Roles */ |
| int sepol_user_get_num_roles(const sepol_user_t * user) |
| { |
| |
| return user->num_roles; |
| } |
| |
| int sepol_user_add_role(sepol_handle_t * handle, |
| sepol_user_t * user, const char *role) |
| { |
| |
| char *role_cp; |
| char **roles_realloc; |
| |
| if (sepol_user_has_role(user, role)) |
| return STATUS_SUCCESS; |
| |
| role_cp = strdup(role); |
| roles_realloc = realloc(user->roles, |
| sizeof(char *) * (user->num_roles + 1)); |
| |
| if (!role_cp || !roles_realloc) |
| goto omem; |
| |
| user->num_roles++; |
| user->roles = roles_realloc; |
| user->roles[user->num_roles - 1] = role_cp; |
| |
| return STATUS_SUCCESS; |
| |
| omem: |
| ERR(handle, "out of memory, could not add role %s", role); |
| free(role_cp); |
| free(roles_realloc); |
| return STATUS_ERR; |
| } |
| |
| hidden_def(sepol_user_add_role) |
| |
| int sepol_user_has_role(const sepol_user_t * user, const char *role) |
| { |
| |
| unsigned int i; |
| |
| for (i = 0; i < user->num_roles; i++) |
| if (!strcmp(user->roles[i], role)) |
| return 1; |
| return 0; |
| } |
| |
| hidden_def(sepol_user_has_role) |
| |
| int sepol_user_set_roles(sepol_handle_t * handle, |
| sepol_user_t * user, |
| const char **roles_arr, unsigned int num_roles) |
| { |
| |
| unsigned int i; |
| char **tmp_roles = NULL; |
| |
| if (num_roles > 0) { |
| |
| /* First, make a copy */ |
| tmp_roles = (char **)calloc(1, sizeof(char *) * num_roles); |
| if (!tmp_roles) |
| goto omem; |
| |
| for (i = 0; i < num_roles; i++) { |
| tmp_roles[i] = strdup(roles_arr[i]); |
| if (!tmp_roles[i]) |
| goto omem; |
| } |
| } |
| |
| /* Apply other changes */ |
| for (i = 0; i < user->num_roles; i++) |
| free(user->roles[i]); |
| free(user->roles); |
| user->roles = tmp_roles; |
| user->num_roles = num_roles; |
| return STATUS_SUCCESS; |
| |
| omem: |
| ERR(handle, "out of memory, could not allocate roles array for" |
| "user %s", user->name); |
| |
| if (tmp_roles) { |
| for (i = 0; i < num_roles; i++) { |
| if (!tmp_roles[i]) |
| break; |
| free(tmp_roles[i]); |
| } |
| } |
| free(tmp_roles); |
| return STATUS_ERR; |
| } |
| |
| int sepol_user_get_roles(sepol_handle_t * handle, |
| const sepol_user_t * user, |
| const char ***roles_arr, unsigned int *num_roles) |
| { |
| |
| unsigned int i; |
| const char **tmp_roles = |
| (const char **)malloc(sizeof(char *) * user->num_roles); |
| if (!tmp_roles) |
| goto omem; |
| |
| for (i = 0; i < user->num_roles; i++) |
| tmp_roles[i] = user->roles[i]; |
| |
| *roles_arr = tmp_roles; |
| *num_roles = user->num_roles; |
| return STATUS_SUCCESS; |
| |
| omem: |
| ERR(handle, "out of memory, could not " |
| "allocate roles array for user %s", user->name); |
| free(tmp_roles); |
| return STATUS_ERR; |
| } |
| |
| hidden_def(sepol_user_get_roles) |
| |
| void sepol_user_del_role(sepol_user_t * user, const char *role) |
| { |
| |
| unsigned int i; |
| for (i = 0; i < user->num_roles; i++) { |
| if (!strcmp(user->roles[i], role)) { |
| free(user->roles[i]); |
| user->roles[i] = NULL; |
| user->roles[i] = user->roles[user->num_roles - 1]; |
| user->num_roles--; |
| } |
| } |
| } |
| |
| /* Create */ |
| int sepol_user_create(sepol_handle_t * handle, sepol_user_t ** user_ptr) |
| { |
| |
| sepol_user_t *user = (sepol_user_t *) malloc(sizeof(sepol_user_t)); |
| |
| if (!user) { |
| ERR(handle, "out of memory, " |
| "could not create selinux user record"); |
| return STATUS_ERR; |
| } |
| |
| user->roles = NULL; |
| user->num_roles = 0; |
| user->name = NULL; |
| user->mls_level = NULL; |
| user->mls_range = NULL; |
| |
| *user_ptr = user; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_user_create) |
| |
| /* Deep copy clone */ |
| int sepol_user_clone(sepol_handle_t * handle, |
| const sepol_user_t * user, sepol_user_t ** user_ptr) |
| { |
| |
| sepol_user_t *new_user = NULL; |
| unsigned int i; |
| |
| if (sepol_user_create(handle, &new_user) < 0) |
| goto err; |
| |
| if (sepol_user_set_name(handle, new_user, user->name) < 0) |
| goto err; |
| |
| for (i = 0; i < user->num_roles; i++) { |
| if (sepol_user_add_role(handle, new_user, user->roles[i]) < 0) |
| goto err; |
| } |
| |
| if (user->mls_level && |
| (sepol_user_set_mlslevel(handle, new_user, user->mls_level) < 0)) |
| goto err; |
| |
| if (user->mls_range && |
| (sepol_user_set_mlsrange(handle, new_user, user->mls_range) < 0)) |
| goto err; |
| |
| *user_ptr = new_user; |
| return STATUS_SUCCESS; |
| |
| err: |
| ERR(handle, "could not clone selinux user record"); |
| sepol_user_free(new_user); |
| return STATUS_ERR; |
| } |
| |
| /* Destroy */ |
| void sepol_user_free(sepol_user_t * user) |
| { |
| |
| unsigned int i; |
| |
| if (!user) |
| return; |
| |
| free(user->name); |
| for (i = 0; i < user->num_roles; i++) |
| free(user->roles[i]); |
| free(user->roles); |
| free(user->mls_level); |
| free(user->mls_range); |
| free(user); |
| } |
| |
| hidden_def(sepol_user_free) |