1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 29 #include "com/sun/star/security/CertificateValidity.hpp" 30 #include "com/sun/star/security/XCertificateExtension.hpp" 31 #include "com/sun/star/security/XSanExtension.hpp" 32 #include <com/sun/star/security/ExtAltNameType.hpp> 33 #include "com/sun/star/task/XInteractionAbort.hpp" 34 #include "com/sun/star/task/XInteractionApprove.hpp" 35 #include "com/sun/star/task/XInteractionRequest.hpp" 36 #include "com/sun/star/ucb/CertificateValidationRequest.hpp" 37 #include <com/sun/star/uno/Reference.hxx> 38 39 #include <com/sun/star/uno/Sequence.hxx> 40 #include "vos/mutex.hxx" 41 #include "tools/datetime.hxx" 42 #include "svl/zforlist.hxx" 43 #include "vcl/svapp.hxx" 44 45 #include "ids.hrc" 46 #include "getcontinuations.hxx" 47 #include "sslwarndlg.hxx" 48 #include "unknownauthdlg.hxx" 49 50 #include "iahndl.hxx" 51 52 #define DESCRIPTION_1 1 53 #define DESCRIPTION_2 2 54 #define TITLE 3 55 56 #define OID_SUBJECT_ALTERNATIVE_NAME "2.5.29.17" 57 58 59 using namespace com::sun::star; 60 61 namespace { 62 63 String 64 getContentPart( const String& _rRawString ) 65 { 66 // search over some parts to find a string 67 //static char* aIDs[] = { "CN", "OU", "O", "E", NULL }; 68 static char const * aIDs[] = { "CN=", "OU=", "O=", "E=", NULL };// By CP 69 String sPart; 70 int i = 0; 71 while ( aIDs[i] ) 72 { 73 String sPartId = String::CreateFromAscii( aIDs[i++] ); 74 xub_StrLen nContStart = _rRawString.Search( sPartId ); 75 if ( nContStart != STRING_NOTFOUND ) 76 { 77 nContStart = nContStart + sPartId.Len(); 78 xub_StrLen nContEnd 79 = _rRawString.Search( sal_Unicode( ',' ), nContStart ); 80 sPart = String( _rRawString, nContStart, nContEnd - nContStart ); 81 break; 82 } 83 } 84 return sPart; 85 } 86 87 bool 88 isDomainMatch( 89 rtl::OUString hostName, uno::Sequence< ::rtl::OUString > certHostNames) 90 { 91 for ( int i = 0; i < certHostNames.getLength(); i++){ 92 ::rtl::OUString element = certHostNames[i]; 93 94 if (element.getLength() == 0) 95 continue; 96 97 if (hostName.equalsIgnoreAsciiCase( element )) 98 return true; 99 100 if ( 0 == element.indexOf( rtl::OUString::createFromAscii( "*" ) ) && 101 hostName.getLength() >= element.getLength() ) 102 { 103 rtl::OUString cmpStr = element.copy( 1 ); 104 if ( hostName.matchIgnoreAsciiCase( 105 cmpStr, hostName.getLength() - cmpStr.getLength()) ) 106 return true; 107 } 108 } 109 110 return false; 111 } 112 113 rtl::OUString 114 getLocalizedDatTimeStr( 115 uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory, 116 util::DateTime const & rDateTime ) 117 { 118 rtl::OUString aDateTimeStr; 119 Date aDate; 120 Time aTime; 121 122 aDate = Date( rDateTime.Day, rDateTime.Month, rDateTime.Year ); 123 aTime = Time( rDateTime.Hours, rDateTime.Minutes, rDateTime.Seconds ); 124 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 ); 133 134 pNumberFormatter->GetOutputString( 135 aDate - *pNullDate, nFormat, aTmpStr, &pColor ); 136 aDateTimeStr = aTmpStr + rtl::OUString(RTL_CONSTASCII_USTRINGPARAM(" ")); 137 138 nFormat = pNumberFormatter->GetStandardFormat( NUMBERFORMAT_TIME, eUILang ); 139 pNumberFormatter->GetOutputString( 140 aTime.GetTimeInDays(), nFormat, aTmpStr, &pColor ); 141 aDateTimeStr += aTmpStr; 142 143 return aDateTimeStr; 144 } 145 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)) 152 { 153 try 154 { 155 vos::OGuard aGuard(Application::GetSolarMutex()); 156 157 std::auto_ptr< ResMgr > xManager( 158 ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(uui))); 159 std::auto_ptr< UnknownAuthDialog > xDialog( 160 new UnknownAuthDialog( pParent, 161 rXCert, 162 xServiceFactory, 163 xManager.get())); 164 165 // Get correct ressource string 166 rtl::OUString aMessage; 167 168 std::vector< rtl::OUString > aArguments; 169 aArguments.push_back( getContentPart( rXCert->getSubjectName()) ); 170 171 if (xManager.get()) 172 { 173 ResId aResId(RID_UUI_ERRHDL, *xManager.get()); 174 if (ErrorResource(aResId).getString( 175 ERRCODE_UUI_UNKNOWNAUTH_UNTRUSTED, &aMessage)) 176 { 177 aMessage = UUIInteractionHelper::replaceMessageWithArguments( 178 aMessage, aArguments ); 179 xDialog->setDescriptionText( aMessage ); 180 } 181 } 182 183 return static_cast<sal_Bool> (xDialog->Execute()); 184 } 185 catch (std::bad_alloc const &) 186 { 187 throw uno::RuntimeException( 188 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")), 189 uno::Reference< uno::XInterface >()); 190 } 191 } 192 193 sal_Bool 194 executeSSLWarnDialog( 195 Window * pParent, 196 uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory, 197 const uno::Reference< security::XCertificate >& rXCert, 198 sal_Int32 const & failure, 199 const rtl::OUString & hostName ) 200 SAL_THROW((uno::RuntimeException)) 201 { 202 try 203 { 204 vos::OGuard aGuard(Application::GetSolarMutex()); 205 206 std::auto_ptr< ResMgr > xManager( 207 ResMgr::CreateResMgr(CREATEVERSIONRESMGR_NAME(uui))); 208 std::auto_ptr< SSLWarnDialog > xDialog( 209 new SSLWarnDialog( pParent, 210 rXCert, 211 xServiceFactory, 212 xManager.get())); 213 214 // Get correct ressource string 215 rtl::OUString aMessage_1; 216 std::vector< rtl::OUString > aArguments_1; 217 218 switch( failure ) 219 { 220 case SSLWARN_TYPE_DOMAINMISMATCH: 221 aArguments_1.push_back( hostName ); 222 aArguments_1.push_back( 223 getContentPart( rXCert->getSubjectName()) ); 224 aArguments_1.push_back( hostName ); 225 break; 226 case SSLWARN_TYPE_EXPIRED: 227 aArguments_1.push_back( 228 getContentPart( rXCert->getSubjectName()) ); 229 aArguments_1.push_back( 230 getLocalizedDatTimeStr( xServiceFactory, 231 rXCert->getNotValidAfter() ) ); 232 aArguments_1.push_back( 233 getLocalizedDatTimeStr( xServiceFactory, 234 rXCert->getNotValidAfter() ) ); 235 break; 236 case SSLWARN_TYPE_INVALID: 237 break; 238 } 239 240 if (xManager.get()) 241 { 242 ResId aResId(RID_UUI_ERRHDL, *xManager.get()); 243 if (ErrorResource(aResId).getString( 244 ERRCODE_AREA_UUI_UNKNOWNAUTH + failure + DESCRIPTION_1, 245 &aMessage_1)) 246 { 247 aMessage_1 = UUIInteractionHelper::replaceMessageWithArguments( 248 aMessage_1, aArguments_1 ); 249 xDialog->setDescription1Text( aMessage_1 ); 250 } 251 252 rtl::OUString aTitle; 253 ErrorResource(aResId).getString( 254 ERRCODE_AREA_UUI_UNKNOWNAUTH + failure + TITLE, &aTitle); 255 xDialog->SetText( aTitle ); 256 } 257 258 return static_cast<sal_Bool> (xDialog->Execute()); 259 } 260 catch (std::bad_alloc const &) 261 { 262 throw uno::RuntimeException( 263 rtl::OUString(RTL_CONSTASCII_USTRINGPARAM("out of memory")), 264 uno::Reference< uno::XInterface >()); 265 } 266 } 267 268 void 269 handleCertificateValidationRequest_( 270 Window * pParent, 271 uno::Reference< lang::XMultiServiceFactory > const & xServiceFactory, 272 ucb::CertificateValidationRequest const & rRequest, 273 uno::Sequence< uno::Reference< task::XInteractionContinuation > > const & 274 rContinuations) 275 SAL_THROW((uno::RuntimeException)) 276 { 277 uno::Reference< task::XInteractionApprove > xApprove; 278 uno::Reference< task::XInteractionAbort > xAbort; 279 getContinuations(rContinuations, &xApprove, &xAbort); 280 281 sal_Int32 failures = rRequest.CertificateValidity; 282 sal_Bool trustCert = sal_True; 283 284 if ( ((failures & security::CertificateValidity::UNTRUSTED) 285 == security::CertificateValidity::UNTRUSTED ) || 286 ((failures & security::CertificateValidity::ISSUER_UNTRUSTED) 287 == security::CertificateValidity::ISSUER_UNTRUSTED) || 288 ((failures & security::CertificateValidity::ROOT_UNTRUSTED) 289 == security::CertificateValidity::ROOT_UNTRUSTED) ) 290 { 291 trustCert = executeUnknownAuthDialog( pParent, 292 xServiceFactory, 293 rRequest.Certificate ); 294 } 295 296 uno::Sequence< uno::Reference< security::XCertificateExtension > > extensions = rRequest.Certificate->getExtensions(); 297 uno::Sequence< security::CertAltNameEntry > altNames; 298 for (sal_Int32 i = 0 ; i < extensions.getLength(); i++){ 299 uno::Reference< security::XCertificateExtension >element = extensions[i]; 300 301 rtl::OString aId ( (const sal_Char *)element->getExtensionId().getArray(), element->getExtensionId().getLength()); 302 if (aId.equals(OID_SUBJECT_ALTERNATIVE_NAME)) 303 { 304 uno::Reference< security::XSanExtension > sanExtension ( element, uno::UNO_QUERY ); 305 altNames = sanExtension->getAlternativeNames(); 306 break; 307 } 308 } 309 310 ::rtl::OUString certHostName = getContentPart( rRequest.Certificate->getSubjectName() ); 311 uno::Sequence< ::rtl::OUString > certHostNames(altNames.getLength() + 1); 312 313 certHostNames[0] = certHostName; 314 315 for(int n = 1; n < altNames.getLength(); n++){ 316 if (altNames[n].Type == security::ExtAltNameType_DNS_NAME){ 317 altNames[n].Value >>= certHostNames[n]; 318 } 319 } 320 321 if ( (!isDomainMatch( 322 rRequest.HostName, 323 certHostNames )) && 324 trustCert ) 325 { 326 trustCert = executeSSLWarnDialog( pParent, 327 xServiceFactory, 328 rRequest.Certificate, 329 SSLWARN_TYPE_DOMAINMISMATCH, 330 rRequest.HostName ); 331 } 332 333 if ( (((failures & security::CertificateValidity::TIME_INVALID) 334 == security::CertificateValidity::TIME_INVALID) || 335 ((failures & security::CertificateValidity::NOT_TIME_NESTED) 336 == security::CertificateValidity::NOT_TIME_NESTED)) && 337 trustCert ) 338 { 339 trustCert = executeSSLWarnDialog( pParent, 340 xServiceFactory, 341 rRequest.Certificate, 342 SSLWARN_TYPE_EXPIRED, 343 rRequest.HostName ); 344 } 345 346 if ( (((failures & security::CertificateValidity::REVOKED) 347 == security::CertificateValidity::REVOKED) || 348 ((failures & security::CertificateValidity::SIGNATURE_INVALID) 349 == security::CertificateValidity::SIGNATURE_INVALID) || 350 ((failures & security::CertificateValidity::EXTENSION_INVALID) 351 == security::CertificateValidity::EXTENSION_INVALID) || 352 ((failures & security::CertificateValidity::INVALID) 353 == security::CertificateValidity::INVALID)) && 354 trustCert ) 355 { 356 trustCert = executeSSLWarnDialog( pParent, 357 xServiceFactory, 358 rRequest.Certificate, 359 SSLWARN_TYPE_INVALID, 360 rRequest.HostName ); 361 } 362 363 if ( trustCert ) 364 { 365 if (xApprove.is()) 366 xApprove->select(); 367 } 368 else 369 { 370 if (xAbort.is()) 371 xAbort->select(); 372 } 373 } 374 375 } // namespace 376 377 bool 378 UUIInteractionHelper::handleCertificateValidationRequest( 379 uno::Reference< task::XInteractionRequest > const & rRequest) 380 SAL_THROW((uno::RuntimeException)) 381 { 382 uno::Any aAnyRequest(rRequest->getRequest()); 383 384 ucb::CertificateValidationRequest aCertificateValidationRequest; 385 if (aAnyRequest >>= aCertificateValidationRequest) 386 { 387 handleCertificateValidationRequest_(getParentProperty(), 388 m_xServiceFactory, 389 aCertificateValidationRequest, 390 rRequest->getContinuations()); 391 return true; 392 } 393 394 return false; 395 } 396 397