Skip to content
This repository was archived by the owner on Dec 20, 2023. It is now read-only.

Commit 5dfb14b

Browse files
emargolisrobszewczyk
authored andcommitted
Fix TCP Connection Denial-Of-Service (DOS) Vulnerability.
-- Configured a default idle time for inbound Weave TCP connections after which the idle connection will be destroyed. -- Limited the number of inbound Weave TCP connections. -- Limited the number of Weave TCP connections from single IP address. This change addresses CVE security vulnerability: CVE-2019-5043
1 parent 0445517 commit 5dfb14b

File tree

4 files changed

+96
-1
lines changed

4 files changed

+96
-1
lines changed

src/lib/core/WeaveConfig.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1012,6 +1012,37 @@
10121012
#define WEAVE_CONFIG_MAX_CONNECTIONS INET_CONFIG_NUM_TCP_ENDPOINTS
10131013
#endif // WEAVE_CONFIG_MAX_CONNECTIONS
10141014

1015+
/**
1016+
* @def WEAVE_CONFIG_MAX_INCOMING_TCP_CONNECTIONS
1017+
*
1018+
* @brief
1019+
* Maximum number of simultaneously active inbound TCP connections.
1020+
*
1021+
* Regardless of what #WEAVE_CONFIG_MAX_INCOMING_TCP_CONNECTIONS
1022+
* is set to, the total number of inbound connections cannot exceed
1023+
* #WEAVE_CONFIG_MAX_CONNECTIONS, which is the overall limit for
1024+
* inbound and outbound connections.
1025+
*/
1026+
#ifndef WEAVE_CONFIG_MAX_INCOMING_TCP_CONNECTIONS
1027+
#define WEAVE_CONFIG_MAX_INCOMING_TCP_CONNECTIONS (WEAVE_CONFIG_MAX_CONNECTIONS * 4 / 5)
1028+
#endif // WEAVE_CONFIG_MAX_INCOMING_TCP_CONNECTIONS
1029+
1030+
/**
1031+
* @def WEAVE_CONFIG_MAX_INCOMING_TCP_CON_FROM_SINGLE_IP
1032+
*
1033+
* @brief
1034+
* Maximum number of simultaneously active inbound TCP connections
1035+
* from the single IP address.
1036+
*
1037+
* Regardless of what #WEAVE_CONFIG_MAX_INCOMING_TCP_CON_FROM_SINGLE_IP
1038+
* is set to, the total number of inbound connections from a single IP
1039+
* address cannot exceed #WEAVE_CONFIG_MAX_CONNECTIONS or
1040+
* #WEAVE_CONFIG_MAX_INCOMING_TCP_CONNECTIONS.
1041+
*/
1042+
#ifndef WEAVE_CONFIG_MAX_INCOMING_TCP_CON_FROM_SINGLE_IP
1043+
#define WEAVE_CONFIG_MAX_INCOMING_TCP_CON_FROM_SINGLE_IP 2
1044+
#endif // WEAVE_CONFIG_MAX_INCOMING_TCP_CON_FROM_SINGLE_IP
1045+
10151046
/**
10161047
* @def WEAVE_CONFIG_MAX_TUNNELS
10171048
*
@@ -1836,6 +1867,18 @@
18361867
#define WEAVE_CONFIG_SERVICE_DIR_CONNECT_TIMEOUT_MSECS (10000)
18371868
#endif // WEAVE_CONFIG_SERVICE_DIR_CONNECT_TIMEOUT_MSECS
18381869

1870+
/**
1871+
* @def WEAVE_CONFIG_DEFAULT_INCOMING_CONNECTION_IDLE_TIMEOUT
1872+
*
1873+
* @brief
1874+
* The default minimum amount of time, in milliseconds, that an inbound idle
1875+
* connection will be allowed to exist before being destroyed.
1876+
*
1877+
*/
1878+
#ifndef WEAVE_CONFIG_DEFAULT_INCOMING_CONNECTION_IDLE_TIMEOUT
1879+
#define WEAVE_CONFIG_DEFAULT_INCOMING_CONNECTION_IDLE_TIMEOUT 15000
1880+
#endif // WEAVE_CONFIG_DEFAULT_INCOMING_CONNECTION_IDLE_TIMEOUT
1881+
18391882
/**
18401883
* @def WEAVE_CONFIG_MSG_COUNTER_SYNC_RESP_TIMEOUT
18411884
*

src/lib/core/WeaveConnection.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1635,6 +1635,7 @@ void WeaveConnection::Init(WeaveMessageLayer *msgLayer)
16351635
#if WEAVE_CONFIG_ENABLE_DNS_RESOLVER
16361636
mDNSOptions = 0;
16371637
#endif
1638+
mFlags = 0;
16381639
}
16391640

16401641
// Default OnConnectionClosed handler.

src/lib/core/WeaveMessageLayer.cpp

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,7 @@ WEAVE_ERROR WeaveMessageLayer::Init(InitContext *context)
152152
ExchangeMgr = NULL;
153153
SecurityMgr = NULL;
154154
IsListening = context->listenTCP || context->listenUDP;
155-
IncomingConIdleTimeout = 0;
155+
IncomingConIdleTimeout = WEAVE_CONFIG_DEFAULT_INCOMING_CONNECTION_IDLE_TIMEOUT;
156156

157157
//Internal and for Debug Only; When set, Message Layer drops message and returns.
158158
mDropMessage = false;
@@ -773,6 +773,27 @@ WeaveConnection *WeaveMessageLayer::NewConnection()
773773
return NULL;
774774
}
775775

776+
void WeaveMessageLayer::GetIncomingTCPConCount(const IPAddress &peerAddr, uint16_t &count, uint16_t &countFromIP)
777+
{
778+
count = 0;
779+
countFromIP = 0;
780+
781+
WeaveConnection *con = (WeaveConnection *) mConPool;
782+
for (int i = 0; i < WEAVE_CONFIG_MAX_CONNECTIONS; i++, con++)
783+
{
784+
if (con->mRefCount > 0 &&
785+
con->NetworkType == WeaveConnection::kNetworkType_IP &&
786+
con->IsIncoming())
787+
{
788+
count++;
789+
if (con->PeerAddr == peerAddr)
790+
{
791+
countFromIP++;
792+
}
793+
}
794+
}
795+
}
796+
776797
/**
777798
* Create a new WeaveConnectionTunnel object from a pool.
778799
*
@@ -1631,6 +1652,9 @@ void WeaveMessageLayer::HandleIncomingBleConnection(BLEEndPoint *bleEP)
16311652
// Set the default idle timeout.
16321653
con->SetIdleTimeout(msgLayer->IncomingConIdleTimeout);
16331654

1655+
// Set incoming connection flag.
1656+
con->SetIncoming(true);
1657+
16341658
// If the exchange manager has been initialized, call its callback.
16351659
if (msgLayer->ExchangeMgr != NULL)
16361660
msgLayer->ExchangeMgr->HandleConnectionReceived(con);
@@ -1646,6 +1670,8 @@ void WeaveMessageLayer::HandleIncomingTcpConnection(TCPEndPoint *listeningEP, TC
16461670
INET_ERROR err;
16471671
IPAddress localAddr;
16481672
uint16_t localPort;
1673+
uint16_t incomingTCPConCount;
1674+
uint16_t incomingTCPConCountFromIP;
16491675
WeaveMessageLayer *msgLayer = (WeaveMessageLayer *) listeningEP->AppState;
16501676

16511677
// Immediately close the connection if there's no callback registered.
@@ -1657,6 +1683,17 @@ void WeaveMessageLayer::HandleIncomingTcpConnection(TCPEndPoint *listeningEP, TC
16571683
return;
16581684
}
16591685

1686+
// Fail if too many incoming TCP connections.
1687+
msgLayer->GetIncomingTCPConCount(peerAddr, incomingTCPConCount, incomingTCPConCountFromIP);
1688+
if (incomingTCPConCount == WEAVE_CONFIG_MAX_INCOMING_TCP_CONNECTIONS ||
1689+
incomingTCPConCountFromIP == WEAVE_CONFIG_MAX_INCOMING_TCP_CON_FROM_SINGLE_IP)
1690+
{
1691+
conEP->Free();
1692+
if (msgLayer->OnAcceptError != NULL)
1693+
msgLayer->OnAcceptError(msgLayer, WEAVE_ERROR_TOO_MANY_CONNECTIONS);
1694+
return;
1695+
}
1696+
16601697
// Attempt to allocate a connection object. Fail if too many connections.
16611698
WeaveConnection *con = msgLayer->NewConnection();
16621699
if (con == NULL)
@@ -1691,6 +1728,9 @@ void WeaveMessageLayer::HandleIncomingTcpConnection(TCPEndPoint *listeningEP, TC
16911728
// Set the default idle timeout.
16921729
con->SetIdleTimeout(msgLayer->IncomingConIdleTimeout);
16931730

1731+
// Set incoming connection flag.
1732+
con->SetIncoming(true);
1733+
16941734
// If the exchange manager has been initialized, call its callback.
16951735
if (msgLayer->ExchangeMgr != NULL)
16961736
msgLayer->ExchangeMgr->HandleConnectionReceived(con);

src/lib/core/WeaveMessageLayer.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,9 @@ class WeaveConnection
364364
typedef void (*ReceiveErrorFunct)(WeaveConnection *con, WEAVE_ERROR err);
365365
ReceiveErrorFunct OnReceiveError;
366366

367+
bool IsIncoming(void) const { return GetFlag(mFlags, kFlag_IsIncoming); }
368+
void SetIncoming(bool val) { SetFlag(mFlags, kFlag_IsIncoming, val); }
369+
367370
private:
368371
enum
369372
{
@@ -381,6 +384,13 @@ class WeaveConnection
381384
uint8_t mDNSOptions;
382385
#endif
383386

387+
enum FlagsEnum
388+
{
389+
kFlag_IsIncoming = 0x01, /**< The connection was initiated by external node. */
390+
};
391+
392+
uint8_t mFlags; /**< Various flags associated with the connection. */
393+
384394
void Init(WeaveMessageLayer *msgLayer);
385395
void MakeConnectedTcp(TCPEndPoint *endPoint, const IPAddress &localAddr, const IPAddress &peerAddr);
386396
WEAVE_ERROR StartConnect(void);
@@ -734,6 +744,7 @@ class NL_DLL_EXPORT WeaveMessageLayer
734744
uint16_t maxLen);
735745
WEAVE_ERROR DecodeMessageWithLength(PacketBuffer *msgBuf, uint64_t sourceNodeId, WeaveConnection *con,
736746
WeaveMessageInfo *msgInfo, uint8_t **rPayload, uint16_t *rPayloadLen, uint32_t *rFrameLen);
747+
void GetIncomingTCPConCount(const IPAddress &peerAddr, uint16_t &count, uint16_t &countFromIP);
737748

738749
static void HandleUDPMessage(UDPEndPoint *endPoint, PacketBuffer *msg, const IPPacketInfo *pktInfo);
739750
static void HandleUDPReceiveError(UDPEndPoint *endPoint, INET_ERROR err, const IPPacketInfo *pktInfo);

0 commit comments

Comments
 (0)