void tgl_do_send_encr_msg (struct tgl_state *TLS, struct tgl_message *M, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { if (M->flags & TGLMF_SERVICE) { tgl_do_send_encr_msg_action (TLS, M, callback, callback_extra); return; } tgl_peer_t *P = tgl_peer_get (TLS, M->to_id); if (!P || P->encr_chat.state != sc_ok) { vlogprintf (E_WARNING, "Unknown encrypted chat\n"); if (callback) { callback (TLS, callback_extra, 0, M); } return; } assert (M->flags & TGLMF_ENCRYPTED); clear_packet (); out_int (CODE_messages_send_encrypted); out_int (CODE_input_encrypted_chat); out_int (tgl_get_peer_id (M->to_id)); out_long (P->encr_chat.access_hash); out_long (M->id); encr_start (); out_int (CODE_decrypted_message_layer); out_random (15 + 4 * (lrand48 () % 3)); out_int (TGL_ENCRYPTED_LAYER); out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != TLS->our_id)); out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == TLS->our_id) - 2); out_int (CODE_decrypted_message); out_long (M->id); out_int (P->encr_chat.ttl); out_cstring ((void *)M->message, M->message_len); switch (M->media.type) { case tgl_message_media_none: out_int (CODE_decrypted_message_media_empty); break; case tgl_message_media_geo: out_int (CODE_decrypted_message_media_geo_point); out_double (M->media.geo.latitude); out_double (M->media.geo.longitude); break; default: assert (0); } encr_finish (&P->encr_chat); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra); }
static void send_file_encrypted_end (struct tgl_state *TLS, struct send_file *f, void *callback, void *callback_extra) { out_int (CODE_messages_send_encrypted_file); out_int (CODE_input_encrypted_chat); out_int (tgl_get_peer_id (f->to_id)); tgl_peer_t *P = tgl_peer_get (TLS, f->to_id); assert (P); out_long (P->encr_chat.access_hash); long long r; tglt_secure_random (&r, 8); out_long (r); encr_start (); out_int (CODE_decrypted_message_layer); out_random (15 + 4 * (lrand48 () % 3)); out_int (TGL_ENCRYPTED_LAYER); out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != TLS->our_id)); out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == TLS->our_id)); out_int (CODE_decrypted_message); out_long (r); out_int (P->encr_chat.ttl); out_string (""); int *save_ptr = packet_ptr; if (f->flags == -1) { out_int (CODE_decrypted_message_media_photo); } else if ((f->flags & TGLDF_VIDEO)) { out_int (CODE_decrypted_message_media_video); } else if ((f->flags & TGLDF_AUDIO)) { out_int (CODE_decrypted_message_media_audio); } else { out_int (CODE_decrypted_message_media_document); } if (f->flags == -1 || !(f->flags & TGLDF_AUDIO)) { out_cstring ("", 0); out_int (90); out_int (90); } if (f->flags == -1) { out_int (f->w); out_int (f->h); } else if (f->flags & TGLDF_VIDEO) { out_int (f->duration); out_string (tg_mime_by_filename (f->file_name)); out_int (f->w); out_int (f->h); } else if (f->flags & TGLDF_AUDIO) { out_int (f->duration); out_string (tg_mime_by_filename (f->file_name)); } else { out_string (""); out_string (tg_mime_by_filename (f->file_name)); // document } out_int (f->size); out_cstring ((void *)f->key, 32); out_cstring ((void *)f->init_iv, 32); int *save_in_ptr = in_ptr; int *save_in_end = in_end; in_ptr = save_ptr; in_end = packet_ptr; assert (skip_type_any (TYPE_TO_PARAM(decrypted_message_media)) >= 0); assert (in_ptr == in_end); in_ptr = save_ptr; in_end = packet_ptr; struct tl_ds_decrypted_message_media *DS_DMM = fetch_ds_type_decrypted_message_media (TYPE_TO_PARAM (decrypted_message_media)); in_end = save_in_ptr; in_ptr = save_in_end; int peer_type = tgl_get_peer_type (f->to_id); int peer_id = tgl_get_peer_id (f->to_id); int date = time (NULL); encr_finish (&P->encr_chat); if (f->size < (16 << 20)) { out_int (CODE_input_encrypted_file_uploaded); } else { out_int (CODE_input_encrypted_file_big_uploaded); } out_long (f->id); out_int (f->part_num); if (f->size < (16 << 20)) { 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))); tfree_secure (f->iv, 32); bl_do_create_message_encr_new (TLS, r, &TLS->our_id, &peer_type, &peer_id, &date, NULL, 0, DS_DMM, NULL, NULL, TGLMF_OUT | TGLMF_UNREAD | TGLMF_ENCRYPTED | TGLMF_CREATE | TGLMF_CREATED); free_ds_type_decrypted_message_media (DS_DMM, TYPE_TO_PARAM (decrypted_message_media)); struct tgl_message *M = tgl_message_get (TLS, r); assert (M); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &send_encr_file_methods, M, callback, callback_extra); tfree_str (f->file_name); tfree (f, sizeof (*f)); }
void tgl_do_send_encr_msg_action (struct tgl_state *TLS, struct tgl_message *M, void (*callback)(struct tgl_state *TLS, void *callback_extra, int success, struct tgl_message *M), void *callback_extra) { tgl_peer_t *P = tgl_peer_get (TLS, M->to_id); if (!P || P->encr_chat.state != sc_ok) { vlogprintf (E_WARNING, "Unknown encrypted chat\n"); if (callback) { callback (TLS, callback_extra, 0, 0); } return; } assert (M->flags & TGLMF_ENCRYPTED); clear_packet (); out_int (CODE_messages_send_encrypted_service); out_int (CODE_input_encrypted_chat); out_int (tgl_get_peer_id (M->to_id)); out_long (P->encr_chat.access_hash); out_long (M->id); encr_start (); out_int (CODE_decrypted_message_layer); out_random (15 + 4 * (lrand48 () % 3)); out_int (TGL_ENCRYPTED_LAYER); out_int (2 * P->encr_chat.in_seq_no + (P->encr_chat.admin_id != TLS->our_id)); out_int (2 * P->encr_chat.out_seq_no + (P->encr_chat.admin_id == TLS->our_id) - 2); out_int (CODE_decrypted_message_service); out_long (M->id); switch (M->action.type) { case tgl_message_action_notify_layer: out_int (CODE_decrypted_message_action_notify_layer); out_int (M->action.layer); break; case tgl_message_action_set_message_ttl: out_int (CODE_decrypted_message_action_set_message_t_t_l); out_int (M->action.ttl); break; case tgl_message_action_request_key: out_int (CODE_decrypted_message_action_request_key); out_long (M->action.exchange_id); out_cstring ((void *)M->action.g_a, 256); break; case tgl_message_action_accept_key: out_int (CODE_decrypted_message_action_accept_key); out_long (M->action.exchange_id); out_cstring ((void *)M->action.g_a, 256); out_long (M->action.key_fingerprint); break; case tgl_message_action_commit_key: out_int (CODE_decrypted_message_action_commit_key); out_long (M->action.exchange_id); out_long (M->action.key_fingerprint); break; case tgl_message_action_abort_key: out_int (CODE_decrypted_message_action_abort_key); out_long (M->action.exchange_id); break; case tgl_message_action_noop: out_int (CODE_decrypted_message_action_noop); break; default: assert (0); } encr_finish (&P->encr_chat); tglq_send_query (TLS, TLS->DC_working, packet_ptr - packet_buffer, packet_buffer, &msg_send_encr_methods, M, callback, callback_extra); }
int cli_main(int argc, char* argv[]) { const char* server_name = 0; const char* env; msg_debug_init(); encr_start(); prep_sender(); service = argv[0]; if (argc > 1 && argv[1][0] != '-' && argv[1][0] != '+') { server_name = argv[1]; ++argv; --argc; } if (argc > 1) load_patterns(argv + 1); if (server_name == 0 && (server_name = getenv("SERVER")) == 0) die1(1, "Server address not named on command line nor in $SERVER"); if (!resolve_ipv4name(server_name, &ip)) die3(1, "Could not resolve '", server_name, "'"); brandom_init(); if ((env = getenv("KEYDIR")) != 0) keydir = env; load_keys(server_name); if ((env = getenv("PORT")) != 0) port = strtoul(env, 0, 10); if (port == 0) port = 11014; if ((sock = socket_udp()) == -1) die1sys(1, "Could not create UDP socket"); if (!socket_connect4(sock, &ip, port)) die1sys(1, "Could not bind socket"); if (!str_ready(&packet, 65535) || !str_ready(&rpacket, 4+4+8+256*5)) die1(1, "Out of memory"); getenvu("ACK_TIMEOUT", &ack_timeout); getenvu("CID_TIMEOUT", &cid_timeout); getenvu("RETRANSMITS", &retransmits); getenvu("READWAIT", &readwait); getenvu("STARTLINES", &startlines); if (getenv("EXITONEOF") != 0) exitoneof = 1; if (getenv("NOFILES") == 0 && getenv("NOFILE") == 0) buffer = buffer_file_init(); else buffer = buffer_nofile_init(); sig_all_catch(sigfn); exitasap = 0; mainloop(); return 0; }