Category: Windows

Venafi Issue – Certs Immediately Revoked as Superseded When Using Stand-Alone Microsoft AD CS CA

Background:

Environment

  • Dev environment, Venafi 25.3.0.2740
  • Microsoft ADCS stand-alone CA
  • Enrollment method: DCOM
  • CA object uses a local account on the ADCS server
  • No custom workflows
  • No customizations
  • No consumers/app installation tied to the cert object
  • Simple certificate object created for testing

Problem

When a certificate is requested from Venafi against the stand-alone Microsoft CA, ADCS successfully issues the certificate, but the certificate is immediately revoked with revocation reason:

  • Superseded

This is happening to the same certificate that was just issued, not a prior cert.

Expected behavior

Venafi should submit the CSR, obtain the issued certificate, and leave the newly issued certificate valid.

Actual behavior

Venafi submits the CSR, ADCS issues the certificate successfully, and then the same certificate is immediately revoked as Superseded.

Evidence gathered

1. ADCS database confirms issued cert is the same cert being revoked

Example request:

  • Request ID: 41
  • Requester Name: HOSTNAME\venafi
  • Common Name: 20260331-withrevoke.example.com
  • Serial Number: 55000000299749d000d299f5ae000100000029
  • Disposition: Revoked
  • Disposition Message: Revoked by HOSTNAME\venafi
  • Revocation Reason: 0x4 — Superseded

This proves Venafi is revoking the cert it just obtained.

2. ADCS request contents are valid

For the same request, ADCS shows the CSR and issued certificate are normal and match expectations.

Request attributes

  • CertificateTemplate: WebServer
  • ccm: venafihost.servers.example.com

CSR / issued cert contents

  • Subject: CN=20260331-withrevoke.example.com, O=”Uniti Group, Inc”, L=Little Rock, S=Arkansas, C=US
  • SAN: DNS Name=20260331-withrevoke.example.com
  • RSA 2048 key
  • Certificate issued successfully before revoke

This suggests the CA is not returning malformed or obviously incorrect cert content.

3. Security event log confirms immediate issue then revoke

After enabling Certification Services auditing, Security log shows this sequence:

Event 4886

  • Certificate Services received the request

Event 4887

  • Certificate Services approved the request and issued the certificate
  • Requester: HOSTNAME\venafi
  • DCOM/RPC authentication path used
  • Template shown as WebServer

Event 4870

  • Certificate Services revoked the certificate
  • Same serial number as the issued certificate
  • Reason: 4 (Superseded)

This happens effectively immediately.

4. Pattern is repeatable

Querying the CA database for requests from HOSTNAME\venafi shows a repeated pattern where most requests are immediately revoked with:

  • Disposition: Revoked
  • Revocation Reason: Superseded
  • Disposition Message: Revoked by HOSTNAME\venafi

The exceptions were tests where revoke capability had been intentionally removed from the Venafi CA account.

5. Permission test changed behavior but did not fix root cause

When Issue and Manage Certificates was removed from the Venafi CA account, the request no longer completed the revoke path and instead failed earlier with:

  • PostCSR failed with error: CCertAdmin::SetCertificateExtension: Access is denied. 0x80070005

This indicates Venafi is performing CA administrative operations after CSR submission, and revocation happens later in that same general post-issuance path.

6. Procmon on the Venafi host shows VPlatform.exe using both CertRequest and CertAdmin

Procmon on CWWAPP1989D captured VPlatform.exe doing the following:

Cert enrollment path

VPlatform.exe queries and activates:

  • HKCR\CLSID\{98AFF3F0-5524-11D0-8812-00A0C903B83C}
  • CertRequest Class
  • C:\Windows\System32\certcli.dll

CA admin path

VPlatform.exe then queries and activates:

  • HKCR\CLSID\{37EABAF0-7FB6-11D0-8817-00A0C903B83C}
  • CertAdmin Class
  • %systemroot%\system32\certadm.dll

DCOM/RPC communication

Procmon also shows:

  • endpoint mapper (135) traffic via svchost.exe
  • VPlatform.exe connecting to the CA host on dynamic RPC port 50014

This strongly suggests:

  • VPlatform.exe first issues via CertRequest
  • then immediately performs CA admin operations via CertAdmin

Given the ADCS security logs, that admin path appears to be what revokes the newly issued cert.

Additional observations

Stand-alone CA

This is a stand-alone Microsoft CA, not enterprise template-based ADCS.

No special Venafi workflow/customization

This is a dev system with:

  • no custom workflows
  • no special consumers
  • no installation/application integration
  • minimal test object

That makes this look less like an environmental customization problem and more like:

  • default Venafi behavior in this integration path, or
  • a product defect in the stand-alone Microsoft CA DCOM path

Failed auth events also observed

We saw Security log 4625 failures from CWWAPP1989D for WINDSTREAM\g9897431.

From the Security log:

  • 11:53:34 — 4886 request received
  • 11:53:36 — 4887 certificate issued
  • 11:53:36 — 4870 certificate revoked
  • 11:53:36 — multiple 4625 failures for DOMAIN\venafisystemuser
  • 11:53:37 — another 4625

Since time resolution in the log is seconds, it is possible Venafi is requesting the cert under the configured credential (HOSTNAME\venafi), attempting to do something else under DOMAIN\venafisystemuser, getting an auth failure, and then revoking the certificate under the configured credential (DOMAIN\venafisystemuser). I would be surprised if this is the case because “superseded” is a very specific revocation reason. I would expect something like a generic “Unspecified” or “Cessation of Operation” to be used.

Summary conclusion

Current evidence indicates that:

  • Venafi successfully enrolls the certificate from the stand-alone Microsoft CA using DCOM / CertRequest
  • VPlatform.exe then immediately invokes the Microsoft CA admin COM interface (CertAdmin)
  • the newly issued certificate is then revoked by the Venafi CA account with reason Superseded

At this point, this appears to be:

  • Venafi-driven post-issuance behavior
  • not spontaneous ADCS behavior
  • and likely either:
    1. expected-but-unwanted default behavior in this integration mode, or
    2. a product defect in the stand-alone Microsoft CA DCOM workflow

Resolution

The issue was resolved by changing the policy module settings to set the cert request to pending instead of automatically issue. While I expected this to leave the cert in a pending state and require manual intervention (or a batch job to bulk approve whatever is pending), the cert was immediately issued.

 

Creating and Using an AD CS Custom Policy Module

This information relates to the custom CA policy module implementation at https://github.com/ljr55555/CustomEkuPolicy

Values Used in this Implementation

The following GUID values are used within the code

LIBID CustomEkuPolicyModule 71e54225-3720-45d5-a181-1ce854b74c58

CLSID CustomEkuPolicyModule bea77360-4ed0-469c-a888-7b5cac3b8776

Project GUID 98d72278-b7ab-4f6b-817c-55dac0796675

Documentation is written while adding the custom module to a CA named UG-IssuingCA-02

Code Overview

CustomEkuPolicy.dll is a custom AD CS policy module implemented as a native ATL COM DLL. It is designed to work as a wrapper around Microsoft’s default AD CS policy module rather than replacing that behavior entirely.

Purpose

The DLL adds a controlled enhancement to certificate issuance:

  • preserve normal Microsoft CA policy behavior
  • preserve compatibility with Venafi/MS CA workflows
  • inject Server Authentication and Client Authentication EKUs only when appropriate

High-level behavior

When the CA processes a certificate request, the module does the following:

  1. Loads and delegates to the Microsoft default policy module:
    • CertificateAuthority_MicrosoftDefault.Policy
  2. Lets the default policy module evaluate the request normally:
    • issuance
    • pending/deny decisions
    • standard AD CS behavior
  3. If the default policy module decides to issue immediately:
    • inspect the request/certificate context
    • determine whether the certificate is eligible for EKU injection
  4. Inject the following EKUs only when all conditions are met:
    • Server Authentication: 1.3.6.1.5.5.7.3.1
    • Client Authentication: 1.3.6.1.5.5.7.3.2

Injection conditions

EKU injection occurs only if:

  • the default Microsoft policy module returned issue now
  • the certificate is not a CA certificate
  • the certificate’s template/type name is allowed
  • the certificate does not already contain an EKU extension

If any of those conditions are not met, the request is left unchanged.

Why the wrapper design is used

Earlier testing showed that completely replacing Microsoft’s default policy logic caused incompatibility with Venafi.
To avoid that, this module wraps the default policy module and preserves its normal behavior first, then applies the EKU enhancement afterward.

This design is what allows:

  • successful issuance through Venafi
  • retention of normal CA behavior
  • selective EKU injection

Template/type filtering

The module supports a registry-driven allow-list of certificate template/type names.

Registry path:

HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\<CAName>\PolicyModules\CustomEkuPolicy.Module

 

Registry value:

AllowedTemplateNames

Type:

REG_MULTI_SZ

If the registry value is missing or empty, the module defaults to allowing only:

WebServer

This prevents the module from broadly injecting TLS EKUs into unrelated certificate types such as code-signing or other special-purpose leaf certificates.

Important implementation details

  • Implemented as ICertPolicy2
  • Built as an in-process COM DLL loaded by certsrv.exe
  • Uses ATL for COM plumbing
  • Uses CryptoAPI to ASN.1-encode the EKU extension
  • Supports binary extension values returned by AD CS as either:
    • VT_BSTR
    • VT_ARRAY | VT_UI1

Failure behavior

If EKU injection fails:

  • the module logs the failure
  • the default Microsoft issuance decision is preserved

This means the module is effectively fail-open with respect to EKU injection, to avoid breaking certificate issuance workflows.

Result

In normal operation, certificates of the allowed type that do not already contain EKUs are issued with:

  • Server Authentication
  • Client Authentication

Other certificate types are left unchanged.

Function Reference Table

Function Location Called from Calls Purpose
DllMain dllmain.cpp Windows loader _AtlModule.DllMain Standard DLL entry point for process/thread attach and detach.
DllCanUnloadNow dllmain.cpp COM runtime _AtlModule.DllCanUnloadNow Standard COM export used to determine whether the DLL can be unloaded.
DllGetClassObject dllmain.cpp COM runtime _AtlModule.DllGetClassObject Standard COM export that returns the class factory for CCustomEkuPolicyModule.
DllRegisterServer dllmain.cpp COM registration tools / COM runtime if invoked _AtlModule.DllRegisterServer Standard COM registration export. Manual registry registration is used operationally instead.
DllUnregisterServer dllmain.cpp COM registration tools / COM runtime if invoked _AtlModule.DllUnregisterServer Standard COM unregistration export.
GetTypeInfoCount CustomEkuPolicyModule.cpp COM/IDispatch clients if they query dispatch metadata none Minimal IDispatch stub implementation. Returns no type information.
GetTypeInfo CustomEkuPolicyModule.cpp COM/IDispatch clients none Minimal IDispatch stub implementation. Not implemented for this module.
GetIDsOfNames CustomEkuPolicyModule.cpp COM/IDispatch clients none Minimal IDispatch stub implementation. Not used by AD CS in this design.
Invoke CustomEkuPolicyModule.cpp COM/IDispatch clients none Minimal IDispatch stub implementation. Not used by AD CS in this design.
Initialize CustomEkuPolicyModule.cpp AD CS when the policy module is initialized EnsureDefaultPolicyLoaded, LoadConfiguration, m_spDefaultPolicy->Initialize Stores the CA config string, loads registry-based configuration, loads the Microsoft default policy module, and delegates initialization to the default module.
VerifyRequest CustomEkuPolicyModule.cpp AD CS for each certificate request EnsureDefaultPolicyLoaded, m_spDefaultPolicy->VerifyRequest, TryInjectDefaultEku, LogHr Main policy processing function. Delegates request handling to the Microsoft default policy module and, if the request is immediately issued, attempts EKU injection.
GetDescription CustomEkuPolicyModule.cpp AD CS / administrative interfaces none Returns a human-readable description of the policy module.
ShutDown CustomEkuPolicyModule.cpp AD CS during service shutdown / module unload m_spDefaultPolicy->ShutDown Delegates shutdown to the default policy module.
GetManageModule CustomEkuPolicyModule.cpp AD CS / administrative interfaces m_spDefaultPolicy2->GetManageModule Pass-through to the default policy module’s ICertPolicy2::GetManageModule() when available.
EnsureDefaultPolicyLoaded CustomEkuPolicyModule.cpp Initialize, VerifyRequest CLSIDFromProgID, CoCreateInstance, QueryInterface Loads the Microsoft default policy module (CertificateAuthority_MicrosoftDefault.Policy) and caches interface pointers.
LoadConfiguration CustomEkuPolicyModule.cpp Initialize LoadAllowedTemplateNamesFromRegistry Loads custom registry-driven configuration for the wrapper module.
LoadAllowedTemplateNamesFromRegistry CustomEkuPolicyModule.cpp LoadConfiguration RegOpenKeyExW, RegQueryValueExW, RegCloseKey, LogInfo Reads AllowedTemplateNames from the CA policy module registry key and populates the internal allow-list. Falls back to WebServer if not configured.
TryInjectDefaultEku CustomEkuPolicyModule.cpp VerifyRequest CoCreateInstance, SetContext, IsCaRequest, GetTemplateName, IsTemplateAllowed, IsExtensionPresent, BuildDefaultEkuEncoded, SetExtensionBytes, LogInfo, LogHr Performs the conditional EKU injection logic after default policy approval.
GetExtensionBytes CustomEkuPolicyModule.cpp IsExtensionPresent, IsCaRequest, GetTemplateName ICertServerPolicy::GetCertificateExtension, ICertServerPolicy::GetCertificateExtensionFlags, VariantClear Reads a certificate/request extension value from ICertServerPolicy as binary.
SetExtensionBytes CustomEkuPolicyModule.cpp TryInjectDefaultEku SysAllocStringByteLen, ICertServerPolicy::SetCertificateExtension, VariantClear Writes a binary certificate/request extension value back through ICertServerPolicy. Used to inject EKU.
IsExtensionPresent CustomEkuPolicyModule.cpp TryInjectDefaultEku GetExtensionBytes, VariantClear Checks whether a specific extension OID already exists in the current request/certificate context.
BuildDefaultEkuEncoded CustomEkuPolicyModule.cpp TryInjectDefaultEku CryptEncodeObjectEx Builds and ASN.1-encodes the default EKU extension containing Server Auth and Client Auth OIDs.
IsCaRequest CustomEkuPolicyModule.cpp TryInjectDefaultEku GetExtensionBytes, VariantBinaryToBytes, CryptDecodeObjectEx, VariantClear, LocalFree Reads and decodes Basic Constraints to determine whether the request is for a CA certificate.
VariantBinaryToBytes CustomEkuPolicyModule.cpp IsCaRequest, GetTemplateName SysStringByteLen, SafeArrayGetLBound, SafeArrayGetUBound, SafeArrayAccessData, SafeArrayUnaccessData Normalizes binary values returned from AD CS (VT_BSTR or `VT_ARRAY
GetTemplateName CustomEkuPolicyModule.cpp TryInjectDefaultEku GetExtensionBytes, VariantBinaryToBytes, CryptDecodeObjectEx, VariantClear, LocalFree Reads and decodes the certificate template/type name extension (1.3.6.1.4.1.311.20.2).
IsTemplateAllowed CustomEkuPolicyModule.cpp TryInjectDefaultEku EqualsIgnoreCase Checks whether the decoded template/type name matches one of the allowed names from configuration.
EqualsIgnoreCase CustomEkuPolicyModule.cpp IsTemplateAllowed towlower Case-insensitive string comparison helper for template/type matching.
LogEventWord CustomEkuPolicyModule.cpp LogInfo, LogHr RegisterEventSourceW, ReportEventW, DeregisterEventSource Low-level Windows Event Log writer for the CustomEkuPolicy source.
LogInfo CustomEkuPolicyModule.cpp Multiple internal functions LogEventWord Convenience wrapper for informational event logging.
LogHr CustomEkuPolicyModule.cpp Multiple internal functions StringCchPrintfW, LogEventWord Convenience wrapper for logging HRESULT failures to the Windows Event Log.

Code Flow

This section describes how the main code paths in CustomEkuPolicy.dll work.

1. DLL load and COM registration

The DLL is an ATL COM in-process server.

Key file:

  • dllmain.cpp

Key responsibilities:

  • exports standard COM entry points:
    • DllMain
    • DllCanUnloadNow
    • DllGetClassObject
    • DllRegisterServer
    • DllUnregisterServer
  • exposes the COM class:
    • CCustomEkuPolicyModule

The class is registered in the ATL object map with:

OBJECT_ENTRY_AUTO(CLSID_CustomEkuPolicyModule, CCustomEkuPolicyModule)

This is what allows AD CS to instantiate the policy module through COM.

2. AD CS loads the policy module

When Certificate Services starts, AD CS reads the configured active policy module from the registry and creates the COM object.

Main class:

  • CCustomEkuPolicyModule

Implemented interface:

  • ICertPolicy2

This class is the entry point for all CA policy decisions handled by the DLL.

3. Initialize()

Function:

  • CCustomEkuPolicyModule::Initialize(BSTR strConfig)

Purpose:

  • store the CA configuration string
  • load configuration from registry
  • load the Microsoft default policy module
  • delegate initialization to the default module

Flow:

  1. Save strConfig
  2. Call EnsureDefaultPolicyLoaded()
  3. Call LoadConfiguration()
  4. Call the default module’s Initialize()

This ensures the wrapper is fully initialized before the CA begins handling requests.

4. EnsureDefaultPolicyLoaded()

Function:

  • EnsureDefaultPolicyLoaded()

Purpose:

  • create an instance of the Microsoft default policy module

How it works:

  1. Resolve the ProgID:

CertificateAuthority_MicrosoftDefault.Policy

  1. Convert it to a CLSID using CLSIDFromProgID
  2. Create the COM object with CoCreateInstance
  3. Store:
    • ICertPolicy
    • optionally ICertPolicy2

Why this matters:

  • This is the core wrapper behavior
  • Instead of replacing Microsoft policy behavior, the module delegates to it first

5. LoadConfiguration()

Function:

  • LoadConfiguration()

Purpose:

  • load custom module behavior from registry

Currently this loads:

  • AllowedTemplateNames

Supporting function:

  • LoadAllowedTemplateNamesFromRegistry()

Flow:

  1. Read the CA name from strConfig
  2. Build registry path:

HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\<CAName>\PolicyModules\CustomEkuPolicy.Module

  1. Read AllowedTemplateNames as REG_MULTI_SZ
  2. Store values in:
    • m_allowedTemplateNames

Fallback behavior:

  • if the value is missing or unusable, default to:
    • WebServer

This controls which certificate types are eligible for EKU injection.

6. VerifyRequest()

Function:

  • CCustomEkuPolicyModule::VerifyRequest(…)

This is the most important function in the module.

Purpose:

  • let Microsoft default policy evaluate the request
  • preserve its result
  • attempt EKU injection only after successful default issuance

Flow:

  1. Call EnsureDefaultPolicyLoaded()
  2. Call the default module’s:

m_spDefaultPolicy->VerifyRequest(…)

  1. If the default module fails:
    • return the failure unchanged
  2. If the default module returns a disposition other than:

VR_INSTANT_OK

then exit without modification

  1. If the request is being issued immediately:
    • call TryInjectDefaultEku(Context)
  2. If EKU injection fails:
    • log the failure
    • preserve the default issue decision
  3. Return success

7. TryInjectDefaultEku()

Function:

  • TryInjectDefaultEku(LONG Context)

Purpose:

  • inspect the certificate request/certificate context
  • determine whether EKU injection should happen
  • add the EKU extension if appropriate

Flow:

  1. Create ICertServerPolicy
  2. Call SetContext(Context)
  3. Determine whether the request is a CA certificate:
    • IsCaRequest()
  4. If CA cert:
    • skip
  5. Read certificate type/template name:
    • GetTemplateName()
  6. Check whether template/type is allowed:
    • IsTemplateAllowed()
  7. If not allowed:
    • skip
  8. Check whether EKU already exists:
    • IsExtensionPresent(“2.5.29.37”)
  9. If EKU already exists:
    • skip
  10. Build the encoded EKU extension:
  • BuildDefaultEkuEncoded()
  1. Write the extension:
  • SetExtensionBytes(“2.5.29.37”, …)

Only if all of those conditions succeed does the module inject the EKU.

8. IsCaRequest()

Function:

  • IsCaRequest(ICertServerPolicy* pServer, bool& isCa)

Purpose:

  • prevent EKU injection on CA certificates

How it works:

  1. Read Basic Constraints extension:
    • OID 2.5.29.19
  2. Decode it with CryptoAPI
  3. Check fCA
  4. Set isCa = true if CA certificate

This protects subordinate CA and CA certificate requests from receiving inappropriate TLS EKUs.

9. GetTemplateName()

Function:

  • GetTemplateName(ICertServerPolicy* pServer, std::wstring& templateName)

Purpose:

  • identify the certificate type/template name

How it works:

  1. Read extension:
    • 1.3.6.1.4.1.311.20.2
  2. Convert returned binary value into bytes
  3. Decode the string value
  4. Return the template/type name

Example expected values:

  • WebServer

This is the main filter used to decide whether EKU injection is allowed.

10. IsTemplateAllowed()

Function:

  • IsTemplateAllowed(const std::wstring& templateName) const

Purpose:

  • compare the certificate type name against the configured allow-list

How it works:

  • case-insensitive comparison against m_allowedTemplateNames

If the template/type is not in the allow-list, the request is left unchanged.

11. IsExtensionPresent()

Function:

  • IsExtensionPresent(ICertServerPolicy* pServer, LPCWSTR wszOid, bool& present)

Purpose:

  • determine whether a specific extension already exists

Used for:

  • checking whether 2.5.29.37 Enhanced Key Usage is already present

If it is already present, the module does not modify it.

This preserves explicitly requested EKUs.

12. BuildDefaultEkuEncoded()

Function:

  • BuildDefaultEkuEncoded(BYTE** ppbEncoded, DWORD* pcbEncoded)

Purpose:

  • ASN.1-encode the default EKU list

EKUs encoded:

  • Server Authentication
    • 1.3.6.1.5.5.7.3.1
  • Client Authentication
    • 1.3.6.1.5.5.7.3.2

How it works:

  1. Build CERT_ENHKEY_USAGE
  2. Encode it using:
    • CryptEncodeObjectEx
  3. Return the encoded blob

This produces the value written into extension 2.5.29.37.

13. SetExtensionBytes()

Function:

  • SetExtensionBytes(ICertServerPolicy* pServer, LPCWSTR wszOid, const BYTE* pbData, DWORD cbData, LONG extFlags)

Purpose:

  • write a binary certificate extension back into the current request/certificate context

How it works:

  1. Convert the encoded bytes into a binary BSTR
  2. Wrap in a VARIANT
  3. Call:
    • ICertServerPolicy::SetCertificateExtension(…)

This is the actual point where EKU injection occurs.

14. VariantBinaryToBytes()

Function:

  • VariantBinaryToBytes(const VARIANT& var, std::vector<BYTE>& bytes)

Purpose:

  • normalize AD CS binary extension values into a byte vector

Why it exists:

  • AD CS may return binary property values as either:
    • VT_BSTR
    • VT_ARRAY | VT_UI1

This helper makes downstream decoding logic reliable and avoids earlier failures caused by assuming only one format.

15. Logging

Functions:

  • LogEventWord()
  • LogInfo()
  • LogHr()

Purpose:

  • write operational/debug events to the Windows Application log

Used for:

  • initialization failures
  • EKU injection failures
  • important decision points

This was added mainly to make runtime behavior observable and troubleshoot CA/AD CS integration.

16. Failure model

The wrapper preserves Microsoft default behavior wherever possible.

Important principle:

  • default policy decision comes first
  • EKU injection is best effort
  • if EKU injection fails, issuance is not blocked unless the default policy blocked it

This makes the module effectively fail-open for EKU injection, while still preserving standard CA behavior.

Summary of end-to-end request flow

In simplified form, the code path is:

  1. AD CS loads CustomEkuPolicy.dll
  2. Initialize() loads the Microsoft default policy module and configuration
  3. On each request, VerifyRequest() calls the Microsoft default policy module
  4. If Microsoft policy chooses immediate issuance:
    • inspect request
    • check CA/not-CA
    • check template/type allow-list
    • check existing EKU
    • inject Server Auth + Client Auth EKU if eligible
  5. Return the Microsoft default issuance result

Build

Install Build Tools for Visual Studio 2022 with the Desktop development with C++ workload, including the MSVC v143 toolset, Windows SDK, and ATL support.

Build the project from the x64 Native Tools Command Prompt for VS 2022 using msbuild CustomEkuPolicy.vcxproj /p:Configuration=Release /p:Platform=x64

The equivalent of make clean is

msbuild CustomEkuPolicy.vcxproj /t:Clean /p:Configuration=Release /p:Platform=x64

Installation

Copy the file into a location on the CA server. I am using a path under c:\program files\EKUPolicy\CustomEkuPolicy

Create a REG file to import the COM registration

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\CLSID\{BEA77360-4ED0-469C-A888-7B5CAC3B8776}]

@=”CustomEkuPolicyModule Class”

“ProgID”=”CustomEkuPolicy.Module”

“VersionIndependentProgID”=”CustomEkuPolicy.Module”

[HKEY_CLASSES_ROOT\CLSID\{BEA77360-4ED0-469C-A888-7B5CAC3B8776}\InprocServer32]

@=”C:\\Program Files\\EKUPolicy\\CustomEkuPolicy\\CustomEkuPolicy.dll”

“ThreadingModel”=”Both”

[HKEY_CLASSES_ROOT\CustomEkuPolicy.Module]

@=”CustomEkuPolicyModule Class”

“CLSID”=”{BEA77360-4ED0-469C-A888-7B5CAC3B8776}”

[HKEY_CLASSES_ROOT\CustomEkuPolicy.Module\CLSID]

@=”{BEA77360-4ED0-469C-A888-7B5CAC3B8776}”

In an elevated command prompt, import the reg file and verify the values are present

Back up the current registry settings

Add key for custom module

reg add “HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\<CAName>\PolicyModules\CustomEkuPolicy.Module” /f

Add WebServer to the registry key for the custom policy module unless you want to rely on the DLL defaults

reg add “HKLM\SYSTEM\CurrentControlSet\Services\CertSvc\Configuration\<CANAME>\PolicyModules\CustomEkuPolicy.Module” /v AllowedTemplateNames /t REG_MULTI_SZ /d “WebServer\0” /f

And activate the custom module:

Restart the certificate server service

 

Querying the RPC Endpoint Mapper

A lot of RPC services start out on a standard port (TCP port 135) and then move over to a dynamically allocated port. Fortunately, there’s a way to ask the RPC endpoint mapper what services are available and what port(s) have been assigned to that service. It uses the portqry command:

C:\PortQryV2>portqry -n host2043.servers.example.com -e 135 -p tcp -v

Note: the -v option only displays extra data in local mode

Querying target system called:

 host2043.servers.example.com

Attempting to resolve name to IP address...


Name resolved to 10.237.73.103

querying...

TCP port 135 (epmap service): LISTENING

Using ephemeral source port
Querying Endpoint Mapper Database...
Server's response:

UUID: 04eeb297-cbf4-466b-8a2a-bfd6a2f10bba EFSK RPC Interface
ncacn_np:host2043.servers.example.com[\\pipe\\efsrpc]

UUID: 367abb81-9844-35f1-ad32-98f038001003
ncacn_ip_tcp:host2043.servers.example.com[50007]

UUID: 91ae6020-9e3c-11cf-8d7c-00aa00c091be
ncacn_np:host2043.servers.example.com[\\pipe\\cert]

UUID: 91ae6020-9e3c-11cf-8d7c-00aa00c091be
ncacn_ip_tcp:host2043.servers.example.com[50006]

UUID: 29770a8f-829b-4158-90a2-78cd488501f7
ncacn_np:host2043.servers.example.com[\\pipe\\SessEnvPublicRpc]

UUID: 29770a8f-829b-4158-90a2-78cd488501f7
ncacn_ip_tcp:host2043.servers.example.com[50004]

UUID: 7f1343fe-50a9-4927-a778-0c5859517bac DfsDs service
ncacn_np:host2043.servers.example.com[\\PIPE\\wkssvc]

UUID: f6beaff7-1e19-4fbb-9f8f-b89e2018337c Windows Event Log
ncacn_np:host2043.servers.example.com[\\pipe\\eventlog]

UUID: f6beaff7-1e19-4fbb-9f8f-b89e2018337c Windows Event Log
ncacn_ip_tcp:host2043.servers.example.com[50002]

UUID: 1ff70682-0a51-30e8-076d-740be8cee98b
ncacn_np:host2043.servers.example.com[\\PIPE\\atsvc]

UUID: 378e52b0-c0a9-11cf-822d-00aa0051e40f
ncacn_np:host2043.servers.example.com[\\PIPE\\atsvc]

UUID: 33d84484-3626-47ee-8c6f-e7e98b113be1
ncacn_np:host2043.servers.example.com[\\PIPE\\atsvc]

UUID: 86d35949-83c9-4044-b424-db363231fd0c
ncacn_np:host2043.servers.example.com[\\PIPE\\atsvc]

UUID: 86d35949-83c9-4044-b424-db363231fd0c
ncacn_ip_tcp:host2043.servers.example.com[50003]

UUID: 3a9ef155-691d-4449-8d05-09ad57031823
ncacn_np:host2043.servers.example.com[\\PIPE\\atsvc]

UUID: 3a9ef155-691d-4449-8d05-09ad57031823
ncacn_ip_tcp:host2043.servers.example.com[50003]

UUID: c9ac6db5-82b7-4e55-ae8a-e464ed7b4277 Impl friendly name
ncacn_hvsocket:host2043.servers.example.com[F58797F6-C9F3-4D63-9BD4-E52AC020E586]

UUID: 76f226c3-ec14-4325-8a99-6a46348418af
ncacn_np:host2043.servers.example.com[\\PIPE\\InitShutdown]

UUID: d95afe70-a6d5-4259-822e-2c84da1ddb0d
ncacn_np:host2043.servers.example.com[\\PIPE\\InitShutdown]

UUID: d95afe70-a6d5-4259-822e-2c84da1ddb0d
ncacn_ip_tcp:host2043.servers.example.com[50001]

UUID: 12345778-1234-abcd-ef00-0123456789ac
ncacn_np:host2043.servers.example.com[\\pipe\\lsass]

UUID: 12345778-1234-abcd-ef00-0123456789ac
ncacn_ip_tcp:host2043.servers.example.com[50000]

UUID: 0b1c2170-5732-4e0e-8cd3-d9b16f3b84d7 RemoteAccessCheck
ncacn_np:host2043.servers.example.com[\\pipe\\lsass]

UUID: 0b1c2170-5732-4e0e-8cd3-d9b16f3b84d7 RemoteAccessCheck
ncacn_ip_tcp:host2043.servers.example.com[50000]

UUID: 0b1c2170-5732-4e0e-8cd3-d9b16f3b84d7 RemoteAccessCheck
ncacn_ip_tcp:host2043.servers.example.com[50005]

UUID: 0b1c2170-5732-4e0e-8cd3-d9b16f3b84d7 RemoteAccessCheck
ncacn_np:host2043.servers.example.com[\\pipe\\lsass]

UUID: 0b1c2170-5732-4e0e-8cd3-d9b16f3b84d7 RemoteAccessCheck
ncacn_ip_tcp:host2043.servers.example.com[50000]

UUID: 0b1c2170-5732-4e0e-8cd3-d9b16f3b84d7 RemoteAccessCheck
ncacn_ip_tcp:host2043.servers.example.com[50005]

UUID: b25a52bf-e5dd-4f4a-aea6-8ca7272a0e86 KeyIso
ncacn_np:host2043.servers.example.com[\\pipe\\lsass]

UUID: b25a52bf-e5dd-4f4a-aea6-8ca7272a0e86 KeyIso
ncacn_ip_tcp:host2043.servers.example.com[50000]

UUID: b25a52bf-e5dd-4f4a-aea6-8ca7272a0e86 KeyIso
ncacn_ip_tcp:host2043.servers.example.com[50005]

UUID: 8fb74744-b2ff-4c00-be0d-9ef9a191fe1b Ngc Pop Key Service
ncacn_np:host2043.servers.example.com[\\pipe\\lsass]

UUID: 8fb74744-b2ff-4c00-be0d-9ef9a191fe1b Ngc Pop Key Service
ncacn_ip_tcp:host2043.servers.example.com[50000]

UUID: 8fb74744-b2ff-4c00-be0d-9ef9a191fe1b Ngc Pop Key Service
ncacn_ip_tcp:host2043.servers.example.com[50005]

UUID: 51a227ae-825b-41f2-b4a9-1ac9557a1018 Ngc Pop Key Service
ncacn_np:host2043.servers.example.com[\\pipe\\lsass]

UUID: 51a227ae-825b-41f2-b4a9-1ac9557a1018 Ngc Pop Key Service
ncacn_ip_tcp:host2043.servers.example.com[50000]

UUID: 51a227ae-825b-41f2-b4a9-1ac9557a1018 Ngc Pop Key Service
ncacn_ip_tcp:host2043.servers.example.com[50005]

UUID: df1941c5-fe89-4e79-bf10-463657acf44d EFS RPC Interface
ncacn_np:host2043.servers.example.com[\\pipe\\efsrpc]

Total endpoints found: 38



==== End of RPC Endpoint Mapper query response ====




Chocolate Chip Cookies with Dark Cherries and Almond Flour

Anya made me birthday cookies! I wanted to save the recipe because they turned out really well.

 
Ingredients:
  • 1 3/4 cups all-purpose flour
  • 1/2 cup almond flour
  • 1 teaspoon baking soda
  • 1/2 teaspoon salt
  • 1 cup unsalted butter, softened
  • 1 cup maple syrup
  • 1/2 cup plain Greek yogurt
  • 2 large eggs
  • 2 cups semi-sweet chocolate chips
  • 1 cup frozen dark cherries, roughly chopped
Instructions:
  1. Preheat your oven to 375°F. Line baking sheets with parchment paper.
  2. In a medium bowl, whisk together the all-purpose flour, almond flour, baking soda, and salt. Set aside.
  3. In a large mixing bowl, beat the softened butter with the maple syrup until well mixed. The mixture will be looser than a typical creamed butter-sugar mixture due to the syrup.
  4. Mix in the Greek yogurt until smooth. Beat in the eggs one at a time, mixing well after each addition.
  5. Gradually add the dry ingredients to the wet ingredients, mixing until just combined. The dough will be a bit softer due to the syrup and yogurt.
  6. Gently fold in the chocolate chips and frozen dark cherries until evenly distributed throughout the dough.
  7. Drop rounded tablespoons of dough onto the prepared baking sheets, leaving about 2 inches between each cookie to allow for spreading.
  8. Bake the cookies in the preheated oven for 10-12 minutes, or until the edges are golden brown and the centers are set but still soft. If you made really big cookies, this may be more like 20 minutes!
  9. Allow the cookies to cool on the baking sheet for about 5 minutes before transferring them to a wire rack to cool completely.

Typing Unicode Characters

Found an interesting way to enter Unicode characters in Windows (beyond finding it in charmap and then copy/pasting the character!). There’s the technique where you hold alt, hit the plus on your numeric keypad, enter the hex code for the character, then release the alt key. Since a lot of laptops don’t have numeric keypads … this approach isn’t always feasible.

But there’s another way — once you’ve typed the hex code and your cursor is immediately after the code, press Alt-x …

The code magics itself into a Unicode character. You can even put your cursor immediately after a Unicode character, press Alt-x, and the character will turn back into the hex code.

Baked French Toast Casserole with Maple Syrup

Ingredients

  • 1 loaf French bread (~16 ounces)
  • 8 large eggs
  • 1.5 cups heavy whipping cream
  • 1.5 cups milk
  • 2 tablespoons maple syrup
  • 1 teaspoon vanilla extract
  • 1/4 teaspoon ground cinnamon
  • 1/4 teaspoon ground nutmeg
  • Dash salt

Directions

Slice bread into 20 slices, 1-inch each. Arrange slices in a generously buttered 9 by 13-inch baking dish in 2 rows, overlapping the slices. In a large bowl, combine the eggs, half-and-half, milk, sugar, vanilla, cinnamon, nutmeg and salt and beat with a rotary beater or whisk until blended but not too bubbly. Pour mixture over the bread slices, making sure all are covered evenly with the milk-egg mixture. Spoon some of the mixture in between the slices. Cover with foil and refrigerate overnight.

The next day, preheat oven to 350 degrees F.

Bake for 40 minutes, until puffed and lightly golden. Serve with maple syrup, fresh fruit, and fresh whipped cream.