// Copyright (c) 2012 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 "chrome/browser/ssl/ssl_config_service_manager.h"

#include <stdint.h>

#include <algorithm>
#include <string>
#include <vector>

#include "base/bind.h"
#include "base/location.h"
#include "base/macros.h"
#include "base/metrics/field_trial_params.h"
#include "base/strings/string_util.h"
#include "base/values.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "components/content_settings/core/browser/content_settings_utils.h"
#include "components/content_settings/core/common/content_settings.h"
#include "components/prefs/pref_change_registrar.h"
#include "components/prefs/pref_member.h"
#include "components/prefs/pref_registry_simple.h"
#include "components/prefs/pref_service.h"
#include "mojo/public/cpp/bindings/interface_ptr_set.h"
#include "net/cert/cert_verifier.h"
#include "net/ssl/ssl_cipher_suite_names.h"
#include "net/ssl/ssl_config_service.h"
#include "url/url_canon.h"

namespace base {
class SingleThreadTaskRunner;
}

namespace {

// Converts a ListValue of StringValues into a vector of strings. Any Values
// which cannot be converted will be skipped.
std::vector<std::string> ListValueToStringVector(const base::ListValue* value) {
  std::vector<std::string> results;
  results.reserve(value->GetSize());
  std::string s;
  for (auto it = value->begin(); it != value->end(); ++it) {
    if (!it->GetAsString(&s))
      continue;
    results.push_back(s);
  }
  return results;
}

// Parses a vector of cipher suite strings, returning a sorted vector
// containing the underlying SSL/TLS cipher suites. Unrecognized/invalid
// cipher suites will be ignored.
std::vector<uint16_t> ParseCipherSuites(
    const std::vector<std::string>& cipher_strings) {
  std::vector<uint16_t> cipher_suites;
  cipher_suites.reserve(cipher_strings.size());

  for (auto it = cipher_strings.begin(); it != cipher_strings.end(); ++it) {
    uint16_t cipher_suite = 0;
    if (!net::ParseSSLCipherString(*it, &cipher_suite)) {
      LOG(ERROR) << "Ignoring unrecognized or unparsable cipher suite: " << *it;
      continue;
    }
    cipher_suites.push_back(cipher_suite);
  }
  std::sort(cipher_suites.begin(), cipher_suites.end());
  return cipher_suites;
}

// Writes the SSL protocol version represented by a string to |version|. Returns
// false if the string is not recognized.
bool SSLProtocolVersionFromString(const std::string& version_str,
                                  network::mojom::SSLVersion* version) {
  if (version_str == switches::kSSLVersionTLSv1) {
    *version = network::mojom::SSLVersion::kTLS1;
    return true;
  }
  if (version_str == switches::kSSLVersionTLSv11) {
    *version = network::mojom::SSLVersion::kTLS11;
    return true;
  }
  if (version_str == switches::kSSLVersionTLSv12) {
    *version = network::mojom::SSLVersion::kTLS12;
    return true;
  }
  if (version_str == switches::kSSLVersionTLSv13) {
    *version = network::mojom::SSLVersion::kTLS13;
    return true;
  }
  return false;
}

// Given a vector of hostname patterns |patterns|, returns a vector containing
// the canonical form. Any entries which cannot be parsed are skipped.
std::vector<std::string> CanonicalizeHostnamePatterns(
    const std::vector<std::string>& patterns) {
  std::vector<std::string> out;
  out.reserve(patterns.size());
  for (base::StringPiece pattern : patterns) {
    std::string canon_pattern;
    url::Component canon_component;
    url::StdStringCanonOutput canon_output(&canon_pattern);
    if (!url::CanonicalizeHost(pattern.data(),
                               url::Component(0, pattern.size()), &canon_output,
                               &canon_component)) {
      continue;
    }
    canon_output.Complete();
    out.push_back(canon_pattern);
  }
  return out;
}

const char kTLS13VariantExperimentName[] = "TLS13Variant";

////////////////////////////////////////////////////////////////////////////////
//  SSLConfigServiceManagerPref

// The manager for holding and updating one or more
// network::mojom::SSLConfigClients.
class SSLConfigServiceManagerPref : public SSLConfigServiceManager {
 public:
  explicit SSLConfigServiceManagerPref(PrefService* local_state);
  ~SSLConfigServiceManagerPref() override {}

  // Register local_state SSL preferences.
  static void RegisterPrefs(PrefRegistrySimple* registry);

  void AddToNetworkContextParams(
      network::mojom::NetworkContextParams* network_context_params) override;

  void FlushForTesting() override;

 private:
  // Callback for preference changes.  This will post the changes to the IO
  // thread with SetNewSSLConfig.
  void OnPreferenceChanged(PrefService* prefs, const std::string& pref_name);

  // Returns the current SSLConfig settings from preferences. Assumes
  // |disabled_cipher_suites_| is up-to-date, but reads all other settings from
  // live prefs.
  network::mojom::SSLConfigPtr GetSSLConfigFromPrefs() const;

  // Processes changes to the disabled cipher suites preference, updating the
  // cached list of parsed SSL/TLS cipher suites that are disabled.
  void OnDisabledCipherSuitesChange(PrefService* local_state);

  PrefChangeRegistrar local_state_change_registrar_;

  // The local_state prefs.
  BooleanPrefMember rev_checking_enabled_;
  BooleanPrefMember rev_checking_required_local_anchors_;
  BooleanPrefMember symantec_legacy_infrastructure_enabled_;
  StringPrefMember ssl_version_min_;
  StringPrefMember ssl_version_max_;
  StringPrefMember tls13_variant_;
  StringListPrefMember h2_client_cert_coalescing_host_patterns_;

  // The cached list of disabled SSL cipher suites.
  std::vector<uint16_t> disabled_cipher_suites_;

  mojo::InterfacePtrSet<network::mojom::SSLConfigClient> ssl_config_client_set_;

  DISALLOW_COPY_AND_ASSIGN(SSLConfigServiceManagerPref);
};

SSLConfigServiceManagerPref::SSLConfigServiceManagerPref(
    PrefService* local_state) {
  DCHECK(local_state);

  const std::string tls13_variant =
      base::GetFieldTrialParamValue(kTLS13VariantExperimentName, "variant");
  const char* tls13_value = nullptr;
  const char* version_value = nullptr;
  if (tls13_variant == "disabled") {
    tls13_value = switches::kTLS13VariantDisabled;
  } else if (tls13_variant == "draft23") {
    tls13_value = switches::kTLS13VariantDraft23;
    version_value = switches::kSSLVersionTLSv13;
  } else if (tls13_variant == "final") {
    tls13_value = switches::kTLS13VariantFinal;
    version_value = switches::kSSLVersionTLSv13;
  }

  if (tls13_value) {
    local_state->SetDefaultPrefValue(prefs::kTLS13Variant,
                                     base::Value(tls13_value));
  }
  if (version_value) {
    local_state->SetDefaultPrefValue(prefs::kSSLVersionMax,
                                     base::Value(version_value));
  }

  PrefChangeRegistrar::NamedChangeCallback local_state_callback =
      base::BindRepeating(&SSLConfigServiceManagerPref::OnPreferenceChanged,
                          base::Unretained(this), local_state);

  rev_checking_enabled_.Init(prefs::kCertRevocationCheckingEnabled, local_state,
                             local_state_callback);
  rev_checking_required_local_anchors_.Init(
      prefs::kCertRevocationCheckingRequiredLocalAnchors, local_state,
      local_state_callback);
  symantec_legacy_infrastructure_enabled_.Init(
      prefs::kCertEnableSymantecLegacyInfrastructure, local_state,
      local_state_callback);
  ssl_version_min_.Init(prefs::kSSLVersionMin, local_state,
                        local_state_callback);
  ssl_version_max_.Init(prefs::kSSLVersionMax, local_state,
                        local_state_callback);
  tls13_variant_.Init(prefs::kTLS13Variant, local_state, local_state_callback);
  h2_client_cert_coalescing_host_patterns_.Init(
      prefs::kH2ClientCertCoalescingHosts, local_state, local_state_callback);

  local_state_change_registrar_.Init(local_state);
  local_state_change_registrar_.Add(prefs::kCipherSuiteBlacklist,
                                    local_state_callback);

  // Populate |disabled_cipher_suites_| with the initial pref value.
  OnDisabledCipherSuitesChange(local_state);
}

// static
void SSLConfigServiceManagerPref::RegisterPrefs(PrefRegistrySimple* registry) {
  net::SSLConfig default_config;
  net::CertVerifier::Config default_verifier_config;
  registry->RegisterBooleanPref(prefs::kCertRevocationCheckingEnabled,
                                default_verifier_config.enable_rev_checking);
  registry->RegisterBooleanPref(
      prefs::kCertRevocationCheckingRequiredLocalAnchors,
      default_verifier_config.require_rev_checking_local_anchors);
  registry->RegisterBooleanPref(
      prefs::kCertEnableSymantecLegacyInfrastructure,
      default_verifier_config.disable_symantec_enforcement);
  registry->RegisterStringPref(prefs::kSSLVersionMin, std::string());
  registry->RegisterStringPref(prefs::kSSLVersionMax, std::string());
  registry->RegisterStringPref(prefs::kTLS13Variant, std::string());
  registry->RegisterListPref(prefs::kCipherSuiteBlacklist);
  registry->RegisterListPref(prefs::kH2ClientCertCoalescingHosts);
}

void SSLConfigServiceManagerPref::AddToNetworkContextParams(
    network::mojom::NetworkContextParams* network_context_params) {
  network_context_params->initial_ssl_config = GetSSLConfigFromPrefs();
  network::mojom::SSLConfigClientPtr ssl_config_client;
  network_context_params->ssl_config_client_request =
      mojo::MakeRequest(&ssl_config_client);
  ssl_config_client_set_.AddPtr(std::move(ssl_config_client));
}

void SSLConfigServiceManagerPref::FlushForTesting() {
  ssl_config_client_set_.FlushForTesting();
}

void SSLConfigServiceManagerPref::OnPreferenceChanged(
    PrefService* prefs,
    const std::string& pref_name_in) {
  DCHECK(prefs);
  if (pref_name_in == prefs::kCipherSuiteBlacklist)
    OnDisabledCipherSuitesChange(prefs);

  network::mojom::SSLConfigPtr new_config = GetSSLConfigFromPrefs();
  network::mojom::SSLConfig* raw_config = new_config.get();

  ssl_config_client_set_.ForAllPtrs(
      [raw_config](network::mojom::SSLConfigClient* client) {
        // Mojo calls consume all InterfacePtrs passed to them, so have to
        // clone the config for each call.
        client->OnSSLConfigUpdated(raw_config->Clone());
      });
}

network::mojom::SSLConfigPtr
SSLConfigServiceManagerPref::GetSSLConfigFromPrefs() const {
  network::mojom::SSLConfigPtr config = network::mojom::SSLConfig::New();

  // rev_checking_enabled was formerly a user-settable preference, but now
  // it is managed-only.
  if (rev_checking_enabled_.IsManaged())
    config->rev_checking_enabled = rev_checking_enabled_.GetValue();
  else
    config->rev_checking_enabled = false;
  config->rev_checking_required_local_anchors =
      rev_checking_required_local_anchors_.GetValue();
  config->symantec_enforcement_disabled =
      symantec_legacy_infrastructure_enabled_.GetValue();
  std::string version_min_str = ssl_version_min_.GetValue();
  std::string version_max_str = ssl_version_max_.GetValue();
  std::string tls13_variant_str = tls13_variant_.GetValue();

  network::mojom::SSLVersion version_min;
  if (SSLProtocolVersionFromString(version_min_str, &version_min))
    config->version_min = version_min;

  network::mojom::SSLVersion version_max;
  if (SSLProtocolVersionFromString(version_max_str, &version_max) &&
      version_max >= network::mojom::SSLVersion::kTLS12) {
    config->version_max = version_max;
  }

  if (tls13_variant_str == switches::kTLS13VariantDisabled) {
    if (config->version_max > network::mojom::SSLVersion::kTLS12)
      config->version_max = network::mojom::SSLVersion::kTLS12;
  } else if (tls13_variant_str == switches::kTLS13VariantDraft23) {
    config->tls13_variant = network::mojom::TLS13Variant::kDraft23;
  } else if (tls13_variant_str == switches::kTLS13VariantFinal) {
    config->tls13_variant = network::mojom::TLS13Variant::kFinal;
  }

  config->disabled_cipher_suites = disabled_cipher_suites_;
  config->client_cert_pooling_policy = CanonicalizeHostnamePatterns(
      h2_client_cert_coalescing_host_patterns_.GetValue());

  return config;
}

void SSLConfigServiceManagerPref::OnDisabledCipherSuitesChange(
    PrefService* local_state) {
  const base::ListValue* value =
      local_state->GetList(prefs::kCipherSuiteBlacklist);
  disabled_cipher_suites_ = ParseCipherSuites(ListValueToStringVector(value));
}

}  // namespace

////////////////////////////////////////////////////////////////////////////////
//  SSLConfigServiceManager

// static
SSLConfigServiceManager* SSLConfigServiceManager::CreateDefaultManager(
    PrefService* local_state) {
  return new SSLConfigServiceManagerPref(local_state);
}

// static
void SSLConfigServiceManager::RegisterPrefs(PrefRegistrySimple* registry) {
  SSLConfigServiceManagerPref::RegisterPrefs(registry);
}
