User: Refactor to load attributes on construction.

This commit is contained in:
Chris PeBenito 2018-08-06 15:59:54 -04:00
parent 5de464a226
commit 08c2ee0cdc

View File

@ -22,59 +22,68 @@ cdef class User(PolicySymbol):
"""A user.""" """A user."""
cdef sepol.user_datum_t *handle cdef:
uintptr_t key
readonly str name
readonly frozenset roles
Level _level
Range _range
@staticmethod @staticmethod
cdef factory(SELinuxPolicy policy, sepol.user_datum_t *symbol): cdef inline User factory(SELinuxPolicy policy, sepol.user_datum_t *symbol):
"""Factory function for constructing User objects.""" """Factory function for constructing User objects."""
u = User() cdef User u = User.__new__(User)
u.policy = policy u.policy = policy
u.handle = symbol u.key = <uintptr_t>symbol
return u u.name = policy.user_value_to_name(symbol.s.value - 1)
def __str__(self):
return self.policy.user_value_to_name(self.handle.s.value - 1)
def _eq(self, User other):
"""Low-level equality check (C pointers)."""
return self.handle == other.handle
@property
def roles(self):
# object_r is implicitly added to all roles by the compiler. # object_r is implicitly added to all roles by the compiler.
# technically it is incorrect to skip it, but policy writers # technically it is incorrect to skip it, but policy writers
# and analysts don't expect to see it in results, and it # and analysts don't expect to see it in results, and it
# will confuse, especially for role set equality user queries. # will confuse, especially for role set equality user queries.
return set(r for r in RoleEbitmapIterator.factory(self.policy, &self.handle.roles.roles) u.roles = frozenset(r for r in RoleEbitmapIterator.factory(policy, &symbol.roles.roles)
if r != "object_r") if r != "object_r")
if policy.mls:
u._level = Level.factory(policy, &symbol.exp_dfltlevel)
u._range = Range.factory(policy, &symbol.exp_range)
return u
def __str__(self):
return self.name
def _eq(self, User other):
"""Low-level equality check (C pointers)."""
return self.key == other.key
@property @property
def mls_level(self): def mls_level(self):
"""The user's default MLS level.""" """The user's default MLS level."""
if not self.policy.mls: if self._level:
return self._level
else:
raise MLSDisabled raise MLSDisabled
return Level.factory(self.policy, &self.handle.exp_dfltlevel)
@property @property
def mls_range(self): def mls_range(self):
"""The user's MLS range.""" """The user's MLS range."""
if not self.policy.mls: if self._range:
return self._range
else:
raise MLSDisabled raise MLSDisabled
return Range.factory(self.policy, &self.handle.exp_range)
def statement(self): def statement(self):
roles = list(str(r) for r in self.roles) roles = list(str(r) for r in self.roles)
stmt = "user {0} roles ".format(self) stmt = "user {0} roles ".format(self.name)
if len(roles) > 1: if len(roles) > 1:
stmt += "{{ {0} }}".format(' '.join(roles)) stmt += "{{ {0} }}".format(' '.join(roles))
else: else:
stmt += roles[0] stmt += roles[0]
try: if self._level:
stmt += " level {0.mls_level} range {0.mls_range};".format(self) stmt += " level {0.mls_level} range {0.mls_range};".format(self)
except MLSDisabled: else:
stmt += ";" stmt += ";"
return stmt return stmt