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.
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/PKG-INFO +1 -1
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/database.py +6 -6
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/ntds.py +12 -3
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/__init__.py +2 -0
- dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/attributeschema.py +28 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/certificationauthority.py +5 -0
- dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/computer.py +51 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/configuration.py +5 -0
- dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/crossref.py +27 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/crossrefcontainer.py +5 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/domaindns.py +5 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/group.py +10 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/grouppolicycontainer.py +5 -0
- dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/msfve_recoveryinformation.py +45 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntdsdsa.py +5 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/object.py +41 -10
- dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/organizationalperson.py +33 -0
- dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/organizationalunit.py +51 -0
- dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/person.py +23 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/pkienrollmentservice.py +5 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/server.py +5 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/site.py +16 -1
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/top.py +5 -0
- dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/trusteddomain.py +49 -0
- dissect_database-1.2.dev9/dissect/database/ese/ntds/objects/user.py +141 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/schema.py +3 -3
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/util.py +103 -33
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/PKG-INFO +1 -1
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/SOURCES.txt +1 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/conftest.py +7 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_ntds.py +127 -1
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_pek.py +2 -2
- dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/attributeschema.py +0 -13
- dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/computer.py +0 -29
- dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/crossref.py +0 -13
- dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/organizationalperson.py +0 -18
- dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/organizationalunit.py +0 -26
- dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/person.py +0 -13
- dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/trusteddomain.py +0 -13
- dissect_database-1.2.dev7/dissect/database/ese/ntds/objects/user.py +0 -74
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/.git-blame-ignore-revs +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/COPYRIGHT +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/LICENSE +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/MANIFEST.in +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/README.md +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/c_db.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/c_db.pyi +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/db.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/tools/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/tools/c_rpm.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/tools/c_rpm.pyi +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/bsd/tools/rpm.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/c_ese.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/c_ese.pyi +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/compression.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/cursor.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ese.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/exception.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/index.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/lcmapstring.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_ds.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_ds.pyi +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_pek.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_pek.pyi +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_sd.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/c_sd.pyi +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/applicationsettings.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/builtindomain.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/classschema.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/classstore.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/container.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/controlaccessright.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/crldistributionpoint.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dfsconfiguration.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/displayspecifier.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dmd.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dnsnode.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dnszone.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/domain.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/domainpolicy.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/dsuisettings.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/filelinktracking.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/foreignsecurityprincipal.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/infrastructureupdate.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/intersitetransport.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/intersitetransportcontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecbase.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecfilter.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecisakmppolicy.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecnegotiationpolicy.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecnfa.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ipsecpolicy.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/leaf.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/linktrackobjectmovetable.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/linktrackvolumetable.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/locality.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/lostandfound.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msauthz_centralaccesspolicies.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msauthz_centralaccessrules.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_content.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_contentset.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_globalsettings.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_localsettings.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_member.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_replicationgroup.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_subscriber.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_subscription.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdfsr_topology.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msdns_serversettings.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_authnpolicies.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_authnpolicysilos.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_claimstransformationpolicies.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_claimtype.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_claimtypepropertybase.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_claimtypes.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_optionalfeature.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_passwordsettingscontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_quotacontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_resourceproperties.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_resourceproperty.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_resourcepropertylist.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_shadowprincipalcontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msds_valuetype.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msimaging_psps.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/mskds_provserverconfiguration.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msmqenterprisesettings.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/mspki_enterpriseoid.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/mspki_privatekeyrecoveryagent.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/msspp_activationobjectscontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/mstpm_informationobjectscontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntdsconnection.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntdsservice.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntdssitesettings.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntfrssettings.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/physicallocation.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/pkicertificatetemplate.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/querypolicy.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ridmanager.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ridset.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/rpccontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/rrasadministrationdictionary.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/samserver.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/secret.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/securityobject.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/serverscontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/sitelink.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/sitescontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/subnetcontainer.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/subschema.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/pek.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/query.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/sd.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/tools/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/tools/ntds.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/page.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/record.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/sorting_table.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/table.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/certlog.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/impacket.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/sru.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/tools/ual.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/util.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/exception.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/c_sqlite3.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/c_sqlite3.pyi +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/encryption/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/encryption/sqlcipher/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/encryption/sqlcipher/exception.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/encryption/sqlcipher/sqlcipher.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/exception.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/sqlite3.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/util.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/sqlite3/wal.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/dependency_links.txt +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/entry_points.txt +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/requires.txt +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect.database.egg-info/top_level.txt +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/pyproject.toml +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/setup.cfg +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_docs/Makefile +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_docs/conf.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_docs/index.rst +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_tools/sqlite3/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_tools/sqlite3/generate_sqlite.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/_util.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/bsd/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/bsd/conftest.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/bsd/test_db.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/bsd/test_rpm.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/conftest.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/conftest.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_benchmark.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_query.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_schema.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_sd.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/ntds/test_util.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_cursor.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_ese.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_index.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_page.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_record.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/test_table.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/tools/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/tools/test_certlog.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/tools/test_sru.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/ese/tools/test_ual.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/__init__.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/conftest.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_default_values.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_row.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_sqlcipher.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_sqlite3.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_util.py +0 -0
- {dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/tests/sqlite3/test_wal.py +0 -0
- {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.
|
|
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
|
{dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/database.py
RENAMED
|
@@ -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,
|
|
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) ->
|
|
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 =
|
|
52
|
+
result = DatabaseFlag(0)
|
|
53
53
|
flags = self.hiddeninfo.get("flags_col")
|
|
54
|
-
for idx, member in enumerate(
|
|
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
|
|
259
|
+
if SearchFlag.Indexed in schema.search_flags:
|
|
260
260
|
name = f"INDEX_{schema.id:08x}"
|
|
261
|
-
elif
|
|
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(
|
|
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(
|
|
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(
|
|
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")
|
|
@@ -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")
|
|
@@ -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")
|
{dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/group.py
RENAMED
|
@@ -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()
|
|
@@ -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
|
{dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/ntdsdsa.py
RENAMED
|
@@ -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()
|
{dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/object.py
RENAMED
|
@@ -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
|
|
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
|
-
|
|
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] =
|
|
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) ->
|
|
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
|
-
|
|
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")
|
{dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/server.py
RENAMED
|
@@ -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()
|
{dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/site.py
RENAMED
|
@@ -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."""
|
{dissect_database-1.2.dev7 → dissect_database-1.2.dev9}/dissect/database/ese/ntds/objects/top.py
RENAMED
|
@@ -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")
|