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 |