summaryrefslogtreecommitdiff
path: root/ripd
diff options
context:
space:
mode:
Diffstat (limited to 'ripd')
-rw-r--r--ripd/ChangeLog16
-rw-r--r--ripd/rip_interface.c18
-rw-r--r--ripd/ripd.c205
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. */