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