diff --git a/seinfo b/seinfo index 8d14983..0186c4c 100755 --- a/seinfo +++ b/seinfo @@ -155,6 +155,48 @@ try: else: q = setools.userquery.UserQuery(p) + else: + if p.mls: + mls = "enabled" + else: + mls = "disabled" + + print("Statistics for policy file: {0}".format(args.policy)) + print("Policy Version: {0} (MLS {1})".format(p.version, mls)) + print(" Classes: {0:7} Permissions: {1:7}".format( + p.class_count, p.permission_count)) + print(" Sensitivities: {0:7} Categories: {1:7}".format( + p.level_count, p.category_count)) + print(" Types: {0:7} Attributes: {1:7}".format( + p.type_count, p.attribute_count)) + print(" Users: {0:7} Roles: {1:7}".format( + p.user_count, p.role_count)) + print(" Booleans: {0:7} Cond. Expr.: {1:7}".format( + p.boolean_count, p.conditional_count)) + print(" Allow: {0:7} Neverallow: {1:7}".format( + p.allow_count, p.neverallow_count)) + print(" Auditallow: {0:7} Dontaudit: {1:7}".format( + p.auditallow_count, p.dontaudit_count)) + print(" Type_trans: {0:7} Type_change: {1:7}".format( + p.type_transition_count, p.type_change_count)) + print(" Type_member: {0:7} Range_trans: {1:7}".format( + p.type_member_count, p.range_transition_count)) + print(" Role allow: {0:7} Role_trans: {1:7}".format( + p.role_allow_count, p.role_transition_count)) + print(" Constraints: {0:7} Validatetrans: {1:7}".format( + p.constraint_count, p.validatetrans_count)) + print(" MLS Constrain: {0:7} MLS Val. Tran: {1:7}".format( + p.mlsconstraint_count, p.mlsvalidatetrans_count)) + print(" Initial SIDs: {0:7} Fs_use: {1:7}".format( + p.initialsids_count, p.fs_use_count)) + print(" Genfscon: {0:7} Portcon: {1:7}".format( + p.genfscon_count, p.portcon_count)) + print(" Netifcon: {0:7} Nodecon: {1:7}".format( + p.netifcon_count, p.nodecon_count)) + print(" Permissives: {0:7} Polcap: {1:7}".format( + p.permissives_count, p.polcap_count)) + sys.exit(0) + for item in sorted(q.results()): if args.expand: print(item.statement()) diff --git a/setools/policyrep/__init__.py b/setools/policyrep/__init__.py index 6720ab1..3e4e04d 100644 --- a/setools/policyrep/__init__.py +++ b/setools/policyrep/__init__.py @@ -20,6 +20,7 @@ # The idea is that this is module provides convenient # abstractions and methods for accessing the policy # structures. +from itertools import chain from . import qpol @@ -70,6 +71,10 @@ class SELinuxPolicy(object): raise OSError( "Error opening policy file \"{0}\": {1}".format(policyfile, err)) + # + # Policy properties + # + @property def handle_unknown(self): """The handle unknown permissions setting (allow,deny,reject)""" @@ -85,6 +90,175 @@ class SELinuxPolicy(object): """The policy database version (e.g. v29)""" return self.policy.version() + # + # Policy statistics + # + + @property + def allow_count(self): + """The number of (type) allow rules.""" + return self.policy.avrule_allow_count() + + @property + def attribute_count(self): + """The number of (type) attributes.""" + return sum(1 for _ in self.attributes()) + + @property + def auditallow_count(self): + """The number of auditallow rules.""" + return self.policy.avrule_auditallow_count() + + @property + def boolean_count(self): + """The number of Booleans.""" + return self.policy.bool_count() + + @property + def category_count(self): + """The number of categories.""" + return self.policy.cat_count() + + @property + def class_count(self): + """The number of object classes.""" + return self.policy.class_count() + + @property + def common_count(self): + """The number of common permission sets.""" + return self.policy.common_count() + + @property + def conditional_count(self): + """The number of conditionals.""" + return self.policy.cond_count() + + @property + def constraint_count(self): + """The number of standard constraints.""" + return sum(1 for _ in self.constraints()) + + @property + def dontaudit_count(self): + """The number of dontaudit rules.""" + return self.policy.avrule_dontaudit_count() + + @property + def fs_use_count(self): + """fs_use_* statements.""" + return self.policy.fs_use_count() + + @property + def genfscon_count(self): + """The number of genfscon statements.""" + return self.policy.genfscon_count() + + @property + def initialsids_count(self): + """The number of initial sid statements.""" + return self.policy.isid_count() + + @property + def level_count(self): + """The number of levels.""" + return self.policy.level_count() + + @property + def mlsconstraint_count(self): + """The number of MLS constraints.""" + return sum(1 for _ in self.mlsconstraints()) + + @property + def mlsvalidatetrans_count(self): + """The number of MLS validatetrans.""" + return sum(1 for _ in self.mlsvalidatetrans()) + + @property + def netifcon_count(self): + """The number of netifcon statements.""" + return self.policy.netifcon_count() + + @property + def neverallow_count(self): + """The number of neverallow rules.""" + return self.policy.avrule_neverallow_count() + + @property + def nodecon_count(self): + """The number of nodecon statements.""" + return self.policy.nodecon_count() + + @property + def permission_count(self): + """The number of permissions.""" + return sum(len(c.perms) for c in chain(self.commons(), self.classes())) + + @property + def permissives_count(self): + """The number of permissive types.""" + return self.policy.permissive_count() + + @property + def polcap_count(self): + """The number of policy capabilities.""" + return self.policy.polcap_count() + + @property + def portcon_count(self): + """The number of portcon statements.""" + return self.policy.portcon_count() + + @property + def range_transition_count(self): + """The number of range_transition rules.""" + return self.policy.range_trans_count() + + @property + def role_count(self): + """The number of roles.""" + return self.policy.role_count() + + @property + def role_allow_count(self): + """The number of (role) allow rules.""" + return self.policy.role_allow_count() + + @property + def role_transition_count(self): + """The number of role_transition rules.""" + return self.policy.role_trans_count() + + @property + def type_count(self): + """The number of types.""" + return sum(1 for _ in self.types()) + + @property + def type_change_count(self): + """The number of type_change rules.""" + return self.policy.terule_change_count() + + @property + def type_member_count(self): + """The number of type_member rules.""" + return self.policy.terule_member_count() + + @property + def type_transition_count(self): + """The number of type_transition rules.""" + return self.policy.terule_trans_count() + self.policy.filename_trans_count() + + @property + def user_count(self): + """The number of users.""" + return self.policy.user_count() + + @property + def validatetrans_count(self): + """The number of validatetrans.""" + return sum(1 for _ in self.validatetrans()) + # # Policy components lookup functions # @@ -105,6 +279,15 @@ class SELinuxPolicy(object): # Policy components generators # + def attributes(self): + """Generator which yields all (type) attributes.""" + + # libqpol unfortunately iterates over attributes and aliases + for type_ in self.policy.type_iter(): + t = typeattr.TypeAttr(self.policy, type_) + if t.isattr: + yield t + def classes(self): """Generator which yields all object classes.""" @@ -206,6 +389,22 @@ class SELinuxPolicy(object): if c.ismls: yield c + def mlsvalidatetrans(self): + """Generator which yields all mlsvalidatetrans.""" + + for validatetrans in self.policy.validatetrans_iter(): + v = constraint.ValidateTrans(self.policy, validatetrans) + if v.ismls: + yield v + + def validatetrans(self): + """Generator which yields all validatetrans.""" + + for validatetrans in self.policy.validatetrans_iter(): + v = constraint.ValidateTrans(self.policy, validatetrans) + if not v.ismls: + yield v + # # In-policy Labeling statement generators # diff --git a/setools/policyrep/constraint.py b/setools/policyrep/constraint.py index 1399232..cc8d70e 100644 --- a/setools/policyrep/constraint.py +++ b/setools/policyrep/constraint.py @@ -190,7 +190,7 @@ class Constraint(symbol.PolicySymbol): return objclass.ObjClass(self.policy, self.qpol_symbol.object_class(self.policy)) -class ValidateTrans(symbol.PolicySymbol): +class ValidateTrans(Constraint): """A validate transition rule.""" pass diff --git a/setools/policyrep/qpol.i b/setools/policyrep/qpol.i index 53a60ca..7e10bf7 100644 --- a/setools/policyrep/qpol.i +++ b/setools/policyrep/qpol.i @@ -359,6 +359,18 @@ typedef enum qpol_capability return NULL; }; + size_t type_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_type_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject role_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_role_from_void) %} qpol_iterator_t *role_iter() { @@ -373,6 +385,18 @@ typedef enum qpol_capability return NULL; }; + size_t role_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_role_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject level_iter(); qpol_iterator_t *level_iter() { BEGIN_EXCEPTION @@ -385,6 +409,19 @@ typedef enum qpol_capability fail: return NULL; }; + + size_t level_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_level_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject cat_iter(); qpol_iterator_t *cat_iter() { BEGIN_EXCEPTION @@ -397,6 +434,19 @@ typedef enum qpol_capability fail: return NULL; }; + + size_t cat_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_cat_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject user_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_user_from_void) %} qpol_iterator_t *user_iter() { @@ -411,6 +461,19 @@ typedef enum qpol_capability return NULL; }; + size_t user_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_user_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + %newobject bool_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_bool_from_void) %} qpol_iterator_t *bool_iter() { @@ -425,6 +488,18 @@ typedef enum qpol_capability return NULL; }; + size_t bool_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_bool_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject class_iter(char*); %pythoncode %{ @QpolGenerator(_qpol.qpol_class_from_void) %} qpol_iterator_t *class_iter(char *perm=NULL) { @@ -445,6 +520,18 @@ typedef enum qpol_capability return NULL; }; + size_t class_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_class_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject common_iter(char*); %pythoncode %{ @QpolGenerator(_qpol.qpol_common_from_void) %} qpol_iterator_t *common_iter(char *perm=NULL) { @@ -465,6 +552,18 @@ typedef enum qpol_capability return NULL; }; + size_t common_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_common_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject fs_use_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_fs_use_from_void) %} qpol_iterator_t *fs_use_iter() { @@ -479,6 +578,18 @@ typedef enum qpol_capability return NULL; }; + size_t fs_use_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_fs_use_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject genfscon_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_genfscon_from_void) %} qpol_iterator_t *genfscon_iter() { @@ -493,6 +604,18 @@ typedef enum qpol_capability return NULL; }; + size_t genfscon_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_genfscon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject isid_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_isid_from_void) %} qpol_iterator_t *isid_iter() { @@ -507,6 +630,18 @@ typedef enum qpol_capability return NULL; }; + size_t isid_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_isid_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject netifcon_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_netifcon_from_void) %} qpol_iterator_t *netifcon_iter() { @@ -521,6 +656,18 @@ typedef enum qpol_capability return NULL; }; + size_t netifcon_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_netifcon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject nodecon_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_nodecon_from_void) %} qpol_iterator_t *nodecon_iter() { @@ -535,6 +682,18 @@ typedef enum qpol_capability return NULL; }; + size_t nodecon_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_nodecon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject portcon_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_portcon_from_void) %} qpol_iterator_t *portcon_iter() { @@ -549,6 +708,18 @@ typedef enum qpol_capability return NULL; }; + size_t portcon_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_portcon_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject constraint_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_constraint_from_void) %} qpol_iterator_t *constraint_iter() { @@ -563,6 +734,18 @@ typedef enum qpol_capability return NULL; }; + size_t constraint_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_constraint_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject validatetrans_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_validatetrans_from_void) %} qpol_iterator_t *validatetrans_iter() { @@ -577,6 +760,18 @@ typedef enum qpol_capability return NULL; }; + size_t validatetrans_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_validatetrans_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject role_allow_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_role_allow_from_void) %} qpol_iterator_t *role_allow_iter() { @@ -591,6 +786,18 @@ typedef enum qpol_capability return NULL; }; + size_t role_allow_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_role_allow_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject role_trans_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_role_trans_from_void) %} qpol_iterator_t *role_trans_iter() { @@ -605,6 +812,18 @@ typedef enum qpol_capability return NULL; }; + size_t role_trans_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_role_trans_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject range_trans_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_range_trans_from_void) %} qpol_iterator_t *range_trans_iter() { @@ -619,6 +838,18 @@ typedef enum qpol_capability return NULL; }; + size_t range_trans_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_range_trans_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject avrule_iter(int); %pythoncode %{ @QpolGenerator(_qpol.qpol_avrule_from_void) %} qpol_iterator_t *avrule_iter() { @@ -638,6 +869,58 @@ typedef enum qpol_capability return NULL; }; + size_t avrule_allow_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_avrule_iter(self, QPOL_RULE_ALLOW, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + size_t avrule_auditallow_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_avrule_iter(self, QPOL_RULE_AUDITALLOW, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + size_t avrule_neverallow_count() { + if (qpol_policy_has_capability(self, QPOL_CAP_NEVERALLOW)) { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_avrule_iter(self, QPOL_RULE_NEVERALLOW, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + } else { + return 0; + } + fail: + return 0; + }; + + size_t avrule_dontaudit_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_avrule_iter(self, QPOL_RULE_DONTAUDIT, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject terule_iter(int); %pythoncode %{ @QpolGenerator(_qpol.qpol_terule_from_void) %} qpol_iterator_t *terule_iter() { @@ -654,6 +937,42 @@ typedef enum qpol_capability return NULL; }; + size_t terule_trans_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_terule_iter(self, QPOL_RULE_TYPE_TRANS, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + size_t terule_change_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_terule_iter(self, QPOL_RULE_TYPE_CHANGE, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + + size_t terule_member_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_terule_iter(self, QPOL_RULE_TYPE_MEMBER, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject cond_iter(); qpol_iterator_t *cond_iter() { BEGIN_EXCEPTION @@ -666,6 +985,19 @@ typedef enum qpol_capability fail: return NULL; }; + + size_t cond_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_cond_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject filename_trans_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_filename_trans_from_void) %} qpol_iterator_t *filename_trans_iter() { @@ -680,6 +1012,18 @@ typedef enum qpol_capability return NULL; }; + size_t filename_trans_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_filename_trans_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject permissive_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_type_from_void) %} qpol_iterator_t *permissive_iter() { @@ -694,6 +1038,18 @@ typedef enum qpol_capability return NULL; }; + size_t permissive_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_permissive_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject typebounds_iter(); qpol_iterator_t *typebounds_iter() { BEGIN_EXCEPTION @@ -706,6 +1062,19 @@ typedef enum qpol_capability fail: return NULL; }; + + size_t typebounds_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_typebounds_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + %newobject polcap_iter(); %pythoncode %{ @QpolGenerator(_qpol.qpol_polcap_from_void) %} qpol_iterator_t *polcap_iter() { @@ -719,6 +1088,19 @@ typedef enum qpol_capability fail: return NULL; }; + + size_t polcap_count() { + qpol_iterator_t *iter; + size_t count = 0; + if (qpol_policy_get_polcap_iter(self, &iter)) { + SWIG_exception(SWIG_MemoryError, "Out of Memory"); + } + qpol_iterator_get_size(iter, &count); + return count; + fail: + return 0; + }; + }; /* qpol iterator */