Commit message: CVE-2017-13053/BGP: fix VPN route target bounds checks

decode_rt_routing_info() didn't check bounds before fetching 4 octets of
the origin AS field and could over-read the input buffer, put it right.

It also fetched the varying number of octets of the route target field
from 4 octets lower than the correct offset, put it right.

It also used the same temporary buffer explicitly through as_printf()
and implicitly through bgp_vpn_rd_print() so the end result of snprintf()
was not what was originally intended.

This fixes a buffer over-read discovered by Bhargava Shastry,
SecT/TU Berlin.

Add a test using the capture file supplied by the reporter(s).
CVE: CVE-2017-13053
CWE: CWE-125
Vulnerability description: The BGP parser in tcpdump before 4.9.2 has a buffer over-read in print-bgp.c:decode_rt_routing_info().

Project: tcpdump
File: print-bgp.c

decode_labeled_vpn_l2(netdissect_options *ndo,
                      const u_char *pptr, char *buf, u_int buflen)
{
        int plen,tlen,stringlen,tlv_type,tlv_len,ttlv_len;

	ND_TCHECK2(pptr[0], 2);
        plen=EXTRACT_16BITS(pptr);
        tlen=plen;
        pptr+=2;
	/* Old and new L2VPN NLRI share AFI/SAFI
         *   -> Assume a 12 Byte-length NLRI is auto-discovery-only
         *      and > 17 as old format. Complain for the middle case
         */
        if (plen==12) {
	    /* assume AD-only with RD, BGPNH */
	    ND_TCHECK2(pptr[0],12);
	    buf[0]='\0';
	    stringlen=snprintf(buf, buflen, "RD: %s, BGPNH: %s",
			       bgp_vpn_rd_print(ndo, pptr),
			       ipaddr_string(ndo, pptr+8)
			       );
	    UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
	    pptr+=12;
	    tlen-=12;
	    return plen;
        } else if (plen>17) {
	    /* assume old format */
	    /* RD, ID, LBLKOFF, LBLBASE */

	    ND_TCHECK2(pptr[0],15);
	    buf[0]='\0';
	    stringlen=snprintf(buf, buflen, "RD: %s, CE-ID: %u, Label-Block Offset: %u, Label Base %u",
			       bgp_vpn_rd_print(ndo, pptr),
			       EXTRACT_16BITS(pptr+8),
			       EXTRACT_16BITS(pptr+10),
			       EXTRACT_24BITS(pptr+12)>>4); /* the label is offsetted by 4 bits so lets shift it right */
	    UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
	    pptr+=15;
	    tlen-=15;

	    /* ok now the variable part - lets read out TLVs*/
	    while (tlen>0) {
		if (tlen < 3)
		    return -1;
		ND_TCHECK2(pptr[0], 3);
		tlv_type=*pptr++;
		tlv_len=EXTRACT_16BITS(pptr);
		ttlv_len=tlv_len;
		pptr+=2;

		switch(tlv_type) {
		case 1:
		    if (buflen!=0) {
			stringlen=snprintf(buf,buflen, "\n\t\tcircuit status vector (%u) length: %u: 0x",
					   tlv_type,
					   tlv_len);
			UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
		    }
		    ttlv_len=ttlv_len/8+1; /* how many bytes do we need to read ? */
		    while (ttlv_len>0) {
			ND_TCHECK(pptr[0]);
			if (buflen!=0) {
			    stringlen=snprintf(buf,buflen, "%02x",*pptr++);
			    UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
			}
			ttlv_len--;
		    }
		    break;
		default:
		    if (buflen!=0) {
			stringlen=snprintf(buf,buflen, "\n\t\tunknown TLV #%u, length: %u",
					   tlv_type,
					   tlv_len);
			UPDATE_BUF_BUFLEN(buf, buflen, stringlen);
		    }
		    break;
		}
		tlen-=(tlv_len<<3); /* the tlv-length is expressed in bits so lets shift it right */
	    }
	    return plen+2;

        } else {
	    /* complain bitterly ? */
	    /* fall through */
            goto trunc;
        }

trunc:
        return -2;
}

Project: tcpdump
File: print-bgp.c

decode_prefix6(netdissect_options *ndo,
               const u_char *pd, u_int itemlen, char *buf, u_int buflen)
{
	struct in6_addr addr;
	u_int plen, plenbytes;

	ND_TCHECK(pd[0]);
	ITEMCHECK(1);
	plen = pd[0];
	if (128 < plen)
		return -1;
	itemlen -= 1;

	memset(&addr, 0, sizeof(addr));
	plenbytes = (plen + 7) / 8;
	ND_TCHECK2(pd[1], plenbytes);
	ITEMCHECK(plenbytes);
	memcpy(&addr, &pd[1], plenbytes);
	if (plen % 8) {
		addr.s6_addr[plenbytes - 1] &=
			((0xff00 >> (plen % 8)) & 0xff);
	}
	snprintf(buf, buflen, "%s/%d", ip6addr_string(ndo, &addr), plen);
	return 1 + plenbytes;

trunc:
	return -2;

badtlv:
	return -3;
}