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

Side by Side Diff: net/base/ssl_client_socket_win.cc

Issue 118039: Implement SSL client authentication for Windows.... (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: Upload before checkin Created 11 years, 6 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 unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « net/base/ssl_client_socket_win.h ('k') | net/base/ssl_config_service.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
OLDNEW
« no previous file with comments | « net/base/ssl_client_socket_win.h ('k') | net/base/ssl_config_service.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698