summaryrefslogtreecommitdiff
path: root/Servers/LookupServer
diff options
context:
space:
mode:
authorAndreas Kling <kling@serenityos.org>2020-01-26 13:45:15 +0100
committerAndreas Kling <kling@serenityos.org>2020-01-26 13:49:46 +0100
commita9ec2225a5769be903f8cc19b50025d83b94f4ac (patch)
tree9c55882528c13e4308d4a9fa01f9e1fbd63a36f6 /Servers/LookupServer
parent00be9b33b1ad58a08463ae86e76742cb6db60324 (diff)
downloadserenity-a9ec2225a5769be903f8cc19b50025d83b94f4ac.zip
LookupServer: Retry with 0x20 randomization turned off on EREFUSED
Apparently some authoritative servers don't handle 0x20 randomization well and may send EREFUSED. Retry with randomization turned off then. Reference: https://github.com/dns-violations/dns-violations/blob/master/2017/DVE-2017-0006.md More work towards #10.
Diffstat (limited to 'Servers/LookupServer')
-rw-r--r--Servers/LookupServer/DNSRequest.cpp16
-rw-r--r--Servers/LookupServer/DNSRequest.h7
-rw-r--r--Servers/LookupServer/DNSResponse.cpp4
-rw-r--r--Servers/LookupServer/DNSResponse.h16
-rw-r--r--Servers/LookupServer/LookupServer.cpp13
-rw-r--r--Servers/LookupServer/LookupServer.h3
6 files changed, 48 insertions, 11 deletions
diff --git a/Servers/LookupServer/DNSRequest.cpp b/Servers/LookupServer/DNSRequest.cpp
index f70fe02aff..ef1048ccca 100644
--- a/Servers/LookupServer/DNSRequest.cpp
+++ b/Servers/LookupServer/DNSRequest.cpp
@@ -13,22 +13,24 @@ DNSRequest::DNSRequest()
{
}
-void DNSRequest::add_question(const String& name, u16 record_type)
+void DNSRequest::add_question(const String& name, u16 record_type, ShouldRandomizeCase should_randomize_case)
{
ASSERT(m_questions.size() <= UINT16_MAX);
if (name.is_empty())
return;
- // Randomize the 0x20 bit in every ASCII character.
StringBuilder builder;
for (size_t i = 0; i < name.length(); ++i) {
u8 ch = name[i];
- if (isalpha(ch)) {
- if (arc4random_uniform(2))
- ch |= 0x20;
- else
- ch &= ~0x20;
+ if (should_randomize_case == ShouldRandomizeCase::Yes) {
+ // Randomize the 0x20 bit in every ASCII character.
+ if (isalpha(ch)) {
+ if (arc4random_uniform(2))
+ ch |= 0x20;
+ else
+ ch &= ~0x20;
+ }
}
builder.append(ch);
}
diff --git a/Servers/LookupServer/DNSRequest.h b/Servers/LookupServer/DNSRequest.h
index 4a73b35718..f702a4ede3 100644
--- a/Servers/LookupServer/DNSRequest.h
+++ b/Servers/LookupServer/DNSRequest.h
@@ -12,11 +12,16 @@
#define T_PTR 12
#define T_MX 15
+enum class ShouldRandomizeCase {
+ No = 0,
+ Yes
+};
+
class DNSRequest {
public:
DNSRequest();
- void add_question(const String& name, u16 record_type);
+ void add_question(const String& name, u16 record_type, ShouldRandomizeCase);
const Vector<DNSQuestion>& questions() const { return m_questions; }
diff --git a/Servers/LookupServer/DNSResponse.cpp b/Servers/LookupServer/DNSResponse.cpp
index 4d86dcb528..5be6fba62f 100644
--- a/Servers/LookupServer/DNSResponse.cpp
+++ b/Servers/LookupServer/DNSResponse.cpp
@@ -44,6 +44,10 @@ Optional<DNSResponse> DNSResponse::from_raw_response(const u8* raw_data, size_t
DNSResponse response;
response.m_id = response_header.id();
+ response.m_code = response_header.response_code();
+
+ if (response.code() != DNSResponse::Code::NOERROR)
+ return response;
size_t offset = sizeof(DNSPacket);
diff --git a/Servers/LookupServer/DNSResponse.h b/Servers/LookupServer/DNSResponse.h
index 2e0da23044..078e007a98 100644
--- a/Servers/LookupServer/DNSResponse.h
+++ b/Servers/LookupServer/DNSResponse.h
@@ -26,10 +26,26 @@ public:
return m_answers.size();
}
+ enum class Code : u8 {
+ NOERROR = 0,
+ FORMERR = 1,
+ SERVFAIL = 2,
+ NXDOMAIN = 3,
+ NOTIMP = 4,
+ REFUSED = 5,
+ YXDOMAIN = 6,
+ XRRSET = 7,
+ NOTAUTH = 8,
+ NOTZONE = 9,
+ };
+
+ Code code() const { return (Code)m_code; }
+
private:
DNSResponse() {}
u16 m_id { 0 };
+ u8 m_code { 0 };
Vector<DNSQuestion> m_questions;
Vector<DNSAnswer> m_answers;
};
diff --git a/Servers/LookupServer/LookupServer.cpp b/Servers/LookupServer/LookupServer.cpp
index ae7605d76f..4cf7dfc36a 100644
--- a/Servers/LookupServer/LookupServer.cpp
+++ b/Servers/LookupServer/LookupServer.cpp
@@ -161,7 +161,7 @@ void LookupServer::service_client(RefPtr<CLocalSocket> socket)
}
}
-Vector<String> LookupServer::lookup(const String& hostname, bool& did_timeout, unsigned short record_type)
+Vector<String> LookupServer::lookup(const String& hostname, bool& did_timeout, unsigned short record_type, ShouldRandomizeCase should_randomize_case)
{
if (auto it = m_lookup_cache.find(hostname); it != m_lookup_cache.end()) {
auto& cached_lookup = it->value;
@@ -172,7 +172,7 @@ Vector<String> LookupServer::lookup(const String& hostname, bool& did_timeout, u
}
DNSRequest request;
- request.add_question(hostname, record_type);
+ request.add_question(hostname, record_type, should_randomize_case);
auto buffer = request.to_byte_buffer();
@@ -216,6 +216,15 @@ Vector<String> LookupServer::lookup(const String& hostname, bool& did_timeout, u
dbgprintf("LookupServer: ID mismatch (%u vs %u) :(\n", response.id(), request.id());
return {};
}
+
+ if (response.code() == DNSResponse::Code::REFUSED) {
+ if (should_randomize_case == ShouldRandomizeCase::Yes) {
+ // Retry with 0x20 case randomization turned off.
+ return lookup(hostname, did_timeout, record_type, ShouldRandomizeCase::No);
+ }
+ return {};
+ }
+
if (response.question_count() != request.question_count()) {
dbgprintf("LookupServer: Question count (%u vs %u) :(\n", response.question_count(), request.question_count());
return {};
diff --git a/Servers/LookupServer/LookupServer.h b/Servers/LookupServer/LookupServer.h
index 0ef7d29322..5c8120cd4c 100644
--- a/Servers/LookupServer/LookupServer.h
+++ b/Servers/LookupServer/LookupServer.h
@@ -26,6 +26,7 @@
#pragma once
+#include "DNSRequest.h"
#include <AK/HashMap.h>
#include <AK/RefPtr.h>
#include <AK/String.h>
@@ -44,7 +45,7 @@ public:
private:
void load_etc_hosts();
void service_client(RefPtr<CLocalSocket>);
- Vector<String> lookup(const String& hostname, bool& did_timeout, unsigned short record_type);
+ Vector<String> lookup(const String& hostname, bool& did_timeout, unsigned short record_type, ShouldRandomizeCase = ShouldRandomizeCase::Yes);
int make_dns_request_socket(sockaddr_in& dst_addr);