Deconstructing the Smartcard Removal Policy Service

Windows Vista and Windows Server 2008 introduced a new service that is dedicated to monitoring the removal of smartcards on the system and handling of the event as defined by the Smartcard Removal Policy service (ScRemoveOption) that is configured for the system. This service (ScPolicySvc) is hosted in one of the svchost.exe processes on the system.

The service recognizes four different registry values; Do nothing (0), Lock session (1) , Logoff session(2) and Disconnect Session(3) – the last only being relevant if the user is connected via a terminal session.

During a smartcard logon, the Smartcard Logon Credential Provider (SmartcardCredentialProvider.dll) is used to gather the smartcard credentials that will be used for authentication. This CP also writes a registry entry into HKLMSoftwareMicrosoftWindows NTCurrentVersionRemoval Policy that contains the ID of the session being logged on to and the name of the redirected smartcard reader and a value to indicate how many times it has been removed.

The Smartcard Removal Service then monitors this key and spins up a new thread for monitoring that session each time that it detects a value being written to it, it then deletes the subkey containing the session ID once it has picked up the new session it should start monitoring.

Consequently, when a smartcard is removed from a session on the server the thread monitoring that session triggers the appropriate action (Lock/Logoff/Disconnect) and then exits.
If the service detects that the number of times the card has been removed from the reader has changed between the time when the value was written to the registry and the current value for the reader - the removal policy also kicks in for that reader.
You can monitor that behaviour by stopping the ScRemovePolicy and removing/reinserting the smartard after a successful logon - this shold cause the ScRemovePolicy service to disconnect or lock the user as soon as it is started again.

At reconnect the user initially receives an initial "temporary" session ID from the pool of free sessions on the server. This is used during the authentication - it's obviously impossible to match disconnected sessions to the connecting user until the user has authenticated.
if it is determined after authentication that an existing session is present for that user the initial session is ended and the user is reconnected to the existing session. If no existing disconnected session exists then the initial session ID is used for the duration of that session.

ScPolicySvc keeps two lists of sessions it is monitoring; one for the active sessions and one for the inactive sessions. Usually the thread stops monitoring the session at disconnect but in some circumstances the thread is first moved to the inactive list rather than ended to cater for autoreconnect when the session has lost connectivity rather than having been disconnected on purpose.

A simplified view of the reconnect process is as follows:

  1. A new session is created on the TS when a client connects via RDP - SmartCardCredentialProvider.dll writes the session ID into the Removal Policy registry key (in Hex format)
  2. Once the client has authenticated - the TS subsystem determines if the user has an existing disconnected session and if so, tears down the new session and reconnects the user to the existing session (or pops up a choice window if multiple disconnected sessions exist for that user).
  3. The Smartcard Removal Policy service picks up the session ID used during the authentication from a call to WinStationQueryInformation by passing in the current session ID and getting back the "temporary" session ID used in pWinStationInformation (these may be the same if the user wasn't reconnecting and the "temporary" session ID became the "permanent" session ID).
    It then makes a registry query for that value under HKLMSoftwareMicrosoftWindows NTCurrentVersionRemoval Policy and spins up a thread to start monitoring the associated session if it finds the value and then deletes the registry value when it has consumed it.
    If the service cannot match the ID it just picked up from the call to WinStationQueryInformation to an existing session on the TS the thread is not spun up and the entry is not removed from the registry.

 To monitor this in action for troubleshooting purposes, the following can be done:

  • Set up Procmon to monitor HKLMSoftwareMicrosoftWindows NTCurrentVersionRemoval Policy.
  • Create the key HKLMSOFTWAREPoliciesMicrosoftWindowsCertProp and underneath that a DWORD DebugLevel with the value of 0x0000000f
  • Isolate the ScPolicySvc service into its own SVCHOST.exe process by running “sc config ScPolicySvc type= own”

Once the server has rebooted it should be running ScPolicySvc in a separate SVCHost process and be ready for troubleshooting using a debugger like Windbg.
Attach Windbg to the PID of the svchost.exe process containing the ScPolicySvc service and you should get debug messages at key points during the smartcard removal process.
At the same time you should see LogonUI.exe writing to the Removal Policy registry key and svchost deleting from it shortly afterwards.

[Note: As pointed out to me it would probably be a lot simpler to just stop the ScPolicySvc service and do a Smartcard Logon with Procmon running if you don't want to debug this - that way you can also examine the entry the credential provider writes because it won't be removed until you start it again]

 

Further reading:

SCARD_READERSTATE Structure
http://msdn.microsoft.com/en-us/library/aa379808(VS.85).aspx

WTSSESSION_NOTIFICATION Structure
http://msdn.microsoft.com/en-us/library/aa383843(VS.85).aspx

WinStationQueryInformationW function
http://msdn.microsoft.com/en-us/library/aa383827(VS.85).aspx