packetgen-plugin-ipsec 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,66 @@
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
+ # This class handles Certificate Request payloads.
13
+ #
14
+ # A CertReq payload consists of the IKE generic payload Plugin (see {Payload})
15
+ # and some specific fields:
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
+ # | Cert Encoding | |
22
+ # +-+-+-+-+-+-+-+-+ +
23
+ # | |
24
+ # ~ Certification Authority ~
25
+ # | |
26
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
+ # These specific fields are:
28
+ # * {#encoding},
29
+ # * and {#content} (Certification Authority).
30
+ #
31
+ # == Create a CertReq payload
32
+ # # Create a IKE packet with a CertReq payload
33
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::CertReq', encoding: 'X509_CERT_SIG')
34
+ # pkt.ike_certreq.content.read OpenSSL::Digest::SHA1.digest(ca_cert.to_der)
35
+ # pkt.calc_length
36
+ # @author Sylvain Daubert
37
+ class CertReq < Cert
38
+ # Payload type number
39
+ PAYLOAD_TYPE = 38
40
+
41
+ # Get list of 20-byte string (SHA-1 hashes)
42
+ # @return [String]
43
+ def human_content
44
+ strs = []
45
+ idx = 0
46
+ while idx < content.size
47
+ strs << content[idx, 20]
48
+ idx += 20
49
+ end
50
+ strs.map(&:inspect).join(',')
51
+ end
52
+
53
+ # @return [String]
54
+ def inspect
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
60
+ end
61
+ end
62
+ end
63
+
64
+ Header.add_class IKE::CertReq
65
+ end
66
+ end
@@ -0,0 +1,99 @@
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
+ # This class handles Identification - Initiator payloads, denoted IDi
13
+ # (see RFC 7296, §3.5).
14
+ #
15
+ # A ID payload consists of the IKE generic payload Plugin (see {Payload})
16
+ # and some specific fields:
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
+ # | ID Type | RESERVED |
23
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
24
+ # | |
25
+ # ~ Identification Data ~
26
+ # | |
27
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
28
+ # These specific fields are:
29
+ # * {#type} (ID type),
30
+ # * {#reserved},
31
+ # * and {#content} (Identification Data).
32
+ #
33
+ # == Create a IDi payload
34
+ # # Create a IKE packet with a IDi payload
35
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::IDi', type: 'FQDN')
36
+ # pkt.ike_idi.content.read 'fqdn.example.org'
37
+ # pkt.calc_length
38
+ # @author Sylvain Daubert
39
+ class IDi < Payload
40
+ # Payload type number
41
+ PAYLOAD_TYPE = 35
42
+
43
+ TYPES = {
44
+ 'IPV4_ADDR' => 1,
45
+ 'FQDN' => 2,
46
+ 'RFC822_ADDR' => 3,
47
+ 'IPV6_ADDR' => 5,
48
+ 'DER_ASN1_DN' => 9,
49
+ 'DER_ASN1_GN' => 10,
50
+ 'KEY_ID' => 11
51
+ }.freeze
52
+
53
+ # @attribute [r] type
54
+ # 8-bit ID type
55
+ # @return [Integer]
56
+ define_field_before :content, :type, PacketGen::Types::Int8Enum, enum: TYPES
57
+ # @attribute reserved
58
+ # 24-bit reserved field
59
+ # @return [Integer]
60
+ define_field_before :content, :reserved, PacketGen::Types::Int24
61
+
62
+ # Get ID type name
63
+ # @return [String]
64
+ def human_type
65
+ self[:type].to_human
66
+ end
67
+
68
+ # Get human readable content, from {#type}
69
+ # @return [String]
70
+ def human_content
71
+ case type
72
+ when TYPES['IPV4_ADDR'], TYPES['IPV4_ADDR']
73
+ IPAddr.ntop(content)
74
+ when TYPES['DER_ASN1_DN'], TYPES['DER_ASN1_GN']
75
+ OpenSSL::X509::Name.new(content).to_s
76
+ else
77
+ content.inspect
78
+ end
79
+ end
80
+ end
81
+
82
+ # This class handles Identification - Responder payloads, denoted IDr.
83
+ # See {IDi}.
84
+ #
85
+ # == Create a IDr payload
86
+ # # Create a IKE packet with a IDr payload
87
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::IDr', type: 'FQDN')
88
+ # pkt.ike_idr.content.read 'fqdn.example.org'
89
+ # @author Sylvain Daubert
90
+ class IDr < IDi
91
+ # Payload type number
92
+ PAYLOAD_TYPE = 36
93
+ end
94
+ end
95
+
96
+ Header.add_class IKE::IDi
97
+ Header.add_class IKE::IDr
98
+ end
99
+ end
@@ -0,0 +1,79 @@
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
+ # This class handles Key Exchange payloads, as defined in RFC 7296 §3.4
13
+ #
14
+ # A KE payload contains a generic payload Plugin (see {Payload}) and some
15
+ # specific fields:
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
+ # | Diffie-Hellman Group Num | RESERVED |
22
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23
+ # | |
24
+ # ~ Key Exchange Data ~
25
+ # | |
26
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
+ # These specific fields are:
28
+ # * {#group_num} (type {PacketGen::Types::Int16}),
29
+ # * {#reserved} (type {PacketGen::Types::Int16}),
30
+ # * and {#content} (type {PacketGen::Types::String}).
31
+ #
32
+ # == Create a KE payload
33
+ # # Create a IKE packet with a KE payload
34
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE')
35
+ # # group name is taken from Transform::DH_* constants
36
+ # pkt.add('IKE::KE', group: 'MODP4096')
37
+ # # group number may also be used
38
+ # pkt.ike_ke.group = 1
39
+ # pkt.calc_length
40
+ # @author Sylvain Daubert
41
+ class KE < Payload
42
+ # Payload type number
43
+ PAYLOAD_TYPE = 34
44
+
45
+ # @!attribute group_num
46
+ # 16-bit DH group number
47
+ # @return [Integer]
48
+ define_field_before :content, :group_num, PacketGen::Types::Int16
49
+ # @!attribute reserved
50
+ # 16-bit reserved field
51
+ # @return [Integer]
52
+ define_field_before :content, :reserved, PacketGen::Types::Int16, default: 0
53
+
54
+ def initialize(options={})
55
+ super
56
+ self.group = options[:group] if options[:group]
57
+ end
58
+
59
+ # Set group
60
+ # @param [Integer,String] value may be a String taken from
61
+ # {Transform}+::DH_*+ constant names.
62
+ # @return [Integer]
63
+ def group=(value)
64
+ group = case value
65
+ when Integer
66
+ value
67
+ else
68
+ cname = "DH_#{value}"
69
+ Transform.const_defined?(cname) ? Transform.const_get(cname) : nil
70
+ end
71
+ raise ArgumentError, "unknown group #{value.inspect}" unless group
72
+ self[:group_num].value = group
73
+ end
74
+ end
75
+ end
76
+
77
+ Header.add_class IKE::KE
78
+ end
79
+ end
@@ -0,0 +1,40 @@
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
+ # This class handles Nonce payloads, as defined in RFC 7296 §3.9.
13
+ #
14
+ # A Nonce payload contains a generic payload Plugin (see {Payload}) and
15
+ # data field (type {PacketGen::Types::String}):
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
+ # | |
22
+ # ~ Nonce Data ~
23
+ # | |
24
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
25
+ #
26
+ # == Create a Nonce payload
27
+ # # Create a IKE packet with a Nonce payload
28
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE')
29
+ # pkt.add('IKE::Nonce', data: "abcdefgh")
30
+ # pkt.calc_length
31
+ # @author Sylvain Daubert
32
+ class Nonce < Payload
33
+ # Payload type number
34
+ PAYLOAD_TYPE = 40
35
+ end
36
+ end
37
+
38
+ Header.add_class IKE::Nonce
39
+ end
40
+ end
@@ -0,0 +1,159 @@
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
+ # This class handles Notify payloads, as defined in RFC 7296 §3.10.
13
+ #
14
+ # A Notify payload contains a generic payload Plugin (see {Payload}) and
15
+ # some specific fields:
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
+ # | Protocol ID | SPI Size | Notify Message Type |
22
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
23
+ # | |
24
+ # ~ Security Parameter Index (SPI) ~
25
+ # | |
26
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
27
+ # | |
28
+ # ~ Notification Data ~
29
+ # | |
30
+ # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
31
+ # These specific fields are:
32
+ # * {#protocol} (type {PacketGen::Types::Int8}),
33
+ # * {#spi_size} (type {PacketGen::Types::Int8}),
34
+ # * {#message_type} (type {PacketGen::Types::Int16}),
35
+ # * {#spi} (type {PacketGen::Types::String}),
36
+ # * {#content} (type {PacketGen::Types::String}).
37
+ #
38
+ # == Create a Notify payload
39
+ # # Create a IKE packet with a Notify payload
40
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::Notify', protocol: 'IKE', type: 'INVALID_SYNTAX')
41
+ # pkt.ike_notify.spi # => ""
42
+ # pkt.ike_notify.content # => ""
43
+ # pkt.calc_length
44
+ # == Create a Notify payload with a SPI
45
+ # # Create a IKE packet with a Notify payload
46
+ # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::Notify', protocol: 'ESP', spi_size: 4, type: 'INVALID_SYNTAX')
47
+ # pkt.ike_notify.spi.read PacketGen::Types::Int32.new(0x12345678).to_s
48
+ # pkt.calc_length
49
+ # @author Sylvain Daubert
50
+ class Notify < Payload
51
+ # Payload type number
52
+ PAYLOAD_TYPE = 41
53
+
54
+ # Message types
55
+ TYPES = {
56
+ 'UNSUPPORTED_CRITICAL_PAYLOAD' => 1,
57
+ 'INVALID_IKE_SPI' => 4,
58
+ 'INVALID_MAJOR_VERSION' => 5,
59
+ 'INVALID_SYNTAX' => 7,
60
+ 'INVALID_MESSAGE_ID' => 9,
61
+ 'INVALID_SPI' => 11,
62
+ 'NO_PROPOSAL_CHOSEN' => 14,
63
+ 'INVALID_KE_PAYLOAD' => 17,
64
+ 'AUTHENTICATION_FAILED' => 24,
65
+ 'SINGLE_PAIR_REQUIRED' => 34,
66
+ 'NO_ADDITIONAL_SAS' => 35,
67
+ 'INTERNAL_ADDRESS_FAILURE' => 36,
68
+ 'FAILED_CP_REQUIRED' => 37,
69
+ 'TS_UNACCEPTABLE' => 38,
70
+ 'INVALID_SELECTORS' => 39,
71
+ 'TEMPORARY_FAILURE' => 43,
72
+ 'CHILD_SA_NOT_FOUND' => 44,
73
+ 'INITIAL_CONTACT' => 16_384,
74
+ 'SET_WINDOW_SIZE' => 16_385,
75
+ 'ADDITIONAL_TS_POSSIBLE' => 16_386,
76
+ 'IPCOMP_SUPPORTED' => 16_387,
77
+ 'NAT_DETECTION_SOURCE_IP' => 16_388,
78
+ 'NAT_DETECTION_DESTINATION_IP' => 16_389,
79
+ 'COOKIE' => 16_390,
80
+ 'USE_TRANSPORT_MODE' => 16_391,
81
+ 'HTTP_CERT_LOOKUP_SUPPORTED' => 16_392,
82
+ 'REKEY_SA' => 16_393,
83
+ 'ESP_TFC_PADDING_NOT_SUPPORTED' => 16_394,
84
+ 'NON_FIRST_FRAGMENTS_ALSO' => 16_395,
85
+ }.freeze
86
+
87
+ # @!attribute [r] protocol
88
+ # 8-bit protocol ID. If this notification concerns an existing
89
+ # SA whose SPI is given in the SPI field, this field indicates the
90
+ # type of that SA. For notifications concerning Child SAs, this
91
+ # field MUST contain either (2) to indicate AH or (3) to indicate
92
+ # ESP. Of the notifications defined in this document, the SPI is
93
+ # included only with INVALID_SELECTORS, REKEY_SA, and
94
+ # CHILD_SA_NOT_FOUND. If the SPI field is empty, this field MUST be
95
+ # sent as zero and MUST be ignored on receipt.
96
+ # @return [Integer]
97
+ define_field_before :content, :protocol, PacketGen::Types::Int8Enum, enum: PROTOCOLS
98
+ # @!attribute spi_size
99
+ # 8-bit SPI size. Give size of SPI field. Length in octets of the SPI as
100
+ # defined by the IPsec protocol ID or zero if no SPI is applicable. For a
101
+ # notification concerning the IKE SA, the SPI Size MUST be zero and
102
+ # the field must be empty.Set to 0 for an initial IKE SA
103
+ # negotiation, as SPI is obtained from outer Plugin.
104
+ # @return [Integer]
105
+ define_field_before :content, :spi_size, PacketGen::Types::Int8, default: 0
106
+ # @!attribute message_type
107
+ # 16-bit notify message type. Specifies the type of notification message.
108
+ # @return [Integer]
109
+ define_field_before :content, :message_type, PacketGen::Types::Int16Enum, enum: TYPES, default: 0
110
+ # @!attribute spi
111
+ # the sending entity's SPI. When the {#spi_size} field is zero,
112
+ # this field is not present in the proposal.
113
+ # @return [String]
114
+ define_field_before :content, :spi, PacketGen::Types::String,
115
+ builder: ->(h, t) { t.new(length_from: h[:spi_size]) }
116
+
117
+ alias type message_type
118
+
119
+ def initialize(options={})
120
+ if options[:spi] && options[:spi_size].nil?
121
+ options[:spi_size] = options[:spi].size
122
+ end
123
+ super
124
+ self.protocol = options[:protocol] if options[:protocol]
125
+ self.message_type = options[:message_type] if options[:message_type]
126
+ self.message_type = options[:type] if options[:type]
127
+ end
128
+
129
+ alias type= message_type=
130
+
131
+ # Get protocol name
132
+ # @return [String]
133
+ def human_protocol
134
+ self[:protocol].to_human
135
+ end
136
+
137
+ # Get message type name
138
+ # @return [String]
139
+ def human_message_type
140
+ self[:message_type].to_human
141
+ end
142
+ alias human_type human_message_type
143
+
144
+ # @return [String]
145
+ def inspect
146
+ super do |attr|
147
+ next unless attr == :protocol
148
+
149
+ str = Inspect.shift_level
150
+ str << Inspect::FMT_ATTR % [self[attr].class.to_s.sub(/.*::/, ''), attr,
151
+ human_protocol]
152
+ end
153
+ end
154
+ end
155
+ end
156
+
157
+ Header.add_class IKE::Notify
158
+ end
159
+ end