diff --git a/tests/testapp/CMakeLists.txt b/tests/testapp/CMakeLists.txt index 84b8ba7526..1610f0da85 100644 --- a/tests/testapp/CMakeLists.txt +++ b/tests/testapp/CMakeLists.txt @@ -17,8 +17,6 @@ add_test(NAME testapp_auth_provider_test set(memcached_testapp_SOURCES $ - openssl_impl.cc - ssl_impl.h subdoc_encoder.cc subdoc_encoder.h testapp.cc diff --git a/tests/testapp/openssl_impl.cc b/tests/testapp/openssl_impl.cc deleted file mode 100644 index d18f19d9cf..0000000000 --- a/tests/testapp/openssl_impl.cc +++ /dev/null @@ -1,117 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright 2017 Couchbase, Inc. - * - * 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 "ssl_impl.h" -#include "testapp.h" - -#include -#include -#include - -static SSL_CTX *ssl_ctx = nullptr; -static SSL *ssl = nullptr; -static BIO *bio = nullptr; -static BIO *ssl_bio_r = nullptr; -static BIO *ssl_bio_w = nullptr; - -SOCKET create_connect_ssl_socket(in_port_t port) { - SOCKET sfd; - if (ssl_port == in_port_t(-1)) { - throw std::runtime_error( - "create_connect_ssl_socket: Can't connect to ssl_port == -1"); - } - - std::tie(sfd, ssl_ctx, bio) = - cb::net::new_ssl_socket("", port, AF_INET, {}); - - if (sfd == INVALID_SOCKET) { - ADD_FAILURE() << "Failed to connect over ssl to 127.0.0.1:" << port; - return INVALID_SOCKET; - } - - // SSL "trickery". To ensure we have full control over send/receive of data. - // Switch out the BIO_ssl_connect BIO for a plain memory BIO - // Now send/receive is done under our control. byte by byte, large chunks - // etc... - BIO_get_ssl(bio, &ssl); - EXPECT_EQ(nullptr, ssl_bio_r); - ssl_bio_r = BIO_new(BIO_s_mem()); - - EXPECT_EQ(nullptr, ssl_bio_w); - ssl_bio_w = BIO_new(BIO_s_mem()); - - // Note: previous BIOs attached to 'bio' freed as a result of this call. - SSL_set_bio(ssl, ssl_bio_r, ssl_bio_w); - - return sfd; -} - -void destroy_ssl_socket() { - BIO_free_all(bio); - bio = nullptr; - ssl_bio_r = nullptr; - ssl_bio_w = nullptr; - - SSL_CTX_free(ssl_ctx); - ssl_ctx = nullptr; - if (sock_ssl != INVALID_SOCKET) { - cb::net::closesocket(sock_ssl); - sock_ssl = INVALID_SOCKET; - } -} - -ssize_t phase_send_ssl(const void *buf, size_t len) { - ssize_t rv = 0, send_rv = 0; - - long send_len = 0; - char* send_buf = nullptr; - /* push the data through SSL into the BIO */ - rv = (ssize_t)SSL_write(ssl, (const char*)buf, (int)len); - send_len = BIO_get_mem_data(ssl_bio_w, &send_buf); - - send_rv = socket_send(sock_ssl, send_buf, send_len); - - if (send_rv > 0) { - EXPECT_EQ(send_len, send_rv); - (void)BIO_reset(ssl_bio_w); - } else { - /* flag failure to user */ - rv = send_rv; - } - - return rv; -} - -ssize_t phase_recv_ssl(void* buf, size_t len) { - ssize_t rv; - - /* can we read some data? */ - while ((rv = SSL_peek(ssl, buf, (int)len)) == -1) { - /* nope, keep feeding SSL until we can */ - rv = socket_recv(sock_ssl, reinterpret_cast(buf), len); - - if (rv > 0) { - /* write into the BIO what came off the network */ - BIO_write(ssl_bio_r, buf, rv); - } else if (rv == 0) { - return rv; /* peer closed */ - } - } - - /* now pull the data out and return */ - return SSL_read(ssl, buf, (int)len); -} diff --git a/tests/testapp/ssl_impl.h b/tests/testapp/ssl_impl.h deleted file mode 100644 index e01e0cf0c6..0000000000 --- a/tests/testapp/ssl_impl.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C++; tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- */ -/* - * Copyright 2017 Couchbase, Inc. - * - * 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. - */ -#pragma once - -#include - -/* - * This file hides the #ifdef's and select the appropriate SSL - * implementation to use. All of the different backends MUST provide - * the following methods: - */ - -/** - * Create and connect the ssl_socket to the given port - */ -SOCKET create_connect_ssl_socket(in_port_t port); - -/** - * Destroy and clean up the global ssl connection - */ -void destroy_ssl_socket(); - -/** - * Send the provided buffer - * - * @param buf The data to send - * @param len The size of the buffer - * @return the number of bytes sent - */ -ssize_t phase_send_ssl(const void *buf, size_t len); - -/** - * Receive the requested number of bytes - * - * @param buf Where to store the data - * @param len The number of bytes to read - * @return the number of bytes received - */ -ssize_t phase_recv_ssl(void *buf, size_t len); diff --git a/tests/testapp/testapp.cc b/tests/testapp/testapp.cc index 45efabf922..dcc6b00f90 100644 --- a/tests/testapp/testapp.cc +++ b/tests/testapp/testapp.cc @@ -16,7 +16,6 @@ #include "testapp.h" -#include "ssl_impl.h" #include #include #include @@ -42,18 +41,9 @@ McdEnvironment* mcd_env = nullptr; -/* test phases (bitmasks) */ -#define phase_plain 0x2 -#define phase_ssl 0x4 - -#define phase_max 4 -static int current_phase = 0; - pid_t server_pid = -1; in_port_t port = -1; -in_port_t ssl_port = -1; SOCKET sock = INVALID_SOCKET; -SOCKET sock_ssl; static time_t server_start_time = 0; // used in embedded mode to shutdown memcached @@ -66,8 +56,6 @@ int memcached_verbose = 0; // thread in the same process or not static bool embedded_memcached_server; -static SOCKET connect_to_server_ssl(in_port_t ssl_port); - time_t get_server_start_time() { return server_start_time; } @@ -201,7 +189,6 @@ bool TestappTest::isJSON(std::string_view value) { // per test setup function. void TestappTest::SetUp() { verify_server_running(); - current_phase = phase_plain; sock = connect_to_server_plain(port); ASSERT_NE(INVALID_SOCKET, sock); @@ -230,13 +217,10 @@ const std::string TestappTest::bucketName = "default"; void McdTestappTest::SetUp() { verify_server_running(); if (getProtocolParam() == TransportProtocols::McbpPlain) { - current_phase = phase_plain; sock = connect_to_server_plain(port); ASSERT_NE(INVALID_SOCKET, sock); } else { - current_phase = phase_ssl; - sock_ssl = connect_to_server_ssl(ssl_port); - ASSERT_NE(INVALID_SOCKET, sock_ssl); + // Not reached (exception is thrown) } set_json_feature(hasJSONSupport() == ClientJSONSupport::Yes); @@ -251,13 +235,7 @@ void McdTestappTest::SetUp() { // per test tear-down function. void McdTestappTest::TearDown() { - if (getProtocolParam() == TransportProtocols::McbpPlain) { - cb::net::closesocket(sock); - } else { - cb::net::closesocket(sock_ssl); - sock_ssl = INVALID_SOCKET; - destroy_ssl_socket(); - } + cb::net::closesocket(sock); } ClientJSONSupport McdTestappTest::hasJSONSupport() const { @@ -488,13 +466,10 @@ void TestappTest::parse_portnumber_file() { // The tests which don't use the MemcachedConnection class needs the // global variables port and ssl_port to be set port = (in_port_t)-1; - ssl_port = (in_port_t)-1; connectionMap.iterate([](const MemcachedConnection& connection) { if (connection.getFamily() == AF_INET) { - if (connection.isSsl()) { - ssl_port = connection.getPort(); - } else { + if (!connection.isSsl()) { port = connection.getPort(); } } @@ -511,19 +486,6 @@ void TestappTest::parse_portnumber_file() { "connection from: " + ss.str()); } - - if (ssl_port == in_port_t(-1)) { - std::stringstream ss; - connectionMap.iterate([&ss](const MemcachedConnection& connection) { - ss << "[" << connection.to_string() << "]," << std::endl; - }); - - throw std::runtime_error( - "parse_portnumber_file: Failed to locate a SSL IPv4 " - "connection from: " + - ss.str()); - } - EXPECT_EQ(0, remove(portnumber_file.c_str())); } catch (const std::exception& e) { std::cerr << "FATAL ERROR in parse_portnumber_file!" << std::endl @@ -645,37 +607,15 @@ SOCKET connect_to_server_plain(in_port_t port) { return create_connect_plain_socket(port); } -static SOCKET connect_to_server_ssl(in_port_t ssl_port) { - if (ssl_port == in_port_t(-1)) { - throw std::runtime_error( - "connect_to_server_ssl: Can't connect to port == -1"); - } - SOCKET sock = create_connect_ssl_socket(ssl_port); - if (sock == INVALID_SOCKET) { - ADD_FAILURE() << "Failed to connect SSL socket to port" << ssl_port; - return INVALID_SOCKET; - } - - return sock; -} - /* re-connect to server. Uses global port and ssl_port values. New socket-fd written to global "sock" and "ssl_bio" */ void reconnect_to_server() { - if (current_phase == phase_ssl) { - cb::net::closesocket(sock_ssl); - destroy_ssl_socket(); - - sock_ssl = connect_to_server_ssl(ssl_port); - ASSERT_NE(INVALID_SOCKET, sock_ssl); - } else { - cb::net::closesocket(sock); - sock = connect_to_server_plain(port); - ASSERT_NE(INVALID_SOCKET, sock); - } + cb::net::closesocket(sock); + sock = connect_to_server_plain(port); + ASSERT_NE(INVALID_SOCKET, sock); } static void set_feature(cb::mcbp::Feature feature, bool enable) { @@ -939,37 +879,9 @@ void TestappTest::stop_memcached_server() { } } -ssize_t socket_send(SOCKET s, const char* buf, size_t len) { - return cb::net::send(s, buf, len, 0); -} - -static ssize_t phase_send(const void* buf, size_t len) { - if (current_phase == phase_ssl) { - return phase_send_ssl(buf, len); - } else { - return socket_send(sock, reinterpret_cast(buf), len); - } -} - -ssize_t socket_recv(SOCKET s, char* buf, size_t len) { - return cb::net::recv(s, buf, len, 0); -} - -ssize_t phase_recv(void* buf, size_t len) { - if (current_phase == phase_ssl) { - return phase_recv_ssl(buf, len); - } else { - return socket_recv(sock, reinterpret_cast(buf), len); - } -} - static bool dump_socket_traffic = getenv("TESTAPP_PACKET_DUMP") != nullptr; static const std::string phase_get_errno() { - if (current_phase == phase_ssl) { - /* could do with more work here, but so far this has sufficed */ - return "SSL error"; - } return cb_strerror(); } @@ -985,7 +897,7 @@ void safe_send(const void* buf, size_t len, bool hickup) { } } - nw = phase_send(ptr + offset, num_bytes); + nw = cb::net::send(sock, ptr + offset, num_bytes, 0); if (nw == -1) { if (errno != EINTR) { @@ -1001,12 +913,7 @@ void safe_send(const void* buf, size_t len, bool hickup) { } if (dump_socket_traffic) { - if (current_phase == phase_ssl) { - std::cerr << "SSL"; - } else { - std::cerr << "PLAIN"; - } - std::cerr << "> "; + std::cerr << "PLAIN> "; for (ssize_t ii = 0; ii < nw; ++ii) { std::cerr << "0x" << std::hex << std::setfill('0') << std::setw(2) @@ -1026,7 +933,8 @@ bool safe_recv(void* buf, size_t len) { return true; } do { - ssize_t nr = phase_recv(((char*)buf) + offset, len - offset); + ssize_t nr = + cb::net::recv(sock, ((char*)buf) + offset, len - offset, 0); if (nr == -1) { EXPECT_EQ(EINTR, errno) << "Failed to read: " << phase_get_errno(); @@ -1081,12 +989,7 @@ bool safe_recv_packetT(T& info) { if (dump_socket_traffic) { if (dump_socket_traffic) { - if (current_phase == phase_ssl) { - std::cerr << "SSL"; - } else { - std::cerr << "PLAIN"; - } - std::cerr << "< "; + std::cerr << "PLAIN< "; for (const auto& val : info) { std::cerr << cb::to_hex(uint8_t(val)) << ", "; } diff --git a/tests/testapp/testapp.h b/tests/testapp/testapp.h index ff684e68a5..a2245c114c 100644 --- a/tests/testapp/testapp.h +++ b/tests/testapp/testapp.h @@ -64,10 +64,6 @@ extern SOCKET sock; extern in_port_t port; extern pid_t server_pid; -// Needed by testapp_tests -extern in_port_t ssl_port; -extern SOCKET sock_ssl; - // Set of HELLO features which are currently enabled. extern std::set enabled_hello_features; @@ -351,6 +347,13 @@ class McdTestappTest /// return the TransportProtocol parameter for this test instance. TransportProtocols getProtocolParam() const { + // We've removed support for anything but McbpPlain + if (std::get<0>(GetParam()) != TransportProtocols::McbpPlain) { + throw std::runtime_error( + "McdTestappTest::getProtocolParam(): Only McbpPlain is " + "supported from the old style tests"); + } + return std::get<0>(GetParam()); } @@ -460,11 +463,6 @@ bool safe_recv_packet(void* buf, size_t size); bool safe_recv_packet(std::vector& buf); bool safe_recv_packet(std::vector& buf); -/* The opposite of safe_recv. Simply tries to read from the socket (will use - * SSL if the socket is SSL configured. - */ -ssize_t phase_recv(void* buf, size_t len); - SOCKET create_connect_plain_socket(in_port_t port); time_t get_server_start_time(); @@ -485,8 +483,6 @@ stats_response_t request_stats(); */ uint64_t extract_single_stat(const stats_response_t& stats, const char* name); -ssize_t socket_recv(SOCKET s, char* buf, size_t len); -ssize_t socket_send(SOCKET s, const char* buf, size_t len); void adjust_memcached_clock( int64_t clock_shift, cb::mcbp::request::AdjustTimePayload::TimeType timeType); diff --git a/tests/testapp/testapp_audit.cc b/tests/testapp/testapp_audit.cc index f5047e0f84..941214119a 100644 --- a/tests/testapp/testapp_audit.cc +++ b/tests/testapp/testapp_audit.cc @@ -272,7 +272,7 @@ TEST_P(AuditTest, AuditIllegalFrame_MB31071) { safe_send(blob.data(), blob.size(), false); // This should terminate the conenction - EXPECT_EQ(0, phase_recv(blob.data(), blob.size())); + EXPECT_EQ(0, cb::net::recv(sock, blob.data(), blob.size(), 0)); reconnect_to_server(); bool found = false; diff --git a/tests/testapp/testapp_tests.cc b/tests/testapp/testapp_tests.cc index a497981fda..4f268c0c8f 100644 --- a/tests/testapp/testapp_tests.cc +++ b/tests/testapp/testapp_tests.cc @@ -102,7 +102,7 @@ void test_quit_impl(ClientOpcode cmd) { } /* Socket should be closed now, read should return 0 */ - EXPECT_EQ(0, phase_recv(blob.data(), blob.size())); + EXPECT_EQ(0, cb::net::recv(sock, blob.data(), blob.size(), 0)); reconnect_to_server(); } @@ -652,7 +652,7 @@ TEST_P(McdTestappTest, ExceedMaxPacketSize) { // the server will read the header, and figure out that the packet // is too big and close the socket std::vector blob(1024); - EXPECT_EQ(0, phase_recv(blob.data(), blob.size())); + EXPECT_EQ(0, cb::net::recv(sock, blob.data(), blob.size(), 0)); reconnect_to_server(); } @@ -709,8 +709,7 @@ TEST_F(TestappTest, CollectionsSelectBucket) { INSTANTIATE_TEST_SUITE_P( Transport, McdTestappTest, - ::testing::Combine(::testing::Values(TransportProtocols::McbpPlain, - TransportProtocols::McbpSsl), + ::testing::Combine(::testing::Values(TransportProtocols::McbpPlain), ::testing::Values(ClientJSONSupport::Yes, ClientJSONSupport::No)), McdTestappTest::PrintToStringCombinedName); diff --git a/tests/testapp/testapp_topkeys.cc b/tests/testapp/testapp_topkeys.cc index 69c71b7f06..a6751002cb 100644 --- a/tests/testapp/testapp_topkeys.cc +++ b/tests/testapp/testapp_topkeys.cc @@ -251,7 +251,7 @@ TEST_P(McdTopkeysTest, test_topkeys) { INSTANTIATE_TEST_SUITE_P( Transport, McdTopkeysTest, - ::testing::Combine(::testing::Values(TransportProtocols::McbpSsl), + ::testing::Combine(::testing::Values(TransportProtocols::McbpPlain), ::testing::Values(ClientJSONSupport::Yes, ClientJSONSupport::No)), McdTestappTest::PrintToStringCombinedName);