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,163 +1,176 @@
|
|
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 Authentication payloads.
|
12
|
+
#
|
13
|
+
# A AUTH payload consists of the IKE generic payload Plugin (see {Payload})
|
14
|
+
# and some specific fields:
|
15
|
+
# 1 2 3
|
16
|
+
# 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
|
17
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
18
|
+
# | Next Payload |C| RESERVED | Payload Length |
|
19
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
20
|
+
# | Auth Method | RESERVED |
|
21
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
22
|
+
# | |
|
23
|
+
# ~ Authentication Data ~
|
24
|
+
# | |
|
25
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
26
|
+
# These specific fields are:
|
27
|
+
# * {#type} (ID type),
|
28
|
+
# * {#reserved},
|
29
|
+
# * and {#content} (Identification Data).
|
30
|
+
#
|
31
|
+
# == Create a KE payload
|
32
|
+
# # create a IKE packet with a Auth payload
|
33
|
+
# pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::Auth', auth_method: 'SHARED_KEY')
|
34
|
+
# pkt.calc_length
|
35
|
+
# @author Sylvain Daubert
|
36
|
+
class Auth < Payload
|
37
|
+
# Payload type number
|
38
|
+
PAYLOAD_TYPE = 39
|
39
|
+
|
40
|
+
# Authentication methods
|
41
|
+
METHODS = {
|
42
|
+
'RSA_SIGNATURE' => 1,
|
43
|
+
'SHARED_KEY' => 2,
|
44
|
+
'DSA_SIGNATURE' => 3,
|
45
|
+
'ECDSA256' => 9,
|
46
|
+
'ECDSA384' => 10,
|
47
|
+
'ECDSA512' => 11,
|
48
|
+
'PASSWORD' => 12,
|
49
|
+
'NULL' => 13,
|
50
|
+
'DIGITAL_SIGNATURE' => 14
|
51
|
+
}.freeze
|
8
52
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
|
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
|
-
# | Auth Method | RESERVED |
|
22
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
23
|
-
# | |
|
24
|
-
# ~ Authentication Data ~
|
25
|
-
# | |
|
26
|
-
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
27
|
-
# These specific fields are:
|
28
|
-
# * {#type} (ID type),
|
29
|
-
# * {#reserved},
|
30
|
-
# * and {#content} (Identification Data).
|
31
|
-
#
|
32
|
-
# == Create a KE payload
|
33
|
-
# # create a IKE packet with a Auth payload
|
34
|
-
# pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::Auth', auth_method: 'SHARED_KEY')
|
35
|
-
# pkt.calc_length
|
36
|
-
# @author Sylvain Daubert
|
37
|
-
class Auth < Payload
|
38
|
-
# Payload type number
|
39
|
-
PAYLOAD_TYPE = 39
|
53
|
+
# @attribute [r] auth_method
|
54
|
+
# 8-bit Auth Method
|
55
|
+
# @return [Integer]
|
56
|
+
define_attr_before :content, :auth_method, BinStruct::Int8Enum, enum: METHODS
|
57
|
+
# @attribute reserved
|
58
|
+
# 24-bit reserved field
|
59
|
+
# @return [Integer]
|
60
|
+
define_attr_before :content, :reserved, BinStruct::Int24
|
40
61
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
62
|
+
# Check authentication (see RFC 7296 §2.15)
|
63
|
+
# @param [Packet] init_msg first IKE message sent by peer
|
64
|
+
# @param [String] nonce my nonce, sent in first message
|
65
|
+
# @param [String] sk_p secret key used to compute prf(SK_px, IDx')
|
66
|
+
# @param [Integer] prf PRF type to use (see {Transform}+::PRF_*+ constants)
|
67
|
+
# @param [String] shared_secret shared secret to use as PSK (shared secret
|
68
|
+
# method only)
|
69
|
+
# @param [OpenSSL::X509::Certificate] cert certificate to check AUTH signature,
|
70
|
+
# if not embedded in IKE message
|
71
|
+
# @return [Boolean]
|
72
|
+
# @note For now, only NULL, SHARED_KEY and RSA, DSA and ECDSA signatures are
|
73
|
+
# supported.
|
74
|
+
# @note For certificates, only check AUTH authenticity with given (or guessed
|
75
|
+
# from packet) certificate, but certificate chain is not verified.
|
76
|
+
def check?(init_msg: nil, nonce: '', sk_p: '', prf: 1, shared_secret: '', # rubocop:disable Metrics/ParameterLists
|
77
|
+
cert: nil)
|
78
|
+
raise TypeError, 'init_msg should be a Packet' unless init_msg.is_a?(PacketGen::Packet)
|
52
79
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
80
|
+
signed_octets = build_signed_octets(init_msg, nonce, sk_p, prf)
|
81
|
+
case auth_method
|
82
|
+
when METHODS['SHARED_KEY']
|
83
|
+
check_shared_key?(shared_secret, signed_octets)
|
84
|
+
when METHODS['RSA_SIGNATURE'], METHODS['ECDSA256'], METHODS['ECDSA384'],
|
85
|
+
METHODS['ECDSA512']
|
86
|
+
check_signature?(cert, signed_octets)
|
87
|
+
when METHOD_NULL
|
88
|
+
true
|
89
|
+
else
|
90
|
+
raise NotImplementedError, "unsupported auth method #{human_auth_method}"
|
91
|
+
end
|
92
|
+
end
|
61
93
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
# @param [String] shared_secret shared secret to use as PSK (shared secret
|
68
|
-
# method only)
|
69
|
-
# @param [OpenSSL::X509::Certificate] cert certificate to check AUTH signature,
|
70
|
-
# if not embedded in IKE message
|
71
|
-
# @return [Boolean]
|
72
|
-
# @note For now, only NULL, SHARED_KEY and RSA, DSA and ECDSA signatures are
|
73
|
-
# supported.
|
74
|
-
# @note For certificates, only check AUTH authenticity with given (or guessed
|
75
|
-
# from packet) certificate, but certificate chain is not verified.
|
76
|
-
def check?(init_msg: nil, nonce: '', sk_p: '', prf: 1, shared_secret: '',
|
77
|
-
cert: nil)
|
78
|
-
raise TypeError, 'init_msg should be a Packet' unless init_msg.is_a?(Packet)
|
79
|
-
signed_octets = init_msg.ike.to_s
|
80
|
-
signed_octets << nonce
|
81
|
-
id = packet.ike.flag_i? ? packet.ike_idi : packet.ike_idr
|
82
|
-
signed_octets << prf(prf, sk_p, id.to_s[4, id.length - 4])
|
94
|
+
# Get authentication method name
|
95
|
+
# @return [String]
|
96
|
+
def human_auth_method
|
97
|
+
self[:auth_method].to_human
|
98
|
+
end
|
83
99
|
|
84
|
-
|
85
|
-
when METHODS['SHARED_KEY']
|
86
|
-
auth = prf(prf(shared_secret, 'Key Pad for IKEv2'), signed_octets)
|
87
|
-
auth == content
|
88
|
-
when METHODS['RSA_SIGNATURE'], METHODS['ECDSA256'], METHODS['ECDSA384'],
|
89
|
-
METHODS['ECDSA512']
|
90
|
-
if packet.ike_cert
|
91
|
-
# FIXME: Expect a ENCODING_X509_CERT_SIG
|
92
|
-
# Others types not supported for now...
|
93
|
-
cert = OpenSSL::X509::Certificate.new(packet.ike_cert.content)
|
94
|
-
elsif cert.nil?
|
95
|
-
raise CryptoError, 'a certificate should be provided'
|
96
|
-
end
|
100
|
+
private
|
97
101
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
signature = format_signature(cert.public_key, content.to_s)
|
117
|
-
cert.public_key.verify(digest, signature, signed_octets)
|
118
|
-
when METHOD_NULL
|
119
|
-
true
|
120
|
-
else
|
121
|
-
raise NotImplementedError, "unsupported auth method #{human_auth_method}"
|
122
|
-
end
|
102
|
+
def build_signed_octets(init_msg, nonce, sk_p, prf)
|
103
|
+
signed_octets = init_msg.ike.to_s
|
104
|
+
signed_octets << nonce
|
105
|
+
id = packet.ike.flag_i? ? packet.ike_idi : packet.ike_idr
|
106
|
+
signed_octets << prf(prf, sk_p, id.to_s[4, id.length - 4])
|
107
|
+
end
|
108
|
+
|
109
|
+
def prf(type, key, msg)
|
110
|
+
case type
|
111
|
+
when Transform::PRF_HMAC_MD5, Transform::PRF_HMAC_SHA1,
|
112
|
+
Transform::PRF_HMAC_SHA2_256, Transform::PRF_HMAC_SHA2_384,
|
113
|
+
Transform::PRF_HMAC_SHA2_512
|
114
|
+
digestname = Transform.constants.grep(/PRF_/)
|
115
|
+
.detect { |c| Transform.const_get(c) == type }
|
116
|
+
.to_s.sub(/^PRF_HMAC_/, '').sub('2_', '')
|
117
|
+
digest = OpenSSL::Digest.const_get(digestname).new
|
118
|
+
else
|
119
|
+
raise NotImplementedError, 'for now, only HMAC-based PRF are supported'
|
123
120
|
end
|
121
|
+
hmac = OpenSSL::HMAC.new(key, digest)
|
122
|
+
hmac << msg
|
123
|
+
hmac.digest
|
124
|
+
end
|
125
|
+
|
126
|
+
def check_shared_key?(shared_secret, signed_octets)
|
127
|
+
auth = prf(prf(shared_secret, 'Key Pad for IKEv2'), signed_octets)
|
128
|
+
auth == content
|
129
|
+
end
|
124
130
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
131
|
+
def check_signature?(cert, signed_octets)
|
132
|
+
if packet.ike_cert
|
133
|
+
# FIXME: Expect a ENCODING_X509_CERT_SIG
|
134
|
+
# Others types not supported for now...
|
135
|
+
cert = OpenSSL::X509::Certificate.new(packet.ike_cert.content)
|
136
|
+
elsif cert.nil?
|
137
|
+
raise CryptoError, 'a certificate should be provided'
|
129
138
|
end
|
130
139
|
|
131
|
-
|
140
|
+
text = cert.to_text
|
141
|
+
digest = build_digest_object(text)
|
142
|
+
signature = format_signature(cert.public_key, content.to_s)
|
143
|
+
cert.public_key.verify(digest, signature, signed_octets)
|
144
|
+
end
|
132
145
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
raise NotImplementedError, 'for now, only HMAC-based PRF are supported'
|
146
|
+
def build_digest_object(text)
|
147
|
+
m = text.match(/Public Key Algorithm: ([a-zA-Z0-9-]+)/)
|
148
|
+
case m[1]
|
149
|
+
when 'id-ecPublicKey'
|
150
|
+
m2 = text.match(/Public-Key: \((\d+) bit\)/)
|
151
|
+
case m2[1]
|
152
|
+
when '256', '384'
|
153
|
+
OpenSSL::Digest.new("SHA#{m2[1]}")
|
154
|
+
when '521'
|
155
|
+
OpenSSL::Digest.new(SHA512)
|
144
156
|
end
|
145
|
-
|
146
|
-
|
147
|
-
|
157
|
+
when /sha([235]\d+)/
|
158
|
+
OpenSSL::Digest.new("SHA#{$1}")
|
159
|
+
when /sha1/, 'rsaEncryption'
|
160
|
+
OpenSSL::Digest.new('SHA1')
|
148
161
|
end
|
162
|
+
end
|
149
163
|
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
end
|
164
|
+
def format_signature(pkey, sig)
|
165
|
+
if pkey.is_a?(OpenSSL::PKey::EC)
|
166
|
+
# PKey::EC need a signature as a DER string representing a sequence of
|
167
|
+
# 2 integers: r and s
|
168
|
+
r = OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(sig[0, sig.size / 2], 2).to_i)
|
169
|
+
s = OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(sig[sig.size / 2,
|
170
|
+
sig.size / 2], 2).to_i)
|
171
|
+
OpenSSL::ASN1::Sequence.new([r, s]).to_der
|
172
|
+
else
|
173
|
+
sig
|
161
174
|
end
|
162
175
|
end
|
163
176
|
end
|
@@ -1,76 +1,75 @@
|
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
#
|
37
|
-
|
38
|
-
class Cert < Payload
|
39
|
-
# Payload type number
|
40
|
-
PAYLOAD_TYPE = 37
|
9
|
+
module PacketGen::Plugin
|
10
|
+
class IKE
|
11
|
+
# This class handles Certificate payloads.
|
12
|
+
#
|
13
|
+
# A Cert payload consists of the IKE generic payload Plugin (see {Payload})
|
14
|
+
# and some specific fields:
|
15
|
+
# 1 2 3
|
16
|
+
# 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
|
17
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
18
|
+
# | Next Payload |C| RESERVED | Payload Length |
|
19
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
20
|
+
# | Cert Encoding | |
|
21
|
+
# +-+-+-+-+-+-+-+-+ +
|
22
|
+
# | |
|
23
|
+
# ~ Certificate Data ~
|
24
|
+
# | |
|
25
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
26
|
+
# These specific fields are:
|
27
|
+
# * {#encoding},
|
28
|
+
# * and {#content} (Certificate Data).
|
29
|
+
#
|
30
|
+
# == Create a Cert payload
|
31
|
+
# # Create a IKE packet with a Cert payload
|
32
|
+
# pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::Cert', encoding: 'X509_CERT_SIG')
|
33
|
+
# certs = cert.to_der << ca_cert.to_der
|
34
|
+
# pkt.ike_cert.content.read certs
|
35
|
+
# pkt.calc_length
|
36
|
+
# @author Sylvain Daubert
|
37
|
+
class Cert < Payload
|
38
|
+
# Payload type number
|
39
|
+
PAYLOAD_TYPE = 37
|
41
40
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
41
|
+
# Certificate encoding
|
42
|
+
ENCODINGS = {
|
43
|
+
'PKCS7_WRAPPED_X509' => 1,
|
44
|
+
'PGP' => 2,
|
45
|
+
'DNS_SIGNED_KEY' => 3,
|
46
|
+
'X509_CERT_SIG' => 4,
|
47
|
+
'KERBEROS_TOKEN' => 6,
|
48
|
+
'X509_CRL' => 7,
|
49
|
+
'X509_ARL' => 8,
|
50
|
+
'SPKI_CERT' => 9,
|
51
|
+
'X509_CERT_ATTR' => 10,
|
52
|
+
'HASH_URL_X509_CERT' => 12,
|
53
|
+
'HASH_URL_X509_BUNDLE' => 13
|
54
|
+
}.freeze
|
55
55
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
56
|
+
# @attribute encoding
|
57
|
+
# 8-bit certificate encoding
|
58
|
+
# @return [Integer]
|
59
|
+
define_attr_before :content, :encoding, BinStruct::Int8Enum, enum: ENCODINGS
|
60
60
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
61
|
+
def initialize(options={})
|
62
|
+
super
|
63
|
+
self.encoding = options[:encoding] if options[:encoding]
|
64
|
+
end
|
65
65
|
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
end
|
66
|
+
# Get encoding name
|
67
|
+
# @return [String]
|
68
|
+
def human_encoding
|
69
|
+
self[:encoding].to_human
|
71
70
|
end
|
72
71
|
end
|
73
|
-
|
74
|
-
Header.add_class IKE::Cert
|
75
72
|
end
|
73
|
+
|
74
|
+
PacketGen::Header.add_class IKE::Cert
|
76
75
|
end
|
@@ -1,66 +1,65 @@
|
|
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
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
#
|
36
|
-
|
37
|
-
class CertReq < Cert
|
38
|
-
# Payload type number
|
39
|
-
PAYLOAD_TYPE = 38
|
9
|
+
module PacketGen::Plugin
|
10
|
+
class IKE
|
11
|
+
# This class handles Certificate Request payloads.
|
12
|
+
#
|
13
|
+
# A CertReq payload consists of the IKE generic payload Plugin (see {Payload})
|
14
|
+
# and some specific fields:
|
15
|
+
# 1 2 3
|
16
|
+
# 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
|
17
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
18
|
+
# | Next Payload |C| RESERVED | Payload Length |
|
19
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
20
|
+
# | Cert Encoding | |
|
21
|
+
# +-+-+-+-+-+-+-+-+ +
|
22
|
+
# | |
|
23
|
+
# ~ Certification Authority ~
|
24
|
+
# | |
|
25
|
+
# +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
26
|
+
# These specific fields are:
|
27
|
+
# * {#encoding},
|
28
|
+
# * and {#content} (Certification Authority).
|
29
|
+
#
|
30
|
+
# == Create a CertReq payload
|
31
|
+
# # Create a IKE packet with a CertReq payload
|
32
|
+
# pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::CertReq', encoding: 'X509_CERT_SIG')
|
33
|
+
# pkt.ike_certreq.content.read OpenSSL::Digest::SHA1.digest(ca_cert.to_der)
|
34
|
+
# pkt.calc_length
|
35
|
+
# @author Sylvain Daubert
|
36
|
+
class CertReq < Cert
|
37
|
+
# Payload type number
|
38
|
+
PAYLOAD_TYPE = 38
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
end
|
50
|
-
strs.map(&:inspect).join(',')
|
40
|
+
# Get list of 20-byte string (SHA-1 hashes)
|
41
|
+
# @return [String]
|
42
|
+
def human_content
|
43
|
+
strs = []
|
44
|
+
idx = 0
|
45
|
+
while idx < content.size
|
46
|
+
strs << content[idx, 20]
|
47
|
+
idx += 20
|
51
48
|
end
|
49
|
+
strs.map(&:inspect).join(',')
|
50
|
+
end
|
51
|
+
|
52
|
+
# @return [String]
|
53
|
+
def inspect
|
54
|
+
super do |attr|
|
55
|
+
next unless attr == :content
|
52
56
|
|
53
|
-
|
54
|
-
|
55
|
-
super do |attr|
|
56
|
-
next unless attr == :content
|
57
|
-
str = Inspect.shift_level
|
58
|
-
str << Inspect::FMT_ATTR % ['hashes', :content, human_content]
|
59
|
-
end
|
57
|
+
str = PacketGen::Inspect.shift_level
|
58
|
+
str << (PacketGen::Inspect::FMT_ATTR % ['hashes', :content, human_content])
|
60
59
|
end
|
61
60
|
end
|
62
61
|
end
|
63
|
-
|
64
|
-
Header.add_class IKE::CertReq
|
65
62
|
end
|
63
|
+
|
64
|
+
PacketGen::Header.add_class IKE::CertReq
|
66
65
|
end
|