summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThanos Doukoudakis <thanos.doukoudakis@isode.com>2017-08-14 16:08:44 (GMT)
committerThanos Doukoudakis <thanos.doukoudakis@isode.com>2017-08-15 08:48:42 (GMT)
commit2b6a7dfacc10644c1c6c79e59c953ad1537bd161 (patch)
tree9cb5170b99d3db0fd91bc9c170edb5375ca1ddda /Swiften
parentc5aa27ee869cc4859e494bde8ddf7da60e177f40 (diff)
downloadswift-2b6a7dfacc10644c1c6c79e59c953ad1537bd161.zip
swift-2b6a7dfacc10644c1c6c79e59c953ad1537bd161.tar.bz2
Improve Swift’s interactions with Smart Cards
This patch improves logging and refactors SchannelContext and CAPICertificate classes, to improve logging and how Swift interacts with smart cards. Test-Information: Tested on Windows 10 (Qt 5.7) Change-Id: Ic4d306beafb9e5d253731769f222e6949995d5e7
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/TLS/CAPICertificate.cpp49
-rw-r--r--Swiften/TLS/Schannel/SchannelContext.cpp27
2 files changed, 40 insertions, 36 deletions
diff --git a/Swiften/TLS/CAPICertificate.cpp b/Swiften/TLS/CAPICertificate.cpp
index a46b9f6..f10ad47 100644
--- a/Swiften/TLS/CAPICertificate.cpp
+++ b/Swiften/TLS/CAPICertificate.cpp
@@ -14,6 +14,7 @@
#include <Swiften/Base/Log.h>
#include <Swiften/Network/TimerFactory.h>
#include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/TLS/Schannel/SchannelUtil.h>
// Size of the SHA1 hash
#define SHA1_HASH_LEN 20
@@ -43,6 +44,7 @@ CAPICertificate::CAPICertificate(const std::string& capiUri, TimerFactory* timer
}
CAPICertificate::~CAPICertificate() {
+ SWIFT_LOG(debug) << "Destroying the CAPICertificate" << std::endl;
if (smartCardTimer_) {
smartCardTimer_->stop();
smartCardTimer_->onTick.disconnect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this));
@@ -50,7 +52,9 @@ CAPICertificate::~CAPICertificate() {
}
if (certStoreHandle_) {
- CertCloseStore(certStoreHandle_, 0);
+ if (CertCloseStore(certStoreHandle_, 0) == FALSE) {
+ SWIFT_LOG(debug) << "Failed to close the certificate store handle" << std::endl;
+ }
}
if (cardHandle_) {
@@ -80,7 +84,7 @@ const std::string& CAPICertificate::getSmartCardReaderName() const {
return smartCardReaderName_;
}
-PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::string &certName) {
+PCCERT_CONTEXT findCertificateInStore(HCERTSTORE certStoreHandle, const std::string &certName) {
if (!boost::iequals(certName.substr(0, 5), "sha1:")) {
// Find client certificate. Note that this sample just searches for a
@@ -105,8 +109,7 @@ PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::st
}
-
-void CAPICertificate::setUri (const std::string& capiUri) {
+void CAPICertificate::setUri(const std::string& capiUri) {
valid_ = false;
/* Syntax: "certstore:" <cert_store> ":" <hash> ":" <hash_of_cert> */
@@ -118,7 +121,7 @@ void CAPICertificate::setUri (const std::string& capiUri) {
/* Substring of subject: uses "storename" */
std::string capiIdentity = capiUri.substr(10);
std::string newCertStoreName;
- size_t pos = capiIdentity.find_first_of (':');
+ size_t pos = capiIdentity.find_first_of(':');
if (pos == std::string::npos) {
/* Using the default certificate store */
@@ -146,49 +149,38 @@ void CAPICertificate::setUri (const std::string& capiUri) {
certStore_ = newCertStoreName;
- PCCERT_CONTEXT certContext = findCertificateInStore (certStoreHandle_, certName_);
-
+ ScopedCertContext certContext(findCertificateInStore(certStoreHandle_, certName_));
if (!certContext) {
return;
}
-
/* Now verify that we can have access to the corresponding private key */
DWORD len;
- CRYPT_KEY_PROV_INFO *pinfo;
- HCRYPTPROV hprov;
- HCRYPTKEY key;
-
if (!CertGetCertificateContextProperty(certContext,
CERT_KEY_PROV_INFO_PROP_ID,
NULL,
&len)) {
- CertFreeCertificateContext(certContext);
+ SWIFT_LOG(error) << "Error while retrieving context properties" << std::endl;
return;
}
- pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len));
+ std::shared_ptr<CRYPT_KEY_PROV_INFO> pinfo(static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len)), free);
if (!pinfo) {
- CertFreeCertificateContext(certContext);
return;
}
- if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) {
- CertFreeCertificateContext(certContext);
- free(pinfo);
+ if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo.get(), &len)) {
return;
}
+ certContext.FreeContext();
- CertFreeCertificateContext(certContext);
-
+ HCRYPTPROV hprov;
// Now verify if we have access to the private key
if (!CryptAcquireContextW(&hprov, pinfo->pwszContainerName, pinfo->pwszProvName, pinfo->dwProvType, 0)) {
- free(pinfo);
return;
}
-
char smartCardReader[1024];
DWORD bufferLength = sizeof(smartCardReader);
if (!CryptGetProvParam(hprov, PP_SMARTCARD_READER, (BYTE *)&smartCardReader, &bufferLength, 0)) {
@@ -205,19 +197,19 @@ void CAPICertificate::setUri (const std::string& capiUri) {
smartCardTimer_ = timerFactory_->createTimer(SMARTCARD_EJECTION_CHECK_FREQUENCY_MILLISECONDS);
}
else {
- ///Need to handle an error here
+ CryptReleaseContext(hprov, 0);
+ return;
}
}
+ HCRYPTKEY key;
if (!CryptGetUserKey(hprov, pinfo->dwKeySpec, &key)) {
CryptReleaseContext(hprov, 0);
- free(pinfo);
return;
}
CryptDestroyKey(key);
CryptReleaseContext(hprov, 0);
- free(pinfo);
if (smartCardTimer_) {
smartCardTimer_->onTick.connect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this));
@@ -227,7 +219,7 @@ void CAPICertificate::setUri (const std::string& capiUri) {
valid_ = true;
}
-static void smartcard_check_status (SCARDCONTEXT hContext,
+static void smartcard_check_status(SCARDCONTEXT hContext,
const char* pReader,
SCARDHANDLE hCardHandle, /* Can be 0 on the first call */
SCARDHANDLE* newCardHandle, /* The handle returned */
@@ -288,7 +280,7 @@ static void smartcard_check_status (SCARDCONTEXT hContext,
}
}
-bool CAPICertificate::checkIfSmartCardPresent () {
+bool CAPICertificate::checkIfSmartCardPresent() {
if (!smartCardReaderName_.empty()) {
DWORD dwState;
smartcard_check_status(scardContext_, smartCardReaderName_.c_str(), cardHandle_, &cardHandle_, &dwState);
@@ -317,8 +309,6 @@ bool CAPICertificate::checkIfSmartCardPresent () {
break;
}
-
-
switch (dwState) {
case SCARD_ABSENT:
return false;
@@ -342,6 +332,7 @@ bool CAPICertificate::checkIfSmartCardPresent () {
void CAPICertificate::handleSmartCardTimerTick() {
bool poll = checkIfSmartCardPresent();
if (lastPollingResult_ && !poll) {
+ SWIFT_LOG(debug) << "CAPI Certificate detected that the certificate card was removed" << std::endl;
onCertificateCardRemoved();
}
lastPollingResult_ = poll;
diff --git a/Swiften/TLS/Schannel/SchannelContext.cpp b/Swiften/TLS/Schannel/SchannelContext.cpp
index 5799157..c07d009 100644
--- a/Swiften/TLS/Schannel/SchannelContext.cpp
+++ b/Swiften/TLS/Schannel/SchannelContext.cpp
@@ -16,6 +16,7 @@
#include <WinHTTP.h> /* For SECURITY_FLAG_IGNORE_CERT_CN_INVALID */
+#include <Swiften/Base/Log.h>
#include <Swiften/TLS/CAPICertificate.h>
#include <Swiften/TLS/Schannel/SchannelCertificate.h>
@@ -39,13 +40,20 @@ SchannelContext::SchannelContext(bool tls1_0Workaround) : state_(Start), secCont
//------------------------------------------------------------------------
SchannelContext::~SchannelContext() {
- if (myCertStore_) CertCloseStore(myCertStore_, 0);
+ SWIFT_LOG(debug) << "Destroying SchannelContext" << std::endl;
+ if (myCertStore_) {
+ if (CertCloseStore(myCertStore_, 0) == FALSE) {
+ SWIFT_LOG(debug) << "Failed to close the certificate store" << std::endl;
+ }
+ }
}
//------------------------------------------------------------------------
void SchannelContext::determineStreamSizes() {
- QueryContextAttributes(contextHandle_, SECPKG_ATTR_STREAM_SIZES, &streamSizes_);
+ if (QueryContextAttributes(contextHandle_, SECPKG_ATTR_STREAM_SIZES, &streamSizes_) != SEC_E_OK) {
+ SWIFT_LOG(debug) << "QueryContextAttributes failed to determinate the stream size" << std::endl;
+ }
}
//------------------------------------------------------------------------
@@ -267,8 +275,8 @@ void SchannelContext::continueHandshake(const SafeByteArray& data) {
SecBuffer inBuffers[2];
// Provide Schannel with the remote host's handshake data
- inBuffers[0].pvBuffer = (char*)(&receivedData_[0]);
- inBuffers[0].cbBuffer = (unsigned long)receivedData_.size();
+ inBuffers[0].pvBuffer = static_cast<char*>(&receivedData_[0]);
+ inBuffers[0].cbBuffer = static_cast<unsigned long>(receivedData_.size());
inBuffers[0].BufferType = SECBUFFER_TOKEN;
inBuffers[1].pvBuffer = NULL;
@@ -483,8 +491,8 @@ void SchannelContext::decryptAndProcessData(const SafeByteArray& data) {
// contexts. Additionally, a second SECBUFFER_TOKEN type buffer that contains a security token
// must also be supplied.
//
- inBuffers[0].pvBuffer = (char*)(&receivedData_[0]);
- inBuffers[0].cbBuffer = (unsigned long)receivedData_.size();
+ inBuffers[0].pvBuffer = static_cast<char*>(&receivedData_[0]);
+ inBuffers[0].cbBuffer = static_cast<unsigned long>(receivedData_.size());
inBuffers[0].BufferType = SECBUFFER_DATA;
inBuffers[1].BufferType = SECBUFFER_EMPTY;
@@ -578,7 +586,7 @@ void SchannelContext::encryptAndSendData(const SafeByteArray& data) {
outBuffers[0].BufferType = SECBUFFER_STREAM_HEADER;
outBuffers[1].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader;
- outBuffers[1].cbBuffer = (unsigned long)bytesToSend;
+ outBuffers[1].cbBuffer = static_cast<unsigned long>(bytesToSend);
outBuffers[1].BufferType = SECBUFFER_DATA;
outBuffers[2].pvBuffer = &sendBuffer[0] + streamSizes_.cbHeader + bytesToSend;
@@ -645,6 +653,7 @@ std::vector<Certificate::ref> SchannelContext::getPeerCertificateChain() const {
SECURITY_STATUS status = QueryContextAttributes(contextHandle_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, pServerCert.Reset());
if (status != SEC_E_OK) {
+ SWIFT_LOG(debug) << "Error while Querying the Certificate Chain" << std::endl;
return certificateChain;
}
certificateChain.push_back(std::make_shared<SchannelCertificate>(pServerCert));
@@ -678,6 +687,10 @@ ByteArray SchannelContext::getFinishMessage() const {
if (ret == SEC_E_OK) {
return createByteArray(((unsigned char*) bindings.Bindings) + bindings.Bindings->dwApplicationDataOffset + 11 /* tls-unique:*/, bindings.Bindings->cbApplicationDataLength - 11);
}
+ else {
+ SWIFT_LOG(debug) << "Error while retrieving Finish Message" << std::endl;
+ }
+
return ByteArray();
}