mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 14:47:44 +00:00
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.
This commit is contained in:
parent
00be9b33b1
commit
a9ec2225a5
6 changed files with 48 additions and 11 deletions
|
@ -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);
|
ASSERT(m_questions.size() <= UINT16_MAX);
|
||||||
|
|
||||||
if (name.is_empty())
|
if (name.is_empty())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Randomize the 0x20 bit in every ASCII character.
|
|
||||||
StringBuilder builder;
|
StringBuilder builder;
|
||||||
for (size_t i = 0; i < name.length(); ++i) {
|
for (size_t i = 0; i < name.length(); ++i) {
|
||||||
u8 ch = name[i];
|
u8 ch = name[i];
|
||||||
if (isalpha(ch)) {
|
if (should_randomize_case == ShouldRandomizeCase::Yes) {
|
||||||
if (arc4random_uniform(2))
|
// Randomize the 0x20 bit in every ASCII character.
|
||||||
ch |= 0x20;
|
if (isalpha(ch)) {
|
||||||
else
|
if (arc4random_uniform(2))
|
||||||
ch &= ~0x20;
|
ch |= 0x20;
|
||||||
|
else
|
||||||
|
ch &= ~0x20;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
builder.append(ch);
|
builder.append(ch);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,11 +12,16 @@
|
||||||
#define T_PTR 12
|
#define T_PTR 12
|
||||||
#define T_MX 15
|
#define T_MX 15
|
||||||
|
|
||||||
|
enum class ShouldRandomizeCase {
|
||||||
|
No = 0,
|
||||||
|
Yes
|
||||||
|
};
|
||||||
|
|
||||||
class DNSRequest {
|
class DNSRequest {
|
||||||
public:
|
public:
|
||||||
DNSRequest();
|
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; }
|
const Vector<DNSQuestion>& questions() const { return m_questions; }
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,10 @@ Optional<DNSResponse> DNSResponse::from_raw_response(const u8* raw_data, size_t
|
||||||
|
|
||||||
DNSResponse response;
|
DNSResponse response;
|
||||||
response.m_id = response_header.id();
|
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);
|
size_t offset = sizeof(DNSPacket);
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,26 @@ public:
|
||||||
return m_answers.size();
|
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:
|
private:
|
||||||
DNSResponse() {}
|
DNSResponse() {}
|
||||||
|
|
||||||
u16 m_id { 0 };
|
u16 m_id { 0 };
|
||||||
|
u8 m_code { 0 };
|
||||||
Vector<DNSQuestion> m_questions;
|
Vector<DNSQuestion> m_questions;
|
||||||
Vector<DNSAnswer> m_answers;
|
Vector<DNSAnswer> m_answers;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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()) {
|
if (auto it = m_lookup_cache.find(hostname); it != m_lookup_cache.end()) {
|
||||||
auto& cached_lookup = it->value;
|
auto& cached_lookup = it->value;
|
||||||
|
@ -172,7 +172,7 @@ Vector<String> LookupServer::lookup(const String& hostname, bool& did_timeout, u
|
||||||
}
|
}
|
||||||
|
|
||||||
DNSRequest request;
|
DNSRequest request;
|
||||||
request.add_question(hostname, record_type);
|
request.add_question(hostname, record_type, should_randomize_case);
|
||||||
|
|
||||||
auto buffer = request.to_byte_buffer();
|
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());
|
dbgprintf("LookupServer: ID mismatch (%u vs %u) :(\n", response.id(), request.id());
|
||||||
return {};
|
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()) {
|
if (response.question_count() != request.question_count()) {
|
||||||
dbgprintf("LookupServer: Question count (%u vs %u) :(\n", response.question_count(), request.question_count());
|
dbgprintf("LookupServer: Question count (%u vs %u) :(\n", response.question_count(), request.question_count());
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "DNSRequest.h"
|
||||||
#include <AK/HashMap.h>
|
#include <AK/HashMap.h>
|
||||||
#include <AK/RefPtr.h>
|
#include <AK/RefPtr.h>
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
|
@ -44,7 +45,7 @@ public:
|
||||||
private:
|
private:
|
||||||
void load_etc_hosts();
|
void load_etc_hosts();
|
||||||
void service_client(RefPtr<CLocalSocket>);
|
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);
|
int make_dns_request_socket(sockaddr_in& dst_addr);
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue