diff options
author | Håvard Pettersen <havardpe@oath.com> | 2020-02-13 11:32:34 +0000 |
---|---|---|
committer | Håvard Pettersen <havardpe@oath.com> | 2020-02-13 13:58:33 +0000 |
commit | 556d6b002d93391abc2e8cf7c8b1d1d133b12d32 (patch) | |
tree | 2130148d7b1c0ef30bd049f499f21e0c0011b23d | |
parent | 762abbd7f48f3afe8257faf581c7defce160ad4f (diff) |
extend crypto engine api
send spec for client connections to enable SNI as well as server name
verification
28 files changed, 180 insertions, 73 deletions
diff --git a/fbench/src/httpclient/httpclient.cpp b/fbench/src/httpclient/httpclient.cpp index 002d2770dcd..99134a6e297 100644 --- a/fbench/src/httpclient/httpclient.cpp +++ b/fbench/src/httpclient/httpclient.cpp @@ -1,5 +1,6 @@ // Copyright 2017 Yahoo Holdings. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root. #include "httpclient.h" +#include <vespa/vespalib/net/socket_spec.h> #include <cassert> #include <cstring> @@ -69,7 +70,8 @@ HTTPClient::connect_socket() if (!handle.valid()) { return false; } - _socket = vespalib::SyncCryptoSocket::create(*_engine, std::move(handle), false); + _socket = vespalib::SyncCryptoSocket::create_client(*_engine, std::move(handle), + vespalib::SocketSpec::from_host_port(_hostname, _port)); return bool(_socket); } diff --git a/fnet/src/tests/connect/connect_test.cpp b/fnet/src/tests/connect/connect_test.cpp index b70b3fa8b01..d94b6759077 100644 --- a/fnet/src/tests/connect/connect_test.cpp +++ b/fnet/src/tests/connect/connect_test.cpp @@ -65,7 +65,11 @@ struct BlockingCryptoEngine : public CryptoEngine { Gate handshake_work_enter; Gate handshake_work_exit; Gate handshake_socket_deleted; - CryptoSocket::UP create_crypto_socket(SocketHandle socket, bool) override { + CryptoSocket::UP create_client_crypto_socket(SocketHandle socket, const SocketSpec &) override { + return std::make_unique<BlockingCryptoSocket>(std::move(socket), + handshake_work_enter, handshake_work_exit, handshake_socket_deleted); + } + CryptoSocket::UP create_server_crypto_socket(SocketHandle socket) override { return std::make_unique<BlockingCryptoSocket>(std::move(socket), handshake_work_enter, handshake_work_exit, handshake_socket_deleted); } diff --git a/fnet/src/vespa/fnet/connection.cpp b/fnet/src/vespa/fnet/connection.cpp index 5f7adb32af0..c5afd627a5a 100644 --- a/fnet/src/vespa/fnet/connection.cpp +++ b/fnet/src/vespa/fnet/connection.cpp @@ -9,6 +9,7 @@ #include "config.h" #include "transport_thread.h" #include "transport.h" +#include <vespa/vespalib/net/socket_spec.h> #include <vespa/log/log.h> LOG_SETUP(".fnet"); @@ -472,7 +473,7 @@ FNET_Connection::FNET_Connection(FNET_TransportThread *owner, _streamer(streamer), _serverAdapter(serverAdapter), _adminChannel(nullptr), - _socket(owner->owner().create_crypto_socket(std::move(socket), true)), + _socket(owner->owner().create_server_crypto_socket(std::move(socket))), _resolve_handler(nullptr), _context(), _state(FNET_CONNECTING), @@ -579,7 +580,7 @@ FNET_Connection::handle_add_event() { if (_resolve_handler) { auto tweak = [this](vespalib::SocketHandle &handle) { return Owner()->tune(handle); }; - _socket = Owner()->owner().create_crypto_socket(_resolve_handler->address.connect(tweak), false); + _socket = Owner()->owner().create_client_crypto_socket(_resolve_handler->address.connect(tweak), vespalib::SocketSpec(GetSpec())); _ioc_socket_fd = _socket->get_fd(); _resolve_handler.reset(); } diff --git a/fnet/src/vespa/fnet/transport.cpp b/fnet/src/vespa/fnet/transport.cpp index 28e645d9e03..d3b52969c8c 100644 --- a/fnet/src/vespa/fnet/transport.cpp +++ b/fnet/src/vespa/fnet/transport.cpp @@ -54,9 +54,15 @@ FNET_Transport::resolve_async(const vespalib::string &spec, } vespalib::CryptoSocket::UP -FNET_Transport::create_crypto_socket(vespalib::SocketHandle socket, bool is_server) +FNET_Transport::create_client_crypto_socket(vespalib::SocketHandle socket, const vespalib::SocketSpec &spec) { - return _crypto_engine->create_crypto_socket(std::move(socket), is_server); + return _crypto_engine->create_client_crypto_socket(std::move(socket), spec); +} + +vespalib::CryptoSocket::UP +FNET_Transport::create_server_crypto_socket(vespalib::SocketHandle socket) +{ + return _crypto_engine->create_server_crypto_socket(std::move(socket)); } FNET_TransportThread * diff --git a/fnet/src/vespa/fnet/transport.h b/fnet/src/vespa/fnet/transport.h index 8d1ba48c1b0..02ef22c7fb6 100644 --- a/fnet/src/vespa/fnet/transport.h +++ b/fnet/src/vespa/fnet/transport.h @@ -79,17 +79,25 @@ public: vespalib::AsyncResolver::ResultHandler::WP result_handler); /** - * Wrap a plain socket endpoint in a CryptoSocket. The + * Wrap a plain socket endpoint (client side) in a CryptoSocket. The * implementation will be determined by the CryptoEngine used by * this Transport. * * @return socket abstraction able to perform encryption and decryption * @param socket low-level socket - * @param is_server which end of the connection the socket - * represents. This is needed to support - * asymmetrical handshaking. + * @param spec who we are connecting to **/ - vespalib::CryptoSocket::UP create_crypto_socket(vespalib::SocketHandle socket, bool is_server); + vespalib::CryptoSocket::UP create_client_crypto_socket(vespalib::SocketHandle socket, const vespalib::SocketSpec &spec); + + /** + * Wrap a plain socket endpoint (server side) in a CryptoSocket. The + * implementation will be determined by the CryptoEngine used by + * this Transport. + * + * @return socket abstraction able to perform encryption and decryption + * @param socket low-level socket + **/ + vespalib::CryptoSocket::UP create_server_crypto_socket(vespalib::SocketHandle socket); /** * Select one of the underlying transport threads. The selection diff --git a/storage/src/tests/frameworkimpl/status/statustest.cpp b/storage/src/tests/frameworkimpl/status/statustest.cpp index 81d91e2f08a..7c259f00899 100644 --- a/storage/src/tests/frameworkimpl/status/statustest.cpp +++ b/storage/src/tests/frameworkimpl/status/statustest.cpp @@ -19,7 +19,7 @@ vespalib::string fetch(int port, const vespalib::string &path) { auto crypto = vespalib::CryptoEngine::get_default(); auto socket = vespalib::SocketSpec::from_port(port).client_address().connect(); assert(socket.valid()); - auto conn = vespalib::SyncCryptoSocket::create(*crypto, std::move(socket), false); + auto conn = vespalib::SyncCryptoSocket::create_client(*crypto, std::move(socket), vespalib::SocketSpec::from_host_port("localhost", port)); vespalib::string http_req = vespalib::make_string("GET %s HTTP/1.1\r\n" "Host: localhost:%d\r\n" "\r\n", path.c_str(), port); diff --git a/vbench/src/vbench/core/socket.cpp b/vbench/src/vbench/core/socket.cpp index 822b96b2c07..0431b6889a8 100644 --- a/vbench/src/vbench/core/socket.cpp +++ b/vbench/src/vbench/core/socket.cpp @@ -29,7 +29,8 @@ Socket::Socket(SyncCryptoSocket::UP socket) } Socket::Socket(CryptoEngine &crypto, const string &host, int port) - : _socket(SyncCryptoSocket::create(crypto, connect(host, port), false)), + : _socket(SyncCryptoSocket::create_client(crypto, connect(host, port), + vespalib::SocketSpec::from_host_port(host, port))), _input(), _output(), _taint(), diff --git a/vbench/src/vbench/core/socket.h b/vbench/src/vbench/core/socket.h index 0e8848e8292..4b5721c0fb7 100644 --- a/vbench/src/vbench/core/socket.h +++ b/vbench/src/vbench/core/socket.h @@ -52,7 +52,7 @@ struct ServerSocket { Stream::UP accept(CryptoEngine &crypto) { vespalib::SocketHandle handle = server_socket.accept(); if (handle.valid()) { - return std::make_unique<Socket>(SyncCryptoSocket::create(crypto, std::move(handle), true)); + return std::make_unique<Socket>(SyncCryptoSocket::create_server(crypto, std::move(handle))); } else { return Stream::UP(); } diff --git a/vespalib/src/tests/net/crypto_socket/crypto_socket_test.cpp b/vespalib/src/tests/net/crypto_socket/crypto_socket_test.cpp index 62bad716597..e938e15f4e6 100644 --- a/vespalib/src/tests/net/crypto_socket/crypto_socket_test.cpp +++ b/vespalib/src/tests/net/crypto_socket/crypto_socket_test.cpp @@ -17,6 +17,7 @@ #include <fcntl.h> using namespace vespalib; +using namespace vespalib::test; struct SocketPair { SocketHandle client; @@ -204,7 +205,9 @@ void verify_crypto_socket(SocketPair &sockets, CryptoEngine &engine, bool is_ser SocketHandle &my_handle = is_server ? sockets.server : sockets.client; my_handle.set_blocking(false); SmartBuffer read_buffer(4096); - CryptoSocket::UP my_socket = engine.create_crypto_socket(std::move(my_handle), is_server); + CryptoSocket::UP my_socket = is_server + ? engine.create_server_crypto_socket(std::move(my_handle)) + : engine.create_client_crypto_socket(std::move(my_handle), local_spec); TEST_DO(verify_handshake(*my_socket)); drain(*my_socket, read_buffer); TEST_DO(verify_socket_io(*my_socket, read_buffer, is_server)); @@ -226,19 +229,19 @@ TEST_MT_FFF("require that encrypted async socket io works with XorCryptoEngine", } TEST_MT_FFF("require that encrypted async socket io works with TlsCryptoEngine", - 2, SocketPair(), TlsCryptoEngine(vespalib::test::make_tls_options_for_testing()), TimeBomb(60)) + 2, SocketPair(), TlsCryptoEngine(make_tls_options_for_testing()), TimeBomb(60)) { TEST_DO(verify_crypto_socket(f1, f2, (thread_id == 0))); } TEST_MT_FFF("require that encrypted async socket io works with MaybeTlsCryptoEngine(true)", - 2, SocketPair(), MaybeTlsCryptoEngine(std::make_shared<TlsCryptoEngine>(vespalib::test::make_tls_options_for_testing()), true), TimeBomb(60)) + 2, SocketPair(), MaybeTlsCryptoEngine(std::make_shared<TlsCryptoEngine>(make_tls_options_for_testing()), true), TimeBomb(60)) { TEST_DO(verify_crypto_socket(f1, f2, (thread_id == 0))); } TEST_MT_FFF("require that encrypted async socket io works with MaybeTlsCryptoEngine(false)", - 2, SocketPair(), MaybeTlsCryptoEngine(std::make_shared<TlsCryptoEngine>(vespalib::test::make_tls_options_for_testing()), false), TimeBomb(60)) + 2, SocketPair(), MaybeTlsCryptoEngine(std::make_shared<TlsCryptoEngine>(make_tls_options_for_testing()), false), TimeBomb(60)) { TEST_DO(verify_crypto_socket(f1, f2, (thread_id == 0))); } diff --git a/vespalib/src/tests/net/socket_spec/socket_spec_test.cpp b/vespalib/src/tests/net/socket_spec/socket_spec_test.cpp index 0c2b92bbb53..f2da6b70bf3 100644 --- a/vespalib/src/tests/net/socket_spec/socket_spec_test.cpp +++ b/vespalib/src/tests/net/socket_spec/socket_spec_test.cpp @@ -123,4 +123,8 @@ TEST("require that replace_host gives invalid spec when used with less than 2 ho TEST_DO(verify_invalid(SocketSpec("ipc/name:my_socket").replace_host("foo"))); } +TEST("require that invalid socket spec is not valid") { + EXPECT_FALSE(SocketSpec::invalid.valid()); +} + TEST_MAIN() { TEST_RUN_ALL(); } diff --git a/vespalib/src/tests/net/sync_crypto_socket/sync_crypto_socket_test.cpp b/vespalib/src/tests/net/sync_crypto_socket/sync_crypto_socket_test.cpp index 76ecd9453b6..56767051dad 100644 --- a/vespalib/src/tests/net/sync_crypto_socket/sync_crypto_socket_test.cpp +++ b/vespalib/src/tests/net/sync_crypto_socket/sync_crypto_socket_test.cpp @@ -17,6 +17,7 @@ #include <fcntl.h> using namespace vespalib; +using namespace vespalib::test; struct SocketPair { SocketHandle client; @@ -97,7 +98,9 @@ void verify_socket_io(SyncCryptoSocket &socket, bool is_server) { void verify_crypto_socket(SocketPair &sockets, CryptoEngine &engine, bool is_server) { SocketHandle &my_handle = is_server ? sockets.server : sockets.client; my_handle.set_blocking(false); - SyncCryptoSocket::UP my_socket = SyncCryptoSocket::create(engine, std::move(my_handle), is_server); + SyncCryptoSocket::UP my_socket = is_server + ? SyncCryptoSocket::create_server(engine, std::move(my_handle)) + : SyncCryptoSocket::create_client(engine, std::move(my_handle), local_spec); ASSERT_TRUE(my_socket); TEST_DO(verify_socket_io(*my_socket, is_server)); TEST_DO(verify_graceful_shutdown(*my_socket, is_server)); @@ -118,19 +121,19 @@ TEST_MT_FFF("require that encrypted sync socket io works with XorCryptoEngine", } TEST_MT_FFF("require that encrypted sync socket io works with TlsCryptoEngine", - 2, SocketPair(), TlsCryptoEngine(vespalib::test::make_tls_options_for_testing()), TimeBomb(60)) + 2, SocketPair(), TlsCryptoEngine(make_tls_options_for_testing()), TimeBomb(60)) { TEST_DO(verify_crypto_socket(f1, f2, (thread_id == 0))); } TEST_MT_FFF("require that encrypted sync socket io works with MaybeTlsCryptoEngine(true)", - 2, SocketPair(), MaybeTlsCryptoEngine(std::make_shared<TlsCryptoEngine>(vespalib::test::make_tls_options_for_testing()), true), TimeBomb(60)) + 2, SocketPair(), MaybeTlsCryptoEngine(std::make_shared<TlsCryptoEngine>(make_tls_options_for_testing()), true), TimeBomb(60)) { TEST_DO(verify_crypto_socket(f1, f2, (thread_id == 0))); } TEST_MT_FFF("require that encrypted sync socket io works with MaybeTlsCryptoEngine(false)", - 2, SocketPair(), MaybeTlsCryptoEngine(std::make_shared<TlsCryptoEngine>(vespalib::test::make_tls_options_for_testing()), false), TimeBomb(60)) + 2, SocketPair(), MaybeTlsCryptoEngine(std::make_shared<TlsCryptoEngine>(make_tls_options_for_testing()), false), TimeBomb(60)) { TEST_DO(verify_crypto_socket(f1, f2, (thread_id == 0))); } diff --git a/vespalib/src/tests/portal/portal_test.cpp b/vespalib/src/tests/portal/portal_test.cpp index e54700306fe..0bd029c0c3a 100644 --- a/vespalib/src/tests/portal/portal_test.cpp +++ b/vespalib/src/tests/portal/portal_test.cpp @@ -14,13 +14,14 @@ #include <vespa/vespalib/util/latch.h> using namespace vespalib; +using namespace vespalib::test; //----------------------------------------------------------------------------- vespalib::string do_http(int port, CryptoEngine::SP crypto, const vespalib::string &method, const vespalib::string &uri, bool send_host = true) { auto socket = SocketSpec::from_port(port).client_address().connect(); ASSERT_TRUE(socket.valid()); - auto conn = SyncCryptoSocket::create(*crypto, std::move(socket), false); + auto conn = SyncCryptoSocket::create_client(*crypto, std::move(socket), local_spec); vespalib::string http_req = vespalib::make_string("%s %s HTTP/1.1\r\n" "My-Header: my value\r\n" "%s" @@ -75,7 +76,7 @@ Encryption::~Encryption() = default; auto null_crypto() { return std::make_shared<NullCryptoEngine>(); } auto xor_crypto() { return std::make_shared<XorCryptoEngine>(); } -auto tls_crypto() { return std::make_shared<TlsCryptoEngine>(vespalib::test::make_tls_options_for_testing()); } +auto tls_crypto() { return std::make_shared<TlsCryptoEngine>(make_tls_options_for_testing()); } auto maybe_tls_crypto(bool client_tls) { return std::make_shared<MaybeTlsCryptoEngine>(tls_crypto(), client_tls); } std::vector<Encryption> crypto_list = {{"no encryption", null_crypto()}, @@ -260,18 +261,18 @@ TEST("require that connection errors do not block shutdown by leaking resources" auto bound = portal->bind("/test", handler); { // close before sending anything auto socket = SocketSpec::from_port(portal->listen_port()).client_address().connect(); - auto conn = SyncCryptoSocket::create(*crypto.engine, std::move(socket), false); + auto conn = SyncCryptoSocket::create_client(*crypto.engine, std::move(socket), local_spec); } { // send partial request then close connection auto socket = SocketSpec::from_port(portal->listen_port()).client_address().connect(); - auto conn = SyncCryptoSocket::create(*crypto.engine, std::move(socket), false); + auto conn = SyncCryptoSocket::create_client(*crypto.engine, std::move(socket), local_spec); vespalib::string req = "GET /test HTTP/1.1\r\n" "Host: local"; ASSERT_EQUAL(conn->write(req.data(), req.size()), ssize_t(req.size())); } { // send request then close without reading response auto socket = SocketSpec::from_port(portal->listen_port()).client_address().connect(); - auto conn = SyncCryptoSocket::create(*crypto.engine, std::move(socket), false); + auto conn = SyncCryptoSocket::create_client(*crypto.engine, std::move(socket), local_spec); vespalib::string req = "GET /test HTTP/1.1\r\n" "Host: localhost\r\n" "\r\n"; diff --git a/vespalib/src/vespa/vespalib/net/crypto_engine.cpp b/vespalib/src/vespa/vespalib/net/crypto_engine.cpp index a52d4eeb690..a92b0e06bbe 100644 --- a/vespalib/src/vespa/vespalib/net/crypto_engine.cpp +++ b/vespalib/src/vespa/vespalib/net/crypto_engine.cpp @@ -250,16 +250,29 @@ CryptoEngine::get_default() } CryptoSocket::UP -NullCryptoEngine::create_crypto_socket(SocketHandle socket, bool is_server) +NullCryptoEngine::create_client_crypto_socket(SocketHandle socket, const SocketSpec &) { - net::tls::ConnectionStatistics::get(is_server).inc_insecure_connections(); + net::tls::ConnectionStatistics::get(false).inc_insecure_connections(); return std::make_unique<NullCryptoSocket>(std::move(socket)); } CryptoSocket::UP -XorCryptoEngine::create_crypto_socket(SocketHandle socket, bool is_server) +NullCryptoEngine::create_server_crypto_socket(SocketHandle socket) { - return std::make_unique<XorCryptoSocket>(std::move(socket), is_server); + net::tls::ConnectionStatistics::get(true).inc_insecure_connections(); + return std::make_unique<NullCryptoSocket>(std::move(socket)); +} + +CryptoSocket::UP +XorCryptoEngine::create_client_crypto_socket(SocketHandle socket, const SocketSpec &) +{ + return std::make_unique<XorCryptoSocket>(std::move(socket), false); +} + +CryptoSocket::UP +XorCryptoEngine::create_server_crypto_socket(SocketHandle socket) +{ + return std::make_unique<XorCryptoSocket>(std::move(socket), true); } } // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/net/crypto_engine.h b/vespalib/src/vespa/vespalib/net/crypto_engine.h index 1cb1305e039..4deacf9a6c7 100644 --- a/vespalib/src/vespa/vespalib/net/crypto_engine.h +++ b/vespalib/src/vespa/vespalib/net/crypto_engine.h @@ -9,6 +9,8 @@ namespace vespalib { +class SocketSpec; + /** * Component responsible for wrapping low-level sockets into * appropriate CryptoSocket instances. This is the top-level interface @@ -17,7 +19,8 @@ namespace vespalib { **/ struct CryptoEngine { using SP = std::shared_ptr<CryptoEngine>; - virtual CryptoSocket::UP create_crypto_socket(SocketHandle socket, bool is_server) = 0; + virtual CryptoSocket::UP create_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) = 0; + virtual CryptoSocket::UP create_server_crypto_socket(SocketHandle socket) = 0; virtual ~CryptoEngine(); static CryptoEngine::SP get_default(); }; @@ -26,7 +29,8 @@ struct CryptoEngine { * Crypto engine without encryption. **/ struct NullCryptoEngine : public CryptoEngine { - CryptoSocket::UP create_crypto_socket(SocketHandle socket, bool is_server) override; + CryptoSocket::UP create_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) override; + CryptoSocket::UP create_server_crypto_socket(SocketHandle socket) override; }; /** @@ -35,7 +39,8 @@ struct NullCryptoEngine : public CryptoEngine { * from TLS. **/ struct XorCryptoEngine : public CryptoEngine { - CryptoSocket::UP create_crypto_socket(SocketHandle socket, bool is_server) override; + CryptoSocket::UP create_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) override; + CryptoSocket::UP create_server_crypto_socket(SocketHandle socket) override; }; } // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/net/socket_spec.cpp b/vespalib/src/vespa/vespalib/net/socket_spec.cpp index d1376ce1dd7..06682086670 100644 --- a/vespalib/src/vespa/vespalib/net/socket_spec.cpp +++ b/vespalib/src/vespa/vespalib/net/socket_spec.cpp @@ -41,6 +41,8 @@ SocketSpec::address(bool server) const return SocketAddress(); } +SocketSpec SocketSpec::invalid; + SocketSpec::SocketSpec(const vespalib::string &spec) : SocketSpec() { diff --git a/vespalib/src/vespa/vespalib/net/socket_spec.h b/vespalib/src/vespa/vespalib/net/socket_spec.h index f28b14573ac..01af382d638 100644 --- a/vespalib/src/vespa/vespalib/net/socket_spec.h +++ b/vespalib/src/vespa/vespalib/net/socket_spec.h @@ -24,6 +24,7 @@ private: : _type(type), _node(node), _port(port) {} SocketAddress address(bool server) const; public: + static SocketSpec invalid; explicit SocketSpec(const vespalib::string &spec); vespalib::string spec() const; SocketSpec replace_host(const vespalib::string &new_host) const; diff --git a/vespalib/src/vespa/vespalib/net/sync_crypto_socket.cpp b/vespalib/src/vespa/vespalib/net/sync_crypto_socket.cpp index 29388035bda..3aa2d3b0683 100644 --- a/vespalib/src/vespa/vespalib/net/sync_crypto_socket.cpp +++ b/vespalib/src/vespa/vespalib/net/sync_crypto_socket.cpp @@ -29,6 +29,25 @@ void set_blocking(int fd) { } // namespace vespalib::<unnamed> +SyncCryptoSocket::UP +SyncCryptoSocket::create(CryptoSocket::UP socket) +{ + set_blocking(socket->get_fd()); + for (;;) { + switch (socket->handshake()) { + case CryptoSocket::HandshakeResult::FAIL: + return std::unique_ptr<SyncCryptoSocket>(nullptr); + case CryptoSocket::HandshakeResult::DONE: + return UP(new SyncCryptoSocket(std::move(socket))); + case CryptoSocket::HandshakeResult::NEED_READ: + case CryptoSocket::HandshakeResult::NEED_WRITE: + break; + case CryptoSocket::HandshakeResult::NEED_WORK: + socket->do_handshake_work(); + } + } +} + SyncCryptoSocket::~SyncCryptoSocket() = default; ssize_t @@ -90,23 +109,15 @@ SyncCryptoSocket::half_close() } SyncCryptoSocket::UP -SyncCryptoSocket::create(CryptoEngine &engine, SocketHandle socket, bool is_server) +SyncCryptoSocket::create_client(CryptoEngine &engine, SocketHandle socket, const SocketSpec &spec) { - auto crypto_socket = engine.create_crypto_socket(std::move(socket), is_server); - set_blocking(crypto_socket->get_fd()); - for (;;) { - switch (crypto_socket->handshake()) { - case CryptoSocket::HandshakeResult::FAIL: - return std::unique_ptr<SyncCryptoSocket>(nullptr); - case CryptoSocket::HandshakeResult::DONE: - return UP(new SyncCryptoSocket(std::move(crypto_socket))); - case CryptoSocket::HandshakeResult::NEED_READ: - case CryptoSocket::HandshakeResult::NEED_WRITE: - break; - case CryptoSocket::HandshakeResult::NEED_WORK: - crypto_socket->do_handshake_work(); - } - } + return create(engine.create_client_crypto_socket(std::move(socket), spec)); +} + +SyncCryptoSocket::UP +SyncCryptoSocket::create_server(CryptoEngine &engine, SocketHandle socket) +{ + return create(engine.create_server_crypto_socket(std::move(socket))); } } // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/net/sync_crypto_socket.h b/vespalib/src/vespa/vespalib/net/sync_crypto_socket.h index 00d6cbca0db..36fcfe12ed9 100644 --- a/vespalib/src/vespa/vespalib/net/sync_crypto_socket.h +++ b/vespalib/src/vespa/vespalib/net/sync_crypto_socket.h @@ -19,17 +19,20 @@ namespace vespalib { **/ class SyncCryptoSocket { +public: + using UP = std::unique_ptr<SyncCryptoSocket>; private: CryptoSocket::UP _socket; SmartBuffer _buffer; SyncCryptoSocket(CryptoSocket::UP socket) : _socket(std::move(socket)), _buffer(0) {} + static UP create(CryptoSocket::UP socket); public: - using UP = std::unique_ptr<SyncCryptoSocket>; ~SyncCryptoSocket(); ssize_t read(char *buf, size_t len); ssize_t write(const char *buf, size_t len); ssize_t half_close(); - static UP create(CryptoEngine &engine, SocketHandle socket, bool is_server); + static UP create_client(CryptoEngine &engine, SocketHandle socket, const SocketSpec &spec); + static UP create_server(CryptoEngine &engine, SocketHandle socket); }; } // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.cpp b/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.cpp index 5f20280e0e2..c425ab75ce8 100644 --- a/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.cpp +++ b/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.cpp @@ -91,13 +91,22 @@ AutoReloadingTlsCryptoEngine::EngineSP AutoReloadingTlsCryptoEngine::acquire_cur return _current_engine; } -CryptoSocket::UP AutoReloadingTlsCryptoEngine::create_crypto_socket(SocketHandle socket, bool is_server) { - return acquire_current_engine()->create_crypto_socket(std::move(socket), is_server); +CryptoSocket::UP AutoReloadingTlsCryptoEngine::create_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) { + return acquire_current_engine()->create_client_crypto_socket(std::move(socket), spec); +} + +CryptoSocket::UP AutoReloadingTlsCryptoEngine::create_server_crypto_socket(SocketHandle socket) { + return acquire_current_engine()->create_server_crypto_socket(std::move(socket)); +} + +std::unique_ptr<TlsCryptoSocket> +AutoReloadingTlsCryptoEngine::create_tls_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) { + return acquire_current_engine()->create_tls_client_crypto_socket(std::move(socket), spec); } std::unique_ptr<TlsCryptoSocket> -AutoReloadingTlsCryptoEngine::create_tls_crypto_socket(SocketHandle socket, bool is_server) { - return acquire_current_engine()->create_tls_crypto_socket(std::move(socket), is_server); +AutoReloadingTlsCryptoEngine::create_tls_server_crypto_socket(SocketHandle socket) { + return acquire_current_engine()->create_tls_server_crypto_socket(std::move(socket)); } } diff --git a/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h b/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h index 6287fdd4f63..e268cbc8f1a 100644 --- a/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h +++ b/vespalib/src/vespa/vespalib/net/tls/auto_reloading_tls_crypto_engine.h @@ -45,8 +45,10 @@ public: EngineSP acquire_current_engine() const; - CryptoSocket::UP create_crypto_socket(SocketHandle socket, bool is_server) override; - std::unique_ptr<TlsCryptoSocket> create_tls_crypto_socket(SocketHandle socket, bool is_server) override; + CryptoSocket::UP create_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) override; + CryptoSocket::UP create_server_crypto_socket(SocketHandle socket) override; + std::unique_ptr<TlsCryptoSocket> create_tls_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) override; + std::unique_ptr<TlsCryptoSocket> create_tls_server_crypto_socket(SocketHandle socket) override; }; } diff --git a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.cpp b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.cpp index 891f8cdab23..f7f0284bded 100644 --- a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.cpp +++ b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.cpp @@ -6,15 +6,19 @@ namespace vespalib { CryptoSocket::UP -MaybeTlsCryptoEngine::create_crypto_socket(SocketHandle socket, bool is_server) +MaybeTlsCryptoEngine::create_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) { - if (is_server) { - return std::make_unique<MaybeTlsCryptoSocket>(std::move(socket), _tls_engine); - } else if (_use_tls_when_client) { - return _tls_engine->create_crypto_socket(std::move(socket), false); + if (_use_tls_when_client) { + return _tls_engine->create_client_crypto_socket(std::move(socket), spec); } else { - return _null_engine->create_crypto_socket(std::move(socket), false); + return _null_engine->create_client_crypto_socket(std::move(socket), spec); } } +CryptoSocket::UP +MaybeTlsCryptoEngine::create_server_crypto_socket(SocketHandle socket) +{ + return std::make_unique<MaybeTlsCryptoSocket>(std::move(socket), _tls_engine); +} + } // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.h b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.h index 29909fa115d..147a770bc8f 100644 --- a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.h +++ b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_engine.h @@ -28,7 +28,8 @@ public: : _null_engine(std::make_shared<NullCryptoEngine>()), _tls_engine(std::move(tls_engine)), _use_tls_when_client(use_tls_when_client) {} - CryptoSocket::UP create_crypto_socket(SocketHandle socket, bool is_server) override; + CryptoSocket::UP create_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) override; + CryptoSocket::UP create_server_crypto_socket(SocketHandle socket) override; }; } // namespace vespalib diff --git a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.cpp b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.cpp index 9af6703acbc..8ab6adad2e5 100644 --- a/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.cpp +++ b/vespalib/src/vespa/vespalib/net/tls/maybe_tls_crypto_socket.cpp @@ -50,7 +50,7 @@ public: } if (looksLikeTlsToMe(src.data)) { CryptoSocket::UP &self = _self; // need copy due to self destruction - auto tls_socket = _factory->create_tls_crypto_socket(std::move(_socket), true); + auto tls_socket = _factory->create_tls_server_crypto_socket(std::move(_socket)); tls_socket->inject_read_data(src.data, src.size); self = std::move(tls_socket); return self->handshake(); diff --git a/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.cpp b/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.cpp index 58d99cc7108..d0475f3e88d 100644 --- a/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.cpp +++ b/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.cpp @@ -12,9 +12,17 @@ TlsCryptoEngine::TlsCryptoEngine(net::tls::TransportSecurityOptions tls_opts, ne } std::unique_ptr<TlsCryptoSocket> -TlsCryptoEngine::create_tls_crypto_socket(SocketHandle socket, bool is_server) +TlsCryptoEngine::create_tls_client_crypto_socket(SocketHandle socket, const SocketSpec &) { - auto mode = is_server ? net::tls::CryptoCodec::Mode::Server : net::tls::CryptoCodec::Mode::Client; + auto mode = net::tls::CryptoCodec::Mode::Client; + auto codec = net::tls::CryptoCodec::create_default_codec(_tls_ctx, SocketAddress::peer_address(socket.get()), mode); + return std::make_unique<net::tls::CryptoCodecAdapter>(std::move(socket), std::move(codec)); +} + +std::unique_ptr<TlsCryptoSocket> +TlsCryptoEngine::create_tls_server_crypto_socket(SocketHandle socket) +{ + auto mode = net::tls::CryptoCodec::Mode::Server; auto codec = net::tls::CryptoCodec::create_default_codec(_tls_ctx, SocketAddress::peer_address(socket.get()), mode); return std::make_unique<net::tls::CryptoCodecAdapter>(std::move(socket), std::move(codec)); } diff --git a/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.h b/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.h index dc7d7eaf9ce..5e760cf5585 100644 --- a/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.h +++ b/vespalib/src/vespa/vespalib/net/tls/tls_crypto_engine.h @@ -11,7 +11,8 @@ namespace vespalib { class AbstractTlsCryptoEngine : public CryptoEngine { public: - virtual std::unique_ptr<TlsCryptoSocket> create_tls_crypto_socket(SocketHandle socket, bool is_server) = 0; + virtual std::unique_ptr<TlsCryptoSocket> create_tls_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) = 0; + virtual std::unique_ptr<TlsCryptoSocket> create_tls_server_crypto_socket(SocketHandle socket) = 0; }; /** @@ -24,9 +25,13 @@ private: public: explicit TlsCryptoEngine(net::tls::TransportSecurityOptions tls_opts, net::tls::AuthorizationMode authz_mode = net::tls::AuthorizationMode::Enforce); - std::unique_ptr<TlsCryptoSocket> create_tls_crypto_socket(SocketHandle socket, bool is_server) override; - CryptoSocket::UP create_crypto_socket(SocketHandle socket, bool is_server) override { - return create_tls_crypto_socket(std::move(socket), is_server); + std::unique_ptr<TlsCryptoSocket> create_tls_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) override; + std::unique_ptr<TlsCryptoSocket> create_tls_server_crypto_socket(SocketHandle socket) override; + CryptoSocket::UP create_client_crypto_socket(SocketHandle socket, const SocketSpec &spec) override { + return create_tls_client_crypto_socket(std::move(socket), spec); + } + CryptoSocket::UP create_server_crypto_socket(SocketHandle socket) override { + return create_tls_server_crypto_socket(std::move(socket)); } std::shared_ptr<net::tls::TlsContext> tls_context() const noexcept { return _tls_ctx; }; diff --git a/vespalib/src/vespa/vespalib/portal/portal.cpp b/vespalib/src/vespa/vespalib/portal/portal.cpp index 47719ea4c69..a6d44348e5e 100644 --- a/vespalib/src/vespa/vespalib/portal/portal.cpp +++ b/vespalib/src/vespa/vespalib/portal/portal.cpp @@ -143,7 +143,7 @@ Portal::handle_accept(portal::HandleGuard guard, SocketHandle socket) { socket.set_blocking(false); socket.set_keepalive(true); - new HttpConnection(std::move(guard), _reactor, _crypto->create_crypto_socket(std::move(socket), true), + new HttpConnection(std::move(guard), _reactor, _crypto->create_server_crypto_socket(std::move(socket)), [this](HttpConnection *conn) { handle_http(conn); diff --git a/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.cpp b/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.cpp index c685bffc23e..dcd2ced8036 100644 --- a/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.cpp +++ b/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.cpp @@ -67,6 +67,8 @@ npxYSKVCyo3a/Vo33V8/H0WgOXioKEZJxA== namespace vespalib::test { +SocketSpec local_spec("tcp/localhost:123"); + vespalib::net::tls::TransportSecurityOptions make_tls_options_for_testing() { return vespalib::net::tls::TransportSecurityOptions(ca_pem, cert_pem, key_pem); } diff --git a/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.h b/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.h index a1f1d5958f9..41e5d7cc86d 100644 --- a/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.h +++ b/vespalib/src/vespa/vespalib/test/make_tls_options_for_testing.h @@ -2,11 +2,19 @@ #pragma once +#include <vespa/vespalib/net/socket_spec.h> #include <vespa/vespalib/net/tls/transport_security_options.h> namespace vespalib::test { /** + * A socket spec representing "tcp/localhost:123". Used by unit tests + * performing hostname verification against the tls options created + * below. + **/ +extern SocketSpec local_spec; + +/** * Make security options allowing you to talk to yourself using * TLS. This is intended for testing purposes only. **/ |