The latest changes of bss_dgram.c affected the behavior of BIO_CTRL_DGRAM_GET_PEER, which now requires to preset the expected IP type before requesting the current peer. This was done to prevent that the user always has to use sockaddr_storage, even if he doesn't use IPv6 at all. The default is to return the length of a sockaddr structure which is always wrong, therefore existing DTLS applications which rely on this function for cookie generation, such as s_server/s_client, don't work anymore. Additionally, this requires that the user has to guess which IP type the peer has. This can be difficult, e.g. if the client uses IPv4 to connect to an IPv6 socket and a system returns AF_INET then.
A better solution is to use the num parameter of BIO_ctrl() to limit the length
if desired. When num is 0, the function returns either sockaddr_in or
sockaddr_in6, depending on what's necessary, so the user should use
sockaddr_storage. If the user knows that he only uses IPv4 and doesn't want to
use sockaddr_storage, he can limit the copied length by setting the num
parameter to sizeof(struct sockaddr_in). He can then check if the family
variable of the passed structure is really AF_INET and try again with
sockaddr_storage or handle it as an error in case it's not.
Index: crypto/bio/bss_dgram.c
===================================================================
RCS file: /v/openssl/cvs/openssl/crypto/bio/bss_dgram.c,v
retrieving revision 1.7.2.20
diff -u -r1.7.2.20 bss_dgram.c
--- crypto/bio/bss_dgram.c 22 Nov 2009 12:24:43 -0000 1.7.2.20
+++ crypto/bio/bss_dgram.c 26 Nov 2009 10:20:24 -0000
@@ -566,18 +970,24 @@
break;
case BIO_CTRL_DGRAM_GET_PEER:
to = (struct sockaddr *) ptr;
- switch (to->sa_family)
+ switch (data->peer.sa.sa_family)
{
case AF_INET:
-
memcpy(to,&data->peer,(ret=sizeof(data->peer.sa_in)));
+ if (num == 0 || num > sizeof(data->peer.sa_in))
+ num = sizeof(data->peer.sa_in);
+ memcpy(to,&data->peer,(ret=num));
break;
#if OPENSSL_USE_IPV6
case AF_INET6:
-
memcpy(to,&data->peer,(ret=sizeof(data->peer.sa_in6)));
+ if (num == 0 || num > sizeof(data->peer.sa_in6))
+ num = sizeof(data->peer.sa_in6);
+ memcpy(to,&data->peer,(ret=num));
break;
#endif
default:
-
memcpy(to,&data->peer,(ret=sizeof(data->peer.sa)));
+ if (num == 0 || num > sizeof(data->peer.sa))
+ num = sizeof(data->peer.sa);
+ memcpy(to,&data->peer,(ret=num));
break;
}
break;
get_peer.patch
Description: Binary data
