diff options
author | Mili Verma <mili.verma@isode.com> | 2015-07-01 11:12:56 (GMT) |
---|---|---|
committer | Mili Verma <mili.verma@isode.com> | 2015-07-02 12:06:54 (GMT) |
commit | 87137e983ed986df774a3373168a7611dff583c1 (patch) | |
tree | 6e7d3356ca499b4803e495970d6de9c0e702b48d | |
parent | d65daf31d58ad432dadb1639f05a0d7f7f367d01 (diff) | |
download | swift-87137e983ed986df774a3373168a7611dff583c1.zip swift-87137e983ed986df774a3373168a7611dff583c1.tar.bz2 |
Reestablish connection with smart card
When the card is reset in shared mode (which is the mode we use), an application
trying to access certain commands will be returned the value SCARD_W_RESET_CARD.
When this occurs SCardReconnect() must be called. This wasn't done before so
this patch fixes it.
Also provides more logging for SCard function returns.
Test-information:
Tested on Windows using NIST smart cards.
Before the fix, the Card Removed Error was seen often even after the initial
connection was established. After the fix, the reconnect attempt is done so the
error is not seen.
Also verified that if a card is removed deliberately, then the user is logged
out.
Change-Id: I94748ab9ff944a79de655646e1e06a8b61776f4b
-rw-r--r-- | Swiften/TLS/CAPICertificate.cpp | 66 |
1 files changed, 42 insertions, 24 deletions
diff --git a/Swiften/TLS/CAPICertificate.cpp b/Swiften/TLS/CAPICertificate.cpp index d10ae6d..f492c50 100644 --- a/Swiften/TLS/CAPICertificate.cpp +++ b/Swiften/TLS/CAPICertificate.cpp @@ -1,7 +1,7 @@ /* - * Copyright (c) 2012 Isode Limited, London, England. - * Licensed under the simplified BSD license. - * See Documentation/Licenses/BSD-simplified.txt for more information. + * Copyright (c) 2012-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once @@ -17,6 +17,11 @@ // Size of the SHA1 hash #define SHA1_HASH_LEN 20 +#define DEBUG_SCARD_STATUS(function, status) \ +{ \ + boost::shared_ptr<boost::system::error_code> errorCode = boost::make_shared<boost::system::error_code>(status, boost::system::system_category()); \ + SWIFT_LOG(debug) << std::hex << function << ": status: 0x" << status << ": " << errorCode->message() << std::endl; \ +} namespace Swift { @@ -48,11 +53,13 @@ CAPICertificate::~CAPICertificate() { } if (cardHandle_) { - (void) SCardDisconnect(cardHandle_, SCARD_LEAVE_CARD); + LONG result = SCardDisconnect(cardHandle_, SCARD_LEAVE_CARD); + DEBUG_SCARD_STATUS("SCardDisconnect", result); } if (scardContext_) { - SCardReleaseContext(scardContext_); + LONG result = SCardReleaseContext(scardContext_); + DEBUG_SCARD_STATUS("SCardReleaseContext", result); } } @@ -191,6 +198,7 @@ void CAPICertificate::setUri (const std::string& capiUri) { smartCardReaderName_ = smartCardReader; LONG result = SCardEstablishContext(SCARD_SCOPE_USER, NULL, NULL, &scardContext_); + DEBUG_SCARD_STATUS("SCardEstablishContext", result); if (SCARD_S_SUCCESS == result) { // Initiate monitoring for smartcard ejection smartCardTimer_ = timerFactory_->createTimer(SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS); @@ -223,25 +231,16 @@ static void smartcard_check_status (SCARDCONTEXT hContext, SCARDHANDLE hCardHandle, /* Can be 0 on the first call */ SCARDHANDLE* newCardHandle, /* The handle returned */ DWORD* pdwState) { + DWORD shareMode = SCARD_SHARE_SHARED; + DWORD preferredProtocols = SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1; + DWORD dwAP; + LONG result; + if (hCardHandle == 0) { - DWORD dwAP; - LONG result = SCardConnect(hContext, pReader, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, &hCardHandle, &dwAP); + result = SCardConnect(hContext, pReader, shareMode, preferredProtocols, &hCardHandle, &dwAP); + DEBUG_SCARD_STATUS("SCardConnect", result); if (SCARD_S_SUCCESS != result) { hCardHandle = 0; - if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) { - *pdwState = SCARD_ABSENT; - } - else { - *pdwState = SCARD_UNKNOWN; - } - - if (newCardHandle == NULL) { - (void) SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); - hCardHandle = 0; - } - else { - *newCardHandle = hCardHandle; - } } } @@ -249,7 +248,26 @@ static void smartcard_check_status (SCARDCONTEXT hContext, DWORD cch = sizeof(szReader); BYTE bAttr[32]; DWORD cByte = 32; - LONG result = SCardStatus(hCardHandle, /* Unfortunately we can't use NULL here */ szReader, &cch, pdwState, NULL, (LPBYTE)&bAttr, &cByte); + size_t countStatusAttempts = 0; + + while (hCardHandle && (countStatusAttempts < 2)) { + *pdwState = SCARD_UNKNOWN; + + result = SCardStatus(hCardHandle, /* Unfortunately we can't use NULL here */ szReader, &cch, pdwState, NULL, (LPBYTE)&bAttr, &cByte); + DEBUG_SCARD_STATUS("SCardStatus", result); + countStatusAttempts++; + + if ((SCARD_W_RESET_CARD == result) && (countStatusAttempts < 2)) { + result = SCardReconnect(hCardHandle, shareMode, preferredProtocols, SCARD_RESET_CARD, &dwAP); + DEBUG_SCARD_STATUS("SCardReconnect", result); + if (SCARD_S_SUCCESS != result) { + break; + } + } + else { + break; + } + } if (SCARD_S_SUCCESS != result) { if (SCARD_E_NO_SMARTCARD == result || SCARD_W_REMOVED_CARD == result) { @@ -261,8 +279,8 @@ static void smartcard_check_status (SCARDCONTEXT hContext, } if (newCardHandle == NULL) { - (void) SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); - hCardHandle = 0; + result = SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); + DEBUG_SCARD_STATUS("SCardDisconnect", result); } else { *newCardHandle = hCardHandle; |