Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit fff3205

Browse files
Briastanneberger
authored andcommitted
rtr: Check for plausible length of ASPA PDU
- [draft-ietf-sidrops-8210bis-21] specifies that an ASPA PDU must have a length that is divisible by 4 to be correct. This commit adds a check and if its length is not divisible by 4 a `Corrupt Data (0)` error is sent. - The unit tests in `test_aspa.c` are extended by checks for sent error PDUs. [draft-ietf-sidrops-8210bis-21]: https://datatracker.ietf.org/doc/html/draft-ietf-sidrops-8210bis-21#name-aspa-pdu
1 parent 7fb3b1b commit fff3205

File tree

3 files changed

+96
-2
lines changed

3 files changed

+96
-2
lines changed

rtrlib/rtr/packets.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -540,6 +540,15 @@ static int rtr_receive_pdu(struct rtr_socket *rtr_socket, void *pdu, const size_
540540
goto error;
541541
}
542542

543+
// ASPA PDUs must have a length that is divisible by 4 Since the minimum length
544+
// is 12 (no Provider Autonomous System Numbers) and each Provider Autonomous
545+
// System Number that is added will increase the length by 4 octets. Thus,
546+
// if the length is not divisible by 0 the received data is corrupt.
547+
if (((struct pdu_aspa *)pdu)->len % 4 != 0) {
548+
error = CORRUPT_DATA;
549+
goto error;
550+
}
551+
543552
if (((struct pdu_aspa *)pdu)->zero != 0)
544553
RTR_DBG1("Warning: Zero field of received ASPA PDU doesn't contain 0");
545554
}

rtrlib/rtr/rtr_pdus.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,13 @@ enum pdu_error_type {
1313
DUPLICATE_ANNOUNCEMENT = 7,
1414
UNEXPECTED_PROTOCOL_VERSION = 8,
1515
INCORRECT_ASPA_PROVIDER_LIST = 9,
16-
PDU_TOO_BIG = 32
16+
17+
// This error code is not specified in the RPKI to router
18+
// drafts/RFCs but solely used internally to differentiate
19+
// between a PDU that is too big and other `CORRUPT_DATA`
20+
// scenarios so that appropriate logging and other actions
21+
// can be performed.
22+
PDU_TOO_BIG = 32,
1723
};
1824

1925
enum pdu_type {

tests/test_aspa.c

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,27 @@ struct update_callback *expected_callbacks;
3131
size_t callback_index;
3232
size_t callback_count;
3333

34+
/*
35+
* Expected error PDUs sent by the RTRlib in the tests.
36+
*
37+
* Other PDUs are not expected since the tests pass the test data
38+
* directly to the receiver function circumventing the need of an
39+
* initially sent SerialQuery or ResetQuery.
40+
*/
41+
struct sent_pdu *expected_error_pdus;
42+
size_t expected_error_pdus_index;
43+
size_t expected_error_pdus_count;
44+
3445
struct update_callback {
3546
struct aspa_table *source;
3647
struct aspa_record record;
3748
enum aspa_operation_type type;
3849
};
3950

51+
struct sent_pdu {
52+
uint16_t error_code;
53+
};
54+
4055
#define BYTES16(X) lrtr_convert_short(TO_HOST_HOST_BYTE_ORDER, X)
4156
#define BYTES32(X) lrtr_convert_long(TO_HOST_HOST_BYTE_ORDER, X)
4257

@@ -78,6 +93,16 @@ struct update_callback {
7893

7994
#define EXPECT_NO_UPDATE_CALLBACKS() \
8095
expect_update_callbacks(NULL, 0)
96+
97+
#define ERROR_PDU(err_code) ((struct sent_pdu) {.error_code = err_code})
98+
99+
#define EXPECT_ERROR_PDUS_SENT(...) \
100+
struct sent_pdu _LINEVAR(_sent_pdus)[] = {__VA_ARGS__}; \
101+
expect_sent_pdus(_LINEVAR(_sent_pdus), \
102+
(size_t)(sizeof(_LINEVAR(_sent_pdus)) / sizeof(struct sent_pdu)))
103+
104+
#define EXPECT_NO_ERROR_PDUS_SENT() \
105+
expect_sent_pdus(NULL, 0)
81106
// clang-format on
82107

83108
#define ASPA_ANNOUNCE 1
@@ -88,6 +113,11 @@ static int custom_send(const struct tr_socket *socket __attribute__((unused)), c
88113
{
89114
const struct pdu_error *err = pdu;
90115

116+
assert(expected_error_pdus != NULL);
117+
assert(expected_error_pdus_index < expected_error_pdus_count);
118+
uint16_t error_code = BYTES16(err->error_code);
119+
assert(expected_error_pdus[expected_error_pdus_index].error_code == error_code);
120+
91121
if (err->type == 10) {
92122
uint32_t *errlen = (uint32_t *)((char *)err->rest + err->len_enc_pdu);
93123

@@ -198,6 +228,20 @@ static void expect_update_callbacks(struct update_callback callbacks[], size_t c
198228
}
199229
}
200230

231+
static void expect_sent_pdus(struct sent_pdu sent_pdus[], size_t count)
232+
{
233+
expected_error_pdus = sent_pdus;
234+
expected_error_pdus_index = 0;
235+
expected_error_pdus_count = count;
236+
}
237+
238+
static void clear_expected_sent_pdus(void)
239+
{
240+
expected_error_pdus = NULL;
241+
expected_error_pdus_index = 0;
242+
expected_error_pdus_count = 0;
243+
}
244+
201245
static void aspa_update_callback(struct aspa_table *s, const struct aspa_record record,
202246
const struct rtr_socket *rtr_sockt __attribute__((unused)),
203247
const enum aspa_operation_type operation_type)
@@ -316,6 +360,7 @@ static void test_no_aspa(struct rtr_socket *socket)
316360
end_cache_response(RTR_PROTOCOL_VERSION_2, 0, 437);
317361

318362
EXPECT_NO_UPDATE_CALLBACKS();
363+
EXPECT_NO_ERROR_PDUS_SENT();
319364

320365
assert(rtr_sync(socket) == RTR_SUCCESS);
321366
assert(callback_index == callback_count);
@@ -336,6 +381,7 @@ static void test_regular_announcement(struct rtr_socket *socket)
336381
EXPECT_UPDATE_CALLBACKS(
337382
ADDED(RECORD(1100, ASNS(1101, 1102, 1103, 1104))),
338383
);
384+
EXPECT_NO_ERROR_PDUS_SENT();
339385

340386
assert(rtr_sync(socket) == RTR_SUCCESS);
341387
assert(callback_index == callback_count);
@@ -359,6 +405,7 @@ static void test_withdraw(struct rtr_socket *socket)
359405
EXPECT_UPDATE_CALLBACKS(
360406
REMOVED(RECORD(1100, ASNS(1101, 1102, 1103, 1104))),
361407
);
408+
EXPECT_NO_ERROR_PDUS_SENT();
362409

363410
assert(rtr_sync(socket) == RTR_SUCCESS);
364411
assert(callback_index == callback_count);
@@ -380,6 +427,7 @@ static void test_regular_announcements(struct rtr_socket *socket)
380427
ADDED(RECORD(1100, ASNS(1101, 1102, 1103, 1104))),
381428
ADDED(RECORD(4400, ASNS(4401))),
382429
);
430+
EXPECT_NO_ERROR_PDUS_SENT();
383431

384432
assert(rtr_sync(socket) == RTR_SUCCESS);
385433
assert(callback_index == callback_count);
@@ -405,6 +453,7 @@ static void test_announce_existing(struct rtr_socket *socket)
405453

406454
// No updates expected, fails at first PDU
407455
EXPECT_NO_UPDATE_CALLBACKS();
456+
EXPECT_ERROR_PDUS_SENT(ERROR_PDU(DUPLICATE_ANNOUNCEMENT));
408457

409458
assert(rtr_sync(socket) == RTR_ERROR);
410459
assert(callback_index == callback_count);
@@ -427,6 +476,7 @@ static void test_announce_twice(struct rtr_socket *socket)
427476

428477
// No updates expected, fails at first PDU
429478
EXPECT_NO_UPDATE_CALLBACKS();
479+
EXPECT_ERROR_PDUS_SENT(ERROR_PDU(DUPLICATE_ANNOUNCEMENT));
430480

431481
assert(rtr_sync(socket) == RTR_ERROR);
432482
assert(callback_index == callback_count);
@@ -449,6 +499,7 @@ static void test_withdraw_nonexisting(struct rtr_socket *socket)
449499

450500
// No updates expected, fails at first PDU
451501
EXPECT_NO_UPDATE_CALLBACKS();
502+
EXPECT_ERROR_PDUS_SENT(ERROR_PDU(WITHDRAWAL_OF_UNKNOWN_RECORD));
452503

453504
assert(rtr_sync(socket) == RTR_ERROR);
454505
assert(callback_index == callback_count);
@@ -478,6 +529,8 @@ static void test_announce_withdraw(struct rtr_socket *socket)
478529
#else
479530
EXPECT_NO_UPDATE_CALLBACKS();
480531
#endif
532+
EXPECT_NO_ERROR_PDUS_SENT();
533+
481534

482535
assert(rtr_sync(socket) == RTR_SUCCESS);
483536
assert(callback_index == callback_count);
@@ -516,6 +569,7 @@ static void test_withdraw_announce(struct rtr_socket *socket)
516569
ADDED(RECORD(1100, ASNS(2201, 2202, 2203, 2204))),
517570
);
518571
#endif
572+
EXPECT_NO_ERROR_PDUS_SENT();
519573

520574
assert(rtr_sync(socket) == RTR_SUCCESS);
521575
assert(callback_index == callback_count);
@@ -540,6 +594,7 @@ static void test_regular(struct rtr_socket *socket)
540594
ADDED(RECORD(1101, ASNS(1100, 1102, 1103, 1104))),
541595
ADDED(RECORD(2200, ASNS(2201, 2202, 2203, 2204))),
542596
);
597+
EXPECT_NO_ERROR_PDUS_SENT();
543598

544599
assert(rtr_sync(socket) == RTR_SUCCESS);
545600
assert(callback_index == callback_count);
@@ -557,6 +612,7 @@ static void test_regular(struct rtr_socket *socket)
557612
EXPECT_UPDATE_CALLBACKS(
558613
ADDED(RECORD(3300, ASNS(3301, 3302, 3303, 3304))),
559614
);
615+
EXPECT_NO_ERROR_PDUS_SENT();
560616

561617
assert(rtr_sync(socket) == RTR_SUCCESS);
562618
assert(callback_index == callback_count);
@@ -579,6 +635,7 @@ static void test_regular(struct rtr_socket *socket)
579635
ADDED(RECORD(1100, ASNS(1201, 1202, 1203, 1204))),
580636
REMOVED(RECORD(2200, ASNS(2201, 2202, 2203, 2204))),
581637
);
638+
EXPECT_NO_ERROR_PDUS_SENT();
582639

583640
assert(rtr_sync(socket) == RTR_SUCCESS);
584641
assert(callback_index == callback_count);
@@ -605,6 +662,7 @@ static void test_regular(struct rtr_socket *socket)
605662
printf("Ignoring No-Ops!\n");
606663
EXPECT_NO_UPDATE_CALLBACKS();
607664
#endif
665+
EXPECT_NO_ERROR_PDUS_SENT();
608666

609667
assert(rtr_sync(socket) == RTR_SUCCESS);
610668
assert(callback_index == callback_count);
@@ -644,6 +702,7 @@ static void test_regular_swap(struct rtr_socket *socket)
644702
ADDED_TO(dst_table, RECORD(1100, ASNS(1101, 1102, 1103, 1104))),
645703
ADDED_TO(dst_table, RECORD(4400, ASNS(4401)))
646704
);
705+
EXPECT_NO_ERROR_PDUS_SENT();
647706

648707
assert(rtr_sync(socket) == RTR_SUCCESS);
649708
assert(callback_index == callback_count);
@@ -672,6 +731,7 @@ static void test_regular_swap(struct rtr_socket *socket)
672731
ADDED_TO(dst_table, RECORD(1101, ASNS(1100, 1102, 1103, 1104))),
673732
ADDED_TO(dst_table, RECORD(3300, ASNS(3301, 3302, 3303, 3304))),
674733
);
734+
EXPECT_NO_ERROR_PDUS_SENT();
675735

676736
assert(aspa_table_src_replace(dst_table, src_table, socket, true, true) == ASPA_SUCCESS);
677737
assert(callback_index == callback_count);
@@ -697,6 +757,7 @@ static void test_withdraw_twice(struct rtr_socket *socket)
697757
ADDED(RECORD(1901, ASNS(1900, 1902, 1903, 1904))),
698758
ADDED(RECORD(2200, ASNS(2201, 2202, 2203, 2204))),
699759
);
760+
EXPECT_NO_ERROR_PDUS_SENT();
700761

701762
assert(rtr_sync(socket) == RTR_SUCCESS);
702763
assert(callback_index == callback_count);
@@ -714,6 +775,7 @@ static void test_withdraw_twice(struct rtr_socket *socket)
714775
EXPECT_UPDATE_CALLBACKS(
715776
ADDED(RECORD(3300, ASNS(3301, 3302, 3303, 3304))),
716777
);
778+
EXPECT_NO_ERROR_PDUS_SENT();
717779

718780
assert(rtr_sync(socket) == RTR_SUCCESS);
719781
assert(callback_index == callback_count);
@@ -730,9 +792,10 @@ static void test_withdraw_twice(struct rtr_socket *socket)
730792
APPEND_ASPA(RTR_PROTOCOL_VERSION_2, ASPA_WITHDRAW, 2200, ASNS());
731793
APPEND_ASPA(RTR_PROTOCOL_VERSION_2, ASPA_WITHDRAW, 1900, ASNS());
732794
APPEND_ASPA(RTR_PROTOCOL_VERSION_2, ASPA_ANNOUNCE, 1900, ASNS(1201, 1202, 1203, 1204));
733-
APPEND_ASPA(RTR_PROTOCOL_VERSION_2, ASPA_ANNOUNCE, 0, ASNS());
734795
end_cache_response(RTR_PROTOCOL_VERSION_2, 0, 444);
735796

797+
EXPECT_ERROR_PDUS_SENT(ERROR_PDU(WITHDRAWAL_OF_UNKNOWN_RECORD));
798+
736799
// Callback behavior deviates for different update mechanisms
737800
// Swap-In: No callback because update computation fails
738801
// In-Place: Callbacks until failed operation, then callbacks from undo
@@ -761,6 +824,7 @@ static void test_announce_withdraw_announce_twice(struct rtr_socket *socket)
761824
EXPECT_UPDATE_CALLBACKS(
762825
ADDED(RECORD(1400, ASNS(1401, 1402, 1403, 1404))),
763826
);
827+
EXPECT_NO_ERROR_PDUS_SENT();
764828

765829
assert(rtr_sync(socket) == RTR_SUCCESS);
766830

@@ -774,6 +838,8 @@ static void test_announce_withdraw_announce_twice(struct rtr_socket *socket)
774838
APPEND_ASPA(RTR_PROTOCOL_VERSION_2, ASPA_ANNOUNCE, 1400, ASNS(1201, 1202, 1203));
775839
end_cache_response(RTR_PROTOCOL_VERSION_2, 0, 444);
776840

841+
EXPECT_ERROR_PDUS_SENT(ERROR_PDU(DUPLICATE_ANNOUNCEMENT));
842+
777843
// Callback behavior deviates for different update mechanisms
778844
// Swap-In: No callback because update computation fails
779845
// In-Place: Callbacks until failed operation, then callbacks from undo
@@ -802,6 +868,7 @@ static void test_multiple_syncs(struct rtr_socket *socket)
802868
ADDED(RECORD(1, ASNS(2, 3, 4, 5))),
803869
ADDED(RECORD(2, ASNS(3, 4, 5, 6))),
804870
);
871+
EXPECT_NO_ERROR_PDUS_SENT();
805872

806873
assert(rtr_sync(socket) == RTR_SUCCESS);
807874
assert(callback_index == callback_count);
@@ -839,6 +906,7 @@ static void test_multiple_syncs(struct rtr_socket *socket)
839906
ADDED(RECORD(c_an, ASNS(c_an + 1, c_an + 2, c_an + 3, c_an + 4))),
840907
ADDED(RECORD(c_an + 1, ASNS(c_an + 2, c_an + 3, c_an + 4, c_an + 5))),
841908
);
909+
EXPECT_NO_ERROR_PDUS_SENT();
842910
assert(rtr_sync(socket) == RTR_SUCCESS);
843911
assert(callback_index == callback_count);
844912

@@ -904,6 +972,7 @@ static void test_many_pdus(struct rtr_socket *socket)
904972
}
905973

906974
expect_update_callbacks(callbacks, N);
975+
EXPECT_NO_ERROR_PDUS_SENT();
907976

908977
// sync
909978
assert(rtr_sync(socket) == RTR_SUCCESS);
@@ -931,6 +1000,7 @@ static void test_corrupt_pdu_length_field(struct rtr_socket *socket)
9311000

9321001
// No updates expected, fails at first PDU
9331002
EXPECT_NO_UPDATE_CALLBACKS();
1003+
EXPECT_ERROR_PDUS_SENT(ERROR_PDU(CORRUPT_DATA));
9341004
assert(rtr_sync(socket) == RTR_ERROR);
9351005
assert(callback_index == callback_count);
9361006

@@ -955,6 +1025,8 @@ static void test_corrupt_pdu_provider_autonomous_system_number_list_in_announcem
9551025

9561026
// No updates expected, fails at first PDU
9571027
EXPECT_NO_UPDATE_CALLBACKS();
1028+
EXPECT_ERROR_PDUS_SENT(ERROR_PDU(INCORRECT_ASPA_PROVIDER_LIST));
1029+
9581030
assert(rtr_sync(socket) == RTR_ERROR);
9591031
assert(callback_index == callback_count);
9601032

@@ -978,6 +1050,9 @@ static void test_corrupt_pdu_provider_autonomous_system_number_list_in_withdraw(
9781050
APPEND_ASPA(RTR_PROTOCOL_VERSION_2, ASPA_WITHDRAW, 1100, ASNS(42));
9791051
end_cache_response(RTR_PROTOCOL_VERSION_2, 0, 444);
9801052

1053+
EXPECT_NO_UPDATE_CALLBACKS();
1054+
EXPECT_ERROR_PDUS_SENT(ERROR_PDU(CORRUPT_DATA));
1055+
9811056
assert(rtr_sync(socket) == RTR_ERROR);
9821057
assert(callback_index == callback_count);
9831058

@@ -1006,6 +1081,9 @@ static void test_error_pdu_to_be_truncated(struct rtr_socket *socket)
10061081
APPEND_ASPA(RTR_PROTOCOL_VERSION_2, ASPA_ANNOUNCE, 1100, asns);
10071082
end_cache_response(RTR_PROTOCOL_VERSION_2, 0, 444);
10081083

1084+
EXPECT_NO_UPDATE_CALLBACKS();
1085+
EXPECT_ERROR_PDUS_SENT(ERROR_PDU(DUPLICATE_ANNOUNCEMENT));
1086+
10091087
assert(rtr_sync(socket) == RTR_ERROR);
10101088
assert(callback_index == callback_count);
10111089

@@ -1051,6 +1129,7 @@ static void cleanup(struct rtr_socket **socket)
10511129
}
10521130

10531131
clear_expected_callbacks();
1132+
clear_expected_sent_pdus();
10541133
}
10551134

10561135
static struct rtr_socket *create_socket(bool is_resetting)

0 commit comments

Comments
 (0)