// Licensed to the Apache Software Foundation (ASF) under one
// or more contributor license agreements.  See the NOTICE file
// distributed with this work for additional information
// regarding copyright ownership.  The ASF licenses this file
// to you under the Apache License, Version 2.0 (the
// "License"); you may not use this file except in compliance
// with the License.  You may obtain a copy of the License at
//
//   http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing,
// software distributed under the License is distributed on an
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
// KIND, either express or implied.  See the License for the
// specific language governing permissions and limitations
// under the License.

#include "kudu/security/tls_context.h"

#include <mutex>
#include <string>
#include <vector>

#include <boost/algorithm/string/predicate.hpp>
#include <gflags/gflags.h>
#include <openssl/err.h>
#include <openssl/ssl.h>
#include <openssl/x509.h>
#include <openssl/x509v3.h>

#include "kudu/gutil/strings/substitute.h"
#include "kudu/security/ca/cert_management.h"
#include "kudu/security/cert.h"
#include "kudu/security/crypto.h"
#include "kudu/security/init.h"
#include "kudu/security/openssl_util.h"
#include "kudu/security/security_flags.h"
#include "kudu/security/tls_handshake.h"
#include "kudu/util/flag_tags.h"
#include "kudu/util/net/net_util.h"
#include "kudu/util/scoped_cleanup.h"
#include "kudu/util/status.h"
#include "kudu/util/user.h"

using strings::Substitute;
using std::string;
using std::unique_lock;

DEFINE_int32_hidden(ipki_server_key_size, 2048,
             "the number of bits for server cert's private key. The server cert "
             "is used for TLS connections to and from clients and other servers.");
TAG_FLAG(ipki_server_key_size, experimental);

namespace kudu {
namespace security {

using ca::CertRequestGenerator;

template<> struct SslTypeTraits<SSL> {
  static constexpr auto kFreeFunc = &SSL_free;
};
template<> struct SslTypeTraits<X509_STORE_CTX> {
  static constexpr auto kFreeFunc = &X509_STORE_CTX_free;
};

TlsContext::TlsContext()
    : tls_ciphers_(kudu::security::SecurityDefaults::kDefaultTlsCiphers),
      tls_min_protocol_(kudu::security::SecurityDefaults::kDefaultTlsMinVersion),
      lock_(RWMutex::Priority::PREFER_READING),
      trusted_cert_count_(0),
      has_cert_(false),
      is_external_cert_(false) {
  security::InitializeOpenSSL();
}

TlsContext::TlsContext(std::string tls_ciphers, std::string tls_min_protocol)
    : tls_ciphers_(std::move(tls_ciphers)),
      tls_min_protocol_(std::move(tls_min_protocol)),
      lock_(RWMutex::Priority::PREFER_READING),
      trusted_cert_count_(0),
      has_cert_(false),
      is_external_cert_(false) {
  security::InitializeOpenSSL();
}

Status TlsContext::Init() {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  CHECK(!ctx_);

  // NOTE: 'SSLv23 method' sounds like it would enable only SSLv2 and SSLv3, but in fact
  // this is a sort of wildcard which enables all methods (including TLSv1 and later).
  // We explicitly disable SSLv2 and SSLv3 below so that only TLS methods remain.
  // See the discussion on https://trac.torproject.org/projects/tor/ticket/11598 for more
  // info.
  ctx_ = ssl_make_unique(SSL_CTX_new(SSLv23_method()));
  if (!ctx_) {
    return Status::RuntimeError("failed to create TLS context", GetOpenSSLErrors());
  }
  SSL_CTX_set_mode(ctx_.get(), SSL_MODE_AUTO_RETRY | SSL_MODE_ENABLE_PARTIAL_WRITE);

  // Disable SSLv2 and SSLv3 which are vulnerable to various issues such as POODLE.
  // We support versions back to TLSv1.0 since OpenSSL on RHEL 6.4 and earlier does not
  // not support TLSv1.1 or later.
  //
  // Disable SSL/TLS compression to free up CPU resources and be less prone
  // to attacks exploiting the compression feature:
  //   https://tools.ietf.org/html/rfc7525#section-3.3
  auto options = SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_COMPRESSION;

  if (boost::iequals(tls_min_protocol_, "TLSv1.2")) {
#if OPENSSL_VERSION_NUMBER < 0x10001000L
    return Status::InvalidArgument(
        "--rpc_tls_min_protocol=TLSv1.2 is not be supported on this platform. "
        "TLSv1 is the latest supported TLS protocol.");
#else
    options |= SSL_OP_NO_TLSv1 | SSL_OP_NO_TLSv1_1;
#endif
  } else if (boost::iequals(tls_min_protocol_, "TLSv1.1")) {
#if OPENSSL_VERSION_NUMBER < 0x10001000L
    return Status::InvalidArgument(
        "--rpc_tls_min_protocol=TLSv1.1 is not be supported on this platform. "
        "TLSv1 is the latest supported TLS protocol.");
#else
    options |= SSL_OP_NO_TLSv1;
#endif
  } else if (!boost::iequals(tls_min_protocol_, "TLSv1")) {
    return Status::InvalidArgument("unknown value provided for --rpc_tls_min_protocol flag",
                                   tls_min_protocol_);
  }

  SSL_CTX_set_options(ctx_.get(), options);

  OPENSSL_RET_NOT_OK(
      SSL_CTX_set_cipher_list(ctx_.get(), tls_ciphers_.c_str()),
      "failed to set TLS ciphers");

  // Enable ECDH curves. For OpenSSL 1.1.0 and up, this is done automatically.
#ifndef OPENSSL_NO_ECDH
#if OPENSSL_VERSION_NUMBER < 0x10002000L
  // OpenSSL 1.0.1 and below only support setting a single ECDH curve at once.
  // We choose prime256v1 because it's the first curve listed in the "modern
  // compatibility" section of the Mozilla Server Side TLS recommendations,
  // accessed Feb. 2017.
  c_unique_ptr<EC_KEY> ecdh { EC_KEY_new_by_curve_name(NID_X9_62_prime256v1), &EC_KEY_free };
  OPENSSL_RET_IF_NULL(ecdh, "failed to create prime256v1 curve");
  OPENSSL_RET_NOT_OK(SSL_CTX_set_tmp_ecdh(ctx_.get(), ecdh.get()),
                     "failed to set ECDH curve");
#elif OPENSSL_VERSION_NUMBER < 0x10100000L
  // OpenSSL 1.0.2 provides the set_ecdh_auto API which internally figures out
  // the best curve to use.
  OPENSSL_RET_NOT_OK(SSL_CTX_set_ecdh_auto(ctx_.get(), 1),
                     "failed to configure ECDH support");
#endif
#endif

  // TODO(KUDU-1926): is it possible to disable client-side renegotiation? it seems there
  // have been various CVEs related to this feature that we don't need.
  return Status::OK();
}

Status TlsContext::VerifyCertChainUnlocked(const Cert& cert) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  X509_STORE* store = SSL_CTX_get_cert_store(ctx_.get());
  auto store_ctx = ssl_make_unique<X509_STORE_CTX>(X509_STORE_CTX_new());

  OPENSSL_RET_NOT_OK(X509_STORE_CTX_init(store_ctx.get(), store, cert.GetTopOfChainX509(), nullptr),
                     "could not init X509_STORE_CTX");
  int rc = X509_verify_cert(store_ctx.get());
  if (rc != 1) {
    int err = X509_STORE_CTX_get_error(store_ctx.get());
    if (err == X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT) {
      // It's OK to provide a self-signed cert.
      ERR_clear_error(); // in case it left anything on the queue.
      return Status::OK();
    }

    // Get the cert that failed to verify.
    X509* cur_cert = X509_STORE_CTX_get_current_cert(store_ctx.get());
    string cert_details;
    if (cur_cert) {
      cert_details = Substitute(" (error with cert: subject=$0, issuer=$1)",
                                X509NameToString(X509_get_subject_name(cur_cert)),
                                X509NameToString(X509_get_issuer_name(cur_cert)));
    }

    ERR_clear_error(); // in case it left anything on the queue.
    return Status::RuntimeError(
        Substitute("could not verify certificate chain$0", cert_details),
        X509_verify_cert_error_string(err));
  }
  return Status::OK();
}

Status TlsContext::UseCertificateAndKey(const Cert& cert, const PrivateKey& key) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  // Verify that the cert and key match.
  RETURN_NOT_OK(cert.CheckKeyMatch(key));

  std::unique_lock<RWMutex> lock(lock_);

  // Verify that the appropriate CA certs have been loaded into the context
  // before we adopt a cert. Otherwise, client connections without the CA cert
  // available would fail.
  RETURN_NOT_OK(VerifyCertChainUnlocked(cert));

  CHECK(!has_cert_);

  OPENSSL_RET_NOT_OK(SSL_CTX_use_PrivateKey(ctx_.get(), key.GetRawData()),
                     "failed to use private key");
  OPENSSL_RET_NOT_OK(SSL_CTX_use_certificate(ctx_.get(), cert.GetTopOfChainX509()),
                     "failed to use certificate");
  has_cert_ = true;
  return Status::OK();
}

Status TlsContext::AddTrustedCertificate(const Cert& cert) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  VLOG(2) << "Trusting certificate " << cert.SubjectName();

  {
    // Workaround for a leak in OpenSSL <1.0.1:
    //
    // If we start trusting a cert, and its internal public-key field hasn't
    // yet been populated, then the first time it's used for verification will
    // populate it. In the case that two threads try to populate it at the same time,
    // one of the thread's copies will be leaked.
    //
    // To avoid triggering the race, we populate the internal public key cache
    // field up front before adding it to the trust store.
    //
    // See OpenSSL commit 33a688e80674aaecfac6d9484ec199daa0ee5b61.
    PublicKey k;
    CHECK_OK(cert.GetPublicKey(&k));
  }

  unique_lock<RWMutex> lock(lock_);
  auto* cert_store = SSL_CTX_get_cert_store(ctx_.get());

  // Iterate through the certificate chain and add each individual certificate to the store.
  for (int i = 0; i < cert.chain_len(); ++i) {
    X509* inner_cert = sk_X509_value(cert.GetRawData(), i);
    int rc = X509_STORE_add_cert(cert_store, inner_cert);
    if (rc <= 0) {
      // Ignore the common case of re-adding a cert that is already in the
      // trust store.
      auto err = ERR_peek_error();
      if (ERR_GET_LIB(err) == ERR_LIB_X509 &&
          ERR_GET_REASON(err) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
        ERR_clear_error();
        return Status::OK();
      }
      OPENSSL_RET_NOT_OK(rc, "failed to add trusted certificate");
    }
  }
  trusted_cert_count_ += 1;
  return Status::OK();
}

Status TlsContext::DumpTrustedCerts(vector<string>* cert_ders) const {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  shared_lock<RWMutex> lock(lock_);

  vector<string> ret;
  auto* cert_store = SSL_CTX_get_cert_store(ctx_.get());

  CRYPTO_w_lock(CRYPTO_LOCK_X509_STORE);
  auto unlock = MakeScopedCleanup([&]() {
      CRYPTO_w_unlock(CRYPTO_LOCK_X509_STORE);
    });
  for (int i = 0; i < sk_X509_OBJECT_num(cert_store->objs); i++) {
    X509_OBJECT* obj = sk_X509_OBJECT_value(cert_store->objs, i);
    if (obj->type != X509_LU_X509) continue;
    Cert c;
    c.AdoptAndAddRefX509(obj->data.x509);
    string der;
    RETURN_NOT_OK(c.ToString(&der, DataFormat::DER));
    ret.emplace_back(std::move(der));
  }

  cert_ders->swap(ret);
  return Status::OK();
}

namespace {
Status SetCertAttributes(CertRequestGenerator::Config* config) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  RETURN_NOT_OK_PREPEND(GetFQDN(&config->hostname), "could not determine FQDN for CSR");

  // If the server has logged in from a keytab, then we have a 'real' identity,
  // and our desired CN should match the local username mapped from the Kerberos
  // principal name. Otherwise, we'll make up a common name based on the hostname.
  boost::optional<string> principal = GetLoggedInPrincipalFromKeytab();
  if (!principal) {
    string uid;
    RETURN_NOT_OK_PREPEND(GetLoggedInUser(&uid),
                          "couldn't get local username");
    config->user_id = uid;
    return Status::OK();
  }
  string uid;
  RETURN_NOT_OK_PREPEND(security::MapPrincipalToLocalName(*principal, &uid),
                        "could not get local username for krb5 principal");
  config->user_id = uid;
  config->kerberos_principal = *principal;
  return Status::OK();
}
} // anonymous namespace

Status TlsContext::GenerateSelfSignedCertAndKey() {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  // Step 1: generate the private key to be self signed.
  PrivateKey key;
  RETURN_NOT_OK_PREPEND(GeneratePrivateKey(FLAGS_ipki_server_key_size,
                                           &key),
                                           "failed to generate private key");

  // Step 2: generate a CSR so that the self-signed cert can eventually be
  // replaced with a CA-signed cert.
  CertRequestGenerator::Config config;
  RETURN_NOT_OK(SetCertAttributes(&config));
  CertRequestGenerator gen(config);
  RETURN_NOT_OK_PREPEND(gen.Init(), "could not initialize CSR generator");
  CertSignRequest csr;
  RETURN_NOT_OK_PREPEND(gen.GenerateRequest(key, &csr), "could not generate CSR");

  // Step 3: generate a self-signed cert that we can use for terminating TLS
  // connections until we get the CA-signed cert.
  Cert cert;
  RETURN_NOT_OK_PREPEND(ca::CertSigner::SelfSignCert(key, config, &cert),
                        "failed to self-sign cert");

  // Workaround for an OpenSSL memory leak caused by a race in x509v3_cache_extensions.
  // Upon first use of each certificate, this function gets called to parse various
  // fields of the certificate. However, it's racey, so if multiple "first calls"
  // happen concurrently, one call overwrites the cached data from another, causing
  // a leak. Calling this nonsense X509_check_ca() forces the X509 extensions to
  // get cached, so we don't hit the race later. 'VerifyCertChain' also has the
  // effect of triggering the racy codepath.
  ignore_result(X509_check_ca(cert.GetTopOfChainX509()));
  ERR_clear_error(); // in case it left anything on the queue.

  // Step 4: Adopt the new key and cert.
  unique_lock<RWMutex> lock(lock_);
  CHECK(!has_cert_);
  OPENSSL_RET_NOT_OK(SSL_CTX_use_PrivateKey(ctx_.get(), key.GetRawData()),
                     "failed to use private key");
  OPENSSL_RET_NOT_OK(SSL_CTX_use_certificate(ctx_.get(), cert.GetTopOfChainX509()),
                     "failed to use certificate");
  has_cert_ = true;
  csr_ = std::move(csr);
  return Status::OK();
}

boost::optional<CertSignRequest> TlsContext::GetCsrIfNecessary() const {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  shared_lock<RWMutex> lock(lock_);
  if (csr_) {
    return csr_->Clone();
  }
  return boost::none;
}

Status TlsContext::AdoptSignedCert(const Cert& cert) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  unique_lock<RWMutex> lock(lock_);

  // Verify that the appropriate CA certs have been loaded into the context
  // before we adopt a cert. Otherwise, client connections without the CA cert
  // available would fail.
  RETURN_NOT_OK(VerifyCertChainUnlocked(cert));

  if (!csr_) {
    // A signed cert has already been adopted.
    return Status::OK();
  }

  PublicKey csr_key;
  RETURN_NOT_OK(csr_->GetPublicKey(&csr_key));
  PublicKey cert_key;
  RETURN_NOT_OK(cert.GetPublicKey(&cert_key));
  bool equals;
  RETURN_NOT_OK(csr_key.Equals(cert_key, &equals));
  if (!equals) {
    return Status::RuntimeError("certificate public key does not match the CSR public key");
  }

  OPENSSL_RET_NOT_OK(SSL_CTX_use_certificate(ctx_.get(), cert.GetTopOfChainX509()),
                     "failed to use certificate");

  // This should never fail since we already compared the cert's public key
  // against the CSR, but better safe than sorry. If this *does* fail, it
  // appears to remove the private key from the SSL_CTX, so we are left in a bad
  // state.
  OPENSSL_CHECK_OK(SSL_CTX_check_private_key(ctx_.get()))
    << "certificate does not match the private key";

  csr_ = boost::none;

  return Status::OK();
}

Status TlsContext::LoadCertificateAndKey(const string& certificate_path,
                                         const string& key_path) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  Cert c;
  RETURN_NOT_OK(c.FromFile(certificate_path, DataFormat::PEM));
  PrivateKey k;
  RETURN_NOT_OK(k.FromFile(key_path, DataFormat::PEM));
  is_external_cert_ = true;
  return UseCertificateAndKey(c, k);
}

Status TlsContext::LoadCertificateAndPasswordProtectedKey(const string& certificate_path,
                                                          const string& key_path,
                                                          const PasswordCallback& password_cb) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  Cert c;
  RETURN_NOT_OK_PREPEND(c.FromFile(certificate_path, DataFormat::PEM),
                        "failed to load certificate");
  PrivateKey k;
  RETURN_NOT_OK_PREPEND(k.FromFile(key_path, DataFormat::PEM, password_cb),
                        "failed to load private key file");
  RETURN_NOT_OK(UseCertificateAndKey(c, k));
  is_external_cert_ = true;
  return Status::OK();
}

Status TlsContext::LoadCertificateAuthority(const string& certificate_path) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  if (has_cert_) DCHECK(is_external_cert_);
  Cert c;
  RETURN_NOT_OK(c.FromFile(certificate_path, DataFormat::PEM));
  return AddTrustedCertificate(c);
}

Status TlsContext::InitiateHandshake(TlsHandshakeType handshake_type,
                                     TlsHandshake* handshake) const {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  CHECK(ctx_);
  CHECK(!handshake->ssl_);
  {
    shared_lock<RWMutex> lock(lock_);
    handshake->adopt_ssl(ssl_make_unique(SSL_new(ctx_.get())));
  }
  if (!handshake->ssl_) {
    return Status::RuntimeError("failed to create SSL handle", GetOpenSSLErrors());
  }

  SSL_set_bio(handshake->ssl(),
              BIO_new(BIO_s_mem()),
              BIO_new(BIO_s_mem()));

  switch (handshake_type) {
    case TlsHandshakeType::SERVER:
      SSL_set_accept_state(handshake->ssl());
      break;
    case TlsHandshakeType::CLIENT:
      SSL_set_connect_state(handshake->ssl());
      break;
  }

  return Status::OK();
}

} // namespace security
} // namespace kudu
