Secret chats: check that his_layer is monotonic

GitOrigin-RevId: cb6b50e768a90c5afcece185bea2e7209a9939f5
This commit is contained in:
Arseny Smirnov 2018-06-14 18:00:10 +03:00
parent 3a8c0f131e
commit e5c90f239f
3 changed files with 29 additions and 4 deletions

View File

@ -903,7 +903,7 @@ Status SecretChatActor::do_inbound_message_encrypted(std::unique_ptr<logevent::I
return status;
}
Status SecretChatActor::check_seq_no(int in_seq_no, int out_seq_no) {
Status SecretChatActor::check_seq_no(int in_seq_no, int out_seq_no, int32 his_layer) {
if (in_seq_no < 0) {
return Status::OK();
}
@ -924,6 +924,9 @@ Status SecretChatActor::check_seq_no(int in_seq_no, int out_seq_no) {
if (seq_no_state_.my_out_seq_no < in_seq_no) {
return Status::Error("in_seq_no is bigger than seq_no_state_.my_out_seq_no");
}
if (his_layer < seq_no_state_.his_layer) {
return Status::Error("his_layer is not monotonic");
}
return Status::OK();
}
@ -935,7 +938,7 @@ Status SecretChatActor::do_inbound_message_decrypted_unchecked(
};
auto in_seq_no = message->decrypted_message_layer->in_seq_no_;
auto out_seq_no = message->decrypted_message_layer->out_seq_no_;
auto status = check_seq_no(in_seq_no, out_seq_no);
auto status = check_seq_no(in_seq_no, out_seq_no, message->his_layer());
if (status.is_error() && status.code() != 2 /* not gap found */) {
message->qts_ack.set_value(Unit());
if (message->logevent_id()) {
@ -1136,6 +1139,11 @@ void SecretChatActor::update_seq_no_state(const T &new_seq_no_state) {
seq_no_state_.my_in_seq_no = new_seq_no_state.my_in_seq_no;
seq_no_state_.my_out_seq_no = new_seq_no_state.my_out_seq_no;
auto new_his_layer = new_seq_no_state.his_layer();
if (new_his_layer != -1) {
seq_no_state_.his_layer = new_his_layer;
}
if (seq_no_state_.his_in_seq_no != new_seq_no_state.his_in_seq_no) {
seq_no_state_.his_in_seq_no = new_seq_no_state.his_in_seq_no;
on_his_in_seq_no_updated();

View File

@ -149,6 +149,7 @@ class SecretChatActor : public NetQueryCallback {
int32 my_in_seq_no = 0;
int32 my_out_seq_no = 0;
int32 his_in_seq_no = 0;
int32 his_layer = 0;
int32 resend_end_seq_no = -1;
@ -157,11 +158,12 @@ class SecretChatActor : public NetQueryCallback {
}
template <class StorerT>
void store(StorerT &storer) const {
storer.store_int(message_id);
storer.store_int(message_id | HAS_LAYER);
storer.store_int(my_in_seq_no);
storer.store_int(my_out_seq_no);
storer.store_int(his_in_seq_no);
storer.store_int(resend_end_seq_no);
storer.store_int(his_layer);
}
template <class ParserT>
@ -171,7 +173,14 @@ class SecretChatActor : public NetQueryCallback {
my_out_seq_no = parser.fetch_int();
his_in_seq_no = parser.fetch_int();
resend_end_seq_no = parser.fetch_int();
bool has_layer = (message_id & HAS_LAYER) != 0;
if (has_layer) {
message_id &= static_cast<int32>(~HAS_LAYER);
his_layer = parser.fetch_int();
}
}
static constexpr uint32 HAS_LAYER = 1u << 31;
};
struct ConfigState {
@ -516,7 +525,7 @@ class SecretChatActor : public NetQueryCallback {
bool seq_no_state_changed_ = false;
int32 last_binlog_message_id_ = -1;
Status check_seq_no(int in_seq_no, int out_seq_no) TD_WARN_UNUSED_RESULT;
Status check_seq_no(int in_seq_no, int out_seq_no, int32 his_layer) TD_WARN_UNUSED_RESULT;
void on_his_in_seq_no_updated();
void on_seq_no_state_changed();

View File

@ -205,6 +205,10 @@ class InboundSecretMessage : public LogEventHelper<InboundSecretMessage, SecretC
int32 my_out_seq_no = -1;
int32 his_in_seq_no = -1;
int32 his_layer() const {
return decrypted_message_layer->layer_;
}
EncryptedFileLocation file;
bool has_encrypted_file;
@ -292,6 +296,10 @@ class OutboundSecretMessage : public LogEventHelper<OutboundSecretMessage, Secre
int32 my_out_seq_no = -1;
int32 his_in_seq_no = -1;
int32 his_layer() const {
return -1;
}
bool is_sent = false;
bool is_service = false;
bool is_rewritable = false;