packetgen-plugin-ipsec 1.0.0

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.
@@ -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