| OLD | NEW | 
 | (Empty) | 
|     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 |  | 
|     3 // found in the LICENSE file. |  | 
|     4  |  | 
|     5 #include "net/base/ssl_client_socket_win.h" |  | 
|     6  |  | 
|     7 #include <schnlsp.h> |  | 
|     8  |  | 
|     9 #include "base/lock.h" |  | 
|    10 #include "base/singleton.h" |  | 
|    11 #include "base/stl_util-inl.h" |  | 
|    12 #include "base/string_util.h" |  | 
|    13 #include "net/base/connection_type_histograms.h" |  | 
|    14 #include "net/base/io_buffer.h" |  | 
|    15 #include "net/base/net_errors.h" |  | 
|    16 #include "net/base/ssl_cert_request_info.h" |  | 
|    17 #include "net/base/ssl_info.h" |  | 
|    18  |  | 
|    19 #pragma comment(lib, "secur32.lib") |  | 
|    20  |  | 
|    21 namespace net { |  | 
|    22  |  | 
|    23 //----------------------------------------------------------------------------- |  | 
|    24  |  | 
|    25 // TODO(wtc): See http://msdn.microsoft.com/en-us/library/aa377188(VS.85).aspx |  | 
|    26 // for the other error codes we may need to map. |  | 
|    27 static int MapSecurityError(SECURITY_STATUS err) { |  | 
|    28   // There are numerous security error codes, but these are the ones we thus |  | 
|    29   // far find interesting. |  | 
|    30   switch (err) { |  | 
|    31     case SEC_E_WRONG_PRINCIPAL:  // Schannel |  | 
|    32     case CERT_E_CN_NO_MATCH:  // CryptoAPI |  | 
|    33       return ERR_CERT_COMMON_NAME_INVALID; |  | 
|    34     case SEC_E_UNTRUSTED_ROOT:  // Schannel |  | 
|    35     case CERT_E_UNTRUSTEDROOT:  // CryptoAPI |  | 
|    36       return ERR_CERT_AUTHORITY_INVALID; |  | 
|    37     case SEC_E_CERT_EXPIRED:  // Schannel |  | 
|    38     case CERT_E_EXPIRED:  // CryptoAPI |  | 
|    39       return ERR_CERT_DATE_INVALID; |  | 
|    40     case CRYPT_E_NO_REVOCATION_CHECK: |  | 
|    41       return ERR_CERT_NO_REVOCATION_MECHANISM; |  | 
|    42     case CRYPT_E_REVOCATION_OFFLINE: |  | 
|    43       return ERR_CERT_UNABLE_TO_CHECK_REVOCATION; |  | 
|    44     case CRYPT_E_REVOKED:  // Schannel and CryptoAPI |  | 
|    45       return ERR_CERT_REVOKED; |  | 
|    46     case SEC_E_CERT_UNKNOWN: |  | 
|    47     case CERT_E_ROLE: |  | 
|    48       return ERR_CERT_INVALID; |  | 
|    49     // We received an unexpected_message or illegal_parameter alert message |  | 
|    50     // from the server. |  | 
|    51     case SEC_E_ILLEGAL_MESSAGE: |  | 
|    52       return ERR_SSL_PROTOCOL_ERROR; |  | 
|    53     case SEC_E_ALGORITHM_MISMATCH: |  | 
|    54       return ERR_SSL_VERSION_OR_CIPHER_MISMATCH; |  | 
|    55     case SEC_E_INVALID_HANDLE: |  | 
|    56       return ERR_UNEXPECTED; |  | 
|    57     case SEC_E_OK: |  | 
|    58       return OK; |  | 
|    59     default: |  | 
|    60       LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED"; |  | 
|    61       return ERR_FAILED; |  | 
|    62   } |  | 
|    63 } |  | 
|    64  |  | 
|    65 // Returns true if the two CERT_CONTEXTs contain the same certificate. |  | 
|    66 bool SameCert(PCCERT_CONTEXT a, PCCERT_CONTEXT b) { |  | 
|    67   return a == b || |  | 
|    68          (a->cbCertEncoded == b->cbCertEncoded && |  | 
|    69          memcmp(a->pbCertEncoded, b->pbCertEncoded, b->cbCertEncoded) == 0); |  | 
|    70 } |  | 
|    71  |  | 
|    72 //----------------------------------------------------------------------------- |  | 
|    73  |  | 
|    74 // A bitmask consisting of these bit flags encodes which versions of the SSL |  | 
|    75 // protocol (SSL 2.0, SSL 3.0, and TLS 1.0) are enabled. |  | 
|    76 enum { |  | 
|    77   SSL2 = 1 << 0, |  | 
|    78   SSL3 = 1 << 1, |  | 
|    79   TLS1 = 1 << 2, |  | 
|    80   SSL_VERSION_MASKS = 1 << 3  // The number of SSL version bitmasks. |  | 
|    81 }; |  | 
|    82  |  | 
|    83 // CredHandleClass simply gives a default constructor and a destructor to |  | 
|    84 // SSPI's CredHandle type (a C struct). |  | 
|    85 class CredHandleClass : public CredHandle { |  | 
|    86  public: |  | 
|    87   CredHandleClass() { |  | 
|    88     dwLower = 0; |  | 
|    89     dwUpper = 0; |  | 
|    90   } |  | 
|    91  |  | 
|    92   ~CredHandleClass() { |  | 
|    93     if (dwLower || dwUpper) { |  | 
|    94       SECURITY_STATUS status = FreeCredentialsHandle(this); |  | 
|    95       DCHECK(status == SEC_E_OK); |  | 
|    96     } |  | 
|    97   } |  | 
|    98 }; |  | 
|    99  |  | 
|   100 // A table of CredHandles. |  | 
|   101 class CredHandleTable { |  | 
|   102  public: |  | 
|   103   CredHandleTable() {} |  | 
|   104  |  | 
|   105   ~CredHandleTable() { |  | 
|   106     STLDeleteContainerPairSecondPointers(client_cert_creds_.begin(), |  | 
|   107                                          client_cert_creds_.end()); |  | 
|   108   } |  | 
|   109  |  | 
|   110   CredHandle* GetHandle(PCCERT_CONTEXT client_cert, int ssl_version_mask) { |  | 
|   111     DCHECK(0 < ssl_version_mask && |  | 
|   112            ssl_version_mask < arraysize(anonymous_creds_)); |  | 
|   113     CredHandleClass* handle; |  | 
|   114     AutoLock lock(lock_); |  | 
|   115     if (client_cert) { |  | 
|   116       CredHandleMapKey key = std::make_pair(client_cert, ssl_version_mask); |  | 
|   117       CredHandleMap::const_iterator it = client_cert_creds_.find(key); |  | 
|   118       if (it == client_cert_creds_.end()) { |  | 
|   119         handle = new CredHandleClass; |  | 
|   120         client_cert_creds_[key] = handle; |  | 
|   121       } else { |  | 
|   122         handle = it->second; |  | 
|   123       } |  | 
|   124     } else { |  | 
|   125       handle = &anonymous_creds_[ssl_version_mask]; |  | 
|   126     } |  | 
|   127     if (!handle->dwLower && !handle->dwUpper) |  | 
|   128       InitializeHandle(handle, client_cert, ssl_version_mask); |  | 
|   129     return handle; |  | 
|   130   } |  | 
|   131  |  | 
|   132  private: |  | 
|   133   // CredHandleMapKey is a std::pair consisting of these two components: |  | 
|   134   //   PCCERT_CONTEXT client_cert |  | 
|   135   //   int ssl_version_mask |  | 
|   136   typedef std::pair<PCCERT_CONTEXT, int> CredHandleMapKey; |  | 
|   137  |  | 
|   138   typedef std::map<CredHandleMapKey, CredHandleClass*> CredHandleMap; |  | 
|   139  |  | 
|   140   static void InitializeHandle(CredHandle* handle, |  | 
|   141                                PCCERT_CONTEXT client_cert, |  | 
|   142                                int ssl_version_mask); |  | 
|   143  |  | 
|   144   Lock lock_; |  | 
|   145  |  | 
|   146   // Anonymous (no client certificate) CredHandles for all possible |  | 
|   147   // combinations of SSL versions.  Defined as an array for fast lookup. |  | 
|   148   CredHandleClass anonymous_creds_[SSL_VERSION_MASKS]; |  | 
|   149  |  | 
|   150   // CredHandles that use a client certificate. |  | 
|   151   CredHandleMap client_cert_creds_; |  | 
|   152 }; |  | 
|   153  |  | 
|   154 // static |  | 
|   155 void CredHandleTable::InitializeHandle(CredHandle* handle, |  | 
|   156                                        PCCERT_CONTEXT client_cert, |  | 
|   157                                        int ssl_version_mask) { |  | 
|   158   SCHANNEL_CRED schannel_cred = {0}; |  | 
|   159   schannel_cred.dwVersion = SCHANNEL_CRED_VERSION; |  | 
|   160   if (client_cert) { |  | 
|   161     schannel_cred.cCreds = 1; |  | 
|   162     schannel_cred.paCred = &client_cert; |  | 
|   163     // Schannel will make its own copy of client_cert. |  | 
|   164   } |  | 
|   165  |  | 
|   166   // The global system registry settings take precedence over the value of |  | 
|   167   // schannel_cred.grbitEnabledProtocols. |  | 
|   168   schannel_cred.grbitEnabledProtocols = 0; |  | 
|   169   if (ssl_version_mask & SSL2) |  | 
|   170     schannel_cred.grbitEnabledProtocols |= SP_PROT_SSL2; |  | 
|   171   if (ssl_version_mask & SSL3) |  | 
|   172     schannel_cred.grbitEnabledProtocols |= SP_PROT_SSL3; |  | 
|   173   if (ssl_version_mask & TLS1) |  | 
|   174     schannel_cred.grbitEnabledProtocols |= SP_PROT_TLS1; |  | 
|   175  |  | 
|   176   // The default session lifetime is 36000000 milliseconds (ten hours).  Set |  | 
|   177   // schannel_cred.dwSessionLifespan to change the number of milliseconds that |  | 
|   178   // Schannel keeps the session in its session cache. |  | 
|   179  |  | 
|   180   // We can set the key exchange algorithms (RSA or DH) in |  | 
|   181   // schannel_cred.{cSupportedAlgs,palgSupportedAlgs}. |  | 
|   182  |  | 
|   183   // Although SCH_CRED_AUTO_CRED_VALIDATION is convenient, we have to use |  | 
|   184   // SCH_CRED_MANUAL_CRED_VALIDATION for three reasons. |  | 
|   185   // 1. SCH_CRED_AUTO_CRED_VALIDATION doesn't allow us to get the certificate |  | 
|   186   //    context if the certificate validation fails. |  | 
|   187   // 2. SCH_CRED_AUTO_CRED_VALIDATION returns only one error even if the |  | 
|   188   //    certificate has multiple errors. |  | 
|   189   // 3. SCH_CRED_AUTO_CRED_VALIDATION doesn't allow us to ignore untrusted CA |  | 
|   190   //    and expired certificate errors.  There are only flags to ignore the |  | 
|   191   //    name mismatch and unable-to-check-revocation errors. |  | 
|   192   // |  | 
|   193   // TODO(wtc): Look into undocumented or poorly documented flags: |  | 
|   194   //   SCH_CRED_RESTRICTED_ROOTS |  | 
|   195   //   SCH_CRED_REVOCATION_CHECK_CACHE_ONLY |  | 
|   196   //   SCH_CRED_CACHE_ONLY_URL_RETRIEVAL |  | 
|   197   //   SCH_CRED_MEMORY_STORE_CERT |  | 
|   198   schannel_cred.dwFlags |= SCH_CRED_NO_DEFAULT_CREDS | |  | 
|   199                            SCH_CRED_MANUAL_CRED_VALIDATION; |  | 
|   200   TimeStamp expiry; |  | 
|   201   SECURITY_STATUS status; |  | 
|   202  |  | 
|   203   status = AcquireCredentialsHandle( |  | 
|   204       NULL,  // Not used |  | 
|   205       UNISP_NAME,  // Microsoft Unified Security Protocol Provider |  | 
|   206       SECPKG_CRED_OUTBOUND, |  | 
|   207       NULL,  // Not used |  | 
|   208       &schannel_cred, |  | 
|   209       NULL,  // Not used |  | 
|   210       NULL,  // Not used |  | 
|   211       handle, |  | 
|   212       &expiry);  // Optional |  | 
|   213   if (status != SEC_E_OK) { |  | 
|   214     DLOG(ERROR) << "AcquireCredentialsHandle failed: " << status; |  | 
|   215     // GetHandle will return a pointer to an uninitialized CredHandle, which |  | 
|   216     // will cause InitializeSecurityContext to fail with SEC_E_INVALID_HANDLE. |  | 
|   217   } |  | 
|   218 } |  | 
|   219  |  | 
|   220 // For the SSL sockets to share SSL sessions by session resumption handshakes, |  | 
|   221 // they need to use the same CredHandle.  The GetCredHandle function creates |  | 
|   222 // and returns a shared CredHandle. |  | 
|   223 // |  | 
|   224 // The versions of the SSL protocol enabled are a property of the CredHandle. |  | 
|   225 // So we need a separate CredHandle for each combination of SSL versions. |  | 
|   226 // Most of the time Chromium will use only one or two combinations of SSL |  | 
|   227 // versions (for example, SSL3 | TLS1 for normal use, plus SSL3 when visiting |  | 
|   228 // TLS-intolerant servers).  These CredHandles are initialized only when |  | 
|   229 // needed. |  | 
|   230  |  | 
|   231 static CredHandle* GetCredHandle(PCCERT_CONTEXT client_cert, |  | 
|   232                                  int ssl_version_mask) { |  | 
|   233   // It doesn't matter whether GetCredHandle returns NULL or a pointer to an |  | 
|   234   // uninitialized CredHandle on failure.  Both of them cause |  | 
|   235   // InitializeSecurityContext to fail with SEC_E_INVALID_HANDLE. |  | 
|   236   if (ssl_version_mask <= 0 || ssl_version_mask >= SSL_VERSION_MASKS) { |  | 
|   237     NOTREACHED(); |  | 
|   238     return NULL; |  | 
|   239   } |  | 
|   240   return Singleton<CredHandleTable>::get()->GetHandle(client_cert, |  | 
|   241                                                       ssl_version_mask); |  | 
|   242 } |  | 
|   243  |  | 
|   244 //----------------------------------------------------------------------------- |  | 
|   245  |  | 
|   246 // A memory certificate store for client certificates.  This allows us to |  | 
|   247 // close the "MY" system certificate store when we finish searching for |  | 
|   248 // client certificates. |  | 
|   249 class ClientCertStore { |  | 
|   250  public: |  | 
|   251   ClientCertStore() { |  | 
|   252     store_ = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, NULL, 0, NULL); |  | 
|   253   } |  | 
|   254  |  | 
|   255   ~ClientCertStore() { |  | 
|   256     if (store_) { |  | 
|   257       BOOL ok = CertCloseStore(store_, CERT_CLOSE_STORE_CHECK_FLAG); |  | 
|   258       DCHECK(ok); |  | 
|   259     } |  | 
|   260   } |  | 
|   261  |  | 
|   262   PCCERT_CONTEXT CopyCertContext(PCCERT_CONTEXT client_cert) { |  | 
|   263     PCCERT_CONTEXT copy; |  | 
|   264     BOOL ok = CertAddCertificateContextToStore(store_, client_cert, |  | 
|   265                                                CERT_STORE_ADD_USE_EXISTING, |  | 
|   266                                                ©); |  | 
|   267     DCHECK(ok); |  | 
|   268     return ok ? copy : NULL; |  | 
|   269   } |  | 
|   270  |  | 
|   271  private: |  | 
|   272   HCERTSTORE store_; |  | 
|   273 }; |  | 
|   274  |  | 
|   275 //----------------------------------------------------------------------------- |  | 
|   276  |  | 
|   277 // Size of recv_buffer_ |  | 
|   278 // |  | 
|   279 // Ciphertext is decrypted one SSL record at a time, so recv_buffer_ needs to |  | 
|   280 // have room for a full SSL record, with the header and trailer.  Here is the |  | 
|   281 // breakdown of the size: |  | 
|   282 //   5: SSL record header |  | 
|   283 //   16K: SSL record maximum size |  | 
|   284 //   64: >= SSL record trailer (16 or 20 have been observed) |  | 
|   285 static const int kRecvBufferSize = (5 + 16*1024 + 64); |  | 
|   286  |  | 
|   287 SSLClientSocketWin::SSLClientSocketWin(ClientSocket* transport_socket, |  | 
|   288                                        const std::string& hostname, |  | 
|   289                                        const SSLConfig& ssl_config) |  | 
|   290 #pragma warning(suppress: 4355) |  | 
|   291     : io_callback_(this, &SSLClientSocketWin::OnIOComplete), |  | 
|   292       transport_(transport_socket), |  | 
|   293       hostname_(hostname), |  | 
|   294       ssl_config_(ssl_config), |  | 
|   295       user_callback_(NULL), |  | 
|   296       user_buf_len_(0), |  | 
|   297       next_state_(STATE_NONE), |  | 
|   298       creds_(NULL), |  | 
|   299       isc_status_(SEC_E_OK), |  | 
|   300       payload_send_buffer_len_(0), |  | 
|   301       bytes_sent_(0), |  | 
|   302       decrypted_ptr_(NULL), |  | 
|   303       bytes_decrypted_(0), |  | 
|   304       received_ptr_(NULL), |  | 
|   305       bytes_received_(0), |  | 
|   306       writing_first_token_(false), |  | 
|   307       completed_handshake_(false), |  | 
|   308       ignore_ok_result_(false), |  | 
|   309       renegotiating_(false) { |  | 
|   310   memset(&stream_sizes_, 0, sizeof(stream_sizes_)); |  | 
|   311   memset(in_buffers_, 0, sizeof(in_buffers_)); |  | 
|   312   memset(&send_buffer_, 0, sizeof(send_buffer_)); |  | 
|   313   memset(&ctxt_, 0, sizeof(ctxt_)); |  | 
|   314 } |  | 
|   315  |  | 
|   316 SSLClientSocketWin::~SSLClientSocketWin() { |  | 
|   317   Disconnect(); |  | 
|   318 } |  | 
|   319  |  | 
|   320 void SSLClientSocketWin::GetSSLInfo(SSLInfo* ssl_info) { |  | 
|   321   if (!server_cert_) |  | 
|   322     return; |  | 
|   323  |  | 
|   324   ssl_info->cert = server_cert_; |  | 
|   325   ssl_info->cert_status = server_cert_verify_result_.cert_status; |  | 
|   326   SecPkgContext_ConnectionInfo connection_info; |  | 
|   327   SECURITY_STATUS status = QueryContextAttributes( |  | 
|   328       &ctxt_, SECPKG_ATTR_CONNECTION_INFO, &connection_info); |  | 
|   329   if (status == SEC_E_OK) { |  | 
|   330     // TODO(wtc): compute the overall security strength, taking into account |  | 
|   331     // dwExchStrength and dwHashStrength.  dwExchStrength needs to be |  | 
|   332     // normalized. |  | 
|   333     ssl_info->security_bits = connection_info.dwCipherStrength; |  | 
|   334   } |  | 
|   335 } |  | 
|   336  |  | 
|   337 void SSLClientSocketWin::GetSSLCertRequestInfo( |  | 
|   338     SSLCertRequestInfo* cert_request_info) { |  | 
|   339   cert_request_info->host_and_port = hostname_;  // TODO(wtc): no port! |  | 
|   340   cert_request_info->client_certs.clear(); |  | 
|   341  |  | 
|   342   // Get the certificate_authorities field of the CertificateRequest message. |  | 
|   343   // Schannel doesn't return the certificate_types field of the |  | 
|   344   // CertificateRequest message to us, so we can't filter the client |  | 
|   345   // certificates properly. :-( |  | 
|   346   SecPkgContext_IssuerListInfoEx issuer_list; |  | 
|   347   SECURITY_STATUS status = QueryContextAttributes( |  | 
|   348       &ctxt_, SECPKG_ATTR_ISSUER_LIST_EX, &issuer_list); |  | 
|   349   if (status != SEC_E_OK) { |  | 
|   350     DLOG(ERROR) << "QueryContextAttributes (issuer list) failed: " << status; |  | 
|   351     return; |  | 
|   352   } |  | 
|   353  |  | 
|   354   // Client certificates of the user are in the "MY" system certificate store. |  | 
|   355   HCERTSTORE my_cert_store = CertOpenSystemStore(NULL, L"MY"); |  | 
|   356   if (!my_cert_store) { |  | 
|   357     FreeContextBuffer(issuer_list.aIssuers); |  | 
|   358     return; |  | 
|   359   } |  | 
|   360  |  | 
|   361   // Enumerate the client certificates. |  | 
|   362   CERT_CHAIN_FIND_BY_ISSUER_PARA find_by_issuer_para; |  | 
|   363   memset(&find_by_issuer_para, 0, sizeof(find_by_issuer_para)); |  | 
|   364   find_by_issuer_para.cbSize = sizeof(find_by_issuer_para); |  | 
|   365   find_by_issuer_para.pszUsageIdentifier = szOID_PKIX_KP_CLIENT_AUTH; |  | 
|   366   find_by_issuer_para.cIssuer = issuer_list.cIssuers; |  | 
|   367   find_by_issuer_para.rgIssuer = issuer_list.aIssuers; |  | 
|   368  |  | 
|   369   PCCERT_CHAIN_CONTEXT chain_context = NULL; |  | 
|   370  |  | 
|   371   for (;;) { |  | 
|   372     // Find a certificate chain. |  | 
|   373     chain_context = CertFindChainInStore(my_cert_store, |  | 
|   374                                          X509_ASN_ENCODING, |  | 
|   375                                          0, |  | 
|   376                                          CERT_CHAIN_FIND_BY_ISSUER, |  | 
|   377                                          &find_by_issuer_para, |  | 
|   378                                          chain_context); |  | 
|   379     if (!chain_context) { |  | 
|   380       DWORD err = GetLastError(); |  | 
|   381       if (err != CRYPT_E_NOT_FOUND) |  | 
|   382         DLOG(ERROR) << "CertFindChainInStore failed: " << err; |  | 
|   383       break; |  | 
|   384     } |  | 
|   385  |  | 
|   386     // Get the leaf certificate. |  | 
|   387     PCCERT_CONTEXT cert_context = |  | 
|   388         chain_context->rgpChain[0]->rgpElement[0]->pCertContext; |  | 
|   389     // Copy it to our own certificate store, so that we can close the "MY" |  | 
|   390     // certificate store before returning from this function. |  | 
|   391     PCCERT_CONTEXT cert_context2 = |  | 
|   392         Singleton<ClientCertStore>::get()->CopyCertContext(cert_context); |  | 
|   393     if (!cert_context2) { |  | 
|   394       NOTREACHED(); |  | 
|   395       continue; |  | 
|   396     } |  | 
|   397     scoped_refptr<X509Certificate> cert = X509Certificate::CreateFromHandle( |  | 
|   398         cert_context2, X509Certificate::SOURCE_LONE_CERT_IMPORT); |  | 
|   399     cert_request_info->client_certs.push_back(cert); |  | 
|   400   } |  | 
|   401  |  | 
|   402   FreeContextBuffer(issuer_list.aIssuers); |  | 
|   403  |  | 
|   404   BOOL ok = CertCloseStore(my_cert_store, CERT_CLOSE_STORE_CHECK_FLAG); |  | 
|   405   DCHECK(ok); |  | 
|   406 } |  | 
|   407  |  | 
|   408 int SSLClientSocketWin::Connect(CompletionCallback* callback) { |  | 
|   409   DCHECK(transport_.get()); |  | 
|   410   DCHECK(next_state_ == STATE_NONE); |  | 
|   411   DCHECK(!user_callback_); |  | 
|   412  |  | 
|   413   int ssl_version_mask = 0; |  | 
|   414   if (ssl_config_.ssl2_enabled) |  | 
|   415     ssl_version_mask |= SSL2; |  | 
|   416   if (ssl_config_.ssl3_enabled) |  | 
|   417     ssl_version_mask |= SSL3; |  | 
|   418   if (ssl_config_.tls1_enabled) |  | 
|   419     ssl_version_mask |= TLS1; |  | 
|   420   // If we pass 0 to GetCredHandle, we will let Schannel select the protocols, |  | 
|   421   // rather than enabling no protocols.  So we have to fail here. |  | 
|   422   if (ssl_version_mask == 0) |  | 
|   423     return ERR_NO_SSL_VERSIONS_ENABLED; |  | 
|   424   PCCERT_CONTEXT cert_context = NULL; |  | 
|   425   if (ssl_config_.client_cert) |  | 
|   426     cert_context = ssl_config_.client_cert->os_cert_handle(); |  | 
|   427   creds_ = GetCredHandle(cert_context, ssl_version_mask); |  | 
|   428  |  | 
|   429   memset(&ctxt_, 0, sizeof(ctxt_)); |  | 
|   430  |  | 
|   431   SecBufferDesc buffer_desc; |  | 
|   432   DWORD out_flags; |  | 
|   433   DWORD flags = ISC_REQ_SEQUENCE_DETECT   | |  | 
|   434                 ISC_REQ_REPLAY_DETECT     | |  | 
|   435                 ISC_REQ_CONFIDENTIALITY   | |  | 
|   436                 ISC_RET_EXTENDED_ERROR    | |  | 
|   437                 ISC_REQ_ALLOCATE_MEMORY   | |  | 
|   438                 ISC_REQ_STREAM; |  | 
|   439  |  | 
|   440   send_buffer_.pvBuffer = NULL; |  | 
|   441   send_buffer_.BufferType = SECBUFFER_TOKEN; |  | 
|   442   send_buffer_.cbBuffer = 0; |  | 
|   443  |  | 
|   444   buffer_desc.cBuffers = 1; |  | 
|   445   buffer_desc.pBuffers = &send_buffer_; |  | 
|   446   buffer_desc.ulVersion = SECBUFFER_VERSION; |  | 
|   447  |  | 
|   448   TimeStamp expiry; |  | 
|   449   SECURITY_STATUS status; |  | 
|   450  |  | 
|   451   status = InitializeSecurityContext( |  | 
|   452       creds_, |  | 
|   453       NULL,  // NULL on the first call |  | 
|   454       const_cast<wchar_t*>(ASCIIToWide(hostname_).c_str()), |  | 
|   455       flags, |  | 
|   456       0,  // Reserved |  | 
|   457       SECURITY_NATIVE_DREP,  // TODO(wtc): MSDN says this should be set to 0. |  | 
|   458       NULL,  // NULL on the first call |  | 
|   459       0,  // Reserved |  | 
|   460       &ctxt_,  // Receives the new context handle |  | 
|   461       &buffer_desc, |  | 
|   462       &out_flags, |  | 
|   463       &expiry); |  | 
|   464   if (status != SEC_I_CONTINUE_NEEDED) { |  | 
|   465     DLOG(ERROR) << "InitializeSecurityContext failed: " << status; |  | 
|   466     return MapSecurityError(status); |  | 
|   467   } |  | 
|   468  |  | 
|   469   writing_first_token_ = true; |  | 
|   470   next_state_ = STATE_HANDSHAKE_WRITE; |  | 
|   471   int rv = DoLoop(OK); |  | 
|   472   if (rv == ERR_IO_PENDING) |  | 
|   473     user_callback_ = callback; |  | 
|   474   return rv; |  | 
|   475 } |  | 
|   476  |  | 
|   477 void SSLClientSocketWin::Disconnect() { |  | 
|   478   // TODO(wtc): Send SSL close_notify alert. |  | 
|   479   completed_handshake_ = false; |  | 
|   480   transport_->Disconnect(); |  | 
|   481  |  | 
|   482   if (send_buffer_.pvBuffer) |  | 
|   483     FreeSendBuffer(); |  | 
|   484   if (ctxt_.dwLower || ctxt_.dwUpper) { |  | 
|   485     DeleteSecurityContext(&ctxt_); |  | 
|   486     memset(&ctxt_, 0, sizeof(ctxt_)); |  | 
|   487   } |  | 
|   488   if (server_cert_) |  | 
|   489     server_cert_ = NULL; |  | 
|   490  |  | 
|   491   // TODO(wtc): reset more members? |  | 
|   492   bytes_decrypted_ = 0; |  | 
|   493   bytes_received_ = 0; |  | 
|   494   writing_first_token_ = false; |  | 
|   495   renegotiating_ = false; |  | 
|   496 } |  | 
|   497  |  | 
|   498 bool SSLClientSocketWin::IsConnected() const { |  | 
|   499   // Ideally, we should also check if we have received the close_notify alert |  | 
|   500   // message from the server, and return false in that case.  We're not doing |  | 
|   501   // that, so this function may return a false positive.  Since the upper |  | 
|   502   // layer (HttpNetworkTransaction) needs to handle a persistent connection |  | 
|   503   // closed by the server when we send a request anyway, a false positive in |  | 
|   504   // exchange for simpler code is a good trade-off. |  | 
|   505   return completed_handshake_ && transport_->IsConnected(); |  | 
|   506 } |  | 
|   507  |  | 
|   508 bool SSLClientSocketWin::IsConnectedAndIdle() const { |  | 
|   509   // Unlike IsConnected, this method doesn't return a false positive. |  | 
|   510   // |  | 
|   511   // Strictly speaking, we should check if we have received the close_notify |  | 
|   512   // alert message from the server, and return false in that case.  Although |  | 
|   513   // the close_notify alert message means EOF in the SSL layer, it is just |  | 
|   514   // bytes to the transport layer below, so transport_->IsConnectedAndIdle() |  | 
|   515   // returns the desired false when we receive close_notify. |  | 
|   516   return completed_handshake_ && transport_->IsConnectedAndIdle(); |  | 
|   517 } |  | 
|   518  |  | 
|   519 int SSLClientSocketWin::Read(IOBuffer* buf, int buf_len, |  | 
|   520                              CompletionCallback* callback) { |  | 
|   521   DCHECK(completed_handshake_); |  | 
|   522   DCHECK(next_state_ == STATE_NONE); |  | 
|   523   DCHECK(!user_callback_); |  | 
|   524  |  | 
|   525   // If we have surplus decrypted plaintext, satisfy the Read with it without |  | 
|   526   // reading more ciphertext from the transport socket. |  | 
|   527   if (bytes_decrypted_ != 0) { |  | 
|   528     int len = std::min(buf_len, bytes_decrypted_); |  | 
|   529     memcpy(buf->data(), decrypted_ptr_, len); |  | 
|   530     decrypted_ptr_ += len; |  | 
|   531     bytes_decrypted_ -= len; |  | 
|   532     if (bytes_decrypted_ == 0) { |  | 
|   533       decrypted_ptr_ = NULL; |  | 
|   534       if (bytes_received_ != 0) { |  | 
|   535         memmove(recv_buffer_.get(), received_ptr_, bytes_received_); |  | 
|   536         received_ptr_ = recv_buffer_.get(); |  | 
|   537       } |  | 
|   538     } |  | 
|   539     return len; |  | 
|   540   } |  | 
|   541  |  | 
|   542   DCHECK(!user_buf_); |  | 
|   543   user_buf_ = buf; |  | 
|   544   user_buf_len_ = buf_len; |  | 
|   545  |  | 
|   546   SetNextStateForRead(); |  | 
|   547   int rv = DoLoop(OK); |  | 
|   548   if (rv == ERR_IO_PENDING) { |  | 
|   549     user_callback_ = callback; |  | 
|   550   } else { |  | 
|   551     user_buf_ = NULL; |  | 
|   552   } |  | 
|   553   return rv; |  | 
|   554 } |  | 
|   555  |  | 
|   556 int SSLClientSocketWin::Write(IOBuffer* buf, int buf_len, |  | 
|   557                               CompletionCallback* callback) { |  | 
|   558   DCHECK(completed_handshake_); |  | 
|   559   DCHECK(next_state_ == STATE_NONE); |  | 
|   560   DCHECK(!user_callback_); |  | 
|   561  |  | 
|   562   DCHECK(!user_buf_); |  | 
|   563   user_buf_ = buf; |  | 
|   564   user_buf_len_ = buf_len; |  | 
|   565  |  | 
|   566   next_state_ = STATE_PAYLOAD_ENCRYPT; |  | 
|   567   int rv = DoLoop(OK); |  | 
|   568   if (rv == ERR_IO_PENDING) { |  | 
|   569     user_callback_ = callback; |  | 
|   570   } else { |  | 
|   571     user_buf_ = NULL; |  | 
|   572   } |  | 
|   573   return rv; |  | 
|   574 } |  | 
|   575  |  | 
|   576 void SSLClientSocketWin::DoCallback(int rv) { |  | 
|   577   DCHECK(rv != ERR_IO_PENDING); |  | 
|   578   DCHECK(user_callback_); |  | 
|   579  |  | 
|   580   // since Run may result in Read being called, clear user_callback_ up front. |  | 
|   581   CompletionCallback* c = user_callback_; |  | 
|   582   user_callback_ = NULL; |  | 
|   583   user_buf_ = NULL; |  | 
|   584   c->Run(rv); |  | 
|   585 } |  | 
|   586  |  | 
|   587 void SSLClientSocketWin::OnIOComplete(int result) { |  | 
|   588   int rv = DoLoop(result); |  | 
|   589   if (rv != ERR_IO_PENDING) |  | 
|   590     DoCallback(rv); |  | 
|   591 } |  | 
|   592  |  | 
|   593 int SSLClientSocketWin::DoLoop(int last_io_result) { |  | 
|   594   DCHECK(next_state_ != STATE_NONE); |  | 
|   595   int rv = last_io_result; |  | 
|   596   do { |  | 
|   597     State state = next_state_; |  | 
|   598     next_state_ = STATE_NONE; |  | 
|   599     switch (state) { |  | 
|   600       case STATE_HANDSHAKE_READ: |  | 
|   601         rv = DoHandshakeRead(); |  | 
|   602         break; |  | 
|   603       case STATE_HANDSHAKE_READ_COMPLETE: |  | 
|   604         rv = DoHandshakeReadComplete(rv); |  | 
|   605         break; |  | 
|   606       case STATE_HANDSHAKE_WRITE: |  | 
|   607         rv = DoHandshakeWrite(); |  | 
|   608         break; |  | 
|   609       case STATE_HANDSHAKE_WRITE_COMPLETE: |  | 
|   610         rv = DoHandshakeWriteComplete(rv); |  | 
|   611         break; |  | 
|   612       case STATE_VERIFY_CERT: |  | 
|   613         rv = DoVerifyCert(); |  | 
|   614         break; |  | 
|   615       case STATE_VERIFY_CERT_COMPLETE: |  | 
|   616         rv = DoVerifyCertComplete(rv); |  | 
|   617         break; |  | 
|   618       case STATE_PAYLOAD_READ: |  | 
|   619         rv = DoPayloadRead(); |  | 
|   620         break; |  | 
|   621       case STATE_PAYLOAD_READ_COMPLETE: |  | 
|   622         rv = DoPayloadReadComplete(rv); |  | 
|   623         break; |  | 
|   624       case STATE_PAYLOAD_ENCRYPT: |  | 
|   625         rv = DoPayloadEncrypt(); |  | 
|   626         break; |  | 
|   627       case STATE_PAYLOAD_WRITE: |  | 
|   628         rv = DoPayloadWrite(); |  | 
|   629         break; |  | 
|   630       case STATE_PAYLOAD_WRITE_COMPLETE: |  | 
|   631         rv = DoPayloadWriteComplete(rv); |  | 
|   632         break; |  | 
|   633       default: |  | 
|   634         rv = ERR_UNEXPECTED; |  | 
|   635         NOTREACHED() << "unexpected state"; |  | 
|   636         break; |  | 
|   637     } |  | 
|   638   } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |  | 
|   639   return rv; |  | 
|   640 } |  | 
|   641  |  | 
|   642 int SSLClientSocketWin::DoHandshakeRead() { |  | 
|   643   next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |  | 
|   644  |  | 
|   645   if (!recv_buffer_.get()) |  | 
|   646     recv_buffer_.reset(new char[kRecvBufferSize]); |  | 
|   647  |  | 
|   648   int buf_len = kRecvBufferSize - bytes_received_; |  | 
|   649  |  | 
|   650   if (buf_len <= 0) { |  | 
|   651     NOTREACHED() << "Receive buffer is too small!"; |  | 
|   652     return ERR_UNEXPECTED; |  | 
|   653   } |  | 
|   654  |  | 
|   655   DCHECK(!transport_buf_); |  | 
|   656   transport_buf_ = new IOBuffer(buf_len); |  | 
|   657  |  | 
|   658   return transport_->Read(transport_buf_, buf_len, &io_callback_); |  | 
|   659 } |  | 
|   660  |  | 
|   661 int SSLClientSocketWin::DoHandshakeReadComplete(int result) { |  | 
|   662   if (result < 0) { |  | 
|   663     transport_buf_ = NULL; |  | 
|   664     return result; |  | 
|   665   } |  | 
|   666  |  | 
|   667   if (transport_buf_) { |  | 
|   668     // A transition to STATE_HANDSHAKE_READ_COMPLETE is set in multiple places, |  | 
|   669     // not only in DoHandshakeRead(), so we may not have a transport_buf_. |  | 
|   670     DCHECK_LE(result, kRecvBufferSize - bytes_received_); |  | 
|   671     char* buf = recv_buffer_.get() + bytes_received_; |  | 
|   672     memcpy(buf, transport_buf_->data(), result); |  | 
|   673     transport_buf_ = NULL; |  | 
|   674   } |  | 
|   675  |  | 
|   676   if (result == 0 && !ignore_ok_result_) |  | 
|   677     return ERR_SSL_PROTOCOL_ERROR;  // Incomplete response :( |  | 
|   678  |  | 
|   679   ignore_ok_result_ = false; |  | 
|   680  |  | 
|   681   bytes_received_ += result; |  | 
|   682  |  | 
|   683   // Process the contents of recv_buffer_. |  | 
|   684   TimeStamp expiry; |  | 
|   685   DWORD out_flags; |  | 
|   686  |  | 
|   687   DWORD flags = ISC_REQ_SEQUENCE_DETECT | |  | 
|   688                 ISC_REQ_REPLAY_DETECT | |  | 
|   689                 ISC_REQ_CONFIDENTIALITY | |  | 
|   690                 ISC_RET_EXTENDED_ERROR | |  | 
|   691                 ISC_REQ_ALLOCATE_MEMORY | |  | 
|   692                 ISC_REQ_STREAM; |  | 
|   693  |  | 
|   694   if (ssl_config_.send_client_cert) |  | 
|   695     flags |= ISC_REQ_USE_SUPPLIED_CREDS; |  | 
|   696  |  | 
|   697   SecBufferDesc in_buffer_desc, out_buffer_desc; |  | 
|   698  |  | 
|   699   in_buffer_desc.cBuffers = 2; |  | 
|   700   in_buffer_desc.pBuffers = in_buffers_; |  | 
|   701   in_buffer_desc.ulVersion = SECBUFFER_VERSION; |  | 
|   702  |  | 
|   703   in_buffers_[0].pvBuffer = recv_buffer_.get(); |  | 
|   704   in_buffers_[0].cbBuffer = bytes_received_; |  | 
|   705   in_buffers_[0].BufferType = SECBUFFER_TOKEN; |  | 
|   706  |  | 
|   707   in_buffers_[1].pvBuffer = NULL; |  | 
|   708   in_buffers_[1].cbBuffer = 0; |  | 
|   709   in_buffers_[1].BufferType = SECBUFFER_EMPTY; |  | 
|   710  |  | 
|   711   out_buffer_desc.cBuffers = 1; |  | 
|   712   out_buffer_desc.pBuffers = &send_buffer_; |  | 
|   713   out_buffer_desc.ulVersion = SECBUFFER_VERSION; |  | 
|   714  |  | 
|   715   send_buffer_.pvBuffer = NULL; |  | 
|   716   send_buffer_.BufferType = SECBUFFER_TOKEN; |  | 
|   717   send_buffer_.cbBuffer = 0; |  | 
|   718  |  | 
|   719   isc_status_ = InitializeSecurityContext( |  | 
|   720       creds_, |  | 
|   721       &ctxt_, |  | 
|   722       NULL, |  | 
|   723       flags, |  | 
|   724       0, |  | 
|   725       SECURITY_NATIVE_DREP, |  | 
|   726       &in_buffer_desc, |  | 
|   727       0, |  | 
|   728       NULL, |  | 
|   729       &out_buffer_desc, |  | 
|   730       &out_flags, |  | 
|   731       &expiry); |  | 
|   732  |  | 
|   733   if (send_buffer_.cbBuffer != 0 && |  | 
|   734       (isc_status_ == SEC_E_OK || |  | 
|   735        isc_status_ == SEC_I_CONTINUE_NEEDED || |  | 
|   736       (FAILED(isc_status_) && (out_flags & ISC_RET_EXTENDED_ERROR)))) { |  | 
|   737     next_state_ = STATE_HANDSHAKE_WRITE; |  | 
|   738     return OK; |  | 
|   739   } |  | 
|   740   return DidCallInitializeSecurityContext(); |  | 
|   741 } |  | 
|   742  |  | 
|   743 int SSLClientSocketWin::DidCallInitializeSecurityContext() { |  | 
|   744   if (isc_status_ == SEC_E_INCOMPLETE_MESSAGE) { |  | 
|   745     next_state_ = STATE_HANDSHAKE_READ; |  | 
|   746     return OK; |  | 
|   747   } |  | 
|   748  |  | 
|   749   if (isc_status_ == SEC_E_OK) { |  | 
|   750     if (in_buffers_[1].BufferType == SECBUFFER_EXTRA) { |  | 
|   751       // Save this data for later. |  | 
|   752       memmove(recv_buffer_.get(), |  | 
|   753               recv_buffer_.get() + (bytes_received_ - in_buffers_[1].cbBuffer), |  | 
|   754               in_buffers_[1].cbBuffer); |  | 
|   755       bytes_received_ = in_buffers_[1].cbBuffer; |  | 
|   756     } else { |  | 
|   757       bytes_received_ = 0; |  | 
|   758     } |  | 
|   759     return DidCompleteHandshake(); |  | 
|   760   } |  | 
|   761  |  | 
|   762   if (FAILED(isc_status_)) { |  | 
|   763     int result = MapSecurityError(isc_status_); |  | 
|   764     // We told Schannel to not verify the server certificate |  | 
|   765     // (SCH_CRED_MANUAL_CRED_VALIDATION), so any certificate error returned by |  | 
|   766     // InitializeSecurityContext must be referring to the bad or missing |  | 
|   767     // client certificate. |  | 
|   768     if (IsCertificateError(result)) { |  | 
|   769       // TODO(wtc): Add new error codes for client certificate errors reported |  | 
|   770       // by the server using SSL/TLS alert messages.  See the MSDN page |  | 
|   771       // "Schannel Error Codes for TLS and SSL Alerts", which maps TLS alert |  | 
|   772       // messages to Windows error codes: |  | 
|   773       // http://msdn.microsoft.com/en-us/library/dd721886%28VS.85%29.aspx |  | 
|   774       return ERR_BAD_SSL_CLIENT_AUTH_CERT; |  | 
|   775     } |  | 
|   776     return result; |  | 
|   777   } |  | 
|   778  |  | 
|   779   if (isc_status_ == SEC_I_INCOMPLETE_CREDENTIALS) |  | 
|   780     return ERR_SSL_CLIENT_AUTH_CERT_NEEDED; |  | 
|   781  |  | 
|   782   DCHECK(isc_status_ == SEC_I_CONTINUE_NEEDED); |  | 
|   783   if (in_buffers_[1].BufferType == SECBUFFER_EXTRA) { |  | 
|   784     memmove(recv_buffer_.get(), |  | 
|   785             recv_buffer_.get() + (bytes_received_ - in_buffers_[1].cbBuffer), |  | 
|   786             in_buffers_[1].cbBuffer); |  | 
|   787     bytes_received_ = in_buffers_[1].cbBuffer; |  | 
|   788     next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |  | 
|   789     ignore_ok_result_ = true;  // OK doesn't mean EOF. |  | 
|   790     return OK; |  | 
|   791   } |  | 
|   792  |  | 
|   793   bytes_received_ = 0; |  | 
|   794   next_state_ = STATE_HANDSHAKE_READ; |  | 
|   795   return OK; |  | 
|   796 } |  | 
|   797  |  | 
|   798 int SSLClientSocketWin::DoHandshakeWrite() { |  | 
|   799   next_state_ = STATE_HANDSHAKE_WRITE_COMPLETE; |  | 
|   800  |  | 
|   801   // We should have something to send. |  | 
|   802   DCHECK(send_buffer_.pvBuffer); |  | 
|   803   DCHECK(send_buffer_.cbBuffer > 0); |  | 
|   804   DCHECK(!transport_buf_); |  | 
|   805  |  | 
|   806   const char* buf = static_cast<char*>(send_buffer_.pvBuffer) + bytes_sent_; |  | 
|   807   int buf_len = send_buffer_.cbBuffer - bytes_sent_; |  | 
|   808   transport_buf_ = new IOBuffer(buf_len); |  | 
|   809   memcpy(transport_buf_->data(), buf, buf_len); |  | 
|   810  |  | 
|   811   return transport_->Write(transport_buf_, buf_len, &io_callback_); |  | 
|   812 } |  | 
|   813  |  | 
|   814 int SSLClientSocketWin::DoHandshakeWriteComplete(int result) { |  | 
|   815   DCHECK(transport_buf_); |  | 
|   816   transport_buf_ = NULL; |  | 
|   817   if (result < 0) |  | 
|   818     return result; |  | 
|   819  |  | 
|   820   DCHECK(result != 0); |  | 
|   821  |  | 
|   822   bytes_sent_ += result; |  | 
|   823   DCHECK(bytes_sent_ <= static_cast<int>(send_buffer_.cbBuffer)); |  | 
|   824  |  | 
|   825   if (bytes_sent_ >= static_cast<int>(send_buffer_.cbBuffer)) { |  | 
|   826     bool overflow = (bytes_sent_ > static_cast<int>(send_buffer_.cbBuffer)); |  | 
|   827     FreeSendBuffer(); |  | 
|   828     bytes_sent_ = 0; |  | 
|   829     if (overflow)  // Bug! |  | 
|   830       return ERR_UNEXPECTED; |  | 
|   831     if (writing_first_token_) { |  | 
|   832       writing_first_token_ = false; |  | 
|   833       DCHECK(bytes_received_ == 0); |  | 
|   834       next_state_ = STATE_HANDSHAKE_READ; |  | 
|   835       return OK; |  | 
|   836     } |  | 
|   837     return DidCallInitializeSecurityContext(); |  | 
|   838   } |  | 
|   839  |  | 
|   840   // Send the remaining bytes. |  | 
|   841   next_state_ = STATE_HANDSHAKE_WRITE; |  | 
|   842   return OK; |  | 
|   843 } |  | 
|   844  |  | 
|   845 // Set server_cert_status_ and return OK or a network error. |  | 
|   846 int SSLClientSocketWin::DoVerifyCert() { |  | 
|   847   next_state_ = STATE_VERIFY_CERT_COMPLETE; |  | 
|   848  |  | 
|   849   DCHECK(server_cert_); |  | 
|   850  |  | 
|   851   return verifier_.Verify(server_cert_, hostname_, |  | 
|   852                           ssl_config_.rev_checking_enabled, |  | 
|   853                           &server_cert_verify_result_, &io_callback_); |  | 
|   854 } |  | 
|   855  |  | 
|   856 int SSLClientSocketWin::DoVerifyCertComplete(int result) { |  | 
|   857   // If we have been explicitly told to accept this certificate, override the |  | 
|   858   // result of verifier_.Verify. |  | 
|   859   // Eventually, we should cache the cert verification results so that we don't |  | 
|   860   // need to call verifier_.Verify repeatedly. But for now we need to do this. |  | 
|   861   // Alternatively, we might be able to store the cert's status along with |  | 
|   862   // the cert in the allowed_bad_certs_ set. |  | 
|   863   if (IsCertificateError(result) && |  | 
|   864       ssl_config_.allowed_bad_certs_.count(server_cert_)) |  | 
|   865     result = OK; |  | 
|   866  |  | 
|   867   LogConnectionTypeMetrics(); |  | 
|   868   if (renegotiating_) { |  | 
|   869     DidCompleteRenegotiation(result); |  | 
|   870   } else { |  | 
|   871     // The initial handshake, kicked off by a Connect, has completed. |  | 
|   872     completed_handshake_ = true; |  | 
|   873     // Exit DoLoop and return the result to the caller of Connect. |  | 
|   874     DCHECK(next_state_ == STATE_NONE); |  | 
|   875   } |  | 
|   876   return result; |  | 
|   877 } |  | 
|   878  |  | 
|   879 int SSLClientSocketWin::DoPayloadRead() { |  | 
|   880   next_state_ = STATE_PAYLOAD_READ_COMPLETE; |  | 
|   881  |  | 
|   882   DCHECK(recv_buffer_.get()); |  | 
|   883  |  | 
|   884   int buf_len = kRecvBufferSize - bytes_received_; |  | 
|   885  |  | 
|   886   if (buf_len <= 0) { |  | 
|   887     NOTREACHED() << "Receive buffer is too small!"; |  | 
|   888     return ERR_FAILED; |  | 
|   889   } |  | 
|   890  |  | 
|   891   DCHECK(!transport_buf_); |  | 
|   892   transport_buf_ = new IOBuffer(buf_len); |  | 
|   893  |  | 
|   894   return transport_->Read(transport_buf_, buf_len, &io_callback_); |  | 
|   895 } |  | 
|   896  |  | 
|   897 int SSLClientSocketWin::DoPayloadReadComplete(int result) { |  | 
|   898   if (result < 0) { |  | 
|   899     transport_buf_ = NULL; |  | 
|   900     return result; |  | 
|   901   } |  | 
|   902   if (transport_buf_) { |  | 
|   903     // This method is called after a state transition following DoPayloadRead(), |  | 
|   904     // or if SetNextStateForRead() was called. We have a transport_buf_ only |  | 
|   905     // in the first case, and we have to transfer the data from transport_buf_ |  | 
|   906     // to recv_buffer_. |  | 
|   907     DCHECK_LE(result, kRecvBufferSize - bytes_received_); |  | 
|   908     char* buf = recv_buffer_.get() + bytes_received_; |  | 
|   909     memcpy(buf, transport_buf_->data(), result); |  | 
|   910     transport_buf_ = NULL; |  | 
|   911   } |  | 
|   912  |  | 
|   913   if (result == 0 && !ignore_ok_result_) { |  | 
|   914     // TODO(wtc): Unless we have received the close_notify alert, we need to |  | 
|   915     // return an error code indicating that the SSL connection ended |  | 
|   916     // uncleanly, a potential truncation attack. |  | 
|   917     if (bytes_received_ != 0) |  | 
|   918       return ERR_FAILED; |  | 
|   919     return OK; |  | 
|   920   } |  | 
|   921  |  | 
|   922   ignore_ok_result_ = false; |  | 
|   923  |  | 
|   924   bytes_received_ += result; |  | 
|   925  |  | 
|   926   // Process the contents of recv_buffer_. |  | 
|   927   SecBuffer buffers[4]; |  | 
|   928   buffers[0].pvBuffer = recv_buffer_.get(); |  | 
|   929   buffers[0].cbBuffer = bytes_received_; |  | 
|   930   buffers[0].BufferType = SECBUFFER_DATA; |  | 
|   931  |  | 
|   932   buffers[1].BufferType = SECBUFFER_EMPTY; |  | 
|   933   buffers[2].BufferType = SECBUFFER_EMPTY; |  | 
|   934   buffers[3].BufferType = SECBUFFER_EMPTY; |  | 
|   935  |  | 
|   936   SecBufferDesc buffer_desc; |  | 
|   937   buffer_desc.cBuffers = 4; |  | 
|   938   buffer_desc.pBuffers = buffers; |  | 
|   939   buffer_desc.ulVersion = SECBUFFER_VERSION; |  | 
|   940  |  | 
|   941   SECURITY_STATUS status; |  | 
|   942   status = DecryptMessage(&ctxt_, &buffer_desc, 0, NULL); |  | 
|   943  |  | 
|   944   if (status == SEC_E_INCOMPLETE_MESSAGE) { |  | 
|   945     next_state_ = STATE_PAYLOAD_READ; |  | 
|   946     return OK; |  | 
|   947   } |  | 
|   948  |  | 
|   949   if (status == SEC_I_CONTEXT_EXPIRED) { |  | 
|   950     // Received the close_notify alert. |  | 
|   951     bytes_received_ = 0; |  | 
|   952     return OK; |  | 
|   953   } |  | 
|   954  |  | 
|   955   if (status != SEC_E_OK && status != SEC_I_RENEGOTIATE) { |  | 
|   956     DCHECK(status != SEC_E_MESSAGE_ALTERED); |  | 
|   957     return MapSecurityError(status); |  | 
|   958   } |  | 
|   959  |  | 
|   960   // The received ciphertext was decrypted in place in recv_buffer_.  Remember |  | 
|   961   // the location and length of the decrypted plaintext and any unused |  | 
|   962   // ciphertext. |  | 
|   963   decrypted_ptr_ = NULL; |  | 
|   964   bytes_decrypted_ = 0; |  | 
|   965   received_ptr_ = NULL; |  | 
|   966   bytes_received_ = 0; |  | 
|   967   for (int i = 1; i < 4; i++) { |  | 
|   968     if (!decrypted_ptr_ && buffers[i].BufferType == SECBUFFER_DATA) { |  | 
|   969       decrypted_ptr_ = static_cast<char*>(buffers[i].pvBuffer); |  | 
|   970       bytes_decrypted_ = buffers[i].cbBuffer; |  | 
|   971     } |  | 
|   972     if (!received_ptr_ && buffers[i].BufferType == SECBUFFER_EXTRA) { |  | 
|   973       received_ptr_ = static_cast<char*>(buffers[i].pvBuffer); |  | 
|   974       bytes_received_ = buffers[i].cbBuffer; |  | 
|   975     } |  | 
|   976   } |  | 
|   977  |  | 
|   978   int len = 0; |  | 
|   979   if (bytes_decrypted_ != 0) { |  | 
|   980     len = std::min(user_buf_len_, bytes_decrypted_); |  | 
|   981     memcpy(user_buf_->data(), decrypted_ptr_, len); |  | 
|   982     decrypted_ptr_ += len; |  | 
|   983     bytes_decrypted_ -= len; |  | 
|   984   } |  | 
|   985   if (bytes_decrypted_ == 0) { |  | 
|   986     decrypted_ptr_ = NULL; |  | 
|   987     if (bytes_received_ != 0) { |  | 
|   988       memmove(recv_buffer_.get(), received_ptr_, bytes_received_); |  | 
|   989       received_ptr_ = recv_buffer_.get(); |  | 
|   990     } |  | 
|   991   } |  | 
|   992  |  | 
|   993   if (status == SEC_I_RENEGOTIATE) { |  | 
|   994     if (bytes_received_ != 0) { |  | 
|   995       // The server requested renegotiation, but there are some data yet to |  | 
|   996       // be decrypted.  The Platform SDK WebClient.c sample doesn't handle |  | 
|   997       // this, so we don't know how to handle this.  Assume this cannot |  | 
|   998       // happen. |  | 
|   999       LOG(ERROR) << "DecryptMessage returned SEC_I_RENEGOTIATE with a buffer " |  | 
|  1000                  << "of type SECBUFFER_EXTRA."; |  | 
|  1001       return ERR_SSL_RENEGOTIATION_REQUESTED; |  | 
|  1002     } |  | 
|  1003     if (len != 0) { |  | 
|  1004       // The server requested renegotiation, but there are some decrypted |  | 
|  1005       // data.  We can't start renegotiation until we have returned all |  | 
|  1006       // decrypted data to the caller. |  | 
|  1007       // |  | 
|  1008       // This hasn't happened during testing.  Assume this cannot happen even |  | 
|  1009       // though we know how to handle this. |  | 
|  1010       LOG(ERROR) << "DecryptMessage returned SEC_I_RENEGOTIATE with a buffer " |  | 
|  1011                  << "of type SECBUFFER_DATA."; |  | 
|  1012       return ERR_SSL_RENEGOTIATION_REQUESTED; |  | 
|  1013     } |  | 
|  1014     // Jump to the handshake sequence.  Will come back when the rehandshake is |  | 
|  1015     // done. |  | 
|  1016     renegotiating_ = true; |  | 
|  1017     next_state_ = STATE_HANDSHAKE_READ_COMPLETE; |  | 
|  1018     ignore_ok_result_ = true;  // OK doesn't mean EOF. |  | 
|  1019     return len; |  | 
|  1020   } |  | 
|  1021  |  | 
|  1022   // If we decrypted 0 bytes, don't report 0 bytes read, which would be |  | 
|  1023   // mistaken for EOF.  Continue decrypting or read more. |  | 
|  1024   if (len == 0) |  | 
|  1025     SetNextStateForRead(); |  | 
|  1026   return len; |  | 
|  1027 } |  | 
|  1028  |  | 
|  1029 int SSLClientSocketWin::DoPayloadEncrypt() { |  | 
|  1030   DCHECK(user_buf_); |  | 
|  1031   DCHECK(user_buf_len_ > 0); |  | 
|  1032  |  | 
|  1033   ULONG message_len = std::min( |  | 
|  1034       stream_sizes_.cbMaximumMessage, static_cast<ULONG>(user_buf_len_)); |  | 
|  1035   ULONG alloc_len = |  | 
|  1036       message_len + stream_sizes_.cbHeader + stream_sizes_.cbTrailer; |  | 
|  1037   user_buf_len_ = message_len; |  | 
|  1038  |  | 
|  1039   payload_send_buffer_.reset(new char[alloc_len]); |  | 
|  1040   memcpy(&payload_send_buffer_[stream_sizes_.cbHeader], |  | 
|  1041          user_buf_->data(), message_len); |  | 
|  1042  |  | 
|  1043   SecBuffer buffers[4]; |  | 
|  1044   buffers[0].pvBuffer = payload_send_buffer_.get(); |  | 
|  1045   buffers[0].cbBuffer = stream_sizes_.cbHeader; |  | 
|  1046   buffers[0].BufferType = SECBUFFER_STREAM_HEADER; |  | 
|  1047  |  | 
|  1048   buffers[1].pvBuffer = &payload_send_buffer_[stream_sizes_.cbHeader]; |  | 
|  1049   buffers[1].cbBuffer = message_len; |  | 
|  1050   buffers[1].BufferType = SECBUFFER_DATA; |  | 
|  1051  |  | 
|  1052   buffers[2].pvBuffer = &payload_send_buffer_[stream_sizes_.cbHeader + |  | 
|  1053                                               message_len]; |  | 
|  1054   buffers[2].cbBuffer = stream_sizes_.cbTrailer; |  | 
|  1055   buffers[2].BufferType = SECBUFFER_STREAM_TRAILER; |  | 
|  1056  |  | 
|  1057   buffers[3].BufferType = SECBUFFER_EMPTY; |  | 
|  1058  |  | 
|  1059   SecBufferDesc buffer_desc; |  | 
|  1060   buffer_desc.cBuffers = 4; |  | 
|  1061   buffer_desc.pBuffers = buffers; |  | 
|  1062   buffer_desc.ulVersion = SECBUFFER_VERSION; |  | 
|  1063  |  | 
|  1064   SECURITY_STATUS status = EncryptMessage(&ctxt_, 0, &buffer_desc, 0); |  | 
|  1065  |  | 
|  1066   if (FAILED(status)) |  | 
|  1067     return MapSecurityError(status); |  | 
|  1068  |  | 
|  1069   payload_send_buffer_len_ = buffers[0].cbBuffer + |  | 
|  1070                              buffers[1].cbBuffer + |  | 
|  1071                              buffers[2].cbBuffer; |  | 
|  1072   DCHECK(bytes_sent_ == 0); |  | 
|  1073  |  | 
|  1074   next_state_ = STATE_PAYLOAD_WRITE; |  | 
|  1075   return OK; |  | 
|  1076 } |  | 
|  1077  |  | 
|  1078 int SSLClientSocketWin::DoPayloadWrite() { |  | 
|  1079   next_state_ = STATE_PAYLOAD_WRITE_COMPLETE; |  | 
|  1080  |  | 
|  1081   // We should have something to send. |  | 
|  1082   DCHECK(payload_send_buffer_.get()); |  | 
|  1083   DCHECK(payload_send_buffer_len_ > 0); |  | 
|  1084   DCHECK(!transport_buf_); |  | 
|  1085  |  | 
|  1086   const char* buf = payload_send_buffer_.get() + bytes_sent_; |  | 
|  1087   int buf_len = payload_send_buffer_len_ - bytes_sent_; |  | 
|  1088   transport_buf_ = new IOBuffer(buf_len); |  | 
|  1089   memcpy(transport_buf_->data(), buf, buf_len); |  | 
|  1090  |  | 
|  1091   return transport_->Write(transport_buf_, buf_len, &io_callback_); |  | 
|  1092 } |  | 
|  1093  |  | 
|  1094 int SSLClientSocketWin::DoPayloadWriteComplete(int result) { |  | 
|  1095   DCHECK(transport_buf_); |  | 
|  1096   transport_buf_ = NULL; |  | 
|  1097   if (result < 0) |  | 
|  1098     return result; |  | 
|  1099  |  | 
|  1100   DCHECK(result != 0); |  | 
|  1101  |  | 
|  1102   bytes_sent_ += result; |  | 
|  1103   DCHECK(bytes_sent_ <= payload_send_buffer_len_); |  | 
|  1104  |  | 
|  1105   if (bytes_sent_ >= payload_send_buffer_len_) { |  | 
|  1106     bool overflow = (bytes_sent_ > payload_send_buffer_len_); |  | 
|  1107     payload_send_buffer_.reset(); |  | 
|  1108     payload_send_buffer_len_ = 0; |  | 
|  1109     bytes_sent_ = 0; |  | 
|  1110     if (overflow)  // Bug! |  | 
|  1111       return ERR_UNEXPECTED; |  | 
|  1112     // Done |  | 
|  1113     return user_buf_len_; |  | 
|  1114   } |  | 
|  1115  |  | 
|  1116   // Send the remaining bytes. |  | 
|  1117   next_state_ = STATE_PAYLOAD_WRITE; |  | 
|  1118   return OK; |  | 
|  1119 } |  | 
|  1120  |  | 
|  1121 int SSLClientSocketWin::DidCompleteHandshake() { |  | 
|  1122   SECURITY_STATUS status = QueryContextAttributes( |  | 
|  1123       &ctxt_, SECPKG_ATTR_STREAM_SIZES, &stream_sizes_); |  | 
|  1124   if (status != SEC_E_OK) { |  | 
|  1125     DLOG(ERROR) << "QueryContextAttributes (stream sizes) failed: " << status; |  | 
|  1126     return MapSecurityError(status); |  | 
|  1127   } |  | 
|  1128   DCHECK(!server_cert_ || renegotiating_); |  | 
|  1129   PCCERT_CONTEXT server_cert_handle = NULL; |  | 
|  1130   status = QueryContextAttributes( |  | 
|  1131       &ctxt_, SECPKG_ATTR_REMOTE_CERT_CONTEXT, &server_cert_handle); |  | 
|  1132   if (status != SEC_E_OK) { |  | 
|  1133     DLOG(ERROR) << "QueryContextAttributes (remote cert) failed: " << status; |  | 
|  1134     return MapSecurityError(status); |  | 
|  1135   } |  | 
|  1136   if (renegotiating_ && |  | 
|  1137       SameCert(server_cert_->os_cert_handle(), server_cert_handle)) { |  | 
|  1138     // We already verified the server certificate.  Either it is good or the |  | 
|  1139     // user has accepted the certificate error. |  | 
|  1140     CertFreeCertificateContext(server_cert_handle); |  | 
|  1141     DidCompleteRenegotiation(OK); |  | 
|  1142   } else { |  | 
|  1143     server_cert_ = X509Certificate::CreateFromHandle( |  | 
|  1144         server_cert_handle, X509Certificate::SOURCE_FROM_NETWORK); |  | 
|  1145  |  | 
|  1146     next_state_ = STATE_VERIFY_CERT; |  | 
|  1147   } |  | 
|  1148   return OK; |  | 
|  1149 } |  | 
|  1150  |  | 
|  1151 // Called when a renegotiation is completed.  |result| is the verification |  | 
|  1152 // result of the server certificate received during renegotiation. |  | 
|  1153 void SSLClientSocketWin::DidCompleteRenegotiation(int result) { |  | 
|  1154   // A rehandshake, started in the middle of a Read, has completed. |  | 
|  1155   renegotiating_ = false; |  | 
|  1156   // Pick up where we left off.  Go back to reading data. |  | 
|  1157   if (result == OK) |  | 
|  1158     SetNextStateForRead(); |  | 
|  1159 } |  | 
|  1160  |  | 
|  1161 void SSLClientSocketWin::LogConnectionTypeMetrics() const { |  | 
|  1162   UpdateConnectionTypeHistograms(CONNECTION_SSL); |  | 
|  1163   if (server_cert_verify_result_.has_md5) |  | 
|  1164     UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5); |  | 
|  1165   if (server_cert_verify_result_.has_md2) |  | 
|  1166     UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2); |  | 
|  1167   if (server_cert_verify_result_.has_md4) |  | 
|  1168     UpdateConnectionTypeHistograms(CONNECTION_SSL_MD4); |  | 
|  1169   if (server_cert_verify_result_.has_md5_ca) |  | 
|  1170     UpdateConnectionTypeHistograms(CONNECTION_SSL_MD5_CA); |  | 
|  1171   if (server_cert_verify_result_.has_md2_ca) |  | 
|  1172     UpdateConnectionTypeHistograms(CONNECTION_SSL_MD2_CA); |  | 
|  1173 } |  | 
|  1174  |  | 
|  1175 void SSLClientSocketWin::SetNextStateForRead() { |  | 
|  1176   if (bytes_received_ == 0) { |  | 
|  1177     next_state_ = STATE_PAYLOAD_READ; |  | 
|  1178   } else { |  | 
|  1179     next_state_ = STATE_PAYLOAD_READ_COMPLETE; |  | 
|  1180     ignore_ok_result_ = true;  // OK doesn't mean EOF. |  | 
|  1181   } |  | 
|  1182 } |  | 
|  1183  |  | 
|  1184 void SSLClientSocketWin::FreeSendBuffer() { |  | 
|  1185   SECURITY_STATUS status = FreeContextBuffer(send_buffer_.pvBuffer); |  | 
|  1186   DCHECK(status == SEC_E_OK); |  | 
|  1187   memset(&send_buffer_, 0, sizeof(send_buffer_)); |  | 
|  1188 } |  | 
|  1189  |  | 
|  1190 }  // namespace net |  | 
| OLD | NEW |