diff options
-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,10 +1,10 @@ /* - * 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 #include <Swiften/Network/TimerFactory.h> #include <Swiften/TLS/CAPICertificate.h> @@ -14,12 +14,17 @@ #include <boost/bind.hpp> #include <boost/algorithm/string/predicate.hpp> // 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 { CAPICertificate::CAPICertificate(const std::string& capiUri, TimerFactory* timerFactory) : valid_(false), uri_(capiUri), @@ -45,17 +50,19 @@ CAPICertificate::~CAPICertificate() { if (certStoreHandle_) { CertCloseStore(certStoreHandle_, 0); } 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); } } bool CAPICertificate::isNull() const { return uri_.empty() || !valid_; } @@ -188,12 +195,13 @@ void CAPICertificate::setUri (const std::string& capiUri) { smartCardReaderName_ = ""; } else { 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); } else { ///Need to handle an error here @@ -220,52 +228,62 @@ void CAPICertificate::setUri (const std::string& capiUri) { static void smartcard_check_status (SCARDCONTEXT hContext, const char* pReader, 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; - } } } char szReader[200]; 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) { *pdwState = SCARD_ABSENT; } else { *pdwState = SCARD_UNKNOWN; } } 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; } } |