Coverage Report

Created: 2023-11-22 10:24

/src/c-toxcore/toxcore/announce.c
Line
Count
Source (jump to first uncovered line)
1
/* SPDX-License-Identifier: GPL-3.0-or-later
2
 * Copyright © 2020-2021 The TokTok team.
3
 */
4
5
/**
6
 * "Server side" of the DHT announcements protocol.
7
 */
8
9
#include "announce.h"
10
11
#include <assert.h>
12
#include <stdlib.h>
13
#include <string.h>
14
15
#include "LAN_discovery.h"
16
#include "ccompat.h"
17
#include "shared_key_cache.h"
18
#include "timed_auth.h"
19
#include "util.h"
20
21
// Settings for the shared key cache
22
3.08k
#define MAX_KEYS_PER_SLOT 4
23
3.08k
#define KEYS_TIMEOUT 600
24
25
uint8_t announce_response_of_request_type(uint8_t request_type)
26
8
{
27
8
    switch (request_type) {
28
6
        case NET_PACKET_DATA_SEARCH_REQUEST:
29
6
            return NET_PACKET_DATA_SEARCH_RESPONSE;
30
31
0
        case NET_PACKET_DATA_RETRIEVE_REQUEST:
32
0
            return NET_PACKET_DATA_RETRIEVE_RESPONSE;
33
34
2
        case NET_PACKET_STORE_ANNOUNCE_REQUEST:
35
2
            return NET_PACKET_STORE_ANNOUNCE_RESPONSE;
36
37
0
        default: {
38
0
            assert(false);
39
0
            return NET_PACKET_MAX;
40
0
        }
41
8
    }
42
8
}
43
44
typedef struct Announce_Entry {
45
    uint64_t store_until;
46
    uint8_t data_public_key[CRYPTO_PUBLIC_KEY_SIZE];
47
    uint8_t *data;
48
    uint32_t length;
49
} Announce_Entry;
50
51
struct Announcements {
52
    const Logger *log;
53
    const Memory *mem;
54
    const Random *rng;
55
    Forwarding *forwarding;
56
    const Mono_Time *mono_time;
57
    DHT *dht;
58
    Networking_Core *net;
59
    const uint8_t *public_key;
60
    const uint8_t *secret_key;
61
62
    Shared_Key_Cache *shared_keys;
63
    uint8_t hmac_key[CRYPTO_HMAC_KEY_SIZE];
64
65
    int32_t synch_offset;
66
67
    uint64_t start_time;
68
69
    Announce_Entry entries[ANNOUNCE_BUCKETS * ANNOUNCE_BUCKET_SIZE];
70
};
71
72
void announce_set_synch_offset(Announcements *announce, int32_t synch_offset)
73
0
{
74
0
    announce->synch_offset = synch_offset;
75
0
}
76
77
/**
78
 * An entry is considered to be "deleted" for the purposes of the protocol
79
 * once it has timed out.
80
 */
81
non_null()
82
static bool entry_is_empty(const Announcements *announce, const Announce_Entry *entry)
83
51
{
84
51
    return mono_time_get(announce->mono_time) >= entry->store_until;
85
51
}
86
87
non_null()
88
static void delete_entry(Announce_Entry *entry)
89
0
{
90
0
    entry->store_until = 0;
91
0
}
92
93
/** Return bits (at most 8) from pk starting at index as uint8_t */
94
non_null()
95
static uint8_t truncate_pk_at_index(const uint8_t *pk, uint16_t index, uint16_t bits)
96
32
{
97
32
    assert(bits < 8);
98
0
    const uint8_t i = index / 8;
99
32
    const uint8_t j = index % 8;
100
32
    return ((uint8_t)((i < CRYPTO_PUBLIC_KEY_SIZE ? pk[i] : 0) << j) >> (8 - bits)) |
101
32
           ((i + 1 < CRYPTO_PUBLIC_KEY_SIZE ? pk[i + 1] : 0) >> (16 - bits - j));
102
32
}
103
104
uint16_t announce_get_bucketnum(const uint8_t *base, const uint8_t *pk)
105
16
{
106
16
    const uint16_t index = bit_by_bit_cmp(base, pk);
107
108
16
    return truncate_pk_at_index(base, index + 1, ANNOUNCE_BUCKET_PREFIX_LENGTH) ^
109
16
           truncate_pk_at_index(pk, index + 1, ANNOUNCE_BUCKET_PREFIX_LENGTH);
110
16
}
111
112
non_null()
113
static Announce_Entry *bucket_of_key(Announcements *announce, const uint8_t *pk)
114
10
{
115
10
    return &announce->entries[announce_get_bucketnum(announce->public_key, pk) * ANNOUNCE_BUCKET_SIZE];
116
10
}
117
118
non_null()
119
static Announce_Entry *get_stored(Announcements *announce, const uint8_t *data_public_key)
120
2
{
121
2
    Announce_Entry *const bucket = bucket_of_key(announce, data_public_key);
122
123
10
    for (uint32_t i = 0; i < ANNOUNCE_BUCKET_SIZE; ++i) {
124
9
        if (pk_equal(bucket[i].data_public_key, data_public_key)) {
125
1
            if (entry_is_empty(announce, &bucket[i])) {
126
1
                break;
127
1
            }
128
129
0
            return &bucket[i];
130
1
        }
131
9
    }
132
133
2
    return nullptr;
134
2
}
135
136
non_null()
137
static const Announce_Entry *bucket_of_key_const(const Announcements *announce, const uint8_t *pk)
138
6
{
139
6
    return &announce->entries[announce_get_bucketnum(announce->public_key, pk) * ANNOUNCE_BUCKET_SIZE];
140
6
}
141
142
non_null()
143
static const Announce_Entry *get_stored_const(const Announcements *announce, const uint8_t *data_public_key)
144
6
{
145
6
    const Announce_Entry *const bucket = bucket_of_key_const(announce, data_public_key);
146
147
38
    for (uint32_t i = 0; i < ANNOUNCE_BUCKET_SIZE; ++i) {
148
34
        if (pk_equal(bucket[i].data_public_key, data_public_key)) {
149
2
            if (entry_is_empty(announce, &bucket[i])) {
150
2
                break;
151
2
            }
152
153
0
            return &bucket[i];
154
2
        }
155
34
    }
156
157
6
    return nullptr;
158
6
}
159
160
161
bool announce_on_stored(const Announcements *announce, const uint8_t *data_public_key,
162
                        announce_on_retrieve_cb *on_retrieve_callback, void *object)
163
0
{
164
0
    const Announce_Entry *const entry = get_stored_const(announce, data_public_key);
165
166
0
    if (entry == nullptr || entry->data == nullptr) {
167
0
        return false;
168
0
    }
169
170
0
    if (on_retrieve_callback != nullptr) {
171
0
        on_retrieve_callback(object, entry->data, entry->length);
172
0
    }
173
174
0
    return true;
175
0
}
176
177
/**
178
 * Return existing entry for this key if it exists, else an empty
179
 * slot in the key's bucket if one exists, else an entry in the key's bucket
180
 * of greatest 2-adic distance greater than that of the key bucket if one
181
 * exists, else nullptr.
182
 */
183
non_null()
184
static Announce_Entry *find_entry_slot(Announcements *announce, const uint8_t *data_public_key)
185
8
{
186
8
    Announce_Entry *const bucket = bucket_of_key(announce, data_public_key);
187
188
8
    Announce_Entry *slot = nullptr;
189
8
    uint16_t min_index = bit_by_bit_cmp(announce->public_key, data_public_key);
190
191
56
    for (uint32_t i = 0; i < ANNOUNCE_BUCKET_SIZE; ++i) {
192
50
        if (pk_equal(bucket[i].data_public_key, data_public_key)) {
193
2
            return &bucket[i];
194
2
        }
195
196
48
        if (entry_is_empty(announce, &bucket[i])) {
197
48
            slot = &bucket[i];
198
48
            min_index = 0;
199
48
            continue;
200
48
        }
201
202
0
        const uint16_t index = bit_by_bit_cmp(announce->public_key, bucket[i].data_public_key);
203
204
0
        if (index < min_index) {
205
0
            slot = &bucket[i];
206
0
            min_index = index;
207
0
        }
208
0
    }
209
210
6
    return slot;
211
8
}
212
213
non_null()
214
static bool would_accept_store_request(Announcements *announce, const uint8_t *data_public_key)
215
6
{
216
6
    return find_entry_slot(announce, data_public_key) != nullptr;
217
6
}
218
219
bool announce_store_data(Announcements *announce, const uint8_t *data_public_key,
220
                         const uint8_t *data, uint32_t length, uint32_t timeout)
221
3
{
222
3
    if (length > MAX_ANNOUNCEMENT_SIZE) {
223
1
        return false;
224
1
    }
225
226
2
    Announce_Entry *entry = find_entry_slot(announce, data_public_key);
227
228
2
    if (entry == nullptr) {
229
0
        return false;
230
0
    }
231
232
2
    if (length > 0) {
233
1
        assert(data != nullptr);
234
235
1
        if (entry->data != nullptr) {
236
0
            free(entry->data);
237
0
        }
238
239
1
        entry->data = (uint8_t *)malloc(length);
240
241
1
        if (entry->data == nullptr) {
242
0
            return false;
243
0
        }
244
245
1
        memcpy(entry->data, data, length);
246
1
    }
247
248
2
    entry->length = length;
249
2
    memcpy(entry->data_public_key, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
250
2
    entry->store_until = mono_time_get(announce->mono_time) + timeout;
251
252
2
    return true;
253
2
}
254
255
non_null()
256
static uint32_t calculate_timeout(const Announcements *announce, uint32_t requested_timeout)
257
22
{
258
22
    const uint64_t uptime = mono_time_get(announce->mono_time) - announce->start_time;
259
22
    const uint32_t max_announcement_timeout = max_u32(
260
22
                (uint32_t)min_u64(
261
22
                    MAX_MAX_ANNOUNCEMENT_TIMEOUT,
262
22
                    uptime / MAX_ANNOUNCEMENT_TIMEOUT_UPTIME_RATIO),
263
22
                MIN_MAX_ANNOUNCEMENT_TIMEOUT);
264
265
22
    return min_u32(max_announcement_timeout, requested_timeout);
266
22
}
267
268
195
#define DATA_SEARCH_TO_AUTH_MAX_SIZE (CRYPTO_PUBLIC_KEY_SIZE * 2 + MAX_PACKED_IPPORT_SIZE + MAX_SENDBACK_SIZE)
269
270
non_null(1, 2, 3, 4, 7) nullable(5)
271
static int create_data_search_to_auth(const Logger *logger, const uint8_t *data_public_key,
272
                                      const uint8_t *requester_key,
273
                                      const IP_Port *source, const uint8_t *sendback, uint16_t sendback_length,
274
                                      uint8_t *dest, uint16_t max_length)
275
65
{
276
65
    if (max_length < DATA_SEARCH_TO_AUTH_MAX_SIZE
277
65
            || sendback_length > MAX_SENDBACK_SIZE) {
278
1
        return -1;
279
1
    }
280
281
64
    memcpy(dest, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
282
64
    memcpy(dest + CRYPTO_PUBLIC_KEY_SIZE, requester_key, CRYPTO_PUBLIC_KEY_SIZE);
283
284
64
    const int ipport_length = pack_ip_port(logger, dest + CRYPTO_PUBLIC_KEY_SIZE * 2, MAX_PACKED_IPPORT_SIZE, source);
285
286
64
    if (ipport_length == -1) {
287
0
        return -1;
288
0
    }
289
290
64
    if (sendback_length > 0) {
291
3
        assert(sendback != nullptr);
292
3
        memcpy(dest + CRYPTO_PUBLIC_KEY_SIZE * 2 + ipport_length, sendback, sendback_length);
293
3
    }
294
295
64
    return CRYPTO_PUBLIC_KEY_SIZE * 2 + ipport_length + sendback_length;
296
64
}
297
298
29
#define DATA_SEARCH_TIMEOUT 60
299
300
non_null()
301
static int create_reply_plain_data_search_request(Announcements *announce,
302
        const IP_Port *source,
303
        const uint8_t *data, uint16_t length,
304
        uint8_t *reply, uint16_t reply_max_length,
305
        uint8_t *to_auth, uint16_t to_auth_length)
306
16
{
307
16
    if (length != CRYPTO_PUBLIC_KEY_SIZE &&
308
16
            length != CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA256_SIZE) {
309
10
        return -1;
310
10
    }
311
312
6
    const uint8_t *const data_public_key = data;
313
314
6
    const uint8_t *previous_hash = nullptr;
315
316
6
    if (length == CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_SHA256_SIZE) {
317
3
        previous_hash = data + CRYPTO_PUBLIC_KEY_SIZE;
318
3
    }
319
320
6
    const int nodes_max_length = (int)reply_max_length -
321
6
                                 (CRYPTO_PUBLIC_KEY_SIZE + 1 + CRYPTO_SHA256_SIZE + TIMED_AUTH_SIZE + 1 + 1);
322
323
6
    if (nodes_max_length < 0) {
324
0
        return -1;
325
0
    }
326
327
6
    uint8_t *p = reply;
328
329
6
    memcpy(p, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
330
6
    p += CRYPTO_PUBLIC_KEY_SIZE;
331
332
6
    const Announce_Entry *const stored = get_stored_const(announce, data_public_key);
333
334
6
    if (stored == nullptr) {
335
6
        *p = 0;
336
6
        ++p;
337
6
    } else {
338
0
        *p = 1;
339
0
        ++p;
340
0
        crypto_sha256(p, stored->data, stored->length);
341
0
        p += CRYPTO_SHA256_SIZE;
342
0
    }
343
344
6
    generate_timed_auth(announce->mono_time, DATA_SEARCH_TIMEOUT, announce->hmac_key,
345
6
                        to_auth, to_auth_length, p);
346
6
    p += TIMED_AUTH_SIZE;
347
348
6
    *p = would_accept_store_request(announce, data_public_key);
349
6
    ++p;
350
351
6
    Node_format nodes_list[MAX_SENT_NODES];
352
6
    const int num_nodes = get_close_nodes(announce->dht, data_public_key, nodes_list,
353
6
                                          net_family_unspec(), ip_is_lan(&source->ip), true);
354
355
6
    if (num_nodes < 0 || num_nodes > MAX_SENT_NODES) {
356
0
        return -1;
357
0
    }
358
359
6
    *p = num_nodes;
360
6
    ++p;
361
362
6
    p += pack_nodes(announce->log, p, nodes_max_length, nodes_list, num_nodes);
363
364
6
    const uint32_t reply_len = p - reply;
365
366
6
    if (previous_hash != nullptr) {
367
3
        uint8_t hash[CRYPTO_SHA256_SIZE];
368
369
3
        crypto_sha256(hash, reply, reply_len);
370
371
3
        if (crypto_sha256_eq(hash, previous_hash)) {
372
1
            return CRYPTO_PUBLIC_KEY_SIZE;
373
1
        }
374
3
    }
375
376
5
    return reply_len;
377
6
}
378
379
non_null()
380
static int create_reply_plain_data_retrieve_request(Announcements *announce,
381
        const IP_Port *source,
382
        const uint8_t *data, uint16_t length,
383
        uint8_t *reply, uint16_t reply_max_length,
384
        uint8_t *to_auth, uint16_t to_auth_length)
385
12
{
386
12
    if (length != CRYPTO_PUBLIC_KEY_SIZE + 1 + TIMED_AUTH_SIZE) {
387
10
        return -1;
388
10
    }
389
390
2
    if (data[CRYPTO_PUBLIC_KEY_SIZE] != 0) {
391
1
        return -1;
392
1
    }
393
394
1
    const uint8_t *const data_public_key = data;
395
1
    const uint8_t *const auth = data + CRYPTO_PUBLIC_KEY_SIZE + 1;
396
397
1
    if (!check_timed_auth(announce->mono_time, DATA_SEARCH_TIMEOUT, announce->hmac_key,
398
1
                          to_auth, to_auth_length, auth)) {
399
1
        return -1;
400
1
    }
401
402
0
    const Announce_Entry *const entry = get_stored_const(announce, data_public_key);
403
404
0
    if (entry == nullptr) {
405
0
        return -1;
406
0
    }
407
408
0
    const uint16_t reply_len = CRYPTO_PUBLIC_KEY_SIZE + 1 + entry->length;
409
410
0
    if (reply_max_length < reply_len) {
411
0
        return -1;
412
0
    }
413
414
0
    memcpy(reply, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
415
0
    reply[CRYPTO_PUBLIC_KEY_SIZE] = 1;
416
0
    memcpy(reply + CRYPTO_PUBLIC_KEY_SIZE + 1, entry->data, entry->length);
417
418
0
    return reply_len;
419
0
}
420
421
non_null()
422
static int create_reply_plain_store_announce_request(Announcements *announce,
423
        const IP_Port *source,
424
        const uint8_t *data, uint16_t length,
425
        uint8_t *reply, uint16_t reply_max_length,
426
        uint8_t *to_auth, uint16_t to_auth_length)
427
33
{
428
33
    const int plain_len = (int)length - (CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE);
429
33
    const int announcement_len = (int)plain_len - (TIMED_AUTH_SIZE + sizeof(uint32_t) + 1);
430
431
33
    const uint8_t *const data_public_key = data;
432
433
33
    if (announcement_len < 0) {
434
11
        return -1;
435
11
    }
436
437
22
    VLA(uint8_t, plain, plain_len);
438
439
22
    const uint8_t* shared_key = shared_key_cache_lookup(announce->shared_keys, data_public_key);
440
441
22
    if (shared_key == nullptr) {
442
        /* Error looking up/deriving the shared key */
443
0
        return -1;
444
0
    }
445
446
22
    if (decrypt_data_symmetric(shared_key,
447
22
                               data + CRYPTO_PUBLIC_KEY_SIZE,
448
22
                               data + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
449
22
                               plain_len + CRYPTO_MAC_SIZE,
450
22
                               plain) != plain_len) {
451
0
        return -1;
452
0
    }
453
454
22
    const uint8_t *const auth = plain;
455
22
    uint32_t requested_timeout;
456
22
    net_unpack_u32(plain + TIMED_AUTH_SIZE, &requested_timeout);
457
22
    const uint32_t timeout = calculate_timeout(announce, requested_timeout);
458
22
    const uint8_t announcement_type = plain[TIMED_AUTH_SIZE + sizeof(uint32_t)];
459
22
    const uint8_t *announcement = plain + TIMED_AUTH_SIZE + sizeof(uint32_t) + 1;
460
461
22
    if (!check_timed_auth(announce->mono_time, DATA_SEARCH_TIMEOUT, announce->hmac_key,
462
22
                          to_auth, to_auth_length, auth)) {
463
15
        return -1;
464
15
    }
465
466
7
    if (announcement_type > 1) {
467
1
        return -1;
468
1
    }
469
470
6
    if (announcement_type == 1) {
471
3
        if (announcement_len != CRYPTO_SHA256_SIZE) {
472
1
            return -1;
473
1
        }
474
475
2
        Announce_Entry *stored = get_stored(announce, data_public_key);
476
477
2
        if (stored == nullptr) {
478
2
            return -1;
479
2
        }
480
481
0
        uint8_t stored_hash[CRYPTO_SHA256_SIZE];
482
0
        crypto_sha256(stored_hash, stored->data, stored->length);
483
484
0
        if (!crypto_sha256_eq(announcement, stored_hash)) {
485
0
            delete_entry(stored);
486
0
            return -1;
487
0
        } else {
488
0
            stored->store_until = mono_time_get(announce->mono_time) + timeout;
489
0
        }
490
3
    } else {
491
3
        if (!announce_store_data(announce, data_public_key, announcement, announcement_len, timeout)) {
492
1
            return -1;
493
1
        }
494
3
    }
495
496
2
    const uint16_t reply_len = CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t) + sizeof(uint64_t);
497
498
2
    if (reply_max_length < reply_len) {
499
0
        return -1;
500
0
    }
501
502
2
    memcpy(reply, data_public_key, CRYPTO_PUBLIC_KEY_SIZE);
503
2
    net_pack_u32(reply + CRYPTO_PUBLIC_KEY_SIZE, timeout);
504
2
    net_pack_u64(reply + CRYPTO_PUBLIC_KEY_SIZE + sizeof(uint32_t),
505
2
                 mono_time_get(announce->mono_time) + announce->synch_offset);
506
2
    return reply_len;
507
2
}
508
509
non_null(1, 2, 3, 7, 9) nullable(5)
510
static int create_reply_plain(Announcements *announce,
511
                              const uint8_t *requester_key, const IP_Port *source, uint8_t type,
512
                              const uint8_t *sendback, uint16_t sendback_length,
513
                              const uint8_t *data, uint16_t length,
514
                              uint8_t *reply, uint16_t reply_max_length)
515
75
{
516
75
    if (length < CRYPTO_PUBLIC_KEY_SIZE) {
517
10
        return -1;
518
10
    }
519
520
65
    const uint8_t *const data_public_key = data;
521
522
65
    uint8_t to_auth[DATA_SEARCH_TO_AUTH_MAX_SIZE];
523
65
    const int to_auth_length = create_data_search_to_auth(announce->log, data_public_key, requester_key, source,
524
65
                               sendback, sendback_length, to_auth, DATA_SEARCH_TO_AUTH_MAX_SIZE);
525
526
65
    if (to_auth_length == -1) {
527
1
        return -1;
528
1
    }
529
530
64
    switch (type) {
531
16
        case NET_PACKET_DATA_SEARCH_REQUEST:
532
16
            return create_reply_plain_data_search_request(announce, source, data, length, reply, reply_max_length, to_auth,
533
16
                    (uint16_t)to_auth_length);
534
535
12
        case NET_PACKET_DATA_RETRIEVE_REQUEST:
536
12
            return create_reply_plain_data_retrieve_request(announce, source, data, length, reply, reply_max_length, to_auth,
537
12
                    (uint16_t)to_auth_length);
538
539
33
        case NET_PACKET_STORE_ANNOUNCE_REQUEST:
540
33
            return create_reply_plain_store_announce_request(announce, source, data, length, reply, reply_max_length, to_auth,
541
33
                    (uint16_t)to_auth_length);
542
543
3
        default:
544
3
            return -1;
545
64
    }
546
64
}
547
548
non_null(1, 2, 5, 7) nullable(3)
549
static int create_reply(Announcements *announce, const IP_Port *source,
550
                        const uint8_t *sendback, uint16_t sendback_length,
551
                        const uint8_t *data, uint16_t length,
552
                        uint8_t *reply, uint16_t reply_max_length)
553
89
{
554
89
    const int plain_len = (int)length - (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE);
555
556
89
    if (plain_len < (int)sizeof(uint64_t)) {
557
14
        return -1;
558
14
    }
559
560
75
    VLA(uint8_t, plain, plain_len);
561
75
    const uint8_t *shared_key = dht_get_shared_key_recv(announce->dht, data + 1);
562
563
75
    if (decrypt_data_symmetric(shared_key,
564
75
                               data + 1 + CRYPTO_PUBLIC_KEY_SIZE,
565
75
                               data + 1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE,
566
75
                               plain_len + CRYPTO_MAC_SIZE,
567
75
                               plain) != plain_len) {
568
0
        return -1;
569
0
    }
570
571
75
    const int plain_reply_max_len = (int)reply_max_length -
572
75
                                    (1 + CRYPTO_PUBLIC_KEY_SIZE + CRYPTO_NONCE_SIZE + CRYPTO_MAC_SIZE);
573
574
75
    if (plain_reply_max_len < sizeof(uint64_t)) {
575
0
        return -1;
576
0
    }
577
578
75
    VLA(uint8_t, plain_reply, plain_reply_max_len);
579
580
75
    const int plain_reply_noping_len = create_reply_plain(announce,
581
75
                                       data + 1, source, data[0],
582
75
                                       sendback, sendback_length,
583
75
                                       plain, plain_len - sizeof(uint64_t),
584
75
                                       plain_reply, plain_reply_max_len - sizeof(uint64_t));
585
586
75
    if (plain_reply_noping_len == -1) {
587
67
        return -1;
588
67
    }
589
590
8
    memcpy(plain_reply + plain_reply_noping_len,
591
8
           plain + (plain_len - sizeof(uint64_t)), sizeof(uint64_t));
592
593
8
    const uint16_t plain_reply_len = plain_reply_noping_len + sizeof(uint64_t);
594
595
8
    const uint8_t response_type = announce_response_of_request_type(data[0]);
596
597
8
    return dht_create_packet(announce->mem, announce->rng, announce->public_key, shared_key,
598
8
                             response_type, plain_reply, plain_reply_len, reply, reply_max_length);
599
75
}
600
601
non_null(1, 2, 3, 5) nullable(7)
602
static void forwarded_request_callback(void *object, const IP_Port *forwarder,
603
                                       const uint8_t *sendback, uint16_t sendback_length,
604
                                       const uint8_t *data, uint16_t length, void *userdata)
605
7
{
606
7
    Announcements *announce = (Announcements *) object;
607
608
7
    uint8_t reply[MAX_FORWARD_DATA_SIZE];
609
610
7
    const int len = create_reply(announce, forwarder,
611
7
                                 sendback, sendback_length,
612
7
                                 data, length, reply, sizeof(reply));
613
614
7
    if (len == -1) {
615
7
        return;
616
7
    }
617
618
0
    forward_reply(announce->net, forwarder, sendback, sendback_length, reply, len);
619
0
}
620
621
non_null(1, 2, 3) nullable(5)
622
static int handle_dht_announce_request(void *object, const IP_Port *source,
623
                                       const uint8_t *data, uint16_t length, void *userdata)
624
82
{
625
82
    Announcements *announce = (Announcements *) object;
626
627
82
    uint8_t reply[MAX_FORWARD_DATA_SIZE];
628
629
82
    const int len = create_reply(announce, source,
630
82
                                 nullptr, 0,
631
82
                                 data, length, reply, sizeof(reply));
632
633
82
    if (len == -1) {
634
74
        return -1;
635
74
    }
636
637
8
    return sendpacket(announce->net, source, reply, len) == len ? 0 : -1;
638
82
}
639
640
Announcements *new_announcements(const Logger *log, const Memory *mem, const Random *rng, const Mono_Time *mono_time,
641
                                 Forwarding *forwarding)
642
3.08k
{
643
3.08k
    if (log == nullptr || mono_time == nullptr || forwarding == nullptr) {
644
0
        return nullptr;
645
0
    }
646
647
3.08k
    Announcements *announce = (Announcements *)calloc(1, sizeof(Announcements));
648
649
3.08k
    if (announce == nullptr) {
650
0
        return nullptr;
651
0
    }
652
653
3.08k
    announce->log = log;
654
3.08k
    announce->mem = mem;
655
3.08k
    announce->rng = rng;
656
3.08k
    announce->forwarding = forwarding;
657
3.08k
    announce->mono_time = mono_time;
658
3.08k
    announce->dht = forwarding_get_dht(forwarding);
659
3.08k
    announce->net = dht_get_net(announce->dht);
660
3.08k
    announce->public_key = dht_get_self_public_key(announce->dht);
661
3.08k
    announce->secret_key = dht_get_self_secret_key(announce->dht);
662
3.08k
    new_hmac_key(announce->rng, announce->hmac_key);
663
3.08k
    announce->shared_keys = shared_key_cache_new(mono_time, mem, announce->secret_key, KEYS_TIMEOUT, MAX_KEYS_PER_SLOT);
664
3.08k
    if (announce->shared_keys == nullptr) {
665
5
        free(announce);
666
5
        return nullptr;
667
5
    }
668
669
3.08k
    announce->start_time = mono_time_get(announce->mono_time);
670
671
3.08k
    set_callback_forwarded_request(forwarding, forwarded_request_callback, announce);
672
673
3.08k
    networking_registerhandler(announce->net, NET_PACKET_DATA_SEARCH_REQUEST, handle_dht_announce_request, announce);
674
3.08k
    networking_registerhandler(announce->net, NET_PACKET_DATA_RETRIEVE_REQUEST, handle_dht_announce_request, announce);
675
3.08k
    networking_registerhandler(announce->net, NET_PACKET_STORE_ANNOUNCE_REQUEST, handle_dht_announce_request, announce);
676
677
3.08k
    return announce;
678
3.08k
}
679
680
void kill_announcements(Announcements *announce)
681
3.08k
{
682
3.08k
    if (announce == nullptr) {
683
5
        return;
684
5
    }
685
686
3.08k
    set_callback_forwarded_request(announce->forwarding, nullptr, nullptr);
687
688
3.08k
    networking_registerhandler(announce->net, NET_PACKET_DATA_SEARCH_REQUEST, nullptr, nullptr);
689
3.08k
    networking_registerhandler(announce->net, NET_PACKET_DATA_RETRIEVE_REQUEST, nullptr, nullptr);
690
3.08k
    networking_registerhandler(announce->net, NET_PACKET_STORE_ANNOUNCE_REQUEST, nullptr, nullptr);
691
692
3.08k
    crypto_memzero(announce->hmac_key, CRYPTO_HMAC_KEY_SIZE);
693
3.08k
    shared_key_cache_free(announce->shared_keys);
694
695
792k
    for (uint32_t i = 0; i < ANNOUNCE_BUCKETS * ANNOUNCE_BUCKET_SIZE; ++i) {
696
788k
        if (announce->entries[i].data != nullptr) {
697
1
            free(announce->entries[i].data);
698
1
        }
699
788k
    }
700
701
3.08k
    free(announce);
702
3.08k
}