diff options
| -rw-r--r-- | ripd/ChangeLog | 32 | ||||
| -rw-r--r-- | ripd/rip_interface.c | 64 | ||||
| -rw-r--r-- | ripd/ripd.c | 124 | ||||
| -rw-r--r-- | ripd/ripd.h | 19 | 
4 files changed, 184 insertions, 55 deletions
| diff --git a/ripd/ChangeLog b/ripd/ChangeLog index 2b65db30..848efee4 100644 --- a/ripd/ChangeLog +++ b/ripd/ChangeLog @@ -1,3 +1,35 @@ +2004-06-06 Paul Jakma <paul.jakma@sun.com> + +	* ripd.h: Add define for the RIPv2 Authentication Data family +	  Move the auth type defines up to where other defines live. +	  Add RIP_AUTH_MD5_COMPAT_SIZE, for backwards compatible +	  md5->auth_len size. Add md5_auth_len field to struct +          rip_interface: (rip_interface_new) Init md5_auth_len to compatible  +          size. +          (ip_rip_authentication_mode_cmd) Extended to handle setting +          md5 auth-length. Appropriate aliases added. +          (no_ip_rip_authentication_mode_cmd) Reset md5_auth_len to +          compatible size. +          (rip_interface_config_write) Teach it about md5_auth_len. +          _always_ write out the auth-length, so that everyone will get +          the setting in their config file, and hence allow for a future +          change of default for md5_auth_len to be less painful - every md5 +          user will have this setting in their config file. +          ripd.c: (rip_packet_dump) Change nasty hard coded constants to  +          symbolic defines. Change various tests of 'ntoh.(variable) == +          constant' to test 'variable == ntoh.(constant)'. Clean up +          indentation on some long lines. +          (rip_auth_simple_password) ditto. +          (rip_auth_md5) ditto, also add length argument and sanity check  +          md5 data offset field. Sanity check md5 auth length, accept RFC +          or old-ripd/cisco lengths. +          (rip_auth_md5_set) as per (rip_packet_dump), also write out +          the configured md5 auth length for the interface (old-ripd or rfc) +          (rip_read) as per (rip_packet_dump) +          (rip_write_rte) ditto +          (rip_response_process) ditto +          (rip_write_rte) ditto +            2004-06-04 JJ Ludman <jacques.ludman@sun.com>  	* ripd.c: Interoperability fix. Correct value for MD5 auth length diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 3d69d6c6..4daa5b38 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -125,6 +125,7 @@ rip_interface_new ()       compatibility. */    /* ri->auth_type = RIP_NO_AUTH; */    ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD; +  ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE;    /* Set default split-horizon behavior.  If the interface is Frame       Relay or SMDS is enabled, the default value for split-horizon is @@ -1678,6 +1679,12 @@ DEFUN (ip_rip_authentication_mode,    ifp = (struct interface *)vty->index;    ri = ifp->info; +  if ( (argc < 1) || (argc > 2) ) +    { +      vty_out (vty, "incorrect argument count%s", VTY_NEWLINE); +      return CMD_WARNING; +    } +        if (strncmp ("md5", argv[0], strlen (argv[0])) == 0)      ri->auth_type = RIP_AUTH_MD5;    else if (strncmp ("text", argv[0], strlen (argv[0])) == 0) @@ -1688,9 +1695,38 @@ DEFUN (ip_rip_authentication_mode,        return CMD_WARNING;      } +  if (argc == 1) +  return CMD_SUCCESS; + +  if ( (argc == 2) && (ri->auth_type != RIP_AUTH_MD5) ) +    { +      vty_out (vty, "auth length argument only valid for md5%s", VTY_NEWLINE); +      return CMD_WARNING; +} + +  if (strncmp ("r", argv[1], 1) == 0) +    ri->md5_auth_len = RIP_AUTH_MD5_SIZE; +  else if (strncmp ("o", argv[1], 1) == 0) +    ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; +  else  +    return CMD_WARNING; +    return CMD_SUCCESS;  } +ALIAS (ip_rip_authentication_mode, +       ip_rip_authentication_mode_authlen_cmd, +       "ip rip authentication mode (md5|text) auth-length (rfc|old-ripd)", +       IP_STR +       "Routing Information Protocol\n" +       "Authentication control\n" +       "Authentication mode\n" +       "Keyed message digest\n" +       "Clear text authentication\n" +       "MD5 authentication data length\n" +       "RFC compatible\n" +       "Old ripd compatible\n") +  DEFUN (no_ip_rip_authentication_mode,         no_ip_rip_authentication_mode_cmd,         "no ip rip authentication mode", @@ -1708,6 +1744,7 @@ DEFUN (no_ip_rip_authentication_mode,    /* ri->auth_type = RIP_NO_AUTH; */    ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD; +  ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE;    return CMD_SUCCESS;  } @@ -1723,6 +1760,20 @@ ALIAS (no_ip_rip_authentication_mode,         "Keyed message digest\n"         "Clear text authentication\n") +ALIAS (no_ip_rip_authentication_mode, +       no_ip_rip_authentication_mode_type_authlen_cmd, +       "no ip rip authentication mode (md5|text) auth-length (rfc|old-ripd)", +       NO_STR +       IP_STR +       "Routing Information Protocol\n" +       "Authentication control\n" +       "Authentication mode\n" +       "Keyed message digest\n" +       "Clear text authentication\n" +       "MD5 authentication data length\n" +       "RFC compatible\n" +       "Old ripd compatible\n") +  DEFUN (ip_rip_authentication_string,         ip_rip_authentication_string_cmd,         "ip rip authentication string LINE", @@ -1988,6 +2039,7 @@ rip_interface_config_write (struct vty *vty)            (ri->ri_send == RI_RIP_UNSPEC)                   &&            (ri->ri_receive == RI_RIP_UNSPEC)                &&            (ri->auth_type != RIP_AUTH_MD5)                  && +          (ri->md5_auth_len != RIP_AUTH_MD5_SIZE)          &&            (!ri->auth_str)                                  &&            (!ri->key_chain)                                 )          continue; @@ -2034,8 +2086,16 @@ rip_interface_config_write (struct vty *vty)        if (ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD)  	vty_out (vty, " ip rip authentication mode text%s", VTY_NEWLINE);  #endif /* 0 */ +        if (ri->auth_type == RIP_AUTH_MD5) -	vty_out (vty, " ip rip authentication mode md5%s", VTY_NEWLINE); +        { +          vty_out (vty, " ip rip authentication mode md5"); +          if (ri->md5_auth_len == RIP_AUTH_MD5_COMPAT_SIZE) +            vty_out (vty, " auth-length old-ripd"); +          else  +            vty_out (vty, " auth-length rfc"); +          vty_out (vty, "%s", VTY_NEWLINE); +        }        if (ri->auth_str)  	vty_out (vty, " ip rip authentication string %s%s", @@ -2165,8 +2225,10 @@ rip_if_init ()    install_element (INTERFACE_NODE, &no_ip_rip_receive_version_num_cmd);    install_element (INTERFACE_NODE, &ip_rip_authentication_mode_cmd); +  install_element (INTERFACE_NODE, &ip_rip_authentication_mode_authlen_cmd);    install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_cmd);    install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_type_cmd); +  install_element (INTERFACE_NODE, &no_ip_rip_authentication_mode_type_authlen_cmd);    install_element (INTERFACE_NODE, &ip_rip_authentication_key_chain_cmd);    install_element (INTERFACE_NODE, &no_ip_rip_authentication_key_chain_cmd); diff --git a/ripd/ripd.c b/ripd/ripd.c index 7567ba2c..69148227 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -701,16 +701,16 @@ rip_packet_dump (struct rip_packet *packet, int size, char *sndrcv)  	{  	  netmask = ip_masklen (rte->mask); -	  if (ntohs (rte->family) == 0xffff) +          if (rte->family == htons (RIP_FAMILY_AUTH))              { -	      if (ntohs (rte->tag) == RIP_AUTH_SIMPLE_PASSWORD) +              if (rte->tag == htons (RIP_AUTH_SIMPLE_PASSWORD))  		{  		  p = (u_char *)&rte->prefix;  		  zlog_info ("  family 0x%X type %d auth string: %s",  			     ntohs (rte->family), ntohs (rte->tag), p);  		} -	      else if (ntohs (rte->tag) == RIP_AUTH_MD5) +              else if (rte->tag == htons (RIP_AUTH_MD5))  		{  		  struct rip_md5_info *md5; @@ -719,11 +719,13 @@ rip_packet_dump (struct rip_packet *packet, int size, char *sndrcv)  		  zlog_info ("  family 0x%X type %d (MD5 authentication)",  			     ntohs (md5->family), ntohs (md5->type));  		  zlog_info ("    RIP-2 packet len %d Key ID %d" -			     " Auth Data len %d", ntohs (md5->packet_len), -			     md5->keyid, md5->auth_len); -		  zlog_info ("    Sequence Number %ld", (u_long)ntohl (md5->sequence)); +                             " Auth Data len %d", +                             ntohs (md5->packet_len), md5->keyid, +                             md5->auth_len); +                  zlog_info ("    Sequence Number %ld", +                             (u_long) ntohl (md5->sequence));  		} -	      else if (ntohs (rte->tag) == RIP_AUTH_DATA) +              else if (rte->tag == htons (RIP_AUTH_DATA))  		{  		  p = (u_char *)&rte->prefix; @@ -731,8 +733,9 @@ rip_packet_dump (struct rip_packet *packet, int size, char *sndrcv)  			     ntohs (rte->family), ntohs (rte->tag));  		  zlog_info ("    MD5: %02X%02X%02X%02X%02X%02X%02X%02X"  			     "%02X%02X%02X%02X%02X%02X%02X", -			     p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7], -			     p[9],p[10],p[11],p[12],p[13],p[14],p[15]); +                             p[0], p[1], p[2], p[3], p[4], p[5], p[6], +                             p[7], p[9], p[10], p[11], p[12], p[13], +                             p[14], p[15]);  		}  	      else  		{ @@ -742,10 +745,10 @@ rip_packet_dump (struct rip_packet *packet, int size, char *sndrcv)              }  	  else  	    zlog_info ("  %s/%d -> %s family %d tag %d metric %ld", -		       inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ),netmask, -		       inet_ntop (AF_INET, &rte->nexthop, nbuf, BUFSIZ), -		       ntohs (rte->family), ntohs (rte->tag),  -		       (u_long)ntohl (rte->metric)); +                       inet_ntop (AF_INET, &rte->prefix, pbuf, BUFSIZ), +                       netmask, inet_ntop (AF_INET, &rte->nexthop, nbuf, +                                           BUFSIZ), ntohs (rte->family), +                       ntohs (rte->tag), (u_long) ntohl (rte->metric));  	}        else  	{ @@ -801,7 +804,7 @@ rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,    ri = ifp->info;    if (ri->auth_type != RIP_AUTH_SIMPLE_PASSWORD -      || ntohs (rte->tag) != RIP_AUTH_SIMPLE_PASSWORD) +      || rte->tag != htons(RIP_AUTH_SIMPLE_PASSWORD))      return 0;    /* Simple password authentication. */ @@ -831,7 +834,7 @@ rip_auth_simple_password (struct rte *rte, struct sockaddr_in *from,  /* RIP version 2 authentication with MD5. */  int  rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from, -	      struct interface *ifp) +              int length, struct interface *ifp)  {    struct rip_interface *ri;    struct rip_md5_info *md5; @@ -845,27 +848,44 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,    char *auth_str = NULL;    if (IS_RIP_DEBUG_EVENT) -    zlog_info ("RIPv2 MD5 authentication from %s", inet_ntoa (from->sin_addr)); +    zlog_info ("RIPv2 MD5 authentication from %s", +               inet_ntoa (from->sin_addr));    ri = ifp->info;    md5 = (struct rip_md5_info *) &packet->rte;    /* Check auth type. */ -  if (ri->auth_type != RIP_AUTH_MD5 || ntohs (md5->type) != RIP_AUTH_MD5) +  if (ri->auth_type != RIP_AUTH_MD5 || md5->type != htons(RIP_AUTH_MD5))      return 0; -/* - * If the authentication length is less than 16, then it must be wrong for - * any interpretation of rfc2082. +  /* If the authentication length is less than 16, then it must be wrong for +   * any interpretation of rfc2082. Some implementations also interpret +   * this as RIP_HEADER_SIZE+ RIP_AUTH_MD5_SIZE, aka RIP_AUTH_MD5_COMPAT_SIZE.   */ -  if (md5->auth_len < RIP_AUTH_MD5_SIZE) +  if ( !((md5->auth_len == RIP_AUTH_MD5_SIZE) +         || (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))      {        if (IS_RIP_DEBUG_EVENT) -       zlog_info ("RIPv2 MD5 authentication, authentication length field too \ -         short"); +        zlog_warn ("RIPv2 MD5 authentication, strange authentication " +                   "length field %d", md5->auth_len);      return 0;      } +  /* grab and verify check packet length */ +  packet_len = ntohs (md5->packet_len); + +  if (packet_len > (length - RIP_HEADER_SIZE - RIP_AUTH_MD5_SIZE)) +    { +      if (IS_RIP_DEBUG_EVENT) +        zlog_warn ("RIPv2 MD5 authentication, packet length field %d " +                   "greater than received length %d!", +                   md5->packet_len, length); +      return 0; +    } + +  /* retrieve authentication data */ +  md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len); +    if (ri->key_chain)      {        keychain = keychain_lookup (ri->key_chain); @@ -886,8 +906,6 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,      return 0;    /* MD5 digest authentication. */ -  packet_len = ntohs (md5->packet_len); -  md5data = (struct rip_md5_data *)(((u_char *) packet) + packet_len);    /* Save digest to pdigest. */    memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE); @@ -897,7 +915,7 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,    strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);    md5_init_ctx (&ctx); -  md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE, \ +  md5_process_bytes (packet, packet_len + RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE,      &ctx);    md5_finish_ctx (&ctx, digest); @@ -967,7 +985,7 @@ rip_auth_md5_set (struct stream *s, struct interface *ifp)    len += RIP_RTE_SIZE;    /* MD5 authentication. */ -  stream_putw (s, 0xffff); +  stream_putw (s, RIP_FAMILY_AUTH);    stream_putw (s, RIP_AUTH_MD5);    /* RIP-2 Packet length.  Actual value is filled in @@ -980,9 +998,11 @@ rip_auth_md5_set (struct stream *s, struct interface *ifp)    else      stream_putc (s, 1); -  /* Auth Data Len.  Set 16 for MD5 authentication -     data. */ -  stream_putc (s, RIP_AUTH_MD5_SIZE); +  /* Auth Data Len.  Set 16 for MD5 authentication data. Older ripds  +   * however expect RIP_HEADER_SIZE + RIP_AUTH_MD5_SIZE so we allow for this +   * to be configurable.  +   */ +  stream_putc (s, ri->md5_auth_len);    /* Sequence Number (non-decreasing). */    /* RFC2080: The value used in the sequence number is @@ -998,8 +1018,8 @@ rip_auth_md5_set (struct stream *s, struct interface *ifp)    stream_set_putp (s, len);    /* Set authentication data. */ -  stream_putw (s, 0xffff); -  stream_putw (s, 0x01); +  stream_putw (s, RIP_FAMILY_AUTH); +  stream_putw (s, RIP_AUTH_DATA);    /* Generate a digest for the RIP packet. */    memset (secret, 0, RIP_AUTH_MD5_SIZE); @@ -1030,7 +1050,7 @@ rip_response_process (struct rip_packet *packet, int size,    /* The Response must be ignored if it is not from the RIP       port. (RFC2453 - Sec. 3.9.2)*/ -  if (ntohs (from->sin_port) != RIP_PORT_DEFAULT)  +  if (from->sin_port != htons(RIP_PORT_DEFAULT))      {        zlog_info ("response doesn't come from RIP port: %d",  		 from->sin_port); @@ -1070,10 +1090,10 @@ rip_response_process (struct rip_packet *packet, int size,        /* Check is done in rip_read(). So, just skipping it */        if (packet->version == RIPv2 &&  	  rte == packet->rte && -	  rte->family == 0xffff) +	  rte->family == htons(RIP_FAMILY_AUTH))  	continue; -      if (ntohs (rte->family) != AF_INET) +      if (rte->family != htons(AF_INET))  	{  	  /* Address family check.  RIP only supports AF_INET. */  	  zlog_info ("Unsupported family %d from %s.", @@ -1795,7 +1815,8 @@ rip_read (struct thread *t)    if ((ri->auth_type == RIP_NO_AUTH)         && rtenum  -      && (packet->version == RIPv2) && (packet->rte->family == 0xffff)) +      && (packet->version == RIPv2)  +      && (packet->rte->family == htons(RIP_FAMILY_AUTH)))      {        if (IS_RIP_DEBUG_EVENT)  	zlog_warn ("packet RIPv%d is dropped because authentication disabled",  @@ -1814,14 +1835,16 @@ rip_read (struct thread *t)       unauthenticated manner. */    if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD  -       || ri->auth_type == RIP_AUTH_MD5) -      && rtenum) +       || ri->auth_type == RIP_AUTH_MD5) && rtenum)      {        /* We follow maximum security. */ -      if (packet->version == RIPv1 && packet->rte->family == 0xffff) +      if (packet->version == RIPv1  +      && packet->rte->family == htons(RIP_FAMILY_AUTH))  	{  	  if (IS_RIP_DEBUG_PACKET) -	    zlog_warn ("packet RIPv%d is dropped because authentication enabled", packet->version); +            zlog_warn +              ("packet RIPv%d is dropped because authentication enabled", +               packet->version);  	  rip_peer_bad_packet (&from);  	  return -1;  	} @@ -1829,27 +1852,29 @@ rip_read (struct thread *t)        /* Check RIPv2 authentication. */        if (packet->version == RIPv2)  	{ -	  if (packet->rte->family == 0xffff) +          if (packet->rte->family == htons(RIP_FAMILY_AUTH))  	    { -	      if (ntohs (packet->rte->tag) == RIP_AUTH_SIMPLE_PASSWORD) +              if (packet->rte->tag == htons(RIP_AUTH_SIMPLE_PASSWORD))                  {  		  ret = rip_auth_simple_password (packet->rte, &from, ifp);  		  if (! ret)  		    {  		      if (IS_RIP_DEBUG_EVENT) -			zlog_warn ("RIPv2 simple password authentication failed"); +                        zlog_warn +                          ("RIPv2 simple password authentication failed");  		      rip_peer_bad_packet (&from);  		      return -1;  		    }  		  else  		    {  		      if (IS_RIP_DEBUG_EVENT) -			zlog_info ("RIPv2 simple password authentication success"); +                        zlog_info +                          ("RIPv2 simple password authentication success");  		    }                  } -	      else if (ntohs (packet->rte->tag) == RIP_AUTH_MD5) +              else if (packet->rte->tag == htons(RIP_AUTH_MD5))                  { -		  ret = rip_auth_md5 (packet, &from, ifp); +                  ret = rip_auth_md5 (packet, &from, len, ifp);  		  if (! ret)  		    {  		      if (IS_RIP_DEBUG_EVENT) @@ -1880,7 +1905,8 @@ rip_read (struct thread *t)  	      if (ri->auth_str || ri->key_chain)  		{  		  if (IS_RIP_DEBUG_EVENT) -		    zlog_warn ("RIPv2 authentication failed: no authentication in packet"); +                    zlog_warn +                      ("RIPv2 authentication failed: no authentication in packet");  		  rip_peer_bad_packet (&from);  		  return -1;  		} @@ -1996,7 +2022,7 @@ rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,  	    {  	      if (ri->auth_str)  		{ -		  stream_putw (s, 0xffff); +		  stream_putw (s, RIP_FAMILY_AUTH);  		  stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);  		  memset ((s->data + s->putp), 0, 16); @@ -2018,7 +2044,7 @@ rip_write_rte (int num, struct stream *s, struct prefix_ipv4 *p,  		      if (key)  			{ -			  stream_putw (s, 0xffff); +			  stream_putw (s, RIP_FAMILY_AUTH);  			  stream_putw (s, RIP_AUTH_SIMPLE_PASSWORD);  			  memset ((s->data + s->putp), 0, 16); diff --git a/ripd/ripd.h b/ripd/ripd.h index 13a72a11..5c50c576 100644 --- a/ripd/ripd.h +++ b/ripd/ripd.h @@ -78,8 +78,18 @@  #define RIP_ROUTE_REDISTRIBUTE           3  #define RIP_ROUTE_INTERFACE              4 -/* RIP MD5 authentication. */ +/* RIPv2 special RTE family types */ +#define RIP_FAMILY_AUTH                  0xffff + +/* RIPv2 authentication types, for RIP_FAMILY_AUTH RTE's */ +#define RIP_NO_AUTH                0 +#define RIP_AUTH_DATA              1 +#define RIP_AUTH_SIMPLE_PASSWORD   2 +#define RIP_AUTH_MD5               3 + +/* RIPv2 MD5 authentication. */  #define RIP_AUTH_MD5_SIZE               16 +#define RIP_AUTH_MD5_COMPAT_SIZE        RIP_RTE_SIZE  /* RIP structure. */  struct rip  @@ -237,10 +247,6 @@ struct rip_interface    int ri_receive;    /* RIPv2 authentication type. */ -#define RIP_NO_AUTH                0 -#define RIP_AUTH_DATA              1 -#define RIP_AUTH_SIMPLE_PASSWORD   2 -#define RIP_AUTH_MD5               3    int auth_type;    /* RIPv2 authentication string. */ @@ -249,6 +255,9 @@ struct rip_interface    /* RIPv2 authentication key chain. */    char *key_chain; +  /* value to use for md5->auth_len */ +  u_int8_t md5_auth_len; +    /* Split horizon flag. */    split_horizon_policy_t split_horizon;    split_horizon_policy_t split_horizon_default; | 
