summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpaul <paul>2006-01-17 17:26:25 +0000
committerpaul <paul>2006-01-17 17:26:25 +0000
commitce541bb1a9feaf1b5da40753236e22e5baf96e8f (patch)
tree3553db16c0cdb87c6da17eed27ca4d800c412b14
parentbf7509dd729580f4e9a54493177598136e7a1e2f (diff)
downloadquagga-ce541bb1a9feaf1b5da40753236e22e5baf96e8f.tar.bz2
quagga-ce541bb1a9feaf1b5da40753236e22e5baf96e8f.tar.xz
[ripd] Fix verification of received MD5 authenticated packets
2006-01-17 Paul Jakma <paul.jakma@sun.com> * ripd.c: (rip_auth_md5) remove pdigest, not needed. Use a local buffer for the auth_str, where it can be properly nul padded. Do so, hence fixing MD5 authentication. Key looked up via key ring should be used in preference to the RIPv1 simple password, not other way around. No need to copy around digests, we can reference them directly. The auth_len received can't be trusted, some implementations lie (e.g. older ripd). (rip_auth_md5_ah_write) rename len local variable to doff to be consistent with other functions. (rip_auth_header_write) add the missing return. (rip_auth_md5_set) use the proper constructs to access stream.
-rw-r--r--ripd/ChangeLog16
-rw-r--r--ripd/ripd.c40
2 files changed, 33 insertions, 23 deletions
diff --git a/ripd/ChangeLog b/ripd/ChangeLog
index a3c0e24b..2b79a61d 100644
--- a/ripd/ChangeLog
+++ b/ripd/ChangeLog
@@ -1,3 +1,19 @@
+2006-01-17 Paul Jakma <paul.jakma@sun.com>
+
+ * ripd.c: (rip_auth_md5) remove pdigest, not needed.
+ Use a local buffer for the auth_str, where it can be properly
+ nul padded. Do so, hence fixing MD5 authentication.
+ Key looked up via key ring should be used in preference to
+ the RIPv1 simple password, not other way around.
+ No need to copy around digests, we can reference them
+ directly.
+ The auth_len received can't be trusted, some implementations
+ lie (e.g. older ripd).
+ (rip_auth_md5_ah_write) rename len local variable to doff
+ to be consistent with other functions.
+ (rip_auth_header_write) add the missing return.
+ (rip_auth_md5_set) use the proper constructs to access stream.
+
2005-10-30 Andrew J. Schorr <ajschorr@alumni.princeton.edu>
* ripd.c: (rip_response_process) Instead of calling
diff --git a/ripd/ripd.c b/ripd/ripd.c
index ec7bd199..40db33f5 100644
--- a/ripd/ripd.c
+++ b/ripd/ripd.c
@@ -865,10 +865,9 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
struct keychain *keychain;
struct key *key;
MD5_CTX ctx;
- u_char pdigest[RIP_AUTH_MD5_SIZE];
u_char digest[RIP_AUTH_MD5_SIZE];
u_int16_t packet_len;
- char *auth_str = NULL;
+ char auth_str[RIP_AUTH_MD5_SIZE];
if (IS_RIP_DEBUG_EVENT)
zlog_debug ("RIPv2 MD5 authentication from %s",
@@ -884,7 +883,7 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
/* 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)
|| (md5->auth_len == RIP_AUTH_MD5_COMPAT_SIZE)))
{
@@ -908,6 +907,8 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
/* retrieve authentication data */
md5data = (struct rip_md5_data *) (((u_char *) packet) + packet_len);
+
+ memset (auth_str, 0, RIP_AUTH_MD5_SIZE);
if (ri->key_chain)
{
@@ -919,30 +920,22 @@ rip_auth_md5 (struct rip_packet *packet, struct sockaddr_in *from,
if (key == NULL)
return 0;
- auth_str = key->string;
+ strncpy (auth_str, key->string, RIP_AUTH_MD5_SIZE);
}
-
- if (ri->auth_str)
- auth_str = ri->auth_str;
+ else if (ri->auth_str)
+ strncpy (auth_str, ri->auth_str, RIP_AUTH_MD5_SIZE);
if (! auth_str)
return 0;
-
+
/* MD5 digest authentication. */
-
- /* Save digest to pdigest. */
- memcpy (pdigest, md5data->digest, RIP_AUTH_MD5_SIZE);
-
- /* Overwrite digest by my secret. */
- memset (md5data->digest, 0, RIP_AUTH_MD5_SIZE);
- strncpy ((char *)md5data->digest, auth_str, RIP_AUTH_MD5_SIZE);
-
memset (&ctx, 0, sizeof(ctx));
MD5Init(&ctx);
- MD5Update(&ctx, packet, packet_len + md5->auth_len);
+ MD5Update(&ctx, packet, packet_len + RIP_HEADER_SIZE);
+ MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
MD5Final(digest, &ctx);
-
- if (memcmp (pdigest, digest, RIP_AUTH_MD5_SIZE) == 0)
+
+ if (memcmp (md5data->digest, digest, RIP_AUTH_MD5_SIZE) == 0)
return packet_len;
else
return 0;
@@ -1000,7 +993,7 @@ static size_t
rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
struct key *key)
{
- size_t len = 0;
+ size_t doff = 0;
assert (s && ri && ri->auth_type == RIP_AUTH_MD5);
@@ -1013,7 +1006,7 @@ rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
* Set to placeholder value here, to true value when RIP-2 Packet length
* is known. Actual value is set in .....().
*/
- len = stream_get_endp(s);
+ doff = stream_get_endp(s);
stream_putw (s, 0);
/* Key ID. */
@@ -1038,7 +1031,7 @@ rip_auth_md5_ah_write (struct stream *s, struct rip_interface *ri,
stream_putl (s, 0);
stream_putl (s, 0);
- return len;
+ return doff;
}
/* If authentication is in used, write the appropriate header
@@ -1061,6 +1054,7 @@ rip_auth_header_write (struct stream *s, struct rip_interface *ri,
return rip_auth_md5_ah_write (s, ri, key);
}
assert (1);
+ return 0;
}
/* Write RIPv2 MD5 authentication data trailer */
@@ -1097,7 +1091,7 @@ rip_auth_md5_set (struct stream *s, struct rip_interface *ri, size_t doff,
/* Generate a digest for the RIP packet. */
memset(&ctx, 0, sizeof(ctx));
MD5Init(&ctx);
- MD5Update(&ctx, s->data, s->endp);
+ MD5Update(&ctx, STREAM_DATA (s), stream_get_endp (s));
MD5Update(&ctx, auth_str, RIP_AUTH_MD5_SIZE);
MD5Final(digest, &ctx);