| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "net/base/ssl_client_socket_win.h" | 5 #include "net/base/ssl_client_socket_win.h" |
| 6 | 6 |
| 7 #include <schnlsp.h> | 7 #include <schnlsp.h> |
| 8 | 8 |
| 9 #include "base/lock.h" | 9 #include "base/lock.h" |
| 10 #include "base/singleton.h" | 10 #include "base/singleton.h" |
| 11 #include "base/string_util.h" | 11 #include "base/string_util.h" |
| (...skipping 213 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 225 isc_status_(SEC_E_OK), | 225 isc_status_(SEC_E_OK), |
| 226 payload_send_buffer_len_(0), | 226 payload_send_buffer_len_(0), |
| 227 bytes_sent_(0), | 227 bytes_sent_(0), |
| 228 decrypted_ptr_(NULL), | 228 decrypted_ptr_(NULL), |
| 229 bytes_decrypted_(0), | 229 bytes_decrypted_(0), |
| 230 received_ptr_(NULL), | 230 received_ptr_(NULL), |
| 231 bytes_received_(0), | 231 bytes_received_(0), |
| 232 writing_first_token_(false), | 232 writing_first_token_(false), |
| 233 completed_handshake_(false), | 233 completed_handshake_(false), |
| 234 ignore_ok_result_(false), | 234 ignore_ok_result_(false), |
| 235 no_client_cert_(false), | |
| 236 renegotiating_(false) { | 235 renegotiating_(false) { |
| 237 memset(&stream_sizes_, 0, sizeof(stream_sizes_)); | 236 memset(&stream_sizes_, 0, sizeof(stream_sizes_)); |
| 238 memset(in_buffers_, 0, sizeof(in_buffers_)); | 237 memset(in_buffers_, 0, sizeof(in_buffers_)); |
| 239 memset(&send_buffer_, 0, sizeof(send_buffer_)); | 238 memset(&send_buffer_, 0, sizeof(send_buffer_)); |
| 240 memset(&ctxt_, 0, sizeof(ctxt_)); | 239 memset(&ctxt_, 0, sizeof(ctxt_)); |
| 241 } | 240 } |
| 242 | 241 |
| 243 SSLClientSocketWin::~SSLClientSocketWin() { | 242 SSLClientSocketWin::~SSLClientSocketWin() { |
| 244 Disconnect(); | 243 Disconnect(); |
| 245 } | 244 } |
| 246 | 245 |
| 247 void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) { | 246 void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) { |
| 248 if (!server_cert_) | 247 if (!server_cert_) |
| 249 return; | 248 return; |
| 250 | 249 |
| 251 ssl_info->cert = server_cert_; | 250 ssl_info->cert = server_cert_; |
| 252 ssl_info->cert_status = server_cert_verify_result_.cert_status; | 251 ssl_info->cert_status = server_cert_verify_result_.cert_status; |
| 253 SecPkgContext_ConnectionInfo connection_info; | 252 SecPkgContext_ConnectionInfo connection_info; |
| 254 SECURITY_STATUS status = QueryContextAttributes( | 253 SECURITY_STATUS status = QueryContextAttributes( |
| 255 &ctxt_, SECPKG_ATTR_CONNECTION_INFO, &connection_info); | 254 &ctxt_, SECPKG_ATTR_CONNECTION_INFO, &connection_info); |
| 256 if (status == SEC_E_OK) { | 255 if (status == SEC_E_OK) { |
| 257 // TODO(wtc): compute the overall security strength, taking into account | 256 // TODO(wtc): compute the overall security strength, taking into account |
| 258 // dwExchStrength and dwHashStrength. dwExchStrength needs to be | 257 // dwExchStrength and dwHashStrength. dwExchStrength needs to be |
| 259 // normalized. | 258 // normalized. |
| 260 ssl_info->security_bits = connection_info.dwCipherStrength; | 259 ssl_info->security_bits = connection_info.dwCipherStrength; |
| 261 } | 260 } |
| 262 } | 261 } |
| 263 | 262 |
| 263 void SSLClientSocketWin::GetSSLCertRequestInfo( |
| 264 SSLCertRequestInfo* cert_request_info) { |
| 265 // TODO(wtc): implement this. |
| 266 } |
| 267 |
| 264 int SSLClientSocketWin::Connect(CompletionCallback* callback) { | 268 int SSLClientSocketWin::Connect(CompletionCallback* callback) { |
| 265 DCHECK(transport_.get()); | 269 DCHECK(transport_.get()); |
| 266 DCHECK(next_state_ == STATE_NONE); | 270 DCHECK(next_state_ == STATE_NONE); |
| 267 DCHECK(!user_callback_); | 271 DCHECK(!user_callback_); |
| 268 | 272 |
| 269 int ssl_version_mask = 0; | 273 int ssl_version_mask = 0; |
| 270 if (ssl_config_.ssl2_enabled) | 274 if (ssl_config_.ssl2_enabled) |
| 271 ssl_version_mask |= SSL2; | 275 ssl_version_mask |= SSL2; |
| 272 if (ssl_config_.ssl3_enabled) | 276 if (ssl_config_.ssl3_enabled) |
| 273 ssl_version_mask |= SSL3; | 277 ssl_version_mask |= SSL3; |
| (...skipping 263 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 537 TimeStamp expiry; | 541 TimeStamp expiry; |
| 538 DWORD out_flags; | 542 DWORD out_flags; |
| 539 | 543 |
| 540 DWORD flags = ISC_REQ_SEQUENCE_DETECT | | 544 DWORD flags = ISC_REQ_SEQUENCE_DETECT | |
| 541 ISC_REQ_REPLAY_DETECT | | 545 ISC_REQ_REPLAY_DETECT | |
| 542 ISC_REQ_CONFIDENTIALITY | | 546 ISC_REQ_CONFIDENTIALITY | |
| 543 ISC_RET_EXTENDED_ERROR | | 547 ISC_RET_EXTENDED_ERROR | |
| 544 ISC_REQ_ALLOCATE_MEMORY | | 548 ISC_REQ_ALLOCATE_MEMORY | |
| 545 ISC_REQ_STREAM; | 549 ISC_REQ_STREAM; |
| 546 | 550 |
| 547 // When InitializeSecurityContext returns SEC_I_INCOMPLETE_CREDENTIALS, | 551 if (ssl_config_.send_client_cert) |
| 548 // John Banes (a Microsoft security developer) said we need to pass in the | |
| 549 // ISC_REQ_USE_SUPPLIED_CREDS flag if we skip finding a client certificate | |
| 550 // and just call InitializeSecurityContext again. (See | |
| 551 // (http://www.derkeiler.com/Newsgroups/microsoft.public.platformsdk.security/
2004-08/0187.html.) | |
| 552 // My testing on XP SP2 and Vista SP1 shows that it still works without | |
| 553 // passing in this flag, but I pass it in to be safe. | |
| 554 if (no_client_cert_) | |
| 555 flags |= ISC_REQ_USE_SUPPLIED_CREDS; | 552 flags |= ISC_REQ_USE_SUPPLIED_CREDS; |
| 556 | 553 |
| 557 SecBufferDesc in_buffer_desc, out_buffer_desc; | 554 SecBufferDesc in_buffer_desc, out_buffer_desc; |
| 558 | 555 |
| 559 in_buffer_desc.cBuffers = 2; | 556 in_buffer_desc.cBuffers = 2; |
| 560 in_buffer_desc.pBuffers = in_buffers_; | 557 in_buffer_desc.pBuffers = in_buffers_; |
| 561 in_buffer_desc.ulVersion = SECBUFFER_VERSION; | 558 in_buffer_desc.ulVersion = SECBUFFER_VERSION; |
| 562 | 559 |
| 563 in_buffers_[0].pvBuffer = recv_buffer_.get(); | 560 in_buffers_[0].pvBuffer = recv_buffer_.get(); |
| 564 in_buffers_[0].cbBuffer = bytes_received_; | 561 in_buffers_[0].cbBuffer = bytes_received_; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 616 } else { | 613 } else { |
| 617 bytes_received_ = 0; | 614 bytes_received_ = 0; |
| 618 } | 615 } |
| 619 return DidCompleteHandshake(); | 616 return DidCompleteHandshake(); |
| 620 } | 617 } |
| 621 | 618 |
| 622 if (FAILED(isc_status_)) { | 619 if (FAILED(isc_status_)) { |
| 623 int result = MapSecurityError(isc_status_); | 620 int result = MapSecurityError(isc_status_); |
| 624 // We told Schannel to not verify the server certificate | 621 // We told Schannel to not verify the server certificate |
| 625 // (SCH_CRED_MANUAL_CRED_VALIDATION), so any certificate error returned by | 622 // (SCH_CRED_MANUAL_CRED_VALIDATION), so any certificate error returned by |
| 626 // InitializeSecurityContext must be referring to the (missing) client | 623 // InitializeSecurityContext must be referring to the bad or missing |
| 627 // certificate. | 624 // client certificate. |
| 628 if (IsCertificateError(result)) { | 625 if (IsCertificateError(result)) { |
| 629 // TODO(wtc): When we support SSL client authentication, we will need to | 626 // TODO(wtc): Add new error codes for client certificate errors reported |
| 630 // add new error codes for client certificate errors reported by the | 627 // by the server using SSL/TLS alert messages. See the MSDN page |
| 631 // server using SSL/TLS alert messages. See http://crbug.com/318. See | 628 // "Schannel Error Codes for TLS and SSL Alerts", which maps TLS alert |
| 632 // also the MSDN page "Schannel Error Codes for TLS and SSL Alerts", | 629 // messages to Windows error codes: |
| 633 // which maps TLS alert messages to Windows error codes: | |
| 634 // http://msdn.microsoft.com/en-us/library/dd721886%28VS.85%29.aspx | 630 // http://msdn.microsoft.com/en-us/library/dd721886%28VS.85%29.aspx |
| 635 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; | 631 return ERR_BAD_SSL_CLIENT_AUTH_CERT; |
| 636 } | 632 } |
| 637 return result; | 633 return result; |
| 638 } | 634 } |
| 639 | 635 |
| 640 if (isc_status_ == SEC_I_INCOMPLETE_CREDENTIALS) { | 636 if (isc_status_ == SEC_I_INCOMPLETE_CREDENTIALS) |
| 641 // We don't support SSL client authentication yet. For now we just set | 637 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |
| 642 // no_client_cert_ to true and call InitializeSecurityContext again. | |
| 643 no_client_cert_ = true; | |
| 644 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | |
| 645 ignore_ok_result_ = true; // OK doesn't mean EOF. | |
| 646 return OK; | |
| 647 } | |
| 648 | 638 |
| 649 DCHECK(isc_status_ == SEC_I_CONTINUE_NEEDED); | 639 DCHECK(isc_status_ == SEC_I_CONTINUE_NEEDED); |
| 650 if (in_buffers_[1].BufferType == SECBUFFER_EXTRA) { | 640 if (in_buffers_[1].BufferType == SECBUFFER_EXTRA) { |
| 651 memmove(recv_buffer_.get(), | 641 memmove(recv_buffer_.get(), |
| 652 recv_buffer_.get() + (bytes_received_ - in_buffers_[1].cbBuffer), | 642 recv_buffer_.get() + (bytes_received_ - in_buffers_[1].cbBuffer), |
| 653 in_buffers_[1].cbBuffer); | 643 in_buffers_[1].cbBuffer); |
| 654 bytes_received_ = in_buffers_[1].cbBuffer; | 644 bytes_received_ = in_buffers_[1].cbBuffer; |
| 655 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; | 645 next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |
| 656 ignore_ok_result_ = true; // OK doesn't mean EOF. | 646 ignore_ok_result_ = true; // OK doesn't mean EOF. |
| 657 return OK; | 647 return OK; |
| (...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 982 | 972 |
| 983 // Send the remaining bytes. | 973 // Send the remaining bytes. |
| 984 next_state_ = STATE_PAYLOAD_WRITE; | 974 next_state_ = STATE_PAYLOAD_WRITE; |
| 985 return OK; | 975 return OK; |
| 986 } | 976 } |
| 987 | 977 |
| 988 int SSLClientSocketWin::DidCompleteHandshake() { | 978 int SSLClientSocketWin::DidCompleteHandshake() { |
| 989 SECURITY_STATUS status = QueryContextAttributes( | 979 SECURITY_STATUS status = QueryContextAttributes( |
| 990 &ctxt_, SECPKG_ATTR_STREAM_SIZES, &stream_sizes_); | 980 &ctxt_, SECPKG_ATTR_STREAM_SIZES, &stream_sizes_); |
| 991 if (status != SEC_E_OK) { | 981 if (status != SEC_E_OK) { |
| 992 DLOG(ERROR) << "QueryContextAttributes failed: " << status; | 982 DLOG(ERROR) << "QueryContextAttributes (stream sizes) failed: " << status; |
| 993 return MapSecurityError(status); | 983 return MapSecurityError(status); |
| 994 } | 984 } |
| 995 DCHECK(!server_cert_ || renegotiating_); | 985 DCHECK(!server_cert_ || renegotiating_); |
| 996 PCCERT_CONTEXT server_cert_handle = NULL; | 986 PCCERT_CONTEXT server_cert_handle = NULL; |
| 997 status = QueryContextAttributes( | 987 status = QueryContextAttributes( |
| 998 &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_handle); | 988 &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_handle); |
| 999 if (status != SEC_E_OK) { | 989 if (status != SEC_E_OK) { |
| 1000 DLOG(ERROR) << "QueryContextAttributes failed: " << status; | 990 DLOG(ERROR) << "QueryContextAttributes (remote cert) failed: " << status; |
| 1001 return MapSecurityError(status); | 991 return MapSecurityError(status); |
| 1002 } | 992 } |
| 1003 if (renegotiating_ && | 993 if (renegotiating_ && |
| 1004 SameCert(server_cert_->os_cert_handle(), server_cert_handle)) { | 994 SameCert(server_cert_->os_cert_handle(), server_cert_handle)) { |
| 1005 // We already verified the server certificate. Either it is good or the | 995 // We already verified the server certificate. Either it is good or the |
| 1006 // user has accepted the certificate error. | 996 // user has accepted the certificate error. |
| 1007 CertFreeCertificateContext(server_cert_handle); | 997 CertFreeCertificateContext(server_cert_handle); |
| 1008 DidCompleteRenegotiation(OK); | 998 DidCompleteRenegotiation(OK); |
| 1009 } else { | 999 } else { |
| 1010 server_cert_ = X509Certificate::CreateFromHandle( | 1000 server_cert_ = X509Certificate::CreateFromHandle( |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1048 } | 1038 } |
| 1049 } | 1039 } |
| 1050 | 1040 |
| 1051 void SSLClientSocketWin::FreeSendBuffer() { | 1041 void SSLClientSocketWin::FreeSendBuffer() { |
| 1052 SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer); | 1042 SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer); |
| 1053 DCHECK(status == SEC_E_OK); | 1043 DCHECK(status == SEC_E_OK); |
| 1054 memset(&send_buffer_, 0, sizeof(send_buffer_)); | 1044 memset(&send_buffer_, 0, sizeof(send_buffer_)); |
| 1055 } | 1045 } |
| 1056 | 1046 |
| 1057 } // namespace net | 1047 } // namespace net |
| OLD | NEW |