diff --git a/src/ldaptool/decode/_decoder.py b/src/ldaptool/decode/_decoder.py index ad36bf9..3027f44 100644 --- a/src/ldaptool/decode/_decoder.py +++ b/src/ldaptool/decode/_decoder.py @@ -100,6 +100,13 @@ class Attribute: except Exception: return + def _try_decode_grouptype(self) -> None: + if self.utf8_clean: + try: + self.decoded = _types.grouptype.parse(self.utf8_clean.strip()) + except Exception: + return + def _try_decode(self, args: Arguments) -> None: if self.name in ("objectSid", "securityIdentifier"): self._try_decode_sid() @@ -115,6 +122,8 @@ class Attribute: self._try_decode_timestamp(args) elif self.name == "userAccountControl": self._try_decode_uac() + elif self.name == "groupType": + self._try_decode_grouptype() @property def _base64_value(self) -> str: diff --git a/src/ldaptool/decode/_types/__init__.py b/src/ldaptool/decode/_types/__init__.py index 10adf6c..e60d093 100644 --- a/src/ldaptool/decode/_types/__init__.py +++ b/src/ldaptool/decode/_types/__init__.py @@ -1,8 +1,9 @@ from __future__ import annotations -from . import sid, timestamp, uac +from . import grouptype, sid, timestamp, uac __all__ = [ + "grouptype", "sid", "timestamp", "uac", diff --git a/src/ldaptool/decode/_types/grouptype.py b/src/ldaptool/decode/_types/grouptype.py new file mode 100644 index 0000000..fb5ad1a --- /dev/null +++ b/src/ldaptool/decode/_types/grouptype.py @@ -0,0 +1,29 @@ +from __future__ import annotations + +import enum +import typing + + +class GroupTypeFlags(enum.IntFlag): + SYSTEM = 0x00000001 + SCOPE_GLOBAL = 0x00000002 + SCOPE_DOMAIN = 0x00000004 + SCOPE_UNIVERSAL = 0x00000008 + APP_BASIC = 0x00000010 + APP_QUERY = 0x00000020 + SECURITY = 0x80000000 # otherwise distribution + + def flags(self) -> list[GroupTypeFlags]: + # ignore "uncovered" bits for now + value = self.value + members = [] + for member in GroupTypeFlags: + member_value = member.value + if member_value and member_value & value == member_value: + members.append(member) + return members + + +def parse(value: str) -> str: + members = GroupTypeFlags(int(value)).flags() + return ", ".join(typing.cast(str, member.name) for member in members)