summaryrefslogtreecommitdiff
path: root/net/quagga/patches/patch-ab
diff options
context:
space:
mode:
authortonnerre <tonnerre@pkgsrc.org>2008-05-13 22:30:47 +0000
committertonnerre <tonnerre@pkgsrc.org>2008-05-13 22:30:47 +0000
commit849a884778c317fa1a9adf1152368ad8f6ce0f77 (patch)
tree9243374d9dcec1524770c127f0f3ffea81dcb9fe /net/quagga/patches/patch-ab
parentc12369e3f48e7c5403eeaee43f1e41668fdf2fa2 (diff)
downloadpkgsrc-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-ab178
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