[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: comment on v4mapped-api-harmful



	to be clear, i have been pointing this problem out since 2553bis
	discussions group (apifolks).

>o Do not intentionally use RFC2553 section 3.7 (IPv4 traffic on AF_INET6
>  socket).  Implement server applications by using separate AF_INET and
>  AF_INET6 listening sockets.  Explicitly set the IPV6_V6ONLY socket
>  option to on, whenever the socket option is available on the system.
>==> please provide some overview on the migration path (kernel/library, 
>apps) from the current state to this.
>Reversing the default value would appear to be totally unacceptable, 
>because it'd break _all_ current apps.

	it'd breaks apps that assume IPv4 mapped address support, such as:
	- server program that listens to AF_INET6 socket only to receive both
	  IPv4 and IPv6 inbound traffic.
		can be worked around by running two instance of the app,
		one for AF_INET and one for AF_INET6
	- client program that uses getaddrinfo(3) with AI_MAPPED and AF_INET6
	  socket to connect to IPv4 and IPv6 destination
		should be rewritten to socket(2) after getaddrinfo(3)

	the change in default behavior shouldn't break applications if
	appliations are correctly written to handle IPv4 traffic on AF_INET
	socket, and IPv6 traffic on AF_INET6 socket.

	the following code fragment (server side) should avoid vulnerability
	on systems with/without IPv4 mapped address behavior, assuming:
	- bind(2) to the same port on AF_INET and AF_INET6 does not conflict
	  (yes, some systems they do conflict and you can open only one of them)
	- 2553bis IPV6_V6ONLY is implemented
	- getaddrinfo(3) returns both AF_INET and AF_INET6 wildcard address
	  on AI_PASSIVE
	i dunno, on how many systems, the above assumption holds.  due to the
	lack of specification bind(2) behavior varies very much by
	implementation.

>Perhaps detecting the behaviour might be doable by some test macro..

	getsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &v, sizeof(v))?

itojun


int socks[NSOCK];
int nsocks;

foo(port)
	char *port;
{
	struct addrinfo hints, *res, *res0;
	int s;
	const int on = 1;

	memset(&hints, 0, sizeof(hints));
	hints.ai_socktype = SOCK_STREAM;	/* of DGRAM if you want to */
	hints.ai_flags = AI_PASSIVE;
	getaddrinfo(NULL, port, &hints, &res0);
	nsocks = 0;
	for (res = res0; res; res = res->ai_next) {
		s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
		if (s < 0)
			continue;
#ifdef IPV6_V6ONLY
		if (res->ai_family == AF_INET6 && setsockopt(s, IPPROTO_IPV6,
		    IPV6_V6ONLY, &on, sizeof(on)) < 0) {
			close(s);
			continue;
		}
#endif
		if (bind(s, res->ai_addr, res->ai_addrlen) < 0) {
			close(s);
			continue;
		}
		if (listen(s, 5) < 0) {
			close(s);
			continue;
		}
		socks[nsocks++] = s;
	}
	if (nsocks == 0)
		exit(1);

	/* handle socks[0] to socks[nsocks - 1] by select(2) or poll(2 )*/
}