Version 3.6.0.4, tag libreoffice-3.6.0.4
[LibreOffice.git] / uui / source / iahndl-ssl.cxx
blob06ef9b70b7a3f0de8f1906df04e08f726da18a91
1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 /*************************************************************************
4 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
6 * Copyright 2000, 2010 Oracle and/or its affiliates.
8 * OpenOffice.org - a multi-platform office productivity suite
10 * This file is part of OpenOffice.org.
12 * OpenOffice.org is free software: you can redistribute it and/or modify
13 * it under the terms of the GNU Lesser General Public License version 3
14 * only, as published by the Free Software Foundation.
16 * OpenOffice.org is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License version 3 for more details
20 * (a copy is included in the LICENSE file that accompanied this code).
22 * You should have received a copy of the GNU Lesser General Public License
23 * version 3 along with OpenOffice.org. If not, see
24 * <http://www.openoffice.org/license.html>
25 * for a copy of the LGPLv3 License.
27 ************************************************************************/
30 #include "com/sun/star/security/CertificateValidity.hpp"
31 #include "com/sun/star/security/XCertificateExtension.hpp"
32 #include "com/sun/star/security/XSanExtension.hpp"
33 #include <com/sun/star/security/ExtAltNameType.hpp>
34 #include "com/sun/star/task/XInteractionAbort.hpp"
35 #include "com/sun/star/task/XInteractionApprove.hpp"
36 #include "com/sun/star/task/XInteractionRequest.hpp"
37 #include "com/sun/star/ucb/CertificateValidationRequest.hpp"
38 #include <com/sun/star/uno/Reference.hxx>
40 #include "osl/mutex.hxx"
41 #include <com/sun/star/uno/Sequence.hxx>
42 #include "svl/zforlist.hxx"
43 #include "vcl/svapp.hxx"
45 #include "ids.hrc"
46 #include "getcontinuations.hxx"
47 #include "sslwarndlg.hxx"
48 #include "unknownauthdlg.hxx"
50 #include "iahndl.hxx"
52 #include <boost/scoped_ptr.hpp>
54 #define DESCRIPTION_1 1
55 #define TITLE 3
57 #define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17"
60 using namespace com::sun::star;
62 namespace {
64 String
65 getContentPart( const String& _rRawString )
67 // search over some parts to find a string
68 static char const * aIDs[] = { "CN=", "OU=", "O=", "E=", NULL };
69 String sPart;
70 int i = 0;
71 while ( aIDs[i] )
73 String sPartId = String::CreateFromAscii( aIDs[i++] );
74 xub_StrLen nContStart = _rRawString.Search( sPartId );
75 if ( nContStart != STRING_NOTFOUND )
77 nContStart = nContStart + sPartId.Len();
78 xub_StrLen nContEnd
79 = _rRawString.Search( sal_Unicode( ',' ), nContStart );
80 sPart = String( _rRawString, nContStart, nContEnd - nContStart );
81 break;
84 return sPart;
87 bool
88 isDomainMatch(
89 rtl::OUString hostName, uno::Sequence< ::rtl::OUString > certHostNames)
91 for ( int i = 0; i < certHostNames.getLength(); i++){
92 ::rtl::OUString element = certHostNames[i];
94 if (element.isEmpty())
95 continue;
97 if (hostName.equalsIgnoreAsciiCase( element ))
98 return true;
100 if ( 0 == element.indexOf( rtl::OUString( "*" ) ) &&
101 hostName.getLength() >= element.getLength() )
103 rtl::OUString cmpStr = element.copy( 1 );
104 if ( hostName.matchIgnoreAsciiCase(
105 cmpStr, hostName.getLength() - cmpStr.getLength()) )
106 return true;
110 return false;
113 rtl::OUString
114 getLocalizedDatTimeStr(
115 uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
116 util::DateTime const & rDateTime )
118 rtl::OUString aDateTimeStr;
119 Date aDate( Date::EMPTY );
120 Time aTime( Time::EMPTY );
122 aDate = Date( rDateTime.Day, rDateTime.Month, rDateTime.Year );
123 aTime = Time( rDateTime.Hours, rDateTime.Minutes, rDateTime.Seconds );
125 LanguageType eUILang = Application::GetSettings().GetUILanguage();
126 SvNumberFormatter *pNumberFormatter
127 = new SvNumberFormatter( xServiceFactory, eUILang );
128 String aTmpStr;
129 Color* pColor = NULL;
130 Date* pNullDate = pNumberFormatter->GetNullDate();
131 sal_uInt32 nFormat
132 = pNumberFormatter->GetStandardFormat( NUMBERFORMAT_DATE, eUILang );
134 pNumberFormatter->GetOutputString(
135 aDate - *pNullDate, nFormat, aTmpStr, &pColor );
136 aDateTimeStr = aTmpStr + rtl::OUString(" ");
138 nFormat = pNumberFormatter->GetStandardFormat( NUMBERFORMAT_TIME, eUILang );
139 pNumberFormatter->GetOutputString(
140 aTime.GetTimeInDays(), nFormat, aTmpStr, &pColor );
141 aDateTimeStr += aTmpStr;
143 return aDateTimeStr;
146 sal_Bool
147 executeUnknownAuthDialog(
148 Window * pParent,
149 uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
150 const uno::Reference< security::XCertificate >& rXCert)
151 SAL_THROW((uno::RuntimeException))
155 SolarMutexGuard aGuard;
157 boost::scoped_ptr< ResMgr > xManager(ResMgr::CreateResMgr("uui"));
158 boost::scoped_ptr< UnknownAuthDialog > xDialog(
159 new UnknownAuthDialog( pParent,
160 rXCert,
161 xServiceFactory,
162 xManager.get()));
164 // Get correct resource string
165 rtl::OUString aMessage;
167 std::vector< rtl::OUString > aArguments;
168 aArguments.push_back( getContentPart( rXCert->getSubjectName()) );
170 if (xManager.get())
172 ResId aResId(RID_UUI_ERRHDL, *xManager.get());
173 if (ErrorResource(aResId).getString(
174 ERRCODE_UUI_UNKNOWNAUTH_UNTRUSTED, aMessage))
176 aMessage = UUIInteractionHelper::replaceMessageWithArguments(
177 aMessage, aArguments );
178 xDialog->setDescriptionText( aMessage );
182 return static_cast<sal_Bool> (xDialog->Execute());
184 catch (std::bad_alloc const &)
186 throw uno::RuntimeException(
187 rtl::OUString("out of memory"),
188 uno::Reference< uno::XInterface >());
192 sal_Bool
193 executeSSLWarnDialog(
194 Window * pParent,
195 uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
196 const uno::Reference< security::XCertificate >& rXCert,
197 sal_Int32 const & failure,
198 const rtl::OUString & hostName )
199 SAL_THROW((uno::RuntimeException))
203 SolarMutexGuard aGuard;
205 boost::scoped_ptr< ResMgr > xManager(ResMgr::CreateResMgr("uui"));
206 boost::scoped_ptr< SSLWarnDialog > xDialog(
207 new SSLWarnDialog( pParent,
208 rXCert,
209 xServiceFactory,
210 xManager.get()));
212 // Get correct resource string
213 rtl::OUString aMessage_1;
214 std::vector< rtl::OUString > aArguments_1;
216 switch( failure )
218 case SSLWARN_TYPE_DOMAINMISMATCH:
219 aArguments_1.push_back( hostName );
220 aArguments_1.push_back(
221 getContentPart( rXCert->getSubjectName()) );
222 aArguments_1.push_back( hostName );
223 break;
224 case SSLWARN_TYPE_EXPIRED:
225 aArguments_1.push_back(
226 getContentPart( rXCert->getSubjectName()) );
227 aArguments_1.push_back(
228 getLocalizedDatTimeStr( xServiceFactory,
229 rXCert->getNotValidAfter() ) );
230 aArguments_1.push_back(
231 getLocalizedDatTimeStr( xServiceFactory,
232 rXCert->getNotValidAfter() ) );
233 break;
234 case SSLWARN_TYPE_INVALID:
235 break;
238 if (xManager.get())
240 ResId aResId(RID_UUI_ERRHDL, *xManager.get());
241 if (ErrorResource(aResId).getString(
242 ERRCODE_AREA_UUI_UNKNOWNAUTH + failure + DESCRIPTION_1,
243 aMessage_1))
245 aMessage_1 = UUIInteractionHelper::replaceMessageWithArguments(
246 aMessage_1, aArguments_1 );
247 xDialog->setDescription1Text( aMessage_1 );
250 rtl::OUString aTitle;
251 ErrorResource(aResId).getString(
252 ERRCODE_AREA_UUI_UNKNOWNAUTH + failure + TITLE, aTitle);
253 xDialog->SetText( aTitle );
256 return static_cast<sal_Bool> (xDialog->Execute());
258 catch (std::bad_alloc const &)
260 throw uno::RuntimeException(
261 rtl::OUString("out of memory"),
262 uno::Reference< uno::XInterface >());
266 void
267 handleCertificateValidationRequest_(
268 Window * pParent,
269 uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory,
270 ucb::CertificateValidationRequest const & rRequest,
271 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const &
272 rContinuations)
273 SAL_THROW((uno::RuntimeException))
275 uno::Reference< task::XInteractionApprove > xApprove;
276 uno::Reference< task::XInteractionAbort > xAbort;
277 getContinuations(rContinuations, &xApprove, &xAbort);
279 sal_Int32 failures = rRequest.CertificateValidity;
280 sal_Bool trustCert = sal_True;
282 if ( ((failures & security::CertificateValidity::UNTRUSTED)
283 == security::CertificateValidity::UNTRUSTED ) ||
284 ((failures & security::CertificateValidity::ISSUER_UNTRUSTED)
285 == security::CertificateValidity::ISSUER_UNTRUSTED) ||
286 ((failures & security::CertificateValidity::ROOT_UNTRUSTED)
287 == security::CertificateValidity::ROOT_UNTRUSTED) )
289 trustCert = executeUnknownAuthDialog( pParent,
290 xServiceFactory,
291 rRequest.Certificate );
294 uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = rRequest.Certificate->getExtensions();
295 uno::Sequence< security::CertAltNameEntry > altNames;
296 for (sal_Int32 i = 0 ; i < extensions.getLength(); i++){
297 uno::Reference< security::XCertificateExtension >element = extensions[i];
299 rtl::OString aId ( (const sal_Char *)element->getExtensionId().getArray(), element->getExtensionId().getLength());
300 if (aId.equals(OID_SUBJECT_ALTERNATIVE_NAME))
302 uno::Reference< security::XSanExtension > sanExtension ( element, uno::UNO_QUERY );
303 altNames = sanExtension->getAlternativeNames();
304 break;
308 ::rtl::OUString certHostName = getContentPart( rRequest.Certificate->getSubjectName() );
309 uno::Sequence< ::rtl::OUString > certHostNames(altNames.getLength() + 1);
311 certHostNames[0] = certHostName;
313 for(int n = 1; n < altNames.getLength(); n++){
314 if (altNames[n].Type == security::ExtAltNameType_DNS_NAME){
315 altNames[n].Value >>= certHostNames[n];
319 if ( (!isDomainMatch(
320 rRequest.HostName,
321 certHostNames )) &&
322 trustCert )
324 trustCert = executeSSLWarnDialog( pParent,
325 xServiceFactory,
326 rRequest.Certificate,
327 SSLWARN_TYPE_DOMAINMISMATCH,
328 rRequest.HostName );
331 if ( (((failures & security::CertificateValidity::TIME_INVALID)
332 == security::CertificateValidity::TIME_INVALID) ||
333 ((failures & security::CertificateValidity::NOT_TIME_NESTED)
334 == security::CertificateValidity::NOT_TIME_NESTED)) &&
335 trustCert )
337 trustCert = executeSSLWarnDialog( pParent,
338 xServiceFactory,
339 rRequest.Certificate,
340 SSLWARN_TYPE_EXPIRED,
341 rRequest.HostName );
344 if ( (((failures & security::CertificateValidity::REVOKED)
345 == security::CertificateValidity::REVOKED) ||
346 ((failures & security::CertificateValidity::SIGNATURE_INVALID)
347 == security::CertificateValidity::SIGNATURE_INVALID) ||
348 ((failures & security::CertificateValidity::EXTENSION_INVALID)
349 == security::CertificateValidity::EXTENSION_INVALID) ||
350 ((failures & security::CertificateValidity::INVALID)
351 == security::CertificateValidity::INVALID)) &&
352 trustCert )
354 trustCert = executeSSLWarnDialog( pParent,
355 xServiceFactory,
356 rRequest.Certificate,
357 SSLWARN_TYPE_INVALID,
358 rRequest.HostName );
361 if ( trustCert )
363 if (xApprove.is())
364 xApprove->select();
366 else
368 if (xAbort.is())
369 xAbort->select();
373 } // namespace
375 bool
376 UUIInteractionHelper::handleCertificateValidationRequest(
377 uno::Reference< task::XInteractionRequest > const & rRequest)
378 SAL_THROW((uno::RuntimeException))
380 uno::Any aAnyRequest(rRequest->getRequest());
382 ucb::CertificateValidationRequest aCertificateValidationRequest;
383 if (aAnyRequest >>= aCertificateValidationRequest)
385 handleCertificateValidationRequest_(getParentProperty(),
386 m_xServiceFactory,
387 aCertificateValidationRequest,
388 rRequest->getContinuations());
389 return true;
392 return false;
395 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */