SerfSession.cxx (fb7f54d2) | SerfSession.cxx (c58749d7) |
---|---|
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 --- 39 unchanged lines hidden (view full) --- 48#include <com/sun/star/security/CertificateContainer.hpp> 49#include <com/sun/star/security/XCertificateContainer.hpp> 50#include <com/sun/star/ucb/Lock.hpp> 51#include <com/sun/star/xml/crypto/XSEInitializer.hpp> 52 53using namespace com::sun::star; 54using namespace http_dav_ucp; 55 | 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 --- 39 unchanged lines hidden (view full) --- 48#include <com/sun/star/security/CertificateContainer.hpp> 49#include <com/sun/star/security/XCertificateContainer.hpp> 50#include <com/sun/star/ucb/Lock.hpp> 51#include <com/sun/star/xml/crypto/XSEInitializer.hpp> 52 53using namespace com::sun::star; 54using namespace http_dav_ucp; 55 |
56 |
|
56// ------------------------------------------------------------------- 57// static members! 58bool SerfSession::m_bGlobalsInited = false; 59osl::Mutex SerfSession::m_aGlobalMutex; 60//SerfLockStore SerfSession::m_aSerfLockStore; 61 62// ------------------------------------------------------------------- 63// Constructor --- 200 unchanged lines hidden (view full) --- 264 inAprSocket, 265 getSerfBktAlloc() ); 266 267 if ( isSSLNeeded() ) 268 { 269 tmpInputBkt = serf_bucket_ssl_decrypt_create( tmpInputBkt, 270 0, 271 getSerfBktAlloc() ); | 57// ------------------------------------------------------------------- 58// static members! 59bool SerfSession::m_bGlobalsInited = false; 60osl::Mutex SerfSession::m_aGlobalMutex; 61//SerfLockStore SerfSession::m_aSerfLockStore; 62 63// ------------------------------------------------------------------- 64// Constructor --- 200 unchanged lines hidden (view full) --- 265 inAprSocket, 266 getSerfBktAlloc() ); 267 268 if ( isSSLNeeded() ) 269 { 270 tmpInputBkt = serf_bucket_ssl_decrypt_create( tmpInputBkt, 271 0, 272 getSerfBktAlloc() ); |
272 serf_ssl_server_cert_callback_set( serf_bucket_ssl_decrypt_context_get( tmpInputBkt ), 273 Serf_CertificationValidation, 274 this ); | 273 /** Set the callback that is called to authenticate the 274 certifcate (chain). 275 */ 276 serf_ssl_server_cert_chain_callback_set( 277 serf_bucket_ssl_decrypt_context_get(tmpInputBkt), 278 Serf_CertificateChainValidation, 279 this); |
275 serf_ssl_set_hostname( serf_bucket_ssl_decrypt_context_get( tmpInputBkt ), 276 getHostinfo() ); 277 278 *outSerfOutputBucket = serf_bucket_ssl_encrypt_create( *outSerfOutputBucket, 279 serf_bucket_ssl_decrypt_context_get( tmpInputBkt ), 280 getSerfBktAlloc() ); 281 } 282 --- 77 unchanged lines hidden (view full) --- 360 sal_Int32 nContEnd 361 = _rRawString.indexOf( sal_Unicode( ',' ), nContStart ); 362 sPart = _rRawString.copy( nContStart, nContEnd - nContStart ); 363 } 364 return sPart; 365 } 366} // namespace 367 | 280 serf_ssl_set_hostname( serf_bucket_ssl_decrypt_context_get( tmpInputBkt ), 281 getHostinfo() ); 282 283 *outSerfOutputBucket = serf_bucket_ssl_encrypt_create( *outSerfOutputBucket, 284 serf_bucket_ssl_decrypt_context_get( tmpInputBkt ), 285 getSerfBktAlloc() ); 286 } 287 --- 77 unchanged lines hidden (view full) --- 365 sal_Int32 nContEnd 366 = _rRawString.indexOf( sal_Unicode( ',' ), nContStart ); 367 sPart = _rRawString.copy( nContStart, nContEnd - nContStart ); 368 } 369 return sPart; 370 } 371} // namespace 372 |
368apr_status_t SerfSession::verifySerfCertificate( int inFailures, 369 const serf_ssl_certificate_t * inCert ) 370{ 371 OSL_ASSERT( inCert ); | |
372 | 373 |
373 uno::Reference< security::XCertificateContainer > xCertificateContainer; 374 try | 374apr_status_t SerfSession::verifySerfCertificateChain ( 375 int, 376 const char** pCertificateChainBase64Encoded, 377 const int nCertificateChainLength) 378{ 379 // Check arguments. 380 if (pCertificateChainBase64Encoded == NULL || nCertificateChainLength<=0) |
375 { | 381 { |
376 xCertificateContainer 377 = uno::Reference< security::XCertificateContainer >( 378 getMSF()->createInstance( 379 rtl::OUString::createFromAscii( 380 "com.sun.star.security.CertificateContainer" ) ), 381 uno::UNO_QUERY ); 382 } 383 catch ( uno::Exception const & ) 384 { 385 } 386 387 if ( !xCertificateContainer.is() ) | 382 OSL_ASSERT(pCertificateChainBase64Encoded != NULL); 383 OSL_ASSERT(nCertificateChainLength>0); |
388 return SERF_SSL_CERT_UNKNOWN_FAILURE; | 384 return SERF_SSL_CERT_UNKNOWN_FAILURE; |
389 390 inFailures = 0; 391 392 const char * subjectItem = static_cast<char*>(apr_hash_get( serf_ssl_cert_subject( inCert, getAprPool() ), 393 "CN", APR_HASH_KEY_STRING )); 394 if ( subjectItem == 0 ) 395 { 396 subjectItem = static_cast<char*>(apr_hash_get( serf_ssl_cert_subject( inCert, getAprPool() ), 397 "OU", APR_HASH_KEY_STRING )); | |
398 } | 385 } |
399 rtl::OUString cert_subject; 400 if ( subjectItem != 0 ) 401 { 402 cert_subject = rtl::OUString( subjectItem, strlen( subjectItem ), RTL_TEXTENCODING_UTF8, 0 ); 403 } 404 else 405 { 406 rtl::OUString::createFromAscii( "unknown subject" ); 407 } | |
408 | 386 |
409 security::CertificateContainerStatus certificateContainer( 410 xCertificateContainer->hasCertificate( 411 getHostName(), cert_subject ) ); 412 413 if ( certificateContainer != security::CertificateContainerStatus_NOCERT ) 414 { 415 return certificateContainer == security::CertificateContainerStatus_TRUSTED 416 ? APR_SUCCESS 417 : SERF_SSL_CERT_UNKNOWN_FAILURE; 418 } 419 | 387 // Create some crypto objects to decode and handle the base64 388 // encoded certificate chain. |
420 uno::Reference< xml::crypto::XSEInitializer > xSEInitializer; | 389 uno::Reference< xml::crypto::XSEInitializer > xSEInitializer; |
390 uno::Reference< security::XCertificateContainer > xCertificateContainer; 391 uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext; 392 uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv; |
|
421 try 422 { | 393 try 394 { |
395 // Create a certificate container. 396 xCertificateContainer = uno::Reference< security::XCertificateContainer >( 397 getMSF()->createInstance( 398 rtl::OUString::createFromAscii( 399 "com.sun.star.security.CertificateContainer" ) ), 400 uno::UNO_QUERY_THROW); 401 |
|
423 xSEInitializer = uno::Reference< xml::crypto::XSEInitializer >( 424 getMSF()->createInstance( 425 rtl::OUString::createFromAscii( "com.sun.star.xml.crypto.SEInitializer" ) ), | 402 xSEInitializer = uno::Reference< xml::crypto::XSEInitializer >( 403 getMSF()->createInstance( 404 rtl::OUString::createFromAscii( "com.sun.star.xml.crypto.SEInitializer" ) ), |
426 uno::UNO_QUERY ); | 405 uno::UNO_QUERY_THROW); 406 407 xSecurityContext = xSEInitializer->createSecurityContext( rtl::OUString() ); 408 if (xSecurityContext.is()) 409 xSecurityEnv = xSecurityContext->getSecurityEnvironment(); 410 411 if ( ! xSecurityContext.is() || ! xSecurityEnv.is()) 412 { 413 // Do we have to dispose xSEInitializer or xCertificateContainer? 414 return SERF_SSL_CERT_UNKNOWN_FAILURE; 415 } |
427 } | 416 } |
428 catch ( uno::Exception const & ) | 417 catch ( uno::Exception const &) |
429 { | 418 { |
419 return SERF_SSL_CERT_UNKNOWN_FAILURE; |
|
430 } 431 | 420 } 421 |
432 if ( !xSEInitializer.is() ) | 422 // Decode the server certificate. 423 uno::Reference< security::XCertificate > xServerCertificate( 424 xSecurityEnv->createCertificateFromAscii( 425 rtl::OUString::createFromAscii(pCertificateChainBase64Encoded[0]))); 426 if ( ! xServerCertificate.is()) |
433 return SERF_SSL_CERT_UNKNOWN_FAILURE; 434 | 427 return SERF_SSL_CERT_UNKNOWN_FAILURE; 428 |
435 uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext( 436 xSEInitializer->createSecurityContext( rtl::OUString() ) ); 437 438 uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv( 439 xSecurityContext->getSecurityEnvironment() ); 440 441 //The end entity certificate 442 const char * eeCertB64 = serf_ssl_cert_export( inCert, getAprPool() ); 443 444 rtl::OString sEECertB64( eeCertB64 ); 445 446 uno::Reference< security::XCertificate > xEECert( 447 xSecurityEnv->createCertificateFromAscii( 448 rtl::OStringToOUString( sEECertB64, RTL_TEXTENCODING_ASCII_US ) ) ); 449 450 std::vector< uno::Reference< security::XCertificate > > vecCerts; 451 const serf_ssl_certificate_t * issuerCert = inCert; 452 do | 429 // Get the subject from the server certificate. 430 ::rtl::OUString sServerCertificateSubject (xServerCertificate->getSubjectName()); 431 sal_Int32 nIndex = 0; 432 while (nIndex >= 0) |
453 { | 433 { |
454 //get the intermediate certificate 455 issuerCert = NULL; // TODO - figure out how to retrieve certificate chain - ssl_cert_signedby( issuerCert ); 456 if ( NULL == issuerCert ) | 434 const ::rtl::OUString sToken (sServerCertificateSubject.getToken(0, ',', nIndex)); 435 if (sToken.compareToAscii("CN=", 3) == 0) 436 { 437 sServerCertificateSubject = sToken.copy(3); |
457 break; | 438 break; |
439 } 440 else if (sToken.compareToAscii(" CN=", 4) == 0) 441 { 442 sServerCertificateSubject = sToken.copy(4); 443 break; 444 } 445 } |
|
458 | 446 |
459 const char * imCertB64 = serf_ssl_cert_export( issuerCert, getAprPool() ); 460 rtl::OString sInterMediateCertB64( imCertB64 ); | 447 // When the certificate container already contains a (trusted) 448 // entry for the server then we do not have to authenticate any 449 // certificate. 450 const security::CertificateContainerStatus eStatus ( 451 xCertificateContainer->hasCertificate( 452 getHostName(), sServerCertificateSubject ) ); 453 if (eStatus != security::CertificateContainerStatus_NOCERT) 454 { 455 return eStatus == security::CertificateContainerStatus_TRUSTED 456 ? APR_SUCCESS 457 : SERF_SSL_CERT_UNKNOWN_FAILURE; 458 } |
461 | 459 |
462 uno::Reference< security::XCertificate> xImCert( | 460 // The shortcut failed, so try to verify the whole chain. This is 461 // done outside the isDomainMatch() block because the result is 462 // used by the interaction handler. 463 std::vector< uno::Reference< security::XCertificate > > aChain; 464 for (int nIndex=1; nIndex<nCertificateChainLength; ++nIndex) 465 { 466 uno::Reference< security::XCertificate > xCertificate( |
463 xSecurityEnv->createCertificateFromAscii( | 467 xSecurityEnv->createCertificateFromAscii( |
464 rtl::OStringToOUString( 465 sInterMediateCertB64, RTL_TEXTENCODING_ASCII_US ) ) ); 466 if ( xImCert.is() ) 467 vecCerts.push_back( xImCert ); | 468 rtl::OUString::createFromAscii(pCertificateChainBase64Encoded[nIndex]))); 469 if ( ! xCertificate.is()) 470 return SERF_SSL_CERT_UNKNOWN_FAILURE; 471 aChain.push_back(xCertificate); |
468 } | 472 } |
469 while ( 1 ); | 473 const sal_Int64 nVerificationResult (xSecurityEnv->verifyCertificate( 474 xServerCertificate, 475 ::comphelper::containerToSequence(aChain))); |
470 | 476 |
471 sal_Int64 certValidity = xSecurityEnv->verifyCertificate( xEECert, 472 ::comphelper::containerToSequence( vecCerts ) ); 473 474 if ( isDomainMatch( GetHostnamePart( xEECert.get()->getSubjectName() ) ) ) | 477 // When the certificate matches the host name then we can use the 478 // result of the verification. 479 if (isDomainMatch(sServerCertificateSubject)) |
475 { | 480 { |
476 // if host name matched with certificate then look if the 477 // certificate was ok 478 if( certValidity == security::CertificateValidity::VALID ) | 481 482 if (nVerificationResult == 0) 483 { 484 // Certificate (chain) is valid. 485 xCertificateContainer->addCertificate(getHostName(), sServerCertificateSubject, sal_True); |
479 return APR_SUCCESS; | 486 return APR_SUCCESS; |
487 } 488 else if ((nVerificationResult & security::CertificateValidity::CHAIN_INCOMPLETE) != 0) 489 { 490 // We do not have enough information for verification, 491 // neither automatically (as we just discovered) nor 492 // manually (so there is no point in showing any dialog.) 493 return SERF_SSL_CERT_UNKNOWN_FAILURE; 494 } 495 else if ((nVerificationResult & 496 (security::CertificateValidity::INVALID | security::CertificateValidity::REVOKED)) != 0) 497 { 498 // Certificate (chain) is invalid. 499 xCertificateContainer->addCertificate(getHostName(), sServerCertificateSubject, sal_False); 500 return SERF_SSL_CERT_UNKNOWN_FAILURE; 501 } 502 else 503 { 504 // For all other we have to ask the user. 505 } |
|
480 } 481 | 506 } 507 |
508 // We have not been able to automatically verify (or falsify) the 509 // certificate chain. To resolve this we have to ask the user. |
|
482 const uno::Reference< ucb::XCommandEnvironment > xEnv( getRequestEnvironment().m_xEnv ); 483 if ( xEnv.is() ) 484 { | 510 const uno::Reference< ucb::XCommandEnvironment > xEnv( getRequestEnvironment().m_xEnv ); 511 if ( xEnv.is() ) 512 { |
485 inFailures = static_cast< int >( certValidity ); 486 | |
487 uno::Reference< task::XInteractionHandler > xIH( xEnv->getInteractionHandler() ); 488 if ( xIH.is() ) 489 { 490 rtl::Reference< ucbhelper::SimpleCertificateValidationRequest > 491 xRequest( new ucbhelper::SimpleCertificateValidationRequest( | 513 uno::Reference< task::XInteractionHandler > xIH( xEnv->getInteractionHandler() ); 514 if ( xIH.is() ) 515 { 516 rtl::Reference< ucbhelper::SimpleCertificateValidationRequest > 517 xRequest( new ucbhelper::SimpleCertificateValidationRequest( |
492 (sal_Int32)inFailures, xEECert, getHostName() ) ); | 518 static_cast<sal_Int32>(nVerificationResult), xServerCertificate, getHostName() ) ); |
493 xIH->handle( xRequest.get() ); 494 495 rtl::Reference< ucbhelper::InteractionContinuation > xSelection 496 = xRequest->getSelection(); 497 498 if ( xSelection.is() ) 499 { 500 uno::Reference< task::XInteractionApprove > xApprove( 501 xSelection.get(), uno::UNO_QUERY ); 502 if ( xApprove.is() ) 503 { | 519 xIH->handle( xRequest.get() ); 520 521 rtl::Reference< ucbhelper::InteractionContinuation > xSelection 522 = xRequest->getSelection(); 523 524 if ( xSelection.is() ) 525 { 526 uno::Reference< task::XInteractionApprove > xApprove( 527 xSelection.get(), uno::UNO_QUERY ); 528 if ( xApprove.is() ) 529 { |
504 xCertificateContainer->addCertificate( getHostName(), cert_subject, sal_True ); | 530 xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, sal_True ); |
505 return APR_SUCCESS; 506 } 507 else 508 { 509 // Don't trust cert | 531 return APR_SUCCESS; 532 } 533 else 534 { 535 // Don't trust cert |
510 xCertificateContainer->addCertificate( getHostName(), cert_subject, sal_False ); | 536 xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, sal_False ); |
511 return SERF_SSL_CERT_UNKNOWN_FAILURE; 512 } 513 } 514 } 515 else 516 { 517 // Don't trust cert | 537 return SERF_SSL_CERT_UNKNOWN_FAILURE; 538 } 539 } 540 } 541 else 542 { 543 // Don't trust cert |
518 xCertificateContainer->addCertificate( getHostName(), cert_subject, sal_False ); | 544 xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, sal_False ); |
519 return SERF_SSL_CERT_UNKNOWN_FAILURE; 520 } 521 } | 545 return SERF_SSL_CERT_UNKNOWN_FAILURE; 546 } 547 } |
548 |
|
522 return SERF_SSL_CERT_UNKNOWN_FAILURE; 523} 524 525serf_bucket_t* SerfSession::acceptSerfResponse( serf_request_t * inSerfRequest, 526 serf_bucket_t * inSerfStreamBucket, 527 apr_pool_t* /*inAprPool*/ ) 528{ 529 // get the per-request bucket allocator --- 1072 unchanged lines hidden --- | 549 return SERF_SSL_CERT_UNKNOWN_FAILURE; 550} 551 552serf_bucket_t* SerfSession::acceptSerfResponse( serf_request_t * inSerfRequest, 553 serf_bucket_t * inSerfStreamBucket, 554 apr_pool_t* /*inAprPool*/ ) 555{ 556 // get the per-request bucket allocator --- 1072 unchanged lines hidden --- |