diff --git a/libqpol/default_object_query.c b/libqpol/default_object_query.c deleted file mode 100644 index 3b6b3d0..0000000 --- a/libqpol/default_object_query.c +++ /dev/null @@ -1,270 +0,0 @@ -/** -* @file -* Defines the public interface for searching and iterating over default objects. -* -* @author Richard Haines richard_c_haines@btinternet.com -* -* Copyright (C) 2006-2007 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 -* License as published by the Free Software Foundation; either -* version 2.1 of the License, or (at your option) any later version. -* -* This library is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -* Lesser General Public License for more details. -* -* You should have received a copy of the GNU Lesser General Public -* License along with this library; if not, write to the Free Software -* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include -#include -#include -#include -#include -#include -#include -#include "qpol_internal.h" -#include "iterator_internal.h" - -int qpol_default_object_get_class(const qpol_policy_t *policy, const qpol_default_object_t * datum, const qpol_class_t **cls) -{ - class_datum_t *internal_datum = NULL; - - if (policy == NULL || datum == NULL || cls == NULL) { - if (cls != NULL) - *cls = NULL; - ERR(policy, "%s", strerror(EINVAL)); - errno = EINVAL; - return STATUS_ERR; - } - *cls = NULL; - - internal_datum = (class_datum_t *)datum; - - /* These will be zero if no default_objects set */ - if (internal_datum->default_user || internal_datum->default_role || - internal_datum->default_type || - internal_datum->default_range) { - *cls = (const qpol_class_t *) datum; - } - return STATUS_SUCCESS; -} - -int qpol_default_object_get_user_default(const qpol_policy_t *policy, const qpol_default_object_t * datum, const char **value) -{ - class_datum_t *internal_datum = NULL; - - if (policy == NULL || datum == NULL || value == NULL) { - if (value != NULL) - *value = NULL; - ERR(policy, "%s", strerror(EINVAL)); - errno = EINVAL; - return STATUS_ERR; - } - *value = NULL; - - /* The user default started in ver 27 */ - if (!qpol_policy_has_capability(policy, QPOL_CAP_DEFAULT_OBJECTS)) - return STATUS_SUCCESS; - - internal_datum = (class_datum_t *)datum; - - if (internal_datum->default_user == DEFAULT_SOURCE) { - *value = "source"; - } else if (internal_datum->default_user == DEFAULT_TARGET) { - *value = "target"; - } - return STATUS_SUCCESS; -} - -int qpol_default_object_get_role_default(const qpol_policy_t *policy, const qpol_default_object_t * datum, const char **value) -{ - class_datum_t *internal_datum = NULL; - - if (policy == NULL || datum == NULL || value == NULL) { - if (value != NULL) - *value = NULL; - ERR(policy, "%s", strerror(EINVAL)); - errno = EINVAL; - return STATUS_ERR; - } - *value = NULL; - - /* The role default started in ver 27 */ - if (!qpol_policy_has_capability(policy, QPOL_CAP_DEFAULT_OBJECTS)) - return STATUS_SUCCESS; - - internal_datum = (class_datum_t *)datum; - - if (internal_datum->default_role == DEFAULT_SOURCE) { - *value = "source"; - } else if (internal_datum->default_role == DEFAULT_TARGET) { - *value = "target"; - } - return STATUS_SUCCESS; -} - -int qpol_default_object_get_type_default(const qpol_policy_t *policy, const qpol_default_object_t * datum, const char **value) -{ - class_datum_t *internal_datum = NULL; - - if (policy == NULL || datum == NULL || value == NULL) { - if (value != NULL) - *value = NULL; - ERR(policy, "%s", strerror(EINVAL)); - errno = EINVAL; - return STATUS_ERR; - } - *value = NULL; - - /* The type default started in ver 28 */ - if (!qpol_policy_has_capability(policy, QPOL_CAP_DEFAULT_TYPE)) - return STATUS_SUCCESS; - - internal_datum = (class_datum_t *)datum; - - if (internal_datum->default_type == DEFAULT_SOURCE) { - *value = "source"; - } else if (internal_datum->default_type == DEFAULT_TARGET) { - *value = "target"; - } - return STATUS_SUCCESS; -} - -int qpol_default_object_get_range_default(const qpol_policy_t *policy, const qpol_default_object_t * datum, const char **value) -{ - class_datum_t *internal_datum = NULL; - - if (policy == NULL || datum == NULL || value == NULL) { - if (value != NULL) - *value = NULL; - ERR(policy, "%s", strerror(EINVAL)); - errno = EINVAL; - return STATUS_ERR; - } - *value = NULL; - - /* The range default started in ver 27 */ - if (!qpol_policy_has_capability(policy, QPOL_CAP_DEFAULT_OBJECTS)) - return STATUS_SUCCESS; - - internal_datum = (class_datum_t *)datum; - - switch (internal_datum->default_range) { - case DEFAULT_SOURCE_LOW: - *value = "source low"; - break; - case DEFAULT_SOURCE_HIGH: - *value = "source high"; - break; - case DEFAULT_SOURCE_LOW_HIGH: - *value = "source low_high"; - break; - case DEFAULT_TARGET_LOW: - *value = "target low"; - break; - case DEFAULT_TARGET_HIGH: - *value = "target high"; - break; - case DEFAULT_TARGET_LOW_HIGH: - *value = "target low_high"; - break; - default: - break; - } - return STATUS_SUCCESS; -} - -/* As default objects are in classes use these, however will need to calc number of default objects manually in top.tcl*/ -int qpol_policy_get_default_object_iter(const qpol_policy_t *policy, qpol_iterator_t **iter) -{ - policydb_t *db; - int error = 0; - hash_state_t *hs = NULL; - - if (policy == NULL || iter == NULL) { - if (iter != NULL) - *iter = NULL; - ERR(policy, "%s", strerror(EINVAL)); - errno = EINVAL; - return STATUS_ERR; - } - - db = &policy->p->p; -/* - class_datum_t *cladatum; - sepol_security_class_t tclass; - char *class; - - for (tclass = 1; tclass <= db->p_classes.nprim; tclass++) { - cladatum = db->class_val_to_struct[tclass - 1]; - class = db->p_class_val_to_name[tclass - 1]; - - if (cladatum->default_user == DEFAULT_SOURCE) { - printf("default_user %s source;\n", class); - } else if (cladatum->default_user == DEFAULT_TARGET) { - printf("default_user %s target;\n", class); - } - - if (cladatum->default_role == DEFAULT_SOURCE) { - printf("default_role %s source;\n", class); - } else if (cladatum->default_role == DEFAULT_TARGET) { - printf("default_role %s target;\n", class); - } - - if (cladatum->default_type == DEFAULT_SOURCE) { - printf("default_type %s source;\n", class); - } else if (cladatum->default_type == DEFAULT_TARGET) { - printf("default_type %s target;\n", class); - } - - switch (cladatum->default_range) { - case DEFAULT_SOURCE_LOW: - printf("default_range %s source low;\n", class); - break; - case DEFAULT_SOURCE_HIGH: - printf("default_range %s source high;\n", class); - break; - case DEFAULT_SOURCE_LOW_HIGH: - printf("default_range %s source low_high;\n", class); - break; - case DEFAULT_TARGET_LOW: - printf("default_range %s target low;\n", class); - break; - case DEFAULT_TARGET_HIGH: - printf("default_range %s target high;\n", class); - break; - case DEFAULT_TARGET_LOW_HIGH: - printf("default_range %s target low_high;\n", class); - break; - default: - break; - } - } -*/ - hs = calloc(1, sizeof(hash_state_t)); - if (hs == NULL) { - error = errno; - ERR(policy, "%s", strerror(ENOMEM)); - errno = error; - return STATUS_ERR; - } - hs->table = &db->p_classes.table; - hs->node = (*(hs->table))->htable[0]; - - if (qpol_iterator_create(policy, (void *)hs, hash_state_get_cur, - hash_state_next, hash_state_end, hash_state_size, free, iter)) { - free(hs); - return STATUS_ERR; - } - - if (hs->node == NULL) - hash_state_next(*iter); - - return STATUS_SUCCESS; -} diff --git a/setools/policyrep/default.pxi b/setools/policyrep/default.pxi index 16c9dce..8aab637 100644 --- a/setools/policyrep/default.pxi +++ b/setools/policyrep/default.pxi @@ -1,5 +1,5 @@ # Copyright 2014, 2016 Tresys Technology, LLC -# Copyright 2016-2017, Chris PeBenito +# Copyright 2016-2018, Chris PeBenito # # This file is part of SETools. # @@ -18,70 +18,10 @@ # . # -# -# Factory functions -# -cdef DefaultIterator default_iterator_factory(SELinuxPolicy policy, qpol_iterator_t *iter): - """Factory function for default_* statement iterator.""" - i = DefaultIterator() - i.policy = policy - i.iter = iter - return i - - -cdef inline Default default_factory(SELinuxPolicy policy, ObjClass tclass, - const qpol_default_object_t *handle, user, role, type_, range_): - - """Factory function for creating default_* statement objects.""" - - if user: - obj = Default() - obj.policy = policy - obj.handle = handle - obj.ruletype = DefaultRuletype.default_user - obj.tclass = tclass - obj._default = DefaultValue[user] - return obj - - if role: - obj = Default() - obj.policy = policy - obj.handle = handle - obj.ruletype = DefaultRuletype.default_role - obj.tclass = tclass - obj._default = DefaultValue[role] - return obj - - if type_: - obj = Default() - obj.policy = policy - obj.handle = handle - obj.ruletype = DefaultRuletype.default_type - obj.tclass = tclass - obj._default = DefaultValue[type_] - return obj - - if range_: - # range_ is something like "source low_high" - rng = range_.split() - obj = RangeDefault() - obj.policy = policy - obj.handle = handle - obj.ruletype = DefaultRuletype.default_range - obj.tclass = tclass - obj._default = DefaultValue[rng[0]] - obj.default_range = DefaultRangeValue[rng[1]] - return obj - - raise ValueError("At least one of user, role, type_, or range_ must be specified.") - - -# -# Classes -# class DefaultRuletype(PolicyEnum): """Enumeration of default rule types.""" + default_user = 1 default_role = 2 default_type = 3 @@ -91,24 +31,47 @@ class DefaultRuletype(PolicyEnum): class DefaultValue(PolicyEnum): """Enumeration of default values.""" - source = 1 - target = 2 + + source = sepol.DEFAULT_SOURCE + target = sepol.DEFAULT_TARGET + + @classmethod + def from_default_range(cls, range_): + default_map = {sepol.DEFAULT_SOURCE_LOW: sepol.DEFAULT_SOURCE, + sepol.DEFAULT_SOURCE_HIGH: sepol.DEFAULT_SOURCE, + sepol.DEFAULT_SOURCE_LOW_HIGH: sepol.DEFAULT_SOURCE, + sepol.DEFAULT_TARGET_LOW: sepol.DEFAULT_TARGET, + sepol.DEFAULT_TARGET_HIGH: sepol.DEFAULT_TARGET, + sepol.DEFAULT_TARGET_LOW_HIGH: sepol.DEFAULT_TARGET} + + return cls(default_map[range_]) class DefaultRangeValue(PolicyEnum): """Enumeration of default range values.""" + low = 1 high = 2 low_high = 3 + @classmethod + def from_default_range(cls, range_): + default_map = {sepol.DEFAULT_SOURCE_LOW: 1, + sepol.DEFAULT_SOURCE_HIGH: 2, + sepol.DEFAULT_SOURCE_LOW_HIGH: 3, + sepol.DEFAULT_TARGET_LOW: 1, + sepol.DEFAULT_TARGET_HIGH: 2, + sepol.DEFAULT_TARGET_LOW_HIGH: 3} + + return cls(default_map[range_]) + cdef class Default(PolicySymbol): """Base class for default_* statements.""" cdef: - const qpol_default_object_t *handle public object ruletype public object tclass object _default @@ -116,10 +79,49 @@ cdef class Default(PolicySymbol): # the default object is not exposed as a Python # attribute, as it collides with CPython code - def _eq(self, Default other): - """Low-level equality check (C pointers).""" - return self.handle == other.handle \ - and self.ruletype == other.ruletype + @staticmethod + cdef factory(SELinuxPolicy policy, ObjClass tclass, user, role, type_, range_): + """Factory function for Default objects.""" + + if user: + obj = Default() + obj.policy = policy + obj.tclass = tclass + obj.ruletype = DefaultRuletype.default_user + obj._default = DefaultValue(user) + return obj + + if role: + obj = Default() + obj.policy = policy + obj.tclass = tclass + obj.ruletype = DefaultRuletype.default_role + obj._default = DefaultValue(role) + return obj + + if type_: + obj = Default() + obj.policy = policy + obj.tclass = tclass + obj.ruletype = DefaultRuletype.default_type + obj._default = DefaultValue(type_) + return obj + + if range_: + obj = DefaultRange() + obj.policy = policy + obj.ruletype = DefaultRuletype.default_range + obj.tclass = tclass + obj._default = DefaultValue.from_default_range(range_) + obj.default_range = DefaultRangeValue.from_default_range(range_) + return obj + + raise ValueError("At least one of user, role, type_, or range_ must be specified.") + + def __eq__(self, other): + return self.ruletype == other.ruletype \ + and self.tclass == other.tclass \ + and self.default == other.default def __str__(self): return "{0.ruletype} {0.tclass} {0.default};".format(self) @@ -139,7 +141,7 @@ cdef class Default(PolicySymbol): return str(self) -cdef class RangeDefault(Default): +cdef class DefaultRange(Default): """A default_range statement.""" @@ -148,103 +150,15 @@ cdef class RangeDefault(Default): def __str__(self): return "{0.ruletype} {0.tclass} {0.default} {0.default_range};".format(self) + def __eq__(self, other): + return self.ruletype == other.ruletype \ + and self.tclass == other.tclass \ + and self.default == other.default \ + and self.default_range == other.default_range -cdef class DefaultIterator: + def __hash__(self): + return hash("{0.ruletype}|{0.tclass}".format(self)) - """ - Iterate over all policy defaults. - - The low level policy groups default_* settings by object class. - Since each class can have up to four default_* statements, - this has a sub iterator which yields up to - four Default objects. - """ - - cdef: - qpol_iterator_t *iter - SELinuxPolicy policy - object sub_iter - - def __dealloc__(self): - if self.iter: - qpol_iterator_destroy(&self.iter) - - def __iter__(self): - return self - - def __next__(self): - cdef void *item - cdef const qpol_default_object_t *symbol - cdef const qpol_class_t *cls - cdef const char *user - cdef const char *role - cdef const char *type_ - cdef const char *range_ - - # drain sub-iterator first, if one exists - if self.sub_iter: - try: - return self.sub_iter.__next__() - except StopIteration: - # sub_iter completed, clear - self.sub_iter = None - - while not qpol_iterator_end(self.iter): - qpol_iterator_get_item(self.iter, &item) - qpol_iterator_next(self.iter) - symbol = item - - # qpol will essentially iterate over all classes - # and emit NULL for classes that don't set a default. - if qpol_default_object_get_class(self.policy.handle, symbol, &cls): - ex = LowLevelPolicyError("Error reading default's class: {}".format( - strerror(errno))) - ex.errno = errno - raise ex - - if cls: - tclass = class_factory(self.policy, cls) - else: - continue - - dfts = [] - if qpol_default_object_get_user_default(self.policy.handle, symbol, &user): - ex = LowLevelPolicyError("Error reading default's user: {}".format( - strerror(errno))) - ex.errno = errno - raise ex - elif user: - dfts.append(default_factory(self.policy, tclass, symbol, user, None, None, None)) - - if qpol_default_object_get_role_default(self.policy.handle, symbol, &role): - ex = LowLevelPolicyError("Error reading default's role: {}".format( - strerror(errno))) - ex.errno = errno - raise ex - elif role: - dfts.append(default_factory(self.policy, tclass, symbol, None, role, None, None)) - - if qpol_default_object_get_type_default(self.policy.handle, symbol, &type_): - ex = LowLevelPolicyError("Error reading default's type: {}".format( - strerror(errno))) - ex.errno = errno - raise ex - elif type_: - dfts.append(default_factory(self.policy, tclass, symbol, None, None, type_, None)) - - if qpol_default_object_get_range_default(self.policy.handle, symbol, &range_): - ex = LowLevelPolicyError("Error reading default's range: {}".format( - strerror(errno))) - ex.errno = errno - raise ex - elif range_: - dfts.append(default_factory(self.policy, tclass, symbol, None, None, None, range_)) - - if not dfts: - raise LowLevelPolicyError("Policy structure error: {} did not have any defaults.". - format(strerror(errno))) - - self.sub_iter = iter(dfts) - return self.sub_iter.__next__() - - raise StopIteration + def __lt__(self, other): + # this is used by Python sorting functions + return str(self) < str(other) diff --git a/setools/policyrep/libpolicyrep.pyx b/setools/policyrep/libpolicyrep.pyx index 74dc94f..c03f88f 100644 --- a/setools/policyrep/libpolicyrep.pyx +++ b/setools/policyrep/libpolicyrep.pyx @@ -184,16 +184,6 @@ cdef extern from "include/qpol/context_query.h": int qpol_context_get_type(const qpol_policy_t * policy, const qpol_context_t * context, const qpol_type_t ** type) int qpol_context_get_range(const qpol_policy_t * policy, const qpol_context_t * context, const qpol_mls_range_t ** range) -cdef extern from "include/qpol/default_object_query.h": - ctypedef struct qpol_default_object_t: - pass - int qpol_policy_get_default_object_iter(const qpol_policy_t *policy, qpol_iterator_t **iter) - int qpol_default_object_get_class(const qpol_policy_t *policy, const qpol_default_object_t *datum, const qpol_class_t **cls) - int qpol_default_object_get_user_default(const qpol_policy_t *policy, const qpol_default_object_t *datum, const char **value) - int qpol_default_object_get_role_default(const qpol_policy_t *policy, const qpol_default_object_t *datum, const char **value) - int qpol_default_object_get_type_default(const qpol_policy_t *policy, const qpol_default_object_t *datum, const char **value) - int qpol_default_object_get_range_default(const qpol_policy_t *policy, const qpol_default_object_t *datum, const char **value) - cdef extern from "include/qpol/ftrule_query.h": ctypedef struct qpol_filename_trans_t: pass diff --git a/setools/policyrep/objclass.pxi b/setools/policyrep/objclass.pxi index 3b9dce3..e118cf3 100644 --- a/setools/policyrep/objclass.pxi +++ b/setools/policyrep/objclass.pxi @@ -115,6 +115,20 @@ cdef class ObjClass(PolicySymbol): return qpol_iterator_factory(self.policy, iter, constraint_factory_iter) + def defaults(self): + """Iterator for the defaults for this object class.""" + if self.handle.default_user: + yield Default.factory(self.policy, self, self.handle.default_user, None, None, None) + + if self.handle.default_role: + yield Default.factory(self.policy, self, None, self.handle.default_role, None, None) + + if self.handle.default_type: + yield Default.factory(self.policy, self, None, None, self.handle.default_type, None) + + if self.handle.default_range: + yield Default.factory(self.policy, self, None, None, None, self.handle.default_range) + @property def perms(self): """The set of the object class's permissions.""" diff --git a/setools/policyrep/selinuxpolicy.pxi b/setools/policyrep/selinuxpolicy.pxi index ef903de..64c22a2 100644 --- a/setools/policyrep/selinuxpolicy.pxi +++ b/setools/policyrep/selinuxpolicy.pxi @@ -564,11 +564,8 @@ cdef class SELinuxPolicy: def defaults(self): """Iterator over all default_* statements.""" - cdef qpol_iterator_t *iter - if qpol_policy_get_default_object_iter(self.handle, &iter): - raise MemoryError - - return default_iterator_factory(self, iter) + for cls in ObjClassHashtabIterator.factory(self, &self.handle.p.p.symtab[sepol.SYM_CLASSES].table): + yield from cls.defaults() def levels(self): """Iterator which yields all level declarations.""" diff --git a/setup.py b/setup.py index a943ecb..8f9890b 100644 --- a/setup.py +++ b/setup.py @@ -72,7 +72,6 @@ ext_py_mods = [Extension('setools.policyrep.libpolicyrep', 'libqpol/cond_query.c', 'libqpol/constraint_query.c', 'libqpol/context_query.c', - 'libqpol/default_object_query.c', 'libqpol/ftrule_query.c', 'libqpol/iterator.c', 'libqpol/mlsrule_query.c',