[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_attr.c b/bgpd/bgp_attr.c
index b463b3c..dd3cc96 100644
--- a/bgpd/bgp_attr.c
+++ b/bgpd/bgp_attr.c
@@ -892,7 +892,8 @@
   *as4_path = aspath_parse (peer->ibuf, length, 1);
 
   /* Set aspath attribute flag. */
-  attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
+  if (as4_path)
+    attr->flag |= ATTR_FLAG_BIT (BGP_ATTR_AS4_PATH);
 
   return 0;
 }
@@ -1126,10 +1127,10 @@
    */
   if (attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AS4_AGGREGATOR) ) )
     {
-      assert (attre);
-      
       if ( attr->flag & (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR) ) )
         {
+          assert (attre);
+          
           /* received both.
            * if the as_number in aggregator is not AS_TRANS,
            *  then AS4_AGGREGATOR and AS4_PATH shall be ignored
@@ -1170,7 +1171,7 @@
             zlog_debug ("[AS4] %s BGP not AS4 capable peer send"
                         " AS4_AGGREGATOR but no AGGREGATOR, will take"
                         " it as if AGGREGATOR with AS_TRANS had been there", peer->host);
-          attre->aggregator_as = as4_aggregator;
+          (attre = bgp_attr_extra_get (attr))->aggregator_as = as4_aggregator;
           /* sweep it under the carpet and simulate a "good" AGGREGATOR */
           attr->flag |= (ATTR_FLAG_BIT (BGP_ATTR_AGGREGATOR));
         }
@@ -1543,6 +1544,21 @@
       flag = stream_getc (BGP_INPUT (peer));
       type = stream_getc (BGP_INPUT (peer));
 
+      /* Check whether Extended-Length applies and is in bounds */
+      if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN)
+          && ((endp - startp) < (BGP_ATTR_MIN_LEN + 1)))
+	{
+	  zlog (peer->log, LOG_WARNING, 
+		"%s Extended length set, but just %u bytes of attr header",
+		peer->host,
+		(unsigned long) (endp - STREAM_PNT (BGP_INPUT (peer))));
+
+	  bgp_notify_send (peer, 
+			   BGP_NOTIFY_UPDATE_ERR, 
+			   BGP_NOTIFY_UPDATE_ATTR_LENG_ERR);
+	  return -1;
+	}
+
       /* Check extended attribue length bit. */
       if (CHECK_FLAG (flag, BGP_ATTR_FLAG_EXTLEN))
 	length = stream_getw (BGP_INPUT (peer));