Repository: mesos
Updated Branches:
  refs/heads/master d6685e492 -> 067034047


SSL: Made SSLTest fixture publicly accessible.

Refactored libprocess SSL tests to be available for reuse by other
projects.

Review: https://reviews.apache.org/r/37871


Project: http://git-wip-us.apache.org/repos/asf/mesos/repo
Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/06703404
Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/06703404
Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/06703404

Branch: refs/heads/master
Commit: 067034047317bb42ad41d2d93851b373108987d3
Parents: d6685e4
Author: Jojy Varghese <[email protected]>
Authored: Mon Aug 31 09:37:48 2015 -0400
Committer: Joris Van Remoortere <[email protected]>
Committed: Mon Aug 31 10:38:23 2015 -0400

----------------------------------------------------------------------
 3rdparty/libprocess/Makefile.am                 |   3 +-
 3rdparty/libprocess/include/Makefile.am         |   2 +
 .../libprocess/include/process/ssl/gtest.hpp    | 349 +++++++++++++++++++
 .../include/process/ssl/utilities.hpp           | 115 ++++++
 3rdparty/libprocess/src/openssl_util.cpp        | 262 --------------
 3rdparty/libprocess/src/openssl_util.hpp        | 111 ------
 3rdparty/libprocess/src/ssl/utilities.cpp       | 262 ++++++++++++++
 3rdparty/libprocess/src/tests/ssl_tests.cpp     | 313 +----------------
 8 files changed, 732 insertions(+), 685 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mesos/blob/06703404/3rdparty/libprocess/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/Makefile.am b/3rdparty/libprocess/Makefile.am
index 7ef5158..6361ac6 100644
--- a/3rdparty/libprocess/Makefile.am
+++ b/3rdparty/libprocess/Makefile.am
@@ -83,8 +83,7 @@ libprocess_la_SOURCES +=      \
     src/libevent_ssl_socket.hpp        \
     src/openssl.cpp            \
     src/openssl.hpp            \
-    src/openssl_util.cpp       \
-    src/openssl_util.hpp
+    src/ssl/utilities.cpp
 endif
 
 libprocess_la_CPPFLAGS =                       \

http://git-wip-us.apache.org/repos/asf/mesos/blob/06703404/3rdparty/libprocess/include/Makefile.am
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/Makefile.am 
b/3rdparty/libprocess/include/Makefile.am
index 3b6108d..fcc62e9 100644
--- a/3rdparty/libprocess/include/Makefile.am
+++ b/3rdparty/libprocess/include/Makefile.am
@@ -57,6 +57,8 @@ nobase_include_HEADERS =              \
   process/sequence.hpp                 \
   process/shared.hpp                   \
   process/socket.hpp                   \
+  process/ssl/gtest.hpp                        \
+  process/ssl/utilities.hpp            \
   process/statistics.hpp               \
   process/system.hpp                   \
   process/subprocess.hpp               \

http://git-wip-us.apache.org/repos/asf/mesos/blob/06703404/3rdparty/libprocess/include/process/ssl/gtest.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/ssl/gtest.hpp 
b/3rdparty/libprocess/include/process/ssl/gtest.hpp
new file mode 100644
index 0000000..a6051b7
--- /dev/null
+++ b/3rdparty/libprocess/include/process/ssl/gtest.hpp
@@ -0,0 +1,349 @@
+/**
+ * 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.
+ */
+
+#ifndef __PROCESS_SSL_TEST_HPP__
+#define __PROCESS_SSL_TEST_HPP__
+
+#ifdef USE_SSL_SOCKET
+
+#include <openssl/rsa.h>
+#include <openssl/bio.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include <process/io.hpp>
+#include <process/socket.hpp>
+
+#include <process/ssl/utilities.hpp>
+
+using std::map;
+using std::string;
+using std::vector;
+
+using namespace process;
+using namespace process::network;
+
+namespace process {
+namespace network {
+namespace openssl {
+
+// Forward declare the `reinitialize()` function since we want to
+// programatically change SSL flags during tests.
+void reinitialize();
+
+} // namespace openssl {
+} // namespace network {
+} // namespace process {
+
+
+/**
+ * A Test fixture that sets up SSL keys and certificates.
+ *
+ * This class sets up a private key and certificate pair at
+ * SSLTest::key_path and SSLTest::certificate_path.
+ * It also sets up an independent 'scrap' pair that can be used to
+ * test an invalid certificate authority chain. These can be found at
+ * SSLTest::scrap_key_path and SSLTest::scrap_certificate_path.
+ *
+ * There are some helper functions like SSLTest::setup_server and
+ * SSLTest::launch_client that factor out common behavior used in
+ * tests.
+ */
+class SSLTest : public ::testing::Test
+{
+protected:
+  SSLTest() : data("Hello World!") {}
+
+  /**
+   * @return The path to the authorized private key.
+   */
+  static const Path& key_path()
+  {
+    static Path path(path::join(os::getcwd(), "key.pem"));
+    return path;
+  }
+
+  /**
+   * @return The path to the authorized certificate.
+   */
+  static const Path& certificate_path()
+  {
+    static Path path(path::join(os::getcwd(), "cert.pem"));
+    return path;
+  }
+
+  /**
+   * @return The path to the unauthorized private key.
+   */
+  static const Path& scrap_key_path()
+  {
+    static Path path(path::join(os::getcwd(), "scrap_key.pem"));
+    return path;
+  }
+
+  /**
+   * @return The path to the unauthorized certificate.
+   */
+  static const Path& scrap_certificate_path()
+  {
+    static Path path(path::join(os::getcwd(), "scrap_cert.pem"));
+    return path;
+  }
+
+  static void cleanup_directories()
+  {
+    os::rm(key_path().value);
+    os::rm(certificate_path().value);
+    os::rm(scrap_key_path().value);
+    os::rm(scrap_certificate_path().value);
+  }
+
+  static void SetUpTestCase()
+  {
+    // We store the allocated objects in these results so that we can
+    // have a consolidated 'cleanup()' function. This makes all the
+    // 'EXIT()' calls more readable and less error prone.
+    Result<EVP_PKEY*> private_key = None();
+    Result<X509*> certificate = None();
+    Result<EVP_PKEY*> scrap_key = None();
+    Result<X509*> scrap_certificate = None();
+
+    auto cleanup = [&private_key, &certificate, &scrap_key, 
&scrap_certificate](
+        bool failure = true) {
+      if (private_key.isSome()) { EVP_PKEY_free(private_key.get()); }
+      if (certificate.isSome()) { X509_free(certificate.get()); }
+      if (scrap_key.isSome()) { EVP_PKEY_free(scrap_key.get()); }
+      if (scrap_certificate.isSome()) { X509_free(scrap_certificate.get()); }
+
+      // If we are under a failure condition, clean up any files we
+      // already generated. The expected behavior is that they will be
+      // cleaned up in 'TearDownTestCase()'; however, we call ABORT
+      // during 'SetUpTestCase()' failures.
+      if (failure) {
+        cleanup_directories();
+      }
+    };
+
+    // Generate the authority key.
+    private_key = openssl::generate_private_rsa_key();
+    if (private_key.isError()) {
+      ABORT("Could not generate private key: " + private_key.error());
+    }
+
+    // Figure out the hostname that 'INADDR_LOOPBACK' will bind to.
+    // Set the hostname of the certificate to this hostname so that
+    // hostname verification of the certificate will pass.
+    Try<string> hostname = net::getHostname(net::IP(INADDR_LOOPBACK));
+    if (hostname.isError()) {
+      cleanup();
+      ABORT("Could not determine hostname of 'INADDR_LOOPBACK': " +
+            hostname.error());
+    }
+
+    // Generate an authorized certificate.
+    certificate = openssl::generate_x509(
+        private_key.get(),
+        private_key.get(),
+        None(),
+        1,
+        365,
+        hostname.get());
+
+    if (certificate.isError()) {
+      cleanup();
+      ABORT("Could not generate certificate: " + certificate.error());
+    }
+
+    // Write the authority key to disk.
+    Try<Nothing> key_write =
+      openssl::write_key_file(private_key.get(), key_path());
+
+    if (key_write.isError()) {
+      cleanup();
+      ABORT("Could not write private key to disk: " + key_write.error());
+    }
+
+    // Write the authorized certificate to disk.
+    Try<Nothing> certificate_write =
+      openssl::write_certificate_file(certificate.get(), certificate_path());
+
+    if (certificate_write.isError()) {
+      cleanup();
+      ABORT("Could not write certificate to disk: " +
+            certificate_write.error());
+    }
+
+    // Generate a scrap key.
+    scrap_key = openssl::generate_private_rsa_key();
+    if (scrap_key.isError()) {
+      cleanup();
+      ABORT("Could not generate a scrap private key: " + scrap_key.error());
+    }
+
+    // Write the scrap key to disk.
+    key_write = openssl::write_key_file(scrap_key.get(), scrap_key_path());
+
+    if (key_write.isError()) {
+      cleanup();
+      ABORT("Could not write scrap key to disk: " + key_write.error());
+    }
+
+    // Generate a scrap certificate.
+    scrap_certificate =
+      openssl::generate_x509(scrap_key.get(), scrap_key.get());
+
+    if (scrap_certificate.isError()) {
+      cleanup();
+      ABORT("Could not generate a scrap certificate: " +
+            scrap_certificate.error());
+    }
+
+    // Write the scrap certificate to disk.
+    certificate_write = openssl::write_certificate_file(
+        scrap_certificate.get(),
+        scrap_certificate_path());
+
+    if (certificate_write.isError()) {
+      cleanup();
+      ABORT("Could not write scrap certificate to disk: " +
+            certificate_write.error());
+    }
+
+    // Since we successfully set up all our state, we call cleanup
+    // with failure set to 'false'.
+    cleanup(false);
+  }
+
+  static void TearDownTestCase()
+  {
+    // Clean up all the pem files we generated.
+    cleanup_directories();
+  }
+
+  virtual void SetUp()
+  {
+    // This unsets all the SSL environment variables. Necessary for
+    // ensuring a clean starting slate between tests.
+    os::unsetenv("SSL_ENABLED");
+    os::unsetenv("SSL_SUPPORT_DOWNGRADE");
+    os::unsetenv("SSL_CERT_FILE");
+    os::unsetenv("SSL_KEY_FILE");
+    os::unsetenv("SSL_VERIFY_CERT");
+    os::unsetenv("SSL_REQUIRE_CERT");
+    os::unsetenv("SSL_VERIFY_DEPTH");
+    os::unsetenv("SSL_CA_DIR");
+    os::unsetenv("SSL_CA_FILE");
+    os::unsetenv("SSL_CIPHERS");
+    os::unsetenv("SSL_ENABLE_SSL_V3");
+    os::unsetenv("SSL_ENABLE_TLS_V1_0");
+    os::unsetenv("SSL_ENABLE_TLS_V1_1");
+    os::unsetenv("SSL_ENABLE_TLS_V1_2");
+  }
+
+  /**
+   * Initializes a listening server.
+   *
+   * @param environment The SSL environment variables to launch the
+   *     server socket with.
+   *
+   * @return Socket if successful otherwise an Error.
+   */
+  Try<Socket> setup_server(const map<string, string>& environment)
+  {
+    foreachpair (const string& name, const string& value, environment) {
+      os::setenv(name, value);
+    }
+    openssl::reinitialize();
+
+    const Try<Socket> create = Socket::create(Socket::SSL);
+    if (create.isError()) {
+      return Error(create.error());
+    }
+
+    Socket server = create.get();
+
+    // We need to explicitly bind to INADDR_LOOPBACK so the
+    // certificate we create in this test fixture can be verified.
+    Try<Address> bind = server.bind(Address(net::IP(INADDR_LOOPBACK), 0));
+    if (bind.isError()) {
+      return Error(bind.error());
+    }
+
+    const Try<Nothing> listen = server.listen(BACKLOG);
+    if (listen.isError()) {
+      return Error(listen.error());
+    }
+
+    return server;
+  }
+
+  /**
+   * Launches a test SSL client as a subprocess connecting to the
+   * server.
+   *
+   * The subprocess calls the 'ssl-client' binary with the provided
+   * environment.
+   *
+   * @param environment The SSL environment variables to launch the
+   *     SSL client subprocess with.
+   * @param use_ssl_socket Whether the SSL client will try to connect
+   *     using an SSL socket or a POLL socket.
+   *
+   * @return Subprocess if successful otherwise an Error.
+   */
+  Try<Subprocess> launch_client(
+      const map<string, string>& environment,
+      const Socket& server,
+      bool use_ssl_socket)
+  {
+    const Try<Address> address = server.address();
+    if (address.isError()) {
+      return Error(address.error());
+    }
+
+    // Set up arguments to be passed to the 'client-ssl' binary.
+    const vector<string> argv = {
+      "ssl-client",
+      "--use_ssl=" + stringify(use_ssl_socket),
+      "--server=127.0.0.1",
+      "--port=" + stringify(address.get().port),
+      "--data=" + data};
+
+    Result<string> path = os::realpath(BUILD_DIR);
+    if (!path.isSome()) {
+      return Error("Could not establish build directory path");
+    }
+
+    return subprocess(
+        path::join(path.get(), "ssl-client"),
+        argv,
+        Subprocess::PIPE(),
+        Subprocess::PIPE(),
+        Subprocess::FD(STDERR_FILENO),
+        None(),
+        environment);
+  }
+
+  static constexpr size_t BACKLOG = 5;
+
+  const string data;
+};
+
+#endif // USE_SSL_SOCKET
+
+#endif // __PROCESS_SSL_TEST_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/06703404/3rdparty/libprocess/include/process/ssl/utilities.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/include/process/ssl/utilities.hpp 
b/3rdparty/libprocess/include/process/ssl/utilities.hpp
new file mode 100644
index 0000000..25d3a38
--- /dev/null
+++ b/3rdparty/libprocess/include/process/ssl/utilities.hpp
@@ -0,0 +1,115 @@
+/**
+* Licensed 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
+*/
+
+#ifndef __OPENSSL_UTIL_HPP__
+#define __OPENSSL_UTIL_HPP__
+
+#ifdef USE_SSL_SOCKET
+
+#include <openssl/ssl.h>
+#include <openssl/x509.h>
+
+#include <stout/nothing.hpp>
+#include <stout/path.hpp>
+#include <stout/try.hpp>
+
+namespace process {
+namespace network {
+namespace openssl {
+
+/**
+ * Generates an RSA key.
+ *
+ * The caller is responsible for calling `EVP_PKEY_free` on the
+ * returned EVP_PKEY.
+ * @see <a 
href="https://www.openssl.org/docs/crypto/RSA_generate_key.html";>RSA_generate_key_ex</a>
 // NOLINT
+ *
+ * @param bits The modulus size used to generate the key.
+ * @param exponent The public exponent, an odd number.
+ *
+ * @return A pointer to an EVP_PKEY if successful otherwise an Error.
+ */
+Try<EVP_PKEY*> generate_private_rsa_key(
+    int bits = 2048,
+    unsigned long exponent = RSA_F4);
+
+
+/**
+ * Generates an X509 certificate.
+ *
+ * The X509 certificate is generated for the @param subject_key and
+ * signed by the @param sign_key. The caller is responsible for
+ * calling `X509_free` on the returned X509 object.
+ * The common name of the certificate will be set to @param hostname
+ * or that of the localhost if @param hostname is not provided.
+ * If a @param parent_certificate is provided, then the issuer name of
+ * the certificate will be set to the subject name of the
+ * @param parent_certificate. Otherwise, it is assumed this is a
+ * self-signed certificate in which case the @param subject_key must
+ * be the same as the @param sign_key, and the issuer name will be the
+ * same as the subject name.
+ *
+ * @param subject_key The key that will be made public by the
+ *     certificate.
+ * @param sign_key The private key used to sign the certificate.
+ * @param parent_certificate An optional parent certificate that will
+ *     be used to set the issuer name.
+ * @param serial The serial number of the certificate.
+ * @param days The number of days from the current time that the
+ *     certificate will be valid.
+ * @param hostname An optional hostname used to set the common name of
+ *     the certificate.
+ *
+ * @return A pointer to an X509 certificate if successful otherwise an
+ *     Error.
+ */
+Try<X509*> generate_x509(
+    EVP_PKEY* subject_key,
+    EVP_PKEY* sign_key,
+    const Option<X509*>& parent_certificate = None(),
+    int serial = 1,
+    int days = 365,
+    Option<std::string> hostname = None());
+
+
+/**
+ * Writes a private key (EVP_PKEY) to a file on disk.
+ * @see <a 
href="https://www.openssl.org/docs/crypto/pem.html";>PEM_write_PrivateKey</a> // 
NOLINT
+ *
+ * @param private_key The private key to write.
+ * @param path The file location to create the file.
+ *
+ * @return Nothing if successful otherwise an Error.
+ */
+Try<Nothing> write_key_file(EVP_PKEY* private_key, const Path& path);
+
+
+/**
+ * Writes an X509 certificate (X509) to a file on disk.
+ * @see <a 
href="https://www.openssl.org/docs/crypto/pem.html";>PEM_write_X509</a> // NOLINT
+ *
+ * @param x509 The certificate to write.
+ * @param path The file location to create the file.
+ *
+ * @return Nothing if successful otherwise an Error.
+ */
+Try<Nothing> write_certificate_file(X509* x509, const Path& path);
+
+} // namespace openssl {
+} // namespace network {
+} // namespace process {
+
+#endif // USE_SSL_SOCKET
+
+#endif // __OPENSSL_UTIL_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/06703404/3rdparty/libprocess/src/openssl_util.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/openssl_util.cpp 
b/3rdparty/libprocess/src/openssl_util.cpp
deleted file mode 100644
index 42b2860..0000000
--- a/3rdparty/libprocess/src/openssl_util.cpp
+++ /dev/null
@@ -1,262 +0,0 @@
-/**
-* Licensed 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 "openssl_util.hpp"
-
-#include <openssl/err.h>
-#include <openssl/rsa.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
-#include <stout/net.hpp>
-#include <stout/stringify.hpp>
-
-// TODO(jmlvanre): Add higher level abstractions for key and
-// certificate generation.
-
-namespace process {
-namespace network {
-namespace openssl {
-
-Try<EVP_PKEY*> generate_private_rsa_key(int bits, unsigned long _exponent)
-{
-  // Allocate the in-memory structure for the private key.
-  EVP_PKEY* private_key = EVP_PKEY_new();
-  if (private_key == NULL) {
-    return Error("Failed to allocate key: EVP_PKEY_new");
-  }
-
-  // Allocate space for the exponent.
-  BIGNUM* exponent = BN_new();
-  if (exponent == NULL) {
-    EVP_PKEY_free(private_key);
-    return Error("Failed to allocate exponent: BN_new");
-  }
-
-  // Assign the exponent.
-  if (BN_set_word(exponent, _exponent) != 1) {
-    BN_free(exponent);
-    EVP_PKEY_free(private_key);
-    return Error("Failed to set exponent: BN_set_word");
-  }
-
-  // Allocate the in-memory structure for the key pair.
-  RSA* rsa = RSA_new();
-  if (rsa == NULL) {
-    BN_free(exponent);
-    EVP_PKEY_free(private_key);
-    return Error("Failed to allocate RSA: RSA_new");
-  }
-
-  // Generate the RSA key pair.
-  if (RSA_generate_key_ex(rsa, bits, exponent, NULL) != 1) {
-    RSA_free(rsa);
-    BN_free(exponent);
-    EVP_PKEY_free(private_key);
-    return Error(ERR_error_string(ERR_get_error(), NULL));
-  }
-
-  // We no longer need the exponent, so let's free it.
-  BN_free(exponent);
-
-  // Associate the RSA key with the private key. If this association
-  // is successful, then the RSA key will be freed when the private
-  // key is freed.
-  if (EVP_PKEY_assign_RSA(private_key, rsa) != 1) {
-    RSA_free(rsa);
-    EVP_PKEY_free(private_key);
-    return Error("Failed to assign RSA key: EVP_PKEY_assign_RSA");
-  }
-
-  return private_key;
-}
-
-
-Try<X509*> generate_x509(
-    EVP_PKEY* subject_key,
-    EVP_PKEY* sign_key,
-    const Option<X509*>& parent_certificate,
-    int serial,
-    int days,
-    Option<std::string> hostname)
-{
-  Option<X509_NAME*> issuer_name = None();
-  if (parent_certificate.isNone()) {
-    // If there is no parent certificate, then the subject and
-    // signing key must be the same.
-    if (subject_key != sign_key) {
-      return Error("Subject vs signing key mismatch");
-    }
-  } else {
-    // If there is a parent certificate, then set the issuer name to
-    // be that of the parent.
-    issuer_name = X509_get_subject_name(parent_certificate.get());
-
-    if (issuer_name.get() == NULL) {
-      return Error("Failed to get subject name of parent certificate: "
-        "X509_get_subject_name");
-    }
-  }
-
-  // Allocate the in-memory structure for the certificate.
-  X509* x509 = X509_new();
-  if (x509 == NULL) {
-    return Error("Failed to allocate certification: X509_new");
-  }
-
-  // Set the version to V3.
-  if (X509_set_version(x509, 2) != 1) {
-    X509_free(x509);
-    return Error("Failed to set version: X509_set_version");
-  }
-
-  // Set the serial number.
-  if (ASN1_INTEGER_set(X509_get_serialNumber(x509), serial) != 1) {
-    X509_free(x509);
-    return Error("Failed to set serial number: ASN1_INTEGER_set");
-  }
-
-  // Make this certificate valid for 'days' number of days from now.
-  if (X509_gmtime_adj(X509_get_notBefore(x509), 0) == NULL ||
-      X509_gmtime_adj(X509_get_notAfter(x509),
-                      60L * 60L * 24L * days) == NULL) {
-    X509_free(x509);
-    return Error("Failed to set valid days of certificate: X509_gmtime_adj");
-  }
-
-  // Set the public key for our certificate based on the subject key.
-  if (X509_set_pubkey(x509, subject_key) != 1) {
-    X509_free(x509);
-    return Error("Failed to set public key: X509_set_pubkey");
-  }
-
-  // Figure out our hostname if one was not provided.
-  if (hostname.isNone()) {
-    const Try<std::string> _hostname = net::hostname();
-    if (_hostname.isError()) {
-      X509_free(x509);
-      return Error("Failed to determine hostname");
-    }
-
-    hostname = _hostname.get();
-  }
-
-  // Grab the subject name of the new certificate.
-  X509_NAME* name = X509_get_subject_name(x509);
-  if (name == NULL) {
-    X509_free(x509);
-    return Error("Failed to get subject name: X509_get_subject_name");
-  }
-
-  // Set the country code, organization, and common name.
-  if (X509_NAME_add_entry_by_txt(
-          name,
-          "C",
-          MBSTRING_ASC,
-          reinterpret_cast<const unsigned char*>("US"),
-          -1,
-          -1,
-          0) != 1) {
-    X509_free(x509);
-    return Error("Failed to set country code: X509_NAME_add_entry_by_txt");
-  }
-
-  if (X509_NAME_add_entry_by_txt(
-          name,
-          "O",
-          MBSTRING_ASC,
-          reinterpret_cast<const unsigned char*>("Test"),
-          -1,
-          -1,
-          0) != 1) {
-    X509_free(x509);
-    return Error("Failed to set organization name: 
X509_NAME_add_entry_by_txt");
-  }
-
-  if (X509_NAME_add_entry_by_txt(
-          name,
-          "CN",
-          MBSTRING_ASC,
-          reinterpret_cast<const unsigned char*>(hostname.get().c_str()),
-          -1,
-          -1,
-          0) != 1) {
-    X509_free(x509);
-    return Error("Failed to set common name: X509_NAME_add_entry_by_txt");
-  }
-
-  // Set the issuer name to be the same as the subject if it is not
-  // already set (this is a self-signed certificate).
-  if (issuer_name.isNone()) {
-    issuer_name = name;
-  }
-
-  CHECK_SOME(issuer_name);
-  if (X509_set_issuer_name(x509, issuer_name.get()) != 1) {
-    X509_free(x509);
-    return Error("Failed to set issuer name: X509_set_issuer_name");
-  }
-
-  // Sign the certificate with the sign key.
-  if (X509_sign(x509, sign_key, EVP_sha1()) == 0) {
-    X509_free(x509);
-    return Error("Failed to sign certificate: X509_sign");
-  }
-
-  return x509;
-}
-
-
-Try<Nothing> write_key_file(EVP_PKEY* private_key, const Path& path)
-{
-  // We use 'FILE*' here because it is an API requirement by openssl.
-  FILE* file = fopen(path.value.c_str(), "wb");
-  if (file == NULL) {
-    return Error("Failed to open file '" + stringify(path) + "' for writing");
-  }
-
-  if (PEM_write_PrivateKey(file, private_key, NULL, NULL, 0, NULL, NULL) != 1) 
{
-    fclose(file);
-    return Error("Failed to write private key to file '" + stringify(path) +
-      "': PEM_write_PrivateKey");
-  }
-
-  fclose(file);
-
-  return Nothing();
-}
-
-
-Try<Nothing> write_certificate_file(X509* x509, const Path& path)
-{
-  // We use 'FILE*' here because it is an API requirement by openssl.
-  FILE* file = fopen(path.value.c_str(), "wb");
-  if (file == NULL) {
-    return Error("Failed to open file '" + stringify(path) + "' for writing");
-  }
-
-  if (PEM_write_X509(file, x509) != 1) {
-    fclose(file);
-    return Error("Failed to write certificate to file '" + stringify(path) +
-      "': PEM_write_X509");
-  }
-
-  fclose(file);
-
-  return Nothing();
-}
-
-} // namespace openssl {
-} // namespace network {
-} // namespace process {

http://git-wip-us.apache.org/repos/asf/mesos/blob/06703404/3rdparty/libprocess/src/openssl_util.hpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/openssl_util.hpp 
b/3rdparty/libprocess/src/openssl_util.hpp
deleted file mode 100644
index 0890b63..0000000
--- a/3rdparty/libprocess/src/openssl_util.hpp
+++ /dev/null
@@ -1,111 +0,0 @@
-/**
-* Licensed 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
-*/
-
-#ifndef __OPENSSL_UTIL_HPP__
-#define __OPENSSL_UTIL_HPP__
-
-#include <openssl/ssl.h>
-#include <openssl/x509.h>
-
-#include <stout/nothing.hpp>
-#include <stout/path.hpp>
-#include <stout/try.hpp>
-
-namespace process {
-namespace network {
-namespace openssl {
-
-/**
- * Generates an RSA key.
- *
- * The caller is responsible for calling `EVP_PKEY_free` on the
- * returned EVP_PKEY.
- * @see <a 
href="https://www.openssl.org/docs/crypto/RSA_generate_key.html";>RSA_generate_key_ex</a>
 // NOLINT
- *
- * @param bits The modulus size used to generate the key.
- * @param exponent The public exponent, an odd number.
- *
- * @return A pointer to an EVP_PKEY if successful otherwise an Error.
- */
-Try<EVP_PKEY*> generate_private_rsa_key(
-    int bits = 2048,
-    unsigned long exponent = RSA_F4);
-
-
-/**
- * Generates an X509 certificate.
- *
- * The X509 certificate is generated for the @param subject_key and
- * signed by the @param sign_key. The caller is responsible for
- * calling `X509_free` on the returned X509 object.
- * The common name of the certificate will be set to @param hostname
- * or that of the localhost if @param hostname is not provided.
- * If a @param parent_certificate is provided, then the issuer name of
- * the certificate will be set to the subject name of the
- * @param parent_certificate. Otherwise, it is assumed this is a
- * self-signed certificate in which case the @param subject_key must
- * be the same as the @param sign_key, and the issuer name will be the
- * same as the subject name.
- *
- * @param subject_key The key that will be made public by the
- *     certificate.
- * @param sign_key The private key used to sign the certificate.
- * @param parent_certificate An optional parent certificate that will
- *     be used to set the issuer name.
- * @param serial The serial number of the certificate.
- * @param days The number of days from the current time that the
- *     certificate will be valid.
- * @param hostname An optional hostname used to set the common name of
- *     the certificate.
- *
- * @return A pointer to an X509 certificate if successful otherwise an
- *     Error.
- */
-Try<X509*> generate_x509(
-    EVP_PKEY* subject_key,
-    EVP_PKEY* sign_key,
-    const Option<X509*>& parent_certificate = None(),
-    int serial = 1,
-    int days = 365,
-    Option<std::string> hostname = None());
-
-
-/**
- * Writes a private key (EVP_PKEY) to a file on disk.
- * @see <a 
href="https://www.openssl.org/docs/crypto/pem.html";>PEM_write_PrivateKey</a> // 
NOLINT
- *
- * @param private_key The private key to write.
- * @param path The file location to create the file.
- *
- * @return Nothing if successful otherwise an Error.
- */
-Try<Nothing> write_key_file(EVP_PKEY* private_key, const Path& path);
-
-
-/**
- * Writes an X509 certificate (X509) to a file on disk.
- * @see <a 
href="https://www.openssl.org/docs/crypto/pem.html";>PEM_write_X509</a> // NOLINT
- *
- * @param x509 The certificate to write.
- * @param path The file location to create the file.
- *
- * @return Nothing if successful otherwise an Error.
- */
-Try<Nothing> write_certificate_file(X509* x509, const Path& path);
-
-} // namespace openssl {
-} // namespace network {
-} // namespace process {
-
-#endif // __OPENSSL_UTIL_HPP__

http://git-wip-us.apache.org/repos/asf/mesos/blob/06703404/3rdparty/libprocess/src/ssl/utilities.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/ssl/utilities.cpp 
b/3rdparty/libprocess/src/ssl/utilities.cpp
new file mode 100644
index 0000000..b244964
--- /dev/null
+++ b/3rdparty/libprocess/src/ssl/utilities.cpp
@@ -0,0 +1,262 @@
+/**
+* Licensed 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 <process/ssl/utilities.hpp>
+
+#include <openssl/err.h>
+#include <openssl/rsa.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+
+#include <stout/net.hpp>
+#include <stout/stringify.hpp>
+
+// TODO(jmlvanre): Add higher level abstractions for key and
+// certificate generation.
+
+namespace process {
+namespace network {
+namespace openssl {
+
+Try<EVP_PKEY*> generate_private_rsa_key(int bits, unsigned long _exponent)
+{
+  // Allocate the in-memory structure for the private key.
+  EVP_PKEY* private_key = EVP_PKEY_new();
+  if (private_key == NULL) {
+    return Error("Failed to allocate key: EVP_PKEY_new");
+  }
+
+  // Allocate space for the exponent.
+  BIGNUM* exponent = BN_new();
+  if (exponent == NULL) {
+    EVP_PKEY_free(private_key);
+    return Error("Failed to allocate exponent: BN_new");
+  }
+
+  // Assign the exponent.
+  if (BN_set_word(exponent, _exponent) != 1) {
+    BN_free(exponent);
+    EVP_PKEY_free(private_key);
+    return Error("Failed to set exponent: BN_set_word");
+  }
+
+  // Allocate the in-memory structure for the key pair.
+  RSA* rsa = RSA_new();
+  if (rsa == NULL) {
+    BN_free(exponent);
+    EVP_PKEY_free(private_key);
+    return Error("Failed to allocate RSA: RSA_new");
+  }
+
+  // Generate the RSA key pair.
+  if (RSA_generate_key_ex(rsa, bits, exponent, NULL) != 1) {
+    RSA_free(rsa);
+    BN_free(exponent);
+    EVP_PKEY_free(private_key);
+    return Error(ERR_error_string(ERR_get_error(), NULL));
+  }
+
+  // We no longer need the exponent, so let's free it.
+  BN_free(exponent);
+
+  // Associate the RSA key with the private key. If this association
+  // is successful, then the RSA key will be freed when the private
+  // key is freed.
+  if (EVP_PKEY_assign_RSA(private_key, rsa) != 1) {
+    RSA_free(rsa);
+    EVP_PKEY_free(private_key);
+    return Error("Failed to assign RSA key: EVP_PKEY_assign_RSA");
+  }
+
+  return private_key;
+}
+
+
+Try<X509*> generate_x509(
+    EVP_PKEY* subject_key,
+    EVP_PKEY* sign_key,
+    const Option<X509*>& parent_certificate,
+    int serial,
+    int days,
+    Option<std::string> hostname)
+{
+  Option<X509_NAME*> issuer_name = None();
+  if (parent_certificate.isNone()) {
+    // If there is no parent certificate, then the subject and
+    // signing key must be the same.
+    if (subject_key != sign_key) {
+      return Error("Subject vs signing key mismatch");
+    }
+  } else {
+    // If there is a parent certificate, then set the issuer name to
+    // be that of the parent.
+    issuer_name = X509_get_subject_name(parent_certificate.get());
+
+    if (issuer_name.get() == NULL) {
+      return Error("Failed to get subject name of parent certificate: "
+        "X509_get_subject_name");
+    }
+  }
+
+  // Allocate the in-memory structure for the certificate.
+  X509* x509 = X509_new();
+  if (x509 == NULL) {
+    return Error("Failed to allocate certification: X509_new");
+  }
+
+  // Set the version to V3.
+  if (X509_set_version(x509, 2) != 1) {
+    X509_free(x509);
+    return Error("Failed to set version: X509_set_version");
+  }
+
+  // Set the serial number.
+  if (ASN1_INTEGER_set(X509_get_serialNumber(x509), serial) != 1) {
+    X509_free(x509);
+    return Error("Failed to set serial number: ASN1_INTEGER_set");
+  }
+
+  // Make this certificate valid for 'days' number of days from now.
+  if (X509_gmtime_adj(X509_get_notBefore(x509), 0) == NULL ||
+      X509_gmtime_adj(X509_get_notAfter(x509),
+                      60L * 60L * 24L * days) == NULL) {
+    X509_free(x509);
+    return Error("Failed to set valid days of certificate: X509_gmtime_adj");
+  }
+
+  // Set the public key for our certificate based on the subject key.
+  if (X509_set_pubkey(x509, subject_key) != 1) {
+    X509_free(x509);
+    return Error("Failed to set public key: X509_set_pubkey");
+  }
+
+  // Figure out our hostname if one was not provided.
+  if (hostname.isNone()) {
+    const Try<std::string> _hostname = net::hostname();
+    if (_hostname.isError()) {
+      X509_free(x509);
+      return Error("Failed to determine hostname");
+    }
+
+    hostname = _hostname.get();
+  }
+
+  // Grab the subject name of the new certificate.
+  X509_NAME* name = X509_get_subject_name(x509);
+  if (name == NULL) {
+    X509_free(x509);
+    return Error("Failed to get subject name: X509_get_subject_name");
+  }
+
+  // Set the country code, organization, and common name.
+  if (X509_NAME_add_entry_by_txt(
+          name,
+          "C",
+          MBSTRING_ASC,
+          reinterpret_cast<const unsigned char*>("US"),
+          -1,
+          -1,
+          0) != 1) {
+    X509_free(x509);
+    return Error("Failed to set country code: X509_NAME_add_entry_by_txt");
+  }
+
+  if (X509_NAME_add_entry_by_txt(
+          name,
+          "O",
+          MBSTRING_ASC,
+          reinterpret_cast<const unsigned char*>("Test"),
+          -1,
+          -1,
+          0) != 1) {
+    X509_free(x509);
+    return Error("Failed to set organization name: 
X509_NAME_add_entry_by_txt");
+  }
+
+  if (X509_NAME_add_entry_by_txt(
+          name,
+          "CN",
+          MBSTRING_ASC,
+          reinterpret_cast<const unsigned char*>(hostname.get().c_str()),
+          -1,
+          -1,
+          0) != 1) {
+    X509_free(x509);
+    return Error("Failed to set common name: X509_NAME_add_entry_by_txt");
+  }
+
+  // Set the issuer name to be the same as the subject if it is not
+  // already set (this is a self-signed certificate).
+  if (issuer_name.isNone()) {
+    issuer_name = name;
+  }
+
+  CHECK_SOME(issuer_name);
+  if (X509_set_issuer_name(x509, issuer_name.get()) != 1) {
+    X509_free(x509);
+    return Error("Failed to set issuer name: X509_set_issuer_name");
+  }
+
+  // Sign the certificate with the sign key.
+  if (X509_sign(x509, sign_key, EVP_sha1()) == 0) {
+    X509_free(x509);
+    return Error("Failed to sign certificate: X509_sign");
+  }
+
+  return x509;
+}
+
+
+Try<Nothing> write_key_file(EVP_PKEY* private_key, const Path& path)
+{
+  // We use 'FILE*' here because it is an API requirement by openssl.
+  FILE* file = fopen(path.value.c_str(), "wb");
+  if (file == NULL) {
+    return Error("Failed to open file '" + stringify(path) + "' for writing");
+  }
+
+  if (PEM_write_PrivateKey(file, private_key, NULL, NULL, 0, NULL, NULL) != 1) 
{
+    fclose(file);
+    return Error("Failed to write private key to file '" + stringify(path) +
+      "': PEM_write_PrivateKey");
+  }
+
+  fclose(file);
+
+  return Nothing();
+}
+
+
+Try<Nothing> write_certificate_file(X509* x509, const Path& path)
+{
+  // We use 'FILE*' here because it is an API requirement by openssl.
+  FILE* file = fopen(path.value.c_str(), "wb");
+  if (file == NULL) {
+    return Error("Failed to open file '" + stringify(path) + "' for writing");
+  }
+
+  if (PEM_write_X509(file, x509) != 1) {
+    fclose(file);
+    return Error("Failed to write certificate to file '" + stringify(path) +
+      "': PEM_write_X509");
+  }
+
+  fclose(file);
+
+  return Nothing();
+}
+
+} // namespace openssl {
+} // namespace network {
+} // namespace process {

http://git-wip-us.apache.org/repos/asf/mesos/blob/06703404/3rdparty/libprocess/src/tests/ssl_tests.cpp
----------------------------------------------------------------------
diff --git a/3rdparty/libprocess/src/tests/ssl_tests.cpp 
b/3rdparty/libprocess/src/tests/ssl_tests.cpp
index 7a316bc..ee30a02 100644
--- a/3rdparty/libprocess/src/tests/ssl_tests.cpp
+++ b/3rdparty/libprocess/src/tests/ssl_tests.cpp
@@ -14,22 +14,19 @@
 
 #include <stdio.h>
 
-#include <openssl/rsa.h>
-#include <openssl/bio.h>
-#include <openssl/x509.h>
-#include <openssl/x509v3.h>
-
 #include <process/future.hpp>
 #include <process/gtest.hpp>
 #include <process/io.hpp>
 #include <process/socket.hpp>
 #include <process/subprocess.hpp>
 
+#include <process/ssl/gtest.hpp>
+#include <process/ssl/utilities.hpp>
+
 #include <stout/gtest.hpp>
 #include <stout/os.hpp>
 
 #include "openssl.hpp"
-#include "openssl_util.hpp"
 
 using std::map;
 using std::string;
@@ -38,18 +35,6 @@ using std::vector;
 // We only run these tests if we have configured with '--enable-ssl'.
 #ifdef USE_SSL_SOCKET
 
-namespace process {
-namespace network {
-namespace openssl {
-
-// Forward declare the `reinitialize()` function since we want to
-// programatically change SSL flags during tests.
-void reinitialize();
-
-} // namespace openssl {
-} // namespace network {
-} // namespace process {
-
 using namespace process;
 using namespace process::network;
 
@@ -98,298 +83,6 @@ Future<Nothing> await_subprocess(
 }
 
 
-/**
- * A Test fixture that sets up SSL keys and certificates.
- *
- * This class sets up a private key and certificate pair at
- * SSLTest::key_path and SSLTest::certificate_path.
- * It also sets up an independent 'scrap' pair that can be used to
- * test an invalid certificate authority chain. These can be found at
- * SSLTest::scrap_key_path and SSLTest::scrap_certificate_path.
- *
- * There are some helper functions like SSLTest::setup_server and
- * SSLTest::launch_client that factor out common behavior used in
- * tests.
- */
-class SSLTest : public ::testing::Test
-{
-protected:
-  SSLTest() : data("Hello World!") {}
-
-  /**
-   * @return The path to the authorized private key.
-   */
-  static const Path& key_path()
-  {
-    static Path path(path::join(os::getcwd(), "key.pem"));
-    return path;
-  }
-
-  /**
-   * @return The path to the authorized certificate.
-   */
-  static const Path& certificate_path()
-  {
-    static Path path(path::join(os::getcwd(), "cert.pem"));
-    return path;
-  }
-
-  /**
-   * @return The path to the unauthorized private key.
-   */
-  static const Path& scrap_key_path()
-  {
-    static Path path(path::join(os::getcwd(), "scrap_key.pem"));
-    return path;
-  }
-
-  /**
-   * @return The path to the unauthorized certificate.
-   */
-  static const Path& scrap_certificate_path()
-  {
-    static Path path(path::join(os::getcwd(), "scrap_cert.pem"));
-    return path;
-  }
-
-  static void SetUpTestCase()
-  {
-    // We store the allocated objects in these results so that we can
-    // have a consolidated 'cleanup()' function. This makes all the
-    // 'EXIT()' calls more readable and less error prone.
-    Result<EVP_PKEY*> private_key = None();
-    Result<X509*> certificate = None();
-    Result<EVP_PKEY*> scrap_key = None();
-    Result<X509*> scrap_certificate = None();
-
-    auto cleanup = [&private_key, &certificate, &scrap_key, 
&scrap_certificate](
-        bool failure = true) {
-      if (private_key.isSome()) { EVP_PKEY_free(private_key.get()); }
-      if (certificate.isSome()) { X509_free(certificate.get()); }
-      if (scrap_key.isSome()) { EVP_PKEY_free(scrap_key.get()); }
-      if (scrap_certificate.isSome()) { X509_free(scrap_certificate.get()); }
-
-      // If we are under a failure condition, clean up any files we
-      // already generated. The expected behavior is that they will be
-      // cleaned up in 'TearDownTestCase()'; however, we call ABORT
-      // during 'SetUpTestCase()' failures.
-      if (failure) {
-        os::rm(key_path().value);
-        os::rm(certificate_path().value);
-        os::rm(scrap_key_path().value);
-        os::rm(scrap_certificate_path().value);
-      }
-    };
-
-    // Generate the authority key.
-    private_key = openssl::generate_private_rsa_key();
-    if (private_key.isError()) {
-      ABORT("Could not generate private key: " + private_key.error());
-    }
-
-    // Figure out the hostname that 'INADDR_LOOPBACK' will bind to.
-    // Set the hostname of the certificate to this hostname so that
-    // hostname verification of the certificate will pass.
-    Try<string> hostname = net::getHostname(net::IP(INADDR_LOOPBACK));
-    if (hostname.isError()) {
-      cleanup();
-      ABORT("Could not determine hostname of 'INADDR_LOOPBACK': " +
-            hostname.error());
-    }
-
-    // Generate an authorized certificate.
-    certificate = openssl::generate_x509(
-        private_key.get(),
-        private_key.get(),
-        None(),
-        1,
-        365,
-        hostname.get());
-
-    if (certificate.isError()) {
-      cleanup();
-      ABORT("Could not generate certificate: " + certificate.error());
-    }
-
-    // Write the authority key to disk.
-    Try<Nothing> key_write =
-      openssl::write_key_file(private_key.get(), key_path());
-
-    if (key_write.isError()) {
-      cleanup();
-      ABORT("Could not write private key to disk: " + key_write.error());
-    }
-
-    // Write the authorized certificate to disk.
-    Try<Nothing> certificate_write =
-      openssl::write_certificate_file(certificate.get(), certificate_path());
-
-    if (certificate_write.isError()) {
-      cleanup();
-      ABORT("Could not write certificate to disk: " +
-            certificate_write.error());
-    }
-
-    // Generate a scrap key.
-    scrap_key = openssl::generate_private_rsa_key();
-    if (scrap_key.isError()) {
-      cleanup();
-      ABORT("Could not generate a scrap private key: " + scrap_key.error());
-    }
-
-    // Write the scrap key to disk.
-    key_write = openssl::write_key_file(scrap_key.get(), scrap_key_path());
-
-    if (key_write.isError()) {
-      cleanup();
-      ABORT("Could not write scrap key to disk: " + key_write.error());
-    }
-
-    // Generate a scrap certificate.
-    scrap_certificate =
-      openssl::generate_x509(scrap_key.get(), scrap_key.get());
-
-    if (scrap_certificate.isError()) {
-      cleanup();
-      ABORT("Could not generate a scrap certificate: " +
-            scrap_certificate.error());
-    }
-
-    // Write the scrap certificate to disk.
-    certificate_write = openssl::write_certificate_file(
-        scrap_certificate.get(),
-        scrap_certificate_path());
-
-    if (certificate_write.isError()) {
-      cleanup();
-      ABORT("Could not write scrap certificate to disk: " +
-            certificate_write.error());
-    }
-
-    // Since we successfully set up all our state, we call cleanup
-    // with failure set to 'false'.
-    cleanup(false);
-  }
-
-  static void TearDownTestCase()
-  {
-    // Clean up all the pem files we generated.
-    os::rm(key_path().value);
-    os::rm(certificate_path().value);
-    os::rm(scrap_key_path().value);
-    os::rm(scrap_certificate_path().value);
-  }
-
-  virtual void SetUp()
-  {
-    // This unsets all the SSL environment variables. Necessary for
-    // ensuring a clean starting slate between tests.
-    os::unsetenv("SSL_ENABLED");
-    os::unsetenv("SSL_SUPPORT_DOWNGRADE");
-    os::unsetenv("SSL_CERT_FILE");
-    os::unsetenv("SSL_KEY_FILE");
-    os::unsetenv("SSL_VERIFY_CERT");
-    os::unsetenv("SSL_REQUIRE_CERT");
-    os::unsetenv("SSL_VERIFY_DEPTH");
-    os::unsetenv("SSL_CA_DIR");
-    os::unsetenv("SSL_CA_FILE");
-    os::unsetenv("SSL_CIPHERS");
-    os::unsetenv("SSL_ENABLE_SSL_V3");
-    os::unsetenv("SSL_ENABLE_TLS_V1_0");
-    os::unsetenv("SSL_ENABLE_TLS_V1_1");
-    os::unsetenv("SSL_ENABLE_TLS_V1_2");
-  }
-
-  /**
-   * Initializes a listening server.
-   *
-   * @param environment The SSL environment variables to launch the
-   *     server socket with.
-   *
-   * @return Socket if successful otherwise an Error.
-   */
-  Try<Socket> setup_server(const map<string, string>& environment)
-  {
-    foreachpair (const string& name, const string& value, environment) {
-      os::setenv(name, value);
-    }
-    openssl::reinitialize();
-
-    const Try<Socket> create = Socket::create(Socket::SSL);
-    if (create.isError()) {
-      return Error(create.error());
-    }
-
-    Socket server = create.get();
-
-    // We need to explicitly bind to INADDR_LOOPBACK so the
-    // certificate we create in this test fixture can be verified.
-    Try<Address> bind = server.bind(Address(net::IP(INADDR_LOOPBACK), 0));
-    if (bind.isError()) {
-      return Error(bind.error());
-    }
-
-    const Try<Nothing> listen = server.listen(BACKLOG);
-    if (listen.isError()) {
-      return Error(listen.error());
-    }
-
-    return server;
-  }
-
-  /**
-   * Launches a test SSL client as a subprocess connecting to the
-   * server.
-   *
-   * The subprocess calls the 'ssl-client' binary with the provided
-   * environment.
-   *
-   * @param environment The SSL environment variables to launch the
-   *     SSL client subprocess with.
-   * @param use_ssl_socket Whether the SSL client will try to connect
-   *     using an SSL socket or a POLL socket.
-   *
-   * @return Subprocess if successful otherwise an Error.
-   */
-  Try<Subprocess> launch_client(
-      const map<string, string>& environment,
-      const Socket& server,
-      bool use_ssl_socket)
-  {
-    const Try<Address> address = server.address();
-    if (address.isError()) {
-      return Error(address.error());
-    }
-
-    // Set up arguments to be passed to the 'client-ssl' binary.
-    const vector<string> argv = {
-      "ssl-client",
-      "--use_ssl=" + stringify(use_ssl_socket),
-      "--server=127.0.0.1",
-      "--port=" + stringify(address.get().port),
-      "--data=" + data};
-
-    Result<string> path = os::realpath(BUILD_DIR);
-    if (!path.isSome()) {
-      return Error("Could not establish build directory path");
-    }
-
-    return subprocess(
-        path::join(path.get(), "ssl-client"),
-        argv,
-        Subprocess::PIPE(),
-        Subprocess::PIPE(),
-        Subprocess::FD(STDERR_FILENO),
-        None(),
-        environment);
-  }
-
-  static constexpr size_t BACKLOG = 5;
-
-  const string data;
-};
-
-
 // Ensure that we can't create an SSL socket when SSL is not enabled.
 TEST(SSL, Disabled)
 {

Reply via email to