// 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/util/openssl_util.h"

#include <openssl/crypto.h>
#include <openssl/err.h>
#include <openssl/rand.h> // IWYU pragma: keep

#include <cerrno>
#include <cstdint>
#include <cstdio>
#include <mutex>
#include <string>
#include <vector>

#include <glog/logging.h>

#include "kudu/gutil/strings/split.h"
#include "kudu/gutil/strings/strip.h"
#include "kudu/gutil/strings/substitute.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include "kudu/util/debug/leakcheck_disabler.h"
#endif
#include "kudu/util/errno.h"
#include "kudu/util/flags.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include "kudu/util/mutex.h"
#endif
#include "kudu/util/scoped_cleanup.h"
#include "kudu/util/status.h"
#include "kudu/util/subprocess.h"
#if OPENSSL_VERSION_NUMBER < 0x10100000L
#include "kudu/util/thread.h"
#endif

using std::ostringstream;
using std::string;
using std::vector;

namespace kudu {
namespace security {

namespace {

// Determine whether initialization was ever called.
//
// Thread safety:
// - written by DoInitializeOpenSSL (single-threaded, due to std::call_once)
// - read by DisableOpenSSLInitialization (must not be concurrent with above)
bool g_ssl_is_initialized = false;

// If true, then we expect someone else has initialized SSL.
//
// Thread safety:
// - read by DoInitializeOpenSSL (single-threaded, due to std::call_once)
// - written by DisableOpenSSLInitialization (must not be concurrent with above)
bool g_disable_ssl_init = false;

// Array of locks used by OpenSSL.
// We use an intentionally-leaked C-style array here to avoid non-POD static data.
//
// As of OpenSSL 1.1, locking callbacks are no longer used.
#if OPENSSL_VERSION_NUMBER < 0x10100000L
Mutex* kCryptoLocks = nullptr;

// Lock/Unlock the nth lock. Only to be used by OpenSSL.
void LockingCB(int mode, int type, const char* /*file*/, int /*line*/) {
  DCHECK(kCryptoLocks);
  Mutex* m = &kCryptoLocks[type];
  if (mode & CRYPTO_LOCK) {
    m->lock();
  } else {
    m->unlock();
  }
}

void ThreadIdCB(CRYPTO_THREADID* tid) {
  CRYPTO_THREADID_set_numeric(tid, Thread::UniqueThreadId());
}
#endif

void CheckFIPSMode() {
  auto fips_mode = FIPS_mode();
  // If the environment variable KUDU_REQUIRE_FIPS_MODE is set to "1", we
  // check if FIPS approved mode is enabled. If not, we crash the process.
  // As this is used in clients as well, we can't use gflags to set this.
  if (GetBooleanEnvironmentVariable("KUDU_REQUIRE_FIPS_MODE")) {
    CHECK(fips_mode) << "FIPS mode required by environment variable "
                        "KUDU_REQUIRE_FIPS_MODE, but it is not enabled.";
  }
  VLOG(2) << "FIPS mode is " << (fips_mode ? "enabled" : "disabled.");
}

Status CheckOpenSSLInitialized() {
#if OPENSSL_VERSION_NUMBER < 0x10100000L
  // Starting with OpenSSL 1.1.0, the old thread API became obsolete
  // (see changelist 2e52e7df5 in the OpenSSL upstream repo), and
  // CRYPTO_get_locking_callback() always returns nullptr. Also, the library
  // always initializes its internals for multi-threaded usage.
  // Another point is that starting with version 1.1.0, SSL_CTX_new()
  // initializes the OpenSSL library under the hood, so SSL_CTX_new() would
  // not return nullptr unless there was an error during the initialization
  // of the library. That makes this code in CheckOpenSSLInitialized() obsolete
  // starting with OpenSSL version 1.1.0.
  //
  // Starting with OpenSSL 1.1.0, there isn't a straightforward way to
  // determine whether the library has already been initialized if using just
  // the API (well, there is CRYPTO_secure_malloc_initialized() but that's just
  // for the crypto library and it's implementation-dependent). But from the
  // other side, the whole idea that this method should check whether the
  // library has already been initialized is not relevant anymore: even if it's
  // not yet initialized, the first call to SSL_CTX_new() (from, say,
  // TlsContext::Init()) will initialize the library under the hood, so the
  // library will be ready for multi-thread usage by Kudu.
  if (!CRYPTO_get_locking_callback()) {
    return Status::RuntimeError("Locking callback not initialized");
  }
  auto ctx = ssl_make_unique(SSL_CTX_new(SSLv23_method()));
  if (!ctx) {
    ERR_clear_error();
    return Status::RuntimeError(
        "SSL library appears uninitialized (cannot create SSL_CTX)");
  }
#endif
  CheckFIPSMode();
  return Status::OK();
}

void DoInitializeOpenSSL() {
  // In case the user's thread has left some error around, clear it.
  ERR_clear_error();
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  if (g_disable_ssl_init) {
    VLOG(2) << "Not initializing OpenSSL (disabled by application)";
    return;
  }
#if OPENSSL_VERSION_NUMBER >= 0x10100000L
  // The OPENSSL_init_ssl manpage [1] says "As of version 1.1.0 OpenSSL will
  // automatically allocate all resources it needs so no explicit initialisation
  // is required." However, eliding library initialization leads to a memory
  // leak in some versions of OpenSSL 1.1 when the first OpenSSL call is
  // ERR_peek_error (see [2] for details; the issue was addressed in OpenSSL
  // 1.1.0i (OPENSSL_VERSION_NUMBER 0x1010009f)). In Kudu this is often the
  // case due to prolific application of the SCOPED_OPENSSL_NO_PENDING_ERRORS
  // macro.
  //
  // Rather than determine whether this particular OpenSSL instance is
  // leak-free, we'll initialize the library explicitly.
  //
  // 1. https://www.openssl.org/docs/man1.1.0/ssl/OPENSSL_init_ssl.html
  // 2. https://github.com/openssl/openssl/issues/5899
  CHECK_EQ(1, OPENSSL_init_ssl(0, nullptr));
#else
  // Check that OpenSSL isn't already initialized. If it is, it's likely
  // we are embedded in (or embedding) another application/library which
  // initializes OpenSSL, and we risk installing conflicting callbacks
  // or crashing due to concurrent initialization attempts. In that case,
  // log a warning.
  auto ctx = ssl_make_unique(SSL_CTX_new(SSLv23_method()));
  if (ctx) {
    LOG(WARNING) << "It appears that OpenSSL has been previously initialized by "
                    "code outside of Kudu. Please first properly initialize "
                    "OpenSSL for multi-threaded usage (setting thread callback "
                    "functions for OpenSSL of versions earlier than 1.1.0) and "
                    "then call kudu::client::DisableOpenSSLInitialization() "
                    "to avoid potential crashes due to conflicting initialization.";
    // Continue anyway; all of the below is idempotent, except for the locking callback,
    // which we check before overriding. They aren't thread-safe, however -- that's why
    // we try to get embedding applications to do the right thing here rather than risk a
    // potential initialization race.
  } else {
    // As expected, SSL is not initialized, so SSL_CTX_new() failed. Make sure
    // it didn't leave anything in our error queue.
    ERR_clear_error();
  }

  SSL_load_error_strings();
  SSL_library_init();
  OpenSSL_add_all_algorithms();
  RAND_poll();

  if (!CRYPTO_get_locking_callback()) {
    // Initialize the OpenSSL mutexes. We intentionally leak these, so ignore
    // LSAN warnings.
    debug::ScopedLeakCheckDisabler d;
    int num_locks = CRYPTO_num_locks();
    CHECK(!kCryptoLocks);
    kCryptoLocks = new Mutex[num_locks];

    // Callbacks used by OpenSSL required in a multi-threaded setting.
    CRYPTO_set_locking_callback(LockingCB);

    CRYPTO_THREADID_set_callback(ThreadIdCB);
  }
#endif
  CheckFIPSMode();
  g_ssl_is_initialized = true;
}

} // anonymous namespace

// Reads a STACK_OF(X509) from the BIO and returns it.
STACK_OF(X509)* PEM_read_STACK_OF_X509(BIO* bio, void* /* unused */, pem_password_cb* /* unused */,
    void* /* unused */) {
  // Extract information from the chain certificate.
  STACK_OF(X509_INFO)* info = PEM_X509_INFO_read_bio(bio, nullptr, nullptr, nullptr);
  if (!info) return nullptr;
  SCOPED_CLEANUP({
    sk_X509_INFO_pop_free(info, X509_INFO_free);
  });

  // Initialize the Stack.
  STACK_OF(X509)* sk = sk_X509_new_null();

  // Iterate through the chain certificate and add each one to the stack.
  for (int i = 0; i < sk_X509_INFO_num(info); ++i) {
    X509_INFO *stack_item = sk_X509_INFO_value(info, i);
    sk_X509_push(sk, stack_item->x509);
    // We don't want the ScopedCleanup to free the x509 certificates as well since we will
    // use it as a part of the STACK_OF(X509) object to be returned, so we set it to nullptr.
    // We will take the responsibility of freeing it when we are done with the STACK_OF(X509).
    stack_item->x509 = nullptr;
  }
  return sk;
}

// Writes a STACK_OF(X509) to the BIO.
int PEM_write_STACK_OF_X509(BIO* bio, STACK_OF(X509)* obj) {
  int chain_len = sk_X509_num(obj);
  // Iterate through the stack and add each one to the BIO.
  for (int i = 0; i < chain_len; ++i) {
    X509* cert_item = sk_X509_value(obj, i);
    int ret = PEM_write_bio_X509(bio, cert_item);
    if (ret <= 0) return ret;
  }
  return 1;
}

// Reads a single X509 certificate and returns a STACK_OF(X509) with the single certificate.
STACK_OF(X509)* DER_read_STACK_OF_X509(BIO* bio, void* /* unused */) {
  // We don't support chain certificates written in DER format.
  auto x = ssl_make_unique(d2i_X509_bio(bio, nullptr));
  if (!x) return nullptr;
  STACK_OF(X509)* sk = sk_X509_new_null();
  if (sk_X509_push(sk, x.get()) == 0) {
    return nullptr;
  }
  x.release();
  return sk;
}

// Writes a single X509 certificate that it gets from the STACK_OF(X509) 'obj'.
int DER_write_STACK_OF_X509(BIO* bio, STACK_OF(X509)* obj) {
  int chain_len = sk_X509_num(obj);
  // We don't support chain certificates written in DER format.
  DCHECK_EQ(chain_len, 1);
  X509* cert_item = sk_X509_value(obj, 0);
  if (cert_item == nullptr) return 0;
  return i2d_X509_bio(bio, cert_item);
}

void free_STACK_OF_X509(STACK_OF(X509)* sk) {
  sk_X509_pop_free(sk, X509_free);
}

Status DisableOpenSSLInitialization() {
  if (g_disable_ssl_init) return Status::OK();
  if (g_ssl_is_initialized) {
    return Status::IllegalState("SSL already initialized. Initialization can only be disabled "
                                "before first usage.");
  }
  RETURN_NOT_OK(CheckOpenSSLInitialized());
  g_disable_ssl_init = true;
  return Status::OK();
}

void InitializeOpenSSL() {
  static std::once_flag ssl_once;
  std::call_once(ssl_once, DoInitializeOpenSSL);
}

string GetOpenSSLErrors() {
  ostringstream serr;
  uint32_t l;
  int line, flags;
  const char *file, *data;
  bool is_first = true;
  while ((l = ERR_get_error_line_data(&file, &line, &data, &flags)) != 0) {
    if (is_first) {
      is_first = false;
    } else {
      serr << " ";
    }

    char buf[256];
    ERR_error_string_n(l, buf, sizeof(buf));
    serr << buf << ":" << file << ":" << line;
    if (flags & ERR_TXT_STRING) {
      serr << ":" << data;
    }
  }
  return serr.str();
}

string GetSSLErrorDescription(int error_code) {
  switch (error_code) {
    case SSL_ERROR_NONE: return "";
    case SSL_ERROR_ZERO_RETURN: return "SSL_ERROR_ZERO_RETURN";
    case SSL_ERROR_WANT_READ: return "SSL_ERROR_WANT_READ";
    case SSL_ERROR_WANT_WRITE: return "SSL_ERROR_WANT_WRITE";
    case SSL_ERROR_WANT_CONNECT: return "SSL_ERROR_WANT_CONNECT";
    case SSL_ERROR_WANT_ACCEPT: return "SSL_ERROR_WANT_ACCEPT";
    case SSL_ERROR_WANT_X509_LOOKUP: return "SSL_ERROR_WANT_X509_LOOKUP";
    case SSL_ERROR_SYSCALL: {
      string queued_error = GetOpenSSLErrors();
      if (!queued_error.empty()) {
        return queued_error;
      }
      return kudu::ErrnoToString(errno);
    };
    default: return GetOpenSSLErrors();
  }
}

const string& DataFormatToString(DataFormat fmt) {
  static const string kStrFormatUnknown = "UNKNOWN";
  static const string kStrFormatDer = "DER";
  static const string kStrFormatPem = "PEM";
  switch (fmt) {
    case DataFormat::DER:
      return kStrFormatDer;
    case DataFormat::PEM:
      return kStrFormatPem;
    default:
      return kStrFormatUnknown;
  }
}

Status GetPasswordFromShellCommand(const string& cmd, string* password) {
  vector<string> argv = strings::Split(cmd, " ", strings::SkipEmpty());
  if (argv.empty()) {
    return Status::RuntimeError("invalid empty private key password command");
  }
  string stderr, stdout;
  Status s = Subprocess::Call(argv, "" /* stdin */, &stdout, &stderr);
  if (!s.ok()) {
    return Status::RuntimeError(strings::Substitute(
        "failed to run private key password command: $0", s.ToString()), stderr);
  }
  StripTrailingWhitespace(&stdout);
  *password = stdout;
  return Status::OK();
}

string GetProtocolName(const SSL* ssl) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  return SSL_get_version(ssl);
}

string GetCipherDescription(const SSL* ssl) {
  SCOPED_OPENSSL_NO_PENDING_ERRORS;
  const SSL_CIPHER* cipher = SSL_get_current_cipher(ssl);
  if (!cipher) {
    return "NONE";
  }
  char buf[512];
  const char* description = SSL_CIPHER_description(cipher, buf, sizeof(buf));
  if (!description) {
    return "NONE";
  }
  string ret(description);
  StripTrailingNewline(&ret);
  StripDupCharacters(&ret, ' ', 0);
  return ret;
}

} // namespace security
} // namespace kudu
