Thu May 15 08:44:57 2008 UTC ()
pullup ticket #2376 - requested by tonnerre
quagga: fixes denial of service

revisions pulled up:
- pkgsrc/net/quagga/Makefile		1.31
- pkgsrc/net/quagga/distinfo		1.10
- pkgsrc/net/quagga/patches/patch-ab	1.3
- pkgsrc/net/quagga/patches/patch-ac	1.3

   Module Name:	pkgsrc
   Committed By:	tonnerre
   Date:		Tue May 13 22:30:47 UTC 2008

   Modified Files:
   	pkgsrc/net/quagga: Makefile distinfo
   Added Files:
   	pkgsrc/net/quagga/patches: patch-ab patch-ac

   Log Message:
   Add patch for CVE-2007-1995 for stable quagga (NLRI attributes denial of
   service).


(rtr)
diff -r1.30 -r1.30.6.1 pkgsrc/net/quagga/Makefile
diff -r1.9 -r1.9.16.1 pkgsrc/net/quagga/distinfo
diff -r0 -r1.2.26.1 pkgsrc/net/quagga/patches/patch-ab
diff -r0 -r1.2.26.1 pkgsrc/net/quagga/patches/patch-ac

cvs diff -r1.30 -r1.30.6.1 pkgsrc/net/quagga/Makefile (expand / switch to unified diff)

--- pkgsrc/net/quagga/Makefile 2007/09/07 22:07:31 1.30
+++ pkgsrc/net/quagga/Makefile 2008/05/15 08:44:57 1.30.6.1
@@ -1,18 +1,19 @@ @@ -1,18 +1,19 @@
1# $NetBSD: Makefile,v 1.30 2007/09/07 22:07:31 jlam Exp $ 1# $NetBSD: Makefile,v 1.30.6.1 2008/05/15 08:44:57 rtr Exp $
2# Based on KAME Id: Makefile,v 1.1.2.1.2.1.10.2 1999/01/05 11:03:50 itojun Exp 2# Based on KAME Id: Makefile,v 1.1.2.1.2.1.10.2 1999/01/05 11:03:50 itojun Exp
3# 3#
4 4
5DISTNAME= quagga-0.98.6 5DISTNAME= quagga-0.98.6
 6PKGREVISION= 1
6CATEGORIES= net 7CATEGORIES= net
7MASTER_SITES= http://www.quagga.net/download/ 8MASTER_SITES= http://www.quagga.net/download/
8 9
9MAINTAINER= gdt@NetBSD.org 10MAINTAINER= gdt@NetBSD.org
10HOMEPAGE= http://www.quagga.net/ 11HOMEPAGE= http://www.quagga.net/
11COMMENT= Free multithreaded routing daemon software (fork of zebra) 12COMMENT= Free multithreaded routing daemon software (fork of zebra)
12 13
13.include "../../mk/bsd.prefs.mk" 14.include "../../mk/bsd.prefs.mk"
14 15
15GNU_CONFIGURE= YES 16GNU_CONFIGURE= YES
16USE_TOOLS+= gmake perl 17USE_TOOLS+= gmake perl
17USE_LIBTOOL= YES 18USE_LIBTOOL= YES
18 19

cvs diff -r1.9 -r1.9.16.1 pkgsrc/net/quagga/distinfo (expand / switch to unified diff)

--- pkgsrc/net/quagga/distinfo 2006/06/05 19:28:25 1.9
+++ pkgsrc/net/quagga/distinfo 2008/05/15 08:44:57 1.9.16.1
@@ -1,6 +1,8 @@ @@ -1,6 +1,8 @@
1$NetBSD: distinfo,v 1.9 2006/06/05 19:28:25 gdt Exp $ 1$NetBSD: distinfo,v 1.9.16.1 2008/05/15 08:44:57 rtr Exp $
2 2
3SHA1 (quagga-0.98.6.tar.gz) = 2234d1235f504e9dc5865cc8d5fd4e250bf43ed5 3SHA1 (quagga-0.98.6.tar.gz) = 2234d1235f504e9dc5865cc8d5fd4e250bf43ed5
4RMD160 (quagga-0.98.6.tar.gz) = e15cd93b5d321660d7e29fc27174352967342879 4RMD160 (quagga-0.98.6.tar.gz) = e15cd93b5d321660d7e29fc27174352967342879
5Size (quagga-0.98.6.tar.gz) = 2019992 bytes 5Size (quagga-0.98.6.tar.gz) = 2019992 bytes
6SHA1 (patch-aa) = 507d9cccd719e31d0710425858a80cef1215093d 6SHA1 (patch-aa) = 507d9cccd719e31d0710425858a80cef1215093d
 7SHA1 (patch-ab) = 3165bb9d31ea7a3a3231e3fe3a0c374ef7b98f00
 8SHA1 (patch-ac) = 401c64dd7588ca4736079ecd796deaff6a45d447

File Added: pkgsrc/net/quagga/patches/Attic/patch-ab
$NetBSD: patch-ab,v 1.2.26.1 2008/05/15 08:44:57 rtr 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

File Added: pkgsrc/net/quagga/patches/Attic/patch-ac
$NetBSD: patch-ac,v 1.2.26.1 2008/05/15 08:44:57 rtr Exp $

--- lib/stream.h
+++ lib/stream.h
@@ -59,7 +59,9 @@ struct stream_fifo
 #define STREAM_SIZE(S)  ((S)->size)
 #define STREAM_REMAIN(S) ((S)->size - (S)->putp)
 #define STREAM_DATA(S)  ((S)->data)
-
+/* number of bytes still to be read */
+#define STREAM_READABLE(S) ((S)->endp - (S)->getp)
+  
 /* Stream prototypes. */
 struct stream *stream_new (size_t);
 void stream_free (struct stream *);