Version 6.1.4.1, tag libreoffice-6.1.4.1
[LibreOffice.git] / uui / source / iahndl-ssl.cxx
blob096f81b21d4c08a03d1826d853c856cb979a0189
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/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>
38 #include <ids.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 ( int i = 0; i < certHostNames.getLength(); i++){
85 OUString element = certHostNames[i];
87 if (element.isEmpty())
88 continue;
90 if (hostName.equalsIgnoreAsciiCase( element ))
91 return true;
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()) )
99 return true;
103 return false;
106 OUString
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 );
120 OUString aTmpStr;
121 Color* pColor = nullptr;
122 const Date& rNullDate = pNumberFormatter->GetNullDate();
123 sal_uInt32 nFormat
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;
134 return aDateTimeStr;
137 bool
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
148 OUString aMessage;
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
168 bool
169 executeSSLWarnDialog(
170 weld::Window * pParent,
171 uno::Reference< uno::XComponentContext > const & xContext,
172 const uno::Reference< security::XCertificate >& rXCert,
173 SslWarnType failure,
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;
185 switch( failure )
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 );
194 break;
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() ) );
206 break;
207 case SslWarnType::INVALID:
208 pMessageKey = STR_UUI_SSLWARN_INVALID;
209 pTitleKey = STR_UUI_SSLWARN_INVALID_TITLE;
210 break;
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());
227 void
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 &
233 rContinuations)
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,
250 xContext,
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);
263 break;
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(
287 rRequest.HostName,
288 certHostNames )) &&
289 trustCert )
291 trustCert = executeSSLWarnDialog( pParent,
292 xContext,
293 rRequest.Certificate,
294 SslWarnType::DOMAINMISMATCH,
295 rRequest.HostName );
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)) &&
302 trustCert )
304 trustCert = executeSSLWarnDialog( pParent,
305 xContext,
306 rRequest.Certificate,
307 SslWarnType::EXPIRED,
308 rRequest.HostName );
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)) &&
319 trustCert )
321 trustCert = executeSSLWarnDialog( pParent,
322 xContext,
323 rRequest.Certificate,
324 SslWarnType::INVALID,
325 rRequest.HostName );
328 if ( trustCert )
330 if (xApprove.is())
331 xApprove->select();
333 else
335 if (xAbort.is())
336 xAbort->select();
340 } // namespace
342 bool
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),
353 m_xContext,
354 aCertificateValidationRequest,
355 rRequest->getContinuations());
356 return true;
359 return false;
362 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */