diff options
author | René Meusel <[email protected]> | 2019-02-19 13:05:25 +0100 |
---|---|---|
committer | Hannes Rantzsch <[email protected]> | 2019-04-16 10:47:40 +0200 |
commit | cf9a53cc488cf704e7393765325cbc9277fc36d5 (patch) | |
tree | a05043322f37033e9604436de423a25278e9c4bb | |
parent | 7887a4fff97560303ab2c1b63e2a25f1153c0d3a (diff) |
adapt Stream<> API to be compatibile to OpenSSL
-rw-r--r-- | src/lib/asio/asio_async_handshake_op.h | 8 | ||||
-rw-r--r-- | src/lib/asio/asio_async_read_op.h | 8 | ||||
-rw-r--r-- | src/lib/asio/asio_stream.h | 181 | ||||
-rw-r--r-- | src/tests/unit_asio_stream.cpp | 21 |
4 files changed, 179 insertions, 39 deletions
diff --git a/src/lib/asio/asio_async_handshake_op.h b/src/lib/asio/asio_async_handshake_op.h index 3f3bea2ab..61a8077d9 100644 --- a/src/lib/asio/asio_async_handshake_op.h +++ b/src/lib/asio/asio_async_handshake_op.h @@ -10,7 +10,7 @@ namespace Botan { template <class Channel, class StreamLayer, class Handler> struct AsyncHandshakeOperation { - AsyncHandshakeOperation(Channel& channel, StreamCore& core, + AsyncHandshakeOperation(Channel* channel, StreamCore& core, StreamLayer& nextLayer, Handler&& handler) : channel_(channel), core_(core), @@ -36,7 +36,7 @@ struct AsyncHandshakeOperation boost::asio::buffer(core_.input_buffer_, bytesTransferred); try { - channel_.received_data( + channel_->received_data( static_cast<const uint8_t*>(read_buffer.data()), read_buffer.size()); } @@ -58,7 +58,7 @@ struct AsyncHandshakeOperation return; } - if(!channel_.is_active() && !ec) + if(!channel_->is_active() && !ec) { // we need more tls data from the socket nextLayer_.async_read_some(core_.input_buffer_, std::move(*this)); @@ -76,7 +76,7 @@ struct AsyncHandshakeOperation } private: - Channel& channel_; + Channel* channel_; StreamCore& core_; StreamLayer& nextLayer_; Handler handler_; diff --git a/src/lib/asio/asio_async_read_op.h b/src/lib/asio/asio_async_read_op.h index 84d002a6b..78b761037 100644 --- a/src/lib/asio/asio_async_read_op.h +++ b/src/lib/asio/asio_async_read_op.h @@ -11,7 +11,7 @@ template <class Channel, class StreamLayer, class Handler, class MutableBufferSequence> struct AsyncReadOperation { - AsyncReadOperation(Channel& channel, StreamCore& core, StreamLayer& nextLayer, + AsyncReadOperation(Channel* channel, StreamCore& core, StreamLayer& nextLayer, Handler&& handler, const MutableBufferSequence& buffers) : channel_(channel), core_(core), nextLayer_(nextLayer), handler_(std::forward<Handler>(handler)), buffers_(buffers) {} @@ -35,8 +35,8 @@ struct AsyncReadOperation boost::asio::buffer(core_.input_buffer_, bytes_transferred); try { - channel_.received_data(static_cast<const uint8_t*>(read_buffer.data()), - read_buffer.size()); + channel_->received_data(static_cast<const uint8_t*>(read_buffer.data()), + read_buffer.size()); } catch(...) { @@ -63,7 +63,7 @@ struct AsyncReadOperation } private: - Channel& channel_; + Channel* channel_; StreamCore& core_; StreamLayer& nextLayer_; Handler handler_; diff --git a/src/lib/asio/asio_stream.h b/src/lib/asio/asio_stream.h index ced9a65ef..540d48767 100644 --- a/src/lib/asio/asio_stream.h +++ b/src/lib/asio/asio_stream.h @@ -23,30 +23,126 @@ class Stream : public StreamBase<Channel> { public: using next_layer_type = typename std::remove_reference<StreamLayer>::type; - using lowest_layer_type = typename next_layer_type::lowest_layer_type; - using executor_type = typename next_layer_type::executor_type; + using native_handle_type = typename std::add_pointer<Channel>::type; + + enum handshake_type + { + client, + server + }; + + private: + void validate_handshake_type(handshake_type type) + { + if(type != handshake_type::client) + { + throw Not_Implemented("server-side TLS stream is not implemented"); + } + } + + bool validate_handshake_type(handshake_type type, boost::system::error_code& ec) + { + if(type != handshake_type::client) + { + ec = make_error_code(Botan::error::not_implemented); + return false; + } + + return true; + } + public: template <typename... Args> Stream(StreamLayer nextLayer, Args&& ... args) : StreamBase<Channel>(std::forward<Args>(args)...), nextLayer_(std::forward<StreamLayer>(nextLayer)) {} + // + // -- -- accessor methods + // + executor_type get_executor() noexcept { return nextLayer_.get_executor(); } const next_layer_type& next_layer() const { return nextLayer_; } next_layer_type& next_layer() { return nextLayer_; } lowest_layer_type& lowest_layer() { return nextLayer_.lowest_layer(); } + const lowest_layer_type& lowest_layer() const { return nextLayer_.lowest_layer(); } + + native_handle_type native_handle() { return &this->channel_; } + + // + // -- -- configuration and callback setters + // + + template< + typename VerifyCallback> + void set_verify_callback(VerifyCallback callback) + { + BOTAN_UNUSED(callback); + throw Not_Implemented("set_verify_callback is not implemented"); + } + + template< + typename VerifyCallback> + void set_verify_callback(VerifyCallback callback, + boost::system::error_code& ec) + { + BOTAN_UNUSED(callback); + ec = make_error_code(Botan::error::not_implemented); + } + + void set_verify_depth(int depth) + { + BOTAN_UNUSED(depth); + throw Not_Implemented("set_verify_depth is not implemented"); + } + + void set_verify_depth(int depth, + boost::system::error_code& ec) + { + BOTAN_UNUSED(depth); + ec = make_error_code(Botan::error::not_implemented); + } - Channel& channel() { return this->channel_; } + template <typename verify_mode> + void set_verify_mode(verify_mode v) + { + BOTAN_UNUSED(v); + throw Not_Implemented("set_verify_mode is not implemented"); + } + + template <typename verify_mode> + void set_verify_mode(verify_mode v, + boost::system::error_code& ec) + { + BOTAN_UNUSED(v); + ec = make_error_code(Botan::error::not_implemented); + } + + // + // -- -- handshake methods + // + + void handshake(handshake_type type) + { + validate_handshake_type(type); - const Channel& channel() const { return this->channel_; } + boost::system::error_code ec; + handshake(type, ec); + boost::asio::detail::throw_error(ec, "handshake"); + } - void handshake(boost::system::error_code& ec) + void handshake(handshake_type type, boost::system::error_code& ec) { - while(!channel().is_active()) + if(!validate_handshake_type(type, ec)) + { + return; + } + + while(!native_handle()->is_active()) { writePendingTlsData(ec); if(ec) @@ -64,8 +160,8 @@ class Stream : public StreamBase<Channel> try { - channel().received_data(static_cast<const uint8_t*>(read_buffer.data()), - read_buffer.size()); + native_handle()->received_data(static_cast<const uint8_t*>(read_buffer.data()), + read_buffer.size()); } catch(...) { @@ -77,22 +173,33 @@ class Stream : public StreamBase<Channel> } } - void handshake() + template<typename ConstBufferSequence> + void handshake(handshake_type type, const ConstBufferSequence& buffers) { - boost::system::error_code ec; - handshake(ec); - boost::asio::detail::throw_error(ec, "handshake"); + BOTAN_UNUSED(type, buffers); + throw Not_Implemented("server-side TLS stream is not implemented"); + } + + template<typename ConstBufferSequence> + void handshake(handshake_type type, + const ConstBufferSequence& buffers, + boost::system::error_code& ec) + { + BOTAN_UNUSED(type, buffers); + ec = make_error_code(Botan::error::not_implemented); } template <typename HandshakeHandler> BOOST_ASIO_INITFN_RESULT_TYPE(HandshakeHandler, void(boost::system::error_code)) - async_handshake(HandshakeHandler&& handler) + async_handshake(handshake_type type, HandshakeHandler&& handler) { // If you get an error on the following line it means that your handler does // not meet the documented type requirements for a HandshakeHandler. BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(HandshakeHandler, handler) type_check; + validate_handshake_type(type); + boost::asio::async_completion<HandshakeHandler, void(boost::system::error_code)> init(handler); @@ -103,11 +210,29 @@ class Stream : public StreamBase<Channel> return init.result.get(); } + template <typename ConstBufferSequence, typename BufferedHandshakeHandler> + BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, + void(boost::system::error_code, std::size_t)) + async_handshake(handshake_type type, + const ConstBufferSequence& buffers, + BufferedHandshakeHandler&& handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a BufferedHandshakeHandler. + BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(BufferedHandshakeHandler, handler) type_check; + BOTAN_UNUSED(type, buffers, handler); + throw Not_Implemented("buffered async handshake is not implemented"); + } + + // + // -- -- shutdown methods + // + void shutdown(boost::system::error_code& ec) { try { - channel().close(); + native_handle()->close(); } catch(...) { @@ -124,6 +249,20 @@ class Stream : public StreamBase<Channel> boost::asio::detail::throw_error(ec, "shutdown"); } + template <typename ShutdownHandler> + void async_shutdown(ShutdownHandler&& handler) + { + // If you get an error on the following line it means that your handler does + // not meet the documented type requirements for a ShutdownHandler. + BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(ShutdownHandler, handler) type_check; + BOTAN_UNUSED(handler); + throw Not_Implemented("async shutdown is not implemented"); + } + + // + // -- -- I/O methods + // + template <typename MutableBufferSequence> std::size_t read_some(const MutableBufferSequence& buffers, boost::system::error_code& ec) @@ -143,8 +282,8 @@ class Stream : public StreamBase<Channel> try { - channel().received_data(static_cast<const uint8_t*>(read_buffer.data()), - read_buffer.size()); + native_handle()->received_data(static_cast<const uint8_t*>(read_buffer.data()), + read_buffer.size()); } catch(...) { @@ -174,7 +313,7 @@ class Stream : public StreamBase<Channel> try { - channel().send(static_cast<const uint8_t*>(buffer.data()), buffer.size()); + native_handle()->send(static_cast<const uint8_t*>(buffer.data()), buffer.size()); } catch(...) { @@ -212,8 +351,8 @@ class Stream : public StreamBase<Channel> try { - channel().send(static_cast<const uint8_t*>(buffer.data()), - buffer.size()); + native_handle()->send(static_cast<const uint8_t*>(buffer.data()), + buffer.size()); } catch(...) { @@ -264,7 +403,7 @@ class Stream : public StreamBase<Channel> create_async_handshake_op(Handler&& handler) { return Botan::AsyncHandshakeOperation<Channel, StreamLayer, Handler>( - channel(), this->core_, nextLayer_, std::forward<Handler>(handler)); + native_handle(), this->core_, nextLayer_, std::forward<Handler>(handler)); } template <typename Handler, typename MutableBufferSequence> @@ -275,7 +414,7 @@ class Stream : public StreamBase<Channel> { return Botan::AsyncReadOperation<Channel, StreamLayer, Handler, MutableBufferSequence>( - channel(), this->core_, nextLayer_, std::forward<Handler>(handler), + native_handle(), this->core_, nextLayer_, std::forward<Handler>(handler), buffers); } diff --git a/src/tests/unit_asio_stream.cpp b/src/tests/unit_asio_stream.cpp index 5103ba120..32350df2d 100644 --- a/src/tests/unit_asio_stream.cpp +++ b/src/tests/unit_asio_stream.cpp @@ -169,10 +169,10 @@ class ASIO_Stream_Tests final : public Test MockSocket socket; TestStream ssl{socket}; - ssl.handshake(); + ssl.handshake(TestStream::client); Test::Result result("sync TLS handshake"); - result.test_eq("feeds data into channel until active", ssl.channel().is_active(), true); + result.test_eq("feeds data into channel until active", ssl.native_handle()->is_active(), true); results.push_back(result); } @@ -185,10 +185,10 @@ class ASIO_Stream_Tests final : public Test socket.ec_ = expected_ec; error_code ec; - ssl.handshake(ec); + ssl.handshake(TestStream::client, ec); Test::Result result("sync TLS handshake error"); - result.test_eq("does not activate channel", ssl.channel().is_active(), false); + result.test_eq("does not activate channel", ssl.native_handle()->is_active(), false); result.confirm("propagates error code", ec == expected_ec); results.push_back(result); } @@ -202,10 +202,10 @@ class ASIO_Stream_Tests final : public Test auto handler = [&](const boost::system::error_code&) { - result.test_eq("feeds data into channel until active", ssl.channel().is_active(), true); + result.test_eq("feeds data into channel until active", ssl.native_handle()->is_active(), true); }; - ssl.async_handshake(handler); + ssl.async_handshake(TestStream::client, handler); results.push_back(result); } @@ -221,11 +221,11 @@ class ASIO_Stream_Tests final : public Test auto handler = [&](const boost::system::error_code &ec) { - result.test_eq("does not activate channel", ssl.channel().is_active(), false); + result.test_eq("does not activate channel", ssl.native_handle()->is_active(), false); result.confirm("propagates error code", ec == expected_ec); }; - ssl.async_handshake(handler); + ssl.async_handshake(TestStream::client, handler); results.push_back(result); } @@ -465,6 +465,7 @@ class ASIO_Stream_Tests final : public Test results.push_back(result); } + public: std::vector<Test::Result> run() override { @@ -498,6 +499,6 @@ class ASIO_Stream_Tests final : public Test BOTAN_REGISTER_TEST("asio_stream", ASIO_Stream_Tests); -#endif - } // namespace Botan_Tests + +#endif |