Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

next/254/20240120/v1 #414

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions htp/bstr.c
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ int bstr_chr(const bstr *b, int c) {
size_t i = 0;
while (i < len) {
if (data[i] == c) {
return i;
return (int) i;
}

i++;
Expand Down Expand Up @@ -322,7 +322,7 @@ int bstr_rchr(const bstr *b, int c) {
size_t i = len;
while (i > 0) {
if (data[i - 1] == c) {
return i - 1;
return (int) (i - 1);
}

i--;
Expand Down Expand Up @@ -506,7 +506,7 @@ int bstr_util_mem_index_of_mem(const void *_data1, size_t len1, const void *_dat
}

if (j == len2) {
return i;
return (int) i;
}
}

Expand All @@ -529,7 +529,7 @@ int bstr_util_mem_index_of_mem_nocase(const void *_data1, size_t len1, const voi
}

if (j == len2) {
return i;
return (int) i;
}
}

Expand Down Expand Up @@ -560,7 +560,7 @@ int bstr_util_mem_index_of_mem_nocasenorzero(const void *_data1, size_t len1, co
}

if (j == len2) {
return i;
return (int) i;
}
}

Expand Down
16 changes: 8 additions & 8 deletions htp/htp_base64.c
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,7 @@ int htp_base64_decode(htp_base64_decoder *decoder, const void *_code_in, int len
if (codechar == code_in + length_in) {
decoder->step = step_a;
decoder->plainchar = *plainchar;
return plainchar - plaintext_out;
return (int) (plainchar - plaintext_out);
}
fragment = (char) htp_base64_decode_single(*codechar++);
} while (fragment < 0);
Expand All @@ -111,14 +111,14 @@ int htp_base64_decode(htp_base64_decoder *decoder, const void *_code_in, int len
if (codechar == code_in + length_in) {
decoder->step = step_b;
decoder->plainchar = *plainchar;
return plainchar - plaintext_out;
return (int) (plainchar - plaintext_out);
}
fragment = (char) htp_base64_decode_single(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x030) >> 4;
*plainchar = (unsigned char) ((fragment & 0x00f) << 4);
if (--length_out == 0) {
return plainchar - plaintext_out;
return (int) (plainchar - plaintext_out);
}
/* fall through */

Expand All @@ -127,14 +127,14 @@ int htp_base64_decode(htp_base64_decoder *decoder, const void *_code_in, int len
if (codechar == code_in + length_in) {
decoder->step = step_c;
decoder->plainchar = *plainchar;
return plainchar - plaintext_out;
return (int) (plainchar - plaintext_out);
}
fragment = (char) htp_base64_decode_single(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03c) >> 2;
*plainchar = (unsigned char) ((fragment & 0x003) << 6);
if (--length_out == 0) {
return plainchar - plaintext_out;
return (int) (plainchar - plaintext_out);
}
/* fall through */

Expand All @@ -143,13 +143,13 @@ int htp_base64_decode(htp_base64_decoder *decoder, const void *_code_in, int len
if (codechar == code_in + length_in) {
decoder->step = step_d;
decoder->plainchar = *plainchar;
return plainchar - plaintext_out;
return (int) (plainchar - plaintext_out);
}
fragment = (char) htp_base64_decode_single(*codechar++);
} while (fragment < 0);
*plainchar++ |= (fragment & 0x03f);
if (--length_out == 0) {
return plainchar - plaintext_out;
return (int) (plainchar - plaintext_out);
}
/* fall through */
}
Expand Down Expand Up @@ -185,7 +185,7 @@ bstr *htp_base64_decode_mem(const void *data, size_t len) {
unsigned char *tmpstr = malloc(len);
if (tmpstr == NULL) return NULL;

int resulting_len = htp_base64_decode(&decoder, data, len, tmpstr, len);
int resulting_len = htp_base64_decode(&decoder, data, (int) len, tmpstr, (int) len);
if (resulting_len > 0) {
r = bstr_dup_mem(tmpstr, resulting_len);
}
Expand Down
4 changes: 2 additions & 2 deletions htp/htp_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -528,7 +528,7 @@ void htp_config_set_compression_bomb_limit(htp_cfg_t *cfg, size_t bomblimit) {
if (bomblimit > INT32_MAX) {
cfg->compression_bomb_limit = INT32_MAX;
} else {
cfg->compression_bomb_limit = bomblimit;
cfg->compression_bomb_limit = (int32_t) bomblimit;
}
}

Expand All @@ -538,7 +538,7 @@ void htp_config_set_compression_time_limit(htp_cfg_t *cfg, size_t useclimit) {
if (useclimit >= 1000000) {
cfg->compression_time_limit = 1000000;
} else {
cfg->compression_time_limit = useclimit;
cfg->compression_time_limit = (int32_t) useclimit;
}
}

Expand Down
6 changes: 3 additions & 3 deletions htp/htp_decompressors.c
Original file line number Diff line number Diff line change
Expand Up @@ -232,12 +232,12 @@ htp_status_t htp_gzip_decompressor_decompress(htp_decompressor_t *drec1, htp_tx_
}

restart:
if (consumed > d->len) {
if (consumed > d->len || d->len > UINT32_MAX ) {
htp_log(d->tx->connp, HTP_LOG_MARK, HTP_LOG_ERROR, 0, "GZip decompressor: consumed > d->len");
return HTP_ERROR;
}
drec->stream.next_in = (unsigned char *) (d->data + consumed);
drec->stream.avail_in = d->len - consumed;
drec->stream.avail_in = (uint32_t) (d->len - consumed);

while (drec->stream.avail_in != 0) {
// If there's no more data left in the
Expand Down Expand Up @@ -275,7 +275,7 @@ htp_status_t htp_gzip_decompressor_decompress(htp_decompressor_t *drec1, htp_tx_
}
memcpy(drec->header + drec->header_len, drec->stream.next_in, consumed);
drec->stream.next_in = (unsigned char *) (d->data + consumed);
drec->stream.avail_in = d->len - consumed;
drec->stream.avail_in = (uint32_t) (d->len - consumed);
drec->header_len += consumed;
}
if (drec->header_len == LZMA_PROPS_SIZE + 8) {
Expand Down
2 changes: 2 additions & 0 deletions htp/htp_private.h
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ htp_status_t htp_tx_urldecode_params_inplace(htp_tx_t *tx, bstr *input);

void htp_connp_destroy_decompressors(htp_connp_t *connp);

htp_status_t htp_header_has_token(const unsigned char *hvp, size_t hvlen, const unsigned char *value);

#ifndef HAVE_STRLCAT
size_t strlcat(char *dst, const char *src, size_t size);
#endif
Expand Down
8 changes: 1 addition & 7 deletions htp/htp_request.c
Original file line number Diff line number Diff line change
Expand Up @@ -744,21 +744,15 @@ htp_status_t htp_connp_REQ_PROTOCOL(htp_connp_t *connp) {
} else {
// Let's check if the protocol was simply missing
int64_t pos = connp->in_current_read_offset;
int afterspaces = 0;
// Probe if data looks like a header line
while (pos < connp->in_current_len) {
if (connp->in_current_data[pos] == ':') {
if (!htp_is_space(connp->in_current_data[pos])) {
htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0, "Request line: missing protocol");
connp->in_tx->is_protocol_0_9 = 0;
// Switch to request header parsing.
connp->in_state = htp_connp_REQ_HEADERS;
connp->in_tx->request_progress = HTP_REQUEST_HEADERS;
return HTP_OK;
} else if (htp_is_lws(connp->in_current_data[pos])) {
// Allows spaces after header name
afterspaces = 1;
} else if (htp_is_space(connp->in_current_data[pos]) || afterspaces == 1) {
break;
}
pos++;
}
Expand Down
7 changes: 2 additions & 5 deletions htp/htp_transaction.c
Original file line number Diff line number Diff line change
Expand Up @@ -405,7 +405,7 @@ static htp_status_t htp_tx_process_request_headers(htp_tx_t *tx) {
// (2.2.22 on Ubuntu 12.04 LTS) instead errors out with "Unknown Transfer-Encoding: identity".
// And it behaves strangely, too, sending a 501 and proceeding to process the request
// (e.g., PHP is run), but without the body. It then closes the connection.
if (bstr_cmp_c_nocase(te->value, "chunked") != 0) {
if (htp_header_has_token(bstr_ptr(te->value), bstr_len(te->value), (unsigned char*) "chunked") != HTP_OK) {
// Invalid T-E header value.
tx->request_transfer_coding = HTP_CODING_INVALID;
tx->flags |= HTP_REQUEST_INVALID_T_E;
Expand Down Expand Up @@ -585,10 +585,7 @@ static htp_status_t htp_tx_process_request_headers(htp_tx_t *tx) {
rc = htp_hook_run_all(tx->connp->cfg->hook_request_headers, tx);
if (rc != HTP_OK) return rc;

// We cannot proceed if the request is invalid.
if (tx->flags & HTP_REQUEST_INVALID) {
return HTP_ERROR;
}
// We still proceed if the request is invalid.

return HTP_OK;
}
Expand Down
8 changes: 4 additions & 4 deletions htp/htp_transcoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ int htp_transcode_params(htp_connp_t *connp, htp_table_t **params, int destroy_o
// Convert the parameters, one by one
bstr *name = NULL;
bstr *value = NULL;
for (int i = 0, n = htp_table_size(input_params); i < n; i++) {
for (size_t i = 0, n = htp_table_size(input_params); i < n; i++) {
value = htp_table_get_index(input_params, i, &name);

bstr *new_name = NULL, *new_value = NULL;
Expand All @@ -85,7 +85,7 @@ int htp_transcode_params(htp_connp_t *connp, htp_table_t **params, int destroy_o
iconv_close(cd);

bstr *b = NULL;
for (int j = 0, k = htp_table_size(output_params); j < k; j++) {
for (size_t j = 0, k = htp_table_size(output_params); j < k; j++) {
b = htp_table_get_index(output_params, j, NULL);
bstr_free(b);
}
Expand All @@ -101,7 +101,7 @@ int htp_transcode_params(htp_connp_t *connp, htp_table_t **params, int destroy_o
iconv_close(cd);

bstr *b = NULL;
for (int j = 0, k = htp_table_size(output_params); j < k; j++) {
for (size_t j = 0, k = htp_table_size(output_params); j < k; j++) {
b = htp_table_get_index(output_params, j, NULL);
bstr_free(b);
}
Expand All @@ -120,7 +120,7 @@ int htp_transcode_params(htp_connp_t *connp, htp_table_t **params, int destroy_o
// Destroy the old parameter table if necessary
if (destroy_old) {
bstr *b = NULL;
for (int i = 0, n = htp_table_size(input_params); i < n; i++) {
for (size_t i = 0, n = htp_table_size(input_params); i < n; i++) {
b = htp_table_get_index(input_params, i, NULL);
bstr_free(b);
}
Expand Down
61 changes: 59 additions & 2 deletions htp/htp_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ int64_t htp_parse_content_length(bstr *b, htp_connp_t *connp) {
while ((pos < len) && (data[pos] < '0' || data[pos] > '9')) {
if (!htp_is_lws(data[pos]) && connp != NULL && r == 0) {
htp_log(connp, HTP_LOG_MARK, HTP_LOG_WARNING, 0,
"C-L value with extra data in the beginnning");
"C-L value with extra data in the beginning");
r = -1;
}
pos++;
Expand Down Expand Up @@ -540,7 +540,7 @@ static htp_status_t htp_parse_port(unsigned char *data, size_t len, int *port, i
*invalid = 1;
} else if ((port_parsed > 0) && (port_parsed < 65536)) {
// Valid port number.
*port = port_parsed;
*port = (int) port_parsed;
} else {
// Port number out of range.
*port = -1;
Expand Down Expand Up @@ -2536,3 +2536,60 @@ htp_uri_t *htp_uri_alloc(void) {
char *htp_get_version(void) {
return HTP_VERSION_STRING_FULL;
}

/**
* Tells if a header value (haystack) contains a token (needle)
* This is done with a caseless comparison
*
* @param[in] hvp header value pointer
* @param[in] hvlen length of header value buffer
* @param[in] value token to look for (null-terminated string), should be a lowercase constant
* @return HTP_OK if the header has the token; HTP_ERROR if it has not.
*/
htp_status_t htp_header_has_token(const unsigned char *hvp, size_t hvlen, const unsigned char *value) {
int state = 0;
// offset to compare in value
size_t v_off = 0;
// The header value is a list of comma-separated tokens (with additional spaces)
for (size_t i = 0; i < hvlen; i++) {
switch (state) {
case 0:
if (v_off == 0 && htp_is_space(hvp[i])) {
// skip leading space
continue;
}
if (tolower(hvp[i]) == value[v_off]) {
v_off++;
if (value[v_off] == 0) {
// finish validation if end of token
state = 2;
}
continue;
} else {
// wait for a new token
v_off = 0;
state = 1;
}
// fallthrough
case 1:
if (hvp[i] == ',') {
// start of next token
state = 0;
}
break;
case 2:
if (hvp[i] == ',') {
return HTP_OK;
}
if (!htp_is_space(hvp[i])) {
// trailing junk in token, wait for a next one
v_off = 0;
state = 1;
}
}
}
if (state == 2) {
return HTP_OK;
}
return HTP_ERROR;
}
1 change: 0 additions & 1 deletion test/test_main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -558,7 +558,6 @@ TEST_F(ConnectionParsing, Http_0_9_Multiple) {
ASSERT_GE(rc, 0);

ASSERT_EQ(1, htp_list_size(connp->conn->transactions));
ASSERT_TRUE(connp->conn->flags & HTP_CONN_HTTP_0_9_EXTRA);

htp_tx_t *tx = (htp_tx_t *) htp_list_get(connp->conn->transactions, 0);
ASSERT_TRUE(tx != NULL);
Expand Down
36 changes: 36 additions & 0 deletions test/test_utils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1801,3 +1801,39 @@ TEST_F(UrlencodedParser, UrlDecode1) {
ASSERT_EQ(0, bstr_cmp_c(s, "/one/two/three/%3"));
bstr_free(s);
}

TEST(UtilTest, HeaderHasToken) {
char data[100];

// Basic
strcpy(data, "chunked");
EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));

// Negative
strcpy(data, "notchunked");
EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, "chunkednot");
EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, "chunk,ed");
EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, "chunk ed");
EXPECT_EQ(HTP_ERROR, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));

// Positive
strcpy(data, " notchunked , chunked , yetanother");
EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, "chunked,yetanother");
EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, "not,chunked");
EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, "chunk,chunked");
EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, " chunked");
EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, "chunked ");
EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, "chunked,");
EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
strcpy(data, ",chunked");
EXPECT_EQ(HTP_OK, htp_header_has_token((unsigned char*) data, strlen(data), (unsigned char *)"chunked"));
}