nss: upgrade to release 3.73
[LibreOffice.git] / uui / source / iahndl-ssl.cxx
blobdf156bc44e3a8e2adc62088401738a8ace312f8d
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*
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 <svl/zforlist.hxx>
35 #include <unotools/resmgr.hxx>
36 #include <vcl/svapp.hxx>
37 #include <vcl/settings.hxx>
39 #include <ids.hrc>
40 #include "getcontinuations.hxx"
41 #include "sslwarndlg.hxx"
42 #include "unknownauthdlg.hxx"
44 #include "iahndl.hxx"
46 #include <memory>
48 #define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17"
51 using namespace com::sun::star;
53 namespace {
55 OUString
56 getContentPart( const OUString& _rRawString )
58 // search over some parts to find a string
59 static char const * aIDs[] = { "CN=", "OU=", "O=", "E=", nullptr };
60 OUString sPart;
61 int i = 0;
62 while ( aIDs[i] )
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 );
70 if ( nContEnd != -1 )
71 sPart = _rRawString.copy( nContStart, nContEnd - nContStart );
72 else
73 sPart = _rRawString.copy( nContStart );
74 break;
77 return sPart;
80 bool
81 isDomainMatch(
82 const OUString& hostName, const uno::Sequence< OUString >& certHostNames)
84 for ( const OUString& element : certHostNames){
85 if (element.isEmpty())
86 continue;
88 if (hostName.equalsIgnoreAsciiCase( element ))
89 return true;
91 if (element.startsWith("*") &&
92 hostName.getLength() >= element.getLength() )
94 OUString cmpStr = element.copy( 1 );
95 if ( hostName.matchIgnoreAsciiCase(
96 cmpStr, hostName.getLength() - cmpStr.getLength()) )
97 return true;
101 return false;
104 OUString
105 getLocalizedDatTimeStr(
106 uno::Reference< uno::XComponentContext> const & xContext,
107 util::DateTime const & rDateTime )
109 OUString aDateTimeStr;
110 Date aDate( Date::EMPTY );
111 tools::Time aTime( tools::Time::EMPTY );
113 aDate = Date( rDateTime.Day, rDateTime.Month, rDateTime.Year );
114 aTime = tools::Time( rDateTime.Hours, rDateTime.Minutes, rDateTime.Seconds );
116 LanguageType eUILang = Application::GetSettings().GetUILanguageTag().getLanguageType();
117 SvNumberFormatter *pNumberFormatter = new SvNumberFormatter( xContext, eUILang );
118 OUString aTmpStr;
119 const Color* pColor = nullptr;
120 const Date& rNullDate = pNumberFormatter->GetNullDate();
121 sal_uInt32 nFormat
122 = pNumberFormatter->GetStandardFormat( SvNumFormatType::DATE, eUILang );
124 pNumberFormatter->GetOutputString( aDate - rNullDate, nFormat, aTmpStr, &pColor );
125 aDateTimeStr = aTmpStr + " ";
127 nFormat = pNumberFormatter->GetStandardFormat( SvNumFormatType::TIME, eUILang );
128 pNumberFormatter->GetOutputString(
129 aTime.GetTimeInDays(), nFormat, aTmpStr, &pColor );
130 aDateTimeStr += aTmpStr;
132 return aDateTimeStr;
135 bool
136 executeUnknownAuthDialog(
137 weld::Window * pParent,
138 uno::Reference< uno::XComponentContext > const & xContext,
139 const uno::Reference< security::XCertificate >& rXCert)
141 SolarMutexGuard aGuard;
143 UnknownAuthDialog aDialog(pParent, rXCert, xContext);
145 // Get correct resource string
146 OUString aMessage;
148 std::vector< OUString > aArguments;
149 aArguments.push_back( getContentPart( rXCert->getSubjectName()) );
151 std::locale aResLocale(Translate::Create("uui"));
153 aMessage = Translate::get(STR_UUI_UNKNOWNAUTH_UNTRUSTED, aResLocale);
154 aMessage = UUIInteractionHelper::replaceMessageWithArguments(
155 aMessage, aArguments );
156 aDialog.setDescriptionText( aMessage );
158 return static_cast<bool>(aDialog.run());
161 enum class SslWarnType {
162 DOMAINMISMATCH, EXPIRED, INVALID
165 bool
166 executeSSLWarnDialog(
167 weld::Window * pParent,
168 uno::Reference< uno::XComponentContext > const & xContext,
169 const uno::Reference< security::XCertificate >& rXCert,
170 SslWarnType failure,
171 const OUString & hostName )
173 SolarMutexGuard aGuard;
175 SSLWarnDialog aDialog(pParent, rXCert, xContext);
177 // Get correct resource string
178 std::vector< OUString > aArguments_1;
179 char const * pMessageKey = nullptr;
180 char const * pTitleKey = nullptr;
182 switch( failure )
184 case SslWarnType::DOMAINMISMATCH:
185 pMessageKey = STR_UUI_SSLWARN_DOMAINMISMATCH;
186 pTitleKey = STR_UUI_SSLWARN_DOMAINMISMATCH_TITLE;
187 aArguments_1.push_back( hostName );
188 aArguments_1.push_back(
189 getContentPart( rXCert->getSubjectName()) );
190 aArguments_1.push_back( hostName );
191 break;
192 case SslWarnType::EXPIRED:
193 pMessageKey = STR_UUI_SSLWARN_EXPIRED;
194 pTitleKey = STR_UUI_SSLWARN_EXPIRED_TITLE;
195 aArguments_1.push_back(
196 getContentPart( rXCert->getSubjectName()) );
197 aArguments_1.push_back(
198 getLocalizedDatTimeStr( xContext,
199 rXCert->getNotValidAfter() ) );
200 aArguments_1.push_back(
201 getLocalizedDatTimeStr( xContext,
202 rXCert->getNotValidAfter() ) );
203 break;
204 case SslWarnType::INVALID:
205 pMessageKey = STR_UUI_SSLWARN_INVALID;
206 pTitleKey = STR_UUI_SSLWARN_INVALID_TITLE;
207 break;
208 default: assert(false);
211 std::locale aResLocale(Translate::Create("uui"));
213 OUString aMessage_1 = Translate::get(pMessageKey, aResLocale);
214 aMessage_1 = UUIInteractionHelper::replaceMessageWithArguments(
215 aMessage_1, aArguments_1 );
216 aDialog.setDescription1Text( aMessage_1 );
218 OUString aTitle = Translate::get(pTitleKey, aResLocale);
219 aDialog.set_title(aTitle);
221 return static_cast<bool>(aDialog.run());
224 void
225 handleCertificateValidationRequest_(
226 weld::Window * pParent,
227 uno::Reference< uno::XComponentContext > const & xContext,
228 ucb::CertificateValidationRequest const & rRequest,
229 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
230 rContinuations)
232 uno::Reference< task::XInteractionApprove > xApprove;
233 uno::Reference< task::XInteractionAbort > xAbort;
234 getContinuations(rContinuations, &xApprove, &xAbort);
236 if ( comphelper::LibreOfficeKit::isActive() && xApprove.is() )
238 xApprove->select();
239 return;
242 sal_Int32 failures = rRequest.CertificateValidity;
243 bool trustCert = true;
245 if ( ((failures & security::CertificateValidity::UNTRUSTED)
246 == security::CertificateValidity::UNTRUSTED ) ||
247 ((failures & security::CertificateValidity::ISSUER_UNTRUSTED)
248 == security::CertificateValidity::ISSUER_UNTRUSTED) ||
249 ((failures & security::CertificateValidity::ROOT_UNTRUSTED)
250 == security::CertificateValidity::ROOT_UNTRUSTED) )
252 trustCert = executeUnknownAuthDialog( pParent,
253 xContext,
254 rRequest.Certificate );
257 uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = rRequest.Certificate->getExtensions();
258 uno::Reference< security::XSanExtension > sanExtension;
259 auto pExtension = std::find_if(extensions.begin(), extensions.end(),
260 [](const uno::Reference< security::XCertificateExtension >& element) {
261 OString aId ( reinterpret_cast<const char *>(element->getExtensionId().getConstArray()), element->getExtensionId().getLength());
262 return aId == OID_SUBJECT_ALTERNATIVE_NAME;
264 if (pExtension != extensions.end())
266 sanExtension = uno::Reference<security::XSanExtension>(*pExtension, uno::UNO_QUERY);
269 std::vector<security::CertAltNameEntry> altNames;
270 if (sanExtension.is())
272 altNames = comphelper::sequenceToContainer<std::vector<security::CertAltNameEntry>>(sanExtension->getAlternativeNames());
275 OUString certHostName = getContentPart( rRequest.Certificate->getSubjectName() );
276 uno::Sequence< OUString > certHostNames(altNames.size() + 1);
278 certHostNames[0] = certHostName;
280 for (size_t n = 0; n < altNames.size(); ++n)
282 if (altNames[n].Type == security::ExtAltNameType_DNS_NAME)
284 altNames[n].Value >>= certHostNames[n+1];
288 if ( (!isDomainMatch(
289 rRequest.HostName,
290 certHostNames )) &&
291 trustCert )
293 trustCert = executeSSLWarnDialog( pParent,
294 xContext,
295 rRequest.Certificate,
296 SslWarnType::DOMAINMISMATCH,
297 rRequest.HostName );
300 else if ( (((failures & security::CertificateValidity::TIME_INVALID)
301 == security::CertificateValidity::TIME_INVALID) ||
302 ((failures & security::CertificateValidity::NOT_TIME_NESTED)
303 == security::CertificateValidity::NOT_TIME_NESTED)) &&
304 trustCert )
306 trustCert = executeSSLWarnDialog( pParent,
307 xContext,
308 rRequest.Certificate,
309 SslWarnType::EXPIRED,
310 rRequest.HostName );
313 else if ( (((failures & security::CertificateValidity::REVOKED)
314 == security::CertificateValidity::REVOKED) ||
315 ((failures & security::CertificateValidity::SIGNATURE_INVALID)
316 == security::CertificateValidity::SIGNATURE_INVALID) ||
317 ((failures & security::CertificateValidity::EXTENSION_INVALID)
318 == security::CertificateValidity::EXTENSION_INVALID) ||
319 ((failures & security::CertificateValidity::INVALID)
320 == security::CertificateValidity::INVALID)) &&
321 trustCert )
323 trustCert = executeSSLWarnDialog( pParent,
324 xContext,
325 rRequest.Certificate,
326 SslWarnType::INVALID,
327 rRequest.HostName );
330 if ( trustCert )
332 if (xApprove.is())
333 xApprove->select();
335 else
337 if (xAbort.is())
338 xAbort->select();
342 } // namespace
344 bool
345 UUIInteractionHelper::handleCertificateValidationRequest(
346 uno::Reference< task::XInteractionRequest > const & rRequest)
348 uno::Any aAnyRequest(rRequest->getRequest());
350 ucb::CertificateValidationRequest aCertificateValidationRequest;
351 if (aAnyRequest >>= aCertificateValidationRequest)
353 uno::Reference<awt::XWindow> xParent = getParentXWindow();
354 handleCertificateValidationRequest_(Application::GetFrameWeld(xParent),
355 m_xContext,
356 aCertificateValidationRequest,
357 rRequest->getContinuations());
358 return true;
361 return false;
364 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */