Disclaimer: All postings are provided "AS IS" with no warranties, and confer no rights. This weblog does not represent the thoughts, intentions, plans or strategies of Microsoft. Because a weblog is intended to provide a semi-permanent point-in-time snapshot, you should not consider out of date posts to reflect current thoughts and opinions.
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 HKLM\Software\Microsoft\Windows NT\CurrentVersion\Removal 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:
To monitor this in action for troubleshooting purposes, the following can be done:
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]
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).aspxWinStationQueryInformationW functionhttp://msdn.microsoft.com/en-us/library/aa383827(VS.85).aspx
Wow, this is exactly what I was looking for! Thanks so much for posting this. I need to do something similar in my smart card credential provider but when I watch the "Removal Policy" key in ProcMon, I see that the value being created is a REG_BINARY, instead of the REG_SZ that I would expect given that it is the reader name. If I want to write the smart card info to that key, should I use a REG_SZ? Otherwise, are there special considerations I need to take into account as far as formatting the data? It looks like you're just outputing UTF16 data into a REG_BINARY, but I want to be sure.
Hi Adam, if this is time-critical for you then I would really advise opening up a case with Microsoft Developer Support to work on it in realtime. I'm looking at the Smartcard Removal Policy service in a case I'm working on but I haven't had the time to dig more into the exact specifics for what is written by the smartcard credential provider as it's not directly related to the issue I'm working on.
Are you testing the different smartcard readers from two different clients or from two smartcard readers attached to the same client? Are you using the same smartcard in each or two different smartcards?
One thing that might interest you is that the Smartcard Removal Service subscribes to a session change notification - that's how it is detecting things like Disconnect or Logoff session.
Ok, I can open up a case. I tested the smart card readers from a variety of clients, but they all tended to use the same smart card. I'm not as worried about the session change notification semantics because those seem to work correctly; I'm more worried about the form of the data I have to write out. If the integer at the end of the stream isn't the right value, the session will lock right after login because the smart card removal policy will be looking for a smart card reader with the wrong name.
Looking closer at this it seems the entry at the end is the number of times the card has been removed from the reader. This is to be able to pick up if the card is removed from the reader after the registry entry is written but before the smartcard removal policy starts monitoring it - if there is a difference between the counter in the service and the value in the registry it means that the card was removed before we started monitoring it and we need to disconnect immediately.
Hey, to revisit this topic... I'm striking out finding any ms docs on what exactly should be put in registry for card removal service to work properly. Anyone have examples or example code?
@Steve: Yes, there is unfortunately not a lot of documentation on this, I assume you're considering writing your own Smartcard Credential Provider....?
Opening up a support case with developer support and asking specifically about this would probably be your best option - otherwise you can try stopping the service and check on the registry entry that gets written when you log on using the standard smartcard credential provider.
One thing of note is that the ID for the session is in Hex if I remember correctly, so make sure your CP uses the same format (otherwise you'll get problems when you get above 5 simultaneous logons and user 0xa comes in and you write 10).