Skip to content
Open
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
2 changes: 2 additions & 0 deletions dissect/database/ese/ntds/objects/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
from dissect.database.ese.ntds.objects.msds_resourcepropertylist import MSDSResourcePropertyList
from dissect.database.ese.ntds.objects.msds_shadowprincipalcontainer import MSDSShadowPrincipalContainer
from dissect.database.ese.ntds.objects.msds_valuetype import MSDSValueType
from dissect.database.ese.ntds.objects.msfve_recoveryinformation import MSFVERecoveryInformation
from dissect.database.ese.ntds.objects.msimaging_psps import MSImagingPSPs
from dissect.database.ese.ntds.objects.mskds_provserverconfiguration import MSKDSProvServerConfiguration
from dissect.database.ese.ntds.objects.msmqenterprisesettings import MSMQEnterpriseSettings
Expand Down Expand Up @@ -174,6 +175,7 @@
"MSDSResourcePropertyList",
"MSDSShadowPrincipalContainer",
"MSDSValueType",
"MSFVERecoveryInformation",
"MSImagingPSPs",
"MSKDSProvServerConfiguration",
"MSMQEnterpriseSettings",
Expand Down
7 changes: 7 additions & 0 deletions dissect/database/ese/ntds/objects/computer.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from typing import TYPE_CHECKING

from dissect.database.ese.ntds.objects.msfve_recoveryinformation import MSFVERecoveryInformation
from dissect.database.ese.ntds.objects.user import User

if TYPE_CHECKING:
Expand All @@ -22,6 +23,12 @@ class Computer(User):
def __repr_body__(self) -> str:
return f"name={self.name!r}"

def fve_recovery_information(self) -> Iterator[MSFVERecoveryInformation]:
"""Return the BitLocker recovery information objects associated with this computer."""
for child in self.children():
if isinstance(child, MSFVERecoveryInformation):
yield child

def managed_by(self) -> Iterator[Object]:
"""Return the objects that manage this computer."""
self._assert_local()
Expand Down
45 changes: 45 additions & 0 deletions dissect/database/ese/ntds/objects/msfve_recoveryinformation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from __future__ import annotations

from typing import TYPE_CHECKING
from uuid import UUID

from dissect.database.ese.ntds.objects.top import Top

if TYPE_CHECKING:
from dissect.database.ese.ntds.objects import Computer


class MSFVERecoveryInformation(Top):
"""Represents a msFVE-RecoveryInformation object in the Active Directory.

References:
- https://learn.microsoft.com/en-us/windows/win32/adschema/c-msfve-recoveryinformation
"""

__object_class__ = "msFVE-RecoveryInformation"

@property
def volume_guid(self) -> UUID:
"""Return the volume GUID associated with this recovery information."""
return UUID(bytes_le=self.get("msFVE-VolumeGuid"))

@property
def recovery_guid(self) -> UUID:
"""Return the recovery GUID associated with this recovery information."""
return UUID(bytes_le=self.get("msFVE-RecoveryGuid"))

@property
def recovery_password(self) -> str:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def recovery_password(self) -> str:
def recovery_password(self) -> str | None:

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Either change the typing, or if the msFVE-RecoveryPassword attribute is always present, always return something

"""Return the recovery password associated with this recovery information."""
return self.get("msFVE-RecoveryPassword")

@property
def key_package(self) -> bytes | None:
"""Return the key package associated with this recovery information, if any."""
return self.get("msFVE-KeyPackage")

def computer(self) -> Computer:
"""Return the computer object associated with this recovery information."""
if (parent := self.parent()) is None:
raise ValueError("msFVE-RecoveryInformation object has no parent computer")
return parent