Coverage Report

Created: 2026-10-24 08:16

/work/toxcore/onion_client.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2016-2026 The TokTok team.
3
 * Copyright © 2013 Tox project.
4
 */
5
6
/**
7
 * Implementation of the client part of docs/Prevent_Tracking.txt (The part that
8
 * uses the onion stuff to connect to the friend)
9
 */
10
#include "onion_client.h"
11
12
#include <assert.h>
13
#include <string.h>
14
15
#include "DHT.h"
16
#include "LAN_discovery.h"
17
#include "TCP_connection.h"
18
#include "attributes.h"
19
#include "ccompat.h"
20
#include "crypto_core.h"
21
#include "group_announce.h"
22
#include "group_onion_announce.h"
23
#include "list.h"
24
#include "logger.h"
25
#include "mem.h"
26
#include "mono_time.h"
27
#include "net_crypto.h"
28
#include "network.h"
29
#include "onion.h"
30
#include "onion_announce.h"
31
#include "ping_array.h"
32
#include "sort.h"
33
#include "timed_auth.h"
34
#include "util.h"
35
36
/** @brief defines for the array size and timeout for onion announce packets. */
37
1.92k
#define ANNOUNCE_ARRAY_SIZE 256
38
1.92k
#define ANNOUNCE_TIMEOUT 10
39
40
typedef struct Onion_Node {
41
    uint8_t     public_key[CRYPTO_PUBLIC_KEY_SIZE];
42
    IP_Port     ip_port;
43
    uint8_t     ping_id[ONION_PING_ID_SIZE];
44
    uint8_t     data_public_key[CRYPTO_PUBLIC_KEY_SIZE];
45
    uint8_t     is_stored;  // Tribool.
46
47
    uint64_t    added_time;
48
49
    uint64_t    timestamp;
50
51
    uint64_t    last_pinged;
52
53
    uint8_t     pings_since_last_response;
54
55
    uint32_t    path_used;
56
} Onion_Node;
57
58
typedef struct Onion_Client_Paths {
59
    Onion_Path paths[NUMBER_ONION_PATHS];
60
    uint64_t last_path_success[NUMBER_ONION_PATHS];
61
    uint64_t last_path_used[NUMBER_ONION_PATHS];
62
    uint64_t path_creation_time[NUMBER_ONION_PATHS];
63
    /* number of times used without success. */
64
    unsigned int last_path_used_times[NUMBER_ONION_PATHS];
65
} Onion_Client_Paths;
66
67
typedef struct Last_Pinged {
68
    uint8_t     public_key[CRYPTO_PUBLIC_KEY_SIZE];
69
    uint64_t    timestamp;
70
} Last_Pinged;
71
72
struct Onion_Friend {
73
    bool is_valid;
74
    bool is_online;
75
76
    bool know_dht_public_key;
77
    uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
78
    uint8_t real_public_key[CRYPTO_PUBLIC_KEY_SIZE];
79
80
    Onion_Node clients_list[MAX_ONION_CLIENTS];
81
    uint8_t temp_public_key[CRYPTO_PUBLIC_KEY_SIZE];
82
    uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
83
84
    uint64_t last_dht_pk_onion_sent;
85
    uint64_t last_dht_pk_dht_sent;
86
87
    uint64_t last_noreplay;
88
89
    uint64_t last_populated;  // the last time we had a fully populated client nodes list
90
    uint64_t time_last_pinged; // the last time we pinged this friend with any node
91
92
    uint32_t run_count;
93
    uint32_t pings;  // how many sucessful pings we've made for this friend
94
95
    Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
96
    uint8_t last_pinged_index;
97
98
    recv_tcp_relay_cb *_Nullable tcp_relay_node_callback;
99
    void *_Nullable tcp_relay_node_callback_object;
100
    uint32_t tcp_relay_node_callback_number;
101
102
    onion_dht_pk_cb *_Nullable dht_pk_callback;
103
    void *_Nullable dht_pk_callback_object;
104
    uint32_t dht_pk_callback_number;
105
106
    uint8_t  gc_data[GCA_PUBLIC_ANNOUNCE_MAX_SIZE];
107
    uint8_t  gc_public_key[ENC_PUBLIC_KEY_SIZE];
108
    uint16_t gc_data_length;
109
    bool     is_groupchat;
110
};
111
112
static const Onion_Friend empty_onion_friend = {false};
113
114
typedef struct Onion_Data_Handler {
115
    oniondata_handler_cb *_Nullable function;
116
    void *_Nullable object;
117
} Onion_Data_Handler;
118
119
struct Onion_Client {
120
    const Mono_Time *_Nonnull mono_time;
121
    const Logger *_Nonnull logger;
122
    const Random *_Nonnull rng;
123
    const Memory *_Nonnull mem;
124
125
    DHT     *_Nonnull dht;
126
    Net_Crypto *_Nonnull c;
127
    Networking_Core *_Nonnull net;
128
    Onion_Friend    *_Nullable friends_list;
129
    uint32_t       friends_list_capacity;
130
    uint32_t       num_friends;
131
132
    BS_List        friends_lookup;
133
134
    Onion_Node clients_announce_list[MAX_ONION_CLIENTS_ANNOUNCE];
135
    uint64_t last_announce;
136
137
    Onion_Client_Paths onion_paths_self;
138
    Onion_Client_Paths onion_paths_friends;
139
140
    uint8_t secret_symmetric_key[CRYPTO_SYMMETRIC_KEY_SIZE];
141
    uint64_t last_run;
142
    uint64_t first_run;
143
    uint64_t last_time_connected;
144
145
    uint8_t temp_public_key[CRYPTO_PUBLIC_KEY_SIZE];
146
    uint8_t temp_secret_key[CRYPTO_SECRET_KEY_SIZE];
147
148
    Last_Pinged last_pinged[MAX_STORED_PINGED_NODES];
149
150
    Node_format path_nodes[MAX_PATH_NODES];
151
    uint16_t path_nodes_index;
152
153
    Node_format path_nodes_bs[MAX_PATH_NODES];
154
    uint16_t path_nodes_index_bs;
155
156
    Ping_Array *_Nonnull announce_ping_array;
157
    uint8_t last_pinged_index;
158
    Onion_Data_Handler onion_data_handlers[256];
159
160
    uint64_t last_packet_recv;
161
    uint64_t last_populated;  // the last time we had a fully populated path nodes list
162
163
    unsigned int onion_connected;
164
    bool udp_connected;
165
166
    onion_group_announce_cb *_Nullable group_announce_response;
167
    void *_Nullable group_announce_response_user_data;
168
};
169
170
uint32_t onion_get_friend_count(const Onion_Client *const onion_c)
171
124k
{
172
124k
    return onion_c->num_friends;
173
124k
}
174
175
Onion_Friend *onion_get_friend(const Onion_Client *const onion_c, uint32_t friend_num)
176
184k
{
177
184k
    return &onion_c->friends_list[friend_num];
178
184k
}
179
180
const uint8_t *onion_friend_get_gc_public_key(const Onion_Friend *const onion_friend)
181
12.3k
{
182
12.3k
    return onion_friend->gc_public_key;
183
12.3k
}
184
185
const uint8_t *onion_friend_get_gc_public_key_num(const Onion_Client *const onion_c, uint32_t num)
186
1.06k
{
187
1.06k
    return onion_c->friends_list[num].gc_public_key;
188
1.06k
}
189
190
void onion_friend_set_gc_public_key(Onion_Friend *const onion_friend, const uint8_t *public_key)
191
120
{
192
120
    memcpy(onion_friend->gc_public_key, public_key, ENC_PUBLIC_KEY_SIZE);
193
120
}
194
195
void onion_friend_set_gc_data(Onion_Friend *const onion_friend, const uint8_t *gc_data, uint16_t gc_data_length)
196
245
{
197
245
    if (gc_data_length > 0 && gc_data != nullptr) {
198
120
        assert(gc_data_length <= GCA_PUBLIC_ANNOUNCE_MAX_SIZE);
199
120
        memcpy(onion_friend->gc_data, gc_data, gc_data_length);
200
120
    }
201
202
245
    onion_friend->gc_data_length = gc_data_length;
203
245
    onion_friend->is_groupchat = true;
204
245
}
205
206
bool onion_friend_is_groupchat(const Onion_Friend *const onion_friend)
207
184k
{
208
184k
    return onion_friend->is_groupchat;
209
184k
}
210
211
/** @brief Add a node to the path_nodes bootstrap array.
212
 *
213
 * If a node with the given public key was already in the bootstrap array, this function has no
214
 * effect and returns successfully. There is currently no way to update the IP/port for a bootstrap
215
 * node, so if it changes, the Onion_Client must be recreated.
216
 *
217
 * @param onion_c The onion client object.
218
 * @param ip_port IP/port for the bootstrap node.
219
 * @param public_key DHT public key for the bootstrap node.
220
 *
221
 * @retval false on failure
222
 * @retval true on success
223
 */
224
bool onion_add_bs_path_node(Onion_Client *onion_c, const IP_Port *ip_port, const uint8_t *public_key)
225
3.12k
{
226
3.12k
    if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {
227
0
        return false;
228
0
    }
229
230
80.4k
    for (unsigned int i = 0; i < MAX_PATH_NODES; ++i) {
231
78.4k
        if (pk_equal(public_key, onion_c->path_nodes_bs[i].public_key)) {
232
1.16k
            return true;
233
1.16k
        }
234
78.4k
    }
235
236
1.96k
    onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].ip_port = *ip_port;
237
1.96k
    memcpy(onion_c->path_nodes_bs[onion_c->path_nodes_index_bs % MAX_PATH_NODES].public_key, public_key,
238
1.96k
           CRYPTO_PUBLIC_KEY_SIZE);
239
240
1.96k
    const uint16_t last = onion_c->path_nodes_index_bs;
241
1.96k
    ++onion_c->path_nodes_index_bs;
242
243
1.96k
    if (onion_c->path_nodes_index_bs < last) {
244
0
        onion_c->path_nodes_index_bs = MAX_PATH_NODES + 1;
245
0
    }
246
247
1.96k
    return true;
248
3.12k
}
249
250
/** @brief Add a node to the path_nodes array.
251
 *
252
 * return -1 on failure
253
 * return 0 on success
254
 */
255
static int onion_add_path_node(Onion_Client *_Nonnull onion_c, const IP_Port *_Nonnull ip_port, const uint8_t *_Nonnull public_key)
256
166k
{
257
166k
    if (!net_family_is_ipv4(ip_port->ip.family) && !net_family_is_ipv6(ip_port->ip.family)) {
258
6.19k
        return -1;
259
6.19k
    }
260
261
1.15M
    for (unsigned int i = 0; i < MAX_PATH_NODES; ++i) {
262
1.14M
        if (pk_equal(public_key, onion_c->path_nodes[i].public_key)) {
263
150k
            return -1;
264
150k
        }
265
1.14M
    }
266
267
9.82k
    onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].ip_port = *ip_port;
268
9.82k
    memcpy(onion_c->path_nodes[onion_c->path_nodes_index % MAX_PATH_NODES].public_key, public_key,
269
9.82k
           CRYPTO_PUBLIC_KEY_SIZE);
270
271
9.82k
    const uint16_t last = onion_c->path_nodes_index;
272
9.82k
    ++onion_c->path_nodes_index;
273
274
9.82k
    if (onion_c->path_nodes_index < last) {
275
0
        onion_c->path_nodes_index = MAX_PATH_NODES + 1;
276
0
    }
277
278
9.82k
    return 0;
279
159k
}
280
281
/** @brief Put up to max_num nodes in nodes.
282
 *
283
 * return the number of nodes.
284
 */
285
uint16_t onion_backup_nodes(const Onion_Client *onion_c, Node_format *nodes, uint16_t max_num)
286
995
{
287
995
    if (max_num == 0) {
288
0
        return 0;
289
0
    }
290
291
995
    const uint16_t num_nodes = min_u16(onion_c->path_nodes_index, MAX_PATH_NODES);
292
995
    uint16_t i = 0;
293
294
1.00k
    while (i < max_num && i < num_nodes) {
295
13
        nodes[i] = onion_c->path_nodes[(onion_c->path_nodes_index - (1 + i)) % num_nodes];
296
13
        ++i;
297
13
    }
298
299
1.19k
    for (uint16_t j = 0; i < max_num && j < MAX_PATH_NODES && j < onion_c->path_nodes_index_bs; ++j) {
300
199
        bool already_saved = false;
301
302
205
        for (uint16_t k = 0; k < num_nodes; ++k) {
303
10
            if (pk_equal(nodes[k].public_key, onion_c->path_nodes_bs[j].public_key)) {
304
4
                already_saved = true;
305
4
                break;
306
4
            }
307
10
        }
308
309
199
        if (!already_saved) {
310
195
            nodes[i] = onion_c->path_nodes_bs[j];
311
195
            ++i;
312
195
        }
313
199
    }
314
315
995
    return i;
316
995
}
317
318
/** @brief Put up to max_num random nodes in nodes.
319
 *
320
 * return the number of nodes.
321
 */
322
static uint16_t random_nodes_path_onion(const Onion_Client *_Nonnull onion_c, Node_format *_Nonnull nodes, uint16_t max_num)
323
7.66k
{
324
7.66k
    if (max_num == 0) {
325
0
        return 0;
326
0
    }
327
328
7.66k
    const uint16_t num_nodes = min_u16(onion_c->path_nodes_index, MAX_PATH_NODES);
329
330
    // if (dht_non_lan_connected(onion_c->dht)) {
331
7.66k
    if (dht_isconnected(onion_c->dht)) {
332
6.49k
        if (num_nodes == 0) {
333
0
            return 0;
334
0
        }
335
336
25.9k
        for (unsigned int i = 0; i < max_num; ++i) {
337
19.4k
            const uint32_t rand_idx = random_range_u32(onion_c->rng, num_nodes);
338
19.4k
            nodes[i] = onion_c->path_nodes[rand_idx];
339
19.4k
        }
340
6.49k
    } else {
341
1.17k
        const int random_tcp = get_random_tcp_con_number(onion_c->c);
342
343
1.17k
        if (random_tcp == -1) {
344
685
            return 0;
345
685
        }
346
347
487
        if (num_nodes >= 2) {
348
0
            nodes[0] = empty_node_format;
349
0
            nodes[0].ip_port = tcp_connections_number_to_ip_port(random_tcp);
350
351
0
            for (unsigned int i = 1; i < max_num; ++i) {
352
0
                const uint32_t rand_idx = random_range_u32(onion_c->rng, num_nodes);
353
0
                nodes[i] = onion_c->path_nodes[rand_idx];
354
0
            }
355
487
        } else {
356
487
            const uint16_t num_nodes_bs = min_u16(onion_c->path_nodes_index_bs, MAX_PATH_NODES);
357
358
487
            if (num_nodes_bs == 0) {
359
0
                return 0;
360
0
            }
361
362
487
            nodes[0] = empty_node_format;
363
487
            nodes[0].ip_port = tcp_connections_number_to_ip_port(random_tcp);
364
365
1.46k
            for (unsigned int i = 1; i < max_num; ++i) {
366
976
                const uint32_t rand_idx = random_range_u32(onion_c->rng, num_nodes_bs);
367
976
                nodes[i] = onion_c->path_nodes_bs[rand_idx];
368
976
            }
369
487
        }
370
487
    }
371
372
6.98k
    return max_num;
373
7.66k
}
374
375
/**
376
 * return -1 if nodes are suitable for creating a new path.
377
 * return path number of already existing similar path if one already exists.
378
 */
379
static int is_path_used(const Mono_Time *_Nonnull mono_time, const Onion_Client_Paths *_Nonnull onion_paths, const Node_format *_Nonnull nodes)
380
6.98k
{
381
36.3k
    for (unsigned int i = 0; i < NUMBER_ONION_PATHS; ++i) {
382
32.6k
        if (mono_time_is_timeout(mono_time, onion_paths->last_path_success[i], ONION_PATH_TIMEOUT)) {
383
18.3k
            continue;
384
18.3k
        }
385
386
14.2k
        if (mono_time_is_timeout(mono_time, onion_paths->path_creation_time[i], ONION_PATH_MAX_LIFETIME)) {
387
0
            continue;
388
0
        }
389
390
        // TODO(irungentoo): do we really have to check it with the last node?
391
14.2k
        if (ipport_equal(&onion_paths->paths[i].ip_port1, &nodes[ONION_PATH_LENGTH - 1].ip_port)) {
392
3.24k
            return i;
393
3.24k
        }
394
14.2k
    }
395
396
3.73k
    return -1;
397
6.98k
}
398
399
/** is path timed out */
400
static bool path_timed_out(const Mono_Time *_Nonnull mono_time, const Onion_Client_Paths *_Nonnull onion_paths, uint32_t pathnum)
401
65.6k
{
402
65.6k
    pathnum = pathnum % NUMBER_ONION_PATHS;
403
404
65.6k
    const bool is_new = onion_paths->last_path_success[pathnum] == onion_paths->path_creation_time[pathnum];
405
65.6k
    const uint64_t timeout = is_new ? ONION_PATH_FIRST_TIMEOUT : ONION_PATH_TIMEOUT;
406
407
65.6k
    return (onion_paths->last_path_used_times[pathnum] >= ONION_PATH_MAX_NO_RESPONSE_USES
408
65.6k
            && mono_time_is_timeout(mono_time, onion_paths->last_path_used[pathnum], timeout))
409
65.6k
           || mono_time_is_timeout(mono_time, onion_paths->path_creation_time[pathnum], ONION_PATH_MAX_LIFETIME);
410
65.6k
}
411
412
/** should node be considered to have timed out */
413
static bool onion_node_timed_out(const Onion_Node *_Nonnull node, const Mono_Time *_Nonnull mono_time)
414
1.23M
{
415
1.23M
    return node->timestamp == 0
416
1.23M
           || (node->pings_since_last_response >= ONION_NODE_MAX_PINGS
417
598k
               && mono_time_is_timeout(mono_time, node->last_pinged, ONION_NODE_TIMEOUT));
418
1.23M
}
419
420
/** @brief Create a new path or use an old suitable one (if pathnum is valid)
421
 * or a random one from onion_paths.
422
 *
423
 * return -1 on failure
424
 * return 0 on success
425
 *
426
 * TODO(irungentoo): Make this function better, it currently probably is
427
 * vulnerable to some attacks that could deanonimize us.
428
 */
429
static int random_path(const Onion_Client *_Nonnull onion_c, Onion_Client_Paths *_Nonnull onion_paths, uint32_t pathnum, Onion_Path *_Nonnull path)
430
38.0k
{
431
38.0k
    if (pathnum == UINT32_MAX) {
432
33.2k
        pathnum = random_range_u32(onion_c->rng, NUMBER_ONION_PATHS);
433
33.2k
    } else {
434
4.88k
        pathnum = pathnum % NUMBER_ONION_PATHS;
435
4.88k
    }
436
437
38.0k
    if (path_timed_out(onion_c->mono_time, onion_paths, pathnum)) {
438
7.66k
        Node_format nodes[ONION_PATH_LENGTH];
439
440
7.66k
        if (random_nodes_path_onion(onion_c, nodes, ONION_PATH_LENGTH) != ONION_PATH_LENGTH) {
441
685
            return -1;
442
685
        }
443
444
6.98k
        const int n = is_path_used(onion_c->mono_time, onion_paths, nodes);
445
446
6.98k
        if (n == -1) {
447
3.73k
            if (create_onion_path(onion_c->rng, onion_c->dht, &onion_paths->paths[pathnum], nodes) == -1) {
448
0
                return -1;
449
0
            }
450
451
3.73k
            onion_paths->path_creation_time[pathnum] = mono_time_get(onion_c->mono_time);
452
3.73k
            onion_paths->last_path_success[pathnum] = onion_paths->path_creation_time[pathnum];
453
3.73k
            onion_paths->last_path_used_times[pathnum] = ONION_PATH_MAX_NO_RESPONSE_USES / 2;
454
455
3.73k
            uint32_t path_num = random_u32(onion_c->rng);
456
3.73k
            path_num /= NUMBER_ONION_PATHS;
457
3.73k
            path_num *= NUMBER_ONION_PATHS;
458
3.73k
            path_num += pathnum;
459
460
3.73k
            onion_paths->paths[pathnum].path_num = path_num;
461
3.73k
        } else {
462
3.24k
            assert(0 <= n && n < NUMBER_ONION_PATHS);
463
3.24k
            pathnum = n;
464
3.24k
        }
465
6.98k
    }
466
467
37.3k
    if (onion_paths->last_path_used_times[pathnum] < ONION_PATH_MAX_NO_RESPONSE_USES) {
468
31.7k
        onion_paths->last_path_used[pathnum] = mono_time_get(onion_c->mono_time);
469
31.7k
    }
470
471
37.3k
    ++onion_paths->last_path_used_times[pathnum];
472
37.3k
    *path = onion_paths->paths[pathnum];
473
37.3k
    return 0;
474
38.0k
}
475
476
/** Set path timeouts, return the path number. */
477
static uint32_t set_path_timeouts(Onion_Client *_Nonnull onion_c, uint32_t num, uint32_t path_num)
478
33.3k
{
479
33.3k
    if (num > onion_c->num_friends) {
480
0
        return -1;
481
0
    }
482
483
33.3k
    Onion_Client_Paths *onion_paths;
484
485
33.3k
    if (num == 0) {
486
21.5k
        onion_paths = &onion_c->onion_paths_self;
487
21.5k
    } else {
488
11.8k
        onion_paths = &onion_c->onion_paths_friends;
489
11.8k
    }
490
491
33.3k
    if (onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num) {
492
33.0k
        onion_paths->last_path_success[path_num % NUMBER_ONION_PATHS] = mono_time_get(onion_c->mono_time);
493
33.0k
        onion_paths->last_path_used_times[path_num % NUMBER_ONION_PATHS] = 0;
494
495
33.0k
        Node_format nodes[ONION_PATH_LENGTH];
496
497
33.0k
        if (onion_path_to_nodes(nodes, ONION_PATH_LENGTH, &onion_paths->paths[path_num % NUMBER_ONION_PATHS]) == 0) {
498
132k
            for (unsigned int i = 0; i < ONION_PATH_LENGTH; ++i) {
499
99.1k
                onion_add_path_node(onion_c, &nodes[i].ip_port, nodes[i].public_key);
500
99.1k
            }
501
33.0k
        }
502
503
33.0k
        return path_num;
504
33.0k
    }
505
506
301
    return -1;
507
33.3k
}
508
509
/** @brief Function to send onion packet via TCP and UDP.
510
 *
511
 * return -1 on failure.
512
 * return 0 on success.
513
 */
514
static int send_onion_packet_tcp_udp(const Onion_Client *_Nonnull onion_c, const Onion_Path *_Nonnull path, const IP_Port *_Nonnull dest, const uint8_t *_Nonnull data, uint16_t length)
515
37.3k
{
516
37.3k
    if (net_family_is_ipv4(path->ip_port1.ip.family) || net_family_is_ipv6(path->ip_port1.ip.family)) {
517
30.8k
        uint8_t packet[ONION_MAX_PACKET_SIZE];
518
30.8k
        const int len = create_onion_packet(onion_c->mem, onion_c->rng, packet, sizeof(packet), path, dest, data, length);
519
520
30.8k
        if (len == -1) {
521
0
            return -1;
522
0
        }
523
524
30.8k
        if (sendpacket(onion_c->net, &path->ip_port1, packet, len) != len) {
525
0
            return -1;
526
0
        }
527
528
30.8k
        return 0;
529
30.8k
    }
530
531
6.54k
    unsigned int tcp_connections_number;
532
533
6.54k
    if (ip_port_to_tcp_connections_number(&path->ip_port1, &tcp_connections_number)) {
534
6.54k
        uint8_t packet[ONION_MAX_PACKET_SIZE];
535
6.54k
        const int len = create_onion_packet_tcp(onion_c->mem, onion_c->rng, packet, sizeof(packet), path, dest, data, length);
536
537
6.54k
        if (len == -1) {
538
0
            return -1;
539
0
        }
540
541
6.54k
        return send_tcp_onion_request(onion_c->c, tcp_connections_number, packet, len);
542
6.54k
    }
543
544
6
    return -1;
545
6.54k
}
546
547
/** @brief Creates a sendback for use in an announce request.
548
 *
549
 * num is 0 if we used our secret public key for the announce
550
 * num is 1 + friendnum if we use a temporary one.
551
 *
552
 * Public key is the key we will be sending it to.
553
 * ip_port is the ip_port of the node we will be sending
554
 * it to.
555
 *
556
 * sendback must be at least ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
557
 *
558
 * return -1 on failure
559
 * return 0 on success
560
 *
561
 */
562
static int new_sendback(Onion_Client *_Nonnull onion_c, uint32_t num, const uint8_t *_Nonnull public_key, const IP_Port *_Nonnull ip_port, uint32_t path_num, uint64_t *_Nonnull sendback)
563
35.2k
{
564
35.2k
    uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
565
35.2k
    memcpy(data, &num, sizeof(uint32_t));
566
35.2k
    memcpy(&data[sizeof(uint32_t)], public_key, CRYPTO_PUBLIC_KEY_SIZE);
567
35.2k
    const int packed_len = pack_ip_port(onion_c->logger, &data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE], SIZE_IPPORT, ip_port);
568
35.2k
    if (packed_len < 0) {
569
0
        LOGGER_ERROR(onion_c->logger, "failed to pack IP/port");
570
0
        return -1;
571
0
    }
572
35.2k
    assert(packed_len <= SIZE_IPPORT);
573
35.2k
    memzero(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + packed_len], SIZE_IPPORT - packed_len);
574
35.2k
    memcpy(&data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT], &path_num, sizeof(uint32_t));
575
35.2k
    *sendback = ping_array_add(onion_c->announce_ping_array, onion_c->mono_time, onion_c->rng, data, sizeof(data));
576
577
35.2k
    if (*sendback == 0) {
578
0
        LOGGER_TRACE(onion_c->logger, "generating sendback in announce ping array failed");
579
0
        return -1;
580
0
    }
581
582
35.2k
    return 0;
583
35.2k
}
584
585
/** @brief Checks if the sendback is valid and returns the public key contained in it in ret_pubkey and the
586
 * ip contained in it in ret_ip_port
587
 *
588
 * sendback is the sendback ONION_ANNOUNCE_SENDBACK_DATA_LENGTH big
589
 * ret_pubkey must be at least CRYPTO_PUBLIC_KEY_SIZE big
590
 * ret_ip_port must be at least 1 big
591
 *
592
 * return -1 on failure
593
 * return num (see new_sendback(...)) on success
594
 */
595
static uint32_t check_sendback(Onion_Client *_Nonnull onion_c, const uint8_t *_Nonnull sendback, uint8_t *_Nonnull ret_pubkey, IP_Port *_Nonnull ret_ip_port, uint32_t *_Nonnull path_num)
596
33.9k
{
597
33.9k
    uint64_t sback;
598
33.9k
    memcpy(&sback, sendback, sizeof(uint64_t));
599
33.9k
    uint8_t data[sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT + sizeof(uint32_t)];
600
601
33.9k
    if (ping_array_check(onion_c->announce_ping_array, onion_c->mono_time, data, sizeof(data), sback) != sizeof(data)) {
602
604
        return -1;
603
604
    }
604
605
33.3k
    memcpy(ret_pubkey, data + sizeof(uint32_t), CRYPTO_PUBLIC_KEY_SIZE);
606
33.3k
    unpack_ip_port(ret_ip_port, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE, SIZE_IPPORT, false);
607
33.3k
    memcpy(path_num, data + sizeof(uint32_t) + CRYPTO_PUBLIC_KEY_SIZE + SIZE_IPPORT, sizeof(uint32_t));
608
609
33.3k
    uint32_t num;
610
33.3k
    memcpy(&num, data, sizeof(uint32_t));
611
33.3k
    return num;
612
33.9k
}
613
614
static int client_send_announce_request(Onion_Client *_Nonnull onion_c, uint32_t num, const IP_Port *_Nonnull dest,
615
                                        const uint8_t *_Nonnull dest_pubkey, const uint8_t *_Nullable ping_id, uint32_t pathnum)
616
35.9k
{
617
35.9k
    if (num > onion_c->num_friends) {
618
0
        LOGGER_TRACE(onion_c->logger, "not sending announce to out of bounds friend %u (num friends: %u)", num, onion_c->num_friends);
619
0
        return -1;
620
0
    }
621
622
35.9k
    uint64_t sendback;
623
35.9k
    Onion_Path path;
624
625
35.9k
    if (num == 0) {
626
23.6k
        if (random_path(onion_c, &onion_c->onion_paths_self, pathnum, &path) == -1) {
627
685
            LOGGER_TRACE(onion_c->logger, "cannot find path to self");
628
685
            return -1;
629
685
        }
630
23.6k
    } else {
631
12.3k
        if (random_path(onion_c, &onion_c->onion_paths_friends, pathnum, &path) == -1) {
632
0
            LOGGER_TRACE(onion_c->logger, "cannot find path to friend");
633
0
            return -1;
634
0
        }
635
12.3k
    }
636
637
35.2k
    if (new_sendback(onion_c, num, dest_pubkey, dest, path.path_num, &sendback) == -1) {
638
0
        return -1;
639
0
    }
640
641
35.2k
    uint8_t zero_ping_id[ONION_PING_ID_SIZE] = {0};
642
643
35.2k
    if (ping_id == nullptr) {
644
30.2k
        ping_id = zero_ping_id;
645
30.2k
    }
646
647
35.2k
    uint8_t request[ONION_ANNOUNCE_REQUEST_MAX_SIZE];
648
35.2k
    int len;
649
650
35.2k
    if (num == 0) {
651
22.9k
        len = create_announce_request(
652
22.9k
                  onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, nc_get_self_public_key(onion_c->c),
653
22.9k
                  nc_get_self_secret_key(onion_c->c), ping_id, nc_get_self_public_key(onion_c->c),
654
22.9k
                  onion_c->temp_public_key, sendback);
655
22.9k
    } else {
656
12.3k
        Onion_Friend *onion_friend = &onion_c->friends_list[num - 1];
657
658
12.3k
        if (onion_friend->gc_data_length == 0) { // contact is a friend
659
11.1k
            len = create_announce_request(
660
11.1k
                      onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key,
661
11.1k
                      onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key,
662
11.1k
                      zero_ping_id, sendback);
663
11.1k
        } else { // contact is a gc
664
1.13k
            onion_friend->is_groupchat = true;
665
666
1.13k
            len = create_gca_announce_request(
667
1.13k
                      onion_c->mem, onion_c->rng, request, sizeof(request), dest_pubkey, onion_friend->temp_public_key,
668
1.13k
                      onion_friend->temp_secret_key, ping_id, onion_friend->real_public_key,
669
1.13k
                      zero_ping_id, sendback, onion_friend->gc_data,
670
1.13k
                      onion_friend->gc_data_length);
671
1.13k
        }
672
12.3k
    }
673
674
35.2k
    if (len == -1) {
675
0
        LOGGER_TRACE(onion_c->logger, "failed to create announce request");
676
0
        return -1;
677
0
    }
678
679
35.2k
    Ip_Ntoa ip_str;
680
35.2k
    LOGGER_TRACE(onion_c->logger, "sending onion packet to %s:%d (%02x, %d bytes)",
681
35.2k
                 net_ip_ntoa(&dest->ip, &ip_str), net_ntohs(dest->port), request[0], len);
682
35.2k
    return send_onion_packet_tcp_udp(onion_c, &path, dest, request, len);
683
35.2k
}
684
685
typedef struct Onion_Node_Cmp {
686
    const Memory *_Nonnull mem;
687
    const Mono_Time *_Nonnull mono_time;
688
    const uint8_t *_Nonnull comp_public_key;
689
} Onion_Node_Cmp;
690
691
static int onion_node_cmp(const Onion_Node_Cmp *_Nonnull cmp, const Onion_Node *_Nonnull entry1, const Onion_Node *_Nonnull entry2)
692
372k
{
693
372k
    const bool t1 = onion_node_timed_out(entry1, cmp->mono_time);
694
372k
    const bool t2 = onion_node_timed_out(entry2, cmp->mono_time);
695
696
372k
    if (t1 && t2) {
697
132k
        return 0;
698
132k
    }
699
700
240k
    if (t1) {
701
32.2k
        return -1;
702
32.2k
    }
703
704
208k
    if (t2) {
705
20.1k
        return 1;
706
20.1k
    }
707
708
188k
    const int closest = id_closest(cmp->comp_public_key, entry1->public_key, entry2->public_key);
709
710
188k
    if (closest == 1) {
711
158k
        return 1;
712
158k
    }
713
714
29.9k
    if (closest == 2) {
715
29.9k
        return -1;
716
29.9k
    }
717
718
18.4E
    return 0;
719
29.9k
}
720
721
static bool onion_node_less_handler(const void *_Nonnull object, const void *_Nonnull a, const void *_Nonnull b)
722
372k
{
723
372k
    const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object;
724
372k
    const Onion_Node *entry1 = (const Onion_Node *)a;
725
372k
    const Onion_Node *entry2 = (const Onion_Node *)b;
726
727
372k
    return onion_node_cmp(cmp, entry1, entry2) < 0;
728
372k
}
729
730
static const void *_Nonnull onion_node_get_handler(const void *_Nonnull arr, uint32_t index)
731
754k
{
732
754k
    const Onion_Node *entries = (const Onion_Node *)arr;
733
754k
    return &entries[index];
734
754k
}
735
736
static void onion_node_set_handler(void *_Nonnull arr, uint32_t index, const void *_Nonnull val)
737
700k
{
738
700k
    Onion_Node *entries = (Onion_Node *)arr;
739
700k
    const Onion_Node *entry = (const Onion_Node *)val;
740
700k
    entries[index] = *entry;
741
700k
}
742
743
static void *_Nonnull onion_node_subarr_handler(void *_Nonnull arr, uint32_t index, uint32_t size)
744
0
{
745
0
    Onion_Node *entries = (Onion_Node *)arr;
746
0
    return &entries[index];
747
0
}
748
749
static void *_Nullable onion_node_alloc_handler(const void *_Nonnull object, uint32_t size)
750
33.3k
{
751
33.3k
    const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object;
752
33.3k
    Onion_Node *tmp = (Onion_Node *)mem_valloc(cmp->mem, size, sizeof(Onion_Node));
753
754
33.3k
    if (tmp == nullptr) {
755
0
        return nullptr;
756
0
    }
757
758
33.3k
    return tmp;
759
33.3k
}
760
761
static void onion_node_delete_handler(const void *_Nonnull object, void *_Nonnull arr, uint32_t size)
762
33.3k
{
763
33.3k
    const Onion_Node_Cmp *cmp = (const Onion_Node_Cmp *)object;
764
33.3k
    mem_delete(cmp->mem, arr);
765
33.3k
}
766
767
static const Sort_Funcs onion_node_cmp_funcs = {
768
    onion_node_less_handler,
769
    onion_node_get_handler,
770
    onion_node_set_handler,
771
    onion_node_subarr_handler,
772
    onion_node_alloc_handler,
773
    onion_node_delete_handler,
774
};
775
776
static void sort_onion_node_list(const Memory *_Nonnull mem, const Mono_Time *_Nonnull mono_time, Onion_Node *_Nonnull list, unsigned int length, const uint8_t *_Nonnull comp_public_key)
777
33.3k
{
778
    // Pass comp_public_key to sort with each Onion_Node entry, so the
779
    // comparison function can use it as the base of comparison.
780
33.3k
    const Onion_Node_Cmp cmp = {
781
33.3k
        mem,
782
33.3k
        mono_time,
783
33.3k
        comp_public_key,
784
33.3k
    };
785
786
33.3k
    merge_sort(list, length, &cmp, &onion_node_cmp_funcs);
787
33.3k
}
788
789
static int client_add_to_list(Onion_Client *_Nonnull onion_c, uint32_t num, const uint8_t *_Nonnull public_key, const IP_Port *_Nonnull ip_port, uint8_t is_stored,
790
                              const uint8_t *_Nonnull pingid_or_key, uint32_t path_used)
791
33.3k
{
792
33.3k
    if (num > onion_c->num_friends) {
793
0
        return -1;
794
0
    }
795
796
33.3k
    Onion_Node *node_list = nullptr;
797
33.3k
    const uint8_t *reference_id = nullptr;
798
33.3k
    unsigned int list_length;
799
800
33.3k
    if (num == 0) {
801
21.5k
        node_list = onion_c->clients_announce_list;
802
21.5k
        reference_id = nc_get_self_public_key(onion_c->c);
803
21.5k
        list_length = MAX_ONION_CLIENTS_ANNOUNCE;
804
805
21.5k
        if (is_stored == 1 && !pk_equal(pingid_or_key, onion_c->temp_public_key)) {
806
0
            is_stored = 0;
807
0
        }
808
21.5k
    } else {
809
11.8k
        if (is_stored >= 2) {
810
0
            return -1;
811
0
        }
812
813
11.8k
        node_list = onion_c->friends_list[num - 1].clients_list;
814
11.8k
        reference_id = onion_c->friends_list[num - 1].real_public_key;
815
11.8k
        list_length = MAX_ONION_CLIENTS;
816
11.8k
    }
817
818
33.3k
    sort_onion_node_list(onion_c->mem, onion_c->mono_time, node_list, list_length, reference_id);
819
820
33.3k
    int index = -1;
821
33.3k
    bool stored = false;
822
823
33.3k
    if (onion_node_timed_out(&node_list[0], onion_c->mono_time)
824
33.3k
            || id_closest(reference_id, node_list[0].public_key, public_key) == 2) {
825
31.3k
        index = 0;
826
31.3k
    }
827
828
313k
    for (unsigned int i = 0; i < list_length; ++i) {
829
303k
        if (pk_equal(node_list[i].public_key, public_key)) {
830
22.5k
            index = i;
831
22.5k
            stored = true;
832
22.5k
            break;
833
22.5k
        }
834
303k
    }
835
836
33.3k
    if (index == -1) {
837
1.49k
        return 0;
838
1.49k
    }
839
840
31.8k
    memcpy(node_list[index].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
841
31.8k
    node_list[index].ip_port = *ip_port;
842
843
    // TODO(irungentoo): remove this and find a better source of nodes to use for paths.
844
31.8k
    onion_add_path_node(onion_c, ip_port, public_key);
845
846
31.8k
    if (is_stored == 1) {
847
8.81k
        memcpy(node_list[index].data_public_key, pingid_or_key, CRYPTO_PUBLIC_KEY_SIZE);
848
23.0k
    } else {
849
23.0k
        memcpy(node_list[index].ping_id, pingid_or_key, ONION_PING_ID_SIZE);
850
23.0k
    }
851
852
31.8k
    node_list[index].is_stored = is_stored;
853
31.8k
    node_list[index].timestamp = mono_time_get(onion_c->mono_time);
854
31.8k
    node_list[index].pings_since_last_response = 0;
855
856
31.8k
    if (!stored) {
857
9.28k
        node_list[index].last_pinged = 0;
858
9.28k
        node_list[index].added_time = mono_time_get(onion_c->mono_time);
859
9.28k
    }
860
861
31.8k
    node_list[index].path_used = path_used;
862
31.8k
    return 0;
863
33.3k
}
864
865
static bool good_to_ping(const Mono_Time *_Nonnull mono_time, Last_Pinged *_Nonnull last_pinged, uint8_t *_Nonnull last_pinged_index, const uint8_t *_Nonnull public_key)
866
27.3k
{
867
160k
    for (unsigned int i = 0; i < MAX_STORED_PINGED_NODES; ++i) {
868
151k
        if (!mono_time_is_timeout(mono_time, last_pinged[i].timestamp, MIN_NODE_PING_TIME)) {
869
125k
            if (pk_equal(last_pinged[i].public_key, public_key)) {
870
18.9k
                return false;
871
18.9k
            }
872
125k
        }
873
151k
    }
874
875
8.37k
    memcpy(last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
876
8.37k
    last_pinged[*last_pinged_index % MAX_STORED_PINGED_NODES].timestamp = mono_time_get(mono_time);
877
8.37k
    ++*last_pinged_index;
878
8.37k
    return true;
879
27.3k
}
880
881
static int client_ping_nodes(Onion_Client *_Nonnull onion_c, uint32_t num, const Node_format *_Nonnull nodes, uint16_t num_nodes, const IP_Port *_Nonnull source)
882
33.3k
{
883
33.3k
    if (num > onion_c->num_friends) {
884
0
        return -1;
885
0
    }
886
887
33.3k
    if (num_nodes == 0) {
888
0
        return 0;
889
0
    }
890
891
33.3k
    const Onion_Node *node_list = nullptr;
892
33.3k
    const uint8_t *reference_id = nullptr;
893
33.3k
    unsigned int list_length;
894
895
33.3k
    Last_Pinged *last_pinged = nullptr;
896
33.3k
    uint8_t *last_pinged_index = nullptr;
897
898
33.3k
    if (num == 0) {
899
21.5k
        node_list = onion_c->clients_announce_list;
900
21.5k
        reference_id = nc_get_self_public_key(onion_c->c);
901
21.5k
        list_length = MAX_ONION_CLIENTS_ANNOUNCE;
902
21.5k
        last_pinged = onion_c->last_pinged;
903
21.5k
        last_pinged_index = &onion_c->last_pinged_index;
904
21.5k
    } else {
905
11.8k
        node_list = onion_c->friends_list[num - 1].clients_list;
906
11.8k
        reference_id = onion_c->friends_list[num - 1].real_public_key;
907
11.8k
        list_length = MAX_ONION_CLIENTS;
908
11.8k
        last_pinged = onion_c->friends_list[num - 1].last_pinged;
909
11.8k
        last_pinged_index = &onion_c->friends_list[num - 1].last_pinged_index;
910
11.8k
    }
911
912
33.3k
    const bool lan_ips_accepted = ip_is_lan(&source->ip);
913
914
137k
    for (uint32_t i = 0; i < num_nodes; ++i) {
915
104k
        if (!lan_ips_accepted) {
916
19.9k
            if (ip_is_lan(&nodes[i].ip_port.ip)) {
917
6.62k
                continue;
918
6.62k
            }
919
19.9k
        }
920
921
97.5k
        if (onion_node_timed_out(&node_list[0], onion_c->mono_time)
922
97.5k
                || id_closest(reference_id, node_list[0].public_key, nodes[i].public_key) == 2
923
97.5k
                || onion_node_timed_out(&node_list[1], onion_c->mono_time)
924
97.5k
                || id_closest(reference_id, node_list[1].public_key, nodes[i].public_key) == 2) {
925
96.1k
            uint32_t j;
926
927
            /* check if node is already in list. */
928
950k
            for (j = 0; j < list_length; ++j) {
929
923k
                if (pk_equal(node_list[j].public_key, nodes[i].public_key)) {
930
68.8k
                    break;
931
68.8k
                }
932
923k
            }
933
934
96.1k
            if (!net_socket_family_compatible(onion_c->net, &nodes[i].ip_port, false)) {
935
0
                continue;
936
0
            }
937
938
96.1k
            if (j == list_length && good_to_ping(onion_c->mono_time, last_pinged, last_pinged_index, nodes[i].public_key)) {
939
8.38k
                client_send_announce_request(onion_c, num, &nodes[i].ip_port, nodes[i].public_key, nullptr, -1);
940
8.38k
            }
941
96.1k
        }
942
97.5k
    }
943
944
33.3k
    return 0;
945
33.3k
}
946
947
static bool handle_group_announce_response(Onion_Client *_Nonnull onion_c, uint32_t num, const uint8_t *_Nonnull plain, size_t plain_size)
948
1.06k
{
949
1.06k
    if (onion_c->group_announce_response == nullptr) {
950
0
        return true;
951
0
    }
952
953
1.06k
    return onion_c->group_announce_response(onion_c, num, plain, plain_size, onion_c->group_announce_response_user_data);
954
1.06k
}
955
956
static int handle_announce_response(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length,
957
                                    void *_Nullable userdata)
958
1.13k
{
959
1.13k
    Onion_Client *onion_c = (Onion_Client *)object;
960
1.13k
    if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > GCA_ANNOUNCE_RESPONSE_MAX_SIZE) {
961
0
        LOGGER_TRACE(onion_c->logger, "invalid announce response length: %u (min: %u, max: %u)",
962
0
                     length, (unsigned int)ONION_ANNOUNCE_RESPONSE_MIN_SIZE, (unsigned int)GCA_ANNOUNCE_RESPONSE_MAX_SIZE);
963
0
        return 1;
964
0
    }
965
966
1.13k
    uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE] = {0};
967
1.13k
    IP_Port ip_port = {{{0}}};
968
1.13k
    uint32_t path_num = 0;
969
1.13k
    const uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port, &path_num);
970
971
1.13k
    if (num > onion_c->num_friends) {
972
2
        return 1;
973
2
    }
974
975
1.13k
    uint8_t plain[1 + ONION_PING_ID_SIZE + GCA_ANNOUNCE_RESPONSE_MAX_SIZE - ONION_ANNOUNCE_RESPONSE_MIN_SIZE];
976
1.13k
    const uint32_t plain_size = 1 + ONION_PING_ID_SIZE + length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
977
1.13k
    int len;
978
1.13k
    const uint16_t nonce_start = 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH;
979
1.13k
    const uint16_t ciphertext_start = nonce_start + CRYPTO_NONCE_SIZE;
980
1.13k
    const uint16_t ciphertext_size = length - ciphertext_start;
981
982
1.13k
    if (num == 0) {
983
2
        len = decrypt_data(onion_c->mem, public_key, nc_get_self_secret_key(onion_c->c),
984
2
                           &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
985
1.13k
    } else {
986
1.13k
        if (!onion_c->friends_list[num - 1].is_valid) {
987
0
            LOGGER_TRACE(onion_c->logger, "friend number %lu is invalid", (unsigned long)(num - 1));
988
0
            return 1;
989
0
        }
990
991
1.13k
        len = decrypt_data(onion_c->mem, public_key, onion_c->friends_list[num - 1].temp_secret_key,
992
1.13k
                           &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
993
1.13k
    }
994
995
1.13k
    if (len < 0) {
996
        // This happens a lot, so don't log it.
997
0
        return 1;
998
0
    }
999
1000
1.13k
    if ((uint32_t)len != plain_size) {
1001
0
        LOGGER_WARNING(onion_c->logger, "decrypted size (%lu) is not the expected plain text size (%lu)", (unsigned long)len, (unsigned long)plain_size);
1002
0
        return 1;
1003
0
    }
1004
1005
1.13k
    const uint32_t path_used = set_path_timeouts(onion_c, num, path_num);
1006
1007
1.13k
    if (client_add_to_list(onion_c, num, public_key, &ip_port, plain[0], plain + 1, path_used) == -1) {
1008
0
        LOGGER_WARNING(onion_c->logger, "failed to add client to list");
1009
0
        return 1;
1010
0
    }
1011
1012
1.13k
    uint16_t len_nodes = 0;
1013
1014
1.13k
    if (plain_size <= 1 + ONION_PING_ID_SIZE) {
1015
2
        return 1;
1016
2
    }
1017
1018
1.13k
    const uint8_t nodes_count = plain[1 + ONION_PING_ID_SIZE];
1019
1020
1.13k
    if (nodes_count > 0) {
1021
1.13k
        if (nodes_count > MAX_SENT_NODES) {
1022
0
            return 1;
1023
0
        }
1024
1025
1.13k
        Node_format nodes[MAX_SENT_NODES];
1026
1.13k
        const int num_nodes = unpack_nodes(nodes, nodes_count, &len_nodes, plain + 2 + ONION_PING_ID_SIZE,
1027
1.13k
                                           plain_size - 2 - ONION_PING_ID_SIZE, false);
1028
1029
1.13k
        if (num_nodes < 0) {
1030
0
            LOGGER_WARNING(onion_c->logger, "no nodes to unpack in onion response");
1031
0
            return 1;
1032
0
        }
1033
1034
1.13k
        if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) {
1035
0
            LOGGER_WARNING(onion_c->logger, "pinging %d nodes failed", num_nodes);
1036
0
            return 1;
1037
0
        }
1038
1.13k
    }
1039
1040
1.13k
    if (len_nodes + 1 < length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE) {
1041
1.06k
        const uint16_t offset = 2 + ONION_PING_ID_SIZE + len_nodes;
1042
1043
1.06k
        if (plain_size < offset) {
1044
0
            return 1;
1045
0
        }
1046
1047
1.06k
        if (!handle_group_announce_response(onion_c, num, plain + offset, plain_size - offset)) {
1048
0
            return 1;
1049
0
        }
1050
1.06k
    }
1051
1052
    // TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline?
1053
1.13k
    onion_c->last_packet_recv = mono_time_get(onion_c->mono_time);
1054
1.13k
    LOGGER_TRACE(onion_c->logger, "onion has received a packet at %llu",
1055
1.13k
                 (unsigned long long)onion_c->last_packet_recv);
1056
1057
1.13k
    return 0;
1058
1.13k
}
1059
1060
/* TODO(jfreegman): DEPRECATE */
1061
static int handle_announce_response_old(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length,
1062
                                        void *_Nullable userdata)
1063
32.8k
{
1064
32.8k
    Onion_Client *onion_c = (Onion_Client *)object;
1065
32.8k
    if (length < ONION_ANNOUNCE_RESPONSE_MIN_SIZE || length > ONION_ANNOUNCE_RESPONSE_MAX_SIZE) {
1066
0
        LOGGER_TRACE(onion_c->logger, "invalid announce response length: %u (min: %u, max: %u)",
1067
0
                     length, (unsigned int)ONION_ANNOUNCE_RESPONSE_MIN_SIZE, (unsigned int)ONION_ANNOUNCE_RESPONSE_MAX_SIZE);
1068
0
        return 1;
1069
0
    }
1070
1071
32.8k
    const uint16_t len_nodes = length - ONION_ANNOUNCE_RESPONSE_MIN_SIZE;
1072
1073
32.8k
    uint8_t public_key[CRYPTO_PUBLIC_KEY_SIZE] = {0};
1074
32.8k
    IP_Port ip_port = {{{0}}};
1075
32.8k
    uint32_t path_num = 0;
1076
32.8k
    const uint32_t num = check_sendback(onion_c, packet + 1, public_key, &ip_port, &path_num);
1077
1078
32.8k
    if (num > onion_c->num_friends) {
1079
604
        return 1;
1080
604
    }
1081
1082
32.2k
    const uint16_t plain_size = 1 + ONION_PING_ID_SIZE + len_nodes;
1083
32.2k
    VLA(uint8_t, plain, plain_size);
1084
32.2k
    int len;
1085
32.2k
    const uint16_t nonce_start = 1 + ONION_ANNOUNCE_SENDBACK_DATA_LENGTH;
1086
32.2k
    const uint16_t ciphertext_start = nonce_start + CRYPTO_NONCE_SIZE;
1087
32.2k
    const uint16_t ciphertext_size = length - ciphertext_start;
1088
1089
32.2k
    if (num == 0) {
1090
21.5k
        len = decrypt_data(onion_c->mem, public_key, nc_get_self_secret_key(onion_c->c),
1091
21.5k
                           &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
1092
21.5k
    } else {
1093
10.7k
        if (!onion_c->friends_list[num - 1].is_valid) {
1094
8
            LOGGER_TRACE(onion_c->logger, "friend number %lu is invalid", (unsigned long)(num - 1));
1095
8
            return 1;
1096
8
        }
1097
1098
10.7k
        len = decrypt_data(onion_c->mem, public_key, onion_c->friends_list[num - 1].temp_secret_key,
1099
10.7k
                           &packet[nonce_start], &packet[ciphertext_start], ciphertext_size, plain);
1100
10.7k
    }
1101
1102
32.2k
    if (len < 0) {
1103
        // This happens a lot, so don't log it.
1104
51
        return 1;
1105
51
    }
1106
1107
32.2k
    if ((uint32_t)len != plain_size) {
1108
0
        LOGGER_WARNING(onion_c->logger, "decrypted size (%lu) is not the expected plain text size (%u)", (unsigned long)len, plain_size);
1109
0
        return 1;
1110
0
    }
1111
1112
32.2k
    const uint32_t path_used = set_path_timeouts(onion_c, num, path_num);
1113
1114
32.2k
    if (client_add_to_list(onion_c, num, public_key, &ip_port, plain[0], plain + 1, path_used) == -1) {
1115
0
        LOGGER_WARNING(onion_c->logger, "failed to add client to list");
1116
0
        return 1;
1117
0
    }
1118
1119
32.2k
    if (len_nodes != 0) {
1120
32.2k
        Node_format nodes[MAX_SENT_NODES];
1121
32.2k
        const int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, nullptr, plain + 1 + ONION_PING_ID_SIZE, len_nodes, false);
1122
1123
32.2k
        if (num_nodes <= 0) {
1124
0
            LOGGER_WARNING(onion_c->logger, "no nodes to unpack in onion response");
1125
0
            return 1;
1126
0
        }
1127
1128
32.2k
        if (client_ping_nodes(onion_c, num, nodes, num_nodes, source) == -1) {
1129
0
            LOGGER_WARNING(onion_c->logger, "pinging %d nodes failed", num_nodes);
1130
0
            return 1;
1131
0
        }
1132
32.2k
    }
1133
1134
    // TODO(irungentoo): LAN vs non LAN ips?, if we are connected only to LAN, are we offline?
1135
32.2k
    onion_c->last_packet_recv = mono_time_get(onion_c->mono_time);
1136
32.2k
    LOGGER_TRACE(onion_c->logger, "onion has received a packet at %llu",
1137
32.2k
                 (unsigned long long)onion_c->last_packet_recv);
1138
1139
32.2k
    return 0;
1140
32.2k
}
1141
1142
27.8k
#define DATA_IN_RESPONSE_MIN_SIZE ONION_DATA_IN_RESPONSE_MIN_SIZE
1143
1144
static int handle_data_response(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull packet, uint16_t length, void *_Nonnull userdata)
1145
2.14k
{
1146
2.14k
    Onion_Client *onion_c = (Onion_Client *)object;
1147
1148
2.14k
    if (length <= (ONION_DATA_RESPONSE_MIN_SIZE + DATA_IN_RESPONSE_MIN_SIZE)) {
1149
0
        return 1;
1150
0
    }
1151
1152
2.14k
    if (length > MAX_DATA_REQUEST_SIZE) {
1153
0
        return 1;
1154
0
    }
1155
1156
2.14k
    const uint16_t temp_plain_size = length - ONION_DATA_RESPONSE_MIN_SIZE;
1157
2.14k
    VLA(uint8_t, temp_plain, temp_plain_size);
1158
2.14k
    int len = decrypt_data(onion_c->mem, packet + 1 + CRYPTO_NONCE_SIZE, onion_c->temp_secret_key, packet + 1,
1159
2.14k
                           packet + 1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE,
1160
2.14k
                           length - (1 + CRYPTO_NONCE_SIZE + CRYPTO_PUBLIC_KEY_SIZE), temp_plain);
1161
1162
2.14k
    if ((uint32_t)len != temp_plain_size) {
1163
0
        return 1;
1164
0
    }
1165
1166
2.14k
    const uint16_t plain_size = temp_plain_size - DATA_IN_RESPONSE_MIN_SIZE;
1167
2.14k
    VLA(uint8_t, plain, plain_size);
1168
2.14k
    len = decrypt_data(onion_c->mem, temp_plain, nc_get_self_secret_key(onion_c->c),
1169
2.14k
                       packet + 1, temp_plain + CRYPTO_PUBLIC_KEY_SIZE,
1170
2.14k
                       temp_plain_size - CRYPTO_PUBLIC_KEY_SIZE, plain);
1171
1172
2.14k
    if ((uint32_t)len != plain_size) {
1173
0
        return 1;
1174
0
    }
1175
1176
2.14k
    if (onion_c->onion_data_handlers[plain[0]].function == nullptr) {
1177
0
        return 1;
1178
0
    }
1179
1180
2.14k
    return onion_c->onion_data_handlers[plain[0]].function(onion_c->onion_data_handlers[plain[0]].object, temp_plain, plain,
1181
2.14k
            plain_size, userdata);
1182
2.14k
}
1183
1184
31.4k
#define DHTPK_DATA_MIN_LENGTH (1 + sizeof(uint64_t) + CRYPTO_PUBLIC_KEY_SIZE)
1185
8.95k
#define DHTPK_DATA_MAX_LENGTH (DHTPK_DATA_MIN_LENGTH + sizeof(Node_format)*MAX_SENT_NODES)
1186
static int handle_dhtpk_announce(void *_Nonnull object, const uint8_t *_Nonnull source_pubkey, const uint8_t *_Nonnull data, uint16_t length,
1187
                                 void *_Nullable userdata)
1188
2.11k
{
1189
2.11k
    Onion_Client *onion_c = (Onion_Client *)object;
1190
2.11k
    if (length < DHTPK_DATA_MIN_LENGTH) {
1191
0
        return 1;
1192
0
    }
1193
1194
2.11k
    if (length > DHTPK_DATA_MAX_LENGTH) {
1195
0
        return 1;
1196
0
    }
1197
1198
2.11k
    const int friend_num = onion_friend_num(onion_c, source_pubkey);
1199
1200
2.11k
    if (friend_num == -1) {
1201
7
        return 1;
1202
7
    }
1203
1204
2.10k
    uint64_t no_replay;
1205
2.10k
    net_unpack_u64(data + 1, &no_replay);
1206
1207
2.10k
    if (no_replay <= onion_c->friends_list[friend_num].last_noreplay) {
1208
1.58k
        return 1;
1209
1.58k
    }
1210
1211
527
    onion_c->friends_list[friend_num].last_noreplay = no_replay;
1212
1213
527
    if (onion_c->friends_list[friend_num].dht_pk_callback != nullptr) {
1214
527
        onion_c->friends_list[friend_num].dht_pk_callback(onion_c->friends_list[friend_num].dht_pk_callback_object,
1215
527
                onion_c->friends_list[friend_num].dht_pk_callback_number, data + 1 + sizeof(uint64_t), userdata);
1216
527
    }
1217
1218
527
    onion_set_friend_dht_pubkey(onion_c, friend_num, data + 1 + sizeof(uint64_t));
1219
1220
527
    const uint16_t len_nodes = length - DHTPK_DATA_MIN_LENGTH;
1221
1222
527
    if (len_nodes != 0) {
1223
527
        Node_format nodes[MAX_SENT_NODES];
1224
527
        const int num_nodes = unpack_nodes(nodes, MAX_SENT_NODES, nullptr, data + 1 + sizeof(uint64_t) + CRYPTO_PUBLIC_KEY_SIZE,
1225
527
                                           len_nodes, true);
1226
1227
527
        if (num_nodes <= 0) {
1228
0
            return 1;
1229
0
        }
1230
1231
1.82k
        for (int i = 0; i < num_nodes; ++i) {
1232
1.29k
            const Family family = nodes[i].ip_port.ip.family;
1233
1234
1.29k
            if (net_family_is_ipv4(family) || net_family_is_ipv6(family)) {
1235
1.10k
                dht_send_nodes_request(onion_c->dht, &nodes[i].ip_port, nodes[i].public_key, onion_c->friends_list[friend_num].dht_public_key);
1236
1.10k
            } else if (net_family_is_tcp_ipv4(family) || net_family_is_tcp_ipv6(family)) {
1237
187
                if (onion_c->friends_list[friend_num].tcp_relay_node_callback != nullptr) {
1238
187
                    void *obj = onion_c->friends_list[friend_num].tcp_relay_node_callback_object;
1239
187
                    const uint32_t number = onion_c->friends_list[friend_num].tcp_relay_node_callback_number;
1240
187
                    onion_c->friends_list[friend_num].tcp_relay_node_callback(obj, number, &nodes[i].ip_port, nodes[i].public_key);
1241
187
                }
1242
187
            }
1243
1.29k
        }
1244
527
    }
1245
1246
527
    return 0;
1247
527
}
1248
1249
static int handle_tcp_onion(void *_Nonnull object, const uint8_t *_Nonnull data, uint16_t length, void *_Nonnull userdata)
1250
6.53k
{
1251
6.53k
    if (length == 0) {
1252
0
        return 1;
1253
0
    }
1254
1255
6.53k
    IP_Port ip_port = {{{0}}};
1256
6.53k
    ip_port.ip.family = net_family_tcp_server();
1257
1258
6.53k
    if (data[0] == NET_PACKET_ANNOUNCE_RESPONSE) {
1259
70
        return handle_announce_response(object, &ip_port, data, length, userdata);
1260
70
    }
1261
1262
6.46k
    if (data[0] == NET_PACKET_ANNOUNCE_RESPONSE_OLD) {
1263
6.12k
        return handle_announce_response_old(object, &ip_port, data, length, userdata);
1264
6.12k
    }
1265
1266
337
    if (data[0] == NET_PACKET_ONION_DATA_RESPONSE) {
1267
337
        return handle_data_response(object, &ip_port, data, length, userdata);
1268
337
    }
1269
1270
0
    return 1;
1271
337
}
1272
1273
/** @brief Send data of length length to friendnum.
1274
 * Maximum length of data is ONION_CLIENT_MAX_DATA_SIZE.
1275
 * This data will be received by the friend using the Onion_Data_Handlers callbacks.
1276
 *
1277
 * Even if this function succeeds, the friend might not receive any data.
1278
 *
1279
 * return the number of packets sent on success
1280
 * return -1 on failure.
1281
 */
1282
int send_onion_data(Onion_Client *onion_c, int friend_num, const uint8_t *data, uint16_t length)
1283
18.3k
{
1284
18.3k
    if ((uint32_t)friend_num >= onion_c->num_friends) {
1285
0
        return -1;
1286
0
    }
1287
1288
18.3k
    if (length + DATA_IN_RESPONSE_MIN_SIZE > MAX_DATA_REQUEST_SIZE) {
1289
0
        return -1;
1290
0
    }
1291
1292
18.3k
    if (length == 0) {
1293
0
        return -1;
1294
0
    }
1295
1296
18.3k
    unsigned int good_nodes[MAX_ONION_CLIENTS];
1297
18.3k
    unsigned int num_good = 0;
1298
18.3k
    unsigned int num_nodes = 0;
1299
18.3k
    const Onion_Node *node_list = onion_c->friends_list[friend_num].clients_list;
1300
1301
164k
    for (unsigned int i = 0; i < MAX_ONION_CLIENTS; ++i) {
1302
146k
        if (onion_node_timed_out(&node_list[i], onion_c->mono_time)) {
1303
140k
            continue;
1304
140k
        }
1305
1306
5.90k
        ++num_nodes;
1307
1308
5.90k
        if (node_list[i].is_stored != 0) {
1309
2.17k
            good_nodes[num_good] = i;
1310
2.17k
            ++num_good;
1311
2.17k
        }
1312
5.90k
    }
1313
1314
18.3k
    if (num_good < (num_nodes - 1) / 4 + 1) {
1315
17.6k
        return -1;
1316
17.6k
    }
1317
1318
704
    uint8_t nonce[CRYPTO_NONCE_SIZE];
1319
704
    random_nonce(onion_c->rng, nonce);
1320
1321
704
    const uint16_t packet_size = DATA_IN_RESPONSE_MIN_SIZE + length;
1322
704
    VLA(uint8_t, packet, packet_size);
1323
704
    memcpy(packet, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
1324
704
    int len = encrypt_data(onion_c->mem, onion_c->friends_list[friend_num].real_public_key,
1325
704
                           nc_get_self_secret_key(onion_c->c), nonce, data,
1326
704
                           length, packet + CRYPTO_PUBLIC_KEY_SIZE);
1327
1328
704
    if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE != packet_size) {
1329
0
        return -1;
1330
0
    }
1331
1332
704
    unsigned int good = 0;
1333
1334
2.85k
    for (unsigned int i = 0; i < num_good; ++i) {
1335
2.14k
        Onion_Path path;
1336
1337
2.14k
        if (random_path(onion_c, &onion_c->onion_paths_friends, -1, &path) == -1) {
1338
0
            continue;
1339
0
        }
1340
1341
2.14k
        uint8_t o_packet[ONION_MAX_PACKET_SIZE];
1342
2.14k
        len = create_data_request(
1343
2.14k
                  onion_c->mem, onion_c->rng, o_packet, sizeof(o_packet), onion_c->friends_list[friend_num].real_public_key,
1344
2.14k
                  node_list[good_nodes[i]].data_public_key, nonce, packet, packet_size);
1345
1346
2.14k
        if (len == -1) {
1347
0
            continue;
1348
0
        }
1349
1350
2.14k
        if (send_onion_packet_tcp_udp(onion_c, &path, &node_list[good_nodes[i]].ip_port, o_packet, len) == 0) {
1351
2.14k
            ++good;
1352
2.14k
        }
1353
2.14k
    }
1354
1355
704
    return good;
1356
704
}
1357
1358
/** @brief Try to send the dht public key via the DHT instead of onion
1359
 *
1360
 * Even if this function succeeds, the friend might not receive any data.
1361
 *
1362
 * return the number of packets sent on success
1363
 * return -1 on failure.
1364
 */
1365
static int send_dht_dhtpk(const Onion_Client *_Nonnull onion_c, int friend_num, const uint8_t *_Nonnull data, uint16_t length)
1366
4.89k
{
1367
4.89k
    if ((uint32_t)friend_num >= onion_c->num_friends) {
1368
0
        return -1;
1369
0
    }
1370
1371
4.89k
    if (!onion_c->friends_list[friend_num].know_dht_public_key) {
1372
1.38k
        return -1;
1373
1.38k
    }
1374
1375
3.50k
    uint8_t nonce[CRYPTO_NONCE_SIZE];
1376
3.50k
    random_nonce(onion_c->rng, nonce);
1377
1378
3.50k
    const uint16_t temp_size = DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE + length;
1379
3.50k
    VLA(uint8_t, temp, temp_size);
1380
3.50k
    memcpy(temp, nc_get_self_public_key(onion_c->c), CRYPTO_PUBLIC_KEY_SIZE);
1381
3.50k
    memcpy(temp + CRYPTO_PUBLIC_KEY_SIZE, nonce, CRYPTO_NONCE_SIZE);
1382
3.50k
    int len = encrypt_data(onion_c->mem, onion_c->friends_list[friend_num].real_public_key,
1383
3.50k
                           nc_get_self_secret_key(onion_c->c), nonce, data,
1384
3.50k
                           length, temp + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE);
1385
1386
3.50k
    if ((uint32_t)len + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE != temp_size) {
1387
0
        return -1;
1388
0
    }
1389
1390
3.50k
    uint8_t packet_data[MAX_CRYPTO_REQUEST_SIZE];
1391
3.50k
    len = create_request(
1392
3.50k
              onion_c->mem, onion_c->rng, dht_get_self_public_key(onion_c->dht), dht_get_self_secret_key(onion_c->dht), packet_data,
1393
3.50k
              onion_c->friends_list[friend_num].dht_public_key, temp, temp_size, CRYPTO_PACKET_DHTPK);
1394
3.50k
    assert(len <= UINT16_MAX);
1395
3.50k
    const Net_Packet packet = {packet_data, (uint16_t)len};
1396
1397
3.50k
    if (len == -1) {
1398
0
        return -1;
1399
0
    }
1400
1401
3.50k
    return route_to_friend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, &packet);
1402
3.50k
}
1403
1404
static int handle_dht_dhtpk(void *_Nonnull object, const IP_Port *_Nonnull source, const uint8_t *_Nonnull source_pubkey, const uint8_t *_Nonnull packet, uint16_t length,
1405
                            void *_Nonnull userdata)
1406
346
{
1407
346
    Onion_Client *onion_c = (Onion_Client *)object;
1408
1409
346
    if (length < DHTPK_DATA_MIN_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE) {
1410
0
        return 1;
1411
0
    }
1412
1413
346
    if (length > DHTPK_DATA_MAX_LENGTH + DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE) {
1414
0
        return 1;
1415
0
    }
1416
1417
346
    uint8_t plain[DHTPK_DATA_MAX_LENGTH];
1418
346
    const int len = decrypt_data(onion_c->mem, packet, nc_get_self_secret_key(onion_c->c),
1419
346
                                 packet + CRYPTO_PUBLIC_KEY_SIZE,
1420
346
                                 packet + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
1421
346
                                 length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE), plain);
1422
1423
346
    if (len != length - (DATA_IN_RESPONSE_MIN_SIZE + CRYPTO_NONCE_SIZE)) {
1424
0
        return 1;
1425
0
    }
1426
1427
346
    if (!pk_equal(source_pubkey, plain + 1 + sizeof(uint64_t))) {
1428
0
        return 1;
1429
0
    }
1430
1431
346
    return handle_dhtpk_announce(onion_c, packet, plain, len, userdata);
1432
346
}
1433
1434
/** @brief Send the packets to tell our friends what our DHT public key is.
1435
 *
1436
 * if onion_dht_both is 0, use only the onion to send the packet.
1437
 * if it is 1, use only the dht.
1438
 * if it is something else, use both.
1439
 *
1440
 * return the number of packets sent on success
1441
 * return -1 on failure.
1442
 */
1443
static int send_dhtpk_announce(Onion_Client *_Nonnull onion_c, uint32_t friend_num, uint8_t onion_dht_both)
1444
6.49k
{
1445
6.49k
    if (friend_num >= onion_c->num_friends) {
1446
0
        return -1;
1447
0
    }
1448
1449
6.49k
    uint8_t data[DHTPK_DATA_MAX_LENGTH];
1450
6.49k
    data[0] = ONION_DATA_DHTPK;
1451
6.49k
    const uint64_t no_replay = mono_time_get(onion_c->mono_time);
1452
6.49k
    net_pack_u64(data + 1, no_replay);
1453
6.49k
    memcpy(data + 1 + sizeof(uint64_t), dht_get_self_public_key(onion_c->dht), CRYPTO_PUBLIC_KEY_SIZE);
1454
6.49k
    Node_format nodes[MAX_SENT_NODES];
1455
6.49k
    const uint16_t num_relays = copy_connected_tcp_relays(onion_c->c, nodes, MAX_SENT_NODES / 2);
1456
6.49k
    uint16_t num_nodes = closelist_nodes(onion_c->dht, &nodes[num_relays], MAX_SENT_NODES - num_relays);
1457
6.49k
    num_nodes += num_relays;
1458
6.49k
    int nodes_len = 0;
1459
1460
6.49k
    if (num_nodes != 0) {
1461
6.49k
        nodes_len = pack_nodes(onion_c->logger, data + DHTPK_DATA_MIN_LENGTH, DHTPK_DATA_MAX_LENGTH - DHTPK_DATA_MIN_LENGTH,
1462
6.49k
                               nodes, num_nodes);
1463
1464
6.49k
        if (nodes_len <= 0) {
1465
0
            return -1;
1466
0
        }
1467
6.49k
    }
1468
1469
6.49k
    int num1 = -1;
1470
6.49k
    int num2 = -1;
1471
1472
6.49k
    if (onion_dht_both != 1) {
1473
1.60k
        num1 = send_onion_data(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
1474
1.60k
    }
1475
1476
6.49k
    if (onion_dht_both != 0) {
1477
4.89k
        num2 = send_dht_dhtpk(onion_c, friend_num, data, DHTPK_DATA_MIN_LENGTH + nodes_len);
1478
4.89k
    }
1479
1480
6.49k
    if (num1 == -1) {
1481
6.02k
        return num2;
1482
6.02k
    }
1483
1484
474
    if (num2 == -1) {
1485
474
        return num1;
1486
474
    }
1487
1488
18.4E
    return num1 + num2;
1489
473
}
1490
1491
/** @brief Get the friend_num of a friend.
1492
 *
1493
 * return -1 on failure.
1494
 * return friend number on success.
1495
 */
1496
int onion_friend_num(const Onion_Client *onion_c, const uint8_t *public_key)
1497
3.10k
{
1498
3.10k
    return bs_list_find(&onion_c->friends_lookup, public_key);
1499
3.10k
}
1500
1501
/** @brief Set the size of the friend list to num.
1502
 *
1503
 * @retval -1 if mem_vrealloc fails.
1504
 * @retval 0 if it succeeds.
1505
 */
1506
static int realloc_onion_friends(Onion_Client *_Nonnull onion_c, uint32_t num)
1507
2.89k
{
1508
2.89k
    if (num == 0) {
1509
1.92k
        mem_delete(onion_c->mem, onion_c->friends_list);
1510
1.92k
        onion_c->friends_list = nullptr;
1511
1.92k
        onion_c->friends_list_capacity = 0;
1512
1.92k
        return 0;
1513
1.92k
    }
1514
1515
969
    if (num <= onion_c->friends_list_capacity) {
1516
155
        return 0;
1517
155
    }
1518
1519
    // Geometric growth: Double the capacity or set to num if starting.
1520
814
    uint32_t new_capacity = onion_c->friends_list_capacity == 0 ? num : onion_c->friends_list_capacity * 2;
1521
814
    if (new_capacity < num) {
1522
0
        new_capacity = num;
1523
0
    }
1524
1525
814
    Onion_Friend *newonion_friends = (Onion_Friend *)mem_vrealloc(onion_c->mem, onion_c->friends_list, new_capacity, sizeof(Onion_Friend));
1526
1527
814
    if (newonion_friends == nullptr) {
1528
0
        return -1;
1529
0
    }
1530
1531
814
    onion_c->friends_list = newonion_friends;
1532
814
    onion_c->friends_list_capacity = new_capacity;
1533
814
    return 0;
1534
814
}
1535
1536
/** @brief Add a friend who we want to connect to.
1537
 *
1538
 * return -1 on failure.
1539
 * return the friend number on success or if the friend was already added.
1540
 */
1541
int onion_addfriend(Onion_Client *onion_c, const uint8_t *public_key)
1542
983
{
1543
983
    const int num = onion_friend_num(onion_c, public_key);
1544
1545
983
    if (num != -1) {
1546
1
        return num;
1547
1
    }
1548
1549
982
    uint32_t index = (uint32_t) -1;
1550
1551
2.59k
    for (uint32_t i = 0; i < onion_c->num_friends; ++i) {
1552
1.62k
        if (!onion_c->friends_list[i].is_valid) {
1553
13
            index = i;
1554
13
            break;
1555
13
        }
1556
1.62k
    }
1557
1558
982
    if (index == (uint32_t) -1) {
1559
969
        if (realloc_onion_friends(onion_c, onion_c->num_friends + 1) == -1) {
1560
0
            return -1;
1561
0
        }
1562
1563
969
        index = onion_c->num_friends;
1564
969
        onion_c->friends_list[onion_c->num_friends] = empty_onion_friend;
1565
969
        ++onion_c->num_friends;
1566
969
    }
1567
1568
982
    onion_c->friends_list[index].is_valid = true;
1569
982
    memcpy(onion_c->friends_list[index].real_public_key, public_key, CRYPTO_PUBLIC_KEY_SIZE);
1570
982
    crypto_new_keypair(onion_c->rng, onion_c->friends_list[index].temp_public_key,
1571
982
                       onion_c->friends_list[index].temp_secret_key);
1572
1573
982
    if (!bs_list_add(&onion_c->friends_lookup, public_key, index)) {
1574
0
        LOGGER_ERROR(onion_c->logger, "Failed to add friend to lookup list (index: %u)", index);
1575
0
        return -1;
1576
0
    }
1577
1578
982
    return index;
1579
982
}
1580
1581
/** @brief Delete a friend.
1582
 *
1583
 * return -1 on failure.
1584
 * return the deleted friend number on success.
1585
 */
1586
int onion_delfriend(Onion_Client *onion_c, int friend_num)
1587
975
{
1588
975
    if ((uint32_t)friend_num >= onion_c->num_friends) {
1589
1
        return -1;
1590
1
    }
1591
1592
#if 0
1593
1594
    if (onion_c->friends_list[friend_num].know_dht_public_key) {
1595
        dht_delfriend(onion_c->dht, onion_c->friends_list[friend_num].dht_public_key, 0);
1596
    }
1597
1598
#endif /* 0 */
1599
1600
974
    if (!bs_list_remove(&onion_c->friends_lookup, onion_c->friends_list[friend_num].real_public_key, friend_num)) {
1601
0
        LOGGER_ERROR(onion_c->logger, "Failed to remove friend from lookup list (index: %d)", friend_num);
1602
0
    }
1603
1604
974
    crypto_memzero(&onion_c->friends_list[friend_num], sizeof(Onion_Friend));
1605
974
    uint32_t i;
1606
1607
1.93k
    for (i = onion_c->num_friends; i != 0; --i) {
1608
1.48k
        if (onion_c->friends_list[i - 1].is_valid) {
1609
523
            break;
1610
523
        }
1611
1.48k
    }
1612
1613
974
    onion_c->num_friends = i;
1614
1615
974
    return friend_num;
1616
975
}
1617
1618
/** @brief Set the function for this friend that will be callbacked with object and number
1619
 * when that friend gives us one of the TCP relays they are connected to.
1620
 *
1621
 * object and number will be passed as argument to this function.
1622
 *
1623
 * return -1 on failure.
1624
 * return 0 on success.
1625
 */
1626
int recv_tcp_relay_handler(Onion_Client *onion_c, int friend_num,
1627
                           recv_tcp_relay_cb *callback, void *object, uint32_t number)
1628
973
{
1629
973
    if ((uint32_t)friend_num >= onion_c->num_friends) {
1630
0
        return -1;
1631
0
    }
1632
1633
973
    onion_c->friends_list[friend_num].tcp_relay_node_callback = callback;
1634
973
    onion_c->friends_list[friend_num].tcp_relay_node_callback_object = object;
1635
973
    onion_c->friends_list[friend_num].tcp_relay_node_callback_number = number;
1636
973
    return 0;
1637
973
}
1638
1639
/** @brief Set the function for this friend that will be callbacked with object and number
1640
 * when that friend gives us their DHT temporary public key.
1641
 *
1642
 * object and number will be passed as argument to this function.
1643
 *
1644
 * return -1 on failure.
1645
 * return 0 on success.
1646
 */
1647
int onion_dht_pk_callback(Onion_Client *onion_c, int friend_num,
1648
                          onion_dht_pk_cb *function, void *object, uint32_t number)
1649
975
{
1650
975
    if ((uint32_t)friend_num >= onion_c->num_friends) {
1651
0
        return -1;
1652
0
    }
1653
1654
975
    onion_c->friends_list[friend_num].dht_pk_callback = function;
1655
975
    onion_c->friends_list[friend_num].dht_pk_callback_object = object;
1656
975
    onion_c->friends_list[friend_num].dht_pk_callback_number = number;
1657
975
    return 0;
1658
975
}
1659
1660
/** @brief Set a friend's DHT public key.
1661
 *
1662
 * return -1 on failure.
1663
 * return 0 on success.
1664
 */
1665
int onion_set_friend_dht_pubkey(Onion_Client *onion_c, int friend_num, const uint8_t *dht_key)
1666
1.03k
{
1667
1.03k
    if ((uint32_t)friend_num >= onion_c->num_friends) {
1668
1
        return -1;
1669
1
    }
1670
1671
1.03k
    if (!onion_c->friends_list[friend_num].is_valid) {
1672
0
        return -1;
1673
0
    }
1674
1675
1.03k
    if (onion_c->friends_list[friend_num].know_dht_public_key) {
1676
523
        if (pk_equal(dht_key, onion_c->friends_list[friend_num].dht_public_key)) {
1677
521
            return -1;
1678
521
        }
1679
523
    }
1680
1681
511
    onion_c->friends_list[friend_num].know_dht_public_key = true;
1682
511
    memcpy(onion_c->friends_list[friend_num].dht_public_key, dht_key, CRYPTO_PUBLIC_KEY_SIZE);
1683
1684
511
    return 0;
1685
1.03k
}
1686
1687
/** @brief Copy friends DHT public key into dht_key.
1688
 *
1689
 * return 0 on failure (no key copied).
1690
 * return 1 on success (key copied).
1691
 */
1692
unsigned int onion_getfriend_dht_pubkey(const Onion_Client *onion_c, int friend_num, uint8_t *dht_key)
1693
4
{
1694
4
    if ((uint32_t)friend_num >= onion_c->num_friends) {
1695
1
        return 0;
1696
1
    }
1697
1698
3
    if (!onion_c->friends_list[friend_num].is_valid) {
1699
0
        return 0;
1700
0
    }
1701
1702
3
    if (!onion_c->friends_list[friend_num].know_dht_public_key) {
1703
0
        return 0;
1704
0
    }
1705
1706
3
    memcpy(dht_key, onion_c->friends_list[friend_num].dht_public_key, CRYPTO_PUBLIC_KEY_SIZE);
1707
3
    return 1;
1708
3
}
1709
1710
/** @brief Get the ip of friend friendnum and put it in ip_port
1711
 *
1712
 * @retval -1 if public_key does NOT refer to a friend
1713
 * @retval  0 if public_key refers to a friend and we failed to find the friend (yet)
1714
 * @retval  1 if public_key refers to a friend and we found them
1715
 */
1716
int onion_getfriendip(const Onion_Client *onion_c, int friend_num, IP_Port *ip_port)
1717
2
{
1718
2
    uint8_t dht_public_key[CRYPTO_PUBLIC_KEY_SIZE];
1719
1720
2
    if (onion_getfriend_dht_pubkey(onion_c, friend_num, dht_public_key) == 0) {
1721
0
        return -1;
1722
0
    }
1723
1724
2
    return dht_getfriendip(onion_c->dht, dht_public_key, ip_port);
1725
2
}
1726
1727
/** @brief Set if friend is online or not.
1728
 *
1729
 * NOTE: This function is there and should be used so that we don't send
1730
 * useless packets to the friend if they are online.
1731
 *
1732
 * return -1 on failure.
1733
 * return 0 on success.
1734
 */
1735
int onion_set_friend_online(Onion_Client *onion_c, int friend_num, bool is_online)
1736
521
{
1737
521
    if ((uint32_t)friend_num >= onion_c->num_friends) {
1738
1
        return -1;
1739
1
    }
1740
1741
520
    onion_c->friends_list[friend_num].is_online = is_online;
1742
1743
    /* This should prevent some clock related issues */
1744
520
    if (!is_online) {
1745
17
        onion_c->friends_list[friend_num].last_noreplay = 0;
1746
17
        onion_c->friends_list[friend_num].run_count = 0;
1747
17
    }
1748
1749
520
    return 0;
1750
521
}
1751
1752
static void populate_path_nodes(Onion_Client *_Nonnull onion_c)
1753
7.48k
{
1754
7.48k
    Node_format node_list[MAX_FRIEND_CLIENTS];
1755
1756
7.48k
    const unsigned int num_nodes = randfriends_nodes(onion_c->dht, node_list, MAX_FRIEND_CLIENTS);
1757
1758
42.6k
    for (unsigned int i = 0; i < num_nodes; ++i) {
1759
35.1k
        onion_add_path_node(onion_c, &node_list[i].ip_port, node_list[i].public_key);
1760
35.1k
    }
1761
7.48k
}
1762
1763
/* How often we ping new friends per node */
1764
7.18k
#define ANNOUNCE_FRIEND_NEW_INTERVAL 3
1765
1766
/* How long we consider a friend new based on the value of their run_count */
1767
7.46k
#define ANNOUNCE_FRIEND_RUN_COUNT_BEGINNING 5
1768
1769
/* How often we try to re-populate the nodes lists if we don't meet a minimum threshhold of nodes */
1770
1.02k
#define ANNOUNCE_POPULATE_TIMEOUT (60 * 10)
1771
1772
/* The max time between lookup requests for a friend per node */
1773
277
#define ANNOUNCE_FRIEND_MAX_INTERVAL (60 * 60)
1774
1775
/* Max exponent when calculating the announce request interval */
1776
277
#define MAX_RUN_COUNT_EXPONENT 12
1777
1778
static void do_friend(Onion_Client *_Nonnull onion_c, uint32_t friendnum)
1779
7.46k
{
1780
7.46k
    if (friendnum >= onion_c->num_friends) {
1781
0
        return;
1782
0
    }
1783
1784
7.46k
    Onion_Friend *o_friend = &onion_c->friends_list[friendnum];
1785
1786
7.46k
    if (!o_friend->is_valid) {
1787
2
        return;
1788
2
    }
1789
1790
7.46k
    uint32_t interval;
1791
7.46k
    const uint64_t tm = mono_time_get(onion_c->mono_time);
1792
7.46k
    const bool friend_is_new = o_friend->run_count <= ANNOUNCE_FRIEND_RUN_COUNT_BEGINNING;
1793
1794
7.46k
    if (!friend_is_new) {
1795
        // how often we ping a node for a friend depends on how many times we've already tried.
1796
        // the interval increases exponentially, as the longer a friend has been offline, the less
1797
        // likely the case is that they're online and failed to find us
1798
277
        const uint32_t c = 1 << min_u32(MAX_RUN_COUNT_EXPONENT, o_friend->run_count - 2);
1799
277
        interval = min_u32(c, ANNOUNCE_FRIEND_MAX_INTERVAL);
1800
7.18k
    } else {
1801
7.18k
        interval = ANNOUNCE_FRIEND_NEW_INTERVAL;
1802
7.18k
    }
1803
1804
7.46k
    if (o_friend->is_online) {
1805
2.53k
        return;
1806
2.53k
    }
1807
1808
4.92k
    assert(interval >= ANNOUNCE_FRIEND_NEW_INTERVAL); // an int overflow would be devastating
1809
1810
    /* send packets to friend telling them our DHT public key. */
1811
4.92k
    if (mono_time_is_timeout(onion_c->mono_time, onion_c->friends_list[friendnum].last_dht_pk_onion_sent,
1812
4.92k
                             ONION_DHTPK_SEND_INTERVAL)) {
1813
1.60k
        if (send_dhtpk_announce(onion_c, friendnum, 0) >= 1) {
1814
474
            onion_c->friends_list[friendnum].last_dht_pk_onion_sent = tm;
1815
474
        }
1816
1.60k
    }
1817
1818
4.92k
    if (mono_time_is_timeout(onion_c->mono_time, onion_c->friends_list[friendnum].last_dht_pk_dht_sent,
1819
4.92k
                             DHT_DHTPK_SEND_INTERVAL)) {
1820
4.89k
        if (send_dhtpk_announce(onion_c, friendnum, 1) >= 1) {
1821
90
            onion_c->friends_list[friendnum].last_dht_pk_dht_sent = tm;
1822
90
        }
1823
4.89k
    }
1824
1825
4.92k
    uint16_t count = 0;  // number of alive path nodes
1826
1827
4.92k
    Onion_Node *node_list = o_friend->clients_list;
1828
1829
44.3k
    for (unsigned i = 0; i < MAX_ONION_CLIENTS; ++i) {
1830
39.4k
        if (onion_node_timed_out(&node_list[i], onion_c->mono_time)) {
1831
30.7k
            continue;
1832
30.7k
        }
1833
1834
8.64k
        ++count;
1835
1836
        // we don't want new nodes to be pinged immediately
1837
8.64k
        if (node_list[i].last_pinged == 0) {
1838
1.83k
            node_list[i].last_pinged = tm;
1839
1.83k
            continue;
1840
1.83k
        }
1841
1842
        // node hasn't responded in a while so we skip it
1843
6.81k
        if (node_list[i].pings_since_last_response >= ONION_NODE_MAX_PINGS) {
1844
87
            continue;
1845
87
        }
1846
1847
        // space requests out between nodes
1848
6.72k
        if (!mono_time_is_timeout(onion_c->mono_time, o_friend->time_last_pinged, interval / (MAX_ONION_CLIENTS / 2))) {
1849
582
            continue;
1850
582
        }
1851
1852
6.14k
        if (!mono_time_is_timeout(onion_c->mono_time, node_list[i].last_pinged, interval)) {
1853
4.42k
            continue;
1854
4.42k
        }
1855
1856
1.72k
        if (client_send_announce_request(onion_c, friendnum + 1, &node_list[i].ip_port,
1857
1.72k
                                         node_list[i].public_key, nullptr, -1) == 0) {
1858
1.72k
            node_list[i].last_pinged = tm;
1859
1.72k
            o_friend->time_last_pinged = tm;
1860
1.72k
            ++node_list[i].pings_since_last_response;
1861
1.72k
            ++o_friend->pings;
1862
1863
1.72k
            if (o_friend->pings % (MAX_ONION_CLIENTS / 2) == 0) {
1864
375
                ++o_friend->run_count;
1865
375
            }
1866
1.72k
        }
1867
1.72k
    }
1868
1869
4.92k
    if (count == MAX_ONION_CLIENTS) {
1870
196
        if (!friend_is_new) {
1871
0
            o_friend->last_populated = tm;
1872
0
        }
1873
1874
196
        return;
1875
196
    }
1876
1877
    // check if path nodes list for this friend needs to be repopulated
1878
4.73k
    if (count <= MAX_ONION_CLIENTS / 2
1879
4.73k
            || mono_time_is_timeout(onion_c->mono_time, o_friend->last_populated, ANNOUNCE_POPULATE_TIMEOUT)) {
1880
4.22k
        const uint16_t num_nodes = min_u16(onion_c->path_nodes_index, MAX_PATH_NODES);
1881
4.22k
        const uint16_t n = min_u16(num_nodes, MAX_PATH_NODES / 4);
1882
1883
4.22k
        if (n == 0) {
1884
0
            return;
1885
0
        }
1886
1887
4.22k
        o_friend->last_populated = tm;
1888
1889
11.4k
        for (uint16_t i = 0; i < n; ++i) {
1890
7.27k
            const uint32_t num = random_range_u32(onion_c->rng, num_nodes);
1891
7.27k
            client_send_announce_request(onion_c, friendnum + 1, &onion_c->path_nodes[num].ip_port,
1892
7.27k
                                         onion_c->path_nodes[num].public_key, nullptr, -1);
1893
7.27k
        }
1894
4.22k
    }
1895
4.73k
}
1896
1897
/** Function to call when onion data packet with contents beginning with byte is received. */
1898
void oniondata_registerhandler(Onion_Client *onion_c, uint8_t byte, oniondata_handler_cb *cb, void *object)
1899
5.64k
{
1900
5.64k
    onion_c->onion_data_handlers[byte].function = cb;
1901
5.64k
    onion_c->onion_data_handlers[byte].object = object;
1902
5.64k
}
1903
1904
void onion_group_announce_register(Onion_Client *onion_c, onion_group_announce_cb *func, void *user_data)
1905
3.62k
{
1906
3.62k
    onion_c->group_announce_response = func;
1907
3.62k
    onion_c->group_announce_response_user_data = user_data;
1908
3.62k
}
1909
1910
33.4k
#define ANNOUNCE_INTERVAL_NOT_ANNOUNCED 3
1911
27.4k
#define ANNOUNCE_INTERVAL_ANNOUNCED ONION_NODE_PING_INTERVAL
1912
1913
27.5k
#define TIME_TO_STABLE (ONION_NODE_PING_INTERVAL * 6)
1914
0
#define ANNOUNCE_INTERVAL_STABLE (ONION_NODE_PING_INTERVAL * 8)
1915
1916
static bool key_list_contains(const uint8_t *const *_Nonnull keys, uint16_t keys_size, const uint8_t *_Nonnull public_key)
1917
32.0k
{
1918
54.4k
    for (uint16_t i = 0; i < keys_size; ++i) {
1919
40.9k
        if (memeq(keys[i], CRYPTO_PUBLIC_KEY_SIZE, public_key, CRYPTO_PUBLIC_KEY_SIZE)) {
1920
18.5k
            return true;
1921
18.5k
        }
1922
40.9k
    }
1923
1924
13.5k
    return false;
1925
32.0k
}
1926
1927
/** Does path with path_num exist. */
1928
static bool path_exists(const Mono_Time *_Nonnull mono_time, const Onion_Client_Paths *_Nonnull onion_paths, uint32_t path_num)
1929
27.5k
{
1930
27.5k
    if (path_timed_out(mono_time, onion_paths, path_num)) {
1931
31
        return false;
1932
31
    }
1933
1934
27.5k
    return onion_paths->paths[path_num % NUMBER_ONION_PATHS].path_num == path_num;
1935
27.5k
}
1936
1937
/**
1938
 * A node/path is considered "stable" if it has survived for at least TIME_TO_STABLE
1939
 * and the latest packets sent to it are not timing out.
1940
 */
1941
static bool path_is_stable(const Mono_Time *_Nonnull mono_time, const Onion_Client_Paths *_Nonnull paths, uint32_t pathnum, const Onion_Node *_Nonnull node)
1942
27.4k
{
1943
27.4k
    return mono_time_is_timeout(mono_time, node->added_time, TIME_TO_STABLE)
1944
27.4k
           && !(node->pings_since_last_response > 0
1945
0
                && mono_time_is_timeout(mono_time, node->last_pinged, ONION_NODE_TIMEOUT))
1946
27.4k
           && mono_time_is_timeout(mono_time, paths->path_creation_time[pathnum], TIME_TO_STABLE)
1947
27.4k
           && !(paths->last_path_used_times[pathnum] > 0
1948
0
                && mono_time_is_timeout(mono_time, paths->last_path_used[pathnum], ONION_PATH_TIMEOUT));
1949
27.4k
}
1950
1951
static void do_announce(Onion_Client *_Nonnull onion_c)
1952
7.48k
{
1953
7.48k
    unsigned int count = 0;
1954
7.48k
    Onion_Node *node_list = onion_c->clients_announce_list;
1955
1956
97.2k
    for (unsigned int i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
1957
89.7k
        if (onion_node_timed_out(&node_list[i], onion_c->mono_time)) {
1958
52.1k
            continue;
1959
52.1k
        }
1960
1961
37.6k
        ++count;
1962
1963
        /* Don't announce ourselves the first time this is run to new peers */
1964
37.6k
        if (node_list[i].last_pinged == 0) {
1965
4.04k
            node_list[i].last_pinged = 1;
1966
4.04k
            continue;
1967
4.04k
        }
1968
1969
33.6k
        if (node_list[i].pings_since_last_response >= ONION_NODE_MAX_PINGS) {
1970
209
            continue;
1971
209
        }
1972
1973
33.4k
        unsigned int interval = ANNOUNCE_INTERVAL_NOT_ANNOUNCED;
1974
1975
33.4k
        if (node_list[i].is_stored != 0
1976
33.4k
                && path_exists(onion_c->mono_time, &onion_c->onion_paths_self, node_list[i].path_used)) {
1977
27.4k
            interval = ANNOUNCE_INTERVAL_ANNOUNCED;
1978
1979
27.4k
            const uint32_t pathnum = node_list[i].path_used % NUMBER_ONION_PATHS;
1980
1981
            /* If a node/path is considered "stable", it can be pinged less aggressively. */
1982
27.4k
            if (path_is_stable(onion_c->mono_time, &onion_c->onion_paths_self, pathnum, &node_list[i])) {
1983
0
                interval = ANNOUNCE_INTERVAL_STABLE;
1984
0
            }
1985
27.4k
        }
1986
1987
33.4k
        if (mono_time_is_timeout(onion_c->mono_time, node_list[i].last_pinged, interval)
1988
33.4k
                || mono_time_is_timeout(onion_c->mono_time, onion_c->last_announce, ONION_NODE_PING_INTERVAL)) {
1989
5.02k
            uint32_t path_to_use = node_list[i].path_used;
1990
1991
5.02k
            if (node_list[i].pings_since_last_response == ONION_NODE_MAX_PINGS - 1
1992
5.02k
                    && mono_time_is_timeout(onion_c->mono_time, node_list[i].added_time, TIME_TO_STABLE)) {
1993
                /* Last chance for a long-lived node - try a random path */
1994
0
                path_to_use = -1;
1995
0
            }
1996
1997
5.02k
            if (client_send_announce_request(onion_c, 0, &node_list[i].ip_port, node_list[i].public_key,
1998
5.02k
                                             node_list[i].ping_id, path_to_use) == 0) {
1999
5.02k
                node_list[i].last_pinged = mono_time_get(onion_c->mono_time);
2000
5.02k
                ++node_list[i].pings_since_last_response;
2001
5.02k
                onion_c->last_announce = mono_time_get(onion_c->mono_time);
2002
5.02k
            }
2003
5.02k
        }
2004
33.4k
    }
2005
2006
7.48k
    if (count == MAX_ONION_CLIENTS_ANNOUNCE) {
2007
2.01k
        onion_c->last_populated = mono_time_get(onion_c->mono_time);
2008
2.01k
        return;
2009
2.01k
    }
2010
2011
    // check if list needs to be re-populated
2012
5.47k
    if (count <= MAX_ONION_CLIENTS_ANNOUNCE / 2
2013
5.47k
            || mono_time_is_timeout(onion_c->mono_time, onion_c->last_populated, ANNOUNCE_POPULATE_TIMEOUT)) {
2014
5.47k
        uint16_t num_nodes;
2015
5.47k
        const Node_format *path_nodes;
2016
2017
5.47k
        if (onion_c->path_nodes_index == 0) {
2018
538
            num_nodes = min_u16(onion_c->path_nodes_index_bs, MAX_PATH_NODES);
2019
538
            path_nodes = onion_c->path_nodes_bs;
2020
4.93k
        } else {
2021
4.93k
            num_nodes = min_u16(onion_c->path_nodes_index, MAX_PATH_NODES);
2022
4.93k
            path_nodes = onion_c->path_nodes;
2023
4.93k
        }
2024
2025
5.47k
        if (num_nodes == 0) {
2026
132
            return;
2027
132
        }
2028
2029
        // Don't send announces to the same node twice. If we don't have many nodes,
2030
        // the random selection below may have overlaps. This ensures that we deduplicate
2031
        // nodes before sending packets to save some bandwidth.
2032
        //
2033
        // TODO(iphydf): Figure out why on esp32, this is necessary for the onion
2034
        // connection to succeed. This is an optimisation and shouldn't be necessary.
2035
5.34k
        const uint8_t *targets[MAX_ONION_CLIENTS_ANNOUNCE / 2];
2036
5.34k
        unsigned int targets_count = 0;
2037
2038
37.3k
        for (unsigned int i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE / 2; ++i) {
2039
32.0k
            const uint32_t num = random_range_u32(onion_c->rng, num_nodes);
2040
32.0k
            const Node_format *target = &path_nodes[num];
2041
2042
32.0k
            if (!key_list_contains(targets, targets_count, target->public_key)) {
2043
13.5k
                client_send_announce_request(onion_c, 0, &target->ip_port, target->public_key, nullptr, -1);
2044
2045
13.5k
                targets[targets_count] = target->public_key;
2046
13.5k
                ++targets_count;
2047
13.5k
                assert(targets_count <= MAX_ONION_CLIENTS_ANNOUNCE / 2);
2048
18.5k
            } else {
2049
18.5k
                Ip_Ntoa ip_str;
2050
18.5k
                LOGGER_TRACE(onion_c->logger, "not sending repeated announce request to %s:%d",
2051
18.5k
                             net_ip_ntoa(&target->ip_port.ip, &ip_str), net_ntohs(target->ip_port.port));
2052
18.5k
            }
2053
32.0k
        }
2054
5.34k
    }
2055
5.47k
}
2056
2057
/**
2058
 * @retval false if we are not connected to the network.
2059
 * @retval true if we are.
2060
 */
2061
static bool onion_isconnected(Onion_Client *_Nonnull onion_c)
2062
8.35k
{
2063
8.35k
    unsigned int live = 0;
2064
8.35k
    unsigned int announced = 0;
2065
2066
8.35k
    if (mono_time_is_timeout(onion_c->mono_time, onion_c->last_packet_recv, ONION_OFFLINE_TIMEOUT)) {
2067
1.99k
        LOGGER_TRACE(onion_c->logger, "onion is NOT connected: last packet received at %llu (timeout=%u)",
2068
1.99k
                     (unsigned long long)onion_c->last_packet_recv, (unsigned int)ONION_OFFLINE_TIMEOUT);
2069
1.99k
        onion_c->last_populated = 0;
2070
1.99k
        return false;
2071
1.99k
    }
2072
2073
6.36k
    if (onion_c->path_nodes_index == 0) {
2074
0
        LOGGER_TRACE(onion_c->logger, "onion is NOT connected: no path nodes available");
2075
0
        onion_c->last_populated = 0;
2076
0
        return false;
2077
0
    }
2078
2079
82.7k
    for (unsigned int i = 0; i < MAX_ONION_CLIENTS_ANNOUNCE; ++i) {
2080
76.3k
        if (!onion_node_timed_out(&onion_c->clients_announce_list[i], onion_c->mono_time)) {
2081
37.6k
            ++live;
2082
2083
37.6k
            if (onion_c->clients_announce_list[i].is_stored != 0) {
2084
27.7k
                ++announced;
2085
27.7k
            }
2086
37.6k
        }
2087
76.3k
    }
2088
2089
6.36k
    unsigned int pnodes = onion_c->path_nodes_index;
2090
2091
6.36k
    if (pnodes > MAX_ONION_CLIENTS_ANNOUNCE) {
2092
2.23k
        pnodes = MAX_ONION_CLIENTS_ANNOUNCE;
2093
2.23k
    }
2094
2095
    /* Consider ourselves online if we are announced to half or more nodes
2096
     * we are connected to */
2097
6.36k
    if (live != 0 && announced != 0) {
2098
5.31k
        if ((live / 2) <= announced && (pnodes / 2) <= live) {
2099
5.12k
            LOGGER_TRACE(onion_c->logger, "onion is connected: %u live nodes, %u announced, %d path nodes",
2100
5.12k
                         live, announced, (int)pnodes);
2101
5.12k
            return true;
2102
5.12k
        }
2103
5.31k
    }
2104
2105
1.24k
    onion_c->last_populated = 0;
2106
2107
1.24k
    LOGGER_TRACE(onion_c->logger, "onion is NOT connected: %u live nodes, %u announced, %d path nodes",
2108
1.24k
                 live, announced, (int)pnodes);
2109
1.24k
    return false;
2110
6.36k
}
2111
2112
static void reset_friend_run_counts(Onion_Client *_Nonnull onion_c)
2113
440
{
2114
703
    for (uint32_t i = 0; i < onion_c->num_friends; ++i) {
2115
263
        Onion_Friend *o_friend = &onion_c->friends_list[i];
2116
2117
263
        if (o_friend->is_valid) {
2118
263
            o_friend->run_count = 0;
2119
263
        }
2120
263
    }
2121
440
}
2122
2123
280k
#define ONION_CONNECTION_SECONDS 3
2124
5.11k
#define ONION_CONNECTED_TIMEOUT 10
2125
2126
Onion_Connection_Status onion_connection_status(const Onion_Client *onion_c)
2127
259k
{
2128
259k
    if (onion_c->onion_connected >= ONION_CONNECTION_SECONDS) {
2129
144k
        if (onion_c->udp_connected) {
2130
1.51k
            return ONION_CONNECTION_STATUS_UDP;
2131
1.51k
        }
2132
2133
142k
        return ONION_CONNECTION_STATUS_TCP;
2134
144k
    }
2135
2136
114k
    return ONION_CONNECTION_STATUS_NONE;
2137
259k
}
2138
2139
void do_onion_client(Onion_Client *onion_c)
2140
132k
{
2141
132k
    if (onion_c->last_run == mono_time_get(onion_c->mono_time)) {
2142
123k
        return;
2143
123k
    }
2144
2145
8.30k
    if (mono_time_is_timeout(onion_c->mono_time, onion_c->first_run, ONION_CONNECTION_SECONDS)) {
2146
7.48k
        populate_path_nodes(onion_c);
2147
7.48k
        do_announce(onion_c);
2148
7.48k
    }
2149
2150
8.30k
    if (onion_isconnected(onion_c)) {
2151
5.11k
        if (mono_time_is_timeout(onion_c->mono_time, onion_c->last_time_connected, ONION_CONNECTED_TIMEOUT)) {
2152
440
            reset_friend_run_counts(onion_c);
2153
440
        }
2154
2155
5.11k
        onion_c->last_time_connected = mono_time_get(onion_c->mono_time);
2156
2157
5.11k
        if (onion_c->onion_connected < ONION_CONNECTION_SECONDS * 2) {
2158
2.26k
            ++onion_c->onion_connected;
2159
2.26k
        }
2160
5.11k
    } else {
2161
3.18k
        if (onion_c->onion_connected != 0) {
2162
1
            --onion_c->onion_connected;
2163
1
        }
2164
3.18k
    }
2165
2166
8.30k
    onion_c->udp_connected = dht_non_lan_connected(onion_c->dht);
2167
2168
8.30k
    if (mono_time_is_timeout(onion_c->mono_time, onion_c->first_run, ONION_CONNECTION_SECONDS * 2)) {
2169
6.25k
        set_tcp_onion_status(nc_get_tcp_c(onion_c->c), !onion_c->udp_connected);
2170
6.25k
    }
2171
2172
8.30k
    if (onion_connection_status(onion_c) != ONION_CONNECTION_STATUS_NONE) {
2173
11.7k
        for (uint32_t i = 0; i < onion_c->num_friends; ++i) {
2174
7.46k
            do_friend(onion_c, i);
2175
7.46k
        }
2176
4.24k
    }
2177
2178
8.30k
    if (onion_c->last_run == 0) {
2179
460
        onion_c->first_run = mono_time_get(onion_c->mono_time);
2180
460
    }
2181
2182
8.30k
    onion_c->last_run = mono_time_get(onion_c->mono_time);
2183
8.30k
}
2184
2185
Onion_Client *new_onion_client(const Logger *logger, const Memory *mem, const Random *rng, const Mono_Time *mono_time, Net_Crypto *c,
2186
                               DHT *dht, Networking_Core *net)
2187
1.93k
{
2188
1.93k
    if (c == nullptr) {
2189
0
        return nullptr;
2190
0
    }
2191
2192
1.93k
    Onion_Client *onion_c = (Onion_Client *)mem_alloc(mem, sizeof(Onion_Client));
2193
2194
1.93k
    if (onion_c == nullptr) {
2195
3
        return nullptr;
2196
3
    }
2197
2198
1.92k
    Ping_Array *const temp_ping_array = ping_array_new(mem, ANNOUNCE_ARRAY_SIZE, ANNOUNCE_TIMEOUT);
2199
2200
1.92k
    if (temp_ping_array == nullptr) {
2201
3
        mem_delete(mem, onion_c);
2202
3
        return nullptr;
2203
3
    }
2204
1.92k
    onion_c->announce_ping_array = temp_ping_array;
2205
2206
1.92k
    onion_c->mono_time = mono_time;
2207
1.92k
    onion_c->logger = logger;
2208
1.92k
    onion_c->rng = rng;
2209
1.92k
    onion_c->mem = mem;
2210
1.92k
    onion_c->dht = dht;
2211
1.92k
    onion_c->net = net;
2212
1.92k
    onion_c->c = c;
2213
1.92k
    onion_c->friends_list_capacity = 0;
2214
1.92k
    bs_list_init(&onion_c->friends_lookup, mem, CRYPTO_PUBLIC_KEY_SIZE, 0, memcmp);
2215
2216
1.92k
    new_symmetric_key(rng, onion_c->secret_symmetric_key);
2217
1.92k
    crypto_new_keypair(rng, onion_c->temp_public_key, onion_c->temp_secret_key);
2218
1.92k
    networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, &handle_announce_response, onion_c);
2219
1.92k
    networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE_OLD, &handle_announce_response_old, onion_c);
2220
1.92k
    networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, &handle_data_response, onion_c);
2221
1.92k
    oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, &handle_dhtpk_announce, onion_c);
2222
1.92k
    cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, &handle_dht_dhtpk, onion_c);
2223
1.92k
    set_onion_packet_tcp_connection_callback(nc_get_tcp_c(onion_c->c), &handle_tcp_onion, onion_c);
2224
2225
1.92k
    return onion_c;
2226
1.92k
}
2227
2228
void kill_onion_client(Onion_Client *onion_c)
2229
1.93k
{
2230
1.93k
    if (onion_c == nullptr) {
2231
6
        return;
2232
6
    }
2233
2234
1.92k
    const Memory *mem = onion_c->mem;
2235
2236
1.92k
    ping_array_kill(onion_c->announce_ping_array);
2237
1.92k
    realloc_onion_friends(onion_c, 0);
2238
1.92k
    bs_list_free(&onion_c->friends_lookup);
2239
1.92k
    networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE, nullptr, nullptr);
2240
1.92k
    networking_registerhandler(onion_c->net, NET_PACKET_ANNOUNCE_RESPONSE_OLD, nullptr, nullptr);
2241
1.92k
    networking_registerhandler(onion_c->net, NET_PACKET_ONION_DATA_RESPONSE, nullptr, nullptr);
2242
1.92k
    oniondata_registerhandler(onion_c, ONION_DATA_DHTPK, nullptr, nullptr);
2243
1.92k
    cryptopacket_registerhandler(onion_c->dht, CRYPTO_PACKET_DHTPK, nullptr, nullptr);
2244
1.92k
    set_onion_packet_tcp_connection_callback(nc_get_tcp_c(onion_c->c), nullptr, nullptr);
2245
1.92k
    crypto_memzero(onion_c, sizeof(Onion_Client));
2246
1.92k
    mem_delete(mem, onion_c);
2247
1.92k
}
2248
2249
uint64_t onion_testonly_get_last_packet_recv(const Onion_Client *onion_c)
2250
4
{
2251
4
    return onion_c->last_packet_recv;
2252
4
}
2253
2254
void onion_testonly_get_temp_public_key(const Onion_Client *onion_c, uint8_t *public_key)
2255
0
{
2256
0
    memcpy(public_key, onion_c->temp_public_key, CRYPTO_PUBLIC_KEY_SIZE);
2257
0
}
2258
2259
void onion_testonly_get_secret_symmetric_key(const Onion_Client *onion_c, uint8_t *secret_key)
2260
0
{
2261
0
    memcpy(secret_key, onion_c->secret_symmetric_key, CRYPTO_SYMMETRIC_KEY_SIZE);
2262
0
}