void tgl_do_create_keys_end (struct tgl_state *TLS, struct tgl_secret_chat *U) { assert (TLS->encr_prime); BIGNUM *g_b = BN_bin2bn (U->g_key, 256, 0); ensure_ptr (g_b); assert (tglmp_check_g_a (TLS, TLS->encr_prime_bn, g_b) >= 0); BIGNUM *p = TLS->encr_prime_bn; ensure_ptr (p); BIGNUM *r = BN_new (); ensure_ptr (r); BIGNUM *a = BN_bin2bn ((void *)U->key, 256, 0); ensure_ptr (a); ensure (BN_mod_exp (r, g_b, a, p, TLS->BN_ctx)); unsigned char *t = talloc (256); memcpy (t, U->key, 256); memset (U->key, 0, sizeof (U->key)); BN_bn2bin (r, (void *)(((char *)(U->key)) + (256 - BN_num_bytes (r)))); static unsigned char sha_buffer[20]; sha1 ((void *)U->key, 256, sha_buffer); long long k = *(long long *)(sha_buffer + 12); if (k != U->key_fingerprint) { vlogprintf (E_WARNING, "Key fingerprint mismatch (my 0x%llx 0x%llx)\n", (unsigned long long)k, (unsigned long long)U->key_fingerprint); U->state = sc_deleted; } memcpy (U->first_key_sha, sha_buffer, 20); tfree_secure (t, 256); BN_clear_free (g_b); BN_clear_free (r); BN_clear_free (a); }
static void read_incoming (struct bufferevent *bev, void *_arg) { vlogprintf (E_WARNING, "Read from incoming connection\n"); struct in_ev *ev = _arg; assert (ev->bev == bev); ev->in_buf_pos += bufferevent_read (bev, ev->in_buf + ev->in_buf_pos, 4096 - ev->in_buf_pos); while (1) { int pos = 0; int ok = 0; while (pos < ev->in_buf_pos) { if (ev->in_buf[pos] == '\n') { if (!ev->error) { ev->in_buf[pos] = 0; interpreter_ex (ev->in_buf, ev); } else { ev->error = 0; } ok = 1; ev->in_buf_pos -= (pos + 1); memmove (ev->in_buf, ev->in_buf + pos + 1, ev->in_buf_pos); pos = 0; } else { pos ++; } } if (ok) { ev->in_buf_pos += bufferevent_read (bev, ev->in_buf + ev->in_buf_pos, 4096 - ev->in_buf_pos); } else { if (ev->in_buf_pos == 4096) { ev->error = 1; } break; } } }
void bl_do_dc_option (struct tgl_state *TLS, int flags, int id, const char *name, int l1, const char *ip, int l2, int port) /* {{{ */ { struct tgl_dc *DC = TLS->DC_list[id]; if (DC) { struct tgl_dc_option *O = DC->options[flags & 3]; while (O) { if (!strncmp (O->ip, ip, l2)) { return; } O = O->next; } } vlogprintf (E_NOTICE, "DC%d '%.*s' update: %.*s:%d\n", id, l1, name, l2, ip, port ); tglmp_alloc_dc (TLS, flags, id, tstrndup (ip, l2), port ); }
void logprintf(char const *format, ...) { va_list va; va_start(va, format); vlogprintf(format, va); va_end(va); }
void event_incoming (struct bufferevent *bev, short what, void *_arg) { struct in_ev *ev = _arg; if (what & (BEV_EVENT_EOF | BEV_EVENT_ERROR)) { vlogprintf (E_WARNING, "Closing incoming connection\n"); assert (ev->fd >= 0); close (ev->fd); bufferevent_free (bev); ev->bev = 0; if (!--ev->refcnt) { free (ev); } } }
/** * Print message to stdout, adding a newline "if needed" * A newline is needed if this function has not yet been invoked * since last statistics printout */ int flprintf(const char *fmt, ...) { va_list ap; va_start(ap, fmt); if(udpc_log) return vlogprintf(udpc_log, fmt, ap); else { printNewlineIfNeeded(); return vfprintf(stderr, fmt, ap); } }
void flogprintf(FILE *f, char const *format, ...) { va_list va; va_start(va, format); if(f == stderr || f == stdout) vlogprintf(format, va); else vfprintf(f, format, va); va_end(va); }
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 accept_incoming (evutil_socket_t efd, short what, void *arg) { vlogprintf (E_WARNING, "Accepting incoming connection\n"); socklen_t clilen = 0; struct sockaddr_in cli_addr; int fd = accept (efd, (struct sockaddr *)&cli_addr, &clilen); assert (fd >= 0); struct bufferevent *bev = bufferevent_socket_new (TLS->ev_base, fd, 0); struct in_ev *e = malloc (sizeof (*e)); e->bev = bev; e->refcnt = 1; e->in_buf_pos = 0; e->error = 0; e->fd = fd; bufferevent_setcb (bev, read_incoming, 0, event_incoming, e); bufferevent_enable (bev, EV_READ | EV_WRITE); }
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); }
/** * Print message to the log, if not null */ int logprintf(FILE *logfile, const char *fmt, ...) { va_list ap; va_start(ap, fmt); return vlogprintf(logfile, fmt, ap); }
void bl_do_encr_chat (struct tgl_state *TLS, int id, long long *access_hash, int *date, int *admin, int *user_id, void *key, void *g_key, void *first_key_id, int *state, int *ttl, int *layer, int *in_seq_no, int *last_in_seq_no, int *out_seq_no, long long *key_fingerprint, int flags, const char *print_name, int print_name_len) /* {{{ */ { tgl_peer_t *_U = tgl_peer_get (TLS, TGL_MK_ENCR_CHAT (id)); unsigned updates = 0; if ((flags & TGLPF_CREATE) && (flags != TGL_FLAGS_UNCHANGED)) { if (!_U) { _U = talloc0 (sizeof (*_U)); _U->id = TGL_MK_ENCR_CHAT (id); tglp_insert_encrypted_chat (TLS, _U); } else { assert (!(_U->flags & TGLPF_CREATED)); } updates |= TGL_UPDATE_CREATED; } else { assert (_U->flags & TGLPF_CREATED); } struct tgl_secret_chat *U = (void *)_U; if (flags == TGL_FLAGS_UNCHANGED) { flags = U->flags; } flags &= TGLECF_TYPE_MASK; if ((flags & TGLECF_TYPE_MASK) != (U->flags & TGLECF_TYPE_MASK)) { updates |= TGL_UPDATE_FLAGS; } U->flags = (U->flags & ~TGLECF_TYPE_MASK) | flags; if (access_hash && *access_hash != U->access_hash) { U->access_hash = *access_hash; U->id.access_hash = *access_hash; updates |= TGL_UPDATE_ACCESS_HASH; } if (date) { U->date = *date; } if (admin) { U->admin_id = *admin; } if (user_id) { U->user_id = *user_id; } if (key_fingerprint) { U->key_fingerprint = *key_fingerprint; } if (in_seq_no) { U->in_seq_no = *in_seq_no; } if (out_seq_no) { U->out_seq_no = *out_seq_no; } if (last_in_seq_no) { U->last_in_seq_no = *last_in_seq_no; } tgl_peer_t *Us = tgl_peer_get (TLS, TGL_MK_USER (U->user_id)); if (!U->print_name) { if (print_name) { U->print_name = tstrndup (print_name, print_name_len); } else { if (Us) { U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", Us->user.first_name, Us->user.last_name, 0); } else { static char buf[100]; tsnprintf (buf, 99, "user#%d", U->user_id); U->print_name = TLS->callback.create_print_name (TLS, TGL_MK_ENCR_CHAT (id), "!", buf, 0, 0); } tglp_peer_insert_name (TLS, (void *)U); } } if (g_key) { if (!U->g_key) { U->g_key = talloc (256); } memcpy (U->g_key, g_key, 256); } if (key) { memcpy (U->key, key, 256); } if (first_key_id) { memcpy (U->first_key_sha, first_key_id, 20); } if (state) { if (U->state == sc_waiting && *state == sc_ok) { tgl_do_create_keys_end (TLS, U); } if ((int)U->state != *state) { switch (*state) { case sc_request: updates |= TGL_UPDATE_REQUESTED; break; case sc_ok: updates |= TGL_UPDATE_WORKING; vlogprintf (E_WARNING, "Secret chat in ok state\n"); break; default: break; } } U->state = *state; } if (TLS->callback.secret_chat_update && updates) { TLS->callback.secret_chat_update (TLS, U, updates); } }