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 ---