Skip to content

Commit

Permalink
fix: msPKI-RA-Application-Policies parsing (#88)
Browse files Browse the repository at this point in the history
  • Loading branch information
JonasBK authored Jan 19, 2024
1 parent da92d29 commit fb9b86c
Show file tree
Hide file tree
Showing 4 changed files with 61 additions and 3 deletions.
24 changes: 24 additions & 0 deletions src/CommonLib/Enums/PKIPrivateKeyFlag.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;

namespace SharpHoundCommonLib.Enums
{
// from https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-crtd/f6122d87-b999-4b92-bff8-f465e8949667
[Flags]
public enum PKIPrivateKeyFlag : uint
{
REQUIRE_PRIVATE_KEY_ARCHIVAL = 0x00000001,
EXPORTABLE_KEY = 0x00000010,
STRONG_KEY_PROTECTION_REQUIRED = 0x00000020,
REQUIRE_ALTERNATE_SIGNATURE_ALGORITHM = 0x00000040,
REQUIRE_SAME_KEY_RENEWAL = 0x00000080,
USE_LEGACY_PROVIDER = 0x00000100,
ATTEST_NONE = 0x00000000,
ATTEST_REQUIRED = 0x00002000,
ATTEST_PREFERRED = 0x00001000,
ATTESTATION_WITHOUT_POLICY = 0x00004000,
EK_TRUST_ON_USE = 0x00000200,
EK_VALIDATE_CERT = 0x00000400,
EK_VALIDATE_KEY = 0x00000800,
HELLO_LOGON_KEY = 0x00200000
}
}
1 change: 1 addition & 0 deletions src/CommonLib/LDAPProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ public static class LDAPProperties
public const string PKINameFlag = "mspki-certificate-name-flag";
public const string ExtendedKeyUsage = "pkiextendedkeyusage";
public const string NumSignaturesRequired = "mspki-ra-signature";
public const string PKIPrivateKeyFlag = "mspki-private-key-flag";
public const string ApplicationPolicies = "mspki-ra-application-policies";
public const string IssuancePolicies = "mspki-ra-policies";
public const string CertificateApplicationPolicy = "mspki-certificate-application-policy";
Expand Down
2 changes: 1 addition & 1 deletion src/CommonLib/LDAPQueries/CommonProperties.cs
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ public static class CommonProperties
LDAPProperties.PKIEnrollmentFlag, LDAPProperties.DisplayName, LDAPProperties.Name, LDAPProperties.TemplateSchemaVersion, LDAPProperties.CertTemplateOID,
LDAPProperties.PKIOverlappedPeriod, LDAPProperties.PKIExpirationPeriod, LDAPProperties.ExtendedKeyUsage, LDAPProperties.NumSignaturesRequired,
LDAPProperties.CertificateApplicationPolicy, LDAPProperties.IssuancePolicies, LDAPProperties.CrossCertificatePair,
LDAPProperties.ApplicationPolicies
LDAPProperties.ApplicationPolicies, LDAPProperties.PKIPrivateKeyFlag
};
}
}
37 changes: 35 additions & 2 deletions src/CommonLib/Processors/LDAPPropertyProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -514,9 +514,15 @@ public static Dictionary<string, object> ReadCertTemplateProperties(ISearchResul
if (entry.GetIntProperty(LDAPProperties.NumSignaturesRequired, out var authorizedSignatures))
props.Add("authorizedsignatures", authorizedSignatures);

props.Add("applicationpolicies", entry.GetArrayProperty(LDAPProperties.ApplicationPolicies));
props.Add("issuancepolicies", entry.GetArrayProperty(LDAPProperties.IssuancePolicies));
bool hasUseLegacyProvider = false;
if (entry.GetIntProperty(LDAPProperties.PKIPrivateKeyFlag, out var privateKeyFlagsRaw))
{
var privateKeyFlags = (PKIPrivateKeyFlag)privateKeyFlagsRaw;
hasUseLegacyProvider = privateKeyFlags.HasFlag(PKIPrivateKeyFlag.USE_LEGACY_PROVIDER);
}

props.Add("applicationpolicies", ParseCertTemplateApplicationPolicies(entry.GetArrayProperty(LDAPProperties.ApplicationPolicies), schemaVersion, hasUseLegacyProvider));
props.Add("issuancepolicies", entry.GetArrayProperty(LDAPProperties.IssuancePolicies));

// Construct effectiveekus
string[] effectiveekus = schemaVersion == 1 & ekus.Length > 0 ? ekus : certificateapplicationpolicy;
Expand Down Expand Up @@ -578,6 +584,33 @@ public Dictionary<string, object> ParseAllProperties(ISearchResultEntry entry)
return props;
}

/// <summary>
/// Parse CertTemplate attribute msPKI-RA-Application-Policies
/// </summary>
/// <param name="applicationPolicies"></param>
/// <param name="schemaVersion"></param>
/// <param name="hasUseLegacyProvider"></param>
private static string[] ParseCertTemplateApplicationPolicies(string[] applicationPolicies, int schemaVersion, bool hasUseLegacyProvider)
{
if (applicationPolicies == null
|| applicationPolicies.Length == 0
|| schemaVersion == 1
|| schemaVersion == 2
|| (schemaVersion == 4 && hasUseLegacyProvider)) {
return applicationPolicies;
} else {
// 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('`');
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))
.Select(parts => parts[2])
.ToArray();
}
}

/// <summary>
/// Does a best guess conversion of the property to a type useable by the UI
/// </summary>
Expand Down

0 comments on commit fb9b86c

Please sign in to comment.