lib/packetgen/plugin/ike.rb in packetgen-plugin-ipsec-1.0.2 vs lib/packetgen/plugin/ike.rb in packetgen-plugin-ipsec-1.0.3
- old
+ new
@@ -1,241 +1,242 @@
+# frozen_string_literal: true
+
# This file is part of IPsec packetgen plugin.
# See https://github.com/sdaubert/packetgen-plugin-ipsec for more informations
# Copyright (c) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
# This program is published under MIT license.
-# frozen_string_literal: true
+module PacketGen::Plugin
+ # This class handles a pseudo-Plugin used to differentiate ESP from IKE Plugins
+ # in a UDP datagram with port 4500.
+ # @author Sylvain Daubert
+ class NonESPMarker < PacketGen::Header::Base
+ # @!attribute non_esp_marker
+ # 32-bit zero marker to differentiate IKE packet over UDP port 4500 from ESP ones
+ # @return [Integer]
+ define_field :non_esp_marker, PacketGen::Types::Int32, default: 0
+ # @!attribute body
+ # @return [PacketGen::Types::String,PacketGen::Header::Base]
+ define_field :body, PacketGen::Types::String
-module PacketGen
- module Plugin
- # This class handles a pseudo-Plugin used to differentiate ESP from IKE Plugins
- # in a UDP datagram with port 4500.
- # @author Sylvain Daubert
- class NonESPMarker < PacketGen::Header::Base
- # @!attribute non_esp_marker
- # 32-bit zero marker to differentiate IKE packet over UDP port 4500 from ESP ones
- # @return [Integer]
- define_field :non_esp_marker, PacketGen::Types::Int32, default: 0
- # @!attribute body
- # @return [PacketGen::Types::String,PacketGen::Header::Base]
- define_field :body, PacketGen::Types::String
-
- # Check non_esp_marker field
- # @see [PacketGen::Header::Base#parse?]
- def parse?
- non_esp_marker.zero?
- end
+ # Check non_esp_marker field
+ # @see [PacketGen::Header::Base#parse?]
+ def parse?
+ non_esp_marker.zero?
end
+ end
- # IKE is the Internet Key Exchange protocol (RFC 7296). Ony IKEv2 is supported.
- #
- # A IKE Plugin consists of a Plugin, and a set of payloads. This class
- # handles IKE Plugin. For payloads, see {IKE::Payload}.
- #
- # == IKE Plugin
- # The format of a IKE Plugin is shown below:
- # 1 2 3
- # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- # | IKE SA Initiator's SPI |
- # | |
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- # | IKE SA Responder's SPI |
- # | |
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- # | Next Payload | MjVer | MnVer | Exchange Type | Flags |
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- # | Message ID |
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- # | Length |
- # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- # A IKE Plugin consists of:
- # * a IKE SA initiator SPI ({#init_spi}, {PacketGen::Types::Int64} type),
- # * a IKE SA responder SPI ({#resp_spi}, {PacketGen::Types::Int64} type),
- # * a Next Payload field ({#next}, {PacketGen::Types::Int8} type),
- # * a Version field ({#version}, {PacketGen::Types::Int8} type, with first 4-bit field
- # as major number, and last 4-bit field as minor number),
- # * a Exchange type ({#exchange_type}, {PacketGen::Types::Int8} type),
- # * a {#flags} field ({PacketGen::Types::Int8} type),
- # * a Message ID ({#message_id}, {PacketGen::Types::Int32} type),
- # * and a {#length} ({PacketGen::Types::Int32} type).
- #
- # == Create a IKE Plugin
- # === Standalone
- # ike = PacketGen::Plugin::IKE.new
- # === Classical IKE packet
- # pkt = PacketGen.gen('IP').add('UDP').add('IKE')
- # # access to IKE Plugin
- # pkt.ike # => PacketGen::Plugin::IKE
- # === NAT-T IKE packet
- # # NonESPMarker is used to insert a 32-bit null field between UDP Plugin
- # # and IKE one to differentiate it from ESP-in-UDP (see RFC 3948)
- # pkt = PacketGen.gen('IP').add('UDP').add('NonESPMarker').add('IKE)
- # @author Sylvain Daubert
- class IKE < PacketGen::Header::Base
- # Classical well-known UDP port for IKE
- UDP_PORT1 = 500
- # Well-known UDP port for IKE when NAT is detected
- UDP_PORT2 = 4500
+ # IKE is the Internet Key Exchange protocol (RFC 7296). Ony IKEv2 is supported.
+ #
+ # A IKE Plugin consists of a Plugin, and a set of payloads. This class
+ # handles IKE Plugin. For payloads, see {IKE::Payload}.
+ #
+ # == IKE Plugin
+ # The format of a IKE Plugin is shown below:
+ # 1 2 3
+ # 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | IKE SA Initiator's SPI |
+ # | |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | IKE SA Responder's SPI |
+ # | |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Next Payload | MjVer | MnVer | Exchange Type | Flags |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Message ID |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # | Length |
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ # A IKE Plugin consists of:
+ # * a IKE SA initiator SPI ({#init_spi}, {PacketGen::Types::Int64} type),
+ # * a IKE SA responder SPI ({#resp_spi}, {PacketGen::Types::Int64} type),
+ # * a Next Payload field ({#next}, {PacketGen::Types::Int8} type),
+ # * a Version field ({#version}, {PacketGen::Types::Int8} type, with first 4-bit field
+ # as major number, and last 4-bit field as minor number),
+ # * a Exchange type ({#exchange_type}, {PacketGen::Types::Int8} type),
+ # * a {#flags} field ({PacketGen::Types::Int8} type),
+ # * a Message ID ({#message_id}, {PacketGen::Types::Int32} type),
+ # * and a {#length} ({PacketGen::Types::Int32} type).
+ #
+ # == Create a IKE Plugin
+ # === Standalone
+ # ike = PacketGen::Plugin::IKE.new
+ # === Classical IKE packet
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE')
+ # # access to IKE Plugin
+ # pkt.ike # => PacketGen::Plugin::IKE
+ # === NAT-T IKE packet
+ # # NonESPMarker is used to insert a 32-bit null field between UDP Plugin
+ # # and IKE one to differentiate it from ESP-in-UDP (see RFC 3948)
+ # pkt = PacketGen.gen('IP').add('UDP').add('NonESPMarker').add('IKE)
+ # @author Sylvain Daubert
+ class IKE < PacketGen::Header::Base
+ # Classical well-known UDP port for IKE
+ UDP_PORT1 = 500
+ # Well-known UDP port for IKE when NAT is detected
+ UDP_PORT2 = 4500
- PROTOCOLS = {
- 'IKE' => 1,
- 'AH' => 2,
- 'ESP' => 3
- }.freeze
+ # Protocols supported by IKE
+ PROTOCOLS = {
+ 'IKE' => 1,
+ 'AH' => 2,
+ 'ESP' => 3
+ }.freeze
- EXCHANGE_TYPES = {
- 'IKE_SA_INIT' => 34,
- 'IKE_AUTH' => 35,
- 'CREATE_CHILD_SA' => 36,
- 'INFORMATIONAL' => 37
- }.freeze
+ # Known echange types
+ EXCHANGE_TYPES = {
+ 'IKE_SA_INIT' => 34,
+ 'IKE_AUTH' => 35,
+ 'CREATE_CHILD_SA' => 36,
+ 'INFORMATIONAL' => 37
+ }.freeze
- # @!attribute init_spi
- # 64-bit initiator SPI
- # @return [Integer]
- define_field :init_spi, PacketGen::Types::Int64
- # @!attribute resp_spi
- # 64-bit responder SPI
- # @return [Integer]
- define_field :resp_spi, PacketGen::Types::Int64
- # @!attribute next
- # 8-bit next payload type
- # @return [Integer]
- define_field :next, PacketGen::Types::Int8
- # @!attribute version
- # 8-bit IKE version
- # @return [Integer]
- define_field :version, PacketGen::Types::Int8, default: 0x20
- # @!attribute [r] exchange_type
- # 8-bit exchange type
- # @return [Integer]
- define_field :exchange_type, PacketGen::Types::Int8Enum, enum: EXCHANGE_TYPES
- # @!attribute flags
- # 8-bit flags
- # @return [Integer]
- define_field :flags, PacketGen::Types::Int8
- # @!attribute message_id
- # 32-bit message ID
- # @return [Integer]
- define_field :message_id, PacketGen::Types::Int32
- # @!attribute length
- # 32-bit length of total message (Plugin + payloads)
- # @return [Integer]
- define_field :length, PacketGen::Types::Int32
+ # @!attribute init_spi
+ # 64-bit initiator SPI
+ # @return [Integer]
+ define_field :init_spi, PacketGen::Types::Int64
+ # @!attribute resp_spi
+ # 64-bit responder SPI
+ # @return [Integer]
+ define_field :resp_spi, PacketGen::Types::Int64
+ # @!attribute next
+ # 8-bit next payload type
+ # @return [Integer]
+ define_field :next, PacketGen::Types::Int8
+ # @!attribute version
+ # 8-bit IKE version
+ # @return [Integer]
+ define_field :version, PacketGen::Types::Int8, default: 0x20
+ # @!attribute [r] exchange_type
+ # 8-bit exchange type
+ # @return [Integer]
+ define_field :exchange_type, PacketGen::Types::Int8Enum, enum: EXCHANGE_TYPES
+ # @!attribute flags
+ # 8-bit flags
+ # @return [Integer]
+ define_field :flags, PacketGen::Types::Int8
+ # @!attribute message_id
+ # 32-bit message ID
+ # @return [Integer]
+ define_field :message_id, PacketGen::Types::Int32
+ # @!attribute length
+ # 32-bit length of total message (Plugin + payloads)
+ # @return [Integer]
+ define_field :length, PacketGen::Types::Int32
- # Defining a body permits using Packet#parse to parse IKE payloads.
- # But this method is hidden as prefered way to access payloads is via #payloads
- define_field :body, PacketGen::Types::String
+ # Defining a body permits using Packet#parse to parse IKE payloads.
+ # But this method is hidden as prefered way to access payloads is via #payloads
+ define_field :body, PacketGen::Types::String
- # @!attribute mjver
- # 4-bit major version value
- # @return [Integer]
- # @!attribute mnver
- # 4-bit minor version value
- # @return [Integer]
- define_bit_fields_on :version, :mjver, 4, :mnver, 4
+ # @!attribute mjver
+ # 4-bit major version value
+ # @return [Integer]
+ # @!attribute mnver
+ # 4-bit minor version value
+ # @return [Integer]
+ define_bit_fields_on :version, :mjver, 4, :mnver, 4
- # @!attribute rsv1
- # @return [Integer]
- # @!attribute rsv2
- # @return [Integer]
- # @!attribute flag_i
- # bit set in message sent by the original initiator
- # @return [Boolean]
- # @!attribute flag_r
- # indicate this message is a response to a message containing the same Message ID
- # @return [Boolean]
- # @!attribute flag_v
- # version flag. Ignored by IKEv2 peers, and should be set to 0
- # @return [Boolean]
- define_bit_fields_on :flags, :rsv1, 2, :flag_r, :flag_v, :flag_i, :rsv2, 3
+ # @!attribute rsv1
+ # @return [Integer]
+ # @!attribute rsv2
+ # @return [Integer]
+ # @!attribute flag_i
+ # bit set in message sent by the original initiator
+ # @return [Boolean]
+ # @!attribute flag_r
+ # indicate this message is a response to a message containing the same Message ID
+ # @return [Boolean]
+ # @!attribute flag_v
+ # version flag. Ignored by IKEv2 peers, and should be set to 0
+ # @return [Boolean]
+ define_bit_fields_on :flags, :rsv1, 2, :flag_r, :flag_v, :flag_i, :rsv2, 3
- # @param [Hash] options
- # @see PacketGen::Header::Base#initialize
- def initialize(options={})
- super
- calc_length unless options[:length]
- self.type = options[:type] if options[:type]
- self.type = options[:exchange_type] if options[:exchange_type]
- end
+ # @param [Hash] options
+ # @see PacketGen::Header::Base#initialize
+ def initialize(options={})
+ super
+ calc_length unless options[:length]
+ self.type = options[:type] if options[:type]
+ self.type = options[:exchange_type] if options[:exchange_type]
+ end
- alias type exchange_type
- alias type= exchange_type=
+ alias type exchange_type
+ alias type= exchange_type=
- # Get exchange type name
- # @return [String
- def human_exchange_type
- self[:exchange_type].to_human
- end
- alias human_type human_exchange_type
+ # Get exchange type name
+ # @return [String
+ def human_exchange_type
+ self[:exchange_type].to_human
+ end
+ alias human_type human_exchange_type
- # Calculate length field
- # @return [Integer]
- def calc_length
- PacketGen::Header::Base.calculate_and_set_length self
- end
+ # Calculate length field
+ # @return [Integer]
+ def calc_length
+ PacketGen::Header::Base.calculate_and_set_length self
+ end
- # IKE payloads
- # @return [Array<Payload>]
- def payloads
- payloads = []
- body = self.body
- while body.is_a?(Payload)
- payloads << body
- body = body.body
- end
- payloads
+ # IKE payloads
+ # @return [Array<Payload>]
+ def payloads
+ payloads = []
+ body = self.body
+ while body.is_a?(Payload)
+ payloads << body
+ body = body.body
end
+ payloads
+ end
- # @return [String]
- def inspect
- super do |attr|
- case attr
- when :flags
- str_flags = ''.dup
- %w[r v i].each do |flag|
- str_flags << (send("flag_#{flag}?") ? flag.upcase : '.')
- end
- str = Inspect.shift_level
- str << Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''), attr,
- str_flags]
+ # @return [String]
+ def inspect
+ super do |attr|
+ case attr
+ when :flags
+ str_flags = +''
+ %w[r v i].each do |flag|
+ str_flags << (send("flag_#{flag}?") ? flag.upcase : '.')
end
+ str = PacketGen::Inspect.shift_level
+ str << PacketGen::Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''), attr,
+ str_flags]
end
end
+ end
- # Toggle +I+ and +R+ flags.
- # @return [self]
- def reply!
- self.flag_r = !self.flag_r?
- self.flag_i = !self.flag_i?
- self
- end
-
- # @api private
- # @note This method is used internally by PacketGen and should not be
- # directly called
- # @param [Packet] packet
- # @return [void]
- def added_to_packet(packet)
- return unless packet.is? 'UDP'
- return unless packet.udp.sport.zero?
- packet.udp.sport = if packet.is?('NonESPMarker')
- UDP_PORT2
- else
- UDP_PORT1
- end
- end
+ # Toggle +I+ and +R+ flags.
+ # @return [self]
+ def reply!
+ self.flag_r = !self.flag_r?
+ self.flag_i = !self.flag_i?
+ self
end
- Header.add_class IKE
- Header.add_class NonESPMarker
+ # @api private
+ # @note This method is used internally by PacketGen and should not be
+ # directly called
+ # @param [Packet] packet
+ # @return [void]
+ def added_to_packet(packet)
+ return unless packet.is? 'UDP'
+ return unless packet.udp.sport.zero?
- PacketGen::Header::UDP.bind IKE, dport: IKE::UDP_PORT1
- PacketGen::Header::UDP.bind IKE, sport: IKE::UDP_PORT1
- PacketGen::Header::UDP.bind NonESPMarker, dport: IKE::UDP_PORT2
- PacketGen::Header::UDP.bind NonESPMarker, sport: IKE::UDP_PORT2
- NonESPMarker.bind IKE
+ packet.udp.sport = if packet.is?('NonESPMarker')
+ UDP_PORT2
+ else
+ UDP_PORT1
+ end
+ end
end
+
+ PacketGen::Header.add_class IKE
+ PacketGen::Header.add_class NonESPMarker
+
+ PacketGen::Header::UDP.bind IKE, dport: IKE::UDP_PORT1
+ PacketGen::Header::UDP.bind IKE, sport: IKE::UDP_PORT1
+ PacketGen::Header::UDP.bind NonESPMarker, dport: IKE::UDP_PORT2
+ PacketGen::Header::UDP.bind NonESPMarker, sport: IKE::UDP_PORT2
+ NonESPMarker.bind IKE
end
require_relative 'ike/payload'