Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(352)

Unified Diff: net/http/http_network_transaction.cc

Issue 6804032: Add TLS-SRP (RFC 5054) support Base URL: http://git.chromium.org/git/chromium.git@trunk
Patch Set: remove "httpsv" scheme, minor NSS/OpenSSL changes Created 9 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/http/http_network_transaction.h ('k') | net/http/http_network_transaction_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/http/http_network_transaction.cc
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index e0967c60da61f7b86887f153e4b46433bc05d65f..847a59146d81e4660de7d699c0038938620197b2 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -17,6 +17,7 @@
#include "base/string_number_conversions.h"
#include "base/string_util.h"
#include "base/stringprintf.h"
+#include "base/utf_string_conversions.h"
#include "build/build_config.h"
#include "googleurl/src/gurl.h"
#include "net/base/auth.h"
@@ -197,6 +198,49 @@ int HttpNetworkTransaction::RestartWithCertificate(
return rv;
}
+void HttpNetworkTransaction::SetTLSLoginAuthData(AuthData* auth_data) {
+ DCHECK(!stream_request_.get()) << "Can't set TLS login on existing stream";
+ DCHECK(!stream_.get());
+ DCHECK_EQ(STATE_NONE, next_state_);
+
+ DCHECK(!auth_data->username.empty());
+ DCHECK(!auth_data->password.empty());
+
+ tls_auth_data_ = auth_data;
+ ssl_config_.tls_username = UTF16ToUTF8(auth_data->username);
+ ssl_config_.tls_password = UTF16ToUTF8(auth_data->password);
+ ssl_config_.use_tls_auth = true;
+ ssl_config_.ssl3_enabled = false;
+ ssl_config_.tls1_enabled = true;
+}
+
+int HttpNetworkTransaction::RestartWithTLSLogin(CompletionCallback* callback) {
+ DCHECK(!stream_request_.get());
+ DCHECK(!stream_.get());
+ DCHECK_EQ(STATE_NONE, next_state_);
+
+ DCHECK(!ssl_config_.tls_username.empty());
+ DCHECK(!ssl_config_.tls_password.empty());
+ DCHECK(ssl_config_.use_tls_auth);
+ DCHECK(ssl_config_.tls1_enabled);
+ DCHECK(!ssl_config_.ssl3_enabled);
+
+ DCHECK(response_.login_request_info.get());
+ DCHECK(tls_auth_data_.get());
+ session_->tls_client_login_cache()->Add(
+ WideToUTF8(response_.login_request_info->host_and_port),
+ tls_auth_data_);
+
+ // Reset the other member variables.
+ // Note: this is necessary only with SSL renegotiation.
+ ResetStateForRestart();
+ next_state_ = STATE_CREATE_STREAM;
+ int rv = DoLoop(OK);
+ if (rv == ERR_IO_PENDING)
+ user_callback_ = callback;
+ return rv;
+}
+
int HttpNetworkTransaction::RestartWithAuth(
const string16& username,
const string16& password,
@@ -330,7 +374,9 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
return ((headers_valid_ && response_.headers) || response_.ssl_info.cert ||
- response_.cert_request_info) ? &response_ : NULL;
+ !response_.ssl_info.tls_username.empty() ||
+ response_.cert_request_info || response_.login_request_info) ?
+ &response_ : NULL;
}
LoadState HttpNetworkTransaction::GetLoadState() const {
@@ -425,6 +471,14 @@ void HttpNetworkTransaction::OnNeedsClientAuth(
OnIOComplete(ERR_SSL_CLIENT_AUTH_CERT_NEEDED);
}
+void HttpNetworkTransaction::OnNeedsTLSLogin(
+ AuthChallengeInfo* login_info) {
+ DCHECK_EQ(STATE_CREATE_STREAM_COMPLETE, next_state_);
+
+ response_.login_request_info = login_info;
+ OnIOComplete(ERR_TLS_CLIENT_LOGIN_NEEDED);
+}
+
void HttpNetworkTransaction::OnHttpsProxyTunnelResponse(
const HttpResponseInfo& response_info,
HttpStream* stream) {
@@ -542,6 +596,33 @@ int HttpNetworkTransaction::DoLoop(int result) {
}
int HttpNetworkTransaction::DoCreateStream() {
+ DCHECK(request_);
+
+ // Set TLS login, if available.
+ if (ssl_config_.use_tls_auth) {
+ // TODO(sqs): implement some way of forcing TLS auth (as right below)
+ // if (...) ssl_config_.require_tls_auth = true;
+ if (ssl_config_.tls_username.empty()) {
+ scoped_refptr<AuthData> tls_auth_data;
+ bool found_login = session_->tls_client_login_cache()->Lookup(
+ net::GetHostAndPort(request_->url),
+ &tls_auth_data);
+ if (found_login) {
+ LOG(INFO) << "Got TLS login from cache";
+ SetTLSLoginAuthData(tls_auth_data);
+ DCHECK(!ssl_config_.tls_username.empty());
+ DCHECK(!ssl_config_.tls_password.empty());
+ } else if (ssl_config_.require_tls_auth) {
+ response_.login_request_info = new AuthChallengeInfo;
+ response_.login_request_info->host_and_port =
+ UTF8ToWide(net::GetHostAndPort(request_->url));
+ response_.login_request_info->scheme = ASCIIToWide(net::kTLSSRPScheme);
+ response_.login_request_info->over_protocol = AUTH_OVER_TLS;
+ return ERR_TLS_CLIENT_LOGIN_NEEDED;
+ }
+ }
+ }
+
next_state_ = STATE_CREATE_STREAM_COMPLETE;
stream_request_.reset(
@@ -1037,16 +1118,56 @@ int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
GetHostAndPort(request_->url));
}
+ // Check for TLS-SRP-related errors.
+ if (ssl_config_.use_tls_auth) {
+ if (ssl_config_.tls_username.empty() && ssl_config_.tls_password.empty()) {
+ if (error == ERR_SSL_UNKNOWN_PSK_IDENTITY_ALERT) {
+ // RFC 5054 unknown_psk_identity idiom: The Client Hello contained no
+ // SRP username, but the server wishes to connect using an SRP cipher
+ // suite.
+ error = ERR_TLS_CLIENT_LOGIN_NEEDED;
+ }
+ } else if (!ssl_config_.tls_username.empty() &&
+ ssl_config_.tls_password.empty()) {
+ LOG(WARNING) << "SSL handshake error: empty TLS password";
+ } else if (!ssl_config_.tls_username.empty() &&
+ !ssl_config_.tls_password.empty()) {
+ if (error == ERR_SSL_BAD_RECORD_MAC_ALERT ||
+ error == ERR_SSL_UNKNOWN_PSK_IDENTITY_ALERT) {
+ // The TLS-SRP login probably failed.
+ // TODO(sqs): also verify that we did attempt to use an SRP cipher suite
+ error = ERR_TLS_CLIENT_LOGIN_FAILED;
+ }
+ }
+
+ if (error == ERR_TLS_CLIENT_LOGIN_FAILED)
+ session_->tls_client_login_cache()->Remove(GetHostAndPort(request_->url));
+
+ // Handle TLS-SRP errors now.
+ if (error == ERR_TLS_CLIENT_LOGIN_FAILED ||
+ error == ERR_TLS_CLIENT_LOGIN_NEEDED) {
+ DCHECK(!response_.login_request_info.get());
+ response_.login_request_info = new AuthChallengeInfo;
+ response_.login_request_info->host_and_port =
+ UTF8ToWide(GetHostAndPort(request_->url));
+ response_.login_request_info->scheme = ASCIIToWide(net::kTLSSRPScheme);
+ response_.login_request_info->over_protocol = AUTH_OVER_TLS;
+ return error;
+ }
+ }
+
switch (error) {
case ERR_SSL_PROTOCOL_ERROR:
case ERR_SSL_VERSION_OR_CIPHER_MISMATCH:
case ERR_SSL_DECOMPRESSION_FAILURE_ALERT:
case ERR_SSL_BAD_RECORD_MAC_ALERT:
if (ssl_config_.tls1_enabled &&
- !SSLConfigService::IsKnownStrictTLSServer(request_->url.host())) {
+ !SSLConfigService::IsKnownStrictTLSServer(request_->url.host()) &&
+ !ssl_config_.require_tls_auth) {
// This could be a TLS-intolerant server, an SSL 3.0 server that
// chose a TLS-only cipher suite or a server with buggy DEFLATE
// support. Turn off TLS 1.0, DEFLATE support and retry.
+ LOG(WARNING) << "Set server TLS intolerant: " << request_->url;
session_->http_stream_factory()->AddTLSIntolerantServer(request_->url);
ResetConnectionAndRequestForResend();
error = OK;
« no previous file with comments | « net/http/http_network_transaction.h ('k') | net/http/http_network_transaction_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698