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.
- dissect_database-1.1.dev4/MANIFEST.in +4 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/PKG-INFO +6 -3
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/btree.py +30 -19
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/c_ese.py +19 -2
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/c_ese.pyi +16 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/cursor.py +74 -54
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/ese.py +1 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/index.py +16 -8
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/lcmapstring.py +1 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/__init__.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/c_ds.py +94 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/c_ds.pyi +329 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/c_pek.py +59 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/c_pek.pyi +125 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/c_sd.py +121 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/c_sd.pyi +158 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/database.py +414 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/ntds.py +91 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/__init__.py +213 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/applicationsettings.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/attributeschema.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/builtindomain.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/certificationauthority.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/classschema.py +42 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/classstore.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/computer.py +29 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/configuration.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/container.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/controlaccessright.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/crldistributionpoint.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/crossref.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/crossrefcontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dfsconfiguration.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/displayspecifier.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dmd.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dnsnode.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dnszone.py +26 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/domain.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/domaindns.py +21 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/domainpolicy.py +26 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/dsuisettings.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/filelinktracking.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/foreignsecurityprincipal.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/group.py +48 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/grouppolicycontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/infrastructureupdate.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/intersitetransport.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/intersitetransportcontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecbase.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecfilter.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecisakmppolicy.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecnegotiationpolicy.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecnfa.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ipsecpolicy.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/leaf.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/linktrackobjectmovetable.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/linktrackvolumetable.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/locality.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/lostandfound.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msauthz_centralaccesspolicies.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msauthz_centralaccessrules.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_content.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_contentset.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_globalsettings.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_localsettings.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_member.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_replicationgroup.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_subscriber.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_subscription.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdfsr_topology.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msdns_serversettings.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_authnpolicies.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_authnpolicysilos.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_claimstransformationpolicies.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_claimtype.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_claimtypepropertybase.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_claimtypes.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_optionalfeature.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_passwordsettingscontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_quotacontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_resourceproperties.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_resourceproperty.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_resourcepropertylist.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_shadowprincipalcontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msds_valuetype.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msimaging_psps.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/mskds_provserverconfiguration.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msmqenterprisesettings.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/mspki_enterpriseoid.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/mspki_privatekeyrecoveryagent.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/msspp_activationobjectscontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/mstpm_informationobjectscontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntdsconnection.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntdsdsa.py +26 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntdsservice.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntdssitesettings.py +26 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ntfrssettings.py +26 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/object.py +267 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/organizationalperson.py +18 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/organizationalunit.py +26 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/person.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/physicallocation.py +26 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/pkicertificatetemplate.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/pkienrollmentservice.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/querypolicy.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ridmanager.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/ridset.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/rpccontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/rrasadministrationdictionary.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/samserver.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/secret.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/securityobject.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/server.py +26 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/serverscontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/site.py +26 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/sitelink.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/sitescontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/subnetcontainer.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/subschema.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/top.py +16 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/trusteddomain.py +13 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/objects/user.py +68 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/pek.py +134 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/query.py +218 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/schema.py +350 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/sd.py +191 -0
- dissect_database-1.1.dev4/dissect/database/ese/ntds/util.py +497 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/record.py +7 -1
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/table.py +44 -32
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/sqlite3.py +15 -7
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect.database.egg-info/PKG-INFO +6 -3
- dissect_database-1.1.dev4/dissect.database.egg-info/SOURCES.txt +206 -0
- dissect_database-1.1.dev4/dissect.database.egg-info/requires.txt +10 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/pyproject.toml +7 -2
- dissect_database-1.1.dev4/tests/conftest.py +19 -0
- dissect_database-1.1.dev4/tests/ese/ntds/conftest.py +47 -0
- dissect_database-1.1.dev4/tests/ese/ntds/test_benchmark.py +49 -0
- dissect_database-1.1.dev4/tests/ese/ntds/test_ntds.py +261 -0
- dissect_database-1.1.dev4/tests/ese/ntds/test_pek.py +37 -0
- dissect_database-1.1.dev4/tests/ese/ntds/test_query.py +121 -0
- dissect_database-1.1.dev4/tests/ese/ntds/test_schema.py +16 -0
- dissect_database-1.1.dev4/tests/ese/ntds/test_sd.py +19 -0
- dissect_database-1.1.dev4/tests/ese/ntds/test_util.py +110 -0
- dissect_database-1.1.dev4/tests/sqlite3/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tox.ini +11 -1
- dissect_database-1.1.dev2/.gitattributes +0 -1
- dissect_database-1.1.dev2/MANIFEST.in +0 -2
- dissect_database-1.1.dev2/dissect.database.egg-info/SOURCES.txt +0 -97
- dissect_database-1.1.dev2/dissect.database.egg-info/requires.txt +0 -6
- dissect_database-1.1.dev2/tests/_data/bsd/btree.db.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/bsd/hash.db.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/bsd/recno.db.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/bsd/rpm/Packages.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/Windows.edb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/basic.edb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/binary.edb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/default.edb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/index.edb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/large.edb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/multi.edb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/text.edb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/tools/CertLog.edb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/tools/Current.mdb.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/ese/tools/SRUDB.dat.gz +0 -0
- dissect_database-1.1.dev2/tests/_data/sqlite3/empty.sqlite +0 -0
- dissect_database-1.1.dev2/tests/_data/sqlite3/test.sqlite +0 -0
- dissect_database-1.1.dev2/tests/_data/sqlite3/test.sqlite-wal +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/COPYRIGHT +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/LICENSE +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/README.md +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/c_db.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/c_db.pyi +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/db.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/tools/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/tools/c_rpm.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/tools/c_rpm.pyi +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/bsd/tools/rpm.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/compression.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/exception.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/page.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/sorting_table.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/certlog.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/impacket.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/sru.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/tools/ual.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/ese/util.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/exception.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/c_sqlite3.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/c_sqlite3.pyi +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/exception.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/util.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect/database/sqlite3/wal.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect.database.egg-info/dependency_links.txt +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/dissect.database.egg-info/top_level.txt +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/setup.cfg +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_docs/Makefile +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_docs/conf.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_docs/index.rst +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_tools/sqlite3/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_tools/sqlite3/generate_sqlite.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/_util.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/bsd/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/bsd/conftest.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/bsd/test_db.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/bsd/test_rpm.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/conftest.py +0 -0
- {dissect_database-1.1.dev2/tests/ese/tools → dissect_database-1.1.dev4/tests/ese/ntds}/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_cursor.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_ese.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_index.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_page.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_record.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/test_table.py +0 -0
- {dissect_database-1.1.dev2/tests/sqlite3 → dissect_database-1.1.dev4/tests/ese/tools}/__init__.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/tools/test_certlog.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/tools/test_sru.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/ese/tools/test_ual.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/conftest.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_default_values.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_row.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_sqlite3.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_util.py +0 -0
- {dissect_database-1.1.dev2 → dissect_database-1.1.dev4}/tests/sqlite3/test_wal.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dissect.database
|
|
3
|
-
Version: 1.1.
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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) ->
|
|
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
|
-
|
|
143
|
-
|
|
151
|
+
lo, hi = 0, page.node_count - 1
|
|
152
|
+
res = 0
|
|
144
153
|
|
|
145
154
|
node = None
|
|
146
|
-
while
|
|
147
|
-
|
|
148
|
-
node = page.node(
|
|
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
|
-
|
|
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
|
-
|
|
163
|
+
if res < 0:
|
|
164
|
+
lo = mid + 1
|
|
162
165
|
else:
|
|
163
|
-
|
|
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
|
-
|
|
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
|
-
//
|
|
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
|
-
//
|
|
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
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
|
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) ->
|
|
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
|
-
|
|
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.
|
|
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.
|
|
141
|
+
return self.record()
|
|
92
142
|
|
|
93
|
-
def seek(self, **kwargs: RecordValue) ->
|
|
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.
|
|
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) ->
|
|
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
|
-
|
|
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.
|
|
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()
|
|
@@ -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
|
-
|
|
118
|
-
|
|
119
|
-
|
|
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
|
-
|
|
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
|
|
|
@@ -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)
|