Skip to content

Parsing LinkStateRequestPacket with authentication has error #2

@mmosko

Description

@mmosko

When parsing an LinkStateRequestPacket with authentication, the parser incorrectly swallows 12 bytes of authentication and thinks it's an additional LinkStateRequest.

Example code

       let lsa_request_bytes = create_lsa_request_with_auth_bytes();
        let (remaining, ospfv2_packet) = ospf_parser::parse_ospfv2_packet(lsa_request_bytes.as_slice()).unwrap();
        let Ospfv2Packet::LinkStateRequest(lsa_request) = ospfv2_packet else {
            panic!("failed to parse Ospfv2");
        };
pub fn create_lsa_request_with_auth_bytes() -> Vec<u8> {
    vec![
        0x2,        // version
        0x3,        // packet type
        0x0, 0x24,  // packet length (36)
        0x2, 0x2, 0x2, 0x2,     // router
        0x0, 0x0, 0x0, 0x0,     // area
        0x0, 0x0,               // checksum
        0x0, 0x2,               // au type
        0x0, 0x0, 0x1, 0x10,    // authentication
        0x69, 0xa, 0xc0, 0xb2,
        // -----
        0x0, 0x0, 0x0, 0x1,     // LS type
        0x1, 0x1, 0x1, 0x1,     // link state ID
        0x1, 0x1, 0x1, 0x1,     // adv. router
        // -----
        // signature
        0x98, 0x35, 0xda, 0x13, 0xd5, 0x3f, 0xe9, 0x51,
        0xd8, 0x40, 0xf4, 0xab, 0x10, 0x17, 0xc0, 0x2c]
}

parses as:

LinkStateRequest(
    OspfLinkStateRequestPacket {
        header: Ospfv2PacketHeader {
            version: 2,
            packet_type: OspfPacketType(
                3,
            ),
            packet_length: 36,
            router_id: 33686018,
            area_id: 0,
            checksum: 0,
            au_type: 2,
            authentication: 1169993416882,
        },
        requests: [
            OspfLinkStateRequest {
                link_state_type: 1,
                link_state_id: 16843009,
                advertising_router: 16843009,
            },
            OspfLinkStateRequest {
                link_state_type: 2553666067,
                link_state_id: 3577735505,
                advertising_router: 3628135595,
            },
        ],
    },
)

remaining: 0x1017c02c

The solution is to limit the parsing to the packet length:

use nom::bytes::complete::take;
use nom::combinator::complete;
use nom::combinator::map_parser;
use nom::multi::many0;

#[derive(Debug, NomBE)]
pub struct OspfLinkStateRequestPacket {
    #[nom(Verify = "header.packet_type == OspfPacketType::LinkStateRequest")]
    pub header: Ospfv2PacketHeader,
    // Subtract the 24-byte OSPF header from total packet_length
    #[nom(Parse = "{
        let len = (header.packet_length as usize).saturating_sub(24);
        map_parser(take(len), many0(complete(OspfLinkStateRequest::parse_be)))
    }")]
    pub requests: Vec<OspfLinkStateRequest>,
}

With this patch, the output is:

LinkStateRequest(
    OspfLinkStateRequestPacket {
        header: Ospfv2PacketHeader {
            version: 2,
            packet_type: OspfPacketType(
                3,
            ),
            packet_length: 36,
            router_id: 33686018,
            area_id: 0,
            checksum: 0,
            au_type: 2,
            authentication: 1169993416882,
        },
        requests: [
            OspfLinkStateRequest {
                link_state_type: 1,
                link_state_id: 16843009,
                advertising_router: 16843009,
            },
        ],
    },
)
"9835da13d53fe951d840f4ab1017c02c"

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions