packetgen-plugin-ipsec 1.0.2 → 1.1.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/.github/workflows/specs.yml +32 -0
- data/.rubocop.yml +28 -3
- data/Gemfile +18 -0
- data/README.md +12 -6
- data/Rakefile +10 -4
- data/lib/packetgen/plugin/crypto.rb +38 -4
- data/lib/packetgen/plugin/esp.rb +410 -378
- data/lib/packetgen/plugin/ike/auth.rb +153 -140
- data/lib/packetgen/plugin/ike/cert.rb +61 -62
- data/lib/packetgen/plugin/ike/certreq.rb +51 -52
- data/lib/packetgen/plugin/ike/id.rb +80 -81
- data/lib/packetgen/plugin/ike/ke.rb +64 -65
- data/lib/packetgen/plugin/ike/nonce.rb +29 -31
- data/lib/packetgen/plugin/ike/notify.rb +134 -139
- data/lib/packetgen/plugin/ike/payload.rb +75 -76
- data/lib/packetgen/plugin/ike/sa.rb +515 -452
- data/lib/packetgen/plugin/ike/sk.rb +221 -221
- data/lib/packetgen/plugin/ike/ts.rb +226 -223
- data/lib/packetgen/plugin/ike/vendor_id.rb +28 -30
- data/lib/packetgen/plugin/ike.rb +213 -217
- data/lib/packetgen/plugin/ipsec_version.rb +8 -1
- data/lib/packetgen-plugin-ipsec.rb +2 -0
- data/packetgen-plugin-ipsec.gemspec +6 -11
- metadata +11 -88
- data/.travis.yml +0 -14
@@ -1,261 +1,261 @@
|
|
1
1
|
# coding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
2
4
|
# This file is part of IPsec packetgen plugin.
|
3
5
|
# See https://github.com/sdaubert/packetgen-plugin-ipsec for more informations
|
4
6
|
# Copyright (c) 2018 Sylvain Daubert <sylvain.daubert@laposte.net>
|
5
7
|
# This program is published under MIT license.
|
6
8
|
|
7
|
-
|
9
|
+
module PacketGen::Plugin
|
10
|
+
class IKE
|
11
|
+
# This class handles encrypted payloads, denoted SK.
|
12
|
+
#
|
13
|
+
# The encrypted payload contains other payloads in encrypted form.
|
14
|
+
# The Encrypted payload consists of the IKE generic payload Plugin followed
|
15
|
+
# by individual fields as follows:
|
16
|
+
# 1 2 3
|
17
|
+
# 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
|
18
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
19
|
+
# | Next Payload |C| RESERVED | Payload Length |
|
20
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
21
|
+
# | Initialization Vector |
|
22
|
+
# | (length is block size for encryption algorithm) |
|
23
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
24
|
+
# ~ Encrypted IKE Payloads ~
|
25
|
+
# + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
26
|
+
# | | Padding (0-255 octets) |
|
27
|
+
# +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
28
|
+
# | | Pad Length |
|
29
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
30
|
+
# ~ Integrity Checksum Data ~
|
31
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
32
|
+
# Encrypted payloads are set in {#content} field, as a {BinStruct::String}.
|
33
|
+
# All others fields are only set when decrypting a previously read SK
|
34
|
+
# payload. They also may be set manually to encrypt IKE payloads.
|
35
|
+
#
|
36
|
+
# == Read and decrypt a SK payload
|
37
|
+
# # Read a IKE packet
|
38
|
+
# pkt = PacketGen.read(str)
|
39
|
+
# # decrypt SK payload
|
40
|
+
# cipher = OpenSSL::Cipher.new('aes-128-ctr')
|
41
|
+
# cipher.decrypt
|
42
|
+
# cipher_key = aes_key
|
43
|
+
# hmac = OpenSSL::HMAC.new(hmac_key, OpenSSL::Digest::SHA256.new)
|
44
|
+
# pkt.ike_sk.decrypt! cipher, intmode: hmac, icv_length: 16 # => true if authentication is verified
|
45
|
+
# pkt.ike_sk.body # => kind of PacketGen::Plugin::IKE::Payload
|
46
|
+
#
|
47
|
+
# == Set and encrypt a SK payload
|
48
|
+
# # Create a IKE packet
|
49
|
+
# pkt = PacketGen.gen('IP').add('IP').add('UDP').add('IKE', init_spi: 0x123456789, resp_spi: 0x987654321, type: 'IKE_AUTH', message_id: 1)
|
50
|
+
# # Add SK payload
|
51
|
+
# pkt.add('IKE::SK', icv_length: 16)
|
52
|
+
# # Add others unencrypted payloads
|
53
|
+
# pkt.add('IKE::IDi').add('IKE::Auth').add('IKE::SA').add('IKE::TSi').add('IKE::TSr')
|
54
|
+
# # encrypt SK payload
|
55
|
+
# cipher = OpenSSL::Cipher.new('aes-128-ctr')
|
56
|
+
# cipher.encrypt
|
57
|
+
# cipher_key = aes_key
|
58
|
+
# hmac = OpenSSL::HMAC.new(hmac_key, OpenSSL::Digest::SHA256.new)
|
59
|
+
# pkt.ike_sk.encrypt! cipher, iv, salt: salt, intmode: hmac
|
60
|
+
# pkt.ike_sk.body # => String
|
61
|
+
# pkt.calc_length
|
62
|
+
#
|
63
|
+
# @author Sylvain Daubert
|
64
|
+
class SK < Payload
|
65
|
+
include Crypto
|
8
66
|
|
9
|
-
|
10
|
-
|
11
|
-
class IKE
|
12
|
-
# This class handles encrypted payloads, denoted SK.
|
13
|
-
#
|
14
|
-
# The encrypted payload contains other payloads in encrypted form.
|
15
|
-
# The Encrypted payload consists of the IKE generic payload Plugin followed
|
16
|
-
# by individual fields as follows:
|
17
|
-
# 1 2 3
|
18
|
-
# 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
|
19
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
20
|
-
# | Next Payload |C| RESERVED | Payload Length |
|
21
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
22
|
-
# | Initialization Vector |
|
23
|
-
# | (length is block size for encryption algorithm) |
|
24
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
25
|
-
# ~ Encrypted IKE Payloads ~
|
26
|
-
# + +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
27
|
-
# | | Padding (0-255 octets) |
|
28
|
-
# +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
|
29
|
-
# | | Pad Length |
|
30
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
31
|
-
# ~ Integrity Checksum Data ~
|
32
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
33
|
-
# Encrypted payloads are set in {#content} field, as a {PacketGen::Types::String}.
|
34
|
-
# All others fields are only set when decrypting a previously read SK
|
35
|
-
# payload. They also may be set manually to encrypt IKE payloads.
|
36
|
-
#
|
37
|
-
# == Read and decrypt a SK payload
|
38
|
-
# # Read a IKE packet
|
39
|
-
# pkt = PacketGen.read(str)
|
40
|
-
# # decrypt SK payload
|
41
|
-
# cipher = OpenSSL::Cipher.new('aes-128-ctr')
|
42
|
-
# cipher.decrypt
|
43
|
-
# cipher_key = aes_key
|
44
|
-
# hmac = OpenSSL::HMAC.new(hmac_key, OpenSSL::Digest::SHA256.new)
|
45
|
-
# pkt.ike_sk.decrypt! cipher, intmode: hmac, icv_length: 16 # => true if authentication is verified
|
46
|
-
# pkt.ike_sk.body # => kind of PacketGen::Plugin::IKE::Payload
|
47
|
-
#
|
48
|
-
# == Set and encrypt a SK payload
|
49
|
-
# # Create a IKE packet
|
50
|
-
# pkt = PacketGen.gen('IP').add('IP').add('UDP').add('IKE', init_spi: 0x123456789, resp_spi: 0x987654321, type: 'IKE_AUTH', message_id: 1)
|
51
|
-
# # Add SK payload
|
52
|
-
# pkt.add('IKE::SK', icv_length: 16)
|
53
|
-
# # Add others unencrypted payloads
|
54
|
-
# pkt.add('IKE::IDi').add('IKE::Auth').add('IKE::SA').add('IKE::TSi').add('IKE::TSr')
|
55
|
-
# # encrypt SK payload
|
56
|
-
# cipher = OpenSSL::Cipher.new('aes-128-ctr')
|
57
|
-
# cipher.encrypt
|
58
|
-
# cipher_key = aes_key
|
59
|
-
# hmac = OpenSSL::HMAC.new(hmac_key, OpenSSL::Digest::SHA256.new)
|
60
|
-
# pkt.ike_sk.encrypt! cipher, iv, salt: salt, intmode: hmac
|
61
|
-
# pkt.ike_sk.body # => String
|
62
|
-
# pkt.calc_length
|
63
|
-
#
|
64
|
-
# @author Sylvain Daubert
|
65
|
-
class SK < Payload
|
66
|
-
include Crypto
|
67
|
+
# Payload type number
|
68
|
+
PAYLOAD_TYPE = 46
|
67
69
|
|
68
|
-
|
69
|
-
|
70
|
+
# ICV (Integrity Check Value) length
|
71
|
+
# @return [Integer]
|
72
|
+
attr_accessor :icv_length
|
70
73
|
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
def initialize(options={})
|
78
|
-
@icv_length = options[:icv_length] || 0
|
79
|
-
super
|
80
|
-
end
|
74
|
+
# @param [Hash] options
|
75
|
+
# @option options [Integer] :icv_length ICV length
|
76
|
+
def initialize(options={})
|
77
|
+
@icv_length = options[:icv_length] || 0
|
78
|
+
super
|
79
|
+
end
|
81
80
|
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
81
|
+
# Decrypt in-place SK payload.
|
82
|
+
# @param [OpenSSL::Cipher] cipher keyed cipher
|
83
|
+
# This cipher is confidentiality-only one, or AEAD one. To use a second
|
84
|
+
# cipher to add integrity, use +:intmode+ option.
|
85
|
+
# @param [Hash] options
|
86
|
+
# @option options [Boolean] :parse parse deciphered payload to retrieve
|
87
|
+
# Plugins (default: +true+)
|
88
|
+
# @option options [Fixnum] :icv_length ICV length for captured packets,
|
89
|
+
# or read from PCapNG files
|
90
|
+
# @option options [String] :salt salt value for CTR and GCM modes
|
91
|
+
# @option options [OpenSSL::HMAC] :intmode integrity mode to use with a
|
92
|
+
# confidentiality-only cipher. Only HMAC are supported.
|
93
|
+
# @return [Boolean] +true+ if SK payload is authenticated
|
94
|
+
def decrypt!(cipher, options={})
|
95
|
+
opt = { salt: '', parse: true }.merge!(options)
|
97
96
|
|
98
|
-
|
97
|
+
set_crypto cipher, opt[:intmode]
|
98
|
+
iv = compute_iv_for_decrypting(opt[:salt].b, self[:content])
|
99
99
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
when 'cbc'
|
105
|
-
cipher.padding = 0
|
106
|
-
real_iv = iv = self[:content].slice!(0, 16)
|
107
|
-
when 'ctr'
|
108
|
-
iv = self[:content].slice!(0, 8)
|
109
|
-
real_iv = force_binary(opt[:salt]) + iv + [1].pack('N')
|
110
|
-
else
|
111
|
-
real_iv = iv = self[:content].slice!(0, 16)
|
100
|
+
if authenticated?
|
101
|
+
if @icv_length.zero?
|
102
|
+
@icv_length = opt[:icv_length].to_i if opt[:icv_length]
|
103
|
+
raise PacketGen::ParseError, 'unknown ICV size' if @icv_length.zero?
|
112
104
|
end
|
113
|
-
|
105
|
+
icv = self[:content].slice!(-@icv_length, @icv_length)
|
106
|
+
end
|
114
107
|
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
raise ParseError, 'unknown ICV size' if @icv_length.zero?
|
119
|
-
end
|
120
|
-
icv = self[:content].slice!(-@icv_length, @icv_length)
|
121
|
-
end
|
108
|
+
authenticate_if_needed iv, icv
|
109
|
+
private_decrypt opt
|
110
|
+
end
|
122
111
|
|
123
|
-
|
124
|
-
|
125
|
-
|
112
|
+
# Encrypt in-place SK payload.
|
113
|
+
# @param [OpenSSL::Cipher] cipher keyed cipher
|
114
|
+
# This cipher is confidentiality-only one, or AEAD one. To use a second
|
115
|
+
# cipher to add integrity, use +:intmode+ option.
|
116
|
+
# @param [String] iv IV to encipher SK payload content
|
117
|
+
# * CTR and GCM modes: +iv+ is 8-bytes long.
|
118
|
+
# @param [Hash] options
|
119
|
+
# @option options [Fixnum] :icv_length ICV length for captured packets,
|
120
|
+
# or read from PCapNG files
|
121
|
+
# @option options [String] :salt salt value for CTR and GCM modes
|
122
|
+
# @option options [Fixnum] :pad_length set a padding length
|
123
|
+
# @option options [String] :padding set a padding. No check with
|
124
|
+
# +:pad_length+ is made. If +:pad_length+ is not set, +:padding+
|
125
|
+
# length is shortened to correct padding length
|
126
|
+
# @option options [OpenSSL::HMAC] :intmode integrity mode to use with a
|
127
|
+
# confidentiality-only cipher. Only HMAC are supported.
|
128
|
+
# @return [self]
|
129
|
+
def encrypt!(cipher, iv, options={}) # rubocop:disable Naming/MethodParameterName
|
130
|
+
opt = { salt: '' }.merge!(options)
|
126
131
|
|
127
|
-
|
128
|
-
|
129
|
-
# This cipher is confidentiality-only one, or AEAD one. To use a second
|
130
|
-
# cipher to add integrity, use +:intmode+ option.
|
131
|
-
# @param [String] iv IV to encipher SK payload content
|
132
|
-
# * CTR and GCM modes: +iv+ is 8-bytes long.
|
133
|
-
# @param [Hash] options
|
134
|
-
# @option options [Fixnum] :icv_length ICV length for captured packets,
|
135
|
-
# or read from PCapNG files
|
136
|
-
# @option options [String] :salt salt value for CTR and GCM modes
|
137
|
-
# @option options [Fixnum] :pad_length set a padding length
|
138
|
-
# @option options [String] :padding set a padding. No check with
|
139
|
-
# +:pad_length+ is made. If +:pad_length+ is not set, +:padding+
|
140
|
-
# length is shortened to correct padding length
|
141
|
-
# @option options [OpenSSL::HMAC] :intmode integrity mode to use with a
|
142
|
-
# confidentiality-only cipher. Only HMAC are supported.
|
143
|
-
# @return [self]
|
144
|
-
def encrypt!(cipher, iv, options={})
|
145
|
-
opt = { salt: '' }.merge!(options)
|
132
|
+
set_crypto cipher, opt[:intmode]
|
133
|
+
compute_iv_for_encrypting iv, opt[:salt]
|
146
134
|
|
147
|
-
|
135
|
+
authenticate_if_needed iv
|
136
|
+
encrypted_msg = encrypt_body(iv, opt)
|
137
|
+
encrypted_msg << generate_auth_tag(opt) if authenticated?
|
138
|
+
self[:content].read(iv + encrypted_msg)
|
148
139
|
|
149
|
-
|
150
|
-
|
151
|
-
cipher.iv = real_iv
|
140
|
+
# Remove plain payloads
|
141
|
+
self[:body] = BinStruct::String.new
|
152
142
|
|
153
|
-
|
143
|
+
remove_enciphered_packets
|
144
|
+
self.calc_length
|
145
|
+
self
|
146
|
+
end
|
154
147
|
|
155
|
-
|
156
|
-
pad_length = opt[:pad_length]
|
157
|
-
padding = force_binary(opt[:padding] || ([0] * pad_length).pack('C*'))
|
158
|
-
else
|
159
|
-
pad_length = cipher.block_size
|
160
|
-
pad_length = 16 if cipher.block_size == 1 # Some AES mode returns 1...
|
161
|
-
pad_length -= (self[:body].sz + iv.size + 1) % cipher.block_size
|
162
|
-
pad_length = 0 if pad_length == 16
|
163
|
-
padding = force_binary(opt[:padding] || ([0] * pad_length).pack('C*'))
|
164
|
-
padding = padding[0, pad_length]
|
165
|
-
end
|
166
|
-
msg = self[:body].to_s + padding + PacketGen::Types::Int8.new(pad_length).to_s
|
167
|
-
encrypted_msg = encipher(msg)
|
168
|
-
cipher.final # message is already padded. No need for mode padding
|
148
|
+
private
|
169
149
|
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
150
|
+
def authenticate_if_needed(iv, icv=nil) # rubocop:disable Naming/MethodParameterName
|
151
|
+
if @conf.authenticated?
|
152
|
+
@conf.auth_tag = icv if icv
|
153
|
+
@conf.auth_data = get_ad
|
154
|
+
elsif @intg
|
155
|
+
@intg.reset
|
156
|
+
@intg.update get_ad
|
157
|
+
@intg.update iv
|
158
|
+
@icv = icv
|
159
|
+
else
|
160
|
+
@icv = nil
|
161
|
+
end
|
162
|
+
end
|
179
163
|
|
180
|
-
|
181
|
-
|
164
|
+
def encrypt_body(iv, opt) # rubocop:disable Naming/MethodParameterName
|
165
|
+
padding, pad_length = compute_padding(iv, opt)
|
166
|
+
msg = self[:body].to_s + padding.b + BinStruct::Int8.new(value: pad_length).to_s
|
167
|
+
encrypted_msg = encipher(msg)
|
168
|
+
@conf.final # message is already padded. No need for mode padding
|
169
|
+
encrypted_msg
|
170
|
+
end
|
182
171
|
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
172
|
+
def compute_padding(iv, opt) # rubocop:disable Naming/MethodParameterName
|
173
|
+
if opt[:pad_length]
|
174
|
+
pad_length = opt[:pad_length]
|
175
|
+
padding = opt[:padding] || ([0] * pad_length).pack('C*')
|
176
|
+
else
|
177
|
+
pad_length = compute_pad_length(iv)
|
178
|
+
padding = opt[:padding] || ([0] * pad_length).pack('C*')
|
179
|
+
padding = padding[0, pad_length]
|
180
|
+
end
|
181
|
+
[padding, pad_length]
|
182
|
+
end
|
190
183
|
|
191
|
-
|
192
|
-
|
184
|
+
def compute_pad_length(iv) # rubocop:disable Naming/MethodParameterName
|
185
|
+
pad_length = @conf.block_size
|
186
|
+
pad_length = 16 if @conf.block_size == 1 # Some AES mode returns 1...
|
187
|
+
pad_length -= (self[:body].sz + iv.size + 1) % @conf.block_size
|
188
|
+
pad_length = 0 if pad_length == 16
|
189
|
+
pad_length
|
190
|
+
end
|
191
|
+
|
192
|
+
def generate_auth_tag(opt)
|
193
|
+
@icv_length = opt[:icv_length] if opt[:icv_length]
|
194
|
+
if @conf.authenticated?
|
195
|
+
@conf.auth_tag[0, @icv_length]
|
196
|
+
else
|
197
|
+
@intg.digest[0, @icv_length]
|
193
198
|
end
|
199
|
+
end
|
194
200
|
|
195
|
-
|
201
|
+
def remove_enciphered_packets
|
202
|
+
id = header_id(self)
|
203
|
+
return if id >= packet.headers.size - 1
|
196
204
|
|
197
|
-
|
198
|
-
|
199
|
-
@conf.auth_tag = icv if icv
|
200
|
-
@conf.auth_data = get_ad
|
201
|
-
elsif @intg
|
202
|
-
@intg.reset
|
203
|
-
@intg.update get_ad
|
204
|
-
@intg.update iv
|
205
|
-
@icv = icv
|
206
|
-
else
|
207
|
-
@icv = nil
|
208
|
-
end
|
205
|
+
(packet.headers.size - 1).downto(id + 1) do |index|
|
206
|
+
packet.headers.delete_at index
|
209
207
|
end
|
208
|
+
end
|
210
209
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
end
|
222
|
-
str << self.to_s[0, SK.new.sz]
|
210
|
+
# From RFC 7206, §5.1: The associated data MUST consist of the partial
|
211
|
+
# contents of the IKEv2 message, starting from the first octet of the
|
212
|
+
# Fixed IKE Plugin through the last octet of the Payload Plugin of the
|
213
|
+
# Encrypted Payload (i.e., the fourth octet of the Encrypted Payload).
|
214
|
+
def get_ad # rubocop:disable Naming/AccessorMethodName
|
215
|
+
str = packet.ike.to_s[0, IKE.new.sz]
|
216
|
+
current_payload = packet.ike[:body]
|
217
|
+
until current_payload.is_a? SK
|
218
|
+
str << current_payload.to_s
|
219
|
+
current_payload = current_payload[:body]
|
223
220
|
end
|
221
|
+
str << self.to_s[0, SK.new.sz]
|
222
|
+
end
|
224
223
|
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
self[:content].read ''
|
224
|
+
def private_decrypt(options)
|
225
|
+
plain_msg = decipher(content.to_s)
|
226
|
+
# Remove cipher text
|
227
|
+
self[:content].read ''
|
230
228
|
|
231
|
-
|
232
|
-
|
233
|
-
return false unless authenticate!
|
234
|
-
end
|
229
|
+
# check authentication tag
|
230
|
+
return false if authenticated? && !authenticate!
|
235
231
|
|
236
|
-
|
237
|
-
|
238
|
-
payloads
|
232
|
+
payloads = remove_padding(plain_msg)
|
233
|
+
if options[:parse]
|
234
|
+
parse_ike_payloads(payloads)
|
235
|
+
else
|
236
|
+
self[:body].read payloads
|
237
|
+
end
|
239
238
|
|
240
|
-
|
241
|
-
|
242
|
-
klass = IKE.constants.select do |c|
|
243
|
-
cst = IKE.const_get(c)
|
244
|
-
cst.is_a?(Class) && (cst < Payload) && (cst::PAYLOAD_TYPE == self.next)
|
245
|
-
end
|
246
|
-
klass = klass.nil? ? Payload : IKE.const_get(klass.first)
|
247
|
-
firsth = klass.protocol_name
|
248
|
-
pkt = Packet.parse(payloads, first_header: firsth)
|
249
|
-
packet.encapsulate(pkt, parsing: true) unless pkt.nil?
|
250
|
-
else
|
251
|
-
self[:body].read payloads
|
252
|
-
end
|
239
|
+
true
|
240
|
+
end
|
253
241
|
|
254
|
-
|
242
|
+
def remove_padding(msg)
|
243
|
+
pad_len = BinStruct::Int8.new.read(msg[-1]).to_i
|
244
|
+
msg[0, msg.size - 1 - pad_len]
|
245
|
+
end
|
246
|
+
|
247
|
+
def parse_ike_payloads(payloads)
|
248
|
+
klass = IKE.constants.select do |c|
|
249
|
+
cst = IKE.const_get(c)
|
250
|
+
cst.is_a?(Class) && (cst < Payload) && (self.next == cst::PAYLOAD_TYPE)
|
255
251
|
end
|
252
|
+
klass = klass.nil? ? Payload : IKE.const_get(klass.first)
|
253
|
+
firsth = klass.protocol_name
|
254
|
+
pkt = PacketGen::Packet.parse(payloads, first_header: firsth)
|
255
|
+
packet.encapsulate(pkt, parsing: true) unless pkt.nil?
|
256
256
|
end
|
257
257
|
end
|
258
|
-
|
259
|
-
Header.add_class IKE::SK
|
260
258
|
end
|
259
|
+
|
260
|
+
PacketGen::Header.add_class IKE::SK
|
261
261
|
end
|