dissect.database 1.1.dev2__tar.gz → 1.1.dev4__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 (230) hide show
  1. dissect_database-1.1.dev4/MANIFEST.in +4 -0
  2. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/PKG-INFO +6 -3
  3. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/btree.py +30 -19
  4. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/c_ese.py +19 -2
  5. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/c_ese.pyi +16 -0
  6. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/cursor.py +74 -54
  7. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/ese.py +1 -0
  8. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/index.py +16 -8
  9. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/lcmapstring.py +1 -0
  10. dissect_database-1.1.dev4/dissect/database/ese/ntds/__init__.py +13 -0
  11. dissect_database-1.1.dev4/dissect/database/ese/ntds/c_ds.py +94 -0
  12. dissect_database-1.1.dev4/dissect/database/ese/ntds/c_ds.pyi +329 -0
  13. dissect_database-1.1.dev4/dissect/database/ese/ntds/c_pek.py +59 -0
  14. dissect_database-1.1.dev4/dissect/database/ese/ntds/c_pek.pyi +125 -0
  15. dissect_database-1.1.dev4/dissect/database/ese/ntds/c_sd.py +121 -0
  16. dissect_database-1.1.dev4/dissect/database/ese/ntds/c_sd.pyi +158 -0
  17. dissect_database-1.1.dev4/dissect/database/ese/ntds/database.py +414 -0
  18. dissect_database-1.1.dev4/dissect/database/ese/ntds/ntds.py +91 -0
  19. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/__init__.py +213 -0
  20. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/applicationsettings.py +13 -0
  21. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/attributeschema.py +13 -0
  22. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/builtindomain.py +13 -0
  23. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/certificationauthority.py +13 -0
  24. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/classschema.py +42 -0
  25. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/classstore.py +13 -0
  26. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/computer.py +29 -0
  27. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/configuration.py +13 -0
  28. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/container.py +13 -0
  29. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/controlaccessright.py +13 -0
  30. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/crldistributionpoint.py +13 -0
  31. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/crossref.py +13 -0
  32. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/crossrefcontainer.py +13 -0
  33. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dfsconfiguration.py +13 -0
  34. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/displayspecifier.py +13 -0
  35. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dmd.py +13 -0
  36. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dnsnode.py +13 -0
  37. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dnszone.py +26 -0
  38. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/domain.py +13 -0
  39. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/domaindns.py +21 -0
  40. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/domainpolicy.py +26 -0
  41. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dsuisettings.py +13 -0
  42. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/filelinktracking.py +13 -0
  43. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/foreignsecurityprincipal.py +13 -0
  44. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/group.py +48 -0
  45. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/grouppolicycontainer.py +13 -0
  46. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/infrastructureupdate.py +13 -0
  47. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/intersitetransport.py +13 -0
  48. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/intersitetransportcontainer.py +13 -0
  49. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecbase.py +13 -0
  50. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecfilter.py +13 -0
  51. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecisakmppolicy.py +13 -0
  52. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecnegotiationpolicy.py +13 -0
  53. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecnfa.py +13 -0
  54. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecpolicy.py +13 -0
  55. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/leaf.py +13 -0
  56. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/linktrackobjectmovetable.py +13 -0
  57. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/linktrackvolumetable.py +13 -0
  58. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/locality.py +13 -0
  59. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/lostandfound.py +13 -0
  60. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msauthz_centralaccesspolicies.py +13 -0
  61. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msauthz_centralaccessrules.py +13 -0
  62. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_content.py +13 -0
  63. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_contentset.py +13 -0
  64. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_globalsettings.py +13 -0
  65. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_localsettings.py +13 -0
  66. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_member.py +13 -0
  67. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_replicationgroup.py +13 -0
  68. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_subscriber.py +13 -0
  69. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_subscription.py +13 -0
  70. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_topology.py +13 -0
  71. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdns_serversettings.py +13 -0
  72. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_authnpolicies.py +13 -0
  73. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_authnpolicysilos.py +13 -0
  74. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_claimstransformationpolicies.py +13 -0
  75. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_claimtype.py +13 -0
  76. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_claimtypepropertybase.py +13 -0
  77. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_claimtypes.py +13 -0
  78. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_optionalfeature.py +13 -0
  79. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_passwordsettingscontainer.py +13 -0
  80. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_quotacontainer.py +13 -0
  81. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_resourceproperties.py +13 -0
  82. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_resourceproperty.py +13 -0
  83. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_resourcepropertylist.py +13 -0
  84. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_shadowprincipalcontainer.py +13 -0
  85. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_valuetype.py +13 -0
  86. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msimaging_psps.py +13 -0
  87. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/mskds_provserverconfiguration.py +13 -0
  88. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msmqenterprisesettings.py +13 -0
  89. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/mspki_enterpriseoid.py +13 -0
  90. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/mspki_privatekeyrecoveryagent.py +13 -0
  91. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msspp_activationobjectscontainer.py +13 -0
  92. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/mstpm_informationobjectscontainer.py +13 -0
  93. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntdsconnection.py +13 -0
  94. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntdsdsa.py +26 -0
  95. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntdsservice.py +13 -0
  96. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntdssitesettings.py +26 -0
  97. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntfrssettings.py +26 -0
  98. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/object.py +267 -0
  99. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/organizationalperson.py +18 -0
  100. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/organizationalunit.py +26 -0
  101. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/person.py +13 -0
  102. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/physicallocation.py +26 -0
  103. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/pkicertificatetemplate.py +13 -0
  104. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/pkienrollmentservice.py +13 -0
  105. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/querypolicy.py +13 -0
  106. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ridmanager.py +13 -0
  107. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ridset.py +13 -0
  108. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/rpccontainer.py +13 -0
  109. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/rrasadministrationdictionary.py +13 -0
  110. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/samserver.py +13 -0
  111. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/secret.py +13 -0
  112. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/securityobject.py +13 -0
  113. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/server.py +26 -0
  114. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/serverscontainer.py +13 -0
  115. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/site.py +26 -0
  116. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/sitelink.py +13 -0
  117. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/sitescontainer.py +13 -0
  118. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/subnetcontainer.py +13 -0
  119. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/subschema.py +13 -0
  120. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/top.py +16 -0
  121. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/trusteddomain.py +13 -0
  122. dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/user.py +68 -0
  123. dissect_database-1.1.dev4/dissect/database/ese/ntds/pek.py +134 -0
  124. dissect_database-1.1.dev4/dissect/database/ese/ntds/query.py +218 -0
  125. dissect_database-1.1.dev4/dissect/database/ese/ntds/schema.py +350 -0
  126. dissect_database-1.1.dev4/dissect/database/ese/ntds/sd.py +191 -0
  127. dissect_database-1.1.dev4/dissect/database/ese/ntds/util.py +497 -0
  128. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/record.py +7 -1
  129. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/table.py +44 -32
  130. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/sqlite3.py +15 -7
  131. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect.database.egg-info/PKG-INFO +6 -3
  132. dissect_database-1.1.dev4/dissect.database.egg-info/SOURCES.txt +206 -0
  133. dissect_database-1.1.dev4/dissect.database.egg-info/requires.txt +10 -0
  134. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/pyproject.toml +7 -2
  135. dissect_database-1.1.dev4/tests/conftest.py +19 -0
  136. dissect_database-1.1.dev4/tests/ese/ntds/conftest.py +47 -0
  137. dissect_database-1.1.dev4/tests/ese/ntds/test_benchmark.py +49 -0
  138. dissect_database-1.1.dev4/tests/ese/ntds/test_ntds.py +261 -0
  139. dissect_database-1.1.dev4/tests/ese/ntds/test_pek.py +37 -0
  140. dissect_database-1.1.dev4/tests/ese/ntds/test_query.py +121 -0
  141. dissect_database-1.1.dev4/tests/ese/ntds/test_schema.py +16 -0
  142. dissect_database-1.1.dev4/tests/ese/ntds/test_sd.py +19 -0
  143. dissect_database-1.1.dev4/tests/ese/ntds/test_util.py +110 -0
  144. dissect_database-1.1.dev4/tests/sqlite3/__init__.py +0 -0
  145. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tox.ini +11 -1
  146. dissect_database-1.1.dev2/.gitattributes +0 -1
  147. dissect_database-1.1.dev2/MANIFEST.in +0 -2
  148. dissect_database-1.1.dev2/dissect.database.egg-info/SOURCES.txt +0 -97
  149. dissect_database-1.1.dev2/dissect.database.egg-info/requires.txt +0 -6
  150. dissect_database-1.1.dev2/tests/_data/bsd/btree.db.gz +0 -0
  151. dissect_database-1.1.dev2/tests/_data/bsd/hash.db.gz +0 -0
  152. dissect_database-1.1.dev2/tests/_data/bsd/recno.db.gz +0 -0
  153. dissect_database-1.1.dev2/tests/_data/bsd/rpm/Packages.gz +0 -0
  154. dissect_database-1.1.dev2/tests/_data/ese/Windows.edb.gz +0 -0
  155. dissect_database-1.1.dev2/tests/_data/ese/basic.edb.gz +0 -0
  156. dissect_database-1.1.dev2/tests/_data/ese/binary.edb.gz +0 -0
  157. dissect_database-1.1.dev2/tests/_data/ese/default.edb.gz +0 -0
  158. dissect_database-1.1.dev2/tests/_data/ese/index.edb.gz +0 -0
  159. dissect_database-1.1.dev2/tests/_data/ese/large.edb.gz +0 -0
  160. dissect_database-1.1.dev2/tests/_data/ese/multi.edb.gz +0 -0
  161. dissect_database-1.1.dev2/tests/_data/ese/text.edb.gz +0 -0
  162. dissect_database-1.1.dev2/tests/_data/ese/tools/CertLog.edb.gz +0 -0
  163. dissect_database-1.1.dev2/tests/_data/ese/tools/Current.mdb.gz +0 -0
  164. dissect_database-1.1.dev2/tests/_data/ese/tools/SRUDB.dat.gz +0 -0
  165. dissect_database-1.1.dev2/tests/_data/sqlite3/empty.sqlite +0 -0
  166. dissect_database-1.1.dev2/tests/_data/sqlite3/test.sqlite +0 -0
  167. dissect_database-1.1.dev2/tests/_data/sqlite3/test.sqlite-wal +0 -0
  168. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/COPYRIGHT +0 -0
  169. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/LICENSE +0 -0
  170. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/README.md +0 -0
  171. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/__init__.py +0 -0
  172. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/__init__.py +0 -0
  173. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/c_db.py +0 -0
  174. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/c_db.pyi +0 -0
  175. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/db.py +0 -0
  176. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/tools/__init__.py +0 -0
  177. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/tools/c_rpm.py +0 -0
  178. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/tools/c_rpm.pyi +0 -0
  179. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/tools/rpm.py +0 -0
  180. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/__init__.py +0 -0
  181. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/compression.py +0 -0
  182. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/exception.py +0 -0
  183. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/page.py +0 -0
  184. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/sorting_table.py +0 -0
  185. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/__init__.py +0 -0
  186. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/certlog.py +0 -0
  187. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/impacket.py +0 -0
  188. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/sru.py +0 -0
  189. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/ual.py +0 -0
  190. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/util.py +0 -0
  191. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/exception.py +0 -0
  192. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/__init__.py +0 -0
  193. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/c_sqlite3.py +0 -0
  194. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/c_sqlite3.pyi +0 -0
  195. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/exception.py +0 -0
  196. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/util.py +0 -0
  197. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/wal.py +0 -0
  198. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect.database.egg-info/dependency_links.txt +0 -0
  199. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect.database.egg-info/top_level.txt +0 -0
  200. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/setup.cfg +0 -0
  201. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/__init__.py +0 -0
  202. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_docs/Makefile +0 -0
  203. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_docs/conf.py +0 -0
  204. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_docs/index.rst +0 -0
  205. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_tools/sqlite3/__init__.py +0 -0
  206. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_tools/sqlite3/generate_sqlite.py +0 -0
  207. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_util.py +0 -0
  208. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/bsd/__init__.py +0 -0
  209. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/bsd/conftest.py +0 -0
  210. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/bsd/test_db.py +0 -0
  211. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/bsd/test_rpm.py +0 -0
  212. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/__init__.py +0 -0
  213. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/conftest.py +0 -0
  214. {dissect_database-1.1.dev2/tests/ese/tools → dissect_database-1.1.dev4/tests/ese/ntds}/__init__.py +0 -0
  215. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_cursor.py +0 -0
  216. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_ese.py +0 -0
  217. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_index.py +0 -0
  218. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_page.py +0 -0
  219. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_record.py +0 -0
  220. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_table.py +0 -0
  221. {dissect_database-1.1.dev2/tests/sqlite3 → dissect_database-1.1.dev4/tests/ese/tools}/__init__.py +0 -0
  222. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/tools/test_certlog.py +0 -0
  223. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/tools/test_sru.py +0 -0
  224. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/tools/test_ual.py +0 -0
  225. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/conftest.py +0 -0
  226. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_default_values.py +0 -0
  227. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_row.py +0 -0
  228. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_sqlite3.py +0 -0
  229. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_util.py +0 -0
  230. {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_wal.py +0 -0
@@ -0,0 +1,4 @@
1
+ exclude .gitattributes
2
+ exclude .gitignore
3
+ recursive-exclude .github/ *
4
+ recursive-exclude tests/_data/ *
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dissect.database
3
- Version: 1.1.dev2
3
+ Version: 1.1.dev4
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
@@ -22,10 +22,13 @@ Description-Content-Type: text/markdown
22
22
  License-File: LICENSE
23
23
  License-File: COPYRIGHT
24
24
  Requires-Dist: dissect.cstruct<5,>=4
25
- Requires-Dist: dissect.util<4,>=3.5
25
+ Requires-Dist: dissect.util<4,>=3.24.dev1
26
+ Provides-Extra: full
27
+ Requires-Dist: pycryptodome; extra == "full"
26
28
  Provides-Extra: dev
29
+ Requires-Dist: dissect.database[full]; extra == "dev"
27
30
  Requires-Dist: dissect.cstruct<5.0.dev,>=4.0.dev; extra == "dev"
28
- Requires-Dist: dissect.util<4.0.dev,>=3.5.dev; extra == "dev"
31
+ Requires-Dist: dissect.util<4.0.dev,>=3.24.dev; extra == "dev"
29
32
  Dynamic: license-file
30
33
 
31
34
  # dissect.database
@@ -116,7 +116,8 @@ class BTree:
116
116
  """
117
117
  page = self._page
118
118
  while True:
119
- node = find_node(page, key)
119
+ num = find_node(page, key)
120
+ node = page.node(num)
120
121
 
121
122
  if page.is_branch:
122
123
  page = self.db.page(node.child)
@@ -132,35 +133,45 @@ class BTree:
132
133
  return self.node()
133
134
 
134
135
 
135
- def find_node(page: Page, key: bytes) -> Node:
136
+ def find_node(page: Page, key: bytes) -> int:
136
137
  """Search a page for a node matching ``key``.
137
138
 
139
+ Referencing Extensible-Storage-Engine source, they bail out early if they find an exact match.
140
+ However, we prefer to always find the _first_ node that is greater than or equal to the key,
141
+ so we can handle cases where there are duplicate index keys. This is important for "range" searches
142
+ where we want to find all keys matching a certain prefix, and not end up somewhere in the middle of the range.
143
+
138
144
  Args:
139
145
  page: The page to search.
140
146
  key: The key to search.
147
+
148
+ Returns:
149
+ The node number of the first node that's greater than or equal to the key.
141
150
  """
142
- first_node_idx = 0
143
- last_node_idx = page.node_count - 1
151
+ lo, hi = 0, page.node_count - 1
152
+ res = 0
144
153
 
145
154
  node = None
146
- while first_node_idx < last_node_idx:
147
- node_idx = (first_node_idx + last_node_idx) // 2
148
- node = page.node(node_idx)
155
+ while lo < hi:
156
+ mid = (lo + hi) // 2
157
+ node = page.node(mid)
149
158
 
150
159
  # It turns out that the way BTree keys are compared matches 1:1 with how Python compares bytes
151
160
  # First compare data, then length
152
- if key < node.key:
153
- last_node_idx = node_idx
154
- elif key == node.key:
155
- if page.is_branch:
156
- # If there's an exact match on a key on a branch page, the actual leaf nodes are in the next branch
157
- # Page keys for branch pages appear to be non-inclusive upper bounds
158
- node_idx = min(node_idx + 1, page.node_count - 1)
159
- node = page.node(node_idx)
161
+ res = (key < node.key) - (key > node.key)
160
162
 
161
- return node
163
+ if res < 0:
164
+ lo = mid + 1
162
165
  else:
163
- first_node_idx = node_idx + 1
166
+ hi = mid
167
+
168
+ # Final comparison on the last node
169
+ node = page.node(lo)
170
+ res = (key < node.key) - (key > node.key)
171
+
172
+ if page.is_branch and res == 0:
173
+ # If there's an exact match on a key on a branch page, the actual leaf nodes are in the next branch
174
+ # Page keys for branch pages appear to be non-inclusive upper bounds
175
+ lo = min(lo + 1, page.node_count - 1)
164
176
 
165
- # We're at the last node
166
- return page.node(first_node_idx)
177
+ return lo
@@ -231,7 +231,7 @@ struct DBFILEHDR {
231
231
  BKINFOTYPE bkinfoTypeCopyPrev; // Type of Last successful Incremental backup
232
232
  BKINFOTYPE bkinfoTypeDiffPrev; // Type of Last successful Differential backup
233
233
 
234
- // 476 bytes
234
+ // 476 bytes
235
235
  ULONG ulIncrementalReseedCount; // number of times incremental reseed has been initiated on this database
236
236
  LOGTIME logtimeIncrementalReseed; // the date of the last time that incremental reseed was initiated on this database
237
237
  ULONG ulIncrementalReseedCountOld; // number of times incremental reseed was initiated on this database before the last defrag
@@ -240,7 +240,7 @@ struct DBFILEHDR {
240
240
  LOGTIME logtimePagePatch; // the date of the last time that a page was patched as a part of incremental reseed
241
241
  ULONG ulPagePatchCountOld; // number of pages patched in the database as a part of incremental reseed before the last defrag
242
242
 
243
- // 508 bytes
243
+ // 508 bytes
244
244
  QWORD qwSortVersion; // DEPRECATED: In old versions had "default" (?English?) LCID version, in new versions has 0xFFFFFFFFFFFF.
245
245
 
246
246
  // 516 bytes // checksum during recovery state
@@ -399,6 +399,22 @@ flag TAGFLD_HEADER : uint8 {
399
399
  Encrypted = 0x40, // fEncrypted
400
400
  };
401
401
 
402
+ flag FIELDFLAG : uint16 {
403
+ NotNull = 0x0001, // NULL values not allowed
404
+ Version = 0x0002, // Version field
405
+ Autoincrement = 0x0004, // Autoincrement field
406
+ Multivalued = 0x0008, // Multi-valued column
407
+ Default = 0x0010, // Column has ISAM default value
408
+ EscrowUpdate = 0x0020, // Escrow updated column
409
+ Finalize = 0x0040, // Finalizable column
410
+ UserDefinedDefault = 0x0080, // The default value is generated through a callback
411
+ TemplateColumnESE98 = 0x0100, // Template table column created in ESE98 (ie. fDerived bit will be set in TAGFLD of records of derived tables)
412
+ DeleteOnZero = 0x0200, // DeleteOnZero column
413
+ PrimaryIndexPlaceholder = 0x0800, // Field is no longer in primary index, but must be retained as a placeholder
414
+ Compressed = 0x1000, // Data stored in the column should be compressed
415
+ Encrypted = 0x2000, // Data stored in the column is encrypted
416
+ };
417
+
402
418
  flag JET_bitIndex : uint32 {
403
419
  Unique = 0x00000001,
404
420
  Primary = 0x00000002,
@@ -467,5 +483,6 @@ TAG_FLAG = c_ese.TAG_FLAG
467
483
  TAGFLD_HEADER = c_ese.TAGFLD_HEADER
468
484
  CODEPAGE = c_ese.CODEPAGE
469
485
  COMPRESSION_SCHEME = c_ese.COMPRESSION_SCHEME
486
+ FIELDFLAG = c_ese.FIELDFLAG
470
487
  IDBFLAG = c_ese.IDBFLAG
471
488
  IDXFLAG = c_ese.IDXFLAG
@@ -426,6 +426,21 @@ class _c_ese(__cs__.cstruct):
426
426
  Null = ...
427
427
  Encrypted = ...
428
428
 
429
+ class FIELDFLAG(__cs__.Flag):
430
+ NotNull = ...
431
+ Version = ...
432
+ Autoincrement = ...
433
+ Multivalued = ...
434
+ Default = ...
435
+ EscrowUpdate = ...
436
+ Finalize = ...
437
+ UserDefinedDefault = ...
438
+ TemplateColumnESE98 = ...
439
+ DeleteOnZero = ...
440
+ PrimaryIndexPlaceholder = ...
441
+ Compressed = ...
442
+ Encrypted = ...
443
+
429
444
  class JET_bitIndex(__cs__.Flag):
430
445
  Unique = ...
431
446
  Primary = ...
@@ -487,5 +502,6 @@ TAG_FLAG: TypeAlias = c_ese.TAG_FLAG
487
502
  TAGFLD_HEADER: TypeAlias = c_ese.TAGFLD_HEADER
488
503
  CODEPAGE: TypeAlias = c_ese.CODEPAGE
489
504
  COMPRESSION_SCHEME: TypeAlias = c_ese.COMPRESSION_SCHEME
505
+ FIELDFLAG: TypeAlias = c_ese.FIELDFLAG
490
506
  IDBFLAG: TypeAlias = c_ese.IDBFLAG
491
507
  IDXFLAG: TypeAlias = c_ese.IDXFLAG
@@ -3,12 +3,14 @@ from __future__ import annotations
3
3
  from typing import TYPE_CHECKING
4
4
 
5
5
  from dissect.database.ese.btree import BTree
6
- from dissect.database.ese.exception import NoNeighbourPageError
6
+ from dissect.database.ese.exception import KeyNotFoundError, NoNeighbourPageError
7
7
  from dissect.database.ese.record import Record
8
8
 
9
9
  if TYPE_CHECKING:
10
10
  from collections.abc import Iterator
11
11
 
12
+ from typing_extensions import Self
13
+
12
14
  from dissect.database.ese.index import Index
13
15
  from dissect.database.ese.page import Node
14
16
  from dissect.database.ese.util import RecordValue
@@ -30,13 +32,10 @@ class Cursor:
30
32
  self._secondary = None if index.is_primary else BTree(self.db, self.table.root)
31
33
 
32
34
  def __iter__(self) -> Iterator[Record]:
33
- while True:
34
- yield self._record()
35
-
36
- try:
37
- self._primary.next()
38
- except NoNeighbourPageError:
39
- break
35
+ record = self.record()
36
+ while record is not None:
37
+ yield record
38
+ record = self.next()
40
39
 
41
40
  def _node(self) -> Node:
42
41
  """Return the node the cursor is currently on. Resolves the secondary index if needed.
@@ -50,7 +49,7 @@ class Cursor:
50
49
  node = self._secondary.search(node.data.tobytes(), exact=True)
51
50
  return node
52
51
 
53
- def _record(self) -> Record:
52
+ def record(self) -> Record:
54
53
  """Return the record the cursor is currently on.
55
54
 
56
55
  Returns:
@@ -58,25 +57,76 @@ class Cursor:
58
57
  """
59
58
  return Record(self.table, self._node())
60
59
 
61
- def reset(self) -> None:
60
+ def reset(self) -> Self:
62
61
  """Reset the internal state."""
63
62
  self._primary.reset()
64
63
  if self._secondary:
65
64
  self._secondary.reset()
65
+ return self
66
+
67
+ def next(self) -> Record | None:
68
+ """Move the cursor to the next record and return it.
69
+
70
+ Can move the cursor to the next page as a side effect.
66
71
 
67
- def search(self, **kwargs: RecordValue) -> Record:
72
+ Returns:
73
+ A :class:`~dissect.database.ese.record.Record` object of the next record.
74
+ """
75
+ try:
76
+ self._primary.next()
77
+ except NoNeighbourPageError:
78
+ return None
79
+ return self.record()
80
+
81
+ def prev(self) -> Record | None:
82
+ """Move the cursor to the previous node and return it.
83
+
84
+ Can move the cursor to the previous page as a side effect.
85
+
86
+ Returns:
87
+ A :class:`~dissect.database.ese.record.Record` object of the previous record.
88
+ """
89
+ try:
90
+ self._primary.prev()
91
+ except NoNeighbourPageError:
92
+ return None
93
+ return self.record()
94
+
95
+ def make_key(self, *args: RecordValue, **kwargs: RecordValue) -> bytes:
96
+ """Generate a key for this index from the given values.
97
+
98
+ Args:
99
+ *args: The values to generate a key for.
100
+ **kwargs: The columns and values to generate a key for.
101
+
102
+ Returns:
103
+ The generated key as bytes.
104
+ """
105
+ if not args and not kwargs:
106
+ raise ValueError("At least one value must be provided")
107
+
108
+ if args and kwargs:
109
+ raise ValueError("Cannot mix positional and keyword arguments in make_key")
110
+
111
+ if args and not len(args) == 1 and not isinstance(args[0], list):
112
+ raise ValueError("When using positional arguments, provide a single list of values")
113
+
114
+ return self.index.make_key(args[0] if args else kwargs)
115
+
116
+ def search(self, *args: RecordValue, **kwargs: RecordValue) -> Record:
68
117
  """Search the index for the requested values.
69
118
 
70
119
  Searching modifies the cursor state. Searching again will search from the current position.
71
120
  Reset the cursor with :meth:`reset` to start from the beginning.
72
121
 
73
122
  Args:
123
+ *args: The values to search for.
74
124
  **kwargs: The columns and values to search for.
75
125
 
76
126
  Returns:
77
127
  A :class:`~dissect.database.ese.record.Record` object of the found record.
78
128
  """
79
- key = self.index.make_key(kwargs)
129
+ key = self.make_key(*args, **kwargs)
80
130
  return self.search_key(key, exact=True)
81
131
 
82
132
  def search_key(self, key: bytes, exact: bool = True) -> Record:
@@ -88,24 +138,27 @@ class Cursor:
88
138
  next record that is greater than or equal to the key.
89
139
  """
90
140
  self._primary.search(key, exact)
91
- return self._record()
141
+ return self.record()
92
142
 
93
- def seek(self, **kwargs: RecordValue) -> None:
143
+ def seek(self, *args: RecordValue, **kwargs: RecordValue) -> Self:
94
144
  """Seek to the record with the given values.
95
145
 
96
146
  Args:
147
+ *args: The values to seek to.
97
148
  **kwargs: The columns and values to seek to.
98
149
  """
99
- key = self.index.make_key(kwargs)
150
+ key = self.make_key(*args, **kwargs)
100
151
  self.search_key(key, exact=False)
152
+ return self
101
153
 
102
- def seek_key(self, key: bytes) -> None:
154
+ def seek_key(self, key: bytes) -> Self:
103
155
  """Seek to the record with the given ``key``.
104
156
 
105
157
  Args:
106
158
  key: The key to seek to.
107
159
  """
108
160
  self._primary.search(key, exact=False)
161
+ return self
109
162
 
110
163
  def find(self, **kwargs: RecordValue) -> Record | None:
111
164
  """Find a record in the index.
@@ -130,7 +183,10 @@ class Cursor:
130
183
  other_columns = kwargs
131
184
 
132
185
  # We need at least an exact match on the indexed columns
133
- self.search(**indexed_columns)
186
+ try:
187
+ self.search(**indexed_columns)
188
+ except KeyNotFoundError:
189
+ return
134
190
 
135
191
  current_key = self._primary.node().key
136
192
 
@@ -150,7 +206,7 @@ class Cursor:
150
206
  if current_key != self._primary.node().key:
151
207
  break
152
208
 
153
- record = self._record()
209
+ record = self.record()
154
210
  for k, v in other_columns.items():
155
211
  value = record.get(k)
156
212
  # If the record value is a list, we do a check based on the queried value
@@ -172,39 +228,3 @@ class Cursor:
172
228
  self._primary.next()
173
229
  except NoNeighbourPageError:
174
230
  break
175
-
176
- def record(self) -> Record:
177
- """Return the record the cursor is currently on.
178
-
179
- Returns:
180
- A :class:`~dissect.database.ese.record.Record` object of the current record.
181
- """
182
- return self._record()
183
-
184
- def next(self) -> Record:
185
- """Move the cursor to the next record and return it.
186
-
187
- Can move the cursor to the next page as a side effect.
188
-
189
- Returns:
190
- A :class:`~dissect.database.ese.record.Record` object of the next record.
191
- """
192
- try:
193
- self._primary.next()
194
- except NoNeighbourPageError:
195
- raise IndexError("No next record")
196
- return self._record()
197
-
198
- def prev(self) -> Record:
199
- """Move the cursor to the previous node and return it.
200
-
201
- Can move the cursor to the previous page as a side effect.
202
-
203
- Returns:
204
- A :class:`~dissect.database.ese.record.Record` object of the previous record.
205
- """
206
- try:
207
- self._primary.prev()
208
- except NoNeighbourPageError:
209
- raise IndexError("No previous record")
210
- return self._record()
@@ -36,6 +36,7 @@ class ESE:
36
36
  self.fh = fh
37
37
  self.impacket_compat = impacket_compat
38
38
 
39
+ self.fh.seek(0)
39
40
  self.header = c_ese.DBFILEHDR(fh)
40
41
  if self.header.ulMagic != ulDAEMagic:
41
42
  raise InvalidDatabase("invalid file header signature")
@@ -74,16 +74,17 @@ class Index:
74
74
  """Create a new cursor for this index."""
75
75
  return Cursor(self)
76
76
 
77
- def search(self, **kwargs) -> Record:
77
+ def search(self, *args, **kwargs) -> Record:
78
78
  """Search the index for the requested values.
79
79
 
80
80
  Args:
81
+ *args: The values to search for.
81
82
  **kwargs: The columns and values to search for.
82
83
 
83
84
  Returns:
84
85
  A :class:`~dissect.database.ese.record.Record` object of the found record.
85
86
  """
86
- return self.cursor().search(**kwargs)
87
+ return self.cursor().search(*args, **kwargs)
87
88
 
88
89
  def search_key(self, key: bytes) -> Node:
89
90
  """Search the index for a specific ``key``.
@@ -105,20 +106,27 @@ class Index:
105
106
  values = {c.name: record[c.name] for c in self.columns}
106
107
  return self.make_key(values)
107
108
 
108
- def make_key(self, values: dict[str, RecordValue]) -> bytes:
109
+ def make_key(self, values: list[RecordValue] | dict[str, RecordValue]) -> bytes:
109
110
  """Generate a key out of the given values.
110
111
 
111
112
  Args:
112
- values: A map of the column names and values to generate a key for.
113
+ values: A map of the column names and values to generate a key for, or a list of values in the order of the
114
+ index columns.
113
115
  """
114
116
  key_buf = []
115
117
  key_remaining = self._key_most
116
118
 
117
- for column in self.columns:
118
- if column.name not in values:
119
- break
119
+ if isinstance(values, dict):
120
+ tmp = []
121
+ for column in self.columns:
122
+ if column.name not in values:
123
+ break
124
+ tmp.append(values[column.name])
125
+
126
+ values = tmp
120
127
 
121
- key_part = encode_key(self, column, values[column.name], self._var_seg_mac)
128
+ for column, value in zip(self.columns, values, strict=False):
129
+ key_part = encode_key(self, column, value, self._var_seg_mac)
122
130
  key_buf.append(key_part)
123
131
  key_remaining -= len(key_part)
124
132
 
@@ -1,5 +1,6 @@
1
1
  # Based on Wine source
2
2
  # https://github.com/wine-mirror/wine/blob/master/dlls/kernelbase/locale.c
3
+ # http://www.flounder.com/localeexplorer.htm
3
4
 
4
5
  from enum import IntEnum, IntFlag
5
6
 
@@ -0,0 +1,13 @@
1
+ from __future__ import annotations
2
+
3
+ from dissect.database.ese.ntds.ntds import NTDS
4
+ from dissect.database.ese.ntds.objects import Computer, Group, Object, Server, User
5
+
6
+ __all__ = [
7
+ "NTDS",
8
+ "Computer",
9
+ "Group",
10
+ "Object",
11
+ "Server",
12
+ "User",
13
+ ]
@@ -0,0 +1,94 @@
1
+ from __future__ import annotations
2
+
3
+ from dissect.cstruct import cstruct
4
+
5
+ ds_def = """
6
+ typedef struct _USER_PROPERTY {
7
+ WORD NameLength;
8
+ WORD ValueLength;
9
+ WORD PropertyFlag;
10
+ WCHAR PropertyName[NameLength / 2];
11
+ CHAR PropertyValue[ValueLength];
12
+ } USER_PROPERTY;
13
+
14
+ typedef struct _USER_PROPERTIES_HEADER {
15
+ DWORD Reserved1;
16
+ DWORD Length;
17
+ WORD Reserved2;
18
+ WORD Reserved3;
19
+ CHAR Reserved4[96];
20
+ WORD PropertySignature;
21
+ WORD PropertyCount;
22
+ } USER_PROPERTIES_HEADER;
23
+
24
+ typedef struct _ADAM_PROPERTIES_HEADER { // For lack of a better name
25
+ DWORD Reserved1;
26
+ DWORD Reserved2;
27
+ DWORD Reserved3;
28
+ DWORD Reserved4;
29
+ DWORD Reserved5;
30
+ DWORD Reserved6;
31
+ } ADAM_PROPERTIES_HEADER;
32
+
33
+ typedef struct _KERB_KEY_DATA {
34
+ WORD Reserved1;
35
+ WORD Reserved2;
36
+ DWORD Reserved3;
37
+ DWORD KeyType;
38
+ DWORD KeyLength;
39
+ DWORD KeyOffset;
40
+ } KERB_KEY_DATA;
41
+
42
+ typedef struct _KERB_STORED_CREDENTIAL {
43
+ WORD Revision;
44
+ WORD Flags;
45
+ WORD CredentialCount;
46
+ WORD OldCredentialCount;
47
+ WORD DefaultSaltLength;
48
+ WORD DefaultSaltMaximumLength;
49
+ DWORD DefaultSaltOffset;
50
+ KERB_KEY_DATA Credentials[CredentialCount];
51
+ KERB_KEY_DATA OldCredentials[OldCredentialCount];
52
+ // CHAR DefaultSalt[DefaultSaltLength];
53
+ // CHAR KeyValues[...];
54
+ } KERB_STORED_CREDENTIAL;
55
+
56
+ typedef struct _KERB_KEY_DATA_NEW {
57
+ WORD Reserved1;
58
+ WORD Reserved2;
59
+ DWORD Reserved3;
60
+ DWORD IterationCount;
61
+ DWORD KeyType;
62
+ DWORD KeyLength;
63
+ DWORD KeyOffset;
64
+ } KERB_KEY_DATA_NEW;
65
+
66
+ typedef struct _KERB_STORED_CREDENTIAL_NEW {
67
+ WORD Revision;
68
+ WORD Flags;
69
+ WORD CredentialCount;
70
+ WORD ServiceCredentialCount;
71
+ WORD OldCredentialCount;
72
+ WORD OlderCredentialCount;
73
+ WORD DefaultSaltLength;
74
+ WORD DefaultSaltMaximumLength;
75
+ DWORD DefaultSaltOffset;
76
+ DWORD DefaultIterationCount;
77
+ KERB_KEY_DATA_NEW Credentials[CredentialCount];
78
+ KERB_KEY_DATA_NEW ServiceCredentials[ServiceCredentialCount];
79
+ KERB_KEY_DATA_NEW OldCredentials[OldCredentialCount];
80
+ KERB_KEY_DATA_NEW OlderCredentials[OlderCredentialCount];
81
+ // CHAR DefaultSalt[DefaultSaltLength];
82
+ // CHAR KeyValues[...];
83
+ } KERB_STORED_CREDENTIAL_NEW;
84
+
85
+ typedef struct _WDIGEST_CREDENTIALS {
86
+ BYTE Reserved1;
87
+ BYTE Reserved2;
88
+ BYTE Version;
89
+ BYTE NumberOfHashes;
90
+ CHAR Reserved3[12];
91
+ CHAR Hash[29][16]; // The formal definition has Hash1, Hash2, ..., Hash29
92
+ } WDIGEST_CREDENTIALS;
93
+ """
94
+ c_ds = cstruct(ds_def)