summaryrefslogtreecommitdiffstats
path: root/net/http
diff options
context:
space:
mode:
authorwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-12 21:45:11 +0000
committerwtc@chromium.org <wtc@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-12 21:45:11 +0000
commit0b45559b42825a157d3f468e1a5ee102cc67d9a8 (patch)
tree00d25404d9803f5e905eab058cd175dca9fb68e0 /net/http
parent37a24e0d9e75a916c13900cf34d7c6b54acc2001 (diff)
downloadchromium_src-0b45559b42825a157d3f468e1a5ee102cc67d9a8.zip
chromium_src-0b45559b42825a157d3f468e1a5ee102cc67d9a8.tar.gz
chromium_src-0b45559b42825a157d3f468e1a5ee102cc67d9a8.tar.bz2
Specify new methods for supporting SSL client authentication.
See the changes to url_request.h and ssl_cert_request_info.h. They are similar to the methods for handling SSL certificate errors and HTTP authentication. The handling of servers that request but don't require SSL client authentication is reimplemented using the new methods. R=rvargas,eroman BUG=http://crbug.com/318 TEST=none Review URL: http://codereview.chromium.org/118039 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@18322 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/http')
-rw-r--r--net/http/http_cache.cc45
-rw-r--r--net/http/http_network_transaction.cc55
-rw-r--r--net/http/http_network_transaction.h7
-rw-r--r--net/http/http_response_info.cc2
-rw-r--r--net/http/http_response_info.h9
-rw-r--r--net/http/http_transaction.h7
-rw-r--r--net/http/http_transaction_unittest.h7
7 files changed, 118 insertions, 14 deletions
diff --git a/net/http/http_cache.cc b/net/http/http_cache.cc
index f87b306..4453480 100644
--- a/net/http/http_cache.cc
+++ b/net/http/http_cache.cc
@@ -20,6 +20,7 @@
#include "net/base/io_buffer.h"
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
+#include "net/base/ssl_cert_request_info.h"
#include "net/disk_cache/disk_cache.h"
#include "net/http/http_network_layer.h"
#include "net/http/http_network_session.h"
@@ -166,6 +167,8 @@ class HttpCache::Transaction
// HttpTransaction methods:
virtual int Start(const HttpRequestInfo*, CompletionCallback*);
virtual int RestartIgnoringLastError(CompletionCallback*);
+ virtual int RestartWithCertificate(X509Certificate* client_cert,
+ CompletionCallback* callback);
virtual int RestartWithAuth(const std::wstring& username,
const std::wstring& password,
CompletionCallback* callback);
@@ -249,6 +252,10 @@ class HttpCache::Transaction
// error code.
int RestartNetworkRequest();
+ // Called to restart a network transaction with a client certificate.
+ // Returns network error code.
+ int RestartNetworkRequestWithCertificate(X509Certificate* client_cert);
+
// Called to restart a network transaction with authentication credentials.
// Returns network error code.
int RestartNetworkRequestWithAuth(const std::wstring& username,
@@ -414,6 +421,25 @@ int HttpCache::Transaction::RestartIgnoringLastError(
return rv;
}
+int HttpCache::Transaction::RestartWithCertificate(
+ X509Certificate* client_cert,
+ CompletionCallback* callback) {
+ DCHECK(callback);
+
+ // ensure that we only have one asynchronous call at a time.
+ DCHECK(!callback_);
+
+ if (revoked())
+ return ERR_UNEXPECTED;
+
+ int rv = RestartNetworkRequestWithCertificate(client_cert);
+
+ if (rv == ERR_IO_PENDING)
+ callback_ = callback;
+
+ return rv;
+}
+
int HttpCache::Transaction::RestartWithAuth(
const std::wstring& username,
const std::wstring& password,
@@ -499,7 +525,8 @@ const HttpResponseInfo* HttpCache::Transaction::GetResponseInfo() const {
// Null headers means we encountered an error or haven't a response yet
if (auth_response_.headers)
return &auth_response_;
- return (response_.headers || response_.ssl_info.cert) ? &response_ : NULL;
+ return (response_.headers || response_.ssl_info.cert ||
+ response_.cert_request_info) ? &response_ : NULL;
}
LoadState HttpCache::Transaction::GetLoadState() const {
@@ -805,6 +832,18 @@ int HttpCache::Transaction::RestartNetworkRequest() {
return rv;
}
+int HttpCache::Transaction::RestartNetworkRequestWithCertificate(
+ X509Certificate* client_cert) {
+ DCHECK(mode_ & WRITE || mode_ == NONE);
+ DCHECK(network_trans_.get());
+
+ int rv = network_trans_->RestartWithCertificate(client_cert,
+ &network_info_callback_);
+ if (rv != ERR_IO_PENDING)
+ OnNetworkInfoAvailable(rv);
+ return rv;
+}
+
int HttpCache::Transaction::RestartNetworkRequestWithAuth(
const std::wstring& username,
const std::wstring& password) {
@@ -1092,6 +1131,10 @@ void HttpCache::Transaction::OnNetworkInfoAvailable(int result) {
// so GetResponseInfo() should never returns NULL here.
DCHECK(response);
response_.ssl_info = response->ssl_info;
+ } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+ const HttpResponseInfo* response = network_trans_->GetResponseInfo();
+ DCHECK(response);
+ response_.cert_request_info = response->cert_request_info;
}
HandleResult(result);
}
diff --git a/net/http/http_network_transaction.cc b/net/http/http_network_transaction.cc
index dcdd5ec..4fbd5cb 100644
--- a/net/http/http_network_transaction.cc
+++ b/net/http/http_network_transaction.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -17,6 +17,7 @@
#include "net/base/load_flags.h"
#include "net/base/net_errors.h"
#include "net/base/net_util.h"
+#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_client_socket.h"
#include "net/base/upload_data_stream.h"
#include "net/http/http_auth.h"
@@ -189,6 +190,21 @@ int HttpNetworkTransaction::RestartIgnoringLastError(
return rv;
}
+int HttpNetworkTransaction::RestartWithCertificate(
+ X509Certificate* client_cert,
+ CompletionCallback* callback) {
+ ssl_config_.client_cert = client_cert;
+ ssl_config_.send_client_cert = true;
+ next_state_ = STATE_INIT_CONNECTION;
+ // Reset the other member variables.
+ // Note: this is necessary only with SSL renegotiation.
+ ResetStateForRestart();
+ int rv = DoLoop(OK);
+ if (rv == ERR_IO_PENDING)
+ user_callback_ = callback;
+ return rv;
+}
+
int HttpNetworkTransaction::RestartWithAuth(
const std::wstring& username,
const std::wstring& password,
@@ -346,7 +362,8 @@ int HttpNetworkTransaction::Read(IOBuffer* buf, int buf_len,
}
const HttpResponseInfo* HttpNetworkTransaction::GetResponseInfo() const {
- return (response_.headers || response_.ssl_info.cert) ? &response_ : NULL;
+ return (response_.headers || response_.ssl_info.cert ||
+ response_.cert_request_info) ? &response_ : NULL;
}
LoadState HttpNetworkTransaction::GetLoadState() const {
@@ -603,6 +620,8 @@ int HttpNetworkTransaction::DoSSLConnectComplete(int result) {
if (result == OK) {
next_state_ = STATE_WRITE_HEADERS;
+ } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+ HandleCertificateRequest();
} else {
result = HandleSSLHandshakeError(result);
}
@@ -746,13 +765,19 @@ int HttpNetworkTransaction::HandleConnectionClosedBeforeEndOfHeaders() {
}
int HttpNetworkTransaction::DoReadHeadersComplete(int result) {
- if (using_ssl_ && IsCertificateError(result)) {
- // We don't handle a certificate error during SSL renegotiation, so we
- // have to return an error that's not in the certificate error range
- // (-2xx).
- LOG(ERROR) << "Got a server certificate with error " << result
- << " during SSL renegotiation";
- result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
+ // We can get a certificate error or ERR_SSL_CLIENT_AUTH_CERT_NEEDED here
+ // due to SSL renegotiation.
+ if (using_ssl_) {
+ if (IsCertificateError(result)) {
+ // We don't handle a certificate error during SSL renegotiation, so we
+ // have to return an error that's not in the certificate error range
+ // (-2xx).
+ LOG(ERROR) << "Got a server certificate with error " << result
+ << " during SSL renegotiation";
+ result = ERR_CERT_ERROR_IN_SSL_RENEGOTIATION;
+ } else if (result == ERR_SSL_CLIENT_AUTH_CERT_NEEDED) {
+ HandleCertificateRequest();
+ }
}
if (result < 0)
@@ -1217,6 +1242,18 @@ int HttpNetworkTransaction::HandleCertificateError(int error) {
return error;
}
+void HttpNetworkTransaction::HandleCertificateRequest() {
+ response_.cert_request_info = new SSLCertRequestInfo;
+ SSLClientSocket* ssl_socket =
+ reinterpret_cast<SSLClientSocket*>(connection_.socket());
+ ssl_socket->GetSSLCertRequestInfo(response_.cert_request_info);
+
+ // Close the connection while the user is selecting a certificate to send
+ // to the server.
+ connection_.socket()->Disconnect();
+ connection_.Reset();
+}
+
int HttpNetworkTransaction::HandleSSLHandshakeError(int error) {
switch (error) {
case ERR_SSL_PROTOCOL_ERROR:
diff --git a/net/http/http_network_transaction.h b/net/http/http_network_transaction.h
index fb21384..13d88b9 100644
--- a/net/http/http_network_transaction.h
+++ b/net/http/http_network_transaction.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -44,6 +44,8 @@ class HttpNetworkTransaction : public HttpTransaction {
virtual int Start(const HttpRequestInfo* request_info,
CompletionCallback* callback);
virtual int RestartIgnoringLastError(CompletionCallback* callback);
+ virtual int RestartWithCertificate(X509Certificate* client_cert,
+ CompletionCallback* callback);
virtual int RestartWithAuth(const std::wstring& username,
const std::wstring& password,
CompletionCallback* callback);
@@ -160,6 +162,9 @@ class HttpNetworkTransaction : public HttpTransaction {
// returns the same error code.
int HandleCertificateError(int error);
+ // Called to handle a client certificate request.
+ void HandleCertificateRequest();
+
// Called to possibly recover from an SSL handshake error. Sets next_state_
// and returns OK if recovering from the error. Otherwise, the same error
// code is returned.
diff --git a/net/http/http_response_info.cc b/net/http/http_response_info.cc
index bc2fbe3..0db95b5 100644
--- a/net/http/http_response_info.cc
+++ b/net/http/http_response_info.cc
@@ -3,6 +3,8 @@
// found in the LICENSE file.
#include "net/http/http_response_info.h"
+
+#include "net/base/ssl_cert_request_info.h"
#include "net/http/http_response_headers.h"
namespace net {
diff --git a/net/http/http_response_info.h b/net/http/http_response_info.h
index 88f89e7..7cbe13c 100644
--- a/net/http/http_response_info.h
+++ b/net/http/http_response_info.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -13,6 +13,7 @@
namespace net {
class HttpResponseHeaders;
+class SSLCertRequestInfo;
class HttpResponseInfo {
public:
@@ -41,6 +42,12 @@ class HttpResponseInfo {
// will contain additional information about the authentication challenge.
scoped_refptr<AuthChallengeInfo> auth_challenge;
+ // The SSL client certificate request info.
+ // TODO(wtc): does this really belong in HttpResponseInfo? I put it here
+ // because it is similar to |auth_challenge|, but unlike HTTP authentication
+ // challenge, client certificate request is not part of an HTTP response.
+ scoped_refptr<SSLCertRequestInfo> cert_request_info;
+
// The SSL connection info (if HTTPS).
SSLInfo ssl_info;
diff --git a/net/http/http_transaction.h b/net/http/http_transaction.h
index cc7dd92..14612e9 100644
--- a/net/http/http_transaction.h
+++ b/net/http/http_transaction.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -13,6 +13,7 @@ namespace net {
class HttpRequestInfo;
class HttpResponseInfo;
class IOBuffer;
+class X509Certificate;
// Represents a single HTTP transaction (i.e., a single request/response pair).
// HTTP redirects are not followed and authentication challenges are not
@@ -50,6 +51,10 @@ class HttpTransaction {
//
virtual int RestartIgnoringLastError(CompletionCallback* callback) = 0;
+ // Restarts the HTTP transaction with a client certificate.
+ virtual int RestartWithCertificate(X509Certificate* client_cert,
+ CompletionCallback* callback) = 0;
+
// Restarts the HTTP transaction with authentication credentials.
virtual int RestartWithAuth(const std::wstring& username,
const std::wstring& password,
diff --git a/net/http/http_transaction_unittest.h b/net/http/http_transaction_unittest.h
index d0a51b0..f72c305 100644
--- a/net/http/http_transaction_unittest.h
+++ b/net/http/http_transaction_unittest.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
@@ -234,6 +234,11 @@ class MockNetworkTransaction : public net::HttpTransaction {
return net::ERR_FAILED;
}
+ virtual int RestartWithCertificate(net::X509Certificate* client_cert,
+ net::CompletionCallback* callback) {
+ return net::ERR_FAILED;
+ }
+
virtual int RestartWithAuth(const std::wstring& username,
const std::wstring& password,
net::CompletionCallback* callback) {