From 2d7988d719d1f3cab9ac4a0762786c4b07443671 Mon Sep 17 00:00:00 2001 From: vinay tripathi Date: Tue, 6 Jun 2023 12:57:55 +0530 Subject: ipsec: separate UDP and UDP-encapsulated ESP packet processing This fix differentiates UDP and UDP-encapsulated ESP packets processing. While UDP-encapsulated ESP traffic is processed as IPsec traffic, UDP as other plain-text protocols is NOT dispatched against SPD policies. Key logic is taken from RFC 3948, and is based on the fact that the checksum of UDP packet encapsulating ESP packet must be zero. Type: fix Signed-off-by: vinay tripathi Change-Id: Ib1b4d240eea8e89f2daf17ec833905f26cdb31bd --- src/vnet/ipsec/ipsec_input.c | 41 +++++++++++++++++++++++++++++++++-------- 1 file changed, 33 insertions(+), 8 deletions(-) (limited to 'src/vnet/ipsec/ipsec_input.c') diff --git a/src/vnet/ipsec/ipsec_input.c b/src/vnet/ipsec/ipsec_input.c index 0e92ae9f1a7..8f9eb204c55 100644 --- a/src/vnet/ipsec/ipsec_input.c +++ b/src/vnet/ipsec/ipsec_input.c @@ -299,6 +299,15 @@ ipsec_esp_packet_process (vlib_main_t *vm, ipsec_main_t *im, ip4_header_t *ip0, search_flow_cache = im->input_flow_cache_flag; udp_or_esp: + /* SPI ID field in the ESP header MUST NOT be a zero value */ + if (esp0->spi == 0) + { + /* Drop the packet if SPI ID is zero */ + *ipsec_unprocessed += 1; + next[0] = IPSEC_INPUT_NEXT_DROP; + return; + } + if (im->fp_spd_ipv4_in_is_enabled && PREDICT_TRUE (INDEX_INVALID != spd0->fp_spd.ip4_in_lookup_hash_idx)) { @@ -538,20 +547,36 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm, ip0 = vlib_buffer_get_current (b[0]); - if (PREDICT_TRUE - (ip0->protocol == IP_PROTOCOL_IPSEC_ESP - || ip0->protocol == IP_PROTOCOL_UDP)) + if (ip0->protocol == IP_PROTOCOL_UDP) { + udp_header_t *udp0 = NULL; + udp0 = (udp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0)); - esp0 = (esp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0)); - if (PREDICT_FALSE (ip0->protocol == IP_PROTOCOL_UDP)) + /* As per rfc3948 in UDP Encapsulated Header, UDP checksum must be + * Zero, and receivers must not depen upon UPD checksum. + * inside ESP header , SPI ID value MUST NOT be a zero value + * */ + + if (udp0->checksum == 0) { - /* FIXME Skip, if not a UDP encapsulated packet */ - esp0 = (esp_header_t *) ((u8 *) esp0 + sizeof (udp_header_t)); + esp0 = (esp_header_t *) ((u8 *) udp0 + sizeof (udp_header_t)); + + ipsec_esp_packet_process (vm, im, ip0, esp0, thread_index, spd0, + b, node, &ipsec_bypassed, + &ipsec_dropped, &ipsec_matched, + &ipsec_unprocessed, next); + if (ipsec_bypassed > 0) + goto ipsec_bypassed; } + } + else if (PREDICT_TRUE (ip0->protocol == IP_PROTOCOL_IPSEC_ESP)) + { + esp0 = (esp_header_t *) ((u8 *) ip0 + ip4_header_bytes (ip0)); ipsec_esp_packet_process (vm, im, ip0, esp0, thread_index, spd0, b, node, &ipsec_bypassed, &ipsec_dropped, &ipsec_matched, &ipsec_unprocessed, next); + if (ipsec_bypassed > 0) + goto ipsec_bypassed; } else if (ip0->protocol == IP_PROTOCOL_IPSEC_AH) { @@ -694,6 +719,7 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm, } else { + ipsec_bypassed: ipsec_unprocessed += 1; } n_left_from -= 1; @@ -725,7 +751,6 @@ VLIB_NODE_FN (ipsec4_input_node) (vlib_main_t * vm, return frame->n_vectors; } - /* *INDENT-OFF* */ VLIB_REGISTER_NODE (ipsec4_input_node) = { .name = "ipsec4-input-feature", -- cgit 1.2.3-korg