diff options
author | Guy Harris <guy@alum.mit.edu> | 2019-06-12 11:32:21 -0700 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2019-06-12 11:32:21 -0700 |
commit | 2e9d0ae34ece4d6f67f4d66a4c3628febf0b13dd (patch) | |
tree | c09a4191cd220422464f94b1806556d14307a2eb | |
parent | 978ccfe2193d270ad7e22ca0c7420b41e9de4f2c (diff) | |
download | libpcap-2e9d0ae34ece4d6f67f4d66a4c3628febf0b13dd.tar.gz |
Read the magic number into a byte array.
Apparently, in some C implementations, attempting to do an fread() into
a variable of a 32-bit unsigned integral type with a size of 1 and a
count of 4 returns 0 with an EOF indication; see GitHub pull request
We can make the size be the size of the variable and the count be 1, but
that means that the count returned by an fread() terminated by an EOF
will be 0, not the number of bytes successfully read, so the "truncated
dump file" message will give an invalid count:
tcpdump: truncated dump file; tried to read 4 file header bytes,
only got 0
If, instead, we read into an array of 4 bytes, with a size of 1 and a
count of 4, we'll get the right short count back.
Pass the byte array to the file-type-specific "is this a file of this
type?" routines, so that if we add support for files where the magic
number isn't byte-order dependent (e.g., Microsoft Network Monitor), we
can handle them more cleanly (check for the standard magic number as a
4-byte array, rather than as its numerical value in both the host's byte
order and the byte-swapped byte order).
-rw-r--r-- | savefile.c | 8 | ||||
-rw-r--r-- | sf-pcap.c | 24 | ||||
-rw-r--r-- | sf-pcap.h | 2 | ||||
-rw-r--r-- | sf-pcapng.c | 14 | ||||
-rw-r--r-- | sf-pcapng.h | 2 |
5 files changed, 28 insertions, 22 deletions
@@ -332,7 +332,7 @@ pcap_t* pcap_hopen_offline(intptr_t osfd, char *errbuf) } #endif -static pcap_t *(*check_headers[])(bpf_u_int32, FILE *, u_int, char *, int *) = { +static pcap_t *(*check_headers[])(const uint8_t *, FILE *, u_int, char *, int *) = { pcap_check_header, pcap_ng_check_header }; @@ -347,7 +347,7 @@ pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision, char *errbuf) { register pcap_t *p; - bpf_u_int32 magic; + uint8_t magic[4]; size_t amt_read; u_int i; int err; @@ -359,8 +359,8 @@ pcap_fopen_offline_with_tstamp_precision(FILE *fp, u_int precision, * Windows Sniffer, and Microsoft Network Monitor) all have magic * numbers that are unique in their first 4 bytes. */ - amt_read = fread(&magic, sizeof(magic), 1, fp); - if (amt_read != 1) { + amt_read = fread(&magic, 1, sizeof(magic), fp); + if (amt_read != sizeof(magic)) { if (ferror(fp)) { pcap_fmt_errmsg_for_errno(errbuf, PCAP_ERRBUF_SIZE, errno, "error reading dump file"); @@ -150,9 +150,10 @@ struct pcap_sf { * relevant information from the header. */ pcap_t * -pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, +pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf, int *err) { + bpf_u_int32 magic_int; struct pcap_file_header hdr; size_t amt_read; pcap_t *p; @@ -169,11 +170,14 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, * number for a pcap savefile, or for a byte-swapped pcap * savefile. */ - if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC && - magic != NSEC_TCPDUMP_MAGIC) { - magic = SWAPLONG(magic); - if (magic != TCPDUMP_MAGIC && magic != KUZNETZOV_TCPDUMP_MAGIC && - magic != NSEC_TCPDUMP_MAGIC) + memcpy(&magic_int, magic, sizeof(magic_int)); + if (magic_int != TCPDUMP_MAGIC && + magic_int != KUZNETZOV_TCPDUMP_MAGIC && + magic_int != NSEC_TCPDUMP_MAGIC) { + magic_int = SWAPLONG(magic_int); + if (magic_int != TCPDUMP_MAGIC && + magic_int != KUZNETZOV_TCPDUMP_MAGIC && + magic_int != NSEC_TCPDUMP_MAGIC) return (NULL); /* nope */ swapped = 1; } @@ -182,7 +186,7 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, * They are. Put the magic number in the header, and read * the rest of the header. */ - hdr.magic = magic; + hdr.magic = magic_int; amt_read = fread(((char *)&hdr) + sizeof hdr.magic, 1, sizeof(hdr) - sizeof(hdr.magic), fp); if (amt_read != sizeof(hdr) - sizeof(hdr.magic)) { @@ -273,7 +277,7 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, switch (precision) { case PCAP_TSTAMP_PRECISION_MICRO: - if (magic == NSEC_TCPDUMP_MAGIC) { + if (magic_int == NSEC_TCPDUMP_MAGIC) { /* * The file has nanoseconds, the user * wants microseconds; scale the @@ -290,7 +294,7 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, break; case PCAP_TSTAMP_PRECISION_NANO: - if (magic == NSEC_TCPDUMP_MAGIC) { + if (magic_int == NSEC_TCPDUMP_MAGIC) { /* * The file has nanoseconds, the * user wants nanoseconds; nothing to do. @@ -344,7 +348,7 @@ pcap_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, break; } - if (magic == KUZNETZOV_TCPDUMP_MAGIC) { + if (magic_int == KUZNETZOV_TCPDUMP_MAGIC) { /* * XXX - the patch that's in some versions of libpcap * changes the packet header but not the magic number, @@ -31,7 +31,7 @@ #ifndef sf_pcap_h #define sf_pcap_h -extern pcap_t *pcap_check_header(bpf_u_int32 magic, FILE *fp, +extern pcap_t *pcap_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf, int *err); #endif diff --git a/sf-pcapng.c b/sf-pcapng.c index 7394ce46..52f795f7 100644 --- a/sf-pcapng.c +++ b/sf-pcapng.c @@ -761,9 +761,10 @@ add_interface(pcap_t *p, struct block_cursor *cursor, char *errbuf) * relevant information from the header. */ pcap_t * -pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, - int *err) +pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision, + char *errbuf, int *err) { + bpf_u_int32 magic_int; size_t amt_read; bpf_u_int32 total_length; bpf_u_int32 byte_order_magic; @@ -785,7 +786,8 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, * Check whether the first 4 bytes of the file are the block * type for a pcapng savefile. */ - if (magic != BT_SHB) { + memcpy(&magic_int, magic, sizeof(magic_int)); + if (magic_int != BT_SHB) { /* * XXX - check whether this looks like what the block * type would be after being munged by mapping between @@ -944,12 +946,12 @@ pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, u_int precision, char *errbuf, */ bhdrp = (struct block_header *)p->buffer; shbp = (struct section_header_block *)((u_char *)p->buffer + sizeof(struct block_header)); - bhdrp->block_type = magic; + bhdrp->block_type = magic_int; bhdrp->total_length = total_length; shbp->byte_order_magic = byte_order_magic; if (read_bytes(fp, - (u_char *)p->buffer + (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)), - total_length - (sizeof(magic) + sizeof(total_length) + sizeof(byte_order_magic)), + (u_char *)p->buffer + (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)), + total_length - (sizeof(magic_int) + sizeof(total_length) + sizeof(byte_order_magic)), 1, errbuf) == -1) goto fail; diff --git a/sf-pcapng.h b/sf-pcapng.h index d99b0d4e..835082a5 100644 --- a/sf-pcapng.h +++ b/sf-pcapng.h @@ -26,7 +26,7 @@ #ifndef sf_pcapng_h #define sf_pcapng_h -extern pcap_t *pcap_ng_check_header(bpf_u_int32 magic, FILE *fp, +extern pcap_t *pcap_ng_check_header(const uint8_t *magic, FILE *fp, u_int precision, char *errbuf, int *err); #endif |