Source code

Revision control

Copy as Markdown

Other Tools

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* test_httpdefaultclient.c
*
* Test HttpDefaultClient header parsing, in particular that a malformed
* HTTP response whose body is larger than its declared Content-Length is
* rejected rather than overflowing the response buffer (bug 2050034).
*
*/
#include "testutil.h"
#include "testutil_nss.h"
#include "pkix_pl_common.h"
#include "pkix_pl_httpdefaultclient.h"
static void *plContext = NULL;
/*
* Drives pkix_pl_HttpDefaultClient_HdrCheckComplete over a single,
* fully-buffered HTTP response and checks the resulting connectStatus.
*
* "response"/"responseLen" describe the bytes the client has just received
* (header and body together, exactly as a single read would have delivered
* them). "expectedStatus" is the connectStatus the header parser should
* settle on.
*/
static void
testResponse(
char *subTestName,
const char *response,
PKIX_UInt32 responseLen,
HttpConnectStatus expectedStatus)
{
PKIX_PL_HttpDefaultClient *client = NULL;
PKIX_Boolean keepGoing = PKIX_FALSE;
char *rcvBuf = NULL;
PKIX_TEST_STD_VARS();
subTest(subTestName);
PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_HttpDefaultClient_Create(
"localhost", 80, &client, plContext));
/*
* Hand the client a receive buffer holding the whole response. The
* buffer is sized exactly to the bytes received, so an over-copy past
* the declared Content-Length is caught by ASan as a heap overflow.
*/
PKIX_TEST_EXPECT_NO_ERROR(
PKIX_PL_Malloc(responseLen, (void **)&rcvBuf, plContext));
PORT_Memcpy(rcvBuf, response, responseLen);
client->rcvBuf = rcvBuf;
client->capacity = responseLen;
client->filledupBytes = 0;
client->connectStatus = HTTP_RECV_HDR;
/* Ownership of rcvBuf passes to the client; it is freed on Destroy. */
rcvBuf = NULL;
PKIX_TEST_EXPECT_NO_ERROR(pkix_pl_HttpDefaultClient_HdrCheckComplete(
client, responseLen, &keepGoing, plContext));
if (client->connectStatus != expectedStatus) {
pkixTestErrorMsg =
"HdrCheckComplete produced an unexpected connectStatus.";
goto cleanup;
}
cleanup:
PKIX_TEST_DECREF_AC(client);
PKIX_TEST_RETURN();
}
int
test_httpdefaultclient(int argc, char *argv[])
{
/*
* A 1-byte body that occupies its full declared Content-Length: the
* parser should report a complete message.
*/
const char *exact =
"HTTP/1.0 200 OK\r\n"
"Content-Type: application/ocsp-response\r\n"
"Content-Length: 1\r\n"
"\r\n"
"A";
/*
* Content-Length declares more than is present: the parser should ask
* for more body data.
*/
const char *shortBody =
"HTTP/1.0 200 OK\r\n"
"Content-Type: application/ocsp-response\r\n"
"Content-Length: 16\r\n"
"\r\n"
"A";
/*
* The malformed case from bug 2050034: Content-Length declares 1 byte
* but 64 body bytes are delivered in the same buffer. The parser must
* reject the response rather than copy 64 bytes into a 1-byte buffer.
*/
const char *overflow =
"HTTP/1.0 200 OK\r\n"
"Content-Type: application/ocsp-response\r\n"
"Content-Length: 1\r\n"
"\r\n"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
PKIX_UInt32 actualMinorVersion = 0;
PKIX_TEST_STD_VARS();
startTests("HttpDefaultClient");
PKIX_TEST_EXPECT_NO_ERROR(PKIX_Initialize(PKIX_TRUE, /* nssInitNeeded */
PKIX_MAJOR_VERSION,
PKIX_MINOR_VERSION,
PKIX_MINOR_VERSION,
&actualMinorVersion,
&plContext));
testResponse("Body matches Content-Length (complete)",
exact, PL_strlen(exact), HTTP_COMPLETE);
testResponse("Body shorter than Content-Length (need more)",
shortBody, PL_strlen(shortBody), HTTP_RECV_BODY);
testResponse("Body longer than Content-Length (bug 2050034)",
overflow, PL_strlen(overflow), HTTP_ERROR);
cleanup:
PKIX_Shutdown(plContext);
PKIX_TEST_RETURN();
endTests("HttpDefaultClient");
return (0);
}