Better valid certificate check, consider filter data

Otherwise, testSignCertificateSubjectName that has an explicit certificate
subject name requirement would fail when user has other valid certificates,
but not this one.

Change-Id: Ic3c440a8316314c922a53a51085a3e829f235f6d
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137593
Tested-by: Jenkins
Reviewed-by: Mike Kaganski <mike.kaganski@collabora.com>
diff --git a/filter/qa/pdf.cxx b/filter/qa/pdf.cxx
index 04bd417..7cb713f 100644
--- a/filter/qa/pdf.cxx
+++ b/filter/qa/pdf.cxx
@@ -65,7 +65,14 @@ CPPUNIT_TEST_FIXTURE(Test, testSignCertificateSubjectName)
        = xSEInitializer->createSecurityContext(OUString());
    uno::Reference<xml::crypto::XSecurityEnvironment> xSecurityEnvironment
        = xSecurityContext->getSecurityEnvironment();
    if (!GetValidCertificate(xSecurityEnvironment->getPersonalCertificates()))
    uno::Sequence<beans::PropertyValue> aFilterData{
        comphelper::makePropertyValue("SignPDF", true),
        comphelper::makePropertyValue(
            "SignCertificateSubjectName",
            OUString(
                "CN=Xmlsecurity RSA Test example Alice,O=Xmlsecurity RSA Test,ST=England,C=UK")),
    };
    if (!GetValidCertificate(xSecurityEnvironment->getPersonalCertificates(), aFilterData))
    {
        return;
    }
@@ -83,13 +90,6 @@ CPPUNIT_TEST_FIXTURE(Test, testSignCertificateSubjectName)
    SvMemoryStream aStream;
    uno::Reference<io::XOutputStream> xOutputStream(new utl::OStreamWrapper(aStream));

    uno::Sequence<beans::PropertyValue> aFilterData{
        comphelper::makePropertyValue("SignPDF", true),
        comphelper::makePropertyValue(
            "SignCertificateSubjectName",
            OUString(
                "CN=Xmlsecurity RSA Test example Alice,O=Xmlsecurity RSA Test,ST=England,C=UK")),
    };
    uno::Sequence<beans::PropertyValue> aDescriptor{
        comphelper::makePropertyValue("FilterName", OUString("writer_pdf_Export")),
        comphelper::makePropertyValue("FilterData", aFilterData),
diff --git a/include/unotest/macros_test.hxx b/include/unotest/macros_test.hxx
index 6a476cf..dc5ca20 100644
--- a/include/unotest/macros_test.hxx
+++ b/include/unotest/macros_test.hxx
@@ -95,7 +95,8 @@ public:

    static bool IsValid(const css::uno::Reference<css::security::XCertificate>& cert);
    static css::uno::Reference<css::security::XCertificate> GetValidCertificate(
        const css::uno::Sequence<css::uno::Reference<css::security::XCertificate>>& certs);
        const css::uno::Sequence<css::uno::Reference<css::security::XCertificate>>& certs,
        const css::uno::Sequence<css::beans::PropertyValue>& rFilterData = {});

protected:
    css::uno::Reference<css::frame::XDesktop2> mxDesktop;
diff --git a/unotest/source/cpp/macros_test.cxx b/unotest/source/cpp/macros_test.cxx
index 6e8a26c..76105b88 100644
--- a/unotest/source/cpp/macros_test.cxx
+++ b/unotest/source/cpp/macros_test.cxx
@@ -173,16 +173,43 @@ void MacrosTest::tearDownNssGpg()
#endif
}

namespace
{
struct Valid
{
    DateTime now;
    OUString subjectName;
    Valid(const css::uno::Sequence<css::beans::PropertyValue>& rFilterData)
        : now(DateTime::SYSTEM)
    {
        for (const auto& propVal : rFilterData)
        {
            if (propVal.Name == "SignCertificateSubjectName")
                propVal.Value >>= subjectName;
        }
    }
    bool operator()(const css::uno::Reference<css::security::XCertificate>& cert) const
    {
        if (!now.IsBetween(cert->getNotValidBefore(), cert->getNotValidAfter()))
            return false;
        if (!subjectName.isEmpty() && subjectName != cert->getSubjectName())
            return false;
        return true;
    }
};
}

bool MacrosTest::IsValid(const css::uno::Reference<css::security::XCertificate>& cert)
{
    return DateTime(DateTime::SYSTEM)
        .IsBetween(cert->getNotValidBefore(), cert->getNotValidAfter());
    const Valid test({});
    return test(cert);
}

css::uno::Reference<css::security::XCertificate> MacrosTest::GetValidCertificate(
    const css::uno::Sequence<css::uno::Reference<css::security::XCertificate>>& certs)
    const css::uno::Sequence<css::uno::Reference<css::security::XCertificate>>& certs,
    const css::uno::Sequence<css::beans::PropertyValue>& rFilterData)
{
    if (auto it = std::find_if(certs.begin(), certs.end(), IsValid); it != certs.end())
    if (auto it = std::find_if(certs.begin(), certs.end(), Valid(rFilterData)); it != certs.end())
        return *it;
    return {};
}