diff options
Diffstat (limited to 'xmlsecurity/source/helper/xmlsignaturehelper.cxx')
-rw-r--r-- | xmlsecurity/source/helper/xmlsignaturehelper.cxx | 68 |
1 files changed, 67 insertions, 1 deletions
diff --git a/xmlsecurity/source/helper/xmlsignaturehelper.cxx b/xmlsecurity/source/helper/xmlsignaturehelper.cxx index 0b5825b125..3b13f79f33 100644 --- a/xmlsecurity/source/helper/xmlsignaturehelper.cxx +++ b/xmlsecurity/source/helper/xmlsignaturehelper.cxx @@ -22,6 +22,7 @@ #include <documentsignaturehelper.hxx> #include <xsecctl.hxx> #include <biginteger.hxx> +#include <certificate.hxx> #include <UriBindingHelper.hxx> @@ -702,7 +703,72 @@ XMLSignatureHelper::CheckAndUpdateSignatureInformation( } if (CheckX509Data(xSecEnv, temp, certs, tempResult)) { - datas.emplace_back(tempResult); + if (rInfo.maEncapsulatedX509Certificates.empty()) // optional, XAdES + { + datas.emplace_back(tempResult); + } + else + { + // check for consistency between X509Data and EncapsulatedX509Certificate + // (LO produces just the signing certificate in X509Data and + // the entire chain in EncapsulatedX509Certificate so in this case + // using EncapsulatedX509Certificate yields additional intermediate + // certificates that may help in verifying) + std::vector<SignatureInformation::X509CertInfo> encapsulatedCertInfos; + for (OUString const& it : rInfo.maEncapsulatedX509Certificates) + { + encapsulatedCertInfos.emplace_back(); + encapsulatedCertInfos.back().X509Certificate = it; + } + std::vector<uno::Reference<security::XCertificate>> encapsulatedCerts; + SignatureInformation::X509Data encapsulatedResult; + if (CheckX509Data(xSecEnv, encapsulatedCertInfos, encapsulatedCerts, encapsulatedResult)) + { + auto const pXCertificate(dynamic_cast<xmlsecurity::Certificate*>(certs.back().get())); + auto const pECertificate(dynamic_cast<xmlsecurity::Certificate*>(encapsulatedCerts.back().get())); + assert(pXCertificate && pECertificate); // was just created by CheckX509Data + if (pXCertificate->getSHA256Thumbprint() == pECertificate->getSHA256Thumbprint()) + { + // both are chains - take the longer one + if (encapsulatedCerts.size() < certs.size()) + { + datas.emplace_back(tempResult); + } + else + { +#if 0 + // extra info needed in testSigningMultipleTimes_ODT + // ... but with it, it fails with BROKEN signature? + // fails even on the first signature, because somehow + // the xd:SigningCertificate element was signed + // containing only one certificate, but in the final + // file it contains all 3 certificates due to this here. + for (size_t i = 0; i < encapsulatedResult.size(); ++i) + { + encapsulatedResult[i].X509IssuerName = encapsulatedCerts[i]->getIssuerName(); + encapsulatedResult[i].X509SerialNumber = xmlsecurity::bigIntegerToNumericString(encapsulatedCerts[i]->getSerialNumber()); + encapsulatedResult[i].X509Subject = encapsulatedCerts[i]->getSubjectName(); + auto const pCertificate(dynamic_cast<xmlsecurity::Certificate*>(encapsulatedCerts[i].get())); + assert(pCertificate); // this was just created by CheckX509Data + OUStringBuffer aBuffer; + comphelper::Base64::encode(aBuffer, pCertificate->getSHA256Thumbprint()); + encapsulatedResult[i].CertDigest = aBuffer.makeStringAndClear(); + } + datas.emplace_back(encapsulatedResult); +#else + // keep the X509Data stuff in datas but return the + // longer EncapsulatedX509Certificate chain + datas.emplace_back(tempResult); +#endif + certs = encapsulatedCerts; // overwrite this seems easier + } + } + else + { + SAL_WARN("xmlsecurity.comp", "X509Data and EncapsulatedX509Certificate contain different certificates"); + } + } + } } // rInfo is a copy, update the original |