You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openoffice.apache.org by af...@apache.org on 2012/03/01 11:14:03 UTC

svn commit: r1295493 - in /incubator/ooo/trunk: ext_libraries/serf/ main/ucb/source/ucp/webdav/

Author: af
Date: Thu Mar  1 10:14:02 2012
New Revision: 1295493

URL: http://svn.apache.org/viewvc?rev=1295493&view=rev
Log:
118569: Use whole certification chain for verification.

Added:
    incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68.patch
    incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68b.patch
Modified:
    incubator/ooo/trunk/ext_libraries/serf/makefile.mk
    incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.cxx
    incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.hxx
    incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.cxx
    incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.hxx

Modified: incubator/ooo/trunk/ext_libraries/serf/makefile.mk
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/ext_libraries/serf/makefile.mk?rev=1295493&r1=1295492&r2=1295493&view=diff
==============================================================================
--- incubator/ooo/trunk/ext_libraries/serf/makefile.mk (original)
+++ incubator/ooo/trunk/ext_libraries/serf/makefile.mk Thu Mar  1 10:14:02 2012
@@ -37,8 +37,15 @@ LIBSERFVERSION=$(SERF_MAJOR).$(SERF_MINO
 TARFILE_NAME=$(PRJNAME)-$(LIBSERFVERSION)
 TARFILE_MD5=3b179ed18f65c43141528aa6d2440db4
 
+# Apply patches that provide callbacks for ssl certificate verification with the
+# whole certificate chain (issue68.patch).  The patch is taken from serf's
+# issue 68 (http://code.google.com/p/serf/issues/detail?id=68).
+# This patch needs some minor fixes (issue68b.patch) for proper initialization of
+# some callbacks and export of new functions.
+PATCH_FILES=$(TARFILE_NAME).issue68.patch $(TARFILE_NAME).issue68b.patch
+
 # disable default used Transfer-Encoding = chunked for sending requests.
-PATCH_FILES=$(TARFILE_NAME).nochunkedtransferencoding.patch
+PATCH_FILES+=$(TARFILE_NAME).nochunkedtransferencoding.patch
 
 .IF "$(OS)"=="WNT"
 

Added: incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68.patch
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68.patch?rev=1295493&view=auto
==============================================================================
--- incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68.patch (added)
+++ incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68.patch Thu Mar  1 10:14:02 2012
@@ -0,0 +1,164 @@
+--- misc/serf-1.0.0/buckets/ssl_buckets.c	2011-07-13 04:39:16.000000000 +0200
++++ misc/build/serf-1.0.0/buckets/ssl_buckets.c	2012-02-24 14:26:51.766979700 +0100
+@@ -173,6 +173,9 @@
+     serf_ssl_need_server_cert_t server_cert_callback;
+     void *server_cert_userdata;
+ 
++    serf_ssl_need_server_cert_chain_t server_cert_chain_callback;
++    void *server_cert_chain_userdata;
++    
+     const char *cert_path;
+ 
+     X509 *cached_cert;
+@@ -385,6 +388,25 @@
+ #endif
+ };
+ 
++/* Returns a NULL terminated list of Base64 encoded DER certificates. */
++static const char **export_certificates(STACK_OF(X509) *chain, 
++                                        apr_pool_t *pool)
++{
++    const char **certificates;
++    int i, depth;
++
++    depth = sk_X509_num(chain);
++    certificates = apr_pcalloc(pool, sizeof(*certificates) * (depth + 1));
++
++    for (i = 0; i < depth; ++i) {
++        serf_ssl_certificate_t cert;
++        cert.ssl_cert = sk_X509_value(chain, i);
++        *(certificates+i) = serf_ssl_cert_export(&cert, pool);
++    }
++     
++    return certificates;   
++}
++
+ static int
+ validate_server_certificate(int cert_valid, X509_STORE_CTX *store_ctx)
+ {
+@@ -457,6 +479,39 @@
+         apr_pool_destroy(subpool);
+     }
+ 
++    /* This provides the entire chain so we only call it when the end 
++     * entity certificate is reached. */
++    if (ctx->server_cert_chain_callback && depth == 0) {
++        apr_status_t status;
++        STACK_OF(X509) *chain;
++        const char **ascii_certs;
++        apr_pool_t *subpool;
++
++        apr_pool_create(&subpool, ctx->pool);
++ 
++        chain = X509_STORE_CTX_get1_chain(store_ctx);
++        /* Fallback to the current certificate if the chain cannot be 
++         * retrieved. */
++        if ( ! chain) {
++            chain = sk_X509_new_null();
++            sk_X509_push(chain, X509_dup(server_cert));
++        }
++        ascii_certs = export_certificates(chain, subpool); 
++
++        /* Callback for further verification. */
++        status = 
++            ctx->server_cert_chain_callback(ctx->server_cert_chain_userdata, 
++                                            failures, ascii_certs);
++        if (status == APR_SUCCESS)
++            cert_valid = 1;
++        else
++            /* Pass the error back to the caller through the context-run. */
++            ctx->pending_err = status;
++        
++        sk_X509_pop_free(chain, X509_free);
++        apr_pool_destroy(subpool);
++    }
++
+     return cert_valid;
+ }
+ 
+@@ -1009,6 +1064,16 @@
+     context->server_cert_userdata = data;
+ }
+ 
++
++void serf_ssl_server_cert_chain_callback_set(
++    serf_ssl_context_t *context,
++    serf_ssl_need_server_cert_chain_t callback,
++    void *data)
++{
++    context->server_cert_chain_callback = callback;
++    context->server_cert_chain_userdata = data;
++}
++
+ static serf_ssl_context_t *ssl_init_context(void)
+ {
+     serf_ssl_context_t *ssl_ctx;
+--- misc/serf-1.0.0/serf_bucket_types.h	2011-06-25 18:01:01.000000000 +0200
++++ misc/build/serf-1.0.0/serf_bucket_types.h	2012-02-24 14:26:51.790981100 +0100
+@@ -486,6 +486,11 @@
+     int failures,
+     const serf_ssl_certificate_t *cert);
+ 
++typedef apr_status_t (*serf_ssl_need_server_cert_chain_t)(
++    void *data,
++    int failures,
++    const char **certs);
++
+ void serf_ssl_client_cert_provider_set(
+     serf_ssl_context_t *context,
+     serf_ssl_need_client_cert_t callback,
+@@ -508,6 +513,16 @@
+     void *data);
+ 
+ /**
++ * Set a callback to override the default SSL server certificate validation
++ * algorithm. This callback is provided with the certificate chain of the 
++ * server.
++ */
++void serf_ssl_server_cert_chain_callback_set(
++    serf_ssl_context_t *context,
++    serf_ssl_need_server_cert_chain_t callback,
++    void *data);
++
++/**
+  * Use the default root CA certificates as included with the OpenSSL library.
+  */
+ apr_status_t serf_ssl_use_default_certificates(
+@@ -630,4 +645,4 @@
+ }
+ #endif
+ 
+-#endif	/* !SERF_BUCKET_TYPES_H */
++#endif /* !SERF_BUCKET_TYPES_H */
+--- misc/serf-1.0.0/test/serf_get.c	2011-06-25 18:01:01.000000000 +0200
++++ misc/build/serf-1.0.0/test/serf_get.c	2012-02-24 14:29:02.520458400 +0100
+@@ -49,6 +49,21 @@
+     return APR_SUCCESS;
+ }
+ 
++static apr_status_t print_cert_chain(void *data, int failures,
++                                     const char **certs)
++{
++    const char *current;
++    while ((current = *certs) != NULL)
++    {   
++        printf("-----BEGIN CERTIFICATE-----\n");
++        printf("%s\n", current);
++        printf("-----END CERTIFICATE-----\n");
++        ++certs;
++    }    
++
++    return APR_SUCCESS;
++}
++
+ static apr_status_t conn_setup(apr_socket_t *skt,
+                                 serf_bucket_t **input_bkt,
+                                 serf_bucket_t **output_bkt,
+@@ -65,6 +80,7 @@
+             ctx->ssl_ctx = serf_bucket_ssl_decrypt_context_get(c);
+         }
+         serf_ssl_server_cert_callback_set(ctx->ssl_ctx, ignore_all_cert_errors, NULL);
++        serf_ssl_server_cert_chain_callback_set(ctx->ssl_ctx, print_cert_chain, NULL);
+         serf_ssl_set_hostname(ctx->ssl_ctx, ctx->hostinfo);
+ 
+         *output_bkt = serf_bucket_ssl_encrypt_create(*output_bkt, ctx->ssl_ctx,

Added: incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68b.patch
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68b.patch?rev=1295493&view=auto
==============================================================================
--- incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68b.patch (added)
+++ incubator/ooo/trunk/ext_libraries/serf/serf-1.0.0.issue68b.patch Thu Mar  1 10:14:02 2012
@@ -0,0 +1,108 @@
+--- misc/serf-1.0.0/buckets/ssl_buckets.c	2012-02-29 11:04:40.203782000 +0100
++++ misc/build/serf-1.0.0/buckets/ssl_buckets.c	2012-02-29 10:55:33.127491000 +0100
+@@ -481,37 +481,45 @@
+ 
+     /* This provides the entire chain so we only call it when the end 
+      * entity certificate is reached. */
+-    if (ctx->server_cert_chain_callback && depth == 0) {
+-        apr_status_t status;
+-        STACK_OF(X509) *chain;
+-        const char **ascii_certs;
+-        apr_pool_t *subpool;
++    if (ctx->server_cert_chain_callback != NULL)
++    {
++        if (depth == 0)
++        {
++            apr_status_t status;
++            STACK_OF(X509) *chain;
++            const char **ascii_certs;
++            apr_pool_t *subpool;
+ 
+-        apr_pool_create(&subpool, ctx->pool);
++            apr_pool_create(&subpool, ctx->pool);
+  
+-        chain = X509_STORE_CTX_get1_chain(store_ctx);
+-        /* Fallback to the current certificate if the chain cannot be 
+-         * retrieved. */
+-        if ( ! chain) {
+-            chain = sk_X509_new_null();
+-            sk_X509_push(chain, X509_dup(server_cert));
+-        }
+-        ascii_certs = export_certificates(chain, subpool); 
+-
+-        /* Callback for further verification. */
+-        status = 
+-            ctx->server_cert_chain_callback(ctx->server_cert_chain_userdata, 
+-                                            failures, ascii_certs);
+-        if (status == APR_SUCCESS)
+-            cert_valid = 1;
+-        else
+-            /* Pass the error back to the caller through the context-run. */
+-            ctx->pending_err = status;
++            chain = X509_STORE_CTX_get1_chain(store_ctx);
++            /* Fallback to the current certificate if the chain cannot be 
++             * retrieved. */
++            if ( ! chain) {
++                chain = sk_X509_new_null();
++                sk_X509_push(chain, X509_dup(server_cert));
++            }
++            ascii_certs = export_certificates(chain, subpool); 
++
++            /* Callback for further verification. */
++            status = 
++                ctx->server_cert_chain_callback(ctx->server_cert_chain_userdata, 
++                    failures, ascii_certs, sk_X509_num(chain));
++            if (status == APR_SUCCESS)
++                cert_valid = 1;
++            else
++                /* Pass the error back to the caller through the context-run. */
++                ctx->pending_err = status;
+         
+-        sk_X509_pop_free(chain, X509_free);
+-        apr_pool_destroy(subpool);
++            sk_X509_pop_free(chain, X509_free);
++            apr_pool_destroy(subpool);
++        }
++        else
++        {
++            // Keep the process going until depth==0 is reached.
++            cert_valid = 1;
++        }
+     }
+-
+     return cert_valid;
+ }
+ 
+@@ -1091,6 +1099,10 @@
+     ssl_ctx->pool = pool;
+     ssl_ctx->allocator = allocator;
+ 
++    ssl_ctx->cert_callback = NULL;
++    ssl_ctx->server_cert_callback = NULL;
++    ssl_ctx->server_cert_chain_callback = NULL;
++
+     ssl_ctx->ctx = SSL_CTX_new(SSLv23_client_method());
+ 
+     SSL_CTX_set_client_cert_cb(ssl_ctx->ctx, ssl_need_client_cert);
+--- misc/serf-1.0.0/build/serf.def	2011-07-15 23:47:01.000000000 +0200
++++ misc/build/serf-1.0.0/build/serf.def	2012-02-27 14:24:23.526967200 +0100
+@@ -83,6 +83,7 @@
+ serf_ssl_client_cert_provider_set
+ serf_ssl_client_cert_password_set
+ serf_ssl_server_cert_callback_set
++serf_ssl_server_cert_chain_callback_set
+ serf_ssl_use_default_certificates
+ serf_ssl_set_hostname
+ serf_ssl_cert_depth
+--- misc/serf-1.0.0/serf_bucket_types.h	2012-02-29 11:04:40.226783300 +0100
++++ misc/build/serf-1.0.0/serf_bucket_types.h	2012-02-27 14:24:23.510966300 +0100
+@@ -489,7 +489,8 @@
+ typedef apr_status_t (*serf_ssl_need_server_cert_chain_t)(
+     void *data,
+     int failures,
+-    const char **certs);
++    const char **certs,
++    int nCertificateChainLength);
+ 
+ void serf_ssl_client_cert_provider_set(
+     serf_ssl_context_t *context,

Modified: incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.cxx?rev=1295493&r1=1295492&r2=1295493&view=diff
==============================================================================
--- incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.cxx (original)
+++ incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.cxx Thu Mar  1 10:14:02 2012
@@ -61,13 +61,14 @@ extern "C" apr_status_t Serf_Credentials
                                              pool );
 }
 
-extern "C" apr_status_t Serf_CertificationValidation( void *data,
-                                                      int failures,
-                                                      const serf_ssl_certificate_t *cert )
+extern "C" apr_status_t Serf_CertificateChainValidation(
+    void* pSerfSession,
+    int nFailures,
+    const char** pCertificateChainBase64Encoded,
+    int nCertificateChainLength)
 {
-    SerfSession* pSerfSession = static_cast< SerfSession* >( data );
-    return pSerfSession->verifySerfCertificate( failures, 
-                                                cert );
+    return static_cast<SerfSession*>(pSerfSession)
+        ->verifySerfCertificateChain(nFailures, pCertificateChainBase64Encoded, nCertificateChainLength);
 }
 
 extern "C" apr_status_t Serf_SetupRequest( serf_request_t *request,

Modified: incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.hxx?rev=1295493&r1=1295492&r2=1295493&view=diff
==============================================================================
--- incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.hxx (original)
+++ incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfCallbacks.hxx Thu Mar  1 10:14:02 2012
@@ -37,12 +37,14 @@ extern "C" apr_status_t Serf_Credentials
                                           void *baton,
                                           int code, 
                                           const char *authn_type,
-                                          const char *realm,
-                                          apr_pool_t *pool );
+                                          const char *realm,
+                                          apr_pool_t *pool );
 
-extern "C" apr_status_t Serf_CertificationValidation( void *data,
-                                                      int failures,
-                                                      const serf_ssl_certificate_t *cert );
+extern "C" apr_status_t Serf_CertificateChainValidation(
+    void* pSerfSession,
+    int nFailures,
+    const char** pCertificateChainBase64Encoded,
+    int nCertificateChainLength);
 
 extern "C" apr_status_t Serf_SetupRequest( serf_request_t *request,
                                            void *setup_baton,

Modified: incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.cxx?rev=1295493&r1=1295492&r2=1295493&view=diff
==============================================================================
--- incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.cxx (original)
+++ incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.cxx Thu Mar  1 10:14:02 2012
@@ -53,6 +53,7 @@
 using namespace com::sun::star;
 using namespace http_dav_ucp;
 
+
 // -------------------------------------------------------------------
 // static members!
 bool SerfSession::m_bGlobalsInited = false;
@@ -269,9 +270,13 @@ apr_status_t SerfSession::setupSerfConne
         tmpInputBkt = serf_bucket_ssl_decrypt_create( tmpInputBkt,
                                                       0,
                                                       getSerfBktAlloc() );
-        serf_ssl_server_cert_callback_set( serf_bucket_ssl_decrypt_context_get( tmpInputBkt ), 
-                                           Serf_CertificationValidation, 
-                                           this );
+        /** Set the callback that is called to authenticate the
+            certifcate (chain).
+        */
+        serf_ssl_server_cert_chain_callback_set(
+            serf_bucket_ssl_decrypt_context_get(tmpInputBkt),
+            Serf_CertificateChainValidation,
+            this);
         serf_ssl_set_hostname( serf_bucket_ssl_decrypt_context_get( tmpInputBkt ), 
                                getHostinfo() );
 
@@ -365,131 +370,152 @@ namespace {
     }
 } // namespace
 
-apr_status_t SerfSession::verifySerfCertificate( int inFailures,
-                                                 const serf_ssl_certificate_t * inCert )
+
+apr_status_t SerfSession::verifySerfCertificateChain (
+    int,
+    const char** pCertificateChainBase64Encoded,
+    const int nCertificateChainLength)
 {
-    OSL_ASSERT( inCert );
+    // Check arguments.
+    if (pCertificateChainBase64Encoded == NULL || nCertificateChainLength<=0)
+    {
+        OSL_ASSERT(pCertificateChainBase64Encoded != NULL);
+        OSL_ASSERT(nCertificateChainLength>0);
+        return SERF_SSL_CERT_UNKNOWN_FAILURE;
+    }
 
+    // Create some crypto objects to decode and handle the base64
+    // encoded certificate chain.
+    uno::Reference< xml::crypto::XSEInitializer > xSEInitializer;
     uno::Reference< security::XCertificateContainer > xCertificateContainer;
+    uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext;
+    uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv;
     try
     {
-        xCertificateContainer
-            = uno::Reference< security::XCertificateContainer >(
-                getMSF()->createInstance(
-                    rtl::OUString::createFromAscii(
-                        "com.sun.star.security.CertificateContainer" ) ),
-                uno::UNO_QUERY );
-    }
-    catch ( uno::Exception const & )
-    {
-    }
+        // Create a certificate container.
+        xCertificateContainer = uno::Reference< security::XCertificateContainer >(
+            getMSF()->createInstance(
+                rtl::OUString::createFromAscii(
+                    "com.sun.star.security.CertificateContainer" ) ),
+            uno::UNO_QUERY_THROW);
 
-    if ( !xCertificateContainer.is() )
-        return SERF_SSL_CERT_UNKNOWN_FAILURE;
+        xSEInitializer = uno::Reference< xml::crypto::XSEInitializer >(
+            getMSF()->createInstance(
+                rtl::OUString::createFromAscii( "com.sun.star.xml.crypto.SEInitializer" ) ),
+            uno::UNO_QUERY_THROW);
 
-    inFailures = 0;
+        xSecurityContext = xSEInitializer->createSecurityContext( rtl::OUString() );
+        if (xSecurityContext.is())
+            xSecurityEnv = xSecurityContext->getSecurityEnvironment();
 
-    const char * subjectItem = static_cast<char*>(apr_hash_get( serf_ssl_cert_subject( inCert, getAprPool() ),
-                                                                "CN", APR_HASH_KEY_STRING ));
-    if ( subjectItem == 0 )
-    {
-        subjectItem = static_cast<char*>(apr_hash_get( serf_ssl_cert_subject( inCert, getAprPool() ),
-                                                       "OU", APR_HASH_KEY_STRING ));
+        if ( ! xSecurityContext.is() || ! xSecurityEnv.is())
+        {
+            // Do we have to dispose xSEInitializer or xCertificateContainer?
+            return SERF_SSL_CERT_UNKNOWN_FAILURE;
+        }
     }
-    rtl::OUString cert_subject;
-    if ( subjectItem != 0 )
+    catch ( uno::Exception const &)
     {
-        cert_subject = rtl::OUString( subjectItem, strlen( subjectItem ), RTL_TEXTENCODING_UTF8, 0 );
+        return SERF_SSL_CERT_UNKNOWN_FAILURE;
     }
-    else
+
+    // Decode the server certificate.
+    uno::Reference< security::XCertificate > xServerCertificate(
+        xSecurityEnv->createCertificateFromAscii(
+            rtl::OUString::createFromAscii(pCertificateChainBase64Encoded[0])));
+    if ( ! xServerCertificate.is())
+        return SERF_SSL_CERT_UNKNOWN_FAILURE;
+
+    // Get the subject from the server certificate.
+    ::rtl::OUString sServerCertificateSubject (xServerCertificate->getSubjectName());
+    sal_Int32 nIndex = 0;
+    while (nIndex >= 0)
     {
-        rtl::OUString::createFromAscii( "unknown subject" );
+        const ::rtl::OUString sToken (sServerCertificateSubject.getToken(0, ',', nIndex));
+        if (sToken.compareToAscii("CN=", 3) == 0)
+        {
+            sServerCertificateSubject = sToken.copy(3);
+            break;
+        }
+        else if (sToken.compareToAscii(" CN=", 4) == 0)
+        {
+            sServerCertificateSubject = sToken.copy(4);
+            break;
+        }
     }
 
-    security::CertificateContainerStatus certificateContainer(
+    // When the certificate container already contains a (trusted)
+    // entry for the server then we do not have to authenticate any
+    // certificate.
+    const security::CertificateContainerStatus eStatus (
         xCertificateContainer->hasCertificate(
-            getHostName(), cert_subject ) );
-
-    if ( certificateContainer != security::CertificateContainerStatus_NOCERT )
+            getHostName(), sServerCertificateSubject ) );
+    if (eStatus != security::CertificateContainerStatus_NOCERT)
     {
-        return certificateContainer == security::CertificateContainerStatus_TRUSTED
+        return eStatus == security::CertificateContainerStatus_TRUSTED
                ? APR_SUCCESS
                : SERF_SSL_CERT_UNKNOWN_FAILURE;
     }
 
-    uno::Reference< xml::crypto::XSEInitializer > xSEInitializer;
-    try
+    // The shortcut failed, so try to verify the whole chain.  This is
+    // done outside the isDomainMatch() block because the result is
+    // used by the interaction handler.
+    std::vector< uno::Reference< security::XCertificate > > aChain;
+    for (int nIndex=1; nIndex<nCertificateChainLength; ++nIndex)
     {
-        xSEInitializer = uno::Reference< xml::crypto::XSEInitializer >(
-            getMSF()->createInstance(
-                rtl::OUString::createFromAscii( "com.sun.star.xml.crypto.SEInitializer" ) ),
-            uno::UNO_QUERY );
-    }
-    catch ( uno::Exception const & )
-    {
-    }
-
-    if ( !xSEInitializer.is() )
-        return SERF_SSL_CERT_UNKNOWN_FAILURE;
-
-    uno::Reference< xml::crypto::XXMLSecurityContext > xSecurityContext(
-        xSEInitializer->createSecurityContext( rtl::OUString() ) );
-
-    uno::Reference< xml::crypto::XSecurityEnvironment > xSecurityEnv(
-        xSecurityContext->getSecurityEnvironment() );
-
-    //The end entity certificate
-    const char * eeCertB64 = serf_ssl_cert_export( inCert, getAprPool() );
-
-    rtl::OString sEECertB64( eeCertB64 );
-
-    uno::Reference< security::XCertificate > xEECert(
-        xSecurityEnv->createCertificateFromAscii(
-            rtl::OStringToOUString( sEECertB64, RTL_TEXTENCODING_ASCII_US ) ) );
-
-    std::vector< uno::Reference< security::XCertificate > > vecCerts;
-    const serf_ssl_certificate_t * issuerCert = inCert;
-    do
-    {
-        //get the intermediate certificate
-        issuerCert = NULL; // TODO - figure out how to retrieve certificate chain - ssl_cert_signedby( issuerCert );
-        if ( NULL == issuerCert )
-            break;
-
-        const char * imCertB64 = serf_ssl_cert_export( issuerCert, getAprPool() );
-        rtl::OString sInterMediateCertB64( imCertB64 );
-
-        uno::Reference< security::XCertificate> xImCert(
+        uno::Reference< security::XCertificate > xCertificate(
             xSecurityEnv->createCertificateFromAscii(
-                rtl::OStringToOUString(
-                    sInterMediateCertB64, RTL_TEXTENCODING_ASCII_US ) ) );
-        if ( xImCert.is() )
-            vecCerts.push_back( xImCert );
+                rtl::OUString::createFromAscii(pCertificateChainBase64Encoded[nIndex])));
+        if ( ! xCertificate.is())
+            return SERF_SSL_CERT_UNKNOWN_FAILURE;
+        aChain.push_back(xCertificate);
     }
-    while ( 1 );
-
-    sal_Int64 certValidity = xSecurityEnv->verifyCertificate( xEECert,
-        ::comphelper::containerToSequence( vecCerts ) );
+    const sal_Int64 nVerificationResult (xSecurityEnv->verifyCertificate(
+            xServerCertificate,
+            ::comphelper::containerToSequence(aChain)));
 
-    if ( isDomainMatch( GetHostnamePart( xEECert.get()->getSubjectName() ) ) )
+    // When the certificate matches the host name then we can use the
+    // result of the verification.
+    if (isDomainMatch(sServerCertificateSubject))
     {
-        // if host name matched with certificate then look if the
-        // certificate was ok
-        if( certValidity == security::CertificateValidity::VALID )
+
+        if (nVerificationResult == 0)
+        {
+            // Certificate (chain) is valid.
+            xCertificateContainer->addCertificate(getHostName(), sServerCertificateSubject,  sal_True);
             return APR_SUCCESS;
+        }
+        else if ((nVerificationResult & security::CertificateValidity::CHAIN_INCOMPLETE) != 0)
+        {
+            // We do not have enough information for verification,
+            // neither automatically (as we just discovered) nor
+            // manually (so there is no point in showing any dialog.)
+            return SERF_SSL_CERT_UNKNOWN_FAILURE;
+        }
+        else if ((nVerificationResult &
+                (security::CertificateValidity::INVALID | security::CertificateValidity::REVOKED)) != 0)
+        {
+            // Certificate (chain) is invalid.
+            xCertificateContainer->addCertificate(getHostName(), sServerCertificateSubject,  sal_False);
+            return SERF_SSL_CERT_UNKNOWN_FAILURE;
+        }
+        else
+        {
+            // For all other we have to ask the user.
+        }
     }
 
+    // We have not been able to automatically verify (or falsify) the
+    // certificate chain.  To resolve this we have to ask the user.
     const uno::Reference< ucb::XCommandEnvironment > xEnv( getRequestEnvironment().m_xEnv );
     if ( xEnv.is() )
     {
-        inFailures = static_cast< int >( certValidity );
-
         uno::Reference< task::XInteractionHandler > xIH( xEnv->getInteractionHandler() );
         if ( xIH.is() )
         {
             rtl::Reference< ucbhelper::SimpleCertificateValidationRequest >
                 xRequest( new ucbhelper::SimpleCertificateValidationRequest(
-                    (sal_Int32)inFailures, xEECert, getHostName() ) );
+                        static_cast<sal_Int32>(nVerificationResult), xServerCertificate, getHostName() ) );
             xIH->handle( xRequest.get() );
 
             rtl::Reference< ucbhelper::InteractionContinuation > xSelection
@@ -501,13 +527,13 @@ apr_status_t SerfSession::verifySerfCert
                     xSelection.get(), uno::UNO_QUERY );
                 if ( xApprove.is() )
                 {
-                    xCertificateContainer->addCertificate( getHostName(), cert_subject,  sal_True );
+                    xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject,  sal_True );
                     return APR_SUCCESS;
                 }
                 else
                 {
                     // Don't trust cert
-                    xCertificateContainer->addCertificate( getHostName(), cert_subject, sal_False );
+                    xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, sal_False );
                     return SERF_SSL_CERT_UNKNOWN_FAILURE;
                 }
             }
@@ -515,10 +541,11 @@ apr_status_t SerfSession::verifySerfCert
         else
         {
             // Don't trust cert
-            xCertificateContainer->addCertificate( getHostName(), cert_subject, sal_False );
+            xCertificateContainer->addCertificate( getHostName(), sServerCertificateSubject, sal_False );
             return SERF_SSL_CERT_UNKNOWN_FAILURE;
         }
     }
+
     return SERF_SSL_CERT_UNKNOWN_FAILURE;
 }
 

Modified: incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.hxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.hxx?rev=1295493&r1=1295492&r2=1295493&view=diff
==============================================================================
--- incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.hxx (original)
+++ incubator/ooo/trunk/main/ucb/source/ucp/webdav/SerfSession.hxx Thu Mar  1 10:14:02 2012
@@ -91,11 +91,13 @@ public:
                                          serf_request_t * inRequest, 
                                          int inCode, 
                                          const char *inAuthProtocol,
-                                         const char *inRealm,
+                                         const char *inRealm,
                                          apr_pool_t *inAprPool );
 
-    apr_status_t verifySerfCertificate( int inFailures,
-                                        const serf_ssl_certificate_t * inCert );
+    apr_status_t verifySerfCertificateChain (
+        int nFailures,
+        const char** pCertificateChainBase64Encoded,
+        int nCertificateChainLength);
 
     serf_bucket_t* acceptSerfResponse( serf_request_t * inSerfRequest,
                                        serf_bucket_t * inSerfStreamBucket,