diff --git a/src/client/ns_turn_ioaddr.c b/src/client/ns_turn_ioaddr.c index 5740e7c8..810476fe 100644 --- a/src/client/ns_turn_ioaddr.c +++ b/src/client/ns_turn_ioaddr.c @@ -483,9 +483,9 @@ int ioa_addr_is_loopback(ioa_addr *addr) return (u[0] == 127); } else if(addr->ss.sa_family == AF_INET6) { const uint8_t *u = ((const uint8_t*)&(addr->s6.sin6_addr)); - if(u[7] == 1) { + if(u[15] == 1) { int i; - for(i=0;i<7;++i) { + for(i=0;i<15;++i) { if(u[i]) return 0; } @@ -496,6 +496,31 @@ int ioa_addr_is_loopback(ioa_addr *addr) return 0; } +/* +To avoid a vulnerability this function checks whether the addr is in 0.0.0.0/8 or ::/128. +Source from (INADDR_ANY) 0.0.0.0/32 and (in6addr_any) ::/128 routed to loopback on Linux systems for old BSD backward compatibility. +https://github.com/torvalds/linux/blob/a2f5ea9e314ba6778f885c805c921e9362ec0420/net/ipv6/tcp_ipv6.c#L182 +To avoid any trouble we match the whole 0.0.0.0/8 that defined in RFC6890 as local network "this". +*/ +int ioa_addr_is_zero(ioa_addr *addr) +{ + if(addr) { + if(addr->ss.sa_family == AF_INET) { + const uint8_t *u = ((const uint8_t*)&(addr->s4.sin_addr)); + return (u[0] == 0); + } else if(addr->ss.sa_family == AF_INET6) { + const uint8_t *u = ((const uint8_t*)&(addr->s6.sin6_addr)); + int i; + for(i=0;i<=15;++i) { + if(u[i]) + return 0; + } + return 1; + } + } + return 0; +} + /////// Map "public" address to "private" address ////////////// // Must be called only in a single-threaded context, diff --git a/src/client/ns_turn_ioaddr.h b/src/client/ns_turn_ioaddr.h index a83d0fab..bdd21dd7 100644 --- a/src/client/ns_turn_ioaddr.h +++ b/src/client/ns_turn_ioaddr.h @@ -89,6 +89,7 @@ void ioa_addr_range_cpy(ioa_addr_range* dest, const ioa_addr_range* src); int ioa_addr_is_multicast(ioa_addr *a); int ioa_addr_is_loopback(ioa_addr *addr); +int ioa_addr_is_zero(ioa_addr *addr); /////// Map "public" address to "private" address ////////////// diff --git a/src/server/ns_turn_server.c b/src/server/ns_turn_server.c index 3d264ada..40b91afc 100644 --- a/src/server/ns_turn_server.c +++ b/src/server/ns_turn_server.c @@ -273,6 +273,8 @@ static int good_peer_addr(turn_turnserver *server, const char* realm, ioa_addr * return 0; if( !*(server->allow_loopback_peers) && ioa_addr_is_loopback(peer_addr)) return 0; + if (ioa_addr_is_zero(peer_addr)) + return 0; { int i;