mirror of
https://github.com/zeek/zeek.git
synced 2025-10-08 17:48:21 +00:00
Allow '<' and '>' in MIME multipart boundaries.
The spec doesn't actually seem to permit these, but Seth had a (private) pcap showing them used in the wild (and the HTTP/MIME analyzer failed to parse content as a result).
This commit is contained in:
parent
c870fefbef
commit
08822e0dd4
3 changed files with 42 additions and 38 deletions
|
@ -1025,8 +1025,11 @@ void HTTP_Analyzer::DeliverStream(int len, const u_char* data, bool is_orig)
|
|||
}
|
||||
else
|
||||
{
|
||||
ProtocolViolation("not a http reply line");
|
||||
reply_state = EXPECT_REPLY_NOTHING;
|
||||
if ( line != end_of_line )
|
||||
{
|
||||
ProtocolViolation("not a http reply line");
|
||||
reply_state = EXPECT_REPLY_NOTHING;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
|
|
@ -246,11 +246,16 @@ int MIME_get_field_name(int len, const char* data, data_chunk_t* name)
|
|||
}
|
||||
|
||||
// See RFC 2045, page 12.
|
||||
int MIME_is_tspecial (char ch)
|
||||
int MIME_is_tspecial (char ch, bool is_boundary = false)
|
||||
{
|
||||
return ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '@' ||
|
||||
ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' ||
|
||||
ch == '/' || ch == '[' || ch == ']' || ch == '?' || ch == '=';
|
||||
if ( is_boundary )
|
||||
return ch == '(' || ch == ')' || ch == '@' ||
|
||||
ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' ||
|
||||
ch == '/' || ch == '[' || ch == ']' || ch == '?' || ch == '=';
|
||||
else
|
||||
return ch == '(' || ch == ')' || ch == '<' || ch == '>' || ch == '@' ||
|
||||
ch == ',' || ch == ';' || ch == ':' || ch == '\\' || ch == '"' ||
|
||||
ch == '/' || ch == '[' || ch == ']' || ch == '?' || ch == '=';
|
||||
}
|
||||
|
||||
int MIME_is_field_name_char (char ch)
|
||||
|
@ -258,26 +263,27 @@ int MIME_is_field_name_char (char ch)
|
|||
return ch >= 33 && ch <= 126 && ch != ':';
|
||||
}
|
||||
|
||||
int MIME_is_token_char (char ch)
|
||||
int MIME_is_token_char (char ch, bool is_boundary = false)
|
||||
{
|
||||
return ch >= 33 && ch <= 126 && ! MIME_is_tspecial(ch);
|
||||
return ch >= 33 && ch <= 126 && ! MIME_is_tspecial(ch, is_boundary);
|
||||
}
|
||||
|
||||
// See RFC 2045, page 12.
|
||||
// A token is composed of characters that are not SPACE, CTLs or tspecials
|
||||
int MIME_get_token(int len, const char* data, data_chunk_t* token)
|
||||
int MIME_get_token(int len, const char* data, data_chunk_t* token,
|
||||
bool is_boundary)
|
||||
{
|
||||
int i = MIME_skip_lws_comments(len, data);
|
||||
while ( i < len )
|
||||
{
|
||||
int j;
|
||||
|
||||
if ( MIME_is_token_char(data[i]) )
|
||||
if ( MIME_is_token_char(data[i], is_boundary) )
|
||||
{
|
||||
token->data = (data + i);
|
||||
for ( j = i; j < len; ++j )
|
||||
{
|
||||
if ( ! MIME_is_token_char(data[j]) )
|
||||
if ( ! MIME_is_token_char(data[j], is_boundary) )
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -359,7 +365,7 @@ int MIME_get_quoted_string(int len, const char* data, data_chunk_t* str)
|
|||
return -1;
|
||||
}
|
||||
|
||||
int MIME_get_value(int len, const char* data, BroString*& buf)
|
||||
int MIME_get_value(int len, const char* data, BroString*& buf, bool is_boundary)
|
||||
{
|
||||
int offset = MIME_skip_lws_comments(len, data);
|
||||
|
||||
|
@ -380,7 +386,7 @@ int MIME_get_value(int len, const char* data, BroString*& buf)
|
|||
else
|
||||
{
|
||||
data_chunk_t str;
|
||||
int end = MIME_get_token(len, data, &str);
|
||||
int end = MIME_get_token(len, data, &str, is_boundary);
|
||||
if ( end < 0 )
|
||||
return -1;
|
||||
|
||||
|
@ -863,8 +869,22 @@ int MIME_Entity::ParseFieldParameters(int len, const char* data)
|
|||
len -= offset;
|
||||
|
||||
BroString* val = 0;
|
||||
// token or quoted-string
|
||||
offset = MIME_get_value(len, data, val);
|
||||
|
||||
if ( current_field_type == MIME_CONTENT_TYPE &&
|
||||
content_type == CONTENT_TYPE_MULTIPART &&
|
||||
strcasecmp_n(attr, "boundary") == 0 )
|
||||
{
|
||||
// token or quoted-string (and some lenience for characters
|
||||
// not explicitly allowed by the RFC, but encountered in the wild)
|
||||
offset = MIME_get_value(len, data, val, true);
|
||||
data_chunk_t vd = get_data_chunk(val);
|
||||
multipart_boundary = new BroString((const u_char*)vd.data,
|
||||
vd.length, 1);
|
||||
}
|
||||
else
|
||||
// token or quoted-string
|
||||
offset = MIME_get_value(len, data, val);
|
||||
|
||||
if ( offset < 0 )
|
||||
{
|
||||
IllegalFormat("value not found in parameter specification");
|
||||
|
@ -874,8 +894,6 @@ int MIME_Entity::ParseFieldParameters(int len, const char* data)
|
|||
|
||||
data += offset;
|
||||
len -= offset;
|
||||
|
||||
ParseParameter(attr, get_data_chunk(val));
|
||||
delete val;
|
||||
}
|
||||
|
||||
|
@ -920,24 +938,6 @@ void MIME_Entity::ParseContentEncoding(data_chunk_t encoding_mechanism)
|
|||
content_encoding = i;
|
||||
}
|
||||
|
||||
void MIME_Entity::ParseParameter(data_chunk_t attr, data_chunk_t val)
|
||||
{
|
||||
switch ( current_field_type ) {
|
||||
case MIME_CONTENT_TYPE:
|
||||
if ( content_type == CONTENT_TYPE_MULTIPART &&
|
||||
strcasecmp_n(attr, "boundary") == 0 )
|
||||
multipart_boundary = new BroString((const u_char*)val.data, val.length, 1);
|
||||
break;
|
||||
|
||||
case MIME_CONTENT_TRANSFER_ENCODING:
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int MIME_Entity::CheckBoundaryDelimiter(int len, const char* data)
|
||||
{
|
||||
if ( ! multipart_boundary )
|
||||
|
|
|
@ -117,7 +117,6 @@ protected:
|
|||
|
||||
void ParseContentType(data_chunk_t type, data_chunk_t sub_type);
|
||||
void ParseContentEncoding(data_chunk_t encoding_mechanism);
|
||||
void ParseParameter(data_chunk_t attr, data_chunk_t val);
|
||||
|
||||
void BeginBody();
|
||||
void NewDataLine(int len, const char* data, int trailing_CRLF);
|
||||
|
@ -275,9 +274,11 @@ extern int MIME_count_leading_lws(int len, const char* data);
|
|||
extern int MIME_count_trailing_lws(int len, const char* data);
|
||||
extern int MIME_skip_comments(int len, const char* data);
|
||||
extern int MIME_skip_lws_comments(int len, const char* data);
|
||||
extern int MIME_get_token(int len, const char* data, data_chunk_t* token);
|
||||
extern int MIME_get_token(int len, const char* data, data_chunk_t* token,
|
||||
bool is_boundary = false);
|
||||
extern int MIME_get_slash_token_pair(int len, const char* data, data_chunk_t* first, data_chunk_t* second);
|
||||
extern int MIME_get_value(int len, const char* data, BroString*& buf);
|
||||
extern int MIME_get_value(int len, const char* data, BroString*& buf,
|
||||
bool is_boundary = false);
|
||||
extern int MIME_get_field_name(int len, const char* data, data_chunk_t* name);
|
||||
extern BroString* MIME_decode_quoted_pairs(data_chunk_t buf);
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue