Added PFS support. Parallel auth_key generation. Small bug fixes
This commit is contained in:
parent
bc5a7e671c
commit
e179f25fe9
@ -1,2 +1,4 @@
|
|||||||
decryptedMessageMediaVideoL12#4cee6ef3 thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
decryptedMessageMediaVideoL12#4cee6ef3 thumb:bytes thumb_w:int thumb_h:int duration:int w:int h:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
||||||
decryptedMessageMediaAudioL12#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
decryptedMessageMediaAudioL12#6080758f duration:int size:int key:bytes iv:bytes = DecryptedMessageMedia;
|
||||||
|
|
||||||
|
auth.bindTempAuthKey perm_auth_key_id:long nonce:long expires_at:int encrypted_message:string = Bool;
|
||||||
|
27
loop.c
27
loop.c
@ -226,6 +226,16 @@ int is_authorized (void) {
|
|||||||
return tgl_authorized_dc (cur_a_dc);
|
return tgl_authorized_dc (cur_a_dc);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int all_authorized (void) {
|
||||||
|
int i;
|
||||||
|
for (i = 0; i <= tgl_state.max_dc_num; i++) if (tgl_state.DC_list[i]) {
|
||||||
|
if (!tgl_authorized_dc (tgl_state.DC_list[i])) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
int config_got;
|
int config_got;
|
||||||
|
|
||||||
int got_config (void) {
|
int got_config (void) {
|
||||||
@ -492,24 +502,11 @@ int loop (void) {
|
|||||||
#endif
|
#endif
|
||||||
update_prompt ();
|
update_prompt ();
|
||||||
|
|
||||||
if (!tgl_authorized_dc (tgl_state.DC_working)) {
|
net_loop (0, all_authorized);
|
||||||
cur_a_dc = tgl_state.DC_working;
|
|
||||||
tgl_dc_authorize (tgl_state.DC_working);
|
|
||||||
net_loop (0, is_authorized);
|
|
||||||
}
|
|
||||||
|
|
||||||
tgl_do_help_get_config (on_get_config, 0);
|
|
||||||
net_loop (0, got_config);
|
|
||||||
|
|
||||||
if (verbosity >= E_DEBUG) {
|
|
||||||
logprintf ("DC_info: %d new DC got\n", new_dc_num);
|
|
||||||
}
|
|
||||||
|
|
||||||
int i;
|
int i;
|
||||||
for (i = 0; i <= tgl_state.max_dc_num; i++) if (tgl_state.DC_list[i] && !tgl_authorized_dc (tgl_state.DC_list[i])) {
|
for (i = 0; i <= tgl_state.max_dc_num; i++) if (tgl_state.DC_list[i] && !tgl_authorized_dc (tgl_state.DC_list[i])) {
|
||||||
cur_a_dc = tgl_state.DC_list[i];
|
assert (0);
|
||||||
tgl_dc_authorize (cur_a_dc);
|
|
||||||
net_loop (0, is_authorized);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!tgl_signed_dc (tgl_state.DC_working)) {
|
if (!tgl_signed_dc (tgl_state.DC_working)) {
|
||||||
|
6
lua-tg.c
6
lua-tg.c
@ -477,6 +477,7 @@ enum lua_query_type {
|
|||||||
lq_load_document_thumb,
|
lq_load_document_thumb,
|
||||||
lq_delete_msg,
|
lq_delete_msg,
|
||||||
lq_restore_msg,
|
lq_restore_msg,
|
||||||
|
lq_accept_secret_chat
|
||||||
};
|
};
|
||||||
|
|
||||||
struct lua_query_extra {
|
struct lua_query_extra {
|
||||||
@ -1000,6 +1001,10 @@ void lua_do_all (void) {
|
|||||||
tgl_do_delete_msg ((long)lua_ptr[p + 1], lua_empty_cb, lua_ptr[p]);
|
tgl_do_delete_msg ((long)lua_ptr[p + 1], lua_empty_cb, lua_ptr[p]);
|
||||||
p += 2;
|
p += 2;
|
||||||
break;
|
break;
|
||||||
|
case lq_accept_secret_chat:
|
||||||
|
tgl_do_accept_encr_chat_request (lua_ptr[p + 1], lua_secret_chat_cb, lua_ptr[p]);
|
||||||
|
p += 2;
|
||||||
|
break;
|
||||||
/*
|
/*
|
||||||
lq_delete_msg,
|
lq_delete_msg,
|
||||||
lq_restore_msg,
|
lq_restore_msg,
|
||||||
@ -1076,6 +1081,7 @@ struct lua_function functions[] = {
|
|||||||
{"create_group_chat", lq_create_group_chat, { lfp_user, lfp_string, lfp_none }},
|
{"create_group_chat", lq_create_group_chat, { lfp_user, lfp_string, lfp_none }},
|
||||||
{"delete_msg", lq_delete_msg, { lfp_msg, lfp_none }},
|
{"delete_msg", lq_delete_msg, { lfp_msg, lfp_none }},
|
||||||
{"restore_msg", lq_restore_msg, { lfp_positive_number, lfp_none }},
|
{"restore_msg", lq_restore_msg, { lfp_positive_number, lfp_none }},
|
||||||
|
{"accept_secret_chat", lq_accept_secret_chat, { lfp_secret_chat, lfp_none }},
|
||||||
{ 0, 0, { lfp_none}}
|
{ 0, 0, { lfp_none}}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
9
main.c
9
main.c
@ -331,6 +331,13 @@ void parse_config (void) {
|
|||||||
strcpy (buf + l, "binlog_enabled");
|
strcpy (buf + l, "binlog_enabled");
|
||||||
config_lookup_bool (&conf, buf, &binlog_enabled);
|
config_lookup_bool (&conf, buf, &binlog_enabled);
|
||||||
|
|
||||||
|
int pfs_enabled;
|
||||||
|
strcpy (buf + l, "pfs_enabled");
|
||||||
|
config_lookup_bool (&conf, buf, &pfs_enabled);
|
||||||
|
if (pfs_enabled) {
|
||||||
|
tgl_enable_pfs ();
|
||||||
|
}
|
||||||
|
|
||||||
if (binlog_enabled) {
|
if (binlog_enabled) {
|
||||||
parse_config_val (&conf, &binlog_file_name, "binlog", BINLOG_FILE, config_directory);
|
parse_config_val (&conf, &binlog_file_name, "binlog", BINLOG_FILE, config_directory);
|
||||||
tgl_set_binlog_mode (1);
|
tgl_set_binlog_mode (1);
|
||||||
@ -534,7 +541,7 @@ int main (int argc, char **argv) {
|
|||||||
running_for_first_time ();
|
running_for_first_time ();
|
||||||
parse_config ();
|
parse_config ();
|
||||||
|
|
||||||
tgl_set_rsa_key ("/etc/ " PROG_NAME "/server.pub");
|
tgl_set_rsa_key ("/etc/" PROG_NAME "/server.pub");
|
||||||
tgl_set_rsa_key ("tg-server.pub");
|
tgl_set_rsa_key ("tg-server.pub");
|
||||||
|
|
||||||
|
|
||||||
|
328
mtproto-client.c
328
mtproto-client.c
@ -78,9 +78,6 @@
|
|||||||
//int verbosity;
|
//int verbosity;
|
||||||
static int auth_success;
|
static int auth_success;
|
||||||
//static enum tgl_dc_state c_state;
|
//static enum tgl_dc_state c_state;
|
||||||
static char nonce[256];
|
|
||||||
static char new_nonce[256];
|
|
||||||
static char server_nonce[256];
|
|
||||||
//extern int binlog_enabled;
|
//extern int binlog_enabled;
|
||||||
//extern int disable_auto_accept;
|
//extern int disable_auto_accept;
|
||||||
//extern int allow_weak_random;
|
//extern int allow_weak_random;
|
||||||
@ -122,7 +119,7 @@ static char Response[MAX_RESPONSE_SIZE];
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#define TG_SERVER_PUBKEY_FILENAME "tg-server.pub"
|
#define TG_SERVER_PUBKEY_FILENAME "tg-server.pub"
|
||||||
static char *rsa_public_key_name; // = TG_SERVER_PUBKEY_FILENAME;
|
//static char *rsa_public_key_name; // = TG_SERVER_PUBKEY_FILENAME;
|
||||||
static RSA *pubKey;
|
static RSA *pubKey;
|
||||||
static long long pk_fingerprint;
|
static long long pk_fingerprint;
|
||||||
|
|
||||||
@ -140,7 +137,7 @@ static int rsa_load_public_key (const char *public_key_name) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
vlogprintf (E_WARNING, "public key '%s' loaded successfully\n", rsa_public_key_name);
|
vlogprintf (E_WARNING, "public key '%s' loaded successfully\n", public_key_name);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -235,17 +232,32 @@ static int send_req_pq_packet (struct connection *c) {
|
|||||||
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
||||||
assert (D->state == st_init);
|
assert (D->state == st_init);
|
||||||
|
|
||||||
tglt_secure_random (nonce, 16);
|
tglt_secure_random (D->nonce, 16);
|
||||||
unenc_msg_header.out_msg_id = 0;
|
unenc_msg_header.out_msg_id = 0;
|
||||||
clear_packet ();
|
clear_packet ();
|
||||||
out_int (CODE_req_pq);
|
out_int (CODE_req_pq);
|
||||||
out_ints ((int *)nonce, 4);
|
out_ints ((int *)D->nonce, 4);
|
||||||
rpc_send_packet (c);
|
rpc_send_packet (c);
|
||||||
|
|
||||||
D->state = st_reqpq_sent;
|
D->state = st_reqpq_sent;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int send_req_pq_temp_packet (struct connection *c) {
|
||||||
|
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
||||||
|
assert (D->state == st_authorized);
|
||||||
|
|
||||||
|
tglt_secure_random (D->nonce, 16);
|
||||||
|
unenc_msg_header.out_msg_id = 0;
|
||||||
|
clear_packet ();
|
||||||
|
out_int (CODE_req_pq);
|
||||||
|
out_ints ((int *)D->nonce, 4);
|
||||||
|
rpc_send_packet (c);
|
||||||
|
|
||||||
|
D->state = st_reqpq_sent_temp;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned long long gcd (unsigned long long a, unsigned long long b) {
|
static unsigned long long gcd (unsigned long long a, unsigned long long b) {
|
||||||
return b ? gcd (b, a % b) : a;
|
return b ? gcd (b, a % b) : a;
|
||||||
@ -253,7 +265,8 @@ static unsigned long long gcd (unsigned long long a, unsigned long long b) {
|
|||||||
|
|
||||||
//typedef unsigned int uint128_t __attribute__ ((mode(TI)));
|
//typedef unsigned int uint128_t __attribute__ ((mode(TI)));
|
||||||
|
|
||||||
static int process_respq_answer (struct connection *c, char *packet, int len) {
|
static int process_respq_answer (struct connection *c, char *packet, int len, int temp_key) {
|
||||||
|
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
||||||
unsigned long long what;
|
unsigned long long what;
|
||||||
unsigned p1, p2;
|
unsigned p1, p2;
|
||||||
int i;
|
int i;
|
||||||
@ -263,8 +276,8 @@ static int process_respq_answer (struct connection *c, char *packet, int len) {
|
|||||||
assert (*(int *) (packet + 16) == len - 20);
|
assert (*(int *) (packet + 16) == len - 20);
|
||||||
assert (!(len & 3));
|
assert (!(len & 3));
|
||||||
assert (*(int *) (packet + 20) == CODE_resPQ);
|
assert (*(int *) (packet + 20) == CODE_resPQ);
|
||||||
assert (!memcmp (packet + 24, nonce, 16));
|
assert (!memcmp (packet + 24, D->nonce, 16));
|
||||||
memcpy (server_nonce, packet + 40, 16);
|
memcpy (D->server_nonce, packet + 40, 16);
|
||||||
char *from = packet + 56;
|
char *from = packet + 56;
|
||||||
int clen = *from++;
|
int clen = *from++;
|
||||||
assert (clen <= 8);
|
assert (clen <= 8);
|
||||||
@ -340,7 +353,7 @@ static int process_respq_answer (struct connection *c, char *packet, int len) {
|
|||||||
// create inner part (P_Q_inner_data)
|
// create inner part (P_Q_inner_data)
|
||||||
clear_packet ();
|
clear_packet ();
|
||||||
packet_ptr += 5;
|
packet_ptr += 5;
|
||||||
out_int (CODE_p_q_inner_data);
|
out_int (temp_key ? CODE_p_q_inner_data_temp : CODE_p_q_inner_data);
|
||||||
out_cstring (packet + 57, clen);
|
out_cstring (packet + 57, clen);
|
||||||
//out_int (0x0f01); // pq=15
|
//out_int (0x0f01); // pq=15
|
||||||
|
|
||||||
@ -372,18 +385,21 @@ static int process_respq_answer (struct connection *c, char *packet, int len) {
|
|||||||
|
|
||||||
//out_int (0x0301); // p=3
|
//out_int (0x0301); // p=3
|
||||||
//out_int (0x0501); // q=5
|
//out_int (0x0501); // q=5
|
||||||
out_ints ((int *) nonce, 4);
|
out_ints ((int *) D->nonce, 4);
|
||||||
out_ints ((int *) server_nonce, 4);
|
out_ints ((int *) D->server_nonce, 4);
|
||||||
tglt_secure_random (new_nonce, 32);
|
tglt_secure_random (D->new_nonce, 32);
|
||||||
out_ints ((int *) new_nonce, 8);
|
out_ints ((int *) D->new_nonce, 8);
|
||||||
|
if (temp_key) {
|
||||||
|
out_int (tgl_state.temp_key_expire_time);
|
||||||
|
}
|
||||||
sha1 ((unsigned char *) (packet_buffer + 5), (packet_ptr - packet_buffer - 5) * 4, (unsigned char *) packet_buffer);
|
sha1 ((unsigned char *) (packet_buffer + 5), (packet_ptr - packet_buffer - 5) * 4, (unsigned char *) packet_buffer);
|
||||||
|
|
||||||
int l = encrypt_packet_buffer ();
|
int l = encrypt_packet_buffer ();
|
||||||
|
|
||||||
clear_packet ();
|
clear_packet ();
|
||||||
out_int (CODE_req_DH_params);
|
out_int (CODE_req_DH_params);
|
||||||
out_ints ((int *) nonce, 4);
|
out_ints ((int *) D->nonce, 4);
|
||||||
out_ints ((int *) server_nonce, 4);
|
out_ints ((int *) D->server_nonce, 4);
|
||||||
//out_int (0x0301); // p=3
|
//out_int (0x0301); // p=3
|
||||||
//out_int (0x0501); // q=5
|
//out_int (0x0501); // q=5
|
||||||
if (p1 < 256) {
|
if (p1 < 256) {
|
||||||
@ -414,7 +430,7 @@ static int process_respq_answer (struct connection *c, char *packet, int len) {
|
|||||||
out_long (pk_fingerprint);
|
out_long (pk_fingerprint);
|
||||||
out_cstring ((char *) encrypt_buffer, l);
|
out_cstring ((char *) encrypt_buffer, l);
|
||||||
|
|
||||||
tgl_state.net_methods->get_dc (c)->state = st_reqdh_sent;
|
D->state = temp_key ? st_reqdh_sent_temp : st_reqdh_sent;
|
||||||
|
|
||||||
return rpc_send_packet (c);
|
return rpc_send_packet (c);
|
||||||
}
|
}
|
||||||
@ -515,7 +531,8 @@ int tglmp_check_g_bn (BIGNUM *p, BIGNUM *g) {
|
|||||||
return tglmp_check_g (s, g);
|
return tglmp_check_g (s, g);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int process_dh_answer (struct connection *c, char *packet, int len) {
|
static int process_dh_answer (struct connection *c, char *packet, int len, int temp_key) {
|
||||||
|
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
||||||
vlogprintf (E_DEBUG, "process_dh_answer(), len=%d\n", len);
|
vlogprintf (E_DEBUG, "process_dh_answer(), len=%d\n", len);
|
||||||
//if (len < 116) {
|
//if (len < 116) {
|
||||||
// vlogprintf (E_ERROR, "%u * %u = %llu", p1, p2, what);
|
// vlogprintf (E_ERROR, "%u * %u = %llu", p1, p2, what);
|
||||||
@ -525,9 +542,9 @@ static int process_dh_answer (struct connection *c, char *packet, int len) {
|
|||||||
assert (*(int *) (packet + 16) == len - 20);
|
assert (*(int *) (packet + 16) == len - 20);
|
||||||
assert (!(len & 3));
|
assert (!(len & 3));
|
||||||
assert (*(int *) (packet + 20) == (int)CODE_server_DH_params_ok);
|
assert (*(int *) (packet + 20) == (int)CODE_server_DH_params_ok);
|
||||||
assert (!memcmp (packet + 24, nonce, 16));
|
assert (!memcmp (packet + 24, D->nonce, 16));
|
||||||
assert (!memcmp (packet + 40, server_nonce, 16));
|
assert (!memcmp (packet + 40, D->server_nonce, 16));
|
||||||
tgl_init_aes_unauth (server_nonce, new_nonce, AES_DECRYPT);
|
tgl_init_aes_unauth (D->server_nonce, D->new_nonce, AES_DECRYPT);
|
||||||
in_ptr = (int *)(packet + 56);
|
in_ptr = (int *)(packet + 56);
|
||||||
in_end = (int *)(packet + len);
|
in_end = (int *)(packet + len);
|
||||||
int l = prefetch_strlen ();
|
int l = prefetch_strlen ();
|
||||||
@ -536,8 +553,8 @@ static int process_dh_answer (struct connection *c, char *packet, int len) {
|
|||||||
assert (in_ptr == in_end);
|
assert (in_ptr == in_end);
|
||||||
assert (l >= 60);
|
assert (l >= 60);
|
||||||
assert (decrypt_buffer[5] == (int)CODE_server_DH_inner_data);
|
assert (decrypt_buffer[5] == (int)CODE_server_DH_inner_data);
|
||||||
assert (!memcmp (decrypt_buffer + 6, nonce, 16));
|
assert (!memcmp (decrypt_buffer + 6, D->nonce, 16));
|
||||||
assert (!memcmp (decrypt_buffer + 10, server_nonce, 16));
|
assert (!memcmp (decrypt_buffer + 10, D->server_nonce, 16));
|
||||||
int g = decrypt_buffer[14];
|
int g = decrypt_buffer[14];
|
||||||
in_ptr = decrypt_buffer + 15;
|
in_ptr = decrypt_buffer + 15;
|
||||||
in_end = decrypt_buffer + (l >> 2);
|
in_end = decrypt_buffer + (l >> 2);
|
||||||
@ -556,7 +573,6 @@ static int process_dh_answer (struct connection *c, char *packet, int len) {
|
|||||||
assert (!memcmp (decrypt_buffer, sha1_buffer, 20));
|
assert (!memcmp (decrypt_buffer, sha1_buffer, 20));
|
||||||
assert ((char *) in_end - (char *) in_ptr < 16);
|
assert ((char *) in_end - (char *) in_ptr < 16);
|
||||||
|
|
||||||
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
|
||||||
D->server_time_delta = server_time - time (0);
|
D->server_time_delta = server_time - time (0);
|
||||||
D->server_time_udelta = server_time - get_utime (CLOCK_MONOTONIC);
|
D->server_time_udelta = server_time - get_utime (CLOCK_MONOTONIC);
|
||||||
//logprintf ( "server time is %d, delta = %d\n", server_time, server_time_delta);
|
//logprintf ( "server time is %d, delta = %d\n", server_time, server_time_delta);
|
||||||
@ -565,8 +581,8 @@ static int process_dh_answer (struct connection *c, char *packet, int len) {
|
|||||||
clear_packet ();
|
clear_packet ();
|
||||||
packet_ptr += 5;
|
packet_ptr += 5;
|
||||||
out_int (CODE_client_DH_inner_data);
|
out_int (CODE_client_DH_inner_data);
|
||||||
out_ints ((int *) nonce, 4);
|
out_ints ((int *) D->nonce, 4);
|
||||||
out_ints ((int *) server_nonce, 4);
|
out_ints ((int *) D->server_nonce, 4);
|
||||||
out_long (0LL);
|
out_long (0LL);
|
||||||
|
|
||||||
BN_init (&dh_g);
|
BN_init (&dh_g);
|
||||||
@ -586,8 +602,8 @@ static int process_dh_answer (struct connection *c, char *packet, int len) {
|
|||||||
ensure (BN_mod_exp (&auth_key_num, &g_a, dh_power, &dh_prime, tgl_state.BN_ctx));
|
ensure (BN_mod_exp (&auth_key_num, &g_a, dh_power, &dh_prime, tgl_state.BN_ctx));
|
||||||
l = BN_num_bytes (&auth_key_num);
|
l = BN_num_bytes (&auth_key_num);
|
||||||
assert (l >= 250 && l <= 256);
|
assert (l >= 250 && l <= 256);
|
||||||
assert (BN_bn2bin (&auth_key_num, (unsigned char *)D->auth_key));
|
assert (BN_bn2bin (&auth_key_num, (unsigned char *)(temp_key ? D->temp_auth_key : D->auth_key)));
|
||||||
memset (D->auth_key + l, 0, 256 - l);
|
memset (temp_key ? D->temp_auth_key + l : D->auth_key + l, 0, 256 - l);
|
||||||
BN_free (dh_power);
|
BN_free (dh_power);
|
||||||
BN_free (&auth_key_num);
|
BN_free (&auth_key_num);
|
||||||
BN_free (&dh_g);
|
BN_free (&dh_g);
|
||||||
@ -600,53 +616,103 @@ static int process_dh_answer (struct connection *c, char *packet, int len) {
|
|||||||
|
|
||||||
//hexdump ((char *)packet_buffer, (char *)packet_ptr);
|
//hexdump ((char *)packet_buffer, (char *)packet_ptr);
|
||||||
|
|
||||||
l = encrypt_packet_buffer_aes_unauth (server_nonce, new_nonce);
|
l = encrypt_packet_buffer_aes_unauth (D->server_nonce, D->new_nonce);
|
||||||
|
|
||||||
clear_packet ();
|
clear_packet ();
|
||||||
out_int (CODE_set_client_DH_params);
|
out_int (CODE_set_client_DH_params);
|
||||||
out_ints ((int *) nonce, 4);
|
out_ints ((int *) D->nonce, 4);
|
||||||
out_ints ((int *) server_nonce, 4);
|
out_ints ((int *) D->server_nonce, 4);
|
||||||
out_cstring ((char *) encrypt_buffer, l);
|
out_cstring ((char *) encrypt_buffer, l);
|
||||||
|
|
||||||
tgl_state.net_methods->get_dc (c)->state = st_client_dh_sent;
|
D->state = temp_key ? st_client_dh_sent_temp : st_client_dh_sent;;
|
||||||
|
|
||||||
return rpc_send_packet (c);
|
return rpc_send_packet (c);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void create_temp_auth_key (struct connection *c) {
|
||||||
|
send_req_pq_temp_packet (c);
|
||||||
|
}
|
||||||
|
|
||||||
static int process_auth_complete (struct connection *c UU, char *packet, int len) {
|
int tglmp_encrypt_inner_temp (struct connection *c, int *msg, int msg_ints, int useful, void *data, long long msg_id);
|
||||||
|
static long long generate_next_msg_id (struct tgl_dc *DC);
|
||||||
|
static long long msg_id_override;
|
||||||
|
static void mpc_on_get_config (void *extra, int success);
|
||||||
|
static int process_auth_complete (struct connection *c UU, char *packet, int len, int temp_key) {
|
||||||
|
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
||||||
vlogprintf (E_DEBUG, "process_dh_answer(), len=%d\n", len);
|
vlogprintf (E_DEBUG, "process_dh_answer(), len=%d\n", len);
|
||||||
assert (len == 72);
|
assert (len == 72);
|
||||||
assert (!*(long long *) packet);
|
assert (!*(long long *) packet);
|
||||||
assert (*(int *) (packet + 16) == len - 20);
|
assert (*(int *) (packet + 16) == len - 20);
|
||||||
assert (!(len & 3));
|
assert (!(len & 3));
|
||||||
assert (*(int *) (packet + 20) == CODE_dh_gen_ok);
|
assert (*(int *) (packet + 20) == CODE_dh_gen_ok);
|
||||||
assert (!memcmp (packet + 24, nonce, 16));
|
assert (!memcmp (packet + 24, D->nonce, 16));
|
||||||
assert (!memcmp (packet + 40, server_nonce, 16));
|
assert (!memcmp (packet + 40, D->server_nonce, 16));
|
||||||
static unsigned char tmp[44], sha1_buffer[20];
|
static unsigned char tmp[44], sha1_buffer[20];
|
||||||
memcpy (tmp, new_nonce, 32);
|
memcpy (tmp, D->new_nonce, 32);
|
||||||
tmp[32] = 1;
|
tmp[32] = 1;
|
||||||
//GET_DC(c)->auth_key_id = *(long long *)(sha1_buffer + 12);
|
//GET_DC(c)->auth_key_id = *(long long *)(sha1_buffer + 12);
|
||||||
|
|
||||||
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
if (!temp_key) {
|
||||||
bl_do_set_auth_key_id (D->id, (unsigned char *)D->auth_key);
|
bl_do_set_auth_key_id (D->id, (unsigned char *)D->auth_key);
|
||||||
sha1 ((unsigned char *)D->auth_key, 256, sha1_buffer);
|
sha1 ((unsigned char *)D->auth_key, 256, sha1_buffer);
|
||||||
|
} else {
|
||||||
|
sha1 ((unsigned char *)D->temp_auth_key, 256, sha1_buffer);
|
||||||
|
D->temp_auth_key_id = *(long long *)(sha1_buffer + 12);
|
||||||
|
}
|
||||||
|
|
||||||
memcpy (tmp + 33, sha1_buffer, 8);
|
memcpy (tmp + 33, sha1_buffer, 8);
|
||||||
sha1 (tmp, 41, sha1_buffer);
|
sha1 (tmp, 41, sha1_buffer);
|
||||||
assert (!memcmp (packet + 56, sha1_buffer + 4, 16));
|
assert (!memcmp (packet + 56, sha1_buffer + 4, 16));
|
||||||
D->server_salt = *(long long *)server_nonce ^ *(long long *)new_nonce;
|
D->server_salt = *(long long *)D->server_nonce ^ *(long long *)D->new_nonce;
|
||||||
|
|
||||||
//kprintf ("OK\n");
|
//kprintf ("OK\n");
|
||||||
|
|
||||||
//c->status = conn_error;
|
//c->status = conn_error;
|
||||||
//sleep (1);
|
//sleep (1);
|
||||||
|
|
||||||
tgl_state.net_methods->get_dc (c)->state = st_authorized;
|
D->state = st_authorized;
|
||||||
//return 1;
|
//return 1;
|
||||||
vlogprintf (E_DEBUG, "Auth success\n");
|
vlogprintf (E_DEBUG, "Auth success\n");
|
||||||
auth_success ++;
|
auth_success ++;
|
||||||
|
if (temp_key) {
|
||||||
|
//D->flags |= 2;
|
||||||
|
|
||||||
|
long long msg_id = generate_next_msg_id (D);
|
||||||
|
clear_packet ();
|
||||||
|
out_int (CODE_bind_auth_key_inner);
|
||||||
|
long long rand;
|
||||||
|
tglt_secure_random (&rand, 8);
|
||||||
|
out_long (rand);
|
||||||
|
out_long (D->temp_auth_key_id);
|
||||||
|
out_long (D->auth_key_id);
|
||||||
|
|
||||||
|
struct tgl_session *S = tgl_state.net_methods->get_session (c);
|
||||||
|
if (!S->session_id) {
|
||||||
|
tglt_secure_random (&S->session_id, 8);
|
||||||
|
}
|
||||||
|
out_long (S->session_id);
|
||||||
|
int expires = time (0) + D->server_time_delta + tgl_state.temp_key_expire_time;
|
||||||
|
out_int (expires);
|
||||||
|
|
||||||
|
static int data[1000];
|
||||||
|
int len = tglmp_encrypt_inner_temp (c, packet_buffer, packet_ptr - packet_buffer, 0, data, msg_id);
|
||||||
|
msg_id_override = msg_id;
|
||||||
|
tgl_do_send_bind_temp_key (D, rand, expires, (void *)data, len, msg_id);
|
||||||
|
msg_id_override = 0;
|
||||||
|
} else {
|
||||||
D->flags |= 1;
|
D->flags |= 1;
|
||||||
|
if (tgl_state.enable_pfs) {
|
||||||
|
create_temp_auth_key (c);
|
||||||
|
} else {
|
||||||
|
D->temp_auth_key_id = D->auth_key_id;
|
||||||
|
memcpy (D->temp_auth_key, D->auth_key, 256);
|
||||||
|
D->flags |= 2;
|
||||||
|
if (!(D->flags & 4)) {
|
||||||
|
tgl_do_help_get_config_dc (D, mpc_on_get_config, D);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//write_auth_file ();
|
//write_auth_file ();
|
||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
@ -681,8 +747,11 @@ static long long generate_next_msg_id (struct tgl_dc *DC) {
|
|||||||
|
|
||||||
static void init_enc_msg (struct tgl_session *S, int useful) {
|
static void init_enc_msg (struct tgl_session *S, int useful) {
|
||||||
struct tgl_dc *DC = S->dc;
|
struct tgl_dc *DC = S->dc;
|
||||||
assert (DC->auth_key_id);
|
assert (DC->state == st_authorized);
|
||||||
enc_msg.auth_key_id = DC->auth_key_id;
|
//assert (DC->flags & 2);
|
||||||
|
assert (DC->temp_auth_key_id);
|
||||||
|
vlogprintf (E_DEBUG, "temp_auth_key_id = 0x%016llx, auth_key_id = 0x%016llx\n", DC->temp_auth_key_id, DC->auth_key_id);
|
||||||
|
enc_msg.auth_key_id = DC->temp_auth_key_id;
|
||||||
// assert (DC->server_salt);
|
// assert (DC->server_salt);
|
||||||
enc_msg.server_salt = DC->server_salt;
|
enc_msg.server_salt = DC->server_salt;
|
||||||
if (!S->session_id) {
|
if (!S->session_id) {
|
||||||
@ -690,7 +759,7 @@ static void init_enc_msg (struct tgl_session *S, int useful) {
|
|||||||
}
|
}
|
||||||
enc_msg.session_id = S->session_id;
|
enc_msg.session_id = S->session_id;
|
||||||
//enc_msg.auth_key_id2 = auth_key_id;
|
//enc_msg.auth_key_id2 = auth_key_id;
|
||||||
enc_msg.msg_id = generate_next_msg_id (DC);
|
enc_msg.msg_id = msg_id_override ? msg_id_override : generate_next_msg_id (DC);
|
||||||
//enc_msg.msg_id -= 0x10000000LL * (lrand48 () & 15);
|
//enc_msg.msg_id -= 0x10000000LL * (lrand48 () & 15);
|
||||||
//kprintf ("message id %016llx\n", enc_msg.msg_id);
|
//kprintf ("message id %016llx\n", enc_msg.msg_id);
|
||||||
enc_msg.seq_no = S->seq_no;
|
enc_msg.seq_no = S->seq_no;
|
||||||
@ -700,7 +769,16 @@ static void init_enc_msg (struct tgl_session *S, int useful) {
|
|||||||
S->seq_no += 2;
|
S->seq_no += 2;
|
||||||
};
|
};
|
||||||
|
|
||||||
static int aes_encrypt_message (struct tgl_dc *DC, struct encrypted_message *enc) {
|
static void init_enc_msg_inner_temp (struct tgl_dc *DC, long long msg_id) {
|
||||||
|
enc_msg.auth_key_id = DC->auth_key_id;
|
||||||
|
tglt_secure_random (&enc_msg.server_salt, 8);
|
||||||
|
tglt_secure_random (&enc_msg.session_id, 8);
|
||||||
|
enc_msg.msg_id = msg_id;
|
||||||
|
enc_msg.seq_no = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static int aes_encrypt_message (char *key, struct encrypted_message *enc) {
|
||||||
unsigned char sha1_buffer[20];
|
unsigned char sha1_buffer[20];
|
||||||
const int MINSZ = offsetof (struct encrypted_message, message);
|
const int MINSZ = offsetof (struct encrypted_message, message);
|
||||||
const int UNENCSZ = offsetof (struct encrypted_message, server_salt);
|
const int UNENCSZ = offsetof (struct encrypted_message, server_salt);
|
||||||
@ -710,13 +788,16 @@ static int aes_encrypt_message (struct tgl_dc *DC, struct encrypted_message *enc
|
|||||||
//printf ("enc_len is %d\n", enc_len);
|
//printf ("enc_len is %d\n", enc_len);
|
||||||
vlogprintf (E_DEBUG, "sending message with sha1 %08x\n", *(int *)sha1_buffer);
|
vlogprintf (E_DEBUG, "sending message with sha1 %08x\n", *(int *)sha1_buffer);
|
||||||
memcpy (enc->msg_key, sha1_buffer + 4, 16);
|
memcpy (enc->msg_key, sha1_buffer + 4, 16);
|
||||||
tgl_init_aes_auth (DC->auth_key, enc->msg_key, AES_ENCRYPT);
|
tgl_init_aes_auth (key, enc->msg_key, AES_ENCRYPT);
|
||||||
//hexdump ((char *)enc, (char *)enc + enc_len + 24);
|
//hexdump ((char *)enc, (char *)enc + enc_len + 24);
|
||||||
return tgl_pad_aes_encrypt ((char *) &enc->server_salt, enc_len, (char *) &enc->server_salt, MAX_MESSAGE_INTS * 4 + (MINSZ - UNENCSZ));
|
return tgl_pad_aes_encrypt ((char *) &enc->server_salt, enc_len, (char *) &enc->server_salt, MAX_MESSAGE_INTS * 4 + (MINSZ - UNENCSZ));
|
||||||
}
|
}
|
||||||
|
|
||||||
long long tglmp_encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful) {
|
long long tglmp_encrypt_send_message (struct connection *c, int *msg, int msg_ints, int flags) {
|
||||||
struct tgl_dc *DC = tgl_state.net_methods->get_dc (c);
|
struct tgl_dc *DC = tgl_state.net_methods->get_dc (c);
|
||||||
|
if (!(DC->flags & 4) && !(flags & 2)) {
|
||||||
|
return generate_next_msg_id (DC);
|
||||||
|
}
|
||||||
struct tgl_session *S = tgl_state.net_methods->get_session (c);
|
struct tgl_session *S = tgl_state.net_methods->get_session (c);
|
||||||
assert (S);
|
assert (S);
|
||||||
|
|
||||||
@ -732,17 +813,41 @@ long long tglmp_encrypt_send_message (struct connection *c, int *msg, int msg_in
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
init_enc_msg (S, useful);
|
init_enc_msg (S, flags & 1);
|
||||||
|
|
||||||
//hexdump ((char *)msg, (char *)msg + (msg_ints * 4));
|
//hexdump ((char *)msg, (char *)msg + (msg_ints * 4));
|
||||||
int l = aes_encrypt_message (DC, &enc_msg);
|
int l = aes_encrypt_message (DC->temp_auth_key, &enc_msg);
|
||||||
//hexdump ((char *)&enc_msg, (char *)&enc_msg + l + 24);
|
//hexdump ((char *)&enc_msg, (char *)&enc_msg + l + 24);
|
||||||
assert (l > 0);
|
assert (l > 0);
|
||||||
|
vlogprintf (E_DEBUG, "Sending message to DC%d: %s:%d with key_id=%lld\n", DC->id, DC->ip, DC->port, enc_msg.auth_key_id);
|
||||||
rpc_send_message (c, &enc_msg, l + UNENCSZ);
|
rpc_send_message (c, &enc_msg, l + UNENCSZ);
|
||||||
|
|
||||||
|
|
||||||
return client_last_msg_id;
|
return client_last_msg_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int tglmp_encrypt_inner_temp (struct connection *c, int *msg, int msg_ints, int useful, void *data, long long msg_id) {
|
||||||
|
struct tgl_dc *DC = tgl_state.net_methods->get_dc (c);
|
||||||
|
struct tgl_session *S = tgl_state.net_methods->get_session (c);
|
||||||
|
assert (S);
|
||||||
|
|
||||||
|
const int UNENCSZ = offsetof (struct encrypted_message, server_salt);
|
||||||
|
if (msg_ints <= 0 || msg_ints > MAX_MESSAGE_INTS - 4) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
memcpy (enc_msg.message, msg, msg_ints * 4);
|
||||||
|
enc_msg.msg_len = msg_ints * 4;
|
||||||
|
|
||||||
|
init_enc_msg_inner_temp (DC, msg_id);
|
||||||
|
|
||||||
|
int l = aes_encrypt_message (DC->auth_key, &enc_msg);
|
||||||
|
assert (l > 0);
|
||||||
|
//rpc_send_message (c, &enc_msg, l + UNENCSZ);
|
||||||
|
memcpy (data, &enc_msg, l + UNENCSZ);
|
||||||
|
|
||||||
|
return l + UNENCSZ;
|
||||||
|
}
|
||||||
|
|
||||||
static int good_messages;
|
static int good_messages;
|
||||||
|
|
||||||
static void rpc_execute_answer (struct connection *c, long long msg_id UU);
|
static void rpc_execute_answer (struct connection *c, long long msg_id UU);
|
||||||
@ -930,9 +1035,19 @@ static int process_rpc_message (struct connection *c UU, struct encrypted_messag
|
|||||||
vlogprintf (E_DEBUG, "process_rpc_message(), len=%d\n", len);
|
vlogprintf (E_DEBUG, "process_rpc_message(), len=%d\n", len);
|
||||||
assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15));
|
assert (len >= MINSZ && (len & 15) == (UNENCSZ & 15));
|
||||||
struct tgl_dc *DC = tgl_state.net_methods->get_dc (c);
|
struct tgl_dc *DC = tgl_state.net_methods->get_dc (c);
|
||||||
|
if (enc->auth_key_id != DC->temp_auth_key_id && enc->auth_key_id != DC->auth_key_id) {
|
||||||
|
vlogprintf (E_ERROR, "received msg from dc %d with auth_key_id %lld (perm_auth_key_id %lld temp_auth_key_id %lld)\n",
|
||||||
|
DC->id, enc->auth_key_id, DC->auth_key_id, DC->temp_auth_key_id);
|
||||||
|
}
|
||||||
|
if (enc->auth_key_id == DC->temp_auth_key_id) {
|
||||||
|
assert (enc->auth_key_id == DC->temp_auth_key_id);
|
||||||
|
assert (DC->temp_auth_key_id);
|
||||||
|
tgl_init_aes_auth (DC->temp_auth_key + 8, enc->msg_key, AES_DECRYPT);
|
||||||
|
} else {
|
||||||
assert (enc->auth_key_id == DC->auth_key_id);
|
assert (enc->auth_key_id == DC->auth_key_id);
|
||||||
assert (DC->auth_key_id);
|
assert (DC->auth_key_id);
|
||||||
tgl_init_aes_auth (DC->auth_key + 8, enc->msg_key, AES_DECRYPT);
|
tgl_init_aes_auth (DC->auth_key + 8, enc->msg_key, AES_DECRYPT);
|
||||||
|
}
|
||||||
int l = tgl_pad_aes_decrypt ((char *)&enc->server_salt, len - UNENCSZ, (char *)&enc->server_salt, len - UNENCSZ);
|
int l = tgl_pad_aes_decrypt ((char *)&enc->server_salt, len - UNENCSZ, (char *)&enc->server_salt, len - UNENCSZ);
|
||||||
assert (l == len - UNENCSZ);
|
assert (l == len - UNENCSZ);
|
||||||
//assert (enc->auth_key_id2 == enc->auth_key_id);
|
//assert (enc->auth_key_id2 == enc->auth_key_id);
|
||||||
@ -946,6 +1061,7 @@ static int process_rpc_message (struct connection *c UU, struct encrypted_messag
|
|||||||
//write_auth_file ();
|
//write_auth_file ();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int this_server_time = enc->msg_id >> 32LL;
|
int this_server_time = enc->msg_id >> 32LL;
|
||||||
if (!DC->server_time_delta) {
|
if (!DC->server_time_delta) {
|
||||||
DC->server_time_delta = this_server_time - get_utime (CLOCK_REALTIME);
|
DC->server_time_delta = this_server_time - get_utime (CLOCK_REALTIME);
|
||||||
@ -973,6 +1089,20 @@ static int process_rpc_message (struct connection *c UU, struct encrypted_messag
|
|||||||
in_ptr = enc->message;
|
in_ptr = enc->message;
|
||||||
in_end = in_ptr + (enc->msg_len / 4);
|
in_end = in_ptr + (enc->msg_len / 4);
|
||||||
|
|
||||||
|
/*{
|
||||||
|
assert (len <= 10000);
|
||||||
|
static char s[1 << 20];
|
||||||
|
int p = 0;
|
||||||
|
int i;
|
||||||
|
//static int buf[10000];
|
||||||
|
//assert (tgl_state.net_methods->read_in_lookup (c, buf, len) == len);
|
||||||
|
|
||||||
|
for (i = 0; i < in_end - in_ptr; i++) {
|
||||||
|
p += sprintf (s + p, "%08x ", *(int *)(in_ptr + i));
|
||||||
|
}
|
||||||
|
vlogprintf (E_DEBUG, "%s\n", s);
|
||||||
|
}*/
|
||||||
|
|
||||||
struct tgl_session *S = tgl_state.net_methods->get_session (c);
|
struct tgl_session *S = tgl_state.net_methods->get_session (c);
|
||||||
if (enc->msg_id & 1) {
|
if (enc->msg_id & 1) {
|
||||||
tgln_insert_msg_id (S, enc->msg_id);
|
tgln_insert_msg_id (S, enc->msg_id);
|
||||||
@ -985,8 +1115,23 @@ static int process_rpc_message (struct connection *c UU, struct encrypted_messag
|
|||||||
|
|
||||||
|
|
||||||
static int rpc_execute (struct connection *c, int op, int len) {
|
static int rpc_execute (struct connection *c, int op, int len) {
|
||||||
vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d : received rpc answer %d with %d content bytes\n", tgl_state.net_methods->get_dc(c)->id, op, len);
|
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
||||||
/* if (op < 0) {
|
vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d (%s:%d) : received rpc answer %d with %d content bytes\n", D->id, D->ip, D->port, op, len);
|
||||||
|
|
||||||
|
/*{
|
||||||
|
assert (len <= 10000);
|
||||||
|
static char s[1 << 20];
|
||||||
|
int p = 0;
|
||||||
|
int i;
|
||||||
|
static int buf[10000];
|
||||||
|
assert (tgl_state.net_methods->read_in_lookup (c, buf, len) == len);
|
||||||
|
|
||||||
|
for (i = 0; i < len / 4; i++) {
|
||||||
|
p += sprintf (s + p, "%08x ", *(int *)(buf + i));
|
||||||
|
}
|
||||||
|
vlogprintf (E_DEBUG, "%s\n", s);
|
||||||
|
}*/
|
||||||
|
/* if (op < 0) {
|
||||||
assert (tgl_state.net_methods->read_in (c, Response, Response_len) == Response_len);
|
assert (tgl_state.net_methods->read_in (c, Response, Response_len) == Response_len);
|
||||||
return 0;
|
return 0;
|
||||||
}*/
|
}*/
|
||||||
@ -1005,27 +1150,26 @@ static int rpc_execute (struct connection *c, int op, int len) {
|
|||||||
#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__)
|
#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__)
|
||||||
// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
||||||
#endif
|
#endif
|
||||||
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
|
||||||
int o = D->state;
|
int o = D->state;
|
||||||
if (D->flags & 1) { o = st_authorized;}
|
//if (D->flags & 1) { o = st_authorized;}
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case st_reqpq_sent:
|
case st_reqpq_sent:
|
||||||
process_respq_answer (c, Response/* + 8*/, Response_len/* - 12*/);
|
process_respq_answer (c, Response/* + 8*/, Response_len/* - 12*/, 0);
|
||||||
#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__)
|
|
||||||
// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
case st_reqdh_sent:
|
case st_reqdh_sent:
|
||||||
process_dh_answer (c, Response/* + 8*/, Response_len/* - 12*/);
|
process_dh_answer (c, Response/* + 8*/, Response_len/* - 12*/, 0);
|
||||||
#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__)
|
|
||||||
// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
case st_client_dh_sent:
|
case st_client_dh_sent:
|
||||||
process_auth_complete (c, Response/* + 8*/, Response_len/* - 12*/);
|
process_auth_complete (c, Response/* + 8*/, Response_len/* - 12*/, 0);
|
||||||
#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__)
|
return 0;
|
||||||
// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
case st_reqpq_sent_temp:
|
||||||
#endif
|
process_respq_answer (c, Response/* + 8*/, Response_len/* - 12*/, 1);
|
||||||
|
return 0;
|
||||||
|
case st_reqdh_sent_temp:
|
||||||
|
process_dh_answer (c, Response/* + 8*/, Response_len/* - 12*/, 1);
|
||||||
|
return 0;
|
||||||
|
case st_client_dh_sent_temp:
|
||||||
|
process_auth_complete (c, Response/* + 8*/, Response_len/* - 12*/, 1);
|
||||||
return 0;
|
return 0;
|
||||||
case st_authorized:
|
case st_authorized:
|
||||||
if (op < 0 && op >= -999) {
|
if (op < 0 && op >= -999) {
|
||||||
@ -1033,9 +1177,6 @@ static int rpc_execute (struct connection *c, int op, int len) {
|
|||||||
} else {
|
} else {
|
||||||
process_rpc_message (c, (void *)(Response/* + 8*/), Response_len/* - 12*/);
|
process_rpc_message (c, (void *)(Response/* + 8*/), Response_len/* - 12*/);
|
||||||
}
|
}
|
||||||
#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__)
|
|
||||||
// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
|
||||||
#endif
|
|
||||||
return 0;
|
return 0;
|
||||||
default:
|
default:
|
||||||
vlogprintf (E_ERROR, "fatal: cannot receive answer in state %d\n", D->state);
|
vlogprintf (E_ERROR, "fatal: cannot receive answer in state %d\n", D->state);
|
||||||
@ -1051,23 +1192,37 @@ static int tc_close (struct connection *c, int who) {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void mpc_on_get_config (void *extra, int success) {
|
||||||
|
assert (success);
|
||||||
|
struct tgl_dc *D = extra;
|
||||||
|
D->flags |= 4;
|
||||||
|
}
|
||||||
|
|
||||||
static int tc_becomes_ready (struct connection *c) {
|
static int tc_becomes_ready (struct connection *c) {
|
||||||
vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d becomed ready\n", tgl_state.net_methods->get_dc(c)->id);
|
vlogprintf (E_DEBUG, "outbound rpc connection from dc #%d becomed ready\n", tgl_state.net_methods->get_dc(c)->id);
|
||||||
//char byte = 0xef;
|
//char byte = 0xef;
|
||||||
//assert (tgl_state.net_methods->write_out (c, &byte, 1) == 1);
|
//assert (tgl_state.net_methods->write_out (c, &byte, 1) == 1);
|
||||||
//tgl_state.net_methods->flush_out (c);
|
//tgl_state.net_methods->flush_out (c);
|
||||||
|
|
||||||
#if !defined(__MACH__) && !defined(__FreeBSD__) && !defined(__OpenBSD__) && !defined (__CYGWIN__)
|
|
||||||
// setsockopt (c->fd, IPPROTO_TCP, TCP_QUICKACK, (int[]){0}, 4);
|
|
||||||
#endif
|
|
||||||
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
struct tgl_dc *D = tgl_state.net_methods->get_dc (c);
|
||||||
|
if (D->flags & 1) { D->state = st_authorized; }
|
||||||
int o = D->state;
|
int o = D->state;
|
||||||
if (D->flags & 1) { o = st_authorized; }
|
if (o == st_authorized && !tgl_state.enable_pfs) {
|
||||||
|
D->temp_auth_key_id = D->auth_key_id;
|
||||||
|
memcpy (D->temp_auth_key, D->auth_key, 256);
|
||||||
|
D->flags |= 2;
|
||||||
|
}
|
||||||
switch (o) {
|
switch (o) {
|
||||||
case st_init:
|
case st_init:
|
||||||
send_req_pq_packet (c);
|
send_req_pq_packet (c);
|
||||||
break;
|
break;
|
||||||
case st_authorized:
|
case st_authorized:
|
||||||
|
if (!(D->flags & 2)) {
|
||||||
|
assert (!D->temp_auth_key_id);
|
||||||
|
create_temp_auth_key (c);
|
||||||
|
} else if (!(D->flags & 4)) {
|
||||||
|
tgl_do_help_get_config_dc (D, mpc_on_get_config, D);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
vlogprintf (E_DEBUG, "c_state = %d\n", D->state);
|
vlogprintf (E_DEBUG, "c_state = %d\n", D->state);
|
||||||
@ -1158,6 +1313,11 @@ void tgln_insert_msg_id (struct tgl_session *S, long long id) {
|
|||||||
|
|
||||||
//extern struct tgl_dc *DC_list[];
|
//extern struct tgl_dc *DC_list[];
|
||||||
|
|
||||||
|
|
||||||
|
static void regen_temp_key_gw (evutil_socket_t fd, short what, void *arg) {
|
||||||
|
tglmp_regenerate_temp_auth_key (arg);
|
||||||
|
}
|
||||||
|
|
||||||
struct tgl_dc *tglmp_alloc_dc (int id, char *ip, int port UU) {
|
struct tgl_dc *tglmp_alloc_dc (int id, char *ip, int port UU) {
|
||||||
assert (!tgl_state.DC_list[id]);
|
assert (!tgl_state.DC_list[id]);
|
||||||
struct tgl_dc *DC = talloc0 (sizeof (*DC));
|
struct tgl_dc *DC = talloc0 (sizeof (*DC));
|
||||||
@ -1168,6 +1328,9 @@ struct tgl_dc *tglmp_alloc_dc (int id, char *ip, int port UU) {
|
|||||||
if (id > tgl_state.max_dc_num) {
|
if (id > tgl_state.max_dc_num) {
|
||||||
tgl_state.max_dc_num = id;
|
tgl_state.max_dc_num = id;
|
||||||
}
|
}
|
||||||
|
DC->ev = evtimer_new (tgl_state.ev_base, regen_temp_key_gw, DC);
|
||||||
|
static struct timeval p;
|
||||||
|
event_add (DC->ev, &p);
|
||||||
return DC;
|
return DC;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1211,3 +1374,26 @@ void tgl_dc_iterator_ex (void (*iterator)(struct tgl_dc *DC, void *extra), void
|
|||||||
iterator (tgl_state.DC_list[i], extra);
|
iterator (tgl_state.DC_list[i], extra);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void tglmp_regenerate_temp_auth_key (struct tgl_dc *D) {
|
||||||
|
D->flags &= ~6;
|
||||||
|
D->temp_auth_key_id = 0;
|
||||||
|
memset (D->temp_auth_key, 0, 256);
|
||||||
|
|
||||||
|
if (!D->sessions[0]) {
|
||||||
|
tgl_dc_authorize (D);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct tgl_session *S = D->sessions[0];
|
||||||
|
tglt_secure_random (&S->session_id, 8);
|
||||||
|
S->seq_no = 0;
|
||||||
|
|
||||||
|
event_del (S->ev);
|
||||||
|
S->ack_tree = tree_clear_long (S->ack_tree);
|
||||||
|
|
||||||
|
if (S->c) {
|
||||||
|
create_temp_auth_key (S->c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -45,11 +45,12 @@ struct tgl_dc;
|
|||||||
|
|
||||||
struct connection;
|
struct connection;
|
||||||
|
|
||||||
long long tglmp_encrypt_send_message (struct connection *c, int *msg, int msg_ints, int useful);
|
long long tglmp_encrypt_send_message (struct connection *c, int *msg, int msg_ints, int flags);
|
||||||
void tglmp_dc_create_session (struct tgl_dc *DC);
|
void tglmp_dc_create_session (struct tgl_dc *DC);
|
||||||
int tglmp_check_g (unsigned char p[256], BIGNUM *g);
|
int tglmp_check_g (unsigned char p[256], BIGNUM *g);
|
||||||
int tglmp_check_DH_params (BIGNUM *p, int g);
|
int tglmp_check_DH_params (BIGNUM *p, int g);
|
||||||
struct tgl_dc *tglmp_alloc_dc (int id, char *ip, int port);
|
struct tgl_dc *tglmp_alloc_dc (int id, char *ip, int port);
|
||||||
|
void tglmp_regenerate_temp_auth_key (struct tgl_dc *D);
|
||||||
|
|
||||||
void tgln_insert_msg_id (struct tgl_session *S, long long id);
|
void tgln_insert_msg_id (struct tgl_session *S, long long id);
|
||||||
void tglmp_on_start (void);
|
void tglmp_on_start (void);
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
#define CODE_resPQ 0x05162463
|
#define CODE_resPQ 0x05162463
|
||||||
#define CODE_req_DH_params 0xd712e4be
|
#define CODE_req_DH_params 0xd712e4be
|
||||||
#define CODE_p_q_inner_data 0x83c95aec
|
#define CODE_p_q_inner_data 0x83c95aec
|
||||||
|
#define CODE_p_q_inner_data_temp 0x3c6a84d4
|
||||||
#define CODE_server_DH_inner_data 0xb5890dba
|
#define CODE_server_DH_inner_data 0xb5890dba
|
||||||
#define CODE_server_DH_params_fail 0x79cb045d
|
#define CODE_server_DH_params_fail 0x79cb045d
|
||||||
#define CODE_server_DH_params_ok 0xd0e8075c
|
#define CODE_server_DH_params_ok 0xd0e8075c
|
||||||
@ -48,6 +49,8 @@
|
|||||||
#define CODE_dh_gen_retry 0x46dc1fb9
|
#define CODE_dh_gen_retry 0x46dc1fb9
|
||||||
#define CODE_dh_gen_fail 0xa69dae02
|
#define CODE_dh_gen_fail 0xa69dae02
|
||||||
|
|
||||||
|
#define CODE_bind_auth_key_inner 0x75a3f765
|
||||||
|
|
||||||
/* service messages */
|
/* service messages */
|
||||||
#define CODE_rpc_result 0xf35c6d01
|
#define CODE_rpc_result 0xf35c6d01
|
||||||
#define CODE_rpc_error 0x2144ca19
|
#define CODE_rpc_error 0x2144ca19
|
||||||
|
69
queries.c
69
queries.c
@ -101,6 +101,7 @@ static int alarm_query (struct query *q) {
|
|||||||
return 0;
|
return 0;
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
|
if (q->session->session_id == q->session_id) {
|
||||||
clear_packet ();
|
clear_packet ();
|
||||||
out_int (CODE_msg_container);
|
out_int (CODE_msg_container);
|
||||||
out_int (1);
|
out_int (1);
|
||||||
@ -109,7 +110,14 @@ static int alarm_query (struct query *q) {
|
|||||||
out_int (4 * q->data_len);
|
out_int (4 * q->data_len);
|
||||||
out_ints (q->data, q->data_len);
|
out_ints (q->data, q->data_len);
|
||||||
|
|
||||||
tglmp_encrypt_send_message (q->session->c, packet_buffer, packet_ptr - packet_buffer, 0);
|
tglmp_encrypt_send_message (q->session->c, packet_buffer, packet_ptr - packet_buffer, q->flags & QUERY_FORCE_SEND);
|
||||||
|
} else {
|
||||||
|
q->msg_id = tglmp_encrypt_send_message (q->session->c, q->data, q->data_len, (q->flags & QUERY_FORCE_SEND) | 1);
|
||||||
|
q->session_id = q->session->session_id;
|
||||||
|
if (!(q->session->dc->flags & 4) && !(q->flags & QUERY_FORCE_SEND)) {
|
||||||
|
q->session_id = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -126,7 +134,7 @@ static void alarm_query_gateway (evutil_socket_t fd, short what, void *arg) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
struct query *tglq_send_query (struct tgl_dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra) {
|
struct query *tglq_send_query_ex (struct tgl_dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra, int flags) {
|
||||||
assert (DC);
|
assert (DC);
|
||||||
assert (DC->auth_key_id);
|
assert (DC->auth_key_id);
|
||||||
if (!DC->sessions[0]) {
|
if (!DC->sessions[0]) {
|
||||||
@ -137,12 +145,17 @@ struct query *tglq_send_query (struct tgl_dc *DC, int ints, void *data, struct q
|
|||||||
q->data_len = ints;
|
q->data_len = ints;
|
||||||
q->data = talloc (4 * ints);
|
q->data = talloc (4 * ints);
|
||||||
memcpy (q->data, data, 4 * ints);
|
memcpy (q->data, data, 4 * ints);
|
||||||
q->msg_id = tglmp_encrypt_send_message (DC->sessions[0]->c, data, ints, 1);
|
q->msg_id = tglmp_encrypt_send_message (DC->sessions[0]->c, data, ints, 1 | (flags & QUERY_FORCE_SEND));
|
||||||
q->session = DC->sessions[0];
|
q->session = DC->sessions[0];
|
||||||
q->seq_no = DC->sessions[0]->seq_no - 1;
|
q->seq_no = q->session->seq_no - 1;
|
||||||
|
q->session_id = q->session->session_id;
|
||||||
|
if (!(DC->flags & 4) && !(flags & QUERY_FORCE_SEND)) {
|
||||||
|
q->session_id = 0;
|
||||||
|
}
|
||||||
vlogprintf (E_DEBUG, "Msg_id is %lld %p\n", q->msg_id, q);
|
vlogprintf (E_DEBUG, "Msg_id is %lld %p\n", q->msg_id, q);
|
||||||
q->methods = methods;
|
q->methods = methods;
|
||||||
q->DC = DC;
|
q->DC = DC;
|
||||||
|
q->flags = flags & QUERY_FORCE_SEND;
|
||||||
if (queries_tree) {
|
if (queries_tree) {
|
||||||
vlogprintf (E_DEBUG + 2, "%lld %lld\n", q->msg_id, queries_tree->x->msg_id);
|
vlogprintf (E_DEBUG + 2, "%lld %lld\n", q->msg_id, queries_tree->x->msg_id);
|
||||||
}
|
}
|
||||||
@ -164,6 +177,10 @@ struct query *tglq_send_query (struct tgl_dc *DC, int ints, void *data, struct q
|
|||||||
return q;
|
return q;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct query *tglq_send_query (struct tgl_dc *DC, int ints, void *data, struct query_methods *methods, void *extra, void *callback, void *callback_extra) {
|
||||||
|
return tglq_send_query_ex (DC, ints, data, methods, extra, callback, callback_extra, 0);
|
||||||
|
}
|
||||||
|
|
||||||
static int fail_on_error (struct query *q UU, int error_code UU, int l UU, char *error UU) {
|
static int fail_on_error (struct query *q UU, int error_code UU, int l UU, char *error UU) {
|
||||||
fprintf (stderr, "error #%d: %.*s\n", error_code, l, error);
|
fprintf (stderr, "error #%d: %.*s\n", error_code, l, error);
|
||||||
assert (0);
|
assert (0);
|
||||||
@ -364,6 +381,13 @@ void tgl_do_help_get_config (void (*callback)(void *, int), void *callback_extra
|
|||||||
out_int (CODE_help_get_config);
|
out_int (CODE_help_get_config);
|
||||||
tglq_send_query (tgl_state.DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra);
|
tglq_send_query (tgl_state.DC_working, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tgl_do_help_get_config_dc (struct tgl_dc *D, void (*callback)(void *, int), void *callback_extra) {
|
||||||
|
clear_packet ();
|
||||||
|
tgl_do_insert_header ();
|
||||||
|
out_int (CODE_help_get_config);
|
||||||
|
tglq_send_query_ex (D, packet_ptr - packet_buffer, packet_buffer, &help_get_config_methods, 0, callback, callback_extra, 2);
|
||||||
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
/* {{{ Send code */
|
/* {{{ Send code */
|
||||||
@ -2822,6 +2846,7 @@ static int get_difference_on_answer (struct query *q UU) {
|
|||||||
bl_do_set_seq (fetch_int ());
|
bl_do_set_seq (fetch_int ());
|
||||||
//difference_got = 1;
|
//difference_got = 1;
|
||||||
|
|
||||||
|
vlogprintf (E_DEBUG, "Empty difference. Seq = %d\n", tgl_state.seq);
|
||||||
if (q->callback) {
|
if (q->callback) {
|
||||||
((void (*)(void *, int))q->callback) (q->callback_extra, 1);
|
((void (*)(void *, int))q->callback) (q->callback_extra, 1);
|
||||||
}
|
}
|
||||||
@ -2862,6 +2887,7 @@ static int get_difference_on_answer (struct query *q UU) {
|
|||||||
bl_do_set_date (fetch_int ());
|
bl_do_set_date (fetch_int ());
|
||||||
if (x == CODE_updates_difference) {
|
if (x == CODE_updates_difference) {
|
||||||
bl_do_set_seq (fetch_int ());
|
bl_do_set_seq (fetch_int ());
|
||||||
|
vlogprintf (E_DEBUG, "Difference end. New seq = %d\n", tgl_state.seq);
|
||||||
} else {
|
} else {
|
||||||
fetch_int ();
|
fetch_int ();
|
||||||
}
|
}
|
||||||
@ -3172,6 +3198,41 @@ void tgl_do_restore_msg (long long id, void (*callback)(void *callback_extra, in
|
|||||||
}
|
}
|
||||||
/* }}} */
|
/* }}} */
|
||||||
|
|
||||||
|
static void set_flag_4 (void *_D, int success) {
|
||||||
|
struct tgl_dc *D = _D;
|
||||||
|
assert (success);
|
||||||
|
D->flags |= 4;
|
||||||
|
|
||||||
|
static struct timeval ptimeout;
|
||||||
|
ptimeout.tv_sec = tgl_state.temp_key_expire_time * 0.9;
|
||||||
|
event_add (D->ev, &ptimeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int send_bind_temp_on_answer (struct query *q UU) {
|
||||||
|
assert (fetch_int () == (int)CODE_bool_true);
|
||||||
|
struct tgl_dc *D = q->extra;
|
||||||
|
D->flags |= 2;
|
||||||
|
tgl_do_help_get_config_dc (D, set_flag_4, D);
|
||||||
|
vlogprintf (E_DEBUG, "Bind successful in dc %d\n", D->id);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct query_methods send_bind_temp_methods = {
|
||||||
|
.on_answer = send_bind_temp_on_answer,
|
||||||
|
.type = TYPE_TO_PARAM (bool)
|
||||||
|
};
|
||||||
|
|
||||||
|
void tgl_do_send_bind_temp_key (struct tgl_dc *D, long long nonce, int expires_at, void *data, int len, long long msg_id) {
|
||||||
|
clear_packet ();
|
||||||
|
out_int (CODE_auth_bind_temp_auth_key);
|
||||||
|
out_long (D->auth_key_id);
|
||||||
|
out_long (nonce);
|
||||||
|
out_int (expires_at);
|
||||||
|
out_cstring (data, len);
|
||||||
|
struct query *q = tglq_send_query_ex (D, packet_ptr - packet_buffer, packet_buffer, &send_bind_temp_methods, D, 0, 0, 2);
|
||||||
|
assert (q->msg_id == msg_id);
|
||||||
|
}
|
||||||
|
|
||||||
static int update_status_on_answer (struct query *q UU) {
|
static int update_status_on_answer (struct query *q UU) {
|
||||||
fetch_bool ();
|
fetch_bool ();
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
struct event;
|
struct event;
|
||||||
|
|
||||||
#define QUERY_ACK_RECEIVED 1
|
#define QUERY_ACK_RECEIVED 1
|
||||||
|
#define QUERY_FORCE_SEND 2
|
||||||
|
|
||||||
struct query;
|
struct query;
|
||||||
struct query_methods {
|
struct query_methods {
|
||||||
@ -41,6 +42,7 @@ struct query {
|
|||||||
int data_len;
|
int data_len;
|
||||||
int flags;
|
int flags;
|
||||||
int seq_no;
|
int seq_no;
|
||||||
|
long long session_id;
|
||||||
void *data;
|
void *data;
|
||||||
struct query_methods *methods;
|
struct query_methods *methods;
|
||||||
struct event *ev;
|
struct event *ev;
|
||||||
@ -65,6 +67,7 @@ void work_timers (void);
|
|||||||
|
|
||||||
double get_double_time (void);
|
double get_double_time (void);
|
||||||
|
|
||||||
|
void tgl_do_send_bind_temp_key (struct tgl_dc *D, long long nonce, int expires_at, void *data, int len, long long msg_id);
|
||||||
|
|
||||||
// For binlog
|
// For binlog
|
||||||
|
|
||||||
|
11
tgl-layout.h
11
tgl-layout.h
@ -46,6 +46,10 @@ enum tgl_dc_state {
|
|||||||
st_reqpq_sent,
|
st_reqpq_sent,
|
||||||
st_reqdh_sent,
|
st_reqdh_sent,
|
||||||
st_client_dh_sent,
|
st_client_dh_sent,
|
||||||
|
st_init_temp,
|
||||||
|
st_reqpq_sent_temp,
|
||||||
|
st_reqdh_sent_temp,
|
||||||
|
st_client_dh_sent_temp,
|
||||||
st_authorized,
|
st_authorized,
|
||||||
st_error
|
st_error
|
||||||
};
|
};
|
||||||
@ -71,8 +75,15 @@ struct tgl_dc {
|
|||||||
char *user;
|
char *user;
|
||||||
struct tgl_session *sessions[MAX_DC_SESSIONS];
|
struct tgl_session *sessions[MAX_DC_SESSIONS];
|
||||||
char auth_key[256];
|
char auth_key[256];
|
||||||
|
char temp_auth_key[256];
|
||||||
|
char nonce[256];
|
||||||
|
char new_nonce[256];
|
||||||
|
char server_nonce[256];
|
||||||
long long auth_key_id;
|
long long auth_key_id;
|
||||||
|
long long temp_auth_key_id;
|
||||||
|
|
||||||
long long server_salt;
|
long long server_salt;
|
||||||
|
struct event *ev;
|
||||||
|
|
||||||
int server_time_delta;
|
int server_time_delta;
|
||||||
double server_time_udelta;
|
double server_time_udelta;
|
||||||
|
6
tgl.c
6
tgl.c
@ -69,12 +69,16 @@ void tgl_init (void) {
|
|||||||
if (!tgl_state.callback.create_print_name) {
|
if (!tgl_state.callback.create_print_name) {
|
||||||
tgl_state.callback.create_print_name = tgls_default_create_print_name;
|
tgl_state.callback.create_print_name = tgls_default_create_print_name;
|
||||||
}
|
}
|
||||||
|
if (!tgl_state.temp_key_expire_time) {
|
||||||
|
tgl_state.temp_key_expire_time = 60; //100000;
|
||||||
|
}
|
||||||
|
|
||||||
tglmp_on_start ();
|
tglmp_on_start ();
|
||||||
}
|
}
|
||||||
|
|
||||||
int tgl_authorized_dc (struct tgl_dc *DC) {
|
int tgl_authorized_dc (struct tgl_dc *DC) {
|
||||||
assert (DC);
|
assert (DC);
|
||||||
return DC->auth_key_id;
|
return (DC->flags & 4) != 0;//DC->auth_key_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int tgl_signed_dc (struct tgl_dc *DC) {
|
int tgl_signed_dc (struct tgl_dc *DC) {
|
||||||
|
8
tgl.h
8
tgl.h
@ -136,6 +136,8 @@ struct tgl_state {
|
|||||||
struct tgl_dc *DC_working;
|
struct tgl_dc *DC_working;
|
||||||
int max_dc_num;
|
int max_dc_num;
|
||||||
int dc_working_num;
|
int dc_working_num;
|
||||||
|
int enable_pfs;
|
||||||
|
int temp_key_expire_time;
|
||||||
|
|
||||||
long long cur_uploading_bytes;
|
long long cur_uploading_bytes;
|
||||||
long long cur_uploaded_bytes;
|
long long cur_uploaded_bytes;
|
||||||
@ -219,6 +221,10 @@ static inline void tgl_set_verbosity (int val) {
|
|||||||
tgl_state.verbosity = val;
|
tgl_state.verbosity = val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void tgl_enable_pfs (void) {
|
||||||
|
tgl_state.enable_pfs = 1;
|
||||||
|
}
|
||||||
|
|
||||||
static inline void tgl_set_test_mode (void) {
|
static inline void tgl_set_test_mode (void) {
|
||||||
tgl_state.test_mode ++;
|
tgl_state.test_mode ++;
|
||||||
}
|
}
|
||||||
@ -267,6 +273,8 @@ void tgl_do_create_group_chat (tgl_peer_id_t id, char *chat_topic, void (*callba
|
|||||||
void tgl_do_delete_msg (long long id, void (*callback)(void *callback_extra, int success), void *callback_extra);
|
void tgl_do_delete_msg (long long id, void (*callback)(void *callback_extra, int success), void *callback_extra);
|
||||||
void tgl_do_restore_msg (long long id, void (*callback)(void *callback_extra, int success), void *callback_extra);
|
void tgl_do_restore_msg (long long id, void (*callback)(void *callback_extra, int success), void *callback_extra);
|
||||||
void tgl_do_update_status (int online, void (*callback)(void *callback_extra, int success), void *callback_extra);
|
void tgl_do_update_status (int online, void (*callback)(void *callback_extra, int success), void *callback_extra);
|
||||||
|
void tgl_do_help_get_config_dc (struct tgl_dc *D, void (*callback)(void *, int), void *callback_extra);
|
||||||
|
|
||||||
|
|
||||||
void tgl_do_visualize_key (tgl_peer_id_t id, unsigned char buf[16]);
|
void tgl_do_visualize_key (tgl_peer_id_t id, unsigned char buf[16]);
|
||||||
|
|
||||||
|
@ -427,6 +427,7 @@ static int do_skip_seq (int seq) {
|
|||||||
}
|
}
|
||||||
if (seq > tgl_state.seq + 1) {
|
if (seq > tgl_state.seq + 1) {
|
||||||
vlogprintf (E_NOTICE, "Hole in seq (seq = %d, cur_seq = %d)\n", seq, tgl_state.seq);
|
vlogprintf (E_NOTICE, "Hole in seq (seq = %d, cur_seq = %d)\n", seq, tgl_state.seq);
|
||||||
|
//vlogprintf (E_NOTICE, "lock_diff = %s\n", (tgl_state.locks & TGL_LOCK_DIFF) ? "true" : "false");
|
||||||
tgl_do_get_difference (0, 0, 0);
|
tgl_do_get_difference (0, 0, 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user