From f80fc87599bb59efcbd43cffeb1a160845c16180 Mon Sep 17 00:00:00 2001 From: Jason Ish Date: Thu, 25 Sep 2025 11:31:27 -0600 Subject: [PATCH] test/ike: add test for duplicate proposals Ticket: #7902 --- tests/ikev1-duplicate-proposals/README.md | 9 ++ tests/ikev1-duplicate-proposals/gen-pkt.py | 111 ++++++++++++++++++ .../ikev1-duplicate-proposals/generated.pcap | Bin 0 -> 258 bytes tests/ikev1-duplicate-proposals/test.yaml | 10 ++ 4 files changed, 130 insertions(+) create mode 100644 tests/ikev1-duplicate-proposals/README.md create mode 100755 tests/ikev1-duplicate-proposals/gen-pkt.py create mode 100644 tests/ikev1-duplicate-proposals/generated.pcap create mode 100644 tests/ikev1-duplicate-proposals/test.yaml diff --git a/tests/ikev1-duplicate-proposals/README.md b/tests/ikev1-duplicate-proposals/README.md new file mode 100644 index 000000000..b3bc56a9d --- /dev/null +++ b/tests/ikev1-duplicate-proposals/README.md @@ -0,0 +1,9 @@ +Test the logging of IKEv1 records in the presence of duplicate proposals. + +Ticket: https://redmine.openinfosecfoundation.org/issues/7902 + +## PCAP + +Based on the the PCAP found in tests/ikev1-rules/ikev1-isakmp-main-mode.pcap (md5sum: e7e6d064e402997e81ea26b481963731): +- First packet was extracted +- LLM used to generate scapy script to create identical packet, then add duplicate proposal diff --git a/tests/ikev1-duplicate-proposals/gen-pkt.py b/tests/ikev1-duplicate-proposals/gen-pkt.py new file mode 100755 index 000000000..30b9a85c3 --- /dev/null +++ b/tests/ikev1-duplicate-proposals/gen-pkt.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python3 +# +# Generated by Claude Code based on an input packet. + +from scapy.all import * + +def generate_isakmp_packet(): + # Build packet using raw bytes for exact control + + # Ethernet header (14 bytes) + eth_bytes = bytes.fromhex("00175aed7af0001da18b36d00800") + + # IP header (20 bytes) + ip_bytes = bytes.fromhex("45c000cc02890000ff111e84c0a80c01c0a80c02") + + # UDP header (8 bytes) + udp_bytes = bytes.fromhex("01f401f400b8291c") + + # ISAKMP header (28 bytes) + isakmp_header = bytes.fromhex( + "e47a591fd057587f" # init_cookie + "0000000000000000" # resp_cookie + "01" # next_payload (SA) + "10" # version + "02" # exch_type (Identity Protection) + "00" # flags + "00000000" # message_id + "000000b0" # length (176 bytes total) + ) + + # SA payload header and DOI/Situation (12 bytes) + sa_header = bytes.fromhex( + "0d" # next_payload (VendorID) + "00" # reserved + "0044" # length (68 bytes) + "00000001" # DOI (IPSEC) + "00000001" # situation (identity) + ) + + # Proposal (20 bytes) + proposal = bytes.fromhex( + "00" # next_payload (None) + "00" # reserved + "0038" # length (56 bytes) + "01" # proposal number + "01" # protocol (ISAKMP) + "00" # SPI size + "01" # number of transforms + ) + + # Transform header (8 bytes) + transform = bytes.fromhex( + "00" # next_payload (None) + "00" # reserved + "0030" # length (48 bytes) + "01" # transform number + "01" # transform ID (KEY_IKE) + "0000" # reserved + ) + + # Transform attributes (40 bytes - includes duplicate life duration) + attributes = bytes.fromhex( + "80010007" # Encryption (AES) + "800e0080" # Key Length (128) + "80020002" # Hash (SHA) + "000c0004" # Life Duration (attribute) - moved after Hash + "00015180" # 86400 seconds + "80040002" # Group (1024 MODP) + "80030001" # Auth (PSK) + "800b0001" # Life Type (seconds) + "000c0004" # Life Duration (duplicate attribute) + "0000ffff" # 65535 seconds + ) + + # Vendor IDs + vid1 = bytes.fromhex("0d0000144a131c81070358455c5728f20e95452f") # NAT-T + vid2 = bytes.fromhex("0d000014439b59f8ba676c4c7737ae22eab8f582") + vid3 = bytes.fromhex("0d0000147d9419a65310ca6f2c179d9215529d56") + vid4 = bytes.fromhex("0000001490cb80913ebb696e086381b5ec427b1f") # last one has next_payload=0 + + # Combine all parts + packet_bytes = ( + eth_bytes + + ip_bytes + + udp_bytes + + isakmp_header + + sa_header + + proposal + + transform + + attributes + + vid1 + + vid2 + + vid3 + + vid4 + ) + + # Create Scapy packet from raw bytes + packet = Ether(packet_bytes) + + # Set timestamp + packet.time = 1439117415.368374 + + return packet + +# Generate the packet +packet = generate_isakmp_packet() + +# Write to pcap file +wrpcap("generated.pcap", [packet]) + +print("ISAKMP packet generated and saved to generated.pcap") diff --git a/tests/ikev1-duplicate-proposals/generated.pcap b/tests/ikev1-duplicate-proposals/generated.pcap new file mode 100644 index 0000000000000000000000000000000000000000..12cc5cfaed5a2a9d7a8cca9c8f9c3634d4ef0360 GIT binary patch literal 258 zc-p&ic+)~A1{MYw`2U}Qfe}cj8ypY)HjkCz7LX0X4B}C5t3EKuF6=hDz`@{pfZ+^N zCs4JZT+4wKJd8lh#Q25r3&RdgnI~0|@)yD*>R~1_3NXQ#8+aKQTo@o0fUpH4BbYV- z(hLoZ4D1bj3=IuT3``6>KqoNFf}kUFg9=l)q%u-?gN@3;w3E8$j%($8WXPZ ziEpZ_K1j@YcI1y;={Y{-=IfMR?fBXR604mexhz=VRKAY*+)1KAbHjjkiA*@%Fwt&z OW*$d!