Skip to content

Commit

Permalink
Specify new methods for supporting SSL client authentication.
Browse files Browse the repository at this point in the history
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
  • Loading branch information
wtc@chromium.org committed Jun 12, 2009
1 parent 37a24e0 commit 0b45559
Show file tree
Hide file tree
Showing 25 changed files with 282 additions and 60 deletions.
3 changes: 3 additions & 0 deletions net/base/net_error_list.h
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ NET_ERROR(PROXY_AUTH_REQUESTED, -115)
// certificate error.
NET_ERROR(CERT_ERROR_IN_SSL_RENEGOTIATION, -116)

// The SSL handshake failed because of a bad or missing client certificate.
NET_ERROR(BAD_SSL_CLIENT_AUTH_CERT, -117)

// Certificate error codes
//
// The values of certificate error codes must be consecutive.
Expand Down
7 changes: 7 additions & 0 deletions net/base/socket_test_util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ class MockClientSocket : public net::SSLClientSocket {

// SSLClientSocket methods:
virtual void GetSSLInfo(net::SSLInfo* ssl_info);
virtual void GetSSLCertRequestInfo(
net::SSLCertRequestInfo* cert_request_info);
virtual void Disconnect();
virtual bool IsConnected() const;
virtual bool IsConnectedAndIdle() const;
Expand Down Expand Up @@ -105,6 +107,11 @@ void MockClientSocket::GetSSLInfo(net::SSLInfo* ssl_info) {
NOTREACHED();
}

void MockClientSocket::GetSSLCertRequestInfo(
net::SSLCertRequestInfo* cert_request_info) {
NOTREACHED();
}

void MockClientSocket::Disconnect() {
connected_ = false;
callback_ = NULL;
Expand Down
37 changes: 37 additions & 0 deletions net/base/ssl_cert_request_info.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
// Copyright (c) 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.

#ifndef NET_BASE_SSL_CERT_REQUEST_INFO_H_
#define NET_BASE_SSL_CERT_REQUEST_INFO_H_

#include <string>
#include <vector>

#include "base/ref_counted.h"

namespace net {

class X509Certificate;

// The SSLCertRequestInfo class contains the info that allows a user to
// select a certificate to send to the SSL server for client authentication.
class SSLCertRequestInfo
: public base::RefCountedThreadSafe<SSLCertRequestInfo> {
public:
// The host and port of the SSL server that requested client authentication.
std::string host_and_port;

// A list of client certificates that match the server's criteria in the
// SSL CertificateRequest message. In TLS 1.0, the CertificateRequest
// message is defined as:
// struct {
// ClientCertificateType certificate_types<1..2^8-1>;
// DistinguishedName certificate_authorities<3..2^16-1>;
// } CertificateRequest;
std::vector<scoped_refptr<X509Certificate> > client_certs;
};

} // namespace net

#endif // NET_BASE_SSL_CERT_REQUEST_INFO_H_
8 changes: 7 additions & 1 deletion net/base/ssl_client_socket.h
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -9,6 +9,7 @@

namespace net {

class SSLCertRequestInfo;
class SSLInfo;

// A client socket that uses SSL as the transport layer.
Expand All @@ -21,6 +22,11 @@ class SSLClientSocket : public ClientSocket {
public:
// Gets the SSL connection information of the socket.
virtual void GetSSLInfo(SSLInfo* ssl_info) = 0;

// Gets the SSL CertificateRequest info of the socket after Connect failed
// with ERR_SSL_CLIENT_AUTH_CERT_NEEDED.
virtual void GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) = 0;
};

} // namespace net
Expand Down
8 changes: 6 additions & 2 deletions net/base/ssl_client_socket_mac.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// Copyright (c) 2008 The Chromium Authors. All rights reserved.
// Copyright (c) 2008-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.

Expand Down Expand Up @@ -418,6 +418,11 @@ void SSLClientSocketMac::GetSSLInfo(SSLInfo* ssl_info) {
ssl_info->security_bits = KeySizeOfCipherSuite(suite);
}

void SSLClientSocketMac::GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) {
// TODO(wtc): implement this.
}

void SSLClientSocketMac::DoCallback(int rv) {
DCHECK(rv != ERR_IO_PENDING);
DCHECK(user_callback_);
Expand Down Expand Up @@ -743,7 +748,6 @@ OSStatus SSLClientSocketMac::SSLWriteCallback(SSLConnectionRef connection,
if (rv > 0) {
us->send_buffer_.erase(us->send_buffer_.begin(),
us->send_buffer_.begin() + rv);

}
} while (rv > 0 && !us->send_buffer_.empty());

Expand Down
3 changes: 2 additions & 1 deletion net/base/ssl_client_socket_mac.h
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -31,6 +31,7 @@ class SSLClientSocketMac : public SSLClientSocket {

// SSLClientSocket methods:
virtual void GetSSLInfo(SSLInfo* ssl_info);
virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);

// ClientSocket methods:
virtual int Connect(CompletionCallback* callback);
Expand Down
7 changes: 6 additions & 1 deletion net/base/ssl_client_socket_nss.cc
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -490,6 +490,11 @@ void SSLClientSocketNSS::GetSSLInfo(SSLInfo* ssl_info) {
LeaveFunction("");
}

void SSLClientSocketNSS::GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) {
// TODO(wtc): implement this.
}

void SSLClientSocketNSS::DoCallback(int rv) {
EnterFunction(rv);
DCHECK(rv != ERR_IO_PENDING);
Expand Down
3 changes: 2 additions & 1 deletion net/base/ssl_client_socket_nss.h
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -40,6 +40,7 @@ class SSLClientSocketNSS : public SSLClientSocket {

// SSLClientSocket methods:
virtual void GetSSLInfo(SSLInfo* ssl_info);
virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);

// ClientSocket methods:
virtual int Connect(CompletionCallback* callback);
Expand Down
46 changes: 18 additions & 28 deletions net/base/ssl_client_socket_win.cc
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -232,7 +232,6 @@ SSLClientSocketWin::SSLClientSocketWin(ClientSocket* transport_socket,
writing_first_token_(false),
completed_handshake_(false),
ignore_ok_result_(false),
no_client_cert_(false),
renegotiating_(false) {
memset(&stream_sizes_, 0, sizeof(stream_sizes_));
memset(in_buffers_, 0, sizeof(in_buffers_));
Expand Down Expand Up @@ -261,6 +260,11 @@ void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) {
}
}

void SSLClientSocketWin::GetSSLCertRequestInfo(
SSLCertRequestInfo* cert_request_info) {
// TODO(wtc): implement this.
}

int SSLClientSocketWin::Connect(CompletionCallback* callback) {
DCHECK(transport_.get());
DCHECK(next_state_ == STATE_NONE);
Expand Down Expand Up @@ -544,14 +548,7 @@ int SSLClientSocketWin::DoHandshakeReadComplete(int result) {
ISC_REQ_ALLOCATE_MEMORY |
ISC_REQ_STREAM;

// When InitializeSecurityContext returns SEC_I_INCOMPLETE_CREDENTIALS,
// John Banes (a Microsoft security developer) said we need to pass in the
// ISC_REQ_USE_SUPPLIED_CREDS flag if we skip finding a client certificate
// and just call InitializeSecurityContext again. (See
// (http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/2004-08/0187.html.)
// My testing on XP SP2 and Vista SP1 shows that it still works without
// passing in this flag, but I pass it in to be safe.
if (no_client_cert_)
if (ssl_config_.send_client_cert)
flags |= ISC_REQ_USE_SUPPLIED_CREDS;

SecBufferDesc in_buffer_desc, out_buffer_desc;
Expand Down Expand Up @@ -623,28 +620,21 @@ int SSLClientSocketWin::DidCallInitializeSecurityContext() {
int result = MapSecurityError(isc_status_);
// We told Schannel to not verify the server certificate
// (SCH_CRED_MANUAL_CRED_VALIDATION), so any certificate error returned by
// InitializeSecurityContext must be referring to the (missing) client
// certificate.
// InitializeSecurityContext must be referring to the bad or missing
// client certificate.
if (IsCertificateError(result)) {
// TODO(wtc): When we support SSL client authentication, we will need to
// add new error codes for client certificate errors reported by the
// server using SSL/TLS alert messages. See http://crbug.com/318. See
// also the MSDN page "Schannel Error Codes for TLS and SSL Alerts",
// which maps TLS alert messages to Windows error codes:
// TODO(wtc): Add new error codes for client certificate errors reported
// by the server using SSL/TLS alert messages. See the MSDN page
// "Schannel Error Codes for TLS and SSL Alerts", which maps TLS alert
// messages to Windows error codes:
// http://msdn.microsoft.com/en-us/library/dd721886%28VS.85%29.aspx
return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
return ERR_BAD_SSL_CLIENT_AUTH_CERT;
}
return result;
}

if (isc_status_ == SEC_I_INCOMPLETE_CREDENTIALS) {
// We don't support SSL client authentication yet. For now we just set
// no_client_cert_ to true and call InitializeSecurityContext again.
no_client_cert_ = true;
next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
ignore_ok_result_ = true; // OK doesn't mean EOF.
return OK;
}
if (isc_status_ == SEC_I_INCOMPLETE_CREDENTIALS)
return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;

DCHECK(isc_status_ == SEC_I_CONTINUE_NEEDED);
if (in_buffers_[1].BufferType == SECBUFFER_EXTRA) {
Expand Down Expand Up @@ -989,15 +979,15 @@ int SSLClientSocketWin::DidCompleteHandshake() {
SECURITY_STATUS status = QueryContextAttributes(
&ctxt_, SECPKG_ATTR_STREAM_SIZES, &stream_sizes_);
if (status != SEC_E_OK) {
DLOG(ERROR) << "QueryContextAttributes failed: " << status;
DLOG(ERROR) << "QueryContextAttributes (stream sizes) failed: " << status;
return MapSecurityError(status);
}
DCHECK(!server_cert_ || renegotiating_);
PCCERT_CONTEXT server_cert_handle = NULL;
status = QueryContextAttributes(
&ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_handle);
if (status != SEC_E_OK) {
DLOG(ERROR) << "QueryContextAttributes failed: " << status;
DLOG(ERROR) << "QueryContextAttributes (remote cert) failed: " << status;
return MapSecurityError(status);
}
if (renegotiating_ &&
Expand Down
6 changes: 2 additions & 4 deletions net/base/ssl_client_socket_win.h
Original file line number Diff line number Diff line change
@@ -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.

Expand Down Expand Up @@ -36,6 +36,7 @@ class SSLClientSocketWin : public SSLClientSocket {

// SSLClientSocket methods:
virtual void GetSSLInfo(SSLInfo* ssl_info);
virtual void GetSSLCertRequestInfo(SSLCertRequestInfo* cert_request_info);

// ClientSocket methods:
virtual int Connect(CompletionCallback* callback);
Expand Down Expand Up @@ -147,9 +148,6 @@ class SSLClientSocketWin : public SSLClientSocket {
// to be interpreted as EOF.
bool ignore_ok_result_;

// True if the user has no client certificate.
bool no_client_cert_;

// Renegotiation is in progress.
bool renegotiating_;
};
Expand Down
12 changes: 10 additions & 2 deletions net/base/ssl_config_service.h
Original file line number Diff line number Diff line change
@@ -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.

Expand All @@ -18,7 +18,7 @@ struct SSLConfig {
// Default to SSL 2.0 off, SSL 3.0 on, and TLS 1.0 on.
SSLConfig()
: rev_checking_enabled(false), ssl2_enabled(false),
ssl3_enabled(true), tls1_enabled(true) {
ssl3_enabled(true), tls1_enabled(true), send_client_cert(false) {
}

bool rev_checking_enabled; // True if server certificate revocation
Expand All @@ -27,11 +27,19 @@ struct SSLConfig {
bool ssl3_enabled; // True if SSL 3.0 is enabled.
bool tls1_enabled; // True if TLS 1.0 is enabled.

// TODO(wtc): move the following members to a new SSLParams structure. They
// are not SSL configuration settings.

// Add any known-bad SSL certificates to allowed_bad_certs_ that should not
// trigger an ERR_CERT_*_INVALID error when calling SSLClientSocket::Connect.
// This would normally be done in response to the user explicitly accepting
// the bad certificate.
std::set<scoped_refptr<X509Certificate> > allowed_bad_certs_;

// True if we should send client_cert to the server.
bool send_client_cert;

scoped_refptr<X509Certificate> client_cert;
};

// This class is responsible for getting and setting the SSL configuration.
Expand Down
Loading

0 comments on commit 0b45559

Please sign in to comment.