PKI Troubleshooting
Error 0x80094800: Template Not Supported
Symptom
Certificate not issued (Denied) Denied by Policy Module 0x80094800
The requested certificate template is not supported by the Active Directory Certificate Services policy: Linux-Workstation-Auth.
The requested certificate template is not supported by this CA. 0x80094800 (-2146875392 CERTSRV_E_UNSUPPORTED_CERT_TYPE)
This error occurs when submitting a CSR with certreq:
certreq -submit -config "{ad-server}\HOME-ROOT-CA" \
-attrib "CertificateTemplate:Linux-Workstation-Auth" \
"C:\Certs\hostname-eaptls.csr" "C:\Certs\hostname-eaptls.cer"
Fix 1: Add Enroll Permission for Authenticated Users
Diagnosis
Check if Authenticated Users has Enroll permission:
ssh home-dc01 'dsacls "CN=Linux-Workstation-Auth,CN=Certificate Templates,CN=Public Key Services,CN=Services,CN=Configuration,DC=inside,DC=domusdigitalis,DC=dev" | findstr /i "enroll"'
If output shows only READ permissions and no "Enroll" extended right, this fix is needed.
Solution
Add Certificate-Enrollment extended right for Authenticated Users:
# Create PowerShell script
cat > /tmp/fix-template-permissions.ps1 << 'EOF'
Import-Module ActiveDirectory
$ConfigNC = (Get-ADRootDSE).configurationNamingContext
$TemplateDN = "CN=Linux-Workstation-Auth,CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC"
Write-Host "Getting ACL for template..."
$ACL = Get-Acl -Path "AD:$TemplateDN"
Write-Host "Creating identity for Authenticated Users..."
$Identity = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-11")
Write-Host "Creating Enroll GUID..."
$EnrollGUID = New-Object Guid "0e10c968-78fb-11d2-90d4-00c04f79dc55"
Write-Host "Creating access rule..."
$AccessRule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
$Identity, `
([System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight), `
([System.Security.AccessControl.AccessControlType]::Allow), `
$EnrollGUID
Write-Host "Adding access rule..."
$ACL.AddAccessRule($AccessRule)
Write-Host "Applying ACL..."
Set-Acl -Path "AD:$TemplateDN" -AclObject $ACL
Write-Host "SUCCESS: Certificate-Enrollment permission granted to Authenticated Users"
EOF
# Transfer and execute
scp /tmp/fix-template-permissions.ps1 home-dc01:C:/Temp/
ssh home-dc01 "powershell.exe -ExecutionPolicy Bypass -File C:\Temp\fix-template-permissions.ps1"
Fix 2: Add ENROLLEE_SUPPLIES_SUBJECT Flag
Diagnosis
Check template flags:
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Linux-Workstation-Auth'''} -Properties flags | Select-Object Name,flags"'
Compare with working WebServer template:
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Web Server'''} -Properties flags | Select-Object Name,flags"'
If Linux-Workstation-Auth flags = 131680 and WebServer flags = 66113, the ENROLLEE_SUPPLIES_SUBJECT flag is missing.
Solution
Add ENROLLEE_SUPPLIES_SUBJECT flag (bit 0):
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; $template = Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Linux-Workstation-Auth'''}; Set-ADObject -Identity \$template -Replace @{flags = 131681}"'
This sets flags from 131680 to 131681 (adding bit 0).
Verification
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Linux-Workstation-Auth'''} -Properties flags | Select-Object Name,flags"'
Expected: flags : 131681
Fix 3: Downgrade Schema Version
Diagnosis
Check template schema version:
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Linux-Workstation-Auth'''} -Properties msPKI-Template-Schema-Version | Select-Object Name,msPKI-Template-Schema-Version"'
If schema version = 2, but CA only supports version 1 templates, this fix is needed.
Compare with WebServer:
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Web Server'''} -Properties msPKI-Template-Schema-Version | Select-Object Name,msPKI-Template-Schema-Version"'
WebServer should show version 1.
Solution
Downgrade schema version from 2 to 1:
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; $template = Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Linux-Workstation-Auth'''}; Set-ADObject -Identity \$template -Replace @{'''msPKI-Template-Schema-Version''' = 1}"'
Verification
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Linux-Workstation-Auth'''} -Properties msPKI-Template-Schema-Version | Select-Object Name,msPKI-Template-Schema-Version"'
Expected: msPKI-Template-Schema-Version : 1
Fix 4: Correct Validity Period Encoding
Symptom
After fixing the above three issues, error changes to:
Certificate not issued (Denied) Denied by Policy Module The specified time is invalid. 0x8007076d (WIN32: 1901 ERROR_INVALID_TIME)
This indicates the validity period encoding is incorrect.
Diagnosis
Check validity periods:
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Linux-Workstation-Auth'''} -Properties pKIExpirationPeriod | Select-Object Name,pKIExpirationPeriod"'
Compare with working WebServer template:
ssh home-dc01 'powershell.exe -Command "$ConfigNC = (Get-ADRootDSE).configurationNamingContext; Get-ADObject -SearchBase \"CN=Certificate Templates,CN=Public Key Services,CN=Services,\$ConfigNC\" -Filter {displayName -eq '''Web Server'''} -Properties pKIExpirationPeriod | Select-Object Name,pKIExpirationPeriod"'
If byte arrays differ, the encoding is incorrect.
Solution
Copy the working validity period from WebServer template:
# Create PowerShell script
cat > /tmp/fix-validity-period.ps1 << 'EOF'
$ConfigNC = (Get-ADRootDSE).configurationNamingContext
$webserver = Get-ADObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC" -Filter {displayName -eq 'Web Server'} -Properties pKIExpirationPeriod
$template = Get-ADObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC" -Filter {displayName -eq 'Linux-Workstation-Auth'}
Set-ADObject -Identity $template -Replace @{'pKIExpirationPeriod' = $webserver.pKIExpirationPeriod}
Write-Host "Validity period updated to match WebServer template"
Restart-Service certsvc
Write-Host "CA service restarted"
EOF
# Transfer and execute
scp /tmp/fix-validity-period.ps1 home-dc01:C:/Temp/
ssh home-dc01 "powershell.exe -ExecutionPolicy Bypass -File C:\Temp\fix-validity-period.ps1"
| The CA service (certsvc) must be restarted for validity period changes to take effect. |
Apply All Fixes
Once all four fixes are applied, restart the CA service and test:
Restart CA Service
ssh home-dc01 "net stop certsvc && net start certsvc"
Or via PowerShell:
ssh home-dc01 "powershell.exe -Command 'Restart-Service certsvc'"
Test Certificate Enrollment
HOSTNAME=$(cat /etc/hostname)
ssh home-dc01 <<EOF
del C:\\Certs\\${HOSTNAME}-eaptls.rsp
certreq -submit -config "{ad-server}\\HOME-ROOT-CA" -attrib "CertificateTemplate:Linux-Workstation-Auth" "C:\\Certs\\${HOSTNAME}-eaptls.csr" "C:\\Certs\\${HOSTNAME}-eaptls.cer"
EOF
Expected output:
RequestId: 77
RequestId: "77"
Certificate retrieved(Issued) Issued
Complete Fix Script
For convenience, here’s a complete script that applies all fixes:
#!/bin/bash
# fix-linux-workstation-auth-template.sh
# Fixes all four issues with Linux-Workstation-Auth template
set -euo pipefail
echo "=== Fixing Linux-Workstation-Auth Template ==="
# Fix 1: Add Enroll Permission
cat > /tmp/fix-all-template-issues.ps1 << 'EOF'
Import-Module ActiveDirectory
$ConfigNC = (Get-ADRootDSE).configurationNamingContext
$TemplateDN = "CN=Linux-Workstation-Auth,CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC"
# Fix 1: Add Enroll Permission
Write-Host "Fix 1: Adding Enroll permission..."
$ACL = Get-Acl -Path "AD:$TemplateDN"
$Identity = New-Object System.Security.Principal.SecurityIdentifier("S-1-5-11")
$EnrollGUID = New-Object Guid "0e10c968-78fb-11d2-90d4-00c04f79dc55"
$AccessRule = New-Object System.DirectoryServices.ActiveDirectoryAccessRule `
$Identity, `
([System.DirectoryServices.ActiveDirectoryRights]::ExtendedRight), `
([System.Security.AccessControl.AccessControlType]::Allow), `
$EnrollGUID
$ACL.AddAccessRule($AccessRule)
Set-Acl -Path "AD:$TemplateDN" -AclObject $ACL
Write-Host " ✓ Enroll permission added"
# Fix 2: Add ENROLLEE_SUPPLIES_SUBJECT flag
Write-Host "Fix 2: Adding ENROLLEE_SUPPLIES_SUBJECT flag..."
$template = Get-ADObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC" -Filter {displayName -eq 'Linux-Workstation-Auth'}
Set-ADObject -Identity $template -Replace @{flags = 131681}
Write-Host " ✓ Flag added"
# Fix 3: Downgrade schema version
Write-Host "Fix 3: Setting schema version to 1..."
Set-ADObject -Identity $template -Replace @{'msPKI-Template-Schema-Version' = 1}
Write-Host " ✓ Schema version set to 1"
# Fix 4: Copy validity period from WebServer
Write-Host "Fix 4: Fixing validity period..."
$webserver = Get-ADObject -SearchBase "CN=Certificate Templates,CN=Public Key Services,CN=Services,$ConfigNC" -Filter {displayName -eq 'Web Server'} -Properties pKIExpirationPeriod
Set-ADObject -Identity $template -Replace @{'pKIExpirationPeriod' = $webserver.pKIExpirationPeriod}
Write-Host " ✓ Validity period corrected"
# Restart CA service
Write-Host "Restarting Certificate Authority service..."
Restart-Service certsvc
Write-Host " ✓ CA service restarted"
Write-Host ""
Write-Host "SUCCESS: All fixes applied to Linux-Workstation-Auth template"
EOF
# Transfer and execute
echo "Transferring script to home-dc01..."
scp /tmp/fix-all-template-issues.ps1 home-dc01:C:/Temp/
echo "Executing fixes on home-dc01..."
ssh home-dc01 "powershell.exe -ExecutionPolicy Bypass -File C:\Temp\fix-all-template-issues.ps1"
echo ""
echo "=== Template Fixed - Ready for Certificate Enrollment ==="
Save as fix-linux-workstation-auth-template.sh, make executable, and run:
chmod +x fix-linux-workstation-auth-template.sh
./fix-linux-workstation-auth-template.sh
Prevention
When creating new certificate templates for Linux workstation authentication:
-
Always set Authenticated Users permissions:
-
Read
-
Enroll
-
-
Use Schema Version 1 (Windows 2000 compatibility)
-
Set flags to include ENROLLEE_SUPPLIES_SUBJECT
-
Use working templates as base:
-
Duplicate "Web Server" template instead of "Workstation Authentication"
-
Web Server template has correct encoding and compatibility
-
-
Test immediately after creation:
-
Submit test CSR
-
Verify no 0x80094800 errors
-
Error: Certificate/Key Mismatch - EAP-TLS Fails
Symptom
802.1X authentication fails immediately during TLS handshake:
Jan 27 20:55:24 modestus-razer wpa_supplicant[3337]: OpenSSL: tls_read_pkcs12 - Failed to use PKCS#12 file error:05800074:x509 certificate routines::key values mismatch
Jan 27 20:55:24 modestus-razer wpa_supplicant[3337]: TLS: Failed to load private key '{key-dir}/hostname-eaptls.key'
Jan 27 20:55:24 modestus-razer wpa_supplicant[3337]: EAP-TLS: Failed to initialize SSL.
Jan 27 20:55:24 modestus-razer wpa_supplicant[3337]: enp130s0: CTRL-REQ-PASSPHRASE-0:Private key passphrase needed for SSID
NetworkManager shows:
Error: Connection activation failed: Secrets were required, but not provided
The supplicant state reaches "associated" but never completes:
Jan 27 20:55:22 modestus-razer NetworkManager[3287]: <info> [1769576122.1423] device (enp130s0): supplicant interface state: disconnected -> associated
Jan 27 20:55:47 modestus-razer NetworkManager[3287]: <warn> [1769576147.0386] device (enp130s0): Activation: (ethernet) association took too long.
Root Cause
The certificate and private key do not match.
This happens when: - You generated multiple CSRs and got them confused - You installed the wrong key file from /tmp - You regenerated the CSR without replacing the certificate
Diagnosis
Verify certificate and key match by comparing their modulus hashes:
# Check certificate modulus
openssl x509 -noout -modulus -in {cert-dir}/hostname-eaptls.pem | openssl md5
# Check private key modulus (needs sudo)
sudo openssl rsa -noout -modulus -in {key-dir}/hostname-eaptls.key | openssl md5
Hashes MUST match exactly. Example:
# Certificate
MD5(stdin)= b82b8dd7c0f1c3aafc4e31c046b64edf
# Private key
MD5(stdin)= b82b8dd7c0f1c3aafc4e31c046b64edf ✓ Match!
If hashes differ, the cert and key don’t belong together:
# Certificate
MD5(stdin)= b82b8dd7c0f1c3aafc4e31c046b64edf
# Private key
MD5(stdin)= b66262b6f8bc42a15141fb3386b6e6ee ✗ MISMATCH!
Solution
Find the correct matching key file and install it:
# Check all potential key files in /tmp
for keyfile in /tmp/*.key; do
echo "=== Checking $keyfile ==="
openssl rsa -noout -modulus -in "$keyfile" 2>/dev/null | openssl md5
done
# Compare to certificate hash
openssl x509 -noout -modulus -in {cert-dir}/hostname-eaptls.pem | openssl md5
# Install the matching key
sudo cp /tmp/hostname-eaptls.key {key-dir}/hostname-eaptls.key
sudo chmod 600 {key-dir}/hostname-eaptls.key
# Verify they match now
openssl x509 -noout -modulus -in {cert-dir}/hostname-eaptls.pem | openssl md5
sudo openssl rsa -noout -modulus -in {key-dir}/hostname-eaptls.key | openssl md5
Test Fix
Reconnect and verify:
# Reconnect
sudo nmcli connection up "Wired-802.1X"
# Check success
nmcli device show enp130s0 | grep -E "STATE|IP4.ADDRESS"
# Should show:
# GENERAL.STATE: 100 (connected)
# IP4.ADDRESS[1]: 10.50.40.xxx/24
Prevention
To avoid this issue:
-
Keep key and CSR together - Generate both in the same directory with matching names:
bash openssl req -new -newkey rsa:2048 -nodes \ -keyout /tmp/$(hostname)-eaptls.key \ -out /tmp/$(hostname)-eaptls.csr \ -subj "/O=Domus Digitalis/OU=Endpoints/CN=$(hostname).inside.domusdigitalis.dev" -
Don’t regenerate CSR - If you need a new certificate, regenerate BOTH the key and CSR together
-
Install immediately - After getting the signed certificate, install both files right away:
bash sudo cp /tmp/$(hostname)-eaptls.pem /etc/ssl/certs/ sudo cp /tmp/$(hostname)-eaptls.key /etc/ssl/private/ sudo chmod 644 /etc/ssl/certs/$(hostname)-eaptls.pem sudo chmod 600 /etc/ssl/private/$(hostname)-eaptls.key -
Verify match before using - Always verify hash match before configuring 802.1X