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
@@ -1,260 +1,260 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
# This file is part of IPsec packetgen plugin.
|
3
5
|
# See https://github.com/sdaubert/packetgen-plugin-ipsec for more informations
|
4
6
|
# Copyright (c) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
|
5
7
|
# This program is published under MIT license.
|
6
8
|
|
7
|
-
|
9
|
+
module PacketGen::Plugin
|
10
|
+
class IKE
|
11
|
+
# TrafficSelector substructure, as defined in RFC 7296, §3.13.1:
|
12
|
+
# 1 2 3
|
13
|
+
# 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
|
14
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
15
|
+
# | TS Type |IP Protocol ID*| Selector Length |
|
16
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
17
|
+
# | Start Port* | End Port* |
|
18
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
19
|
+
# | |
|
20
|
+
# ~ Starting Address* ~
|
21
|
+
# | |
|
22
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
23
|
+
# | |
|
24
|
+
# ~ Ending Address* ~
|
25
|
+
# | |
|
26
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
27
|
+
# @author Sylvain Daubert
|
28
|
+
class TrafficSelector < PacketGen::Types::Fields
|
29
|
+
# IPv4 traffic selector type
|
30
|
+
TS_IPV4_ADDR_RANGE = 7
|
31
|
+
# IPv6 traffic selector type
|
32
|
+
TS_IPV6_ADDR_RANGE = 8
|
8
33
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
+
# @!attribute [r] type
|
35
|
+
# 8-bit TS type
|
36
|
+
# @return [Integer]
|
37
|
+
define_field :type, PacketGen::Types::Int8, default: 7
|
38
|
+
# @!attribute [r] protocol
|
39
|
+
# 8-bit protocol ID
|
40
|
+
# @return [Integer]
|
41
|
+
define_field :protocol, PacketGen::Types::Int8, default: 0
|
42
|
+
# @!attribute length
|
43
|
+
# 16-bit Selector Length
|
44
|
+
# @return [Integer]
|
45
|
+
define_field :length, PacketGen::Types::Int16
|
46
|
+
# @!attribute start_port
|
47
|
+
# 16-bit Start port
|
48
|
+
# @return [Integer]
|
49
|
+
define_field :start_port, PacketGen::Types::Int16, default: 0
|
50
|
+
# @!attribute end_port
|
51
|
+
# 16-bit End port
|
52
|
+
# @return [Integer]
|
53
|
+
define_field :end_port, PacketGen::Types::Int16, default: 65_535
|
54
|
+
# @!attribute start_addr
|
55
|
+
# starting address
|
56
|
+
# @return [IP::Addr, IPv6::Addr]
|
57
|
+
define_field :start_addr, PacketGen::Header::IP::Addr
|
58
|
+
# @!attribute end_addr
|
59
|
+
# starting address
|
60
|
+
# @return [IP::Addr, IPv6::Addr]
|
61
|
+
define_field :end_addr, PacketGen::Header::IP::Addr
|
34
62
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
# 16-bit Start port
|
49
|
-
# @return [Integer]
|
50
|
-
define_field :start_port, PacketGen::Types::Int16, default: 0
|
51
|
-
# @!attribute end_port
|
52
|
-
# 16-bit End port
|
53
|
-
# @return [Integer]
|
54
|
-
define_field :end_port, PacketGen::Types::Int16, default: 65_535
|
55
|
-
# @!attribute start_addr
|
56
|
-
# starting address
|
57
|
-
# @return [IP::Addr, IPv6::Addr]
|
58
|
-
define_field :start_addr, PacketGen::Header::IP::Addr
|
59
|
-
# @!attribute end_addr
|
60
|
-
# starting address
|
61
|
-
# @return [IP::Addr, IPv6::Addr]
|
62
|
-
define_field :end_addr, PacketGen::Header::IP::Addr
|
63
|
+
# @param [Hash] options
|
64
|
+
# @option [Range] :ports port range
|
65
|
+
# @option [Integer] :start_port start port
|
66
|
+
# @option [Integer] :end_port end port
|
67
|
+
def initialize(options={})
|
68
|
+
super
|
69
|
+
select_addr options
|
70
|
+
self[:start_addr].from_human(options[:start_addr]) if options[:start_addr]
|
71
|
+
self[:end_addr].from_human(options[:end_addr]) if options[:end_addr]
|
72
|
+
self.type = options[:type] if options[:type]
|
73
|
+
self.protocol = options[:protocol] if options[:protocol]
|
74
|
+
self[:length].value = sz unless options[:length]
|
75
|
+
return unless options[:ports]
|
63
76
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
# @option [Integer] :end_port end port
|
68
|
-
def initialize(options={})
|
69
|
-
super
|
70
|
-
select_addr options
|
71
|
-
self[:start_addr].from_human(options[:start_addr]) if options[:start_addr]
|
72
|
-
self[:end_addr].from_human(options[:end_addr]) if options[:end_addr]
|
73
|
-
self.type = options[:type] if options[:type]
|
74
|
-
self.protocol = options[:protocol] if options[:protocol]
|
75
|
-
self[:length].value = sz unless options[:length]
|
77
|
+
self.start_port = options[:ports].begin
|
78
|
+
self.end_port = options[:ports].end
|
79
|
+
end
|
76
80
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
+
# Populate object from a string
|
82
|
+
# @param [String] str
|
83
|
+
# @return [self]
|
84
|
+
def read(str)
|
85
|
+
super
|
86
|
+
select_addr_from_type type
|
87
|
+
super
|
88
|
+
end
|
81
89
|
|
82
|
-
|
83
|
-
# @param [String] str
|
84
|
-
# @return [self]
|
85
|
-
def read(str)
|
86
|
-
super
|
87
|
-
select_addr_from_type type
|
88
|
-
super
|
89
|
-
end
|
90
|
+
undef type=, protocol=
|
90
91
|
|
91
|
-
|
92
|
+
# Set type
|
93
|
+
# @param [Integer,String] value
|
94
|
+
# @return [Integer]
|
95
|
+
def type=(value)
|
96
|
+
type = case value
|
97
|
+
when Integer
|
98
|
+
value
|
99
|
+
else
|
100
|
+
c = self.class.constants.grep(/TS_#{value.upcase}/).first
|
101
|
+
c ? self.class.const_get(c) : nil
|
102
|
+
end
|
103
|
+
raise ArgumentError, "unknown type #{value.inspect}" unless type
|
92
104
|
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
def type=(value)
|
97
|
-
type = case value
|
98
|
-
when Integer
|
99
|
-
value
|
100
|
-
else
|
101
|
-
c = self.class.constants.grep(/TS_#{value.upcase}/).first
|
102
|
-
c ? self.class.const_get(c) : nil
|
103
|
-
end
|
104
|
-
raise ArgumentError, "unknown type #{value.inspect}" unless type
|
105
|
-
select_addr_from_type type
|
106
|
-
self[:type].value = type
|
107
|
-
end
|
105
|
+
select_addr_from_type type
|
106
|
+
self[:type].value = type
|
107
|
+
end
|
108
108
|
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
self[:protocol].value = protocol
|
121
|
-
end
|
109
|
+
# Set protocol
|
110
|
+
# @param [Integer,String] value
|
111
|
+
# @return [Integer]
|
112
|
+
def protocol=(value)
|
113
|
+
protocol = case value
|
114
|
+
when Integer
|
115
|
+
value
|
116
|
+
else
|
117
|
+
PacketGen::Proto.getprotobyname(value)
|
118
|
+
end
|
119
|
+
raise ArgumentError, "unknown protocol #{value.inspect}" unless protocol
|
122
120
|
|
123
|
-
|
124
|
-
|
125
|
-
def to_human
|
126
|
-
h = start_addr << '-' << end_addr
|
127
|
-
unless human_protocol.empty?
|
128
|
-
h << "/#{human_protocol}"
|
129
|
-
h << "[#{start_port}-#{end_port}]" if (start_port..end_port) != (0..65_535)
|
130
|
-
end
|
131
|
-
h
|
132
|
-
end
|
121
|
+
self[:protocol].value = protocol
|
122
|
+
end
|
133
123
|
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
Proto.getprotobynumber(protocol) || protocol.to_s
|
142
|
-
end
|
124
|
+
# Get a human readable string
|
125
|
+
# @return [String]
|
126
|
+
def to_human
|
127
|
+
h = start_addr << '-' << end_addr
|
128
|
+
unless human_protocol.empty?
|
129
|
+
h << "/#{human_protocol}"
|
130
|
+
h << "[#{start_port}-#{end_port}]" if (start_port..end_port) != (0..65_535)
|
143
131
|
end
|
132
|
+
h
|
133
|
+
end
|
144
134
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
else
|
154
|
-
"type #{type}"
|
155
|
-
end
|
135
|
+
# Get human readable protocol name. If protocol ID is 0, an empty string
|
136
|
+
# is returned.
|
137
|
+
# @return [String]
|
138
|
+
def human_protocol
|
139
|
+
if protocol.zero?
|
140
|
+
''
|
141
|
+
else
|
142
|
+
PacketGen::Proto.getprotobynumber(protocol) || protocol.to_s
|
156
143
|
end
|
144
|
+
end
|
157
145
|
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
else
|
169
|
-
raise ArgumentError, "unknown type #{type}"
|
170
|
-
end
|
146
|
+
# Get human readable TS type
|
147
|
+
# @return [String]
|
148
|
+
def human_type
|
149
|
+
case type
|
150
|
+
when TS_IPV4_ADDR_RANGE
|
151
|
+
'IPv4'
|
152
|
+
when TS_IPV6_ADDR_RANGE
|
153
|
+
'IPv6'
|
154
|
+
else
|
155
|
+
"type #{type}"
|
171
156
|
end
|
157
|
+
end
|
158
|
+
|
159
|
+
private
|
172
160
|
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
161
|
+
def select_addr_from_type(type)
|
162
|
+
case type
|
163
|
+
when TS_IPV4_ADDR_RANGE, 'IPV4', 'IPv4', 'ipv4', nil
|
164
|
+
self[:start_addr] = PacketGen::Header::IP::Addr.new unless self[:start_addr].is_a?(PacketGen::Header::IP::Addr)
|
165
|
+
self[:end_addr] = PacketGen::Header::IP::Addr.new unless self[:end_addr].is_a?(PacketGen::Header::IP::Addr)
|
166
|
+
when TS_IPV6_ADDR_RANGE, 'IPV6', 'IPv6', 'ipv6'
|
167
|
+
self[:start_addr] = PacketGen::Header::IPv6::Addr.new unless self[:start_addr].is_a?(PacketGen::Header::IPv6::Addr)
|
168
|
+
self[:end_addr] = PacketGen::Header::IPv6::Addr.new unless self[:end_addr].is_a?(PacketGen::Header::IPv6::Addr)
|
169
|
+
else
|
170
|
+
raise ArgumentError, "unknown type #{type}"
|
183
171
|
end
|
184
172
|
end
|
185
173
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
174
|
+
def select_addr(options)
|
175
|
+
if options[:type]
|
176
|
+
select_addr_from_type options[:type]
|
177
|
+
elsif options[:start_addr]
|
178
|
+
ipv4 = IPAddr.new(options[:start_addr]).ipv4?
|
179
|
+
self.type = ipv4 ? TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE
|
180
|
+
elsif options[:end_addr]
|
181
|
+
ipv4 = IPAddr.new(options[:end_addr]).ipv4?
|
182
|
+
self.type = ipv4 ? TS_IPV4_ADDR_RANGE : TS_IPV6_ADDR_RANGE
|
183
|
+
end
|
190
184
|
end
|
185
|
+
end
|
191
186
|
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
# 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
|
198
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
199
|
-
# | Next Payload |C| RESERVED | Payload Length |
|
200
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
201
|
-
# | Number of TSs | RESERVED |
|
202
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
203
|
-
# | |
|
204
|
-
# ~ <Traffic Selectors> ~
|
205
|
-
# | |
|
206
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
207
|
-
# These specific fields are:
|
208
|
-
# * {#num_ts},
|
209
|
-
# * {#rsv1},
|
210
|
-
# * {#rsv2},
|
211
|
-
# * and {#traffic_selectors}.
|
212
|
-
#
|
213
|
-
# == Create a TSi payload
|
214
|
-
# # Create a IKE packet with a TSi payload
|
215
|
-
# pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::TSi')
|
216
|
-
# # add a traffic selector to this payload
|
217
|
-
# pkt.ike_tsi.traffic_selectors << { protocol: 'tcp', ports: 1..1024, start_addr: '20.0.0.1', end_addr: '21.255.255.254' }
|
218
|
-
# # add another traffic selector (IPv6, all protocols)
|
219
|
-
# pkt.ike_tsi.traffic_selectors << { start_addr: '2001::1', end_addr: '200a:ffff:ffff:ffff:ffff:ffff:ffff:ffff' }
|
220
|
-
# @author Sylvain Daubert
|
221
|
-
class TSi < Payload
|
222
|
-
# Payload type number
|
223
|
-
PAYLOAD_TYPE = 44
|
187
|
+
# Set of {TrafficSelector}, used by {TSi} and {TSr}.
|
188
|
+
# @author Sylvain Daubert
|
189
|
+
class TrafficSelectors < PacketGen::Types::Array
|
190
|
+
set_of TrafficSelector
|
191
|
+
end
|
224
192
|
|
225
|
-
|
193
|
+
# This class handles Traffic Selector - Initiator payloads, denoted TSi.
|
194
|
+
#
|
195
|
+
# A TSi payload consists of the IKE generic payload Plugin (see {Payload})
|
196
|
+
# and some specific fields:
|
197
|
+
# 1 2 3
|
198
|
+
# 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
|
199
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
200
|
+
# | Next Payload |C| RESERVED | Payload Length |
|
201
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
202
|
+
# | Number of TSs | RESERVED |
|
203
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
204
|
+
# | |
|
205
|
+
# ~ <Traffic Selectors> ~
|
206
|
+
# | |
|
207
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
208
|
+
# These specific fields are:
|
209
|
+
# * {#num_ts},
|
210
|
+
# * {#rsv1},
|
211
|
+
# * {#rsv2},
|
212
|
+
# * and {#traffic_selectors}.
|
213
|
+
#
|
214
|
+
# == Create a TSi payload
|
215
|
+
# # Create a IKE packet with a TSi payload
|
216
|
+
# pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::TSi')
|
217
|
+
# # add a traffic selector to this payload
|
218
|
+
# pkt.ike_tsi.traffic_selectors << { protocol: 'tcp', ports: 1..1024, start_addr: '20.0.0.1', end_addr: '21.255.255.254' }
|
219
|
+
# # add another traffic selector (IPv6, all protocols)
|
220
|
+
# pkt.ike_tsi.traffic_selectors << { start_addr: '2001::1', end_addr: '200a:ffff:ffff:ffff:ffff:ffff:ffff:ffff' }
|
221
|
+
# @author Sylvain Daubert
|
222
|
+
class TSi < Payload
|
223
|
+
# Payload type number
|
224
|
+
PAYLOAD_TYPE = 44
|
226
225
|
|
227
|
-
|
228
|
-
# 8-bit Number of TSs
|
229
|
-
# @return [Integer]
|
230
|
-
define_field_before :body, :num_ts, PacketGen::Types::Int8
|
231
|
-
# @!attribute rsv
|
232
|
-
# 24-bit RESERVED field
|
233
|
-
# @return [Integer]
|
234
|
-
define_field_before :body, :rsv, PacketGen::Types::Int24
|
226
|
+
remove_field :content
|
235
227
|
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
228
|
+
# @!attribute num_ts
|
229
|
+
# 8-bit Number of TSs
|
230
|
+
# @return [Integer]
|
231
|
+
define_field_before :body, :num_ts, PacketGen::Types::Int8
|
232
|
+
# @!attribute rsv
|
233
|
+
# 24-bit RESERVED field
|
234
|
+
# @return [Integer]
|
235
|
+
define_field_before :body, :rsv, PacketGen::Types::Int24
|
242
236
|
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
end
|
237
|
+
# @!attribute traffic_selectors
|
238
|
+
# Set of {TrafficSelector}
|
239
|
+
# @return {TrafficSelectors}
|
240
|
+
define_field_before :body, :traffic_selectors, TrafficSelectors,
|
241
|
+
builder: ->(h, t) { t.new(counter: h[:num_ts]) }
|
242
|
+
alias selectors traffic_selectors
|
250
243
|
|
251
|
-
|
252
|
-
|
253
|
-
|
244
|
+
# Compute length and set {#length} field
|
245
|
+
# @return [Integer] new length
|
246
|
+
def calc_length
|
247
|
+
selectors.each(&:calc_length)
|
248
|
+
super
|
254
249
|
end
|
255
250
|
end
|
256
251
|
|
257
|
-
|
258
|
-
|
252
|
+
class TSr < TSi
|
253
|
+
# Payload type number
|
254
|
+
PAYLOAD_TYPE = 45
|
255
|
+
end
|
259
256
|
end
|
257
|
+
|
258
|
+
PacketGen::Header.add_class IKE::TSi
|
259
|
+
PacketGen::Header.add_class IKE::TSr
|
260
260
|
end
|