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