Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion dissect/database/ese/ntds/objects/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from typing import TYPE_CHECKING

from dissect.database.ese.ntds.objects.organizationalperson import OrganizationalPerson
from dissect.database.ese.ntds.util import UserAccountControl
from dissect.database.ese.ntds.util import SAMAccountType, UserAccountControl

if TYPE_CHECKING:
from collections.abc import Iterator
Expand All @@ -29,6 +29,11 @@ def sam_account_name(self) -> str:
"""Return the user's sAMAccountName."""
return self.get("sAMAccountName")

@property
def sam_account_type(self) -> SAMAccountType:
"""Return the user's sAMAccountType."""
return self.get("sAMAccountType")

@property
def primary_group_id(self) -> str | None:
"""Return the user's primaryGroupID."""
Expand Down
16 changes: 15 additions & 1 deletion dissect/database/ese/ntds/util.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

import struct
from enum import IntFlag
from enum import IntEnum, IntFlag
from typing import TYPE_CHECKING, Any
from uuid import UUID

Expand Down Expand Up @@ -136,6 +136,19 @@ class UserAccountControl(IntFlag):
TRUSTED_TO_AUTHENTICATE_FOR_DELEGATION = 0x01000000


class SAMAccountType(IntEnum):
SAM_DOMAIN_OBJECT = 0x0
SAM_GROUP_OBJECT = 0x10000000
SAM_NON_SECURITY_GROUP_OBJECT = 0x10000001
SAM_ALIAS_OBJECT = 0x20000000
SAM_NON_SECURITY_ALIAS_OBJECT = 0x20000001
SAM_USER_OBJECT = 0x30000000
SAM_MACHINE_ACCOUNT = 0x30000001
SAM_TRUST_ACCOUNT = 0x30000002
SAM_APP_BASIC_GROUP = 0x40000000
SAM_APP_QUERY_GROUP = 0x40000001


class SearchFlags(IntFlag):
Indexed = 0x00000001
ContainerIndexed = 0x00000002
Expand Down Expand Up @@ -274,6 +287,7 @@ def _decode_supplemental_credentials(db: Database, value: bytes) -> dict[str, by
"instanceType": (lambda db, value: int(value), lambda db, value: InstanceType(int(value))),
"systemFlags": (lambda db, value: int(value), lambda db, value: SystemFlags(int(value))),
"searchFlags": (lambda db, value: int(value), lambda db, value: SearchFlags(int(value))),
"sAMAccountType": (lambda db, value: int(value), lambda db, value: SAMAccountType(int(value))),
"userAccountControl": (lambda db, value: int(value), lambda db, value: UserAccountControl(int(value))),
"objectGUID": (lambda db, value: value.bytes_le, lambda db, value: UUID(bytes_le=value)),
"badPasswordTime": (None, lambda db, value: wintimestamp(int(value))),
Expand Down
3 changes: 3 additions & 0 deletions tests/ese/ntds/test_ntds.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import pytest

from dissect.database.ese.ntds.objects import Computer, Group, Server, SubSchema, User
from dissect.database.ese.ntds.util import SAMAccountType

if TYPE_CHECKING:
from dissect.database.ese.ntds import NTDS
Expand Down Expand Up @@ -87,6 +88,7 @@ def test_users(goad: NTDS) -> None:
]

assert users[3].distinguished_name == "CN=BRANDON.STARK,CN=USERS,DC=NORTH,DC=SEVENKINGDOMS,DC=LOCAL"
assert users[3].sam_account_type == SAMAccountType.SAM_USER_OBJECT
assert users[3].cn == "brandon.stark"
assert users[3].city == "Winterfell"

Expand All @@ -105,6 +107,7 @@ def test_computers(goad: NTDS) -> None:
computers: list[Computer] = sorted(goad.computers(), key=lambda x: x.name)
assert len(computers) == 3
assert computers[0].name == "CASTELBLACK"
assert computers[0].sam_account_type == SAMAccountType.SAM_MACHINE_ACCOUNT
assert computers[1].name == "KINGSLANDING"
assert computers[2].name == "WINTERFELL"

Expand Down
Loading