summaryrefslogtreecommitdiffstats
path: root/xmlsecurity/source/dialogs/certificateviewer.cxx
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-07 09:06:44 +0000
commited5640d8b587fbcfed7dd7967f3de04b37a76f26 (patch)
tree7a5f7c6c9d02226d7471cb3cc8fbbf631b415303 /xmlsecurity/source/dialogs/certificateviewer.cxx
parentInitial commit. (diff)
downloadlibreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.tar.xz
libreoffice-ed5640d8b587fbcfed7dd7967f3de04b37a76f26.zip
Adding upstream version 4:7.4.7.upstream/4%7.4.7upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'xmlsecurity/source/dialogs/certificateviewer.cxx')
-rw-r--r--xmlsecurity/source/dialogs/certificateviewer.cxx377
1 files changed, 377 insertions, 0 deletions
diff --git a/xmlsecurity/source/dialogs/certificateviewer.cxx b/xmlsecurity/source/dialogs/certificateviewer.cxx
new file mode 100644
index 000000000..1801cdf53
--- /dev/null
+++ b/xmlsecurity/source/dialogs/certificateviewer.cxx
@@ -0,0 +1,377 @@
+/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
+/*
+ * This file is part of the LibreOffice project.
+ *
+ * This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * This file incorporates work covered by the following license notice:
+ *
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed
+ * with this work for additional information regarding copyright
+ * ownership. The ASF licenses this file to you under the Apache
+ * License, Version 2.0 (the "License"); you may not use this file
+ * except in compliance with the License. You may obtain a copy of
+ * the License at http://www.apache.org/licenses/LICENSE-2.0 .
+ */
+
+#include <sal/config.h>
+
+#include <string_view>
+
+#include <certificatechooser.hxx>
+#include <certificateviewer.hxx>
+#include <com/sun/star/security/XCertificate.hpp>
+
+#include <com/sun/star/security/CertificateCharacters.hpp>
+#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
+#include <com/sun/star/security/CertificateValidity.hpp>
+
+#include <unotools/localedatawrapper.hxx>
+#include <unotools/datetime.hxx>
+
+#include <strings.hrc>
+#include <resourcemanager.hxx>
+#include <comphelper/xmlsechelper.hxx>
+#include <tools/datetime.hxx>
+#include <bitmaps.hlst>
+
+#include <vcl/settings.hxx>
+#include <vcl/svapp.hxx>
+
+using namespace comphelper;
+using namespace ::com::sun::star;
+using namespace ::com::sun::star::uno;
+
+CertificateViewer::CertificateViewer(weld::Window* _pParent,
+ const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& _rxSecurityEnvironment,
+ const css::uno::Reference< css::security::XCertificate >& _rXCert, bool bCheckForPrivateKey,
+ CertificateChooser* pParentChooser)
+ : GenericDialogController(_pParent, "xmlsec/ui/viewcertdialog.ui", "ViewCertDialog")
+ , mbCheckForPrivateKey(bCheckForPrivateKey)
+ , mpParentChooser(pParentChooser)
+ , mxTabCtrl(m_xBuilder->weld_notebook("tabcontrol"))
+{
+ mxTabCtrl->connect_enter_page(LINK(this, CertificateViewer, ActivatePageHdl));
+
+ mxSecurityEnvironment = _rxSecurityEnvironment;
+ mxCert = _rXCert;
+
+ mxGeneralPage.reset(new CertificateViewerGeneralTP(mxTabCtrl->get_page("general"), this));
+ mxDetailsPage.reset(new CertificateViewerDetailsTP(mxTabCtrl->get_page("details"), this));
+ if (!mxSecurityEnvironment->buildCertificatePath(mxCert).hasElements())
+ mxTabCtrl->remove_page("path");
+ else
+ mxPathId.reset(new CertificateViewerCertPathTP(mxTabCtrl->get_page("path"), this));
+ mxTabCtrl->set_current_page("general");
+}
+
+IMPL_LINK(CertificateViewer, ActivatePageHdl, const OString&, rPage, void)
+{
+ if (rPage == "path")
+ mxPathId->ActivatePage();
+}
+
+CertificateViewerTP::CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription,
+ const OString& rID, CertificateViewer* pDlg)
+ : mxBuilder(Application::CreateBuilder(pParent, rUIXMLDescription))
+ , mxContainer(mxBuilder->weld_container(rID))
+ , mpDlg(pDlg)
+{
+}
+
+CertificateViewerGeneralTP::CertificateViewerGeneralTP(weld::Container* pParent, CertificateViewer* pDlg)
+ : CertificateViewerTP(pParent, "xmlsec/ui/certgeneral.ui", "CertGeneral", pDlg)
+ , m_xCertImg(mxBuilder->weld_image("certimage"))
+ , m_xHintNotTrustedFT(mxBuilder->weld_label("hintnotrust"))
+ , m_xIssuedToLabelFT(mxBuilder->weld_label("issued_to"))
+ , m_xIssuedToFT(mxBuilder->weld_label("issued_to_value"))
+ , m_xIssuedByLabelFT(mxBuilder->weld_label("issued_by"))
+ , m_xIssuedByFT(mxBuilder->weld_label("issued_by_value"))
+ , m_xValidFromDateFT(mxBuilder->weld_label("valid_from_value"))
+ , m_xValidToDateFT(mxBuilder->weld_label("valid_to_value"))
+ , m_xKeyImg(mxBuilder->weld_image("keyimage"))
+ , m_xHintCorrespPrivKeyFT(mxBuilder->weld_label("privatekey"))
+{
+ //Verify the certificate
+ sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(mpDlg->mxCert,
+ Sequence<Reference<css::security::XCertificate> >());
+
+ bool bCertValid = certStatus == css::security::CertificateValidity::VALID;
+
+ if ( !bCertValid )
+ {
+ m_xCertImg->set_from_icon_name(BMP_STATE_NOT_VALIDATED);
+ m_xHintNotTrustedFT->set_label(XsResId(STR_CERTIFICATE_NOT_VALIDATED));
+ }
+
+ // insert data
+ css::uno::Reference< css::security::XCertificate > xCert = mpDlg->mxCert;
+
+ OUString sSubjectName(xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind()));
+ if (!sSubjectName.isEmpty())
+ m_xIssuedToFT->set_label(sSubjectName);
+ else
+ m_xIssuedToLabelFT->hide();
+ OUString sIssuerName(xmlsec::GetContentPart(xCert->getIssuerName(), xCert->getCertificateKind()));
+ if (!sIssuerName.isEmpty())
+ m_xIssuedByFT->set_label(sIssuerName);
+ else
+ m_xIssuedByLabelFT->hide();
+
+ DateTime aDateTimeStart( DateTime::EMPTY );
+ DateTime aDateTimeEnd( DateTime::EMPTY );
+ utl::typeConvert( xCert->getNotValidBefore(), aDateTimeStart );
+ utl::typeConvert( xCert->getNotValidAfter(), aDateTimeEnd );
+
+ OUString sValidFromDate = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeStart.GetDate()));
+ OUString sValidToDate = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeEnd.GetDate()));
+
+ m_xValidFromDateFT->set_label(sValidFromDate);
+ m_xValidToDateFT->set_label(sValidToDate);
+
+ // Check if we have the private key...
+ bool bHasPrivateKey = false;
+ // #i41270# Check only if we have that certificate in our security environment
+ if (pDlg->mbCheckForPrivateKey)
+ {
+ tools::Long nCertificateCharacters = pDlg->mxSecurityEnvironment->getCertificateCharacters(xCert);
+ bHasPrivateKey = (nCertificateCharacters & security::CertificateCharacters::HAS_PRIVATE_KEY);
+ }
+ if (!bHasPrivateKey)
+ {
+ m_xKeyImg->hide();
+ m_xHintCorrespPrivKeyFT->hide();
+ }
+}
+
+void CertificateViewerDetailsTP::InsertElement(const OUString& rField, const OUString& rValue,
+ const OUString& rDetails, bool bFixedWidthFont)
+{
+ m_aUserData.emplace_back(std::make_unique<Details_UserDatat>(rDetails, bFixedWidthFont));
+ OUString sId(weld::toId(m_aUserData.back().get()));
+ m_xElementsLB->append(sId, rField);
+ m_xElementsLB->set_text(m_xElementsLB->n_children() -1, rValue, 1);
+}
+
+CertificateViewerDetailsTP::CertificateViewerDetailsTP(weld::Container* pParent, CertificateViewer* pDlg)
+ : CertificateViewerTP(pParent, "xmlsec/ui/certdetails.ui", "CertDetails", pDlg)
+ , m_xElementsLB(mxBuilder->weld_tree_view("tablecontainer"))
+ , m_xValueDetails(mxBuilder->weld_text_view("valuedetails"))
+{
+ const int nWidth = m_xElementsLB->get_approximate_digit_width() * 60;
+ const int nHeight = m_xElementsLB->get_height_rows(8);
+ m_xElementsLB->set_size_request(nWidth, nHeight);
+ m_xValueDetails->set_size_request(nWidth, nHeight);
+ m_xElementsLB->set_column_fixed_widths( { nWidth / 2 } );
+
+ // fill list box
+ Reference< security::XCertificate > xCert = mpDlg->mxCert;
+ sal_uInt16 nLineBreak = 16;
+ const char* const pHexSep = " ";
+ OUString aLBEntry;
+ OUString aDetails;
+ // Certificate Versions are reported wrong (#i35107#) - 0 == "V1", 1 == "V2", ..., n = "V(n+1)"
+ aLBEntry = "V" + OUString::number( xCert->getVersion() + 1 );
+ InsertElement( XsResId( STR_VERSION ), aLBEntry, aLBEntry );
+ Sequence< sal_Int8 > aSeq = xCert->getSerialNumber();
+ aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
+ aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
+ InsertElement( XsResId( STR_SERIALNUM ), aLBEntry, aDetails, true );
+
+ std::pair< OUString, OUString> pairIssuer =
+ xmlsec::GetDNForCertDetailsView(xCert->getIssuerName());
+ aLBEntry = pairIssuer.first;
+ aDetails = pairIssuer.second;
+ InsertElement( XsResId( STR_ISSUER ), aLBEntry, aDetails );
+
+ DateTime aDateTime( DateTime::EMPTY );
+ utl::typeConvert( xCert->getNotValidBefore(), aDateTime );
+ aLBEntry = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime.GetDate())) + " ";
+ aLBEntry += Application::GetSettings().GetUILocaleDataWrapper().getTime(tools::Time(aDateTime.GetTime()));
+ InsertElement( XsResId( STR_VALIDFROM ), aLBEntry, aLBEntry );
+ utl::typeConvert( xCert->getNotValidAfter(), aDateTime );
+ aLBEntry = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime.GetDate()) ) + " ";
+ aLBEntry += Application::GetSettings().GetUILocaleDataWrapper().getTime(tools::Time(aDateTime.GetTime()));
+ InsertElement( XsResId( STR_VALIDTO ), aLBEntry, aLBEntry );
+
+ std::pair< OUString, OUString > pairSubject =
+ xmlsec::GetDNForCertDetailsView(xCert->getSubjectName());
+ aLBEntry = pairSubject.first;
+ aDetails = pairSubject.second;
+ InsertElement( XsResId( STR_SUBJECT ), aLBEntry, aDetails );
+
+ aLBEntry = aDetails = xCert->getSubjectPublicKeyAlgorithm();
+ InsertElement( XsResId( STR_SUBJECT_PUBKEY_ALGO ), aLBEntry, aDetails );
+ aSeq = xCert->getSubjectPublicKeyValue();
+ aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
+ aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
+ InsertElement( XsResId( STR_SUBJECT_PUBKEY_VAL ), aLBEntry, aDetails, true );
+
+ aLBEntry = aDetails = xCert->getSignatureAlgorithm();
+ InsertElement( XsResId( STR_SIGNATURE_ALGO ), aLBEntry, aDetails );
+
+ CertificateChooser* pChooser = mpDlg->GetParentChooser();
+ if (pChooser)
+ {
+ aLBEntry = CertificateChooser::UsageInClearText( mpDlg->mxCert->getCertificateUsage() );
+ InsertElement( XsResId( STR_USE ), aLBEntry, aLBEntry );
+ }
+
+ aSeq = xCert->getSHA1Thumbprint();
+ aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
+ aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
+ InsertElement( XsResId( STR_THUMBPRINT_SHA1 ), aLBEntry, aDetails, true );
+
+ aSeq = xCert->getMD5Thumbprint();
+ aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
+ aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
+ InsertElement( XsResId( STR_THUMBPRINT_MD5 ), aLBEntry, aDetails, true );
+
+ m_xElementsLB->connect_changed(LINK(this, CertificateViewerDetailsTP, ElementSelectHdl));
+}
+
+IMPL_LINK_NOARG(CertificateViewerDetailsTP, ElementSelectHdl, weld::TreeView&, void)
+{
+ int nEntry = m_xElementsLB->get_selected_index();
+ OUString aElementText;
+ bool bFixedWidthFont;
+ if (nEntry != -1)
+ {
+ const Details_UserDatat* p = weld::fromId<Details_UserDatat*>(m_xElementsLB->get_id(nEntry));
+ aElementText = p->maTxt;
+ bFixedWidthFont = p->mbFixedWidthFont;
+ }
+ else
+ bFixedWidthFont = false;
+
+ m_xValueDetails->set_monospace(bFixedWidthFont);
+ m_xValueDetails->set_text(aElementText);
+}
+
+CertificateViewerCertPathTP::CertificateViewerCertPathTP(weld::Container* pParent, CertificateViewer* pDlg)
+ : CertificateViewerTP(pParent, "xmlsec/ui/certpage.ui", "CertPage", pDlg)
+ , mpParent(pDlg)
+ , mbFirstActivateDone(false)
+ , mxCertPathLB(mxBuilder->weld_tree_view("signatures"))
+ , mxScratchIter(mxCertPathLB->make_iterator())
+ , mxViewCertPB(mxBuilder->weld_button("viewcert"))
+ , mxCertStatusML(mxBuilder->weld_text_view("status"))
+ , mxCertOK(mxBuilder->weld_label("certok"))
+ , mxCertNotValidated(mxBuilder->weld_label("certnotok"))
+{
+ const int nWidth = mxCertPathLB->get_approximate_digit_width() * 60;
+ const int nHeight = mxCertPathLB->get_height_rows(6);
+ mxCertPathLB->set_size_request(nWidth, nHeight);
+ mxCertStatusML->set_size_request(nWidth, nHeight);
+
+ mxCertPathLB->connect_changed( LINK( this, CertificateViewerCertPathTP, CertSelectHdl ) );
+ mxViewCertPB->connect_clicked( LINK( this, CertificateViewerCertPathTP, ViewCertHdl ) );
+}
+
+CertificateViewerCertPathTP::~CertificateViewerCertPathTP()
+{
+ if (mxCertificateViewer)
+ mxCertificateViewer->response(RET_OK);
+}
+
+void CertificateViewerCertPathTP::ActivatePage()
+{
+ if ( mbFirstActivateDone )
+ return;
+
+ mbFirstActivateDone = true;
+ Sequence< Reference< security::XCertificate > > aCertPath =
+ mpParent->mxSecurityEnvironment->buildCertificatePath( mpParent->mxCert );
+ const Reference< security::XCertificate >* pCertPath = aCertPath.getConstArray();
+
+ sal_Int32 i, nCnt = aCertPath.getLength();
+ std::unique_ptr<weld::TreeIter> xParent;
+ for (i = nCnt-1; i >= 0; i--)
+ {
+ const Reference< security::XCertificate > rCert = pCertPath[ i ];
+ OUString sName = xmlsec::GetContentPart( rCert->getSubjectName(), rCert->getCertificateKind() );
+ //Verify the certificate
+ sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(rCert,
+ Sequence<Reference<css::security::XCertificate> >());
+ bool bCertValid = certStatus == css::security::CertificateValidity::VALID;
+ InsertCert(xParent.get(), sName, rCert, bCertValid);
+ if (!xParent)
+ {
+ xParent = mxCertPathLB->make_iterator();
+ (void)mxCertPathLB->get_iter_first(*xParent);
+ }
+ else
+ {
+ (void)mxCertPathLB->iter_children(*xParent);
+ }
+ }
+
+ if (xParent)
+ mxCertPathLB->select(*xParent);
+ mxViewCertPB->set_sensitive(false); // Own certificate selected
+
+ while (xParent)
+ {
+ mxCertPathLB->expand_row(*xParent);
+ if (!mxCertPathLB->iter_parent(*xParent))
+ xParent.reset();
+ }
+
+ CertSelectHdl(*mxCertPathLB);
+}
+
+IMPL_LINK_NOARG(CertificateViewerCertPathTP, ViewCertHdl, weld::Button&, void)
+{
+ std::unique_ptr<weld::TreeIter> xIter = mxCertPathLB->make_iterator();
+ if (mxCertPathLB->get_selected(xIter.get()))
+ {
+ if (mxCertificateViewer)
+ mxCertificateViewer->response(RET_OK);
+
+ CertPath_UserData* pData = weld::fromId<CertPath_UserData*>(mxCertPathLB->get_id(*xIter));
+ mxCertificateViewer = std::make_shared<CertificateViewer>(mpDlg->getDialog(), mpDlg->mxSecurityEnvironment,
+ pData->mxCert, false, nullptr);
+ weld::DialogController::runAsync(mxCertificateViewer, [this] (sal_Int32) { mxCertificateViewer = nullptr; });
+ }
+}
+
+IMPL_LINK_NOARG(CertificateViewerCertPathTP, CertSelectHdl, weld::TreeView&, void)
+{
+ OUString sStatus;
+
+ std::unique_ptr<weld::TreeIter> xIter = mxCertPathLB->make_iterator();
+ bool bEntry = mxCertPathLB->get_selected(xIter.get());
+ if (bEntry)
+ {
+ CertPath_UserData* pData = weld::fromId<CertPath_UserData*>(mxCertPathLB->get_id(*xIter));
+ if (pData)
+ sStatus = pData->mbValid ? mxCertOK->get_label() : mxCertNotValidated->get_label();
+ }
+
+ mxCertStatusML->set_text(sStatus);
+
+ bool bSensitive = false;
+ if (bEntry)
+ {
+ // if has children, so not the last one in the chain
+ if (mxCertPathLB->iter_children(*xIter))
+ bSensitive = true;
+ }
+ mxViewCertPB->set_sensitive(bSensitive);
+}
+
+void CertificateViewerCertPathTP::InsertCert(const weld::TreeIter* pParent, const OUString& rName,
+ const css::uno::Reference< css::security::XCertificate >& rxCert,
+ bool bValid)
+{
+ auto const sImage = bValid ? std::u16string_view(u"" BMP_CERT_OK) : std::u16string_view(u"" BMP_CERT_NOT_OK);
+ maUserData.emplace_back(std::make_unique<CertPath_UserData>(rxCert, bValid));
+ OUString sId(weld::toId(maUserData.back().get()));
+ mxCertPathLB->insert(pParent, -1, &rName, &sId, nullptr, nullptr, false, mxScratchIter.get());
+ mxCertPathLB->set_image(*mxScratchIter, OUString(sImage));
+}
+
+/* vim:set shiftwidth=4 softtabstop=4 expandtab: */