summaryrefslogtreecommitdiffstats
path: root/xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx
diff options
context:
space:
mode:
Diffstat (limited to 'xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx')
-rw-r--r--xmlsecurity/source/xmlsec/mscrypt/x509certificate_mscryptimpl.cxx92
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;
}