diff --git a/Sharphound.csproj b/Sharphound.csproj index 53049bc..d479efa 100644 --- a/Sharphound.csproj +++ b/Sharphound.csproj @@ -24,8 +24,8 @@ - - + + @@ -33,14 +33,14 @@ - + - + diff --git a/src/Producers/BaseProducer.cs b/src/Producers/BaseProducer.cs index 8bf7016..b8fd9f2 100644 --- a/src/Producers/BaseProducer.cs +++ b/src/Producers/BaseProducer.cs @@ -151,7 +151,7 @@ protected LDAPData CreateConfigNCData() props.AddRange(CommonProperties.TypeResolutionProps); var methods = Context.ResolvedCollectionMethods; - var allObjectTypesQuery = new LDAPFilter().AddContainers().AddConfiguration().AddCertificateTemplates().AddCertificateAuthorities().AddEnterpriseCertificationAuthorities(); + var allObjectTypesQuery = new LDAPFilter().AddContainers().AddConfiguration().AddCertificateTemplates().AddCertificateAuthorities().AddEnterpriseCertificationAuthorities().AddIssuancePolicies(); if ((methods & ResolvedCollectionMethod.ObjectProps) != 0) { diff --git a/src/Producers/ComputerFileProducer.cs b/src/Producers/ComputerFileProducer.cs index 369525e..7069778 100644 --- a/src/Producers/ComputerFileProducer.cs +++ b/src/Producers/ComputerFileProducer.cs @@ -80,7 +80,9 @@ public override async Task Produce() } } +#pragma warning disable CS1998 // Async method lacks 'await' operators and will run synchronously public override async Task ProduceConfigNC() +#pragma warning restore CS1998 // Async method lacks 'await' operators and will run synchronously { // Does not make sense for Computer file } diff --git a/src/Runtime/ObjectProcessors.cs b/src/Runtime/ObjectProcessors.cs index c94d399..ae9779b 100644 --- a/src/Runtime/ObjectProcessors.cs +++ b/src/Runtime/ObjectProcessors.cs @@ -80,15 +80,17 @@ internal async Task ProcessObject(ISearchResultEntry entry, case Label.Configuration: return ProcessContainerObject(entry, resolvedSearchResult); case Label.RootCA: - return await ProcessRootCA(entry, resolvedSearchResult); + return ProcessRootCA(entry, resolvedSearchResult); case Label.AIACA: - return await ProcessAIACA(entry, resolvedSearchResult); + return ProcessAIACA(entry, resolvedSearchResult); case Label.EnterpriseCA: return await ProcessEnterpriseCA(entry, resolvedSearchResult); case Label.NTAuthStore: - return await ProcessNTAuthStore(entry, resolvedSearchResult); + return ProcessNTAuthStore(entry, resolvedSearchResult); case Label.CertTemplate: - return await ProcessCertTemplate(entry, resolvedSearchResult); + return ProcessCertTemplate(entry, resolvedSearchResult); + case Label.IssuancePolicy: + return ProcessIssuancePolicy(entry, resolvedSearchResult); case Label.Base: return null; default: @@ -525,7 +527,7 @@ private Container ProcessContainerObject(ISearchResultEntry entry, return ret; } - private async Task ProcessRootCA(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) + private RootCA ProcessRootCA(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) { var ret = new RootCA { @@ -560,7 +562,7 @@ private async Task ProcessRootCA(ISearchResultEntry entry, ResolvedSearc return ret; } - private async Task ProcessAIACA(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) + private AIACA ProcessAIACA(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) { var ret = new AIACA { @@ -669,7 +671,7 @@ private async Task ProcessEnterpriseCA(ISearchResultEntry entry, R return ret; } - private async Task ProcessNTAuthStore(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) + private NTAuthStore ProcessNTAuthStore(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) { var ret = new NTAuthStore { @@ -710,7 +712,7 @@ private async Task ProcessNTAuthStore(ISearchResultEntry entry, Res return ret; } - private async Task ProcessCertTemplate(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) + private CertTemplate ProcessCertTemplate(ISearchResultEntry entry, ResolvedSearchResult resolvedSearchResult) { var ret = new CertTemplate { @@ -742,5 +744,40 @@ private async Task ProcessCertTemplate(ISearchResultEntry entry, R return ret; } + + private IssuancePolicy ProcessIssuancePolicy(ISearchResultEntry entry, + ResolvedSearchResult resolvedSearchResult) + { + var ret = new IssuancePolicy + { + ObjectIdentifier = resolvedSearchResult.ObjectId + }; + + ret.Properties.Add("domain", resolvedSearchResult.Domain); + ret.Properties.Add("name", resolvedSearchResult.DisplayName); + ret.Properties.Add("distinguishedname", entry.DistinguishedName.ToUpper()); + ret.Properties.Add("domainsid", resolvedSearchResult.DomainSid); + + if ((_methods & ResolvedCollectionMethod.ACL) != 0 || (_methods & ResolvedCollectionMethod.CertServices) != 0) + { + ret.Aces = _aclProcessor.ProcessACL(resolvedSearchResult, entry).ToArray(); + ret.IsACLProtected = _aclProcessor.IsACLProtected(entry); + ret.Properties.Add("isaclprotected", ret.IsACLProtected); + } + + if ((_methods & ResolvedCollectionMethod.ObjectProps) != 0 || (_methods & ResolvedCollectionMethod.CertServices) != 0) + { + var issuancePolicyProps = _ldapPropertyProcessor.ReadIssuancePolicyProperties(entry); + ret.Properties.Merge(issuancePolicyProps.Props); + ret.GroupLink = issuancePolicyProps.GroupLink; + } + + if ((_methods & ResolvedCollectionMethod.Container) != 0 || (_methods & ResolvedCollectionMethod.CertServices) != 0) + { + ret.ContainedBy = _containerProcessor.GetContainingObject(entry.DistinguishedName); + } + + return ret; + } } } diff --git a/src/Runtime/OutputWriter.cs b/src/Runtime/OutputWriter.cs index 5258c7d..70820af 100644 --- a/src/Runtime/OutputWriter.cs +++ b/src/Runtime/OutputWriter.cs @@ -33,6 +33,7 @@ public class OutputWriter private readonly JsonDataWriter _enterpriseCAOutput; private readonly JsonDataWriter _nTAuthStoreOutput; private readonly JsonDataWriter _certTemplateOutput; + private readonly JsonDataWriter _issuancePolicyOutput; private int _completedCount; @@ -55,6 +56,7 @@ public OutputWriter(IContext context, Channel outputChannel) _enterpriseCAOutput = new JsonDataWriter(_context, DataType.EnterpriseCAs); _nTAuthStoreOutput = new JsonDataWriter(_context, DataType.NTAuthStores); _certTemplateOutput = new JsonDataWriter(_context, DataType.CertTemplates); + _issuancePolicyOutput = new JsonDataWriter(_context, DataType.IssuancePolicies); _runTimer = new Stopwatch(); _statusTimer = new Timer(_context.StatusInterval); @@ -140,6 +142,9 @@ internal async Task StartWriter() case CertTemplate certTemplate: await _certTemplateOutput.AcceptObject(certTemplate); break; + case IssuancePolicy issuancePolicy: + await _issuancePolicyOutput.AcceptObject(issuancePolicy); + break; default: throw new ArgumentOutOfRangeException(nameof(item)); } @@ -163,6 +168,7 @@ private async Task FlushWriters() await _enterpriseCAOutput.FlushWriter(); await _nTAuthStoreOutput.FlushWriter(); await _certTemplateOutput.FlushWriter(); + await _issuancePolicyOutput.FlushWriter(); CloseOutput(); var fileName = ZipFiles(); return fileName; @@ -192,7 +198,7 @@ private string ZipFiles() _containerOutput.GetFilename(), _domainOutput.GetFilename(), _gpoOutput.GetFilename(), _ouOutput.GetFilename(), _rootCAOutput.GetFilename(), _aIACAOutput.GetFilename(), _enterpriseCAOutput.GetFilename(), _nTAuthStoreOutput.GetFilename(), - _certTemplateOutput.GetFilename() + _certTemplateOutput.GetFilename(),_issuancePolicyOutput.GetFilename() }); foreach (var entry in fileList.Where(x => !string.IsNullOrEmpty(x))) diff --git a/src/Sharphound.cs b/src/Sharphound.cs index b4853c5..920c73a 100644 --- a/src/Sharphound.cs +++ b/src/Sharphound.cs @@ -130,7 +130,7 @@ public IContext Initialize(IContext context, LDAPConfig options) } catch (Exception e) { - context.Logger.LogCritical("unable to write to target directory"); + context.Logger.LogCritical(e, "unable to write to target directory"); context.Flags.IsFaulted = true; } }