Following on from my previous blog entry, while the manual method is simple enough, and we could just import a .REG file to force “Security Packages” and “SecurityProviders” to fixed values, it would be more elegant to have a smarter solution that will make the amendments if necessary.
So here is a VBScript to check if “tspkg” is in “Security Packages” and “credssp.dll” is in “SecurityProviders”, and add them if not. It also reports on the status of the GPO settings affecting DisableRootAutoUpdate and CredentialsDelegation (default and saved), but does not attempt to adjust these as they should be done via GPO rather than registry edits.
Use this script at your own risk – I’ve tested it very briefly but there is no error checking or backing up of the keys/values performed, and it does not attempt to verify the OS version is applicable.
If double-clicked then wscript.exe is used by default and the result is displayed in a pop-up window – if it needs to be run in a computer startup script then make sure to explicitly use cscript.exe (and optionally pipe the output to a log file if needed).
' ============================================ ' CheckCredSSP.vbs ' ' Verifies that the settings necessary for CredSSP are enabled on XP clients ' As per http://support.microsoft.com/kb/951608 ' ' Checks if DisableRootAutoUpdate policy setting is enabled to avoid a 30-second ' delay when clients have no access to Windows Update and NLA is used ' ' Displays a summary of any credential delegation policy settings found ' ============================================ const HKEY_LOCAL_MACHINE = &H80000002 const REG_SZ = 1 strComputer = "."
' Variables to hold results of key enumeration and the value types arrNames = Array() arrTypes = Array()
' Variables to hold values for REG_MULTI_SZ, REG_SZ and REG_DWORD data arrValues = Array() strValue = "" dwValue = 0
' Object to allow us access to the registry Set objReg=GetObject( _ "winmgmts:{impersonationLevel=impersonate}!\\" & _ strComputer & "\root\default:StdRegProv")
' ============================================ ' Check for (and add if necessary) tspkg in REG_MULTI_SZ value ' ============================================ strKeyPath = "SYSTEM\CurrentControlSet\Control\Lsa" strValueName = "Security Packages" bPresent_tspkg = FALSE
If ( objReg.GetMultiStringValue( HKEY_LOCAL_MACHINE, strKeyPath, strValueName, arrValues ) <> 0 ) Then ' Failed to read the value, exit early WScript.Echo "ERROR - Failed to open value: " & strValueName WScript.Quit End If
For Each strElement in arrValues If strElement = "tspkg" Then bPresent_tspkg = TRUE Next
If Not bPresent_tspkg Then ReDim Preserve arrValues( UBound( arrValues ) + 1 ) arrValues( UBound( arrValues ) ) = "tspkg" iError = objReg.SetMultiStringValue( HKEY_LOCAL_MACHINE, strKeyPath, strValueName, arrValues ) If ( iError <> 0 ) Then ' Failed to write the value, exit early WScript.Echo "ERROR - Failed to write value: " & strValueName & vbCrLf & "Error code: " & iError WScript.Quit End If End If
' ============================================ ' Check for (and add if necessary) credssp.dll in REG_SZ value ' ============================================ strKeyPath = "SYSTEM\CurrentControlSet\Control\SecurityProviders" strValueName = "SecurityProviders" bPresent_credssp = FALSE
If ( objReg.GetStringValue( HKEY_LOCAL_MACHINE, strKeyPath, strValueName, strValue ) <> 0 ) Then ' Failed to read the value, exit early WScript.Echo "ERROR - Failed to open value: " & strValueName WScript.Quit End If
' Convert the comma-separated string into an array of strings to check each element arrValues = ConvertStrToArr( strValue ) For Each strElement in arrValues ' We use LTrim() to ignore leading spaces (i.e. spaces after commas) If LTrim( strElement ) = "credssp.dll" Then bPresent_credssp = TRUE Next
If Not bPresent_credssp Then If ( strValue <> "" ) Then strValue = strValue & ", " strValue = strValue & "credssp.dll" iError = objReg.SetStringValue( HKEY_LOCAL_MACHINE, strKeyPath, strValueName, strValue ) If ( iError <> 0 ) Then ' Failed to write the value, exit early WScript.Echo "ERROR - Failed to write value: " & strValueName & vbCrLf & "Error code: " & iError WScript.Quit End If End If
' ============================================ ' Check for DisableRootAutoUpdate = 1 ' ============================================ strKeyPath = "SOFTWARE\Policies\Microsoft\SystemCertificates\AuthRoot" strValueName = "DisableRootAutoUpdate"
strPolicyOutput = vbCrLf & vbCrLf &_ "DisableRootAutoUpdate policy setting "
' Does the value exist and is non-zero? If ( objReg.GetDWORDValue( HKEY_LOCAL_MACHINE, strKeyPath, strValueName, dwValue ) = 0 ) Then If ( dwValue <> 0 ) Then strPolicyOutput = strPolicyOutput & "found : ENABLED" & vbCrLf & vbCrLf Else strPolicyOutput = strPolicyOutput & "found : DISABLED" & vbCrLf & vbCrLf End If Else strPolicyOutput = strPolicyOutput & "NOT found" & vbCrLf &_ "Consider enabling the following policy setting if hitting a ~30 second delay:" & vbCrLf &_ "Administrative Templates > System > Internet Communication Management > Internet Communication Settings" & vbCrLf &_ "Turn off Automatic Root Certificates Update" & vbCrLf & vbCrLf End If
' ============================================ ' Check for any policy settings relating to credential delegation ' ============================================ strKeyPath = "SOFTWARE\Policies\Microsoft\Windows\CredentialsDelegation"
If ( objReg.EnumValues( HKEY_LOCAL_MACHINE, strKeyPath, arrNames, arrTypes ) <> 0 ) Then strPolicyOutput = strPolicyOutput & "Found no credential delegation policy settings (e.g. SSO, saved credentials)" & vbCrLf &_ "Recommend reading KB951608 if SSO is required." & vbCrLf &_ "Or check under:" & vbCrLf &_ "Administrative Templates > System > Credentials Delegation" & vbCrLf Else strPolicyOutput = strPolicyOutput & "Found credential delegation policy settings..." & vbCrLf
strPolicyCheck = CheckPolicy( "DenyDefaultCredentials" ) If ( strPolicyCheck = "" ) Then strPolicyCheck = CheckPolicy( "AllowDefaultCredentials" ) strPolicyCheck = strPolicyCheck & CheckPolicy( "AllowDefCredentialsWhenNTLMOnly" ) Else strPolicyOutput = strPolicyOutput & vbCrLf & "DEFAULT credential delegation (SSO) explicitly DENIED by policy" & vbCrLf End If strPolicyOutput = strPolicyOutput & strPolicyCheck
strPolicyCheck = CheckPolicy( "DenySavedCredentials" ) If ( strPolicyCheck = "" ) Then strPolicyCheck = CheckPolicy( "AllowSavedCredentials" ) strPolicyCheck = strPolicyCheck & CheckPolicy( "AllowSavedCredentialsWhenNTLMOnly" ) Else strPolicyOutput = strPolicyOutput & vbCrLf & "SAVED credential delegation explicitly DENIED by policy" & vbCrLf End If strPolicyOutput = strPolicyOutput & strPolicyCheck End If
' ============================================ ' Display summary of actions ' ============================================ strOutput = "Security Packages - tspkg : "
If Not bPresent_tspkg Then strOutput = strOutput & "PRESENT (added)" Else strOutput = strOutput & "PRESENT" End If
strOutput = strOutput & vbCrLf & vbCrLf &_ "SecurityProviders - credssp.dll : "
If Not bPresent_credssp Then strOutput = strOutput & "PRESENT (added)" Else strOutput = strOutput & "PRESENT" End If
WScript.Echo strOutput & strPolicyOutput
' ============================================ ' Function to convert a comma-separated string into an array of strings ' ============================================ Function ConvertStrToArr ( strInput ) Set objRegExp = CreateObject( "VBScript.RegExp" ) objRegExp.IgnoreCase = TRUE objRegExp.Global = TRUE objRegExp.Pattern = ",(?=([^']*'[^']*')*(?![^']*'))" ConvertStrToArr = Split( objRegExp.Replace(strInput, "\b"), "\b" ) End Function
' ============================================ ' Function to check for a credential delegation policy setting ' ============================================ Function CheckPolicy ( strPolicy ) dwValue = 0 If ( objReg.GetDWORDValue( HKEY_LOCAL_MACHINE, strKeyPath, strPolicy, dwValue ) = 0 ) Then CheckPolicy = strPolicy & " = " & dwValue If ( dwValue <> 0 ) Then CheckPolicy = CheckPolicy & " (ENABLED)" & vbCrLf If ( objReg.EnumValues( HKEY_LOCAL_MACHINE, strKeyPath & "\" & strPolicy, arrNames, arrTypes ) = 0 ) Then If IsArray( arrNames ) Then For i = 0 To UBound( arrNames ) If ( arrTypes( i ) = REG_SZ ) Then If ( objReg.GetStringValue( HKEY_LOCAL_MACHINE, strKeyPath & "\" & strPolicy, arrNames( i ), strValue ) <> 0 ) Then ' Failed to read the value, exit early WScript.Echo "ERROR - Failed to open value: " & arrNames( i ) WScript.Quit End If CheckPolicy = CheckPolicy & " > " & strValue & vbCrLf End If Next Else CheckPolicy = CheckPolicy & " > [no SPNs specified]" & vbCrLf End If Else CheckPolicy = CheckPolicy & " > [no SPNs specified]" & vbCrLf End If Else CheckPolicy = CheckPolicy & " (DISABLED)" & vbCrLf End If End If End Function