<commit_before>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/ssl_client_socket_win.h"

#include <schnlsp.h>

#include "base/lock.h"
#include "base/singleton.h"
#include "base/string_util.h"
#include "net/base/connection_type_histograms.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_info.h"

#pragma comment(lib, "secur32.lib")

namespace net {

//-----------------------------------------------------------------------------

// TODO(wtc): See http://msdn.microsoft.com/en-us/library/aa377188(VS.85).aspx
// for the other error codes we may need to map.
static int MapSecurityError(SECURITY_STATUS err) {
  // There are numerous security error codes, but these are the ones we thus
  // far find interesting.
  switch (err) {
    case SEC_E_WRONG_PRINCIPAL:  // Schannel
    case CERT_E_CN_NO_MATCH:  // CryptoAPI
      return ERR_CERT_COMMON_NAME_INVALID;
    case SEC_E_UNTRUSTED_ROOT:  // Schannel
    case CERT_E_UNTRUSTEDROOT:  // CryptoAPI
      return ERR_CERT_AUTHORITY_INVALID;
    case SEC_E_CERT_EXPIRED:  // Schannel
    case CERT_E_EXPIRED:  // CryptoAPI
      return ERR_CERT_DATE_INVALID;
    case CRYPT_E_NO_REVOCATION_CHECK:
      return ERR_CERT_NO_REVOCATION_MECHANISM;
    case CRYPT_E_REVOCATION_OFFLINE:
      return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
    case CRYPT_E_REVOKED:  // Schannel and CryptoAPI
      return ERR_CERT_REVOKED;
    case SEC_E_CERT_UNKNOWN:
    case CERT_E_ROLE:
      return ERR_CERT_INVALID;
    // We received an unexpected_message or illegal_parameter alert message
    // from the server.
    case SEC_E_ILLEGAL_MESSAGE:
      return ERR_SSL_PROTOCOL_ERROR;
    case SEC_E_ALGORITHM_MISMATCH:
      return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
    case SEC_E_INVALID_HANDLE:
      return ERR_UNEXPECTED;
    case SEC_E_OK:
      return OK;
    default:
      LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
      return ERR_FAILED;
  }
}

// Returns true if the two CERT_CONTEXTs contain the same certificate.
bool SameCert(PCCERT_CONTEXT a, PCCERT_CONTEXT b) {
  return a == b ||
         (a->cbCertEncoded == b->cbCertEncoded &&
         memcmp(a->pbCertEncoded, b->pbCertEncoded, b->cbCertEncoded) == 0);
}

//-----------------------------------------------------------------------------

// A bitmask consisting of these bit flags encodes which versions of the SSL
// protocol (SSL 2.0, SSL 3.0, and TLS 1.0) are enabled.
enum {
  SSL2 = 1 << 0,
  SSL3 = 1 << 1,
  TLS1 = 1 << 2,
  SSL_VERSION_MASKS = 1 << 3  // The number of SSL version bitmasks.
};

// CredHandleClass simply gives a default constructor and a destructor to
// SSPI's CredHandle type (a C struct).  The default constuctor is required
// by STL containers.
class CredHandleClass : public CredHandle {
 public:
  CredHandleClass() {
    dwLower = 0;
    dwUpper = 0;
  }

  ~CredHandleClass() {
    if (dwLower || dwUpper) {
      SECURITY_STATUS status = FreeCredentialsHandle(this);
      DCHECK(status == SEC_E_OK);
    }
  }
};

// A table of CredHandles.
class CredHandleTable {
 public:
  CredHandleTable() {}

  ~CredHandleTable() {}

  CredHandle* GetHandle(PCCERT_CONTEXT client_cert, int ssl_version_mask) {
    DCHECK(0 < ssl_version_mask &&
           ssl_version_mask < arraysize(anonymous_creds_));
    CredHandle* handle;
    AutoLock lock(lock_);
    if (client_cert) {
      handle = &client_cert_creds_[
          std::make_pair(client_cert, ssl_version_mask)];
    } else {
      handle = &anonymous_creds_[ssl_version_mask];
    }
    if (!handle->dwLower && !handle->dwUpper)
      InitializeHandle(handle, client_cert, ssl_version_mask);
    return handle;
  }

 private:
  // CredHandleMapKey is a std::pair consisting of these two components:
  //   PCCERT_CONTEXT client_cert
  //   int ssl_version_mask
  typedef std::pair<PCCERT_CONTEXT, int> CredHandleMapKey;

  typedef std::map<CredHandleMapKey, CredHandleClass> CredHandleMap;

  static void InitializeHandle(CredHandle* handle,
                               PCCERT_CONTEXT client_cert,
                               int ssl_version_mask);

  Lock lock_;<commit_msg>Don't put CredHandleClass in std::map directly because std::map may copy an entry to a new address while resizing, which invokes the destructor on the old entry and invalidates its address.<commit_after>// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "net/base/ssl_client_socket_win.h"

#include <schnlsp.h>

#include "base/lock.h"
#include "base/singleton.h"
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "net/base/connection_type_histograms.h"
#include "net/base/io_buffer.h"
#include "net/base/net_errors.h"
#include "net/base/ssl_cert_request_info.h"
#include "net/base/ssl_info.h"

#pragma comment(lib, "secur32.lib")

namespace net {

//-----------------------------------------------------------------------------

// TODO(wtc): See http://msdn.microsoft.com/en-us/library/aa377188(VS.85).aspx
// for the other error codes we may need to map.
static int MapSecurityError(SECURITY_STATUS err) {
  // There are numerous security error codes, but these are the ones we thus
  // far find interesting.
  switch (err) {
    case SEC_E_WRONG_PRINCIPAL:  // Schannel
    case CERT_E_CN_NO_MATCH:  // CryptoAPI
      return ERR_CERT_COMMON_NAME_INVALID;
    case SEC_E_UNTRUSTED_ROOT:  // Schannel
    case CERT_E_UNTRUSTEDROOT:  // CryptoAPI
      return ERR_CERT_AUTHORITY_INVALID;
    case SEC_E_CERT_EXPIRED:  // Schannel
    case CERT_E_EXPIRED:  // CryptoAPI
      return ERR_CERT_DATE_INVALID;
    case CRYPT_E_NO_REVOCATION_CHECK:
      return ERR_CERT_NO_REVOCATION_MECHANISM;
    case CRYPT_E_REVOCATION_OFFLINE:
      return ERR_CERT_UNABLE_TO_CHECK_REVOCATION;
    case CRYPT_E_REVOKED:  // Schannel and CryptoAPI
      return ERR_CERT_REVOKED;
    case SEC_E_CERT_UNKNOWN:
    case CERT_E_ROLE:
      return ERR_CERT_INVALID;
    // We received an unexpected_message or illegal_parameter alert message
    // from the server.
    case SEC_E_ILLEGAL_MESSAGE:
      return ERR_SSL_PROTOCOL_ERROR;
    case SEC_E_ALGORITHM_MISMATCH:
      return ERR_SSL_VERSION_OR_CIPHER_MISMATCH;
    case SEC_E_INVALID_HANDLE:
      return ERR_UNEXPECTED;
    case SEC_E_OK:
      return OK;
    default:
      LOG(WARNING) << "Unknown error " << err << " mapped to net::ERR_FAILED";
      return ERR_FAILED;
  }
}

// Returns true if the two CERT_CONTEXTs contain the same certificate.
bool SameCert(PCCERT_CONTEXT a, PCCERT_CONTEXT b) {
  return a == b ||
         (a->cbCertEncoded == b->cbCertEncoded &&
         memcmp(a->pbCertEncoded, b->pbCertEncoded, b->cbCertEncoded) == 0);
}

//-----------------------------------------------------------------------------

// A bitmask consisting of these bit flags encodes which versions of the SSL
// protocol (SSL 2.0, SSL 3.0, and TLS 1.0) are enabled.
enum {
  SSL2 = 1 << 0,
  SSL3 = 1 << 1,
  TLS1 = 1 << 2,
  SSL_VERSION_MASKS = 1 << 3  // The number of SSL version bitmasks.
};

// CredHandleClass simply gives a default constructor and a destructor to
// SSPI's CredHandle type (a C struct).
class CredHandleClass : public CredHandle {
 public:
  CredHandleClass() {
    dwLower = 0;
    dwUpper = 0;
  }

  ~CredHandleClass() {
    if (dwLower || dwUpper) {
      SECURITY_STATUS status = FreeCredentialsHandle(this);
      DCHECK(status == SEC_E_OK);
    }
  }
};

// A table of CredHandles.
class CredHandleTable {
 public:
  CredHandleTable() {}

  ~CredHandleTable() {
    STLDeleteContainerPairSecondPointers(client_cert_creds_.begin(),
                                         client_cert_creds_.end());
  }

  CredHandle* GetHandle(PCCERT_CONTEXT client_cert, int ssl_version_mask) {
    DCHECK(0 < ssl_version_mask &&
           ssl_version_mask < arraysize(anonymous_creds_));
    CredHandleClass* handle;
    AutoLock lock(lock_);
    if (client_cert) {
      CredHandleMapKey key = std::make_pair(client_cert, ssl_version_mask);
      CredHandleMap::const_iterator it = client_cert_creds_.find(key);
      if (it == client_cert_creds_.end()) {
        handle = new CredHandleClass;
        client_cert_creds_[key] = handle;
      } else {
        handle = it->second;
      }
    } else {
      handle = &anonymous_creds_[ssl_version_mask];
    }
    if (!handle->dwLower && !handle->dwUpper)
      InitializeHandle(handle, client_cert, ssl_version_mask);
    return handle;
  }

 private:
  // CredHandleMapKey is a std::pair consisting of these two components:
  //   PCCERT_CONTEXT client_cert
  //   int ssl_version_mask
  typedef std::pair<PCCERT_CONTEXT, int> CredHandleMapKey;

  typedef std::map<CredHandleMapKey, CredHandleClass*> CredHandleMap;

  static void InitializeHandle(CredHandle* handle,
                               PCCERT_CONTEXT client_cert,
                               int ssl_version_mask);

  Lock lock_;
{'fraction_non_alphanumeric': 0.12383025027203481, 'fraction_numerical': 0.008487486398258977, 'mean_word_length': 2.869894736842105, 'pattern_counts': {'":': 0, '<': 41, '<?xml version=': 0, '>': 24, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5304229', 'n_tokens_mistral': 3123, 'n_tokens_neox': 3017, 'n_words': 740}