packetgen 2.1.2 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -40,70 +40,44 @@ module PacketGen
40
40
  # pkt = PacketGen.gen('IP').add('UDP').add('IKE').add('IKE::Notify', protocol: 'ESP', spi_size: 4, type: 'INVALID_SYNTAX')
41
41
  # pkt.ike_notify.spi.read PacketGen::Types::Int32.new(0x12345678).to_s
42
42
  # pkt.calc_length
43
- # @author Sylvain Daubert
43
+ # @author Sylvain Daubert
44
44
  class Notify < Payload
45
45
 
46
46
  # Payload type number
47
47
  PAYLOAD_TYPE = 41
48
48
 
49
- # Unsupported critical payload
50
- TYPE_UNSUPPORTED_CRITICAL_PAYLOAD = 1
51
- # Invalid IKE SPI
52
- TYPE_INVALID_IKE_SPI = 4
53
- # Invalid major version
54
- TYPE_INVALID_MAJOR_VERSION = 5
55
- # Invalid syntax
56
- TYPE_INVALID_SYNTAX = 7
57
- # Invalid message ID
58
- TYPE_INVALID_MESSAGE_ID = 9
59
- # Invalid SPI
60
- TYPE_INVALID_SPI = 11
61
- # No proposal chosen (none of the proposed crypto suites was acceptable)
62
- TYPE_NO_PROPOSAL_CHOSEN = 14
63
- # Invalid KE payload
64
- TYPE_INVALID_KE_PAYLOAD = 17
65
- # Authentication failed
66
- TYPE_AUTHENTICATION_FAILED = 24
67
- # Single pair required
68
- TYPE_SINGLE_PAIR_REQUIRED = 34
69
- # No additional SAs
70
- TYPE_NO_ADDITIONAL_SAS = 35
71
- # Internal address failture
72
- TYPE_INTERNAL_ADDRESS_FAILURE = 36
73
- # Failed CP required
74
- TYPE_FAILED_CP_REQUIRED = 37
75
- # traffic selectors unacceptable
76
- TYPE_TS_UNACCEPTABLE = 38
77
- # invalid selectors
78
- TYPE_INVALID_SELECTORS = 39
79
- # Temporary failure
80
- TYPE_TEMPORARY_FAILURE = 43
81
- # Child SA not found
82
- TYPE_CHILD_SA_NOT_FOUND = 44
83
- # Initial contact
84
- TYPE_INITIAL_CONTACT = 16384
85
- # Set window size
86
- TYPE_SET_WINDOW_SIZE = 16385
87
- # Additional traffic selector possible
88
- TYPE_ADDITIONAL_TS_POSSIBLE = 16386
89
- # IPcomp supported
90
- TYPE_IPCOMP_SUPPORTED = 16387
91
- # NAT detection source IP
92
- TYPE_NAT_DETECTION_SOURCE_IP = 16388
93
- # NAT detection destination IP
94
- TYPE_NAT_DETECTION_DESTINATION_IP = 16389
95
- # Cookie
96
- TYPE_COOKIE = 16390
97
- # Use transport mode (tunnel mode is default)
98
- TYPE_USE_TRANSPORT_MODE = 16391
99
- # HTTP certificate look up supported
100
- TYPE_HTTP_CERT_LOOKUP_SUPPORTED = 16392
101
- # Rekey SA
102
- TYPE_REKEY_SA = 16393
103
- # ESP TFC paddin not supported
104
- TYPE_ESP_TFC_PADDING_NOT_SUPPORTED = 16394
105
- # Non-first fragment also
106
- TYPE_NON_FIRST_FRAGMENTS_ALSO = 16395
49
+ # Message types
50
+ TYPES = {
51
+ 'UNSUPPORTED_CRITICAL_PAYLOAD' => 1,
52
+ 'INVALID_IKE_SPI' => 4,
53
+ 'INVALID_MAJOR_VERSION' => 5,
54
+ 'INVALID_SYNTAX' => 7,
55
+ 'INVALID_MESSAGE_ID' => 9,
56
+ 'INVALID_SPI' => 11,
57
+ 'NO_PROPOSAL_CHOSEN' => 14,
58
+ 'INVALID_KE_PAYLOAD' => 17,
59
+ 'AUTHENTICATION_FAILED' => 24,
60
+ 'SINGLE_PAIR_REQUIRED' => 34,
61
+ 'NO_ADDITIONAL_SAS' => 35,
62
+ 'INTERNAL_ADDRESS_FAILURE' => 36,
63
+ 'FAILED_CP_REQUIRED' => 37,
64
+ 'TS_UNACCEPTABLE' => 38,
65
+ 'INVALID_SELECTORS' => 39,
66
+ 'TEMPORARY_FAILURE' => 43,
67
+ 'CHILD_SA_NOT_FOUND' => 44,
68
+ 'INITIAL_CONTACT' => 16384,
69
+ 'SET_WINDOW_SIZE' => 16385,
70
+ 'ADDITIONAL_TS_POSSIBLE' => 16386,
71
+ 'IPCOMP_SUPPORTED' => 16387,
72
+ 'NAT_DETECTION_SOURCE_IP' => 16388,
73
+ 'NAT_DETECTION_DESTINATION_IP' => 16389,
74
+ 'COOKIE' => 16390,
75
+ 'USE_TRANSPORT_MODE' => 16391,
76
+ 'HTTP_CERT_LOOKUP_SUPPORTED' => 16392,
77
+ 'REKEY_SA' => 16393,
78
+ 'ESP_TFC_PADDING_NOT_SUPPORTED' => 16394,
79
+ 'NON_FIRST_FRAGMENTS_ALSO' => 16395,
80
+ }.freeze
107
81
 
108
82
  # @!attribute [r] protocol
109
83
  # 8-bit protocol ID. If this notification concerns an existing
@@ -127,7 +101,7 @@ module PacketGen
127
101
  # @!attribute message_type
128
102
  # 16-bit notify message type. Specifies the type of notification message.
129
103
  # @return [Integer]
130
- define_field_before :content, :message_type, Types::Int16
104
+ define_field_before :content, :message_type, Types::Int16Enum, enum: TYPES, default: 0
131
105
  # @!attribute spi
132
106
  # the sending entity's SPI. When the {#spi_size} field is zero,
133
107
  # this field is not present in the proposal.
@@ -162,20 +136,6 @@ module PacketGen
162
136
  self[:protocol].value = proto
163
137
  end
164
138
 
165
- # Set message type
166
- # @param [Integer,String] value
167
- # @return [Integer]
168
- def message_type=(value)
169
- type = case value
170
- when Integer
171
- value
172
- else
173
- c = self.class.constants.grep(/TYPE_#{value}/).first
174
- c ? self.class.const_get(c) : nil
175
- end
176
- raise ArgumentError, "unknown message type #{value.inspect}" unless type
177
- self[:message_type].value = type
178
- end
179
139
  alias type= message_type=
180
140
 
181
141
  # Get protocol name
@@ -190,10 +150,7 @@ module PacketGen
190
150
  # Get message type name
191
151
  # @return [String]
192
152
  def human_message_type
193
- name = self.class.constants.grep(/TYPE_/).
194
- select { |c| self.class.const_get(c) == type }.
195
- first || "type #{type}"
196
- name.to_s.sub(/TYPE_/, '')
153
+ self[:message_type].to_human
197
154
  end
198
155
  alias human_type human_message_type
199
156
 
@@ -122,11 +122,13 @@ module PacketGen
122
122
  # @author Sylvain Daubert
123
123
  class Transform < Types::Fields
124
124
 
125
- TYPE_ENCR = 1
126
- TYPE_PRF = 2
127
- TYPE_INTG = 3
128
- TYPE_DH = 4
129
- TYPE_ESN = 5
125
+ TYPES = {
126
+ 'ENCR' => 1,
127
+ 'PRF' => 2,
128
+ 'INTG' => 3,
129
+ 'DH' => 4,
130
+ 'ESN' => 5
131
+ }.freeze
130
132
 
131
133
  ENCR_DES_IV64 = 1
132
134
  ENCR_DES = 2
@@ -215,7 +217,7 @@ module PacketGen
215
217
  # 8-bit transform type. The Transform Type is the cryptographic
216
218
  # algorithm type (i.e. encryption, PRF, integrity, etc.)
217
219
  # @return [Integer]
218
- define_field :type, Types::Int8
220
+ define_field :type, Types::Int8Enum, enum: TYPES
219
221
  # @!attribute rsv2
220
222
  # 8-bit reserved field
221
223
  # @return [Integer]
@@ -237,21 +239,6 @@ module PacketGen
237
239
  self.id = options[:id] if options[:id]
238
240
  end
239
241
 
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
242
  # Set transform ID
256
243
  # @param [Integer,String] value
257
244
  # @return [Integer]
@@ -295,10 +282,11 @@ module PacketGen
295
282
  # Get human-readable type
296
283
  # @return [String]
297
284
  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_/, '')
285
+ if self[:type].enum.has_value? self.type
286
+ self[:type].to_human
287
+ else
288
+ "type[#{self.type}]"
289
+ end
302
290
  end
303
291
 
304
292
  # Get human-readable ID
@@ -203,7 +203,8 @@ module PacketGen
203
203
  # +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
204
204
  # These specific fields are:
205
205
  # * {#num_ts},
206
- # * {#reserved},
206
+ # * {#rsv1},
207
+ # * {#rsv2},
207
208
  # * and {#traffic_selectors}.
208
209
  #
209
210
  # == Create a TSi payload
@@ -228,7 +229,7 @@ module PacketGen
228
229
  # First 8-bit RESERVED field
229
230
  # @return [Integer]
230
231
  define_field_before :body, :rsv1, Types::Int8
231
- # @!attribute rsv1
232
+ # @!attribute rsv2
232
233
  # Last 16-bit RESERVED field
233
234
  # @return [Integer]
234
235
  define_field_before :body, :rsv2, Types::Int16
@@ -276,7 +277,7 @@ module PacketGen
276
277
  end
277
278
  str
278
279
  end
279
- end
280
+ end
280
281
 
281
282
  class TSr < TSi
282
283
  # Payload type number
@@ -60,10 +60,12 @@ module PacketGen
60
60
  end
61
61
 
62
62
  # Format a ASN.1 attribute for +#inspect+.
63
- # 3 cases are handled:
64
- # * attribute value is a {Types::Int}: show value as integer and in
63
+ # 4 cases are handled:
64
+ # * attribute value is a =RANS1::Types::Enumerated+: show named value and
65
+ # its integer value as hexdecimal format,
66
+ # * attribute value is a +RASN1::Types::Integer+: show value as integer and in
65
67
  # hexdecimal format,
66
- # * attribute value responds to +#to_human+: call it,
68
+ # * attribute value is a +RASN1::Model+: only show its root type,
67
69
  # * else, +#to_s+ is used to format attribute value.
68
70
  # @param [Symbol] name attribute name
69
71
  # @param [RASN1::Types::Base,RASN1::Model] attr attribute
@@ -98,7 +100,7 @@ module PacketGen
98
100
  o_str = octets.map { |v| " %02x" % v}.join
99
101
  str << o_str
100
102
  str << ' ' * (3*16 - o_str.size) unless o_str.size >= 3*16
101
- str << ' ' << octets.map { |v| v < 128 && v > 13 ? v.chr : '.' }.join
103
+ str << ' ' << octets.map { |v| v < 128 && v > 31 ? v.chr : '.' }.join
102
104
  str << "\n"
103
105
  end
104
106
  end
@@ -99,7 +99,7 @@ module PacketGen
99
99
 
100
100
  # Read packets from +filename+. Mays read Pcap and Pcap-NG formats.
101
101
  #
102
- # For more control, see {PcapNG::File} or {PCAPRUB::Pcap}.
102
+ # For more control, see {PcapNG::File} or +PCAPRUB::Pcap+.
103
103
  # @param [String] filename PcapNG or Pcap file.
104
104
  # @return [Array<Packet>]
105
105
  # @author Sylvain Daubert
@@ -119,7 +119,7 @@ module PacketGen
119
119
  def to_s
120
120
  pad_field :data, :options
121
121
  recalc_block_len
122
- fields.map { |f| @fields[f].to_s }.join
122
+ super
123
123
  end
124
124
 
125
125
 
@@ -89,7 +89,7 @@ module PacketGen
89
89
  check_len_coherency
90
90
  self
91
91
  end
92
-
92
+
93
93
  # Add a xPB to this section
94
94
  # @param [EPB,SPB] xpb
95
95
  # @return [self]
@@ -137,7 +137,7 @@ module PacketGen
137
137
  def to_s
138
138
  pad_field :options
139
139
  recalc_block_len
140
- fields.map { |f| @fields[f].to_s }.join << @packets.map(&:to_s).join
140
+ super << @packets.map(&:to_s).join
141
141
  end
142
142
 
143
143
  end
@@ -154,7 +154,7 @@ module PacketGen
154
154
  end
155
155
  pad_field :options
156
156
  recalc_block_len
157
- fields.map { |f| @fields[f].to_s }.join + body
157
+ super + body
158
158
  end
159
159
 
160
160
 
@@ -91,7 +91,7 @@ module PacketGen
91
91
  def to_s
92
92
  pad_field :data
93
93
  recalc_block_len
94
- fields.map { |f| @fields[f].to_s }.join
94
+ super
95
95
  end
96
96
 
97
97
  end
@@ -54,7 +54,7 @@ module PacketGen
54
54
  self[:block_len].read io.read(4)
55
55
  self[:body].read io.read(self[:block_len].to_i - MIN_SIZE)
56
56
  self[:block_len2].read io.read(4)
57
-
57
+
58
58
  unless self[:block_len].to_i == self[:block_len2].to_i
59
59
  raise InvalidFileError, 'Incoherency in Header Block'
60
60
  end
@@ -67,7 +67,7 @@ module PacketGen
67
67
  def to_s
68
68
  pad_field :body
69
69
  recalc_block_len
70
- @fields.values.map(&:to_s).join
70
+ super
71
71
  end
72
72
 
73
73
  end
@@ -33,7 +33,7 @@ module PacketGen
33
33
  end
34
34
 
35
35
  # Get protocol name from its number
36
- # @param [Integer] number
36
+ # @param [Integer] num
37
37
  # @return [String,nil] return nil for unknown protocol numbers
38
38
  def self.getprotobynumber(num)
39
39
  @cache.key(num)
@@ -10,6 +10,7 @@ module PacketGen
10
10
  end
11
11
 
12
12
  require_relative 'types/int'
13
+ require_relative 'types/enum'
13
14
  require_relative 'types/string'
14
15
  require_relative 'types/int_string'
15
16
  require_relative 'types/fields'
@@ -0,0 +1,165 @@
1
+ # coding: utf-8
2
+ # This file is part of PacketGen
3
+ # See https://github.com/sdaubert/packetgen for more informations
4
+ # Copyright (C) 2032 Sylvain Daubert <sylvain.daubert@laposte.net>
5
+ # This program is published under MIT license.
6
+
7
+ module PacketGen
8
+ module Types
9
+
10
+ # @abstract Base enum class to handle binary integers with limited
11
+ # authorized values
12
+ # An {Enum} type is used to handle an {Int} field with limited
13
+ # and named values.
14
+ #
15
+ # == Simple example
16
+ # enum = Int8Enum.new(0, 'low' => 0, 'medium' => 1, 'high' => 2})
17
+ # In this example, +enum+ is a 8-bit field which may take one
18
+ # among three values: +low+, +medium+ or +high+:
19
+ # enum.value = 'high'
20
+ # enum.value # => 2
21
+ # enum.value = 1
22
+ # enum.value # => 1
23
+ # enum.to_human # => "medium"
24
+ # Setting an unknown value will raise an exception:
25
+ # enum.value = 4 # => raise!
26
+ # enum.value = 'unknown' # => raise!
27
+ # But {#read} will not raise when reading an outbound value. This
28
+ # to enable decoding (or forging) of bad packets.
29
+ # @since 2.1.3
30
+ # @author Sylvain Daubert
31
+ class Enum < Int
32
+
33
+ # @return [Hash]
34
+ attr_reader :enum
35
+
36
+ # @param [Hash] enum enumerated values. Default value is taken from
37
+ # first element unless given.
38
+ # @param [:little,:big,nil] endian
39
+ # @param [Integer,nil] width
40
+ # @param [Integer,nil] default default value
41
+ def initialize(enum, endian=nil, width=nil, default=nil)
42
+ default ||= enum[enum.keys.first]
43
+ super(nil, endian, width, default)
44
+ @enum = enum
45
+ end
46
+
47
+ # Setter for value attribute
48
+ # @param [Integer, String,nil] v value as an Integer or as a String
49
+ # from enumration
50
+ # @return [Integer]
51
+ def value=(v)
52
+ ival = case v
53
+ when NilClass
54
+ nil
55
+ when ::String
56
+ raise ArgumentError, "#{v.inspect} not in enumeration" unless @enum.has_key? v
57
+ @enum[v]
58
+ else
59
+ raise ArgumentError, "#{v.inspect} not in enumeration" unless @enum.has_value? v
60
+ v
61
+ end
62
+ @value = ival
63
+ end
64
+
65
+ # To handle human API: set value from a String
66
+ alias :from_human :value=
67
+
68
+ # Get human readable value (enum name)
69
+ # @return [String]
70
+ def to_human
71
+ @enum.key(to_i) || "<unknown:#{@value}>"
72
+ end
73
+ end
74
+
75
+ # Enumeration on one byte. See {Enum}.
76
+ # @author Sylvain Daubert
77
+ # @since 2.1.3
78
+ class Int8Enum < Enum
79
+ # @param [Integer] default
80
+ # @param [Hash] enum
81
+ def initialize(enum, default=nil)
82
+ super(enum, nil, 1, default)
83
+ @packstr = { nil => 'C' }
84
+ end
85
+ end
86
+
87
+ # Enumeration on 2-byte integer. See {Enum}.
88
+ # @author Sylvain Daubert
89
+ # @since 2.1.3
90
+ class Int16Enum < Enum
91
+ # @param [Hash] enum
92
+ # @param [:big, :little] endian
93
+ # @param [Integer,nil] default default value
94
+ def initialize(enum, endian=:big, default=nil)
95
+ super(enum, endian, 2, default)
96
+ @packstr = { big: 'n', little: 'v' }
97
+ end
98
+ end
99
+
100
+ # Enumeration on big endian 2-byte integer. See {Enum}.
101
+ # @author Sylvain Daubert
102
+ # @since 2.1.3
103
+ class Int16beEnum < Int16Enum
104
+ undef endian=
105
+
106
+ # @param [Hash] enum
107
+ # @param [Integer,nil] default default value
108
+ def initialize(enum, default=nil)
109
+ super(enum, :big, default)
110
+ end
111
+ end
112
+
113
+ # Enumeration on big endian 2-byte integer. See {Enum}.
114
+ # @author Sylvain Daubert
115
+ # @since 2.1.3
116
+ class Int16leEnum < Int16Enum
117
+ undef endian=
118
+
119
+ # @param [Hash] enum
120
+ # @param [Integer,nil] default default value
121
+ def initialize(enum, default=nil)
122
+ super(enum, :little, default)
123
+ end
124
+ end
125
+
126
+ # Enumeration on 4-byte integer. See {Enum}.
127
+ # @author Sylvain Daubert
128
+ # @since 2.1.3
129
+ class Int32Enum < Enum
130
+ # @param [Hash] enum
131
+ # @param [:big, :little] endian
132
+ # @param [Integer,nil] default default value
133
+ def initialize(enum, endian=:big, default=nil)
134
+ super(enum, endian, 4, default)
135
+ @packstr = { big: 'N', little: 'V' }
136
+ end
137
+ end
138
+
139
+ # Enumeration on big endian 4-byte integer. See {Enum}.
140
+ # @author Sylvain Daubert
141
+ # @since 2.1.3
142
+ class Int32beEnum < Int32Enum
143
+ undef endian=
144
+
145
+ # @param [Hash] enum
146
+ # @param [Integer,nil] default default value
147
+ def initialize(enum, default=nil)
148
+ super(enum, :big, default)
149
+ end
150
+ end
151
+
152
+ # Enumeration on big endian 4-byte integer. See {Enum}.
153
+ # @author Sylvain Daubert
154
+ # @since 2.1.3
155
+ class Int32leEnum < Int32Enum
156
+ undef endian=
157
+
158
+ # @param [Hash] enum
159
+ # @param [Integer,nil] default default value
160
+ def initialize(enum, default=nil)
161
+ super(enum, :little, default)
162
+ end
163
+ end
164
+ end
165
+ end