| Index: net/url_request/url_request_unittest.cc
|
| diff --git a/net/url_request/url_request_unittest.cc b/net/url_request/url_request_unittest.cc
|
| index 26185bd77e4c81bcbca145fb7ca9ab76056b5d7c..7791a048d20634fc9fb6494c8afef7e7bae47840 100644
|
| --- a/net/url_request/url_request_unittest.cc
|
| +++ b/net/url_request/url_request_unittest.cc
|
| @@ -9,6 +9,7 @@
|
| #include <windows.h>
|
| #elif defined(USE_NSS)
|
| #include "base/nss_util.h"
|
| +#include <sslproto.h>
|
| #endif
|
|
|
| #include <algorithm>
|
| @@ -33,6 +34,7 @@
|
| #include "net/base/net_module.h"
|
| #include "net/base/net_util.h"
|
| #include "net/base/ssl_connection_status_flags.h"
|
| +#include "net/base/cert_status_flags.h"
|
| #include "net/base/upload_data.h"
|
| #include "net/disk_cache/disk_cache.h"
|
| #include "net/ftp/ftp_network_layer.h"
|
| @@ -56,7 +58,9 @@ namespace {
|
|
|
| const string16 kChrome(ASCIIToUTF16("chrome"));
|
| const string16 kSecret(ASCIIToUTF16("secret"));
|
| +const string16 kWrongSecret(ASCIIToUTF16("wrongsecret"));
|
| const string16 kUser(ASCIIToUTF16("user"));
|
| +const string16 kWrongUser(ASCIIToUTF16("wronguser"));
|
|
|
| base::StringPiece TestNetResourceProvider(int key) {
|
| return "header";
|
| @@ -113,6 +117,16 @@ void CheckSSLInfo(const net::SSLInfo& ssl_info) {
|
| EXPECT_NE(0, cipher_suite);
|
| }
|
|
|
| +// Verify that the AuthChallengeInfo for TLS-SRP has valid values.
|
| +void CheckTLSAuthChallengeInfo(net::AuthChallengeInfo* login_request,
|
| + GURL& request_url) {
|
| + EXPECT_EQ(WideToUTF8(login_request->host_and_port),
|
| + net::GetHostAndPort(request_url));
|
| + EXPECT_EQ(net::kTLSSRPScheme, WideToUTF8(login_request->scheme));
|
| + EXPECT_EQ("", WideToUTF8(login_request->realm));
|
| + EXPECT_EQ(net::AUTH_OVER_TLS, login_request->over_protocol);
|
| +}
|
| +
|
| } // namespace
|
|
|
| // Inherit PlatformTest since we require the autorelease pool on Mac OS X.f
|
| @@ -423,6 +437,30 @@ class SSLClientAuthTestDelegate : public TestDelegate {
|
| int on_certificate_requested_count_;
|
| };
|
|
|
| +class TLSSRPClientLoginTestDelegate : public TestDelegate {
|
| + public:
|
| + TLSSRPClientLoginTestDelegate() :
|
| + on_tls_login_required_count_(0),
|
| + last_login_request_info_(NULL) {
|
| + }
|
| + virtual void OnTLSLoginRequired(
|
| + net::URLRequest* request,
|
| + net::AuthChallengeInfo* login_request_info) {
|
| + on_tls_login_required_count_++;
|
| + last_login_request_info_ = login_request_info;
|
| + MessageLoop::current()->Quit();
|
| + }
|
| + int on_tls_login_required_count() {
|
| + return on_tls_login_required_count_;
|
| + };
|
| + net::AuthChallengeInfo* last_login_request_info() {
|
| + return last_login_request_info_;
|
| + }
|
| + private:
|
| + int on_tls_login_required_count_;
|
| + net::AuthChallengeInfo* last_login_request_info_;
|
| +};
|
| +
|
| } // namespace
|
|
|
| // TODO(davidben): Test the rest of the code. Specifically,
|
| @@ -463,6 +501,366 @@ TEST_F(HTTPSRequestTest, ClientAuthTest) {
|
| }
|
| }
|
|
|
| +TEST_F(HTTPSRequestTest, HTTPSSRPLoginTest) {
|
| + net::TestServer::HTTPSOptions https_options;
|
| + https_options.use_tls_srp = true;
|
| + https_options.only_tls_srp = true;
|
| + net::TestServer test_server(https_options, FilePath());
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + TestDelegate d;
|
| + {
|
| + TestURLRequest r(test_server.GetURL("tlslogininfo"), &d);
|
| + r.SetTLSLogin(kUser, kSecret);
|
| +
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| +
|
| + MessageLoop::current()->Run();
|
| +
|
| + EXPECT_NE(0, d.bytes_received());
|
| + EXPECT_TRUE(d.data_received().find(UTF16ToUTF8(kUser)) !=
|
| + std::string::npos);
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + }
|
| +}
|
| +
|
| +// Provide no TLS login credentials at first; wait to be prompted by the
|
| +// server, and then provide them.
|
| +TEST_F(HTTPSRequestTest, HTTPSSRPLoginContinueTest) {
|
| + net::TestServer::HTTPSOptions https_options;
|
| + https_options.use_tls_srp = true;
|
| + https_options.only_tls_srp = true;
|
| + net::TestServer test_server(https_options, FilePath());
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + TLSSRPClientLoginTestDelegate d;
|
| + {
|
| + GURL https_url = test_server.GetURL("tlslogininfo");
|
| + TestURLRequest r(https_url, &d);
|
| +
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(0, d.bytes_received());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + EXPECT_EQ(1, d.on_tls_login_required_count());
|
| + CheckTLSAuthChallengeInfo(d.last_login_request_info(), https_url);
|
| +
|
| + r.SetTLSLogin(kUser, kSecret);
|
| + r.ContinueWithTLSLogin();
|
| + MessageLoop::current()->Run();
|
| +
|
| + EXPECT_NE(0, d.bytes_received());
|
| + EXPECT_TRUE(d.data_received().find(UTF16ToUTF8(kUser)) !=
|
| + std::string::npos);
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + }
|
| +}
|
| +
|
| +// Open a connection to the same host using SSL certificate auth, and then open
|
| +// a connection to the same host requesting TLS-SRP auth.
|
| +// TODO(sqs): disabled - see todo below.
|
| +//
|
| +// TODO(sqs): This happens on, e.g., GnuTLS/mod_gnutls. If the Client Hello has
|
| +// no "srp" extension but has SRP cipher suites, GnuTLS will choose a non-SRP
|
| +// ciphersuite. Other implementations (OpenSSL, TLS Lite) will send
|
| +// "unknown_psk_identity".
|
| +TEST_F(HTTPSRequestTest, DISABLED_SSLCertThenWantUpgradeToSRP) {
|
| + net::TestServer::HTTPSOptions https_options;
|
| + https_options.use_tls_srp = true;
|
| + https_options.only_tls_srp = false;
|
| + net::TestServer test_server(https_options, FilePath());
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + GURL https_url = test_server.GetURL("tlslogininfo");
|
| +
|
| + {
|
| + TestDelegate d_https;
|
| + d_https.set_allow_certificate_errors(true);
|
| + TestURLRequest r_https(https_url, &d_https);
|
| + // TODO(sqs): need to force this connection to use certificate auth. Right
|
| + // now, TLS Lite sends unknown_psk_identity if the client lists SRP cipher
|
| + // suites even if no srp username is sent in the client hello. One way to
|
| + // force this is to set all of the SRP cipher suites as disabled in the
|
| + // URLRequest's ssl_config, but it's not accessible (ssl_config is actually
|
| + // much deeper than URLRequest).
|
| +
|
| + r_https.Start();
|
| + EXPECT_TRUE(r_https.is_pending());
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(1, d_https.response_started_count());
|
| + EXPECT_NE(0, d_https.bytes_received());
|
| + CheckSSLInfo(r_https.ssl_info());
|
| +
|
| + TLSSRPClientLoginTestDelegate d;
|
| + TestURLRequest r(https_url, &d);
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| +
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(0, d.bytes_received());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + EXPECT_EQ(1, d.on_tls_login_required_count());
|
| + CheckTLSAuthChallengeInfo(d.last_login_request_info(), https_url);
|
| +
|
| + r.SetTLSLogin(kUser, kSecret);
|
| + r.ContinueWithTLSLogin();
|
| +
|
| + MessageLoop::current()->Run();
|
| + EXPECT_NE(0, d.bytes_received());
|
| + EXPECT_TRUE(d.data_received().find(UTF16ToUTF8(kUser)) !=
|
| + std::string::npos);
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + }
|
| +}
|
| +
|
| +TEST_F(HTTPSRequestTest, TLSLoginCredentialsRemainCached) {
|
| + net::TestServer::HTTPSOptions https_options;
|
| + https_options.use_tls_srp = true;
|
| + net::TestServer test_server(https_options, FilePath());
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + GURL https_url = test_server.GetURL("");
|
| +
|
| + GURL::Replacements replacements2;
|
| + replacements2.SetPathStr("tlslogininfo");
|
| + GURL https_url2 = https_url.ReplaceComponents(replacements2);
|
| +
|
| + {
|
| + TLSSRPClientLoginTestDelegate d;
|
| + TestURLRequest r(https_url, &d);
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| +
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(0, d.bytes_received());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + EXPECT_EQ(1, d.on_tls_login_required_count());
|
| + CheckTLSAuthChallengeInfo(d.last_login_request_info(), https_url);
|
| +
|
| + r.SetTLSLogin(kUser, kSecret);
|
| + r.ContinueWithTLSLogin();
|
| +
|
| + MessageLoop::current()->Run();
|
| + EXPECT_NE(0, d.bytes_received());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| +
|
| + // Don't specify credentials for this request.
|
| + TLSSRPClientLoginTestDelegate d2;
|
| + TestURLRequest r2(https_url2, &d2);
|
| + r2.Start();
|
| + EXPECT_TRUE(r2.is_pending());
|
| + MessageLoop::current()->Run();
|
| + EXPECT_NE(0, d2.bytes_received());
|
| + EXPECT_FALSE(d2.received_data_before_response());
|
| + LOG(INFO) << "GOT '" << d2.data_received() << "'";
|
| + EXPECT_TRUE(d2.data_received().find(UTF16ToUTF8(kUser)) !=
|
| + std::string::npos);
|
| + }
|
| +}
|
| +
|
| +TEST_F(HTTPSRequestTest, TLSSRPLoginTest) {
|
| + net::TestServer::HTTPSOptions https_options;
|
| + https_options.use_tls_srp = true;
|
| + https_options.only_tls_srp = true;
|
| + net::TestServer test_server(https_options, FilePath());
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + GURL https_url = test_server.GetURL("tlslogininfo");
|
| +
|
| + {
|
| + TLSSRPClientLoginTestDelegate d;
|
| + TestURLRequest r(https_url, &d);
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| +
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(0, d.bytes_received());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + EXPECT_EQ(1, d.on_tls_login_required_count());
|
| + CheckTLSAuthChallengeInfo(d.last_login_request_info(), https_url);
|
| +
|
| + r.SetTLSLogin(kUser, kSecret);
|
| + r.ContinueWithTLSLogin();
|
| +
|
| + MessageLoop::current()->Run();
|
| + EXPECT_NE(0, d.bytes_received());
|
| + EXPECT_TRUE(d.data_received().find(UTF16ToUTF8(kUser)) !=
|
| + std::string::npos);
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + }
|
| +}
|
| +
|
| +TEST_F(HTTPSRequestTest, TLSSRPSRPLoginWithCertTest) {
|
| + net::TestServer::HTTPSOptions https_options(
|
| + net::TestServer::HTTPSOptions::CERT_OK);
|
| + https_options.use_tls_srp = true;
|
| + net::TestServer test_server(https_options,
|
| + FilePath(FILE_PATH_LITERAL("net/data/ssl")));
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + GURL https_url = test_server.GetURL("tlslogininfo");
|
| +
|
| + TestDelegate d;
|
| + {
|
| + TestURLRequest r(https_url, &d);
|
| + r.SetTLSLogin(kUser, kSecret);
|
| +
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| +
|
| + MessageLoop::current()->Run();
|
| +
|
| + EXPECT_EQ(1, d.response_started_count());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + EXPECT_NE(0, d.bytes_received());
|
| + CheckSSLInfo(r.ssl_info());
|
| + EXPECT_FALSE(net::IsCertStatusError(r.ssl_info().cert_status));
|
| + EXPECT_TRUE(r.ssl_info().cert.get());
|
| + EXPECT_EQ(kUser, r.ssl_info().tls_username);
|
| + EXPECT_TRUE(d.data_received().find(UTF16ToUTF8(kUser)) !=
|
| + std::string::npos);
|
| + }
|
| +}
|
| +
|
| +// Check that we still validate certs on SRP cipher suites that use certs.
|
| +TEST_F(HTTPSRequestTest, TLSSRPSRPBadCertFailureTest) {
|
| + bool cert_err_allowed = false;
|
| + for (int i = 0; i < 2; i++, cert_err_allowed = !cert_err_allowed) {
|
| + net::TestServer::HTTPSOptions https_options(
|
| + net::TestServer::HTTPSOptions::CERT_EXPIRED);
|
| + https_options.use_tls_srp = true;
|
| + net::TestServer test_server(https_options,
|
| + FilePath(FILE_PATH_LITERAL("net/data/ssl")));
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + GURL https_url = test_server.GetURL("tlslogininfo");
|
| +
|
| + TestDelegate d;
|
| + {
|
| + d.set_allow_certificate_errors(cert_err_allowed);
|
| + TestURLRequest r(https_url, &d);
|
| + r.SetTLSLogin(kUser, kSecret);
|
| +
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| + MessageLoop::current()->Run();
|
| +
|
| + EXPECT_EQ(1, d.response_started_count());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + EXPECT_TRUE(d.have_certificate_errors());
|
| +
|
| + if (cert_err_allowed) {
|
| + EXPECT_NE(0, d.bytes_received());
|
| + CheckSSLInfo(r.ssl_info());
|
| + EXPECT_TRUE(d.data_received().find(UTF16ToUTF8(kUser)) !=
|
| + std::string::npos);
|
| + } else {
|
| + EXPECT_EQ(0, d.bytes_received());
|
| + }
|
| + }
|
| + }
|
| +}
|
| +
|
| +TEST_F(HTTPSRequestTest, TLSSRPBadSecretFailureTest) {
|
| + net::TestServer::HTTPSOptions https_options;
|
| + https_options.use_tls_srp = true;
|
| + https_options.only_tls_srp = true;
|
| + net::TestServer test_server(https_options, FilePath());
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + GURL https_url = test_server.GetURL("tlslogininfo");
|
| +
|
| + {
|
| + TLSSRPClientLoginTestDelegate d;
|
| +
|
| + TestURLRequest r(https_url, &d);
|
| + // Try wrong password.
|
| + r.SetTLSLogin(kUser, kWrongSecret);
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(0, d.bytes_received());
|
| + EXPECT_EQ(1, d.on_tls_login_required_count());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| +
|
| + // Now continue with the correct password.
|
| + r.SetTLSLogin(kUser, kSecret);
|
| + r.ContinueWithTLSLogin();
|
| +
|
| + MessageLoop::current()->Run();
|
| + EXPECT_NE(0, d.bytes_received());
|
| + EXPECT_TRUE(d.data_received().find(UTF16ToUTF8(kUser)) !=
|
| + std::string::npos);
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + }
|
| +}
|
| +
|
| +TEST_F(HTTPSRequestTest, TLSSRPBadUsernameTest) {
|
| + net::TestServer::HTTPSOptions https_options;
|
| + https_options.use_tls_srp = true;
|
| + https_options.only_tls_srp = true;
|
| + net::TestServer test_server(https_options, FilePath());
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + GURL https_url = test_server.GetURL("tlslogininfo");
|
| +
|
| + {
|
| + TLSSRPClientLoginTestDelegate d;
|
| +
|
| + TestURLRequest r(https_url, &d);
|
| + // Try wrong password.
|
| + r.SetTLSLogin(kWrongUser, kSecret);
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(0, d.bytes_received());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + EXPECT_EQ(1, d.on_tls_login_required_count());
|
| + CheckTLSAuthChallengeInfo(d.last_login_request_info(), https_url);
|
| +
|
| + // Now continue with the correct password.
|
| + r.SetTLSLogin(kUser, kSecret);
|
| + r.ContinueWithTLSLogin();
|
| +
|
| + MessageLoop::current()->Run();
|
| + EXPECT_NE(0, d.bytes_received());
|
| + EXPECT_TRUE(d.data_received().find(UTF16ToUTF8(kUser)) !=
|
| + std::string::npos);
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + }
|
| +}
|
| +
|
| +TEST_F(HTTPSRequestTest, TLSSRPCancelLoginTest) {
|
| + net::TestServer::HTTPSOptions https_options;
|
| + https_options.use_tls_srp = true;
|
| + https_options.only_tls_srp = true;
|
| + net::TestServer test_server(https_options, FilePath());
|
| + ASSERT_TRUE(test_server.Start());
|
| +
|
| + GURL https_url = test_server.GetURL("");
|
| +
|
| + {
|
| + TLSSRPClientLoginTestDelegate d;
|
| +
|
| + TestURLRequest r(https_url, &d);
|
| + r.Start();
|
| + EXPECT_TRUE(r.is_pending());
|
| + MessageLoop::current()->Run();
|
| +
|
| + EXPECT_EQ(0, d.bytes_received());
|
| + EXPECT_EQ(1, d.on_tls_login_required_count());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| +
|
| + r.CancelTLSLogin();
|
| +
|
| + MessageLoop::current()->Run();
|
| + EXPECT_EQ(0, d.bytes_received());
|
| + EXPECT_FALSE(d.received_data_before_response());
|
| + }
|
| +}
|
| +
|
| TEST_F(URLRequestTestHTTP, CancelTest) {
|
| TestDelegate d;
|
| {
|
|
|