diff options
author | tonnerre <tonnerre@pkgsrc.org> | 2008-05-13 22:30:47 +0000 |
---|---|---|
committer | tonnerre <tonnerre@pkgsrc.org> | 2008-05-13 22:30:47 +0000 |
commit | 849a884778c317fa1a9adf1152368ad8f6ce0f77 (patch) | |
tree | 9243374d9dcec1524770c127f0f3ffea81dcb9fe /net/quagga/patches/patch-ab | |
parent | c12369e3f48e7c5403eeaee43f1e41668fdf2fa2 (diff) | |
download | pkgsrc-849a884778c317fa1a9adf1152368ad8f6ce0f77.tar.gz |
Add patch for CVE-2007-1995 for stable quagga (NLRI attributes denial of
service).
Diffstat (limited to 'net/quagga/patches/patch-ab')
-rw-r--r-- | net/quagga/patches/patch-ab | 178 |
1 files changed, 178 insertions, 0 deletions
diff --git a/net/quagga/patches/patch-ab b/net/quagga/patches/patch-ab new file mode 100644 index 00000000000..e0e8810fbd4 --- /dev/null +++ b/net/quagga/patches/patch-ab @@ -0,0 +1,178 @@ +$NetBSD: patch-ab,v 1.3 2008/05/13 22:30:47 tonnerre Exp $ + +--- bgpd/bgp_attr.c ++++ bgpd/bgp_attr.c +@@ -39,7 +39,7 @@ Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + #include "bgpd/bgp_ecommunity.h" + + /* Attribute strings for logging. */ +-struct message attr_str [] = ++static struct message attr_str [] = + { + { BGP_ATTR_ORIGIN, "ORIGIN" }, + { BGP_ATTR_AS_PATH, "AS_PATH" }, +@@ -58,6 +58,7 @@ struct message attr_str [] = + { BGP_ATTR_MP_UNREACH_NLRI, "MP_UNREACH_NLRI" }, + { 0, NULL } + }; ++int attr_str_max = sizeof(attr_str)/sizeof(attr_str[0]); + + struct hash *cluster_hash; + +@@ -922,24 +923,30 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr, + { + u_int16_t afi; + u_char safi; +- u_char snpa_num; +- u_char snpa_len; +- u_char *lim; + bgp_size_t nlri_len; ++ size_t start; + int ret; + struct stream *s; + + /* Set end of packet. */ +- s = peer->ibuf; +- lim = stream_pnt (s) + length; +- ++ s = BGP_INPUT(peer); ++ start = stream_get_getp(s); ++ ++ /* safe to read statically sized header? */ ++#define BGP_MP_REACH_MIN_SIZE 5 ++ if ((length > STREAM_READABLE(s)) || (length < BGP_MP_REACH_MIN_SIZE)) ++ return -1; ++ + /* Load AFI, SAFI. */ + afi = stream_getw (s); + safi = stream_getc (s); + + /* Get nexthop length. */ + attr->mp_nexthop_len = stream_getc (s); +- ++ ++ if (STREAM_READABLE(s) < attr->mp_nexthop_len) ++ return -1; ++ + /* Nexthop length check. */ + switch (attr->mp_nexthop_len) + { +@@ -986,31 +993,28 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr, + break; + } + +- snpa_num = stream_getc (s); +- +- while (snpa_num--) +- { +- snpa_len = stream_getc (s); +- stream_forward (s, (snpa_len + 1) >> 1); +- } ++ if (!STREAM_READABLE(s)) ++ return -1; ++ ++ { ++ u_char val; ++ if ((val = stream_getc (s))) ++ zlog_warn ("%s sent non-zero value, %u, for defunct SNPA-length field", ++ peer->host, val); ++ } ++ ++ /* must have nrli_len, what is left of the attribute */ ++ nlri_len = length - (stream_get_getp(s) - start); ++ if ((!nlri_len) || (nlri_len > STREAM_READABLE(s))) ++ return -1; + +- /* If peer is based on old draft-00. I read NLRI length from the +- packet. */ +- if (peer->version == BGP_VERSION_MP_4_DRAFT_00) +- { +- bgp_size_t nlri_total_len; +- nlri_total_len = stream_getw (s); +- } +- +- nlri_len = lim - stream_pnt (s); +- + if (safi != BGP_SAFI_VPNV4) + { + ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), nlri_len); + if (ret < 0) + return -1; + } +- ++ + mp_update->afi = afi; + mp_update->safi = safi; + mp_update->nlri = stream_pnt (s); +@@ -1023,24 +1027,26 @@ bgp_mp_reach_parse (struct peer *peer, bgp_size_t length, struct attr *attr, + + /* Multiprotocol unreachable parse */ + int +-bgp_mp_unreach_parse (struct peer *peer, int length, ++bgp_mp_unreach_parse (struct peer *peer, bgp_size_t length, + struct bgp_nlri *mp_withdraw) + { + struct stream *s; + u_int16_t afi; + u_char safi; +- u_char *lim; + u_int16_t withdraw_len; + int ret; + + s = peer->ibuf; +- lim = stream_pnt (s) + length; + ++#define BGP_MP_UNREACH_MIN_SIZE 3 ++ if ((length > STREAM_READABLE(s)) || (length < BGP_MP_UNREACH_MIN_SIZE)) ++ return -1; ++ + afi = stream_getw (s); + safi = stream_getc (s); +- +- withdraw_len = lim - stream_pnt (s); +- ++ ++ withdraw_len = length - BGP_MP_UNREACH_MIN_SIZE; ++ + if (safi != BGP_SAFI_VPNV4) + { + ret = bgp_nlri_sanity_check (peer, afi, stream_pnt (s), withdraw_len); +@@ -1271,13 +1277,23 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, + + /* If error occured immediately return to the caller. */ + if (ret < 0) +- return ret; ++ { ++ zlog (peer->log, LOG_WARNING, ++ "%s: Attribute %s, parse error", ++ peer->host, ++ LOOKUP (attr_str, type)); ++ bgp_notify_send (peer, ++ BGP_NOTIFY_UPDATE_ERR, ++ BGP_NOTIFY_UPDATE_MAL_ATTR); ++ return ret; ++ } + + /* Check the fetched length. */ + if (BGP_INPUT_PNT (peer) != attr_endp) + { + zlog (peer->log, LOG_WARNING, +- "%s BGP attribute fetch error", peer->host); ++ "%s: BGP attribute %s, fetch error", ++ peer->host, LOOKUP (attr_str, type)); + bgp_notify_send (peer, + BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); +@@ -1289,7 +1305,8 @@ bgp_attr_parse (struct peer *peer, struct attr *attr, bgp_size_t size, + if (BGP_INPUT_PNT (peer) != endp) + { + zlog (peer->log, LOG_WARNING, +- "%s BGP attribute length mismatch", peer->host); ++ "%s BGP attribute %s, length mismatch", ++ peer->host, LOOKUP (attr_str, type)); + bgp_notify_send (peer, + BGP_NOTIFY_UPDATE_ERR, + BGP_NOTIFY_UPDATE_ATTR_LENG_ERR); +diff --git a/doc/quagga.info b/doc/quagga.info +diff --git a/lib/stream.h b/lib/stream.h +index f7a94ea..a85e413 100644 |