diff options
Diffstat (limited to 'xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx')
-rw-r--r-- | xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx | 92 |
1 files changed, 85 insertions, 7 deletions
diff --git a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx index a705f3844030..c1e6573cf716 100644 --- a/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx +++ b/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx @@ -32,6 +32,7 @@ #include "oid.hxx" #include <rtl/locale.h> +#include <rtl/ustrbuf.hxx> #include <osl/nlsupport.h> #include <osl/process.h> #include <o3tl/char16_t2wchar_t.hxx> @@ -677,6 +678,67 @@ Sequence<OUString> SAL_CALL X509Certificate_MSCryptImpl::getSupportedServiceName namespace xmlsecurity { +// based on some guesswork and: +// https://datatracker.ietf.org/doc/html/rfc1485 +// https://docs.microsoft.com/en-us/windows/win32/api/wincrypt/nf-wincrypt-certnametostra#CERT_X500_NAME_STR +// the main problem appears to be that in values NSS uses \ escapes but CryptoAPI requires " quotes around value +static OUString CompatDNNSS(OUString const& rDN) +{ + OUStringBuffer buf(rDN.getLength()); + enum { DEFAULT, INVALUE, INQUOTE } state(DEFAULT); + for (sal_Int32 i = 0; i < rDN.getLength(); ++i) + { + if (state == DEFAULT) + { + buf.append(rDN[i]); + if (rDN[i] == '=') + { + if (rDN.getLength() == i+1) + { + break; // invalid? + } + else + { + buf.append('"'); + state = INVALUE; + } + } + } + else if (state == INVALUE) + { + if (rDN[i] == '+' || rDN[i] == ',' || rDN[i] == ';') + { + buf.append('"'); + buf.append(rDN[i]); + state = DEFAULT; + } + else if (rDN[i] == '\\') + { + if (rDN.getLength() == i+1) + { + break; // invalid? + } + if (rDN[i+1] == '"') + { + buf.append('"'); + } + buf.append(rDN[i+1]); + ++i; + } + else + { + buf.append(rDN[i]); + } + if (i+1 == rDN.getLength()) + { + buf.append('"'); + state = DEFAULT; + } + } + } + return buf.makeStringAndClear(); +} + static bool EncodeDistinguishedName(OUString const& rName, CERT_NAME_BLOB & rBlob) { LPCWSTR pszError; @@ -699,22 +761,38 @@ static bool EncodeDistinguishedName(OUString const& rName, CERT_NAME_BLOB & rBlo } bool EqualDistinguishedNames( - OUString const& rName1, OUString const& rName2) + OUString const& rName1, OUString const& rName2, + EqualMode const eMode) { + if (eMode == COMPAT_BOTH && !rName1.isEmpty() && rName1 == rName2) + { // handle case where both need to be converted + return true; + } CERT_NAME_BLOB blob1; if (!EncodeDistinguishedName(rName1, blob1)) { return false; } CERT_NAME_BLOB blob2; - if (!EncodeDistinguishedName(rName2, blob2)) + bool ret(false); + if (!!EncodeDistinguishedName(rName2, blob2)) { - delete[] blob1.pbData; - return false; + ret = CertCompareCertificateName(X509_ASN_ENCODING, + &blob1, &blob2) == TRUE; + delete[] blob2.pbData; + } + if (!ret && eMode == COMPAT_2ND) + { + CERT_NAME_BLOB blob2compat; + if (!EncodeDistinguishedName(CompatDNNSS(rName2), blob2compat)) + { + delete[] blob1.pbData; + return false; + } + ret = CertCompareCertificateName(X509_ASN_ENCODING, + &blob1, &blob2compat) == TRUE; + delete[] blob2compat.pbData; } - bool const ret(CertCompareCertificateName(X509_ASN_ENCODING, - &blob1, &blob2) == TRUE); - delete[] blob2.pbData; delete[] blob1.pbData; return ret; } |