packetgen-plugin-ipsec 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,304 @@
1
+ # This file is part of IPsec packetgen plugin.
2
+ # See https://github.com/sdaubert/packetgen-plugin-ipsec for more informations
3
+ # Copyright (c) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ # frozen_string_literal: true
7
+
8
+ module PacketGen
9
+ module Plugin
10
+ class IKE
11
+ # PacketGen::Header::Base class for IKE payloads. This class may also be used for unknown payloads.
12
+ #
13
+ # This class handles generic IKE payload Plugin:
14
+ # 1 2 3
15
+ # 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
16
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
17
+ # | Next Payload |C| RESERVED | Payload Length |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ # to which a {#content} field is added to handle content of unknown payload types.
20
+ # @author Sylvain Daubert
21
+ class Payload < PacketGen::Header::Base
22
+ # Give protocol name
23
+ # @return [String]
24
+ def self.protocol_name
25
+ return @protocol_name if defined? @protocol_name
26
+
27
+ basename = to_s.sub(/.*::/, '')
28
+ @protocol_name = "IKE::#{basename}"
29
+ end
30
+
31
+ # @!attribute next
32
+ # 8-bit next payload
33
+ # @return [Integer]
34
+ define_field :next, PacketGen::Types::Int8
35
+ # @!attribute flags
36
+ # 8-bit flags
37
+ # @return [Integer]
38
+ define_field :flags, PacketGen::Types::Int8
39
+ # @!attribute length
40
+ # 16-bit payload total length, including generic payload Plugin
41
+ # @return [Integer]
42
+ define_field :length, PacketGen::Types::Int16
43
+ # @!attribute content
44
+ # Payload content. Depends on payload. Variable length.
45
+ # @return [String]
46
+ define_field :content, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:content) }) }
47
+
48
+ # Defining a body permits using Packet#parse to parse next IKE payloads.
49
+ define_field :body, PacketGen::Types::String
50
+
51
+ # @!attribute critical
52
+ # critical flag
53
+ # @return [Boolean]
54
+ # @!attribute hreserved
55
+ # reserved part of {#flags} field
56
+ # @return [Integer]
57
+ define_bit_fields_on :flags, :critical, :hreserved, 7
58
+
59
+ def initialize(options={})
60
+ super
61
+ self[:content].replace(options[:content]) if options[:content]
62
+ calc_length unless options[:length]
63
+ end
64
+
65
+ # Compute length and set {#length} field
66
+ # @return [Integer] new length
67
+ def calc_length
68
+ # Here, #body is next payload, so body size should not be taken in
69
+ # account (payload's real body is #content).
70
+ self.length = sz - self[:body].sz
71
+ end
72
+ end
73
+ end
74
+
75
+ Header.add_class IKE::Payload
76
+ end
77
+ end
78
+
79
+ require_relative 'sa'
80
+ require_relative 'ke'
81
+ require_relative 'nonce'
82
+ require_relative 'notify'
83
+ require_relative 'sk'
84
+ require_relative 'id'
85
+ require_relative 'cert'
86
+ require_relative 'certreq'
87
+ require_relative 'auth'
88
+ require_relative 'ts'
89
+ require_relative 'vendor_id'
90
+
91
+ module PacketGen::Plugin
92
+ IKE.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
93
+ IKE::Payload.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
94
+ IKE::KE.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
95
+ IKE::Nonce.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
96
+ IKE::Notify.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
97
+ IKE::SK.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
98
+ IKE::IDi.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
99
+ IKE::IDr.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
100
+ IKE::Cert.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
101
+ IKE::CertReq.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
102
+ IKE::Auth.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
103
+ IKE::TSi.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
104
+ IKE::TSr.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
105
+ IKE::VendorID.bind IKE::SA, next: IKE::SA::PAYLOAD_TYPE
106
+
107
+ IKE.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
108
+ IKE::Payload.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
109
+ IKE::SA.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
110
+ IKE::Nonce.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
111
+ IKE::Notify.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
112
+ IKE::SK.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
113
+ IKE::IDi.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
114
+ IKE::IDr.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
115
+ IKE::Cert.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
116
+ IKE::CertReq.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
117
+ IKE::Auth.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
118
+ IKE::TSi.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
119
+ IKE::TSr.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
120
+ IKE::VendorID.bind IKE::KE, next: IKE::KE::PAYLOAD_TYPE
121
+
122
+ IKE.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
123
+ IKE::Payload.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
124
+ IKE::SA.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
125
+ IKE::KE.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
126
+ IKE::Notify.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
127
+ IKE::SK.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
128
+ IKE::IDi.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
129
+ IKE::IDr.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
130
+ IKE::Cert.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
131
+ IKE::CertReq.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
132
+ IKE::Auth.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
133
+ IKE::TSi.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
134
+ IKE::TSr.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
135
+ IKE::VendorID.bind IKE::Nonce, next: IKE::Nonce::PAYLOAD_TYPE
136
+
137
+ IKE.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
138
+ IKE::Payload.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
139
+ IKE::SA.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
140
+ IKE::KE.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
141
+ IKE::Nonce.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
142
+ IKE::Notify.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
143
+ IKE::SK.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
144
+ IKE::IDi.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
145
+ IKE::IDr.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
146
+ IKE::Cert.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
147
+ IKE::CertReq.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
148
+ IKE::Auth.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
149
+ IKE::TSi.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
150
+ IKE::TSr.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
151
+ IKE::VendorID.bind IKE::Notify, next: IKE::Notify::PAYLOAD_TYPE
152
+
153
+ IKE.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
154
+ IKE::Payload.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
155
+ IKE::SA.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
156
+ IKE::KE.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
157
+ IKE::Nonce.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
158
+ IKE::Notify.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
159
+ IKE::IDi.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
160
+ IKE::IDr.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
161
+ IKE::Cert.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
162
+ IKE::CertReq.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
163
+ IKE::Auth.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
164
+ IKE::TSi.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
165
+ IKE::TSr.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
166
+ IKE::VendorID.bind IKE::SK, next: IKE::SK::PAYLOAD_TYPE
167
+
168
+ IKE.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
169
+ IKE::Payload.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
170
+ IKE::SA.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
171
+ IKE::KE.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
172
+ IKE::Nonce.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
173
+ IKE::Notify.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
174
+ IKE::SK.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
175
+ IKE::IDr.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
176
+ IKE::Cert.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
177
+ IKE::CertReq.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
178
+ IKE::Auth.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
179
+ IKE::TSi.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
180
+ IKE::TSr.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
181
+ IKE::VendorID.bind IKE::IDi, next: IKE::IDi::PAYLOAD_TYPE
182
+
183
+ IKE.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
184
+ IKE::Payload.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
185
+ IKE::SA.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
186
+ IKE::KE.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
187
+ IKE::Nonce.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
188
+ IKE::Notify.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
189
+ IKE::SK.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
190
+ IKE::IDi.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
191
+ IKE::Cert.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
192
+ IKE::CertReq.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
193
+ IKE::Auth.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
194
+ IKE::TSi.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
195
+ IKE::TSr.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
196
+ IKE::VendorID.bind IKE::IDr, next: IKE::IDr::PAYLOAD_TYPE
197
+
198
+ IKE.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
199
+ IKE::Payload.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
200
+ IKE::SA.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
201
+ IKE::KE.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
202
+ IKE::Nonce.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
203
+ IKE::Notify.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
204
+ IKE::SK.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
205
+ IKE::IDi.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
206
+ IKE::IDr.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
207
+ IKE::CertReq.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
208
+ IKE::Auth.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
209
+ IKE::TSi.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
210
+ IKE::TSr.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
211
+ IKE::VendorID.bind IKE::Cert, next: IKE::Cert::PAYLOAD_TYPE
212
+
213
+ IKE.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
214
+ IKE::Payload.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
215
+ IKE::SA.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
216
+ IKE::KE.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
217
+ IKE::Nonce.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
218
+ IKE::Notify.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
219
+ IKE::SK.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
220
+ IKE::IDi.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
221
+ IKE::IDr.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
222
+ IKE::Cert.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
223
+ IKE::Auth.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
224
+ IKE::TSi.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
225
+ IKE::TSr.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
226
+ IKE::VendorID.bind IKE::CertReq, next: IKE::CertReq::PAYLOAD_TYPE
227
+
228
+ IKE.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
229
+ IKE::Payload.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
230
+ IKE::SA.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
231
+ IKE::KE.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
232
+ IKE::Nonce.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
233
+ IKE::Notify.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
234
+ IKE::SK.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
235
+ IKE::IDi.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
236
+ IKE::IDr.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
237
+ IKE::Cert.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
238
+ IKE::CertReq.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
239
+ IKE::TSi.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
240
+ IKE::TSr.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
241
+ IKE::VendorID.bind IKE::Auth, next: IKE::Auth::PAYLOAD_TYPE
242
+
243
+ IKE.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
244
+ IKE::Payload.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
245
+ IKE::SA.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
246
+ IKE::KE.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
247
+ IKE::Nonce.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
248
+ IKE::Notify.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
249
+ IKE::SK.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
250
+ IKE::IDi.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
251
+ IKE::IDr.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
252
+ IKE::Cert.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
253
+ IKE::CertReq.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
254
+ IKE::Auth.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
255
+ IKE::TSr.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
256
+ IKE::VendorID.bind IKE::TSi, next: IKE::TSi::PAYLOAD_TYPE
257
+
258
+ IKE.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
259
+ IKE::Payload.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
260
+ IKE::SA.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
261
+ IKE::KE.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
262
+ IKE::Nonce.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
263
+ IKE::Notify.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
264
+ IKE::SK.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
265
+ IKE::IDi.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
266
+ IKE::IDr.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
267
+ IKE::Cert.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
268
+ IKE::CertReq.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
269
+ IKE::Auth.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
270
+ IKE::TSi.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
271
+ IKE::VendorID.bind IKE::TSr, next: IKE::TSr::PAYLOAD_TYPE
272
+
273
+ IKE.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
274
+ IKE::Payload.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
275
+ IKE::SA.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
276
+ IKE::KE.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
277
+ IKE::Nonce.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
278
+ IKE::Notify.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
279
+ IKE::SK.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
280
+ IKE::IDi.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
281
+ IKE::IDr.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
282
+ IKE::Cert.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
283
+ IKE::CertReq.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
284
+ IKE::Auth.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
285
+ IKE::TSi.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
286
+ IKE::TSr.bind IKE::VendorID, next: IKE::VendorID::PAYLOAD_TYPE
287
+
288
+ # Last defined. To be used as default if no other may be parsed.
289
+ IKE::SA.bind IKE::Payload, next: ->(v) { v > 0 }
290
+ IKE::KE.bind IKE::Payload, next: ->(v) { v > 0 }
291
+ IKE::Nonce.bind IKE::Payload, next: ->(v) { v > 0 }
292
+ IKE::Notify.bind IKE::Payload, next: ->(v) { v > 0 }
293
+ IKE::SK.bind IKE::Payload, next: ->(v) { v > 0 }
294
+ IKE::IDi.bind IKE::Payload, next: ->(v) { v > 0 }
295
+ IKE::IDr.bind IKE::Payload, next: ->(v) { v > 0 }
296
+ IKE::Cert.bind IKE::Payload, next: ->(v) { v > 0 }
297
+ IKE::CertReq.bind IKE::Payload, next: ->(v) { v > 0 }
298
+ IKE::Auth.bind IKE::Payload, next: ->(v) { v > 0 }
299
+ IKE::TSi.bind IKE::Payload, next: ->(v) { v > 0 }
300
+ IKE::TSr.bind IKE::Payload, next: ->(v) { v > 0 }
301
+ IKE::VendorID.bind IKE::Payload, next: ->(v) { v > 0 }
302
+ IKE.bind IKE::Payload, next: ->(v) { v > 0 }
303
+ IKE::Payload.bind IKE::Payload, next: ->(v) { v > 0 }
304
+ end
@@ -0,0 +1,494 @@
1
+ # coding: utf-8
2
+ # This file is part of IPsec packetgen plugin.
3
+ # See https://github.com/sdaubert/packetgen-plugin-ipsec for more informations
4
+ # Copyright (c) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
5
+ # This program is published under MIT license.
6
+
7
+ # frozen_string_literal: true
8
+
9
+ module PacketGen
10
+ module Plugin
11
+ class IKE
12
+ # Transform attribute.
13
+ # 1 2 3
14
+ # 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
15
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
16
+ # |A| Attribute Type | AF=0 Attribute Length |
17
+ # |F| | AF=1 Attribute Value |
18
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
19
+ # | AF=0 Attribute Value |
20
+ # | AF=1 Not Transmitted |
21
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
22
+ # Such an attribute may have a TLV (Type/length/value) format if AF=0,
23
+ # or a TV format (AF=1).
24
+ # @author Sylvain Daubert
25
+ class Attribute < PacketGen::Types::Fields
26
+ TYPE_KEY_LENGTH = 14
27
+
28
+ # @!attribute type
29
+ # attribute type
30
+ # @return [Integer]
31
+ define_field :type, PacketGen::Types::Int16
32
+ # @!attribute length
33
+ # attribute length
34
+ # @return [Integer]
35
+ define_field :length, PacketGen::Types::Int16
36
+ # @!attribute value
37
+ # attribute value
38
+ # @return [Integer]
39
+ define_field :value, PacketGen::Types::Int32, optional: ->(h) { !h.tv_format? }
40
+
41
+ def initialize(options={})
42
+ super
43
+ if tv_format?
44
+ self[:length].value = (options[:value] & 0xffff)
45
+ else
46
+ self[:length].value = 8 unless options[:length]
47
+ end
48
+ end
49
+
50
+ undef length, value
51
+
52
+ # @return [Integer]
53
+ def length
54
+ tv_format? ? 4 : self[:length].to_i
55
+ end
56
+
57
+ # @return [Integer]
58
+ def value
59
+ tv_format? ? self[:length].to_i : self[:value].to_i
60
+ end
61
+
62
+ # Get a human readable string
63
+ # @return [String]
64
+ def to_human
65
+ name = self.class.constants.grep(/TYPE_/)
66
+ .detect { |c| self.class.const_get(c) == (type & 0x7fff) } || "attr[#{type & 0x7fff}]"
67
+ name = name.to_s.sub(/TYPE_/, '')
68
+ "#{name}=#{value}"
69
+ end
70
+
71
+ # Say if attribute use TV format (+true+) or TLV one (+false+)
72
+ # @return [Boolean]
73
+ def tv_format?
74
+ type & 0x8000 == 0x8000
75
+ end
76
+ end
77
+
78
+ # Set of {Attribute} in a {Transform}
79
+ # @author Sylvain Daubert
80
+ class Attributes < PacketGen::Types::Array
81
+ set_of Attribute
82
+ end
83
+
84
+ # SA Tranform substructure, as defined in RFC 7296 §3.3.2
85
+ # 1 2 3
86
+ # 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
87
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
88
+ # | Last Substruc | RESERVED | Transform Length |
89
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
90
+ # |Transform Type | RESERVED | Transform ID |
91
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
92
+ # | |
93
+ # ~ Transform Attributes ~
94
+ # | |
95
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
96
+ #
97
+ # == Create a Transform
98
+ # # using type and id names
99
+ # trans = PacketGen::Plugin::IKE::Transform.new(type: 'ENCR', id: 'AES_CBC')
100
+ # # using integer values
101
+ # trans = PacketGen::Plugin::IKE::Transform.new(type: 1, id: 12)
102
+ # == Add attributes to a transform
103
+ # # using an Attribute object
104
+ # attr = PacketGen::Plugin::IKE::Attribute.new(type: 14, value: 128)
105
+ # trans.attributes << attr
106
+ # # using a hash
107
+ # trans.attributes << { type: 14, value: 128 }
108
+ # @author Sylvain Daubert
109
+ class Transform < PacketGen::Types::Fields
110
+ TYPES = {
111
+ 'ENCR' => 1,
112
+ 'PRF' => 2,
113
+ 'INTG' => 3,
114
+ 'DH' => 4,
115
+ 'ESN' => 5
116
+ }.freeze
117
+
118
+ ENCR_DES_IV64 = 1
119
+ ENCR_DES = 2
120
+ ENCR_3DES = 3
121
+ ENCR_RC5 = 4
122
+ ENCR_IDEA = 5
123
+ ENCR_CAST = 6
124
+ ENCR_BLOWFISH = 7
125
+ ENCR_3IDEA = 8
126
+ ENCR_DES_IV32 = 9
127
+ ENCR_AES_CBC = 12
128
+ ENCR_AES_CTR = 13
129
+ ENCR_AES_CCM8 = 14
130
+ ENCR_AES_CCM12 = 15
131
+ ENCR_AES_CCM16 = 16
132
+ ENCR_AES_GCM8 = 18
133
+ ENCR_AES_GCM12 = 19
134
+ ENCR_AES_GCM16 = 20
135
+ ENCR_CAMELLIA_CBC = 23
136
+ ENCR_CAMELLIA_CTR = 24
137
+ ENCR_CAMELLIA_CCM8 = 25
138
+ ENCR_CAMELLIA_CCM12 = 26
139
+ ENCR_CAMELLIA_CCM16 = 27
140
+ ENCR_CHACHA20_POLY1305 = 28
141
+
142
+ PRF_HMAC_MD5 = 1
143
+ PRF_HMAC_SHA1 = 2
144
+ PRF_AES128_XCBC = 4
145
+ PRF_HMAC_SHA2_256 = 5
146
+ PRF_HMAC_SHA2_384 = 6
147
+ PRF_HMAC_SHA2_512 = 7
148
+ PRF_AES128_CMAC = 8
149
+
150
+ INTG_NONE = 0
151
+ INTG_HMAC_MD5_96 = 1
152
+ INTG_HMAC_SHA1_96 = 2
153
+ INTG_AES_XCBC_96 = 5
154
+ INTG_HMAC_MD5_128 = 6
155
+ INTG_HMAC_SHA1_160 = 7
156
+ INTG_AES_CMAC_96 = 8
157
+ INTG_AES128_GMAC = 9
158
+ INTG_AES192_GMAC = 10
159
+ INTG_AES256_GMAC = 11
160
+ INTG_HMAC_SHA2_256_128 = 12
161
+ INTG_HMAC_SHA2_384_192 = 13
162
+ INTG_HMAC_SHA2_512_256 = 14
163
+
164
+ DH_NONE = 0
165
+ DH_MODP768 = 1
166
+ DH_MODP1024 = 2
167
+ DH_MODP1536 = 5
168
+ DH_MODP2048 = 14
169
+ DH_MODP3072 = 15
170
+ DH_MODP4096 = 16
171
+ DH_MODP6144 = 17
172
+ DH_MODP8192 = 18
173
+ DH_ECP256 = 19
174
+ DH_ECP384 = 20
175
+ DH_ECP521 = 21
176
+ DH_BRAINPOOLP224 = 27
177
+ DH_BRAINPOOLP256 = 28
178
+ DH_BRAINPOOLP384 = 29
179
+ DH_BRAINPOOLP512 = 30
180
+ DH_CURVE25519 = 31
181
+ DH_CURVE448 = 32
182
+
183
+ ESN_NO_ESN = 0
184
+ ESN_ESN = 1
185
+
186
+ # @!attribute last
187
+ # 8-bit last substructure. Specifies whether or not this is the
188
+ # last Transform Substructure in the Proposal. This field has a value of 0
189
+ # if this was the last Transform Substructure, and a value of 3 if
190
+ # there are more Transform Substructures.
191
+ # @return [Integer]
192
+ define_field :last, PacketGen::Types::Int8
193
+ # @!attribute rsv1
194
+ # 8-bit reserved field
195
+ # @return [Integer]
196
+ define_field :rsv1, PacketGen::Types::Int8
197
+ # @!attribute length
198
+ # 16-bit transform length
199
+ # @return [Integer]
200
+ define_field :length, PacketGen::Types::Int16
201
+ # @!attribute [r] type
202
+ # 8-bit transform type. The Transform Type is the cryptographic
203
+ # algorithm type (i.e. encryption, PRF, integrity, etc.)
204
+ # @return [Integer]
205
+ define_field :type, PacketGen::Types::Int8Enum, enum: TYPES
206
+ # @!attribute rsv2
207
+ # 8-bit reserved field
208
+ # @return [Integer]
209
+ define_field :rsv2, PacketGen::Types::Int8
210
+ # @!attribute [r] id
211
+ # 16-bit transform ID. The Transform ID is the specific instance of
212
+ # the proposed transform type.
213
+ # @return [Integer]
214
+ define_field :id, PacketGen::Types::Int16
215
+ # @!attribute attributes
216
+ # Set of attributes for this transform
217
+ # @return [Attributes]
218
+ define_field :attributes, Attributes, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:attributes) }) }
219
+
220
+ def initialize(options={})
221
+ super
222
+ self.type = options[:type] if options[:type]
223
+ self.id = options[:id] if options[:id]
224
+ self[:length].value = sz unless options[:length]
225
+ end
226
+
227
+ undef id=
228
+
229
+ # Set transform ID
230
+ # @param [Integer,String] value
231
+ # @return [Integer]
232
+ def id=(value)
233
+ id = case value
234
+ when Integer
235
+ value
236
+ else
237
+ c = self.class.constants.grep(/#{human_type}_#{value}/).first
238
+ c ? self.class.const_get(c) : nil
239
+ end
240
+ raise ArgumentError, "unknown ID #{value.inspect}" unless id
241
+ self[:id].value = id
242
+ end
243
+
244
+ # Compute length and set {#length} field
245
+ # @return [Integer] new length
246
+ def calc_length
247
+ PacketGen::Header::Base.calculate_and_set_length self
248
+ end
249
+
250
+ # Get a human readable string
251
+ # @return [String]
252
+ def to_human
253
+ h = "#{human_type}(#{human_id}".dup
254
+ h << ",#{attributes.to_human}" unless attributes.empty?
255
+ h << ')'
256
+ end
257
+
258
+ # Get human-readable type
259
+ # @return [String]
260
+ def human_type
261
+ if self[:type].enum.value? self.type
262
+ self[:type].to_human
263
+ else
264
+ "type[#{self.type}]"
265
+ end
266
+ end
267
+
268
+ # Get human-readable ID
269
+ # @return [String]
270
+ def human_id
271
+ name = self.class.constants.grep(/#{human_type}_/)
272
+ .detect { |c| self.class.const_get(c) == id } || "ID=#{id}"
273
+ name.to_s.sub(/#{human_type}_/, '')
274
+ end
275
+
276
+ # Say if this transform is the last one (from {#last} field)
277
+ # @return [Boolean,nil] returns a Boolean when {#last} has defined value (+0+ => +true+, +3+ => +false+), else +nil+ is returned.
278
+ def last?
279
+ case last
280
+ when 0
281
+ true
282
+ when 3
283
+ false
284
+ end
285
+ end
286
+ end
287
+
288
+ # Set of {Transform} in a {SAProposal}
289
+ # @author Sylvain Daubert
290
+ class Transforms < PacketGen::Types::Array
291
+ set_of Transform
292
+
293
+ # Same as {PacketGen::Types::Array#push} but update previous {Transform#last} attribute
294
+ # @see PacketGen::Types::Array#push
295
+ def push(trans)
296
+ super
297
+ self[-2].last = 3 if size > 1
298
+ self[-1].last = 0
299
+ self
300
+ end
301
+ end
302
+
303
+ # SA Proposal, as defined in RFC 7296 §3.3.1
304
+ # 1 2 3
305
+ # 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
306
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
307
+ # | Last Substruc | RESERVED | Proposal Length |
308
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
309
+ # | Proposal Num | Protocol ID | SPI Size |Num Transforms|
310
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
311
+ # ~ SPI (variable) ~
312
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
313
+ # | |
314
+ # ~ <Transforms> ~
315
+ # | |
316
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
317
+ #
318
+ # == Create a proposal
319
+ # # using protocol name
320
+ # proposal = PacketGen::Plugin::IKE::Proposal.new(num: 1, protocol: 'IKE')
321
+ # # using integer values
322
+ # proposal = PacketGen::Plugin::IKE::Proposal.new(num: 1, protocol: 1)
323
+ # == Add transforms to a proposal
324
+ # # using a Transform object
325
+ # trans = PacketGen::Plugin::IKE::Transform.new(type: 'ENCR', id: '3DES')
326
+ # proposal.transforms << trans
327
+ # # using a hash
328
+ # proposal.transforms << { type: 'ENCR', id: '3DES' }
329
+ # @author Sylvain Daubert
330
+ class SAProposal < PacketGen::Types::Fields
331
+ # @!attribute last
332
+ # 8-bit last substructure. Specifies whether or not this is the
333
+ # last Proposal Substructure in the SA. This field has a value of 0
334
+ # if this was the last Proposal Substructure, and a value of 2 if
335
+ # there are more Proposal Substructures.
336
+ # @return [Integer]
337
+ define_field :last, PacketGen::Types::Int8
338
+ # @!attribute reserved
339
+ # 8-bit reserved field
340
+ # @return [Integer]
341
+ define_field :reserved, PacketGen::Types::Int8
342
+ # @!attribute length
343
+ # 16-bit proposal length
344
+ # @return [Integer]
345
+ define_field :length, PacketGen::Types::Int16
346
+ # @!attribute num
347
+ # 8-bit proposal number. When a proposal is made, the first
348
+ # proposal in an SA payload MUST be 1, and subsequent proposals MUST
349
+ # be one more than the previous proposal (indicating an OR of the
350
+ # two proposals). When a proposal is accepted, the proposal number
351
+ # in the SA payload MUST match the number on the proposal sent that
352
+ # was accepted.
353
+ # @return [Integer]
354
+ define_field :num, PacketGen::Types::Int8, default: 1
355
+ # @!attribute [r] protocol
356
+ # 8-bit protocol ID. Specify IPsec protocol currently negociated.
357
+ # May 1 (IKE), 2 (AH) or 3 (ESP).
358
+ # @return [Integer]
359
+ define_field :protocol, PacketGen::Types::Int8Enum, enum: PROTOCOLS
360
+ # @!attribute spi_size
361
+ # 8-bit SPI size. Give size of SPI field. Set to 0 for an initial IKE SA
362
+ # negotiation, as SPI is obtained from outer Plugin.
363
+ # @return [Integer]
364
+ define_field :spi_size, PacketGen::Types::Int8, default: 0
365
+ # @!attribute num_trans
366
+ # 8-bit number of transformations
367
+ # @return [Integer]
368
+ define_field :num_trans, PacketGen::Types::Int8, default: 0
369
+ # @!attribute spi
370
+ # the sending entity's SPI. When the {#spi_size} field is zero,
371
+ # this field is not present in the proposal.
372
+ # @return [String]
373
+ define_field :spi, PacketGen::Types::String, builder: ->(h, t) { t.new(length_from: h[:spi_size]) }
374
+ # @!attribute transforms
375
+ # 8-bit set of tranforms for this proposal
376
+ # @return [Transforms]
377
+ define_field :transforms, Transforms, builder: ->(h, t) { t.new(counter: h[:num_trans]) }
378
+
379
+ def initialize(options={})
380
+ if options[:spi] && options[:spi_size].nil?
381
+ options[:spi_size] = options[:spi].size
382
+ end
383
+ super
384
+ self.length = sz unless options[:length]
385
+ self.protocol = options[:protocol] if options[:protocol]
386
+ end
387
+
388
+ # Compute length and set {#length} field
389
+ # @return [Integer] new length
390
+ def calc_length
391
+ transforms.each(&:calc_length)
392
+ PacketGen::Header::Base.calculate_and_set_length self
393
+ end
394
+
395
+ # Get a human readable string
396
+ # @return [String]
397
+ def to_human
398
+ str = "##{num} #{human_protocol}".dup
399
+ case spi_size
400
+ when 4
401
+ str << '(spi:0x%08x)' % PacketGen::Types::Int32.new.read(spi).to_i
402
+ when 8
403
+ str << '(spi:0x%016x)' % PacketGen::Types::Int64.new.read(spi).to_i
404
+ end
405
+ str << ":#{transforms.to_human}"
406
+ end
407
+
408
+ # Get protocol name
409
+ # @return [String]
410
+ def human_protocol
411
+ self[:protocol].to_human
412
+ end
413
+
414
+ # Say if this proposal is the last one (from {#last} field)
415
+ # @return [Boolean,nil] returns a Boolean when {#last} has defined value
416
+ # (+0+ => +true+, +2+ => +false+), else +nil+ is returned.
417
+ def last?
418
+ case last
419
+ when 0
420
+ true
421
+ when 2
422
+ false
423
+ end
424
+ end
425
+ end
426
+
427
+ # Set of {SAProposal}
428
+ # @author Sylvain Daubert
429
+ class SAProposals < PacketGen::Types::Array
430
+ set_of SAProposal
431
+
432
+ # Separator used between proposals in {#to_human}
433
+ HUMAN_SEPARATOR = '; '
434
+
435
+ # Same as {PacketGen::Types::Array#push} but update previous {SAProposal#last} attribute
436
+ # @see PacketGen::Types::Array#push
437
+ def push(prop)
438
+ super
439
+ self[-2].last = 2 if size > 1
440
+ self[-1].last = 0
441
+ self
442
+ end
443
+ end
444
+
445
+ # This class handles Security Assocation payloads, as defined in RFC 7296 §3.3.
446
+ #
447
+ # A SA payload contains a generic payload Plugin (see {Payload}) and a set of
448
+ # {SAProposal} ({#proposals} field, which is a {SAProposals} object):
449
+ # 1 2 3
450
+ # 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
451
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
452
+ # | Next Payload |C| RESERVED | Payload Length |
453
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
454
+ # | |
455
+ # ~ <Proposals> ~
456
+ # | |
457
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
458
+ #
459
+ # == Create a SA payload
460
+ # # Create a IKE packet with a SA payload
461
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::SA')
462
+ # # add a proposal. Protocol name is taken from SAProposal::PROTO_* constants
463
+ # pkt.ike_sa.proposals << { num: 1, protocol: 'ESP' }
464
+ # # add a transform to this proposal.
465
+ # # type name is taken from Transform::TYPE_* constants.
466
+ # # ID is taken from Transform::<TYPE>_* constants.
467
+ # pkt.ike_sa.proposals.first.transforms << { type: 'ENCR', id: 'AES_CTR' }
468
+ # # and finally, add an attribute to this transform (here, KEY_SIZE = 128 bits)
469
+ # pkt.ike_sa.proposals[0].transforms[0].attributes << { type: 0x800e, value: 128 }
470
+ # pkt.calc_length
471
+ # @author Sylvain Daubert
472
+ class SA < Payload
473
+ # Payload type number
474
+ PAYLOAD_TYPE = 33
475
+
476
+ remove_field :content
477
+
478
+ # @!attribute proposals
479
+ # Set of SA proposals
480
+ # @return [SAProposals]
481
+ define_field_before :body, :proposals, SAProposals, builder: ->(h, t) { t.new(length_from: -> { h.length - h.offset_of(:proposals) }) }
482
+
483
+ # Compute length and set {#length} field
484
+ # @return [Integer] new length
485
+ def calc_length
486
+ proposals.each(&:calc_length)
487
+ super
488
+ end
489
+ end
490
+ end
491
+
492
+ Header.add_class IKE::SA
493
+ end
494
+ end