From 4ac2b8e585cbf7064f9bdde4eabaf8ff42801142 Mon Sep 17 00:00:00 2001 From: Craig Tiller Date: Fri, 10 Nov 2017 14:14:17 -0800 Subject: Enable clang-tidy as a sanity check, fix up all known failures --- test/core/handshake/client_ssl.cc | 10 +++++----- test/core/handshake/server_ssl.cc | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'test/core/handshake') diff --git a/test/core/handshake/client_ssl.cc b/test/core/handshake/client_ssl.cc index b8cfd627a9..2b149a73b3 100644 --- a/test/core/handshake/client_ssl.cc +++ b/test/core/handshake/client_ssl.cc @@ -246,7 +246,7 @@ static bool client_ssl_test(char* server_alpn_preferred) { pem_key_cert_pair.private_key = (const char*)GRPC_SLICE_START_PTR(key_slice); pem_key_cert_pair.cert_chain = (const char*)GRPC_SLICE_START_PTR(cert_slice); grpc_channel_credentials* ssl_creds = - grpc_ssl_credentials_create(ca_cert, &pem_key_cert_pair, NULL); + grpc_ssl_credentials_create(ca_cert, &pem_key_cert_pair, nullptr); // Establish a channel pointing at the TLS server. Since the gRPC runtime is // lazy, this won't necessarily establish a connection yet. @@ -260,7 +260,7 @@ static bool client_ssl_test(char* server_alpn_preferred) { grpc_args.num_args = 1; grpc_args.args = &ssl_name_override; grpc_channel* channel = - grpc_secure_channel_create(ssl_creds, target, &grpc_args, NULL); + grpc_secure_channel_create(ssl_creds, target, &grpc_args, nullptr); GPR_ASSERT(channel); gpr_free(target); @@ -274,13 +274,13 @@ static bool client_ssl_test(char* server_alpn_preferred) { // completed and we know that the client's ALPN list satisfied the server. int retries = 10; grpc_connectivity_state state = GRPC_CHANNEL_IDLE; - grpc_completion_queue* cq = grpc_completion_queue_create_for_next(NULL); + grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr); while (state != GRPC_CHANNEL_READY && retries-- > 0) { grpc_channel_watch_connectivity_state( - channel, state, grpc_timeout_seconds_to_deadline(3), cq, NULL); + channel, state, grpc_timeout_seconds_to_deadline(3), cq, nullptr); gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr); GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); state = grpc_channel_check_connectivity_state(channel, 0 /* try_to_connect */); diff --git a/test/core/handshake/server_ssl.cc b/test/core/handshake/server_ssl.cc index bb92c8435a..69c4fdc11b 100644 --- a/test/core/handshake/server_ssl.cc +++ b/test/core/handshake/server_ssl.cc @@ -80,18 +80,18 @@ static void server_thread(void* arg) { pem_key_cert_pair.private_key = (const char*)GRPC_SLICE_START_PTR(key_slice); pem_key_cert_pair.cert_chain = (const char*)GRPC_SLICE_START_PTR(cert_slice); grpc_server_credentials* ssl_creds = grpc_ssl_server_credentials_create( - ca_cert, &pem_key_cert_pair, 1, 0, NULL); + ca_cert, &pem_key_cert_pair, 1, 0, nullptr); // Start server listening on local port. char* addr; gpr_asprintf(&addr, "127.0.0.1:%d", port); - grpc_server* server = grpc_server_create(NULL, NULL); + grpc_server* server = grpc_server_create(nullptr, nullptr); GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); free(addr); - grpc_completion_queue* cq = grpc_completion_queue_create_for_next(NULL); + grpc_completion_queue* cq = grpc_completion_queue_create_for_next(nullptr); - grpc_server_register_completion_queue(server, cq, NULL); + grpc_server_register_completion_queue(server, cq, nullptr); grpc_server_start(server); // Wait a bounded number of time until client_handshake_complete is set, @@ -99,16 +99,16 @@ static void server_thread(void* arg) { int retries = 10; while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) { const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr); GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); } gpr_log(GPR_INFO, "Shutting down server"); - grpc_server_shutdown_and_notify(server, cq, NULL); + grpc_server_shutdown_and_notify(server, cq, nullptr); grpc_completion_queue_shutdown(cq); const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, nullptr); GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); grpc_server_destroy(server); -- cgit v1.2.3 From 3f6b10afba43e2855efd2fbeb3f1f4ea6c2a9657 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Sat, 28 Oct 2017 16:57:29 -0700 Subject: Use existing read buffer in security handshaker if present --- CMakeLists.txt | 38 ++++ Makefile | 42 ++++ build.yaml | 17 ++ .../lib/security/transport/security_handshaker.cc | 45 ++-- .../handshake/readahead_handshaker_server_ssl.c | 103 +++++++++ test/core/handshake/server_ssl.c | 200 +---------------- test/core/handshake/server_ssl_common.c | 237 +++++++++++++++++++++ test/core/handshake/server_ssl_common.h | 22 ++ tools/run_tests/generated/sources_and_headers.json | 21 +- tools/run_tests/generated/tests.json | 20 ++ 10 files changed, 525 insertions(+), 220 deletions(-) create mode 100644 test/core/handshake/readahead_handshaker_server_ssl.c create mode 100644 test/core/handshake/server_ssl_common.c create mode 100644 test/core/handshake/server_ssl_common.h (limited to 'test/core/handshake') diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ac6c9b63d..b3cbbbaea5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -466,6 +466,9 @@ endif() if(_gRPC_PLATFORM_LINUX) add_dependencies(buildtests_c handshake_server) endif() +if(_gRPC_PLATFORM_LINUX) +add_dependencies(buildtests_c handshake_server_with_readahead_handshaker) +endif() add_dependencies(buildtests_c hpack_parser_test) add_dependencies(buildtests_c hpack_table_test) add_dependencies(buildtests_c http_parser_test) @@ -7395,6 +7398,7 @@ if(_gRPC_PLATFORM_LINUX) add_executable(handshake_server test/core/handshake/server_ssl.c + test/core/handshake/server_ssl_common.c ) @@ -7421,6 +7425,40 @@ target_link_libraries(handshake_server gpr ) +endif() +endif (gRPC_BUILD_TESTS) +if (gRPC_BUILD_TESTS) +if(_gRPC_PLATFORM_LINUX) + +add_executable(handshake_server_with_readahead_handshaker + test/core/handshake/readahead_handshaker_server_ssl.c + test/core/handshake/server_ssl_common.c +) + + +target_include_directories(handshake_server_with_readahead_handshaker + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR} + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/include + PRIVATE ${BORINGSSL_ROOT_DIR}/include + PRIVATE ${PROTOBUF_ROOT_DIR}/src + PRIVATE ${BENCHMARK_ROOT_DIR}/include + PRIVATE ${ZLIB_ROOT_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/zlib + PRIVATE ${CARES_INCLUDE_DIR} + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/cares/cares + PRIVATE ${CMAKE_CURRENT_BINARY_DIR}/third_party/gflags/include + PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp +) + +target_link_libraries(handshake_server_with_readahead_handshaker + ${_gRPC_SSL_LIBRARIES} + ${_gRPC_ALLTARGETS_LIBRARIES} + grpc_test_util + grpc + gpr_test_util + gpr +) + endif() endif (gRPC_BUILD_TESTS) if (gRPC_BUILD_TESTS) diff --git a/Makefile b/Makefile index 325c9123d9..7c0ee0d17e 100644 --- a/Makefile +++ b/Makefile @@ -1023,6 +1023,7 @@ grpc_ssl_credentials_test: $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test grpc_verify_jwt: $(BINDIR)/$(CONFIG)/grpc_verify_jwt handshake_client: $(BINDIR)/$(CONFIG)/handshake_client handshake_server: $(BINDIR)/$(CONFIG)/handshake_server +handshake_server_with_readahead_handshaker: $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker hpack_parser_fuzzer_test: $(BINDIR)/$(CONFIG)/hpack_parser_fuzzer_test hpack_parser_test: $(BINDIR)/$(CONFIG)/hpack_parser_test hpack_table_test: $(BINDIR)/$(CONFIG)/hpack_table_test @@ -1417,6 +1418,7 @@ buildtests_c: privatelibs_c \ $(BINDIR)/$(CONFIG)/grpc_ssl_credentials_test \ $(BINDIR)/$(CONFIG)/handshake_client \ $(BINDIR)/$(CONFIG)/handshake_server \ + $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker \ $(BINDIR)/$(CONFIG)/hpack_parser_test \ $(BINDIR)/$(CONFIG)/hpack_table_test \ $(BINDIR)/$(CONFIG)/http_parser_test \ @@ -1894,6 +1896,8 @@ test_c: buildtests_c $(Q) $(BINDIR)/$(CONFIG)/handshake_client || ( echo test handshake_client failed ; exit 1 ) $(E) "[RUN] Testing handshake_server" $(Q) $(BINDIR)/$(CONFIG)/handshake_server || ( echo test handshake_server failed ; exit 1 ) + $(E) "[RUN] Testing handshake_server_with_readahead_handshaker" + $(Q) $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker || ( echo test handshake_server_with_readahead_handshaker failed ; exit 1 ) $(E) "[RUN] Testing hpack_parser_test" $(Q) $(BINDIR)/$(CONFIG)/hpack_parser_test || ( echo test hpack_parser_test failed ; exit 1 ) $(E) "[RUN] Testing hpack_table_test" @@ -11221,6 +11225,7 @@ endif HANDSHAKE_SERVER_SRC = \ test/core/handshake/server_ssl.c \ + test/core/handshake/server_ssl_common.c \ HANDSHAKE_SERVER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_SERVER_SRC)))) ifeq ($(NO_SECURE),true) @@ -11242,6 +11247,8 @@ endif $(OBJDIR)/$(CONFIG)/test/core/handshake/server_ssl.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a +$(OBJDIR)/$(CONFIG)/test/core/handshake/server_ssl_common.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + deps_handshake_server: $(HANDSHAKE_SERVER_OBJS:.o=.dep) ifneq ($(NO_SECURE),true) @@ -11251,6 +11258,41 @@ endif endif +HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_SRC = \ + test/core/handshake/readahead_handshaker_server_ssl.c \ + test/core/handshake/server_ssl_common.c \ + +HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS = $(addprefix $(OBJDIR)/$(CONFIG)/, $(addsuffix .o, $(basename $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_SRC)))) +ifeq ($(NO_SECURE),true) + +# You can't build secure targets if you don't have OpenSSL. + +$(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker: openssl_dep_error + +else + + + +$(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker: $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + $(E) "[LD] Linking $@" + $(Q) mkdir -p `dirname $@` + $(Q) $(LD) $(LDFLAGS) $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS) $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a $(LDLIBS) $(LDLIBS_SECURE) -o $(BINDIR)/$(CONFIG)/handshake_server_with_readahead_handshaker + +endif + +$(OBJDIR)/$(CONFIG)/test/core/handshake/readahead_handshaker_server_ssl.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +$(OBJDIR)/$(CONFIG)/test/core/handshake/server_ssl_common.o: $(LIBDIR)/$(CONFIG)/libgrpc_test_util.a $(LIBDIR)/$(CONFIG)/libgrpc.a $(LIBDIR)/$(CONFIG)/libgpr_test_util.a $(LIBDIR)/$(CONFIG)/libgpr.a + +deps_handshake_server_with_readahead_handshaker: $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS:.o=.dep) + +ifneq ($(NO_SECURE),true) +ifneq ($(NO_DEPS),true) +-include $(HANDSHAKE_SERVER_WITH_READAHEAD_HANDSHAKER_OBJS:.o=.dep) +endif +endif + + HPACK_PARSER_FUZZER_TEST_SRC = \ test/core/transport/chttp2/hpack_parser_fuzzer_test.c \ diff --git a/build.yaml b/build.yaml index 592cbb9f8c..adefb5d6d7 100644 --- a/build.yaml +++ b/build.yaml @@ -2579,6 +2579,23 @@ targets: language: c src: - test/core/handshake/server_ssl.c + - test/core/handshake/server_ssl_common.c + deps: + - grpc_test_util + - grpc + - gpr_test_util + - gpr + exclude_iomgrs: + - uv + platforms: + - linux + secure: true +- name: handshake_server_with_readahead_handshaker + build: test + language: c + src: + - test/core/handshake/readahead_handshaker_server_ssl.c + - test/core/handshake/server_ssl_common.c deps: - grpc_test_util - grpc diff --git a/src/core/lib/security/transport/security_handshaker.cc b/src/core/lib/security/transport/security_handshaker.cc index 3d19605617..b42f2699ae 100644 --- a/src/core/lib/security/transport/security_handshaker.cc +++ b/src/core/lib/security/transport/security_handshaker.cc @@ -65,6 +65,25 @@ typedef struct { tsi_handshaker_result *handshaker_result; } security_handshaker; +static size_t move_read_buffer_into_handshake_buffer(grpc_exec_ctx *exec_ctx, + security_handshaker *h) { + size_t bytes_in_read_buffer = h->args->read_buffer->length; + if (h->handshake_buffer_size < bytes_in_read_buffer) { + h->handshake_buffer = + (uint8_t *)gpr_realloc(h->handshake_buffer, bytes_in_read_buffer); + h->handshake_buffer_size = bytes_in_read_buffer; + } + size_t offset = 0; + while (h->args->read_buffer->count > 0) { + grpc_slice next_slice = grpc_slice_buffer_take_first(h->args->read_buffer); + memcpy(h->handshake_buffer + offset, GRPC_SLICE_START_PTR(next_slice), + GRPC_SLICE_LENGTH(next_slice)); + offset += GRPC_SLICE_LENGTH(next_slice); + grpc_slice_unref_internal(exec_ctx, next_slice); + } + return bytes_in_read_buffer; +} + static void security_handshaker_unref(grpc_exec_ctx *exec_ctx, security_handshaker *h) { if (gpr_unref(&h->refs)) { @@ -177,8 +196,6 @@ static void on_peer_checked_inner(grpc_exec_ctx *exec_ctx, } tsi_handshaker_result_destroy(h->handshaker_result); h->handshaker_result = NULL; - // Clear out the read buffer before it gets passed to the transport. - grpc_slice_buffer_reset_and_unref_internal(exec_ctx, h->args->read_buffer); // Add auth context to channel args. grpc_arg auth_context_arg = grpc_auth_context_to_arg(h->auth_context); grpc_channel_args *tmp_args = h->args->args; @@ -311,23 +328,8 @@ static void on_handshake_data_received_from_peer(grpc_exec_ctx *exec_ctx, return; } // Copy all slices received. - size_t i; - size_t bytes_received_size = 0; - for (i = 0; i < h->args->read_buffer->count; i++) { - bytes_received_size += GRPC_SLICE_LENGTH(h->args->read_buffer->slices[i]); - } - if (bytes_received_size > h->handshake_buffer_size) { - h->handshake_buffer = - (uint8_t *)gpr_realloc(h->handshake_buffer, bytes_received_size); - h->handshake_buffer_size = bytes_received_size; - } - size_t offset = 0; - for (i = 0; i < h->args->read_buffer->count; i++) { - size_t slice_size = GPR_SLICE_LENGTH(h->args->read_buffer->slices[i]); - memcpy(h->handshake_buffer + offset, - GRPC_SLICE_START_PTR(h->args->read_buffer->slices[i]), slice_size); - offset += slice_size; - } + size_t bytes_received_size = + move_read_buffer_into_handshake_buffer(exec_ctx, h); // Call TSI handshaker. error = do_handshaker_next_locked(exec_ctx, h, h->handshake_buffer, bytes_received_size); @@ -403,7 +405,10 @@ static void security_handshaker_do_handshake(grpc_exec_ctx *exec_ctx, h->args = args; h->on_handshake_done = on_handshake_done; gpr_ref(&h->refs); - grpc_error *error = do_handshaker_next_locked(exec_ctx, h, NULL, 0); + size_t bytes_received_size = + move_read_buffer_into_handshake_buffer(exec_ctx, h); + grpc_error *error = do_handshaker_next_locked( + exec_ctx, h, h->handshake_buffer, bytes_received_size); if (error != GRPC_ERROR_NONE) { security_handshake_failed_locked(exec_ctx, h, error); gpr_mu_unlock(&h->mu); diff --git a/test/core/handshake/readahead_handshaker_server_ssl.c b/test/core/handshake/readahead_handshaker_server_ssl.c new file mode 100644 index 0000000000..f25c35615c --- /dev/null +++ b/test/core/handshake/readahead_handshaker_server_ssl.c @@ -0,0 +1,103 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * 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 +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/load_file.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#include "src/core/lib/channel/handshaker_factory.h" +#include "src/core/lib/channel/handshaker_registry.h" +#include "src/core/lib/security/transport/security_handshaker.h" + +#include "test/core/handshake/server_ssl_common.h" + +/* The purpose of this test is to exercise the case when a + * grpc *security_handshaker* begins its handshake with data already + * in the read buffer of the handshaker arg. This scenario is created by + * adding a fake "readahead" handshaker at the beginning of the server's + * handshaker list, which just reads from the connection and then places + * read bytes into the read buffer of the handshake arg (to be passed down + * to the security_handshaker). This test is meant to protect code relying on + * this functionality that lives outside of this repo. */ + +static void readahead_handshaker_destroy(grpc_exec_ctx *ctx, + grpc_handshaker *handshaker) { + gpr_free(handshaker); +} + +static void readahead_handshaker_shutdown(grpc_exec_ctx *ctx, + grpc_handshaker *handshaker, + grpc_error *error) {} + +static void readahead_handshaker_do_handshake( + grpc_exec_ctx *ctx, grpc_handshaker *handshaker, + grpc_tcp_server_acceptor *acceptor, grpc_closure *on_handshake_done, + grpc_handshaker_args *args) { + grpc_endpoint_read(ctx, args->endpoint, args->read_buffer, on_handshake_done); +} + +const grpc_handshaker_vtable readahead_handshaker_vtable = { + readahead_handshaker_destroy, readahead_handshaker_shutdown, + readahead_handshaker_do_handshake}; + +static grpc_handshaker *readahead_handshaker_create(grpc_exec_ctx *ctx) { + grpc_handshaker *h = (grpc_handshaker *)gpr_zalloc(sizeof(grpc_handshaker)); + grpc_handshaker_init(&readahead_handshaker_vtable, h); + return h; +} + +static void readahead_handshaker_factory_add_handshakers( + grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *hf, + const grpc_channel_args *args, grpc_handshake_manager *handshake_mgr) { + grpc_handshake_manager_add(handshake_mgr, + readahead_handshaker_create(exec_ctx)); +} + +static void readahead_handshaker_factory_destroy( + grpc_exec_ctx *exec_ctx, grpc_handshaker_factory *handshaker_factory) {} + +static const grpc_handshaker_factory_vtable + readahead_handshaker_factory_vtable = { + readahead_handshaker_factory_add_handshakers, + readahead_handshaker_factory_destroy}; + +int main(int argc, char *argv[]) { + grpc_handshaker_factory readahead_handshaker_factory = { + &readahead_handshaker_factory_vtable}; + grpc_init(); + grpc_handshaker_factory_register(true /* at_start */, HANDSHAKER_SERVER, + &readahead_handshaker_factory); + const char *full_alpn_list[] = {"grpc-exp", "h2"}; + GPR_ASSERT(server_ssl_test(full_alpn_list, 2, "grpc-exp")); + grpc_shutdown(); + return 0; +} diff --git a/test/core/handshake/server_ssl.c b/test/core/handshake/server_ssl.c index 85a8b4de41..8b96076338 100644 --- a/test/core/handshake/server_ssl.c +++ b/test/core/handshake/server_ssl.c @@ -34,205 +34,7 @@ #include "test/core/util/port.h" #include "test/core/util/test_config.h" -#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" -#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" -#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" - -// Handshake completed signal to server thread. -static gpr_event client_handshake_complete; - -static int create_socket(int port) { - int s; - struct sockaddr_in addr; - - addr.sin_family = AF_INET; - addr.sin_port = htons((uint16_t)port); - addr.sin_addr.s_addr = htonl(INADDR_ANY); - - s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) { - perror("Unable to create socket"); - return -1; - } - - if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { - perror("Unable to connect"); - return -1; - } - - return s; -} - -// Simple gRPC server. This listens until client_handshake_complete occurs. -static void server_thread(void *arg) { - const int port = *(int *)arg; - - // Load key pair and establish server SSL credentials. - grpc_ssl_pem_key_cert_pair pem_key_cert_pair; - grpc_slice ca_slice, cert_slice, key_slice; - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); - GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", - grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); - const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice); - pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); - pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); - grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create( - ca_cert, &pem_key_cert_pair, 1, 0, NULL); - - // Start server listening on local port. - char *addr; - gpr_asprintf(&addr, "127.0.0.1:%d", port); - grpc_server *server = grpc_server_create(NULL, NULL); - GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); - free(addr); - - grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); - - grpc_server_register_completion_queue(server, cq, NULL); - grpc_server_start(server); - - // Wait a bounded number of time until client_handshake_complete is set, - // sleeping between polls. - int retries = 10; - while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) { - const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); - GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); - } - - gpr_log(GPR_INFO, "Shutting down server"); - grpc_server_shutdown_and_notify(server, cq, NULL); - grpc_completion_queue_shutdown(cq); - - const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); - grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); - GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); - - grpc_server_destroy(server); - grpc_completion_queue_destroy(cq); - grpc_server_credentials_release(ssl_creds); - grpc_slice_unref(cert_slice); - grpc_slice_unref(key_slice); - grpc_slice_unref(ca_slice); -} - -// This test launches a gRPC server on a separate thread and then establishes a -// TLS handshake via a minimal TLS client. The TLS client has configurable (via -// alpn_list) ALPN settings and can probe at the supported ALPN preferences -// using this (via alpn_expected). -static bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, - const char *alpn_expected) { - bool success = true; - - grpc_init(); - int port = grpc_pick_unused_port_or_die(); - gpr_event_init(&client_handshake_complete); - - // Launch the gRPC server thread. - gpr_thd_options thdopt = gpr_thd_options_default(); - gpr_thd_id thdid; - gpr_thd_options_set_joinable(&thdopt); - GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt)); - - SSL_load_error_strings(); - OpenSSL_add_ssl_algorithms(); - - const SSL_METHOD *method = TLSv1_2_client_method(); - SSL_CTX *ctx = SSL_CTX_new(method); - if (!ctx) { - perror("Unable to create SSL context"); - ERR_print_errors_fp(stderr); - abort(); - } - - // Load key pair. - if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { - ERR_print_errors_fp(stderr); - abort(); - } - if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { - ERR_print_errors_fp(stderr); - abort(); - } - - // Set the cipher list to match the one expressed in - // src/core/tsi/ssl_transport_security.c. - const char *cipher_list = - "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" - "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; - if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { - ERR_print_errors_fp(stderr); - gpr_log(GPR_ERROR, "Couldn't set server cipher list."); - abort(); - } - - // Configure ALPN list the client will send to the server. This must match the - // wire format, see documentation for SSL_CTX_set_alpn_protos. - unsigned int alpn_protos_len = alpn_list_len; - for (unsigned int i = 0; i < alpn_list_len; ++i) { - alpn_protos_len += (unsigned int)strlen(alpn_list[i]); - } - unsigned char *alpn_protos = gpr_malloc(alpn_protos_len); - unsigned char *p = alpn_protos; - for (unsigned int i = 0; i < alpn_list_len; ++i) { - const uint8_t len = (uint8_t)strlen(alpn_list[i]); - *p++ = len; - memcpy(p, alpn_list[i], len); - p += len; - } - GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0); - - // Try and connect to server. We allow a bounded number of retries as we might - // be racing with the server setup on its separate thread. - int retries = 10; - int sock = -1; - while (sock == -1 && retries-- > 0) { - sock = create_socket(port); - if (sock < 0) { - sleep(1); - } - } - GPR_ASSERT(sock > 0); - gpr_log(GPR_INFO, "Connected to server on port %d", port); - - // Establish a SSL* and connect at SSL layer. - SSL *ssl = SSL_new(ctx); - GPR_ASSERT(ssl); - SSL_set_fd(ssl, sock); - if (SSL_connect(ssl) <= 0) { - ERR_print_errors_fp(stderr); - gpr_log(GPR_ERROR, "Handshake failed."); - success = false; - } else { - gpr_log(GPR_INFO, "Handshake successful."); - // Validate ALPN preferred by server matches alpn_expected. - const unsigned char *alpn_selected; - unsigned int alpn_selected_len; - SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len); - if (strlen(alpn_expected) != alpn_selected_len || - strncmp((const char *)alpn_selected, alpn_expected, - alpn_selected_len) != 0) { - gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference"); - success = false; - } - } - gpr_event_set(&client_handshake_complete, &client_handshake_complete); - - SSL_free(ssl); - gpr_free(alpn_protos); - SSL_CTX_free(ctx); - EVP_cleanup(); - close(sock); - - gpr_thd_join(thdid); - - grpc_shutdown(); - - return success; -} +#include "test/core/handshake/server_ssl_common.h" int main(int argc, char *argv[]) { // Handshake succeeeds when the client supplies the standard ALPN list. diff --git a/test/core/handshake/server_ssl_common.c b/test/core/handshake/server_ssl_common.c new file mode 100644 index 0000000000..d1911ecfde --- /dev/null +++ b/test/core/handshake/server_ssl_common.c @@ -0,0 +1,237 @@ +/* + * + * Copyright 2016 gRPC authors. + * + * 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 "test/core/handshake/server_ssl_common.h" + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/load_file.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +#define SSL_CERT_PATH "src/core/tsi/test_creds/server1.pem" +#define SSL_KEY_PATH "src/core/tsi/test_creds/server1.key" +#define SSL_CA_PATH "src/core/tsi/test_creds/ca.pem" + +// Handshake completed signal to server thread. +static gpr_event client_handshake_complete; + +static int create_socket(int port) { + int s; + struct sockaddr_in addr; + + addr.sin_family = AF_INET; + addr.sin_port = htons((uint16_t)port); + addr.sin_addr.s_addr = htonl(INADDR_ANY); + + s = socket(AF_INET, SOCK_STREAM, 0); + if (s < 0) { + perror("Unable to create socket"); + return -1; + } + + if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) { + perror("Unable to connect"); + return -1; + } + + return s; +} + +// Simple gRPC server. This listens until client_handshake_complete occurs. +static void server_thread(void *arg) { + const int port = *(int *)arg; + + // Load key pair and establish server SSL credentials. + grpc_ssl_pem_key_cert_pair pem_key_cert_pair; + grpc_slice ca_slice, cert_slice, key_slice; + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_CA_PATH, 1, &ca_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_CERT_PATH, 1, &cert_slice))); + GPR_ASSERT(GRPC_LOG_IF_ERROR("load_file", + grpc_load_file(SSL_KEY_PATH, 1, &key_slice))); + const char *ca_cert = (const char *)GRPC_SLICE_START_PTR(ca_slice); + pem_key_cert_pair.private_key = (const char *)GRPC_SLICE_START_PTR(key_slice); + pem_key_cert_pair.cert_chain = (const char *)GRPC_SLICE_START_PTR(cert_slice); + grpc_server_credentials *ssl_creds = grpc_ssl_server_credentials_create( + ca_cert, &pem_key_cert_pair, 1, 0, NULL); + + // Start server listening on local port. + char *addr; + gpr_asprintf(&addr, "127.0.0.1:%d", port); + grpc_server *server = grpc_server_create(NULL, NULL); + GPR_ASSERT(grpc_server_add_secure_http2_port(server, addr, ssl_creds)); + free(addr); + + grpc_completion_queue *cq = grpc_completion_queue_create_for_next(NULL); + + grpc_server_register_completion_queue(server, cq, NULL); + grpc_server_start(server); + + // Wait a bounded number of time until client_handshake_complete is set, + // sleeping between polls. + int retries = 10; + while (!gpr_event_get(&client_handshake_complete) && retries-- > 0) { + const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(1); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); + GPR_ASSERT(ev.type == GRPC_QUEUE_TIMEOUT); + } + + gpr_log(GPR_INFO, "Shutting down server"); + grpc_server_shutdown_and_notify(server, cq, NULL); + grpc_completion_queue_shutdown(cq); + + const gpr_timespec cq_deadline = grpc_timeout_seconds_to_deadline(5); + grpc_event ev = grpc_completion_queue_next(cq, cq_deadline, NULL); + GPR_ASSERT(ev.type == GRPC_OP_COMPLETE); + + grpc_server_destroy(server); + grpc_completion_queue_destroy(cq); + grpc_server_credentials_release(ssl_creds); + grpc_slice_unref(cert_slice); + grpc_slice_unref(key_slice); + grpc_slice_unref(ca_slice); +} + +// This test launches a gRPC server on a separate thread and then establishes a +// TLS handshake via a minimal TLS client. The TLS client has configurable (via +// alpn_list) ALPN settings and can probe at the supported ALPN preferences +// using this (via alpn_expected). +bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, + const char *alpn_expected) { + bool success = true; + + grpc_init(); + int port = grpc_pick_unused_port_or_die(); + gpr_event_init(&client_handshake_complete); + + // Launch the gRPC server thread. + gpr_thd_options thdopt = gpr_thd_options_default(); + gpr_thd_id thdid; + gpr_thd_options_set_joinable(&thdopt); + GPR_ASSERT(gpr_thd_new(&thdid, server_thread, &port, &thdopt)); + + SSL_load_error_strings(); + OpenSSL_add_ssl_algorithms(); + + const SSL_METHOD *method = TLSv1_2_client_method(); + SSL_CTX *ctx = SSL_CTX_new(method); + if (!ctx) { + perror("Unable to create SSL context"); + ERR_print_errors_fp(stderr); + abort(); + } + + // Load key pair. + if (SSL_CTX_use_certificate_file(ctx, SSL_CERT_PATH, SSL_FILETYPE_PEM) < 0) { + ERR_print_errors_fp(stderr); + abort(); + } + if (SSL_CTX_use_PrivateKey_file(ctx, SSL_KEY_PATH, SSL_FILETYPE_PEM) < 0) { + ERR_print_errors_fp(stderr); + abort(); + } + + // Set the cipher list to match the one expressed in + // src/core/tsi/ssl_transport_security.c. + const char *cipher_list = + "ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-" + "SHA384:ECDHE-RSA-AES256-GCM-SHA384"; + if (!SSL_CTX_set_cipher_list(ctx, cipher_list)) { + ERR_print_errors_fp(stderr); + gpr_log(GPR_ERROR, "Couldn't set server cipher list."); + abort(); + } + + // Configure ALPN list the client will send to the server. This must match the + // wire format, see documentation for SSL_CTX_set_alpn_protos. + unsigned int alpn_protos_len = alpn_list_len; + for (unsigned int i = 0; i < alpn_list_len; ++i) { + alpn_protos_len += (unsigned int)strlen(alpn_list[i]); + } + unsigned char *alpn_protos = gpr_malloc(alpn_protos_len); + unsigned char *p = alpn_protos; + for (unsigned int i = 0; i < alpn_list_len; ++i) { + const uint8_t len = (uint8_t)strlen(alpn_list[i]); + *p++ = len; + memcpy(p, alpn_list[i], len); + p += len; + } + GPR_ASSERT(SSL_CTX_set_alpn_protos(ctx, alpn_protos, alpn_protos_len) == 0); + + // Try and connect to server. We allow a bounded number of retries as we might + // be racing with the server setup on its separate thread. + int retries = 10; + int sock = -1; + while (sock == -1 && retries-- > 0) { + sock = create_socket(port); + if (sock < 0) { + sleep(1); + } + } + GPR_ASSERT(sock > 0); + gpr_log(GPR_INFO, "Connected to server on port %d", port); + + // Establish a SSL* and connect at SSL layer. + SSL *ssl = SSL_new(ctx); + GPR_ASSERT(ssl); + SSL_set_fd(ssl, sock); + if (SSL_connect(ssl) <= 0) { + ERR_print_errors_fp(stderr); + gpr_log(GPR_ERROR, "Handshake failed."); + success = false; + } else { + gpr_log(GPR_INFO, "Handshake successful."); + // Validate ALPN preferred by server matches alpn_expected. + const unsigned char *alpn_selected; + unsigned int alpn_selected_len; + SSL_get0_alpn_selected(ssl, &alpn_selected, &alpn_selected_len); + if (strlen(alpn_expected) != alpn_selected_len || + strncmp((const char *)alpn_selected, alpn_expected, + alpn_selected_len) != 0) { + gpr_log(GPR_ERROR, "Unexpected ALPN protocol preference"); + success = false; + } + } + gpr_event_set(&client_handshake_complete, &client_handshake_complete); + + SSL_free(ssl); + gpr_free(alpn_protos); + SSL_CTX_free(ctx); + EVP_cleanup(); + close(sock); + + gpr_thd_join(thdid); + + grpc_shutdown(); + + return success; +} diff --git a/test/core/handshake/server_ssl_common.h b/test/core/handshake/server_ssl_common.h new file mode 100644 index 0000000000..67b323d82f --- /dev/null +++ b/test/core/handshake/server_ssl_common.h @@ -0,0 +1,22 @@ +// +// Created by apolcyn on 10/31/17. +// + +#ifndef GRPC_SERVER_SSL_COMMON_H +#define GRPC_SERVER_SSL_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#include "src/core/lib/iomgr/load_file.h" +#include "test/core/util/port.h" +#include "test/core/util/test_config.h" + +bool server_ssl_test(const char *alpn_list[], unsigned int alpn_list_len, + const char *alpn_expected); + +#endif // GRPC_SERVER_SSL_COMMON_H diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 46f4cb6532..9f5e39e054 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1280,7 +1280,26 @@ "language": "c", "name": "handshake_server", "src": [ - "test/core/handshake/server_ssl.c" + "test/core/handshake/server_ssl.c", + "test/core/handshake/server_ssl_common.c" + ], + "third_party": false, + "type": "target" + }, + { + "deps": [ + "gpr", + "gpr_test_util", + "grpc", + "grpc_test_util" + ], + "headers": [], + "is_filegroup": false, + "language": "c", + "name": "handshake_server_with_readahead_handshaker", + "src": [ + "test/core/handshake/readahead_handshaker_server_ssl.c", + "test/core/handshake/server_ssl_common.c" ], "third_party": false, "type": "target" diff --git a/tools/run_tests/generated/tests.json b/tools/run_tests/generated/tests.json index 3b1b6587f6..7f197b4ba0 100644 --- a/tools/run_tests/generated/tests.json +++ b/tools/run_tests/generated/tests.json @@ -1599,6 +1599,26 @@ ], "uses_polling": true }, + { + "args": [], + "benchmark": false, + "ci_platforms": [ + "linux" + ], + "cpu_cost": 1.0, + "exclude_configs": [], + "exclude_iomgrs": [ + "uv" + ], + "flaky": false, + "gtest": false, + "language": "c", + "name": "handshake_server_with_readahead_handshaker", + "platforms": [ + "linux" + ], + "uses_polling": true + }, { "args": [], "benchmark": false, -- cgit v1.2.3 From f51b7e16ee96cbcd23a85aef982ca7a4bada2727 Mon Sep 17 00:00:00 2001 From: Alexander Polcyn Date: Mon, 13 Nov 2017 21:05:32 -0800 Subject: Fix missing copyright, fix merge conflict in updated BUILD --- build.yaml | 4 +++ test/core/handshake/BUILD | 31 ++++++++++++++++++++++ test/core/handshake/server_ssl_common.h | 20 +++++++++++--- tools/run_tests/generated/sources_and_headers.json | 14 +++++++--- 4 files changed, 62 insertions(+), 7 deletions(-) (limited to 'test/core/handshake') diff --git a/build.yaml b/build.yaml index 083f5e9d9b..910b00ebe2 100644 --- a/build.yaml +++ b/build.yaml @@ -2511,6 +2511,8 @@ targets: - name: handshake_server build: test language: c + headers: + - test/core/handshake/server_ssl_common.h src: - test/core/handshake/server_ssl.cc - test/core/handshake/server_ssl_common.cc @@ -2527,6 +2529,8 @@ targets: - name: handshake_server_with_readahead_handshaker build: test language: c + headers: + - test/core/handshake/server_ssl_common.h src: - test/core/handshake/readahead_handshaker_server_ssl.cc - test/core/handshake/server_ssl_common.cc diff --git a/test/core/handshake/BUILD b/test/core/handshake/BUILD index aea4a27e99..a3276b9343 100644 --- a/test/core/handshake/BUILD +++ b/test/core/handshake/BUILD @@ -35,6 +35,18 @@ grpc_cc_test( ], ) +grpc_cc_library( + name = "server_ssl_common", + hdrs = ["server_ssl_common.h"], + srcs = ["server_ssl_common.cc"], + deps = [ + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + grpc_cc_test( name = "server_ssl", srcs = ["server_ssl.cc"], @@ -45,6 +57,25 @@ grpc_cc_test( "//src/core/tsi/test_creds:server1.pem", ], deps = [ + ":server_ssl_common", + "//:gpr", + "//:grpc", + "//test/core/util:gpr_test_util", + "//test/core/util:grpc_test_util", + ], +) + +grpc_cc_test( + name = "handshake_server_with_readahead_handshaker", + srcs = ["readahead_handshaker_server_ssl.cc"], + language = "C++", + data = [ + "//src/core/tsi/test_creds:ca.pem", + "//src/core/tsi/test_creds:server1.key", + "//src/core/tsi/test_creds:server1.pem", + ], + deps = [ + ":server_ssl_common", "//:gpr", "//:grpc", "//test/core/util:gpr_test_util", diff --git a/test/core/handshake/server_ssl_common.h b/test/core/handshake/server_ssl_common.h index 94ac588f0e..77865a408f 100644 --- a/test/core/handshake/server_ssl_common.h +++ b/test/core/handshake/server_ssl_common.h @@ -1,6 +1,20 @@ -// -// Created by apolcyn on 10/31/17. -// +/* + * + * Copyright 2016 gRPC authors. + * + * 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 GRPC_SERVER_SSL_COMMON_H #define GRPC_SERVER_SSL_COMMON_H diff --git a/tools/run_tests/generated/sources_and_headers.json b/tools/run_tests/generated/sources_and_headers.json index 6d361c571b..fce01bf8ff 100644 --- a/tools/run_tests/generated/sources_and_headers.json +++ b/tools/run_tests/generated/sources_and_headers.json @@ -1207,13 +1207,16 @@ "grpc", "grpc_test_util" ], - "headers": [], + "headers": [ + "test/core/handshake/server_ssl_common.h" + ], "is_filegroup": false, "language": "c", "name": "handshake_server", "src": [ "test/core/handshake/server_ssl.cc", - "test/core/handshake/server_ssl_common.cc" + "test/core/handshake/server_ssl_common.cc", + "test/core/handshake/server_ssl_common.h" ], "third_party": false, "type": "target" @@ -1225,13 +1228,16 @@ "grpc", "grpc_test_util" ], - "headers": [], + "headers": [ + "test/core/handshake/server_ssl_common.h" + ], "is_filegroup": false, "language": "c", "name": "handshake_server_with_readahead_handshaker", "src": [ "test/core/handshake/readahead_handshaker_server_ssl.cc", - "test/core/handshake/server_ssl_common.cc" + "test/core/handshake/server_ssl_common.cc", + "test/core/handshake/server_ssl_common.h" ], "third_party": false, "type": "target" -- cgit v1.2.3