diff options
Diffstat (limited to 'ripd/ripd.c')
-rw-r--r-- | ripd/ripd.c | 205 |
1 files changed, 103 insertions, 102 deletions
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. */ |