diff options
Diffstat (limited to 'Swiften/TLS/CAPICertificate.cpp')
-rw-r--r-- | Swiften/TLS/CAPICertificate.cpp | 570 |
1 files changed, 285 insertions, 285 deletions
diff --git a/Swiften/TLS/CAPICertificate.cpp b/Swiften/TLS/CAPICertificate.cpp index 90398e9..29bb338 100644 --- a/Swiften/TLS/CAPICertificate.cpp +++ b/Swiften/TLS/CAPICertificate.cpp @@ -20,332 +20,332 @@ #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; \ + 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), - certStoreHandle_(0), - scardContext_(0), - cardHandle_(0), - certStore_(), - certName_(), - smartCardReaderName_(), - timerFactory_(timerFactory), - lastPollingResult_(true) { - assert(timerFactory_); - - setUri(capiUri); +CAPICertificate::CAPICertificate(const std::string& capiUri, TimerFactory* timerFactory) : + valid_(false), + uri_(capiUri), + certStoreHandle_(0), + scardContext_(0), + cardHandle_(0), + certStore_(), + certName_(), + smartCardReaderName_(), + timerFactory_(timerFactory), + lastPollingResult_(true) { + assert(timerFactory_); + + setUri(capiUri); } CAPICertificate::~CAPICertificate() { - if (smartCardTimer_) { - smartCardTimer_->stop(); - smartCardTimer_->onTick.disconnect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this)); - smartCardTimer_.reset(); - } - - if (certStoreHandle_) { - CertCloseStore(certStoreHandle_, 0); - } - - if (cardHandle_) { - LONG result = SCardDisconnect(cardHandle_, SCARD_LEAVE_CARD); - DEBUG_SCARD_STATUS("SCardDisconnect", result); - } - - if (scardContext_) { - LONG result = SCardReleaseContext(scardContext_); - DEBUG_SCARD_STATUS("SCardReleaseContext", result); - } + if (smartCardTimer_) { + smartCardTimer_->stop(); + smartCardTimer_->onTick.disconnect(boost::bind(&CAPICertificate::handleSmartCardTimerTick, this)); + smartCardTimer_.reset(); + } + + if (certStoreHandle_) { + CertCloseStore(certStoreHandle_, 0); + } + + if (cardHandle_) { + LONG result = SCardDisconnect(cardHandle_, SCARD_LEAVE_CARD); + DEBUG_SCARD_STATUS("SCardDisconnect", result); + } + + if (scardContext_) { + LONG result = SCardReleaseContext(scardContext_); + DEBUG_SCARD_STATUS("SCardReleaseContext", result); + } } bool CAPICertificate::isNull() const { - return uri_.empty() || !valid_; + return uri_.empty() || !valid_; } const std::string& CAPICertificate::getCertStoreName() const { - return certStore_; + return certStore_; } const std::string& CAPICertificate::getCertName() const { - return certName_; + return certName_; } const std::string& CAPICertificate::getSmartCardReaderName() const { - return smartCardReaderName_; + return smartCardReaderName_; } PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::string &certName) { - if (!boost::iequals(certName.substr(0, 5), "sha1:")) { + if (!boost::iequals(certName.substr(0, 5), "sha1:")) { - // Find client certificate. Note that this sample just searches for a - // certificate that contains the user name somewhere in the subject name. - return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /*dwFindFlags*/ 0, CERT_FIND_SUBJECT_STR_A, /* *pvFindPara*/certName.c_str(), /*pPrevCertContext*/ NULL); - } + // Find client certificate. Note that this sample just searches for a + // certificate that contains the user name somewhere in the subject name. + return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /*dwFindFlags*/ 0, CERT_FIND_SUBJECT_STR_A, /* *pvFindPara*/certName.c_str(), /*pPrevCertContext*/ NULL); + } - std::string hexstring = certName.substr(5); - ByteArray byteArray = Hexify::unhexify(hexstring); - CRYPT_HASH_BLOB HashBlob; + std::string hexstring = certName.substr(5); + ByteArray byteArray = Hexify::unhexify(hexstring); + CRYPT_HASH_BLOB HashBlob; - if (byteArray.size() != SHA1_HASH_LEN) { - return NULL; - } - HashBlob.cbData = SHA1_HASH_LEN; - HashBlob.pbData = static_cast<BYTE *>(vecptr(byteArray)); + if (byteArray.size() != SHA1_HASH_LEN) { + return NULL; + } + HashBlob.cbData = SHA1_HASH_LEN; + HashBlob.pbData = static_cast<BYTE *>(vecptr(byteArray)); - // Find client certificate. Note that this sample just searches for a - // certificate that contains the user name somewhere in the subject name. - return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /* dwFindFlags */ 0, CERT_FIND_HASH, &HashBlob, /* pPrevCertContext */ NULL); + // Find client certificate. Note that this sample just searches for a + // certificate that contains the user name somewhere in the subject name. + return CertFindCertificateInStore(certStoreHandle, X509_ASN_ENCODING, /* dwFindFlags */ 0, CERT_FIND_HASH, &HashBlob, /* pPrevCertContext */ NULL); } void CAPICertificate::setUri (const std::string& capiUri) { - valid_ = false; - - /* Syntax: "certstore:" <cert_store> ":" <hash> ":" <hash_of_cert> */ - - if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) { - return; - } - - /* Substring of subject: uses "storename" */ - std::string capiIdentity = capiUri.substr(10); - std::string newCertStoreName; - size_t pos = capiIdentity.find_first_of (':'); - - if (pos == std::string::npos) { - /* Using the default certificate store */ - newCertStoreName = "MY"; - certName_ = capiIdentity; - } - else { - newCertStoreName = capiIdentity.substr(0, pos); - certName_ = capiIdentity.substr(pos + 1); - } - - if (certStoreHandle_ != NULL) { - if (newCertStoreName != certStore_) { - CertCloseStore(certStoreHandle_, 0); - certStoreHandle_ = NULL; - } - } - - if (certStoreHandle_ == NULL) { - certStoreHandle_ = CertOpenSystemStore(0, newCertStoreName.c_str()); - if (!certStoreHandle_) { - return; - } - } - - certStore_ = newCertStoreName; - - PCCERT_CONTEXT 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); - return; - } - - pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len)); - if (!pinfo) { - CertFreeCertificateContext(certContext); - return; - } - - if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) { - CertFreeCertificateContext(certContext); - free(pinfo); - return; - } - - CertFreeCertificateContext(certContext); - - // 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)) { - DWORD error = GetLastError(); - 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 - } - } - - 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)); - smartCardTimer_->start(); - } - - valid_ = true; + valid_ = false; + + /* Syntax: "certstore:" <cert_store> ":" <hash> ":" <hash_of_cert> */ + + if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) { + return; + } + + /* Substring of subject: uses "storename" */ + std::string capiIdentity = capiUri.substr(10); + std::string newCertStoreName; + size_t pos = capiIdentity.find_first_of (':'); + + if (pos == std::string::npos) { + /* Using the default certificate store */ + newCertStoreName = "MY"; + certName_ = capiIdentity; + } + else { + newCertStoreName = capiIdentity.substr(0, pos); + certName_ = capiIdentity.substr(pos + 1); + } + + if (certStoreHandle_ != NULL) { + if (newCertStoreName != certStore_) { + CertCloseStore(certStoreHandle_, 0); + certStoreHandle_ = NULL; + } + } + + if (certStoreHandle_ == NULL) { + certStoreHandle_ = CertOpenSystemStore(0, newCertStoreName.c_str()); + if (!certStoreHandle_) { + return; + } + } + + certStore_ = newCertStoreName; + + PCCERT_CONTEXT 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); + return; + } + + pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len)); + if (!pinfo) { + CertFreeCertificateContext(certContext); + return; + } + + if (!CertGetCertificateContextProperty(certContext, CERT_KEY_PROV_INFO_PROP_ID, pinfo, &len)) { + CertFreeCertificateContext(certContext); + free(pinfo); + return; + } + + CertFreeCertificateContext(certContext); + + // 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)) { + DWORD error = GetLastError(); + 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 + } + } + + 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)); + smartCardTimer_->start(); + } + + valid_ = true; } 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) { - result = SCardConnect(hContext, pReader, shareMode, preferredProtocols, &hCardHandle, &dwAP); - DEBUG_SCARD_STATUS("SCardConnect", result); - if (SCARD_S_SUCCESS != result) { - hCardHandle = 0; - } - } - - char szReader[200]; - DWORD cch = sizeof(szReader); - BYTE bAttr[32]; - DWORD cByte = 32; - 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) { - result = SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); - DEBUG_SCARD_STATUS("SCardDisconnect", result); - } - else { - *newCardHandle = hCardHandle; - } + 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) { + result = SCardConnect(hContext, pReader, shareMode, preferredProtocols, &hCardHandle, &dwAP); + DEBUG_SCARD_STATUS("SCardConnect", result); + if (SCARD_S_SUCCESS != result) { + hCardHandle = 0; + } + } + + char szReader[200]; + DWORD cch = sizeof(szReader); + BYTE bAttr[32]; + DWORD cByte = 32; + 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) { + result = SCardDisconnect(hCardHandle, SCARD_LEAVE_CARD); + DEBUG_SCARD_STATUS("SCardDisconnect", result); + } + else { + *newCardHandle = hCardHandle; + } } bool CAPICertificate::checkIfSmartCardPresent () { - if (!smartCardReaderName_.empty()) { - DWORD dwState; - smartcard_check_status(scardContext_, smartCardReaderName_.c_str(), cardHandle_, &cardHandle_, &dwState); - - switch (dwState) { - case SCARD_ABSENT: - SWIFT_LOG(debug) << "Card absent." << std::endl; - break; - case SCARD_PRESENT: - SWIFT_LOG(debug) << "Card present." << std::endl; - break; - case SCARD_SWALLOWED: - SWIFT_LOG(debug) << "Card swallowed." << std::endl; - break; - case SCARD_POWERED: - SWIFT_LOG(debug) << "Card has power." << std::endl; - break; - case SCARD_NEGOTIABLE: - SWIFT_LOG(debug) << "Card reset and waiting PTS negotiation." << std::endl; - break; - case SCARD_SPECIFIC: - SWIFT_LOG(debug) << "Card has specific communication protocols set." << std::endl; - break; - default: - SWIFT_LOG(debug) << "Unknown or unexpected card state." << std::endl; - break; - } - - - - switch (dwState) { - case SCARD_ABSENT: - return false; - - case SCARD_PRESENT: - case SCARD_SWALLOWED: - case SCARD_POWERED: - case SCARD_NEGOTIABLE: - case SCARD_SPECIFIC: - return true; - - default: - return false; - } - } - else { - return false; - } + if (!smartCardReaderName_.empty()) { + DWORD dwState; + smartcard_check_status(scardContext_, smartCardReaderName_.c_str(), cardHandle_, &cardHandle_, &dwState); + + switch (dwState) { + case SCARD_ABSENT: + SWIFT_LOG(debug) << "Card absent." << std::endl; + break; + case SCARD_PRESENT: + SWIFT_LOG(debug) << "Card present." << std::endl; + break; + case SCARD_SWALLOWED: + SWIFT_LOG(debug) << "Card swallowed." << std::endl; + break; + case SCARD_POWERED: + SWIFT_LOG(debug) << "Card has power." << std::endl; + break; + case SCARD_NEGOTIABLE: + SWIFT_LOG(debug) << "Card reset and waiting PTS negotiation." << std::endl; + break; + case SCARD_SPECIFIC: + SWIFT_LOG(debug) << "Card has specific communication protocols set." << std::endl; + break; + default: + SWIFT_LOG(debug) << "Unknown or unexpected card state." << std::endl; + break; + } + + + + switch (dwState) { + case SCARD_ABSENT: + return false; + + case SCARD_PRESENT: + case SCARD_SWALLOWED: + case SCARD_POWERED: + case SCARD_NEGOTIABLE: + case SCARD_SPECIFIC: + return true; + + default: + return false; + } + } + else { + return false; + } } void CAPICertificate::handleSmartCardTimerTick() { - bool poll = checkIfSmartCardPresent(); - if (lastPollingResult_ && !poll) { - onCertificateCardRemoved(); - } - lastPollingResult_ = poll; - smartCardTimer_->start(); + bool poll = checkIfSmartCardPresent(); + if (lastPollingResult_ && !poll) { + onCertificateCardRemoved(); + } + lastPollingResult_ = poll; + smartCardTimer_->start(); } } |