Fail more cleanly if the file has no records.

If we have no records, we can't determine the link-layer type.

Also:

Use more signed values, and do more sanity checks on the file header and
TLVs to make sure we don't run into the first packet.

When writing the file header, accumulate the header length/first packet
offset in a 32-bit variable, and stuff it into the
offset-to-first-packet fields (plural) once we're done.

Change-Id: I3aeb5258bc16ddd8cf0ec86ef379287d0c4b351a
Reviewed-on: https://code.wireshark.org/review/30620
Reviewed-by: Guy Harris <guy@alum.mit.edu>
This commit is contained in:
Guy Harris 2018-11-13 21:27:38 -08:00
parent 341c3f3c62
commit 13eefba79c
1 changed files with 93 additions and 33 deletions

View File

@ -118,12 +118,12 @@ static gint wtap_to_observer_encap(int wtap_encap);
wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_info)
{
int offset;
guint offset;
capture_file_header file_header;
guint header_offset;
guint i;
tlv_header tlvh;
int seek_increment;
int header_offset;
guint seek_increment;
packet_entry_header packet_header;
observer_dump_private_state * private_state = NULL;
@ -136,7 +136,7 @@ wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_i
return WTAP_OPEN_ERROR;
return WTAP_OPEN_NOT_MINE;
}
offset += (int)sizeof file_header;
offset += (guint)sizeof file_header;
CAPTURE_FILE_HEADER_FROM_LE_IN_PLACE(file_header);
/* check if version info is present */
@ -144,25 +144,46 @@ wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_i
return WTAP_OPEN_NOT_MINE;
}
/* get the location of the first packet */
/* v15 and newer uses high byte offset, in previous versions it will be 0 */
header_offset = file_header.offset_to_first_packet + ((guint)(file_header.offset_to_first_packet_high_byte)<<16);
if (offset > header_offset) {
/*
* The packet data begins before the file header ends.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("Observer: The first packet begins in the middle of the file header");
return WTAP_OPEN_ERROR;
}
/* initialize the private state */
private_state = (observer_dump_private_state *) g_malloc(sizeof(observer_dump_private_state));
private_state->time_format = TIME_INFO_LOCAL;
wth->priv = (void *) private_state;
/* get the location of the first packet */
/* v15 and newer uses high byte offset, in previous versions it will be 0 */
header_offset = file_header.offset_to_first_packet + ((int)(file_header.offset_to_first_packet_high_byte)<<16);
/* process extra information */
for (i = 0; i < file_header.number_of_information_elements; i++) {
/* for safety break if we've reached the first packet */
if (offset >= header_offset)
break;
guint tlv_data_length;
/*
* Make sure reading the TLV header won't put us in the middle
* of the packet data.
*/
if (offset + (guint)sizeof tlvh > header_offset) {
/*
* We're at or past the point where the packet data begins,
* but we have the IE header to read.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("Observer: TLVs run into the first packet data");
return WTAP_OPEN_ERROR;
}
/* read the TLV header */
if (!wtap_read_bytes(wth->fh, &tlvh, sizeof tlvh, err, err_info))
return WTAP_OPEN_ERROR;
offset += (int)sizeof tlvh;
offset += (guint)sizeof tlvh;
TLV_HEADER_FROM_LE_IN_PLACE(tlvh);
if (tlvh.length < sizeof tlvh) {
@ -172,44 +193,80 @@ wtap_open_return_val network_instruments_open(wtap *wth, int *err, gchar **err_i
return WTAP_OPEN_ERROR;
}
tlv_data_length = tlvh.length - (guint)sizeof tlvh;
/*
* Make sure reading the TLV data won't put us in the middle
* of the packet data.
*/
if (offset + tlv_data_length > header_offset) {
/*
* We're at or past the point where the packet data begins,
* but we have the IE data to read.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("Observer: TLVs run into the first packet data");
return WTAP_OPEN_ERROR;
}
/* process (or skip over) the current TLV */
switch (tlvh.type) {
case INFORMATION_TYPE_TIME_INFO:
/* XXX - what if tlvh.length != sizeof sizeof private_state->time_format? */
if (tlvh.length != sizeof tlvh + sizeof private_state->time_format) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("Observer: bad record (time information TLV length %u != %lu)",
tlvh.length,
(unsigned long)(sizeof tlvh + sizeof private_state->time_format));
return WTAP_OPEN_ERROR;
}
if (!wtap_read_bytes(wth->fh, &private_state->time_format,
sizeof private_state->time_format,
err, err_info))
return WTAP_OPEN_ERROR;
private_state->time_format = GUINT32_FROM_LE(private_state->time_format);
offset += (int)sizeof private_state->time_format;
offset += (guint)sizeof private_state->time_format;
break;
default:
seek_increment = tlvh.length - (int)sizeof tlvh;
if (seek_increment > 0) {
if (!wtap_read_bytes(wth->fh, NULL, seek_increment, err, err_info))
tlv_data_length = tlvh.length - (guint)sizeof tlvh;
if (tlv_data_length > 0) {
if (!wtap_read_bytes(wth->fh, NULL, tlv_data_length, err, err_info))
return WTAP_OPEN_ERROR;
}
offset += seek_increment;
offset += tlv_data_length;
}
}
/* get to the first packet */
if (header_offset < offset) {
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("Observer: bad record (offset to first packet %d < %d)",
header_offset, offset);
return WTAP_OPEN_ERROR;
}
seek_increment = header_offset - offset;
if (seek_increment > 0) {
if (seek_increment != 0) {
if (!wtap_read_bytes(wth->fh, NULL, seek_increment, err, err_info))
return WTAP_OPEN_ERROR;
}
/* pull off the packet header */
if (!wtap_read_bytes(wth->fh, &packet_header, sizeof packet_header,
err, err_info))
/*
* We assume that all packets in a file have the same network type,
* whether they're data or expert information packets, and thus
* we can attempt to determine the network type by reading the
* first packet.
*
* If that's *not* the case, we need to use WTAP_ENCAP_PER_PACKET.
*
* Read the packet header. Don't assume there *is* a packet;
* if there isn't, report that as a bad file. (If we use
* WTAP_ENCAP_PER_PACKET, we don't need to handle that case, as
* we don't need to read the first packet.
*/
if (!wtap_read_bytes_or_eof(wth->fh, &packet_header, sizeof packet_header,
err, err_info)) {
if (*err == 0) {
/*
* EOF, so there *are* no records.
*/
*err = WTAP_ERR_BAD_FILE;
*err_info = g_strdup_printf("Observer: No records in the file, so we can't determine the link-layer type");
}
return WTAP_OPEN_ERROR;
}
PACKET_ENTRY_HEADER_FROM_LE_IN_PLACE(packet_header);
/* check the packet's magic number */
@ -603,7 +660,7 @@ gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
{
observer_dump_private_state * private_state = NULL;
capture_file_header file_header;
guint header_offset;
tlv_header comment_header;
tlv_time_info time_header;
char comment[64];
@ -624,8 +681,7 @@ gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
/* initialize the file header */
memset(&file_header, 0x00, sizeof(file_header));
g_strlcpy(file_header.observer_version, network_instruments_magic, 31);
file_header.offset_to_first_packet = (guint16)sizeof(file_header);
file_header.offset_to_first_packet_high_byte = 0;
header_offset = (guint16)sizeof(file_header);
/* create the file comment TLV */
{
@ -643,7 +699,7 @@ gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
/* update the file header to account for the comment TLV */
file_header.number_of_information_elements++;
file_header.offset_to_first_packet += comment_header.length;
header_offset += comment_header.length;
}
/* create the timestamp encoding TLV */
@ -654,9 +710,13 @@ gboolean network_instruments_dump_open(wtap_dumper *wdh, int *err)
/* update the file header to account for the timestamp encoding TLV */
file_header.number_of_information_elements++;
file_header.offset_to_first_packet += time_header.length;
header_offset += time_header.length;
}
/* Store the offset to the first packet */
file_header.offset_to_first_packet_high_byte = (header_offset >> 16);
file_header.offset_to_first_packet = (header_offset & 0xFFFF);
/* write the file header, swapping any multibyte fields first */
CAPTURE_FILE_HEADER_TO_LE_IN_PLACE(file_header);
if (!wtap_dump_file_write(wdh, &file_header, sizeof(file_header), err)) {