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:
@@ -538,7 +538,10 @@ void ILibWebClient_TimerInterruptSink(void *object)
|
||||
{
|
||||
UNREFERENCED_PARAMETER( object );
|
||||
}
|
||||
|
||||
int ILibWebClient_IsFinHeader(ILibWebClient_StateObject wcdo)
|
||||
{
|
||||
return(((ILibWebClientDataObject*)wcdo)->FinHeader);
|
||||
}
|
||||
void ILibWebClient_ResetWCDO(struct ILibWebClientDataObject *wcdo)
|
||||
{
|
||||
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="user">User data that can be set/received</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 ILibWebRequest *wr;
|
||||
@@ -1502,8 +1505,8 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
|
||||
//char *tempPath;
|
||||
//unsigned short tempPort;
|
||||
|
||||
if (wcdo == NULL || wcdo->RequestQueue == NULL) return;
|
||||
if (wcdo->IsWebSocket != 0 && wcdo->Server == 0) { ILibWebClient_OnWebSocketData(socketModule, buffer, p_beginPointer, endPointer, InterruptPtr, user, PAUSE); 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(ILibWebClient_DataResults_OK); }
|
||||
|
||||
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.
|
||||
//
|
||||
*p_beginPointer = endPointer;
|
||||
return;
|
||||
return(ILibWebClient_DataResults_OK);
|
||||
}
|
||||
if (wcdo->FinHeader == 0)
|
||||
{
|
||||
@@ -1589,6 +1592,11 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
|
||||
}
|
||||
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
|
||||
// for easier processing
|
||||
@@ -1654,6 +1662,11 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
|
||||
wcdo->WaitForClose = 0;
|
||||
phfn->FieldData[phfn->FieldDataLength] = '\0';
|
||||
wcdo->BytesLeft = atoi(phfn->FieldData);
|
||||
if (wcdo->BytesLeft < 0)
|
||||
{
|
||||
wcdo->BytesLeft = 0;
|
||||
return(ILibWebClient_DataResults_InvalidContentLength);
|
||||
}
|
||||
}
|
||||
phfn = phfn->NextField;
|
||||
}
|
||||
@@ -1680,7 +1693,7 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
|
||||
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)); }
|
||||
*p_beginPointer += wcdo->HeaderLength;
|
||||
return;
|
||||
return(ILibWebClient_DataResults_OK);
|
||||
}
|
||||
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)); }
|
||||
*p_beginPointer += hdrLen;
|
||||
return;
|
||||
return(ILibWebClient_DataResults_OK);
|
||||
}
|
||||
else
|
||||
{
|
||||
// WebSocket Handshake Error... Unrecoverable, Abort connection
|
||||
ILibWebClient_Disconnect(wcdo);
|
||||
ILibWebClient_DestroyWebClientDataObject(wcdo); // We are destroying here, because WebSockets have independent WCDO objects
|
||||
return;
|
||||
return(ILibWebClient_DataResults_OK);
|
||||
}
|
||||
}
|
||||
if (wr->streamedState == NULL)
|
||||
@@ -1897,14 +1910,14 @@ void ILibWebClient_OnData(ILibAsyncSocket_SocketModule socketModule, char* buffe
|
||||
// VIOLATION of the http specification.
|
||||
//
|
||||
*p_beginPointer = i + 4;
|
||||
return;
|
||||
return(ILibWebClient_DataResults_OK);
|
||||
}
|
||||
if (socketModule != NULL && ILibAsyncSocket_IsFree(socketModule)!=0)
|
||||
{
|
||||
//
|
||||
// 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;
|
||||
}
|
||||
return(ILibWebClient_DataResults_OK);
|
||||
}
|
||||
|
||||
//
|
||||
@@ -2506,7 +2520,7 @@ ILibWebClient_RequestManager ILibCreateWebClient(int PoolSize, void *Chain)
|
||||
RetVal->socks[i] = ILibCreateAsyncSocketModule(
|
||||
Chain,
|
||||
INITIAL_BUFFER_SIZE,
|
||||
&ILibWebClient_OnData,
|
||||
(ILibAsyncSocket_OnData)&ILibWebClient_OnData,
|
||||
&ILibWebClient_OnConnect,
|
||||
&ILibWebClient_OnDisconnectSink,
|
||||
&ILibWebClient_OnSendOKSink);
|
||||
|
||||
@@ -172,11 +172,18 @@ typedef int(*ILibWebClient_OnHttpsConnection)(ILibWebClient_RequestToken sender,
|
||||
|
||||
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_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_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 ILibWebClient_DestroyWebClientDataObject(ILibWebClient_StateObject token);
|
||||
@@ -240,6 +247,7 @@ void ILibWebClient_Pause(ILibWebClient_StateObject wcdo);
|
||||
void ILibWebClient_Disconnect(ILibWebClient_StateObject wcdo);
|
||||
void ILibWebClient_CancelRequest(ILibWebClient_RequestToken RequestToken);
|
||||
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_StateObject ILibWebClient_GetStateObjectFromRequestToken(ILibWebClient_RequestToken token);
|
||||
void **ILibWebClient_RequestToken_GetUserObjects(ILibWebClient_RequestToken tok);
|
||||
|
||||
@@ -760,7 +760,29 @@ void ILibWebServer_OnReceive(void *AsyncServerSocketModule, void *ConnectionToke
|
||||
if (ILibWebServer_Session_GetSystemData(ws)->WebSocket_Request == NULL)
|
||||
{
|
||||
// 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
|
||||
{
|
||||
@@ -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);
|
||||
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user