Skip to content

Commit

Permalink
Handle new paddings in improved TCP protocol.
Browse files Browse the repository at this point in the history
  • Loading branch information
john-preston committed Jun 27, 2018
1 parent 22441ef commit 941288b
Show file tree
Hide file tree
Showing 6 changed files with 198 additions and 109 deletions.
43 changes: 15 additions & 28 deletions Telegram/SourceFiles/mtproto/connection.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1415,7 +1415,7 @@ void ConnectionPrivate::handleReceived() {
}

auto encryptedInts = ints + kExternalHeaderIntsCount;
auto encryptedIntsCount = (intsCount - kExternalHeaderIntsCount);
auto encryptedIntsCount = (intsCount - kExternalHeaderIntsCount) & ~0x03U;
auto encryptedBytesCount = encryptedIntsCount * kIntSize;
auto decryptedBuffer = QByteArray(encryptedBytesCount, Qt::Uninitialized);
auto msgKey = *(MTPint128*)(ints + 2);
Expand Down Expand Up @@ -3062,35 +3062,22 @@ template <typename Response>
bool ConnectionPrivate::readNotSecureResponse(Response &response) {
onReceivedSome();

try {
if (_connection->received().empty()) {
LOG(("AuthKey Error: trying to read response from empty received list"));
return false;
}
if (_connection->received().empty()) {
LOG(("AuthKey Error: "
"trying to read response from empty received list"));
return false;
}

auto buffer = std::move(_connection->received().front());
_connection->received().pop_front();
const auto buffer = std::move(_connection->received().front());
_connection->received().pop_front();

auto answer = buffer.constData();
auto len = buffer.size();
if (len < 5) {
LOG(("AuthKey Error: bad request answer, len = %1").arg(len * sizeof(mtpPrime)));
DEBUG_LOG(("AuthKey Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
return false;
}
if (answer[0] != 0 || answer[1] != 0 || (((uint32)answer[2]) & 0x03) != 1/* || (unixtime() - answer[3] > 300) || (answer[3] - unixtime() > 60)*/) { // didnt sync time yet
LOG(("AuthKey Error: bad request answer start (%1 %2 %3)").arg(answer[0]).arg(answer[1]).arg(answer[2]));
DEBUG_LOG(("AuthKey Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
return false;
}
uint32 answerLen = (uint32)answer[4];
if (answerLen != (len - 5) * sizeof(mtpPrime)) {
LOG(("AuthKey Error: bad request answer %1 <> %2").arg(answerLen).arg((len - 5) * sizeof(mtpPrime)));
DEBUG_LOG(("AuthKey Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
return false;
}
const mtpPrime *from(answer + 5), *end(from + len - 5);
response.read(from, end);
const auto answer = _connection->parseNotSecureResponse(buffer);
if (answer.empty()) {
return false;
}
try {
auto from = answer.data();
response.read(from, from + answer.size());
} catch (Exception &) {
return false;
}
Expand Down
59 changes: 41 additions & 18 deletions Telegram/SourceFiles/mtproto/connection_abstract.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -97,33 +97,56 @@ mtpBuffer AbstractConnection::prepareSecurePacket(
return result;
}

gsl::span<const mtpPrime> AbstractConnection::parseNotSecureResponse(
const mtpBuffer &buffer) const {
const auto answer = buffer.data();
const auto len = buffer.size();
if (len < 6) {
LOG(("Not Secure Error: bad request answer, len = %1"
).arg(len * sizeof(mtpPrime)));
DEBUG_LOG(("Not Secure Error: answer bytes %1"
).arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
return {};
}
if (answer[0] != 0
|| answer[1] != 0
|| (((uint32)answer[2]) & 0x03) != 1
//|| (unixtime() - answer[3] > 300) // We didn't sync time yet.
//|| (answer[3] - unixtime() > 60)
|| false) {
LOG(("Not Secure Error: bad request answer start (%1 %2 %3)"
).arg(answer[0]
).arg(answer[1]
).arg(answer[2]));
DEBUG_LOG(("Not Secure Error: answer bytes %1"
).arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
return {};
}
const auto answerLen = (uint32)answer[4];
if (answerLen < 1 || answerLen > (len - 5) * sizeof(mtpPrime)) {
LOG(("Not Secure Error: bad request answer 1 <= %1 <= %2"
).arg(answerLen
).arg((len - 5) * sizeof(mtpPrime)));
DEBUG_LOG(("Not Secure Error: answer bytes %1"
).arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
return {};
}
return gsl::make_span(answer + 5, answerLen);
}

mtpBuffer AbstractConnection::preparePQFake(const MTPint128 &nonce) const {
return prepareNotSecurePacket(MTPReq_pq(nonce));
}

MTPResPQ AbstractConnection::readPQFakeReply(
const mtpBuffer &buffer) const {
const mtpPrime *answer(buffer.constData());
uint32 len = buffer.size();
if (len < 5) {
LOG(("Fake PQ Error: bad request answer, len = %1").arg(len * sizeof(mtpPrime)));
DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
throw Exception("bad pq reply");
}
if (answer[0] != 0 || answer[1] != 0 || (((uint32)answer[2]) & 0x03) != 1/* || (unixtime() - answer[3] > 300) || (answer[3] - unixtime() > 60)*/) { // didnt sync time yet
LOG(("Fake PQ Error: bad request answer start (%1 %2 %3)").arg(answer[0]).arg(answer[1]).arg(answer[2]));
DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
throw Exception("bad pq reply");
}
uint32 answerLen = (uint32)answer[4];
if (answerLen != (len - 5) * sizeof(mtpPrime)) {
LOG(("Fake PQ Error: bad request answer %1 <> %2").arg(answerLen).arg((len - 5) * sizeof(mtpPrime)));
DEBUG_LOG(("Fake PQ Error: answer bytes %1").arg(Logs::mb(answer, len * sizeof(mtpPrime)).str()));
const auto answer = parseNotSecureResponse(buffer);
if (answer.empty()) {
throw Exception("bad pq reply");
}
const mtpPrime *from(answer + 5), *end(from + len - 5);
auto from = answer.data();
MTPResPQ response;
response.read(from, end);
response.read(from, from + answer.size());
return response;
}

Expand Down
3 changes: 3 additions & 0 deletions Telegram/SourceFiles/mtproto/connection_abstract.h
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,9 @@ class AbstractConnection : public QObject {
MTPint128 msgKey,
uint32 size) const;

gsl::span<const mtpPrime> parseNotSecureResponse(
const mtpBuffer &buffer) const;

// Used to emit error(...) with no real code from the server.
static constexpr auto kErrorCodeOther = -499;

Expand Down
18 changes: 13 additions & 5 deletions Telegram/SourceFiles/mtproto/connection_http.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -169,16 +169,24 @@ void HttpConnection::requestFinished(QNetworkReply *reply) {
emit receivedData();
} else {
try {
auto res_pq = readPQFakeReply(data);
const auto &res_pq_data(res_pq.c_resPQ());
if (res_pq_data.vnonce == _checkNonce) {
DEBUG_LOG(("Connection Info: HTTP-transport to %1 connected by pq-response").arg(_address));
const auto res_pq = readPQFakeReply(data);
const auto &data = res_pq.c_resPQ();
if (data.vnonce == _checkNonce) {
DEBUG_LOG(("Connection Info: "
"HTTP-transport to %1 connected by pq-response"
).arg(_address));
_status = Status::Ready;
_pingTime = getms() - _pingTime;
emit connected();
} else {
DEBUG_LOG(("Connection Error: "
"Wrong nonce received in HTTP fake pq-responce"));
emit error(kErrorCodeOther);
}
} catch (Exception &e) {
DEBUG_LOG(("Connection Error: exception in parsing HTTP fake pq-responce, %1").arg(e.what()));
DEBUG_LOG(("Connection Error: "
"Exception in parsing HTTP fake pq-responce, %1"
).arg(e.what()));
emit error(kErrorCodeOther);
}
}
Expand Down
Loading

0 comments on commit 941288b

Please sign in to comment.