From: Alan T. DeKok Date: Thu, 9 Mar 2023 22:11:46 +0000 (-0500) Subject: add fr_bfd_packet_ok() and use it in proto_bfd_udp X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=f04521ce76a84cc80f1506bc065bf3b45103bf33;p=thirdparty%2Ffreeradius-server.git add fr_bfd_packet_ok() and use it in proto_bfd_udp --- diff --git a/src/listen/bfd/proto_bfd_udp.c b/src/listen/bfd/proto_bfd_udp.c index e2109a1feb9..eee7733bb7e 100644 --- a/src/listen/bfd/proto_bfd_udp.c +++ b/src/listen/bfd/proto_bfd_udp.c @@ -113,6 +113,7 @@ static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time size_t packet_len; bfd_packet_t *packet; + char const *err = NULL; *leftover = 0; /* always for UDP */ @@ -141,9 +142,8 @@ static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time packet_len = data_size; - if (data_size < FR_BFD_HEADER_LENGTH) { - DEBUG2("proto_bfd_udp got 'too short' packet size %zd", data_size); - fail: + if (!fr_bfd_packet_ok(&err, buffer, packet_len)) { + DEBUG2("proto_bfd_udp - Received invalid packet on %s - %s", thread->name, err); thread->stats.total_malformed_requests++; return 0; } @@ -152,68 +152,6 @@ static ssize_t mod_read(fr_listen_t *li, void **packet_ctx, fr_time_t *recv_time packet = (bfd_packet_t *) buffer; - if (packet->version != 1) { - DEBUG("BFD packet has wrong version (%d != 1)", packet->version); - goto fail; - } - - if (packet->length < FR_BFD_HEADER_LENGTH) { - DEBUG("BFD packet header has wrong length (%d < 24)", packet->length); - goto fail; - } - - if (packet->length > sizeof(*packet)) { - DEBUG("BFD packet length is larger than received packet (%d > %zd)", packet->length, sizeof(*packet)); - goto fail; - } - - if (packet->length != packet_len) { - DEBUG("BFD packet is not the size of the data we read from UDP (%d > %zd)", packet->length, packet_len); - goto fail; - } - - if (packet->auth_present) { - if (packet->length < (FR_BFD_HEADER_LENGTH + 2)) { /* auth-type and auth-len */ - DEBUG("BFD packet length is not enough for auth-type and auth-len (%d < 26)", - packet->length); - goto fail; - } - - if (packet->length < 24 + packet->auth.basic.auth_len) { - DEBUG("BFD packet length is not enough for authentication data (%d < %d)", - packet->length, FR_BFD_HEADER_LENGTH + packet->auth.basic.auth_len); - goto fail; - - } - - if (packet->length != FR_BFD_HEADER_LENGTH + packet->auth.basic.auth_len) { - DEBUG("WARNING: What is the extra data?"); - } - - } - - if (packet->detect_multi == 0) { - DEBUG("BFD packet has detect_multi == 0"); - goto fail; - } - - if (packet->multipoint != 0) { - DEBUG("BFD packet has multi != 0"); - goto fail; - } - - if (packet->my_disc == 0) { - DEBUG("BFD packet has my_disc == 0"); - goto fail; - } - - if ((packet->your_disc == 0) && - !((packet->state == BFD_STATE_DOWN) || - (packet->state == BFD_STATE_ADMIN_DOWN))) { - DEBUG("BFD packet has invalid your-disc / state"); - goto fail; - } - /* * Print out what we received. */ diff --git a/src/protocols/bfd/base.c b/src/protocols/bfd/base.c index 732a5133772..5322213a7db 100644 --- a/src/protocols/bfd/base.c +++ b/src/protocols/bfd/base.c @@ -76,6 +76,81 @@ fr_table_num_ordered_t const bfd_auth_type_table[] = { size_t const bfd_auth_type_table_len = NUM_ELEMENTS(bfd_auth_type_table); +bool fr_bfd_packet_ok(char const **err, uint8_t const *packet, size_t packet_len) +{ + bfd_packet_t const *bfd; + char const *msg = NULL; + + if (packet_len < FR_BFD_HEADER_LENGTH) { + msg = "Packet is too short to be BFD"; + fail: + if (err) *err = msg; + return false; + } + + bfd = (bfd_packet_t const *) packet; + + if (bfd->version != 1) { + msg = "Packet has wrong version - should be 1"; + goto fail; + } + + if (bfd->length < FR_BFD_HEADER_LENGTH) { + msg = "Header length is too small"; + goto fail; + } + + if (bfd->length > sizeof(*bfd)) { + msg = "Header length is larger than received packet"; + goto fail; + } + + if (bfd->length != packet_len) { + msg = "Header length is not the same as the amount of data we read"; + goto fail; + } + + if (bfd->auth_present) { + if (bfd->length < (FR_BFD_HEADER_LENGTH + 2)) { /* auth-type and auth-len */ + msg = "Header length is not enough for auth-type and auth-len"; + goto fail; + } + + if (bfd->length != FR_BFD_HEADER_LENGTH + bfd->auth.basic.auth_len) { + msg = "Header length mismatch with auth-len and amount of received data"; + goto fail; + + } + } + + if (bfd->detect_multi == 0) { + msg = "Packet has invalid detect-multi == 0"; + goto fail; + } + + if (bfd->multipoint != 0) { + msg = "Packet has invalid multipoint != 0"; + goto fail; + } + + if (bfd->my_disc == 0) { + msg = "Packet has invalid my-discriminator == 0"; + goto fail; + } + + if ((bfd->your_disc == 0) && + !((bfd->state == BFD_STATE_DOWN) || + (bfd->state == BFD_STATE_ADMIN_DOWN))) { + msg = "Packet has your-discrimator==0, but state is not down or admin-down"; + goto fail; + } + + if (err) *err = NULL; + return true; +} + + + int fr_bfd_init(void) { if (instance_count > 0) { diff --git a/src/protocols/bfd/bfd.h b/src/protocols/bfd/bfd.h index 4993c2bf36b..9ea39d0d015 100644 --- a/src/protocols/bfd/bfd.h +++ b/src/protocols/bfd/bfd.h @@ -163,6 +163,8 @@ ssize_t fr_bfd_decode(TALLOC_CTX *ctx, fr_pair_list_t *out, uint8_t const *packet, size_t packet_len, char const *secret, size_t secret_len); +bool fr_bfd_packet_ok(char const **err, uint8_t const *packet, size_t packet_len); + int fr_bfd_init(void); void fr_bfd_free(void);