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 .
21 #include <com/sun/star/security/CertificateValidity.hpp>
22 #include <com/sun/star/security/XCertificateExtension.hpp>
23 #include <com/sun/star/security/XSanExtension.hpp>
24 #include <com/sun/star/security/ExtAltNameType.hpp>
25 #include <com/sun/star/task/XInteractionAbort.hpp>
26 #include <com/sun/star/task/XInteractionApprove.hpp>
27 #include <com/sun/star/task/XInteractionRequest.hpp>
28 #include <com/sun/star/ucb/CertificateValidationRequest.hpp>
29 #include <com/sun/star/uno/Reference.hxx>
31 #include <comphelper/lok.hxx>
32 #include <comphelper/sequence.hxx>
33 #include <com/sun/star/uno/Sequence.hxx>
34 #include <o3tl/string_view.hxx>
35 #include <svl/numformat.hxx>
36 #include <svl/zforlist.hxx>
37 #include <unotools/resmgr.hxx>
38 #include <vcl/svapp.hxx>
39 #include <vcl/settings.hxx>
42 #include "getcontinuations.hxx"
43 #include "sslwarndlg.hxx"
44 #include "unknownauthdlg.hxx"
50 #define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17"
53 using namespace com::sun::star
;
58 getContentPart( std::u16string_view _rRawString
)
60 // search over some parts to find a string
61 static char const * aIDs
[] = { "CN=", "OU=", "O=", "E=", nullptr };
66 OUString sPartId
= OUString::createFromAscii( aIDs
[i
++] );
67 size_t nContStart
= _rRawString
.find( sPartId
);
68 if ( nContStart
!= std::u16string_view::npos
)
70 nContStart
+= sPartId
.getLength();
71 size_t nContEnd
= _rRawString
.find( ',', nContStart
);
72 if ( nContEnd
!= std::u16string_view::npos
)
73 sPart
= _rRawString
.substr( nContStart
, nContEnd
- nContStart
);
75 sPart
= _rRawString
.substr( nContStart
);
84 std::u16string_view hostName
, const uno::Sequence
< OUString
>& certHostNames
)
86 for ( const OUString
& element
: certHostNames
){
87 if (element
.isEmpty())
90 if (o3tl::equalsIgnoreAsciiCase( hostName
, element
))
93 if (element
.startsWith("*") &&
94 sal_Int32(hostName
.size()) >= element
.getLength() )
96 OUString cmpStr
= element
.copy( 1 );
97 if ( o3tl::matchIgnoreAsciiCase(hostName
,
98 cmpStr
, hostName
.size() - cmpStr
.getLength()) )
107 getLocalizedDatTimeStr(
108 uno::Reference
< uno::XComponentContext
> const & xContext
,
109 util::DateTime
const & rDateTime
)
111 OUString aDateTimeStr
;
112 Date
aDate( Date::EMPTY
);
113 tools::Time
aTime( tools::Time::EMPTY
);
115 aDate
= Date( rDateTime
.Day
, rDateTime
.Month
, rDateTime
.Year
);
116 aTime
= tools::Time( rDateTime
.Hours
, rDateTime
.Minutes
, rDateTime
.Seconds
);
118 LanguageType eUILang
= Application::GetSettings().GetUILanguageTag().getLanguageType();
119 SvNumberFormatter
*pNumberFormatter
= new SvNumberFormatter( xContext
, eUILang
);
121 const Color
* pColor
= nullptr;
122 const Date
& rNullDate
= pNumberFormatter
->GetNullDate();
124 = pNumberFormatter
->GetStandardFormat( SvNumFormatType::DATE
, eUILang
);
126 pNumberFormatter
->GetOutputString( aDate
- rNullDate
, nFormat
, aTmpStr
, &pColor
);
127 aDateTimeStr
= aTmpStr
+ " ";
129 nFormat
= pNumberFormatter
->GetStandardFormat( SvNumFormatType::TIME
, eUILang
);
130 pNumberFormatter
->GetOutputString(
131 aTime
.GetTimeInDays(), nFormat
, aTmpStr
, &pColor
);
132 aDateTimeStr
+= aTmpStr
;
138 executeUnknownAuthDialog(
139 weld::Window
* pParent
,
140 uno::Reference
< uno::XComponentContext
> const & xContext
,
141 const uno::Reference
< security::XCertificate
>& rXCert
)
143 SolarMutexGuard aGuard
;
145 UnknownAuthDialog
aDialog(pParent
, rXCert
, xContext
);
147 // Get correct resource string
150 std::vector
< OUString
> aArguments
{ getContentPart( rXCert
->getSubjectName()) };
152 std::locale
aResLocale(Translate::Create("uui"));
154 aMessage
= Translate::get(STR_UUI_UNKNOWNAUTH_UNTRUSTED
, aResLocale
);
155 aMessage
= UUIInteractionHelper::replaceMessageWithArguments(
156 aMessage
, aArguments
);
157 aDialog
.setDescriptionText( aMessage
);
159 return static_cast<bool>(aDialog
.run());
162 enum class SslWarnType
{
163 DOMAINMISMATCH
, EXPIRED
, INVALID
167 executeSSLWarnDialog(
168 weld::Window
* pParent
,
169 uno::Reference
< uno::XComponentContext
> const & xContext
,
170 const uno::Reference
< security::XCertificate
>& rXCert
,
172 const OUString
& hostName
)
174 SolarMutexGuard aGuard
;
176 SSLWarnDialog
aDialog(pParent
, rXCert
, xContext
);
178 // Get correct resource string
179 std::vector
< OUString
> aArguments_1
;
180 TranslateId pMessageKey
;
181 TranslateId pTitleKey
;
185 case SslWarnType::DOMAINMISMATCH
:
186 pMessageKey
= STR_UUI_SSLWARN_DOMAINMISMATCH
;
187 pTitleKey
= STR_UUI_SSLWARN_DOMAINMISMATCH_TITLE
;
188 aArguments_1
.push_back( hostName
);
189 aArguments_1
.push_back(
190 getContentPart( rXCert
->getSubjectName()) );
191 aArguments_1
.push_back( hostName
);
193 case SslWarnType::EXPIRED
:
194 pMessageKey
= STR_UUI_SSLWARN_EXPIRED
;
195 pTitleKey
= STR_UUI_SSLWARN_EXPIRED_TITLE
;
196 aArguments_1
.push_back(
197 getContentPart( rXCert
->getSubjectName()) );
198 aArguments_1
.push_back(
199 getLocalizedDatTimeStr( xContext
,
200 rXCert
->getNotValidAfter() ) );
201 aArguments_1
.push_back(
202 getLocalizedDatTimeStr( xContext
,
203 rXCert
->getNotValidAfter() ) );
205 case SslWarnType::INVALID
:
206 pMessageKey
= STR_UUI_SSLWARN_INVALID
;
207 pTitleKey
= STR_UUI_SSLWARN_INVALID_TITLE
;
209 default: assert(false);
212 std::locale
aResLocale(Translate::Create("uui"));
214 OUString aMessage_1
= Translate::get(pMessageKey
, aResLocale
);
215 aMessage_1
= UUIInteractionHelper::replaceMessageWithArguments(
216 aMessage_1
, aArguments_1
);
217 aDialog
.setDescription1Text( aMessage_1
);
219 OUString aTitle
= Translate::get(pTitleKey
, aResLocale
);
220 aDialog
.set_title(aTitle
);
222 return static_cast<bool>(aDialog
.run());
226 handleCertificateValidationRequest_(
227 weld::Window
* pParent
,
228 uno::Reference
< uno::XComponentContext
> const & xContext
,
229 ucb::CertificateValidationRequest
const & rRequest
,
230 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > const &
233 uno::Reference
< task::XInteractionApprove
> xApprove
;
234 uno::Reference
< task::XInteractionAbort
> xAbort
;
235 getContinuations(rContinuations
, &xApprove
, &xAbort
);
237 if ( comphelper::LibreOfficeKit::isActive() && xApprove
.is() )
243 sal_Int32 failures
= rRequest
.CertificateValidity
;
244 bool trustCert
= true;
246 if ( ((failures
& security::CertificateValidity::UNTRUSTED
)
247 == security::CertificateValidity::UNTRUSTED
) ||
248 ((failures
& security::CertificateValidity::ISSUER_UNTRUSTED
)
249 == security::CertificateValidity::ISSUER_UNTRUSTED
) ||
250 ((failures
& security::CertificateValidity::ROOT_UNTRUSTED
)
251 == security::CertificateValidity::ROOT_UNTRUSTED
) )
253 trustCert
= executeUnknownAuthDialog( pParent
,
255 rRequest
.Certificate
);
258 const uno::Sequence
< uno::Reference
< security::XCertificateExtension
> > extensions
= rRequest
.Certificate
->getExtensions();
259 uno::Reference
< security::XSanExtension
> sanExtension
;
260 auto pExtension
= std::find_if(extensions
.begin(), extensions
.end(),
261 [](const uno::Reference
< security::XCertificateExtension
>& element
) {
262 OString
aId ( reinterpret_cast<const char *>(element
->getExtensionId().getConstArray()), element
->getExtensionId().getLength());
263 return aId
== OID_SUBJECT_ALTERNATIVE_NAME
;
265 if (pExtension
!= extensions
.end())
267 sanExtension
= uno::Reference
<security::XSanExtension
>(*pExtension
, uno::UNO_QUERY
);
270 std::vector
<security::CertAltNameEntry
> altNames
;
271 if (sanExtension
.is())
273 altNames
= comphelper::sequenceToContainer
<std::vector
<security::CertAltNameEntry
>>(sanExtension
->getAlternativeNames());
276 OUString certHostName
= getContentPart( rRequest
.Certificate
->getSubjectName() );
277 uno::Sequence
< OUString
> certHostNames(altNames
.size() + 1);
278 auto pcertHostNames
= certHostNames
.getArray();
279 pcertHostNames
[0] = certHostName
;
281 for (size_t n
= 0; n
< altNames
.size(); ++n
)
283 if (altNames
[n
].Type
== security::ExtAltNameType_DNS_NAME
)
285 altNames
[n
].Value
>>= pcertHostNames
[n
+1];
289 if ( (!isDomainMatch(
294 trustCert
= executeSSLWarnDialog( pParent
,
296 rRequest
.Certificate
,
297 SslWarnType::DOMAINMISMATCH
,
301 else if ( (((failures
& security::CertificateValidity::TIME_INVALID
)
302 == security::CertificateValidity::TIME_INVALID
) ||
303 ((failures
& security::CertificateValidity::NOT_TIME_NESTED
)
304 == security::CertificateValidity::NOT_TIME_NESTED
)) &&
307 trustCert
= executeSSLWarnDialog( pParent
,
309 rRequest
.Certificate
,
310 SslWarnType::EXPIRED
,
314 else if ( (((failures
& security::CertificateValidity::REVOKED
)
315 == security::CertificateValidity::REVOKED
) ||
316 ((failures
& security::CertificateValidity::SIGNATURE_INVALID
)
317 == security::CertificateValidity::SIGNATURE_INVALID
) ||
318 ((failures
& security::CertificateValidity::EXTENSION_INVALID
)
319 == security::CertificateValidity::EXTENSION_INVALID
) ||
320 ((failures
& security::CertificateValidity::INVALID
)
321 == security::CertificateValidity::INVALID
)) &&
324 trustCert
= executeSSLWarnDialog( pParent
,
326 rRequest
.Certificate
,
327 SslWarnType::INVALID
,
346 UUIInteractionHelper::handleCertificateValidationRequest(
347 uno::Reference
< task::XInteractionRequest
> const & rRequest
)
349 uno::Any
aAnyRequest(rRequest
->getRequest());
351 ucb::CertificateValidationRequest aCertificateValidationRequest
;
352 if (aAnyRequest
>>= aCertificateValidationRequest
)
354 uno::Reference
<awt::XWindow
> xParent
= getParentXWindow();
355 handleCertificateValidationRequest_(Application::GetFrameWeld(xParent
),
357 aCertificateValidationRequest
,
358 rRequest
->getContinuations());
365 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */