summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swiften/TLS/CAPICertificate.cpp66
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;
}
}