summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Swift/QtUI/CAPICertificateSelector.cpp69
-rw-r--r--Swiften/TLS/CAPICertificate.cpp57
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;