Commit message: CVE-2017-13014/White Board: Do more bounds checks.

This fixes a buffer over-read discovered by Yannick Formaggio.

Add a test using the capture file supplied by the reporter(s).

While we're at it, print a truncation error if the packets are
truncated, rather than just, in effect, ignoring the result of the
routines that print particular packet types.
CVE: CVE-2017-13014
CWE: CWE-125
Vulnerability description: The White Board protocol parser in tcpdump before 4.9.2 has a buffer over-read in print-wb.c:wb_prep(), several functions.

Project: tcpdump
File: print-wb.c

wb_dops(netdissect_options *ndo, const struct pkt_dop *dop,
        uint32_t ss, uint32_t es)
{
	const struct dophdr *dh = (const struct dophdr *)((const u_char *)dop + sizeof(*dop));

	ND_PRINT((ndo, " <"));
	for ( ; ss <= es; ++ss) {
		int t;

		if (!ND_TTEST(*dh)) {
			ND_PRINT((ndo, "%s", tstr));
			break;
		}
		t = dh->dh_type;

		if (t > DT_MAXTYPE)
			ND_PRINT((ndo, " dop-%d!", t));
		else {
			ND_PRINT((ndo, " %s", dopstr[t]));
			if (t == DT_SKIP || t == DT_HOLE) {
				uint32_t ts = EXTRACT_32BITS(&dh->dh_ts);
				ND_PRINT((ndo, "%d", ts - ss + 1));
				if (ss > ts || ts > es) {
					ND_PRINT((ndo, "[|]"));
					if (ts < ss)
						return (0);
				}
				ss = ts;
			}
		}
		dh = DOP_NEXT(dh);
	}
	ND_PRINT((ndo, " >"));
	return (0);
}

Project: tcpdump
File: print-wb.c

wb_id(netdissect_options *ndo,
      const struct pkt_id *id, u_int len)
{
	int i;
	const char *cp;
	const struct id_off *io;
	char c;
	int nid;

	ND_PRINT((ndo, " wb-id:"));
	if (len < sizeof(*id) || !ND_TTEST(*id))
		return (-1);
	len -= sizeof(*id);

	ND_PRINT((ndo, " %u/%s:%u (max %u/%s:%u) ",
	       EXTRACT_32BITS(&id->pi_ps.slot),
	       ipaddr_string(ndo, &id->pi_ps.page.p_sid),
	       EXTRACT_32BITS(&id->pi_ps.page.p_uid),
	       EXTRACT_32BITS(&id->pi_mslot),
	       ipaddr_string(ndo, &id->pi_mpage.p_sid),
	       EXTRACT_32BITS(&id->pi_mpage.p_uid)));

	nid = EXTRACT_16BITS(&id->pi_ps.nid);
	len -= sizeof(*io) * nid;
	io = (const struct id_off *)(id + 1);
	cp = (const char *)(io + nid);
	if (ND_TTEST2(cp, len)) {
		ND_PRINT((ndo, "\""));
		fn_print(ndo, (const u_char *)cp, (const u_char *)cp + len);
		ND_PRINT((ndo, "\""));
	}

	c = '<';
	for (i = 0; i < nid && ND_TTEST(*io); ++io, ++i) {
		ND_PRINT((ndo, "%c%s:%u",
		    c, ipaddr_string(ndo, &io->id), EXTRACT_32BITS(&io->off)));
		c = ',';
	}
	if (i >= nid) {
		ND_PRINT((ndo, ">"));
		return (0);
	}
	return (-1);
}

Project: tcpdump
File: print-wb.c

wb_preq(netdissect_options *ndo,
        const struct pkt_preq *preq, u_int len)
{
	ND_PRINT((ndo, " wb-preq:"));
	if (len < sizeof(*preq) || !ND_TTEST(*preq))
		return (-1);

	ND_PRINT((ndo, " need %u/%s:%u",
	       EXTRACT_32BITS(&preq->pp_low),
	       ipaddr_string(ndo, &preq->pp_page.p_sid),
	       EXTRACT_32BITS(&preq->pp_page.p_uid)));
	return (0);
}

Project: tcpdump
File: print-wb.c

wb_rreq(netdissect_options *ndo,
        const struct pkt_rreq *rreq, u_int len)
{
	ND_PRINT((ndo, " wb-rreq:"));
	if (len < sizeof(*rreq) || !ND_TTEST(*rreq))
		return (-1);

	ND_PRINT((ndo, " please repair %s %s:%u<%u:%u>",
	       ipaddr_string(ndo, &rreq->pr_id),
	       ipaddr_string(ndo, &rreq->pr_page.p_sid),
	       EXTRACT_32BITS(&rreq->pr_page.p_uid),
	       EXTRACT_32BITS(&rreq->pr_sseq),
	       EXTRACT_32BITS(&rreq->pr_eseq)));
	return (0);
}