LibreOffice Module xmlsecurity (master) 1
certificateviewer.cxx
Go to the documentation of this file.
1/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2/*
3 * This file is part of the LibreOffice project.
4 *
5 * This Source Code Form is subject to the terms of the Mozilla Public
6 * License, v. 2.0. If a copy of the MPL was not distributed with this
7 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
8 *
9 * This file incorporates work covered by the following license notice:
10 *
11 * Licensed to the Apache Software Foundation (ASF) under one or more
12 * contributor license agreements. See the NOTICE file distributed
13 * with this work for additional information regarding copyright
14 * ownership. The ASF licenses this file to you under the Apache
15 * License, Version 2.0 (the "License"); you may not use this file
16 * except in compliance with the License. You may obtain a copy of
17 * the License at http://www.apache.org/licenses/LICENSE-2.0 .
18 */
19
20#include <sal/config.h>
21
22#include <string_view>
23
25#include <certificateviewer.hxx>
26#include <com/sun/star/security/XCertificate.hpp>
27
28#include <com/sun/star/security/CertificateCharacters.hpp>
29#include <com/sun/star/xml/crypto/XSecurityEnvironment.hpp>
30#include <com/sun/star/security/CertificateValidity.hpp>
31
33#include <unotools/datetime.hxx>
34
35#include <strings.hrc>
36#include <resourcemanager.hxx>
38#include <tools/datetime.hxx>
39#include <bitmaps.hlst>
40
41#include <vcl/settings.hxx>
42#include <vcl/svapp.hxx>
43
44using namespace comphelper;
45using namespace ::com::sun::star;
46using namespace ::com::sun::star::uno;
47
49 const css::uno::Reference< css::xml::crypto::XSecurityEnvironment >& _rxSecurityEnvironment,
50 const css::uno::Reference< css::security::XCertificate >& _rXCert, bool bCheckForPrivateKey,
51 CertificateChooser* pParentChooser)
52 : GenericDialogController(_pParent, "xmlsec/ui/viewcertdialog.ui", "ViewCertDialog")
53 , mbCheckForPrivateKey(bCheckForPrivateKey)
54 , mpParentChooser(pParentChooser)
55 , mxTabCtrl(m_xBuilder->weld_notebook("tabcontrol"))
56{
57 mxTabCtrl->connect_enter_page(LINK(this, CertificateViewer, ActivatePageHdl));
58
59 mxSecurityEnvironment = _rxSecurityEnvironment;
60 mxCert = _rXCert;
61
62 mxGeneralPage.reset(new CertificateViewerGeneralTP(mxTabCtrl->get_page("general"), this));
63 mxDetailsPage.reset(new CertificateViewerDetailsTP(mxTabCtrl->get_page("details"), this));
64 if (!mxSecurityEnvironment->buildCertificatePath(mxCert).hasElements())
65 mxTabCtrl->remove_page("path");
66 else
67 mxPathId.reset(new CertificateViewerCertPathTP(mxTabCtrl->get_page("path"), this));
68 mxTabCtrl->set_current_page("general");
69}
70
71IMPL_LINK(CertificateViewer, ActivatePageHdl, const OUString&, rPage, void)
72{
73 if (rPage == "path")
74 mxPathId->ActivatePage();
75}
76
77CertificateViewerTP::CertificateViewerTP(weld::Container* pParent, const OUString& rUIXMLDescription,
78 const OUString& rID, CertificateViewer* pDlg)
79 : mxBuilder(Application::CreateBuilder(pParent, rUIXMLDescription))
80 , mxContainer(mxBuilder->weld_container(rID))
81 , mpDlg(pDlg)
82{
83}
84
86 : CertificateViewerTP(pParent, "xmlsec/ui/certgeneral.ui", "CertGeneral", pDlg)
87 , m_xCertImg(mxBuilder->weld_image("certimage"))
88 , m_xHintNotTrustedFT(mxBuilder->weld_label("hintnotrust"))
89 , m_xIssuedToLabelFT(mxBuilder->weld_label("issued_to"))
90 , m_xIssuedToFT(mxBuilder->weld_label("issued_to_value"))
91 , m_xIssuedByLabelFT(mxBuilder->weld_label("issued_by"))
92 , m_xIssuedByFT(mxBuilder->weld_label("issued_by_value"))
93 , m_xValidFromDateFT(mxBuilder->weld_label("valid_from_value"))
94 , m_xValidToDateFT(mxBuilder->weld_label("valid_to_value"))
95 , m_xKeyImg(mxBuilder->weld_image("keyimage"))
96 , m_xHintCorrespPrivKeyFT(mxBuilder->weld_label("privatekey"))
97{
98 //Verify the certificate
99 sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(mpDlg->mxCert,
100 Sequence<Reference<css::security::XCertificate> >());
101
102 bool bCertValid = certStatus == css::security::CertificateValidity::VALID;
103
104 if ( !bCertValid )
105 {
106 m_xCertImg->set_from_icon_name(BMP_STATE_NOT_VALIDATED);
107 m_xHintNotTrustedFT->set_label(XsResId(STR_CERTIFICATE_NOT_VALIDATED));
108 }
109
110 // insert data
111 css::uno::Reference< css::security::XCertificate > xCert = mpDlg->mxCert;
112
113 OUString sSubjectName(xmlsec::GetContentPart(xCert->getSubjectName(), xCert->getCertificateKind()));
114 if (!sSubjectName.isEmpty())
115 m_xIssuedToFT->set_label(sSubjectName);
116 else
117 m_xIssuedToLabelFT->hide();
118 OUString sIssuerName(xmlsec::GetContentPart(xCert->getIssuerName(), xCert->getCertificateKind()));
119 if (!sIssuerName.isEmpty())
120 m_xIssuedByFT->set_label(sIssuerName);
121 else
122 m_xIssuedByLabelFT->hide();
123
124 DateTime aDateTimeStart( DateTime::EMPTY );
125 DateTime aDateTimeEnd( DateTime::EMPTY );
126 utl::typeConvert( xCert->getNotValidBefore(), aDateTimeStart );
127 utl::typeConvert( xCert->getNotValidAfter(), aDateTimeEnd );
128
129 OUString sValidFromDate = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeStart.GetDate()));
130 OUString sValidToDate = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeEnd.GetDate()));
131
132 m_xValidFromDateFT->set_label(sValidFromDate);
133 m_xValidToDateFT->set_label(sValidToDate);
134
135 // Check if we have the private key...
136 bool bHasPrivateKey = false;
137 // #i41270# Check only if we have that certificate in our security environment
138 if (pDlg->mbCheckForPrivateKey)
139 {
140 tools::Long nCertificateCharacters = pDlg->mxSecurityEnvironment->getCertificateCharacters(xCert);
141 bHasPrivateKey = (nCertificateCharacters & security::CertificateCharacters::HAS_PRIVATE_KEY);
142 }
143 if (!bHasPrivateKey)
144 {
145 m_xKeyImg->hide();
147 }
148}
149
150void CertificateViewerDetailsTP::InsertElement(const OUString& rField, const OUString& rValue,
151 const OUString& rDetails, bool bFixedWidthFont)
152{
153 m_aUserData.emplace_back(std::make_unique<Details_UserDatat>(rDetails, bFixedWidthFont));
154 OUString sId(weld::toId(m_aUserData.back().get()));
155 m_xElementsLB->append(sId, rField);
156 m_xElementsLB->set_text(m_xElementsLB->n_children() -1, rValue, 1);
157}
158
160 : CertificateViewerTP(pParent, "xmlsec/ui/certdetails.ui", "CertDetails", pDlg)
161 , m_xElementsLB(mxBuilder->weld_tree_view("tablecontainer"))
162 , m_xValueDetails(mxBuilder->weld_text_view("valuedetails"))
163{
164 const int nWidth = m_xElementsLB->get_approximate_digit_width() * 60;
165 const int nHeight = m_xElementsLB->get_height_rows(8);
166 m_xElementsLB->set_size_request(nWidth, nHeight);
167 m_xValueDetails->set_size_request(nWidth, nHeight);
168 m_xElementsLB->set_column_fixed_widths( { nWidth / 2 } );
169
170 // fill list box
171 Reference< security::XCertificate > xCert = mpDlg->mxCert;
172 sal_uInt16 nLineBreak = 16;
173 const char* const pHexSep = " ";
174 OUString aLBEntry;
175 OUString aDetails;
176 // Certificate Versions are reported wrong (#i35107#) - 0 == "V1", 1 == "V2", ..., n = "V(n+1)"
177 aLBEntry = "V" + OUString::number( xCert->getVersion() + 1 );
178 InsertElement( XsResId( STR_VERSION ), aLBEntry, aLBEntry );
179 Sequence< sal_Int8 > aSeq = xCert->getSerialNumber();
180 aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
181 aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
182 InsertElement( XsResId( STR_SERIALNUM ), aLBEntry, aDetails, true );
183
184 std::pair< OUString, OUString> pairIssuer =
185 xmlsec::GetDNForCertDetailsView(xCert->getIssuerName());
186 aLBEntry = pairIssuer.first;
187 aDetails = pairIssuer.second;
188 InsertElement( XsResId( STR_ISSUER ), aLBEntry, aDetails );
189
190 DateTime aDateTime( DateTime::EMPTY );
191 utl::typeConvert( xCert->getNotValidBefore(), aDateTime );
192 aLBEntry = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime.GetDate())) + " ";
194 InsertElement( XsResId( STR_VALIDFROM ), aLBEntry, aLBEntry );
195 utl::typeConvert( xCert->getNotValidAfter(), aDateTime );
196 aLBEntry = Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime.GetDate()) ) + " ";
198 InsertElement( XsResId( STR_VALIDTO ), aLBEntry, aLBEntry );
199
200 std::pair< OUString, OUString > pairSubject =
201 xmlsec::GetDNForCertDetailsView(xCert->getSubjectName());
202 aLBEntry = pairSubject.first;
203 aDetails = pairSubject.second;
204 InsertElement( XsResId( STR_SUBJECT ), aLBEntry, aDetails );
205
206 aLBEntry = aDetails = xCert->getSubjectPublicKeyAlgorithm();
207 InsertElement( XsResId( STR_SUBJECT_PUBKEY_ALGO ), aLBEntry, aDetails );
208 aSeq = xCert->getSubjectPublicKeyValue();
209 aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
210 aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
211 InsertElement( XsResId( STR_SUBJECT_PUBKEY_VAL ), aLBEntry, aDetails, true );
212
213 aLBEntry = aDetails = xCert->getSignatureAlgorithm();
214 InsertElement( XsResId( STR_SIGNATURE_ALGO ), aLBEntry, aDetails );
215
217 if (pChooser)
218 {
219 aLBEntry = CertificateChooser::UsageInClearText( mpDlg->mxCert->getCertificateUsage() );
220 InsertElement( XsResId( STR_USE ), aLBEntry, aLBEntry );
221 }
222
223 aSeq = xCert->getSHA1Thumbprint();
224 aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
225 aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
226 InsertElement( XsResId( STR_THUMBPRINT_SHA1 ), aLBEntry, aDetails, true );
227
228 aSeq = xCert->getMD5Thumbprint();
229 aLBEntry = xmlsec::GetHexString( aSeq, pHexSep );
230 aDetails = xmlsec::GetHexString( aSeq, pHexSep, nLineBreak );
231 InsertElement( XsResId( STR_THUMBPRINT_MD5 ), aLBEntry, aDetails, true );
232
233 m_xElementsLB->connect_changed(LINK(this, CertificateViewerDetailsTP, ElementSelectHdl));
234}
235
237{
238 int nEntry = m_xElementsLB->get_selected_index();
239 OUString aElementText;
240 bool bFixedWidthFont;
241 if (nEntry != -1)
242 {
243 const Details_UserDatat* p = weld::fromId<Details_UserDatat*>(m_xElementsLB->get_id(nEntry));
244 aElementText = p->maTxt;
245 bFixedWidthFont = p->mbFixedWidthFont;
246 }
247 else
248 bFixedWidthFont = false;
249
250 m_xValueDetails->set_monospace(bFixedWidthFont);
251 m_xValueDetails->set_text(aElementText);
252}
253
255 : CertificateViewerTP(pParent, "xmlsec/ui/certpage.ui", "CertPage", pDlg)
256 , mpParent(pDlg)
257 , mbFirstActivateDone(false)
258 , mxCertPathLB(mxBuilder->weld_tree_view("signatures"))
259 , mxScratchIter(mxCertPathLB->make_iterator())
260 , mxViewCertPB(mxBuilder->weld_button("viewcert"))
261 , mxCertStatusML(mxBuilder->weld_text_view("status"))
262 , mxCertOK(mxBuilder->weld_label("certok"))
263 , mxCertNotValidated(mxBuilder->weld_label("certnotok"))
264{
265 const int nWidth = mxCertPathLB->get_approximate_digit_width() * 60;
266 const int nHeight = mxCertPathLB->get_height_rows(6);
267 mxCertPathLB->set_size_request(nWidth, nHeight);
268 mxCertStatusML->set_size_request(nWidth, nHeight);
269
270 mxCertPathLB->connect_changed( LINK( this, CertificateViewerCertPathTP, CertSelectHdl ) );
271 mxViewCertPB->connect_clicked( LINK( this, CertificateViewerCertPathTP, ViewCertHdl ) );
272}
273
275{
277 mxCertificateViewer->response(RET_OK);
278}
279
281{
283 return;
284
285 mbFirstActivateDone = true;
286 Sequence< Reference< security::XCertificate > > aCertPath =
287 mpParent->mxSecurityEnvironment->buildCertificatePath( mpParent->mxCert );
288 const Reference< security::XCertificate >* pCertPath = aCertPath.getConstArray();
289
290 sal_Int32 i, nCnt = aCertPath.getLength();
291 std::unique_ptr<weld::TreeIter> xParent;
292 for (i = nCnt-1; i >= 0; i--)
293 {
294 const Reference< security::XCertificate > rCert = pCertPath[ i ];
295 OUString sName = xmlsec::GetContentPart( rCert->getSubjectName(), rCert->getCertificateKind() );
296 //Verify the certificate
297 sal_Int32 certStatus = mpDlg->mxSecurityEnvironment->verifyCertificate(rCert,
298 Sequence<Reference<css::security::XCertificate> >());
299 bool bCertValid = certStatus == css::security::CertificateValidity::VALID;
300 InsertCert(xParent.get(), sName, rCert, bCertValid);
301 if (!xParent)
302 {
303 xParent = mxCertPathLB->make_iterator();
304 (void)mxCertPathLB->get_iter_first(*xParent);
305 }
306 else
307 {
308 (void)mxCertPathLB->iter_children(*xParent);
309 }
310 }
311
312 if (xParent)
313 mxCertPathLB->select(*xParent);
314 mxViewCertPB->set_sensitive(false); // Own certificate selected
315
316 while (xParent)
317 {
318 mxCertPathLB->expand_row(*xParent);
319 if (!mxCertPathLB->iter_parent(*xParent))
320 xParent.reset();
321 }
322
323 CertSelectHdl(*mxCertPathLB);
324}
325
327{
328 std::unique_ptr<weld::TreeIter> xIter = mxCertPathLB->make_iterator();
329 if (mxCertPathLB->get_selected(xIter.get()))
330 {
331 if (mxCertificateViewer)
332 mxCertificateViewer->response(RET_OK);
333
334 CertPath_UserData* pData = weld::fromId<CertPath_UserData*>(mxCertPathLB->get_id(*xIter));
335 mxCertificateViewer = std::make_shared<CertificateViewer>(mpDlg->getDialog(), mpDlg->mxSecurityEnvironment,
336 pData->mxCert, false, nullptr);
337 weld::DialogController::runAsync(mxCertificateViewer, [this] (sal_Int32) { mxCertificateViewer = nullptr; });
338 }
339}
340
342{
343 OUString sStatus;
344
345 std::unique_ptr<weld::TreeIter> xIter = mxCertPathLB->make_iterator();
346 bool bEntry = mxCertPathLB->get_selected(xIter.get());
347 if (bEntry)
348 {
349 CertPath_UserData* pData = weld::fromId<CertPath_UserData*>(mxCertPathLB->get_id(*xIter));
350 if (pData)
351 sStatus = pData->mbValid ? mxCertOK->get_label() : mxCertNotValidated->get_label();
352 }
353
354 mxCertStatusML->set_text(sStatus);
355
356 bool bSensitive = false;
357 if (bEntry)
358 {
359 // if has children, so not the last one in the chain
360 if (mxCertPathLB->iter_children(*xIter))
361 bSensitive = true;
362 }
363 mxViewCertPB->set_sensitive(bSensitive);
364}
365
366void CertificateViewerCertPathTP::InsertCert(const weld::TreeIter* pParent, const OUString& rName,
367 const css::uno::Reference< css::security::XCertificate >& rxCert,
368 bool bValid)
369{
370 auto const sImage = bValid ? std::u16string_view(u"" BMP_CERT_OK) : std::u16string_view(u"" BMP_CERT_NOT_OK);
371 maUserData.emplace_back(std::make_unique<CertPath_UserData>(rxCert, bValid));
372 OUString sId(weld::toId(maUserData.back().get()));
373 mxCertPathLB->insert(pParent, -1, &rName, &sId, nullptr, nullptr, false, mxScratchIter.get());
374 mxCertPathLB->set_image(*mxScratchIter, OUString(sImage));
375}
376
377/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
Reference< container::XNameAccess > mxContainer
IMPL_LINK_NOARG(CertificateViewerDetailsTP, ElementSelectHdl, weld::TreeView &, void)
IMPL_LINK(CertificateViewer, ActivatePageHdl, const OUString &, rPage, void)
const LocaleDataWrapper & GetUILocaleDataWrapper() const
static const AllSettings & GetSettings()
static OUString UsageInClearText(int bits)
std::vector< std::unique_ptr< CertPath_UserData > > maUserData
CertificateViewerCertPathTP(weld::Container *pParent, CertificateViewer *pDlg)
std::unique_ptr< weld::TextView > mxCertStatusML
std::shared_ptr< CertificateViewer > mxCertificateViewer
std::unique_ptr< weld::TreeIter > mxScratchIter
std::unique_ptr< weld::TreeView > mxCertPathLB
void InsertCert(const weld::TreeIter *pParent, const OUString &_rName, const css::uno::Reference< css::security::XCertificate > &rxCert, bool bValid)
std::unique_ptr< weld::Button > mxViewCertPB
std::vector< std::unique_ptr< Details_UserDatat > > m_aUserData
std::unique_ptr< weld::TreeView > m_xElementsLB
void InsertElement(const OUString &rField, const OUString &rValue, const OUString &rDetails, bool bFixedWidthFont=false)
std::unique_ptr< weld::TextView > m_xValueDetails
CertificateViewerDetailsTP(weld::Container *pParent, CertificateViewer *pDlg)
std::unique_ptr< weld::Image > m_xCertImg
std::unique_ptr< weld::Label > m_xIssuedByFT
std::unique_ptr< weld::Label > m_xHintCorrespPrivKeyFT
std::unique_ptr< weld::Label > m_xValidToDateFT
std::unique_ptr< weld::Label > m_xIssuedByLabelFT
std::unique_ptr< weld::Label > m_xHintNotTrustedFT
CertificateViewerGeneralTP(weld::Container *pParent, CertificateViewer *pDlg)
std::unique_ptr< weld::Label > m_xIssuedToLabelFT
std::unique_ptr< weld::Image > m_xKeyImg
std::unique_ptr< weld::Label > m_xValidFromDateFT
std::unique_ptr< weld::Label > m_xIssuedToFT
CertificateViewerTP(weld::Container *pParent, const OUString &rUIXMLDescription, const OUString &rID, CertificateViewer *pDlg)
CertificateViewer * mpDlg
friend class CertificateViewerDetailsTP
std::unique_ptr< CertificateViewerDetailsTP > mxDetailsPage
std::unique_ptr< weld::Notebook > mxTabCtrl
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)
friend class CertificateViewerGeneralTP
std::unique_ptr< CertificateViewerCertPathTP > mxPathId
std::unique_ptr< CertificateViewerGeneralTP > mxGeneralPage
css::uno::Reference< css::security::XCertificate > mxCert
friend class CertificateViewerCertPathTP
CertificateChooser * GetParentChooser()
css::uno::Reference< css::xml::crypto::XSecurityEnvironment > mxSecurityEnvironment
bool const mbCheckForPrivateKey
sal_Int32 GetDate() const
OUString getDate(const Date &rDate) const
OUString getTime(const tools::Time &rTime, bool bSec=true, bool b100Sec=false) const
sal_Int64 GetTime() const
static bool runAsync(const std::shared_ptr< DialogController > &rController, const std::function< void(sal_Int32)> &)
RegionData_Impl * mpParent
float u
OUString sName
void * p
Sequence< sal_Int8 > aSeq
std::unique_ptr< sal_Int32[]> pData
int i
long Long
void typeConvert(const Date &_rDate, css::util::Date &_rOut)
OUString toId(const void *pValue)
OUString XsResId(TranslateId aId)
OUString sId
RET_OK