This is an automated email from the ASF dual-hosted git repository.

tarmstrong pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/impala.git

commit 6694d147002c9a713f486a9b58d1db74f0be2e85
Author: wzhou-code <wz...@cloudera.com>
AuthorDate: Thu Oct 29 22:32:03 2020 -0700

    IMPALA-10305: Sync Kudu's FIPS compliant changes
    
    kudu-3210 added FIPS compliant changes.
    This patch ports the following patches for kudu-3210 into Impala
    source tree:
      http://gerrit.cloudera.org:8080/16631/
      http://gerrit.cloudera.org:8080/16657/
      http://gerrit.cloudera.org:8080/16658/
      http://gerrit.cloudera.org:8080/16659/
    
    Testing:
     - Passed exhausive tests.
    
    Change-Id: I1aa5e69bf8470e3cfb316e8b6354ad29c28223f4
    Reviewed-on: http://gerrit.cloudera.org:8080/16684
    Reviewed-by: Impala Public Jenkins <impala-public-jenk...@cloudera.com>
    Tested-by: Impala Public Jenkins <impala-public-jenk...@cloudera.com>
---
 be/src/kudu/security/CMakeLists.txt             |  2 +-
 be/src/kudu/security/ca/cert_management-test.cc |  3 +-
 be/src/kudu/security/crypto.cc                  | 13 ++++
 be/src/kudu/security/openssl_util.cc            | 80 +++++++++++++++++++------
 be/src/kudu/security/openssl_util.h             | 33 ++++++----
 be/src/kudu/security/tls_context.cc             | 20 ++++++-
 be/src/kudu/security/tls_handshake.cc           | 24 ++++++--
 be/src/kudu/security/token-test.cc              |  2 +-
 be/src/kudu/util/flags.cc                       | 22 +++++++
 be/src/kudu/util/flags.h                        |  2 +
 be/src/kudu/util/test_util.cc                   | 55 +++++++----------
 be/src/kudu/util/test_util.h                    |  4 ++
 12 files changed, 187 insertions(+), 73 deletions(-)

diff --git a/be/src/kudu/security/CMakeLists.txt 
b/be/src/kudu/security/CMakeLists.txt
index 22e7442..9475e7d 100644
--- a/be/src/kudu/security/CMakeLists.txt
+++ b/be/src/kudu/security/CMakeLists.txt
@@ -73,9 +73,9 @@ set(SECURITY_SRCS
   ca/cert_management.cc
   cert.cc
   crypto.cc
-  kerberos_util.cc
   gssapi.cc
   init.cc
+  kerberos_util.cc
   openssl_util.cc
   ${PORTED_X509_CHECK_HOST_CC}
   security_flags.cc
diff --git a/be/src/kudu/security/ca/cert_management-test.cc 
b/be/src/kudu/security/ca/cert_management-test.cc
index 0c8abc8..f3e6c35 100644
--- a/be/src/kudu/security/ca/cert_management-test.cc
+++ b/be/src/kudu/security/ca/cert_management-test.cc
@@ -71,7 +71,8 @@ class CertManagementTest : public KuduTest {
   template<class CSRGen = CertRequestGenerator>
   CertSignRequest PrepareTestCSR(typename CSRGen::Config config,
                                  PrivateKey* key) {
-    CHECK_OK(GeneratePrivateKey(512, key));
+    int key_size = UseLargeKeys() ? 2048 : 512;
+    CHECK_OK(GeneratePrivateKey(key_size, key));
     CSRGen gen(std::move(config));
     CHECK_OK(gen.Init());
     CertSignRequest req;
diff --git a/be/src/kudu/security/crypto.cc b/be/src/kudu/security/crypto.cc
index 234d193..5e6fd16 100644
--- a/be/src/kudu/security/crypto.cc
+++ b/be/src/kudu/security/crypto.cc
@@ -18,6 +18,9 @@
 #include "kudu/security/crypto.h"
 
 #include <memory>
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+#include <mutex>
+#endif
 #include <ostream>
 #include <string>
 
@@ -67,6 +70,10 @@ int DerWritePublicKey(BIO* bio, EVP_PKEY* key) {
   return i2d_RSA_PUBKEY_bio(bio, rsa.get());
 }
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+OpenSSLMutex mutex;
+#endif
+
 } // anonymous namespace
 
 template<> struct SslTypeTraits<BIGNUM> {
@@ -136,6 +143,9 @@ Status PublicKey::VerifySignature(DigestType digest,
   const EVP_MD* md = GetMessageDigest(digest);
   auto md_ctx = ssl_make_unique(EVP_MD_CTX_create());
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  std::unique_lock<OpenSSLMutex> l(mutex);
+#endif
   OPENSSL_RET_NOT_OK(EVP_DigestVerifyInit(md_ctx.get(), nullptr, md, nullptr, 
GetRawData()),
                      "error initializing verification digest");
   OPENSSL_RET_NOT_OK(EVP_DigestVerifyUpdate(md_ctx.get(), data.data(), 
data.size()),
@@ -228,6 +238,9 @@ Status PrivateKey::MakeSignature(DigestType digest,
   const EVP_MD* md = GetMessageDigest(digest);
   auto md_ctx = ssl_make_unique(EVP_MD_CTX_create());
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  std::unique_lock<OpenSSLMutex> l(mutex);
+#endif
   OPENSSL_RET_NOT_OK(EVP_DigestSignInit(md_ctx.get(), nullptr, md, nullptr, 
GetRawData()),
                      "error initializing signing digest");
   OPENSSL_RET_NOT_OK(EVP_DigestSignUpdate(md_ctx.get(), data.data(), 
data.size()),
diff --git a/be/src/kudu/security/openssl_util.cc 
b/be/src/kudu/security/openssl_util.cc
index e96fcb3..7198db3 100644
--- a/be/src/kudu/security/openssl_util.cc
+++ b/be/src/kudu/security/openssl_util.cc
@@ -17,6 +17,10 @@
 
 #include "kudu/security/openssl_util.h"
 
+#include <openssl/crypto.h>
+#include <openssl/err.h>
+#include <openssl/rand.h> // IWYU pragma: keep
+
 #include <cerrno>
 #include <cstdint>
 #include <cstdio>
@@ -24,21 +28,35 @@
 #include <string>
 #include <vector>
 
+#include <gflags/gflags.h>
 #include <glog/logging.h>
-#include <openssl/crypto.h>
-#include <openssl/err.h>
-#include <openssl/rand.h>
 
+#include "kudu/gutil/macros.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/flag_tags.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"
 
+DEFINE_bool(openssl_defensive_locking,
+            false,
+            "If enabled, cryptographic methods lock more defensively to work 
around thread safety "
+            "issues in certain OpenSSL versions. This makes Kudu servers or 
clients more stable "
+            "when running on an affected OpenSSL version, sacrificing some 
performance.");
+TAG_FLAG(openssl_defensive_locking, unsafe);
+TAG_FLAG(openssl_defensive_locking, hidden);
+TAG_FLAG(openssl_defensive_locking, runtime);
+
 using std::ostringstream;
 using std::string;
 using std::vector;
@@ -81,6 +99,18 @@ void LockingCB(int mode, int type, const char* /*file*/, int 
/*line*/) {
 }
 #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
@@ -112,10 +142,18 @@ Status CheckOpenSSLInitialized() {
         "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
@@ -131,21 +169,8 @@ void DoInitializeOpenSSL() {
   //
   // 1. https://www.openssl.org/docs/man1.1.0/ssl/OPENSSL_init_ssl.html
   // 2. https://github.com/openssl/openssl/issues/5899
-  if (g_disable_ssl_init) {
-    VLOG(2) << "Not initializing OpenSSL (disabled by application)";
-    return;
-  }
   CHECK_EQ(1, OPENSSL_init_ssl(0, nullptr));
-  SCOPED_OPENSSL_NO_PENDING_ERRORS;
 #else
-  // 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;
-  }
-
   // 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
@@ -186,7 +211,7 @@ void DoInitializeOpenSSL() {
     CRYPTO_set_locking_callback(LockingCB);
   }
 #endif
-
+  CheckFIPSMode();
   g_ssl_is_initialized = true;
 }
 
@@ -345,5 +370,26 @@ Status GetPasswordFromShellCommand(const string& cmd, 
string* password) {
   return Status::OK();
 }
 
+OpenSSLMutex::OpenSSLMutex() : 
locking_enabled_(FLAGS_openssl_defensive_locking) {}
+
+void OpenSSLMutex::lock() {
+  if (locking_enabled_) {
+    mutex_.lock();
+  }
+}
+
+bool OpenSSLMutex::try_lock() {
+  if (locking_enabled_) {
+    return mutex_.try_lock();
+  }
+  return true;
+}
+
+void OpenSSLMutex::unlock() {
+  if (locking_enabled_) {
+    mutex_.unlock();
+  }
+}
+
 } // namespace security
 } // namespace kudu
diff --git a/be/src/kudu/security/openssl_util.h 
b/be/src/kudu/security/openssl_util.h
index 00c4ebf..356ecb0 100644
--- a/be/src/kudu/security/openssl_util.h
+++ b/be/src/kudu/security/openssl_util.h
@@ -19,6 +19,7 @@
 
 #include <functional>
 #include <memory>
+#include <mutex>
 #include <ostream>
 #include <string>
 
@@ -189,29 +190,39 @@ class RawDataWrapper {
   c_unique_ptr<RawDataType> data_;
 };
 
+// Wrapper around std::mutex that only locks if a special
+// 'openssl_defensive_locking' flag is set to true. See the description of the
+// flag for more details.
+class OpenSSLMutex {
+ public:
+  OpenSSLMutex();
+  void lock();
+  bool try_lock();
+  void unlock();
 
-namespace internal {
+ private:
+  std::mutex mutex_;
+  const bool locking_enabled_;
+};
 
+namespace internal {
 // Implementation of SCOPED_OPENSSL_NO_PENDING_ERRORS. Use the macro form
 // instead of directly instantiating the implementation class.
 struct ScopedCheckNoPendingSSLErrors {
  public:
-  explicit ScopedCheckNoPendingSSLErrors(const char* func)
-      : func_(func) {
-    DCHECK_EQ(ERR_peek_error(), 0)
-        << "Expected no pending OpenSSL errors on " << func_
-        << " entry, but had: " << GetOpenSSLErrors();
+  explicit ScopedCheckNoPendingSSLErrors(const char* func) : func_(func) {
+    DCHECK_EQ(ERR_peek_error(), 0) << "Expected no pending OpenSSL errors on " 
<< func_
+                                   << " entry, but had: " << 
GetOpenSSLErrors();
   }
   ~ScopedCheckNoPendingSSLErrors() {
-    DCHECK_EQ(ERR_peek_error(), 0)
-        << "Expected no pending OpenSSL errors on " << func_
-        << " exit, but had: " << GetOpenSSLErrors();
+    DCHECK_EQ(ERR_peek_error(), 0) << "Expected no pending OpenSSL errors on " 
<< func_
+                                   << " exit, but had: " << GetOpenSSLErrors();
   }
 
  private:
   const char* const func_;
 };
 
-} // namespace internal
-} // namespace security
+}  // namespace internal
+}  // namespace security
 } // namespace kudu
diff --git a/be/src/kudu/security/tls_context.cc 
b/be/src/kudu/security/tls_context.cc
index a01b779..622165f 100644
--- a/be/src/kudu/security/tls_context.cc
+++ b/be/src/kudu/security/tls_context.cc
@@ -21,6 +21,7 @@
 #include <mutex>
 #include <ostream>
 #include <string>
+#include <type_traits>
 #include <vector>
 
 #include <boost/algorithm/string/predicate.hpp>
@@ -81,6 +82,12 @@ DEFINE_int32(ipki_server_key_size, 2048,
              "is used for TLS connections to and from clients and other 
servers.");
 TAG_FLAG(ipki_server_key_size, experimental);
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+namespace {
+kudu::security::OpenSSLMutex mutex;
+}  // anonymous namespace
+#endif
+
 namespace kudu {
 namespace security {
 
@@ -212,9 +219,13 @@ Status TlsContext::VerifyCertChainUnlocked(const Cert& 
cert) {
   int rc = X509_verify_cert(store_ctx.get());
   if (rc != 1) {
     int err = X509_STORE_CTX_get_error(store_ctx.get());
+
+    // This also clears the errors. It's important to do this before we call
+    // X509NameToString(), as it expects the error stack to be empty and it
+    // calls SCOPED_OPENSSL_NO_PENDING_ERRORS.
+    const auto error_msg = GetOpenSSLErrors();
     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();
     }
 
@@ -227,9 +238,8 @@ Status TlsContext::VerifyCertChainUnlocked(const Cert& 
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),
+        Substitute("could not verify certificate chain$0: $1", cert_details, 
error_msg),
         X509_verify_cert_error_string(err));
   }
   return Status::OK();
@@ -423,6 +433,10 @@ boost::optional<CertSignRequest> 
TlsContext::GetCsrIfNecessary() const {
 
 Status TlsContext::AdoptSignedCert(const Cert& cert) {
   SCOPED_OPENSSL_NO_PENDING_ERRORS;
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+  unique_lock<OpenSSLMutex> lock_global(mutex);
+#endif
   unique_lock<RWMutex> lock(lock_);
 
   if (!csr_) {
diff --git a/be/src/kudu/security/tls_handshake.cc 
b/be/src/kudu/security/tls_handshake.cc
index 5a89592..d61da6d 100644
--- a/be/src/kudu/security/tls_handshake.cc
+++ b/be/src/kudu/security/tls_handshake.cc
@@ -17,16 +17,20 @@
 
 #include "kudu/security/tls_handshake.h"
 
-#include <memory>
-#include <string>
-
 #include <openssl/ssl.h>
 #include <openssl/x509.h>
 #include <openssl/x509v3.h>
 
+#include <memory>
+#if OPENSSL_VERSION_NUMBER < 0x10002000L
+#include <mutex>
+#endif
+#include <string>
+
 #include "kudu/gutil/strings/strip.h"
 #include "kudu/gutil/strings/substitute.h"
 #include "kudu/security/cert.h"
+#include "kudu/security/openssl_util.h"
 #include "kudu/security/tls_socket.h"
 #include "kudu/util/net/socket.h"
 #include "kudu/util/status.h"
@@ -40,6 +44,12 @@ using std::string;
 using std::unique_ptr;
 using strings::Substitute;
 
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+namespace {
+kudu::security::OpenSSLMutex mutex;
+}  // anonymous namespace
+#endif
+
 namespace kudu {
 namespace security {
 
@@ -92,7 +102,13 @@ Status TlsHandshake::Continue(const string& recv, string* 
send) {
   DCHECK(n == recv.size() || (n == -1 && recv.empty()));
   DCHECK_EQ(BIO_ctrl_pending(rbio), recv.size());
 
-  int rc = SSL_do_handshake(ssl_.get());
+  int rc;
+  {
+#if OPENSSL_VERSION_NUMBER < 0x10100000L
+    std::unique_lock<OpenSSLMutex> lock(mutex);
+#endif
+    rc = SSL_do_handshake(ssl_.get());
+  }
   if (rc != 1) {
     int ssl_err = SSL_get_error(ssl_.get(), rc);
     // WANT_READ and WANT_WRITE indicate that the handshake is not yet 
complete.
diff --git a/be/src/kudu/security/token-test.cc 
b/be/src/kudu/security/token-test.cc
index a4d7804..00e4f61 100644
--- a/be/src/kudu/security/token-test.cc
+++ b/be/src/kudu/security/token-test.cc
@@ -57,7 +57,7 @@ namespace security {
 namespace {
 
 // Dummy variables to use when their values don't matter much.
-const int kNumBits = 512;
+const int kNumBits = UseLargeKeys() ? 2048 : 512;
 const int64_t kTokenValiditySeconds = 10;
 const char kUser[] = "user";
 
diff --git a/be/src/kudu/util/flags.cc b/be/src/kudu/util/flags.cc
index 97519c8..dfd2b14 100644
--- a/be/src/kudu/util/flags.cc
+++ b/be/src/kudu/util/flags.cc
@@ -17,10 +17,12 @@
 
 #include "kudu/util/flags.h"
 
+#include <strings.h>
 #include <sys/stat.h>
 #include <unistd.h> // IWYU pragma: keep
 
 #include <cstdlib>
+#include <cstring>
 #include <functional>
 #include <iostream>
 #include <map>
@@ -596,4 +598,24 @@ Status ParseTriState(const char* flag_name, const 
std::string& flag_value,
   return Status::OK();
 }
 
+// Get the value of an environment variable that has boolean semantics.
+bool GetBooleanEnvironmentVariable(const char* env_var_name) {
+  const char* const e = getenv(env_var_name);
+  if ((e == nullptr) ||
+      (strlen(e) == 0) ||
+      (strcasecmp(e, "false") == 0) ||
+      (strcasecmp(e, "0") == 0) ||
+      (strcasecmp(e, "no") == 0)) {
+    return false;
+  }
+  if ((strcasecmp(e, "true") == 0) ||
+      (strcasecmp(e, "1") == 0) ||
+      (strcasecmp(e, "yes") == 0)) {
+    return true;
+  }
+  LOG(FATAL) << Substitute("$0: invalid value for environment variable $0",
+                           e, env_var_name);
+  return false;  // unreachable
+}
+
 } // namespace kudu
diff --git a/be/src/kudu/util/flags.h b/be/src/kudu/util/flags.h
index 033a57f..98f8cb8 100644
--- a/be/src/kudu/util/flags.h
+++ b/be/src/kudu/util/flags.h
@@ -90,5 +90,7 @@ Status ParseTriState(const char* flag_name, const 
std::string& flag_value,
 
 std::string CheckFlagAndRedact(const google::CommandLineFlagInfo& flag, 
EscapeMode mode);
 
+bool GetBooleanEnvironmentVariable(const char* env_var_name);
+
 } // namespace kudu
 #endif /* KUDU_UTIL_FLAGS_H */
diff --git a/be/src/kudu/util/test_util.cc b/be/src/kudu/util/test_util.cc
index 93eac65..90ed621 100644
--- a/be/src/kudu/util/test_util.cc
+++ b/be/src/kudu/util/test_util.cc
@@ -21,8 +21,8 @@
 #include <limits.h>
 #include <unistd.h>
 
+#include <cerrno>
 #include <cstdlib>
-#include <cstring>
 #include <limits>
 #include <map>
 #include <memory>
@@ -51,6 +51,7 @@
 #include "kudu/gutil/walltime.h"
 #include "kudu/util/env.h"
 #include "kudu/util/faststring.h"
+#include "kudu/util/flags.h"
 #include "kudu/util/path_util.h"
 #include "kudu/util/scoped_cleanup.h"
 #include "kudu/util/slice.h"
@@ -76,6 +77,7 @@ namespace kudu {
 
 const char* kInvalidPath = "/dev/invalid-path-for-kudu-tests";
 static const char* const kSlowTestsEnvVar = "KUDU_ALLOW_SLOW_TESTS";
+static const char* const kLargeKeysEnvVar = "KUDU_USE_LARGE_KEYS_IN_TESTS";
 
 static const uint64_t kTestBeganAtMicros = Env::Default()->NowMicros();
 
@@ -100,21 +102,26 @@ KuduTest::KuduTest()
     {"never_fsync", "true"},
     // Disable redaction.
     {"redact", "none"},
-    // Reduce default RSA key length for faster tests. We are using strong/high
-    // TLS v1.2 cipher suites, so minimum possible for TLS-related RSA keys is
-    // 768 bits. However, for the external mini cluster we use 1024 bits 
because
-    // Java default security policies require at least 1024 bits for RSA keys
-    // used in certificates. For uniformity, here 1024 RSA bit keys are used
-    // as well. As for the TSK keys, 512 bits is the minimum since the SHA256
-    // digest is used for token signing/verification.
-    {"ipki_server_key_size", "1024"},
-    {"ipki_ca_key_size", "1024"},
-    {"tsk_num_rsa_bits", "512"},
     // For a generic Kudu test, the local wall-clock time is good enough even
     // if it's not synchronized by NTP. All test components are run at the same
     // node, so there aren't multiple time sources to synchronize.
     {"time_source", "system_unsync"},
   };
+  if (!UseLargeKeys()) {
+    // Reduce default RSA key length for faster tests. We are using strong/high
+    // TLS v1.2 cipher suites, so minimum possible for TLS-related RSA keys is
+    // 768 bits. Java security policies in tests tweaked appropriately to allow
+    // for using smaller RSA keys in certificates. As for the TSK keys, 512 
bits
+    // is the minimum since the SHA256 digest is used for token
+    // signing/verification.
+    flags_for_tests.emplace("ipki_server_key_size", "768");
+    flags_for_tests.emplace("ipki_ca_key_size", "768");
+    flags_for_tests.emplace("tsk_num_rsa_bits", "512");
+    // Some OS distros set the default security level higher than 0, so it's
+    // necessary to override it to use the key length specified above (which 
are
+    // considered lax and don't work in case of security level 2 or higher).
+    flags_for_tests.emplace("openssl_security_level_override", "0");
+  }
   for (const auto& e : flags_for_tests) {
     // We don't check for errors here, because we have some default flags that
     // only apply to certain tests. If a flag is defined in a library which
@@ -177,31 +184,9 @@ void KuduTest::OverrideKrb5Environment() {
 // Test utility functions
 ///////////////////////////////////////////////////
 
-namespace {
-// Get the value of an environment variable that has boolean semantics.
-bool GetBooleanEnvironmentVariable(const char* env_var_name) {
-  const char* const e = getenv(env_var_name);
-  if ((e == nullptr) ||
-      (strlen(e) == 0) ||
-      (strcasecmp(e, "false") == 0) ||
-      (strcasecmp(e, "0") == 0) ||
-      (strcasecmp(e, "no") == 0)) {
-    return false;
-  }
-  if ((strcasecmp(e, "true") == 0) ||
-      (strcasecmp(e, "1") == 0) ||
-      (strcasecmp(e, "yes") == 0)) {
-    return true;
-  }
-  LOG(FATAL) << Substitute("$0: invalid value for environment variable $0",
-                           e, env_var_name);
-  return false;  // unreachable
-}
-} // anonymous namespace
+bool AllowSlowTests() { return 
GetBooleanEnvironmentVariable(kSlowTestsEnvVar); }
 
-bool AllowSlowTests() {
-  return GetBooleanEnvironmentVariable(kSlowTestsEnvVar);
-}
+bool UseLargeKeys() { return GetBooleanEnvironmentVariable(kLargeKeysEnvVar); }
 
 void OverrideFlagForSlowTests(const std::string& flag_name,
                               const std::string& new_value) {
diff --git a/be/src/kudu/util/test_util.h b/be/src/kudu/util/test_util.h
index d320e3e..d9f657a 100644
--- a/be/src/kudu/util/test_util.h
+++ b/be/src/kudu/util/test_util.h
@@ -87,6 +87,10 @@ class KuduTest : public ::testing::Test {
 // Returns true if slow tests are runtime-enabled.
 bool AllowSlowTests();
 
+// Returns true if the KUDU_USE_LARGE_KEYS_IN_TESTS environment variable is set
+// to true. This is required to pass certain tests in FIPS approved mode.
+bool UseLargeKeys();
+
 // Override the given gflag to the new value, only in the case that
 // slow tests are enabled and the user hasn't otherwise overridden
 // it on the command line.

Reply via email to