Skip to content

Commit

Permalink
feat: add IssuancePolicy nodes
Browse files Browse the repository at this point in the history
  • Loading branch information
rvazarkar committed Mar 20, 2024
1 parent fd37e67 commit 5924988
Show file tree
Hide file tree
Showing 5 changed files with 36 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/CommonLib/Enums/DirectoryPaths.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,5 +9,6 @@ public class DirectoryPaths
public const string NTAuthStoreLocation = "CN=NTAuthCertificates,CN=Public Key Services,CN=Services,CN=Configuration";
public const string PKILocation = "CN=Public Key Services,CN=Services,CN=Configuration";
public const string ConfigLocation = "CN=Configuration";
public const string OIDContainerLocation = "CN=OID,CN=Public Key Services,CN=Services,CN=Configuration";
}
}
3 changes: 2 additions & 1 deletion src/CommonLib/Enums/Labels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public enum Label
RootCA,
AIACA,
EnterpriseCA,
NTAuthStore
NTAuthStore,
IssuancePolicy
}
}
17 changes: 15 additions & 2 deletions src/CommonLib/Extensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -375,14 +375,26 @@ public static Label GetLabel(this SearchResultEntry entry)
objectType = Label.CertTemplate;
else if (objectClasses.Contains(PKIEnrollmentServiceClass, StringComparer.InvariantCultureIgnoreCase))
objectType = Label.EnterpriseCA;
else if (objectClasses.Contains(CertificationAutorityClass, StringComparer.InvariantCultureIgnoreCase))
else if (objectClasses.Contains(CertificationAuthorityClass, StringComparer.InvariantCultureIgnoreCase))
{
if (entry.DistinguishedName.Contains(DirectoryPaths.RootCALocation))
objectType = Label.RootCA;
else if (entry.DistinguishedName.Contains(DirectoryPaths.AIACALocation))
objectType = Label.AIACA;
else if (entry.DistinguishedName.Contains(DirectoryPaths.NTAuthStoreLocation))
objectType = Label.NTAuthStore;
}else if (objectClasses.Contains(OIDContainerClass, StringComparer.InvariantCultureIgnoreCase))
{
if (entry.DistinguishedName.StartsWith(DirectoryPaths.OIDContainerLocation,
StringComparison.InvariantCultureIgnoreCase))
objectType = Label.Container;
else
{
if (entry.GetPropertyAsInt(LDAPProperties.Flags, out var flags) && flags == 2)
{
objectType = Label.IssuancePolicy;
}
}
}
}

Expand All @@ -400,7 +412,8 @@ public static Label GetLabel(this SearchResultEntry entry)
private const string ConfigurationClass = "configuration";
private const string PKICertificateTemplateClass = "pKICertificateTemplate";
private const string PKIEnrollmentServiceClass = "pKIEnrollmentService";
private const string CertificationAutorityClass = "certificationAuthority";
private const string CertificationAuthorityClass = "certificationAuthority";
private const string OIDContainerClass = "msPKI-Enterprise-Oid";

#endregion
}
Expand Down
26 changes: 17 additions & 9 deletions src/CommonLib/Processors/LDAPPropertyProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ public static Dictionary<string, object> ReadRootCAProperties(ISearchResultEntry
var rawCertificate = entry.GetByteProperty(LDAPProperties.CACertificate);
if (rawCertificate != null)
{
ParsedCertificate cert = new ParsedCertificate(rawCertificate);
var cert = new ParsedCertificate(rawCertificate);
props.Add("certthumbprint", cert.Thumbprint);
props.Add("certname", cert.Name);
props.Add("certchain", cert.Chain);
Expand Down Expand Up @@ -414,7 +414,7 @@ public static Dictionary<string, object> ReadAIACAProperties(ISearchResultEntry
var rawCertificate = entry.GetByteProperty(LDAPProperties.CACertificate);
if (rawCertificate != null)
{
ParsedCertificate cert = new ParsedCertificate(rawCertificate);
var cert = new ParsedCertificate(rawCertificate);
props.Add("certthumbprint", cert.Thumbprint);
props.Add("certname", cert.Name);
props.Add("certchain", cert.Chain);
Expand All @@ -436,7 +436,7 @@ public static Dictionary<string, object> ReadEnterpriseCAProperties(ISearchResul
var rawCertificate = entry.GetByteProperty(LDAPProperties.CACertificate);
if (rawCertificate != null)
{
ParsedCertificate cert = new ParsedCertificate(rawCertificate);
var cert = new ParsedCertificate(rawCertificate);
props.Add("certthumbprint", cert.Thumbprint);
props.Add("certname", cert.Name);
props.Add("certchain", cert.Chain);
Expand Down Expand Up @@ -506,15 +506,15 @@ public static Dictionary<string, object> ReadCertTemplateProperties(ISearchResul
nameFlags.HasFlag(PKICertificateNameFlag.SUBJECT_REQUIRE_EMAIL));
}

string[] ekus = entry.GetArrayProperty(LDAPProperties.ExtendedKeyUsage);
var ekus = entry.GetArrayProperty(LDAPProperties.ExtendedKeyUsage);
props.Add("ekus", ekus);
string[] certificateapplicationpolicy = entry.GetArrayProperty(LDAPProperties.CertificateApplicationPolicy);
var certificateapplicationpolicy = entry.GetArrayProperty(LDAPProperties.CertificateApplicationPolicy);
props.Add("certificateapplicationpolicy", certificateapplicationpolicy);

if (entry.GetIntProperty(LDAPProperties.NumSignaturesRequired, out var authorizedSignatures))
props.Add("authorizedsignatures", authorizedSignatures);

bool hasUseLegacyProvider = false;
var hasUseLegacyProvider = false;
if (entry.GetIntProperty(LDAPProperties.PKIPrivateKeyFlag, out var privateKeyFlagsRaw))
{
var privateKeyFlags = (PKIPrivateKeyFlag)privateKeyFlagsRaw;
Expand All @@ -525,16 +525,24 @@ public static Dictionary<string, object> ReadCertTemplateProperties(ISearchResul
props.Add("issuancepolicies", entry.GetArrayProperty(LDAPProperties.IssuancePolicies));

// Construct effectiveekus
string[] effectiveekus = schemaVersion == 1 & ekus.Length > 0 ? ekus : certificateapplicationpolicy;
var effectiveekus = schemaVersion == 1 & ekus.Length > 0 ? ekus : certificateapplicationpolicy;
props.Add("effectiveekus", effectiveekus);

// Construct authenticationenabled
bool authenticationenabled = effectiveekus.Intersect(Helpers.AuthenticationOIDs).Any() | effectiveekus.Length == 0;
var authenticationenabled = effectiveekus.Intersect(Helpers.AuthenticationOIDs).Any() | effectiveekus.Length == 0;
props.Add("authenticationenabled", authenticationenabled);

return props;
}

public Dictionary<string, object> ReadIssuancePolicyProperties(ISearchResultEntry entry)
{
var props = GetCommonProps(entry);
props.Add("displayname", entry.GetProperty(LDAPProperties.DisplayName));

return props;
}

/// <summary>
/// Attempts to parse all LDAP attributes outside of the ones already collected and converts them to a human readable
/// format using a best guess
Expand Down Expand Up @@ -602,7 +610,7 @@ private static string[] ParseCertTemplateApplicationPolicies(string[] applicatio
// Format: "Name`Type`Value`Name`Type`Value`..."
// (https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/c55ec697-be3f-4117-8316-8895e4399237)
// Return the Value of Name = "msPKI-RA-Application-Policies" entries
string[] entries = applicationPolicies[0].Split('`');
var entries = applicationPolicies[0].Split('`');
return Enumerable.Range(0, entries.Length / 3)
.Select(i => entries.Skip(i * 3).Take(3).ToArray())
.Where(parts => parts.Length == 3 && parts[0].Equals(LDAPProperties.ApplicationPolicies, StringComparison.OrdinalIgnoreCase))
Expand Down
1 change: 1 addition & 0 deletions src/CommonLib/SearchResultEntryWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ public ResolvedSearchResult ResolveBloodHoundInfo()

break;
case Label.GPO:
case Label.IssuancePolicy:
res.DisplayName = $"{GetProperty(LDAPProperties.DisplayName)}@{itemDomain}";
break;
case Label.Domain:
Expand Down

0 comments on commit 5924988

Please sign in to comment.