summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/TLS')
-rw-r--r--Swiften/TLS/CAPICertificate.cpp151
-rw-r--r--Swiften/TLS/CAPICertificate.h176
-rw-r--r--Swiften/TLS/CertificateWithKey.h12
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContext.cpp11
-rw-r--r--Swiften/TLS/OpenSSL/OpenSSLContext.h2
-rw-r--r--Swiften/TLS/SConscript1
-rw-r--r--Swiften/TLS/Schannel/SchannelContext.cpp27
-rw-r--r--Swiften/TLS/Schannel/SchannelContext.h2
-rw-r--r--Swiften/TLS/TLSContext.h4
9 files changed, 184 insertions, 202 deletions
diff --git a/Swiften/TLS/CAPICertificate.cpp b/Swiften/TLS/CAPICertificate.cpp
new file mode 100644
index 0000000..9a3bbc8
--- /dev/null
+++ b/Swiften/TLS/CAPICertificate.cpp
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2012 Isode Limited, London, England.
+ * Licensed under the simplified BSD license.
+ * See Documentation/Licenses/BSD-simplified.txt for more information.
+ */
+#pragma once
+
+#include <Swiften/TLS/CAPICertificate.h>
+
+#include <boost/algorithm/string/predicate.hpp>
+
+
+namespace Swift {
+CAPICertificate::CAPICertificate(const std::string& capiUri)
+ : valid_(false), uri_(capiUri), certStoreHandle_(0), certStore_(), certName_() {
+ setUri(capiUri);
+}
+
+CAPICertificate::~CAPICertificate() {
+ if (certStoreHandle_) {
+ CertCloseStore(certStoreHandle_, 0);
+ }
+}
+
+bool CAPICertificate::isNull() const {
+ return uri_.empty() || !valid_;
+}
+
+const std::string& CAPICertificate::getCertStoreName() const {
+ return certStore_;
+}
+
+const std::string& CAPICertificate::getCertName() const {
+ return certName_;
+}
+
+void CAPICertificate::setUri (const std::string& capiUri) {
+
+ valid_ = false;
+
+ /* Syntax: "certstore:" [<cert_store> ":"] <cert_id> */
+
+ if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) {
+ return;
+ }
+
+ /* Substring of subject: uses "storename" */
+ std::string capi_identity = capiUri.substr(10);
+ std::string new_certStore_name;
+ size_t pos = capi_identity.find_first_of (':');
+
+ if (pos == std::string::npos) {
+ /* Using the default certificate store */
+ new_certStore_name = "MY";
+ certName_ = capi_identity;
+ }
+ else {
+ new_certStore_name = capi_identity.substr(0, pos);
+ certName_ = capi_identity.substr(pos + 1);
+ }
+
+ PCCERT_CONTEXT pCertContext = NULL;
+
+ if (certStoreHandle_ != NULL) {
+ if (new_certStore_name != certStore_) {
+ CertCloseStore(certStoreHandle_, 0);
+ certStoreHandle_ = NULL;
+ }
+ }
+
+ if (certStoreHandle_ == NULL) {
+ certStoreHandle_ = CertOpenSystemStore(0, certStore_.c_str());
+ if (!certStoreHandle_) {
+ return;
+ }
+ }
+
+ certStore_ = new_certStore_name;
+
+ /* NB: This might have to change, depending on how we locate certificates */
+
+ // Find client certificate. Note that this sample just searches for a
+ // certificate that contains the user name somewhere in the subject name.
+ pCertContext = CertFindCertificateInStore(certStoreHandle_,
+ X509_ASN_ENCODING,
+ 0, // dwFindFlags
+ CERT_FIND_SUBJECT_STR_A,
+ certName_.c_str(), // *pvFindPara
+ NULL ); // pPrevCertContext
+
+ if (!pCertContext) {
+ 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(pCertContext,
+ CERT_KEY_PROV_INFO_PROP_ID,
+ NULL,
+ &len)) {
+ CertFreeCertificateContext(pCertContext);
+ return;
+ }
+
+ pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len));
+ if (!pinfo) {
+ CertFreeCertificateContext(pCertContext);
+ return;
+ }
+
+ if (!CertGetCertificateContextProperty(pCertContext,
+ CERT_KEY_PROV_INFO_PROP_ID,
+ pinfo,
+ &len)) {
+ CertFreeCertificateContext(pCertContext);
+ free(pinfo);
+ return;
+ }
+
+ CertFreeCertificateContext(pCertContext);
+
+ // Now verify if we have access to the private key
+ if (!CryptAcquireContextW(&hprov,
+ pinfo->pwszContainerName,
+ pinfo->pwszProvName,
+ pinfo->dwProvType,
+ 0)) {
+ free(pinfo);
+ return;
+ }
+
+ if (!CryptGetUserKey(hprov, pinfo->dwKeySpec, &key)) {
+ CryptReleaseContext(hprov, 0);
+ free(pinfo);
+ return;
+ }
+
+ CryptDestroyKey(key);
+ CryptReleaseContext(hprov, 0);
+ free(pinfo);
+
+ valid_ = true;
+}
+
+}
diff --git a/Swiften/TLS/CAPICertificate.h b/Swiften/TLS/CAPICertificate.h
index fcdb4c2..d9e2704 100644
--- a/Swiften/TLS/CAPICertificate.h
+++ b/Swiften/TLS/CAPICertificate.h
@@ -9,188 +9,34 @@
#include <Swiften/Base/SafeByteArray.h>
#include <Swiften/TLS/CertificateWithKey.h>
-#include <boost/algorithm/string/predicate.hpp>
-
#define SECURITY_WIN32
+#include <Windows.h>
#include <WinCrypt.h>
namespace Swift {
class CAPICertificate : public Swift::CertificateWithKey {
public:
- CAPICertificate(const std::string& capiUri)
- : valid_(false), uri_(capiUri), cert_store_handle_(0), cert_store_(NULL), cert_name_(NULL) {
- setUri(capiUri);
- }
-
- virtual ~CAPICertificate() {
- if (cert_store_handle_ != NULL)
- {
- CertCloseStore(cert_store_handle_, 0);
- }
- }
-
- virtual bool isNull() const {
- return uri_.empty() || !valid_;
- }
-
- virtual bool isPrivateKeyExportable() const {
- /* We can check with CAPI, but for now the answer is "no" */
- return false;
- }
-
- virtual const std::string& getCertStoreName() const {
- return cert_store_;
- }
-
- virtual const std::string& getCertName() const {
- return cert_name_;
- }
-
- const ByteArray& getData() const {
-////Might need to throw an exception here, or really generate PKCS12 blob from CAPI data?
- assert(0);
- }
-
- void setData(const ByteArray& data) {
- assert(0);
- }
-
- const SafeByteArray& getPassword() const {
-/////Can't pass NULL to createSafeByteArray!
-/////Should this throw an exception instead?
- return createSafeByteArray("");
- }
-
- protected:
- void setUri (const std::string& capiUri) {
-
- valid_ = false;
-
- /* Syntax: "certstore:" [<cert_store> ":"] <cert_id> */
-
- if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) {
- return;
- }
-
- /* Substring of subject: uses "storename" */
- std::string capi_identity = capiUri.substr(10);
- std::string new_cert_store_name;
- size_t pos = capi_identity.find_first_of (':');
-
- if (pos == std::string::npos) {
- /* Using the default certificate store */
- new_cert_store_name = "MY";
- cert_name_ = capi_identity;
- } else {
- new_cert_store_name = capi_identity.substr(0, pos);
- cert_name_ = capi_identity.substr(pos + 1);
- }
+ CAPICertificate(const std::string& capiUri);
- PCCERT_CONTEXT pCertContext = NULL;
+ virtual ~CAPICertificate();
- if (cert_store_handle_ != NULL)
- {
- if (new_cert_store_name != cert_store_) {
- CertCloseStore(cert_store_handle_, 0);
- cert_store_handle_ = NULL;
- }
- }
+ virtual bool isNull() const;
- if (cert_store_handle_ == NULL)
- {
- cert_store_handle_ = CertOpenSystemStore(0, cert_store_.c_str());
- if (!cert_store_handle_)
- {
- return;
- }
- }
+ const std::string& getCertStoreName() const;
- cert_store_ = new_cert_store_name;
+ const std::string& getCertName() const;
- /* NB: This might have to change, depending on how we locate certificates */
-
- // Find client certificate. Note that this sample just searches for a
- // certificate that contains the user name somewhere in the subject name.
- pCertContext = CertFindCertificateInStore(cert_store_handle_,
- X509_ASN_ENCODING,
- 0, // dwFindFlags
- CERT_FIND_SUBJECT_STR_A,
- cert_name_.c_str(), // *pvFindPara
- NULL ); // pPrevCertContext
-
- if (pCertContext == NULL)
- {
- 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(pCertContext,
- CERT_KEY_PROV_INFO_PROP_ID,
- NULL,
- &len))
- {
- CertFreeCertificateContext(pCertContext);
- return;
- }
-
- pinfo = static_cast<CRYPT_KEY_PROV_INFO *>(malloc(len));
- if (!pinfo) {
- CertFreeCertificateContext(pCertContext);
- return;
- }
-
- if (!CertGetCertificateContextProperty(pCertContext,
- CERT_KEY_PROV_INFO_PROP_ID,
- pinfo,
- &len))
- {
- CertFreeCertificateContext(pCertContext);
- free(pinfo);
- return;
- }
-
- CertFreeCertificateContext(pCertContext);
-
- // Now verify if we have access to the private key
- if (!CryptAcquireContextW(&hprov,
- pinfo->pwszContainerName,
- pinfo->pwszProvName,
- pinfo->dwProvType,
- 0))
- {
- free(pinfo);
- return;
- }
-
- if (!CryptGetUserKey(hprov, pinfo->dwKeySpec, &key))
- {
- CryptReleaseContext(hprov, 0);
- free(pinfo);
- return;
- }
-
- CryptDestroyKey(key);
- CryptReleaseContext(hprov, 0);
- free(pinfo);
-
- valid_ = true;
- }
+ private:
+ void setUri (const std::string& capiUri);
private:
bool valid_;
std::string uri_;
- HCERTSTORE cert_store_handle_;
+ HCERTSTORE certStoreHandle_;
/* Parsed components of the uri_ */
- std::string cert_store_;
- std::string cert_name_;
+ std::string certStore_;
+ std::string certName_;
};
}
diff --git a/Swiften/TLS/CertificateWithKey.h b/Swiften/TLS/CertificateWithKey.h
index 6f6ea39..1bdeb03 100644
--- a/Swiften/TLS/CertificateWithKey.h
+++ b/Swiften/TLS/CertificateWithKey.h
@@ -11,22 +11,12 @@
namespace Swift {
class CertificateWithKey {
public:
+ typedef boost::shared_ptr<CertificateWithKey> ref;
CertificateWithKey() {}
virtual ~CertificateWithKey() {}
virtual bool isNull() const = 0;
- virtual bool isPrivateKeyExportable() const = 0;
-
- virtual const std::string& getCertStoreName() const = 0;
-
- virtual const std::string& getCertName() const = 0;
-
- virtual const ByteArray& getData() const = 0;
-
- virtual void setData(const ByteArray& data) = 0;
-
- virtual const SafeByteArray& getPassword() const = 0;
};
}
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
index dd3462f..8076967 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.cpp
@@ -186,17 +186,14 @@ void OpenSSLContext::sendPendingDataToApplication() {
}
bool OpenSSLContext::setClientCertificate(CertificateWithKey * certificate) {
- if (!certificate || certificate->isNull()) {
- return false;
- }
-
- if (!certificate->isPrivateKeyExportable()) {
+ boost::shared_ptr<PKCS12Certificate> pkcs12Certificate = boost::dynamic_pointer_cast<PKCS12Certificate>(certificate);
+ if (!pkcs12Certificate || pkcs12Certificate->isNull()) {
return false;
}
// Create a PKCS12 structure
BIO* bio = BIO_new(BIO_s_mem());
- BIO_write(bio, vecptr(certificate->getData()), certificate->getData().size());
+ BIO_write(bio, vecptr(certificate->getData()), pkcs12Certificate->getData().size());
boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free);
BIO_free(bio);
if (!pkcs12) {
@@ -207,7 +204,7 @@ bool OpenSSLContext::setClientCertificate(CertificateWithKey * certificate) {
X509 *certPtr = 0;
EVP_PKEY* privateKeyPtr = 0;
STACK_OF(X509)* caCertsPtr = 0;
- int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(certificate->getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr);
+ int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(pkcs12Certificate->getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr);
if (result != 1) {
return false;
}
diff --git a/Swiften/TLS/OpenSSL/OpenSSLContext.h b/Swiften/TLS/OpenSSL/OpenSSLContext.h
index b53e715..e98fb49 100644
--- a/Swiften/TLS/OpenSSL/OpenSSLContext.h
+++ b/Swiften/TLS/OpenSSL/OpenSSLContext.h
@@ -22,7 +22,7 @@ namespace Swift {
~OpenSSLContext();
void connect();
- bool setClientCertificate(CertificateWithKey * cert);
+ bool setClientCertificate(CertificateWithKey::ref cert);
void handleDataFromNetwork(const SafeByteArray&);
void handleDataFromApplication(const SafeByteArray&);
diff --git a/Swiften/TLS/SConscript b/Swiften/TLS/SConscript
index a71a446..0e95b8b 100644
--- a/Swiften/TLS/SConscript
+++ b/Swiften/TLS/SConscript
@@ -20,6 +20,7 @@ if myenv.get("HAVE_OPENSSL", 0) :
myenv.Append(CPPDEFINES = "HAVE_OPENSSL")
elif myenv.get("HAVE_SCHANNEL", 0) :
objects += myenv.StaticObject([
+ "CAPICertificate.cpp",
"Schannel/SchannelContext.cpp",
"Schannel/SchannelCertificate.cpp",
"Schannel/SchannelContextFactory.cpp",
diff --git a/Swiften/TLS/Schannel/SchannelContext.cpp b/Swiften/TLS/Schannel/SchannelContext.cpp
index 6f50b3a..ddbebcb 100644
--- a/Swiften/TLS/Schannel/SchannelContext.cpp
+++ b/Swiften/TLS/Schannel/SchannelContext.cpp
@@ -4,8 +4,9 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
-#include "Swiften/TLS/Schannel/SchannelContext.h"
-#include "Swiften/TLS/Schannel/SchannelCertificate.h"
+#include <Swiften/TLS/Schannel/SchannelContext.h>
+#include <Swiften/TLS/Schannel/SchannelCertificate.h>
+#include <Swiften/TLS/CAPICertificate.h>
namespace Swift {
@@ -17,7 +18,7 @@ SchannelContext::SchannelContext()
, m_verificationError(CertificateVerificationError::UnknownError)
, m_my_cert_store(NULL)
, m_cert_store_name("MY")
-, m_cert_name(NULL)
+, m_cert_name()
{
m_ctxtFlags = ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_CONFIDENTIALITY |
@@ -517,22 +518,18 @@ void SchannelContext::encryptAndSendData(const SafeByteArray& data)
//------------------------------------------------------------------------
-bool SchannelContext::setClientCertificate(CertificateWithKey * certificate)
+bool SchannelContext::setClientCertificate(CertificateWithKey::ref certificate)
{
- if (!certificate || certificate->isNull()) {
+ boost::shared_ptr<CAPICertificate> capiCertificate = boost::dynamic_pointer_cast<CAPICertificate>(certificate);
+ if (!capiCertificate || capiCertificate->isNull()) {
return false;
}
- if (!certificate->isPrivateKeyExportable()) {
- // We assume that the Certificate Store Name/Certificate Name
- // are valid at this point
- m_cert_store_name = certificate->getCertStoreName();
- m_cert_name = certificate->getCertName();
-
- return true;
- }
-
- return false;
+ // We assume that the Certificate Store Name/Certificate Name
+ // are valid at this point
+ m_cert_store_name = capiCertificate->getCertStoreName();
+ m_cert_name = capiCertificate->getCertName();
+ return true;
}
//------------------------------------------------------------------------
diff --git a/Swiften/TLS/Schannel/SchannelContext.h b/Swiften/TLS/Schannel/SchannelContext.h
index 0cdb3d7..7726c41 100644
--- a/Swiften/TLS/Schannel/SchannelContext.h
+++ b/Swiften/TLS/Schannel/SchannelContext.h
@@ -37,7 +37,7 @@ namespace Swift
// TLSContext
//
virtual void connect();
- virtual bool setClientCertificate(CertificateWithKey * cert);
+ virtual bool setClientCertificate(CertificateWithKey::ref cert);
virtual void handleDataFromNetwork(const SafeByteArray& data);
virtual void handleDataFromApplication(const SafeByteArray& data);
diff --git a/Swiften/TLS/TLSContext.h b/Swiften/TLS/TLSContext.h
index ada813a..9dee902 100644
--- a/Swiften/TLS/TLSContext.h
+++ b/Swiften/TLS/TLSContext.h
@@ -11,10 +11,10 @@
#include <Swiften/Base/SafeByteArray.h>
#include <Swiften/TLS/Certificate.h>
+#include <Swiften/TLS/CertificateWithKey.h>
#include <Swiften/TLS/CertificateVerificationError.h>
namespace Swift {
- class CertificateWithKey;
class TLSContext {
public:
@@ -22,7 +22,7 @@ namespace Swift {
virtual void connect() = 0;
- virtual bool setClientCertificate(CertificateWithKey * cert) = 0;
+ virtual bool setClientCertificate(CertificateWithKey::ref cert) = 0;
virtual void handleDataFromNetwork(const SafeByteArray&) = 0;
virtual void handleDataFromApplication(const SafeByteArray&) = 0;