Skip to content

Commit

Permalink
NetworkPkg/HttpDxe: Fix the bug when parsing HTTP(S) message body.
Browse files Browse the repository at this point in the history
*v2: Resolve the conflict commit.

*v3: Fixed the failure if BodyLength in HTTP token is less than the received
size of HTTPS message.

HttpBodyParserCallback function is to parse the HTTP(S) message body so as to
confirm whether there is the next message header. But it doesn't record the
parsing message data/length correctly.

This patch is refine the parsing logic so as to fix the potential failure.

Cc: Ye Ting <[email protected]>
Cc: Fu Siyuan <[email protected]>
Cc: Gary Lin <[email protected]>
Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Wu Jiaxin <[email protected]>
Reviewed-by: Fu Siyuan <[email protected]>
Reviewed-by: Ye Ting <[email protected]>
Tested-by: Gary Lin <[email protected]>
  • Loading branch information
jiaxinwu committed Jul 12, 2018
1 parent c6a14de commit 895b87e
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 54 deletions.
112 changes: 58 additions & 54 deletions NetworkPkg/HttpDxe/HttpImpl.c
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,7 @@ HttpBodyParserCallback (
IN VOID *Context
)
{
HTTP_CALLBACK_DATA *CallbackData;
HTTP_TOKEN_WRAP *Wrap;
UINTN BodyLength;
CHAR8 *Body;
Expand All @@ -928,21 +929,18 @@ HttpBodyParserCallback (
return EFI_SUCCESS;
}

Wrap = (HTTP_TOKEN_WRAP *) Context;
Body = Wrap->HttpToken->Message->Body;
BodyLength = Wrap->HttpToken->Message->BodyLength;
CallbackData = (HTTP_CALLBACK_DATA *) Context;

Wrap = (HTTP_TOKEN_WRAP *) (CallbackData->Wrap);
Body = CallbackData->ParseData;
BodyLength = CallbackData->ParseDataLength;

if (Data < Body + BodyLength) {
Wrap->HttpInstance->NextMsg = Data;
} else {
Wrap->HttpInstance->NextMsg = NULL;
}


//
// Free Tx4Token or Tx6Token since already received corrsponding HTTP response.
//
FreePool (Wrap);

return EFI_SUCCESS;
}

Expand Down Expand Up @@ -1191,7 +1189,7 @@ HttpResponseWorker (
HttpMsg->HeaderCount,
HttpMsg->Headers,
HttpBodyParserCallback,
(VOID *) ValueInItem,
(VOID *) (&HttpInstance->CallbackData),
&HttpInstance->MsgParser
);
if (EFI_ERROR (Status)) {
Expand All @@ -1202,18 +1200,28 @@ HttpResponseWorker (
// Check whether we received a complete HTTP message.
//
if (HttpInstance->CacheBody != NULL) {
//
// Record the CallbackData data.
//
HttpInstance->CallbackData.Wrap = (VOID *) Wrap;
HttpInstance->CallbackData.ParseData = (VOID *) HttpInstance->CacheBody;
HttpInstance->CallbackData.ParseDataLength = HttpInstance->CacheLen;

//
// Parse message with CallbackData data.
//
Status = HttpParseMessageBody (HttpInstance->MsgParser, HttpInstance->CacheLen, HttpInstance->CacheBody);
if (EFI_ERROR (Status)) {
goto Error2;
}
}

if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
//
// Free the MsgParse since we already have a full HTTP message.
//
HttpFreeMsgParser (HttpInstance->MsgParser);
HttpInstance->MsgParser = NULL;
}
if (HttpIsMessageComplete (HttpInstance->MsgParser)) {
//
// Free the MsgParse since we already have a full HTTP message.
//
HttpFreeMsgParser (HttpInstance->MsgParser);
HttpInstance->MsgParser = NULL;
}
}

Expand Down Expand Up @@ -1332,12 +1340,26 @@ HttpResponseWorker (
}

//
// Check whether we receive a complete HTTP message.
// Process the received the body packet.
//
HttpMsg->BodyLength = MIN (Fragment.Len, (UINT32) HttpMsg->BodyLength);

CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);

//
// Record the CallbackData data.
//
HttpInstance->CallbackData.Wrap = (VOID *) Wrap;
HttpInstance->CallbackData.ParseData = HttpMsg->Body;
HttpInstance->CallbackData.ParseDataLength = HttpMsg->BodyLength;

//
// Parse Body with CallbackData data.
//
Status = HttpParseMessageBody (
HttpInstance->MsgParser,
(UINTN) Fragment.Len,
(CHAR8 *) Fragment.Bulk
HttpMsg->BodyLength,
HttpMsg->Body
);
if (EFI_ERROR (Status)) {
goto Error2;
Expand All @@ -1352,46 +1374,28 @@ HttpResponseWorker (
}

//
// We receive part of header of next HTTP msg.
// Check whether there is the next message header in the HttpMsg->Body.
//
if (HttpInstance->NextMsg != NULL) {
HttpMsg->BodyLength = MIN ((UINTN) HttpInstance->NextMsg - (UINTN) Fragment.Bulk, HttpMsg->BodyLength);
CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);

HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
if (HttpInstance->CacheLen != 0) {
if (HttpInstance->CacheBody != NULL) {
FreePool (HttpInstance->CacheBody);
}

HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);
if (HttpInstance->CacheBody == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error2;
}

CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
HttpInstance->CacheOffset = 0;
HttpMsg->BodyLength = HttpInstance->NextMsg - (CHAR8 *) HttpMsg->Body;
}

HttpInstance->NextMsg = HttpInstance->CacheBody + ((UINTN) HttpInstance->NextMsg - (UINTN) (Fragment.Bulk + HttpMsg->BodyLength));
HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
if (HttpInstance->CacheLen != 0) {
if (HttpInstance->CacheBody != NULL) {
FreePool (HttpInstance->CacheBody);
}
} else {
HttpMsg->BodyLength = MIN (Fragment.Len, (UINT32) HttpMsg->BodyLength);
CopyMem (HttpMsg->Body, Fragment.Bulk, HttpMsg->BodyLength);
HttpInstance->CacheLen = Fragment.Len - HttpMsg->BodyLength;
if (HttpInstance->CacheLen != 0) {
if (HttpInstance->CacheBody != NULL) {
FreePool (HttpInstance->CacheBody);
}

HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);
if (HttpInstance->CacheBody == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error2;
}
HttpInstance->CacheBody = AllocateZeroPool (HttpInstance->CacheLen);
if (HttpInstance->CacheBody == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Error2;
}

CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
HttpInstance->CacheOffset = 0;
CopyMem (HttpInstance->CacheBody, Fragment.Bulk + HttpMsg->BodyLength, HttpInstance->CacheLen);
HttpInstance->CacheOffset = 0;
if (HttpInstance->NextMsg != NULL) {
HttpInstance->NextMsg = HttpInstance->CacheBody;
}
}

Expand Down
10 changes: 10 additions & 0 deletions NetworkPkg/HttpDxe/HttpProto.c
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,16 @@ HttpTcpReceiveNotifyDpc (
Length = (UINTN) Wrap->TcpWrap.Rx4Data.FragmentTable[0].FragmentLength;
}

//
// Record the CallbackData data.
//
HttpInstance->CallbackData.Wrap = (VOID *) Wrap;
HttpInstance->CallbackData.ParseData = Wrap->HttpToken->Message->Body;
HttpInstance->CallbackData.ParseDataLength = Length;

//
// Parse Body with CallbackData data.
//
Status = HttpParseMessageBody (
HttpInstance->MsgParser,
Length,
Expand Down
10 changes: 10 additions & 0 deletions NetworkPkg/HttpDxe/HttpProto.h
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,15 @@ typedef struct {
EFI_TLS_SESSION_STATE SessionState;
} TLS_CONFIG_DATA;

//
// Callback data for HTTP_PARSER_CALLBACK()
//
typedef struct {
UINTN ParseDataLength;
VOID *ParseData;
VOID *Wrap;
} HTTP_CALLBACK_DATA;

typedef struct _HTTP_PROTOCOL {
UINT32 Signature;
EFI_HTTP_PROTOCOL Http;
Expand Down Expand Up @@ -149,6 +158,7 @@ typedef struct _HTTP_PROTOCOL {
// HTTP message-body parser.
//
VOID *MsgParser;
HTTP_CALLBACK_DATA CallbackData;

EFI_HTTP_VERSION HttpVersion;
UINT32 TimeOutMillisec;
Expand Down

0 comments on commit 895b87e

Please sign in to comment.