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