mirror of
https://github.com/XRPLF/rippled.git
synced 2025-11-21 03:26:01 +00:00
Add ProxyHandshake
This commit is contained in:
@@ -301,6 +301,12 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="..\..\modules\ripple_app\network\ripple_ProxyHandshake.cpp">
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\modules\ripple_app\network\ripple_WSHandler.cpp">
|
<ClCompile Include="..\..\modules\ripple_app\network\ripple_WSHandler.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
||||||
@@ -998,12 +1004,6 @@
|
|||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\modules\ripple_net\protocol\ripple_ProxyProtocol.cpp">
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</ExcludedFromBuild>
|
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</ExcludedFromBuild>
|
|
||||||
</ClCompile>
|
|
||||||
<ClCompile Include="..\..\modules\ripple_net\ripple_net.cpp" />
|
<ClCompile Include="..\..\modules\ripple_net\ripple_net.cpp" />
|
||||||
<ClCompile Include="..\..\modules\ripple_websocket\autosocket\ripple_AutoSocket.cpp">
|
<ClCompile Include="..\..\modules\ripple_websocket\autosocket\ripple_AutoSocket.cpp">
|
||||||
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">true</ExcludedFromBuild>
|
||||||
@@ -1423,6 +1423,7 @@
|
|||||||
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_ProofOfWorkFactory.h" />
|
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_ProofOfWorkFactory.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_SerializedLedger.h" />
|
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_SerializedLedger.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_SerializedTransaction.h" />
|
<ClInclude Include="..\..\modules\ripple_app\misc\ripple_SerializedTransaction.h" />
|
||||||
|
<ClInclude Include="..\..\modules\ripple_app\network\ripple_ProxyHandshake.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_app\network\ripple_WSHandler.h" />
|
<ClInclude Include="..\..\modules\ripple_app\network\ripple_WSHandler.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_app\network\WSConnection.h" />
|
<ClInclude Include="..\..\modules\ripple_app\network\WSConnection.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_app\network\WSDoor.h" />
|
<ClInclude Include="..\..\modules\ripple_app\network\WSDoor.h" />
|
||||||
@@ -1563,7 +1564,6 @@
|
|||||||
<ClInclude Include="..\..\modules\ripple_net\basics\ripple_HttpsClient.h" />
|
<ClInclude Include="..\..\modules\ripple_net\basics\ripple_HttpsClient.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_net\basics\ripple_RPCServer.h" />
|
<ClInclude Include="..\..\modules\ripple_net\basics\ripple_RPCServer.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_net\basics\ripple_SNTPClient.h" />
|
<ClInclude Include="..\..\modules\ripple_net\basics\ripple_SNTPClient.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_net\protocol\ripple_ProxyProtocol.h" />
|
|
||||||
<ClInclude Include="..\..\modules\ripple_net\ripple_net.h" />
|
<ClInclude Include="..\..\modules\ripple_net\ripple_net.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_websocket\autosocket\ripple_AutoSocket.h" />
|
<ClInclude Include="..\..\modules\ripple_websocket\autosocket\ripple_AutoSocket.h" />
|
||||||
<ClInclude Include="..\..\modules\ripple_websocket\ripple_websocket.h" />
|
<ClInclude Include="..\..\modules\ripple_websocket\ripple_websocket.h" />
|
||||||
|
|||||||
@@ -160,9 +160,6 @@
|
|||||||
<Filter Include="[2] Build">
|
<Filter Include="[2] Build">
|
||||||
<UniqueIdentifier>{c69b07a2-44e5-4b06-99a9-81f5d137ea15}</UniqueIdentifier>
|
<UniqueIdentifier>{c69b07a2-44e5-4b06-99a9-81f5d137ea15}</UniqueIdentifier>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter Include="[1] Ripple\ripple_net\protocol">
|
|
||||||
<UniqueIdentifier>{f0308442-e7af-44d4-a76a-c91fbf685e10}</UniqueIdentifier>
|
|
||||||
</Filter>
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="..\..\Subtrees\sqlite\sqlite3.c">
|
<ClCompile Include="..\..\Subtrees\sqlite\sqlite3.c">
|
||||||
@@ -885,8 +882,8 @@
|
|||||||
<ClCompile Include="..\..\modules\ripple_app\main\ripple_FatalErrorReporter.cpp">
|
<ClCompile Include="..\..\modules\ripple_app\main\ripple_FatalErrorReporter.cpp">
|
||||||
<Filter>[1] Ripple\ripple_app\main</Filter>
|
<Filter>[1] Ripple\ripple_app\main</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
<ClCompile Include="..\..\modules\ripple_net\protocol\ripple_ProxyProtocol.cpp">
|
<ClCompile Include="..\..\modules\ripple_app\network\ripple_ProxyHandshake.cpp">
|
||||||
<Filter>[1] Ripple\ripple_net\protocol</Filter>
|
<Filter>[1] Ripple\ripple_app\network</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -1676,8 +1673,8 @@
|
|||||||
<ClInclude Include="..\..\BeastConfig.h">
|
<ClInclude Include="..\..\BeastConfig.h">
|
||||||
<Filter>[2] Build</Filter>
|
<Filter>[2] Build</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
<ClInclude Include="..\..\modules\ripple_net\protocol\ripple_ProxyProtocol.h">
|
<ClInclude Include="..\..\modules\ripple_app\network\ripple_ProxyHandshake.h">
|
||||||
<Filter>[1] Ripple\ripple_net\protocol</Filter>
|
<Filter>[1] Ripple\ripple_app\network</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ REMINDER: KEEP CHANGE LOG UP TO DATE
|
|||||||
Vinnie's List: Changes day to day, descending priority
|
Vinnie's List: Changes day to day, descending priority
|
||||||
(Items marked '*' can be handled by others.)
|
(Items marked '*' can be handled by others.)
|
||||||
|
|
||||||
|
- Emergency implement PROXY protcol
|
||||||
- Get rid of boost::filesystem
|
- Get rid of boost::filesystem
|
||||||
- Deeply create directories specified in config settings
|
- Deeply create directories specified in config settings
|
||||||
- Finish unit tests and code for Validators
|
- Finish unit tests and code for Validators
|
||||||
|
|||||||
371
modules/ripple_app/network/ripple_ProxyHandshake.cpp
Normal file
371
modules/ripple_app/network/ripple_ProxyHandshake.cpp
Normal file
@@ -0,0 +1,371 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
ProxyHandshake::ProxyHandshake (bool expectHandshake)
|
||||||
|
: m_status (expectHandshake ? statusHandshake : statusNone)
|
||||||
|
, m_gotCR (false)
|
||||||
|
{
|
||||||
|
m_buffer.preallocateBytes (maxVersion1Bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
ProxyHandshake::~ProxyHandshake ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
std::size_t ProxyHandshake::feed (void const* inputBuffer, size_t inputBytes)
|
||||||
|
{
|
||||||
|
std::size_t bytesConsumed = 0;
|
||||||
|
|
||||||
|
char const* p = static_cast <char const*> (inputBuffer);
|
||||||
|
|
||||||
|
if (m_status == statusHandshake)
|
||||||
|
{
|
||||||
|
if (! m_gotCR)
|
||||||
|
{
|
||||||
|
while (inputBytes > 0 && m_buffer.length () < maxVersion1Bytes - 1)
|
||||||
|
{
|
||||||
|
beast_wchar c = *p++;
|
||||||
|
++bytesConsumed;
|
||||||
|
--inputBytes;
|
||||||
|
m_buffer += c;
|
||||||
|
|
||||||
|
if (c == '\r')
|
||||||
|
{
|
||||||
|
m_gotCR = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else if (c == '\n')
|
||||||
|
{
|
||||||
|
m_status = statusFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_buffer.length () > maxVersion1Bytes - 1)
|
||||||
|
{
|
||||||
|
m_status = statusFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_status == statusHandshake)
|
||||||
|
{
|
||||||
|
if (inputBytes > 0 && m_gotCR)
|
||||||
|
{
|
||||||
|
bassert (m_buffer.length () < maxVersion1Bytes);
|
||||||
|
|
||||||
|
char const lf ('\n');
|
||||||
|
|
||||||
|
if (*p == lf)
|
||||||
|
{
|
||||||
|
++bytesConsumed;
|
||||||
|
--inputBytes;
|
||||||
|
m_buffer += lf;
|
||||||
|
|
||||||
|
parseLine ();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_status = statusFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return bytesConsumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProxyHandshake::parseLine ()
|
||||||
|
{
|
||||||
|
Version1 p;
|
||||||
|
|
||||||
|
bool success = p.parse (m_buffer.getCharPointer (), m_buffer.length ());
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
m_endpoints = p.endpoints;
|
||||||
|
m_status = statusOk;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
m_status = statusFailed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int ProxyHandshake::indexOfFirstNonNumber (String const& input)
|
||||||
|
{
|
||||||
|
bassert (input.length () > 0);
|
||||||
|
|
||||||
|
int i = 0;
|
||||||
|
for (; i < input.length (); ++i)
|
||||||
|
{
|
||||||
|
if (! CharacterFunctions::isDigit (input [i]))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxyHandshake::chop (String const& what, String& input)
|
||||||
|
{
|
||||||
|
if (input.startsWith (what))
|
||||||
|
{
|
||||||
|
input = input.substring (what.length ());
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxyHandshake::chopUInt (int* value, int limit, String& input)
|
||||||
|
{
|
||||||
|
if (input.length () <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
String const s = input.substring (0, indexOfFirstNonNumber (input));
|
||||||
|
|
||||||
|
if (s.length () <= 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
int const n = s.getIntValue ();
|
||||||
|
|
||||||
|
// Leading zeroes disallowed as per spec, to prevent confusion with octal
|
||||||
|
if (String (n) != s)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (n < 0 || n > limit)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
input = input.substring (s.length ());
|
||||||
|
|
||||||
|
*value = n;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
Proxy protocol lets us filter attackers by learning the source ip and port
|
||||||
|
|
||||||
|
1. Determine if we should use the proxy on a connection
|
||||||
|
- Port just for proxy protocol connections
|
||||||
|
- Filter on source IPs
|
||||||
|
|
||||||
|
2. Read a line from the connection to get the proxy information
|
||||||
|
|
||||||
|
3. Parse the line (human or binary?)
|
||||||
|
|
||||||
|
4. Code Interface to retrieve proxy information (ip/port) on connection
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
ProxyHandshake::Version1::Version1 ()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxyHandshake::IPv4::Addr::chop (String& input)
|
||||||
|
{
|
||||||
|
if (!ProxyHandshake::chopUInt (&a, 255, input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ProxyHandshake::chop (".", input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ProxyHandshake::chopUInt (&b, 255, input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ProxyHandshake::chop (".", input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ProxyHandshake::chopUInt (&c, 255, input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ProxyHandshake::chop (".", input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!ProxyHandshake::chopUInt (&d, 255, input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ProxyHandshake::Version1::parse (void const* headerData, size_t headerBytes)
|
||||||
|
{
|
||||||
|
String input (static_cast <CharPointer_UTF8::CharType const*> (headerData), headerBytes);
|
||||||
|
|
||||||
|
if (input.length () < 2)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (! input.endsWith ("\r\n"))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
input = input.dropLastCharacters (2);
|
||||||
|
|
||||||
|
if (! ProxyHandshake::chop ("PROXY ", input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (ProxyHandshake::chop ("UNKNOWN", input))
|
||||||
|
{
|
||||||
|
endpoints.proto = protoUnknown;
|
||||||
|
|
||||||
|
input = "";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (ProxyHandshake::chop ("TCP4 ", input))
|
||||||
|
{
|
||||||
|
endpoints.proto = protoTcp4;
|
||||||
|
|
||||||
|
if (! endpoints.ipv4.sourceAddr.chop (input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (! ProxyHandshake::chop (" ", input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (! endpoints.ipv4.destAddr.chop (input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (! ProxyHandshake::chop (" ", input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (! ProxyHandshake::chopUInt (&endpoints.ipv4.sourcePort, 65535, input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (! ProxyHandshake::chop (" ", input))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (! ProxyHandshake::chopUInt (&endpoints.ipv4.destPort, 65535, input))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else if (ProxyHandshake::chop ("TCP6 ", input))
|
||||||
|
{
|
||||||
|
endpoints.proto = protoTcp6;
|
||||||
|
|
||||||
|
//bassertfalse;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Can't have anything extra between the last port number and the CRLF
|
||||||
|
if (input.length () > 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
class ProxyHandshakeTests : public UnitTest
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProxyHandshakeTests () : UnitTest ("ProxyHandshake", "ripple", runManual)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string goodIpv4 ()
|
||||||
|
{
|
||||||
|
return "PROXY TCP4 255.255.255.255 255.255.255.255 65535 65535\r\n"; // 56 chars
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string goodIpv6 ()
|
||||||
|
{
|
||||||
|
return "PROXY TCP6 fffffffffffffffffffffffffffffffffffffff.fffffffffffffffffffffffffffffffffffffff 65535 65535\r\n";
|
||||||
|
//1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123 4 (104 chars)
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string goodUnknown ()
|
||||||
|
{
|
||||||
|
return "PROXY UNKNOWN\r\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string goodUnknownBig ()
|
||||||
|
{
|
||||||
|
return "PROXY UNKNOWN fffffffffffffffffffffffffffffffffffffff.fffffffffffffffffffffffffffffffffffffff 65535 65535\r\n";
|
||||||
|
//1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456 7 (107 chars)
|
||||||
|
}
|
||||||
|
|
||||||
|
void testHandshake (std::string const& s, bool shouldSucceed)
|
||||||
|
{
|
||||||
|
if (s.size () > 1)
|
||||||
|
{
|
||||||
|
ProxyHandshake h (true);
|
||||||
|
|
||||||
|
expect (h.getStatus () == ProxyHandshake::statusHandshake);
|
||||||
|
|
||||||
|
for (int i = 0; i < s.size () && h.getStatus () == ProxyHandshake::statusHandshake ; ++i)
|
||||||
|
{
|
||||||
|
std::size_t const bytesConsumed = h.feed (& s[i], 1);
|
||||||
|
|
||||||
|
if (i != s.size () - 1)
|
||||||
|
expect (h.getStatus () == ProxyHandshake::statusHandshake);
|
||||||
|
|
||||||
|
expect (bytesConsumed == 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shouldSucceed)
|
||||||
|
{
|
||||||
|
expect (h.getStatus () == ProxyHandshake::statusOk);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
expect (h.getStatus () == ProxyHandshake::statusFailed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bassertfalse;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void testVersion1String (std::string const& s, bool shouldSucceed)
|
||||||
|
{
|
||||||
|
ProxyHandshake::Version1 p;
|
||||||
|
|
||||||
|
if (shouldSucceed)
|
||||||
|
{
|
||||||
|
expect (p.parse (s.c_str (), s.size ()));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
unexpected (p.parse (s.c_str (), s.size ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 1; i < s.size () - 1; ++i)
|
||||||
|
{
|
||||||
|
String const partial = String (s).dropLastCharacters (i);
|
||||||
|
std::string ss (partial.toStdString ());
|
||||||
|
|
||||||
|
expect (! p.parse (ss.c_str (), ss.size ()));
|
||||||
|
}
|
||||||
|
|
||||||
|
testHandshake (s, shouldSucceed);
|
||||||
|
}
|
||||||
|
|
||||||
|
void testVersion1 ()
|
||||||
|
{
|
||||||
|
beginTestCase ("version1");
|
||||||
|
|
||||||
|
testVersion1String (goodIpv4 (), true);
|
||||||
|
testVersion1String (goodIpv6 (), false);
|
||||||
|
testVersion1String (goodUnknown (), true);
|
||||||
|
testVersion1String (goodUnknownBig (), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void runTest ()
|
||||||
|
{
|
||||||
|
testVersion1 ();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static ProxyHandshakeTests proxyHandshakeTests;
|
||||||
151
modules/ripple_app/network/ripple_ProxyHandshake.h
Normal file
151
modules/ripple_app/network/ripple_ProxyHandshake.h
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
//------------------------------------------------------------------------------
|
||||||
|
/*
|
||||||
|
Copyright (c) 2011-2013, OpenCoin, Inc.
|
||||||
|
*/
|
||||||
|
//==============================================================================
|
||||||
|
|
||||||
|
#ifndef RIPPLE_PROXYYHANDSHAKE_H_INCLUDED
|
||||||
|
#define RIPPLE_PROXYYHANDSHAKE_H_INCLUDED
|
||||||
|
|
||||||
|
/** PROXY protocol handshake state machine.
|
||||||
|
|
||||||
|
The PROXY Protocol:
|
||||||
|
http://haproxy.1wt.eu/download/1.5/doc/proxy-protocol.txt
|
||||||
|
*/
|
||||||
|
class ProxyHandshake
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Status of the handshake state machine. */
|
||||||
|
enum Status
|
||||||
|
{
|
||||||
|
statusNone, // No handshake expected
|
||||||
|
statusHandshake, // Handshake in progress
|
||||||
|
statusFailed, // Handshake failed
|
||||||
|
statusOk, // Handshake succeeded
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Proto
|
||||||
|
{
|
||||||
|
protoTcp4,
|
||||||
|
protoTcp6,
|
||||||
|
protoUnknown
|
||||||
|
};
|
||||||
|
|
||||||
|
/** PROXY information for IPv4 families. */
|
||||||
|
struct IPv4
|
||||||
|
{
|
||||||
|
struct Addr
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
int c;
|
||||||
|
int d;
|
||||||
|
|
||||||
|
bool chop (String& input);
|
||||||
|
};
|
||||||
|
|
||||||
|
Addr sourceAddr;
|
||||||
|
Addr destAddr;
|
||||||
|
int sourcePort;
|
||||||
|
int destPort;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** PROXY information for IPv6 families. */
|
||||||
|
struct IPv6
|
||||||
|
{
|
||||||
|
struct Addr
|
||||||
|
{
|
||||||
|
int a;
|
||||||
|
int b;
|
||||||
|
int c;
|
||||||
|
int d;
|
||||||
|
};
|
||||||
|
|
||||||
|
Addr sourceAddr;
|
||||||
|
Addr destAddr;
|
||||||
|
int sourcePort;
|
||||||
|
int destPort;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Fully decoded PROXY information. */
|
||||||
|
struct Endpoints
|
||||||
|
{
|
||||||
|
Endpoints ()
|
||||||
|
: proto (protoUnknown)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Proto proto;
|
||||||
|
IPv4 ipv4; // valid if proto == protoTcp4
|
||||||
|
IPv6 ipv6; // valid if proto == protoTcp6;
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Parser for PROXY version 1. */
|
||||||
|
struct Version1
|
||||||
|
{
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
// Maximum input buffer size needed, including a null
|
||||||
|
// terminator, as per the PROXY protocol specification.
|
||||||
|
maxBufferBytes = 108
|
||||||
|
};
|
||||||
|
|
||||||
|
Endpoints endpoints;
|
||||||
|
|
||||||
|
Version1 ();
|
||||||
|
|
||||||
|
/** Parse the header.
|
||||||
|
@param rawHeader a pointer to the header data
|
||||||
|
@return `true` If it was parsed successfully.
|
||||||
|
*/
|
||||||
|
bool parse (void const* headerData, size_t headerBytes);
|
||||||
|
};
|
||||||
|
|
||||||
|
//--------------------------------------------------------------------------
|
||||||
|
|
||||||
|
/** Create the handshake state.
|
||||||
|
If a handshake is expected, then it is required.
|
||||||
|
@param wantHandshake `false` to skip handshaking.
|
||||||
|
*/
|
||||||
|
explicit ProxyHandshake (bool expectHandshake = false);
|
||||||
|
|
||||||
|
~ProxyHandshake ();
|
||||||
|
|
||||||
|
inline Status getStatus () const noexcept
|
||||||
|
{
|
||||||
|
return m_status;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Endpoints const& getEndpoints () const noexcept
|
||||||
|
{
|
||||||
|
return m_endpoints;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Feed the handshaking state engine.
|
||||||
|
@return The number of bytes consumed in the input buffer.
|
||||||
|
*/
|
||||||
|
std::size_t feed (void const* inputBuffer, std::size_t inputBytes);
|
||||||
|
|
||||||
|
// Utility functions used by parsers
|
||||||
|
static int indexOfFirstNonNumber (String const& input);
|
||||||
|
static bool chop (String const& what, String& input);
|
||||||
|
static bool chopUInt (int* value, int limit, String& input);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void parseLine ();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
maxVersion1Bytes = 107 // including crlf, not including null term
|
||||||
|
};
|
||||||
|
|
||||||
|
Status m_status;
|
||||||
|
String m_buffer;
|
||||||
|
bool m_gotCR;
|
||||||
|
Endpoints m_endpoints;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -239,6 +239,8 @@ static const uint64 tenTo17m1 = tenTo17 - 1;
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
#include "network/ripple_ProxyHandshake.h" // private?
|
||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
#if ! defined (RIPPLE_MAIN_PART) || RIPPLE_MAIN_PART == 1
|
#if ! defined (RIPPLE_MAIN_PART) || RIPPLE_MAIN_PART == 1
|
||||||
@@ -326,6 +328,7 @@ static DH* handleTmpDh (SSL* ssl, int is_export, int iKeyLength)
|
|||||||
#include "tx/Transactor.cpp"
|
#include "tx/Transactor.cpp"
|
||||||
#include "network/WSConnection.cpp"
|
#include "network/WSConnection.cpp"
|
||||||
#include "network/WSDoor.cpp"
|
#include "network/WSDoor.cpp"
|
||||||
|
#include "network/ripple_ProxyHandshake.cpp"
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|||||||
@@ -25,6 +25,4 @@ namespace ripple
|
|||||||
#include "basics/ripple_RPCServer.cpp"
|
#include "basics/ripple_RPCServer.cpp"
|
||||||
#include "basics/ripple_SNTPClient.cpp"
|
#include "basics/ripple_SNTPClient.cpp"
|
||||||
|
|
||||||
#include "protocol/ripple_ProxyProtocol.cpp"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,8 +32,6 @@ namespace ripple
|
|||||||
#include "basics/ripple_RPCServer.h"
|
#include "basics/ripple_RPCServer.h"
|
||||||
#include "basics/ripple_SNTPClient.h"
|
#include "basics/ripple_SNTPClient.h"
|
||||||
|
|
||||||
#include "protocol/ripple_ProxyProtocol.h"
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
Reference in New Issue
Block a user