Skip to content

Commit

Permalink
Fix client_ssl_test and server_ssl_test when built against OpenSSL 1.…
Browse files Browse the repository at this point in the history
…0.2. (grpc#25865)

* Add Python mTLS greeter example (#40)

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

This reverts commit 383c247.

* 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>
  • Loading branch information
matthewstevenson88 and Ryanfsdf authored Jun 3, 2021
1 parent c46dd9c commit 57dd2eb
Show file tree
Hide file tree
Showing 5 changed files with 80 additions and 4 deletions.
74 changes: 71 additions & 3 deletions test/core/handshake/client_ssl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@
#include <grpc/support/alloc.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/iomgr/load_file.h"
#include "test/core/util/port.h"
Expand All @@ -47,10 +49,34 @@
#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key"
#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.
typedef struct {
int socket;
char* alpn_preferred;
SslLibraryInfo* ssl_library_info;
} server_args;

// Based on https://wiki.openssl.org/index.php/Simple_TLS_Server.
Expand Down Expand Up @@ -135,6 +161,28 @@ static int alpn_select_cb(SSL* /*ssl*/, const uint8_t** out, uint8_t* out_len,
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
// https://wiki.openssl.org/index.php/Simple_TLS_Server and the gRPC core
// internals in src/core/tsi/ssl_transport_security.c.
Expand All @@ -143,6 +191,7 @@ static void server_thread(void* arg) {

SSL_load_error_strings();
OpenSSL_add_ssl_algorithms();
args->ssl_library_info->Notify();

const SSL_METHOD* method = TLSv1_2_server_method();
SSL_CTX* ctx = SSL_CTX_new(method);
Expand All @@ -154,16 +203,23 @@ static void server_thread(void* arg) {

// Load key pair.
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);
abort();
}
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);
abort();
}

// 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 =
"ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-"
"SHA384:ECDHE-RSA-AES256-GCM-SHA384";
Expand All @@ -173,6 +229,14 @@ static void server_thread(void* arg) {
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.
SSL_CTX_set_alpn_select_cb(ctx, alpn_select_cb, args->alpn_preferred);

Expand All @@ -190,6 +254,7 @@ static void server_thread(void* arg) {

// Establish a SSL* and accept at SSL layer.
SSL* ssl = SSL_new(ctx);
SSL_set_info_callback(ssl, ssl_server_info_callback);
GPR_ASSERT(ssl);
SSL_set_fd(ssl, client);
if (SSL_accept(ssl) <= 0) {
Expand All @@ -212,7 +277,6 @@ static void server_thread(void* arg) {
close(client);
close(sock);
SSL_CTX_free(ctx);
EVP_cleanup();
}

// This test launches a minimal TLS server on a separate thread and then
Expand All @@ -238,11 +302,13 @@ static bool client_ssl_test(char* server_alpn_preferred) {
GPR_ASSERT(server_socket > 0 && port > 0);

// 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;
grpc_core::Thread thd("grpc_client_ssl_test", server_thread, &args, &ok);
GPR_ASSERT(ok);
thd.Start();
ssl_library_info.Await();

// Load key pair and establish client SSL credentials.
grpc_ssl_pem_key_cert_pair pem_key_cert_pair;
Expand Down Expand Up @@ -326,6 +392,8 @@ int main(int argc, char* argv[]) {
// preference. This validates the client is correctly validating ALPN returns
// and sanity checks the client_ssl_test.
GPR_ASSERT(!client_ssl_test(const_cast<char*>("foo")));
// Clean up the SSL libraries.
EVP_cleanup();
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions test/core/handshake/readahead_handshaker_server_ssl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ int main(int /*argc*/, char* /*argv*/[]) {
absl::make_unique<grpc_core::ReadAheadHandshakerFactory>());
const char* full_alpn_list[] = {"grpc-exp", "h2"};
GPR_ASSERT(server_ssl_test(full_alpn_list, 2, "grpc-exp"));
CleanupSslLibrary();
grpc_shutdown();
return 0;
}
1 change: 1 addition & 0 deletions test/core/handshake/server_ssl.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,6 @@ int main(int argc, char* argv[]) {
// and sanity checks the server_ssl_test.
const char* fake_alpn_list[] = {"foo"};
GPR_ASSERT(!server_ssl_test(fake_alpn_list, 1, "foo"));
CleanupSslLibrary();
return 0;
}
3 changes: 2 additions & 1 deletion test/core/handshake/server_ssl_common.cc
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,6 @@ bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,
SSL_free(ssl);
gpr_free(alpn_protos);
SSL_CTX_free(ctx);
EVP_cleanup();
close(sock);

thd.Join();
Expand All @@ -278,3 +277,5 @@ bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,

return success;
}

void CleanupSslLibrary() { EVP_cleanup(); }
5 changes: 5 additions & 0 deletions test/core/handshake/server_ssl_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,9 @@
bool server_ssl_test(const char* alpn_list[], unsigned int alpn_list_len,
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

0 comments on commit 57dd2eb

Please sign in to comment.