diff options
author | agayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-29 03:47:04 +0000 |
---|---|---|
committer | agayev@chromium.org <agayev@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-06-29 03:47:04 +0000 |
commit | 5370c013eb6372dbffe91de3fde793da6b74e4e1 (patch) | |
tree | f4a14d0380e1c673c1e0d54f75a192fc1b504b9e /net/udp/udp_socket_libevent.cc | |
parent | 034bda715a6756a9b07de1fe9db9ceb6caf73123 (diff) | |
download | chromium_src-5370c013eb6372dbffe91de3fde793da6b74e4e1.zip chromium_src-5370c013eb6372dbffe91de3fde793da6b74e4e1.tar.gz chromium_src-5370c013eb6372dbffe91de3fde793da6b74e4e1.tar.bz2 |
Add support for random UDP source port selection to avoid birthday attacks in DNS implementation.
BUG=60149
TEST=net_unittests
Review URL: http://codereview.chromium.org/7202011
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@90925 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'net/udp/udp_socket_libevent.cc')
-rw-r--r-- | net/udp/udp_socket_libevent.cc | 82 |
1 files changed, 60 insertions, 22 deletions
diff --git a/net/udp/udp_socket_libevent.cc b/net/udp/udp_socket_libevent.cc index c451696..201f208 100644 --- a/net/udp/udp_socket_libevent.cc +++ b/net/udp/udp_socket_libevent.cc @@ -13,6 +13,7 @@ #include "base/logging.h" #include "base/message_loop.h" #include "base/metrics/stats_counters.h" +#include "base/rand_util.h" #include "net/base/io_buffer.h" #include "net/base/ip_endpoint.h" #include "net/base/net_errors.h" @@ -22,23 +23,38 @@ #include <netinet/in.h> #endif +namespace { + +static const int kBindRetries = 10; +static const int kPortStart = 1024; +static const int kPortEnd = 65535; + +} // namespace net + namespace net { -UDPSocketLibevent::UDPSocketLibevent(net::NetLog* net_log, - const net::NetLog::Source& source) - : socket_(kInvalidSocket), - read_watcher_(this), - write_watcher_(this), - read_buf_len_(0), - recv_from_address_(NULL), - write_buf_len_(0), - read_callback_(NULL), - write_callback_(NULL), - net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { +UDPSocketLibevent::UDPSocketLibevent( + DatagramSocket::BindType bind_type, + const RandIntCallback& rand_int_cb, + net::NetLog* net_log, + const net::NetLog::Source& source) + : socket_(kInvalidSocket), + bind_type_(bind_type), + rand_int_cb_(rand_int_cb), + read_watcher_(this), + write_watcher_(this), + read_buf_len_(0), + recv_from_address_(NULL), + write_buf_len_(0), + read_callback_(NULL), + write_callback_(NULL), + net_log_(BoundNetLog::Make(net_log, NetLog::SOURCE_SOCKET)) { scoped_refptr<NetLog::EventParameters> params; if (source.is_valid()) params = new NetLogSourceParameter("source_dependency", source); net_log_.BeginEvent(NetLog::TYPE_SOCKET_ALIVE, params); + if (bind_type == DatagramSocket::RANDOM_BIND) + DCHECK(!rand_int_cb.is_null()); } UDPSocketLibevent::~UDPSocketLibevent() { @@ -208,6 +224,13 @@ int UDPSocketLibevent::Connect(const IPEndPoint& address) { if (rv < 0) return rv; + if (bind_type_ == DatagramSocket::RANDOM_BIND) + rv = RandomBind(address); + // else connect() does the DatagramSocket::DEFAULT_BIND + + if (rv < 0) + return rv; + struct sockaddr_storage addr_storage; size_t addr_len = sizeof(addr_storage); struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); @@ -224,21 +247,12 @@ int UDPSocketLibevent::Connect(const IPEndPoint& address) { int UDPSocketLibevent::Bind(const IPEndPoint& address) { DCHECK(!is_connected()); - DCHECK(!local_address_.get()); int rv = CreateSocket(address); if (rv < 0) return rv; - - struct sockaddr_storage addr_storage; - size_t addr_len = sizeof(addr_storage); - struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); - if (!address.ToSockAddr(addr, &addr_len)) - return ERR_FAILED; - - rv = bind(socket_, addr, addr_len); + rv = DoBind(address); if (rv < 0) - return MapSystemError(errno); - + return rv; local_address_.reset(); return rv; } @@ -359,4 +373,28 @@ int UDPSocketLibevent::InternalSendTo(IOBuffer* buf, int buf_len, addr_len)); } +int UDPSocketLibevent::DoBind(const IPEndPoint& address) { + struct sockaddr_storage addr_storage; + size_t addr_len = sizeof(addr_storage); + struct sockaddr* addr = reinterpret_cast<struct sockaddr*>(&addr_storage); + if (!address.ToSockAddr(addr, &addr_len)) + return ERR_UNEXPECTED; + int rv = bind(socket_, addr, addr_len); + return rv < 0 ? MapSystemError(errno) : rv; +} + +int UDPSocketLibevent::RandomBind(const IPEndPoint& address) { + DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null()); + + // Construct IPAddressNumber of appropriate size (IPv4 or IPv6) of 0s. + IPAddressNumber ip(address.address().size()); + + for (int i = 0; i < kBindRetries; ++i) { + int rv = DoBind(IPEndPoint(ip, rand_int_cb_.Run(kPortStart, kPortEnd))); + if (rv == OK || rv != ERR_ADDRESS_IN_USE) + return rv; + } + return DoBind(IPEndPoint(ip, 0)); +} + } // namespace net |