summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften/TLS/Schannel/SchannelCertificate.cpp')
-rw-r--r--Swiften/TLS/Schannel/SchannelCertificate.cpp290
1 files changed, 148 insertions, 142 deletions
diff --git a/Swiften/TLS/Schannel/SchannelCertificate.cpp b/Swiften/TLS/Schannel/SchannelCertificate.cpp
index 8aaec00..23c2479 100644
--- a/Swiften/TLS/Schannel/SchannelCertificate.cpp
+++ b/Swiften/TLS/Schannel/SchannelCertificate.cpp
@@ -4,6 +4,12 @@
* See Documentation/Licenses/BSD-simplified.txt for more information.
*/
+/*
+ * Copyright (c) 2016 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
+ */
+
#include "Swiften/TLS/Schannel/SchannelCertificate.h"
#include "Swiften/Base/ByteArray.h"
@@ -20,176 +26,176 @@ namespace Swift {
//------------------------------------------------------------------------
-SchannelCertificate::SchannelCertificate(const ScopedCertContext& certCtxt)
-: m_cert(certCtxt)
+SchannelCertificate::SchannelCertificate(const ScopedCertContext& certCtxt)
+: m_cert(certCtxt)
{
- parse();
+ parse();
}
//------------------------------------------------------------------------
SchannelCertificate::SchannelCertificate(const ByteArray& der)
{
- if (!der.empty())
- {
- // Convert the DER encoded certificate to a PCERT_CONTEXT
- CERT_BLOB certBlob = {0};
- certBlob.cbData = der.size();
- certBlob.pbData = (BYTE*)&der[0];
-
- if (!CryptQueryObject(
- CERT_QUERY_OBJECT_BLOB,
- &certBlob,
- CERT_QUERY_CONTENT_FLAG_CERT,
- CERT_QUERY_FORMAT_FLAG_ALL,
- 0,
- NULL,
- NULL,
- NULL,
- NULL,
- NULL,
- (const void**)m_cert.Reset()))
- {
- // TODO: Because Swiften isn't exception safe, we have no way to indicate failure
- }
- }
+ if (!der.empty())
+ {
+ // Convert the DER encoded certificate to a PCERT_CONTEXT
+ CERT_BLOB certBlob = {0};
+ certBlob.cbData = der.size();
+ certBlob.pbData = (BYTE*)&der[0];
+
+ if (!CryptQueryObject(
+ CERT_QUERY_OBJECT_BLOB,
+ &certBlob,
+ CERT_QUERY_CONTENT_FLAG_CERT,
+ CERT_QUERY_FORMAT_FLAG_ALL,
+ 0,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ (const void**)m_cert.Reset()))
+ {
+ // TODO: Because Swiften isn't exception safe, we have no way to indicate failure
+ }
+ }
}
//------------------------------------------------------------------------
-ByteArray SchannelCertificate::toDER() const
+ByteArray SchannelCertificate::toDER() const
{
- ByteArray result;
+ ByteArray result;
+
+ // Serialize the certificate. The CERT_CONTEXT is already DER encoded.
+ result.resize(m_cert->cbCertEncoded);
+ memcpy(&result[0], m_cert->pbCertEncoded, result.size());
- // Serialize the certificate. The CERT_CONTEXT is already DER encoded.
- result.resize(m_cert->cbCertEncoded);
- memcpy(&result[0], m_cert->pbCertEncoded, result.size());
-
- return result;
+ return result;
}
//------------------------------------------------------------------------
std::string SchannelCertificate::wstrToStr(const std::wstring& wstr)
{
- if (wstr.empty())
- return "";
+ if (wstr.empty())
+ return "";
- // First request the size of the required UTF-8 buffer
- int numRequiredBytes = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
- if (!numRequiredBytes)
- return "";
+ // First request the size of the required UTF-8 buffer
+ int numRequiredBytes = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), NULL, 0, NULL, NULL);
+ if (!numRequiredBytes)
+ return "";
- // Allocate memory for the UTF-8 string
- std::vector<char> utf8Str(numRequiredBytes);
+ // Allocate memory for the UTF-8 string
+ std::vector<char> utf8Str(numRequiredBytes);
- int numConverted = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), &utf8Str[0], numRequiredBytes, NULL, NULL);
- if (!numConverted)
- return "";
+ int numConverted = WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), wstr.size(), &utf8Str[0], numRequiredBytes, NULL, NULL);
+ if (!numConverted)
+ return "";
- std::string str(&utf8Str[0], numConverted);
- return str;
+ std::string str(&utf8Str[0], numConverted);
+ return str;
}
//------------------------------------------------------------------------
-void SchannelCertificate::parse()
+void SchannelCertificate::parse()
{
- //
- // Subject name
- //
- DWORD requiredSize = CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, NULL, 0);
- if (requiredSize > 1)
- {
- vector<char> rawSubjectName(requiredSize);
- CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, &rawSubjectName[0], rawSubjectName.size());
- m_subjectName = std::string(&rawSubjectName[0]);
- }
-
- //
- // Common name
- //
- // Note: We only pull out one common name from the cert.
- requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0);
- if (requiredSize > 1)
- {
- vector<char> rawCommonName(requiredSize);
- requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, &rawCommonName[0], rawCommonName.size());
- m_commonNames.push_back( std::string(&rawCommonName[0]) );
- }
-
- //
- // Subject alternative names
- //
- PCERT_EXTENSION pExtensions = CertFindExtension(szOID_SUBJECT_ALT_NAME2, m_cert->pCertInfo->cExtension, m_cert->pCertInfo->rgExtension);
- if (pExtensions)
- {
- CRYPT_DECODE_PARA decodePara = {0};
- decodePara.cbSize = sizeof(decodePara);
-
- CERT_ALT_NAME_INFO* pAltNameInfo = NULL;
- DWORD altNameInfoSize = 0;
-
- BOOL status = CryptDecodeObjectEx(
- X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
- szOID_SUBJECT_ALT_NAME2,
- pExtensions->Value.pbData,
- pExtensions->Value.cbData,
- CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
- &decodePara,
- &pAltNameInfo,
- &altNameInfoSize);
-
- if (status && pAltNameInfo)
- {
- for (int i = 0; i < pAltNameInfo->cAltEntry; i++)
- {
- if (pAltNameInfo->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME)
- addDNSName( wstrToStr( pAltNameInfo->rgAltEntry[i].pwszDNSName ) );
- }
- }
- }
-
- // if (pExtensions)
- // {
- // vector<wchar_t> subjectAlt
- // CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_SUBJECT_ALT_NAME, pExtensions->Value->pbData, pExtensions->Value->cbData, )
- // }
- //
- // // subjectAltNames
- // int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1);
- // if(subjectAltNameLoc != -1) {
- // X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc);
- // boost::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free);
- // boost::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free);
- // boost::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free);
- // for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) {
- // GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i);
- // if (generalName->type == GEN_OTHERNAME) {
- // OTHERNAME* otherName = generalName->d.otherName;
- // if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) {
- // // XmppAddr
- // if (otherName->value->type != V_ASN1_UTF8STRING) {
- // continue;
- // }
- // ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string;
- // addXMPPAddress(ByteArray(ASN1_STRING_data(xmppAddrValue), ASN1_STRING_length(xmppAddrValue)).toString());
- // }
- // else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) {
- // // SRVName
- // if (otherName->value->type != V_ASN1_IA5STRING) {
- // continue;
- // }
- // ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string;
- // addSRVName(ByteArray(ASN1_STRING_data(srvNameValue), ASN1_STRING_length(srvNameValue)).toString());
- // }
- // }
- // else if (generalName->type == GEN_DNS) {
- // // DNSName
- // addDNSName(ByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)).toString());
- // }
- // }
- // }
+ //
+ // Subject name
+ //
+ DWORD requiredSize = CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, NULL, 0);
+ if (requiredSize > 1)
+ {
+ vector<char> rawSubjectName(requiredSize);
+ CertNameToStr(X509_ASN_ENCODING, &m_cert->pCertInfo->Subject, CERT_OID_NAME_STR, &rawSubjectName[0], rawSubjectName.size());
+ m_subjectName = std::string(&rawSubjectName[0]);
+ }
+
+ //
+ // Common name
+ //
+ // Note: We only pull out one common name from the cert.
+ requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, NULL, 0);
+ if (requiredSize > 1)
+ {
+ vector<char> rawCommonName(requiredSize);
+ requiredSize = CertGetNameString(m_cert, CERT_NAME_ATTR_TYPE, 0, szOID_COMMON_NAME, &rawCommonName[0], rawCommonName.size());
+ m_commonNames.push_back( std::string(&rawCommonName[0]) );
+ }
+
+ //
+ // Subject alternative names
+ //
+ PCERT_EXTENSION pExtensions = CertFindExtension(szOID_SUBJECT_ALT_NAME2, m_cert->pCertInfo->cExtension, m_cert->pCertInfo->rgExtension);
+ if (pExtensions)
+ {
+ CRYPT_DECODE_PARA decodePara = {0};
+ decodePara.cbSize = sizeof(decodePara);
+
+ CERT_ALT_NAME_INFO* pAltNameInfo = NULL;
+ DWORD altNameInfoSize = 0;
+
+ BOOL status = CryptDecodeObjectEx(
+ X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ szOID_SUBJECT_ALT_NAME2,
+ pExtensions->Value.pbData,
+ pExtensions->Value.cbData,
+ CRYPT_DECODE_ALLOC_FLAG | CRYPT_DECODE_NOCOPY_FLAG,
+ &decodePara,
+ &pAltNameInfo,
+ &altNameInfoSize);
+
+ if (status && pAltNameInfo)
+ {
+ for (int i = 0; i < pAltNameInfo->cAltEntry; i++)
+ {
+ if (pAltNameInfo->rgAltEntry[i].dwAltNameChoice == CERT_ALT_NAME_DNS_NAME)
+ addDNSName( wstrToStr( pAltNameInfo->rgAltEntry[i].pwszDNSName ) );
+ }
+ }
+ }
+
+ // if (pExtensions)
+ // {
+ // vector<wchar_t> subjectAlt
+ // CryptDecodeObject(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, szOID_SUBJECT_ALT_NAME, pExtensions->Value->pbData, pExtensions->Value->cbData, )
+ // }
+ //
+ // // subjectAltNames
+ // int subjectAltNameLoc = X509_get_ext_by_NID(cert.get(), NID_subject_alt_name, -1);
+ // if(subjectAltNameLoc != -1) {
+ // X509_EXTENSION* extension = X509_get_ext(cert.get(), subjectAltNameLoc);
+ // std::shared_ptr<GENERAL_NAMES> generalNames(reinterpret_cast<GENERAL_NAMES*>(X509V3_EXT_d2i(extension)), GENERAL_NAMES_free);
+ // std::shared_ptr<ASN1_OBJECT> xmppAddrObject(OBJ_txt2obj(ID_ON_XMPPADDR_OID, 1), ASN1_OBJECT_free);
+ // std::shared_ptr<ASN1_OBJECT> dnsSRVObject(OBJ_txt2obj(ID_ON_DNSSRV_OID, 1), ASN1_OBJECT_free);
+ // for (int i = 0; i < sk_GENERAL_NAME_num(generalNames.get()); ++i) {
+ // GENERAL_NAME* generalName = sk_GENERAL_NAME_value(generalNames.get(), i);
+ // if (generalName->type == GEN_OTHERNAME) {
+ // OTHERNAME* otherName = generalName->d.otherName;
+ // if (OBJ_cmp(otherName->type_id, xmppAddrObject.get()) == 0) {
+ // // XmppAddr
+ // if (otherName->value->type != V_ASN1_UTF8STRING) {
+ // continue;
+ // }
+ // ASN1_UTF8STRING* xmppAddrValue = otherName->value->value.utf8string;
+ // addXMPPAddress(ByteArray(ASN1_STRING_data(xmppAddrValue), ASN1_STRING_length(xmppAddrValue)).toString());
+ // }
+ // else if (OBJ_cmp(otherName->type_id, dnsSRVObject.get()) == 0) {
+ // // SRVName
+ // if (otherName->value->type != V_ASN1_IA5STRING) {
+ // continue;
+ // }
+ // ASN1_IA5STRING* srvNameValue = otherName->value->value.ia5string;
+ // addSRVName(ByteArray(ASN1_STRING_data(srvNameValue), ASN1_STRING_length(srvNameValue)).toString());
+ // }
+ // }
+ // else if (generalName->type == GEN_DNS) {
+ // // DNSName
+ // addDNSName(ByteArray(ASN1_STRING_data(generalName->d.dNSName), ASN1_STRING_length(generalName->d.dNSName)).toString());
+ // }
+ // }
+ // }
}
//------------------------------------------------------------------------