diff options
-rw-r--r-- | Swift/QtUI/CAPICertificateSelector.cpp | 69 | ||||
-rw-r--r-- | Swiften/TLS/CAPICertificate.cpp | 57 |
2 files changed, 59 insertions, 67 deletions
diff --git a/Swift/QtUI/CAPICertificateSelector.cpp b/Swift/QtUI/CAPICertificateSelector.cpp index aa41d70..e7948ef 100644 --- a/Swift/QtUI/CAPICertificateSelector.cpp +++ b/Swift/QtUI/CAPICertificateSelector.cpp @@ -13,6 +13,7 @@ #include <WinCrypt.h> #include <cryptuiapi.h> +#include <Swiften/StringCodecs/Hexify.h> #include <boost/algorithm/string.hpp> namespace Swift { @@ -23,67 +24,23 @@ namespace Swift { #define exclude_columns CRYPTUI_SELECT_LOCATION_COLUMN \ |CRYPTUI_SELECT_INTENDEDUSE_COLUMN - +// Size of the SHA1 hash +#define SHA1_HASH_LEN 20 static std::string getCertUri(PCCERT_CONTEXT cert, const char * cert_store_name) { - DWORD required_size; - char * comma; - char * p_in; - char * p_out; - char * subject_name; - std::string ret = std::string("certstore:") + cert_store_name + ":"; - - required_size = CertNameToStrA(cert->dwCertEncodingType, - &cert->pCertInfo->Subject, - /* Discard attribute names: */ - CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, - NULL, - 0); - - subject_name = static_cast<char *>(malloc(required_size+1)); - - if (!CertNameToStrA(cert->dwCertEncodingType, - &cert->pCertInfo->Subject, - /* Discard attribute names: */ - CERT_SIMPLE_NAME_STR | CERT_NAME_STR_REVERSE_FLAG, - subject_name, - required_size)) { + DWORD cbHash = SHA1_HASH_LEN; + BYTE aHash[SHA1_HASH_LEN]; + std::string ret = std::string("certstore:") + cert_store_name + ":" + "sha1:"; + + if (CertGetCertificateContextProperty(cert, + CERT_HASH_PROP_ID, + aHash, + &cbHash) == FALSE ) { return ""; } - /* Now search for the "," (ignoring escapes) - and truncate the rest of the string */ - if (subject_name[0] == '"') { - for (comma = subject_name + 1; comma[0]; comma++) { - if (comma[0] == '"') { - comma++; - if (comma[0] != '"') { - break; - } - } - } - } else { - comma = strchr(subject_name, ','); - } - - if (comma != NULL) { - *comma = '\0'; - } - - /* We now need to unescape the returned RDN */ - if (subject_name[0] == '"') { - for (p_in = subject_name + 1, p_out = subject_name; p_in[0]; p_in++, p_out++) { - if (p_in[0] == '"') { - p_in++; - } - - p_out[0] = p_in[0]; - } - p_out[0] = '\0'; - } - - ret += subject_name; - free(subject_name); + ByteArray byteArray = createByteArray((char *)(&aHash[0])); + ret += Hexify::hexify(byteArray); return ret; } diff --git a/Swiften/TLS/CAPICertificate.cpp b/Swiften/TLS/CAPICertificate.cpp index 9a3bbc8..a6725c9 100644 --- a/Swiften/TLS/CAPICertificate.cpp +++ b/Swiften/TLS/CAPICertificate.cpp @@ -6,9 +6,13 @@ #pragma once #include <Swiften/TLS/CAPICertificate.h> +#include <Swiften/StringCodecs/Hexify.h> #include <boost/algorithm/string/predicate.hpp> +// Size of the SHA1 hash +#define SHA1_HASH_LEN 20 + namespace Swift { CAPICertificate::CAPICertificate(const std::string& capiUri) @@ -34,11 +38,51 @@ const std::string& CAPICertificate::getCertName() const { return certName_; } +static PCCERT_CONTEXT findCertificateInStore (HCERTSTORE certStoreHandle, const std::string &certName) { + PCCERT_CONTEXT pCertContext = NULL; + + 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. + pCertContext = CertFindCertificateInStore(certStoreHandle, + X509_ASN_ENCODING, + 0, // dwFindFlags + CERT_FIND_SUBJECT_STR_A, + certName.c_str(), // *pvFindPara + NULL ); // pPrevCertContext + return pCertContext; + } + + + 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)); + + // 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_HASH, + &HashBlob, + NULL ); // pPrevCertContext + + return pCertContext; +} + + void CAPICertificate::setUri (const std::string& capiUri) { valid_ = false; - /* Syntax: "certstore:" [<cert_store> ":"] <cert_id> */ + /* Syntax: "certstore:" <cert_store> ":" <hash> ":" <hash_of_cert> */ if (!boost::iequals(capiUri.substr(0, 10), "certstore:")) { return; @@ -77,16 +121,7 @@ void CAPICertificate::setUri (const std::string& capiUri) { 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 + pCertContext = findCertificateInStore (certStoreHandle_, certName_); if (!pCertContext) { return; |