[bgpd] Fix number of DoS security issues, restricted to configured peers.

2007-12-22 Paul Jakma <paul.jakma@sun.com>

	* Fix series of vulnerabilities reported by "Mu Security
	  Research Team", where bgpd can be made to crash by sending
	  malformed packets - requires that bgpd be configured with a
	  session to the peer.
	* bgp_attr.c: (bgp_attr_as4_path) aspath_parse may fail, only
	  set the attribute flag indicating AS4_PATH if we actually managed
	  to parse one.
	  (bgp_attr_munge_as4_attrs) Assert was too general, it is possible
	  to receive AS4_AGGREGATOR before AGGREGATOR.
	  (bgp_attr_parse) Check that we have actually received the extra
	  byte of header for Extended-Length attributes.
	* bgp_attr.h: Fix BGP_ATTR_MIN_LEN to account for the length byte.
	* bgp_open.c: (cap_minsizes) Fix size of CAPABILITY_CODE_RESTART,
	  incorrect -2 left in place from a development version of as4-path
	  patch.
	* bgp_packet.c: (bgp_route_refresh_receive) ORF length parameter
	  needs to be properly sanity checked.
	* tests/bgp_capability_test.c: Test for empty capabilities.
diff --git a/bgpd/bgp_packet.c b/bgpd/bgp_packet.c
index 1fa2fdf..8319a88 100644
--- a/bgpd/bgp_packet.c
+++ b/bgpd/bgp_packet.c
@@ -1960,11 +1960,14 @@
       when_to_refresh = stream_getc (s);
       end = stream_pnt (s) + (size - 5);
 
-      while (stream_pnt (s) < end)
+      while ((stream_pnt (s) + 2) < end)
 	{
 	  orf_type = stream_getc (s); 
 	  orf_len = stream_getw (s);
-
+	  
+	  /* orf_len in bounds? */
+	  if ((stream_pnt (s) + orf_len) > end)
+	    break; /* XXX: Notify instead?? */
 	  if (orf_type == ORF_TYPE_PREFIX
 	      || orf_type == ORF_TYPE_PREFIX_OLD)
 	    {
@@ -1984,6 +1987,12 @@
 			     peer->host, orf_type, orf_len);
 		}
 
+              /* we're going to read at least 1 byte of common ORF header,
+               * and 7 bytes of ORF Address-filter entry from the stream
+               */
+              if (orf_len < 7)
+                break; 
+                
 	      /* ORF prefix-list name */
 	      sprintf (name, "%s.%d.%d", peer->host, afi, safi);