mirror of
https://github.com/vale981/tdesktop
synced 2025-03-06 02:01:40 -05:00
Add random_padding to dns requests.
This commit is contained in:
parent
3cfc3dcecf
commit
93a967dc74
1 changed files with 82 additions and 37 deletions
|
@ -69,7 +69,32 @@ bool CheckPhoneByPrefixesRules(const QString &phone, const QString &rules) {
|
|||
return result;
|
||||
}
|
||||
|
||||
std::vector<DnsEntry> ParseDnsResponse(const QByteArray &response) {
|
||||
QString GenerateRandomPadding() {
|
||||
constexpr char kValid[] = "abcdefghijklmnopqrstuvwxyz"
|
||||
"ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
|
||||
|
||||
auto result = QString();
|
||||
const auto count = [&] {
|
||||
constexpr auto kMinPadding = 13;
|
||||
constexpr auto kMaxPadding = 128;
|
||||
while (true) {
|
||||
const auto result = 1 + (rand_value<uchar>() / 2);
|
||||
Assert(result <= kMaxPadding);
|
||||
if (result >= kMinPadding) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}();
|
||||
result.resize(count);
|
||||
for (auto &ch : result) {
|
||||
ch = kValid[rand_value<uchar>() % (sizeof(kValid) - 1)];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::vector<DnsEntry> ParseDnsResponse(
|
||||
const QByteArray &bytes,
|
||||
std::optional<int> typeRestriction = std::nullopt) {
|
||||
// Read and store to "result" all the data bytes from the response:
|
||||
// { ..,
|
||||
// "Answer": [
|
||||
|
@ -77,48 +102,63 @@ std::vector<DnsEntry> ParseDnsResponse(const QByteArray &response) {
|
|||
// { .., "data": "bytes2", "TTL": int, .. }
|
||||
// ],
|
||||
// .. }
|
||||
auto result = std::vector<DnsEntry>();
|
||||
auto error = QJsonParseError{ 0, QJsonParseError::NoError };
|
||||
auto document = QJsonDocument::fromJson(response, &error);
|
||||
const auto document = QJsonDocument::fromJson(bytes, &error);
|
||||
if (error.error != QJsonParseError::NoError) {
|
||||
LOG(("Config Error: Failed to parse dns response JSON, error: %1"
|
||||
).arg(error.errorString()));
|
||||
return {};
|
||||
} else if (!document.isObject()) {
|
||||
LOG(("Config Error: Not an object received in dns response JSON."));
|
||||
} else {
|
||||
auto response = document.object();
|
||||
auto answerIt = response.find(qsl("Answer"));
|
||||
return {};
|
||||
}
|
||||
const auto response = document.object();
|
||||
const auto answerIt = response.find(qsl("Answer"));
|
||||
if (answerIt == response.constEnd()) {
|
||||
LOG(("Config Error: Could not find Answer "
|
||||
"in dns response JSON."));
|
||||
LOG(("Config Error: Could not find Answer in dns response JSON."));
|
||||
return {};
|
||||
} else if (!(*answerIt).isArray()) {
|
||||
LOG(("Config Error: Not an array received "
|
||||
"in Answer in dns response JSON."));
|
||||
} else {
|
||||
for (auto elem : (*answerIt).toArray()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
auto result = std::vector<DnsEntry>();
|
||||
for (const auto elem : (*answerIt).toArray()) {
|
||||
if (!elem.isObject()) {
|
||||
LOG(("Config Error: Not an object found "
|
||||
"in Answer array in dns response JSON."));
|
||||
} else {
|
||||
auto object = elem.toObject();
|
||||
auto dataIt = object.find(qsl("data"));
|
||||
auto ttlIt = object.find(qsl("TTL"));
|
||||
auto ttl = (ttlIt != object.constEnd())
|
||||
? int64(std::round((*ttlIt).toDouble()))
|
||||
: int64(0);
|
||||
continue;
|
||||
}
|
||||
const auto object = elem.toObject();
|
||||
if (typeRestriction) {
|
||||
const auto typeIt = object.find(qsl("type"));
|
||||
const auto type = int(std::round((*typeIt).toDouble()));
|
||||
if (!(*typeIt).isDouble()) {
|
||||
LOG(("Config Error: Not a number in type field "
|
||||
"in Answer array in dns response JSON."));
|
||||
continue;
|
||||
} else if (type != *typeRestriction) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const auto dataIt = object.find(qsl("data"));
|
||||
if (dataIt == object.constEnd()) {
|
||||
LOG(("Config Error: Could not find data "
|
||||
"in Answer array entry in dns response JSON."));
|
||||
continue;
|
||||
} else if (!(*dataIt).isString()) {
|
||||
LOG(("Config Error: Not a string data found "
|
||||
"in Answer array entry in dns response JSON."));
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
|
||||
const auto ttlIt = object.find(qsl("TTL"));
|
||||
const auto ttl = (ttlIt != object.constEnd())
|
||||
? int64(std::round((*ttlIt).toDouble()))
|
||||
: int64(0);
|
||||
result.push_back({ (*dataIt).toString(), ttl });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -215,7 +255,9 @@ void SpecialConfigRequest::performRequest(const Attempt &attempt) {
|
|||
} break;
|
||||
case Type::Dns: {
|
||||
url.setPath(qsl("/resolve"));
|
||||
url.setQuery(qsl("name=%1&type=16").arg(Global::TxtDomainString()));
|
||||
url.setQuery(qsl("name=%1&type=ANY&random_padding=%2"
|
||||
).arg(Global::TxtDomainString()
|
||||
).arg(GenerateRandomPadding()));
|
||||
request.setRawHeader("Host", "dns.google.com");
|
||||
} break;
|
||||
default: Unexpected("Type in SpecialConfigRequest::performRequest.");
|
||||
|
@ -236,8 +278,11 @@ void SpecialConfigRequest::requestFinished(
|
|||
const auto result = finalizeRequest(reply);
|
||||
switch (type) {
|
||||
case Type::App: handleResponse(result); break;
|
||||
case Type::Dns: handleResponse(
|
||||
ConcatenateDnsTxtFields(ParseDnsResponse(result))); break;
|
||||
case Type::Dns: {
|
||||
constexpr auto kTypeRestriction = 16; // TXT
|
||||
handleResponse(ConcatenateDnsTxtFields(
|
||||
ParseDnsResponse(result, kTypeRestriction)));
|
||||
} break;
|
||||
default: Unexpected("Type in SpecialConfigRequest::requestFinished.");
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue