1212 from collections .abc import Callable
1313
1414 from dissect .database .ese .ntds .database import Database
15+ from dissect .database .ese .ntds .objects import Object
1516
1617
1718# https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adts/7cda533e-d7a4-4aec-a517-91d02ff4a1aa
@@ -144,6 +145,21 @@ class SearchFlags(IntFlag):
144145 Confidential = 0x00000080
145146
146147
148+ def _pek_decrypt (db : Database , value : bytes ) -> bytes :
149+ """Decrypt a PEK-encrypted blob using the database's PEK, if it's unlocked.
150+
151+ Args:
152+ value: The PEK-encrypted data blob.
153+
154+ Returns:
155+ The decrypted data blob.
156+ """
157+ if not db .data .pek .unlocked :
158+ return value
159+
160+ return db .data .pek .decrypt (value )
161+
162+
147163ATTRIBUTE_ENCODE_DECODE_MAP : dict [
148164 str , tuple [Callable [[Database , Any ], Any ] | None , Callable [[Database , Any ], Any ] | None ]
149165] = {
@@ -162,8 +178,23 @@ class SearchFlags(IntFlag):
162178 None ,
163179 lambda db , value : float ("inf" ) if int (value ) == ((1 << 63 ) - 1 ) else wintimestamp (int (value )),
164180 ),
181+ # Protected attributes
182+ "unicodePwd" : (None , _pek_decrypt ),
183+ "dBCSPwd" : (None , _pek_decrypt ),
184+ "ntPwdHistory" : (None , _pek_decrypt ),
185+ "lmPwdHistory" : (None , _pek_decrypt ),
186+ "supplementalCredentials" : (None , _pek_decrypt ),
187+ "currentValue" : (None , _pek_decrypt ),
188+ "priorValue" : (None , _pek_decrypt ),
189+ "initialAuthIncoming" : (None , _pek_decrypt ),
190+ "initialAuthOutgoing" : (None , _pek_decrypt ),
191+ "trustAuthIncoming" : (None , _pek_decrypt ),
192+ "trustAuthOutgoing" : (None , _pek_decrypt ),
193+ "msDS-ExecuteScriptPassword" : (None , _pek_decrypt ),
165194}
166195
196+ # TODO add for protected attributes
197+
167198
168199def _ldapDisplayName_to_DNT (db : Database , value : str ) -> int | str :
169200 """Convert an LDAP display name to its corresponding DNT value.
@@ -179,8 +210,10 @@ def _ldapDisplayName_to_DNT(db: Database, value: str) -> int | str:
179210 return value
180211
181212
182- def _DNT_to_ldapDisplayName (db : Database , value : int ) -> str | int :
183- """Convert a DNT value to its corresponding LDAP display name.
213+ def _DNT_to_ldapDisplayName (db : Database , value : int ) -> str | DN | int :
214+ """Convert a DNT value to its corresponding LDAP display name or distinguished name.
215+
216+ For attributes and classes, the LDAP display name is returned. For objects, the distinguished name is returned.
184217
185218 Args:
186219 value: The Directory Number Tag to look up.
@@ -197,6 +230,18 @@ def _DNT_to_ldapDisplayName(db: Database, value: int) -> str | int:
197230 return value
198231
199232
233+ class DN (str ):
234+ """A distinguished name (DN) string wrapper. Presents the DN as a string but also retains the underlying object."""
235+
236+ __slots__ = ("object" , "parent" )
237+
238+ def __new__ (cls , value : str , object : Object , parent : DN | None = None ):
239+ instance = super ().__new__ (cls , value )
240+ instance .object = object
241+ instance .parent = parent
242+ return instance
243+
244+
200245def _oid_to_attrtyp (db : Database , value : str ) -> int | str :
201246 """Convert OID string or LDAP display name to ATTRTYP value.
202247
0 commit comments