Fix client_ssl_test and server_ssl_test when built against OpenSSL 1.0.2. (#25865)

* Add Python mTLS greeter example (#40)

* Revert "Add Python mTLS greeter example (#40)"

This reverts commit 383c247775.

* Postpone EVP_cleanup until after last server_ssl_test run completes.

* Fix readahead_hs_server_ssl

* Clang fixes and client side initialization fix.

* Comment out EVP_cleanup on client side.

* remove TLS 1.3 ciphers'

* change to using server0 credentials

* log what TLS method is used'

* check compatibility of private key and cert

* Try allowing server to use all ciphers.

* Add logging for test server.

* Fix private key check logging.

* add include for tracing

* define tsi_tracing_enabled flag

* rename tsi_tracing_enabled flag

* try printing bytes to send to peer

* Add automatic curve selection

* Remove logging from SSL transport security

* Add back TLS 1.3 ciphersuites.

Co-authored-by: Ryan Kim <Ryanfsdf@users.noreply.github.com>
pull/26426/head
matthewstevenson88 4 years ago committed by GitHub
parent c46dd9ca9d
commit 57dd2eb02e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 74
      test/core/handshake/client_ssl.cc
  2. 1
      test/core/handshake/readahead_handshaker_server_ssl.cc
  3. 1
      test/core/handshake/server_ssl.cc
  4. 3
      test/core/handshake/server_ssl_common.cc
  5. 5
      test/core/handshake/server_ssl_common.h

@ -38,6 +38,8 @@
#include <grpc/support/alloc.h> #include <grpc/support/alloc.h>
#include <grpc/support/log.h> #include <grpc/support/log.h>
#include "src/core/lib/debug/trace.h"
#include "src/core/lib/gprpp/sync.h"
#include "src/core/lib/gprpp/thd.h" #include "src/core/lib/gprpp/thd.h"
#include "src/core/lib/iomgr/load_file.h" #include "src/core/lib/iomgr/load_file.h"
#include "test/core/util/port.h" #include "test/core/util/port.h"
@ -47,10 +49,34 @@
#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" #define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key"
#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" #define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem"
grpc_core::TraceFlag client_ssl_tsi_tracing_enabled(false, "tsi");
class SslLibraryInfo {
public:
SslLibraryInfo() {}
void Notify() {
grpc_core::MutexLock lock(&mu_);
ready_ = true;
cv_.Signal();
}
void Await() {
grpc_core::MutexLock lock(&mu_);
grpc_core::WaitUntil(&cv_, &mu_, [this] { return ready_; });
}
private:
grpc_core::Mutex mu_;
grpc_core::CondVar cv_;
bool ready_ = false;
};
// Arguments for TLS server thread. // Arguments for TLS server thread.
typedef struct { typedef struct {
int socket; int socket;
char* alpn_preferred; char* alpn_preferred;
SslLibraryInfo* ssl_library_info;
} server_args; } server_args;
// Based on https://wiki.openssl.org/index.php/Simple_TLS_Server. // Based on https://wiki.openssl.org/index.php/Simple_TLS_Server.
@ -135,6 +161,28 @@ static int alpn_select_cb(SSL* /*ssl*/, const uint8_t** out, uint8_t* out_len,
return SSL_TLSEXT_ERR_OK; return SSL_TLSEXT_ERR_OK;
} }
static void ssl_log_where_info(const SSL* ssl, int where, int flag,
const char* msg) {
if ((where & flag) &&
GRPC_TRACE_FLAG_ENABLED(client_ssl_tsi_tracing_enabled)) {
gpr_log(GPR_INFO, "%20.20s - %30.30s - %5.10s", msg,
SSL_state_string_long(ssl), SSL_state_string(ssl));
}
}
static void ssl_server_info_callback(const SSL* ssl, int where, int ret) {
if (ret == 0) {
gpr_log(GPR_ERROR, "ssl_server_info_callback: error occurred.\n");
return;
}
ssl_log_where_info(ssl, where, SSL_CB_LOOP, "Server: LOOP");
ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_START,
"Server: HANDSHAKE START");
ssl_log_where_info(ssl, where, SSL_CB_HANDSHAKE_DONE,
"Server: HANDSHAKE DONE");
}
// Minimal TLS server. This is largely based on the example at // Minimal TLS server. This is largely based on the example at
// https://wiki.openssl.org/index.php/Simple_TLS_Server and the gRPC core // https://wiki.openssl.org/index.php/Simple_TLS_Server and the gRPC core
// internals in src/core/tsi/ssl_transport_security.c. // internals in src/core/tsi/ssl_transport_security.c.
@ -143,6 +191,7 @@ static void server_thread(void* arg) {
SSL_load_error_strings(); SSL_load_error_strings();
OpenSSL_add_ssl_algorithms(); OpenSSL_add_ssl_algorithms();
args->ssl_library_info->Notify();
const SSL_METHOD* method = TLSv1_2_server_method(); const SSL_METHOD* method = TLSv1_2_server_method();
SSL_CTX* ctx = SSL_CTX_new(method); SSL_CTX* ctx = SSL_CTX_new(method);
@ -154,16 +203,23 @@ static void server_thread(void* arg) {
// Load key pair. // Load key pair.
if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) {
perror("Unable to use certificate file.");
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
abort(); abort();
} }
if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) {
perror("Unable to use private key file.");
ERR_print_errors_fp(stderr);
abort();
}
if (SSL_CTX_check_private_key(ctx) != 1) {
perror("Check private key failed.");
ERR_print_errors_fp(stderr); ERR_print_errors_fp(stderr);
abort(); abort();
} }
// Set the cipher list to match the one expressed in // Set the cipher list to match the one expressed in
// src/core/tsi/ssl_transport_security.c. // src/core/tsi/ssl_transport_security.cc.
const char* cipher_list = const char* cipher_list =
"ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-"
"SHA384:ECDHE-RSA-AES256-GCM-SHA384"; "SHA384:ECDHE-RSA-AES256-GCM-SHA384";
@ -173,6 +229,14 @@ static void server_thread(void* arg) {
abort(); abort();
} }
// Enable automatic curve selection. This is a NO-OP when using OpenSSL
// versions > 1.0.2.
if (!SSL_CTX_set_ecdh_auto(ctx, /*onoff=*/1)) {
ERR_print_errors_fp(stderr);
gpr_log(GPR_ERROR, "Couldn't set automatic curve selection.");
abort();
}
// Register the ALPN selection callback. // Register the ALPN selection callback.
SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, args->alpn_preferred); SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, args->alpn_preferred);
@ -190,6 +254,7 @@ static void server_thread(void* arg) {
// Establish a SSL* and accept at SSL layer. // Establish a SSL* and accept at SSL layer.
SSL* ssl = SSL_new(ctx); SSL* ssl = SSL_new(ctx);
SSL_set_info_callback(ssl, ssl_server_info_callback);
GPR_ASSERT(ssl); GPR_ASSERT(ssl);
SSL_set_fd(ssl, client); SSL_set_fd(ssl, client);
if (SSL_accept(ssl) <= 0) { if (SSL_accept(ssl) <= 0) {
@ -212,7 +277,6 @@ static void server_thread(void* arg) {
close(client); close(client);
close(sock); close(sock);
SSL_CTX_free(ctx); SSL_CTX_free(ctx);
EVP_cleanup();
} }
// This test launches a minimal TLS server on a separate thread and then // This test launches a minimal TLS server on a separate thread and then
@ -238,11 +302,13 @@ static bool client_ssl_test(char* server_alpn_preferred) {
GPR_ASSERT(server_socket > 0 && port > 0); GPR_ASSERT(server_socket > 0 && port > 0);
// Launch the TLS server thread. // Launch the TLS server thread.
server_args args = {server_socket, server_alpn_preferred}; SslLibraryInfo ssl_library_info;
server_args args = {server_socket, server_alpn_preferred, &ssl_library_info};
bool ok; bool ok;
grpc_core::Thread thd("grpc_client_ssl_test", server_thread, &args, &ok); grpc_core::Thread thd("grpc_client_ssl_test", server_thread, &args, &ok);
GPR_ASSERT(ok); GPR_ASSERT(ok);
thd.Start(); thd.Start();
ssl_library_info.Await();
// Load key pair and establish client SSL credentials. // Load key pair and establish client SSL credentials.
grpc_ssl_pem_key_cert_pair pem_key_cert_pair; grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
@ -326,6 +392,8 @@ int main(int argc, char* argv[]) {
// preference. This validates the client is correctly validating ALPN returns // preference. This validates the client is correctly validating ALPN returns
// and sanity checks the client_ssl_test. // and sanity checks the client_ssl_test.
GPR_ASSERT(!client_ssl_test(const_cast<char*>("foo"))); GPR_ASSERT(!client_ssl_test(const_cast<char*>("foo")));
// Clean up the SSL libraries.
EVP_cleanup();
return 0; return 0;
} }

@ -83,6 +83,7 @@ int main(int /*argc*/, char* /*argv*/[]) {
absl::make_unique<grpc_core::ReadAheadHandshakerFactory>()); absl::make_unique<grpc_core::ReadAheadHandshakerFactory>());
const char* full_alpn_list[] = {"grpc-exp", "h2"}; const char* full_alpn_list[] = {"grpc-exp", "h2"};
GPR_ASSERT(server_ssl_test(full_alpn_list, 2, "grpc-exp")); GPR_ASSERT(server_ssl_test(full_alpn_list, 2, "grpc-exp"));
CleanupSslLibrary();
grpc_shutdown(); grpc_shutdown();
return 0; return 0;
} }

@ -54,5 +54,6 @@ int main(int argc, char* argv[]) {
// and sanity checks the server_ssl_test. // and sanity checks the server_ssl_test.
const char* fake_alpn_list[] = {"foo"}; const char* fake_alpn_list[] = {"foo"};
GPR_ASSERT(!server_ssl_test(fake_alpn_list, 1, "foo")); GPR_ASSERT(!server_ssl_test(fake_alpn_list, 1, "foo"));
CleanupSslLibrary();
return 0; return 0;
} }

@ -269,7 +269,6 @@ bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,
SSL_free(ssl); SSL_free(ssl);
gpr_free(alpn_protos); gpr_free(alpn_protos);
SSL_CTX_free(ctx); SSL_CTX_free(ctx);
EVP_cleanup();
close(sock); close(sock);
thd.Join(); thd.Join();
@ -278,3 +277,5 @@ bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,
return success; return success;
} }
void CleanupSslLibrary() { EVP_cleanup(); }

@ -33,4 +33,9 @@
bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len, bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,
const char* alpn_expected); const char* alpn_expected);
/** Cleans up the SSL library. To be called after the last call to
* server_ssl_test returns. This is a NO-OP when gRPC is built against OpenSSL
* versions > 1.0.2. */
void CleanupSslLibrary();
#endif // GRPC_SERVER_SSL_COMMON_H #endif // GRPC_SERVER_SSL_COMMON_H

Loading…
Cancel
Save