aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenĂ© Meusel <[email protected]>2019-02-19 13:05:25 +0100
committerHannes Rantzsch <[email protected]>2019-04-16 10:47:40 +0200
commitcf9a53cc488cf704e7393765325cbc9277fc36d5 (patch)
treea05043322f37033e9604436de423a25278e9c4bb
parent7887a4fff97560303ab2c1b63e2a25f1153c0d3a (diff)
adapt Stream<> API to be compatibile to OpenSSL
-rw-r--r--src/lib/asio/asio_async_handshake_op.h8
-rw-r--r--src/lib/asio/asio_async_read_op.h8
-rw-r--r--src/lib/asio/asio_stream.h181
-rw-r--r--src/tests/unit_asio_stream.cpp21
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