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/sequence.hxx>
32 #include <com/sun/star/uno/Sequence.hxx>
33 #include <svl/zforlist.hxx>
34 #include <unotools/resmgr.hxx>
35 #include <vcl/svapp.hxx>
36 #include <vcl/settings.hxx>
40 #include "getcontinuations.hxx"
41 #include "sslwarndlg.hxx"
42 #include "unknownauthdlg.hxx"
48 #define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17"
51 using namespace com::sun::star
;
56 getContentPart( const OUString
& _rRawString
)
58 // search over some parts to find a string
59 static char const * aIDs
[] = { "CN=", "OU=", "O=", "E=", nullptr };
64 OUString sPartId
= OUString::createFromAscii( aIDs
[i
++] );
65 sal_Int32 nContStart
= _rRawString
.indexOf( sPartId
);
66 if ( nContStart
!= -1 )
68 nContStart
+= sPartId
.getLength();
69 sal_Int32 nContEnd
= _rRawString
.indexOf( ',', nContStart
);
71 sPart
= _rRawString
.copy( nContStart
, nContEnd
- nContStart
);
73 sPart
= _rRawString
.copy( nContStart
);
82 const OUString
& hostName
, const uno::Sequence
< OUString
>& certHostNames
)
84 for ( int i
= 0; i
< certHostNames
.getLength(); i
++){
85 OUString element
= certHostNames
[i
];
87 if (element
.isEmpty())
90 if (hostName
.equalsIgnoreAsciiCase( element
))
93 if (element
.startsWith("*") &&
94 hostName
.getLength() >= element
.getLength() )
96 OUString cmpStr
= element
.copy( 1 );
97 if ( hostName
.matchIgnoreAsciiCase(
98 cmpStr
, hostName
.getLength() - 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 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
;
151 aArguments
.push_back( getContentPart( rXCert
->getSubjectName()) );
153 std::locale
aResLocale(Translate::Create("uui"));
154 ErrorResource
aErrorResource(RID_UUI_ERRHDL
, aResLocale
);
156 aMessage
= Translate::get(STR_UUI_UNKNOWNAUTH_UNTRUSTED
, aResLocale
);
157 aMessage
= UUIInteractionHelper::replaceMessageWithArguments(
158 aMessage
, aArguments
);
159 aDialog
.setDescriptionText( aMessage
);
161 return static_cast<bool>(aDialog
.run());
164 enum class SslWarnType
{
165 DOMAINMISMATCH
, EXPIRED
, INVALID
169 executeSSLWarnDialog(
170 weld::Window
* pParent
,
171 uno::Reference
< uno::XComponentContext
> const & xContext
,
172 const uno::Reference
< security::XCertificate
>& rXCert
,
174 const OUString
& hostName
)
176 SolarMutexGuard aGuard
;
178 SSLWarnDialog
aDialog(pParent
, rXCert
, xContext
);
180 // Get correct resource string
181 std::vector
< OUString
> aArguments_1
;
182 char const * pMessageKey
= nullptr;
183 char const * pTitleKey
= nullptr;
187 case SslWarnType::DOMAINMISMATCH
:
188 pMessageKey
= STR_UUI_SSLWARN_DOMAINMISMATCH
;
189 pTitleKey
= STR_UUI_SSLWARN_DOMAINMISMATCH_TITLE
;
190 aArguments_1
.push_back( hostName
);
191 aArguments_1
.push_back(
192 getContentPart( rXCert
->getSubjectName()) );
193 aArguments_1
.push_back( hostName
);
195 case SslWarnType::EXPIRED
:
196 pMessageKey
= STR_UUI_SSLWARN_EXPIRED
;
197 pTitleKey
= STR_UUI_SSLWARN_EXPIRED_TITLE
;
198 aArguments_1
.push_back(
199 getContentPart( rXCert
->getSubjectName()) );
200 aArguments_1
.push_back(
201 getLocalizedDatTimeStr( xContext
,
202 rXCert
->getNotValidAfter() ) );
203 aArguments_1
.push_back(
204 getLocalizedDatTimeStr( xContext
,
205 rXCert
->getNotValidAfter() ) );
207 case SslWarnType::INVALID
:
208 pMessageKey
= STR_UUI_SSLWARN_INVALID
;
209 pTitleKey
= STR_UUI_SSLWARN_INVALID_TITLE
;
211 default: assert(false);
214 std::locale
aResLocale(Translate::Create("uui"));
216 OUString aMessage_1
= Translate::get(pMessageKey
, aResLocale
);
217 aMessage_1
= UUIInteractionHelper::replaceMessageWithArguments(
218 aMessage_1
, aArguments_1
);
219 aDialog
.setDescription1Text( aMessage_1
);
221 OUString aTitle
= Translate::get(pTitleKey
, aResLocale
);
222 aDialog
.set_title(aTitle
);
224 return static_cast<bool>(aDialog
.run());
228 handleCertificateValidationRequest_(
229 weld::Window
* pParent
,
230 uno::Reference
< uno::XComponentContext
> const & xContext
,
231 ucb::CertificateValidationRequest
const & rRequest
,
232 uno::Sequence
< uno::Reference
< task::XInteractionContinuation
> > const &
235 uno::Reference
< task::XInteractionApprove
> xApprove
;
236 uno::Reference
< task::XInteractionAbort
> xAbort
;
237 getContinuations(rContinuations
, &xApprove
, &xAbort
);
239 sal_Int32 failures
= rRequest
.CertificateValidity
;
240 bool trustCert
= true;
242 if ( ((failures
& security::CertificateValidity::UNTRUSTED
)
243 == security::CertificateValidity::UNTRUSTED
) ||
244 ((failures
& security::CertificateValidity::ISSUER_UNTRUSTED
)
245 == security::CertificateValidity::ISSUER_UNTRUSTED
) ||
246 ((failures
& security::CertificateValidity::ROOT_UNTRUSTED
)
247 == security::CertificateValidity::ROOT_UNTRUSTED
) )
249 trustCert
= executeUnknownAuthDialog( pParent
,
251 rRequest
.Certificate
);
254 uno::Sequence
< uno::Reference
< security::XCertificateExtension
> > extensions
= rRequest
.Certificate
->getExtensions();
255 uno::Reference
< security::XSanExtension
> sanExtension
;
256 for (sal_Int32 i
= 0 ; i
< extensions
.getLength(); ++i
)
258 uno::Reference
< security::XCertificateExtension
>element
= extensions
[i
];
259 OString
aId ( reinterpret_cast<const char *>(element
->getExtensionId().getConstArray()), element
->getExtensionId().getLength());
260 if (aId
== OID_SUBJECT_ALTERNATIVE_NAME
)
262 sanExtension
= uno::Reference
<security::XSanExtension
>(element
, uno::UNO_QUERY
);
267 std::vector
<security::CertAltNameEntry
> altNames
;
268 if (sanExtension
.is())
270 altNames
= comphelper::sequenceToContainer
<std::vector
<security::CertAltNameEntry
>>(sanExtension
->getAlternativeNames());
273 OUString certHostName
= getContentPart( rRequest
.Certificate
->getSubjectName() );
274 uno::Sequence
< OUString
> certHostNames(altNames
.size() + 1);
276 certHostNames
[0] = certHostName
;
278 for (size_t n
= 0; n
< altNames
.size(); ++n
)
280 if (altNames
[n
].Type
== security::ExtAltNameType_DNS_NAME
)
282 altNames
[n
].Value
>>= certHostNames
[n
+1];
286 if ( (!isDomainMatch(
291 trustCert
= executeSSLWarnDialog( pParent
,
293 rRequest
.Certificate
,
294 SslWarnType::DOMAINMISMATCH
,
298 else if ( (((failures
& security::CertificateValidity::TIME_INVALID
)
299 == security::CertificateValidity::TIME_INVALID
) ||
300 ((failures
& security::CertificateValidity::NOT_TIME_NESTED
)
301 == security::CertificateValidity::NOT_TIME_NESTED
)) &&
304 trustCert
= executeSSLWarnDialog( pParent
,
306 rRequest
.Certificate
,
307 SslWarnType::EXPIRED
,
311 else if ( (((failures
& security::CertificateValidity::REVOKED
)
312 == security::CertificateValidity::REVOKED
) ||
313 ((failures
& security::CertificateValidity::SIGNATURE_INVALID
)
314 == security::CertificateValidity::SIGNATURE_INVALID
) ||
315 ((failures
& security::CertificateValidity::EXTENSION_INVALID
)
316 == security::CertificateValidity::EXTENSION_INVALID
) ||
317 ((failures
& security::CertificateValidity::INVALID
)
318 == security::CertificateValidity::INVALID
)) &&
321 trustCert
= executeSSLWarnDialog( pParent
,
323 rRequest
.Certificate
,
324 SslWarnType::INVALID
,
343 UUIInteractionHelper::handleCertificateValidationRequest(
344 uno::Reference
< task::XInteractionRequest
> const & rRequest
)
346 uno::Any
aAnyRequest(rRequest
->getRequest());
348 ucb::CertificateValidationRequest aCertificateValidationRequest
;
349 if (aAnyRequest
>>= aCertificateValidationRequest
)
351 uno::Reference
<awt::XWindow
> xParent
= getParentXWindow();
352 handleCertificateValidationRequest_(Application::GetFrameWeld(xParent
),
354 aCertificateValidationRequest
,
355 rRequest
->getContinuations());
362 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */