1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
3 * This file is part of the LibreOffice project.
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/.
9 * This file incorporates work covered by the following license notice:
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 .
20 #include <sal/config.h>
22 #include <string_view>
24 #include <certificatechooser.hxx>
25 #include <certificateviewer.hxx>
26 #include <com/sun/star/security/XCertificate.hpp>
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>
32 #include <unotools/localedatawrapper.hxx>
33 #include <unotools/datetime.hxx>
35 #include <strings.hrc>
36 #include <resourcemanager.hxx>
37 #include <comphelper/xmlsechelper.hxx>
38 #include <tools/datetime.hxx>
39 #include <bitmaps.hlst>
41 #include <vcl/settings.hxx>
42 #include <vcl/svapp.hxx>
44 using namespace comphelper
;
45 using namespace ::com::sun::star
;
46 using namespace ::com::sun::star::uno
;
48 CertificateViewer::CertificateViewer(weld::Window
* _pParent
,
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"))
57 mxTabCtrl
->connect_enter_page(LINK(this, CertificateViewer
, ActivatePageHdl
));
59 mxSecurityEnvironment
= _rxSecurityEnvironment
;
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");
67 mxPathId
.reset(new CertificateViewerCertPathTP(mxTabCtrl
->get_page("path"), this));
68 mxTabCtrl
->set_current_page("general");
71 IMPL_LINK(CertificateViewer
, ActivatePageHdl
, const OString
&, rPage
, void)
74 mxPathId
->ActivatePage();
77 CertificateViewerTP::CertificateViewerTP(weld::Container
* pParent
, const OUString
& rUIXMLDescription
,
78 const OString
& rID
, CertificateViewer
* pDlg
)
79 : mxBuilder(Application::CreateBuilder(pParent
, rUIXMLDescription
))
80 , mxContainer(mxBuilder
->weld_container(rID
))
85 CertificateViewerGeneralTP::CertificateViewerGeneralTP(weld::Container
* pParent
, CertificateViewer
* pDlg
)
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"))
98 //Verify the certificate
99 sal_Int32 certStatus
= mpDlg
->mxSecurityEnvironment
->verifyCertificate(mpDlg
->mxCert
,
100 Sequence
<Reference
<css::security::XCertificate
> >());
102 bool bCertValid
= certStatus
== css::security::CertificateValidity::VALID
;
106 m_xCertImg
->set_from_icon_name(BMP_STATE_NOT_VALIDATED
);
107 m_xHintNotTrustedFT
->set_label(XsResId(STR_CERTIFICATE_NOT_VALIDATED
));
111 css::uno::Reference
< css::security::XCertificate
> xCert
= mpDlg
->mxCert
;
113 OUString
sSubjectName(xmlsec::GetContentPart(xCert
->getSubjectName(), xCert
->getCertificateKind()));
114 if (!sSubjectName
.isEmpty())
115 m_xIssuedToFT
->set_label(sSubjectName
);
117 m_xIssuedToLabelFT
->hide();
118 OUString
sIssuerName(xmlsec::GetContentPart(xCert
->getIssuerName(), xCert
->getCertificateKind()));
119 if (!sIssuerName
.isEmpty())
120 m_xIssuedByFT
->set_label(sIssuerName
);
122 m_xIssuedByLabelFT
->hide();
124 DateTime
aDateTimeStart( DateTime::EMPTY
);
125 DateTime
aDateTimeEnd( DateTime::EMPTY
);
126 utl::typeConvert( xCert
->getNotValidBefore(), aDateTimeStart
);
127 utl::typeConvert( xCert
->getNotValidAfter(), aDateTimeEnd
);
129 OUString sValidFromDate
= Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeStart
.GetDate()));
130 OUString sValidToDate
= Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTimeEnd
.GetDate()));
132 m_xValidFromDateFT
->set_label(sValidFromDate
);
133 m_xValidToDateFT
->set_label(sValidToDate
);
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
)
140 tools::Long nCertificateCharacters
= pDlg
->mxSecurityEnvironment
->getCertificateCharacters(xCert
);
141 bHasPrivateKey
= (nCertificateCharacters
& security::CertificateCharacters::HAS_PRIVATE_KEY
);
146 m_xHintCorrespPrivKeyFT
->hide();
150 void CertificateViewerDetailsTP::InsertElement(const OUString
& rField
, const OUString
& rValue
,
151 const OUString
& rDetails
, bool bFixedWidthFont
)
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);
159 CertificateViewerDetailsTP::CertificateViewerDetailsTP(weld::Container
* pParent
, CertificateViewer
* pDlg
)
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"))
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 } );
171 Reference
< security::XCertificate
> xCert
= mpDlg
->mxCert
;
172 sal_uInt16 nLineBreak
= 16;
173 const char* const pHexSep
= " ";
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 );
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
);
190 DateTime
aDateTime( DateTime::EMPTY
);
191 utl::typeConvert( xCert
->getNotValidBefore(), aDateTime
);
192 aLBEntry
= Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime
.GetDate())) + " ";
193 aLBEntry
+= Application::GetSettings().GetUILocaleDataWrapper().getTime(tools::Time(aDateTime
.GetTime()));
194 InsertElement( XsResId( STR_VALIDFROM
), aLBEntry
, aLBEntry
);
195 utl::typeConvert( xCert
->getNotValidAfter(), aDateTime
);
196 aLBEntry
= Application::GetSettings().GetUILocaleDataWrapper().getDate(Date(aDateTime
.GetDate()) ) + " ";
197 aLBEntry
+= Application::GetSettings().GetUILocaleDataWrapper().getTime(tools::Time(aDateTime
.GetTime()));
198 InsertElement( XsResId( STR_VALIDTO
), aLBEntry
, aLBEntry
);
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
);
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 );
213 aLBEntry
= aDetails
= xCert
->getSignatureAlgorithm();
214 InsertElement( XsResId( STR_SIGNATURE_ALGO
), aLBEntry
, aDetails
);
216 CertificateChooser
* pChooser
= mpDlg
->GetParentChooser();
219 aLBEntry
= CertificateChooser::UsageInClearText( mpDlg
->mxCert
->getCertificateUsage() );
220 InsertElement( XsResId( STR_USE
), aLBEntry
, aLBEntry
);
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 );
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 );
233 m_xElementsLB
->connect_changed(LINK(this, CertificateViewerDetailsTP
, ElementSelectHdl
));
236 IMPL_LINK_NOARG(CertificateViewerDetailsTP
, ElementSelectHdl
, weld::TreeView
&, void)
238 int nEntry
= m_xElementsLB
->get_selected_index();
239 OUString aElementText
;
240 bool bFixedWidthFont
;
243 const Details_UserDatat
* p
= weld::fromId
<Details_UserDatat
*>(m_xElementsLB
->get_id(nEntry
));
244 aElementText
= p
->maTxt
;
245 bFixedWidthFont
= p
->mbFixedWidthFont
;
248 bFixedWidthFont
= false;
250 m_xValueDetails
->set_monospace(bFixedWidthFont
);
251 m_xValueDetails
->set_text(aElementText
);
254 CertificateViewerCertPathTP::CertificateViewerCertPathTP(weld::Container
* pParent
, CertificateViewer
* pDlg
)
255 : CertificateViewerTP(pParent
, "xmlsec/ui/certpage.ui", "CertPage", 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"))
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
);
270 mxCertPathLB
->connect_changed( LINK( this, CertificateViewerCertPathTP
, CertSelectHdl
) );
271 mxViewCertPB
->connect_clicked( LINK( this, CertificateViewerCertPathTP
, ViewCertHdl
) );
274 CertificateViewerCertPathTP::~CertificateViewerCertPathTP()
276 if (mxCertificateViewer
)
277 mxCertificateViewer
->response(RET_OK
);
280 void CertificateViewerCertPathTP::ActivatePage()
282 if ( mbFirstActivateDone
)
285 mbFirstActivateDone
= true;
286 Sequence
< Reference
< security::XCertificate
> > aCertPath
=
287 mpParent
->mxSecurityEnvironment
->buildCertificatePath( mpParent
->mxCert
);
288 const Reference
< security::XCertificate
>* pCertPath
= aCertPath
.getConstArray();
290 sal_Int32 i
, nCnt
= aCertPath
.getLength();
291 std::unique_ptr
<weld::TreeIter
> xParent
;
292 for (i
= nCnt
-1; i
>= 0; i
--)
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
);
303 xParent
= mxCertPathLB
->make_iterator();
304 (void)mxCertPathLB
->get_iter_first(*xParent
);
308 (void)mxCertPathLB
->iter_children(*xParent
);
313 mxCertPathLB
->select(*xParent
);
314 mxViewCertPB
->set_sensitive(false); // Own certificate selected
318 mxCertPathLB
->expand_row(*xParent
);
319 if (!mxCertPathLB
->iter_parent(*xParent
))
323 CertSelectHdl(*mxCertPathLB
);
326 IMPL_LINK_NOARG(CertificateViewerCertPathTP
, ViewCertHdl
, weld::Button
&, void)
328 std::unique_ptr
<weld::TreeIter
> xIter
= mxCertPathLB
->make_iterator();
329 if (mxCertPathLB
->get_selected(xIter
.get()))
331 if (mxCertificateViewer
)
332 mxCertificateViewer
->response(RET_OK
);
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; });
341 IMPL_LINK_NOARG(CertificateViewerCertPathTP
, CertSelectHdl
, weld::TreeView
&, void)
345 std::unique_ptr
<weld::TreeIter
> xIter
= mxCertPathLB
->make_iterator();
346 bool bEntry
= mxCertPathLB
->get_selected(xIter
.get());
349 CertPath_UserData
* pData
= weld::fromId
<CertPath_UserData
*>(mxCertPathLB
->get_id(*xIter
));
351 sStatus
= pData
->mbValid
? mxCertOK
->get_label() : mxCertNotValidated
->get_label();
354 mxCertStatusML
->set_text(sStatus
);
356 bool bSensitive
= false;
359 // if has children, so not the last one in the chain
360 if (mxCertPathLB
->iter_children(*xIter
))
363 mxViewCertPB
->set_sensitive(bSensitive
);
366 void CertificateViewerCertPathTP::InsertCert(const weld::TreeIter
* pParent
, const OUString
& rName
,
367 const css::uno::Reference
< css::security::XCertificate
>& rxCert
,
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
));
377 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */