diff options
-rw-r--r-- | chrome/chrome_tests.gypi | 6 | ||||
-rw-r--r-- | net/base/keygen_handler_openssl.cc | 4 | ||||
-rw-r--r-- | net/base/keygen_handler_unittest.cc | 16 | ||||
-rw-r--r-- | net/base/x509_certificate_openssl.cc | 25 | ||||
-rw-r--r-- | net/base/x509_openssl_util.cc | 12 | ||||
-rw-r--r-- | net/base/x509_openssl_util_unittest.cc | 3 | ||||
-rw-r--r-- | net/http/des.cc | 15 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl.cc | 54 | ||||
-rw-r--r-- | net/socket/ssl_client_socket_openssl.h | 7 | ||||
-rw-r--r-- | net/test/test_server.cc | 2 | ||||
-rw-r--r-- | net/test/test_server.h | 4 |
11 files changed, 120 insertions, 28 deletions
diff --git a/chrome/chrome_tests.gypi b/chrome/chrome_tests.gypi index 24a4161..2904701 100644 --- a/chrome/chrome_tests.gypi +++ b/chrome/chrome_tests.gypi @@ -1891,6 +1891,12 @@ ['exclude', '^../views/'], ], }], + ['use_openssl==1', { + 'sources/': [ + # OpenSSL build does not support firefox importer. See http://crbug.com/64926 + ['exclude', '^browser/importer/'], + ], + }], ], }, { diff --git a/net/base/keygen_handler_openssl.cc b/net/base/keygen_handler_openssl.cc index 0f5d874..ecbd683 100644 --- a/net/base/keygen_handler_openssl.cc +++ b/net/base/keygen_handler_openssl.cc @@ -4,15 +4,15 @@ #include "net/base/keygen_handler.h" -#if defined(USE_OPENSSL) +#include "base/logging.h" namespace net { std::string KeygenHandler::GenKeyAndSignChallenge() { // TODO(bulach): implement me. + NOTIMPLEMENTED(); return ""; } } // namespace net -#endif // USE_OPENSSL diff --git a/net/base/keygen_handler_unittest.cc b/net/base/keygen_handler_unittest.cc index d3bf4f5..408eb76 100644 --- a/net/base/keygen_handler_unittest.cc +++ b/net/base/keygen_handler_unittest.cc @@ -73,7 +73,13 @@ void AssertValidSignedPublicKeyAndChallenge(const std::string& result, // openssl asn1parse -inform DER } -TEST_F(KeygenHandlerTest, SmokeTest) { +// Keygen not yet implemented for OpenSSL: http://crbug.com/64917 +#if defined(USE_OPENSSL) +#define MAYBE_SmokeTest FAILS_SmokeTest +#else +#define MAYBE_SmokeTest SmokeTest +#endif +TEST_F(KeygenHandlerTest, MAYBE_SmokeTest) { KeygenHandler handler(768, "some challenge", GURL("http://www.example.com")); handler.set_stores_key(false); // Don't leave the key-pair behind std::string result = handler.GenKeyAndSignChallenge(); @@ -117,9 +123,15 @@ class ConcurrencyTestTask : public Task { std::string* result_; }; +// Keygen not yet implemented for OpenSSL: http://crbug.com/64917 +#if defined(USE_OPENSSL) +#define MAYBE_ConcurrencyTest FAILS_ConcurrencyTest +#else +#define MAYBE_ConcurrencyTest ConcurrencyTest +#endif // We asynchronously generate the keys so as not to hang up the IO thread. This // test tries to catch concurrency problems in the keygen implementation. -TEST_F(KeygenHandlerTest, ConcurrencyTest) { +TEST_F(KeygenHandlerTest, MAYBE_ConcurrencyTest) { const int NUM_HANDLERS = 5; base::WaitableEvent* events[NUM_HANDLERS] = { NULL }; std::string results[NUM_HANDLERS]; diff --git a/net/base/x509_certificate_openssl.cc b/net/base/x509_certificate_openssl.cc index d2c7653..abddd97 100644 --- a/net/base/x509_certificate_openssl.cc +++ b/net/base/x509_certificate_openssl.cc @@ -425,19 +425,22 @@ int X509Certificate::Verify(const std::string& hostname, cert_handle_, intermediates.get()); CHECK_EQ(1, rv); - if (X509_verify_cert(ctx.get()) == 1) { - return OK; + if (X509_verify_cert(ctx.get()) != 1) { + int x509_error = X509_STORE_CTX_get_error(ctx.get()); + int cert_status = MapCertErrorToCertStatus(x509_error); + LOG(ERROR) << "X509 Verification error " + << X509_verify_cert_error_string(x509_error) + << " : " << x509_error + << " : " << X509_STORE_CTX_get_error_depth(ctx.get()) + << " : " << cert_status; + verify_result->cert_status |= cert_status; + return MapCertStatusToNetError(verify_result->cert_status); } - int x509_error = X509_STORE_CTX_get_error(ctx.get()); - int cert_status = MapCertErrorToCertStatus(x509_error); - LOG(ERROR) << "X509 Verification error " - << X509_verify_cert_error_string(x509_error) - << " : " << x509_error - << " : " << X509_STORE_CTX_get_error_depth(ctx.get()) - << " : " << cert_status; - verify_result->cert_status |= cert_status; - return MapCertStatusToNetError(verify_result->cert_status); + if (IsCertStatusError(verify_result->cert_status)) + return MapCertStatusToNetError(verify_result->cert_status); + + return OK; } // static diff --git a/net/base/x509_openssl_util.cc b/net/base/x509_openssl_util.cc index 9e44c4b..0bb4002 100644 --- a/net/base/x509_openssl_util.cc +++ b/net/base/x509_openssl_util.cc @@ -149,9 +149,17 @@ bool VerifyHostname(const std::string& hostname, } DCHECK(!reference_name.empty()); - // TODO(joth): Add IP address support. See http://crbug.com/62973 if (found_ip6_chars || !found_alpha) { - NOTIMPLEMENTED() << hostname; + // For now we just do simple localhost IP address support, primarily as + // it's needed by the test server. TODO(joth): Replace this with full IP + // address support. See http://crbug.com/62973 + if (hostname == "127.0.0.1" && + std::find(cert_names.begin(), cert_names.end(), hostname) + != cert_names.end()) { + DVLOG(1) << "Allowing localhost IP certificate: " << hostname; + return true; + } + NOTIMPLEMENTED() << hostname; // See comment above. return false; } diff --git a/net/base/x509_openssl_util_unittest.cc b/net/base/x509_openssl_util_unittest.cc index 50589ad..4727d4c 100644 --- a/net/base/x509_openssl_util_unittest.cc +++ b/net/base/x509_openssl_util_unittest.cc @@ -60,7 +60,8 @@ CertificateNameVerifyTestData kNameVerifyTestData[] = { { false, "baz2.example.net", "baz*.example.net" }, { false, "bar.*.example.net", "bar.*.example.net" }, { false, "bar.f*o.example.net", "bar.f*o.example.net" }, - // IP addresses currently not supported. + // IP addresses currently not supported, except for the localhost. + { true, "127.0.0.1", "127.0.0.1" }, { false, "192.168.1.1", "192.168.1.1" }, { false, "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210", "FEDC:BA98:7654:3210:FEDC:BA98:7654:3210" }, diff --git a/net/http/des.cc b/net/http/des.cc index 11d7a26..30706e9 100644 --- a/net/http/des.cc +++ b/net/http/des.cc @@ -6,7 +6,10 @@ #include "base/logging.h" -#if defined(USE_NSS) +#if defined(USE_OPENSSL) +#include <openssl/des.h> +#include "base/openssl_util.h" +#elif defined(USE_NSS) #include <nss.h> #include <pk11pub.h> #include "base/nss_util.h" @@ -87,8 +90,14 @@ void DESMakeKey(const uint8* raw, uint8* key) { #if defined(USE_OPENSSL) void DESEncrypt(const uint8* key, const uint8* src, uint8* hash) { - // TODO(joth): When implementing consider splitting up this file by platform. - NOTIMPLEMENTED(); + base::EnsureOpenSSLInit(); + + DES_key_schedule ks; + DES_set_key_unchecked( + reinterpret_cast<const_DES_cblock*>(const_cast<uint8*>(key)), &ks); + + DES_ecb_encrypt(reinterpret_cast<const_DES_cblock*>(const_cast<uint8*>(src)), + reinterpret_cast<DES_cblock*>(hash), &ks, DES_ENCRYPT); } #elif defined(USE_NSS) diff --git a/net/socket/ssl_client_socket_openssl.cc b/net/socket/ssl_client_socket_openssl.cc index da40011..7fe7712 100644 --- a/net/socket/ssl_client_socket_openssl.cc +++ b/net/socket/ssl_client_socket_openssl.cc @@ -16,6 +16,7 @@ #include "base/singleton.h" #include "net/base/cert_verifier.h" #include "net/base/net_errors.h" +#include "net/base/ssl_cert_request_info.h" #include "net/base/ssl_connection_status_flags.h" #include "net/base/ssl_info.h" @@ -173,6 +174,7 @@ class SSLContext { SSL_CTX_sess_set_remove_cb(ssl_ctx_.get(), RemoveSessionCallbackStatic); SSL_CTX_set_timeout(ssl_ctx_.get(), kSessionCacheTimeoutSeconds); SSL_CTX_sess_set_cache_size(ssl_ctx_.get(), kSessionCacheMaxEntires); + SSL_CTX_set_client_cert_cb(ssl_ctx_.get(), ClientCertCallback); } static int NewSessionCallbackStatic(SSL* ssl, SSL_SESSION* session) { @@ -194,6 +196,12 @@ class SSLContext { session_cache_.OnSessionRemoved(session); } + static int ClientCertCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey) { + SSLClientSocketOpenSSL* socket = Get()->GetClientSocketFromSSL(ssl); + CHECK(socket); + return socket->ClientCertRequestCallback(ssl, x509, pkey); + } + // This is the index used with SSL_get_ex_data to retrieve the owner // SSLClientSocketOpenSSL object from an SSL instance. int ssl_socket_data_index_; @@ -356,7 +364,8 @@ void SSLClientSocketOpenSSL::GetSSLInfo(SSLInfo* ssl_info) { void SSLClientSocketOpenSSL::GetSSLCertRequestInfo( SSLCertRequestInfo* cert_request_info) { - NOTREACHED(); + cert_request_info->host_and_port = host_and_port_.ToString(); + cert_request_info->client_certs = client_certs_; } SSLClientSocket::NextProtoStatus SSLClientSocketOpenSSL::GetNextProto( @@ -493,12 +502,26 @@ int SSLClientSocketOpenSSL::DoHandshake() { int net_error = net::OK; int rv = SSL_do_handshake(ssl_); - if (rv == 1) { + if (client_auth_cert_needed_) { + net_error = ERR_SSL_CLIENT_AUTH_CERT_NEEDED; + // If the handshake already succeeded (because the server requests but + // doesn't require a client cert), we need to invalidate the SSL session + // so that we won't try to resume the non-client-authenticated session in + // the next handshake. This will cause the server to ask for a client + // cert again. + if (rv == 1) { + // Remove from session cache but don't clear this connection. + SSL_SESSION* session = SSL_get_session(ssl_); + if (session) { + int rv = SSL_CTX_remove_session(SSL_get_SSL_CTX(ssl_), session); + LOG_IF(WARNING, !rv) << "Couldn't invalidate SSL session: " << session; + } + } + } else if (rv == 1) { if (trying_cached_session_ && logging::DEBUG_MODE) { DVLOG(2) << "Result of session reuse for " << host_and_port_.ToString() << " is: " << (SSL_session_reused(ssl_) ? "Success" : "Fail"); } - // SSL handshake is completed. Let's verify the certificate. const bool got_cert = !!UpdateServerCert(); DCHECK(got_cert); @@ -519,6 +542,31 @@ int SSLClientSocketOpenSSL::DoHandshake() { return net_error; } +int SSLClientSocketOpenSSL::ClientCertRequestCallback(SSL* ssl, + X509** x509, + EVP_PKEY** pkey) { + DVLOG(3) << "OpenSSL ClientCertRequestCallback called"; + DCHECK(ssl == ssl_); + DCHECK(*x509 == NULL); + DCHECK(*pkey == NULL); + + if (!ssl_config_.send_client_cert) { + client_auth_cert_needed_ = true; + return -1; // Suspends handshake. + } + + // Second pass: a client certificate should have been selected. + if (ssl_config_.client_cert) { + // TODO(joth): We need a way to lookup the private key this + // certificate. See http://crbug.com/64951 and example code in + // http://codereview.chromium.org/5195001/diff/6001/net/socket/ssl_client_socket_openssl.cc + NOTIMPLEMENTED(); + } + + // Send no client certificate. + return 0; +} + int SSLClientSocketOpenSSL::DoVerifyCert(int result) { DCHECK(server_cert_); GotoState(STATE_VERIFY_CERT_COMPLETE); diff --git a/net/socket/ssl_client_socket_openssl.h b/net/socket/ssl_client_socket_openssl.h index e7bfe3c..99e92f2 100644 --- a/net/socket/ssl_client_socket_openssl.h +++ b/net/socket/ssl_client_socket_openssl.h @@ -15,7 +15,9 @@ #include "net/socket/client_socket_handle.h" typedef struct bio_st BIO; +typedef struct evp_pkey_st EVP_PKEY; typedef struct ssl_st SSL; +typedef struct x509_st X509; namespace net { @@ -38,6 +40,10 @@ class SSLClientSocketOpenSSL : public SSLClientSocket { const HostPortPair& host_and_port() const { return host_and_port_; } + // Callback from the SSL layer that indicates the remote server is requesting + // a certificate for this client. + int ClientCertRequestCallback(SSL* ssl, X509** x509, EVP_PKEY** pkey); + // SSLClientSocket methods: virtual void GetSSLInfo(SSLInfo* ssl_info); virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info); @@ -71,7 +77,6 @@ class SSLClientSocketOpenSSL : public SSLClientSocket { int DoVerifyCert(int result); int DoVerifyCertComplete(int result); void DoConnectCallback(int result); - void InvalidateSessionIfBadCertificate(); X509Certificate* UpdateServerCert(); void OnHandshakeIOComplete(int result); diff --git a/net/test/test_server.cc b/net/test/test_server.cc index 0eaf8b5..d2d3fde 100644 --- a/net/test/test_server.cc +++ b/net/test/test_server.cc @@ -314,7 +314,7 @@ FilePath TestServer::GetRootCertificatePath() { } bool TestServer::LoadTestRootCert() { -#if defined(USE_NSS) +#if defined(USE_OPENSSL) || defined(USE_NSS) if (cert_) return true; diff --git a/net/test/test_server.h b/net/test/test_server.h index 00a8fc9..1ae0a50 100644 --- a/net/test/test_server.h +++ b/net/test/test_server.h @@ -22,7 +22,7 @@ #include "base/scoped_handle_win.h" #endif -#if defined(USE_NSS) +#if defined(USE_OPENSSL) || defined(USE_NSS) #include "base/ref_counted.h" #include "net/base/x509_certificate.h" #endif @@ -200,7 +200,7 @@ class TestServer { // If |type_| is TYPE_HTTPS, the TLS settings to use for the test server. HTTPSOptions https_options_; -#if defined(USE_NSS) +#if defined(USE_OPENSSL) || defined(USE_NSS) scoped_refptr<X509Certificate> cert_; #endif |