9#ifndef BOTAN_ASIO_STREAM_H_
10#define BOTAN_ASIO_STREAM_H_
12#include <botan/build.h>
15#include <boost/version.hpp>
16#if BOOST_VERSION >= 106600
18#include <botan/asio_async_ops.h>
19#include <botan/asio_context.h>
20#include <botan/asio_error.h>
22#include <botan/tls_callbacks.h>
23#include <botan/tls_channel.h>
24#include <botan/tls_client.h>
25#include <botan/tls_magic.h>
26#include <botan/tls_server.h>
30#define BOOST_ASIO_DISABLE_SERIAL_PORT
31#include <boost/asio.hpp>
32#include <boost/beast/core.hpp>
47template <
class StreamLayer,
class ChannelT = Channel>
62 template <
typename... Args>
82 template <
typename Arg>
109#if BOOST_VERSION >= 107000
186 template <
typename verify_mode>
198 template <
typename verify_mode>
219 boost::system::error_code ec;
221 boost::asio::detail::throw_error(ec,
"handshake");
263 template <
typename HandshakeHandler>
269 boost::system::error_code ec;
274 boost::asio::async_completion<HandshakeHandler, void(boost::system::error_code)>
init(
handler);
277 op{std::move(
init.completion_handler), *
this, ec};
279 return init.result.get();
283 template <
typename ConstBufferSequence,
typename BufferedHandshakeHandler>
285 void(boost::system::error_code, std::size_t))
330 boost::system::error_code ec;
332 boost::asio::detail::throw_error(ec,
"shutdown");
343 template <
typename Handler,
typename Executor>
346 void operator()(boost::system::error_code ec, std::size_t)
351 using executor_type = boost::asio::associated_executor_t<Handler, Executor>;
353 executor_type get_executor() const noexcept
355 return boost::asio::get_associated_executor(handler, io_executor);
358 using allocator_type = boost::asio::associated_allocator_t<Handler>;
360 allocator_type get_allocator() const noexcept
362 return boost::asio::get_associated_allocator(handler);
366 Executor io_executor;
380 template <
typename ShutdownHandler>
383 boost::system::error_code ec;
391 using ShutdownHandlerWrapper = Wrapper<ShutdownHandler, typename Stream::executor_type>;
394 BOOST_ASIO_SHUTDOWN_HANDLER_CHECK(ShutdownHandler, w) type_check;
396 boost::asio::async_completion<ShutdownHandlerWrapper, void(boost::system::error_code, std::size_t)>
400 op{std::move(
init.completion_handler), *
this, boost::asio::buffer_size(
send_buffer())};
402 return init.result.get();
420 template <
typename MutableBufferSequence>
422 boost::system::error_code& ec)
439 ec = boost::asio::error::eof;
441 else if(ec == boost::asio::error::eof)
460 template <
typename MutableBufferSequence>
463 boost::system::error_code ec;
465 boost::asio::detail::throw_error(ec,
"read_some");
479 template <
typename ConstBufferSequence>
481 boost::system::error_code& ec)
485 return !ec ? boost::asio::buffer_size(
buffers) : 0;
498 template <
typename ConstBufferSequence>
501 boost::system::error_code ec;
503 boost::asio::detail::throw_error(ec,
"write_some");
515 template <
typename ConstBufferSequence,
typename WriteHandler>
518 void(boost::system::error_code, std::size_t))
520 BOOST_ASIO_WRITE_HANDLER_CHECK(WriteHandler,
handler) type_check;
522 boost::asio::async_completion<WriteHandler, void(boost::system::error_code, std::size_t)>
init(
handler);
524 boost::system::error_code ec;
532 op{std::move(
init.completion_handler), *
this, std::size_t(0), ec};
533 return init.result.get();
537 op{std::move(
init.completion_handler), *
this, boost::asio::buffer_size(
buffers)};
539 return init.result.get();
552 template <
typename MutableBufferSequence,
typename ReadHandler>
555 void(boost::system::error_code, std::size_t))
557 BOOST_ASIO_READ_HANDLER_CHECK(ReadHandler,
handler) type_check;
559 boost::asio::async_completion<ReadHandler, void(boost::system::error_code, std::size_t)>
init(
handler);
562 op{std::move(
init.completion_handler), *
this,
buffers};
563 return init.result.get();
598 boost::asio::buffer_copy(m_stream.
m_send_buffer.prepare(size), boost::asio::buffer(data, size))
605 boost::asio::buffer_copy(m_stream.
m_receive_buffer.prepare(size), boost::asio::const_buffer(data, size))
621 return std::chrono::milliseconds(1000);
631 const std::vector<X509_Certificate>& cert_chain,
632 const std::vector<std::shared_ptr<const OCSP::Response>>& ocsp_responses,
633 const std::vector<Certificate_Store*>& trusted_roots,
635 const std::string& hostname,
659 template <
typename MutableBufferSequence>
681 template<
class T = ChannelT>
682 typename std::enable_if<!std::is_same<Channel, T>::value>
::type
694 template<
class T = ChannelT>
695 typename std::enable_if<std::is_same<Channel, T>::value>
::type
754 template <
typename ConstBufferSequence>
760 for(
auto it = boost::asio::buffer_sequence_begin(
buffers);
761 !ec && it != boost::asio::buffer_sequence_end(
buffers);
764 const boost::asio::const_buffer buffer = *it;
767 native_handle()->send(
static_cast<const uint8_t*
>(buffer.data()), buffer.size());
784 native_handle()->received_data(
static_cast<const uint8_t*
>(read_buffer.data()), read_buffer.size());
789 template <
typename Fun>
804 catch(
const std::exception&)
#define BOTAN_UNUSED(...)
virtual void tls_verify_cert_chain(const std::vector< X509_Certificate > &cert_chain, const std::vector< std::shared_ptr< const OCSP::Response > > &ocsp_responses, const std::vector< Certificate_Store * > &trusted_roots, Usage_Type usage, const std::string &hostname, const TLS::Policy &policy)
Credentials_Manager & m_credentials_manager
bool has_verify_callback() const
Server_Information m_server_info
RandomNumberGenerator & m_rng
void set_verify_callback(Verify_Callback callback)
Override the tls_verify_cert_chain callback.
const Verify_Callback & get_verify_callback() const
Session_Manager & m_session_manager
detail::fn_signature_helper< decltype(&Callbacks::tls_verify_cert_chain)>::type Verify_Callback
static Protocol_Version latest_tls_version()
Helper class that implements Botan::TLS::Callbacks.
void tls_record_received(uint64_t, const uint8_t data[], std::size_t size) override
bool tls_session_established(const Botan::TLS::Session &) override
virtual ~StreamCore()=default
void tls_emit_data(const uint8_t data[], std::size_t size) override
void tls_verify_cert_chain(const std::vector< X509_Certificate > &cert_chain, const std::vector< std::shared_ptr< const OCSP::Response > > &ocsp_responses, const std::vector< Certificate_Store * > &trusted_roots, Usage_Type usage, const std::string &hostname, const TLS::Policy &policy) override
std::chrono::milliseconds tls_verify_cert_chain_ocsp_timeout() const override
StreamCore(Stream &stream)
void tls_alert(Botan::TLS::Alert alert) override
boost::asio compatible SSL/TLS stream
Stream(Stream &&other)=default
native_handle_type native_handle()
std::size_t copy_received_data(MutableBufferSequence buffers)
Copy decrypted data into the user-provided buffer.
const boost::asio::mutable_buffer m_input_buffer
void set_verify_mode(verify_mode v, boost::system::error_code &ec)
void try_with_error_code(Fun f, boost::system::error_code &ec)
Catch exceptions and set an error_code.
void set_verify_mode(verify_mode v)
Stream & operator=(const Stream &other)=delete
boost::beast::flat_buffer m_receive_buffer
auto async_read_some(const MutableBufferSequence &buffers, ReadHandler &&handler) -> BOOST_ASIO_INITFN_RESULT_TYPE(ReadHandler, void(boost::system::error_code, std::size_t))
Start an asynchronous read. The function call always returns immediately.
lowest_layer_type & lowest_layer()
const ConstBufferSequence & buffers
std::enable_if<!std::is_same< Channel, T >::value >::type setup_native_handle(Connection_Side, boost::system::error_code &)
Stream(Context &context, Args &&... args)
Construct a new Stream.
void set_verify_depth(int depth)
const next_layer_type & next_layer() const
std::unique_ptr< ChannelT > m_native_handle
Stream(Arg &&arg, Context &context)
Construct a new Stream.
void consume_send_buffer(std::size_t bytesConsumed)
Mark bytes in the send buffer as consumed, removing them from the buffer.
std::enable_if< std::is_same< Channel, T >::value >::type setup_native_handle(Connection_Side side, boost::system::error_code &ec)
Create the native handle.
typename next_layer_type::executor_type executor_type
boost::asio::const_buffer send_buffer() const
void handshake(Connection_Side side)
Performs SSL handshaking.
bool has_received_data() const
Check if decrypted data is available in the receive buffer.
void set_verify_callback(Context::Verify_Callback callback)
Override the tls_verify_cert_chain callback.
typename std::add_pointer< ChannelT >::type native_handle_type
next_layer_type & next_layer()
std::size_t write_some(const ConstBufferSequence &buffers, boost::system::error_code &ec)
Write some data to the stream.
const boost::asio::mutable_buffer & input_buffer()
void process_encrypted_data(const boost::asio::const_buffer &read_buffer, boost::system::error_code &ec)
Pass encrypted data to the native handle for processing.
executor_type get_executor() noexcept
void set_verify_callback(Context::Verify_Callback callback, boost::system::error_code &ec)
Compatibility overload of set_verify_callback.
typename std::remove_reference< StreamLayer >::type next_layer_type
void set_shutdown_received()
std::size_t read_some(const MutableBufferSequence &buffers)
Read some data from the stream.
std::size_t write_some(const ConstBufferSequence &buffers)
Write some data to the stream.
Stream(const Stream &other)=delete
Stream & operator=(Stream &&other)=default
size_t send_pending_encrypted_data(boost::system::error_code &ec)
Synchronously write encrypted data from the send buffer to the next layer.
typename next_layer_type::lowest_layer_type lowest_layer_type
auto async_handshake(Connection_Side side, HandshakeHandler &&handler) ->
Starts an asynchronous SSL handshake.
const ConstBufferSequence BufferedHandshakeHandler && handler
void tls_encrypt(const ConstBufferSequence &buffers, boost::system::error_code &ec)
Pass plaintext data to the native handle for processing.
std::size_t read_some(const MutableBufferSequence &buffers, boost::system::error_code &ec)
Read some data from the stream.
void set_verify_depth(int depth, boost::system::error_code &ec)
virtual ~Stream()=default
std::vector< uint8_t > m_input_buffer_space
bool shutdown_received() const
Indicates whether a close_notify alert has been received from the peer.
void shutdown()
Shut down SSL on the stream.
void handshake(Connection_Side side, boost::system::error_code &ec)
Performs SSL handshaking.
void shutdown(boost::system::error_code &ec)
Shut down SSL on the stream.
BOOST_ASIO_HANDSHAKE_HANDLER_CHECK(BufferedHandshakeHandler, handler) type_check
auto async_write_some(const ConstBufferSequence &buffers, WriteHandler &&handler) -> BOOST_ASIO_INITFN_RESULT_TYPE(WriteHandler, void(boost::system::error_code, std::size_t))
Start an asynchronous write. The function call always returns immediately.
const lowest_layer_type & lowest_layer() const
boost::beast::flat_buffer m_send_buffer
throw Not_Implemented("buffered async handshake is not implemented")
void async_shutdown(ShutdownHandler &&handler)
Asynchronously shut down SSL on the stream.
bool has_data_to_send() const
Check if encrypted data is available in the send buffer.
BOOST_ASIO_INITFN_RESULT_TYPE(BufferedHandshakeHandler, void(boost::system::error_code, std::size_t)) async_handshake(Connection_Side side
ErrorType error_type() const noexcept override