Script based Autoenrollment for Windows clients with EJBCA

Script based Autoenrollment is a legacy way of doing autoenrollment and is kept for legacy reasons. Native autoenrollment (above) provides a more seamless experience.

This section will show you how to set up automatic certificate enroll of machines and users in an Windows environment with EJBCA.

Introduction

  • Use mod_auth_kerb on a Apache2 web server proxy to validate the requesters identity using Kerberos.
  • A login VBS-Script creates a certificate request that is sent to the proxy using IE-components.
  • A Servlet protected by the proxy receives the requests and creates a new cert.
  • The new certificate will use information from the request (UPN and CertificateTemplate) and read.
  • information from active directory (CN,DC etc).
  • Autoenrollment should be configurable in the Admin GUI.

Current Status and Known Issues

Current Status

  • Machine enroll on Domain Controller: WORKING
  • DomainController enroll on Domain Controller: WORKING
  • User enroll (Administrator) on Domain Controller: NOT WORKING (Does not trusts ca-server as Intranet, despite GP)
  • Machine enroll on other WS2K3 client: WORKING (not checked in a while)
  • User enroll (Administrator) on other WS2K3 client: NOT WORKING (Does not trusts ca-server as Intranet, despite GP, also complains about untrusted VBS if ran manually)
  • Machine enroll on WinXP client: WORKING
  • User enroll (Administrator) on WinXP client: WORKING

Known Issues

  • SECURITY: The Servlet should verify that e.g. only Users can request User certificates, DCs only DC certs etc.. and other permissions if possible.
  • The enroll scripts always fetches new certificates. They should use the command=status first to see if a new cert is needed.
  • AdminWeb cannot verify admin certificates if non-"/ejbca/" path is used in URL.
  • Autoenroll Servlet doesn't get X-Remote-User if "/ejbca/" path is used in URL.
  • Order of Subject DNs is wrong compared with MS certs..
  • SSL connection to AD has not been tested.
  • Certificates don't have the CertificateTemplate attrib yet.. looks nicer in Certificate MMC snapin..
  • JavaScript "onchange" behaves strangely in IE6. Only activated when the table is clicked, not the checkbox..
  • Creation of EEPs is inefficient due to attempted removal of EEP before each new request.. (Debug-code)

Machines and Software

Domain Controller: dc1.company.local

  • Windows Server 2003 EE patched to SP2
  • Active Directory
  • DNS Server

CA Server: ca-server.company.local

  • Ubuntu 64 Server 7.10
  • Apache2 with modules
  • Kerberos 5
  • Java 1.6u4
  • JBoss 4.2.2.GA
  • EJBCA 3.6 Alpha
  • Apache Ant 1.7.0

Desktop client: client-01.company.local

  • Windows XP Pro SP1 patched to SP2

Install EJBCA

Configure EJBCA not to respond to external web-requests by editing $EJBCA_HOME/conf/web.properties

...
 httpsserver.bindaddress.pubhttp=127.0.0.1
 httpsserver.bindaddress.pubhttps=127.0.0.1
 httpsserver.bindaddress.privhttps=127.0.0.1
 ...

After installation, go to EJBCA Admin GUI -> System Configuration and configure the autoenrollment settings.

Setting up Kerberos Authentication and Apache

This could probably be done on a Windows server as well, since Apache and Kerberos is supposed to work on that platform too:

$sudo su
#apt-get update
#apt-get install krb5-user apache2 libapache2-mod-auth-kerb
 ** Skip kerberos config.. we will configure this later **
#cd /etc/apache2/mods-enabled/
#ln -s ../mods-available/proxy.load proxy.load
#ln -s ../mods-available/proxy_ajp.load proxy_ajp.load
#ln -s ../mods-available/proxy_balancer.load proxy_balancer.load
#ln -s ../mods-available/rewrite.load rewrite.load
#ln -s ../mods-available/ssl.load ssl.load
#ln -s ../mods-available/headers.load headers.load

Edit /etc/krb5.conf where dc1.company.local is the DNS-name of the Domain Controller and COMPANY.LOCAL is our domain.

[libdefaults]
default_realm = COMPANY.LOCAL

[realms]
COMPANY.LOCAL = {
    kdc = dc1.company.local:88
    admin_server = dc1.company.local:88
}

[domain_realm]
    .company.local = COMPANY.LOCAL
    company.local = COMPANY.LOCAL

[logging]
default = FILE:/var/log/apache2/krb5.log

Edit /etc/network/interfaces and set a static IP address:

...
#iface eth0 inet dhcp
iface eth0 inet static
    address 192.168.0.102	# Address of this machine
    netmask 255.255.255.0
    gateway 192.168.0.101	# In our local network this is the Domain Controller

Use the DC as DNS server in /etc/resolv.conf:

search localdomain
nameserver 192.168.0.101

and restart networking (sudo /etc/init.d/networking restart).

Add "ntdpdate dc1.company.local" to /etc/rc.local or a cron job to make sure the ca-server is syncronized with the Domain Controller.

Create the SSL certificates for the Apache proxy using the same CA as our EJBCA installation and the same subject DN.

$cd $EJBCA_HOME
$bin/ejbca.sh ra addendentity apache-ssl foo123 "CN=ca-server.company.local,O=EJBCA Sample,C=SE" "" ManagementCA "" 1 PEM SERVER
$bin/ejbca.sh ra setclearpwd apache-ssl foo123
$bin/ejbca.sh batch
$ls p12/pem/ca-server.company.local*
p12/pem/ca-server.company.local-CA.pem  p12/pem/ca-server.company.local-Key.pem  p12/pem/ca-server.company.local.pem

Edit /etc/apache2/sites-enabled/000-default to display an apache proxy front for EJBCA:

NameVirtualHost *:80
<VirtualHost *:80>
        DocumentRoot /var/www/

        # Proxy requests to EJBCA instances (only one on local machine configured)
        <Proxy balancer://mycluster-kerb>
                BalancerMember ajp://localhost:8009/ejbca/
        </Proxy>
        ProxyPass / balancer://mycluster-kerb/

        RewriteEngine   On
        # Redirect all but the CRL Distribution Point, OCSP and Helthcheck to HTTPS
        RewriteCond     %{THE_REQUEST} !(/publicweb/webdist/certdist.*cmd=crl|/publicweb/status/)
        RewriteRule     ^(.*)$ https://%{SERVER_NAME}$1 [L,R]
        # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web.
        RewriteCond     %{THE_REQUEST}  /ejbca/
        RewriteRule     ^/ejbca/(.*)$ /$1 [PT]

        # Configure log
        LogLevel warn
        ErrorLog /var/log/apache2/error.log
        CustomLog /var/log/apache2/access.log combined
</VirtualHost>

NameVirtualHost *:443
<VirtualHost *:443>
        DocumentRoot /var/www/

        RewriteEngine   On
        # Treat reqeusts to / and /ejbca/ as the same. Required by EJBCA's Admin Web.
        RewriteCond     %{THE_REQUEST}  /ejbca/
        RewriteRule     ^/ejbca/(.*)$ /$1 [PT]

        # Configure secure SSL for this server using SSL certificate generated by EJBCA
        SSLEngine on
        SSLCipherSuite HIGH
        SSLProtocol all -SSLv2
        SSLCertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local.pem
        SSLCertificateKeyFile /home/jboss/ejbca/p12/pem/ca-server.company.local-Key.pem

        # Require Client SSL certificate for the Admin GUI
        <Location /adminweb>
                SSLVerifyClient require
                SSLVerifyDepth 1
                SSLCACertificateFile /home/jboss/ejbca/p12/pem/ca-server.company.local-CA.pem
        </Location>

        # Require Kerberos authentication for the Autoenroll Servlet
        <Location /autoenroll>
                AuthType Kerberos
                Krb5Keytab /etc/apache2/http.keytab
                KrbAuthRealms COMPANY.LOCAL
                KrbServiceName HTTP
                KrbMethodNegotiate on
                KrbMethodK5Passwd off
                Require valid-user
        </Location>

        # Forward the UPN as variable X-Remote-User
        RewriteCond %{IS_SUBREQ} ^false$
        RewriteCond %{LA-U:REMOTE_USER} (.+)
        RewriteRule .* - [E=RU:%1]
        RequestHeader set X-Remote-User %{RU}e

        # Proxy requests to EJBCA instances (only one on local machine configured)
        <Proxy balancer://mycluster-kerb>
                BalancerMember ajp://localhost:8009/ejbca/
        </Proxy>
        ProxyPass / balancer://mycluster-kerb/

        # Configure log
        LogLevel warn
        ErrorLog /var/log/apache2/error.log
        CustomLog /var/log/apache2/access.log combined
</VirtualHost>

Restart apache with "sudo /etc/init.d/apache2 restart"

Install Windows support tools on the Domain Controller (found in %WIN2k3CD%\SUPPORT\TOOLS\SUPTOOLS.msi) to get ktpass.exe. Create a new user "ca-server@company.local" and a strong password e.g not FooBar123 used here. Create a keytab-file "http.keytab" on the Domain Controller:

ktpass.exe -princ HTTP/ca-server.company.local@COMPANY.LOCAL -mapuser ca-server -crypto DES-CBC-MD5 -ptype KRB5_NT_PRINCIPAL -mapop set +desonly -pass FooBar123 -out http.keytab
 ...
 keysize 55 HTTP/ca-server.company.local@COMPANY.LOCAL ptype 1 (KRB5_NT_PRINCIPAL) vno 3 etype
 0x3 (DES-CBC-MD5) keylength 8 (0x64614c9d256bcd6d)
 ...

And move the file to ca-server.company.local:/etc/apache2/http.keytab change permissions to be readable only by the apache-process:

$chown root:root /etc/apace2/http.keytab

Verify that the keytab is correct:

$kinit Administrator
$kvno HTTP/ca-server.company.local
$klist -e
** Output here should match the one from ktpass.exe **

Verify that the keytab can be used:

$kdestroy
$sudo kinit -k -t /etc/apache2/http.keytab HTTP/ca-server.company.local
$sudo klist
(You should have received a ticket here if everything is working.)
$sudo kdestroy

Add ca-server.company.local (192.168.1.2) to your Domain Controllers DNS server as a "Host (A)" record.

Set up Enrollment Scripts to Run Automatically

Create a Shared directory on the Domain Controller, C:\Shared with read and exec rights by Everyone:

copy %SYSTEMROOT%\system32\certreq.exe C:\Shared\Autoenroll\
copy %SYSTEMROOT%\system32\certcli.dll C:\Shared\Autoenroll\
copy %SYSTEMROOT%\system32\certadm.dll C:\Shared\Autoenroll\
(copy %SYSTEMROOT%\system32\certutil.exe C:\Shared\Autoenroll\ This is used by EnrollDomainController and is already available at all DCs.)

Edit or create C:\Shared\Autoenroll\autoenroll.conf

# This is a primitive config file that does not allow spaces

# The request URL is built from the following properties
# https://[requestpath]?request=...
# 

# Standard SSL-port and using URL rewrite from /ejbca/* to /*
requestpath=ca-server.company.local/autoenroll

# Non-standard SSL-port and not using URL rewrite
#requestpath=ca-server.company.local:4443/ejbca/autoenroll

# Debug setting, use only for manual testing
#debug=true
debug=false

Edit or create C:\Shared\Autoenroll\RequestAndInstall.vbs:

Set oArgs = WScript.Arguments 
	if oArgs.Count < 1 then 
		WScript.Echo "Usage: thisscript.vbs fullpathnameofrequest.inf"
		WScript.Quit 1
	else 
		sRequestInfo = Trim(oArgs(0))
	end if 
	
	Set WS = CreateObject("WScript.Shell")
	
	sRequest = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.req"
	sResult = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.p7b"
	
	Set oFilesystem = CreateObject("Scripting.FileSystemObject")
	On Error Resume Next	' Ignore if we try to delete a file that does not exist
	oFilesystem.DeleteFile(sRequest)
	Err.Clear
	On Error GoTo 0
	sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\"
	
	Set iFile = oFilesystem.OpenTextFile(sSharedDir & "autoenroll.conf") 
	Do While iFile.AtEndOfStream <> True 
	    sLine = iFile.Readline
	    If InStr(Left(sLine,1), "#") = 0 then
	        If InStr(sLine, "requestpath=") <> 0 then
		    	sRequestPath = Trim(Right(sLine, Len(sLine)-Len("requestpath=")))
	        end if 
	        If InStr(sLine, "debug=") <> 0 then
		    	sDebug = Trim(Right(sLine, Len(sLine)-Len("debug=")))
	        end if 
	    End if
	Loop 
	iFile.Close
	
	WS.Run sSharedDir & "certreq.exe -f -new " & sRequestInfo & " " & sRequest, 0, True
	
	sRequestData = ""
	Set objFile = oFilesystem.OpenTextFile(sRequest, 1)
	Do Until objFile.AtEndOfStream
		sRequestData = sRequestData & objFile.ReadLine
	Loop
	objFile.Close
	
	set oIE = CreateObject("InternetExplorer.Application")
	
	oIE.navigate2("https://" & sRequestPath & "?debug=" & sDebug & "&request=" & sRequestData)
	
	If sDebug = "true" Then
		oIE.visible = true
	End If
	
	'Wait max 30 seconds
	wscript.sleep 1000
	counter = 0
	While oIE.Busy = true And counter < 30
		counter = counter + 1
		wscript.sleep 1000
	Wend
	
	sResultData = oIE.Document.Body.innerHTML
	sResultData = Mid(sResultData, 6, Len(sResultData)-11)
	
	Set oFile = oFilesystem.CreateTextFile(sResult, True)
	oFile.WriteLine sResultData
	oFile.Close
	
	on error resume next ' in case the Task Manager is used to close IE.
	If sDebug <> "true" Then
		oIE.quit ' Close the window
		WS.Run sSharedDir & "certreq.exe -accept " & Chr(34) & sResult & Chr(34), 0, True
	End If

Edit or create C:\Shared\Autoenroll\EnrollDomainController.vbs:

This Script is based on the script found at http://www.microsoft.com/technet/prodtechnol/windowsserver2003/technologies/security/advcert.mspx#EURAE
	
	iRole = GetLastDomainRole()
	If iRole <> 4 And iRole <> 5 Then
		WScript.Echo "This script should only run on a Domain Controller."
		WScript.Quit 1
	End If
	
	Set WS = CreateObject("WScript.Shell")
	
	Set objDC = GetObject("LDAP://" & CreateObject("ADSystemInfo").ComputerName) 
	sGUID = objDC.GUID 
	sDNShostname = objDC.DNShostname 
	
	Set oFilesystem = CreateObject("Scripting.FileSystemObject") 
	sTempfilePrefix = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled"
	sRequestInfo = sTempFilePrefix & ".inf"
	sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\"
	
	'Create b64 encoded extension
	Dim aASNsubstring(2, 5) 
	Const HEX_DATA_LENGTH = 1 
	Const ASCIIDATA = 2 
	Const HEXDATA = 3 
	Const HEX_BLOB_LENGTH = 4 
	Const HEX_TYPE = 5
	' Encode DNS
	aASNsubstring(0, ASCIIDATA) = sDNShostname 
	aASNsubstring(0, HEX_TYPE) = "82" 
	For i = 1 to Len(aASNsubstring(0, ASCIIDATA)) 
	    aASNsubstring(0, HEXDATA) = aASNsubstring(0, HEXDATA) & Hex(Asc(Mid(aASNsubstring(0, ASCIIDATA), i, 1))) 
	Next 
	aASNsubstring(0, HEX_DATA_LENGTH) = ComputeASN1 (Len(aASNsubstring(0, HEXDATA)) / 2) 
	sASN = aASNsubstring(0, HEX_TYPE) & aASNsubstring(0, HEX_DATA_LENGTH) & aASNsubstring(0, HEXDATA) 
	' Encode GUID
	aASNsubstring(1, HEXDATA) = sGUID 
	aASNsubstring(1, HEX_TYPE) = "A0" 
	aASNsubstring(1, HEX_DATA_LENGTH) = ComputeASN1 (Len(aASNsubstring(1, HEXDATA)) / 2) 
	sASN = sASN & "A01F06092B0601040182371901" & aASNsubstring(1, HEX_TYPE) & "120410" & aASNsubstring(1, HEXDATA) 
	
	Set oFile = oFilesystem.CreateTextFile(sTempfilePrefix & ".asn") 
	oFile.WriteLine "30" & ComputeASN1 (Len(sASN) / 2) & sASN 
	oFile.Close 
	WS.Run "certutil -f -decodehex " & sTempfilePrefix & ".asn " & sTempfilePrefix & ".bin", 0, True 
	WS.Run "certutil -f -encode " & sTempfilePrefix & ".bin " & sTempfilePrefix & ".b64", 0, True 
	
	Set iFile = oFilesystem.OpenTextFile(sTempfilePrefix & ".b64") 
	Set oFile = oFilesystem.CreateTextFile(sRequestInfo, True)
	oFile.WriteLine "[Version]" 
	oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34) 
	oFile.WriteLine "" 
	oFile.WriteLine "[NewRequest]"
	oFile.WriteLine "Subject = " & Chr(34) & "CN=IgnoredValue" & Chr(34)
	oFile.WriteLine "KeySpec = 1" 
	oFile.WriteLine "KeyLength = 2048" 
	oFile.WriteLine "Exportable = TRUE" 
	oFile.WriteLine "MachineKeySet = TRUE" 
	oFile.WriteLine "SMIME = FALSE" 
	oFile.WriteLine "PrivateKeyArchive = FALSE" 
	oFile.WriteLine "UserProtected = FALSE" 
	oFile.WriteLine "UseExistingKeySet = FALSE"
	oFile.WriteLine "ProviderName = " & Chr(34) & "Microsoft RSA SChannel Cryptographic Provider" & Chr(34) 
	oFile.WriteLine "ProviderType = 12" 
	oFile.WriteLine "RequestType = PKCS10" 
	oFile.WriteLine "KeyUsage = 0xa0"
	oFile.WriteLine "" 
	oFile.WriteLine "[EnhancedKeyUsageExtension]" 
	oFile.WriteLine "OID=1.3.6.1.5.5.7.3.1" 
	oFile.WriteLine "OID=1.3.6.1.5.5.7.3.2" 
	oFile.WriteLine "" 
	oFile.WriteLine "[Extensions]" 
	iLine = 0 
	Do While iFile.AtEndOfStream <> True 
	    sLine = iFile.Readline 
	    If sLine = "-----END CERTIFICATE-----" then 
	        Exit Do 
	    end if 
	    if sLine <> "-----BEGIN CERTIFICATE-----" then 
	        if iLine = 0 then 
	            oFile.WriteLine "2.5.29.17=" & sLine 
	        else 
	            oFile.WriteLine "_continue_=" & sLine 
	        end if 
	        iLine = iLine + 1 
	    end if 
	Loop 
	oFile.WriteLine "Critical=2.5.29.17" 
	oFile.WriteLine "" 
	oFile.WriteLine "[RequestAttributes]" 
	oFile.WriteLine "CertificateTemplate = DomainController"
	oFile.Close
	iFile.Close
	
	WS.Run sSharedDir & "RequestAndInstall.vbs " & sRequestInfo, 0, True
	
	' Sub
	Function ComputeASN1 (iStrLen) 
	    If Len(Hex(iStrLen)) Mod 2 = 0 then 
	        sLength = Hex(iStrLen) 
	    else 
	        sLength = "0" & Hex(iStrLen) 
	    end if 
	    if iStrLen > 127 then 
	        ComputeASN1 = Hex (128 + (Len(sLength) / 2)) & sLength 
	    else 
	        ComputeASN1 = sLength 
	    End If 
	End Function
	
	'Return the domain role number where:
	'-1 Error
	'0 Standalone Workstation
	'1 Member Workstation
	'2 Standalone Server
	'3 Member Server
	'4 Backup Domain Controller
	'5 Primary Domain Controller 
	Function GetLastDomainRole () 
	    On Error Resume Next
	    strComputer = "."
	    Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
	    Set colItems = objWMIService.ExecQuery("Select DomainRole from Win32_ComputerSystem",,48)
	    For Each objItem in colItems
	        iReturn = objItem.DomainRole
	    Next
	    On Error Goto 0
	    GetLastDomainRole = iReturn
	End Function

Edit or create C:\Shared\Autoenroll\EnrollMachine.vbs:

Set WS = CreateObject("WScript.Shell")
	Set oFilesystem = CreateObject("Scripting.FileSystemObject")
	sRequestInfo = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.inf"
	Set oFile = oFilesystem.CreateTextFile(sRequestInfo, True)
	oFile.WriteLine "[Version]" 
	oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34) 
	oFile.WriteLine "" 
	oFile.WriteLine "[NewRequest]"
	oFile.WriteLine "Subject = " & Chr(34) & "CN=IgnoredValue" & Chr(34)
	oFile.WriteLine "KeyLength = 2048" 
	oFile.WriteLine "MachineKeySet = TRUE" 
	oFile.WriteLine "RequestType = PKCS10" 
	oFile.WriteLine "" 
	oFile.WriteLine "[RequestAttributes]" 
	oFile.WriteLine "CertificateTemplate = Machine"
	oFile.Close
	
	sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\"
	WS.Run sSharedDir & "RequestAndInstall.vbs " & sRequestInfo, 0, True

Edit or create C:\Shared\Autoenroll\EnrollUser.vbs:

Set WS = CreateObject("WScript.Shell")
	Set oFilesystem = CreateObject("Scripting.FileSystemObject")
	sRequestInfo = WS.ExpandEnvironmentStrings("%TEMP%") & "\autoenrolled.inf"
	Set oFile = oFilesystem.CreateTextFile(sRequestInfo, True)
	oFile.WriteLine "[Version]" 
	oFile.WriteLine "Signature= " & Chr(34) & "$Windows NT$" & Chr(34) 
	oFile.WriteLine "" 
	oFile.WriteLine "[NewRequest]"
	oFile.WriteLine "Subject = " & Chr(34) & "CN=IgnoredValue" & Chr(34)
	oFile.WriteLine "KeyLength = 2048" 
	oFile.WriteLine "RequestType = PKCS10" 
	oFile.WriteLine "" 
	oFile.WriteLine "[RequestAttributes]" 
	oFile.WriteLine "CertificateTemplate = User"
	oFile.Close
	
	sSharedDir = oFilesystem.GetParentFolderName(WScript.ScriptFullName) & "\"
	WS.Run sSharedDir & "RequestAndInstall.vbs " & sRequestInfo, 0, True

Verify that all the file in Shared\Autoenroll directory has read end exec right for Everyone.

Install Certificate Templates by adding the corresponding Snap-in i the MMC console.

  • Install the root CA-certificate(s) in the NTAuthStore, so windows can verify all cerificates produced by EJBCA. Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> Edit Default Domain Policy -> Computer Configuration -> Windows Settings -> Security Settings -> Public Key Policies -> Trusted Root Certificate Authorities -> Import -> import the root ca certificate and run "gpupdate /force" on machines that are used for testing. (You can fetch the CA certificate using the EJCBA CLI with "$EJBCA_HOME/bin/ejbca.sh ca getcacert ManagementCA ~/ManagementCA.crt -der".)
  • Add Startup Scripts in Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> Edit Default Domain Policy -> Computer Configuration -> Windows Settings -> Scripts -> Startup -> Add the machine-related scripts from the shared directory.
  • Add Login Scripts in Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> Edit Default Domain Policy -> User Configuration -> Windows Settings -> Scripts -> Logon -> Add the user-related scripts from the shared directory.
  • Add the ca-server and shared directory to the Intranet Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> Edit Default Domain Policy -> Computer Configuration | User Configuration (do both!!) -> Administrative Templates -> Windows Components -> Internet Explorer -> Internet Control Page -> Security Page -> Site to Zone assignement list -> Enabled and added "https://ca-server.company.local" to zone "1", "\\Dc1\Shared" to zone "1"
  • Configure clients to synchronize time using NTP: Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> Edit Default Domain Policy -> Computer Configuration -> Administrative Templates -> System -> Windows Time Service -> Time Providers -> Configure Windows NTP Client (Add "dc1.company.local" as an NTP server.) and Enable Windows NTP Client.
  • Use "gpupdate /force" on clients before running tests.

Debugging 

You can enable debug by setting *debug=true* in autoenroll.conf to see the response from the Servlet. Test the machine-cert-retreival script by starting a Console as "LocalSystem". C:\Shared\Autoenroll\ConsoleAsLocalSystem.vbs:

	Set WS = CreateObject("WScript.Shell")
	WS.Run "sc.exe delete lsc", 0, True
	WS.Run "sc.exe create lsc binpath= " & Chr(34) & "cmd /K start" & Chr(34) & " type= own type= interact", 0, True
	WS.Run "sc.exe start lsc", 0, True

Test the machine-cert-retreival script by starting a Console as "LocalSystem". C:\Shared\ConsoleAsLocalSystem.vbs:

	Set WS = CreateObject("WScript.Shell")
	WS.Run "sc.exe delete lsc", 0, True
	WS.Run "sc.exe create lsc binpath= " & Chr(34) & "cmd /K start" & Chr(34) & " type= own type= interact", 0, True
	WS.Run "sc.exe start lsc", 0, True

Adding a custom Administrative template can be done as in this example if needed: Start Menu -> Administration -> Users and Computer -> Right click the domain name -> Properties -> Group Policy -> Edit Default Domain Policy -> Computer Configuration -> Administrative Templates -> Add/Remove Templates -> Add Autoenroll.adm

This is just a sample, but shows how a custom GP can be configured.. (Use the intructions above instead of this template. The example Administrative Template "Autoenroll Related" can be used to force ca-server.company.local into the Intranet zone or add a NTP syncronizing policy. C:\Shared\Autoenroll\Autoenroll.adm:

CLASS MACHINE

CATEGORY "Autoenroll Related"
    CATEGORY "NTP Synch for clients with AD"
     POLICY "Enable NTP synch"
      SUPPORTED "This is a hack to get WinXP clients working"
      EXPLAIN ".."
      KEYNAME "Software\Policies\Microsoft\W32Time\TimeProviders"
      VALUENAME "NtpServer"
      VALUEON NUMERIC 1
      VALUEOFF NUMERIC 0

       ACTIONLISTON
        KEYNAME "Software\Policies\Microsoft\W32Time\Parameters"
        VALUENAME "Type"
        VALUE "NTP"
       
        KEYNAME "Software\Policies\Microsoft\W32Time\Config"
        VALUENAME "AnnounceFlags"
        VALUE NUMERIC 5
        
        KEYNAME "Software\Policies\Microsoft\W32Time\Config"
        VALUENAME "MaxPosPhaseCorrection"
        VALUE NUMERIC 1099511627775
        
        KEYNAME "Software\Policies\Microsoft\W32Time\Config"
        VALUENAME "MaxNegPhaseCorrection"
        VALUE NUMERIC 1099511627775
       END ACTIONLISTON

      PART "NTP Servers in the form ntp.server1.com,0x1 ntp.server2.com,0x1 ntp.server3.com,0x1" EDITTEXT
       KEYNAME "Software\Policies\Microsoft\W32Time\Parameters"
       VALUENAME "NtpServer"
       MAXLEN 4096
      END PART

      PART "Poll interval in seconds" NUMERIC
        KEYNAME "Software\Policies\Microsoft\W32Time\TimeProviders\NtpClient"
        VALUENAME "SpecialPollInterval"
        DEFAULT 900
      END PART
     END POLICY
    END CATEGORY

    CATEGORY "Required trust"
     POLICY "Trust ca-server.company.local"
      SUPPORTED "Might need IE6 for this to work.."
      EXPLAIN "This adds the ca-server.company.local to the list of intranet-sites.."
      KEYNAME "Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\company.local\ca-server"
      VALUENAME "https"
      VALUEON NUMERIC 1
      VALUEOFF NUMERIC 0     
     END POLICY
    END CATEGORY
END CATEGORY 

CLASS USER

CATEGORY "Autoenroll Related"
    CATEGORY "Required trust"
     POLICY "Trust ca-server.company.local"
      SUPPORTED "Might need IE6 for this to work.."
      EXPLAIN "This adds the ca-server.company.local to the list of intranet-sites.."
      KEYNAME "Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\company.local\ca-server"
      VALUENAME "https"
      VALUEON NUMERIC 1
      VALUEOFF NUMERIC 0     
     END POLICY
    END CATEGORY
END CATEGORY

Useful reg-for VMwares with runaway clocks if GP mod didn't work or you want to modify a single client:

Windows Registry Editor Version 5.00

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Config]
"AnnounceFlags"=dword:00000005
"MaxPosPhaseCorrection"=dword:ffffffff
"MaxNegPhaseCorrection"=dword:ffffffff

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters]
"Type"="NTP"
"NtpServer"="dc1.company.local,0x1"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\Parameters\NtpServer]
"NtpServer"="dc1.company.local,0x1"

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpClient]
"SpecialPollInterval"=dword:00000030

[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\W32Time\TimeProviders\NtpServer]
"Enabled"=dword:00000001

References

Other auto enroll references: