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.
- checksums.yaml +7 -0
- data/.gitignore +10 -0
- data/.rubocop.yml +29 -0
- data/.travis.yml +12 -0
- data/Gemfile +3 -0
- data/LICENSE +21 -0
- data/README.md +97 -0
- data/Rakefile +13 -0
- data/lib/packetgen-plugin-ipsec.rb +4 -0
- data/lib/packetgen/plugin/crypto.rb +74 -0
- data/lib/packetgen/plugin/esp.rb +413 -0
- data/lib/packetgen/plugin/ike.rb +241 -0
- data/lib/packetgen/plugin/ike/auth.rb +165 -0
- data/lib/packetgen/plugin/ike/cert.rb +76 -0
- data/lib/packetgen/plugin/ike/certreq.rb +66 -0
- data/lib/packetgen/plugin/ike/id.rb +99 -0
- data/lib/packetgen/plugin/ike/ke.rb +79 -0
- data/lib/packetgen/plugin/ike/nonce.rb +40 -0
- data/lib/packetgen/plugin/ike/notify.rb +159 -0
- data/lib/packetgen/plugin/ike/payload.rb +304 -0
- data/lib/packetgen/plugin/ike/sa.rb +494 -0
- data/lib/packetgen/plugin/ike/sk.rb +261 -0
- data/lib/packetgen/plugin/ike/ts.rb +260 -0
- data/lib/packetgen/plugin/ike/vendor_id.rb +39 -0
- data/lib/packetgen/plugin/ipsec_version.rb +6 -0
- data/packetgen-plugin-ipsec.gemspec +29 -0
- metadata +152 -0
@@ -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
|