diff options
Diffstat (limited to 'ripd')
-rw-r--r-- | ripd/ChangeLog | 16 | ||||
-rw-r--r-- | ripd/rip_interface.c | 18 | ||||
-rw-r--r-- | ripd/ripd.c | 205 |
3 files changed, 131 insertions, 108 deletions
diff --git a/ripd/ChangeLog b/ripd/ChangeLog index 89302d55..52fb6d69 100644 --- a/ripd/ChangeLog +++ b/ripd/ChangeLog @@ -1,3 +1,19 @@ +2006-05-04 Paul Jakma <paul.jakma@sun.com> + + * (general) Fixes for bugs #261 and 262. Thanks to + Konstantin V. Gavrilenko <kos@arhont.com> for the problem + reports, testing of a series of proposed patches and comment + on the proposed changes in behaviour. + * rip_interface.c: (ip_rip_authentication_mode_cmd) Parse all + of the command before making any changes to configured state. + * ripd.c: (rip_read) RIP version control should be absolute and + always apply, fixes bug #261 by allowing RIPv1 to be disabled. + Fix bug #262: If authentication is enabled, then + unauthenticated packets should not be accepted. We do however + make an exception for RIPv1 REQUEST packets, to which we will + reply as RIPv1 can now be disabled fully, to allow ripd to + still provide routing /information/ to simple devices. + 2006-04-28 Andrew J. Schorr <ajschorr@alumni.princeton.edu> * ripd.c: (rip_update_process) Try to fix the logic for sending diff --git a/ripd/rip_interface.c b/ripd/rip_interface.c index 0bc5a311..a5b12db6 100644 --- a/ripd/rip_interface.c +++ b/ripd/rip_interface.c @@ -1558,6 +1558,7 @@ DEFUN (ip_rip_authentication_mode, { struct interface *ifp; struct rip_interface *ri; + int auth_type; ifp = (struct interface *)vty->index; ri = ifp->info; @@ -1569,9 +1570,9 @@ DEFUN (ip_rip_authentication_mode, } if (strncmp ("md5", argv[0], strlen (argv[0])) == 0) - ri->auth_type = RIP_AUTH_MD5; + auth_type = RIP_AUTH_MD5; else if (strncmp ("text", argv[0], strlen (argv[0])) == 0) - ri->auth_type = RIP_AUTH_SIMPLE_PASSWORD; + auth_type = RIP_AUTH_SIMPLE_PASSWORD; else { vty_out (vty, "mode should be md5 or text%s", VTY_NEWLINE); @@ -1579,13 +1580,16 @@ DEFUN (ip_rip_authentication_mode, } if (argc == 1) - return CMD_SUCCESS; + { + ri->auth_type = auth_type; + return CMD_SUCCESS; + } - if ( (argc == 2) && (ri->auth_type != RIP_AUTH_MD5) ) + if ( (argc == 2) && (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; @@ -1593,7 +1597,9 @@ DEFUN (ip_rip_authentication_mode, ri->md5_auth_len = RIP_AUTH_MD5_COMPAT_SIZE; else return CMD_WARNING; - + + ri->auth_type = auth_type; + return CMD_SUCCESS; } diff --git a/ripd/ripd.c b/ripd/ripd.c index e91adb84..518e4861 100644 --- a/ripd/ripd.c +++ b/ripd/ripd.c @@ -1936,35 +1936,29 @@ rip_read (struct thread *t) return -1; } - /* RIP Version check. */ - if (packet->command == RIP_RESPONSE) + /* RIP Version check. RFC2453, 4.6 and 5.1 */ + int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? + rip->version_recv : ri->ri_receive); + if ((packet->version == RIPv1) && !(vrecv & RIPv1)) { - int vrecv = ((ri->ri_receive == RI_RIP_UNSPEC) ? - rip->version_recv : ri->ri_receive); - if (packet->version == RIPv1) - if (! (vrecv & RIPv1)) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug (" packet's v%d doesn't fit to if version spec", - packet->version); - rip_peer_bad_packet (&from); - return -1; - } - if (packet->version == RIPv2) - if (! (vrecv & RIPv2)) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug (" packet's v%d doesn't fit to if version spec", - packet->version); - rip_peer_bad_packet (&from); - return -1; - } + if (IS_RIP_DEBUG_PACKET) + zlog_debug (" packet's v%d doesn't fit to if version spec", + packet->version); + rip_peer_bad_packet (&from); + return -1; } - + if ((packet->version == RIPv2) && !(vrecv & RIPv2)) + { + if (IS_RIP_DEBUG_PACKET) + zlog_debug (" packet's v%d doesn't fit to if version spec", + packet->version); + rip_peer_bad_packet (&from); + return -1; + } + /* RFC2453 5.2 If the router is not configured to authenticate RIP-2 messages, then RIP-1 and unauthenticated RIP-2 messages will be accepted; authenticated RIP-2 messages shall be discarded. */ - if ((ri->auth_type == RIP_NO_AUTH) && rtenum && (packet->version == RIPv2) @@ -1976,94 +1970,101 @@ rip_read (struct thread *t) rip_peer_bad_packet (&from); return -1; } - - /* If the router is configured to authenticate RIP-2 messages, then + + /* RFC: + If the router is configured to authenticate RIP-2 messages, then RIP-1 messages and RIP-2 messages which pass authentication testing shall be accepted; unauthenticated and failed authentication RIP-2 messages shall be discarded. For maximum security, RIP-1 messages should be ignored when authentication is in use (see section 4.1); otherwise, the routing information from authenticated messages will be propagated by RIP-1 routers in an - unauthenticated manner. */ - - if ((ri->auth_type == RIP_AUTH_SIMPLE_PASSWORD - || ri->auth_type == RIP_AUTH_MD5) && rtenum) + unauthenticated manner. + */ + /* We make an exception for RIPv1 REQUEST packets, to which we'll + * always reply regardless of authentication settings, because: + * + * - if there other authorised routers on-link, the REQUESTor can + * passively obtain the routing updates anyway + * - if there are no other authorised routers on-link, RIP can + * easily be disabled for the link to prevent giving out information + * on state of this routers RIP routing table.. + * + * I.e. if RIPv1 has any place anymore these days, it's as a very + * simple way to distribute routing information (e.g. to embedded + * hosts / appliances) and the ability to give out RIPv1 + * routing-information freely, while still requiring RIPv2 + * authentication for any RESPONSEs might be vaguely useful. + */ + if (ri->auth_type != RIP_NO_AUTH + && packet->version == RIPv1) { - /* We follow maximum security. */ - if (packet->version == RIPv1 - && packet->rte->family == htons(RIP_FAMILY_AUTH)) - { - if (IS_RIP_DEBUG_PACKET) - zlog_debug - ("packet RIPv%d is dropped because authentication enabled", - packet->version); + /* Discard RIPv1 messages other than REQUESTs */ + if (packet->command != RIP_REQUEST) + { + if (IS_RIP_DEBUG_PACKET) + zlog_debug ("RIPv1" " dropped because authentication enabled"); + rip_peer_bad_packet (&from); + return -1; + } + } + else if (ri->auth_type != RIP_NO_AUTH) + { + const char *auth_desc; + + if (rtenum == 0) + { + /* There definitely is no authentication in the packet. */ + if (IS_RIP_DEBUG_PACKET) + zlog_debug ("RIPv2 authentication failed: no auth RTE in packet"); + rip_peer_bad_packet (&from); + return -1; + } + + /* First RTE must be an Authentication Family RTE */ + if (packet->rte->family != htons(RIP_FAMILY_AUTH)) + { + if (IS_RIP_DEBUG_PACKET) + zlog_debug ("RIPv2" " dropped because authentication enabled"); rip_peer_bad_packet (&from); return -1; - } - + } + /* Check RIPv2 authentication. */ - if (packet->version == RIPv2) - { - if (packet->rte->family == htons(RIP_FAMILY_AUTH)) - { - 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_debug - ("RIPv2 simple password authentication failed"); - rip_peer_bad_packet (&from); - return -1; - } - else - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug - ("RIPv2 simple password authentication success"); - } - } - else if (packet->rte->tag == htons(RIP_AUTH_MD5)) - { - ret = rip_auth_md5 (packet, &from, len, ifp); - if (! ret) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 MD5 authentication failed"); - rip_peer_bad_packet (&from); - return -1; - } - else - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("RIPv2 MD5 authentication success"); - } - /* Reset RIP packet length to trim MD5 data. */ - len = ret; - } - else - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug ("Unknown authentication type %d", - ntohs (packet->rte->tag)); - rip_peer_bad_packet (&from); - return -1; - } - } - else - { - /* There is no authentication in the packet. */ - if (ri->auth_str || ri->key_chain) - { - if (IS_RIP_DEBUG_EVENT) - zlog_debug - ("RIPv2 authentication failed: no authentication in packet"); - rip_peer_bad_packet (&from); - return -1; - } - } - } + switch (ntohs(packet->rte->tag)) + { + case RIP_AUTH_SIMPLE_PASSWORD: + auth_desc = "simple"; + ret = rip_auth_simple_password (packet->rte, &from, ifp); + break; + + case RIP_AUTH_MD5: + auth_desc = "MD5"; + ret = rip_auth_md5 (packet, &from, len, ifp); + /* Reset RIP packet length to trim MD5 data. */ + len = ret; + break; + + default: + ret = 0; + auth_desc = "unknown type"; + if (IS_RIP_DEBUG_PACKET) + zlog_debug ("RIPv2 Unknown authentication type %d", + ntohs (packet->rte->tag)); + } + + if (ret) + { + if (IS_RIP_DEBUG_PACKET) + zlog_debug ("RIPv2 %s authentication success", auth_desc); + } + else + { + if (IS_RIP_DEBUG_PACKET) + zlog_debug ("RIPv2 %s authentication failure", auth_desc); + rip_peer_bad_packet (&from); + return -1; + } } /* Process each command. */ |