packetgen-plugin-ipsec 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/specs.yml +28 -0
- data/.rubocop.yml +8 -1
- data/.travis.yml +1 -1
- data/Gemfile +11 -0
- data/Rakefile +10 -4
- data/lib/packetgen/plugin/crypto.rb +6 -4
- data/lib/packetgen/plugin/esp.rb +373 -370
- data/lib/packetgen/plugin/ike.rb +218 -217
- data/lib/packetgen/plugin/ike/auth.rb +141 -141
- data/lib/packetgen/plugin/ike/cert.rb +61 -62
- data/lib/packetgen/plugin/ike/certreq.rb +51 -52
- data/lib/packetgen/plugin/ike/id.rb +80 -80
- data/lib/packetgen/plugin/ike/ke.rb +64 -66
- data/lib/packetgen/plugin/ike/nonce.rb +29 -31
- data/lib/packetgen/plugin/ike/notify.rb +135 -139
- data/lib/packetgen/plugin/ike/payload.rb +58 -57
- data/lib/packetgen/plugin/ike/sa.rb +515 -452
- data/lib/packetgen/plugin/ike/sk.rb +219 -221
- data/lib/packetgen/plugin/ike/ts.rb +223 -223
- data/lib/packetgen/plugin/ike/vendor_id.rb +28 -30
- data/lib/packetgen/plugin/ipsec_version.rb +8 -1
- data/packetgen-plugin-ipsec.gemspec +3 -9
- metadata +8 -77
data/lib/packetgen/plugin/ike.rb
CHANGED
@@ -1,241 +1,242 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# This file is part of IPsec packetgen plugin.
|
2
4
|
# See https://github.com/sdaubert/packetgen-plugin-ipsec for more informations
|
3
5
|
# Copyright (c) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
|
4
6
|
# This program is published under MIT license.
|
5
7
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
#
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
# @see [PacketGen::Header::Base#parse?]
|
24
|
-
def parse?
|
25
|
-
non_esp_marker.zero?
|
26
|
-
end
|
8
|
+
module PacketGen::Plugin
|
9
|
+
# This class handles a pseudo-Plugin used to differentiate ESP from IKE Plugins
|
10
|
+
# in a UDP datagram with port 4500.
|
11
|
+
# @author Sylvain Daubert
|
12
|
+
class NonESPMarker < PacketGen::Header::Base
|
13
|
+
# @!attribute non_esp_marker
|
14
|
+
# 32-bit zero marker to differentiate IKE packet over UDP port 4500 from ESP ones
|
15
|
+
# @return [Integer]
|
16
|
+
define_field :non_esp_marker, PacketGen::Types::Int32, default: 0
|
17
|
+
# @!attribute body
|
18
|
+
# @return [PacketGen::Types::String,PacketGen::Header::Base]
|
19
|
+
define_field :body, PacketGen::Types::String
|
20
|
+
|
21
|
+
# Check non_esp_marker field
|
22
|
+
# @see [PacketGen::Header::Base#parse?]
|
23
|
+
def parse?
|
24
|
+
non_esp_marker.zero?
|
27
25
|
end
|
26
|
+
end
|
28
27
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
28
|
+
# IKE is the Internet Key Exchange protocol (RFC 7296). Ony IKEv2 is supported.
|
29
|
+
#
|
30
|
+
# A IKE Plugin consists of a Plugin, and a set of payloads. This class
|
31
|
+
# handles IKE Plugin. For payloads, see {IKE::Payload}.
|
32
|
+
#
|
33
|
+
# == IKE Plugin
|
34
|
+
# The format of a IKE Plugin is shown below:
|
35
|
+
# 1 2 3
|
36
|
+
# 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
|
37
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
38
|
+
# | IKE SA Initiator's SPI |
|
39
|
+
# | |
|
40
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
41
|
+
# | IKE SA Responder's SPI |
|
42
|
+
# | |
|
43
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
44
|
+
# | Next Payload | MjVer | MnVer | Exchange Type | Flags |
|
45
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
46
|
+
# | Message ID |
|
47
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
48
|
+
# | Length |
|
49
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
50
|
+
# A IKE Plugin consists of:
|
51
|
+
# * a IKE SA initiator SPI ({#init_spi}, {PacketGen::Types::Int64} type),
|
52
|
+
# * a IKE SA responder SPI ({#resp_spi}, {PacketGen::Types::Int64} type),
|
53
|
+
# * a Next Payload field ({#next}, {PacketGen::Types::Int8} type),
|
54
|
+
# * a Version field ({#version}, {PacketGen::Types::Int8} type, with first 4-bit field
|
55
|
+
# as major number, and last 4-bit field as minor number),
|
56
|
+
# * a Exchange type ({#exchange_type}, {PacketGen::Types::Int8} type),
|
57
|
+
# * a {#flags} field ({PacketGen::Types::Int8} type),
|
58
|
+
# * a Message ID ({#message_id}, {PacketGen::Types::Int32} type),
|
59
|
+
# * and a {#length} ({PacketGen::Types::Int32} type).
|
60
|
+
#
|
61
|
+
# == Create a IKE Plugin
|
62
|
+
# === Standalone
|
63
|
+
# ike = PacketGen::Plugin::IKE.new
|
64
|
+
# === Classical IKE packet
|
65
|
+
# pkt = PacketGen.gen('IP').add('UDP').add('IKE')
|
66
|
+
# # access to IKE Plugin
|
67
|
+
# pkt.ike # => PacketGen::Plugin::IKE
|
68
|
+
# === NAT-T IKE packet
|
69
|
+
# # NonESPMarker is used to insert a 32-bit null field between UDP Plugin
|
70
|
+
# # and IKE one to differentiate it from ESP-in-UDP (see RFC 3948)
|
71
|
+
# pkt = PacketGen.gen('IP').add('UDP').add('NonESPMarker').add('IKE)
|
72
|
+
# @author Sylvain Daubert
|
73
|
+
class IKE < PacketGen::Header::Base
|
74
|
+
# Classical well-known UDP port for IKE
|
75
|
+
UDP_PORT1 = 500
|
76
|
+
# Well-known UDP port for IKE when NAT is detected
|
77
|
+
UDP_PORT2 = 4500
|
78
|
+
|
79
|
+
# Protocols supported by IKE
|
80
|
+
PROTOCOLS = {
|
81
|
+
'IKE' => 1,
|
82
|
+
'AH' => 2,
|
83
|
+
'ESP' => 3
|
84
|
+
}.freeze
|
85
|
+
|
86
|
+
# Known echange types
|
87
|
+
EXCHANGE_TYPES = {
|
88
|
+
'IKE_SA_INIT' => 34,
|
89
|
+
'IKE_AUTH' => 35,
|
90
|
+
'CREATE_CHILD_SA' => 36,
|
91
|
+
'INFORMATIONAL' => 37
|
92
|
+
}.freeze
|
93
|
+
|
94
|
+
# @!attribute init_spi
|
95
|
+
# 64-bit initiator SPI
|
96
|
+
# @return [Integer]
|
97
|
+
define_field :init_spi, PacketGen::Types::Int64
|
98
|
+
# @!attribute resp_spi
|
99
|
+
# 64-bit responder SPI
|
100
|
+
# @return [Integer]
|
101
|
+
define_field :resp_spi, PacketGen::Types::Int64
|
102
|
+
# @!attribute next
|
103
|
+
# 8-bit next payload type
|
104
|
+
# @return [Integer]
|
105
|
+
define_field :next, PacketGen::Types::Int8
|
106
|
+
# @!attribute version
|
107
|
+
# 8-bit IKE version
|
108
|
+
# @return [Integer]
|
109
|
+
define_field :version, PacketGen::Types::Int8, default: 0x20
|
110
|
+
# @!attribute [r] exchange_type
|
111
|
+
# 8-bit exchange type
|
112
|
+
# @return [Integer]
|
113
|
+
define_field :exchange_type, PacketGen::Types::Int8Enum, enum: EXCHANGE_TYPES
|
114
|
+
# @!attribute flags
|
115
|
+
# 8-bit flags
|
116
|
+
# @return [Integer]
|
117
|
+
define_field :flags, PacketGen::Types::Int8
|
118
|
+
# @!attribute message_id
|
119
|
+
# 32-bit message ID
|
120
|
+
# @return [Integer]
|
121
|
+
define_field :message_id, PacketGen::Types::Int32
|
122
|
+
# @!attribute length
|
123
|
+
# 32-bit length of total message (Plugin + payloads)
|
124
|
+
# @return [Integer]
|
125
|
+
define_field :length, PacketGen::Types::Int32
|
126
|
+
|
127
|
+
# Defining a body permits using Packet#parse to parse IKE payloads.
|
128
|
+
# But this method is hidden as prefered way to access payloads is via #payloads
|
129
|
+
define_field :body, PacketGen::Types::String
|
130
|
+
|
131
|
+
# @!attribute mjver
|
132
|
+
# 4-bit major version value
|
133
|
+
# @return [Integer]
|
134
|
+
# @!attribute mnver
|
135
|
+
# 4-bit minor version value
|
136
|
+
# @return [Integer]
|
137
|
+
define_bit_fields_on :version, :mjver, 4, :mnver, 4
|
138
|
+
|
139
|
+
# @!attribute rsv1
|
140
|
+
# @return [Integer]
|
141
|
+
# @!attribute rsv2
|
142
|
+
# @return [Integer]
|
143
|
+
# @!attribute flag_i
|
144
|
+
# bit set in message sent by the original initiator
|
145
|
+
# @return [Boolean]
|
146
|
+
# @!attribute flag_r
|
147
|
+
# indicate this message is a response to a message containing the same Message ID
|
148
|
+
# @return [Boolean]
|
149
|
+
# @!attribute flag_v
|
150
|
+
# version flag. Ignored by IKEv2 peers, and should be set to 0
|
151
|
+
# @return [Boolean]
|
152
|
+
define_bit_fields_on :flags, :rsv1, 2, :flag_r, :flag_v, :flag_i, :rsv2, 3
|
153
|
+
|
154
|
+
# @param [Hash] options
|
155
|
+
# @see PacketGen::Header::Base#initialize
|
156
|
+
def initialize(options={})
|
157
|
+
super
|
158
|
+
calc_length unless options[:length]
|
159
|
+
self.type = options[:type] if options[:type]
|
160
|
+
self.type = options[:exchange_type] if options[:exchange_type]
|
161
|
+
end
|
161
162
|
|
162
|
-
|
163
|
-
|
163
|
+
alias type exchange_type
|
164
|
+
alias type= exchange_type=
|
164
165
|
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
166
|
+
# Get exchange type name
|
167
|
+
# @return [String
|
168
|
+
def human_exchange_type
|
169
|
+
self[:exchange_type].to_human
|
170
|
+
end
|
171
|
+
alias human_type human_exchange_type
|
171
172
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
173
|
+
# Calculate length field
|
174
|
+
# @return [Integer]
|
175
|
+
def calc_length
|
176
|
+
PacketGen::Header::Base.calculate_and_set_length self
|
177
|
+
end
|
177
178
|
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
end
|
187
|
-
payloads
|
179
|
+
# IKE payloads
|
180
|
+
# @return [Array<Payload>]
|
181
|
+
def payloads
|
182
|
+
payloads = []
|
183
|
+
body = self.body
|
184
|
+
while body.is_a?(Payload)
|
185
|
+
payloads << body
|
186
|
+
body = body.body
|
188
187
|
end
|
188
|
+
payloads
|
189
|
+
end
|
189
190
|
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
end
|
199
|
-
str = Inspect.shift_level
|
200
|
-
str << Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''), attr,
|
201
|
-
str_flags]
|
191
|
+
# @return [String]
|
192
|
+
def inspect
|
193
|
+
super do |attr|
|
194
|
+
case attr
|
195
|
+
when :flags
|
196
|
+
str_flags = +''
|
197
|
+
%w[r v i].each do |flag|
|
198
|
+
str_flags << (send("flag_#{flag}?") ? flag.upcase : '.')
|
202
199
|
end
|
200
|
+
str = PacketGen::Inspect.shift_level
|
201
|
+
str << PacketGen::Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''), attr,
|
202
|
+
str_flags]
|
203
203
|
end
|
204
204
|
end
|
205
|
+
end
|
205
206
|
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
207
|
+
# Toggle +I+ and +R+ flags.
|
208
|
+
# @return [self]
|
209
|
+
def reply!
|
210
|
+
self.flag_r = !self.flag_r?
|
211
|
+
self.flag_i = !self.flag_i?
|
212
|
+
self
|
213
|
+
end
|
213
214
|
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
215
|
+
# @api private
|
216
|
+
# @note This method is used internally by PacketGen and should not be
|
217
|
+
# directly called
|
218
|
+
# @param [Packet] packet
|
219
|
+
# @return [void]
|
220
|
+
def added_to_packet(packet)
|
221
|
+
return unless packet.is? 'UDP'
|
222
|
+
return unless packet.udp.sport.zero?
|
223
|
+
|
224
|
+
packet.udp.sport = if packet.is?('NonESPMarker')
|
225
|
+
UDP_PORT2
|
226
|
+
else
|
227
|
+
UDP_PORT1
|
228
|
+
end
|
228
229
|
end
|
230
|
+
end
|
229
231
|
|
230
|
-
|
231
|
-
|
232
|
+
PacketGen::Header.add_class IKE
|
233
|
+
PacketGen::Header.add_class NonESPMarker
|
232
234
|
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
end
|
235
|
+
PacketGen::Header::UDP.bind IKE, dport: IKE::UDP_PORT1
|
236
|
+
PacketGen::Header::UDP.bind IKE, sport: IKE::UDP_PORT1
|
237
|
+
PacketGen::Header::UDP.bind NonESPMarker, dport: IKE::UDP_PORT2
|
238
|
+
PacketGen::Header::UDP.bind NonESPMarker, sport: IKE::UDP_PORT2
|
239
|
+
NonESPMarker.bind IKE
|
239
240
|
end
|
240
241
|
|
241
242
|
require_relative 'ike/payload'
|