packetgen 2.1.2 → 2.1.3

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.
@@ -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