packetgen 2.1.2 → 2.1.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -9,6 +9,17 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # IEEE 802.11 control frame header
12
+ #
13
+ # This class make a {Dot11} header with {#type} set to +1+
14
+ # (control frame).
15
+ #
16
+ # A IEEE 802.11 control header consists of:
17
+ # * a {#frame_ctrl} ({Types::Int16}),
18
+ # * a {#id}/duration ({Types::Int16le}),
19
+ # * a {#mac1} ({Eth::MacAddr}).
20
+ # * sometimes a {#mac2} ({Eth::MacAddr}),
21
+ # * a {#body} (a {Types::String} or another {Base} class),
22
+ # * and a Frame check sequence ({#fcs}, of type {Types::Int32le}).
12
23
  # @author Sylvain Daubert
13
24
  class Control < Dot11
14
25
 
@@ -49,7 +60,6 @@ module PacketGen
49
60
  if @applicable_fields.include? :mac2
50
61
  @applicable_fields -= %i(mac2) unless SUBTYPES_WITH_MAC2.include? self.subtype
51
62
  elsif SUBTYPES_WITH_MAC2.include? self.subtype
52
- sz = self.sz
53
63
  @applicable_fields[3, 0] = :mac2
54
64
  end
55
65
  end
@@ -9,6 +9,20 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # IEEE 802.11 data frame header
12
+ #
13
+ # This class make a {Dot11} header with {#type} set to +2+
14
+ # (data frame).
15
+ #
16
+ # A IEEE 802.11 data header consists of:
17
+ # * a {#frame_ctrl} ({Types::Int16}),
18
+ # * a {#id}/duration ({Types::Int16le}),
19
+ # * a {#mac2} ({Eth::MacAddr}),
20
+ # * a {#mac3} ({Eth::MacAddr}),
21
+ # * a {#sequence_ctrl} ({Types::Int16}),
22
+ # * sometimes a {#mac4} ({Eth::MacAddr}),
23
+ # * sometimes a {#qos_ctrl} ({Types::Int16}),
24
+ # * a {#body} (a {Types::String} or another {Base} class),
25
+ # * and a Frame check sequence ({#fcs}, of type {Types::Int32le}).
12
26
  # @author Sylvain Daubert
13
27
  class Data < Dot11
14
28
 
@@ -9,6 +9,8 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # IEEE 802.11 information element
12
+ #
13
+ # An {Element} is a piece of data contained in a Dot11 management frame.
12
14
  # @author Sylvain Daubert
13
15
  class Element < Types::TLV
14
16
  # Known element types
@@ -9,6 +9,33 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # IEEE 802.11 management frame header
12
+ #
13
+ # This class make a {Dot11} header with {#type} set to +0+
14
+ # (management frame).
15
+ #
16
+ # A IEEE 802.11 management header consists of:
17
+ # * a {#frame_ctrl} ({Types::Int16}),
18
+ # * a {#id}/duration ({Types::Int16le}),
19
+ # * a {#mac1} ({Eth::MacAddr}).
20
+ # * a {#mac2} ({Eth::MacAddr}),
21
+ # * a {#mac3} ({Eth::MacAddr}),
22
+ # * a {#sequence_ctrl} ({Types::Int16}),
23
+ # * a {#body} (a {Types::String} or another {Base} class),
24
+ # * and a Frame check sequence ({#fcs}, of type {Types::Int32le}).
25
+ #
26
+ # Management frames should be constructed with more headers from
27
+ # {SubMngt} subclasses.
28
+ #
29
+ # By example, build a {DeAuth} frame:
30
+ # PacketGen.gen('Dot11::Management').add('Dot11::DeAuth')
31
+ #
32
+ # Some frames need to have {Element}. By example a {Beacon} frame:
33
+ # pkt = PacketGen.gen('Dot11::Management', mac1: broadcast, mac2: bssid, mac3: bssid).
34
+ # add('Dot11::Beacon')
35
+ # pkt.dot11_beacon.add_elements(type: 'SSID', value: ssid)
36
+ # pkt.dot11_beacon.add_elements(type: 'Rates', value: "\x82\x84\x8b\x96\x12\x24\x48\x6c")
37
+ # pkt.dot11_beacon.add_elements(type: 'DSset', value: "\x06")
38
+ # pkt.dot11_beacon.add_elements(type: 'TIM', value: "\x00\x01\x00\x00")
12
39
  # @author Sylvain Daubert
13
40
  class Management < Dot11
14
41
 
@@ -19,6 +46,22 @@ module PacketGen
19
46
  @applicable_fields -= %i(mac4 qos_ctrl ht_ctrl)
20
47
  define_applicable_fields
21
48
  end
49
+
50
+ # Add an {Element}
51
+ # @param [Integer,String] type element type
52
+ # @param [Object] value element value
53
+ # @return [self]
54
+ # @since 2.1.3
55
+ def add_element(type:, value:)
56
+ if self[:body].is_a? SubMngt
57
+ element = Element.new(type: type, value: value)
58
+ self[:body].elements << element
59
+ else
60
+ raise FormatError, 'Before adding an Element, you have to add a Dot11::SubMngt subclass instance'
61
+ end
62
+
63
+ self
64
+ end
22
65
  end
23
66
  end
24
67
  end
@@ -9,6 +9,12 @@ module PacketGen
9
9
  class Dot11
10
10
 
11
11
  # @abstract Base class for all subtype management frames
12
+ # Subclasses of this class are used to specialize {Management}. A
13
+ # +SubMngt+ class set +subtype+ field in Dot11 header and may add some
14
+ # fields.
15
+ #
16
+ # All SubMngt subclasses have ability to have {Element}. These elements
17
+ # may be accessed through {#elements}.
12
18
  # @author Sylvain Daubert
13
19
  class SubMngt < Base
14
20
  # @return [Array<Element>]
@@ -38,12 +44,23 @@ module PacketGen
38
44
  # @return [String]
39
45
  def inspect
40
46
  str = super
41
- str << Inspect.dashed_line('Dot11 Elements', level=3)
47
+ str << Inspect.dashed_line('Dot11 Elements', 3)
42
48
  @elements.each do |el|
43
49
  str << Inspect.shift_level(4) << el.to_human << "\n"
44
50
  end
45
51
  str
46
52
  end
53
+
54
+ # Add an {Element} to header
55
+ # @param [Integer,String] type element type
56
+ # @param [Object] value element value
57
+ # @return [self]
58
+ # @since 2.1.3
59
+ def add_element(type:, value:)
60
+ element = Element.new(type: type, value: value)
61
+ @elements << element
62
+ self
63
+ end
47
64
 
48
65
  private
49
66
 
@@ -59,6 +76,12 @@ module PacketGen
59
76
  end
60
77
 
61
78
  # IEEE 802.11 Association Request frame
79
+ #
80
+ # Specialize {Dot11::Management} with +subtype+ set to 0.
81
+ #
82
+ # Add fields:
83
+ # * {#cap} ({Types::Int16le}),
84
+ # * {#listen_interval} ({Types::Int16le}).
62
85
  # @author Sylvain Daubert
63
86
  class AssoReq < SubMngt
64
87
  # @!attribute cap
@@ -72,6 +95,13 @@ module PacketGen
72
95
  Management.bind_header AssoReq, op: :and, type: 0, subtype: 0
73
96
 
74
97
  # IEEE 802.11 Association Response frame
98
+ #
99
+ # Specialize {Dot11::Management} with +subtype+ set to 1.
100
+ #
101
+ # Add fields:
102
+ # * {#cap} ({Types::Int16le}),
103
+ # * {#status} ({Types::Int16le}),
104
+ # * {#aid} ({Types::Int16le}).
75
105
  # @author Sylvain Daubert
76
106
  class AssoResp < SubMngt
77
107
  # @!attribute cap
@@ -88,6 +118,13 @@ module PacketGen
88
118
  Management.bind_header AssoResp, op: :and, type: 0, subtype: 1
89
119
 
90
120
  # IEEE 802.11 ReAssociation Request frame
121
+ #
122
+ # Specialize {Dot11::Management} with +subtype+ set to 2.
123
+ #
124
+ # Add fields:
125
+ # * {#cap} ({Types::Int16le}),
126
+ # * {#listen_interval} ({Types::Int16le}),
127
+ # * {#current_ap} ({Eth::MacAddr}).
91
128
  # @author Sylvain Daubert
92
129
  class ReAssoReq < AssoReq
93
130
  # @!attribute current_ap
@@ -98,6 +135,13 @@ module PacketGen
98
135
  Management.bind_header ReAssoReq, op: :and, type: 0, subtype: 2
99
136
 
100
137
  # IEEE 802.11 ReAssociation Response frame
138
+ #
139
+ # Specialize {Dot11::Management} with +subtype+ set to 3.
140
+ #
141
+ # Add fields:
142
+ # * {#cap} ({Types::Int16le}),
143
+ # * {#status} ({Types::Int16le}),
144
+ # * {#aid} ({Types::Int16le}).
101
145
  # @author Sylvain Daubert
102
146
  class ReAssoResp < AssoResp
103
147
  end
@@ -105,6 +149,10 @@ module PacketGen
105
149
  Management.bind_header ReAssoResp, op: :and, type: 0, subtype: 3
106
150
 
107
151
  # IEEE 802.11 Probe Request frame
152
+ #
153
+ # Specialize {Dot11::Management} with +subtype+ set to 4.
154
+ #
155
+ # This class adds no field.
108
156
  # @author Sylvain Daubert
109
157
  class ProbeReq < SubMngt
110
158
  end
@@ -112,6 +160,13 @@ module PacketGen
112
160
  Management.bind_header ProbeReq, op: :and, type: 0, subtype: 4
113
161
 
114
162
  # IEEE 802.11 Probe Response frame
163
+ #
164
+ # Specialize {Dot11::Management} with +subtype+ set to 5.
165
+ #
166
+ # Add fields:
167
+ # * {#timestamp} ({Types::Int64le}),
168
+ # * {#beacon_interval} ({Types::Int16le}),
169
+ # * {#cap} ({Types::Int16le}).
115
170
  # @author Sylvain Daubert
116
171
  class ProbeResp < SubMngt
117
172
  # @!attribute timestamp
@@ -128,6 +183,13 @@ module PacketGen
128
183
  Management.bind_header ProbeResp, op: :and, type: 0, subtype: 5
129
184
 
130
185
  # IEEE 802.11 Beacon frame
186
+ #
187
+ # Specialize {Dot11::Management} with +subtype+ set to 8.
188
+ #
189
+ # Add fields:
190
+ # * {#timestamp} ({Types::Int64le}),
191
+ # * {#interval} ({Types::Int16le}),
192
+ # * {#cap} ({Types::Int16le}).
131
193
  # @author Sylvain Daubert
132
194
  class Beacon < SubMngt
133
195
  # @!attribute timestamp
@@ -144,12 +206,21 @@ module PacketGen
144
206
  Management.bind_header Beacon, op: :and, type: 0, subtype: 8
145
207
 
146
208
  # IEEE 802.11 ATIM frame
209
+ #
210
+ # Specialize {Dot11::Management} with +subtype+ set to 9.
211
+ #
212
+ # This class defines no field.
147
213
  # @author Sylvain Daubert
148
214
  class ATIM < SubMngt; end
149
215
  Header.add_class ATIM
150
216
  Management.bind_header ATIM, op: :and, type: 0, subtype: 9
151
217
 
152
218
  # IEEE 802.11 Disassociation frame
219
+ #
220
+ # Specialize {Dot11::Management} with +subtype+ set to 10.
221
+ #
222
+ # Add fields:
223
+ # * {#reason} ({Types::Int16le}).
153
224
  # @author Sylvain Daubert
154
225
  class Disas < SubMngt
155
226
  # @!attribute reason
@@ -160,6 +231,13 @@ module PacketGen
160
231
  Management.bind_header Disas, op: :and, type: 0, subtype: 10
161
232
 
162
233
  # IEEE 802.11 Authentication frame
234
+ #
235
+ # Specialize {Dot11::Management} with +subtype+ set to 11.
236
+ #
237
+ # Add fields:
238
+ # * {#algo} ({Types::Int16le}),
239
+ # * {#seqnum} ({Types::Int16le}),
240
+ # * {#status} ({Types::Int16le}).
163
241
  # @author Sylvain Daubert
164
242
  class Auth < SubMngt
165
243
  # @!attribute algo
@@ -176,6 +254,11 @@ module PacketGen
176
254
  Management.bind_header Auth, op: :and, type: 0, subtype: 11
177
255
 
178
256
  # IEEE 802.11 Deauthentication frame
257
+ #
258
+ # Specialize {Dot11::Management} with +subtype+ set to 12.
259
+ #
260
+ # Add fields:
261
+ # * {#reason} ({Types::Int16le}).
179
262
  # @author Sylvain Daubert
180
263
  class DeAuth < SubMngt
181
264
  # @!attribute reason
@@ -26,19 +26,19 @@ module PacketGen
26
26
 
27
27
  # IEEE 802.1X packet types
28
28
  TYPES = {
29
- 0 => 'EAP Packet',
30
- 1 => 'Start',
31
- 2 => 'Logoff',
32
- 3 => 'Key',
33
- 4 => 'Encap-ASF-Alert'
34
- }
29
+ 'EAP Packet' => 0,
30
+ 'Start' => 1,
31
+ 'Logoff' => 2,
32
+ 'Key' => 3,
33
+ 'Encap-ASF-Alert' => 4
34
+ }.freeze
35
35
 
36
36
  # @!attribute version
37
37
  # @return [Integer] 8-bit Protocol Version
38
38
  define_field :version, Types::Int8, default: 1
39
39
  # @!attribute type
40
40
  # @return [Integer] 8-bit Packet Type
41
- define_field :type, Types::Int8
41
+ define_field :type, Types::Int8Enum, enum: TYPES
42
42
  # @!attribute length
43
43
  # @return [Integer] 16-bit body length
44
44
  define_field :length, Types::Int16
@@ -46,29 +46,10 @@ module PacketGen
46
46
  # @return [Types::String,Header::Base]
47
47
  define_field :body, Types::String
48
48
 
49
- # @private
50
- alias old_type= type=
51
-
52
- # Set type attribute
53
- # @param [String,Integer] type
54
- # @return [Integer]
55
- def type=(type)
56
- case type
57
- when Integer
58
- self.old_type = type
59
- else
60
- v = TYPES.key(type.to_s)
61
- raise ArgumentError, "unknown type #{type}" if v.nil?
62
- self.old_type = v
63
- end
64
- end
65
-
66
49
  # Get human readable type
67
50
  # @return [String]
68
51
  def human_type
69
- v = TYPES[self.type]
70
- v = self.type if v.nil?
71
- v.to_s
52
+ self[:type].to_human
72
53
  end
73
54
  end
74
55
 
@@ -78,19 +78,21 @@ module PacketGen
78
78
  PROTO_AH = 2
79
79
  PROTO_ESP = 3
80
80
 
81
- TYPE_IKE_SA_INIT = 34
82
- TYPE_IKE_AUTH = 35
83
- TYPE_CREATE_CHILD_SA = 36
84
- TYPE_INFORMATIONAL = 37
81
+ EXCHANGE_TYPES = {
82
+ 'IKE_SA_INIT' => 34,
83
+ 'IKE_AUTH' => 35,
84
+ 'CREATE_CHILD_SA' => 36,
85
+ 'INFORMATIONAL' => 37
86
+ }.freeze
85
87
 
86
88
  # @!attribute init_spi
87
89
  # 64-bit initiator SPI
88
90
  # @return [Integer]
89
- define_field :init_spi, Types::Int64
91
+ define_field :init_spi, Types::Int64
90
92
  # @!attribute resp_spi
91
93
  # 64-bit responder SPI
92
94
  # @return [Integer]
93
- define_field :resp_spi, Types::Int64
95
+ define_field :resp_spi, Types::Int64
94
96
  # @!attribute next
95
97
  # 8-bit next payload type
96
98
  # @return [Integer]
@@ -102,7 +104,7 @@ module PacketGen
102
104
  # @!attribute [r] exchange_type
103
105
  # 8-bit exchange type
104
106
  # @return [Integer]
105
- define_field :exchange_type, Types::Int8
107
+ define_field :exchange_type, Types::Int8Enum, enum: EXCHANGE_TYPES
106
108
  # @!attribute flags
107
109
  # 8-bit flags
108
110
  # @return [Integer]
@@ -152,30 +154,13 @@ module PacketGen
152
154
  self.type = options[:exchange_type] if options[:exchange_type]
153
155
  end
154
156
 
155
- # Set exchange type
156
- # @param [Integer,String] value
157
- # @return [Integer]
158
- def exchange_type=(value)
159
- type = case value
160
- when Integer
161
- value
162
- else
163
- c = self.class.constants.grep(/TYPE_#{value}/).first
164
- c ? self.class.const_get(c) : nil
165
- end
166
- raise ArgumentError, "unknown exchange type #{value.inspect}" unless type
167
- self[:exchange_type].value = type
168
- end
169
157
  alias type exchange_type
170
158
  alias type= exchange_type=
171
159
 
172
160
  # Get exchange type name
173
161
  # @return [String
174
162
  def human_exchange_type
175
- name = self.class.constants.grep(/TYPE_/).
176
- select { |c| self.class.const_get(c) == type }.
177
- first || "type #{type}"
178
- name.to_s.sub(/TYPE_/, '')
163
+ self[:exchange_type].to_human
179
164
  end
180
165
  alias human_type human_exchange_type
181
166
 
@@ -39,50 +39,34 @@ module PacketGen
39
39
  # Payload type number
40
40
  PAYLOAD_TYPE = 37
41
41
 
42
- ENCODING_PKCS7_WRAPPED_X509 = 1
43
- ENCODING_PGP = 2
44
- ENCODING_DNS_SIGNED_KEY = 3
45
- ENCODING_X509_CERT_SIG = 4
46
- ENCODING_KERBEROS_TOKEN = 6
47
- ENCODING_X509_CRL = 7
48
- ENCODING_X509_ARL = 8
49
- ENCODING_SPKI_CERT = 9
50
- ENCODING_X509_CERT_ATTR = 10
51
- ENCODING_HASH_URL_X509_CERT = 12
52
- ENCODING_HASH_URL_X509_BUNDLE = 13
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
53
55
 
54
56
  # @attribute encoding
55
57
  # 8-bit certificate encoding
56
58
  # @return [Integer]
57
- define_field_before :content, :encoding, Types::Int8
59
+ define_field_before :content, :encoding, Types::Int8Enum, enum: ENCODINGS
58
60
 
59
61
  def initialize(options={})
60
62
  super
61
63
  self.encoding = options[:encoding] if options[:encoding]
62
64
  end
63
65
 
64
- # Set encoding
65
- # @param [Integer,String] value
66
- # @return [Integer]
67
- def encoding=(value)
68
- encoding = case value
69
- when Integer
70
- value
71
- else
72
- c = self.class.constants.grep(/ENCODING_#{value}/).first
73
- c ? self.class.const_get(c) : nil
74
- end
75
- raise ArgumentError, "unknown ID encoding #{value.inspect}" unless encoding
76
- self[:encoding].value = encoding
77
- end
78
-
79
66
  # Get encoding name
80
67
  # @return [String]
81
68
  def human_encoding
82
- name = self.class.constants.grep(/ENCODING_/).
83
- select { |c| self.class.const_get(c) == encoding }.
84
- first || "encoding #{encoding}"
85
- name.to_s.sub(/ENCODING_/, '')
69
+ self[:encoding].to_human
86
70
  end
87
71
 
88
72
  # @return [String]