Commit cce98419 authored by vysheng's avatar vysheng

Many improvements in encrypted chats. Can not send/download encrypted messages, for example

parent e4dc0e08
......@@ -78,12 +78,12 @@ char *next_token (int *l) {
#define NOT_FOUND (int)0x80000000
peer_id_t PEER_NOT_FOUND = {.id = NOT_FOUND};
int next_token_int (void) {
long long next_token_int (void) {
int l;
char *s = next_token (&l);
if (!s) { return NOT_FOUND; }
char *r;
int x = strtod (s, &r);
long long x = strtoll (s, &r, 10);
if (r == s + l) {
return x;
} else {
......@@ -139,6 +139,22 @@ peer_id_t next_token_chat (void) {
}
}
peer_id_t next_token_encr_chat (void) {
int l;
char *s = next_token (&l);
if (!s) { return PEER_NOT_FOUND; }
int index = 0;
while (index < peer_num && (!is_same_word (s, l, Peers[index]->print_name) || get_peer_type (Peers[index]->id) != PEER_ENCR_CHAT)) {
index ++;
}
if (index < peer_num) {
return Peers[index]->id;
} else {
return PEER_NOT_FOUND;
}
}
peer_id_t next_token_peer (void) {
int l;
char *s = next_token (&l);
......@@ -232,6 +248,7 @@ char *commands[] = {
"show_license",
"search",
"mark_read",
"visualize_key",
0 };
int commands_flags[] = {
......@@ -259,6 +276,7 @@ int commands_flags[] = {
07,
072,
072,
075,
};
int get_complete_mode (void) {
......@@ -322,6 +340,19 @@ int complete_chat_list (int index, const char *text, int len, char **R) {
}
}
int complete_encr_chat_list (int index, const char *text, int len, char **R) {
index ++;
while (index < peer_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len) || get_peer_type (Peers[index]->id) != PEER_ENCR_CHAT)) {
index ++;
}
if (index < peer_num) {
*R = strdup (Peers[index]->print_name);
return index;
} else {
return -1;
}
}
int complete_user_chat_list (int index, const char *text, int len, char **R) {
index ++;
while (index < peer_num && (!Peers[index]->print_name || strncmp (Peers[index]->print_name, text, len))) {
......@@ -390,6 +421,10 @@ char *command_generator (const char *text, int state) {
index = complete_chat_list (index, text, len, &R);
if (c) { rl_line_buffer[rl_point] = c; }
return R;
case 5:
index = complete_encr_chat_list (index, text, len, &R);
if (c) { rl_line_buffer[rl_point] = c; }
return R;
default:
if (c) { rl_line_buffer[rl_point] = c; }
return 0;
......@@ -446,7 +481,13 @@ void interpreter (char *line UU) {
#define GET_PEER_CHAT \
id = next_token_chat (); \
if (!cmp_peer_id (id, PEER_NOT_FOUND)) { \
printf ("Bad char id\n"); \
printf ("Bad chat id\n"); \
RET; \
}
#define GET_PEER_ENCR_CHAT \
id = next_token_encr_chat (); \
if (!cmp_peer_id (id, PEER_NOT_FOUND)) { \
printf ("Bad encr_chat id\n"); \
RET; \
}
......@@ -512,34 +553,38 @@ void interpreter (char *line UU) {
}
do_forward_message (id, num);
} else if (IS_WORD ("load_photo")) {
int num = next_token_int ();
if (num == NOT_FOUND || num <= 0) {
long long num = next_token_int ();
if (num == NOT_FOUND) {
printf ("Bad msg id\n");
RET;
}
struct message *M = message_get (num);
if (M && !M->service && M->media.type == (int)CODE_message_media_photo) {
do_load_photo (&M->media.photo, 1);
} else if (M && !M->service && M->media.type == (int)CODE_decrypted_message_media_photo) {
do_load_encr_video (&M->media.encr_video, 1); // this is not a bug.
} else {
printf ("Bad msg id\n");
RET;
}
} else if (IS_WORD ("view_photo")) {
int num = next_token_int ();
if (num == NOT_FOUND || num <= 0) {
long long num = next_token_int ();
if (num == NOT_FOUND) {
printf ("Bad msg id\n");
RET;
}
struct message *M = message_get (num);
if (M && !M->service && M->media.type == (int)CODE_message_media_photo) {
do_load_photo (&M->media.photo, 2);
} else if (M && !M->service && M->media.type == (int)CODE_decrypted_message_media_photo) {
do_load_encr_video (&M->media.encr_video, 2); // this is not a bug.
} else {
printf ("Bad msg id\n");
RET;
}
} else if (IS_WORD ("load_video_thumb")) {
int num = next_token_int ();
if (num == NOT_FOUND || num <= 0) {
long long num = next_token_int ();
if (num == NOT_FOUND) {
printf ("Bad msg id\n");
RET;
}
......@@ -551,8 +596,8 @@ void interpreter (char *line UU) {
RET;
}
} else if (IS_WORD ("view_video_thumb")) {
int num = next_token_int ();
if (num == NOT_FOUND || num <= 0) {
long long num = next_token_int ();
if (num == NOT_FOUND) {
printf ("Bad msg id\n");
RET;
}
......@@ -564,27 +609,31 @@ void interpreter (char *line UU) {
RET;
}
} else if (IS_WORD ("load_video")) {
int num = next_token_int ();
if (num == NOT_FOUND || num <= 0) {
long long num = next_token_int ();
if (num == NOT_FOUND) {
printf ("Bad msg id\n");
RET;
}
struct message *M = message_get (num);
if (M && !M->service && M->media.type == (int)CODE_message_media_video) {
do_load_video (&M->media.video, 1);
} else if (M && !M->service && M->media.type == (int)CODE_decrypted_message_media_video) {
do_load_encr_video (&M->media.encr_video, 1);
} else {
printf ("Bad msg id\n");
RET;
}
} else if (IS_WORD ("view_video")) {
int num = next_token_int ();
if (num == NOT_FOUND || num <= 0) {
long long num = next_token_int ();
if (num == NOT_FOUND) {
printf ("Bad msg id\n");
RET;
}
struct message *M = message_get (num);
if (M && !M->service && M->media.type == (int)CODE_message_media_video) {
do_load_video (&M->media.video, 2);
} else if (M && !M->service && M->media.type == (int)CODE_decrypted_message_media_video) {
do_load_encr_video (&M->media.encr_video, 2);
} else {
printf ("Bad msg id\n");
RET;
......@@ -691,6 +740,9 @@ void interpreter (char *line UU) {
} else if (IS_WORD ("mark_read")) {
GET_PEER;
do_mark_read (id);
} else if (IS_WORD ("visualize_key")) {
GET_PEER_ENCR_CHAT;
do_visualize_key (id);
}
#undef IS_WORD
#undef RET
......
......@@ -29,6 +29,9 @@
#define COLOR_BLUE "\033[34;1m"
#define COLOR_MAGENTA "\033[35;1m"
#define COLOR_CYAN "\033[36;1m"
#define COLOR_LCYAN "\033[0;36m"
#define COLOR_INVERSE "\033[7m"
char *get_default_prompt (void);
char *complete_none (const char *text, int state);
......
......@@ -1050,11 +1050,24 @@ void work_update (struct connection *c UU, long long msg_id UU) {
peer_id_t id = MK_ENCR_CHAT (fetch_int ()); // chat_id
fetch_int (); // max_date
fetch_int (); // date
peer_t *P = user_chat_get (id);
int x = -1;
if (P && P->last) {
x = 0;
struct message *M = P->last;
while (M && (!M->out || M->unread)) {
if (M->out) {
M->unread = 0;
x ++;
}
M = M->next;
}
}
print_start ();
push_color (COLOR_YELLOW);
printf ("Messages in encrypted chat ");
printf ("Encrypted chat ");
print_encr_chat_name_full (id, user_chat_get (id));
printf (" marked read \n");
printf (": %d messages marked read \n", x);
pop_color ();
print_end ();
}
......
int thumb_file_size = (82 * 6 - 2) * 4;
int thumb_file [] = {
0xe0ffd8ff, 0x464a1000, 0x01004649, 0x64000101, 0x00006400, 0xa002e2ff,
0x5f434349, 0x464f5250, 0x00454c49, 0x00000101, 0x636c9002, 0x3004736d,
0x6e6d0000, 0x47527274, 0x59582042, 0xdd07205a, 0x04000b00, 0x1b001600,
0x63612400, 0x50417073, 0x00004c50, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x0100d6f6, 0x00000000, 0x636c2dd3,
0x0000736d, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,
0x65640b00, 0x00006373, 0x00000801, 0x70633800, 0x00007472, 0x00004001,
0x74774e00, 0x00007470, 0x00009001, 0x68631400, 0x00006461, 0x0000a401,
0x58722c00, 0x00005a59, 0x0000d001, 0x58621400, 0x00005a59, 0x0000e401,
0x58671400, 0x00005a59, 0x0000f801, 0x54721400, 0x00004352, 0x00000c02,
0x54672000, 0x00004352, 0x00002c02, 0x54622000, 0x00004352, 0x00004c02,
0x68632000, 0x00006d72, 0x00006c02, 0x6c6d2400, 0x00006375, 0x00000000,
0x00000100, 0x6e650c00, 0x00005355, 0x00001c00, 0x73001c00, 0x47005200,
0x20004200, 0x75006200, 0x6c006900, 0x2d007400, 0x6e006900, 0x6c6d0000,
0x00006375, 0x00000000, 0x00000100, 0x6e650c00, 0x00005355, 0x00003200,
0x4e001c00, 0x20006f00, 0x6f006300, 0x79007000, 0x69007200, 0x68006700,
0x2c007400, 0x75002000, 0x65007300, 0x66002000, 0x65007200, 0x6c006500,
0x00007900, 0x59580000, 0x0000205a, 0x00000000, 0x0100d6f6, 0x00000000,
0x66732dd3, 0x00003233, 0x01000000, 0x00004a0c, 0xffffe305, 0x00002af3,
0x00009b07, 0xffff87fd, 0xffffa2fb, 0x0000a3fd, 0x0000d803, 0x595894c0,
0x0000205a, 0x00000000, 0x0000946f, 0x0000ee38, 0x59589003, 0x0000205a,
0x00000000, 0x00009d24, 0x0000830f, 0x5958beb6, 0x0000205a, 0x00000000,
0x0000a562, 0x000090b7, 0x6170de18, 0x00006172, 0x03000000, 0x02000000,
0x00006666, 0x0000a7f2, 0x0000590d, 0x0000d013, 0x61705b0a, 0x00006172,
0x03000000, 0x02000000, 0x00006666, 0x0000a7f2, 0x0000590d, 0x0000d013,
0x61705b0a, 0x00006172, 0x03000000, 0x02000000, 0x00006666, 0x0000a7f2,
0x0000590d, 0x0000d013, 0x68635b0a, 0x00006d72, 0x03000000, 0x00000000,
0x0000d7a3, 0x00007b54, 0x0000cd4c, 0x00009a99, 0x00006626, 0xdbff5c0f,
0x14004300, 0x0f120f0e, 0x1112140d, 0x14161712, 0x21331f18, 0x1f1c1c1f,
0x252f2d3f, 0x4e414a33, 0x4841494d, 0x765c5246, 0x6f575264, 0x66484658,
0x7a6f688c, 0x8485847d, 0x9b91634f, 0x769a808f, 0xff7f8481, 0x014300db,
0x1f171716, 0x213c1f1b, 0x547f3c21, 0x7f7f5448, 0x7f7f7f7f, 0x7f7f7f7f,
0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f,
0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x7f7f7f7f, 0x1100c0ff, 0x005a0008,
0x2201035a, 0x01110200, 0xff011103, 0x001900c4, 0x01010101, 0x00000101,
0x00000000, 0x00000000, 0x02030400, 0xc4ff0605, 0x00103600, 0x02010401,
0x06050304, 0x00000306, 0x01000000, 0x11030200, 0x05211204, 0x13514131,
0x32146122, 0x23918171, 0x72423424, 0x432515a1, 0xa2827444, 0xc4fff0b3,
0x01011400, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x1400c4ff,
0x00000111, 0x00000000, 0x00000000, 0x00000000, 0xdaff0000, 0x01030c00,
0x03110200, 0x003f0011, 0x404434fb, 0xbcb4875c, 0x006b38b0, 0x03dcdb12,
0xf4637f74, 0xe519f153, 0x09d7c5c7, 0x47d29160, 0x20692f18, 0xd06d786a,
0x53f7f922, 0x17b3e260, 0x2fe8668c, 0x1786a473, 0x9775efbd, 0xe917e43a,
0x1d0a1bb0, 0x114d0f82, 0x14651110, 0x35f299ed, 0xe9b09680, 0xf5a4fc2f,
0xe975bd03, 0xb506737b, 0x04444440, 0x5c444044, 0x8e8dedbd, 0xc61adc7b,
0x689c738b, 0x92a0dc01, 0x58e2b77f, 0x7bfb37d1, 0xb5b5e79d, 0xdbf968cc,
0xead3f48d, 0x38ed1313, 0xdea77c86, 0xae089963, 0xc743435a, 0x403fe4ce,
0x392ee1b9, 0xed39e718, 0xd6517e2d, 0x7fc4aa03, 0xb7ad7590, 0x77e7e6ab,
0x34bf705d, 0x7c77ca53, 0x3dea1299, 0x7fb0bcf4, 0x241fadc5, 0x95a7a816,
0x13fbe6f3, 0x3182b135, 0xd1b4b224, 0x1b0d48a2, 0xbf9d26d8, 0x82dc3640,
0x63569a2a, 0xbbd224c3, 0xb9b4714c, 0x1680aec6, 0x3d311856, 0x9b59be91,
0x09876ca6, 0x61d86564, 0x5a9f06d2, 0x36f51b0d, 0x8682e476, 0xacb1b131,
0xd1584363, 0x00456b4d, 0x22d2053b, 0x22202202, 0xf3f30222, 0xe3e513e5,
0xf1e6e1f0, 0x2380496e, 0x5fdcdb68, 0x549b3a27, 0x825e6a6c, 0x6522028b,
0xaf91ccc8, 0x341cf26b, 0x58dbc4b5, 0xf2289add, 0x0854ddbd, 0x0b9247d5,
0xf02b5c54, 0x3f917f92, 0xaf56affd, 0xe3760637, 0x05cebde0, 0xed4c76ce,
0x3cef1b63, 0x7fd8aff8, 0xa0c902ea, 0x7e730d0a, 0x435834f3, 0x26edbb76,
0xd3ec00fd, 0x76d48efa, 0xa8560f2d, 0x0e766331, 0xd319993c, 0x20243209,
0x61b7e6c8, 0x998331d0, 0x640ee802, 0x47a3d493, 0xfab99413, 0x4fd871f1,
0xe9443792, 0x627e051c, 0xd8f3051c, 0x2f28f558, 0x64b51745, 0x1b2bfee3,
0xb8783953, 0x9900fff6, 0xd8176a65, 0x5a3bf56a, 0x1b331fdb, 0x64b3572f,
0xd59a3643, 0xaf3abce1, 0x11dd20bd, 0x01111110, 0x5c141011, 0xb3e3083f,
0xd9b19cc4, 0x17edb20e, 0xa78e9aa1, 0x4ef4de06, 0x00c0bfe7, 0x7e1e442d,
0x9221fe38, 0xedb5c7dc, 0x6338078a, 0x62495b8d, 0xc11d9b8c, 0x49e81b16,
0x51d02bea, 0x3eb86d70, 0xc8bc4f13, 0xa10ec758, 0xd40751c0, 0x5ac94710,
0xc4c8b080, 0x95492b83, 0x975ee696, 0xb7bd96b4, 0x17379cce, 0x82e856e8,
0xe4c2c82a, 0x398e935f, 0x632437ea, 0x7c9c87d2, 0xdc1ddb7c, 0x65a80a48,
0x2309f164, 0x51fab475, 0x081dc11d, 0xda45573b, 0x6622f3f3, 0x48f1b214,
0x676c4edb, 0x243468c7, 0x00ffde60, 0xf1630350, 0xa0076c1d, 0x8f2c0c8b,
0x2383c26b, 0x361a8f4e, 0xaceea6c9, 0x01dd5a5d, 0x11111011, 0xc3780c04,
0xbf093ee2, 0xc7972c0b, 0x00d99040, 0xc0c20eb7, 0x659d3bd4, 0x269ab85e,
0x468e114f, 0x11ad4fdb, 0x83d083d8, 0x8c52f4bd, 0x3c9664bf, 0xa4f9c77c,
0x22a68876, 0xadb18784, 0xf480be83, 0x885a00ea, 0x220e0a88, 0xc303e4f6,
0xc866e058, 0xdddbd661, 0xdf395db1, 0xbad64343, 0xe6e65b03, 0x668e81c3,
0xad619e98, 0xeeb94563, 0xd4d19a3c, 0x3316ce95, 0x9d65f1e1, 0x3bf324fe,
0x0e468f53, 0xc386068c, 0xa89e24f7, 0xf0c7c73b, 0xb60e391f, 0x1b8827cb,
0x58601954, 0xc54f90f9, 0x80886ec5, 0x88088888, 0x1b7bb980, 0xb4c71c23,
0xe6148e39, 0xb12358b8, 0xbd08225d, 0x0ffef085, 0x72b4f025, 0x635ce389,
0xb90277e4, 0x0d05e000, 0x9bf9dbb9, 0x8e749fbc, 0x7ee6abbf, 0x4ddbf4af,
0x728df7f3, 0x10b59adf, 0xe3c38f49, 0xb23c638a, 0xdb3d9349, 0x66899a64,
0x00004dd5, 0xf51b5adf, 0x2220a255, 0xd9ff0f22};
......@@ -41,6 +41,9 @@
#include <openssl/rand.h>
#include <openssl/aes.h>
#include <openssl/sha.h>
#include <openssl/md5.h>
#include "no-preview.h"
#define sha1 SHA1
......@@ -282,6 +285,16 @@ int new_dc_num;
extern struct dc *DC_list[];
extern struct dc *DC_working;
void out_random (int n) {
assert (n <= 16);
static char buf[16];
int i;
for (i = 0; i < n; i++) {
buf[i] = lrand48 () & 255;
}
out_cstring (buf, n);
}
/* {{{ Get config */
int help_get_config_on_answer (struct query *q UU) {
......@@ -780,6 +793,7 @@ void do_send_encr_message (peer_id_t id, const char *msg, int len) {
struct message *M = malloc (sizeof (*M));
memset (M, 0, sizeof (*M));
M->flags = FLAG_ENCRYPTED;
M->from_id = MK_USER (our_id);
M->to_id = id;
M->unread = 1;
......@@ -991,6 +1005,7 @@ void do_get_history (peer_id_t id, int limit) {
}
/* }}} */
/* {{{ Get dialogs */
int get_dialogs_on_answer (struct query *q UU) {
unsigned x = fetch_int ();
assert (x == CODE_messages_dialogs || x == CODE_messages_dialogs_slice);
......@@ -1067,35 +1082,11 @@ void do_get_dialog_list (void) {
out_int (1000);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0);
}
/* }}} */
int allow_send_linux_version = 1;
void do_get_dialog_list_ex (void) {
clear_packet ();
out_int (CODE_invoke_with_layer9);
out_int (CODE_init_connection);
out_int (TG_APP_ID);
if (allow_send_linux_version) {
struct utsname st;
uname (&st);
out_string (st.machine);
static char buf[1000000];
sprintf (buf, "%s %s %s", st.sysname, st.release, st.version);
out_string (buf);
out_string (TG_VERSION " (build " TG_BUILD ")");
out_string ("En");
} else {
out_string ("x86");
out_string ("Linux");
out_string (TG_VERSION);
out_string ("en");
}
out_int (CODE_messages_get_dialogs);
out_int (0);
out_int (0);
out_int (100);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dialogs_methods, 0);
}
/* {{{ Send photo/video file */
struct send_file {
int fd;
long long size;
......@@ -1106,6 +1097,10 @@ struct send_file {
peer_id_t to_id;
int media_type;
char *file_name;
int encr;
unsigned char *iv;
unsigned char *init_iv;
unsigned char *key;
};
void out_peer_id (peer_id_t id) {
......@@ -1158,6 +1153,21 @@ int send_file_on_answer (struct query *q UU) {
return 0;
}
int send_encr_file_on_answer (struct query *q UU) {
assert (fetch_int () == (int)CODE_messages_sent_encrypted_file);
struct message *M = q->extra;
M->date = fetch_int ();
assert (fetch_int () == CODE_encrypted_file);
M->media.encr_photo.id = fetch_long ();
M->media.encr_photo.access_hash = fetch_long ();
M->media.encr_photo.size = fetch_int ();
M->media.encr_photo.dc_id = fetch_int ();
assert (fetch_int () == M->media.encr_photo.key_fingerprint);
print_message (M);
message_insert (M);
return 0;
}
struct query_methods send_file_part_methods = {
.on_answer = send_file_part_on_answer
};
......@@ -1166,6 +1176,10 @@ struct query_methods send_file_methods = {
.on_answer = send_file_on_answer
};
struct query_methods send_encr_file_methods = {
.on_answer = send_encr_file_on_answer
};
void send_part (struct send_file *f) {
if (f->fd >= 0) {
if (!f->part_num) {
......@@ -1178,9 +1192,22 @@ void send_part (struct send_file *f) {
static char buf[512 << 10];
int x = read (f->fd, buf, f->part_size);
assert (x > 0);
out_cstring (buf, x);
f->offset += x;
cur_uploaded_bytes += x;
if (f->encr) {
if (x & 15) {
assert (f->offset == f->size);
while (x & 15) {
buf[x ++] = lrand48 () & 255;
}
}
AES_KEY aes_key;
AES_set_encrypt_key (f->key, 256, &aes_key);
AES_ige_encrypt ((void *)buf, (void *)buf, x, &aes_key, f->iv, 1);
}
out_cstring (buf, x);
if (verbosity >= 2) {
logprintf ("offset=%lld size=%lld\n", f->offset, f->size);
}
......@@ -1193,24 +1220,92 @@ void send_part (struct send_file *f) {
cur_uploaded_bytes -= f->size;
cur_uploading_bytes -= f->size;
clear_packet ();
out_int (CODE_messages_send_media);
out_peer_id (f->to_id);
assert (f->media_type == CODE_input_media_uploaded_photo || f->media_type == CODE_input_media_uploaded_video);
out_int (f->media_type);
out_int (CODE_input_file);
out_long (f->id);
out_int (f->part_num);
char *s = f->file_name + strlen (f->file_name);
while (s >= f->file_name && *s != '/') { s --;}
out_string (s + 1);
out_string ("");
if (f->media_type == CODE_input_media_uploaded_video) {
out_int (100);
if (!f->encr) {
out_int (CODE_messages_send_media);
out_peer_id (f->to_id);
out_int (f->media_type);
out_int (CODE_input_file);
out_long (f->id);
out_int (f->part_num);
char *s = f->file_name + strlen (f->file_name);
while (s >= f->file_name && *s != '/') { s --;}
out_string (s + 1);
out_string ("");
if (f->media_type == CODE_input_media_uploaded_video) {
out_int (100);
out_int (100);
out_int (100);
}
out_long (-lrand48 () * (1ll << 32) - lrand48 ());
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0);
} else {
struct message *M = malloc (sizeof (*M));
memset (M, 0, sizeof (*M));
out_int (CODE_messages_send_encrypted_file);
out_int (CODE_input_encrypted_chat);
out_int (get_peer_id (f->to_id));
peer_t *P = user_chat_get (f->to_id);
assert (P);
out_long (P->encr_chat.access_hash);
long long r = -lrand48 () * (1ll << 32) - lrand48 ();
out_long (r);
encr_start ();
out_int (CODE_decrypted_message);
out_long (r);
out_random (16);
out_string ("");
if (f->media_type == CODE_input_media_uploaded_photo) {
out_int (CODE_decrypted_message_media_photo);
M->media.type = CODE_decrypted_message_media_photo;
} else {
out_int (CODE_decrypted_message_media_video);
M->media.type = CODE_decrypted_message_media_video;
}
out_cstring ((void *)thumb_file, thumb_file_size);
out_int (90);
out_int (90);
if (f->media_type == CODE_input_media_uploaded_video) {
out_int (0);
}
out_int (100);
out_int (100);
out_int (f->size);
out_cstring ((void *)f->key, 32);
out_cstring ((void *)f->init_iv, 32);
encr_finish (&P->encr_chat);
out_int (CODE_input_encrypted_file_uploaded);
out_long (f->id);
out_int (f->part_num);
out_string ("");
unsigned char md5[16];
unsigned char str[64];
memcpy (str, f->key, 32);
memcpy (str + 32, f->init_iv, 32);
MD5 (str, 64, md5);
out_int ((*(int *)md5) ^ (*(int *)(md5 + 4)));
free (f->iv);
M->media.encr_photo.key = f->key;
M->media.encr_photo.iv = f->init_iv;
M->media.encr_photo.key_fingerprint = (*(int *)md5) ^ (*(int *)(md5 + 4));
M->flags = FLAG_ENCRYPTED;
M->from_id = MK_USER (our_id);
M->to_id = f->to_id;
M->unread = 1;
M->message = strdup ("");
M->out = 1;
M->id = r;
M->date = time (0);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M);
}
out_long (-lrand48 () * (1ll << 32) - lrand48 ());
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &send_file_methods, 0);
free (f->file_name);
free (f);
}
......@@ -1231,6 +1326,7 @@ void do_send_photo (int type, peer_id_t to_id, char *file_name) {
return;
}
struct send_file *f = malloc (sizeof (*f));
memset (f, 0, sizeof (*f));
f->fd = fd;
f->size = size;
f->offset = 0;
......@@ -1240,6 +1336,20 @@ void do_send_photo (int type, peer_id_t to_id, char *file_name) {
f->to_id = to_id;
f->media_type = type;
f->file_name = file_name;
if (get_peer_type (f->to_id) == PEER_ENCR_CHAT) {
f->encr = 1;
f->iv = malloc (32);
int i;
for (i = 0; i < 8; i++) {
((int *)f->iv)[i] = mrand48 ();
}
f->init_iv = malloc (32);
memcpy (f->init_iv, f->iv, 32);
f->key = malloc (32);
for (i = 0; i < 8; i++) {
((int *)f->key)[i] = mrand48 ();
}
}
if (f->part_size > (512 << 10)) {
close (fd);
rprintf ("Too big file. Maximal supported size is %d", (512 << 10) * 1000);
......@@ -1247,7 +1357,9 @@ void do_send_photo (int type, peer_id_t to_id, char *file_name) {
}
send_part (f);
}
/* }}} */
/* {{{ Forward */
int fwd_msg_on_answer (struct query *q UU) {
assert (fetch_int () == (int)CODE_messages_stated_message);
struct message *M = fetch_alloc_message ();
......@@ -1273,6 +1385,10 @@ struct query_methods fwd_msg_methods = {
};
void do_forward_message (peer_id_t id, int n) {
if (get_peer_type (id) == PEER_ENCR_CHAT) {
rprintf ("Can not forward messages from secret chat\n");
return;
}
clear_packet ();
out_int (CODE_invoke_with_layer9);
out_int (CODE_messages_forward_message);
......@@ -1281,7 +1397,9 @@ void do_forward_message (peer_id_t id, int n) {
out_long (lrand48 () * (1ll << 32) + lrand48 ());
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &fwd_msg_methods, 0);
}
/* }}} */
/* {{{ Rename chat */
int rename_chat_on_answer (struct query *q UU) {
assert (fetch_int () == (int)CODE_messages_stated_message);
struct message *M = fetch_alloc_message ();
......@@ -1314,7 +1432,9 @@ void do_rename_chat (peer_id_t id, char *name) {
out_string (name);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &rename_chat_methods, 0);
}
/* }}} */
/* {{{ Chat info */
int chat_info_on_answer (struct query *q UU) {
struct chat *C = fetch_alloc_chat_full ();
peer_t *U = (void *)C;
......@@ -1352,7 +1472,9 @@ void do_get_chat_info (peer_id_t id) {
out_int (get_peer_id (id));
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &chat_info_methods, 0);
}
/* }}} */
/* {{{ User info */
int user_info_on_answer (struct query *q UU) {
struct user *U = fetch_alloc_user_full ();
peer_t *C = (void *)U;
......@@ -1394,7 +1516,9 @@ void do_get_user_info (peer_id_t id) {
}
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_info_methods, 0);
}
/* }}} */
/* {{{ Get user info silently */
int user_list_info_silent_on_answer (struct query *q UU) {
assert (fetch_int () == CODE_vector);
int n = fetch_int ();
......@@ -1422,7 +1546,9 @@ void do_get_user_list_info_silent (int num, int *list) {
}
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &user_list_info_silent_methods, 0);
}
/* }}} */
/* {{{ Load photo/video */
struct download {
int offset;
int size;
......@@ -1435,6 +1561,8 @@ struct download {
int fd;
char *name;
long long id;
unsigned char *iv;
unsigned char *key;
};
......@@ -1454,6 +1582,9 @@ void end_load (struct download *D) {
logprintf ("Image is at %s\n", D->name);
}
}
if (D->iv) {
free (D->iv);
}
free (D->name);
free (D);
}
......@@ -1503,7 +1634,16 @@ int download_on_answer (struct query *q) {
assert (len >= 0);
cur_downloaded_bytes += len;
update_prompt ();
assert (write (D->fd, fetch_str (len), len) == len);
if (D->iv) {
unsigned char *ptr = (void *)fetch_str (len);
assert (!(len & 15));
AES_KEY aes_key;
AES_set_decrypt_key (D->key, 256, &aes_key);
AES_ige_encrypt (ptr, ptr, len, &aes_key, D->iv, 0);
assert (write (D->fd, ptr, len) == len);
} else {
assert (write (D->fd, fetch_str (len), len) == len);
}
D->offset += len;
if (D->offset < D->size) {
load_next_part (D);
......@@ -1531,7 +1671,11 @@ void load_next_part (struct download *D) {
out_int (D->local_id);
out_long (D->secret);
} else {
out_int (CODE_input_video_file_location);
if (D->iv) {
out_int (CODE_input_encrypted_file_location);
} else {
out_int (CODE_input_video_file_location);
}
out_long (D->id);
out_long (D->access_hash);
}
......@@ -1545,6 +1689,7 @@ void do_load_photo_size (struct photo_size *P, int next) {
assert (P);
assert (next);
struct download *D = malloc (sizeof (*D));
memset (D, 0, sizeof (*D));
D->id = 0;
D->offset = 0;
D->size = P->size;
......@@ -1580,6 +1725,23 @@ void do_load_video (struct video *V, int next) {
assert (V);
assert (next);
struct download *D = malloc (sizeof (*D));
memset (D, 0, sizeof (*D));
D->offset = 0;
D->size = V->size;
D->id = V->id;
D->access_hash = V->access_hash;
D->dc = V->dc_id;
D->next = next;
D->name = 0;
D->fd = -1;
load_next_part (D);
}
void do_load_encr_video (struct encr_video *V, int next) {
assert (V);
assert (next);
struct download *D = malloc (sizeof (*D));
memset (D, 0, sizeof (*D));
D->offset = 0;
D->size = V->size;
D->id = V->id;
......@@ -1588,9 +1750,21 @@ void do_load_video (struct video *V, int next) {
D->next = next;
D->name = 0;
D->fd = -1;
D->key = V->key;
D->iv = malloc (32);
memcpy (D->iv, V->iv, 32);
load_next_part (D);
unsigned char md5[16];
unsigned char str[64];
memcpy (str, V->key, 32);
memcpy (str + 32, V->iv, 32);
MD5 (str, 64, md5);
assert (V->key_fingerprint == ((*(int *)md5) ^ (*(int *)(md5 + 4))));
}
/* }}} */
/* {{{ Export auth */
char *export_auth_str;
int export_auth_str_len;
int is_export_auth_str (void) {
......@@ -1629,7 +1803,9 @@ void do_export_auth (int num) {
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &export_auth_methods, 0);
net_loop (0, is_export_auth_str);
}
/* }}} */
/* {{{ Import auth */
int import_auth_on_answer (struct query *q UU) {
assert (fetch_int () == (int)CODE_auth_authorization);
fetch_int (); // expires
......@@ -1652,7 +1828,9 @@ void do_import_auth (int num) {
send_query (DC_list[num], packet_ptr - packet_buffer, packet_buffer, &import_auth_methods, 0);
net_loop (0, isn_export_auth_str);
}
/* }}} */
/* {{{ Add contact */
int add_contact_on_answer (struct query *q UU) {
assert (fetch_int () == (int)CODE_contacts_imported_contacts);
assert (fetch_int () == CODE_vector);
......@@ -1720,7 +1898,9 @@ void do_add_contact (const char *phone, int phone_len, const char *first_name, i
out_int (force ? CODE_bool_true : CODE_bool_false);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &add_contact_methods, 0);
}
/* }}} */
/* {{{ Msg search */
int msg_search_on_answer (struct query *q UU) {
return get_history_on_answer (q);
}
......@@ -1742,7 +1922,9 @@ void do_msg_search (peer_id_t id, int from, int to, int limit, const char *s) {
out_int (limit);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_search_methods, 0);
}
/* }}} */
/* {{{ Encr accept */
int send_encr_accept_on_answer (struct query *q UU) {
struct secret_chat *E = fetch_alloc_encrypted_chat ();
......@@ -1860,7 +2042,9 @@ void do_accept_encr_chat_request (struct secret_chat *E) {
out_int (256);
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_dh_config_methods, E);
}
/* }}} */
/* {{{ Get difference */
int unread_messages;
int difference_got;
int seq, pts, qts, last_date;
......@@ -1980,3 +2164,36 @@ void do_get_difference (void) {
send_query (DC_working, packet_ptr - packet_buffer, packet_buffer, &get_state_methods, 0);
}
}
/* }}} */
/* {{{ Visualize key */
char *colors[4] = {COLOR_GREY, COLOR_GREEN, COLOR_CYAN, COLOR_BLUE};
void do_visualize_key (peer_id_t id) {
assert (get_peer_type (id) == PEER_ENCR_CHAT);
peer_t *P = user_chat_get (id);
assert (P);
if (P->encr_chat.state != sc_ok) {
rprintf ("Chat is not initialized yet\n");
return;
}
unsigned char buf[20];
SHA1 ((void *)P->encr_chat.key, 256, buf);
print_start ();
int i;
for (i = 0; i < 16; i++) {
int x = buf[i];
int j;
for (j = 0; j < 4; j ++) {
push_color (colors[x & 3]);
push_color (COLOR_INVERSE);
printf (" ");
pop_color ();
pop_color ();
x = x >> 2;
}
if (i & 1) { printf ("\n"); }
}
print_end ();
}
/* }}} */
......@@ -80,6 +80,7 @@ void do_get_user_list_info_silent (int num, int *list);
void do_get_user_info (peer_id_t id);
void do_forward_message (peer_id_t id, int n);
void do_rename_chat (peer_id_t id, char *name);
void do_load_encr_video (struct encr_video *V, int next);
struct photo;
struct video;
......@@ -97,5 +98,6 @@ void do_msg_search (peer_id_t id, int from, int to, int limit, const char *s);
void do_accept_encr_chat_request (struct secret_chat *E);
void do_get_difference (void);
void do_mark_read (peer_id_t id);
void do_visualize_key (peer_id_t id);
#endif
......@@ -818,6 +818,8 @@ void fetch_encrypted_message (struct message *M) {
peer_id_t chat = MK_ENCR_CHAT (fetch_int ());
M->to_id = chat;
peer_t *P = user_chat_get (chat);
M->flags &= ~(FLAG_EMPTY | FLAG_DELETED);
M->flags |= FLAG_ENCRYPTED;
if (!P) {
logprintf ("Encrypted message to unknown chat. Dropping\n");
M->flags |= FLAG_EMPTY;
......
......@@ -91,9 +91,9 @@ struct encr_video {
int w;
int h;
int duration;
unsigned char *key;
unsigned char *iv;
int duration;
};
struct encr_file {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment