hi_server.c (snort-2.9.16.1) | : | hi_server.c (snort-2.9.17) | ||
---|---|---|---|---|
skipping to change at line 86 | skipping to change at line 86 | |||
#define HTTPRESP_HEADER_LENGTH__GZIP 4 | #define HTTPRESP_HEADER_LENGTH__GZIP 4 | |||
#define HTTPRESP_HEADER_LENGTH__XGZIP 6 | #define HTTPRESP_HEADER_LENGTH__XGZIP 6 | |||
#define HTTPRESP_HEADER_NAME__DEFLATE "deflate" | #define HTTPRESP_HEADER_NAME__DEFLATE "deflate" | |||
#define HTTPRESP_HEADER_LENGTH__DEFLATE 7 | #define HTTPRESP_HEADER_LENGTH__DEFLATE 7 | |||
#define HTTPRESP_HEADER_NAME__CONTENT_LENGTH "Content-length" | #define HTTPRESP_HEADER_NAME__CONTENT_LENGTH "Content-length" | |||
#define HTTPRESP_HEADER_LENGTH__CONTENT_LENGTH 14 | #define HTTPRESP_HEADER_LENGTH__CONTENT_LENGTH 14 | |||
#define HTTPRESP_HEADER_NAME__CONTENT_TYPE "Content-Type" | #define HTTPRESP_HEADER_NAME__CONTENT_TYPE "Content-Type" | |||
#define HTTPRESP_HEADER_LENGTH__CONTENT_TYPE 12 | #define HTTPRESP_HEADER_LENGTH__CONTENT_TYPE 12 | |||
#define HTTPRESP_HEADER_NAME__TRANSFER_ENCODING "Transfer-Encoding" | #define HTTPRESP_HEADER_NAME__TRANSFER_ENCODING "Transfer-Encoding" | |||
#define HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING 17 | #define HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING 17 | |||
#define HTTPRESP_HEADER_NAME__CONTENT_RANGE "Content-Range" | ||||
#define HTTPRESP_HEADER_LENGTH__CONTENT_RANGE 13 | ||||
#define HTTPRESP_HEADER_NAME__ACCEPT_RANGES "Accept-Ranges" | ||||
#define HTTPRESP_HEADER_LENGTH__ACCEPT_RANGES 13 | ||||
#if defined(FEAT_OPEN_APPID) | #if defined(FEAT_OPEN_APPID) | |||
#define HEADER_NAME__VIA "Via" | #define HEADER_NAME__VIA "Via" | |||
#define HEADER_LENGTH__VIA sizeof(HEADER_NAME__VIA)-1 | #define HEADER_LENGTH__VIA sizeof(HEADER_NAME__VIA)-1 | |||
#define HEADER_NAME__SERVER "Server" | #define HEADER_NAME__SERVER "Server" | |||
#define HEADER_LENGTH__SERVER sizeof(HEADER_NAME__SERVER)-1 | #define HEADER_LENGTH__SERVER sizeof(HEADER_NAME__SERVER)-1 | |||
#define HEADER_NAME__X_WORKING_WITH "X-Working-With" | #define HEADER_NAME__X_WORKING_WITH "X-Working-With" | |||
#define HEADER_LENGTH__X_WORKING_WITH sizeof(HEADER_NAME__X_WORKING_WITH)-1 | #define HEADER_LENGTH__X_WORKING_WITH sizeof(HEADER_NAME__X_WORKING_WITH)-1 | |||
#endif /* defined(FEAT_OPEN_APPID) */ | #endif /* defined(FEAT_OPEN_APPID) */ | |||
extern fd_config_t hi_fd_conf; | extern fd_config_t hi_fd_conf; | |||
skipping to change at line 757 | skipping to change at line 761 | |||
return end; | return end; | |||
} | } | |||
} | } | |||
} | } | |||
if(!p || !hi_util_in_bounds(start, end, p)) | if(!p || !hi_util_in_bounds(start, end, p)) | |||
p = end; | p = end; | |||
return p; | return p; | |||
} | } | |||
/* | ||||
* extract_http_content_range() will extract required data from content-range | ||||
* field. Focus is for, when the units is "bytes". | ||||
* The possible syntax as follows, | ||||
* content-range: <units> <start_pos>-<end_pos>/<total_len> | ||||
* content-range: <units> * /<total_len> | ||||
* content-range: <units> <start_pos>-<end_pos>/ * | ||||
*/ | ||||
static const u_char *extract_http_content_range(HI_SESSION *Session, | ||||
const u_char *p, const u_char *start, const u_char *end, | ||||
HEADER_PTR *header_ptr) | ||||
{ | ||||
u_char *crlf = NULL; | ||||
const u_char *unit_start = NULL; | ||||
int is_byte_range = false; | ||||
SkipBlankSpace(start,end,&p); | ||||
if (hi_util_in_bounds(start, end, p) && *p == ':') | ||||
{ | ||||
p++; | ||||
CheckSkipAlertMultipleColon(Session, start, end, &p, HI_SI_SERVER_MODE); | ||||
while (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
if ((*p == ' ') || (*p == '\t')) | ||||
{ | ||||
p++; | ||||
break; | ||||
} | ||||
p++; | ||||
} | ||||
if (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
/* extract unit */ | ||||
unit_start = p; | ||||
while (hi_util_in_bounds(start, end, p) && ( *p != ' ')) | ||||
{ | ||||
p++; | ||||
} | ||||
if (*p != ' ') | ||||
{ | ||||
if (hi_eo_generate_event(Session, HI_EO_SERVER_INVALID_CONTENT_R | ||||
ANGE_UNIT_FMT)) | ||||
{ | ||||
hi_eo_server_event_log(Session, HI_EO_SERVER_INVALID_CONTENT | ||||
_RANGE_UNIT_FMT, NULL, NULL); | ||||
} | ||||
header_ptr->range_flag = RANGE_WITH_RESP_ERROR; | ||||
return end; | ||||
} | ||||
/* Set flag, when unit is bytes. Based on unit, flow will change */ | ||||
if (!strncasecmp((const char *)unit_start, RANGE_UNIT_BYTE, 5)) | ||||
{ | ||||
is_byte_range = true; | ||||
} | ||||
else | ||||
{ | ||||
is_byte_range = false; | ||||
} | ||||
p++; | ||||
if (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
if (is_byte_range == true) | ||||
{ | ||||
if (isdigit((int)*p)) | ||||
{ | ||||
/*if start with digit, then expectation is | ||||
"<start_pos>-<end_pos>/<total_len>" or "<start_pos>-<e | ||||
nd_pos>/ *" | ||||
There is no whitespace between / and * To make it comm | ||||
ent added the space | ||||
pattern other than above mentioned format will flag as | ||||
error */ | ||||
uint64_t start_range = 0; | ||||
uint64_t end_range = 0; | ||||
uint64_t len = 0; | ||||
const u_char *start_ptr = NULL; | ||||
const u_char *end_ptr = NULL; | ||||
const u_char *len_ptr = NULL; | ||||
const u_char *ret_ptr = NULL; | ||||
int is_valid_range = false; | ||||
int delim_1 = false; | ||||
int delim_2 = false; | ||||
int assign = false; | ||||
start_ptr = p; | ||||
p++; | ||||
while (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
if (!isdigit((int)*p)) | ||||
{ | ||||
if (*p == '-') | ||||
{ | ||||
if ((delim_2 == true) || (delim_1 == true)) | ||||
{ | ||||
break; | ||||
} | ||||
delim_1 = true; | ||||
assign = true; | ||||
p++; | ||||
continue; | ||||
} | ||||
else if (*p == '/') | ||||
{ | ||||
if ((delim_1 == false) || (delim_2 == true)) | ||||
{ | ||||
break; | ||||
} | ||||
delim_2 = true; | ||||
assign = true; | ||||
p++; | ||||
continue; | ||||
} | ||||
else if ((*p == '*') || (*p == '\r') || (*p == ' | ||||
\n')) | ||||
{ | ||||
if ((delim_1 == false) || (delim_2 == false) | ||||
) | ||||
{ | ||||
break; | ||||
} | ||||
is_valid_range = true; | ||||
break; | ||||
} | ||||
break; | ||||
} | ||||
/* Here digit only come */ | ||||
if (assign == true) | ||||
{ | ||||
if ((delim_2 == false) && (delim_1 == true)) | ||||
{ | ||||
end_ptr = p; | ||||
} | ||||
else if ((delim_1 == true) && (delim_2 == true)) | ||||
{ | ||||
len_ptr = p; | ||||
} | ||||
else | ||||
{ | ||||
assign = false; | ||||
break; | ||||
} | ||||
assign = false; | ||||
} | ||||
p++; | ||||
} | ||||
if (is_valid_range == true) | ||||
{ | ||||
/* Now check total_len, * means set the flag accordi | ||||
ngly | ||||
or convert str to value and flag as full content | ||||
when differnce between start_pos and end_pos and | ||||
sum with 1 | ||||
equals to total_len, otherwise partial flag set * | ||||
/ | ||||
if (*p == '*') | ||||
{ | ||||
header_ptr->range_flag = RANGE_WITH_RESP_UNKNOWN | ||||
_CONTENT_SIZE; | ||||
} | ||||
else if ((start_ptr) && (end_ptr) && (len_ptr)) | ||||
{ | ||||
int error = false; | ||||
start_range = (uint64_t)SnortStrtol((char *)star | ||||
t_ptr, (char**)&ret_ptr, 10); | ||||
if ((errno == ERANGE) || (start_ptr == ret_ptr) | ||||
|| (start_range > 0xFFFFFFFF)) | ||||
{ | ||||
error = true; | ||||
} | ||||
ret_ptr = NULL; | ||||
end_range = (uint64_t)SnortStrtol((char *)end_pt | ||||
r, (char**)&ret_ptr, 10); | ||||
if ((errno == ERANGE) || (end_ptr == ret_ptr) || | ||||
(end_range > 0xFFFFFFFF)) | ||||
{ | ||||
error = true; | ||||
} | ||||
ret_ptr = NULL; | ||||
len = (uint64_t)SnortStrtol((char *)len_ptr, (ch | ||||
ar**)&ret_ptr, 10); | ||||
if ((errno == ERANGE) || (len_ptr == ret_ptr) || | ||||
(len > 0xFFFFFFFF)) | ||||
{ | ||||
error = true; | ||||
} | ||||
if (error == false) | ||||
{ | ||||
if (((end_range - start_range) + 1) == len) | ||||
{ | ||||
header_ptr->range_flag = RANGE_WITH_RESP | ||||
_FULL_CONTENT; | ||||
} | ||||
else | ||||
{ | ||||
header_ptr->range_flag = RANGE_WITH_RESP | ||||
_PARTIAL_CONTENT; | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
header_ptr->range_flag = RANGE_WITH_RESP_ERR | ||||
OR; | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
header_ptr->range_flag = RANGE_WITH_RESP_ERROR; | ||||
} | ||||
crlf = (u_char *)SnortStrnStr((const char *)p, end - | ||||
p, "\n"); | ||||
if (crlf) | ||||
{ | ||||
return p; | ||||
} | ||||
else | ||||
{ | ||||
header_ptr->header.uri_end = end; | ||||
return end; | ||||
} | ||||
} | ||||
} | ||||
else if (*p == '*') | ||||
{ | ||||
/* To check pattern, "* /<total_len>" and set flag accor | ||||
dingly */ | ||||
header_ptr->range_flag = RANGE_WITH_UNKNOWN_CONTENT_RANG | ||||
E; | ||||
p++; | ||||
if (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
if (*p == '/') | ||||
{ | ||||
p++; | ||||
if (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
if (isdigit((int)*p)) | ||||
{ | ||||
p++; | ||||
while (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
if (isdigit((int)*p)) | ||||
{ | ||||
p++; | ||||
continue; | ||||
} | ||||
else if ((*p == '\r') || (*p == '\n' | ||||
)) /* digit followed by \r or \n */ | ||||
{ | ||||
crlf = (u_char *)SnortStrnStr((c | ||||
onst char *)p, end - p, "\n"); | ||||
if (crlf) | ||||
{ | ||||
return p; | ||||
} | ||||
else | ||||
{ | ||||
header_ptr->header.uri_end = | ||||
end; | ||||
return end; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
} | ||||
} | ||||
} | ||||
} | ||||
header_ptr->range_flag = RANGE_WITH_RESP_ERROR; | ||||
crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n" | ||||
); | ||||
if (crlf) | ||||
{ | ||||
p = crlf; | ||||
return p; | ||||
} | ||||
else | ||||
{ | ||||
header_ptr->header.uri_end = end; | ||||
return end; | ||||
} | ||||
} | ||||
else | ||||
{ | ||||
/* other than byte range is out of scope for snort */ | ||||
while (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
if ((*p == '\r') || (*p == '\n')) | ||||
{ | ||||
header_ptr->range_flag = RANGE_WITH_RESP_NON_BYTE; | ||||
crlf = (u_char *)SnortStrnStr((const char *)p, end - | ||||
p, "\n"); | ||||
if (crlf) | ||||
{ | ||||
p = crlf; | ||||
return p; | ||||
} | ||||
else | ||||
{ | ||||
header_ptr->header.uri_end = end; | ||||
return end; | ||||
} | ||||
} | ||||
p++; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
} | ||||
header_ptr->range_flag = RANGE_WITH_RESP_ERROR; | ||||
crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n"); | ||||
if (crlf) | ||||
{ | ||||
p = crlf; | ||||
return p; | ||||
} | ||||
else | ||||
{ | ||||
header_ptr->header.uri_end = end; | ||||
return end; | ||||
} | ||||
} | ||||
/* extract_http_accept_ranges will extract and set flag based on bytes unit */ | ||||
static const u_char *extract_http_accept_ranges(HI_SESSION *Session, | ||||
const u_char *p, const u_char *start, const u_char *end, | ||||
HEADER_PTR *header_ptr, uint16_t *accept_range_flag) | ||||
{ | ||||
const u_char *start_ptr = NULL; | ||||
const u_char *end_ptr = NULL; | ||||
u_char *crlf = NULL; | ||||
int len = 0; | ||||
*accept_range_flag = ACCEPT_RANGE_UNKNOWN; | ||||
SkipBlankSpace(start,end,&p); | ||||
if (hi_util_in_bounds(start, end, p) && (*p == ':')) | ||||
{ | ||||
p++; | ||||
CheckSkipAlertMultipleColon(Session, start, end, &p, HI_SI_SERVER_MODE); | ||||
while (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
if ((*p == ' ') || (*p == '\t') || (*p == ',')) | ||||
{ | ||||
p++; | ||||
break; | ||||
} | ||||
p++; | ||||
} | ||||
if (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
start_ptr = p; | ||||
while (hi_util_in_bounds(start, end, p)) | ||||
{ | ||||
if ((*p == '\r') || (*p == '\n')) | ||||
{ | ||||
end_ptr = (p - 1); | ||||
break; | ||||
} | ||||
p++; | ||||
} | ||||
if (start_ptr && end_ptr) | ||||
{ | ||||
len = end_ptr - start_ptr; | ||||
if ((len >= 5) && (SnortStrcasestr((const char *)start, len, "by | ||||
tes"))) | ||||
{ | ||||
*accept_range_flag = ACCEPT_RANGE_BYTES; | ||||
} | ||||
else if ((len >= 4) && (!strncasecmp((const char *)start, "none" | ||||
, 4))) | ||||
{ | ||||
*accept_range_flag = ACCEPT_RANGE_NONE; | ||||
} | ||||
else | ||||
{ | ||||
*accept_range_flag = ACCEPT_RANGE_OTHER; | ||||
} | ||||
} | ||||
} | ||||
} | ||||
crlf = (u_char *)SnortStrnStr((const char *)p, end - p, "\n"); | ||||
if (crlf) | ||||
{ | ||||
p = crlf; | ||||
return p; | ||||
} | ||||
else | ||||
{ | ||||
header_ptr->header.uri_end = end; | ||||
return end; | ||||
} | ||||
} | ||||
const u_char *extract_http_transfer_encoding(HI_SESSION *Session, HttpSessionDat a *hsd, | const u_char *extract_http_transfer_encoding(HI_SESSION *Session, HttpSessionDat a *hsd, | |||
const u_char *p, const u_char *start, const u_char *end, | const u_char *p, const u_char *start, const u_char *end, | |||
HEADER_PTR *header_ptr, int iInspectMode) | HEADER_PTR *header_ptr, int iInspectMode) | |||
{ | { | |||
uint8_t unfold_buf[DECODE_BLEN]; | uint8_t unfold_buf[DECODE_BLEN]; | |||
uint32_t unfold_size =0; | uint32_t unfold_size =0; | |||
const u_char *start_ptr, *end_ptr, *cur_ptr; | const u_char *start_ptr, *end_ptr, *cur_ptr; | |||
SkipBlankSpace(start,end,&p); | SkipBlankSpace(start,end,&p); | |||
skipping to change at line 924 | skipping to change at line 1304 | |||
parse_cont_encoding) | parse_cont_encoding) | |||
{ | { | |||
p = extract_http_content_encoding(ServerConf, p, start, end, header_ ptr, header_field_ptr,Session); | p = extract_http_content_encoding(ServerConf, p, start, end, header_ ptr, header_field_ptr,Session); | |||
} | } | |||
else if ( IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_LENGTH , | else if ( IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_LENGTH , | |||
HTTPRESP_HEADER_LENGTH__CONTENT_LENGTH) ) | HTTPRESP_HEADER_LENGTH__CONTENT_LENGTH) ) | |||
{ | { | |||
if(hsd && !hsd->resp_state.last_pkt_chunked) | if(hsd && !hsd->resp_state.last_pkt_chunked) | |||
p = extract_http_content_length(Session, ServerConf, p, start, e nd, header_ptr, header_field_ptr, HI_SI_SERVER_MODE ); | p = extract_http_content_length(Session, ServerConf, p, start, e nd, header_ptr, header_field_ptr, HI_SI_SERVER_MODE ); | |||
} | } | |||
else if (IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__CONTENT_RANGE, | ||||
HTTPRESP_HEADER_LENGTH__CONTENT_RANGE)) | ||||
{ | ||||
p = p + HTTPRESP_HEADER_LENGTH__CONTENT_RANGE; | ||||
p = extract_http_content_range(Session, p, start, end, header_ptr); | ||||
} | ||||
} | } | |||
else if (((p - offset) == 0) && ((*p == 'T') || (*p == 't'))) | else if (((p - offset) == 0) && ((*p == 'T') || (*p == 't'))) | |||
{ | { | |||
if ( IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__TRANSFER_ENCODING, | if ( IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__TRANSFER_ENCODING, | |||
HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING) && par se_trans_encoding ) | HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING) && par se_trans_encoding ) | |||
{ | { | |||
p = p + HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING; | p = p + HTTPRESP_HEADER_LENGTH__TRANSFER_ENCODING; | |||
p = extract_http_transfer_encoding(Session, hsd, p, start, end, head er_ptr, HI_SI_SERVER_MODE); | p = extract_http_transfer_encoding(Session, hsd, p, start, end, head er_ptr, HI_SI_SERVER_MODE); | |||
} | } | |||
} | } | |||
else if (((p - offset) == 0) && ((*p == 'A') || (*p == 'a'))) | ||||
{ | ||||
if (IsHeaderFieldName(p, end, HTTPRESP_HEADER_NAME__ACCEPT_RANGES, | ||||
HTTPRESP_HEADER_LENGTH__ACCEPT_RANGES)) | ||||
{ | ||||
uint16_t accept_range_flag = 0; | ||||
p = p + HTTPRESP_HEADER_LENGTH__ACCEPT_RANGES; | ||||
p = extract_http_accept_ranges(Session, p, start, end, header_ptr, & | ||||
accept_range_flag); | ||||
Session->server.response.accept_range_flag = accept_range_flag; | ||||
} | ||||
} | ||||
#if defined(FEAT_OPEN_APPID) | #if defined(FEAT_OPEN_APPID) | |||
else if(((p - offset) == 0) && ((*p == 'V') || (*p == 'v'))) | else if(((p - offset) == 0) && ((*p == 'V') || (*p == 'v'))) | |||
{ | { | |||
if((ServerConf->appid_enabled) && (IsHeaderFieldName(p, end, HEADER_NAME __VIA, HEADER_LENGTH__VIA))) | if((ServerConf->appid_enabled) && (IsHeaderFieldName(p, end, HEADER_NAME __VIA, HEADER_LENGTH__VIA))) | |||
{ | { | |||
p = p + HEADER_LENGTH__VIA; | p = p + HEADER_LENGTH__VIA; | |||
p = extract_http_server_header(Session, p, start, end, header_ptr, & header_ptr->via); | p = extract_http_server_header(Session, p, start, end, header_ptr, & header_ptr->via); | |||
} | } | |||
} | } | |||
else if(((p - offset) == 0) && ((*p == 'X') || (*p == 'x'))) | else if(((p - offset) == 0) && ((*p == 'X') || (*p == 'x'))) | |||
skipping to change at line 1986 | skipping to change at line 2382 | |||
if ( stat_msg_ptr.uri ) | if ( stat_msg_ptr.uri ) | |||
{ | { | |||
Server->response.status_msg = stat_msg_ptr.uri; | Server->response.status_msg = stat_msg_ptr.uri; | |||
Server->response.status_msg_size = stat_msg_ptr.uri_end - st at_msg_ptr.uri; | Server->response.status_msg_size = stat_msg_ptr.uri_end - st at_msg_ptr.uri; | |||
if ((int)Server->response.status_msg_size <= 0) | if ((int)Server->response.status_msg_size <= 0) | |||
{ | { | |||
CLR_SERVER_STAT_MSG(Server); | CLR_SERVER_STAT_MSG(Server); | |||
} | } | |||
{ | { | |||
header_ptr.range_flag = HTTP_RANGE_NONE; | ||||
ptr = hi_server_extract_header(Session, ServerConf, &he ader_ptr, | ptr = hi_server_extract_header(Session, ServerConf, &he ader_ptr, | |||
stat_msg_ptr.uri_end , end, parse_co nt_encoding, parse_trans_encoding, sd ); | stat_msg_ptr.uri_end , end, parse_co nt_encoding, parse_trans_encoding, sd ); | |||
if (header_ptr.range_flag != HTTP_RANGE_NONE) | ||||
{ | ||||
Server->response.range_flag = header_ptr.range_flag; | ||||
} | ||||
else | ||||
{ | ||||
Server->response.range_flag = HTTP_RESP_RANGE_NONE; | ||||
} | ||||
} | } | |||
} | } | |||
else | else | |||
{ | { | |||
CLR_SERVER_STAT(Server); | CLR_SERVER_STAT(Server); | |||
} | } | |||
} | } | |||
if (header_ptr.header.uri) | if (header_ptr.header.uri) | |||
{ | { | |||
End of changes. 6 change blocks. | ||||
0 lines changed or deleted | 438 lines changed or added |