From 3765e69dbae27caa54e9c1fe5064cc287119bd79 Mon Sep 17 00:00:00 2001 From: vvaltman Date: Wed, 15 Oct 2014 00:20:03 +0400 Subject: [PATCH] Updated secret chats --- binlog.c | 32 +++++++++++++++++++++++++---- binlog.h | 1 + binlog.tl | 2 ++ queries.c | 8 ++++++++ structures.c | 58 ++++++++++++++++++++++++++++++++++++++-------------- tgl-layout.h | 1 + tgl.h | 2 +- 7 files changed, 84 insertions(+), 20 deletions(-) diff --git a/binlog.c b/binlog.c index 3a6e428..8b2c2ac 100644 --- a/binlog.c +++ b/binlog.c @@ -507,6 +507,15 @@ static int fetch_comb_binlog_encr_chat_set_key (void *extra) { return 0; } +static int fetch_comb_binlog_encr_chat_update_seq (void *extra) { + tgl_peer_id_t id = TGL_MK_ENCR_CHAT (fetch_int ()); + tgl_peer_t *_U = tgl_peer_get (id); + assert (_U); + _U->encr_chat.in_seq_no = fetch_int (); + _U->encr_chat.last_in_seq_no = fetch_int (); + return 0; +} + static int fetch_comb_binlog_encr_chat_init (void *extra) { tgl_peer_t *P = talloc0 (sizeof (*P)); P->id = TGL_MK_ENCR_CHAT (fetch_int ()); @@ -798,7 +807,7 @@ static int fetch_comb_binlog_send_message_text (void *extra) { M->to_id = tgl_set_peer_id (t, fetch_int ()); if (t == TGL_PEER_ENCR_CHAT) { tgl_peer_t *P = tgl_peer_get (M->to_id); - if (P) { + if (P && P->encr_chat.layer >= 17) { P->encr_chat.out_seq_no ++; } } @@ -847,7 +856,9 @@ static int fetch_comb_binlog_send_message_action_encr (void *extra) { tgl_peer_t *P = tgl_peer_get (M->to_id); if (P) { - P->encr_chat.out_seq_no ++; + if (P->encr_chat.layer >= 17) { + P->encr_chat.out_seq_no ++; + } } M->unread = 1; @@ -980,7 +991,9 @@ static int fetch_comb_binlog_create_message_media_encr_pending (void *extra) { tgl_peer_t *P = tgl_peer_get (M->to_id); if (P) { - P->encr_chat.out_seq_no ++; + if (P->encr_chat.layer >= 17) { + P->encr_chat.out_seq_no ++; + } } int l = prefetch_strlen (); @@ -1212,6 +1225,7 @@ static int fetch_comb_binlog_msg_seq_update (void *extra) { static int fetch_comb_binlog_msg_update (void *extra) { struct tgl_message *M = tgl_message_get (fetch_long ()); + if (!M) { return 0; } assert (M); if (!(M->flags & FLAG_ENCRYPTED)) { @@ -1297,6 +1311,7 @@ static void replay_log_event (void) { FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_state) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_accepted) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_set_key) + FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_update_seq) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_init) FETCH_COMBINATOR_FUNCTION (binlog_encr_chat_create) @@ -1732,7 +1747,7 @@ void bl_do_encr_chat_set_ttl (struct tgl_secret_chat *U, int ttl) { } void bl_do_encr_chat_set_layer (struct tgl_secret_chat *U, int layer) { - if (U->layer == layer) { return; } + if (U->layer >= layer) { return; } int *ev = alloc_log_event (12); ev[0] = CODE_binlog_encr_chat_set_layer; ev[1] = tgl_get_peer_id (U->id); @@ -1779,6 +1794,15 @@ void bl_do_encr_chat_set_key (struct tgl_secret_chat *E, unsigned char key[], lo add_log_event (ev, 272); } +void bl_do_encr_chat_update_seq (struct tgl_secret_chat *E, int in_seq_no, int out_seq_no) { + int *ev = alloc_log_event (16); + ev[0] = CODE_binlog_encr_chat_update_seq; + ev[1] = tgl_get_peer_id (E->id); + ev[2] = in_seq_no; + ev[3] = out_seq_no; + add_log_event (ev, 16); +} + void bl_do_set_dh_params (int root, unsigned char prime[], int version) { int *ev = alloc_log_event (268); ev[0] = CODE_binlog_set_dh_params; diff --git a/binlog.h b/binlog.h index dba71ce..9b200b3 100644 --- a/binlog.h +++ b/binlog.h @@ -51,6 +51,7 @@ void bl_do_encr_chat_set_layer (struct tgl_secret_chat *U, int layer); void bl_do_encr_chat_accepted (struct tgl_secret_chat *U, const unsigned char g_key[], const unsigned char nonce[], long long key_fingerprint); void bl_do_encr_chat_set_key (struct tgl_secret_chat *E, unsigned char key[], long long key_fingerprint); void bl_do_encr_chat_init (int id, int user_id, unsigned char random[], unsigned char g_a[]); +void bl_do_encr_chat_update_seq (struct tgl_secret_chat *E, int in_seq_no, int out_seq_no); void bl_do_dc_signed (int id); void bl_do_set_working_dc (int num); diff --git a/binlog.tl b/binlog.tl index 6de503f..37bb2c3 100644 --- a/binlog.tl +++ b/binlog.tl @@ -42,6 +42,8 @@ binlog.encrChatSetLayer id:int layer:int = binlog.Update; binlog.encrChatSetState id:int state:int = binlog.Update; binlog.encrChatSetKey id:int key:64*[int] fingerprint:long = binlog.Update; +binlog.encrChatUpdateSeq id:int in_seq_no:int out_seq_no:int = binlog.Update; + binlog.chatCreate id:int flags:int title:string user_num:int date:int version:int photo_big:%binlog.FileLocation photo_small:%binlog.FileLocation = binlog.Update; binlog.chatChangeFlags id:int set_flags:int clear_flags:int = binlog.Update; binlog.chatSetTitle id:int title:string = binlog.Update; diff --git a/queries.c b/queries.c index 7ee13ab..dbc7d60 100644 --- a/queries.c +++ b/queries.c @@ -895,6 +895,8 @@ void tgl_do_send_encr_msg_action (struct tgl_message *M, void (*callback)(void * if (P->encr_chat.layer <= 16) { out_int (CODE_decrypted_message_service_l16); } else { + out_int (CODE_decrypted_message_layer); + out_int (TGL_ENCRYPTED_LAYER); out_int (CODE_decrypted_message_service); } out_long (M->id); @@ -945,6 +947,8 @@ void tgl_do_send_encr_msg (struct tgl_message *M, void (*callback)(void *callbac if (P->encr_chat.layer <= 16) { out_int (CODE_decrypted_message_l16); } else { + out_int (CODE_decrypted_message_layer); + out_int (TGL_ENCRYPTED_LAYER); out_int (CODE_decrypted_message); } out_long (M->id); @@ -1690,6 +1694,8 @@ static void send_part (struct send_file *f, void *callback, void *callback_extra if (P->encr_chat.layer <= 16) { out_int (CODE_decrypted_message_l16); } else { + out_int (CODE_decrypted_message_layer); + out_int (TGL_ENCRYPTED_LAYER); out_int (CODE_decrypted_message); } out_long (r); @@ -2142,6 +2148,8 @@ void tgl_do_send_location(tgl_peer_id_t id, double latitude, double longitude, v if (P->encr_chat.layer <= 16) { out_int (CODE_decrypted_message_l16); } else { + out_int (CODE_decrypted_message_layer); + out_int (TGL_ENCRYPTED_LAYER); out_int (CODE_decrypted_message); } out_long (r); diff --git a/structures.c b/structures.c index 5f127fa..c4b933d 100644 --- a/structures.c +++ b/structures.c @@ -1223,6 +1223,9 @@ void tglf_fetch_encrypted_message (struct tgl_message *M) { int *start = 0; int *end = 0; x = 0; + int out_seq_no = -1; + int in_seq_no = -1; + int drop = 0; if (P && decrypt_encrypted_message (&P->encr_chat) >= 0 && new) { ok = 1; int *save_in_ptr = in_ptr; @@ -1234,30 +1237,44 @@ void tglf_fetch_encrypted_message (struct tgl_message *M) { if (x == CODE_decrypted_message_layer) { int layer = fetch_int (); assert (layer >= 0); + if (P && ((P->flags) & FLAG_CREATED)) { + bl_do_encr_chat_set_layer ((void *)P, layer); + } x = fetch_int (); } assert (x == CODE_decrypted_message || x == CODE_decrypted_message_service || x == CODE_decrypted_message_l16 || x == CODE_decrypted_message_service_l16); //assert (id == fetch_long ()); - fetch_long (); + long long new_id = fetch_long (); + if (P && P->encr_chat.layer >= 17) { + assert (new_id == id); + } ll = prefetch_strlen (); fetch_str (ll); // random_bytes if (x == CODE_decrypted_message || x == CODE_decrypted_message_service) { - int out_seq_no = fetch_int (); - int in_seq_no = fetch_int (); - if (in_seq_no / 2 <= P->encr_chat.in_seq_no) { + out_seq_no = fetch_int (); + in_seq_no = fetch_int (); + if (in_seq_no / 2 != P->encr_chat.in_seq_no + 1) { vlogprintf (E_WARNING, "Hole in seq in secret chat. in_seq_no = %d, expect_seq_no = %d\n", in_seq_no / 2, P->encr_chat.in_seq_no + 1); + drop = 1; } - if (in_seq_no / 2 > P->encr_chat.in_seq_no + 1) { - vlogprintf (E_WARNING, "Hole in seq in secret chat. in_seq_no = %d, expect_seq_no = %d\n", in_seq_no / 2, P->encr_chat.in_seq_no + 1); + if ((in_seq_no & 1) != 1 - (P->encr_chat.admin_id == tgl_state.our_id) || + (out_seq_no & 1) != (P->encr_chat.admin_id == tgl_state.our_id)) { + vlogprintf (E_WARNING, "Bad msg admin\n"); + drop = 1; + } + if (out_seq_no / 2 > P->encr_chat.out_seq_no) { + vlogprintf (E_WARNING, "In seq no is bigger than our's out seq no (out_seq_no = %d, our_out_seq_no = %d). Drop\n", out_seq_no / 2, P->encr_chat.out_seq_no); + drop = 1; + } + if (out_seq_no / 2 < P->encr_chat.last_in_seq_no) { + vlogprintf (E_WARNING, "Clients in_seq_no decreased (out_seq_no = %d, last_out_seq_no = %d). Drop\n", out_seq_no / 2, P->encr_chat.last_in_seq_no); + drop = 1; } //vlogprintf (E_WARNING, "in = %d, out = %d\n", in_seq_no, out_seq_no); - assert (out_seq_no / 2 <= P->encr_chat.out_seq_no); - P->encr_chat.in_seq_no = in_seq_no / 2; + //P->encr_chat.in_seq_no = in_seq_no / 2; if (x == CODE_decrypted_message) { fetch_int (); // ttl } - } else { - P->encr_chat.in_seq_no ++; } if (x == CODE_decrypted_message || x == CODE_decrypted_message_l16) { l = prefetch_strlen (); @@ -1281,19 +1298,30 @@ void tglf_fetch_encrypted_message (struct tgl_message *M) { int *start_file = in_ptr; assert (skip_type_any (TYPE_TO_PARAM (encrypted_file)) >= 0); if (x == CODE_decrypted_message || x == CODE_decrypted_message_l16) { - bl_do_create_message_media_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, l, s, start, end - start, start_file, in_ptr - start_file); + if (!drop) { + bl_do_create_message_media_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, l, s, start, end - start, start_file, in_ptr - start_file); + } } else if (x == CODE_decrypted_message_service || x == CODE_decrypted_message_service_l16) { - bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start); + if (!drop) { + bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start); + } } } else { - assert (skip_type_any (TYPE_TO_PARAM (encrypted_file)) >= 0); - M->media.type = CODE_message_media_empty; + if (!drop) { + assert (skip_type_any (TYPE_TO_PARAM (encrypted_file)) >= 0); + M->media.type = CODE_message_media_empty; + } } } else { if (ok && (x == CODE_decrypted_message_service || x == CODE_decrypted_message_service_l16)) { - bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start); + if (!drop) { + bl_do_create_message_service_encr (id, P->encr_chat.user_id, TGL_PEER_ENCR_CHAT, to_id, date, start, end - start); + } } } + if (!drop) { + bl_do_encr_chat_update_seq ((void *)P, in_seq_no / 2, out_seq_no / 2); + } } void tglf_fetch_encrypted_message_file (struct tgl_message_media *M) { diff --git a/tgl-layout.h b/tgl-layout.h index 22add66..089d1b1 100644 --- a/tgl-layout.h +++ b/tgl-layout.h @@ -306,6 +306,7 @@ struct tgl_secret_chat { int layer; int in_seq_no; int out_seq_no; + int last_in_seq_no; long long access_hash; unsigned char *g_key; unsigned char *nonce; diff --git a/tgl.h b/tgl.h index a1b4f79..57bfeca 100644 --- a/tgl.h +++ b/tgl.h @@ -39,7 +39,7 @@ #define TGL_BUILD "2234" #define TGL_VERSION "1.0.6" -#define TGL_ENCRYPTED_LAYER 17 +#define TGL_ENCRYPTED_LAYER 18 struct connection; struct mtproto_methods;