components/quagga/patches/07-cve-2012-0249.patch
branchs11-sru
changeset 2301 e630b9a06d32
equal deleted inserted replaced
2300:11762b8a16cb 2301:e630b9a06d32
       
     1 The following patches are pulled directly from the GIT repository 
       
     2 for the quagga community. They fix the following CVEs:
       
     3 
       
     4 CVE-2012-0249
       
     5 CVE-2012-0250
       
     6 CVE-2012-0255
       
     7 
       
     8 All of the patched CVEs are included in Quagga 0.99.20.1. This patch
       
     9 file can be removed if Quagga is upgraded to that version.
       
    10 
       
    11 
       
    12 
       
    13 From 5861739f8c38bc36ea9955e5cb2be2bf2f482d70 Mon Sep 17 00:00:00 2001
       
    14 From: Paul Jakma <[email protected]>
       
    15 Date: Mon, 09 Jan 2012 20:59:26 +0000
       
    16 Subject: bgpd: Open option parse errors don't NOTIFY, resulting in abort & DoS
       
    17 
       
    18 * bgp_packet.c: (bgp_open_receive) Errors from bgp_open_option_parse are
       
    19   detected, and the code will stop processing the OPEN and return.  However
       
    20   it does so without calling bgp_notify_send to send a NOTIFY - which means
       
    21   the peer FSM doesn't get stopped, and bgp_read will be called again later.
       
    22   Because it returns, it doesn't go through the code near the end of the
       
    23   function that removes the current message from the peer input streaam.
       
    24   Thus the next call to bgp_read will try to parse a half-parsed stream as
       
    25   if it were a new BGP message, leading to an assert later in the code when
       
    26   it tries to read stuff that isn't there. Add the required call to
       
    27   bgp_notify_send before returning.
       
    28 * bgp_open.c: (bgp_capability_as4) Be a bit stricter, check the length field
       
    29   corresponds to the only value it can be, which is the amount we're going to
       
    30   read off the stream. And make sure the capability flag gets set, so
       
    31   callers can know this capability was read, regardless.
       
    32   (peek_for_as4_capability) Let bgp_capability_as4 do the length check.
       
    33 ---
       
    34 diff --git bgpd/bgp_open.c bgpd/bgp_open.c
       
    35 index 82deb3d..b5b50bb 100644
       
    36 --- bgpd/bgp_open.c
       
    37 +++ bgpd/bgp_open.c
       
    38 @@ -421,13 +421,20 @@ bgp_capability_restart (struct peer *peer, struct capability_header *caphdr)
       
    39  static as_t
       
    40  bgp_capability_as4 (struct peer *peer, struct capability_header *hdr)
       
    41  {
       
    42 +  SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
       
    43 +  
       
    44 +  if (hdr->length != CAPABILITY_CODE_AS4_LEN)
       
    45 +    {
       
    46 +      zlog_err ("%s AS4 capability has incorrect data length %d",
       
    47 +                peer->host, hdr->length);
       
    48 +      return 0;
       
    49 +    }
       
    50 +  
       
    51    as_t as4 = stream_getl (BGP_INPUT(peer));
       
    52    
       
    53    if (BGP_DEBUG (as4, AS4))
       
    54      zlog_debug ("%s [AS4] about to set cap PEER_CAP_AS4_RCV, got as4 %u",
       
    55                  peer->host, as4);
       
    56 -  SET_FLAG (peer->cap, PEER_CAP_AS4_RCV);
       
    57 -  
       
    58    return as4;
       
    59  }
       
    60  
       
    61 @@ -689,9 +696,6 @@ peek_for_as4_capability (struct peer *peer, u_char length)
       
    62  
       
    63  	      if (hdr.code == CAPABILITY_CODE_AS4)
       
    64  	        {
       
    65 -	          if (hdr.length != CAPABILITY_CODE_AS4_LEN)
       
    66 -	            goto end;
       
    67 -                  
       
    68  	          if (BGP_DEBUG (as4, AS4))
       
    69  	            zlog_info ("[AS4] found AS4 capability, about to parse");
       
    70  	          as4 = bgp_capability_as4 (peer, &hdr);
       
    71 diff --git bgpd/bgp_packet.c bgpd/bgp_packet.c
       
    72 index f5a74d1..5d8087a 100644
       
    73 --- bgpd/bgp_packet.c
       
    74 +++ bgpd/bgp_packet.c
       
    75 @@ -1459,9 +1459,13 @@ bgp_open_receive (struct peer *peer, bgp_size_t size)
       
    76    /* Open option part parse. */
       
    77    if (optlen != 0) 
       
    78      {
       
    79 -      ret = bgp_open_option_parse (peer, optlen, &capability);
       
    80 -      if (ret < 0)
       
    81 -	return ret;
       
    82 +      if ((ret = bgp_open_option_parse (peer, optlen, &capability)) < 0)
       
    83 +        {
       
    84 +          bgp_notify_send (peer,
       
    85 +                 BGP_NOTIFY_OPEN_ERR,
       
    86 +                 BGP_NOTIFY_OPEN_UNACEP_HOLDTIME);
       
    87 +	  return ret;
       
    88 +        }
       
    89      }
       
    90    else
       
    91      {
       
    92 --
       
    93 cgit v0.9.0.2
       
    94 From 393b2d64dc0625ba8e01e9e1516efac06d13072e Mon Sep 17 00:00:00 2001
       
    95 From: Denis Ovsienko <[email protected]>
       
    96 Date: Sun, 15 Jan 2012 15:12:19 +0000
       
    97 Subject: ospfd: use LOOKUP() for ospf_packet_type_str
       
    98 
       
    99 * ospf_packet.h: add proper str/max extern declarations
       
   100 * ospf_packet.c
       
   101   * ospf_packet_type_str: rewrite in "struct message", add max value
       
   102   * ospf_packet_add(): use LOOKUP()
       
   103   * ospf_write(): ditto
       
   104   * ospf_hello(): ditto
       
   105   * ospf_read(): ditto
       
   106 * ospf_dump.h: the declaration does not belong here
       
   107 * ospf_dump.c
       
   108   * ospf_header_dump(): use LOOKUP()
       
   109   * show_debugging_ospf(): ditto
       
   110 ---
       
   111 diff --git ospfd/ospf_dump.c ospfd/ospf_dump.c
       
   112 index e65b2e3..8ace095 100644
       
   113 --- ospfd/ospf_dump.c
       
   114 +++ ospfd/ospf_dump.c
       
   115 @@ -661,7 +661,7 @@ ospf_header_dump (struct ospf_header *ospfh)
       
   116    zlog_debug ("Header");
       
   117    zlog_debug ("  Version %d", ospfh->version);
       
   118    zlog_debug ("  Type %d (%s)", ospfh->type,
       
   119 -	     ospf_packet_type_str[ospfh->type]);
       
   120 +	     LOOKUP (ospf_packet_type_str, ospfh->type));
       
   121    zlog_debug ("  Packet Len %d", ntohs (ospfh->length));
       
   122    zlog_debug ("  Router ID %s", inet_ntoa (ospfh->router_id));
       
   123    zlog_debug ("  Area ID %s", inet_ntoa (ospfh->area_id));
       
   124 @@ -1457,7 +1457,7 @@ DEFUN (show_debugging_ospf,
       
   125      if (IS_DEBUG_OSPF_PACKET (i, SEND) && IS_DEBUG_OSPF_PACKET (i, RECV))
       
   126        {
       
   127  	vty_out (vty, "  OSPF packet %s%s debugging is on%s",
       
   128 -		 ospf_packet_type_str[i + 1],
       
   129 +		 LOOKUP (ospf_packet_type_str, i + 1),
       
   130  		 IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "",
       
   131  		 VTY_NEWLINE);
       
   132        }
       
   133 @@ -1465,12 +1465,12 @@ DEFUN (show_debugging_ospf,
       
   134        {
       
   135  	if (IS_DEBUG_OSPF_PACKET (i, SEND))
       
   136  	  vty_out (vty, "  OSPF packet %s send%s debugging is on%s",
       
   137 -		   ospf_packet_type_str[i + 1],
       
   138 +		   LOOKUP (ospf_packet_type_str, i + 1),
       
   139  		   IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "",
       
   140  		   VTY_NEWLINE);
       
   141  	if (IS_DEBUG_OSPF_PACKET (i, RECV))
       
   142  	  vty_out (vty, "  OSPF packet %s receive%s debugging is on%s",
       
   143 -		   ospf_packet_type_str[i + 1],
       
   144 +		   LOOKUP (ospf_packet_type_str, i + 1),
       
   145  		   IS_DEBUG_OSPF_PACKET (i, DETAIL) ? " detail" : "",
       
   146  		   VTY_NEWLINE);
       
   147        }
       
   148 diff --git ospfd/ospf_dump.h ospfd/ospf_dump.h
       
   149 index fb81371..455214f 100644
       
   150 --- ospfd/ospf_dump.h
       
   151 +++ ospfd/ospf_dump.h
       
   152 @@ -121,7 +121,6 @@ extern unsigned long term_debug_ospf_zebra;
       
   153  extern unsigned long term_debug_ospf_nssa;
       
   154  
       
   155  /* Message Strings. */
       
   156 -extern const char *ospf_packet_type_str[];
       
   157  extern char *ospf_lsa_type_str[];
       
   158  
       
   159  /* Prototypes. */
       
   160 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
       
   161 index 0f338d3..03e6d2a 100644
       
   162 --- ospfd/ospf_packet.c
       
   163 +++ ospfd/ospf_packet.c
       
   164 @@ -50,15 +50,16 @@
       
   165  #include "ospfd/ospf_dump.h"
       
   166  
       
   167  /* Packet Type String. */
       
   168 -const char *ospf_packet_type_str[] =
       
   169 -{
       
   170 -  "unknown",
       
   171 -  "Hello",
       
   172 -  "Database Description",
       
   173 -  "Link State Request",
       
   174 -  "Link State Update",
       
   175 -  "Link State Acknowledgment",
       
   176 +const struct message ospf_packet_type_str[] =
       
   177 +{
       
   178 +  { OSPF_MSG_HELLO,   "Hello"                     },
       
   179 +  { OSPF_MSG_DB_DESC, "Database Description"      },
       
   180 +  { OSPF_MSG_LS_REQ,  "Link State Request"        },
       
   181 +  { OSPF_MSG_LS_UPD,  "Link State Update"         },
       
   182 +  { OSPF_MSG_LS_ACK,  "Link State Acknowledgment" },
       
   183  };
       
   184 +const size_t ospf_packet_type_str_max = sizeof (ospf_packet_type_str) /
       
   185 +  sizeof (ospf_packet_type_str[0]);
       
   186  
       
   187  /* OSPF authentication checking function */
       
   188  static int
       
   189 @@ -201,7 +202,7 @@ ospf_packet_add (struct ospf_interface *oi, struct ospf_packet *op)
       
   190  	       "destination %s) called with NULL obuf, ignoring "
       
   191  	       "(please report this bug)!\n",
       
   192  	       IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
       
   193 -	       ospf_packet_type_str[stream_getc_from(op->s, 1)],
       
   194 +	       LOOKUP (ospf_packet_type_str, stream_getc_from(op->s, 1)),
       
   195  	       inet_ntoa (op->dst));
       
   196        return;
       
   197      }
       
   198 @@ -755,7 +756,7 @@ ospf_write (struct thread *thread)
       
   199  	}
       
   200  
       
   201        zlog_debug ("%s sent to [%s] via [%s].",
       
   202 -		 ospf_packet_type_str[type], inet_ntoa (op->dst),
       
   203 +		 LOOKUP (ospf_packet_type_str, type), inet_ntoa (op->dst),
       
   204  		 IF_NAME (oi));
       
   205  
       
   206        if (IS_DEBUG_OSPF_PACKET (type - 1, DETAIL))
       
   207 @@ -801,7 +802,7 @@ ospf_hello (struct ip *iph, struct ospf_header *ospfh,
       
   208          {
       
   209            zlog_debug ("ospf_header[%s/%s]: selforiginated, "
       
   210                       "dropping.",
       
   211 -                     ospf_packet_type_str[ospfh->type],
       
   212 +                     LOOKUP (ospf_packet_type_str, ospfh->type),
       
   213                       inet_ntoa (iph->ip_src));
       
   214          }
       
   215        return;
       
   216 @@ -2571,7 +2572,7 @@ ospf_read (struct thread *thread)
       
   217          }
       
   218  
       
   219        zlog_debug ("%s received from [%s] via [%s]",
       
   220 -                 ospf_packet_type_str[ospfh->type],
       
   221 +                 LOOKUP (ospf_packet_type_str, ospfh->type),
       
   222                   inet_ntoa (ospfh->router_id), IF_NAME (oi));
       
   223        zlog_debug (" src [%s],", inet_ntoa (iph->ip_src));
       
   224        zlog_debug (" dst [%s]", inet_ntoa (iph->ip_dst));
       
   225 diff --git ospfd/ospf_packet.h ospfd/ospf_packet.h
       
   226 index 9a47208..2115f11 100644
       
   227 --- ospfd/ospf_packet.h
       
   228 +++ ospfd/ospf_packet.h
       
   229 @@ -163,4 +163,7 @@ extern int ospf_ls_ack_timer (struct thread *);
       
   230  extern int ospf_poll_timer (struct thread *);
       
   231  extern int ospf_hello_reply_timer (struct thread *);
       
   232  
       
   233 +extern const struct message ospf_packet_type_str[];
       
   234 +extern const size_t ospf_packet_type_str_max;
       
   235 +
       
   236  #endif /* _ZEBRA_OSPF_PACKET_H */
       
   237 --
       
   238 cgit v0.9.0.2
       
   239 From 099ed6744881e71957f2bfeebc4c0727714d2394 Mon Sep 17 00:00:00 2001
       
   240 From: Denis Ovsienko <[email protected]>
       
   241 Date: Fri, 20 Jan 2012 18:32:10 +0000
       
   242 Subject: ospfd: fix ospf_packet_add_top() to use LOOKUP()
       
   243 
       
   244 ---
       
   245 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
       
   246 index 03e6d2a..500f245 100644
       
   247 --- ospfd/ospf_packet.c
       
   248 +++ ospfd/ospf_packet.c
       
   249 @@ -223,7 +223,7 @@ ospf_packet_add_top (struct ospf_interface *oi, struct ospf_packet *op)
       
   250  	       "destination %s) called with NULL obuf, ignoring "
       
   251  	       "(please report this bug)!\n",
       
   252  	       IF_NAME(oi), oi->state, LOOKUP (ospf_ism_state_msg, oi->state),
       
   253 -	       ospf_packet_type_str[stream_getc_from(op->s, 1)],
       
   254 +	       LOOKUP (ospf_packet_type_str, stream_getc_from(op->s, 1)),
       
   255  	       inet_ntoa (op->dst));
       
   256        return;
       
   257      }
       
   258 --
       
   259 cgit v0.9.0.2
       
   260 From 3092cd57fb44c8293995d013bd86937d1a91745f Mon Sep 17 00:00:00 2001
       
   261 From: Denis Ovsienko <[email protected]>
       
   262 Date: Mon, 30 Jan 2012 11:41:39 +0000
       
   263 Subject: ospfd: introduce ospf_packet_minlen[] (BZ#705)
       
   264 
       
   265 This commit ports some of the OSPFv3 packet reception checks
       
   266 to OSPFv2.
       
   267 
       
   268 * ospf_packet.c
       
   269   * ospf_packet_minlen[]: a direct equivalent of ospf6_packet_minlen[]
       
   270   * ospf_packet_examin(): new function designed after the first part
       
   271     of ospf6_packet_examin()
       
   272   * ospf_read(): verify received packet with ospf_packet_examin()
       
   273 * ospf_packet.h: add convenience macros
       
   274 ---
       
   275 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
       
   276 index 500f245..f425da8 100644
       
   277 --- ospfd/ospf_packet.c
       
   278 +++ ospfd/ospf_packet.c
       
   279 @@ -61,6 +61,18 @@ const struct message ospf_packet_type_str[] =
       
   280  const size_t ospf_packet_type_str_max = sizeof (ospf_packet_type_str) /
       
   281    sizeof (ospf_packet_type_str[0]);
       
   282  
       
   283 +/* Minimum (besides OSPF_HEADER_SIZE) lengths for OSPF packets of
       
   284 +   particular types, offset is the "type" field of a packet. */
       
   285 +static const u_int16_t ospf_packet_minlen[] =
       
   286 +{
       
   287 +  0,
       
   288 +  OSPF_HELLO_MIN_SIZE,
       
   289 +  OSPF_DB_DESC_MIN_SIZE,
       
   290 +  OSPF_LS_REQ_MIN_SIZE,
       
   291 +  OSPF_LS_UPD_MIN_SIZE,
       
   292 +  OSPF_LS_ACK_MIN_SIZE,
       
   293 +};
       
   294 +
       
   295  /* OSPF authentication checking function */
       
   296  static int
       
   297  ospf_auth_type (struct ospf_interface *oi)
       
   298 @@ -2309,6 +2321,47 @@ ospf_check_sum (struct ospf_header *ospfh)
       
   299    return 1;
       
   300  }
       
   301  
       
   302 +/* Verify a complete OSPF packet for proper sizing/alignment. */
       
   303 +static unsigned
       
   304 +ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
   305 +{
       
   306 +  u_int16_t bytesdeclared;
       
   307 +
       
   308 +  /* Length, 1st approximation. */
       
   309 +  if (bytesonwire < OSPF_HEADER_SIZE)
       
   310 +  {
       
   311 +    if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   312 +      zlog_debug ("%s: undersized (%u B) packet", __func__, bytesonwire);
       
   313 +    return MSG_NG;
       
   314 +  }
       
   315 +  /* Now it is safe to access header fields. Performing length check, allow
       
   316 +   * for possible extra bytes of crypto auth/padding, which are not counted
       
   317 +   * in the OSPF header "length" field. */
       
   318 +  bytesdeclared = ntohs (oh->length);
       
   319 +  if (bytesdeclared > bytesonwire)
       
   320 +  {
       
   321 +    if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   322 +      zlog_debug ("%s: packet length error (%u real, %u declared)",
       
   323 +                  __func__, bytesonwire, bytesdeclared);
       
   324 +    return MSG_NG;
       
   325 +  }
       
   326 +  /* Length, 2nd approximation. The type-specific constraint is checked
       
   327 +     against declared length, not amount of bytes on wire. */
       
   328 +  if
       
   329 +  (
       
   330 +    oh->type >= OSPF_MSG_HELLO &&
       
   331 +    oh->type <= OSPF_MSG_LS_ACK &&
       
   332 +    bytesdeclared < OSPF_HEADER_SIZE + ospf_packet_minlen[oh->type]
       
   333 +  )
       
   334 +  {
       
   335 +    if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   336 +      zlog_debug ("%s: undersized (%u B) %s packet", __func__,
       
   337 +                  bytesdeclared, LOOKUP (ospf_packet_type_str, oh->type));
       
   338 +    return MSG_NG;
       
   339 +  }
       
   340 +  return MSG_OK;
       
   341 +}
       
   342 +
       
   343  /* OSPF Header verification. */
       
   344  static int
       
   345  ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
       
   346 @@ -2404,10 +2457,10 @@ ospf_read (struct thread *thread)
       
   347    /* prepare for next packet. */
       
   348    ospf->t_read = thread_add_read (master, ospf_read, ospf, ospf->fd);
       
   349  
       
   350 -  /* read OSPF packet. */
       
   351    stream_reset(ospf->ibuf);
       
   352    if (!(ibuf = ospf_recv_packet (ospf->fd, &ifp, ospf->ibuf)))
       
   353      return -1;
       
   354 +  /* This raw packet is known to be at least as big as its IP header. */
       
   355    
       
   356    /* Note that there should not be alignment problems with this assignment
       
   357       because this is at the beginning of the stream data buffer. */
       
   358 @@ -2442,16 +2495,10 @@ ospf_read (struct thread *thread)
       
   359       by ospf_recv_packet() to be correct). */
       
   360    stream_forward_getp (ibuf, iph->ip_hl * 4);
       
   361  
       
   362 -  /* Make sure the OSPF header is really there. */
       
   363 -  if (stream_get_endp (ibuf) - stream_get_getp (ibuf) < OSPF_HEADER_SIZE)
       
   364 -  {
       
   365 -    zlog_debug ("ospf_read: ignored OSPF packet with undersized (%u bytes) header",
       
   366 -                stream_get_endp (ibuf) - stream_get_getp (ibuf));
       
   367 +  ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
       
   368 +  if (MSG_OK != ospf_packet_examin (ospfh, stream_get_endp (ibuf) - stream_get_getp (ibuf)))
       
   369      return -1;
       
   370 -  }
       
   371 -
       
   372    /* Now it is safe to access all fields of OSPF packet header. */
       
   373 -  ospfh = (struct ospf_header *) STREAM_PNT (ibuf);
       
   374  
       
   375    /* associate packet with ospf interface */
       
   376    oi = ospf_if_lookup_recv_if (ospf, iph->ip_src, ifp);
       
   377 diff --git ospfd/ospf_packet.h ospfd/ospf_packet.h
       
   378 index 2115f11..3cbe889 100644
       
   379 --- ospfd/ospf_packet.h
       
   380 +++ ospfd/ospf_packet.h
       
   381 @@ -46,6 +46,10 @@
       
   382  
       
   383  #define OSPF_HELLO_REPLY_DELAY          1
       
   384  
       
   385 +/* Return values of functions involved in packet verification, see ospf6d. */
       
   386 +#define MSG_OK    0
       
   387 +#define MSG_NG    1
       
   388 +
       
   389  struct ospf_packet
       
   390  {
       
   391    struct ospf_packet *next;
       
   392 --
       
   393 cgit v0.9.0.2
       
   394 From 3779a3bf9d27b3cccda7e45223884257af362c28 Mon Sep 17 00:00:00 2001
       
   395 From: Denis Ovsienko <[email protected]>
       
   396 Date: Mon, 30 Jan 2012 12:07:18 +0000
       
   397 Subject: ospfd: review ospf_check_auth()
       
   398 
       
   399 1. The only purpose of "ibuf" argument was to get stream size, which
       
   400 was always equal to OSPF_MAX_PACKET_SIZE + 1, exactly as initialized
       
   401 in ospf_new().
       
   402 
       
   403 2. Fix the packet size check condition, which was incorrect for very
       
   404 large packets, at least in theory.
       
   405 ---
       
   406 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
       
   407 index f425da8..a71cc99 100644
       
   408 --- ospfd/ospf_packet.c
       
   409 +++ ospfd/ospf_packet.c
       
   410 @@ -2255,8 +2255,7 @@ ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
       
   411  }
       
   412  
       
   413  static int
       
   414 -ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
       
   415 -		 struct ospf_header *ospfh)
       
   416 +ospf_check_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
       
   417  {
       
   418    int ret = 0;
       
   419    struct crypt_key *ck;
       
   420 @@ -2282,7 +2281,7 @@ ospf_check_auth (struct ospf_interface *oi, struct stream *ibuf,
       
   421        /* This is very basic, the digest processing is elsewhere */
       
   422        if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE && 
       
   423            ospfh->u.crypt.key_id == ck->key_id &&
       
   424 -          ntohs (ospfh->length) + OSPF_AUTH_SIMPLE_SIZE <= stream_get_size (ibuf))
       
   425 +          ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE <= OSPF_MAX_PACKET_SIZE)
       
   426          ret = 1;
       
   427        else
       
   428          ret = 0;
       
   429 @@ -2406,7 +2405,7 @@ ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
       
   430        return -1;
       
   431      }
       
   432  
       
   433 -  if (! ospf_check_auth (oi, ibuf, ospfh))
       
   434 +  if (! ospf_check_auth (oi, ospfh))
       
   435      {
       
   436        zlog_warn ("interface %s: ospf_read authentication failed.",
       
   437  		 IF_NAME (oi));
       
   438 --
       
   439 cgit v0.9.0.2
       
   440 From 7edfc01207f3eee8f26d5c22cfef7c7f030c52ce Mon Sep 17 00:00:00 2001
       
   441 From: Denis Ovsienko <[email protected]>
       
   442 Date: Mon, 30 Jan 2012 16:32:39 +0000
       
   443 Subject: ospfd: review ospf_check_md5_digest()
       
   444 
       
   445 Rewrite some pointer arithmetics without the additional variables and
       
   446 move byte order conversion inside the function.
       
   447 ---
       
   448 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
       
   449 index a71cc99..5704f9d 100644
       
   450 --- ospfd/ospf_packet.c
       
   451 +++ ospfd/ospf_packet.c
       
   452 @@ -304,24 +304,14 @@ ospf_packet_max (struct ospf_interface *oi)
       
   453  
       
   454  
       
   455  static int
       
   456 -ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
       
   457 -                       u_int16_t length)
       
   458 +ospf_check_md5_digest (struct ospf_interface *oi, struct ospf_header *ospfh)
       
   459  {
       
   460 -  unsigned char *ibuf;
       
   461    MD5_CTX ctx;
       
   462    unsigned char digest[OSPF_AUTH_MD5_SIZE];
       
   463 -  unsigned char *pdigest;
       
   464    struct crypt_key *ck;
       
   465 -  struct ospf_header *ospfh;
       
   466    struct ospf_neighbor *nbr;
       
   467 +  u_int16_t length = ntohs (ospfh->length);
       
   468    
       
   469 -
       
   470 -  ibuf = STREAM_PNT (s);
       
   471 -  ospfh = (struct ospf_header *) ibuf;
       
   472 -
       
   473 -  /* Get pointer to the end of the packet. */
       
   474 -  pdigest = ibuf + length;
       
   475 -
       
   476    /* Get secret key. */
       
   477    ck = ospf_crypt_key_lookup (OSPF_IF_PARAM (oi, auth_crypt),
       
   478  			      ospfh->u.crypt.key_id);
       
   479 @@ -347,12 +337,12 @@ ospf_check_md5_digest (struct ospf_interface *oi, struct stream *s,
       
   480    /* Generate a digest for the ospf packet - their digest + our digest. */
       
   481    memset(&ctx, 0, sizeof(ctx));
       
   482    MD5Init(&ctx);
       
   483 -  MD5Update(&ctx, ibuf, length);
       
   484 +  MD5Update(&ctx, ospfh, length);
       
   485    MD5Update(&ctx, ck->auth_key, OSPF_AUTH_MD5_SIZE);
       
   486    MD5Final(digest, &ctx);
       
   487  
       
   488    /* compare the two */
       
   489 -  if (memcmp (pdigest, digest, OSPF_AUTH_MD5_SIZE))
       
   490 +  if (memcmp ((caddr_t)ospfh + length, digest, OSPF_AUTH_MD5_SIZE))
       
   491      {
       
   492        zlog_warn ("interface %s: ospf_check_md5 checksum mismatch",
       
   493  		 IF_NAME (oi));
       
   494 @@ -2426,7 +2416,7 @@ ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
       
   495      {
       
   496        if (ospfh->checksum != 0)
       
   497  	return -1;
       
   498 -      if (ospf_check_md5_digest (oi, ibuf, ntohs (ospfh->length)) == 0)
       
   499 +      if (ospf_check_md5_digest (oi, ospfh) == 0)
       
   500  	{
       
   501  	  zlog_warn ("interface %s: ospf_read md5 authentication failed.",
       
   502  		     IF_NAME (oi));
       
   503 --
       
   504 cgit v0.9.0.2
       
   505 From fba10fc38f482c617fdfbb81b8d855df56eeda51 Mon Sep 17 00:00:00 2001
       
   506 From: Denis Ovsienko <[email protected]>
       
   507 Date: Fri, 17 Feb 2012 12:20:50 +0000
       
   508 Subject: ospfd: introduce ospf_lsa_minlen[] (BZ#705)
       
   509 
       
   510 This commit ports more packet checks to OSPFv2, in particular, LSA size
       
   511 verification and Router-LSA link blocks verification.
       
   512 
       
   513 * ospf_lsa.h: add LSA size macros
       
   514 * ospf_packet.h: add struct ospf_ls_update
       
   515 * ospf_packet.c
       
   516   * ospf_lsa_minlen[]: a direct equivalent of ospf6_lsa_minlen[]
       
   517   * ospf_router_lsa_links_examin(): new function, verifies trailing
       
   518     part of a Router-LSA
       
   519   * ospf_lsa_examin(): new function like ospf6_lsa_examin()
       
   520   * ospf_lsaseq_examin(): new function like ospf6_lsaseq_examin()
       
   521   * ospf_packet_examin(): add type-specific deeper level checks
       
   522 ---
       
   523 diff --git ospfd/ospf_lsa.h ospfd/ospf_lsa.h
       
   524 index bf3b083..ca0653c 100644
       
   525 --- ospfd/ospf_lsa.h
       
   526 +++ ospfd/ospf_lsa.h
       
   527 @@ -153,6 +153,7 @@ struct router_lsa_link
       
   528  };
       
   529  
       
   530  /* OSPF Router-LSAs structure. */
       
   531 +#define OSPF_ROUTER_LSA_MIN_SIZE                  16U /* w/1 link descriptor */
       
   532  struct router_lsa
       
   533  {
       
   534    struct lsa_header header;
       
   535 @@ -170,6 +171,7 @@ struct router_lsa
       
   536  };
       
   537  
       
   538  /* OSPF Network-LSAs structure. */
       
   539 +#define OSPF_NETWORK_LSA_MIN_SIZE                  8U /* w/1 router-ID */
       
   540  struct network_lsa
       
   541  {
       
   542    struct lsa_header header;
       
   543 @@ -178,6 +180,7 @@ struct network_lsa
       
   544  };
       
   545  
       
   546  /* OSPF Summary-LSAs structure. */
       
   547 +#define OSPF_SUMMARY_LSA_MIN_SIZE                  8U /* w/1 TOS metric block */
       
   548  struct summary_lsa
       
   549  {
       
   550    struct lsa_header header;
       
   551 @@ -187,6 +190,7 @@ struct summary_lsa
       
   552  };
       
   553  
       
   554  /* OSPF AS-external-LSAs structure. */
       
   555 +#define OSPF_AS_EXTERNAL_LSA_MIN_SIZE             16U /* w/1 TOS forwarding block */
       
   556  struct as_external_lsa
       
   557  {
       
   558    struct lsa_header header;
       
   559 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
       
   560 index 5704f9d..3b82820 100644
       
   561 --- ospfd/ospf_packet.c
       
   562 +++ ospfd/ospf_packet.c
       
   563 @@ -73,6 +73,24 @@ static const u_int16_t ospf_packet_minlen[] =
       
   564    OSPF_LS_ACK_MIN_SIZE,
       
   565  };
       
   566  
       
   567 +/* Minimum (besides OSPF_LSA_HEADER_SIZE) lengths for LSAs of particular
       
   568 +   types, offset is the "LSA type" field. */
       
   569 +static const u_int16_t ospf_lsa_minlen[] =
       
   570 +{
       
   571 +  0,
       
   572 +  OSPF_ROUTER_LSA_MIN_SIZE,
       
   573 +  OSPF_NETWORK_LSA_MIN_SIZE,
       
   574 +  OSPF_SUMMARY_LSA_MIN_SIZE,
       
   575 +  OSPF_SUMMARY_LSA_MIN_SIZE,
       
   576 +  OSPF_AS_EXTERNAL_LSA_MIN_SIZE,
       
   577 +  0,
       
   578 +  OSPF_AS_EXTERNAL_LSA_MIN_SIZE,
       
   579 +  0,
       
   580 +  0,
       
   581 +  0,
       
   582 +  0,
       
   583 +};
       
   584 +
       
   585  /* OSPF authentication checking function */
       
   586  static int
       
   587  ospf_auth_type (struct ospf_interface *oi)
       
   588 @@ -2310,11 +2328,199 @@ ospf_check_sum (struct ospf_header *ospfh)
       
   589    return 1;
       
   590  }
       
   591  
       
   592 +/* Verify, that given link/TOS records are properly sized/aligned and match
       
   593 +   Router-LSA "# links" and "# TOS" fields as specified in RFC2328 A.4.2. */
       
   594 +static unsigned
       
   595 +ospf_router_lsa_links_examin
       
   596 +(
       
   597 +  struct router_lsa_link * link,
       
   598 +  u_int16_t linkbytes,
       
   599 +  const u_int16_t num_links
       
   600 +)
       
   601 +{
       
   602 +  unsigned counted_links = 0, thislinklen;
       
   603 +
       
   604 +  while (linkbytes)
       
   605 +  {
       
   606 +    thislinklen = OSPF_ROUTER_LSA_LINK_SIZE + 4 * link->m[0].tos_count;
       
   607 +    if (thislinklen > linkbytes)
       
   608 +    {
       
   609 +      if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   610 +        zlog_debug ("%s: length error in link block #%u", __func__, counted_links);
       
   611 +      return MSG_NG;
       
   612 +    }
       
   613 +    link = (struct router_lsa_link *)((caddr_t) link + thislinklen);
       
   614 +    linkbytes -= thislinklen;
       
   615 +    counted_links++;
       
   616 +  }
       
   617 +  if (counted_links != num_links)
       
   618 +  {
       
   619 +    if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   620 +      zlog_debug ("%s: %u link blocks declared, %u present",
       
   621 +                  __func__, num_links, counted_links);
       
   622 +    return MSG_NG;
       
   623 +  }
       
   624 +  return MSG_OK;
       
   625 +}
       
   626 +
       
   627 +/* Verify, that the given LSA is properly sized/aligned (including type-specific
       
   628 +   minimum length constraint). */
       
   629 +static unsigned
       
   630 +ospf_lsa_examin (struct lsa_header * lsah, const u_int16_t lsalen, const u_char headeronly)
       
   631 +{
       
   632 +  unsigned ret;
       
   633 +  struct router_lsa * rlsa;
       
   634 +  if
       
   635 +  (
       
   636 +    lsah->type < OSPF_MAX_LSA &&
       
   637 +    ospf_lsa_minlen[lsah->type] &&
       
   638 +    lsalen < OSPF_LSA_HEADER_SIZE + ospf_lsa_minlen[lsah->type]
       
   639 +  )
       
   640 +  {
       
   641 +    if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   642 +      zlog_debug ("%s: undersized (%u B) %s",
       
   643 +                  __func__, lsalen, LOOKUP (ospf_lsa_type_msg, lsah->type));
       
   644 +    return MSG_NG;
       
   645 +  }
       
   646 +  switch (lsah->type)
       
   647 +  {
       
   648 +  case OSPF_ROUTER_LSA:
       
   649 +    /* RFC2328 A.4.2, LSA header + 4 bytes followed by N>=1 (12+)-byte link blocks */
       
   650 +    if (headeronly)
       
   651 +    {
       
   652 +      ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_ROUTER_LSA_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
       
   653 +      break;
       
   654 +    }
       
   655 +    rlsa = (struct router_lsa *) lsah;
       
   656 +    ret = ospf_router_lsa_links_examin
       
   657 +    (
       
   658 +      (struct router_lsa_link *) rlsa->link,
       
   659 +      lsalen - OSPF_LSA_HEADER_SIZE - 4, /* skip: basic header, "flags", 0, "# links" */
       
   660 +      ntohs (rlsa->links) /* 16 bits */
       
   661 +    );
       
   662 +    break;
       
   663 +  case OSPF_AS_EXTERNAL_LSA:
       
   664 +    /* RFC2328 A.4.5, LSA header + 4 bytes followed by N>=1 12-bytes long blocks */
       
   665 +  case OSPF_AS_NSSA_LSA:
       
   666 +    /* RFC3101 C, idem */
       
   667 +    ret = (lsalen - OSPF_LSA_HEADER_SIZE - OSPF_AS_EXTERNAL_LSA_MIN_SIZE) % 12 ? MSG_NG : MSG_OK;
       
   668 +    break;
       
   669 +  /* Following LSA types are considered OK length-wise as soon as their minimum
       
   670 +   * length constraint is met and length of the whole LSA is a multiple of 4
       
   671 +   * (basic LSA header size is already a multiple of 4). */
       
   672 +  case OSPF_NETWORK_LSA:
       
   673 +    /* RFC2328 A.4.3, LSA header + 4 bytes followed by N>=1 router-IDs */
       
   674 +  case OSPF_SUMMARY_LSA:
       
   675 +  case OSPF_ASBR_SUMMARY_LSA:
       
   676 +    /* RFC2328 A.4.4, LSA header + 4 bytes followed by N>=1 4-bytes TOS blocks */
       
   677 +#ifdef HAVE_OPAQUE_LSA
       
   678 +  case OSPF_OPAQUE_LINK_LSA:
       
   679 +  case OSPF_OPAQUE_AREA_LSA:
       
   680 +  case OSPF_OPAQUE_AS_LSA:
       
   681 +    /* RFC5250 A.2, "some number of octets (of application-specific
       
   682 +     * data) padded to 32-bit alignment." This is considered equivalent
       
   683 +     * to 4-byte alignment of all other LSA types, see OSPF-ALIGNMENT.txt
       
   684 +     * file for the detailed analysis of this passage. */
       
   685 +#endif
       
   686 +    ret = lsalen % 4 ? MSG_NG : MSG_OK;
       
   687 +    break;
       
   688 +  default:
       
   689 +    if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   690 +      zlog_debug ("%s: unsupported LSA type 0x%02x", __func__, lsah->type);
       
   691 +    return MSG_NG;
       
   692 +  }
       
   693 +  if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV))
       
   694 +    zlog_debug ("%s: alignment error in %s",
       
   695 +                __func__, LOOKUP (ospf_lsa_type_msg, lsah->type));
       
   696 +  return ret;
       
   697 +}
       
   698 +
       
   699 +/* Verify if the provided input buffer is a valid sequence of LSAs. This
       
   700 +   includes verification of LSA blocks length/alignment and dispatching
       
   701 +   of deeper-level checks. */
       
   702 +static unsigned
       
   703 +ospf_lsaseq_examin
       
   704 +(
       
   705 +  struct lsa_header *lsah, /* start of buffered data */
       
   706 +  size_t length,
       
   707 +  const u_char headeronly,
       
   708 +  /* When declared_num_lsas is not 0, compare it to the real number of LSAs
       
   709 +     and treat the difference as an error. */
       
   710 +  const u_int32_t declared_num_lsas
       
   711 +)
       
   712 +{
       
   713 +  u_int32_t counted_lsas = 0;
       
   714 +
       
   715 +  while (length)
       
   716 +  {
       
   717 +    u_int16_t lsalen;
       
   718 +    if (length < OSPF_LSA_HEADER_SIZE)
       
   719 +    {
       
   720 +      if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   721 +        zlog_debug ("%s: undersized (%zu B) trailing (#%u) LSA header",
       
   722 +                    __func__, length, counted_lsas);
       
   723 +      return MSG_NG;
       
   724 +    }
       
   725 +    /* save on ntohs() calls here and in the LSA validator */
       
   726 +    lsalen = ntohs (lsah->length);
       
   727 +    if (lsalen < OSPF_LSA_HEADER_SIZE)
       
   728 +    {
       
   729 +      if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   730 +        zlog_debug ("%s: malformed LSA header #%u, declared length is %u B",
       
   731 +                    __func__, counted_lsas, lsalen);
       
   732 +      return MSG_NG;
       
   733 +    }
       
   734 +    if (headeronly)
       
   735 +    {
       
   736 +      /* less checks here and in ospf_lsa_examin() */
       
   737 +      if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 1))
       
   738 +      {
       
   739 +        if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   740 +          zlog_debug ("%s: malformed header-only LSA #%u", __func__, counted_lsas);
       
   741 +        return MSG_NG;
       
   742 +      }
       
   743 +      lsah = (struct lsa_header *) ((caddr_t) lsah + OSPF_LSA_HEADER_SIZE);
       
   744 +      length -= OSPF_LSA_HEADER_SIZE;
       
   745 +    }
       
   746 +    else
       
   747 +    {
       
   748 +      /* make sure the input buffer is deep enough before further checks */
       
   749 +      if (lsalen > length)
       
   750 +      {
       
   751 +        if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   752 +          zlog_debug ("%s: anomaly in LSA #%u: declared length is %u B, buffered length is %zu B",
       
   753 +                      __func__, counted_lsas, lsalen, length);
       
   754 +        return MSG_NG;
       
   755 +      }
       
   756 +      if (MSG_OK != ospf_lsa_examin (lsah, lsalen, 0))
       
   757 +      {
       
   758 +        if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   759 +          zlog_debug ("%s: malformed LSA #%u", __func__, counted_lsas);
       
   760 +        return MSG_NG;
       
   761 +      }
       
   762 +      lsah = (struct lsa_header *) ((caddr_t) lsah + lsalen);
       
   763 +      length -= lsalen;
       
   764 +    }
       
   765 +    counted_lsas++;
       
   766 +  }
       
   767 +
       
   768 +  if (declared_num_lsas && counted_lsas != declared_num_lsas)
       
   769 +  {
       
   770 +    if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   771 +      zlog_debug ("%s: #LSAs declared (%u) does not match actual (%u)",
       
   772 +                  __func__, declared_num_lsas, counted_lsas);
       
   773 +    return MSG_NG;
       
   774 +  }
       
   775 +  return MSG_OK;
       
   776 +}
       
   777 +
       
   778  /* Verify a complete OSPF packet for proper sizing/alignment. */
       
   779  static unsigned
       
   780  ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
   781  {
       
   782    u_int16_t bytesdeclared;
       
   783 +  unsigned ret;
       
   784 +  struct ospf_ls_update * lsupd;
       
   785  
       
   786    /* Length, 1st approximation. */
       
   787    if (bytesonwire < OSPF_HEADER_SIZE)
       
   788 @@ -2348,7 +2554,59 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
   789                    bytesdeclared, LOOKUP (ospf_packet_type_str, oh->type));
       
   790      return MSG_NG;
       
   791    }
       
   792 -  return MSG_OK;
       
   793 +  switch (oh->type)
       
   794 +  {
       
   795 +  case OSPF_MSG_HELLO:
       
   796 +    /* RFC2328 A.3.2, packet header + OSPF_HELLO_MIN_SIZE bytes followed
       
   797 +       by N>=0 router-IDs. */
       
   798 +    ret = (bytesonwire - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
       
   799 +    break;
       
   800 +  case OSPF_MSG_DB_DESC:
       
   801 +    /* RFC2328 A.3.3, packet header + OSPF_DB_DESC_MIN_SIZE bytes followed
       
   802 +       by N>=0 header-only LSAs. */
       
   803 +    ret = ospf_lsaseq_examin
       
   804 +    (
       
   805 +      (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE),
       
   806 +      bytesonwire - OSPF_HEADER_SIZE - OSPF_DB_DESC_MIN_SIZE,
       
   807 +      1, /* header-only LSAs */
       
   808 +      0
       
   809 +    );
       
   810 +    break;
       
   811 +  case OSPF_MSG_LS_REQ:
       
   812 +    /* RFC2328 A.3.4, packet header followed by N>=0 12-bytes request blocks. */
       
   813 +    ret = (bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) %
       
   814 +      OSPF_LSA_KEY_SIZE ? MSG_NG : MSG_OK;
       
   815 +    break;
       
   816 +  case OSPF_MSG_LS_UPD:
       
   817 +    /* RFC2328 A.3.5, packet header + OSPF_LS_UPD_MIN_SIZE bytes followed
       
   818 +       by N>=0 full LSAs (with N declared beforehand). */
       
   819 +    lsupd = (struct ospf_ls_update *) ((caddr_t) oh + OSPF_HEADER_SIZE);
       
   820 +    ret = ospf_lsaseq_examin
       
   821 +    (
       
   822 +      (struct lsa_header *) ((caddr_t) lsupd + OSPF_LS_UPD_MIN_SIZE),
       
   823 +      bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE,
       
   824 +      0, /* full LSAs */
       
   825 +      ntohl (lsupd->num_lsas) /* 32 bits */
       
   826 +    );
       
   827 +    break;
       
   828 +  case OSPF_MSG_LS_ACK:
       
   829 +    /* RFC2328 A.3.6, packet header followed by N>=0 header-only LSAs. */
       
   830 +    ret = ospf_lsaseq_examin
       
   831 +    (
       
   832 +      (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_LS_ACK_MIN_SIZE),
       
   833 +      bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE,
       
   834 +      1, /* header-only LSAs */
       
   835 +      0
       
   836 +    );
       
   837 +    break;
       
   838 +  default:
       
   839 +    if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
   840 +      zlog_debug ("%s: invalid packet type 0x%02x", __func__, oh->type);
       
   841 +    return MSG_NG;
       
   842 +  }
       
   843 +  if (ret != MSG_OK && IS_DEBUG_OSPF_PACKET (0, RECV))
       
   844 +    zlog_debug ("%s: malformed %s packet", __func__, LOOKUP (ospf_packet_type_str, oh->type));
       
   845 +  return ret;
       
   846  }
       
   847  
       
   848  /* OSPF Header verification. */
       
   849 diff --git ospfd/ospf_packet.h ospfd/ospf_packet.h
       
   850 index 3cbe889..337686a 100644
       
   851 --- ospfd/ospf_packet.h
       
   852 +++ ospfd/ospf_packet.h
       
   853 @@ -121,6 +121,10 @@ struct ospf_db_desc
       
   854    u_int32_t dd_seqnum;
       
   855  };
       
   856  
       
   857 +struct ospf_ls_update
       
   858 +{
       
   859 +  u_int32_t num_lsas;
       
   860 +};
       
   861  
       
   862  /* Macros. */
       
   863  /* XXX Perhaps obsolete; function in ospf_packet.c */
       
   864 --
       
   865 cgit v0.9.0.2
       
   866 From b03ae9f2d22acd8e3f97714a9c0df744676e344d Mon Sep 17 00:00:00 2001
       
   867 From: Denis Ovsienko <[email protected]>
       
   868 Date: Mon, 20 Feb 2012 19:08:10 +0000
       
   869 Subject: ospfd: fix packet length check for auth/LLS cases
       
   870 
       
   871 An OSPFv2 packet with trailing data blocks (authentication and/or
       
   872 link-local signaling) failed the recently implemented packet length
       
   873 check, because trailing data length isn't counted in the packet header
       
   874 "length" field. This commit fixes respective check conditions.
       
   875 
       
   876 * ospf_packet.c
       
   877   * ospf_packet_examin(): use "bytesdeclared" instead of "bytesonwire"
       
   878 ---
       
   879 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
       
   880 index 3b82820..7b661a3 100644
       
   881 --- ospfd/ospf_packet.c
       
   882 +++ ospfd/ospf_packet.c
       
   883 @@ -2559,7 +2559,7 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
   884    case OSPF_MSG_HELLO:
       
   885      /* RFC2328 A.3.2, packet header + OSPF_HELLO_MIN_SIZE bytes followed
       
   886         by N>=0 router-IDs. */
       
   887 -    ret = (bytesonwire - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
       
   888 +    ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_HELLO_MIN_SIZE) % 4 ? MSG_NG : MSG_OK;
       
   889      break;
       
   890    case OSPF_MSG_DB_DESC:
       
   891      /* RFC2328 A.3.3, packet header + OSPF_DB_DESC_MIN_SIZE bytes followed
       
   892 @@ -2567,14 +2567,14 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
   893      ret = ospf_lsaseq_examin
       
   894      (
       
   895        (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_DB_DESC_MIN_SIZE),
       
   896 -      bytesonwire - OSPF_HEADER_SIZE - OSPF_DB_DESC_MIN_SIZE,
       
   897 +      bytesdeclared - OSPF_HEADER_SIZE - OSPF_DB_DESC_MIN_SIZE,
       
   898        1, /* header-only LSAs */
       
   899        0
       
   900      );
       
   901      break;
       
   902    case OSPF_MSG_LS_REQ:
       
   903      /* RFC2328 A.3.4, packet header followed by N>=0 12-bytes request blocks. */
       
   904 -    ret = (bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) %
       
   905 +    ret = (bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_REQ_MIN_SIZE) %
       
   906        OSPF_LSA_KEY_SIZE ? MSG_NG : MSG_OK;
       
   907      break;
       
   908    case OSPF_MSG_LS_UPD:
       
   909 @@ -2584,7 +2584,7 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
   910      ret = ospf_lsaseq_examin
       
   911      (
       
   912        (struct lsa_header *) ((caddr_t) lsupd + OSPF_LS_UPD_MIN_SIZE),
       
   913 -      bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE,
       
   914 +      bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_UPD_MIN_SIZE,
       
   915        0, /* full LSAs */
       
   916        ntohl (lsupd->num_lsas) /* 32 bits */
       
   917      );
       
   918 @@ -2594,7 +2594,7 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
   919      ret = ospf_lsaseq_examin
       
   920      (
       
   921        (struct lsa_header *) ((caddr_t) oh + OSPF_HEADER_SIZE + OSPF_LS_ACK_MIN_SIZE),
       
   922 -      bytesonwire - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE,
       
   923 +      bytesdeclared - OSPF_HEADER_SIZE - OSPF_LS_ACK_MIN_SIZE,
       
   924        1, /* header-only LSAs */
       
   925        0
       
   926      );
       
   927 --
       
   928 cgit v0.9.0.2
       
   929 From 1bdd96caefaa76883bece4d358a60dc890f1e375 Mon Sep 17 00:00:00 2001
       
   930 From: Denis Ovsienko <[email protected]>
       
   931 Date: Sun, 26 Feb 2012 13:00:57 +0000
       
   932 Subject: ospfd: introduce ospf_auth_type_str[]
       
   933 
       
   934 ---
       
   935 diff --git ospfd/ospf_dump.c ospfd/ospf_dump.c
       
   936 index 8ace095..7e11e25 100644
       
   937 --- ospfd/ospf_dump.c
       
   938 +++ ospfd/ospf_dump.c
       
   939 @@ -115,6 +115,16 @@ const struct message ospf_network_type_msg[] =
       
   940  };
       
   941  const int ospf_network_type_msg_max = OSPF_IFTYPE_MAX;
       
   942  
       
   943 +/* AuType */
       
   944 +const struct message ospf_auth_type_str[] =
       
   945 +{
       
   946 +  { OSPF_AUTH_NULL,          "Null"          },
       
   947 +  { OSPF_AUTH_SIMPLE,        "Simple"        },
       
   948 +  { OSPF_AUTH_CRYPTOGRAPHIC, "Cryptographic" },
       
   949 +};
       
   950 +const size_t ospf_auth_type_str_max = sizeof (ospf_auth_type_str) /
       
   951 +  sizeof (ospf_auth_type_str[0]);
       
   952 +
       
   953  /* Configuration debug option variables. */
       
   954  unsigned long conf_debug_ospf_packet[5] = {0, 0, 0, 0, 0};
       
   955  unsigned long conf_debug_ospf_event = 0;
       
   956 @@ -657,6 +667,7 @@ static void
       
   957  ospf_header_dump (struct ospf_header *ospfh)
       
   958  {
       
   959    char buf[9];
       
   960 +  u_int16_t auth_type = ntohs (ospfh->auth_type);
       
   961  
       
   962    zlog_debug ("Header");
       
   963    zlog_debug ("  Version %d", ospfh->version);
       
   964 @@ -666,9 +677,9 @@ ospf_header_dump (struct ospf_header *ospfh)
       
   965    zlog_debug ("  Router ID %s", inet_ntoa (ospfh->router_id));
       
   966    zlog_debug ("  Area ID %s", inet_ntoa (ospfh->area_id));
       
   967    zlog_debug ("  Checksum 0x%x", ntohs (ospfh->checksum));
       
   968 -  zlog_debug ("  AuType %d", ntohs (ospfh->auth_type));
       
   969 +  zlog_debug ("  AuType %s", LOOKUP (ospf_auth_type_str, auth_type));
       
   970  
       
   971 -  switch (ntohs (ospfh->auth_type))
       
   972 +  switch (auth_type)
       
   973      {
       
   974      case OSPF_AUTH_NULL:
       
   975        break;
       
   976 diff --git ospfd/ospf_dump.h ospfd/ospf_dump.h
       
   977 index 455214f..a2d5e8b 100644
       
   978 --- ospfd/ospf_dump.h
       
   979 +++ ospfd/ospf_dump.h
       
   980 @@ -122,6 +122,8 @@ extern unsigned long term_debug_ospf_nssa;
       
   981  
       
   982  /* Message Strings. */
       
   983  extern char *ospf_lsa_type_str[];
       
   984 +extern const struct message ospf_auth_type_str[];
       
   985 +extern const size_t ospf_auth_type_str_max;
       
   986  
       
   987  /* Prototypes. */
       
   988  extern const char *ospf_area_name_string (struct ospf_area *);
       
   989 --
       
   990 cgit v0.9.0.2
       
   991 From e5fa148725fb2a3d1a8df12683f023ff9d65273f Mon Sep 17 00:00:00 2001
       
   992 From: Denis Ovsienko <[email protected]>
       
   993 Date: Sun, 26 Feb 2012 13:59:43 +0000
       
   994 Subject: ospfd: bring ospf_check_auth() into focus
       
   995 
       
   996 The old ospf_check_auth() function did two different jobs depending on
       
   997 AuType. For Null and Simple cases it actually authenticated the packet,
       
   998 but for Cryptographic case it only checked declared packet size (not
       
   999 taking the actual number of bytes on wire into account). The calling
       
  1000 function, ospf_verify_header(), had its own set of MD5/checksum checks
       
  1001 dispatched depending on AuType.
       
  1002 
       
  1003 This commit makes the packet size check work against the real number of
       
  1004 bytes and moves it to ospf_packet_examine(). All MD5/checksum
       
  1005 verification is now performed in ospf_check_auth() function.
       
  1006 
       
  1007 * ospf_packet.c
       
  1008   * ospf_packet_examin(): check length with MD5 bytes in mind
       
  1009   * ospf_verify_header(): remove all AuType-specific code
       
  1010   * ospf_check_auth(): completely rewrite
       
  1011 ---
       
  1012 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
       
  1013 index 7b661a3..05651d3 100644
       
  1014 --- ospfd/ospf_packet.c
       
  1015 +++ ospfd/ospf_packet.c
       
  1016 @@ -91,6 +91,9 @@ static const u_int16_t ospf_lsa_minlen[] =
       
  1017    0,
       
  1018  };
       
  1019  
       
  1020 +/* for ospf_check_auth() */
       
  1021 +static int ospf_check_sum (struct ospf_header *);
       
  1022 +
       
  1023  /* OSPF authentication checking function */
       
  1024  static int
       
  1025  ospf_auth_type (struct ospf_interface *oi)
       
  1026 @@ -2262,44 +2265,91 @@ ospf_check_network_mask (struct ospf_interface *oi, struct in_addr ip_src)
       
  1027   return 0;
       
  1028  }
       
  1029  
       
  1030 +/* Return 1, if the packet is properly authenticated and checksummed,
       
  1031 +   0 otherwise. In particular, check that AuType header field is valid and
       
  1032 +   matches the locally configured AuType, and that D.5 requirements are met. */
       
  1033  static int
       
  1034  ospf_check_auth (struct ospf_interface *oi, struct ospf_header *ospfh)
       
  1035  {
       
  1036 -  int ret = 0;
       
  1037    struct crypt_key *ck;
       
  1038 +  u_int16_t iface_auth_type;
       
  1039 +  u_int16_t pkt_auth_type = ntohs (ospfh->auth_type);
       
  1040  
       
  1041 -  switch (ntohs (ospfh->auth_type))
       
  1042 +  switch (pkt_auth_type)
       
  1043 +  {
       
  1044 +  case OSPF_AUTH_NULL: /* RFC2328 D.5.1 */
       
  1045 +    if (OSPF_AUTH_NULL != (iface_auth_type = ospf_auth_type (oi)))
       
  1046      {
       
  1047 -    case OSPF_AUTH_NULL:
       
  1048 -      ret = 1;
       
  1049 -      break;
       
  1050 -    case OSPF_AUTH_SIMPLE:
       
  1051 -      if (!memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
       
  1052 -	ret = 1;
       
  1053 -      else
       
  1054 -	ret = 0;
       
  1055 -      break;
       
  1056 -    case OSPF_AUTH_CRYPTOGRAPHIC:
       
  1057 -      if ((ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) == NULL)
       
  1058 -	{
       
  1059 -	  ret = 0;
       
  1060 -	  break;
       
  1061 -	}
       
  1062 -      
       
  1063 -      /* This is very basic, the digest processing is elsewhere */
       
  1064 -      if (ospfh->u.crypt.auth_data_len == OSPF_AUTH_MD5_SIZE && 
       
  1065 -          ospfh->u.crypt.key_id == ck->key_id &&
       
  1066 -          ntohs (ospfh->length) + OSPF_AUTH_MD5_SIZE <= OSPF_MAX_PACKET_SIZE)
       
  1067 -        ret = 1;
       
  1068 -      else
       
  1069 -        ret = 0;
       
  1070 -      break;
       
  1071 -    default:
       
  1072 -      ret = 0;
       
  1073 -      break;
       
  1074 +      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       
  1075 +        zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Null",
       
  1076 +                   IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type));
       
  1077 +      return 0;
       
  1078      }
       
  1079 -
       
  1080 -  return ret;
       
  1081 +    if (! ospf_check_sum (ospfh))
       
  1082 +    {
       
  1083 +      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       
  1084 +        zlog_warn ("interface %s: Null auth OK, but checksum error, Router-ID %s",
       
  1085 +                   IF_NAME (oi), inet_ntoa (ospfh->router_id));
       
  1086 +      return 0;
       
  1087 +    }
       
  1088 +    return 1;
       
  1089 +  case OSPF_AUTH_SIMPLE: /* RFC2328 D.5.2 */
       
  1090 +    if (OSPF_AUTH_SIMPLE != (iface_auth_type = ospf_auth_type (oi)))
       
  1091 +    {
       
  1092 +      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       
  1093 +        zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Simple",
       
  1094 +                   IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type));
       
  1095 +      return 0;
       
  1096 +    }
       
  1097 +    if (memcmp (OSPF_IF_PARAM (oi, auth_simple), ospfh->u.auth_data, OSPF_AUTH_SIMPLE_SIZE))
       
  1098 +    {
       
  1099 +      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       
  1100 +        zlog_warn ("interface %s: Simple auth failed", IF_NAME (oi));
       
  1101 +      return 0;
       
  1102 +    }
       
  1103 +    if (! ospf_check_sum (ospfh))
       
  1104 +    {
       
  1105 +      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       
  1106 +        zlog_warn ("interface %s: Simple auth OK, checksum error, Router-ID %s",
       
  1107 +                   IF_NAME (oi), inet_ntoa (ospfh->router_id));
       
  1108 +      return 0;
       
  1109 +    }
       
  1110 +    return 1;
       
  1111 +  case OSPF_AUTH_CRYPTOGRAPHIC: /* RFC2328 D.5.3 */
       
  1112 +    if (OSPF_AUTH_CRYPTOGRAPHIC != (iface_auth_type = ospf_auth_type (oi)))
       
  1113 +    {
       
  1114 +      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       
  1115 +        zlog_warn ("interface %s: auth-type mismatch, local %s, rcvd Cryptographic",
       
  1116 +                   IF_NAME (oi), LOOKUP (ospf_auth_type_str, iface_auth_type));
       
  1117 +      return 0;
       
  1118 +    }
       
  1119 +    if (ospfh->checksum)
       
  1120 +    {
       
  1121 +      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       
  1122 +        zlog_warn ("interface %s: OSPF header checksum is not 0", IF_NAME (oi));
       
  1123 +      return 0;
       
  1124 +    }
       
  1125 +    /* only MD5 crypto method can pass ospf_packet_examin() */
       
  1126 +    if
       
  1127 +    (
       
  1128 +      NULL == (ck = listgetdata (listtail(OSPF_IF_PARAM (oi,auth_crypt)))) ||
       
  1129 +      ospfh->u.crypt.key_id != ck->key_id ||
       
  1130 +      /* Condition above uses the last key ID on the list, which is
       
  1131 +         different from what ospf_crypt_key_lookup() does. A bug? */
       
  1132 +      ! ospf_check_md5_digest (oi, ospfh)
       
  1133 +    )
       
  1134 +    {
       
  1135 +      if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       
  1136 +        zlog_warn ("interface %s: MD5 auth failed", IF_NAME (oi));
       
  1137 +      return 0;
       
  1138 +    }
       
  1139 +    return 1;
       
  1140 +  default:
       
  1141 +    if (IS_DEBUG_OSPF_PACKET (ospfh->type - 1, RECV))
       
  1142 +      zlog_warn ("interface %s: invalid packet auth-type (%02x)",
       
  1143 +                 IF_NAME (oi), pkt_auth_type);
       
  1144 +    return 0;
       
  1145 +  }
       
  1146  }
       
  1147  
       
  1148  static int
       
  1149 @@ -2518,7 +2568,7 @@ ospf_lsaseq_examin
       
  1150  static unsigned
       
  1151  ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
  1152  {
       
  1153 -  u_int16_t bytesdeclared;
       
  1154 +  u_int16_t bytesdeclared, bytesauth;
       
  1155    unsigned ret;
       
  1156    struct ospf_ls_update * lsupd;
       
  1157  
       
  1158 @@ -2533,11 +2583,24 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
  1159     * for possible extra bytes of crypto auth/padding, which are not counted
       
  1160     * in the OSPF header "length" field. */
       
  1161    bytesdeclared = ntohs (oh->length);
       
  1162 -  if (bytesdeclared > bytesonwire)
       
  1163 +  if (ntohs (oh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
       
  1164 +    bytesauth = 0;
       
  1165 +  else
       
  1166 +  {
       
  1167 +    if (oh->u.crypt.auth_data_len != OSPF_AUTH_MD5_SIZE)
       
  1168 +    {
       
  1169 +      if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
  1170 +        zlog_debug ("%s: unsupported crypto auth length (%u B)",
       
  1171 +                    __func__, oh->u.crypt.auth_data_len);
       
  1172 +      return MSG_NG;
       
  1173 +    }
       
  1174 +    bytesauth = OSPF_AUTH_MD5_SIZE;
       
  1175 +  }
       
  1176 +  if (bytesdeclared + bytesauth > bytesonwire)
       
  1177    {
       
  1178      if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
  1179 -      zlog_debug ("%s: packet length error (%u real, %u declared)",
       
  1180 -                  __func__, bytesonwire, bytesdeclared);
       
  1181 +      zlog_debug ("%s: packet length error (%u real, %u+%u declared)",
       
  1182 +                  __func__, bytesonwire, bytesdeclared, bytesauth);
       
  1183      return MSG_NG;
       
  1184    }
       
  1185    /* Length, 2nd approximation. The type-specific constraint is checked
       
  1186 @@ -2645,42 +2708,9 @@ ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
       
  1187        return -1;
       
  1188      }
       
  1189  
       
  1190 -  /* Check authentication. */
       
  1191 -  if (ospf_auth_type (oi) != ntohs (ospfh->auth_type))
       
  1192 -    {
       
  1193 -      zlog_warn ("interface %s: auth-type mismatch, local %d, rcvd %d",
       
  1194 -		 IF_NAME (oi), ospf_auth_type (oi), ntohs (ospfh->auth_type));
       
  1195 -      return -1;
       
  1196 -    }
       
  1197 -
       
  1198 +  /* Check authentication. The function handles logging actions, where required. */
       
  1199    if (! ospf_check_auth (oi, ospfh))
       
  1200 -    {
       
  1201 -      zlog_warn ("interface %s: ospf_read authentication failed.",
       
  1202 -		 IF_NAME (oi));
       
  1203 -      return -1;
       
  1204 -    }
       
  1205 -
       
  1206 -  /* if check sum is invalid, packet is discarded. */
       
  1207 -  if (ntohs (ospfh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
       
  1208 -    {
       
  1209 -      if (! ospf_check_sum (ospfh))
       
  1210 -	{
       
  1211 -	  zlog_warn ("interface %s: ospf_read packet checksum error %s",
       
  1212 -		     IF_NAME (oi), inet_ntoa (ospfh->router_id));
       
  1213 -	  return -1;
       
  1214 -	}
       
  1215 -    }
       
  1216 -  else
       
  1217 -    {
       
  1218 -      if (ospfh->checksum != 0)
       
  1219 -	return -1;
       
  1220 -      if (ospf_check_md5_digest (oi, ospfh) == 0)
       
  1221 -	{
       
  1222 -	  zlog_warn ("interface %s: ospf_read md5 authentication failed.",
       
  1223 -		     IF_NAME (oi));
       
  1224 -	  return -1;
       
  1225 -	}
       
  1226 -    }
       
  1227 +    return -1;
       
  1228  
       
  1229    return 0;
       
  1230  }
       
  1231 --
       
  1232 cgit v0.9.0.2
       
  1233 From a59c5401a2df169de2c780f13a4563548c04a2b7 Mon Sep 17 00:00:00 2001
       
  1234 From: Denis Ovsienko <[email protected]>
       
  1235 Date: Tue, 28 Feb 2012 11:15:29 +0000
       
  1236 Subject: ospfd: reduce ospf_verify_header()
       
  1237 
       
  1238 Protocol version checks fits ospf_packet_examin() better (like it is
       
  1239 implemented in ospf6d), and packet type check is already there.
       
  1240 ---
       
  1241 diff --git ospfd/ospf_packet.c ospfd/ospf_packet.c
       
  1242 index 05651d3..de14ccc 100644
       
  1243 --- ospfd/ospf_packet.c
       
  1244 +++ ospfd/ospf_packet.c
       
  1245 @@ -2582,6 +2582,12 @@ ospf_packet_examin (struct ospf_header * oh, const unsigned bytesonwire)
       
  1246    /* Now it is safe to access header fields. Performing length check, allow
       
  1247     * for possible extra bytes of crypto auth/padding, which are not counted
       
  1248     * in the OSPF header "length" field. */
       
  1249 +  if (oh->version != OSPF_VERSION)
       
  1250 +  {
       
  1251 +    if (IS_DEBUG_OSPF_PACKET (0, RECV))
       
  1252 +      zlog_debug ("%s: invalid (%u) protocol version", __func__, oh->version);
       
  1253 +    return MSG_NG;
       
  1254 +  }
       
  1255    bytesdeclared = ntohs (oh->length);
       
  1256    if (ntohs (oh->auth_type) != OSPF_AUTH_CRYPTOGRAPHIC)
       
  1257      bytesauth = 0;
       
  1258 @@ -2677,21 +2683,6 @@ static int
       
  1259  ospf_verify_header (struct stream *ibuf, struct ospf_interface *oi,
       
  1260  		    struct ip *iph, struct ospf_header *ospfh)
       
  1261  {
       
  1262 -  /* check version. */
       
  1263 -  if (ospfh->version != OSPF_VERSION)
       
  1264 -    {
       
  1265 -      zlog_warn ("interface %s: ospf_read version number mismatch.",
       
  1266 -		 IF_NAME (oi));
       
  1267 -      return -1;
       
  1268 -    }
       
  1269 -
       
  1270 -  /* Valid OSPFv2 packet types are 1 through 5 inclusive. */
       
  1271 -  if (ospfh->type < 1 || ospfh->type > 5)
       
  1272 -  {
       
  1273 -    zlog_warn ("interface %s: invalid packet type %u", IF_NAME (oi), ospfh->type);
       
  1274 -    return -1;
       
  1275 -  }
       
  1276 -
       
  1277    /* Check Area ID. */
       
  1278    if (!ospf_check_area_id (oi, ospfh))
       
  1279      {
       
  1280 --
       
  1281 cgit v0.9.0.2