1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-15 07:43:50 +00:00

1. Updated to use #define for maximum header size

2. Modified AsyncSocket_Disconnect, to shutdown SD_SEND/SHUT_RD, instead of RDWR/BOTH, because sent data could be lost if a reset was sent
3. Added hardening for http.server packet parsing
This commit is contained in:
Bryan Roe
2019-03-26 22:10:29 -07:00
parent 65ebe45873
commit ed18cb7944
4 changed files with 112 additions and 22 deletions

View File

@@ -88,6 +88,7 @@ extern void ILibWebClient_ResetWCDO(struct ILibWebClientDataObject *wcdo);
#define ILibDuktape_WSDEC2WS "\xFF_WSDEC2WS"
extern void ILibWebServer_Digest_ParseAuthenticationHeader(void* table, char* value, int valueLen);
void ILibDuktape_HttpStream_ServerResponse_PUSH(duk_context *ctx, void* writeStream, ILibHTTPPacket *header, void *httpStream);
typedef struct ILibDuktape_Http_ClientRequest_WriteData
{
@@ -115,6 +116,7 @@ typedef struct ILibDuktape_HttpStream_Data
void *chain;
int ConnectMethod;
int endPropagated;
int maxHeaderSize;
}ILibDuktape_HttpStream_Data;
typedef struct ILibDuktape_HttpStream_ServerResponse_State
@@ -680,6 +682,7 @@ duk_ret_t ILibDuktape_HttpStream_http_OnSocketClosed(duk_context *ctx)
duk_pop(ctx); // ...
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_OnSocketReady(duk_context *ctx)
{
void *httpStream;
@@ -1543,6 +1546,27 @@ duk_ret_t ILibDuktape_HttpStream_http_server_onConnectionTimeout(duk_context *ct
}
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_parseError(duk_context *ctx)
{
duk_push_this(ctx); // [httpStream]
ILibDuktape_HttpStream_Data *data = (ILibDuktape_HttpStream_Data*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_HTTPStream2Data);
ILibDuktape_HttpStream_ServerResponse_PUSH(ctx, data->DS->writableStream->pipedReadable, NULL, data->DS->ParentObject); // [httpStream][response]
duk_dup(ctx, -1); duk_put_prop_string(ctx, -3, "\xFF_tmpServerResponse");
duk_get_prop_string(ctx, -1, "writeHead"); // [httpStream][response][writeHead]
duk_dup(ctx, -2); // [httpStream][response][writeHead][this]
duk_dup(ctx, 0); // [httpStream][response][writeHead][this][statusCode]
duk_dup(ctx, 1); // [httpStream][response][writeHead][this][statusCode][statusMessage]
duk_push_object(ctx); // [httpStream][response][writeHead][this][statusCode][statusMessage][headers]
duk_push_string(ctx, "close"); duk_put_prop_string(ctx, -2, "Connection");
duk_call_method(ctx, 3); duk_pop(ctx); // [httpStream][response]
duk_get_prop_string(ctx, -1, "end"); // [httpStream][response][end]
duk_swap_top(ctx, -2); // [httpStream][end][this]
duk_call_method(ctx, 0); duk_pop(ctx); // [httpStream]
return(0);
}
duk_ret_t ILibDuktape_HttpStream_http_server_onConnection(duk_context *ctx)
{
duk_push_this(ctx); // [NS]
@@ -1578,6 +1602,8 @@ duk_ret_t ILibDuktape_HttpStream_http_server_onConnection(duk_context *ctx)
//ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "close", -1, "close");
ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "connect", -1, "connect");
ILibDuktape_EventEmitter_ForwardEvent(ctx, -2, "request", -1, "request");
ILibDuktape_EventEmitter_AddOnEx(ctx, -2, "parseError", ILibDuktape_HttpStream_http_parseError);
if (ILibDuktape_EventEmitter_HasListenersEx(ctx, -1, "upgrade") > 0) { ILibDuktape_EventEmitter_AddOnceEx3(ctx, -2, "upgrade", ILibDuktape_HttpStream_http_server_onUpgrade); }
duk_pop(ctx); // [NS][socket][pipe][this][httpStream]
@@ -1754,8 +1780,34 @@ duk_ret_t ILibDuktape_HttpStream_WriteSink_ChainSink_DynamicBuffer_WriteSink(duk
data = (ILibDuktape_HttpStream_Data*)duk_get_pointer(ctx, -1);
buffer = (char*)Duktape_GetBuffer(ctx, 0, &bufferLen);
ILibWebClient_OnData(NULL, buffer, &beginPointer, (int)bufferLen, NULL, (void**)&(data->WCDO), &PAUSE);
ILibWebClient_DataResults r = ILibWebClient_OnData(NULL, buffer, &beginPointer, (int)bufferLen, NULL, (void**)&(data->WCDO), &PAUSE);
switch (r)
{
case ILibWebClient_DataResults_OK:
if (0 == beginPointer && ILibWebClient_IsFinHeader(data->WCDO) == 0 && ((int)bufferLen - beginPointer >= data->maxHeaderSize))
{
ILibDuktape_EventEmitter_SetupEmit(ctx, data->DS->ParentObject, "parseError"); // [emit][this][parseError]
duk_push_int(ctx, 431); // [emit][this][parseError][statusCode]
duk_push_string(ctx, "Headers too large"); // [emit][this][parseError][statusCode][statusMessage]
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "httpStream: Error in Event handler for 'parseError' "); }
duk_pop(ctx); // ...
}
break;
case ILibWebClient_DataResults_InvalidRequest:
ILibDuktape_EventEmitter_SetupEmit(ctx, data->DS->ParentObject, "parseError"); // [emit][this][parseError]
duk_push_int(ctx, 400); // [emit][this][parseError][statusCode]
duk_push_string(ctx, "Bad Request"); // [emit][this][parseError][statusCode][statusMessage]
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "httpStream: Error in Event handler for 'parseError' "); }
duk_pop(ctx); // ...
case ILibWebClient_DataResults_InvalidContentLength:
ILibDuktape_EventEmitter_SetupEmit(ctx, data->DS->ParentObject, "parseError"); // [emit][this][parseError]
duk_push_int(ctx, 400); // [emit][this][parseError][statusCode]
duk_push_string(ctx, "Invalid content-length specified"); // [emit][this][parseError][statusCode][statusMessage]
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "httpStream: Error in Event handler for 'parseError' "); }
duk_pop(ctx); // ...
default:
break;
}
return(0);
}
duk_ret_t ILibDuktape_HttpStream_WriteSink_ChainSink_DynamicBuffer_EndSink(duk_context *ctx)
@@ -1826,9 +1878,41 @@ ILibTransport_DoneState ILibDuktape_HttpStream_WriteSink(ILibDuktape_DuplexStrea
int beginPointer = 0;
int PAUSE = 0;
int MustBuffer = 0;
int ibp = beginPointer;
ILibDuktape_WritableStream *stream = DS->writableStream;
ILibWebClient_OnData(NULL, buffer, &beginPointer, (int)bufferLen, NULL, (void**)&(data->WCDO), &PAUSE);
ILibWebClient_DataResults r = ILibWebClient_OnData(NULL, buffer, &beginPointer, (int)bufferLen, NULL, (void**)&(data->WCDO), &PAUSE);
switch (r)
{
case ILibWebClient_DataResults_OK:
if (ibp == beginPointer && ILibWebClient_IsFinHeader(data->WCDO) == 0 && (bufferLen - beginPointer >= data->maxHeaderSize))
{
ILibDuktape_EventEmitter_SetupEmit(DS->writableStream->ctx, DS->ParentObject, "parseError"); // [emit][this][parseError]
duk_push_int(DS->writableStream->ctx, 431); // [emit][this][parseError][statusCode]
duk_push_string(DS->writableStream->ctx, "Headers too large"); // [emit][this][parseError][statusCode][statusMessage]
if (duk_pcall_method(DS->writableStream->ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(DS->writableStream->ctx, "httpStream: Error in Event handler for 'parseError' "); }
duk_pop(DS->writableStream->ctx); // ...
return(ILibTransport_DoneState_ERROR);
}
break;
case ILibWebClient_DataResults_InvalidRequest:
ILibDuktape_EventEmitter_SetupEmit(DS->writableStream->ctx, DS->ParentObject, "parseError"); // [emit][this][parseError]
duk_push_int(DS->writableStream->ctx, 400); // [emit][this][parseError][statusCode]
duk_push_string(DS->writableStream->ctx, "Bad Request"); // [emit][this][parseError][statusCode][statusMessage]
if (duk_pcall_method(DS->writableStream->ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(DS->writableStream->ctx, "httpStream: Error in Event handler for 'parseError' "); }
duk_pop(DS->writableStream->ctx); // ...
return(ILibTransport_DoneState_ERROR);
case ILibWebClient_DataResults_InvalidContentLength:
ILibDuktape_EventEmitter_SetupEmit(DS->writableStream->ctx, DS->ParentObject, "parseError"); // [emit][this][parseError]
duk_push_int(DS->writableStream->ctx, 400); // [emit][this][parseError][statusCode]
duk_push_string(DS->writableStream->ctx, "Invalid content-length specified"); // [emit][this][parseError][statusCode][statusMessage]
if (duk_pcall_method(DS->writableStream->ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(DS->writableStream->ctx, "httpStream: Error in Event handler for 'parseError' "); }
duk_pop(DS->writableStream->ctx); // ...
return(ILibTransport_DoneState_ERROR);
default:
break;
}
if ((bufferLen - beginPointer) > 0)
{
@@ -2314,6 +2398,10 @@ duk_ret_t ILibDuktape_HttpStream_ServerResponse_writeHead(duk_context *ctx)
statusMessageLen = 8;
break;
case 200:
statusMessage = "OK";
statusMessageLen = 2;
break;
case 400:
statusMessage = "Bad Request";
statusMessageLen = 11;
break;
@@ -2510,17 +2598,15 @@ void ILibDuktape_HttpStream_ServerResponse_PUSH(duk_context *ctx, void* writeStr
duk_put_prop_string(ctx, -2, ILibDuktape_OBJID); // [resp]
ILibDuktape_WriteID(ctx, "http.serverResponse");
duk_push_fixed_buffer(ctx, sizeof(ILibDuktape_HttpStream_ServerResponse_State)); // [resp][state]
state = (ILibDuktape_HttpStream_ServerResponse_State*)Duktape_GetBuffer(ctx, -1, NULL);
state = Duktape_PushBuffer(ctx, sizeof(ILibDuktape_HttpStream_ServerResponse_State)); // [resp][state]
duk_put_prop_string(ctx, -2, ILibDuktape_SR2State); // [resp]
memset(state, 0, sizeof(ILibDuktape_HttpStream_ServerResponse_State));
state->ctx = ctx;
state->serverResponse = duk_get_heapptr(ctx, -1);
state->implicitHeaderHandling = 1;
state->chain = Duktape_GetChain(ctx);
state->writeStream = writeStream;
state->nativeWriteStream = ILibDuktape_DuplexStream_GetNativeWritable(ctx, writeStream);
state->chunkSupported = ILibDuktape_Headers_IsChunkSupported(header);
state->chunkSupported = header != NULL ? ILibDuktape_Headers_IsChunkSupported(header) : 0;
duk_push_object(ctx); // [resp][implicitHeaders]
duk_put_prop_string(ctx, -2, ILibDuktape_SR2ImplicitHeaders); // [resp]
@@ -3085,8 +3171,11 @@ duk_ret_t ILibduktape_HttpStream_create(duk_context *ctx)
data = (ILibDuktape_HttpStream_Data*)Duktape_PushBuffer(ctx, sizeof(ILibDuktape_HttpStream_Data));
duk_put_prop_string(ctx, -2, ILibDuktape_HTTPStream2Data); // [httpStream]
data->maxHeaderSize = 4096;
ILibDuktape_EventEmitter_CreateEventEx(emitter, "end");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "error");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "parseError");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "continue");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "response");
ILibDuktape_EventEmitter_CreateEventEx(emitter, "upgrade");

View File

@@ -795,11 +795,11 @@ void ILibAsyncSocket_Disconnect(ILibAsyncSocket_SocketModule socketModule)
{
#if defined(_WIN32_WCE) || defined(WIN32)
#if defined(WINSOCK2)
shutdown(s, SD_BOTH);
shutdown(s, SD_SEND);
#endif
closesocket(s);
#elif defined(_POSIX)
shutdown(s, SHUT_RDWR);
shutdown(s, SHUT_RD);
close(s);
#endif
}

View File

@@ -52,6 +52,7 @@ extern "C" {
#endif
#endif
#define HTTP_MAX_HEADER_SIZE 4096
#define WEBSOCKET_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"
#define WEBSOCKET_FIN 0x08000
#define WEBSOCKET_RSV1 0x04000

View File

@@ -765,7 +765,7 @@ void ILibWebServer_OnReceive(void *AsyncServerSocketModule, void *ConnectionToke
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)
if (*p_beginPointer == pbp && (endPointer - pbp >= HTTP_MAX_HEADER_SIZE) && 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