diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj index f50b5e5564..0e1234873b 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj +++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj @@ -75,6 +75,8 @@ + + @@ -306,6 +308,12 @@ true + + true + true + true + true + true true diff --git a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters index be813db54c..6ae621f34a 100644 --- a/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters +++ b/Subtrees/beast/Builds/VisualStudio2012/beast.vcxproj.filters @@ -842,6 +842,12 @@ beast_core\memory + + beast_asio\protocol + + + beast_asio\protocol + @@ -1303,6 +1309,9 @@ beast_asio\basics + + beast_asio\protocol + diff --git a/Subtrees/beast/modules/beast_asio/basics/beast_BufferType.h b/Subtrees/beast/modules/beast_asio/basics/beast_BufferType.h index 24e71d7564..006d624137 100644 --- a/Subtrees/beast/modules/beast_asio/basics/beast_BufferType.h +++ b/Subtrees/beast/modules/beast_asio/basics/beast_BufferType.h @@ -91,10 +91,13 @@ private: std::vector m_buffers; }; +typedef boost::asio::const_buffer ConstBuffer; +typedef boost::asio::mutable_buffer MutableBuffer; + /** Meets the requirements of ConstBufferSequence */ -typedef BufferType ConstBuffers; +typedef BufferType ConstBuffers; /** Meets the requirements of MutableBufferSequence */ -typedef BufferType MutableBuffers; +typedef BufferType MutableBuffers; #endif diff --git a/Subtrees/beast/modules/beast_asio/beast_asio.cpp b/Subtrees/beast/modules/beast_asio/beast_asio.cpp index f8b0817cd5..71a155aafb 100644 --- a/Subtrees/beast/modules/beast_asio/beast_asio.cpp +++ b/Subtrees/beast/modules/beast_asio/beast_asio.cpp @@ -31,6 +31,7 @@ namespace beast #include "sockets/beast_SslContext.cpp" #include "protocol/beast_ProxyHandshake.cpp" +#include "protocol/beast_StreamHandshakeDetectorType.cpp" #include "tests/beast_TestPeerBasics.cpp" #include "tests/beast_TestPeerLogic.cpp" diff --git a/Subtrees/beast/modules/beast_asio/beast_asio.h b/Subtrees/beast/modules/beast_asio/beast_asio.h index be9b236de9..e797f6567f 100644 --- a/Subtrees/beast/modules/beast_asio/beast_asio.h +++ b/Subtrees/beast/modules/beast_asio/beast_asio.h @@ -63,6 +63,8 @@ namespace beast #include "sockets/beast_SslContext.h" #include "protocol/beast_ProxyHandshake.h" +#include "protocol/beast_HandshakeDetectorType.h" +#include "protocol/beast_StreamHandshakeDetectorType.h" #include "tests/beast_TestPeerBasics.h" #include "tests/beast_TestPeer.h" diff --git a/Subtrees/beast/modules/beast_asio/protocol/beast_HandshakeDetectorType.h b/Subtrees/beast/modules/beast_asio/protocol/beast_HandshakeDetectorType.h new file mode 100644 index 0000000000..037a720a74 --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/protocol/beast_HandshakeDetectorType.h @@ -0,0 +1,344 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_HANDSHAKEDETECTORTYPE_H_INCLUDED +#define BEAST_HANDSHAKEDETECTORTYPE_H_INCLUDED + +class DetectPolicy +{ +public: + DetectPolicy () + : m_finished (false) + , m_success (false) + { + } + + /** Returns the minimum number of bytes we need to succeed. + */ + virtual std::size_t needed () = 0; + + /** Returns true if the return value of success() is valid. + */ + bool finished () const noexcept + { + return m_finished; + } + + /** Returns true if the buffers matched the Handshake + */ + bool success () const noexcept + { + bassert (m_finished); + return m_success; + } + +protected: + void conclude (bool success = true) + { + m_finished = true; + m_success = success; + } + + void fail () + { + conclude (false); + } + + //-------------------------------------------------------------------------- + + /** Represents a small, fixed size buffer. + This provides a convenient interface for doing a bytewise + verification/reject test on a handshake protocol. + */ + template + struct Input + { + template + explicit Input (ConstBufferSequence const& buffer) + : m_buffer (boost::asio::buffer (m_storage)) + , m_size (boost::asio::buffer_copy (m_buffer, buffer)) + , m_data (boost::asio::buffer_cast (m_buffer)) + { + } +#if 0 + uint8 const* data () const noexcept + { + return m_data; + } +#endif + + uint8 operator[] (std::size_t index) const noexcept + { + bassert (index >= 0 && index < m_size); + return m_data [index]; + } + + bool peek (std::size_t bytes) const noexcept + { + if (m_size >= bytes) + return true; + return false; + } + + template + bool peek (T* t) noexcept + { + std::size_t const bytes = sizeof (T); + if (m_size >= bytes) + { + std::copy (m_data, m_data + bytes, t); + return true; + } + return false; + } + + bool consume (std::size_t bytes) noexcept + { + if (m_size >= bytes) + { + m_data += bytes; + m_size -= bytes; + return true; + } + return false; + } + + template + bool read (T* t) noexcept + { + std::size_t const bytes = sizeof (T); + if (m_size >= bytes) + { + //this causes a stack corruption. + //std::copy (m_data, m_data + bytes, t); + + memcpy (t, m_data, bytes); + m_data += bytes; + m_size -= bytes; + return true; + } + return false; + } + + // Reads an integraltype in network byte order + template + bool readNetworkInteger (IntegerType* value) + { + // Must be an integral type! + // not available in all versions of std:: unfortunately + //static_bassert (std::is_integral ::value); + IntegerType networkValue; + if (! read (&networkValue)) + return; + *value = fromNetworkByteOrder (networkValue); + return true; + } + + private: + boost::array m_storage; + MutableBuffer m_buffer; + std::size_t m_size; + uint8 const* m_data; + }; + +private: + bool m_finished; + bool m_success; +}; + +// Handshake for SSL 2 +// +// http://tools.ietf.org/html/rfc5246#appendix-E.2 +// +// uint8 V2CipherSpec[3]; +// struct { +// uint16 msg_length; +// uint8 msg_type; +// Version version; Should be 'ProtocolVersion'? +// uint16 cipher_spec_length; +// uint16 session_id_length; +// uint16 challenge_length; +// ... +// +class SSL2 : public DetectPolicy +{ +public: + typedef int arg_type; + + explicit SSL2 (arg_type const&) + { + } + + enum + { + bytesNeeded = 3 + }; + + std::size_t needed () + { + return bytesNeeded; + } + + template + void analyze (ConstBufferSequence const& buffer) + { + Input in (buffer); + + { + uint8 byte; + if (! in.peek (&byte)) + return; + + // First byte must have the high bit set + // + if((byte & 0x80) != 0x80) + return fail (); + } + + // The remaining bits contain the + // length of the following data in bytes. + // + uint16 msg_length; + if (! in.readNetworkInteger(&msg_length)) + return; + + // sizeof (msg_type + + // Version (ProtcolVersion?) + + // cipher_spec_length + + // session_id_length + + // challenge_length) + // + // Should be 9 or greater. + // + if (msg_length < 9) + return fail (); + + uint8 msg_type; + if (! in.read (&msg_type)) + return; + + // The msg_type must be 0x01 for a version 2 ClientHello + // + if (msg_type != 0x01) + return fail (); + + conclude (); + } +}; + +// Handshake for SSL 3 (Also TLS 1.0 and 1.1) +// +// http://www.ietf.org/rfc/rfc2246.txt +// +// Section 7.4. Handshake protocol +// +class SSL3 : public DetectPolicy +{ +public: + typedef int arg_type; // dummy + + explicit SSL3 (arg_type const&) + { + } + + enum + { + bytesNeeded = 6 + }; + + std::size_t needed () + { + return bytesNeeded; + } + + template + void analyze (ConstBufferSequence const& buffer) + { + uint16 version; + Input in (buffer); + + uint8 msg_type; + if (! in.read (&msg_type)) + return; + + // msg_type must be 0x16 = "SSL Handshake" + // + if (msg_type != 0x16) + return fail (); + + if (! in.read (&version)) + return; + version = fromNetworkByteOrder (version); + + uint16 length; + if (! in.read (&length)) + return; + + length = fromNetworkByteOrder (length); + + conclude (); + } +}; + +//-------------------------------------------------------------------------- + +template +class HandshakeDetectorType +{ +public: + typedef typename Logic::arg_type arg_type; + + explicit HandshakeDetectorType (arg_type const& arg = arg_type ()) + : m_logic (arg) + { + } + + std::size_t needed () noexcept + { + return m_logic.needed (); + } + + bool finished () noexcept + { + return m_logic.finished (); + } + + /** If finished is true, this tells us if the handshake was detected. + */ + bool success () noexcept + { + return m_logic.success (); + } + + /** Analyze the buffer to match the Handshake. + Returns `true` if the analysis is complete. + */ + template + bool analyze (ConstBufferSequence const& buffer) + { + bassert (! m_logic.finished ()); + m_logic.analyze (buffer); + return m_logic.finished (); + } + +private: + Logic m_logic; +}; + +#endif diff --git a/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.cpp b/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.cpp new file mode 100644 index 0000000000..31d57f5deb --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.cpp @@ -0,0 +1,19 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + diff --git a/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.h b/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.h new file mode 100644 index 0000000000..7550e77655 --- /dev/null +++ b/Subtrees/beast/modules/beast_asio/protocol/beast_StreamHandshakeDetectorType.h @@ -0,0 +1,78 @@ +//------------------------------------------------------------------------------ +/* + This file is part of Beast: https://github.com/vinniefalco/Beast + Copyright 2013, Vinnie Falco + + Permission to use, copy, modify, and/or distribute this software for any + purpose with or without fee is hereby granted, provided that the above + copyright notice and this permission notice appear in all copies. + + THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + ANY SPECIAL , DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +*/ +//============================================================================== + +#ifndef BEAST_STREAMHANDSHAKEDETECTORTYPE_H_INCLUDED +#define BEAST_STREAMHANDSHAKEDETECTORTYPE_H_INCLUDED + +/** Wraps a HandshakeDetector and does the work on the Socket for you. +*/ +template +class StreamHandshakeDetectorType +{ +protected: + typedef boost::system::error_code error_code; + typedef StreamHandshakeDetectorType This; + +public: + typedef typename Detector::arg_type arg_type; + + explicit StreamHandshakeDetectorType (arg_type const& arg = arg_type ()) + { + } + + template + void async_handshake (Socket& socket, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler) + { +#if 0 + std::size_t const bytes = m_detector.needed (); +#if 1 + boost::asio::async_read (socket, m_buffer.prepare (bytes), boost::bind ( + &This::on_read , this, &socket, + handler, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); +#else + boost::asio::async_read (socket, m_buffer.prepare (bytes), boost::bind ( + &This::on_read2, this, + boost::asio::placeholders::error, boost::asio::placeholders::bytes_transferred)); +#endif +#endif + } + +protected: + template + void on_read (Socket* socket, BOOST_ASIO_MOVE_ARG(HandshakeHandler) handler, + error_code const& ec, std::size_t bytes_transferred) + { + m_buffer.commit (bytes_transferred); + + if (m_detector.analyze (m_buffer.data ())) + { + if (m_detector.success ()) + { + //socket->async_handshake (Socket::server, m_buffer.data (), handler); + } + } + } + +private: + Detector m_detector; + boost::asio::streambuf m_buffer; +}; + +#endif diff --git a/Subtrees/beast/modules/beast_asio/system/beast_BoostIncludes.h b/Subtrees/beast/modules/beast_asio/system/beast_BoostIncludes.h index 588fd45c26..917139a7d3 100644 --- a/Subtrees/beast/modules/beast_asio/system/beast_BoostIncludes.h +++ b/Subtrees/beast/modules/beast_asio/system/beast_BoostIncludes.h @@ -51,10 +51,14 @@ #include #if (BOOST_VERSION / 100) >= 1054 # define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 1 -# define BEAST_ASIO_HAS_FUTURE_RETURNS 1 +# ifndef BEAST_ASIO_HAS_FUTURE_RETURNS +# define BEAST_ASIO_HAS_FUTURE_RETURNS 1 +# endif #else # define BEAST_ASIO_HAS_BUFFEREDHANDSHAKE 0 -# define BEAST_ASIO_HAS_FUTURE_RETURNS 0 +# ifndef BEAST_ASIO_HAS_FUTURE_RETURNS +# define BEAST_ASIO_HAS_FUTURE_RETURNS 0 +# endif #endif #if ! BEAST_ASIO_HAS_FUTURE_RETURNS diff --git a/Subtrees/beast/modules/beast_asio/tests/beast_TestPeerLogicProxyClient.cpp b/Subtrees/beast/modules/beast_asio/tests/beast_TestPeerLogicProxyClient.cpp index fb57deaf55..36a37659ba 100644 --- a/Subtrees/beast/modules/beast_asio/tests/beast_TestPeerLogicProxyClient.cpp +++ b/Subtrees/beast/modules/beast_asio/tests/beast_TestPeerLogicProxyClient.cpp @@ -34,4 +34,3 @@ void TestPeerLogicProxyClient::on_pre_handshake () std::size_t const amount = boost::asio::write ( socket (), boost::asio::buffer (line), error ()); } -