dissect.database 1.2.dev7__tar.gz → 1.2.dev9__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (225) hide show
  1. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/PKG-INFO +1 -1
  2. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/database.py +6 -6
  3. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/ntds.py +12 -3
  4. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/__init__.py +2 -0
  5. dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/attributeschema.py +28 -0
  6. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/certificationauthority.py +5 -0
  7. dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/computer.py +51 -0
  8. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/configuration.py +5 -0
  9. dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/crossref.py +27 -0
  10. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/crossrefcontainer.py +5 -0
  11. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/domaindns.py +5 -0
  12. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/group.py +10 -0
  13. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/grouppolicycontainer.py +5 -0
  14. dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/msfve_recoveryinformation.py +45 -0
  15. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntdsdsa.py +5 -0
  16. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/object.py +41 -10
  17. dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/organizationalperson.py +33 -0
  18. dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/organizationalunit.py +51 -0
  19. dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/person.py +23 -0
  20. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/pkienrollmentservice.py +5 -0
  21. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/server.py +5 -0
  22. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/site.py +16 -1
  23. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/top.py +5 -0
  24. dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/trusteddomain.py +49 -0
  25. dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/user.py +141 -0
  26. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/schema.py +3 -3
  27. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/util.py +103 -33
  28. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/PKG-INFO +1 -1
  29. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/SOURCES.txt +1 -0
  30. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/conftest.py +7 -0
  31. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_ntds.py +127 -1
  32. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_pek.py +2 -2
  33. dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/attributeschema.py +0 -13
  34. dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/computer.py +0 -29
  35. dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/crossref.py +0 -13
  36. dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/organizationalperson.py +0 -18
  37. dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/organizationalunit.py +0 -26
  38. dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/person.py +0 -13
  39. dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/trusteddomain.py +0 -13
  40. dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/user.py +0 -74
  41. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/.git-blame-ignore-revs +0 -0
  42. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/COPYRIGHT +0 -0
  43. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/LICENSE +0 -0
  44. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/MANIFEST.in +0 -0
  45. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/README.md +0 -0
  46. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/__init__.py +0 -0
  47. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/__init__.py +0 -0
  48. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/c_db.py +0 -0
  49. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/c_db.pyi +0 -0
  50. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/db.py +0 -0
  51. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/tools/__init__.py +0 -0
  52. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/tools/c_rpm.py +0 -0
  53. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/tools/c_rpm.pyi +0 -0
  54. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/tools/rpm.py +0 -0
  55. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/__init__.py +0 -0
  56. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/c_ese.py +0 -0
  57. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/c_ese.pyi +0 -0
  58. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/compression.py +0 -0
  59. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/cursor.py +0 -0
  60. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ese.py +0 -0
  61. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/exception.py +0 -0
  62. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/index.py +0 -0
  63. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/lcmapstring.py +0 -0
  64. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/__init__.py +0 -0
  65. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_ds.py +0 -0
  66. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_ds.pyi +0 -0
  67. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_pek.py +0 -0
  68. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_pek.pyi +0 -0
  69. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_sd.py +0 -0
  70. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_sd.pyi +0 -0
  71. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/applicationsettings.py +0 -0
  72. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/builtindomain.py +0 -0
  73. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/classschema.py +0 -0
  74. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/classstore.py +0 -0
  75. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/container.py +0 -0
  76. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/controlaccessright.py +0 -0
  77. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/crldistributionpoint.py +0 -0
  78. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dfsconfiguration.py +0 -0
  79. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/displayspecifier.py +0 -0
  80. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dmd.py +0 -0
  81. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dnsnode.py +0 -0
  82. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dnszone.py +0 -0
  83. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/domain.py +0 -0
  84. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/domainpolicy.py +0 -0
  85. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dsuisettings.py +0 -0
  86. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/filelinktracking.py +0 -0
  87. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/foreignsecurityprincipal.py +0 -0
  88. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/infrastructureupdate.py +0 -0
  89. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/intersitetransport.py +0 -0
  90. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/intersitetransportcontainer.py +0 -0
  91. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecbase.py +0 -0
  92. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecfilter.py +0 -0
  93. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecisakmppolicy.py +0 -0
  94. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecnegotiationpolicy.py +0 -0
  95. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecnfa.py +0 -0
  96. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecpolicy.py +0 -0
  97. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/leaf.py +0 -0
  98. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/linktrackobjectmovetable.py +0 -0
  99. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/linktrackvolumetable.py +0 -0
  100. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/locality.py +0 -0
  101. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/lostandfound.py +0 -0
  102. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msauthz_centralaccesspolicies.py +0 -0
  103. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msauthz_centralaccessrules.py +0 -0
  104. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_content.py +0 -0
  105. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_contentset.py +0 -0
  106. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_globalsettings.py +0 -0
  107. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_localsettings.py +0 -0
  108. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_member.py +0 -0
  109. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_replicationgroup.py +0 -0
  110. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_subscriber.py +0 -0
  111. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_subscription.py +0 -0
  112. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_topology.py +0 -0
  113. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdns_serversettings.py +0 -0
  114. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_authnpolicies.py +0 -0
  115. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_authnpolicysilos.py +0 -0
  116. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_claimstransformationpolicies.py +0 -0
  117. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_claimtype.py +0 -0
  118. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_claimtypepropertybase.py +0 -0
  119. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_claimtypes.py +0 -0
  120. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_optionalfeature.py +0 -0
  121. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_passwordsettingscontainer.py +0 -0
  122. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_quotacontainer.py +0 -0
  123. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_resourceproperties.py +0 -0
  124. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_resourceproperty.py +0 -0
  125. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_resourcepropertylist.py +0 -0
  126. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_shadowprincipalcontainer.py +0 -0
  127. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_valuetype.py +0 -0
  128. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msimaging_psps.py +0 -0
  129. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/mskds_provserverconfiguration.py +0 -0
  130. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msmqenterprisesettings.py +0 -0
  131. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/mspki_enterpriseoid.py +0 -0
  132. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/mspki_privatekeyrecoveryagent.py +0 -0
  133. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msspp_activationobjectscontainer.py +0 -0
  134. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/mstpm_informationobjectscontainer.py +0 -0
  135. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntdsconnection.py +0 -0
  136. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntdsservice.py +0 -0
  137. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntdssitesettings.py +0 -0
  138. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntfrssettings.py +0 -0
  139. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/physicallocation.py +0 -0
  140. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/pkicertificatetemplate.py +0 -0
  141. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/querypolicy.py +0 -0
  142. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ridmanager.py +0 -0
  143. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ridset.py +0 -0
  144. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/rpccontainer.py +0 -0
  145. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/rrasadministrationdictionary.py +0 -0
  146. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/samserver.py +0 -0
  147. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/secret.py +0 -0
  148. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/securityobject.py +0 -0
  149. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/serverscontainer.py +0 -0
  150. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/sitelink.py +0 -0
  151. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/sitescontainer.py +0 -0
  152. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/subnetcontainer.py +0 -0
  153. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/subschema.py +0 -0
  154. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/pek.py +0 -0
  155. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/query.py +0 -0
  156. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/sd.py +0 -0
  157. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/tools/__init__.py +0 -0
  158. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/tools/ntds.py +0 -0
  159. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/page.py +0 -0
  160. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/record.py +0 -0
  161. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/sorting_table.py +0 -0
  162. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/table.py +0 -0
  163. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/__init__.py +0 -0
  164. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/certlog.py +0 -0
  165. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/impacket.py +0 -0
  166. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/sru.py +0 -0
  167. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/ual.py +0 -0
  168. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/util.py +0 -0
  169. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/exception.py +0 -0
  170. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/__init__.py +0 -0
  171. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/c_sqlite3.py +0 -0
  172. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/c_sqlite3.pyi +0 -0
  173. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/encryption/__init__.py +0 -0
  174. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/encryption/sqlcipher/__init__.py +0 -0
  175. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/encryption/sqlcipher/exception.py +0 -0
  176. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/encryption/sqlcipher/sqlcipher.py +0 -0
  177. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/exception.py +0 -0
  178. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/sqlite3.py +0 -0
  179. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/util.py +0 -0
  180. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/wal.py +0 -0
  181. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/dependency_links.txt +0 -0
  182. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/entry_points.txt +0 -0
  183. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/requires.txt +0 -0
  184. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/top_level.txt +0 -0
  185. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/pyproject.toml +0 -0
  186. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/setup.cfg +0 -0
  187. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/__init__.py +0 -0
  188. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_docs/Makefile +0 -0
  189. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_docs/conf.py +0 -0
  190. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_docs/index.rst +0 -0
  191. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_tools/sqlite3/__init__.py +0 -0
  192. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_tools/sqlite3/generate_sqlite.py +0 -0
  193. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_util.py +0 -0
  194. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/bsd/__init__.py +0 -0
  195. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/bsd/conftest.py +0 -0
  196. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/bsd/test_db.py +0 -0
  197. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/bsd/test_rpm.py +0 -0
  198. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/conftest.py +0 -0
  199. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/__init__.py +0 -0
  200. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/conftest.py +0 -0
  201. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/__init__.py +0 -0
  202. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_benchmark.py +0 -0
  203. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_query.py +0 -0
  204. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_schema.py +0 -0
  205. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_sd.py +0 -0
  206. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_util.py +0 -0
  207. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_cursor.py +0 -0
  208. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_ese.py +0 -0
  209. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_index.py +0 -0
  210. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_page.py +0 -0
  211. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_record.py +0 -0
  212. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_table.py +0 -0
  213. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/tools/__init__.py +0 -0
  214. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/tools/test_certlog.py +0 -0
  215. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/tools/test_sru.py +0 -0
  216. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/tools/test_ual.py +0 -0
  217. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/__init__.py +0 -0
  218. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/conftest.py +0 -0
  219. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_default_values.py +0 -0
  220. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_row.py +0 -0
  221. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_sqlcipher.py +0 -0
  222. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_sqlite3.py +0 -0
  223. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_util.py +0 -0
  224. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_wal.py +0 -0
  225. {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tox.ini +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.database
3
- Version: 1.2.dev7
3
+ Version: 1.2.dev9
4
4
  Summary: A Dissect module implementing parsers for various database formats, including Berkeley DB, Microsofts Extensible Storage Engine (ESE) and SQLite3
5
5
  Author-email: Dissect Team <dissect@fox-it.com>
6
6
  License-Expression: Apache-2.0
@@ -11,7 +11,7 @@ from dissect.database.ese.ntds.pek import PEK
11
11
  from dissect.database.ese.ntds.query import Query
12
12
  from dissect.database.ese.ntds.schema import Schema
13
13
  from dissect.database.ese.ntds.sd import SecurityDescriptor
14
- from dissect.database.ese.ntds.util import DN, DatabaseFlags, SearchFlags, encode_value
14
+ from dissect.database.ese.ntds.util import DN, DatabaseFlag, SearchFlag, encode_value
15
15
 
16
16
  if TYPE_CHECKING:
17
17
  from collections.abc import Iterator
@@ -44,14 +44,14 @@ class Database:
44
44
  self.data._make_dn.cache_clear()
45
45
 
46
46
  @cached_property
47
- def flags(self) -> DatabaseFlags | None:
47
+ def flags(self) -> DatabaseFlag | None:
48
48
  """Return the database flags."""
49
49
  if self.hiddeninfo is None:
50
50
  return None
51
51
 
52
- result = DatabaseFlags(0)
52
+ result = DatabaseFlag(0)
53
53
  flags = self.hiddeninfo.get("flags_col")
54
- for idx, member in enumerate(DatabaseFlags.__members__.values()):
54
+ for idx, member in enumerate(DatabaseFlag.__members__.values()):
55
55
  if flags[idx] == ord(b"1"):
56
56
  result = member if result is None else result | member
57
57
 
@@ -256,9 +256,9 @@ class DataTable:
256
256
  if schema.search_flags is None:
257
257
  raise ValueError(f"Attribute is not indexed: {attribute!r}")
258
258
 
259
- if SearchFlags.Indexed in schema.search_flags:
259
+ if SearchFlag.Indexed in schema.search_flags:
260
260
  name = f"INDEX_{schema.id:08x}"
261
- elif SearchFlags.TupleIndexed in schema.search_flags:
261
+ elif SearchFlag.TupleIndexed in schema.search_flags:
262
262
  name = f"INDEX_T_{schema.id:08x}"
263
263
  else:
264
264
  # TODO add ContainerIndexed
@@ -20,6 +20,7 @@ if TYPE_CHECKING:
20
20
  TrustedDomain,
21
21
  User,
22
22
  )
23
+ from dissect.database.ese.ntds.objects.organizationalunit import OrganizationalUnit
23
24
  from dissect.database.ese.ntds.pek import PEK
24
25
 
25
26
 
@@ -83,11 +84,11 @@ class NTDS:
83
84
 
84
85
  def groups(self) -> Iterator[Group]:
85
86
  """Get all group objects from the database."""
86
- yield from self.search(objectCategory="group")
87
+ yield from self.search(objectClass="group")
87
88
 
88
89
  def servers(self) -> Iterator[Server]:
89
90
  """Get all server objects from the database."""
90
- yield from self.search(objectCategory="server")
91
+ yield from self.search(objectClass="server")
91
92
 
92
93
  def users(self) -> Iterator[User]:
93
94
  """Get all user objects from the database."""
@@ -95,7 +96,11 @@ class NTDS:
95
96
 
96
97
  def computers(self) -> Iterator[Computer]:
97
98
  """Get all computer objects from the database."""
98
- yield from self.search(objectCategory="computer")
99
+ yield from self.search(objectClass="computer")
100
+
101
+ def domains(self) -> Iterator[DomainDNS]:
102
+ """Get all domain objects from the database."""
103
+ yield from self.search(objectClass="domainDNS")
99
104
 
100
105
  def trusts(self) -> Iterator[TrustedDomain]:
101
106
  """Get all trust objects from the database."""
@@ -105,6 +110,10 @@ class NTDS:
105
110
  """Get all group policy objects (GPO) objects from the database."""
106
111
  yield from self.search(objectClass="groupPolicyContainer")
107
112
 
113
+ def organizational_units(self) -> Iterator[OrganizationalUnit]:
114
+ """Get all organizational unit (OU) objects from the database."""
115
+ yield from self.search(objectClass="organizationalUnit")
116
+
108
117
  def secrets(self) -> Iterator[Secret]:
109
118
  """Get all secret objects from the database."""
110
119
  yield from self.search(objectClass="secret")
@@ -68,6 +68,7 @@ from dissect.database.ese.ntds.objects.msds_resourceproperty import MSDSResource
68
68
  from dissect.database.ese.ntds.objects.msds_resourcepropertylist import MSDSResourcePropertyList
69
69
  from dissect.database.ese.ntds.objects.msds_shadowprincipalcontainer import MSDSShadowPrincipalContainer
70
70
  from dissect.database.ese.ntds.objects.msds_valuetype import MSDSValueType
71
+ from dissect.database.ese.ntds.objects.msfve_recoveryinformation import MSFVERecoveryInformation
71
72
  from dissect.database.ese.ntds.objects.msimaging_psps import MSImagingPSPs
72
73
  from dissect.database.ese.ntds.objects.mskds_provserverconfiguration import MSKDSProvServerConfiguration
73
74
  from dissect.database.ese.ntds.objects.msmqenterprisesettings import MSMQEnterpriseSettings
@@ -174,6 +175,7 @@ __all__ = [
174
175
  "MSDSResourcePropertyList",
175
176
  "MSDSShadowPrincipalContainer",
176
177
  "MSDSValueType",
178
+ "MSFVERecoveryInformation",
177
179
  "MSImagingPSPs",
178
180
  "MSKDSProvServerConfiguration",
179
181
  "MSMQEnterpriseSettings",
@@ -0,0 +1,28 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, ClassVar
4
+
5
+ from dissect.database.ese.ntds.objects.top import Top
6
+ from dissect.database.ese.ntds.util import SearchFlag, SystemFlagAttribute
7
+
8
+ if TYPE_CHECKING:
9
+ from dissect.database.ese.ntds.objects.object import DecoderMap
10
+
11
+
12
+ class AttributeSchema(Top):
13
+ """Represents an attribute schema object in the Active Directory.
14
+
15
+ References:
16
+ - https://learn.microsoft.com/en-us/windows/win32/adschema/c-attributeschema
17
+ """
18
+
19
+ __object_class__ = "attributeSchema"
20
+ __decoders__: ClassVar[DecoderMap] = {
21
+ "searchFlags": lambda db, value: SearchFlag(value),
22
+ "systemFlags": lambda db, value: SystemFlagAttribute(value),
23
+ }
24
+
25
+ @property
26
+ def search_flags(self) -> SearchFlag | None:
27
+ """Return the searchFlags of this attribute schema."""
28
+ return self.get("searchFlags")
@@ -11,3 +11,8 @@ class CertificationAuthority(Top):
11
11
  """
12
12
 
13
13
  __object_class__ = "certificationAuthority"
14
+
15
+ @property
16
+ def dns_host_name(self) -> str | None:
17
+ """Return the dNSHostName of this Certification Authority."""
18
+ return self.get("dNSHostName")
@@ -0,0 +1,51 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+
5
+ from dissect.database.ese.ntds.objects.msfve_recoveryinformation import MSFVERecoveryInformation
6
+ from dissect.database.ese.ntds.objects.user import User
7
+
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Iterator
10
+
11
+ from dissect.database.ese.ntds.objects import Object
12
+
13
+
14
+ class Computer(User):
15
+ """Represents a computer object in the Active Directory.
16
+
17
+ References:
18
+ - https://learn.microsoft.com/en-us/windows/win32/adschema/c-computer
19
+ """
20
+
21
+ __object_class__ = "computer"
22
+
23
+ def __repr_body__(self) -> str:
24
+ return f"name={self.name!r}"
25
+
26
+ @property
27
+ def dns_host_name(self) -> str | None:
28
+ """Return the dNSHostName of this computer."""
29
+ return self.get("dNSHostName")
30
+
31
+ @property
32
+ def operating_system(self) -> str | None:
33
+ """Return the operatingSystem of this computer."""
34
+ return self.get("operatingSystem")
35
+
36
+ @property
37
+ def operating_system_version(self) -> str | None:
38
+ """Return the operatingSystemVersion of this computer."""
39
+ return self.get("operatingSystemVersion")
40
+
41
+ def fve_recovery_information(self) -> Iterator[MSFVERecoveryInformation]:
42
+ """Return the BitLocker recovery information objects associated with this computer."""
43
+ for child in self.children():
44
+ if isinstance(child, MSFVERecoveryInformation):
45
+ yield child
46
+
47
+ def managed_by(self) -> Iterator[Object]:
48
+ """Return the objects that manage this computer."""
49
+ self._assert_local()
50
+
51
+ yield from self.db.link.links(self.dnt, "managedBy")
@@ -11,3 +11,8 @@ class Configuration(Top):
11
11
  """
12
12
 
13
13
  __object_class__ = "configuration"
14
+
15
+ @property
16
+ def gp_link(self) -> str | None:
17
+ """Return the group policy link of the configuration."""
18
+ return self.get("gPLink")
@@ -0,0 +1,27 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, ClassVar
4
+
5
+ from dissect.database.ese.ntds.objects.top import Top
6
+ from dissect.database.ese.ntds.util import SystemFlagCrossRef
7
+
8
+ if TYPE_CHECKING:
9
+ from dissect.database.ese.ntds.objects.object import DecoderMap
10
+
11
+
12
+ class CrossRef(Top):
13
+ """Represents a cross-reference object in the Active Directory.
14
+
15
+ References:
16
+ - https://learn.microsoft.com/en-us/windows/win32/adschema/c-crossref
17
+ """
18
+
19
+ __object_class__ = "crossRef"
20
+ __decoders__: ClassVar[DecoderMap] = {
21
+ "systemFlags": lambda db, value: SystemFlagCrossRef(value),
22
+ }
23
+
24
+ @property
25
+ def behavior_version(self) -> int | None:
26
+ """Return the msDS-Behavior-Version of this cross-reference."""
27
+ return self.get("msDS-Behavior-Version")
@@ -11,3 +11,8 @@ class CrossRefContainer(Top):
11
11
  """
12
12
 
13
13
  __object_class__ = "crossRefContainer"
14
+
15
+ @property
16
+ def behavior_version(self) -> int | None:
17
+ """Return the msDS-Behavior-Version of this cross-reference container."""
18
+ return self.get("msDS-Behavior-Version")
@@ -19,3 +19,8 @@ class DomainDNS(Domain):
19
19
  if (pek := self.get("pekList")) is not None:
20
20
  return PEK(pek)
21
21
  return None
22
+
23
+ @property
24
+ def behavior_version(self) -> int | None:
25
+ """Return the msDS-Behavior-Version of this domain DNS object."""
26
+ return self.get("msDS-Behavior-Version")
@@ -24,6 +24,16 @@ class Group(Top):
24
24
  """Return the group's sAMAccountName."""
25
25
  return self.get("sAMAccountName")
26
26
 
27
+ @property
28
+ def mail(self) -> str | None:
29
+ """Return the mail address of this group."""
30
+ return self.get("mail")
31
+
32
+ @property
33
+ def admin_count(self) -> int | None:
34
+ """Return the group's adminCount."""
35
+ return self.get("adminCount")
36
+
27
37
  def managed_by(self) -> Iterator[Object]:
28
38
  """Return the objects that manage this group."""
29
39
  self._assert_local()
@@ -11,3 +11,8 @@ class GroupPolicyContainer(Container):
11
11
  """
12
12
 
13
13
  __object_class__ = "groupPolicyContainer"
14
+
15
+ @property
16
+ def file_path(self) -> str | None:
17
+ """Return the gPCFileSysPath of this group policy container."""
18
+ return self.get("gPCFileSysPath")
@@ -0,0 +1,45 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING
4
+ from uuid import UUID
5
+
6
+ from dissect.database.ese.ntds.objects.top import Top
7
+
8
+ if TYPE_CHECKING:
9
+ from dissect.database.ese.ntds.objects import Computer
10
+
11
+
12
+ class MSFVERecoveryInformation(Top):
13
+ """Represents a msFVE-RecoveryInformation object in the Active Directory.
14
+
15
+ References:
16
+ - https://learn.microsoft.com/en-us/windows/win32/adschema/c-msfve-recoveryinformation
17
+ """
18
+
19
+ __object_class__ = "msFVE-RecoveryInformation"
20
+
21
+ @property
22
+ def volume_guid(self) -> UUID:
23
+ """Return the volume GUID associated with this recovery information."""
24
+ return UUID(bytes_le=self.get("msFVE-VolumeGuid"))
25
+
26
+ @property
27
+ def recovery_guid(self) -> UUID:
28
+ """Return the recovery GUID associated with this recovery information."""
29
+ return UUID(bytes_le=self.get("msFVE-RecoveryGuid"))
30
+
31
+ @property
32
+ def recovery_password(self) -> str | None:
33
+ """Return the recovery password associated with this recovery information."""
34
+ return self.get("msFVE-RecoveryPassword")
35
+
36
+ @property
37
+ def key_package(self) -> bytes | None:
38
+ """Return the key package associated with this recovery information, if any."""
39
+ return self.get("msFVE-KeyPackage")
40
+
41
+ def computer(self) -> Computer:
42
+ """Return the computer object associated with this recovery information."""
43
+ if (parent := self.parent()) is None:
44
+ raise ValueError("msFVE-RecoveryInformation object has no parent computer")
45
+ return parent
@@ -19,6 +19,11 @@ class NTDSDSA(ApplicationSettings):
19
19
 
20
20
  __object_class__ = "nTDSDSA"
21
21
 
22
+ @property
23
+ def behavior_version(self) -> int | None:
24
+ """Return the msDS-Behavior-Version of this NTDS DSA object."""
25
+ return self.get("msDS-Behavior-Version")
26
+
22
27
  def domain(self) -> DomainDNS | None:
23
28
  """Return the domain object associated with this NTDS DSA object, if any."""
24
29
  self._assert_local()
@@ -1,19 +1,23 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import struct
3
4
  from functools import cached_property
4
- from typing import TYPE_CHECKING, Any, ClassVar
5
+ from typing import TYPE_CHECKING, Any, ClassVar, TypeAlias
6
+ from uuid import UUID
5
7
 
6
- from dissect.database.ese.ntds.util import InstanceType, decode_value
8
+ from dissect.database.ese.ntds.util import InstanceType, SystemFlag, decode_value
7
9
 
8
10
  if TYPE_CHECKING:
9
- from collections.abc import Iterator
11
+ from collections.abc import Callable, Iterator
10
12
  from datetime import datetime
11
13
 
12
14
  from dissect.database.ese.ntds.database import Database
13
15
  from dissect.database.ese.ntds.sd import SecurityDescriptor
14
- from dissect.database.ese.ntds.util import DN, SystemFlags
16
+ from dissect.database.ese.ntds.util import DN
15
17
  from dissect.database.ese.record import Record
16
18
 
19
+ DecoderMap: TypeAlias = dict[str, Callable[[Database, Any], Any]]
20
+
17
21
 
18
22
  class Object:
19
23
  """Base class for all objects in the NTDS database.
@@ -29,7 +33,19 @@ class Object:
29
33
  - https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-adsc/041c6068-c710-4c74-968f-3040e4208701
30
34
  """
31
35
 
36
+ # Subclasses must override this to specify their object class
32
37
  __object_class__: str
38
+ """The objectClass value for this object."""
39
+
40
+ # Decoders for specific attributes to this object
41
+ __decoders__: ClassVar[DecoderMap] = {
42
+ "Ancestors": lambda db, value: [v[0] for v in struct.iter_unpack("<I", value)],
43
+ "instanceType": lambda db, value: InstanceType(value),
44
+ "systemFlags": lambda db, value: SystemFlag(value),
45
+ "objectGUID": lambda db, value: UUID(bytes_le=value),
46
+ }
47
+
48
+ # All known object classes
33
49
  __known_classes__: ClassVar[dict[str, type[Object]]] = {}
34
50
 
35
51
  def __init__(self, db: Database, record: Record):
@@ -39,6 +55,12 @@ class Object:
39
55
  def __init_subclass__(cls):
40
56
  cls.__known_classes__[cls.__object_class__] = cls
41
57
 
58
+ # Merge parent decoders with any new ones defined on the new class
59
+ decoders = {}
60
+ for parent in reversed(cls.__mro__[1:]):
61
+ decoders |= getattr(parent, "__decoders__", {})
62
+ cls.__decoders__ = decoders | cls.__decoders__
63
+
42
64
  def __repr__(self) -> str:
43
65
  suffix = self.__repr_suffix__()
44
66
  return f"<{self.__class__.__name__} {self.__repr_body__()}{' ' + suffix if suffix else ''}>"
@@ -57,6 +79,11 @@ class Object:
57
79
  def __getattr__(self, name: str) -> Any:
58
80
  return self.get(name)
59
81
 
82
+ def __eq__(self, other: object) -> bool:
83
+ if not isinstance(other, Object):
84
+ return NotImplemented
85
+ return self.record == other.record
86
+
60
87
  @classmethod
61
88
  def from_record(cls, db: Database, record: Record) -> Object:
62
89
  """Create an Object instance from a database record.
@@ -84,7 +111,13 @@ class Object:
84
111
  name: The attribute name to retrieve.
85
112
  raw: Whether to return the raw value without decoding.
86
113
  """
87
- return _get_attribute(self.db, self.record, name, raw=raw)
114
+ value = _get_attribute(self.db, self.record, name, raw=raw)
115
+
116
+ # Allow custom decoders to override the default decoding logic for specific attributes
117
+ # This is convenient for things like enums or timestamps that we want to represent as more meaningful types
118
+ if value is not None and name in self.__decoders__:
119
+ value = self.__decoders__[name](self.db, value)
120
+ return value
88
121
 
89
122
  def as_dict(self) -> dict[str, Any]:
90
123
  """Return the object's attributes as a dictionary."""
@@ -92,7 +125,7 @@ class Object:
92
125
  for key in self.record.as_dict():
93
126
  if (schema := self.db.data.schema.lookup_attribute(column=key)) is not None:
94
127
  key = schema.name
95
- result[key] = _get_attribute(self.db, self.record, key)
128
+ result[key] = self.get(key)
96
129
  return result
97
130
 
98
131
  def parent(self) -> Object | None:
@@ -216,7 +249,7 @@ class Object:
216
249
  return self.get("instanceType")
217
250
 
218
251
  @property
219
- def system_flags(self) -> SystemFlags | None:
252
+ def system_flags(self) -> SystemFlag | None:
220
253
  """Return the object's system flags."""
221
254
  return self.get("systemFlags")
222
255
 
@@ -235,9 +268,7 @@ class Object:
235
268
  @cached_property
236
269
  def sd(self) -> SecurityDescriptor | None:
237
270
  """Return the Security Descriptor for this object."""
238
- if (sd_id := self.get("nTSecurityDescriptor")) is not None:
239
- return self.db.sd.sd(sd_id)
240
- return None
271
+ return self.get("nTSecurityDescriptor")
241
272
 
242
273
  @cached_property
243
274
  def well_known_objects(self) -> list[Object]:
@@ -0,0 +1,33 @@
1
+ from __future__ import annotations
2
+
3
+ from dissect.database.ese.ntds.objects.person import Person
4
+
5
+
6
+ class OrganizationalPerson(Person):
7
+ """Represents an organizational person object in the Active Directory.
8
+
9
+ References:
10
+ - https://learn.microsoft.com/en-us/windows/win32/adschema/c-organizationalperson
11
+ """
12
+
13
+ __object_class__ = "organizationalPerson"
14
+
15
+ @property
16
+ def city(self) -> str | None:
17
+ """Return the city (l) of this organizational person."""
18
+ return self.get("l") # "l" (localityName) represents the city/locality.
19
+
20
+ @property
21
+ def mail(self) -> str | None:
22
+ """Return the mail address of this organizational person."""
23
+ return self.get("mail")
24
+
25
+ @property
26
+ def title(self) -> str | None:
27
+ """Return the title of this organizational person."""
28
+ return self.get("title")
29
+
30
+ @property
31
+ def allowed_to_act_on_behalf_of_other_identity(self) -> str | None:
32
+ """Return the msDS-AllowedToActOnBehalfOfOtherIdentity attribute of this organizational person."""
33
+ return self.get("msDS-AllowedToActOnBehalfOfOtherIdentity")
@@ -0,0 +1,51 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, ClassVar
4
+
5
+ from dissect.database.ese.ntds.objects.top import Top
6
+ from dissect.database.ese.ntds.util import GroupPolicyOption
7
+
8
+ if TYPE_CHECKING:
9
+ from collections.abc import Iterator
10
+
11
+ from dissect.database.ese.ntds.objects import Object
12
+ from dissect.database.ese.ntds.objects.object import DecoderMap
13
+
14
+
15
+ class OrganizationalUnit(Top):
16
+ """Represents an organizational unit object in the Active Directory.
17
+
18
+ References:
19
+ - https://learn.microsoft.com/en-us/windows/win32/adschema/c-organizationalunit
20
+ """
21
+
22
+ __object_class__ = "organizationalUnit"
23
+ __decoders__: ClassVar[DecoderMap] = {
24
+ "gPOptions": lambda db, value: GroupPolicyOption(value),
25
+ }
26
+
27
+ @property
28
+ def gp_link(self) -> str | None:
29
+ """Return the group policy link of the organizational unit."""
30
+ return self.get("gPLink")
31
+
32
+ @property
33
+ def gp_options(self) -> int | None:
34
+ """Return the group policy options of the organizational unit."""
35
+ return self.get("gPOptions")
36
+
37
+ @property
38
+ def telephone_number(self) -> str | None:
39
+ """Return the telephone number of this organizational unit."""
40
+ return self.get("telephoneNumber")
41
+
42
+ @property
43
+ def user_password(self) -> str | None:
44
+ """Return the userPassword of this organizational unit."""
45
+ return self.get("userPassword")
46
+
47
+ def managed_by(self) -> Iterator[Object]:
48
+ """Return the objects that manage this organizational unit."""
49
+ self._assert_local()
50
+
51
+ yield from self.db.link.links(self.dnt, "managedBy")
@@ -0,0 +1,23 @@
1
+ from __future__ import annotations
2
+
3
+ from dissect.database.ese.ntds.objects.top import Top
4
+
5
+
6
+ class Person(Top):
7
+ """Represents a person object in the Active Directory.
8
+
9
+ References:
10
+ - https://learn.microsoft.com/en-us/windows/win32/adschema/c-person
11
+ """
12
+
13
+ __object_class__ = "person"
14
+
15
+ @property
16
+ def telephone_number(self) -> str | None:
17
+ """Return the telephone number of this person."""
18
+ return self.get("telephoneNumber")
19
+
20
+ @property
21
+ def user_password(self) -> str | None:
22
+ """Return the userPassword attribute of this person."""
23
+ return self.get("userPassword")
@@ -11,3 +11,8 @@ class PKIEnrollmentService(Top):
11
11
  """
12
12
 
13
13
  __object_class__ = "pKIEnrollmentService"
14
+
15
+ @property
16
+ def dns_host_name(self) -> str | None:
17
+ """Return the dNSHostName of this PKI Enrollment Service."""
18
+ return self.get("dNSHostName")
@@ -19,6 +19,11 @@ class Server(Top):
19
19
 
20
20
  __object_class__ = "server"
21
21
 
22
+ @property
23
+ def dns_host_name(self) -> str | None:
24
+ """Return the dNSHostName of this server."""
25
+ return self.get("dNSHostName")
26
+
22
27
  def computer(self) -> Computer | None:
23
28
  """Return the computer object associated with this server, if any."""
24
29
  self._assert_local()
@@ -1,13 +1,15 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING
3
+ from typing import TYPE_CHECKING, ClassVar
4
4
 
5
5
  from dissect.database.ese.ntds.objects.top import Top
6
+ from dissect.database.ese.ntds.util import GroupPolicyOption
6
7
 
7
8
  if TYPE_CHECKING:
8
9
  from collections.abc import Iterator
9
10
 
10
11
  from dissect.database.ese.ntds.objects import Object
12
+ from dissect.database.ese.ntds.objects.object import DecoderMap
11
13
 
12
14
 
13
15
  class Site(Top):
@@ -18,6 +20,19 @@ class Site(Top):
18
20
  """
19
21
 
20
22
  __object_class__ = "site"
23
+ __decoders__: ClassVar[DecoderMap] = {
24
+ "gPOptions": lambda db, value: GroupPolicyOption(value),
25
+ }
26
+
27
+ @property
28
+ def gp_link(self) -> str:
29
+ """Return the group policy link of the site."""
30
+ return self.get("gPLink")
31
+
32
+ @property
33
+ def gp_options(self) -> int:
34
+ """Return the group policy options of the site."""
35
+ return self.get("gPOptions", 0)
21
36
 
22
37
  def managed_by(self) -> Iterator[Object]:
23
38
  """Return the objects that manage this site."""
@@ -19,3 +19,8 @@ class Top(Object):
19
19
  def display_name(self) -> str | None:
20
20
  """Return the displayName for this object."""
21
21
  return self.get("displayName")
22
+
23
+ @property
24
+ def description(self) -> str | None:
25
+ """Return the description for this object."""
26
+ return self.get("description")