1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "net/socket/ssl_client_socket_win.h"
6
7 #include <schnlsp.h>
8 #include <map>
9
10 #include "base/compiler_specific.h"
11 #include "base/lazy_instance.h"
12 #include "base/stl_util-inl.h"
13 #include "base/string_util.h"
14 #include "base/synchronization/lock.h"
15 #include "base/utf_string_conversions.h"
16 #include "net/base/cert_verifier.h"
17 #include "net/base/connection_type_histograms.h"
18 #include "net/base/host_port_pair.h"
19 #include "net/base/io_buffer.h"
20 #include "net/base/net_log.h"
21 #include "net/base/net_errors.h"
22 #include "net/base/ssl_cert_request_info.h"
23 #include "net/base/ssl_connection_status_flags.h"
24 #include "net/base/ssl_info.h"
25 #include "net/socket/client_socket_handle.h"
26
27 #pragma comment(lib, "secur32.lib")
28
29 namespace net {
30
31 //-----------------------------------------------------------------------------
32
33 // TODO(wtc): See http://msdn.microsoft.com/en-us/library/aa377188(VS.85).aspx
34 // for the other error codes we may need to map.
MapSecurityError(SECURITY_STATUS err)35 static int MapSecurityError(SECURITY_STATUS err) {
36 // There are numerous security error codes, but these are the ones we thus
37 // far find interesting.
38 switch (err) {
39 case SEC_E_WRONG_PRINCIPAL: // Schannel - server certificate error.
40 case CERT_E_CN_NO_MATCH: // CryptoAPI
41 return ERR_CERT_COMMON_NAME_INVALID;
42 case SEC_E_UNTRUSTED_ROOT: // Schannel - server certificate error or
43 // unknown_ca alert.
44 case CERT_E_UNTRUSTEDROOT: // CryptoAPI
45 return ERR_CERT_AUTHORITY_INVALID;
46 case SEC_E_CERT_EXPIRED: // Schannel - server certificate error or
47 // certificate_expired alert.
48 case CERT_E_EXPIRED: // CryptoAPI
49 return ERR_CERT_DATE_INVALID;
50 case CRYPT_E_NO_REVOCATION_CHECK:
51 return ERR_CERT_NO_REVOCATION_MECHANISM;
52 case CRYPT_E_REVOCATION_OFFLINE:
53 return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
54 case CRYPT_E_REVOKED: // CryptoAPI and Schannel server certificate error,
55 // or certificate_revoked alert.
56 return ERR_CERT_REVOKED;
57
58 // We received one of the following alert messages from the server:
59 // bad_certificate
60 // unsupported_certificate
61 // certificate_unknown
62 case SEC_E_CERT_UNKNOWN:
63 case CERT_E_ROLE:
64 return ERR_CERT_INVALID;
65
66 // We received one of the following alert messages from the server:
67 // decode_error
68 // export_restriction
69 // handshake_failure
70 // illegal_parameter
71 // record_overflow
72 // unexpected_message
73 // and all other TLS alerts not explicitly specified elsewhere.
74 case SEC_E_ILLEGAL_MESSAGE:
75 // We received one of the following alert messages from the server:
76 // decrypt_error
77 // decryption_failed
78 case SEC_E_DECRYPT_FAILURE:
79 // We received one of the following alert messages from the server:
80 // bad_record_mac
81 // decompression_failure
82 case SEC_E_MESSAGE_ALTERED:
83 // TODO(rsleevi): Add SEC_E_INTERNAL_ERROR, which corresponds to an
84 // internal_error alert message being received. However, it is also used
85 // by Schannel for authentication errors that happen locally, so it has
86 // been omitted to prevent masking them as protocol errors.
87 return ERR_SSL_PROTOCOL_ERROR;
88
89 case SEC_E_LOGON_DENIED: // Received a access_denied alert.
90 return ERR_BAD_SSL_CLIENT_AUTH_CERT;
91
92 case SEC_E_UNSUPPORTED_FUNCTION: // Received a protocol_version alert.
93 case SEC_E_ALGORITHM_MISMATCH: // Received an insufficient_security alert.
94 return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
95
96 case SEC_E_NO_CREDENTIALS:
97 return ERR_SSL_CLIENT_AUTH_CERT_NO_PRIVATE_KEY;
98 case SEC_E_INVALID_HANDLE:
99 case SEC_E_INVALID_TOKEN:
100 LOG(ERROR) << "Unexpected error " << err;
101 return ERR_UNEXPECTED;
102 case SEC_E_OK:
103 return OK;
104 default:
105 LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
106 return ERR_FAILED;
107 }
108 }
109
110 //-----------------------------------------------------------------------------
111
112 // A bitmask consisting of these bit flags encodes which versions of the SSL
113 // protocol (SSL 3.0 and TLS 1.0) are enabled.
114 enum {
115 SSL3 = 1 << 0,
116 TLS1 = 1 << 1,
117 SSL_VERSION_MASKS = 1 << 2 // The number of SSL version bitmasks.
118 };
119
120 // CredHandleClass simply gives a default constructor and a destructor to
121 // SSPI's CredHandle type (a C struct).
122 class CredHandleClass : public CredHandle {
123 public:
CredHandleClass()124 CredHandleClass() {
125 SecInvalidateHandle(this);
126 }
127
~CredHandleClass()128 ~CredHandleClass() {
129 if (SecIsValidHandle(this)) {
130 SECURITY_STATUS status = FreeCredentialsHandle(this);
131 DCHECK(status == SEC_E_OK);
132 }
133 }
134 };
135
136 // A table of CredHandles.
137 class CredHandleTable {
138 public:
CredHandleTable()139 CredHandleTable() {}
140
~CredHandleTable()141 ~CredHandleTable() {
142 STLDeleteContainerPairSecondPointers(client_cert_creds_.begin(),
143 client_cert_creds_.end());
144 }
145
GetHandle(PCCERT_CONTEXT client_cert,int ssl_version_mask,CredHandle ** handle_ptr)146 int GetHandle(PCCERT_CONTEXT client_cert,
147 int ssl_version_mask,
148 CredHandle** handle_ptr) {
149 DCHECK(0 < ssl_version_mask &&
150 ssl_version_mask < arraysize(anonymous_creds_));
151 CredHandleClass* handle;
152 base::AutoLock lock(lock_);
153 if (client_cert) {
154 CredHandleMapKey key = std::make_pair(client_cert, ssl_version_mask);
155 CredHandleMap::const_iterator it = client_cert_creds_.find(key);
156 if (it == client_cert_creds_.end()) {
157 handle = new CredHandleClass;
158 client_cert_creds_[key] = handle;
159 } else {
160 handle = it->second;
161 }
162 } else {
163 handle = &anonymous_creds_[ssl_version_mask];
164 }
165 if (!SecIsValidHandle(handle)) {
166 int result = InitializeHandle(handle, client_cert, ssl_version_mask);
167 if (result != OK)
168 return result;
169 }
170 *handle_ptr = handle;
171 return OK;
172 }
173
174 private:
175 // CredHandleMapKey is a std::pair consisting of these two components:
176 // PCCERT_CONTEXT client_cert
177 // int ssl_version_mask
178 typedef std::pair<PCCERT_CONTEXT, int> CredHandleMapKey;
179
180 typedef std::map<CredHandleMapKey, CredHandleClass*> CredHandleMap;
181
182 // Returns OK on success or a network error code on failure.
183 static int InitializeHandle(CredHandle* handle,
184 PCCERT_CONTEXT client_cert,
185 int ssl_version_mask);
186
187 base::Lock lock_;
188
189 // Anonymous (no client certificate) CredHandles for all possible
190 // combinations of SSL versions. Defined as an array for fast lookup.
191 CredHandleClass anonymous_creds_[SSL_VERSION_MASKS];
192
193 // CredHandles that use a client certificate.
194 CredHandleMap client_cert_creds_;
195 };
196
197 static base::LazyInstance<CredHandleTable> g_cred_handle_table(
198 base::LINKER_INITIALIZED);
199
200 // static
InitializeHandle(CredHandle * handle,PCCERT_CONTEXT client_cert,int ssl_version_mask)201 int CredHandleTable::InitializeHandle(CredHandle* handle,
202 PCCERT_CONTEXT client_cert,
203 int ssl_version_mask) {
204 SCHANNEL_CRED schannel_cred = {0};
205 schannel_cred.dwVersion = SCHANNEL_CRED_VERSION;
206 if (client_cert) {
207 schannel_cred.cCreds = 1;
208 schannel_cred.paCred = &client_cert;
209 // Schannel will make its own copy of client_cert.
210 }
211
212 // The global system registry settings take precedence over the value of
213 // schannel_cred.grbitEnabledProtocols.
214 schannel_cred.grbitEnabledProtocols = 0;
215 if (ssl_version_mask & SSL3)
216 schannel_cred.grbitEnabledProtocols |= SP_PROT_SSL3;
217 if (ssl_version_mask & TLS1)
218 schannel_cred.grbitEnabledProtocols |= SP_PROT_TLS1;
219
220 // The default session lifetime is 36000000 milliseconds (ten hours). Set
221 // schannel_cred.dwSessionLifespan to change the number of milliseconds that
222 // Schannel keeps the session in its session cache.
223
224 // We can set the key exchange algorithms (RSA or DH) in
225 // schannel_cred.{cSupportedAlgs,palgSupportedAlgs}.
226
227 // Although SCH_CRED_AUTO_CRED_VALIDATION is convenient, we have to use
228 // SCH_CRED_MANUAL_CRED_VALIDATION for three reasons.
229 // 1. SCH_CRED_AUTO_CRED_VALIDATION doesn't allow us to get the certificate
230 // context if the certificate validation fails.
231 // 2. SCH_CRED_AUTO_CRED_VALIDATION returns only one error even if the
232 // certificate has multiple errors.
233 // 3. SCH_CRED_AUTO_CRED_VALIDATION doesn't allow us to ignore untrusted CA
234 // and expired certificate errors. There are only flags to ignore the
235 // name mismatch and unable-to-check-revocation errors.
236 //
237 // We specify SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT to cause the TLS
238 // certificate status request extension (commonly known as OCSP stapling)
239 // to be sent on Vista or later. This flag matches the
240 // CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT flag that we pass to the
241 // CertGetCertificateChain calls. Note: we specify this flag even when
242 // revocation checking is disabled to avoid doubling the number of
243 // credentials handles we need to acquire.
244 //
245 // TODO(wtc): Look into undocumented or poorly documented flags:
246 // SCH_CRED_RESTRICTED_ROOTS
247 // SCH_CRED_REVOCATION_CHECK_CACHE_ONLY
248 // SCH_CRED_CACHE_ONLY_URL_RETRIEVAL
249 // SCH_CRED_MEMORY_STORE_CERT
250 schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS |
251 SCH_CRED_MANUAL_CRED_VALIDATION |
252 SCH_CRED_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
253 TimeStamp expiry;
254 SECURITY_STATUS status;
255
256 status = AcquireCredentialsHandle(
257 NULL, // Not used
258 UNISP_NAME, // Microsoft Unified Security Protocol Provider
259 SECPKG_CRED_OUTBOUND,
260 NULL, // Not used
261 &schannel_cred,
262 NULL, // Not used
263 NULL, // Not used
264 handle,
265 &expiry); // Optional
266 if (status != SEC_E_OK)
267 LOG(ERROR) << "AcquireCredentialsHandle failed: " << status;
268 return MapSecurityError(status);
269 }
270
271 // For the SSL sockets to share SSL sessions by session resumption handshakes,
272 // they need to use the same CredHandle. The GetCredHandle function creates
273 // and stores a shared CredHandle in *handle_ptr. On success, GetCredHandle
274 // returns OK. On failure, GetCredHandle returns a network error code and
275 // leaves *handle_ptr unchanged.
276 //
277 // The versions of the SSL protocol enabled are a property of the CredHandle.
278 // So we need a separate CredHandle for each combination of SSL versions.
279 // Most of the time Chromium will use only one or two combinations of SSL
280 // versions (for example, SSL3 | TLS1 for normal use, plus SSL3 when visiting
281 // TLS-intolerant servers). These CredHandles are initialized only when
282 // needed.
283
GetCredHandle(PCCERT_CONTEXT client_cert,int ssl_version_mask,CredHandle ** handle_ptr)284 static int GetCredHandle(PCCERT_CONTEXT client_cert,
285 int ssl_version_mask,
286 CredHandle** handle_ptr) {
287 if (ssl_version_mask <= 0 || ssl_version_mask >= SSL_VERSION_MASKS) {
288 NOTREACHED();
289 return ERR_UNEXPECTED;
290 }
291 return g_cred_handle_table.Get().GetHandle(client_cert,
292 ssl_version_mask,
293 handle_ptr);
294 }
295
296 //-----------------------------------------------------------------------------
297
298 // This callback is intended to be used with CertFindChainInStore. In addition
299 // to filtering by extended/enhanced key usage, we do not show expired
300 // certificates and require digital signature usage in the key usage
301 // extension.
302 //
303 // This matches our behavior on Mac OS X and that of NSS. It also matches the
304 // default behavior of IE8. See http://support.microsoft.com/kb/890326 and
305 // http://blogs.msdn.com/b/askie/archive/2009/06/09/my-expired-client-certificates-no-longer-display-when-connecting-to-my-web-server-using-ie8.aspx
ClientCertFindCallback(PCCERT_CONTEXT cert_context,void * find_arg)306 static BOOL WINAPI ClientCertFindCallback(PCCERT_CONTEXT cert_context,
307 void* find_arg) {
308 // Verify the certificate's KU is good.
309 BYTE key_usage;
310 if (CertGetIntendedKeyUsage(X509_ASN_ENCODING, cert_context->pCertInfo,
311 &key_usage, 1)) {
312 if (!(key_usage & CERT_DIGITAL_SIGNATURE_KEY_USAGE))
313 return FALSE;
314 } else {
315 DWORD err = GetLastError();
316 // If |err| is non-zero, it's an actual error. Otherwise the extension
317 // just isn't present, and we treat it as if everything was allowed.
318 if (err) {
319 DLOG(ERROR) << "CertGetIntendedKeyUsage failed: " << err;
320 return FALSE;
321 }
322 }
323
324 // Verify the current time is within the certificate's validity period.
325 if (CertVerifyTimeValidity(NULL, cert_context->pCertInfo) != 0)
326 return FALSE;
327
328 // Verify private key metadata is associated with this certificate.
329 DWORD size = 0;
330 if (!CertGetCertificateContextProperty(
331 cert_context, CERT_KEY_PROV_INFO_PROP_ID, NULL, &size)) {
332 return FALSE;
333 }
334
335 return TRUE;
336 }
337
338 //-----------------------------------------------------------------------------
339
340 // A memory certificate store for client certificates. This allows us to
341 // close the "MY" system certificate store when we finish searching for
342 // client certificates.
343 class ClientCertStore {
344 public:
ClientCertStore()345 ClientCertStore() {
346 store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL);
347 }
348
~ClientCertStore()349 ~ClientCertStore() {
350 if (store_) {
351 BOOL ok = CertCloseStore(store_, CERT_CLOSE_STORE_CHECK_FLAG);
352 DCHECK(ok);
353 }
354 }
355
CopyCertContext(PCCERT_CONTEXT client_cert)356 PCCERT_CONTEXT CopyCertContext(PCCERT_CONTEXT client_cert) {
357 PCCERT_CONTEXT copy;
358 BOOL ok = CertAddCertificateContextToStore(store_, client_cert,
359 CERT_STORE_ADD_USE_EXISTING,
360 ©);
361 DCHECK(ok);
362 return ok ? copy : NULL;
363 }
364
365 private:
366 HCERTSTORE store_;
367 };
368
369 static base::LazyInstance<ClientCertStore> g_client_cert_store(
370 base::LINKER_INITIALIZED);
371
372 //-----------------------------------------------------------------------------
373
374 // Size of recv_buffer_
375 //
376 // Ciphertext is decrypted one SSL record at a time, so recv_buffer_ needs to
377 // have room for a full SSL record, with the header and trailer. Here is the
378 // breakdown of the size:
379 // 5: SSL record header
380 // 16K: SSL record maximum size
381 // 64: >= SSL record trailer (16 or 20 have been observed)
382 static const int kRecvBufferSize = (5 + 16*1024 + 64);
383
SSLClientSocketWin(ClientSocketHandle * transport_socket,const HostPortPair & host_and_port,const SSLConfig & ssl_config,CertVerifier * cert_verifier)384 SSLClientSocketWin::SSLClientSocketWin(ClientSocketHandle* transport_socket,
385 const HostPortPair& host_and_port,
386 const SSLConfig& ssl_config,
387 CertVerifier* cert_verifier)
388 : ALLOW_THIS_IN_INITIALIZER_LIST(
389 handshake_io_callback_(this,
390 &SSLClientSocketWin::OnHandshakeIOComplete)),
391 ALLOW_THIS_IN_INITIALIZER_LIST(
392 read_callback_(this, &SSLClientSocketWin::OnReadComplete)),
393 ALLOW_THIS_IN_INITIALIZER_LIST(
394 write_callback_(this, &SSLClientSocketWin::OnWriteComplete)),
395 transport_(transport_socket),
396 host_and_port_(host_and_port),
397 ssl_config_(ssl_config),
398 user_connect_callback_(NULL),
399 user_read_callback_(NULL),
400 user_read_buf_len_(0),
401 user_write_callback_(NULL),
402 user_write_buf_len_(0),
403 next_state_(STATE_NONE),
404 cert_verifier_(cert_verifier),
405 creds_(NULL),
406 isc_status_(SEC_E_OK),
407 payload_send_buffer_len_(0),
408 bytes_sent_(0),
409 decrypted_ptr_(NULL),
410 bytes_decrypted_(0),
411 received_ptr_(NULL),
412 bytes_received_(0),
413 writing_first_token_(false),
414 ignore_ok_result_(false),
415 renegotiating_(false),
416 need_more_data_(false),
417 net_log_(transport_socket->socket()->NetLog()) {
418 memset(&stream_sizes_, 0, sizeof(stream_sizes_));
419 memset(in_buffers_, 0, sizeof(in_buffers_));
420 memset(&send_buffer_, 0, sizeof(send_buffer_));
421 memset(&ctxt_, 0, sizeof(ctxt_));
422 }
423
~SSLClientSocketWin()424 SSLClientSocketWin::~SSLClientSocketWin() {
425 Disconnect();
426 }
427
GetSSLInfo(SSLInfo * ssl_info)428 void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) {
429 ssl_info->Reset();
430
431 if (!server_cert_)
432 return;
433
434 ssl_info->cert = server_cert_;
435 ssl_info->cert_status = server_cert_verify_result_.cert_status;
436 ssl_info->public_key_hashes = server_cert_verify_result_.public_key_hashes;
437 ssl_info->is_issued_by_known_root =
438 server_cert_verify_result_.is_issued_by_known_root;
439 SecPkgContext_ConnectionInfo connection_info;
440 SECURITY_STATUS status = QueryContextAttributes(
441 &ctxt_, SECPKG_ATTR_CONNECTION_INFO, &connection_info);
442 if (status == SEC_E_OK) {
443 // TODO(wtc): compute the overall security strength, taking into account
444 // dwExchStrength and dwHashStrength. dwExchStrength needs to be
445 // normalized.
446 ssl_info->security_bits = connection_info.dwCipherStrength;
447 }
448 // SecPkgContext_CipherInfo comes from CNG and is available on Vista or
449 // later only. On XP, the next QueryContextAttributes call fails with
450 // SEC_E_UNSUPPORTED_FUNCTION (0x80090302), so ssl_info->connection_status
451 // won't contain the cipher suite. If this is a problem, we can build the
452 // cipher suite from the aiCipher, aiHash, and aiExch fields of
453 // SecPkgContext_ConnectionInfo based on Appendix C of RFC 5246.
454 SecPkgContext_CipherInfo cipher_info = { SECPKGCONTEXT_CIPHERINFO_V1 };
455 status = QueryContextAttributes(
456 &ctxt_, SECPKG_ATTR_CIPHER_INFO, &cipher_info);
457 if (status == SEC_E_OK) {
458 // TODO(wtc): find out what the cipher_info.dwBaseCipherSuite field is.
459 ssl_info->connection_status |=
460 (cipher_info.dwCipherSuite & SSL_CONNECTION_CIPHERSUITE_MASK) <<
461 SSL_CONNECTION_CIPHERSUITE_SHIFT;
462 // SChannel doesn't support TLS compression, so cipher_info doesn't have
463 // any field related to the compression method.
464 }
465
466 if (ssl_config_.ssl3_fallback)
467 ssl_info->connection_status |= SSL_CONNECTION_SSL3_FALLBACK;
468 }
469
GetSSLCertRequestInfo(SSLCertRequestInfo * cert_request_info)470 void SSLClientSocketWin::GetSSLCertRequestInfo(
471 SSLCertRequestInfo* cert_request_info) {
472 cert_request_info->host_and_port = host_and_port_.ToString();
473 cert_request_info->client_certs.clear();
474
475 // Get the certificate_authorities field of the CertificateRequest message.
476 // Schannel doesn't return the certificate_types field of the
477 // CertificateRequest message to us, so we can't filter the client
478 // certificates properly. :-(
479 SecPkgContext_IssuerListInfoEx issuer_list;
480 SECURITY_STATUS status = QueryContextAttributes(
481 &ctxt_, SECPKG_ATTR_ISSUER_LIST_EX, &issuer_list);
482 if (status != SEC_E_OK) {
483 DLOG(ERROR) << "QueryContextAttributes (issuer list) failed: " << status;
484 return;
485 }
486
487 // Client certificates of the user are in the "MY" system certificate store.
488 HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY");
489 if (!my_cert_store) {
490 LOG(ERROR) << "Could not open the \"MY\" system certificate store: "
491 << GetLastError();
492 FreeContextBuffer(issuer_list.aIssuers);
493 return;
494 }
495
496 // Enumerate the client certificates.
497 CERT_CHAIN_FIND_BY_ISSUER_PARA find_by_issuer_para;
498 memset(&find_by_issuer_para, 0, sizeof(find_by_issuer_para));
499 find_by_issuer_para.cbSize = sizeof(find_by_issuer_para);
500 find_by_issuer_para.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH;
501 find_by_issuer_para.cIssuer = issuer_list.cIssuers;
502 find_by_issuer_para.rgIssuer = issuer_list.aIssuers;
503 find_by_issuer_para.pfnFindCallback = ClientCertFindCallback;
504
505 PCCERT_CHAIN_CONTEXT chain_context = NULL;
506
507 for (;;) {
508 // Find a certificate chain.
509 chain_context = CertFindChainInStore(my_cert_store,
510 X509_ASN_ENCODING,
511 0,
512 CERT_CHAIN_FIND_BY_ISSUER,
513 &find_by_issuer_para,
514 chain_context);
515 if (!chain_context) {
516 DWORD err = GetLastError();
517 if (err != CRYPT_E_NOT_FOUND)
518 DLOG(ERROR) << "CertFindChainInStore failed: " << err;
519 break;
520 }
521
522 // Get the leaf certificate.
523 PCCERT_CONTEXT cert_context =
524 chain_context->rgpChain[0]->rgpElement[0]->pCertContext;
525 // Copy it to our own certificate store, so that we can close the "MY"
526 // certificate store before returning from this function.
527 PCCERT_CONTEXT cert_context2 =
528 g_client_cert_store.Get().CopyCertContext(cert_context);
529 if (!cert_context2) {
530 NOTREACHED();
531 continue;
532 }
533 scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle(
534 cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT,
535 X509Certificate::OSCertHandles());
536 cert_request_info->client_certs.push_back(cert);
537 CertFreeCertificateContext(cert_context2);
538 }
539
540 FreeContextBuffer(issuer_list.aIssuers);
541
542 BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG);
543 DCHECK(ok);
544 }
545
546 SSLClientSocket::NextProtoStatus
GetNextProto(std::string * proto)547 SSLClientSocketWin::GetNextProto(std::string* proto) {
548 proto->clear();
549 return kNextProtoUnsupported;
550 }
551
552 #ifdef ANDROID
553 // TODO(kristianm): handle the case when wait_for_connect is true
554 // (sync requests)
555 #endif
Connect(CompletionCallback * callback,bool wait_for_connect)556 int SSLClientSocketWin::Connect(CompletionCallback* callback
557 #ifdef ANDROID
558 , bool wait_for_connect
559 #endif
560 ) {
561 DCHECK(transport_.get());
562 DCHECK(next_state_ == STATE_NONE);
563 DCHECK(!user_connect_callback_);
564
565 net_log_.BeginEvent(NetLog::TYPE_SSL_CONNECT, NULL);
566
567 int rv = InitializeSSLContext();
568 if (rv != OK) {
569 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
570 return rv;
571 }
572
573 writing_first_token_ = true;
574 next_state_ = STATE_HANDSHAKE_WRITE;
575 rv = DoLoop(OK);
576 if (rv == ERR_IO_PENDING) {
577 user_connect_callback_ = callback;
578 } else {
579 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
580 }
581 return rv;
582 }
583
InitializeSSLContext()584 int SSLClientSocketWin::InitializeSSLContext() {
585 int ssl_version_mask = 0;
586 if (ssl_config_.ssl3_enabled)
587 ssl_version_mask |= SSL3;
588 if (ssl_config_.tls1_enabled)
589 ssl_version_mask |= TLS1;
590 // If we pass 0 to GetCredHandle, we will let Schannel select the protocols,
591 // rather than enabling no protocols. So we have to fail here.
592 if (ssl_version_mask == 0)
593 return ERR_NO_SSL_VERSIONS_ENABLED;
594 PCCERT_CONTEXT cert_context = NULL;
595 if (ssl_config_.client_cert)
596 cert_context = ssl_config_.client_cert->os_cert_handle();
597 int result = GetCredHandle(cert_context, ssl_version_mask, &creds_);
598 if (result != OK)
599 return result;
600
601 memset(&ctxt_, 0, sizeof(ctxt_));
602
603 SecBufferDesc buffer_desc;
604 DWORD out_flags;
605 DWORD flags = ISC_REQ_SEQUENCE_DETECT |
606 ISC_REQ_REPLAY_DETECT |
607 ISC_REQ_CONFIDENTIALITY |
608 ISC_RET_EXTENDED_ERROR |
609 ISC_REQ_ALLOCATE_MEMORY |
610 ISC_REQ_STREAM;
611
612 send_buffer_.pvBuffer = NULL;
613 send_buffer_.BufferType = SECBUFFER_TOKEN;
614 send_buffer_.cbBuffer = 0;
615
616 buffer_desc.cBuffers = 1;
617 buffer_desc.pBuffers = &send_buffer_;
618 buffer_desc.ulVersion = SECBUFFER_VERSION;
619
620 TimeStamp expiry;
621 SECURITY_STATUS status;
622
623 status = InitializeSecurityContext(
624 creds_,
625 NULL, // NULL on the first call
626 const_cast<wchar_t*>(ASCIIToWide(host_and_port_.host()).c_str()),
627 flags,
628 0, // Reserved
629 0, // Not used with Schannel.
630 NULL, // NULL on the first call
631 0, // Reserved
632 &ctxt_, // Receives the new context handle
633 &buffer_desc,
634 &out_flags,
635 &expiry);
636 if (status != SEC_I_CONTINUE_NEEDED) {
637 LOG(ERROR) << "InitializeSecurityContext failed: " << status;
638 if (status == SEC_E_INVALID_HANDLE) {
639 // The only handle we passed to this InitializeSecurityContext call is
640 // creds_, so print its contents to figure out why it's invalid.
641 if (creds_) {
642 LOG(ERROR) << "creds_->dwLower = " << creds_->dwLower
643 << "; creds_->dwUpper = " << creds_->dwUpper;
644 } else {
645 LOG(ERROR) << "creds_ is NULL";
646 }
647 }
648 return MapSecurityError(status);
649 }
650
651 return OK;
652 }
653
654
Disconnect()655 void SSLClientSocketWin::Disconnect() {
656 // TODO(wtc): Send SSL close_notify alert.
657 next_state_ = STATE_NONE;
658
659 // Shut down anything that may call us back.
660 verifier_.reset();
661 transport_->socket()->Disconnect();
662
663 if (send_buffer_.pvBuffer)
664 FreeSendBuffer();
665 if (SecIsValidHandle(&ctxt_)) {
666 DeleteSecurityContext(&ctxt_);
667 SecInvalidateHandle(&ctxt_);
668 }
669 if (server_cert_)
670 server_cert_ = NULL;
671
672 // TODO(wtc): reset more members?
673 bytes_decrypted_ = 0;
674 bytes_received_ = 0;
675 writing_first_token_ = false;
676 renegotiating_ = false;
677 need_more_data_ = false;
678 }
679
IsConnected() const680 bool SSLClientSocketWin::IsConnected() const {
681 // Ideally, we should also check if we have received the close_notify alert
682 // message from the server, and return false in that case. We're not doing
683 // that, so this function may return a false positive. Since the upper
684 // layer (HttpNetworkTransaction) needs to handle a persistent connection
685 // closed by the server when we send a request anyway, a false positive in
686 // exchange for simpler code is a good trade-off.
687 return completed_handshake() && transport_->socket()->IsConnected();
688 }
689
IsConnectedAndIdle() const690 bool SSLClientSocketWin::IsConnectedAndIdle() const {
691 // Unlike IsConnected, this method doesn't return a false positive.
692 //
693 // Strictly speaking, we should check if we have received the close_notify
694 // alert message from the server, and return false in that case. Although
695 // the close_notify alert message means EOF in the SSL layer, it is just
696 // bytes to the transport layer below, so
697 // transport_->socket()->IsConnectedAndIdle() returns the desired false
698 // when we receive close_notify.
699 return completed_handshake() && transport_->socket()->IsConnectedAndIdle();
700 }
701
GetPeerAddress(AddressList * address) const702 int SSLClientSocketWin::GetPeerAddress(AddressList* address) const {
703 return transport_->socket()->GetPeerAddress(address);
704 }
705
GetLocalAddress(IPEndPoint * address) const706 int SSLClientSocketWin::GetLocalAddress(IPEndPoint* address) const {
707 return transport_->socket()->GetLocalAddress(address);
708 }
709
SetSubresourceSpeculation()710 void SSLClientSocketWin::SetSubresourceSpeculation() {
711 if (transport_.get() && transport_->socket()) {
712 transport_->socket()->SetSubresourceSpeculation();
713 } else {
714 NOTREACHED();
715 }
716 }
717
SetOmniboxSpeculation()718 void SSLClientSocketWin::SetOmniboxSpeculation() {
719 if (transport_.get() && transport_->socket()) {
720 transport_->socket()->SetOmniboxSpeculation();
721 } else {
722 NOTREACHED();
723 }
724 }
725
WasEverUsed() const726 bool SSLClientSocketWin::WasEverUsed() const {
727 if (transport_.get() && transport_->socket()) {
728 return transport_->socket()->WasEverUsed();
729 }
730 NOTREACHED();
731 return false;
732 }
733
UsingTCPFastOpen() const734 bool SSLClientSocketWin::UsingTCPFastOpen() const {
735 if (transport_.get() && transport_->socket()) {
736 return transport_->socket()->UsingTCPFastOpen();
737 }
738 NOTREACHED();
739 return false;
740 }
741
Read(IOBuffer * buf,int buf_len,CompletionCallback * callback)742 int SSLClientSocketWin::Read(IOBuffer* buf, int buf_len,
743 CompletionCallback* callback) {
744 DCHECK(completed_handshake());
745 DCHECK(!user_read_callback_);
746
747 // If we have surplus decrypted plaintext, satisfy the Read with it without
748 // reading more ciphertext from the transport socket.
749 if (bytes_decrypted_ != 0) {
750 int len = std::min(buf_len, bytes_decrypted_);
751 memcpy(buf->data(), decrypted_ptr_, len);
752 decrypted_ptr_ += len;
753 bytes_decrypted_ -= len;
754 if (bytes_decrypted_ == 0) {
755 decrypted_ptr_ = NULL;
756 if (bytes_received_ != 0) {
757 memmove(recv_buffer_.get(), received_ptr_, bytes_received_);
758 received_ptr_ = recv_buffer_.get();
759 }
760 }
761 return len;
762 }
763
764 DCHECK(!user_read_buf_);
765 // http://crbug.com/16371: We're seeing |buf->data()| return NULL. See if the
766 // user is passing in an IOBuffer with a NULL |data_|.
767 CHECK(buf);
768 CHECK(buf->data());
769 user_read_buf_ = buf;
770 user_read_buf_len_ = buf_len;
771
772 int rv = DoPayloadRead();
773 if (rv == ERR_IO_PENDING) {
774 user_read_callback_ = callback;
775 } else {
776 user_read_buf_ = NULL;
777 user_read_buf_len_ = 0;
778 }
779 return rv;
780 }
781
Write(IOBuffer * buf,int buf_len,CompletionCallback * callback)782 int SSLClientSocketWin::Write(IOBuffer* buf, int buf_len,
783 CompletionCallback* callback) {
784 DCHECK(completed_handshake());
785 DCHECK(!user_write_callback_);
786
787 DCHECK(!user_write_buf_);
788 user_write_buf_ = buf;
789 user_write_buf_len_ = buf_len;
790
791 int rv = DoPayloadEncrypt();
792 if (rv != OK)
793 return rv;
794
795 rv = DoPayloadWrite();
796 if (rv == ERR_IO_PENDING) {
797 user_write_callback_ = callback;
798 } else {
799 user_write_buf_ = NULL;
800 user_write_buf_len_ = 0;
801 }
802 return rv;
803 }
804
SetReceiveBufferSize(int32 size)805 bool SSLClientSocketWin::SetReceiveBufferSize(int32 size) {
806 return transport_->socket()->SetReceiveBufferSize(size);
807 }
808
SetSendBufferSize(int32 size)809 bool SSLClientSocketWin::SetSendBufferSize(int32 size) {
810 return transport_->socket()->SetSendBufferSize(size);
811 }
812
OnHandshakeIOComplete(int result)813 void SSLClientSocketWin::OnHandshakeIOComplete(int result) {
814 int rv = DoLoop(result);
815
816 // The SSL handshake has some round trips. We need to notify the caller of
817 // success or any error, other than waiting for IO.
818 if (rv != ERR_IO_PENDING) {
819 // If there is no connect callback available to call, we are renegotiating
820 // (which occurs because we are in the middle of a Read when the
821 // renegotiation process starts). So we complete the Read here.
822 if (!user_connect_callback_) {
823 CompletionCallback* c = user_read_callback_;
824 user_read_callback_ = NULL;
825 user_read_buf_ = NULL;
826 user_read_buf_len_ = 0;
827 c->Run(rv);
828 return;
829 }
830 net_log_.EndEvent(NetLog::TYPE_SSL_CONNECT, NULL);
831 CompletionCallback* c = user_connect_callback_;
832 user_connect_callback_ = NULL;
833 c->Run(rv);
834 }
835 }
836
OnReadComplete(int result)837 void SSLClientSocketWin::OnReadComplete(int result) {
838 DCHECK(completed_handshake());
839
840 result = DoPayloadReadComplete(result);
841 if (result > 0)
842 result = DoPayloadDecrypt();
843 if (result != ERR_IO_PENDING) {
844 DCHECK(user_read_callback_);
845 CompletionCallback* c = user_read_callback_;
846 user_read_callback_ = NULL;
847 user_read_buf_ = NULL;
848 user_read_buf_len_ = 0;
849 c->Run(result);
850 }
851 }
852
OnWriteComplete(int result)853 void SSLClientSocketWin::OnWriteComplete(int result) {
854 DCHECK(completed_handshake());
855
856 int rv = DoPayloadWriteComplete(result);
857 if (rv != ERR_IO_PENDING) {
858 DCHECK(user_write_callback_);
859 CompletionCallback* c = user_write_callback_;
860 user_write_callback_ = NULL;
861 user_write_buf_ = NULL;
862 user_write_buf_len_ = 0;
863 c->Run(rv);
864 }
865 }
866
867
DoLoop(int last_io_result)868 int SSLClientSocketWin::DoLoop(int last_io_result) {
869 DCHECK(next_state_ != STATE_NONE);
870 int rv = last_io_result;
871 do {
872 State state = next_state_;
873 next_state_ = STATE_NONE;
874 switch (state) {
875 case STATE_HANDSHAKE_READ:
876 rv = DoHandshakeRead();
877 break;
878 case STATE_HANDSHAKE_READ_COMPLETE:
879 rv = DoHandshakeReadComplete(rv);
880 break;
881 case STATE_HANDSHAKE_WRITE:
882 rv = DoHandshakeWrite();
883 break;
884 case STATE_HANDSHAKE_WRITE_COMPLETE:
885 rv = DoHandshakeWriteComplete(rv);
886 break;
887 case STATE_VERIFY_CERT:
888 rv = DoVerifyCert();
889 break;
890 case STATE_VERIFY_CERT_COMPLETE:
891 rv = DoVerifyCertComplete(rv);
892 break;
893 case STATE_COMPLETED_RENEGOTIATION:
894 rv = DoCompletedRenegotiation(rv);
895 break;
896 case STATE_COMPLETED_HANDSHAKE:
897 next_state_ = STATE_COMPLETED_HANDSHAKE;
898 // This is the end of our state machine, so return.
899 return rv;
900 default:
901 rv = ERR_UNEXPECTED;
902 LOG(DFATAL) << "unexpected state " << state;
903 break;
904 }
905 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE);
906 return rv;
907 }
908
DoHandshakeRead()909 int SSLClientSocketWin::DoHandshakeRead() {
910 next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
911
912 if (!recv_buffer_.get())
913 recv_buffer_.reset(new char[kRecvBufferSize]);
914
915 int buf_len = kRecvBufferSize - bytes_received_;
916
917 if (buf_len <= 0) {
918 LOG(DFATAL) << "Receive buffer is too small!";
919 return ERR_UNEXPECTED;
920 }
921
922 DCHECK(!transport_read_buf_);
923 transport_read_buf_ = new IOBuffer(buf_len);
924
925 return transport_->socket()->Read(transport_read_buf_, buf_len,
926 &handshake_io_callback_);
927 }
928
DoHandshakeReadComplete(int result)929 int SSLClientSocketWin::DoHandshakeReadComplete(int result) {
930 if (result < 0) {
931 transport_read_buf_ = NULL;
932 return result;
933 }
934
935 if (transport_read_buf_) {
936 // A transition to STATE_HANDSHAKE_READ_COMPLETE is set in multiple places,
937 // not only in DoHandshakeRead(), so we may not have a transport_read_buf_.
938 DCHECK_LE(result, kRecvBufferSize - bytes_received_);
939 char* buf = recv_buffer_.get() + bytes_received_;
940 memcpy(buf, transport_read_buf_->data(), result);
941 transport_read_buf_ = NULL;
942 }
943
944 if (result == 0 && !ignore_ok_result_)
945 return ERR_SSL_PROTOCOL_ERROR; // Incomplete response :(
946
947 ignore_ok_result_ = false;
948
949 bytes_received_ += result;
950
951 // Process the contents of recv_buffer_.
952 TimeStamp expiry;
953 DWORD out_flags;
954
955 DWORD flags = ISC_REQ_SEQUENCE_DETECT |
956 ISC_REQ_REPLAY_DETECT |
957 ISC_REQ_CONFIDENTIALITY |
958 ISC_RET_EXTENDED_ERROR |
959 ISC_REQ_ALLOCATE_MEMORY |
960 ISC_REQ_STREAM;
961
962 if (ssl_config_.send_client_cert)
963 flags |= ISC_REQ_USE_SUPPLIED_CREDS;
964
965 SecBufferDesc in_buffer_desc, out_buffer_desc;
966
967 in_buffer_desc.cBuffers = 2;
968 in_buffer_desc.pBuffers = in_buffers_;
969 in_buffer_desc.ulVersion = SECBUFFER_VERSION;
970
971 in_buffers_[0].pvBuffer = recv_buffer_.get();
972 in_buffers_[0].cbBuffer = bytes_received_;
973 in_buffers_[0].BufferType = SECBUFFER_TOKEN;
974
975 in_buffers_[1].pvBuffer = NULL;
976 in_buffers_[1].cbBuffer = 0;
977 in_buffers_[1].BufferType = SECBUFFER_EMPTY;
978
979 out_buffer_desc.cBuffers = 1;
980 out_buffer_desc.pBuffers = &send_buffer_;
981 out_buffer_desc.ulVersion = SECBUFFER_VERSION;
982
983 send_buffer_.pvBuffer = NULL;
984 send_buffer_.BufferType = SECBUFFER_TOKEN;
985 send_buffer_.cbBuffer = 0;
986
987 isc_status_ = InitializeSecurityContext(
988 creds_,
989 &ctxt_,
990 NULL,
991 flags,
992 0,
993 0,
994 &in_buffer_desc,
995 0,
996 NULL,
997 &out_buffer_desc,
998 &out_flags,
999 &expiry);
1000
1001 if (isc_status_ == SEC_E_INVALID_TOKEN) {
1002 // Peer sent us an SSL record type that's invalid during SSL handshake.
1003 // TODO(wtc): move this to MapSecurityError after sufficient testing.
1004 LOG(ERROR) << "InitializeSecurityContext failed: " << isc_status_;
1005 return ERR_SSL_PROTOCOL_ERROR;
1006 }
1007
1008 if (send_buffer_.cbBuffer != 0 &&
1009 (isc_status_ == SEC_E_OK ||
1010 isc_status_ == SEC_I_CONTINUE_NEEDED ||
1011 (FAILED(isc_status_) && (out_flags & ISC_RET_EXTENDED_ERROR)))) {
1012 next_state_ = STATE_HANDSHAKE_WRITE;
1013 return OK;
1014 }
1015 return DidCallInitializeSecurityContext();
1016 }
1017
DidCallInitializeSecurityContext()1018 int SSLClientSocketWin::DidCallInitializeSecurityContext() {
1019 if (isc_status_ == SEC_E_INCOMPLETE_MESSAGE) {
1020 next_state_ = STATE_HANDSHAKE_READ;
1021 return OK;
1022 }
1023
1024 if (isc_status_ == SEC_E_OK) {
1025 if (in_buffers_[1].BufferType == SECBUFFER_EXTRA) {
1026 // Save this data for later.
1027 memmove(recv_buffer_.get(),
1028 recv_buffer_.get() + (bytes_received_ - in_buffers_[1].cbBuffer),
1029 in_buffers_[1].cbBuffer);
1030 bytes_received_ = in_buffers_[1].cbBuffer;
1031 } else {
1032 bytes_received_ = 0;
1033 }
1034 return DidCompleteHandshake();
1035 }
1036
1037 if (FAILED(isc_status_)) {
1038 LOG(ERROR) << "InitializeSecurityContext failed: " << isc_status_;
1039 if (isc_status_ == SEC_E_INTERNAL_ERROR) {
1040 // "The Local Security Authority cannot be contacted". This happens
1041 // when the user denies access to the private key for SSL client auth.
1042 return ERR_SSL_CLIENT_AUTH_PRIVATE_KEY_ACCESS_DENIED;
1043 }
1044 int result = MapSecurityError(isc_status_);
1045 // We told Schannel to not verify the server certificate
1046 // (SCH_CRED_MANUAL_CRED_VALIDATION), so any certificate error returned by
1047 // InitializeSecurityContext must be referring to the bad or missing
1048 // client certificate.
1049 if (IsCertificateError(result)) {
1050 // TODO(wtc): Add fine-grained error codes for client certificate errors
1051 // reported by the server using the following SSL/TLS alert messages:
1052 // access_denied
1053 // bad_certificate
1054 // unsupported_certificate
1055 // certificate_expired
1056 // certificate_revoked
1057 // certificate_unknown
1058 // unknown_ca
1059 return ERR_BAD_SSL_CLIENT_AUTH_CERT;
1060 }
1061 return result;
1062 }
1063
1064 if (isc_status_ == SEC_I_INCOMPLETE_CREDENTIALS)
1065 return ERR_SSL_CLIENT_AUTH_CERT_NEEDED;
1066
1067 if (isc_status_ == SEC_I_NO_RENEGOTIATION) {
1068 // Received a no_renegotiation alert message. Although this is just a
1069 // warning, SChannel doesn't seem to allow us to continue after this
1070 // point, so we have to return an error. See http://crbug.com/36835.
1071 return ERR_SSL_NO_RENEGOTIATION;
1072 }
1073
1074 DCHECK(isc_status_ == SEC_I_CONTINUE_NEEDED);
1075 if (in_buffers_[1].BufferType == SECBUFFER_EXTRA) {
1076 memmove(recv_buffer_.get(),
1077 recv_buffer_.get() + (bytes_received_ - in_buffers_[1].cbBuffer),
1078 in_buffers_[1].cbBuffer);
1079 bytes_received_ = in_buffers_[1].cbBuffer;
1080 next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
1081 ignore_ok_result_ = true; // OK doesn't mean EOF.
1082 return OK;
1083 }
1084
1085 bytes_received_ = 0;
1086 next_state_ = STATE_HANDSHAKE_READ;
1087 return OK;
1088 }
1089
DoHandshakeWrite()1090 int SSLClientSocketWin::DoHandshakeWrite() {
1091 next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE;
1092
1093 // We should have something to send.
1094 DCHECK(send_buffer_.pvBuffer);
1095 DCHECK(send_buffer_.cbBuffer > 0);
1096 DCHECK(!transport_write_buf_);
1097
1098 const char* buf = static_cast<char*>(send_buffer_.pvBuffer) + bytes_sent_;
1099 int buf_len = send_buffer_.cbBuffer - bytes_sent_;
1100 transport_write_buf_ = new IOBuffer(buf_len);
1101 memcpy(transport_write_buf_->data(), buf, buf_len);
1102
1103 return transport_->socket()->Write(transport_write_buf_, buf_len,
1104 &handshake_io_callback_);
1105 }
1106
DoHandshakeWriteComplete(int result)1107 int SSLClientSocketWin::DoHandshakeWriteComplete(int result) {
1108 DCHECK(transport_write_buf_);
1109 transport_write_buf_ = NULL;
1110 if (result < 0)
1111 return result;
1112
1113 DCHECK(result != 0);
1114
1115 bytes_sent_ += result;
1116 DCHECK(bytes_sent_ <= static_cast<int>(send_buffer_.cbBuffer));
1117
1118 if (bytes_sent_ >= static_cast<int>(send_buffer_.cbBuffer)) {
1119 bool overflow = (bytes_sent_ > static_cast<int>(send_buffer_.cbBuffer));
1120 FreeSendBuffer();
1121 bytes_sent_ = 0;
1122 if (overflow) { // Bug!
1123 LOG(DFATAL) << "overflow";
1124 return ERR_UNEXPECTED;
1125 }
1126 if (writing_first_token_) {
1127 writing_first_token_ = false;
1128 DCHECK(bytes_received_ == 0);
1129 next_state_ = STATE_HANDSHAKE_READ;
1130 return OK;
1131 }
1132 return DidCallInitializeSecurityContext();
1133 }
1134
1135 // Send the remaining bytes.
1136 next_state_ = STATE_HANDSHAKE_WRITE;
1137 return OK;
1138 }
1139
1140 // Set server_cert_status_ and return OK or a network error.
DoVerifyCert()1141 int SSLClientSocketWin::DoVerifyCert() {
1142 next_state_ = STATE_VERIFY_CERT_COMPLETE;
1143
1144 DCHECK(server_cert_);
1145
1146 int flags = 0;
1147 if (ssl_config_.rev_checking_enabled)
1148 flags |= X509Certificate::VERIFY_REV_CHECKING_ENABLED;
1149 if (ssl_config_.verify_ev_cert)
1150 flags |= X509Certificate::VERIFY_EV_CERT;
1151 verifier_.reset(new SingleRequestCertVerifier(cert_verifier_));
1152 return verifier_->Verify(server_cert_, host_and_port_.host(), flags,
1153 &server_cert_verify_result_,
1154 &handshake_io_callback_);
1155 }
1156
DoVerifyCertComplete(int result)1157 int SSLClientSocketWin::DoVerifyCertComplete(int result) {
1158 DCHECK(verifier_.get());
1159 verifier_.reset();
1160
1161 // If we have been explicitly told to accept this certificate, override the
1162 // result of verifier_.Verify.
1163 // Eventually, we should cache the cert verification results so that we don't
1164 // need to call verifier_.Verify repeatedly. But for now we need to do this.
1165 // Alternatively, we could use the cert's status that we stored along with
1166 // the cert in the allowed_bad_certs vector.
1167 if (IsCertificateError(result) &&
1168 ssl_config_.IsAllowedBadCert(server_cert_))
1169 result = OK;
1170
1171 if (result == OK)
1172 LogConnectionTypeMetrics();
1173 if (renegotiating_) {
1174 DidCompleteRenegotiation();
1175 return result;
1176 }
1177
1178 // The initial handshake has completed.
1179 next_state_ = STATE_COMPLETED_HANDSHAKE;
1180 return result;
1181 }
1182
DoPayloadRead()1183 int SSLClientSocketWin::DoPayloadRead() {
1184 DCHECK(recv_buffer_.get());
1185
1186 int buf_len = kRecvBufferSize - bytes_received_;
1187
1188 if (buf_len <= 0) {
1189 NOTREACHED() << "Receive buffer is too small!";
1190 return ERR_FAILED;
1191 }
1192
1193 int rv;
1194 // If bytes_received_, we have some data from a previous read still ready
1195 // for decoding. Otherwise, we need to issue a real read.
1196 if (!bytes_received_ || need_more_data_) {
1197 DCHECK(!transport_read_buf_);
1198 transport_read_buf_ = new IOBuffer(buf_len);
1199
1200 rv = transport_->socket()->Read(transport_read_buf_, buf_len,
1201 &read_callback_);
1202 if (rv != ERR_IO_PENDING)
1203 rv = DoPayloadReadComplete(rv);
1204 if (rv <= 0)
1205 return rv;
1206 }
1207
1208 // Decode what we've read. If there is not enough data to decode yet,
1209 // this may return ERR_IO_PENDING still.
1210 return DoPayloadDecrypt();
1211 }
1212
1213 // result is the number of bytes that have been read; it should not be
1214 // less than zero; a value of zero means that no additional bytes have
1215 // been read.
DoPayloadReadComplete(int result)1216 int SSLClientSocketWin::DoPayloadReadComplete(int result) {
1217 DCHECK(completed_handshake());
1218
1219 // If IO Pending, there is nothing to do here.
1220 if (result == ERR_IO_PENDING)
1221 return result;
1222
1223 // We completed a Read, so reset the need_more_data_ flag.
1224 need_more_data_ = false;
1225
1226 // Check for error
1227 if (result <= 0) {
1228 transport_read_buf_ = NULL;
1229 if (result == 0 && bytes_received_ != 0) {
1230 // TODO(wtc): Unless we have received the close_notify alert, we need
1231 // to return an error code indicating that the SSL connection ended
1232 // uncleanly, a potential truncation attack. See
1233 // http://crbug.com/18586.
1234 return ERR_SSL_PROTOCOL_ERROR;
1235 }
1236 return result;
1237 }
1238
1239 // Transfer the data from transport_read_buf_ to recv_buffer_.
1240 if (transport_read_buf_) {
1241 DCHECK_LE(result, kRecvBufferSize - bytes_received_);
1242 char* buf = recv_buffer_.get() + bytes_received_;
1243 memcpy(buf, transport_read_buf_->data(), result);
1244 transport_read_buf_ = NULL;
1245 }
1246
1247 bytes_received_ += result;
1248
1249 return result;
1250 }
1251
DoPayloadDecrypt()1252 int SSLClientSocketWin::DoPayloadDecrypt() {
1253 // Process the contents of recv_buffer_.
1254 int len = 0; // the number of bytes we've copied to the user buffer.
1255 while (bytes_received_) {
1256 SecBuffer buffers[4];
1257 buffers[0].pvBuffer = recv_buffer_.get();
1258 buffers[0].cbBuffer = bytes_received_;
1259 buffers[0].BufferType = SECBUFFER_DATA;
1260
1261 buffers[1].BufferType = SECBUFFER_EMPTY;
1262 buffers[2].BufferType = SECBUFFER_EMPTY;
1263 buffers[3].BufferType = SECBUFFER_EMPTY;
1264
1265 SecBufferDesc buffer_desc;
1266 buffer_desc.cBuffers = 4;
1267 buffer_desc.pBuffers = buffers;
1268 buffer_desc.ulVersion = SECBUFFER_VERSION;
1269
1270 SECURITY_STATUS status;
1271 status = DecryptMessage(&ctxt_, &buffer_desc, 0, NULL);
1272
1273 if (status == SEC_E_INCOMPLETE_MESSAGE) {
1274 need_more_data_ = true;
1275 return DoPayloadRead();
1276 }
1277
1278 if (status == SEC_I_CONTEXT_EXPIRED) {
1279 // Received the close_notify alert.
1280 bytes_received_ = 0;
1281 return OK;
1282 }
1283
1284 if (status != SEC_E_OK && status != SEC_I_RENEGOTIATE) {
1285 DCHECK(status != SEC_E_MESSAGE_ALTERED);
1286 LOG(ERROR) << "DecryptMessage failed: " << status;
1287 return MapSecurityError(status);
1288 }
1289
1290 // The received ciphertext was decrypted in place in recv_buffer_. Remember
1291 // the location and length of the decrypted plaintext and any unused
1292 // ciphertext.
1293 decrypted_ptr_ = NULL;
1294 bytes_decrypted_ = 0;
1295 received_ptr_ = NULL;
1296 bytes_received_ = 0;
1297 for (int i = 1; i < 4; i++) {
1298 switch (buffers[i].BufferType) {
1299 case SECBUFFER_DATA:
1300 DCHECK(!decrypted_ptr_ && bytes_decrypted_ == 0);
1301 decrypted_ptr_ = static_cast<char*>(buffers[i].pvBuffer);
1302 bytes_decrypted_ = buffers[i].cbBuffer;
1303 break;
1304 case SECBUFFER_EXTRA:
1305 DCHECK(!received_ptr_ && bytes_received_ == 0);
1306 received_ptr_ = static_cast<char*>(buffers[i].pvBuffer);
1307 bytes_received_ = buffers[i].cbBuffer;
1308 break;
1309 default:
1310 break;
1311 }
1312 }
1313
1314 DCHECK(len == 0);
1315 if (bytes_decrypted_ != 0) {
1316 len = std::min(user_read_buf_len_, bytes_decrypted_);
1317 memcpy(user_read_buf_->data(), decrypted_ptr_, len);
1318 decrypted_ptr_ += len;
1319 bytes_decrypted_ -= len;
1320 }
1321 if (bytes_decrypted_ == 0) {
1322 decrypted_ptr_ = NULL;
1323 if (bytes_received_ != 0) {
1324 memmove(recv_buffer_.get(), received_ptr_, bytes_received_);
1325 received_ptr_ = recv_buffer_.get();
1326 }
1327 }
1328
1329 if (status == SEC_I_RENEGOTIATE) {
1330 if (bytes_received_ != 0) {
1331 // The server requested renegotiation, but there are some data yet to
1332 // be decrypted. The Platform SDK WebClient.c sample doesn't handle
1333 // this, so we don't know how to handle this. Assume this cannot
1334 // happen.
1335 LOG(ERROR) << "DecryptMessage returned SEC_I_RENEGOTIATE with a buffer "
1336 << "of type SECBUFFER_EXTRA.";
1337 return ERR_SSL_RENEGOTIATION_REQUESTED;
1338 }
1339 if (len != 0) {
1340 // The server requested renegotiation, but there are some decrypted
1341 // data. We can't start renegotiation until we have returned all
1342 // decrypted data to the caller.
1343 //
1344 // This hasn't happened during testing. Assume this cannot happen even
1345 // though we know how to handle this.
1346 LOG(ERROR) << "DecryptMessage returned SEC_I_RENEGOTIATE with a buffer "
1347 << "of type SECBUFFER_DATA.";
1348 return ERR_SSL_RENEGOTIATION_REQUESTED;
1349 }
1350 // Jump to the handshake sequence. Will come back when the rehandshake is
1351 // done.
1352 renegotiating_ = true;
1353 ignore_ok_result_ = true; // OK doesn't mean EOF.
1354 // If renegotiation handshake occurred, we need to go back into the
1355 // handshake state machine.
1356 next_state_ = STATE_HANDSHAKE_READ_COMPLETE;
1357 return DoLoop(OK);
1358 }
1359
1360 // We've already copied data into the user buffer, so quit now.
1361 // TODO(mbelshe): We really should keep decoding as long as we can. This
1362 // break out is causing us to return pretty small chunks of data up to the
1363 // application, even though more is already buffered and ready to be
1364 // decoded.
1365 if (len)
1366 break;
1367 }
1368
1369 // If we decrypted 0 bytes, don't report 0 bytes read, which would be
1370 // mistaken for EOF. Continue decrypting or read more.
1371 if (len == 0)
1372 return DoPayloadRead();
1373 return len;
1374 }
1375
DoPayloadEncrypt()1376 int SSLClientSocketWin::DoPayloadEncrypt() {
1377 DCHECK(completed_handshake());
1378 DCHECK(user_write_buf_);
1379 DCHECK(user_write_buf_len_ > 0);
1380
1381 ULONG message_len = std::min(
1382 stream_sizes_.cbMaximumMessage, static_cast<ULONG>(user_write_buf_len_));
1383 ULONG alloc_len =
1384 message_len + stream_sizes_.cbHeader + stream_sizes_.cbTrailer;
1385 user_write_buf_len_ = message_len;
1386
1387 payload_send_buffer_.reset(new char[alloc_len]);
1388 memcpy(&payload_send_buffer_[stream_sizes_.cbHeader],
1389 user_write_buf_->data(), message_len);
1390
1391 SecBuffer buffers[4];
1392 buffers[0].pvBuffer = payload_send_buffer_.get();
1393 buffers[0].cbBuffer = stream_sizes_.cbHeader;
1394 buffers[0].BufferType = SECBUFFER_STREAM_HEADER;
1395
1396 buffers[1].pvBuffer = &payload_send_buffer_[stream_sizes_.cbHeader];
1397 buffers[1].cbBuffer = message_len;
1398 buffers[1].BufferType = SECBUFFER_DATA;
1399
1400 buffers[2].pvBuffer = &payload_send_buffer_[stream_sizes_.cbHeader +
1401 message_len];
1402 buffers[2].cbBuffer = stream_sizes_.cbTrailer;
1403 buffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
1404
1405 buffers[3].BufferType = SECBUFFER_EMPTY;
1406
1407 SecBufferDesc buffer_desc;
1408 buffer_desc.cBuffers = 4;
1409 buffer_desc.pBuffers = buffers;
1410 buffer_desc.ulVersion = SECBUFFER_VERSION;
1411
1412 SECURITY_STATUS status = EncryptMessage(&ctxt_, 0, &buffer_desc, 0);
1413
1414 if (FAILED(status)) {
1415 LOG(ERROR) << "EncryptMessage failed: " << status;
1416 return MapSecurityError(status);
1417 }
1418
1419 payload_send_buffer_len_ = buffers[0].cbBuffer +
1420 buffers[1].cbBuffer +
1421 buffers[2].cbBuffer;
1422 DCHECK(bytes_sent_ == 0);
1423 return OK;
1424 }
1425
DoPayloadWrite()1426 int SSLClientSocketWin::DoPayloadWrite() {
1427 DCHECK(completed_handshake());
1428
1429 // We should have something to send.
1430 DCHECK(payload_send_buffer_.get());
1431 DCHECK(payload_send_buffer_len_ > 0);
1432 DCHECK(!transport_write_buf_);
1433
1434 const char* buf = payload_send_buffer_.get() + bytes_sent_;
1435 int buf_len = payload_send_buffer_len_ - bytes_sent_;
1436 transport_write_buf_ = new IOBuffer(buf_len);
1437 memcpy(transport_write_buf_->data(), buf, buf_len);
1438
1439 int rv = transport_->socket()->Write(transport_write_buf_, buf_len,
1440 &write_callback_);
1441 if (rv != ERR_IO_PENDING)
1442 rv = DoPayloadWriteComplete(rv);
1443 return rv;
1444 }
1445
DoPayloadWriteComplete(int result)1446 int SSLClientSocketWin::DoPayloadWriteComplete(int result) {
1447 DCHECK(transport_write_buf_);
1448 transport_write_buf_ = NULL;
1449 if (result < 0)
1450 return result;
1451
1452 DCHECK(result != 0);
1453
1454 bytes_sent_ += result;
1455 DCHECK(bytes_sent_ <= payload_send_buffer_len_);
1456
1457 if (bytes_sent_ >= payload_send_buffer_len_) {
1458 bool overflow = (bytes_sent_ > payload_send_buffer_len_);
1459 payload_send_buffer_.reset();
1460 payload_send_buffer_len_ = 0;
1461 bytes_sent_ = 0;
1462 if (overflow) { // Bug!
1463 LOG(DFATAL) << "overflow";
1464 return ERR_UNEXPECTED;
1465 }
1466 // Done
1467 return user_write_buf_len_;
1468 }
1469
1470 // Send the remaining bytes.
1471 return DoPayloadWrite();
1472 }
1473
DoCompletedRenegotiation(int result)1474 int SSLClientSocketWin::DoCompletedRenegotiation(int result) {
1475 // The user had a read in progress, which was usurped by the renegotiation.
1476 // Restart the read sequence.
1477 next_state_ = STATE_COMPLETED_HANDSHAKE;
1478 if (result != OK)
1479 return result;
1480 return DoPayloadRead();
1481 }
1482
DidCompleteHandshake()1483 int SSLClientSocketWin::DidCompleteHandshake() {
1484 SECURITY_STATUS status = QueryContextAttributes(
1485 &ctxt_, SECPKG_ATTR_STREAM_SIZES, &stream_sizes_);
1486 if (status != SEC_E_OK) {
1487 LOG(ERROR) << "QueryContextAttributes (stream sizes) failed: " << status;
1488 return MapSecurityError(status);
1489 }
1490 DCHECK(!server_cert_ || renegotiating_);
1491 PCCERT_CONTEXT server_cert_handle = NULL;
1492 status = QueryContextAttributes(
1493 &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_handle);
1494 if (status != SEC_E_OK) {
1495 LOG(ERROR) << "QueryContextAttributes (remote cert) failed: " << status;
1496 return MapSecurityError(status);
1497 }
1498 if (renegotiating_ &&
1499 X509Certificate::IsSameOSCert(server_cert_->os_cert_handle(),
1500 server_cert_handle)) {
1501 // We already verified the server certificate. Either it is good or the
1502 // user has accepted the certificate error.
1503 DidCompleteRenegotiation();
1504 } else {
1505 server_cert_ = X509Certificate::CreateFromHandle(
1506 server_cert_handle, X509Certificate::SOURCE_FROM_NETWORK,
1507 X509Certificate::OSCertHandles());
1508
1509 next_state_ = STATE_VERIFY_CERT;
1510 }
1511 CertFreeCertificateContext(server_cert_handle);
1512 return OK;
1513 }
1514
1515 // Called when a renegotiation is completed. |result| is the verification
1516 // result of the server certificate received during renegotiation.
DidCompleteRenegotiation()1517 void SSLClientSocketWin::DidCompleteRenegotiation() {
1518 DCHECK(!user_connect_callback_);
1519 DCHECK(user_read_callback_);
1520 renegotiating_ = false;
1521 next_state_ = STATE_COMPLETED_RENEGOTIATION;
1522 }
1523
LogConnectionTypeMetrics() const1524 void SSLClientSocketWin::LogConnectionTypeMetrics() const {
1525 UpdateConnectionTypeHistograms(CONNECTION_SSL);
1526 if (server_cert_verify_result_.has_md5)
1527 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5);
1528 if (server_cert_verify_result_.has_md2)
1529 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2);
1530 if (server_cert_verify_result_.has_md4)
1531 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4);
1532 if (server_cert_verify_result_.has_md5_ca)
1533 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA);
1534 if (server_cert_verify_result_.has_md2_ca)
1535 UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA);
1536 }
1537
FreeSendBuffer()1538 void SSLClientSocketWin::FreeSendBuffer() {
1539 SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer);
1540 DCHECK(status == SEC_E_OK);
1541 memset(&send_buffer_, 0, sizeof(send_buffer_));
1542 }
1543
1544 } // namespace net
1545