From 2dd517b4b39deba0a8b966b9b227221bd44b58f2 Mon Sep 17 00:00:00 2001 From: Chris PeBenito Date: Sat, 21 Feb 2015 15:09:52 -0500 Subject: [PATCH] Implement MLS level lookup. --- libqpol/include/qpol/mls_query.h | 6 ++ libqpol/mls_query.c | 138 ++++++++++++++++++++++++++++++- setools/policyrep/mls.py | 43 +++++++++- setools/policyrep/qpol.i | 51 ++++++++++-- 4 files changed, 229 insertions(+), 9 deletions(-) diff --git a/libqpol/include/qpol/mls_query.h b/libqpol/include/qpol/mls_query.h index c5fadc5..b433b78 100644 --- a/libqpol/include/qpol/mls_query.h +++ b/libqpol/include/qpol/mls_query.h @@ -38,6 +38,7 @@ extern "C" typedef struct qpol_cat qpol_cat_t; typedef struct qpol_mls_range qpol_mls_range_t; typedef struct qpol_mls_level qpol_mls_level_t; + typedef struct qpol_semantic_level qpol_semantic_level_t; #include #include @@ -253,6 +254,11 @@ extern "C" extern int qpol_mls_level_get_cat_iter(const qpol_policy_t * policy, const qpol_mls_level_t * level, qpol_iterator_t ** cats); +/* semantic levels */ + extern int qpol_policy_get_semantic_level_by_name(const qpol_policy_t * policy, const char *name, const qpol_semantic_level_t ** datum); + extern int qpol_semantic_level_add_cats_by_name(const qpol_policy_t * policy, const qpol_semantic_level_t * level, const char *low, const char *high); + extern int qpol_mls_level_from_semantic_level(const qpol_policy_t * policy, const qpol_semantic_level_t * src, qpol_mls_level_t **dest); + #ifdef __cplusplus } #endif diff --git a/libqpol/mls_query.c b/libqpol/mls_query.c index c0a242e..dd5acf7 100644 --- a/libqpol/mls_query.c +++ b/libqpol/mls_query.c @@ -6,7 +6,7 @@ * @author Jeremy A. Mowery jmowery@tresys.com * @author Jason Tang jtang@tresys.com * - * Copyright (C) 2006-2007 Tresys Technology, LLC + * Copyright (C) 2006-2007. 2015 Tresys Technology, LLC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -637,3 +637,139 @@ int qpol_mls_level_get_cat_iter(const qpol_policy_t * policy, const qpol_mls_lev return STATUS_SUCCESS; } + +int qpol_mls_level_from_semantic_level(const qpol_policy_t * policy, const qpol_semantic_level_t * src, qpol_mls_level_t **dest) +{ + policydb_t *db = NULL; + mls_semantic_level_t *internal_semantic = NULL; + mls_level_t *internal_level = NULL; + + if (policy == NULL || src == NULL || dest == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + *dest = NULL; + return STATUS_ERR; + } + + internal_semantic = (mls_semantic_level_t*) src; + db = &policy->p->p; + + internal_level = malloc(sizeof(mls_level_t)); + if (!internal_level) { + return STATUS_ERR; + } + mls_level_init(internal_level); + + if(mls_semantic_level_expand(internal_semantic, internal_level, db, policy->sh) < 0) { + mls_level_destroy(internal_level); + free(internal_level); + errno = EINVAL; + *dest = NULL; + return STATUS_ERR; + } + + *dest = (qpol_mls_level_t*) internal_level; + + return STATUS_SUCCESS; +} + +/* semantic level */ +int qpol_policy_get_semantic_level_by_name(const qpol_policy_t * policy, const char *name, const qpol_semantic_level_t ** datum) +{ + policydb_t *db = NULL; + hashtab_datum_t internal_datum = NULL; + mls_semantic_level_t *internal_semantic = NULL; + + if (policy == NULL || name == NULL || datum == NULL) { + if (datum != NULL) + *datum = NULL; + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_semantic = malloc(sizeof(mls_semantic_level_t)); + if (!internal_semantic) { + return STATUS_ERR; + } + mls_semantic_level_init(internal_semantic); + + db = &policy->p->p; + internal_datum = hashtab_search(db->p_levels.table, (hashtab_key_t)name); + if (internal_datum == NULL) { + mls_semantic_level_destroy(internal_semantic); + free(internal_semantic); + *datum = NULL; + ERR(policy, "could not find datum for level %s", name); + errno = ENOENT; + return STATUS_ERR; + } + + internal_semantic->sens = ((level_datum_t*)internal_datum)->level->sens; + + *datum = (qpol_semantic_level_t *) internal_semantic; + + return STATUS_SUCCESS; +} + +int qpol_semantic_level_add_cats_by_name(const qpol_policy_t * policy, const qpol_semantic_level_t * level, const char *low, const char *high) +{ + hashtab_datum_t internal_datum; + policydb_t *db = NULL; + mls_semantic_level_t *internal_level = NULL; + mls_semantic_cat_t *internal_cat = NULL; + + if (policy == NULL || level == NULL || low == NULL || high == NULL) { + ERR(policy, "%s", strerror(EINVAL)); + errno = EINVAL; + return STATUS_ERR; + } + + internal_cat = malloc(sizeof(mls_semantic_cat_t)); + if (!internal_cat) { + return STATUS_ERR; + } + mls_semantic_cat_init(internal_cat); + + db = &policy->p->p; + internal_level = (mls_semantic_level_t*) level; + + internal_datum = hashtab_search(db->p_cats.table, (hashtab_key_t)low); + if (internal_datum == NULL) { + ERR(policy, "could not find datum for cat %s", low); + goto err; + } + internal_cat->low = ((cat_datum_t*)internal_datum)->s.value; + + internal_datum = hashtab_search(db->p_cats.table, (hashtab_key_t)high); + if (internal_datum == NULL) { + ERR(policy, "could not find datum for cat %s", high); + goto err; + } + internal_cat->high = ((cat_datum_t*)internal_datum)->s.value; + + if (internal_cat->low > internal_cat->high) { + ERR(policy, "invalid semantic category range: %s.%s", low, high); + goto err; + } + + if (!(internal_level->cat)) { + internal_level->cat = internal_cat; + } else { + mls_semantic_cat_t *curr = internal_level->cat; + + while(curr->next) { + curr = curr->next; + } + + curr->next = internal_cat; + } + + return STATUS_SUCCESS; + + err: + mls_semantic_cat_destroy(internal_cat); + free(internal_cat); + errno = ENOENT; + return STATUS_ERR; +} diff --git a/setools/policyrep/mls.py b/setools/policyrep/mls.py index b5fde14..e722294 100644 --- a/setools/policyrep/mls.py +++ b/setools/policyrep/mls.py @@ -84,10 +84,47 @@ def level_factory(policy, symbol): Factory function for creating MLS level objects (e.g. levels used in contexts of labeling statements) """ - if not isinstance(symbol, qpol.qpol_mls_level_t): - raise TypeError("MLS levels cannot be looked-up.") + if isinstance(symbol, qpol.qpol_mls_level_t): + return MLSLevel(policy, symbol) - return MLSLevel(policy, symbol) + # parse the level string and construct a semantic representation + sens_split = symbol.split(":") + + sens = sens_split[0] + try: + semantic_level = qpol.qpol_semantic_level_t(policy, sens) + except ValueError: + raise InvalidLevel("{0} is not a valid sensitivity".format(sens)) + + try: + cats = sens_split[1] + except IndexError: + pass + else: + for group in cats.split(","): + catrange = group.split(".") + + if len(catrange) == 2: + try: + semantic_level.add_cats(policy, catrange[0], catrange[1]) + except ValueError: + raise InvalidLevel("{0} is not a valid category range".format(group)) + elif len(catrange) == 1: + try: + semantic_level.add_cats(policy, catrange[0], catrange[0]) + except ValueError: + raise InvalidLevel("{0} is not a valid category".format(group)) + else: + # may not be possible to get here + raise InvalidLevel("{0} is not a valid category range".format(group)) + + # convert to level object + try: + policy_level = qpol.qpol_mls_level_t(policy, semantic_level) + except ValueError: + raise InvalidLevel("{0} is not a valid level".format(symbol)) + + return MLSLevel(policy, policy_level) def level_decl_factory(policy, symbol): diff --git a/setools/policyrep/qpol.i b/setools/policyrep/qpol.i index a2ce416..a0ab679 100644 --- a/setools/policyrep/qpol.i +++ b/setools/policyrep/qpol.i @@ -1561,16 +1561,57 @@ typedef struct qpol_mls_range {} qpol_mls_range_t; }; %} +/* qpol semantic mls level */ +typedef struct qpol_semantic_level {} qpol_semantic_level_t; +%extend qpol_semantic_level { + %exception qpol_semantic_level { + $action + if (!result) { + PyErr_SetString(PyExc_ValueError, "Invalid sensitivity name."); + return NULL; + } + } + + qpol_semantic_level(qpol_policy_t *p, const char *name) { + const qpol_semantic_level_t *l; + qpol_policy_get_semantic_level_by_name(p, name, &l); + return (qpol_semantic_level_t*)l; + }; + + ~qpol_semantic_level() { + /* mls_semantic_level_destroy(self); */ + return; + }; + + %exception add_cats { + $action + if (result) { + PyErr_SetString(PyExc_ValueError, "Invalid category name or category range."); + return NULL; + } + } + int add_cats(qpol_policy_t *p, const char *low, const char *high) { + return qpol_semantic_level_add_cats_by_name(p, self, low, high); + } +}; + /* qpol mls level */ typedef struct qpol_mls_level {} qpol_mls_level_t; %extend qpol_mls_level { - qpol_mls_level() { - BEGIN_EXCEPTION - SWIG_exception(SWIG_RuntimeError, "Cannot directly create qpol_mls_level_t objects"); - END_EXCEPTION - fail: + %exception qpol_mls_level { + $action + if (!result) { + PyErr_SetString(PyExc_ValueError, "Invalid level."); return NULL; + } } + + qpol_mls_level(qpol_policy_t *p, qpol_semantic_level_t *l) { + qpol_mls_level_t *level; + qpol_mls_level_from_semantic_level(p, l, &level); + return level; + } + ~qpol_mls_level() { /* no op */ return;