diff options
author | Hannes Rantzsch <[email protected]> | 2019-03-27 17:24:53 +0100 |
---|---|---|
committer | Hannes Rantzsch <[email protected]> | 2019-04-16 10:48:16 +0200 |
commit | 287a4ba2ad02392d11dbcb6c18c5f7776ead79c4 (patch) | |
tree | 51aff7b987b8c6ba19753db0dbe2332db854ba1d | |
parent | b5a3a91a763b49840b03e05c6043ee4add9ca931 (diff) |
improve constructor interface of Stream
-rw-r--r-- | src/lib/tls/asio/asio_context.h | 40 | ||||
-rw-r--r-- | src/lib/tls/asio/asio_includes.h | 12 | ||||
-rw-r--r-- | src/lib/tls/asio/asio_stream.h | 29 | ||||
-rw-r--r-- | src/lib/tls/asio/asio_stream_base.h | 20 | ||||
-rw-r--r-- | src/lib/tls/asio/info.txt | 1 | ||||
-rw-r--r-- | src/tests/unit_asio_stream.cpp | 196 |
6 files changed, 165 insertions, 133 deletions
diff --git a/src/lib/tls/asio/asio_context.h b/src/lib/tls/asio/asio_context.h new file mode 100644 index 000000000..387d201c0 --- /dev/null +++ b/src/lib/tls/asio/asio_context.h @@ -0,0 +1,40 @@ +/* + * TLS Context + * (C) 2018-2019 Jack Lloyd + * 2018-2019 Hannes Rantzsch, Tim Oesterreich, Rene Meusel + * + * Botan is released under the Simplified BSD License (see license.txt) + */ + +#ifndef BOTAN_ASIO_TLS_CONTEXT_H_ +#define BOTAN_ASIO_TLS_CONTEXT_H_ + +#if defined(BOTAN_HAS_TLS) && defined(BOTAN_HAS_BOOST_ASIO) + +#include <boost/version.hpp> +#if BOOST_VERSION > 106600 + +#include <botan/credentials_manager.h> +#include <botan/rng.h> +#include <botan/tls_policy.h> +#include <botan/tls_server_info.h> +#include <botan/tls_session_manager.h> + +namespace Botan { +namespace TLS { + +struct Context + { + Credentials_Manager* credentialsManager; + RandomNumberGenerator* randomNumberGenerator; + Session_Manager* sessionManager; + Policy* policy; + Server_Information serverInfo; + }; + +} // namespace TLS +} // namespace Botan + +#endif // BOOST_VERSION +#endif // BOTAN_HAS_TLS && BOTAN_HAS_BOOST_ASIO +#endif // BOTAN_ASIO_TLS_CONTEXT_H_ diff --git a/src/lib/tls/asio/asio_includes.h b/src/lib/tls/asio/asio_includes.h index 5f67db148..dfbd24474 100644 --- a/src/lib/tls/asio/asio_includes.h +++ b/src/lib/tls/asio/asio_includes.h @@ -11,12 +11,12 @@ #ifdef BOTAN_HAS_BOOST_ASIO -// We need to define BOOST_ASIO_DISABLE_SERIAL_PORT before any asio imports. Otherwise asio will include <termios.h>, -// which interferes with Botan's amalgamation by defining macros like 'B0' and 'FF1'. -#define BOOST_ASIO_DISABLE_SERIAL_PORT -#include <boost/asio.hpp> -#include <boost/asio/buffer.hpp> -#include <boost/asio/ip/tcp.hpp> + // We need to define BOOST_ASIO_DISABLE_SERIAL_PORT before any asio imports. Otherwise asio will include <termios.h>, + // which interferes with Botan's amalgamation by defining macros like 'B0' and 'FF1'. + #define BOOST_ASIO_DISABLE_SERIAL_PORT + #include <boost/asio.hpp> + #include <boost/asio/buffer.hpp> + #include <boost/asio/ip/tcp.hpp> #endif // BOTAN_HAS_BOOST_ASIO #endif // BOTAN_ASIO_INCLUDES_H_ diff --git a/src/lib/tls/asio/asio_stream.h b/src/lib/tls/asio/asio_stream.h index 4988338ea..1926eadf9 100644 --- a/src/lib/tls/asio/asio_stream.h +++ b/src/lib/tls/asio/asio_stream.h @@ -21,6 +21,7 @@ #include <botan/internal/asio_includes.h> #include <botan/internal/asio_stream_base.h> #include <botan/internal/asio_stream_core.h> +#include <botan/asio_context.h> #include <algorithm> #include <memory> @@ -40,7 +41,9 @@ namespace Botan { namespace TLS { /** - * boost::asio compatible SSL/TLS stream based on TLS::Client or TLS::Server. + * boost::asio compatible SSL/TLS stream + * + * Currently only the TLS::Client specialization is implemented. */ template <class StreamLayer, class Channel> class Stream : public StreamBase<Channel> @@ -55,25 +58,13 @@ class Stream : public StreamBase<Channel> public: template <typename... Args> - explicit Stream(StreamLayer&& nextLayer, Args&& ... args) - : StreamBase<Channel>(std::forward<Args>(args)...), - m_nextLayer(std::forward<StreamLayer>(nextLayer)) {} + explicit Stream(Context& context, Args&& ... args) + : StreamBase<Channel>(context), m_nextLayer(std::forward<Args>(args)...) {} - Stream(StreamLayer&& nextLayer, boost::asio::ssl::context&) - : StreamBase<Channel>(Botan::TLS::Session_Manager_Noop(), Botan::Credentials_Manager()), - m_nextLayer(std::forward<StreamLayer>(nextLayer)) - { - // Configuring a TLS stream via asio::ssl::context is not supported. - // The corresponding configuration objects for Botan are: - // * TLS::Session_Manager - // * Credentials_Manager - // * TLS::Policy - // * TLS::Server_Information - // It would be nice to have a masquarading wrapper that exposes an API - // compatible with asio::ssl::context for convenient drop-in replacement. - // For now, base your TLS configurations on the above mentioned classes. - throw Not_Implemented("cannot handle an asio::ssl::context"); - } + // overload for boost::asio::ssl::stream compatibility + template <typename Arg> + explicit Stream(Arg&& arg, Context& context) + : StreamBase<Channel>(context), m_nextLayer(std::forward<Arg>(arg)) {} Stream(Stream&& other) = default; Stream& operator=(Stream&& other) = default; diff --git a/src/lib/tls/asio/asio_stream_base.h b/src/lib/tls/asio/asio_stream_base.h index 949f76bef..4832b2f8f 100644 --- a/src/lib/tls/asio/asio_stream_base.h +++ b/src/lib/tls/asio/asio_stream_base.h @@ -14,9 +14,8 @@ #include <boost/version.hpp> #if BOOST_VERSION > 106600 -#include <botan/auto_rng.h> #include <botan/tls_client.h> -#include <botan/tls_server.h> +#include <botan/asio_context.h> #include <botan/asio_error.h> #include <botan/internal/asio_stream_core.h> @@ -48,17 +47,13 @@ template <> class StreamBase<Botan::TLS::Client> { public: - StreamBase(Botan::TLS::Session_Manager& sessionManager, - Botan::Credentials_Manager& credentialsManager, - const Botan::TLS::Policy& policy, - const Botan::TLS::Server_Information& serverInfo = - Botan::TLS::Server_Information{}) + StreamBase(Context& context) : m_channel(m_core, - sessionManager, - credentialsManager, - policy, - m_rng, - serverInfo) + *context.sessionManager, + *context.credentialsManager, + *context.policy, + *context.randomNumberGenerator, + context.serverInfo) { } @@ -90,7 +85,6 @@ class StreamBase<Botan::TLS::Client> } Botan::TLS::StreamCore m_core; - Botan::AutoSeeded_RNG m_rng; Botan::TLS::Client m_channel; }; diff --git a/src/lib/tls/asio/info.txt b/src/lib/tls/asio/info.txt index cfca189a7..73afbb960 100644 --- a/src/lib/tls/asio/info.txt +++ b/src/lib/tls/asio/info.txt @@ -3,6 +3,7 @@ TLS_ASIO_STREAM -> 20181218 </defines> <header:public> +asio_context.h asio_stream.h asio_error.h </header:public> diff --git a/src/tests/unit_asio_stream.cpp b/src/tests/unit_asio_stream.cpp index dcb0783de..1cc1ee7c1 100644 --- a/src/tests/unit_asio_stream.cpp +++ b/src/tests/unit_asio_stream.cpp @@ -72,18 +72,18 @@ class ThrowingMockChannel : public MockChannel { public: ThrowingMockChannel(Botan::TLS::StreamCore& core) : MockChannel(core) - { - } - - std::size_t received_data(const uint8_t[], std::size_t) - { - throw Botan::TLS::Unexpected_Message("test_error"); - } - - void send(const uint8_t[], std::size_t) - { - throw Botan::TLS::Unexpected_Message("test_error"); - } + { + } + + std::size_t received_data(const uint8_t[], std::size_t) + { + throw Botan::TLS::Unexpected_Message("test_error"); + } + + void send(const uint8_t[], std::size_t) + { + throw Botan::TLS::Unexpected_Message("test_error"); + } }; } @@ -101,7 +101,7 @@ template <> class StreamBase<Botan_Tests::MockChannel> { public: - StreamBase() + StreamBase(Context& /*ignored*/) : m_channel(m_core) { } @@ -113,7 +113,6 @@ class StreamBase<Botan_Tests::MockChannel> protected: StreamCore m_core; - Botan::AutoSeeded_RNG m_rng; Botan_Tests::MockChannel m_channel; void validate_handshake_type(handshake_type) {} @@ -125,8 +124,8 @@ template <> class StreamBase<Botan_Tests::ThrowingMockChannel> : public StreamBase<Botan_Tests::MockChannel> { public: - StreamBase() - : m_channel(m_core) + StreamBase(Context& c) + : StreamBase<Botan_Tests::MockChannel>(c), m_channel(m_core) { } @@ -157,17 +156,16 @@ class Asio_Stream_Tests final : public Test { using TestStream = boost::beast::test::stream; using FailCount = boost::beast::test::fail_count; - using AsioStream = Botan::TLS::Stream<TestStream&, MockChannel>; - using ThrowingAsioStream = Botan::TLS::Stream<TestStream&, ThrowingMockChannel>; + using AsioStream = Botan::TLS::Stream<TestStream, MockChannel>; + using ThrowingAsioStream = Botan::TLS::Stream<TestStream, ThrowingMockChannel>; boost::string_view test_data() const { return boost::string_view((const char*)TEST_DATA, TEST_DATA_SIZE); } void test_sync_handshake(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}; - - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, test_data()); ssl.handshake(AsioStream::handshake_type::client); @@ -181,11 +179,12 @@ class Asio_Stream_Tests final : public Test net::io_context ioc; // fail right away FailCount fc{0, net::error::eof}; - TestStream socket{ioc, fc}, remote{ioc}; + TestStream remote{ioc}; - socket.connect(remote); + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, fc); + ssl.next_layer().connect(remote); - AsioStream ssl{socket}; // mimic handshake initialization ssl.native_handle()->send(TEST_DATA, TEST_DATA_SIZE); @@ -201,11 +200,11 @@ class Asio_Stream_Tests final : public Test void test_sync_handshake_throw(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}, remote{ioc}; - - socket.connect(remote); + TestStream remote{ioc}; - ThrowingAsioStream ssl{socket}; + Botan::TLS::Context ctx; + ThrowingAsioStream ssl(ctx, ioc, test_data()); + ssl.next_layer().connect(remote); error_code ec; ssl.handshake(AsioStream::handshake_type::client, ec); @@ -219,11 +218,12 @@ class Asio_Stream_Tests final : public Test void test_async_handshake(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}, remote{ioc}; + TestStream remote{ioc}; - socket.connect(remote); + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, test_data()); + ssl.next_layer().connect(remote); - AsioStream ssl{socket}; // mimic handshake initialization ssl.native_handle()->send(TEST_DATA, TEST_DATA_SIZE); @@ -231,14 +231,14 @@ class Asio_Stream_Tests final : public Test auto handler = [&](const error_code&) { - result.confirm("reads from socket", socket.nread() > 0); - result.confirm("writes from socket", socket.nwrite() > 0); + result.confirm("reads from socket", ssl.next_layer().nread() > 0); + result.confirm("writes from socket", ssl.next_layer().nwrite() > 0); result.test_eq("feeds data into channel until active", ssl.native_handle()->is_active(), true); }; ssl.async_handshake(AsioStream::handshake_type::client, handler); - socket.close_remote(); + ssl.next_layer().close_remote(); ioc.run(); results.push_back(result); } @@ -248,11 +248,12 @@ class Asio_Stream_Tests final : public Test net::io_context ioc; // fail right away FailCount fc{0, net::error::eof}; - TestStream socket{ioc, fc}, remote{ioc}; + TestStream remote{ioc}; - socket.connect(remote); + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, fc); + ssl.next_layer().connect(remote); - AsioStream ssl{socket}; // mimic handshake initialization ssl.native_handle()->send(TEST_DATA, TEST_DATA_SIZE); @@ -273,11 +274,11 @@ class Asio_Stream_Tests final : public Test void test_async_handshake_throw(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}, remote{ioc}; - - socket.connect(remote); + TestStream remote{ioc}; - ThrowingAsioStream ssl{socket}; + Botan::TLS::Context ctx; + ThrowingAsioStream ssl(ctx, ioc, test_data()); + ssl.next_layer().connect(remote); Test::Result result("async TLS handshake throw"); @@ -296,9 +297,9 @@ class Asio_Stream_Tests final : public Test void test_sync_read_some_success(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}; - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, test_data()); const std::size_t buf_size = 128; uint8_t buf[buf_size]; @@ -317,9 +318,9 @@ class Asio_Stream_Tests final : public Test void test_sync_read_some_buffer_sequence(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}; - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, test_data()); error_code ec; std::vector<net::mutable_buffer> data; @@ -346,11 +347,11 @@ class Asio_Stream_Tests final : public Test net::io_context ioc; // fail right away FailCount fc{0, net::error::eof}; - TestStream socket{ioc, fc}, remote{ioc}; + TestStream remote{ioc}; - socket.connect(remote); - - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, fc); + ssl.next_layer().connect(remote); uint8_t buf[128]; error_code ec; @@ -367,11 +368,11 @@ class Asio_Stream_Tests final : public Test void test_sync_read_some_throw(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}, remote{ioc}; - - socket.connect(remote); + TestStream remote{ioc}; - ThrowingAsioStream ssl{socket}; + Botan::TLS::Context ctx; + ThrowingAsioStream ssl(ctx, ioc, test_data()); + ssl.next_layer().connect(remote); uint8_t buf[128]; error_code ec; @@ -388,9 +389,10 @@ class Asio_Stream_Tests final : public Test void test_async_read_some_success(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}; + TestStream remote{ioc}; - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, test_data()); uint8_t data[TEST_DATA_SIZE]; error_code ec; @@ -406,7 +408,7 @@ class Asio_Stream_Tests final : public Test net::mutable_buffer buf {data, TEST_DATA_SIZE}; net::async_read(ssl, buf, read_handler); - socket.close_remote(); + ssl.next_layer().close_remote(); ioc.run(); results.push_back(result); } @@ -414,9 +416,8 @@ class Asio_Stream_Tests final : public Test void test_async_read_some_buffer_sequence(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}; - - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, test_data()); error_code ec; std::vector<net::mutable_buffer> data; @@ -438,7 +439,7 @@ class Asio_Stream_Tests final : public Test net::async_read(ssl, data, read_handler); - socket.close_remote(); + ssl.next_layer().close_remote(); ioc.run(); results.push_back(result); } @@ -448,9 +449,8 @@ class Asio_Stream_Tests final : public Test net::io_context ioc; // fail right away FailCount fc{0, net::error::eof}; - TestStream socket{ioc, fc}; - - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, fc); uint8_t data[TEST_DATA_SIZE]; error_code ec; @@ -465,7 +465,7 @@ class Asio_Stream_Tests final : public Test net::mutable_buffer buf {data, TEST_DATA_SIZE}; net::async_read(ssl, buf, read_handler); - socket.close_remote(); + ssl.next_layer().close_remote(); ioc.run(); results.push_back(result); } @@ -473,9 +473,8 @@ class Asio_Stream_Tests final : public Test void test_async_read_some_throw(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc, test_data()}; - - ThrowingAsioStream ssl{socket}; + Botan::TLS::Context ctx; + ThrowingAsioStream ssl(ctx, ioc, test_data()); uint8_t data[TEST_DATA_SIZE]; error_code ec; @@ -490,7 +489,7 @@ class Asio_Stream_Tests final : public Test net::mutable_buffer buf {data, TEST_DATA_SIZE}; net::async_read(ssl, buf, read_handler); - socket.close_remote(); + ssl.next_layer().close_remote(); ioc.run(); results.push_back(result); } @@ -498,10 +497,11 @@ class Asio_Stream_Tests final : public Test void test_sync_write_some_success(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc}, remote{ioc}; - socket.connect(remote); + TestStream remote{ioc}; - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc); + ssl.next_layer().connect(remote); error_code ec; auto bytes_transferred = net::write(ssl, net::const_buffer(TEST_DATA, TEST_DATA_SIZE), ec); @@ -517,10 +517,11 @@ class Asio_Stream_Tests final : public Test void test_sync_write_some_buffer_sequence(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc}, remote{ioc}; - socket.connect(remote); + TestStream remote{ioc}; - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc); + ssl.next_layer().connect(remote); error_code ec; // this should be Botan::TLS::MAX_PLAINTEXT_SIZE + 1024 + 1 @@ -545,7 +546,7 @@ class Asio_Stream_Tests final : public Test result.confirm("writes the correct data", contains(remote.buffer().data().data(), random_data.data(), random_data.size())); result.test_eq("writes the correct amount of data", bytes_transferred, random_data.size()); - result.test_eq("correct number of writes", socket.nwrite(), 2); + result.test_eq("correct number of writes", ssl.next_layer().nwrite(), 2); result.confirm("does not report an error", !ec); results.push_back(result); @@ -556,11 +557,12 @@ class Asio_Stream_Tests final : public Test net::io_context ioc; // fail right away FailCount fc{0, net::error::eof}; - TestStream socket{ioc, fc}, remote{ioc}; + TestStream remote{ioc}; - socket.connect(remote); + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, fc); + ssl.next_layer().connect(remote); - AsioStream ssl{socket}; error_code ec; auto bytes_transferred = net::write(ssl, net::const_buffer(TEST_DATA, TEST_DATA_SIZE), ec); @@ -575,11 +577,11 @@ class Asio_Stream_Tests final : public Test void test_sync_write_some_throw(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc}, remote{ioc}; - - socket.connect(remote); + TestStream remote{ioc}; - ThrowingAsioStream ssl{socket}; + Botan::TLS::Context ctx; + ThrowingAsioStream ssl(ctx, ioc); + ssl.next_layer().connect(remote); error_code ec; auto bytes_transferred = net::write(ssl, net::const_buffer(TEST_DATA, TEST_DATA_SIZE), ec); @@ -594,10 +596,11 @@ class Asio_Stream_Tests final : public Test void test_async_write_some_success(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc}, remote{ioc}; - socket.connect(remote); + TestStream remote{ioc}; - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc); + ssl.next_layer().connect(remote); error_code ec; Test::Result result("async write_some success"); @@ -618,10 +621,11 @@ class Asio_Stream_Tests final : public Test void test_async_write_some_buffer_sequence(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc}, remote{ioc}; - socket.connect(remote); + TestStream remote{ioc}; - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc); + ssl.next_layer().connect(remote); error_code ec; // this should be Botan::TLS::MAX_PLAINTEXT_SIZE + 1024 + 1 @@ -646,7 +650,7 @@ class Asio_Stream_Tests final : public Test result.confirm("writes the correct data", contains(remote.buffer().data().data(), random_data.data(), random_data.size())); result.test_eq("writes the correct amount of data", bytes_transferred, random_data.size()); - result.test_eq("correct number of writes", socket.nwrite(), 2); + result.test_eq("correct number of writes", ssl.next_layer().nwrite(), 2); result.confirm("does not report an error", !ec); }; @@ -661,10 +665,11 @@ class Asio_Stream_Tests final : public Test net::io_context ioc; // fail right away FailCount fc{0, net::error::eof}; - TestStream socket{ioc, fc}, remote{ioc}; - socket.connect(remote); + TestStream remote{ioc}; - AsioStream ssl{socket}; + Botan::TLS::Context ctx; + AsioStream ssl(ctx, ioc, fc); + ssl.next_layer().connect(remote); error_code ec; Test::Result result("async write_some error"); @@ -684,10 +689,11 @@ class Asio_Stream_Tests final : public Test void test_async_write_throw(std::vector<Test::Result>& results) { net::io_context ioc; - TestStream socket{ioc}, remote{ioc}; - socket.connect(remote); + TestStream remote{ioc}; - ThrowingAsioStream ssl{socket}; + Botan::TLS::Context ctx; + ThrowingAsioStream ssl(ctx, ioc); + ssl.next_layer().connect(remote); error_code ec; Test::Result result("async write_some throw"); |