aboutsummaryrefslogtreecommitdiffstats
path: root/libsepol/src/context.c
diff options
context:
space:
mode:
Diffstat (limited to 'libsepol/src/context.c')
-rw-r--r--libsepol/src/context.c338
1 files changed, 338 insertions, 0 deletions
diff --git a/libsepol/src/context.c b/libsepol/src/context.c
new file mode 100644
index 00000000..84dad348
--- /dev/null
+++ b/libsepol/src/context.c
@@ -0,0 +1,338 @@
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+#include <sepol/policydb/policydb.h>
+#include <sepol/policydb/services.h>
+#include "context_internal.h"
+
+#include "debug.h"
+#include "context.h"
+#include "handle.h"
+#include "mls.h"
+
+/* ----- Compatibility ---- */
+int policydb_context_isvalid(const policydb_t * p, const context_struct_t * c)
+{
+
+ return context_is_valid(p, c);
+}
+
+int sepol_check_context(const char *context)
+{
+
+ return sepol_context_to_sid((const sepol_security_context_t)context,
+ strlen(context) + 1, NULL);
+}
+
+/* ---- End compatibility --- */
+
+/*
+ * Return 1 if the fields in the security context
+ * structure `c' are valid. Return 0 otherwise.
+ */
+int context_is_valid(const policydb_t * p, const context_struct_t * c)
+{
+
+ role_datum_t *role;
+ user_datum_t *usrdatum;
+ ebitmap_t types, roles;
+ int ret = 1;
+
+ ebitmap_init(&types);
+ ebitmap_init(&roles);
+ if (!c->role || c->role > p->p_roles.nprim)
+ return 0;
+
+ if (!c->user || c->user > p->p_users.nprim)
+ return 0;
+
+ if (!c->type || c->type > p->p_types.nprim)
+ return 0;
+
+ if (c->role != OBJECT_R_VAL) {
+ /*
+ * Role must be authorized for the type.
+ */
+ role = p->role_val_to_struct[c->role - 1];
+ if (!ebitmap_get_bit(&role->cache, c->type - 1))
+ /* role may not be associated with type */
+ return 0;
+
+ /*
+ * User must be authorized for the role.
+ */
+ usrdatum = p->user_val_to_struct[c->user - 1];
+ if (!usrdatum)
+ return 0;
+
+ if (!ebitmap_get_bit(&usrdatum->cache, c->role - 1))
+ /* user may not be associated with role */
+ return 0;
+ }
+
+ if (!mls_context_isvalid(p, c))
+ return 0;
+
+ return ret;
+}
+
+/*
+ * Write the security context string representation of
+ * the context structure `context' into a dynamically
+ * allocated string of the correct size. Set `*scontext'
+ * to point to this string and set `*scontext_len' to
+ * the length of the string.
+ */
+int context_to_string(sepol_handle_t * handle,
+ const policydb_t * policydb,
+ const context_struct_t * context,
+ char **result, size_t * result_len)
+{
+
+ char *scontext = NULL;
+ size_t scontext_len = 0;
+ char *ptr;
+
+ /* Compute the size of the context. */
+ scontext_len +=
+ strlen(policydb->p_user_val_to_name[context->user - 1]) + 1;
+ scontext_len +=
+ strlen(policydb->p_role_val_to_name[context->role - 1]) + 1;
+ scontext_len += strlen(policydb->p_type_val_to_name[context->type - 1]);
+ scontext_len += mls_compute_context_len(policydb, context);
+
+ /* We must null terminate the string */
+ scontext_len += 1;
+
+ /* Allocate space for the context; caller must free this space. */
+ scontext = malloc(scontext_len);
+ if (!scontext)
+ goto omem;
+ scontext[scontext_len - 1] = '\0';
+
+ /*
+ * Copy the user name, role name and type name into the context.
+ */
+ ptr = scontext;
+ sprintf(ptr, "%s:%s:%s",
+ policydb->p_user_val_to_name[context->user - 1],
+ policydb->p_role_val_to_name[context->role - 1],
+ policydb->p_type_val_to_name[context->type - 1]);
+
+ ptr +=
+ strlen(policydb->p_user_val_to_name[context->user - 1]) + 1 +
+ strlen(policydb->p_role_val_to_name[context->role - 1]) + 1 +
+ strlen(policydb->p_type_val_to_name[context->type - 1]);
+
+ mls_sid_to_context(policydb, context, &ptr);
+
+ *result = scontext;
+ *result_len = scontext_len;
+ return STATUS_SUCCESS;
+
+ omem:
+ ERR(handle, "out of memory, could not convert " "context to string");
+ free(scontext);
+ return STATUS_ERR;
+}
+
+/*
+ * Create a context structure from the given record
+ */
+int context_from_record(sepol_handle_t * handle,
+ const policydb_t * policydb,
+ context_struct_t ** cptr,
+ const sepol_context_t * record)
+{
+
+ context_struct_t *scontext = NULL;
+ user_datum_t *usrdatum;
+ role_datum_t *roldatum;
+ type_datum_t *typdatum;
+
+ /* Hashtab keys are not constant - suppress warnings */
+ char *user = strdup(sepol_context_get_user(record));
+ char *role = strdup(sepol_context_get_role(record));
+ char *type = strdup(sepol_context_get_type(record));
+ const char *mls = sepol_context_get_mls(record);
+
+ scontext = (context_struct_t *) malloc(sizeof(context_struct_t));
+ if (!user || !role || !type || !scontext) {
+ ERR(handle, "out of memory");
+ goto err;
+ }
+ context_init(scontext);
+
+ /* User */
+ usrdatum = (user_datum_t *) hashtab_search(policydb->p_users.table,
+ (hashtab_key_t) user);
+ if (!usrdatum) {
+ ERR(handle, "user %s is not defined", user);
+ goto err_destroy;
+ }
+ scontext->user = usrdatum->s.value;
+
+ /* Role */
+ roldatum = (role_datum_t *) hashtab_search(policydb->p_roles.table,
+ (hashtab_key_t) role);
+ if (!roldatum) {
+ ERR(handle, "role %s is not defined", role);
+ goto err_destroy;
+ }
+ scontext->role = roldatum->s.value;
+
+ /* Type */
+ typdatum = (type_datum_t *) hashtab_search(policydb->p_types.table,
+ (hashtab_key_t) type);
+ if (!typdatum || typdatum->flavor == TYPE_ATTRIB) {
+ ERR(handle, "type %s is not defined", type);
+ goto err_destroy;
+ }
+ scontext->type = typdatum->s.value;
+
+ /* MLS */
+ if (mls && !policydb->mls) {
+ ERR(handle, "MLS is disabled, but MLS context \"%s\" found",
+ mls);
+ goto err_destroy;
+ } else if (!mls && policydb->mls) {
+ ERR(handle, "MLS is enabled, but no MLS context found");
+ goto err_destroy;
+ }
+ if (mls && (mls_from_string(handle, policydb, mls, scontext) < 0))
+ goto err_destroy;
+
+ /* Validity check */
+ if (!context_is_valid(policydb, scontext)) {
+ if (mls) {
+ ERR(handle,
+ "invalid security context: \"%s:%s:%s:%s\"",
+ user, role, type, mls);
+ } else {
+ ERR(handle,
+ "invalid security context: \"%s:%s:%s\"",
+ user, role, type);
+ }
+ goto err_destroy;
+ }
+
+ *cptr = scontext;
+ free(user);
+ free(type);
+ free(role);
+ return STATUS_SUCCESS;
+
+ err_destroy:
+ errno = EINVAL;
+ context_destroy(scontext);
+
+ err:
+ free(scontext);
+ free(user);
+ free(type);
+ free(role);
+ ERR(handle, "could not create context structure");
+ return STATUS_ERR;
+}
+
+/*
+ * Create a record from the given context structure
+ */
+int context_to_record(sepol_handle_t * handle,
+ const policydb_t * policydb,
+ const context_struct_t * context,
+ sepol_context_t ** record)
+{
+
+ sepol_context_t *tmp_record = NULL;
+ char *mls = NULL;
+
+ if (sepol_context_create(handle, &tmp_record) < 0)
+ goto err;
+
+ if (sepol_context_set_user(handle, tmp_record,
+ policydb->p_user_val_to_name[context->user -
+ 1]) < 0)
+ goto err;
+
+ if (sepol_context_set_role(handle, tmp_record,
+ policydb->p_role_val_to_name[context->role -
+ 1]) < 0)
+ goto err;
+
+ if (sepol_context_set_type(handle, tmp_record,
+ policydb->p_type_val_to_name[context->type -
+ 1]) < 0)
+ goto err;
+
+ if (policydb->mls) {
+ if (mls_to_string(handle, policydb, context, &mls) < 0)
+ goto err;
+
+ if (sepol_context_set_mls(handle, tmp_record, mls) < 0)
+ goto err;
+ }
+
+ free(mls);
+ *record = tmp_record;
+ return STATUS_SUCCESS;
+
+ err:
+ ERR(handle, "could not create context record");
+ sepol_context_free(tmp_record);
+ free(mls);
+ return STATUS_ERR;
+}
+
+/*
+ * Create a context structure from the provided string.
+ */
+int context_from_string(sepol_handle_t * handle,
+ const policydb_t * policydb,
+ context_struct_t ** cptr,
+ const char *con_str, size_t con_str_len)
+{
+
+ char *con_cpy = NULL;
+ sepol_context_t *ctx_record = NULL;
+
+ /* sepol_context_from_string expects a NULL-terminated string */
+ con_cpy = malloc(con_str_len + 1);
+ if (!con_cpy)
+ goto omem;
+ memcpy(con_cpy, con_str, con_str_len);
+ con_cpy[con_str_len] = '\0';
+
+ if (sepol_context_from_string(handle, con_cpy, &ctx_record) < 0)
+ goto err;
+
+ /* Now create from the data structure */
+ if (context_from_record(handle, policydb, cptr, ctx_record) < 0)
+ goto err;
+
+ free(con_cpy);
+ sepol_context_free(ctx_record);
+ return STATUS_SUCCESS;
+
+ omem:
+ ERR(handle, "out of memory");
+
+ err:
+ ERR(handle, "could not create context structure");
+ free(con_cpy);
+ sepol_context_free(ctx_record);
+ return STATUS_ERR;
+}
+
+int sepol_context_check(sepol_handle_t * handle,
+ const sepol_policydb_t * policydb,
+ const sepol_context_t * context)
+{
+
+ context_struct_t *con = NULL;
+ int ret = context_from_record(handle, &policydb->p, &con, context);
+ context_destroy(con);
+ free(con);
+ return ret;
+}