Skip to content
Snippets Groups Projects
Commit 423a18ce authored by Yang Tse's avatar Yang Tse
Browse files

Brad House's validation that DNS response address matches the request address

parent f164260e
No related branches found
No related tags found
No related merge requests found
Changelog for the c-ares project
* Aug 25 2008 (Yang Tse)
- Improvement by Brad House:
This patch addresses an issue in which a response could be sent back to the
source port of a client from a different address than the request was made to.
This is one form of a DNS cache poisoning attack.
The patch simply uses recvfrom() rather than recv() and validates that the
address returned from recvfrom() matches the address of the server we have
connected to. Only necessary on UDP sockets as they are connection-less, TCP
is unaffected.
* Aug 4 2008 (Daniel Stenberg)
- Fix by Tofu Linden:
......
......@@ -9,6 +9,7 @@ This is what's new and changed in the c-ares 1.5.3 release:
o library will now be built with _REENTRANT symbol defined if needed
o Improved configure detection of number of arguments for getservbyport_r
o Improved query-ID randomness
o Validate that DNS response address matches the request address
Thanks go to these friendly people for their efforts and contributions:
......
......@@ -429,6 +429,8 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
int i;
ssize_t count;
unsigned char buf[PACKETSZ + 1];
struct sockaddr_in from;
socklen_t fromlen;
if(!read_fds && (read_fd == ARES_SOCKET_BAD))
/* no possible action */
......@@ -462,11 +464,23 @@ static void read_udp_packets(ares_channel channel, fd_set *read_fds,
/* To reduce event loop overhead, read and process as many
* packets as we can. */
do {
count = sread(server->udp_socket, buf, sizeof(buf));
/* Must memset 'from' to 0 as recvfrom() on some systems may
* not use 'from' at all if it doesn't support receiving the
* source address of the response */
memset(&from, 0, sizeof(from));
fromlen = sizeof(from);
count = (ssize_t)recvfrom(server->udp_socket, (void *)buf, sizeof(buf),
0, (struct sockaddr *)&from, &fromlen);
if (count == -1 && try_again(SOCKERRNO))
continue;
else if (count <= 0)
handle_error(channel, i, now);
else if (fromlen && from.sin_addr.s_addr != 0 &&
from.sin_addr.s_addr != server->addr.s_addr)
/* Address response came from did not match the address
* we sent the request to. Someone may be attempting
* to perform a cache poisoning attack */
break;
else
process_answer(channel, buf, (int)count, i, 0, now);
} while (count > 0);
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment