1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-15 15:53:55 +00:00

Added WebServer protections against Malformed packets, invalid content-length, and overly large headers.

This commit is contained in:
Bryan Roe
2019-03-26 01:05:27 -07:00
parent 57a9de8a03
commit 65ebe45873
3 changed files with 69 additions and 14 deletions

View File

@@ -538,7 +538,10 @@ void ILibWebClient_TimerInterruptSink(void *object)
{ {
UNREFERENCED_PARAMETER( object ); UNREFERENCED_PARAMETER( object );
} }
int ILibWebClient_IsFinHeader(ILibWebClient_StateObject wcdo)
{
return(((ILibWebClientDataObject*)wcdo)->FinHeader);
}
void ILibWebClient_ResetWCDO(struct ILibWebClientDataObject *wcdo) void ILibWebClient_ResetWCDO(struct ILibWebClientDataObject *wcdo)
{ {
ILibWebClient_RequestToken rt = NULL; ILibWebClient_RequestToken rt = NULL;
@@ -1485,7 +1488,7 @@ void ILibWebClient_OnWebSocketData(ILibAsyncSocket_SocketModule socketModule, ch
// <param name="InterruptPtr">Function Pointer that triggers when a connection is interrupted</param> // <param name="InterruptPtr">Function Pointer that triggers when a connection is interrupted</param>
// <param name="user">User data that can be set/received</param> // <param name="user">User data that can be set/received</param>
// <param name="PAUSE">Flag to tell the underlying socket to pause reading data</param> // <param name="PAUSE">Flag to tell the underlying socket to pause reading data</param>
void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffer, int *p_beginPointer, int endPointer, void (**InterruptPtr)(void *socketModule, void *user), void **user, int *PAUSE) ILibWebClient_DataResults ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffer, int *p_beginPointer, int endPointer, void (**InterruptPtr)(void *socketModule, void *user), void **user, int *PAUSE)
{ {
struct ILibWebClientDataObject *wcdo = (struct ILibWebClientDataObject*)(*user); struct ILibWebClientDataObject *wcdo = (struct ILibWebClientDataObject*)(*user);
struct ILibWebRequest *wr; struct ILibWebRequest *wr;
@@ -1502,8 +1505,8 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
//char *tempPath; //char *tempPath;
//unsigned short tempPort; //unsigned short tempPort;
if (wcdo == NULL || wcdo->RequestQueue == NULL) return; if (wcdo == NULL || wcdo->RequestQueue == NULL) return(ILibWebClient_DataResults_OK);
if (wcdo->IsWebSocket != 0 && wcdo->Server == 0) { ILibWebClient_OnWebSocketData(socketModule, buffer, p_beginPointer, endPointer, InterruptPtr, user, PAUSE); return; } if (wcdo->IsWebSocket != 0 && wcdo->Server == 0) { ILibWebClient_OnWebSocketData(socketModule, buffer, p_beginPointer, endPointer, InterruptPtr, user, PAUSE); return(ILibWebClient_DataResults_OK); }
if (wcdo->Server == 0) if (wcdo->Server == 0)
{ {
@@ -1525,7 +1528,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
// of the time, it means the remote endpoint is sending invalid packets. // of the time, it means the remote endpoint is sending invalid packets.
// //
*p_beginPointer = endPointer; *p_beginPointer = endPointer;
return; return(ILibWebClient_DataResults_OK);
} }
if (wcdo->FinHeader == 0) if (wcdo->FinHeader == 0)
{ {
@@ -1589,6 +1592,11 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
} }
if (wcdo->header != NULL) if (wcdo->header != NULL)
{ {
if (wcdo->header->Directive == NULL && wcdo->header->StatusCode != -1 && wcdo->Server != 0)
{
return(ILibWebClient_DataResults_InvalidRequest); // We're a server, but we received a Response Packet...
}
// //
// Check to see if this has an absolute path. Might be able to convert it // Check to see if this has an absolute path. Might be able to convert it
// for easier processing // for easier processing
@@ -1654,6 +1662,11 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
wcdo->WaitForClose = 0; wcdo->WaitForClose = 0;
phfn->FieldData[phfn->FieldDataLength] = '\0'; phfn->FieldData[phfn->FieldDataLength] = '\0';
wcdo->BytesLeft = atoi(phfn->FieldData); wcdo->BytesLeft = atoi(phfn->FieldData);
if (wcdo->BytesLeft < 0)
{
wcdo->BytesLeft = 0;
return(ILibWebClient_DataResults_InvalidContentLength);
}
} }
phfn = phfn->NextField; phfn = phfn->NextField;
} }
@@ -1680,7 +1693,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
int zro = 0; int zro = 0;
if (wr->OnResponse != NULL) { wr->OnResponse(wcdo, 0, wcdo->header, NULL, &zro, 0, ILibWebClient_ReceiveStatus_Connection_Established, wr->user1, wr->user2, &(wcdo->PAUSE)); } if (wr->OnResponse != NULL) { wr->OnResponse(wcdo, 0, wcdo->header, NULL, &zro, 0, ILibWebClient_ReceiveStatus_Connection_Established, wr->user1, wr->user2, &(wcdo->PAUSE)); }
*p_beginPointer += wcdo->HeaderLength; *p_beginPointer += wcdo->HeaderLength;
return; return(ILibWebClient_DataResults_OK);
} }
else if (wcdo->header->StatusCode == 101 && wr->requestToken->WebSocketKey != NULL) else if (wcdo->header->StatusCode == 101 && wr->requestToken->WebSocketKey != NULL)
{ {
@@ -1700,14 +1713,14 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
if (wr->OnResponse != NULL) { wr->OnResponse(wcdo, 0, wcdo->header, NULL, &zro, 0, ILibWebClient_ReceiveStatus_Connection_Established, wr->user1, wr->user2, &(wcdo->PAUSE)); } if (wr->OnResponse != NULL) { wr->OnResponse(wcdo, 0, wcdo->header, NULL, &zro, 0, ILibWebClient_ReceiveStatus_Connection_Established, wr->user1, wr->user2, &(wcdo->PAUSE)); }
*p_beginPointer += hdrLen; *p_beginPointer += hdrLen;
return; return(ILibWebClient_DataResults_OK);
} }
else else
{ {
// WebSocket Handshake Error... Unrecoverable, Abort connection // WebSocket Handshake Error... Unrecoverable, Abort connection
ILibWebClient_Disconnect(wcdo); ILibWebClient_Disconnect(wcdo);
ILibWebClient_DestroyWebClientDataObject(wcdo); // We are destroying here, because WebSockets have independent WCDO objects ILibWebClient_DestroyWebClientDataObject(wcdo); // We are destroying here, because WebSockets have independent WCDO objects
return; return(ILibWebClient_DataResults_OK);
} }
} }
if (wr->streamedState == NULL) if (wr->streamedState == NULL)
@@ -1897,14 +1910,14 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
// VIOLATION of the http specification. // VIOLATION of the http specification.
// //
*p_beginPointer = i + 4; *p_beginPointer = i + 4;
return; return(ILibWebClient_DataResults_OK);
} }
if (socketModule != NULL && ILibAsyncSocket_IsFree(socketModule)!=0) if (socketModule != NULL && ILibAsyncSocket_IsFree(socketModule)!=0)
{ {
// //
// The user closed the socket, so just return // The user closed the socket, so just return
// //
return; return(ILibWebClient_DataResults_OK);
} }
} }
@@ -2011,6 +2024,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
// //
*PAUSE = wcdo->PAUSE; *PAUSE = wcdo->PAUSE;
} }
return(ILibWebClient_DataResults_OK);
} }
// //
@@ -2506,7 +2520,7 @@ ILibWebClient_RequestManager ILibCreateWebClient(int PoolSize, void *Chain)
RetVal->socks[i] = ILibCreateAsyncSocketModule( RetVal->socks[i] = ILibCreateAsyncSocketModule(
Chain, Chain,
INITIAL_BUFFER_SIZE, INITIAL_BUFFER_SIZE,
&ILibWebClient_OnData, (ILibAsyncSocket_OnData)&ILibWebClient_OnData,
&ILibWebClient_OnConnect, &ILibWebClient_OnConnect,
&ILibWebClient_OnDisconnectSink, &ILibWebClient_OnDisconnectSink,
&ILibWebClient_OnSendOKSink); &ILibWebClient_OnSendOKSink);

View File

@@ -172,11 +172,18 @@ typedef int(*ILibWebClient_OnHttpsConnection)(ILibWebClient_RequestToken sender,
extern const int ILibMemory_WebClient_RequestToken_CONTAINERSIZE; extern const int ILibMemory_WebClient_RequestToken_CONTAINERSIZE;
typedef enum ILibWebClient_DataResults
{
ILibWebClient_DataResults_OK = 0,
ILibWebClient_DataResults_InvalidRequest = 400,
ILibWebClient_DataResults_InvalidContentLength = 4001
}ILibWebClient_DataResults;
ILibWebClient_RequestManager ILibCreateWebClient(int PoolSize, void *Chain); ILibWebClient_RequestManager ILibCreateWebClient(int PoolSize, void *Chain);
ILibWebClient_StateObject ILibCreateWebClientEx(ILibWebClient_OnResponse OnResponse, ILibAsyncSocket_SocketModule socketModule, void *user1, void *user2); ILibWebClient_StateObject ILibCreateWebClientEx(ILibWebClient_OnResponse OnResponse, ILibAsyncSocket_SocketModule socketModule, void *user1, void *user2);
void ILibWebClient_OnBufferReAllocate(ILibAsyncSocket_SocketModule token, void *user, ptrdiff_t offSet); void ILibWebClient_OnBufferReAllocate(ILibAsyncSocket_SocketModule token, void *user, ptrdiff_t offSet);
void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule,char* buffer,int *p_beginPointer, int endPointer,ILibAsyncSocket_OnInterrupt *InterruptPtr, void **user, int *PAUSE); ILibWebClient_DataResults ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule,char* buffer,int *p_beginPointer, int endPointer,ILibAsyncSocket_OnInterrupt *InterruptPtr, void **user, int *PAUSE);
void ILibDestroyWebClient(void *object); void ILibDestroyWebClient(void *object);
void ILibWebClient_DestroyWebClientDataObject(ILibWebClient_StateObject token); void ILibWebClient_DestroyWebClientDataObject(ILibWebClient_StateObject token);
@@ -240,6 +247,7 @@ void ILibWebClient_Pause(ILibWebClient_StateObject wcdo);
void ILibWebClient_Disconnect(ILibWebClient_StateObject wcdo); void ILibWebClient_Disconnect(ILibWebClient_StateObject wcdo);
void ILibWebClient_CancelRequest(ILibWebClient_RequestToken RequestToken); void ILibWebClient_CancelRequest(ILibWebClient_RequestToken RequestToken);
void ILibWebClient_ResetUserObjects(ILibWebClient_StateObject webstate, void *user1, void *user2); void ILibWebClient_ResetUserObjects(ILibWebClient_StateObject webstate, void *user1, void *user2);
int ILibWebClient_IsFinHeader(ILibWebClient_StateObject wcdo);
ILibWebClient_RequestToken ILibWebClient_GetRequestToken_FromStateObject(ILibWebClient_StateObject WebStateObject); ILibWebClient_RequestToken ILibWebClient_GetRequestToken_FromStateObject(ILibWebClient_StateObject WebStateObject);
ILibWebClient_StateObject ILibWebClient_GetStateObjectFromRequestToken(ILibWebClient_RequestToken token); ILibWebClient_StateObject ILibWebClient_GetStateObjectFromRequestToken(ILibWebClient_RequestToken token);
void **ILibWebClient_RequestToken_GetUserObjects(ILibWebClient_RequestToken tok); void **ILibWebClient_RequestToken_GetUserObjects(ILibWebClient_RequestToken tok);

View File

@@ -760,7 +760,29 @@ void ILibWebServer_OnReceive(void *AsyncServerSocketModule, void *ConnectionToke
if (ILibWebServer_Session_GetSystemData(ws)->WebSocket_Request == NULL) if (ILibWebServer_Session_GetSystemData(ws)->WebSocket_Request == NULL)
{ {
// Normal HTTP Processing Rules // Normal HTTP Processing Rules
ILibWebClient_OnData(ConnectionToken, buffer, p_beginPointer, endPointer, NULL, &(ILibWebServer_Session_GetSystemData(ws)->WebClientDataObject), PAUSE); ILibWebClient_DataResults r;
int pbp = *p_beginPointer;
switch ((r = ILibWebClient_OnData(ConnectionToken, buffer, p_beginPointer, endPointer, NULL, &(ILibWebServer_Session_GetSystemData(ws)->WebClientDataObject), PAUSE)))
{
case ILibWebClient_DataResults_OK:
if (*p_beginPointer == pbp && (endPointer - pbp >= 4096) && ILibWebClient_IsFinHeader(ILibWebServer_Session_GetSystemData(ws)->WebClientDataObject) == 0)
{
// The headers is > 4k
ILibWebServer_Session_GetSystemData(ws)->CloseOverrideFlag = 1; // This will force close the socket when done
ILibWebServer_Send_Raw(ws, "HTTP/1.1 431 Header size too big\r\nConnection: close\r\n\r\n", 55, ILibAsyncSocket_MemoryOwnership_STATIC, ILibWebServer_DoneFlag_Done);
}
break;
case ILibWebClient_DataResults_InvalidRequest:
ILibWebServer_Session_GetSystemData(ws)->CloseOverrideFlag = 1; // This will force close the socket when done
ILibWebServer_Send_Raw(ws, "HTTP/1.1 400 Bad Request\r\nConnection: close\r\n\r\n", 47, ILibAsyncSocket_MemoryOwnership_STATIC, ILibWebServer_DoneFlag_Done);
break;
case ILibWebClient_DataResults_InvalidContentLength:
ILibWebServer_Session_GetSystemData(ws)->CloseOverrideFlag = 1; // This will force close the socket when done
ILibWebServer_Send_Raw(ws, "HTTP/1.1 400 Invalid content length\r\nConnection: close\r\n\r\n", 58, ILibAsyncSocket_MemoryOwnership_STATIC, ILibWebServer_DoneFlag_Done);
break;
default:
break;
}
} }
else else
{ {
@@ -801,7 +823,18 @@ enum ILibWebServer_Status ILibWebServer_RequestAnswered(struct ILibWebServer_Ses
ILibRemoteLogging_printf(ILibChainGetLogger(session->Reserved_Transport.ChainLink.ParentChain), ILibRemoteLogging_Modules_Microstack_Web, ILibRemoteLogging_Flags_VerbosityLevel_1, "WebSession[%p] (Request Answered)", (void*)session); ILibRemoteLogging_printf(ILibChainGetLogger(session->Reserved_Transport.ChainLink.ParentChain), ILibRemoteLogging_Modules_Microstack_Web, ILibRemoteLogging_Flags_VerbosityLevel_1, "WebSession[%p] (Request Answered)", (void*)session);
if (hdr == NULL) return ILibWebServer_ALL_DATA_SENT; if (hdr == NULL)
{
if (ILibWebServer_Session_GetSystemData(session)->CloseOverrideFlag != 0)
{
ILibLifeTime_Add(((struct ILibWebServer_StateModule*)session->Parent)->LifeTime, ILibWebServer_Session_GetSystemData(session)->ConnectionToken, 0, &ILibAsyncSocket_Disconnect, NULL);
return(ILibWebServer_SEND_RESULTED_IN_DISCONNECT);
}
else
{
return ILibWebServer_ALL_DATA_SENT;
}
}
// //
// Virtual Directory State Object // Virtual Directory State Object