Skip to content

Commit

Permalink
Fixed _decompose error in Python 3.11
Browse files Browse the repository at this point in the history
  • Loading branch information
ly4k committed Sep 1, 2023
1 parent 8e6ac36 commit d7291d1
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 21 deletions.
10 changes: 2 additions & 8 deletions certipy/commands/find.py
Original file line number Diff line number Diff line change
Expand Up @@ -778,10 +778,7 @@ def security_to_bloodhound_aces(self, security: ActiveDirectorySecurity) -> List
is_inherited = rights["inherited"]
principal = self.connection.lookup_sid(sid)

try:
standard_rights = list(rights["rights"])
except:
standard_rights = rights["rights"].to_list()
standard_rights = rights["rights"].to_list()

for right in standard_rights:
aces.append(
Expand Down Expand Up @@ -1077,10 +1074,7 @@ def get_ca_permissions(self, ca: LDAPEntry):
for sid, rights in security.aces.items():
if self.hide_admins and is_admin_sid(sid):
continue
try:
ca_rights = list(rights["rights"])
except:
ca_rights = rights["rights"].to_list()
ca_rights = rights["rights"].to_list()
for ca_right in ca_rights:
if ca_right not in access_rights:
access_rights[ca_right] = [
Expand Down
8 changes: 3 additions & 5 deletions certipy/lib/constants.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import enum

from certipy.lib.structs import IntFlag
from certipy.lib.structs import IntFlag, _decompose

# https://github.com/fox-it/BloodHound.py/blob/d665959c58d881900378040e6670fa12f801ccd4/bloodhound/ad/utils.py#L36
WELLKNOWN_SIDS = {
Expand Down Expand Up @@ -237,7 +235,7 @@ class ACTIVE_DIRECTORY_RIGHTS(IntFlag):

def to_list(self):
cls = self.__class__
members, _ = enum._decompose(cls, self._value_)
members, _ = _decompose(cls, self._value_)
filtered_members = []
for member in members:
found = False
Expand All @@ -262,7 +260,7 @@ def to_list(self):
if self._value_ == self.GENERIC_ALL:
return [CERTIFICATE_RIGHTS(self.GENERIC_ALL)]

members, _ = enum._decompose(cls, self._value_)
members, _ = _decompose(cls, self._value_)
filtered_members = []
for member in members:
if str(member) == str(member.value):
Expand Down
43 changes: 36 additions & 7 deletions certipy/lib/structs.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,53 @@

from certipy.lib.formatting import to_pascal_case

def _high_bit(value):
"""returns index of highest bit, or -1 if value is zero or negative"""
return value.bit_length() - 1

def _decompose(flag, value):
"""Extract all members from the value."""
# _decompose is only called if the value is not named
not_covered = value
negative = value < 0
members = []
for member in flag:
member_value = member.value
if member_value and member_value & value == member_value:
members.append(member)
not_covered &= ~member_value
if not negative:
tmp = not_covered
while tmp:
flag_value = 2 ** _high_bit(tmp)
if flag_value in flag._value2member_map_:
members.append(flag._value2member_map_[flag_value])
not_covered &= ~flag_value
tmp &= ~flag_value
if not members and value in flag._value2member_map_:
members.append(flag._value2member_map_[value])
members.sort(key=lambda m: m._value_, reverse=True)
if len(members) > 1 and members[0].value == value:
# we have the breakdown, don't need the value member itself
members.pop(0)
return members, not_covered



class IntFlag(enum.IntFlag):
def to_list(self):
cls = self.__class__
members, _ = enum._decompose(cls, self._value_)
members, _ = _decompose(cls, self._value_)
return members

def to_str_list(self):
try:
return list(map(lambda x: str(x), list(self)))
except:
return list(map(lambda x: str(x), self.to_list()))
return list(map(lambda x: str(x), self.to_list()))

def __str__(self):
cls = self.__class__
if self._name_ is not None:
return "%s" % (to_pascal_case(self._name_))
members, _ = enum._decompose(cls, self._value_)
members, _ = _decompose(cls, self._value_)
if len(members) == 1 and members[0]._name_ is None:
return "%r" % (members[0]._value_)
else:
Expand All @@ -40,7 +69,7 @@ def __str__(self):
cls = self.__class__
if self._name_ is not None:
return "%s" % (to_pascal_case(self._name_))
members, _ = enum._decompose(cls, self._value_)
members, _ = _decompose(cls, self._value_)
if len(members) == 1 and members[0]._name_ is None:
return "%r" % (members[0]._value_)
else:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setup(
name="certipy-ad",
version="4.7.0",
version="4.8.0",
license="MIT",
author="ly4k",
url="https://github.com/ly4k/Certipy",
Expand Down

0 comments on commit d7291d1

Please sign in to comment.