Coverage Report

Created: 2025-10-08 19:34

/work/toxcore/TCP_client.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2025 The TokTok team.
3
 * Copyright © 2014 Tox project.
4
 */
5
6
/**
7
 * Implementation of the TCP relay client part of Tox.
8
 */
9
#include "TCP_client.h"
10
11
#include <assert.h>
12
#include <stdio.h>
13
#include <string.h>
14
15
#include "TCP_common.h"
16
#include "attributes.h"
17
#include "ccompat.h"
18
#include "crypto_core.h"
19
#include "forwarding.h"
20
#include "logger.h"
21
#include "mem.h"
22
#include "mono_time.h"
23
#include "net_profile.h"
24
#include "network.h"
25
#include "util.h"
26
27
typedef struct TCP_Client_Conn {
28
    // TODO(iphydf): Add an enum for this.
29
    uint8_t status; /* 0 if not used, 1 if other is offline, 2 if other is online. */
30
    uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE];
31
    uint32_t number;
32
} TCP_Client_Conn;
33
34
struct TCP_Client_Connection {
35
    TCP_Connection con;
36
    TCP_Client_Status status;
37
    uint8_t self_public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* our public key */
38
    uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE]; /* public key of the server */
39
    IP_Port ip_port; /* The ip and port of the server */
40
    TCP_Proxy_Info proxy_info;
41
    uint8_t recv_nonce[CRYPTO_NONCE_SIZE]; /* Nonce of received packets. */
42
    uint16_t next_packet_length;
43
44
    uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
45
46
    uint64_t kill_at;
47
48
    uint64_t last_pinged;
49
    uint64_t ping_id;
50
51
    uint64_t ping_response_id;
52
    uint64_t ping_request_id;
53
54
    TCP_Client_Conn connections[NUM_CLIENT_CONNECTIONS];
55
    tcp_routing_response_cb *response_callback;
56
    void *response_callback_object;
57
    tcp_routing_status_cb *status_callback;
58
    void *status_callback_object;
59
    tcp_routing_data_cb *data_callback;
60
    void *data_callback_object;
61
    tcp_oob_data_cb *oob_data_callback;
62
    void *oob_data_callback_object;
63
64
    tcp_onion_response_cb *onion_callback;
65
    void *onion_callback_object;
66
67
    forwarded_response_cb *forwarded_response_callback;
68
    void *forwarded_response_callback_object;
69
70
    /* Can be used by user. */
71
    void *custom_object;
72
    uint32_t custom_uint;
73
};
74
75
const uint8_t *tcp_con_public_key(const TCP_Client_Connection *con)
76
591
{
77
591
    return con->public_key;
78
591
}
79
80
IP_Port tcp_con_ip_port(const TCP_Client_Connection *con)
81
471
{
82
471
    return con->ip_port;
83
471
}
84
85
TCP_Client_Status tcp_con_status(const TCP_Client_Connection *con)
86
12.8k
{
87
12.8k
    return con->status;
88
12.8k
}
89
void *tcp_con_custom_object(const TCP_Client_Connection *con)
90
1.23k
{
91
1.23k
    return con->custom_object;
92
1.23k
}
93
uint32_t tcp_con_custom_uint(const TCP_Client_Connection *con)
94
1.23k
{
95
1.23k
    return con->custom_uint;
96
1.23k
}
97
void tcp_con_set_custom_object(TCP_Client_Connection *con, void *object)
98
58
{
99
58
    con->custom_object = object;
100
58
}
101
void tcp_con_set_custom_uint(TCP_Client_Connection *con, uint32_t value)
102
58
{
103
58
    con->custom_uint = value;
104
58
}
105
106
/**
107
 * @retval true on success
108
 * @retval false on failure
109
 */
110
static bool connect_sock_to(const Network *_Nonnull ns, const Logger *_Nonnull logger, const Memory *_Nonnull mem, Socket sock, const IP_Port *_Nonnull ip_port,
111
                            const TCP_Proxy_Info *_Nonnull proxy_info)
112
69
{
113
69
    Net_Err_Connect err;
114
69
    if (proxy_info->proxy_type != TCP_PROXY_NONE) {
115
10
        net_connect(ns, mem, logger, sock, &proxy_info->ip_port, &err);
116
59
    } else {
117
59
        net_connect(ns, mem, logger, sock, ip_port, &err);
118
59
    }
119
69
    switch (err) {
120
69
        case NET_ERR_CONNECT_OK:
121
69
        case NET_ERR_CONNECT_FAILED: {
122
            /* nonblocking socket, connect will never return success */
123
69
            return true;
124
69
        }
125
0
        case NET_ERR_CONNECT_INVALID_FAMILY:
126
0
            return false;
127
69
    }
128
0
    LOGGER_ERROR(logger, "unexpected error code %s from net_connect", net_err_connect_to_string(err));
129
0
    return false;
130
69
}
131
132
/**
133
 * @retval 1 on success.
134
 * @retval 0 on failure.
135
 */
136
static int proxy_http_generate_connection_request(TCP_Client_Connection *_Nonnull tcp_conn)
137
1
{
138
1
    const char one[] = "CONNECT ";
139
1
    const char two[] = " HTTP/1.1\nHost: ";
140
1
    const char three[] = "\r\n\r\n";
141
142
1
    char ip[TOX_INET6_ADDRSTRLEN];
143
144
1
    if (!ip_parse_addr(&tcp_conn->ip_port.ip, ip, sizeof(ip))) {
145
0
        return 0;
146
0
    }
147
148
1
    const uint16_t port = net_ntohs(tcp_conn->ip_port.port);
149
1
    const int written = snprintf((char *)tcp_conn->con.last_packet, MAX_PACKET_SIZE, "%s%s:%hu%s%s:%hu%s", one, ip, port,
150
1
                                 two, ip, port, three);
151
152
1
    if (written < 0 || MAX_PACKET_SIZE < written) {
153
0
        return 0;
154
0
    }
155
156
1
    tcp_conn->con.last_packet_length = written;
157
1
    tcp_conn->con.last_packet_sent = 0;
158
1
    return 1;
159
1
}
160
161
/**
162
 * @retval 1 on success.
163
 * @retval 0 if no data received.
164
 * @retval -1 on failure (connection refused).
165
 */
166
static int proxy_http_read_connection_response(const Logger *_Nonnull logger, const TCP_Client_Connection *_Nonnull tcp_conn)
167
2
{
168
2
    const char success[] = "200";
169
2
    uint8_t data[16]; // draining works the best if the length is a power of 2
170
171
2
    const TCP_Connection *con0 = &tcp_conn->con;
172
2
    const int ret = read_tcp_packet(logger, con0->mem, con0->ns, con0->sock, data, sizeof(data) - 1, &con0->ip_port);
173
174
2
    if (ret == -1) {
175
1
        return 0;
176
1
    }
177
178
1
    data[sizeof(data) - 1] = 0;
179
180
1
    if (strstr((const char *)data, success) != nullptr) {
181
        // drain all data
182
1
        uint16_t data_left = net_socket_data_recv_buffer(tcp_conn->con.ns, tcp_conn->con.sock);
183
184
6
        while (data_left > 0) {
185
5
            uint8_t temp_data[16];
186
5
            const uint16_t temp_data_size = min_u16(data_left, sizeof(temp_data));
187
5
            const TCP_Connection *con = &tcp_conn->con;
188
189
5
            if (read_tcp_packet(logger, con->mem, con->ns, con->sock, temp_data, temp_data_size,
190
5
                                &con->ip_port) == -1) {
191
0
                LOGGER_ERROR(logger, "failed to drain TCP data (but ignoring failure)");
192
0
                return 1;
193
0
            }
194
195
5
            data_left -= temp_data_size;
196
5
        }
197
198
1
        return 1;
199
1
    }
200
201
0
    return -1;
202
1
}
203
204
enum Tcp_Socks5_Proxy_Hs {
205
    TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5          = 0x05,
206
    TCP_SOCKS5_PROXY_HS_COMM_ESTABLISH_REQUEST  = 0x01,
207
    TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED    = 0x00,
208
    TCP_SOCKS5_PROXY_HS_AUTH_METHODS_SUPPORTED  = 0x01,
209
    TCP_SOCKS5_PROXY_HS_NO_AUTH                 = 0x00,
210
    TCP_SOCKS5_PROXY_HS_RESERVED                = 0x00,
211
    TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV4          = 0x01,
212
    TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV6          = 0x04,
213
};
214
215
static void proxy_socks5_generate_greetings(TCP_Client_Connection *_Nonnull tcp_conn)
216
9
{
217
9
    tcp_conn->con.last_packet[0] = TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5;
218
9
    tcp_conn->con.last_packet[1] = TCP_SOCKS5_PROXY_HS_AUTH_METHODS_SUPPORTED;
219
9
    tcp_conn->con.last_packet[2] = TCP_SOCKS5_PROXY_HS_NO_AUTH;
220
221
9
    tcp_conn->con.last_packet_length = 3;
222
9
    tcp_conn->con.last_packet_sent = 0;
223
9
}
224
225
/**
226
 * @retval 1 on success.
227
 * @retval 0 if no data received.
228
 * @retval -1 on failure (connection refused).
229
 */
230
static int socks5_read_handshake_response(const Logger *_Nonnull logger, const TCP_Client_Connection *_Nonnull tcp_conn)
231
2
{
232
2
    uint8_t data[2];
233
2
    const TCP_Connection *con = &tcp_conn->con;
234
2
    const int ret = read_tcp_packet(logger, con->mem, con->ns, con->sock, data, sizeof(data), &con->ip_port);
235
236
2
    if (ret == -1) {
237
1
        return 0;
238
1
    }
239
240
1
    if (data[0] == TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5 && data[1] == TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED) {
241
1
        return 1;
242
1
    }
243
244
0
    return -1;
245
1
}
246
247
static void proxy_socks5_generate_connection_request(TCP_Client_Connection *_Nonnull tcp_conn)
248
1
{
249
1
    tcp_conn->con.last_packet[0] = TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5;
250
1
    tcp_conn->con.last_packet[1] = TCP_SOCKS5_PROXY_HS_COMM_ESTABLISH_REQUEST;
251
1
    tcp_conn->con.last_packet[2] = TCP_SOCKS5_PROXY_HS_RESERVED;
252
1
    uint16_t length = 3;
253
254
1
    if (net_family_is_ipv4(tcp_conn->ip_port.ip.family)) {
255
1
        tcp_conn->con.last_packet[3] = TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV4;
256
1
        ++length;
257
1
        memcpy(tcp_conn->con.last_packet + length, tcp_conn->ip_port.ip.ip.v4.uint8, sizeof(IP4));
258
1
        length += sizeof(IP4);
259
1
    } else {
260
0
        tcp_conn->con.last_packet[3] = TCP_SOCKS5_PROXY_HS_ADDR_TYPE_IPV6;
261
0
        ++length;
262
0
        memcpy(tcp_conn->con.last_packet + length, tcp_conn->ip_port.ip.ip.v6.uint8, sizeof(IP6));
263
0
        length += sizeof(IP6);
264
0
    }
265
266
1
    memcpy(tcp_conn->con.last_packet + length, &tcp_conn->ip_port.port, sizeof(uint16_t));
267
1
    length += sizeof(uint16_t);
268
269
1
    tcp_conn->con.last_packet_length = length;
270
1
    tcp_conn->con.last_packet_sent = 0;
271
1
}
272
273
/**
274
 * @retval 1 on success.
275
 * @retval 0 if no data received.
276
 * @retval -1 on failure (connection refused).
277
 */
278
static int proxy_socks5_read_connection_response(const Logger *_Nonnull logger, const TCP_Client_Connection *_Nonnull tcp_conn)
279
2
{
280
2
    if (net_family_is_ipv4(tcp_conn->ip_port.ip.family)) {
281
2
        uint8_t data[4 + sizeof(IP4) + sizeof(uint16_t)];
282
2
        const TCP_Connection *con = &tcp_conn->con;
283
2
        const int ret = read_tcp_packet(logger, con->mem, con->ns, con->sock, data, sizeof(data), &con->ip_port);
284
285
2
        if (ret == -1) {
286
1
            return 0;
287
1
        }
288
289
1
        if (data[0] == TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5 && data[1] == TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED) {
290
1
            return 1;
291
1
        }
292
1
    } else {
293
0
        uint8_t data[4 + sizeof(IP6) + sizeof(uint16_t)];
294
0
        const TCP_Connection *con = &tcp_conn->con;
295
0
        const int ret = read_tcp_packet(logger, con->mem, con->ns, con->sock, data, sizeof(data), &con->ip_port);
296
297
0
        if (ret == -1) {
298
0
            return 0;
299
0
        }
300
301
0
        if (data[0] == TCP_SOCKS5_PROXY_HS_VERSION_SOCKS5 && data[1] == TCP_SOCKS5_PROXY_HS_COMM_REQUEST_GRANTED) {
302
0
            return 1;
303
0
        }
304
0
    }
305
306
0
    return -1;
307
2
}
308
309
/**
310
 * @retval 0 on success.
311
 * @retval -1 on failure.
312
 */
313
static int generate_handshake(TCP_Client_Connection *_Nonnull tcp_conn)
314
61
{
315
61
    uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
316
61
    crypto_new_keypair(tcp_conn->con.rng, plain, tcp_conn->temp_secret_key);
317
61
    random_nonce(tcp_conn->con.rng, tcp_conn->con.sent_nonce);
318
61
    memcpy(plain + CRYPTO_PUBLIC_KEY_SIZE, tcp_conn->con.sent_nonce, CRYPTO_NONCE_SIZE);
319
61
    memcpy(tcp_conn->con.last_packet, tcp_conn->self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
320
61
    random_nonce(tcp_conn->con.rng, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE);
321
61
    const int len = encrypt_data_symmetric(tcp_conn->con.mem, tcp_conn->con.shared_key, tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE, plain,
322
61
                                           sizeof(plain), tcp_conn->con.last_packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
323
324
61
    if (len != sizeof(plain) + CRYPTO_MAC_SIZE) {
325
0
        return -1;
326
0
    }
327
328
61
    tcp_conn->con.last_packet_length = CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + sizeof(plain) + CRYPTO_MAC_SIZE;
329
61
    tcp_conn->con.last_packet_sent = 0;
330
61
    return 0;
331
61
}
332
333
/**
334
 * @param data must be of length TCP_SERVER_HANDSHAKE_SIZE
335
 *
336
 * @retval 0 on success.
337
 * @retval -1 on failure.
338
 */
339
static int handle_handshake(TCP_Client_Connection *_Nonnull tcp_conn, const uint8_t *_Nonnull data)
340
60
{
341
60
    uint8_t plain[CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE];
342
60
    const int len = decrypt_data_symmetric(tcp_conn->con.mem, tcp_conn->con.shared_key, data, data + CRYPTO_NONCE_SIZE,
343
60
                                           TCP_SERVER_HANDSHAKE_SIZE - CRYPTO_NONCE_SIZE, plain);
344
345
60
    if (len != sizeof(plain)) {
346
0
        return -1;
347
0
    }
348
349
60
    memcpy(tcp_conn->recv_nonce, plain + CRYPTO_PUBLIC_KEY_SIZE, CRYPTO_NONCE_SIZE);
350
60
    encrypt_precompute(plain, tcp_conn->temp_secret_key, tcp_conn->con.shared_key);
351
60
    crypto_memzero(tcp_conn->temp_secret_key, CRYPTO_SECRET_KEY_SIZE);
352
60
    return 0;
353
60
}
354
355
/**
356
 * @retval 1 on success.
357
 * @retval 0 if could not send packet.
358
 * @retval -1 on failure (connection must be killed).
359
 */
360
int send_routing_request(const Logger *logger, TCP_Client_Connection *con, const uint8_t *public_key)
361
109
{
362
109
    uint8_t packet[1 + CRYPTO_PUBLIC_KEY_SIZE];
363
109
    packet[0] = TCP_PACKET_ROUTING_REQUEST;
364
109
    memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
365
109
    return write_packet_tcp_secure_connection(logger, &con->con, packet, sizeof(packet), true);
366
109
}
367
368
void routing_response_handler(TCP_Client_Connection *con, tcp_routing_response_cb *response_callback, void *object)
369
59
{
370
59
    con->response_callback = response_callback;
371
59
    con->response_callback_object = object;
372
59
}
373
374
void routing_status_handler(TCP_Client_Connection *con, tcp_routing_status_cb *status_callback, void *object)
375
59
{
376
59
    con->status_callback = status_callback;
377
59
    con->status_callback_object = object;
378
59
}
379
380
static int tcp_send_ping_response(const Logger *_Nonnull logger, TCP_Client_Connection *_Nonnull con);
381
static int tcp_send_ping_request(const Logger *_Nonnull logger, TCP_Client_Connection *_Nonnull con);
382
383
/**
384
 * @retval 1 on success.
385
 * @retval 0 if could not send packet.
386
 * @retval -1 on failure.
387
 */
388
int send_data(const Logger *logger, TCP_Client_Connection *con, uint8_t con_id, const uint8_t *data, uint16_t length)
389
1.04k
{
390
1.04k
    if (con_id >= NUM_CLIENT_CONNECTIONS) {
391
0
        return -1;
392
0
    }
393
394
1.04k
    if (con->connections[con_id].status != 2) {
395
0
        return -1;
396
0
    }
397
398
1.04k
    if (tcp_send_ping_response(logger, con) == 0 || tcp_send_ping_request(logger, con) == 0) {
399
0
        return 0;
400
0
    }
401
402
1.04k
    const uint16_t packet_size = 1 + length;
403
1.04k
    VLA(uint8_t, packet, packet_size);
404
1.04k
    packet[0] = con_id + NUM_RESERVED_PORTS;
405
1.04k
    memcpy(packet + 1, data, length);
406
1.04k
    return write_packet_tcp_secure_connection(logger, &con->con, packet, packet_size, false);
407
1.04k
}
408
409
/**
410
 * @retval 1 on success.
411
 * @retval 0 if could not send packet.
412
 * @retval -1 on failure.
413
 */
414
int send_oob_packet(const Logger *logger, TCP_Client_Connection *con, const uint8_t *public_key, const uint8_t *data,
415
                    uint16_t length)
416
173
{
417
173
    if (length == 0 || length > TCP_MAX_OOB_DATA_LENGTH) {
418
0
        return -1;
419
0
    }
420
421
173
    const uint16_t packet_size = 1 + CRYPTO_PUBLIC_KEY_SIZE + length;
422
173
    VLA(uint8_t, packet, packet_size);
423
173
    packet[0] = TCP_PACKET_OOB_SEND;
424
173
    memcpy(packet + 1, public_key, CRYPTO_PUBLIC_KEY_SIZE);
425
173
    memcpy(packet + 1 + CRYPTO_PUBLIC_KEY_SIZE, data, length);
426
173
    return write_packet_tcp_secure_connection(logger, &con->con, packet, packet_size, false);
427
173
}
428
429
/** @brief Set the number that will be used as an argument in the callbacks related to con_id.
430
 *
431
 * When not set by this function, the number is -1.
432
 *
433
 * return 0 on success.
434
 * return -1 on failure.
435
 */
436
int set_tcp_connection_number(TCP_Client_Connection *con, uint8_t con_id, uint32_t number)
437
108
{
438
108
    if (con_id >= NUM_CLIENT_CONNECTIONS) {
439
0
        return -1;
440
0
    }
441
442
108
    if (con->connections[con_id].status == 0) {
443
0
        return -1;
444
0
    }
445
446
108
    con->connections[con_id].number = number;
447
108
    return 0;
448
108
}
449
450
void routing_data_handler(TCP_Client_Connection *con, tcp_routing_data_cb *data_callback, void *object)
451
59
{
452
59
    con->data_callback = data_callback;
453
59
    con->data_callback_object = object;
454
59
}
455
456
void oob_data_handler(TCP_Client_Connection *con, tcp_oob_data_cb *oob_data_callback, void *object)
457
59
{
458
59
    con->oob_data_callback = oob_data_callback;
459
59
    con->oob_data_callback_object = object;
460
59
}
461
462
/**
463
 * @retval 1 on success.
464
 * @retval 0 if could not send packet.
465
 * @retval -1 on failure (connection must be killed).
466
 */
467
static int client_send_disconnect_notification(const Logger *_Nonnull logger, TCP_Client_Connection *_Nonnull con, uint8_t id)
468
108
{
469
108
    uint8_t packet[1 + 1];
470
108
    packet[0] = TCP_PACKET_DISCONNECT_NOTIFICATION;
471
108
    packet[1] = id;
472
108
    return write_packet_tcp_secure_connection(logger, &con->con, packet, sizeof(packet), true);
473
108
}
474
475
/**
476
 * @retval 1 on success.
477
 * @retval 0 if could not send packet.
478
 * @retval -1 on failure (connection must be killed).
479
 */
480
static int tcp_send_ping_request(const Logger *_Nonnull logger, TCP_Client_Connection *_Nonnull con)
481
13.0k
{
482
13.0k
    if (con->ping_request_id == 0) {
483
13.0k
        return 1;
484
13.0k
    }
485
486
65
    uint8_t packet[1 + sizeof(uint64_t)];
487
65
    packet[0] = TCP_PACKET_PING;
488
65
    memcpy(packet + 1, &con->ping_request_id, sizeof(uint64_t));
489
65
    const int ret = write_packet_tcp_secure_connection(logger, &con->con, packet, sizeof(packet), true);
490
491
65
    if (ret == 1) {
492
65
        con->ping_request_id = 0;
493
65
    }
494
495
65
    return ret;
496
13.0k
}
497
498
/**
499
 * @retval 1 on success.
500
 * @retval 0 if could not send packet.
501
 * @retval -1 on failure (connection must be killed).
502
 */
503
static int tcp_send_ping_response(const Logger *_Nonnull logger, TCP_Client_Connection *_Nonnull con)
504
13.0k
{
505
13.0k
    if (con->ping_response_id == 0) {
506
13.0k
        return 1;
507
13.0k
    }
508
509
15
    uint8_t packet[1 + sizeof(uint64_t)];
510
15
    packet[0] = TCP_PACKET_PONG;
511
15
    memcpy(packet + 1, &con->ping_response_id, sizeof(uint64_t));
512
15
    const int ret = write_packet_tcp_secure_connection(logger, &con->con, packet, sizeof(packet), true);
513
514
15
    if (ret == 1) {
515
15
        con->ping_response_id = 0;
516
15
    }
517
518
15
    return ret;
519
13.0k
}
520
521
/**
522
 * @retval 1 on success.
523
 * @retval 0 if could not send packet.
524
 * @retval -1 on failure (connection must be killed).
525
 */
526
int send_disconnect_request(const Logger *logger, TCP_Client_Connection *con, uint8_t con_id)
527
108
{
528
108
    if (con_id >= NUM_CLIENT_CONNECTIONS) {
529
0
        return -1;
530
0
    }
531
532
108
    con->connections[con_id].status = 0;
533
108
    con->connections[con_id].number = 0;
534
108
    return client_send_disconnect_notification(logger, con, con_id + NUM_RESERVED_PORTS);
535
108
}
536
537
/**
538
 * @retval 1 on success.
539
 * @retval 0 if could not send packet.
540
 * @retval -1 on failure (connection must be killed).
541
 */
542
int send_onion_request(const Logger *logger, TCP_Client_Connection *con, const uint8_t *data, uint16_t length)
543
1.00k
{
544
1.00k
    const uint16_t packet_size = 1 + length;
545
1.00k
    VLA(uint8_t, packet, packet_size);
546
1.00k
    packet[0] = TCP_PACKET_ONION_REQUEST;
547
1.00k
    memcpy(packet + 1, data, length);
548
1.00k
    return write_packet_tcp_secure_connection(logger, &con->con, packet, packet_size, false);
549
1.00k
}
550
551
void onion_response_handler(TCP_Client_Connection *con, tcp_onion_response_cb *onion_callback, void *object)
552
58
{
553
58
    con->onion_callback = onion_callback;
554
58
    con->onion_callback_object = object;
555
58
}
556
557
/** @retval 1 on success.
558
 * @retval 0 if could not send packet.
559
 * @retval -1 on failure (connection must be killed).
560
 */
561
int send_forward_request_tcp(const Logger *logger, TCP_Client_Connection *con, const IP_Port *dest, const uint8_t *data, uint16_t length)
562
5
{
563
5
    if (length > MAX_FORWARD_DATA_SIZE) {
564
0
        return -1;
565
0
    }
566
567
5
    VLA(uint8_t, packet, 1 + MAX_PACKED_IPPORT_SIZE + length);
568
5
    packet[0] = TCP_PACKET_FORWARD_REQUEST;
569
5
    const int ipport_length = pack_ip_port(logger, packet + 1, MAX_PACKED_IPPORT_SIZE, dest);
570
571
5
    if (ipport_length == -1) {
572
0
        return 0;
573
0
    }
574
575
5
    memcpy(packet + 1 + ipport_length, data, length);
576
5
    return write_packet_tcp_secure_connection(logger, &con->con, packet, 1 + ipport_length + length, false);
577
5
}
578
579
void forwarding_handler(TCP_Client_Connection *con, forwarded_response_cb *forwarded_response_callback, void *object)
580
58
{
581
58
    con->forwarded_response_callback = forwarded_response_callback;
582
58
    con->forwarded_response_callback_object = object;
583
58
}
584
585
/** Create new TCP connection to ip_port/public_key */
586
TCP_Client_Connection *new_tcp_connection(
587
    const Logger *logger, const Memory *mem, const Mono_Time *mono_time, const Random *rng, const Network *ns,
588
    const IP_Port *ip_port, const uint8_t *public_key, const uint8_t *self_public_key, const uint8_t *self_secret_key,
589
    const TCP_Proxy_Info *proxy_info, Net_Profile *_Nullable net_profile)
590
69
{
591
69
    assert(logger != nullptr);
592
69
    assert(mem != nullptr);
593
69
    assert(mono_time != nullptr);
594
69
    assert(rng != nullptr);
595
69
    assert(ns != nullptr);
596
597
69
    if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {
598
0
        LOGGER_ERROR(logger, "Invalid IP family: %d", ip_port->ip.family.value);
599
0
        return nullptr;
600
0
    }
601
602
69
    const TCP_Proxy_Info default_proxyinfo = {{{{0}}}};
603
604
69
    if (proxy_info == nullptr) {
605
3
        proxy_info = &default_proxyinfo;
606
3
    }
607
608
69
    Family family = ip_port->ip.family;
609
610
69
    if (proxy_info->proxy_type != TCP_PROXY_NONE) {
611
10
        family = proxy_info->ip_port.ip.family;
612
10
    }
613
614
69
    const Socket sock = net_socket(ns, family, TOX_SOCK_STREAM, TOX_PROTO_TCP);
615
616
69
    if (!sock_valid(sock)) {
617
0
        LOGGER_ERROR(logger, "Failed to create TCP socket with family %d", family.value);
618
0
        return nullptr;
619
0
    }
620
621
69
    if (!set_socket_nosigpipe(ns, sock)) {
622
0
        LOGGER_ERROR(logger, "Failed to set TCP socket to ignore SIGPIPE");
623
0
        kill_sock(ns, sock);
624
0
        return nullptr;
625
0
    }
626
627
69
    if (!set_socket_nonblock(ns, sock)) {
628
0
        LOGGER_ERROR(logger, "Failed to set TCP socket to non-blocking");
629
0
        kill_sock(ns, sock);
630
0
        return nullptr;
631
0
    }
632
633
69
    if (!connect_sock_to(ns, logger, mem, sock, ip_port, proxy_info)) {
634
0
        Ip_Ntoa ip_ntoa;
635
0
        LOGGER_WARNING(logger, "Failed to connect TCP socket to %s:%u",
636
0
                       net_ip_ntoa(&ip_port->ip, &ip_ntoa), net_ntohs(ip_port->port));
637
0
        kill_sock(ns, sock);
638
0
        return nullptr;
639
0
    }
640
641
69
    TCP_Client_Connection *temp = (TCP_Client_Connection *)mem_alloc(mem, sizeof(TCP_Client_Connection));
642
643
69
    if (temp == nullptr) {
644
0
        LOGGER_ERROR(logger, "Failed to allocate memory for TCP_Client_Connection");
645
0
        kill_sock(ns, sock);
646
0
        return nullptr;
647
0
    }
648
649
69
    temp->con.ns = ns;
650
69
    temp->con.mem = mem;
651
69
    temp->con.rng = rng;
652
69
    temp->con.sock = sock;
653
69
    temp->con.ip_port = *ip_port;
654
69
    temp->con.net_profile = net_profile;
655
69
    memcpy(temp->public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
656
69
    memcpy(temp->self_public_key, self_public_key, CRYPTO_PUBLIC_KEY_SIZE);
657
69
    encrypt_precompute(temp->public_key, self_secret_key, temp->con.shared_key);
658
69
    temp->ip_port = *ip_port;
659
69
    temp->proxy_info = *proxy_info;
660
661
69
    switch (proxy_info->proxy_type) {
662
1
        case TCP_PROXY_HTTP: {
663
1
            temp->status = TCP_CLIENT_PROXY_HTTP_CONNECTING;
664
1
            proxy_http_generate_connection_request(temp);
665
1
            break;
666
0
        }
667
668
9
        case TCP_PROXY_SOCKS5: {
669
9
            temp->status = TCP_CLIENT_PROXY_SOCKS5_CONNECTING;
670
9
            proxy_socks5_generate_greetings(temp);
671
9
            break;
672
0
        }
673
674
59
        case TCP_PROXY_NONE: {
675
59
            temp->status = TCP_CLIENT_CONNECTING;
676
677
59
            if (generate_handshake(temp) == -1) {
678
0
                LOGGER_ERROR(logger, "Failed to generate handshake");
679
0
                kill_sock(ns, sock);
680
0
                mem_delete(mem, temp);
681
0
                return nullptr;
682
0
            }
683
684
59
            break;
685
59
        }
686
69
    }
687
688
69
    temp->kill_at = mono_time_get(mono_time) + TCP_CONNECTION_TIMEOUT;
689
690
69
    return temp;
691
69
}
692
693
static int handle_tcp_client_routing_response(TCP_Client_Connection *_Nonnull conn, const uint8_t *_Nonnull data, uint16_t length)
694
109
{
695
109
    if (length != 1 + 1 + CRYPTO_PUBLIC_KEY_SIZE) {
696
0
        return -1;
697
0
    }
698
699
109
    if (data[1] < NUM_RESERVED_PORTS) {
700
0
        return 0;
701
0
    }
702
703
109
    const uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
704
705
109
    if (conn->connections[con_id].status != 0) {
706
0
        return 0;
707
0
    }
708
709
109
    conn->connections[con_id].status = 1;
710
109
    conn->connections[con_id].number = -1;
711
109
    memcpy(conn->connections[con_id].public_key, data + 2, CRYPTO_PUBLIC_KEY_SIZE);
712
713
109
    if (conn->response_callback != nullptr) {
714
108
        conn->response_callback(conn->response_callback_object, con_id, conn->connections[con_id].public_key);
715
108
    }
716
717
109
    return 0;
718
109
}
719
720
static int handle_tcp_client_connection_notification(TCP_Client_Connection *_Nonnull conn, const uint8_t *_Nonnull data, uint16_t length)
721
108
{
722
108
    if (length != 1 + 1) {
723
0
        return -1;
724
0
    }
725
726
108
    if (data[1] < NUM_RESERVED_PORTS) {
727
0
        return -1;
728
0
    }
729
730
108
    const uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
731
732
108
    if (conn->connections[con_id].status != 1) {
733
0
        return 0;
734
0
    }
735
736
108
    conn->connections[con_id].status = 2;
737
738
108
    if (conn->status_callback != nullptr) {
739
107
        conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
740
107
                              conn->connections[con_id].status);
741
107
    }
742
743
108
    return 0;
744
108
}
745
746
static int handle_tcp_client_disconnect_notification(TCP_Client_Connection *_Nonnull conn, const uint8_t *_Nonnull data, uint16_t length)
747
2
{
748
2
    if (length != 1 + 1) {
749
0
        return -1;
750
0
    }
751
752
2
    if (data[1] < NUM_RESERVED_PORTS) {
753
0
        return -1;
754
0
    }
755
756
2
    const uint8_t con_id = data[1] - NUM_RESERVED_PORTS;
757
758
2
    if (conn->connections[con_id].status == 0) {
759
0
        return 0;
760
0
    }
761
762
2
    if (conn->connections[con_id].status != 2) {
763
0
        return 0;
764
0
    }
765
766
2
    conn->connections[con_id].status = 1;
767
768
2
    if (conn->status_callback != nullptr) {
769
2
        conn->status_callback(conn->status_callback_object, conn->connections[con_id].number, con_id,
770
2
                              conn->connections[con_id].status);
771
2
    }
772
773
2
    return 0;
774
2
}
775
776
static int handle_tcp_client_ping(const Logger *_Nonnull logger, TCP_Client_Connection *_Nonnull conn, const uint8_t *_Nonnull data, uint16_t length)
777
15
{
778
15
    if (length != 1 + sizeof(uint64_t)) {
779
0
        return -1;
780
0
    }
781
782
15
    uint64_t ping_id;
783
15
    memcpy(&ping_id, data + 1, sizeof(uint64_t));
784
15
    conn->ping_response_id = ping_id;
785
15
    tcp_send_ping_response(logger, conn);
786
15
    return 0;
787
15
}
788
789
static int handle_tcp_client_pong(TCP_Client_Connection *_Nonnull conn, const uint8_t *_Nonnull data, uint16_t length)
790
65
{
791
65
    if (length != 1 + sizeof(uint64_t)) {
792
0
        return -1;
793
0
    }
794
795
65
    uint64_t ping_id;
796
65
    memcpy(&ping_id, data + 1, sizeof(uint64_t));
797
798
65
    if (ping_id != 0) {
799
65
        if (ping_id == conn->ping_id) {
800
65
            conn->ping_id = 0;
801
65
        }
802
803
65
        return 0;
804
65
    }
805
806
0
    return -1;
807
65
}
808
809
static int handle_tcp_client_oob_recv(TCP_Client_Connection *_Nonnull conn, const uint8_t *_Nonnull data, uint16_t length, void *_Nullable userdata)
810
173
{
811
173
    if (length <= 1 + CRYPTO_PUBLIC_KEY_SIZE) {
812
0
        return -1;
813
0
    }
814
815
173
    if (conn->oob_data_callback != nullptr) {
816
173
        conn->oob_data_callback(conn->oob_data_callback_object, data + 1, data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
817
173
                                length - (1 + CRYPTO_PUBLIC_KEY_SIZE), userdata);
818
173
    }
819
820
173
    return 0;
821
173
}
822
823
/**
824
 * @retval 0 on success
825
 * @retval -1 on failure
826
 */
827
static int handle_tcp_client_packet(const Logger *_Nonnull logger, TCP_Client_Connection *_Nonnull conn, const uint8_t *_Nonnull data,
828
                                    uint16_t length, void *_Nullable userdata)
829
2.05k
{
830
2.05k
    if (length <= 1) {
831
0
        return -1;
832
0
    }
833
834
2.05k
    netprof_record_packet(conn->con.net_profile, data[0], length, PACKET_DIRECTION_RECV);
835
836
2.05k
    switch (data[0]) {
837
109
        case TCP_PACKET_ROUTING_RESPONSE:
838
109
            return handle_tcp_client_routing_response(conn, data, length);
839
840
108
        case TCP_PACKET_CONNECTION_NOTIFICATION:
841
108
            return handle_tcp_client_connection_notification(conn, data, length);
842
843
2
        case TCP_PACKET_DISCONNECT_NOTIFICATION:
844
2
            return handle_tcp_client_disconnect_notification(conn, data, length);
845
846
15
        case TCP_PACKET_PING:
847
15
            return handle_tcp_client_ping(logger, conn, data, length);
848
849
65
        case TCP_PACKET_PONG:
850
65
            return handle_tcp_client_pong(conn, data, length);
851
852
173
        case TCP_PACKET_OOB_RECV:
853
173
            return handle_tcp_client_oob_recv(conn, data, length, userdata);
854
855
803
        case TCP_PACKET_ONION_RESPONSE: {
856
803
            if (conn->onion_callback != nullptr) {
857
803
                conn->onion_callback(conn->onion_callback_object, data + 1, length - 1, userdata);
858
803
            }
859
803
            return 0;
860
0
        }
861
862
5
        case TCP_PACKET_FORWARDING: {
863
5
            if (conn->forwarded_response_callback != nullptr) {
864
5
                conn->forwarded_response_callback(conn->forwarded_response_callback_object, data + 1, length - 1, userdata);
865
5
            }
866
5
            return 0;
867
0
        }
868
869
778
        default: {
870
778
            if (data[0] < NUM_RESERVED_PORTS) {
871
0
                return -1;
872
0
            }
873
874
778
            const uint8_t con_id = data[0] - NUM_RESERVED_PORTS;
875
876
778
            if (conn->data_callback != nullptr) {
877
778
                conn->data_callback(conn->data_callback_object, conn->connections[con_id].number, con_id, data + 1, length - 1,
878
778
                                    userdata);
879
778
            }
880
778
        }
881
2.05k
    }
882
883
778
    return 0;
884
2.05k
}
885
886
static bool tcp_process_packet(const Logger *_Nonnull logger, TCP_Client_Connection *_Nonnull conn, void *_Nullable userdata)
887
14.0k
{
888
14.0k
    uint8_t packet[MAX_PACKET_SIZE];
889
14.0k
    const int len = read_packet_tcp_secure_connection(logger, conn->con.mem, conn->con.ns, conn->con.sock, &conn->next_packet_length, conn->con.shared_key, conn->recv_nonce, packet, sizeof(packet),
890
14.0k
                    &conn->ip_port);
891
892
14.0k
    if (len == 0) {
893
11.9k
        return false;
894
11.9k
    }
895
896
2.05k
    if (len == -1) {
897
0
        conn->status = TCP_CLIENT_DISCONNECTED;
898
0
        return false;
899
0
    }
900
901
2.05k
    if (handle_tcp_client_packet(logger, conn, packet, len, userdata) == -1) {
902
0
        conn->status = TCP_CLIENT_DISCONNECTED;
903
0
        return false;
904
0
    }
905
906
2.05k
    return true;
907
2.05k
}
908
909
static int do_confirmed_tcp(const Logger *_Nonnull logger, TCP_Client_Connection *_Nonnull conn, const Mono_Time *_Nonnull mono_time,
910
                            void *_Nullable userdata)
911
11.9k
{
912
11.9k
    send_pending_data(logger, &conn->con);
913
11.9k
    tcp_send_ping_response(logger, conn);
914
11.9k
    tcp_send_ping_request(logger, conn);
915
916
11.9k
    if (mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_FREQUENCY)) {
917
65
        uint64_t ping_id = random_u64(conn->con.rng);
918
919
65
        if (ping_id == 0) {
920
0
            ++ping_id;
921
0
        }
922
923
65
        conn->ping_request_id = ping_id;
924
65
        conn->ping_id = ping_id;
925
65
        tcp_send_ping_request(logger, conn);
926
65
        conn->last_pinged = mono_time_get(mono_time);
927
65
    }
928
929
11.9k
    if (conn->ping_id != 0 && mono_time_is_timeout(mono_time, conn->last_pinged, TCP_PING_TIMEOUT)) {
930
0
        conn->status = TCP_CLIENT_DISCONNECTED;
931
0
        return 0;
932
0
    }
933
934
14.0k
    while (tcp_process_packet(logger, conn, userdata)) {
935
        /* Keep reading until error or out of data. */
936
2.05k
    }
937
938
11.9k
    return 0;
939
11.9k
}
940
941
/** Run the TCP connection */
942
void do_tcp_connection(const Logger *logger, const Mono_Time *mono_time,
943
                       TCP_Client_Connection *tcp_connection, void *userdata)
944
12.3k
{
945
12.3k
    if (tcp_connection->status == TCP_CLIENT_DISCONNECTED) {
946
0
        return;
947
0
    }
948
949
12.3k
    if (tcp_connection->status == TCP_CLIENT_PROXY_HTTP_CONNECTING) {
950
2
        if (send_pending_data(logger, &tcp_connection->con) == 0) {
951
2
            const int ret = proxy_http_read_connection_response(logger, tcp_connection);
952
953
2
            if (ret == -1) {
954
0
                tcp_connection->kill_at = 0;
955
0
                tcp_connection->status = TCP_CLIENT_DISCONNECTED;
956
0
            }
957
958
2
            if (ret == 1) {
959
1
                generate_handshake(tcp_connection);
960
1
                tcp_connection->status = TCP_CLIENT_CONNECTING;
961
1
            }
962
2
        }
963
2
    }
964
965
12.3k
    if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_CONNECTING) {
966
346
        if (send_pending_data(logger, &tcp_connection->con) == 0) {
967
2
            const int ret = socks5_read_handshake_response(logger, tcp_connection);
968
969
2
            if (ret == -1) {
970
0
                tcp_connection->kill_at = 0;
971
0
                tcp_connection->status = TCP_CLIENT_DISCONNECTED;
972
0
            }
973
974
2
            if (ret == 1) {
975
1
                proxy_socks5_generate_connection_request(tcp_connection);
976
1
                tcp_connection->status = TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED;
977
1
            }
978
2
        }
979
346
    }
980
981
12.3k
    if (tcp_connection->status == TCP_CLIENT_PROXY_SOCKS5_UNCONFIRMED) {
982
2
        if (send_pending_data(logger, &tcp_connection->con) == 0) {
983
2
            const int ret = proxy_socks5_read_connection_response(logger, tcp_connection);
984
985
2
            if (ret == -1) {
986
0
                tcp_connection->kill_at = 0;
987
0
                tcp_connection->status = TCP_CLIENT_DISCONNECTED;
988
0
            }
989
990
2
            if (ret == 1) {
991
1
                generate_handshake(tcp_connection);
992
1
                tcp_connection->status = TCP_CLIENT_CONNECTING;
993
1
            }
994
2
        }
995
2
    }
996
997
12.3k
    if (tcp_connection->status == TCP_CLIENT_CONNECTING) {
998
63
        if (send_pending_data(logger, &tcp_connection->con) == 0) {
999
60
            tcp_connection->status = TCP_CLIENT_UNCONFIRMED;
1000
60
        }
1001
63
    }
1002
1003
12.3k
    if (tcp_connection->status == TCP_CLIENT_UNCONFIRMED) {
1004
122
        uint8_t data[TCP_SERVER_HANDSHAKE_SIZE];
1005
122
        const TCP_Connection *con = &tcp_connection->con;
1006
122
        const int len = read_tcp_packet(logger, con->mem, con->ns, con->sock, data, sizeof(data), &con->ip_port);
1007
1008
122
        if (sizeof(data) == len) {
1009
60
            if (handle_handshake(tcp_connection, data) == 0) {
1010
60
                tcp_connection->kill_at = UINT64_MAX;
1011
60
                tcp_connection->status = TCP_CLIENT_CONFIRMED;
1012
60
            } else {
1013
0
                tcp_connection->kill_at = 0;
1014
0
                tcp_connection->status = TCP_CLIENT_DISCONNECTED;
1015
0
            }
1016
60
        }
1017
122
    }
1018
1019
12.3k
    if (tcp_connection->status == TCP_CLIENT_CONFIRMED) {
1020
11.9k
        do_confirmed_tcp(logger, tcp_connection, mono_time, userdata);
1021
11.9k
    }
1022
1023
12.3k
    if (tcp_connection->kill_at <= mono_time_get(mono_time)) {
1024
9
        tcp_connection->status = TCP_CLIENT_DISCONNECTED;
1025
9
    }
1026
12.3k
}
1027
1028
/** Kill the TCP connection */
1029
void kill_tcp_connection(TCP_Client_Connection *tcp_connection)
1030
69
{
1031
69
    if (tcp_connection == nullptr) {
1032
0
        return;
1033
0
    }
1034
1035
69
    const Memory *mem = tcp_connection->con.mem;
1036
1037
69
    wipe_priority_list(tcp_connection->con.mem, tcp_connection->con.priority_queue_start);
1038
69
    kill_sock(tcp_connection->con.ns, tcp_connection->con.sock);
1039
69
    crypto_memzero(tcp_connection, sizeof(TCP_Client_Connection));
1040
69
    mem_delete(mem, tcp_connection);
1041
69
}