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; 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) { if (in_seq_no < 0) {
return Status::OK(); 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) { 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"); 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(); 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 in_seq_no = message->decrypted_message_layer->in_seq_no_;
auto out_seq_no = message->decrypted_message_layer->out_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 */) { if (status.is_error() && status.code() != 2 /* not gap found */) {
message->qts_ack.set_value(Unit()); message->qts_ack.set_value(Unit());
if (message->logevent_id()) { 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_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; 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) { 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; seq_no_state_.his_in_seq_no = new_seq_no_state.his_in_seq_no;
on_his_in_seq_no_updated(); on_his_in_seq_no_updated();

View File

@ -149,6 +149,7 @@ class SecretChatActor : public NetQueryCallback {
int32 my_in_seq_no = 0; int32 my_in_seq_no = 0;
int32 my_out_seq_no = 0; int32 my_out_seq_no = 0;
int32 his_in_seq_no = 0; int32 his_in_seq_no = 0;
int32 his_layer = 0;
int32 resend_end_seq_no = -1; int32 resend_end_seq_no = -1;
@ -157,11 +158,12 @@ class SecretChatActor : public NetQueryCallback {
} }
template <class StorerT> template <class StorerT>
void store(StorerT &storer) const { 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_in_seq_no);
storer.store_int(my_out_seq_no); storer.store_int(my_out_seq_no);
storer.store_int(his_in_seq_no); storer.store_int(his_in_seq_no);
storer.store_int(resend_end_seq_no); storer.store_int(resend_end_seq_no);
storer.store_int(his_layer);
} }
template <class ParserT> template <class ParserT>
@ -171,7 +173,14 @@ class SecretChatActor : public NetQueryCallback {
my_out_seq_no = parser.fetch_int(); my_out_seq_no = parser.fetch_int();
his_in_seq_no = parser.fetch_int(); his_in_seq_no = parser.fetch_int();
resend_end_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 { struct ConfigState {
@ -516,7 +525,7 @@ class SecretChatActor : public NetQueryCallback {
bool seq_no_state_changed_ = false; bool seq_no_state_changed_ = false;
int32 last_binlog_message_id_ = -1; 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_his_in_seq_no_updated();
void on_seq_no_state_changed(); 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 my_out_seq_no = -1;
int32 his_in_seq_no = -1; int32 his_in_seq_no = -1;
int32 his_layer() const {
return decrypted_message_layer->layer_;
}
EncryptedFileLocation file; EncryptedFileLocation file;
bool has_encrypted_file; bool has_encrypted_file;
@ -292,6 +296,10 @@ class OutboundSecretMessage : public LogEventHelper<OutboundSecretMessage, Secre
int32 my_out_seq_no = -1; int32 my_out_seq_no = -1;
int32 his_in_seq_no = -1; int32 his_in_seq_no = -1;
int32 his_layer() const {
return -1;
}
bool is_sent = false; bool is_sent = false;
bool is_service = false; bool is_service = false;
bool is_rewritable = false; bool is_rewritable = false;