diff options
author | Guy Harris <guy@alum.mit.edu> | 2014-01-22 00:26:36 +0000 |
---|---|---|
committer | Guy Harris <guy@alum.mit.edu> | 2014-01-22 00:26:36 +0000 |
commit | 90d7c5f59b574e254bc1bb70aaaf12372fe97cc3 (patch) | |
tree | 7bc8e69b7cc459b8dfef190d1b33a7cb092a7bf3 /wiretap | |
parent | 5c825d6a364d83dace7b6c682aa47678e89df79b (diff) |
Don't write out packets that have a "captured length" bigger than we're
willing to read or that's bigger than will fit in the file format;
instead, report an error.
For the "I can't write a packet of that type in that file type" error,
report the file type in question.
svn path=/trunk/; revision=54882
Diffstat (limited to 'wiretap')
-rw-r--r-- | wiretap/5views.c | 6 | ||||
-rw-r--r-- | wiretap/btsnoop.c | 15 | ||||
-rw-r--r-- | wiretap/commview.c | 8 | ||||
-rw-r--r-- | wiretap/erf.c | 13 | ||||
-rw-r--r-- | wiretap/eyesdn.c | 8 | ||||
-rw-r--r-- | wiretap/k12.c | 6 | ||||
-rw-r--r-- | wiretap/k12text.l | 6 | ||||
-rw-r--r-- | wiretap/lanalyzer.c | 8 | ||||
-rw-r--r-- | wiretap/libpcap.c | 6 | ||||
-rw-r--r-- | wiretap/netmon.c | 28 | ||||
-rw-r--r-- | wiretap/nettl.c | 6 | ||||
-rw-r--r-- | wiretap/network_instruments.c | 7 | ||||
-rw-r--r-- | wiretap/netxray.c | 13 | ||||
-rw-r--r-- | wiretap/ngsniffer.c | 7 | ||||
-rw-r--r-- | wiretap/pcapng.c | 6 | ||||
-rw-r--r-- | wiretap/snoop.c | 7 | ||||
-rw-r--r-- | wiretap/visual.c | 6 | ||||
-rw-r--r-- | wiretap/wtap.c | 3 | ||||
-rw-r--r-- | wiretap/wtap.h | 4 |
19 files changed, 154 insertions, 9 deletions
diff --git a/wiretap/5views.c b/wiretap/5views.c index 5ff61101dc..c43fb35c8d 100644 --- a/wiretap/5views.c +++ b/wiretap/5views.c @@ -372,6 +372,12 @@ static gboolean _5views_dump(wtap_dumper *wdh, _5views_dump_t *_5views = (_5views_dump_t *)wdh->priv; t_5VW_TimeStamped_Header HeaderFrame; + /* Don't write out something bigger than we can read. */ + if (phdr->caplen > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + /* Frame Header */ /* constant fields */ HeaderFrame.Key = GUINT32_TO_LE(CST_5VW_RECORDS_HEADER_KEY); diff --git a/wiretap/btsnoop.c b/wiretap/btsnoop.c index 9fc2cb06f4..3c67f84198 100644 --- a/wiretap/btsnoop.c +++ b/wiretap/btsnoop.c @@ -333,6 +333,15 @@ static gboolean btsnoop_dump_h1(wtap_dumper *wdh, const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header; struct btsnooprec_hdr rec_hdr; + /* + * Don't write out anything bigger than we can read. + * (This will also fail on a caplen of 0, as it should.) + */ + if (phdr->caplen-1 > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + if (!btsnoop_dump_partial_rec_hdr(wdh, phdr, pseudo_header, pd, err, &rec_hdr)) return FALSE; @@ -362,6 +371,12 @@ static gboolean btsnoop_dump_h4(wtap_dumper *wdh, const union wtap_pseudo_header *pseudo_header = &phdr->pseudo_header; struct btsnooprec_hdr rec_hdr; + /* Don't write out anything bigger than we can read. */ + if (phdr->caplen > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + if (!btsnoop_dump_partial_rec_hdr(wdh, phdr, pseudo_header, pd, err, &rec_hdr)) return FALSE; diff --git a/wiretap/commview.c b/wiretap/commview.c index 4283a6f44b..0687a18b69 100644 --- a/wiretap/commview.c +++ b/wiretap/commview.c @@ -277,6 +277,14 @@ static gboolean commview_dump(wtap_dumper *wdh, commview_header_t cv_hdr; struct tm *tm; + /* Don't write out anything bigger than we can read. + * (The length field in packet headers is 16 bits, which + * imposes a hard limit.) */ + if (phdr->caplen > 65535) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + memset(&cv_hdr, 0, sizeof(cv_hdr)); cv_hdr.data_len = GUINT16_TO_LE((guint16)phdr->caplen); diff --git a/wiretap/erf.c b/wiretap/erf.c index 7eebe0a44a..5ac2ae76fe 100644 --- a/wiretap/erf.c +++ b/wiretap/erf.c @@ -153,8 +153,7 @@ extern int erf_open(wtap *wth, int *err, gchar **err_info) if (packet_size > WTAP_MAX_PACKET_SIZE) { /* * Probably a corrupt capture file or a file that's not an ERF file - * but that passed earlier tests; don't blow up trying - * to allocate space for an immensely-large packet. + * but that passed earlier tests. */ return 0; } @@ -239,8 +238,8 @@ extern int erf_open(wtap *wth, int *err, gchar **err_info) is reached whereas the record is truncated */ if (packet_size > WTAP_MAX_PACKET_SIZE) { /* - * Probably a corrupt capture file; don't blow up trying - * to allocate space for an immensely-large packet. + * Probably a corrupt capture file or a file that's not an ERF file + * but that passed earlier tests. */ return 0; } @@ -592,6 +591,12 @@ static gboolean erf_dump( gboolean must_add_crc = FALSE; guint32 crc32 = 0x00000000; + /* Don't write anything bigger than we're willing to read. */ + if(phdr->caplen > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + if(wdh->encap == WTAP_ENCAP_PER_PACKET){ encap = phdr->pkt_encap; }else{ diff --git a/wiretap/eyesdn.c b/wiretap/eyesdn.c index 66897b81df..ea0af9ffdd 100644 --- a/wiretap/eyesdn.c +++ b/wiretap/eyesdn.c @@ -417,6 +417,14 @@ static gboolean eyesdn_dump(wtap_dumper *wdh, int protocol; int size; + /* Don't write out anything bigger than we can read. + * (The length field in packet headers is 16 bits, which + * imposes a hard limit.) */ + if (phdr->caplen > 65535) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + usecs=phdr->ts.nsecs/1000; secs=phdr->ts.secs; size=phdr->caplen; diff --git a/wiretap/k12.c b/wiretap/k12.c index 10687f8412..8dfaef6e0c 100644 --- a/wiretap/k12.c +++ b/wiretap/k12.c @@ -1190,7 +1190,7 @@ static gboolean k12_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, /* encountered in k12_dump_src_setting). */ g_hash_table_foreach(file_data->src_by_id,k12_dump_src_setting,wdh); } - obj.record.len = 0x20 + phdr->len; + obj.record.len = 0x20 + phdr->caplen; obj.record.len += (obj.record.len % 4) ? 4 - obj.record.len % 4 : 0; len = obj.record.len; @@ -1198,12 +1198,12 @@ static gboolean k12_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, obj.record.len = g_htonl(obj.record.len); obj.record.type = g_htonl(K12_REC_PACKET); - obj.record.frame_len = g_htonl(phdr->len); + obj.record.frame_len = g_htonl(phdr->caplen); obj.record.input = g_htonl(pseudo_header->k12.input); obj.record.ts = GUINT64_TO_BE((((guint64)phdr->ts.secs - 631152000) * 2000000) + (phdr->ts.nsecs / 1000 * 2)); - memcpy(obj.record.frame,pd,phdr->len); + memcpy(obj.record.frame,pd,phdr->caplen); return k12_dump_record(wdh,len,obj.buffer, err); } diff --git a/wiretap/k12text.l b/wiretap/k12text.l index ebec0ac7b9..afdc267cba 100644 --- a/wiretap/k12text.l +++ b/wiretap/k12text.l @@ -375,6 +375,12 @@ k12text_dump(wtap_dumper *wdh _U_, const struct wtap_pkthdr *phdr, gboolean ret; struct tm *tmp; + /* Don't write anything bigger than we're willing to read. */ + if (phdr->caplen > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + str_enc = NULL; for(i=0; encaps[i].s; i++) { if (phdr->pkt_encap == encaps[i].e) { diff --git a/wiretap/lanalyzer.c b/wiretap/lanalyzer.c index 97f9764411..494e2591de 100644 --- a/wiretap/lanalyzer.c +++ b/wiretap/lanalyzer.c @@ -658,7 +658,7 @@ static gboolean lanalyzer_dump(wtap_dumper *wdh, double x; int i; int len; - struct timeval tv; + struct timeval tv; LA_TmpInfo *itmp = (LA_TmpInfo*)(wdh->priv); struct timeval td; @@ -672,6 +672,12 @@ static gboolean lanalyzer_dump(wtap_dumper *wdh, len = phdr->caplen + (phdr->caplen ? LA_PacketRecordSize : 0); + /* len goes into a 16-bit field, so there's a hard limit of 65535. */ + if (len > 65535) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + if (!s16write(wdh, GUINT16_TO_LE(0x1005), err)) return FALSE; if (!s16write(wdh, GUINT16_TO_LE(len), err)) diff --git a/wiretap/libpcap.c b/wiretap/libpcap.c index c73a357835..a323cde1b3 100644 --- a/wiretap/libpcap.c +++ b/wiretap/libpcap.c @@ -935,6 +935,12 @@ static gboolean libpcap_dump(wtap_dumper *wdh, phdrsize = pcap_get_phdr_size(wdh->encap, pseudo_header); + /* Don't write anything we're not willing to read. */ + if (phdr->caplen + phdrsize > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + rec_hdr.hdr.ts_sec = (guint32) phdr->ts.secs; if(wdh->tsprecision == WTAP_FILE_TSPREC_NSEC) { rec_hdr.hdr.ts_usec = phdr->ts.nsecs; diff --git a/wiretap/netmon.c b/wiretap/netmon.c index ad1aacb8f6..717992a738 100644 --- a/wiretap/netmon.c +++ b/wiretap/netmon.c @@ -1027,6 +1027,34 @@ static gboolean netmon_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, gint64 secs; gint32 nsecs; + switch (wdh->file_type_subtype) { + + case WTAP_FILE_TYPE_SUBTYPE_NETMON_1_x: + /* + * The length fields are 16-bit, so there's a hard limit + * of 65535. + */ + if (phdr->caplen > 65535) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + break; + + case WTAP_FILE_TYPE_SUBTYPE_NETMON_2_x: + /* Don't write anything we're not willing to read. */ + if (phdr->caplen > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + break; + + default: + /* We should never get here - our open routine + should only get called for the types above. */ + *err = WTAP_ERR_UNSUPPORTED_FILE_TYPE; + return FALSE; + } + if (wdh->encap == WTAP_ENCAP_PER_PACKET) { /* * Is this network type supported? diff --git a/wiretap/nettl.c b/wiretap/nettl.c index e869fb711f..ac3f7ed499 100644 --- a/wiretap/nettl.c +++ b/wiretap/nettl.c @@ -734,6 +734,12 @@ static gboolean nettl_dump(wtap_dumper *wdh, struct nettlrec_hdr rec_hdr; guint8 dummyc[24]; + /* Don't write anything we're not willing to read. */ + if (phdr->caplen > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + memset(&rec_hdr,0,sizeof(rec_hdr)); /* HP-UX 11.X header should be 68 bytes */ rec_hdr.hdr_len = g_htons(sizeof(rec_hdr) + 4); diff --git a/wiretap/network_instruments.c b/wiretap/network_instruments.c index 2e9f340288..07e3e3a7e2 100644 --- a/wiretap/network_instruments.c +++ b/wiretap/network_instruments.c @@ -699,6 +699,13 @@ static gboolean observer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, packet_entry_header packet_header; guint64 seconds_since_2000; + /* The captured size field is 16 bits, so there's a hard limit of + 65535. */ + if (phdr->caplen > 65535) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + /* convert the number of seconds since epoch from ANSI-relative to Observer-relative */ if (phdr->ts.secs < ansi_to_observer_epoch_offset) { diff --git a/wiretap/netxray.c b/wiretap/netxray.c index 189c70a04c..774262cf3e 100644 --- a/wiretap/netxray.c +++ b/wiretap/netxray.c @@ -1742,6 +1742,13 @@ netxray_dump_1_1(wtap_dumper *wdh, guint32 t32; struct netxrayrec_1_x_hdr rec_hdr; + /* The captured length field is 16 bits, so there's a hard + limit of 65535. */ + if (phdr->caplen > 65535) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + /* NetXRay/Windows Sniffer files have a capture start date/time in the header, in a UNIX-style format, with one-second resolution, and a start time stamp with microsecond resolution that's just @@ -1908,6 +1915,12 @@ netxray_dump_2_0(wtap_dumper *wdh, guint32 t32; struct netxrayrec_2_x_hdr rec_hdr; + /* Don't write anything we're not willing to read. */ + if (phdr->caplen > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + /* NetXRay/Windows Sniffer files have a capture start date/time in the header, in a UNIX-style format, with one-second resolution, and a start time stamp with microsecond resolution that's just diff --git a/wiretap/ngsniffer.c b/wiretap/ngsniffer.c index 0e33072ca7..58031ff38e 100644 --- a/wiretap/ngsniffer.c +++ b/wiretap/ngsniffer.c @@ -2075,6 +2075,13 @@ ngsniffer_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, guint16 start_date; struct tm *tm; + /* The captured length field is 16 bits, so there's a hard + limit of 65535. */ + if (phdr->caplen > 65535) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + /* Sniffer files have a capture start date in the file header, and have times relative to the beginning of that day in the packet headers; pick the date of the first packet as the capture start diff --git a/wiretap/pcapng.c b/wiretap/pcapng.c index 86be49d20d..6afc024f7c 100644 --- a/wiretap/pcapng.c +++ b/wiretap/pcapng.c @@ -3253,6 +3253,12 @@ pcapng_write_enhanced_packet_block(wtap_dumper *wdh, guint32 comment_len = 0, comment_pad_len = 0; wtapng_if_descr_t int_data; + /* Don't write anything we're not willing to read. */ + if (phdr->caplen > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + phdr_len = (guint32)pcap_get_phdr_size(phdr->pkt_encap, pseudo_header); if ((phdr_len + phdr->caplen) % 4) { pad_len = 4 - ((phdr_len + phdr->caplen) % 4); diff --git a/wiretap/snoop.c b/wiretap/snoop.c index fb9253706b..985cfe9f9e 100644 --- a/wiretap/snoop.c +++ b/wiretap/snoop.c @@ -887,10 +887,17 @@ static gboolean snoop_dump(wtap_dumper *wdh, /* Record length = header length plus data length... */ reclen = (int)sizeof rec_hdr + phdr->caplen + atm_hdrsize; + /* ... plus enough bytes to pad it to a 4-byte boundary. */ padlen = ((reclen + 3) & ~3) - reclen; reclen += padlen; + /* Don't write anything we're not willing to read. */ + if (phdr->caplen + atm_hdrsize > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + rec_hdr.orig_len = g_htonl(phdr->len + atm_hdrsize); rec_hdr.incl_len = g_htonl(phdr->caplen + atm_hdrsize); rec_hdr.rec_len = g_htonl(reclen); diff --git a/wiretap/visual.c b/wiretap/visual.c index d73fa2515a..a0822aa855 100644 --- a/wiretap/visual.c +++ b/wiretap/visual.c @@ -682,6 +682,12 @@ static gboolean visual_dump(wtap_dumper *wdh, const struct wtap_pkthdr *phdr, guint delta_msec; guint32 packet_status; + /* Don't write anything we're not willing to read. */ + if (phdr->caplen > WTAP_MAX_PACKET_SIZE) { + *err = WTAP_ERR_PACKET_TOO_LARGE; + return FALSE; + } + /* If the visual structure was never allocated then nothing useful can be done. */ if (visual == 0) diff --git a/wiretap/wtap.c b/wiretap/wtap.c index d5b4c89e6d..28bba7a79c 100644 --- a/wiretap/wtap.c +++ b/wiretap/wtap.c @@ -797,7 +797,8 @@ static const char *wtap_errlist[] = { NULL, NULL, "Uncompression error", - "Internal error" + "Internal error", + "The packet being written is too large for that format" }; #define WTAP_ERRLIST_SIZE (sizeof wtap_errlist / sizeof wtap_errlist[0]) diff --git a/wiretap/wtap.h b/wiretap/wtap.h index b70c893df7..95459d5462 100644 --- a/wiretap/wtap.h +++ b/wiretap/wtap.h @@ -1546,6 +1546,10 @@ int wtap_register_encap_type(const char* name, const char* short_name); #define WTAP_ERR_INTERNAL -23 /** "Shouldn't happen" internal errors */ +#define WTAP_ERR_PACKET_TOO_LARGE -24 + /** Packet being written is larger than we support; do not use when + reading, use WTAP_ERR_BAD_FILE instead */ + #ifdef __cplusplus } #endif /* __cplusplus */ |