Really fix too long TLS-proxy domain.

GitOrigin-RevId: a07726e8bb75b467d26043d6c9b4ad834a961567
This commit is contained in:
levlam 2020-01-26 01:22:07 +03:00
parent 182e8d29f0
commit eae92b214a
4 changed files with 20 additions and 10 deletions

View File

@ -12,7 +12,7 @@
namespace td { namespace td {
namespace mtproto { namespace mtproto {
Result<ProxySecret> ProxySecret::from_link(Slice encoded_secret) { Result<ProxySecret> ProxySecret::from_link(Slice encoded_secret, bool truncate_if_needed) {
auto r_decoded = hex_decode(encoded_secret); auto r_decoded = hex_decode(encoded_secret);
if (r_decoded.is_error()) { if (r_decoded.is_error()) {
r_decoded = base64url_decode(encoded_secret); r_decoded = base64url_decode(encoded_secret);
@ -20,13 +20,17 @@ Result<ProxySecret> ProxySecret::from_link(Slice encoded_secret) {
if (r_decoded.is_error()) { if (r_decoded.is_error()) {
return Status::Error(400, "Wrong proxy secret"); return Status::Error(400, "Wrong proxy secret");
} }
return from_binary(r_decoded.ok()); return from_binary(r_decoded.ok(), truncate_if_needed);
} }
Result<ProxySecret> ProxySecret::from_binary(Slice raw_unchecked_secret) { Result<ProxySecret> ProxySecret::from_binary(Slice raw_unchecked_secret, bool truncate_if_needed) {
if (raw_unchecked_secret.size() > 17 + 255) { if (raw_unchecked_secret.size() > 17 + MAX_DOMAIN_LENGTH) {
if (truncate_if_needed) {
raw_unchecked_secret.truncate(17 + MAX_DOMAIN_LENGTH);
} else {
return Status::Error(400, "Too long secret"); return Status::Error(400, "Too long secret");
} }
}
if (raw_unchecked_secret.size() == 16 || if (raw_unchecked_secret.size() == 16 ||
(raw_unchecked_secret.size() == 17 && static_cast<unsigned char>(raw_unchecked_secret[0]) == 0xdd) || (raw_unchecked_secret.size() == 17 && static_cast<unsigned char>(raw_unchecked_secret[0]) == 0xdd) ||
(raw_unchecked_secret.size() >= 18 && static_cast<unsigned char>(raw_unchecked_secret[0]) == 0xee)) { (raw_unchecked_secret.size() >= 18 && static_cast<unsigned char>(raw_unchecked_secret[0]) == 0xee)) {

View File

@ -15,8 +15,12 @@ namespace mtproto {
class ProxySecret { class ProxySecret {
public: public:
static Result<ProxySecret> from_link(Slice encoded_secret); static constexpr size_t MAX_DOMAIN_LENGTH = 182; // must be small enough to not overflow TLS-hello length
static Result<ProxySecret> from_binary(Slice raw_unchecked_secret);
static Result<ProxySecret> from_link(Slice encoded_secret, bool truncate_if_needed = false);
static Result<ProxySecret> from_binary(Slice raw_unchecked_secret, bool truncate_if_needed = false);
static ProxySecret from_raw(Slice raw_secret) { static ProxySecret from_raw(Slice raw_secret) {
ProxySecret result; ProxySecret result;
result.secret_ = raw_secret.str(); result.secret_ = raw_secret.str();

View File

@ -6,6 +6,8 @@
// //
#include "td/mtproto/TlsInit.h" #include "td/mtproto/TlsInit.h"
#include "td/mtproto/ProxySecret.h"
#include "td/utils/as.h" #include "td/utils/as.h"
#include "td/utils/BigNum.h" #include "td/utils/BigNum.h"
#include "td/utils/common.h" #include "td/utils/common.h"
@ -157,7 +159,7 @@ class TlsHelloContext {
return grease_.size(); return grease_.size();
} }
Slice get_domain() const { Slice get_domain() const {
return Slice(domain_).substr(0, 255); return Slice(domain_).substr(0, ProxySecret::MAX_DOMAIN_LENGTH);
} }
private: private:
@ -225,7 +227,7 @@ class TlsHelloCalcLength {
} }
Result<size_t> finish() { Result<size_t> finish() {
if (size_ > 515) { if (size_ > 514) {
on_error(Status::Error("Too long for zero padding")); on_error(Status::Error("Too long for zero padding"));
} }
if (size_ < 11 + 32) { if (size_ < 11 + 32) {

View File

@ -134,7 +134,7 @@ class Proxy {
} else if (type_ == Proxy::Type::Mtproto) { } else if (type_ == Proxy::Type::Mtproto) {
parse(server_, parser); parse(server_, parser);
parse(port_, parser); parse(port_, parser);
secret_ = mtproto::ProxySecret::from_link(parser.template fetch_string<Slice>()).move_as_ok(); secret_ = mtproto::ProxySecret::from_link(parser.template fetch_string<Slice>(), true).move_as_ok();
} else { } else {
CHECK(type_ == Proxy::Type::None); CHECK(type_ == Proxy::Type::None);
} }