| #include <errno.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #include <stdio.h> |
| |
| #include "context_internal.h" |
| #include "debug.h" |
| |
| struct sepol_context { |
| |
| /* Selinux user */ |
| char *user; |
| |
| /* Selinux role */ |
| char *role; |
| |
| /* Selinux type */ |
| char *type; |
| |
| /* MLS */ |
| char *mls; |
| }; |
| |
| /* User */ |
| const char *sepol_context_get_user(const sepol_context_t * con) |
| { |
| |
| return con->user; |
| } |
| |
| hidden_def(sepol_context_get_user) |
| |
| int sepol_context_set_user(sepol_handle_t * handle, |
| sepol_context_t * con, const char *user) |
| { |
| |
| char *tmp_user = strdup(user); |
| if (!tmp_user) { |
| ERR(handle, "out of memory, could not set " |
| "context user to %s", user); |
| return STATUS_ERR; |
| } |
| |
| free(con->user); |
| con->user = tmp_user; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_context_set_user) |
| |
| /* Role */ |
| const char *sepol_context_get_role(const sepol_context_t * con) |
| { |
| |
| return con->role; |
| } |
| |
| hidden_def(sepol_context_get_role) |
| |
| int sepol_context_set_role(sepol_handle_t * handle, |
| sepol_context_t * con, const char *role) |
| { |
| |
| char *tmp_role = strdup(role); |
| if (!tmp_role) { |
| ERR(handle, "out of memory, could not set " |
| "context role to %s", role); |
| return STATUS_ERR; |
| } |
| free(con->role); |
| con->role = tmp_role; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_context_set_role) |
| |
| /* Type */ |
| const char *sepol_context_get_type(const sepol_context_t * con) |
| { |
| |
| return con->type; |
| } |
| |
| hidden_def(sepol_context_get_type) |
| |
| int sepol_context_set_type(sepol_handle_t * handle, |
| sepol_context_t * con, const char *type) |
| { |
| |
| char *tmp_type = strdup(type); |
| if (!tmp_type) { |
| ERR(handle, "out of memory, could not set " |
| "context type to %s", type); |
| return STATUS_ERR; |
| } |
| free(con->type); |
| con->type = tmp_type; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_context_set_type) |
| |
| /* MLS */ |
| const char *sepol_context_get_mls(const sepol_context_t * con) |
| { |
| |
| return con->mls; |
| } |
| |
| hidden_def(sepol_context_get_mls) |
| |
| int sepol_context_set_mls(sepol_handle_t * handle, |
| sepol_context_t * con, const char *mls) |
| { |
| |
| char *tmp_mls = strdup(mls); |
| if (!tmp_mls) { |
| ERR(handle, "out of memory, could not set " |
| "MLS fields to %s", mls); |
| return STATUS_ERR; |
| } |
| free(con->mls); |
| con->mls = tmp_mls; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_context_set_mls) |
| |
| /* Create */ |
| int sepol_context_create(sepol_handle_t * handle, sepol_context_t ** con_ptr) |
| { |
| |
| sepol_context_t *con = |
| (sepol_context_t *) malloc(sizeof(sepol_context_t)); |
| |
| if (!con) { |
| ERR(handle, "out of memory, could not " "create context\n"); |
| return STATUS_ERR; |
| } |
| |
| con->user = NULL; |
| con->role = NULL; |
| con->type = NULL; |
| con->mls = NULL; |
| *con_ptr = con; |
| return STATUS_SUCCESS; |
| } |
| |
| hidden_def(sepol_context_create) |
| |
| /* Deep copy clone */ |
| int sepol_context_clone(sepol_handle_t * handle, |
| const sepol_context_t * con, sepol_context_t ** con_ptr) |
| { |
| |
| sepol_context_t *new_con = NULL; |
| |
| if (!con) { |
| *con_ptr = NULL; |
| return 0; |
| } |
| |
| if (sepol_context_create(handle, &new_con) < 0) |
| goto err; |
| |
| if (!(new_con->user = strdup(con->user))) |
| goto omem; |
| |
| if (!(new_con->role = strdup(con->role))) |
| goto omem; |
| |
| if (!(new_con->type = strdup(con->type))) |
| goto omem; |
| |
| if (con->mls && !(new_con->mls = strdup(con->mls))) |
| goto omem; |
| |
| *con_ptr = new_con; |
| return STATUS_SUCCESS; |
| |
| omem: |
| ERR(handle, "out of memory"); |
| |
| err: |
| ERR(handle, "could not clone context record"); |
| sepol_context_free(new_con); |
| return STATUS_ERR; |
| } |
| |
| hidden_def(sepol_context_clone) |
| |
| /* Destroy */ |
| void sepol_context_free(sepol_context_t * con) |
| { |
| |
| if (!con) |
| return; |
| |
| free(con->user); |
| free(con->role); |
| free(con->type); |
| free(con->mls); |
| free(con); |
| } |
| |
| hidden_def(sepol_context_free) |
| |
| int sepol_context_from_string(sepol_handle_t * handle, |
| const char *str, sepol_context_t ** con) |
| { |
| |
| char *tmp = NULL, *low, *high; |
| sepol_context_t *tmp_con = NULL; |
| |
| if (!strcmp(str, "<<none>>")) { |
| *con = NULL; |
| return STATUS_SUCCESS; |
| } |
| |
| if (sepol_context_create(handle, &tmp_con) < 0) |
| goto err; |
| |
| /* Working copy context */ |
| tmp = strdup(str); |
| if (!tmp) { |
| ERR(handle, "out of memory"); |
| goto err; |
| } |
| low = tmp; |
| |
| /* Then, break it into its components */ |
| |
| /* User */ |
| if (!(high = strchr(low, ':'))) |
| goto mcontext; |
| else |
| *high++ = '\0'; |
| if (sepol_context_set_user(handle, tmp_con, low) < 0) |
| goto err; |
| low = high; |
| |
| /* Role */ |
| if (!(high = strchr(low, ':'))) |
| goto mcontext; |
| else |
| *high++ = '\0'; |
| if (sepol_context_set_role(handle, tmp_con, low) < 0) |
| goto err; |
| low = high; |
| |
| /* Type, and possibly MLS */ |
| if (!(high = strchr(low, ':'))) { |
| if (sepol_context_set_type(handle, tmp_con, low) < 0) |
| goto err; |
| } else { |
| *high++ = '\0'; |
| if (sepol_context_set_type(handle, tmp_con, low) < 0) |
| goto err; |
| low = high; |
| if (sepol_context_set_mls(handle, tmp_con, low) < 0) |
| goto err; |
| } |
| |
| free(tmp); |
| *con = tmp_con; |
| |
| return STATUS_SUCCESS; |
| |
| mcontext: |
| errno = EINVAL; |
| ERR(handle, "malformed context \"%s\"", str); |
| |
| err: |
| ERR(handle, "could not construct context from string"); |
| free(tmp); |
| sepol_context_free(tmp_con); |
| return STATUS_ERR; |
| } |
| |
| hidden_def(sepol_context_from_string) |
| |
| int sepol_context_to_string(sepol_handle_t * handle, |
| const sepol_context_t * con, char **str_ptr) |
| { |
| |
| int rc; |
| const int user_sz = strlen(con->user); |
| const int role_sz = strlen(con->role); |
| const int type_sz = strlen(con->type); |
| const int mls_sz = (con->mls) ? strlen(con->mls) : 0; |
| const int total_sz = user_sz + role_sz + type_sz + |
| mls_sz + ((con->mls) ? 3 : 2); |
| |
| char *str = (char *)malloc(total_sz + 1); |
| if (!str) |
| goto omem; |
| |
| if (con->mls) { |
| rc = snprintf(str, total_sz + 1, "%s:%s:%s:%s", |
| con->user, con->role, con->type, con->mls); |
| if (rc < 0 || (rc >= total_sz + 1)) { |
| ERR(handle, "print error"); |
| goto err; |
| } |
| } else { |
| rc = snprintf(str, total_sz + 1, "%s:%s:%s", |
| con->user, con->role, con->type); |
| if (rc < 0 || (rc >= total_sz + 1)) { |
| ERR(handle, "print error"); |
| goto err; |
| } |
| } |
| |
| *str_ptr = str; |
| return STATUS_SUCCESS; |
| |
| omem: |
| ERR(handle, "out of memory"); |
| |
| err: |
| ERR(handle, "could not convert context to string"); |
| free(str); |
| return STATUS_ERR; |
| } |