packetgen 2.2.0 → 2.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 543fd7ef2efee43e0bf0d61c8a6520d178c869a2
4
- data.tar.gz: bcdd42ce36fc83c202abe8c2fd6f820a13a1b588
3
+ metadata.gz: ed1c35530cd3ce2e62507e1a78c92fb5f764a49b
4
+ data.tar.gz: 77d4baf7bc094aa0b04d7e6035e9420233135008
5
5
  SHA512:
6
- metadata.gz: 04c3d376f587f745972f534655f83e5fa12c30e039a58854411f89c57d769c235f9fa8faf1f6bfb37bf2deba639f45ea96a1eea8706dda77ea3c01a753aac502
7
- data.tar.gz: ed8d4002df84be1f0e1ddbcf19dd29bbf8290ed05606648421af3e7914b6288f9aacd8ec252bec6edd1357e5c42923f84400088c0fd2bc744c06e88c179d16b0
6
+ metadata.gz: dbe78e47c236179d9d866ce997778c1b2b65633b751d47d72948bcb0f7f56ccb8bf52fbdd1dd1292844d064493502a11392a7c4c9582552b452522d235bf22b7
7
+ data.tar.gz: 8c972a697a5bbd5c4654c973b1da378c8e733fb8c1887310b281acd0e36ef5de2e83259da0dfdca75a6da54f3c5af510d7cdc943af338aea839f661663ada014
data/.travis.yml CHANGED
@@ -8,10 +8,10 @@ rvm:
8
8
  install:
9
9
  - sudo apt-get update -qq
10
10
  - sudo apt-get install libpcap-dev -qq
11
- - bundler install --path vendor/bundle --jobs=3 --retry=3
11
+ - bundle install --path vendor/bundle --jobs=3 --retry=3
12
12
  before_script:
13
13
  - openssl version
14
14
  - ruby -ropenssl -e 'puts OpenSSL::VERSION'
15
15
  script:
16
- - bundler exec rake
16
+ - bundle exec rake
17
17
  - rvmsudo bundle exec rake spec:sudo
@@ -102,3 +102,4 @@ require_relative 'header/snmp'
102
102
  require_relative 'header/bootp'
103
103
  require_relative 'header/dhcp'
104
104
  require_relative 'header/http'
105
+ require_relative 'header/tftp'
@@ -13,6 +13,8 @@ module PacketGen
13
13
  # @since 2.1.4
14
14
  class MD5 < EAP
15
15
  delete_field :body
16
+ undef body
17
+
16
18
  # @!attribute value_size
17
19
  # @return [Integer] 8-bit value size
18
20
  define_field :value_size, Types::Int8
@@ -16,7 +16,7 @@ module PacketGen
16
16
  end
17
17
 
18
18
  # Populate object from a string or directly from a hash.
19
- # @param [String, Hash]
19
+ # @param [String, Hash] s_or_h
20
20
  # @return [self]
21
21
  def read(s_or_h)
22
22
  case s_or_h
@@ -51,7 +51,7 @@ module PacketGen
51
51
  end
52
52
 
53
53
  # Read human-readable data to populate header data.
54
- # @param [String, Hash]
54
+ # @param [String, Hash] data
55
55
  # @return [self]
56
56
  def from_human(data)
57
57
  read(data)
@@ -534,6 +534,8 @@ module PacketGen
534
534
  PAYLOAD_TYPE = 33
535
535
 
536
536
  delete_field :content
537
+ undef content
538
+
537
539
  # @!attribute proposals
538
540
  # Set of SA proposals
539
541
  # @return [SAProposals]
@@ -221,6 +221,8 @@ module PacketGen
221
221
  PAYLOAD_TYPE = 44
222
222
 
223
223
  delete_field :content
224
+ undef content
225
+
224
226
  # @!attribute num_ts
225
227
  # 8-bit Number of TSs
226
228
  # @return [Integer]
@@ -11,6 +11,8 @@ module PacketGen
11
11
  class DissectError < ParseError; end
12
12
 
13
13
  # Simple Network Management Protocol (SNMP)
14
+ #
15
+ # See https://github.com/sdaubert/packetgen/wiki/SNMP
14
16
  # @author Sylvain Daubert
15
17
  # @since 2.0.0
16
18
  class SNMP < ASN1Base
@@ -110,14 +112,9 @@ module PacketGen
110
112
  sequence :pdu,
111
113
  implicit: SNMP::PDU_GET, constructed: true,
112
114
  content: [integer(:id, value: 0),
113
- enumerated(:error, enum: ERRORS),
114
- integer(:error_index),
115
+ enumerated(:error, value: 0, enum: ERRORS),
116
+ integer(:error_index, value: 0),
115
117
  model(:varbindlist, VariableBindings)]
116
-
117
- # @return [String]
118
- def inspect
119
- Inspect.inspect_body(to_der, self.class)
120
- end
121
118
  end
122
119
 
123
120
  # Class to handle GetNextRequest PDU
@@ -195,11 +192,6 @@ module PacketGen
195
192
  integer(:non_repeaters),
196
193
  integer(:max_repetitions),
197
194
  model(:varbindlist, VariableBindings)]
198
-
199
- # @return [String]
200
- def inspect
201
- Inspect.inspect_body(to_der, self.class)
202
- end
203
195
  end
204
196
 
205
197
  # Class to handle InformRequest PDU
@@ -263,6 +255,16 @@ module PacketGen
263
255
  @elements[:data]
264
256
  end
265
257
 
258
+ # shortcut to PDU
259
+ # @return [GetRequest, Bulk, Trapv1, nil] return `nil` if no CHOICE was done
260
+ def pdu
261
+ if data.chosen.nil?
262
+ nil
263
+ else
264
+ data.root.chosen_value
265
+ end
266
+ end
267
+
266
268
  def inspect
267
269
  str = super
268
270
  str << Inspect.shift_level(2)
@@ -271,7 +273,14 @@ module PacketGen
271
273
  else
272
274
  data = self[:data]
273
275
  str << Inspect::FMT_ATTR % [data.type, :data, data.chosen_value.type]
274
- str << data.chosen_value.inspect
276
+ str << Inspect.dashed_line('ASN.1 content', 2)
277
+ str << data.chosen_value.inspect(1)
278
+ begin
279
+ str << Inspect.inspect_body(self[:message].to_der, 'ASN.1 DER')
280
+ rescue StandardError => ex
281
+ raise unless ex.message =~ /TAG.*not handled/
282
+ end
283
+ str
275
284
  end
276
285
  end
277
286
  end
@@ -0,0 +1,195 @@
1
+ # This file is part of PacketGen
2
+ # See https://github.com/sdaubert/packetgen for more informations
3
+ # Copyright (C) 2016 Sylvain Daubert <sylvain.daubert@laposte.net>
4
+ # This program is published under MIT license.
5
+
6
+ module PacketGen
7
+ module Header
8
+
9
+ # A TFTP (Trivial File Transfer Protocol,
10
+ # {https://tools.ietf.org/html/rfc1350 RFC 1350}) header consists of:
11
+ # * a {#opcode} ({Types::Int16Enum}),
12
+ # * and a body. Its content depends on opcode.
13
+ #
14
+ # Specialized subclasses exists to handle {TFTP::RRQ Read Request},
15
+ # {TFTP::WRQ Write Request}, {TFTP::DATA DATA}, {TFTP::ACK ACK} and
16
+ # {TFTP::ERROR ERROR} packets.
17
+ #
18
+ # == Create a TFTP header
19
+ # # standalone
20
+ # tftp = PacketGen::Header::TFTP.new
21
+ # # in a packet
22
+ # pkt = PacketGen.gen('IP').add('UDP').add('TFTP')
23
+ # # access to TFTP header
24
+ # pkt.tftp # => PacketGen::Header::TFTP
25
+ #
26
+ # == TFTP attributes
27
+ # tftp.opcode = 'RRQ'
28
+ # tftp.opcode = 1
29
+ # tftp.body.read 'this is a body'
30
+ #
31
+ # == TFTP parsing
32
+ # When parsing, only first packet (read or write request) should be decoded
33
+ # as TFTP packet, as others uses custom UDP ports.
34
+ #
35
+ # So, to decode subsequent TFTP packets, a method {#decode!} is provided
36
+ # for this purpose. This method takes a single array argument. This array
37
+ # should contain all subsequent TFTP packets (others packet types may also
38
+ # be included in this array: they won't be modified). +#decode!+ will modify
39
+ # array in-place by replacing UDP packets by TFTP ones (if decoded as TFTP
40
+ # packets):
41
+ # # packets is an array of packets: TFTP::RRQ, UDP (should be TFTP::DATA), UDP (not a TFTP packet) and UDP (TFTP::ACK)
42
+ # packets.map { |pkt| pkt.headers.last.class.to_s }.join(',') # => TFTP::RRQ,UDP,UDP,UDP
43
+ # # Here, decoding TFTP packets
44
+ # packets[0].tftp.decode!(packets[1..-1])
45
+ # packets.map { |pkt| pkt.headers.last.class.to_s }.join(',') # => TFTP::RRQ,TFTP::DATA,UDP,TFTP::ACK
46
+ # @author Sylvain Daubert
47
+ class TFTP < Base
48
+
49
+ # Known opcodes
50
+ OPCODES = {
51
+ 'RRQ' => 1,
52
+ 'WRQ' => 2,
53
+ 'DATA' => 3,
54
+ 'ACK' => 4,
55
+ 'Error' => 5
56
+ }
57
+
58
+ # @!attribute opcode
59
+ # 16-bit operation code
60
+ # @return [Integer]
61
+ define_field :opcode, Types::Int16Enum, enum: OPCODES
62
+
63
+ # @!attribute body
64
+ # @return [String]
65
+ define_field :body, Types::String
66
+
67
+ def initialize(options={})
68
+ type = protocol_name.sub(/^.*::/, '')
69
+ opcode = OPCODES[type]
70
+ if self.class != TFTP and !opcode.nil?
71
+ super({opcode: opcode}.merge(options))
72
+ else
73
+ super
74
+ end
75
+ end
76
+
77
+ # @private
78
+ alias old_read read
79
+
80
+ # Populate object from binary string
81
+ # @param [String] str
82
+ # @return [TFTP]
83
+ def read(str)
84
+ if self.instance_of? TFTP
85
+ super
86
+ if OPCODES.values.include? opcode
87
+ TFTP.const_get(human_opcode).new.read str
88
+ else
89
+ self
90
+ end
91
+ else
92
+ old_read str
93
+ end
94
+ end
95
+
96
+ # Decode subsequent TFTP packets to this one. Packets are modified
97
+ # in place in +ary+.
98
+ # @param [Array<Packet>] ary
99
+ # @return [void]
100
+ def decode!(ary)
101
+ client_tid = packet.udp.sport
102
+ server_tid = nil
103
+ ary.each do |pkt|
104
+ if server_tid.nil?
105
+ next unless pkt.is?('UDP') and pkt.udp.dport == client_tid
106
+ server_tid = pkt.udp.sport
107
+ else
108
+ next unless pkt.is?('UDP')
109
+ tids = [server_tid, client_tid]
110
+ ports = [pkt.udp.sport, pkt.udp.dport]
111
+ next unless (tids - ports).empty?
112
+ end
113
+ tftp = Packet.parse(pkt.body, first_header: 'TFTP')
114
+ udp_dport = pkt.udp.dport
115
+ pkt.encapsulate tftp
116
+ # need to fix it as #encapsulate force it to 69
117
+ pkt.udp.dport = udp_dport
118
+ end
119
+ end
120
+
121
+ # Get human readable opcode
122
+ # @return [String]
123
+ def human_opcode
124
+ self[:opcode].to_human
125
+ end
126
+
127
+ # Callback called when a TFTP header is added to a packet
128
+ # Here, add +#tftp+ method as a shortcut to existing
129
+ # +#tftp(rrq|wrq|data|ack|error)+.
130
+ # @param [Packet] packet
131
+ # @return [void]
132
+ def added_to_packet(packet)
133
+ unless packet.respond_to? :tftp
134
+ packet.instance_eval("def tftp(arg=nil); header(#{self.class}, arg); end")
135
+ end
136
+ end
137
+
138
+ # TFTP Read Request header
139
+ class RRQ < TFTP
140
+ delete_field :body
141
+ undef body
142
+
143
+ # @!attribute filename
144
+ # Filename to access
145
+ # @return [String]
146
+ define_field :filename, Types::CString
147
+
148
+ # @!attribute mode
149
+ # Mode used. Should be +netascii+, +octet+ or +mail+
150
+ # @return [String]
151
+ define_field :mode, Types::CString
152
+ end
153
+
154
+ # TFTP Write Request header
155
+ class WRQ < RRQ; end
156
+
157
+ # TFTP DATA header
158
+ class DATA < TFTP
159
+ # @!attribute block_num
160
+ # 16-bit block number
161
+ # @return [Integer]
162
+ define_field_before :body, :block_num, Types::Int16
163
+ end
164
+
165
+ # TFTP ACK header
166
+ class ACK < TFTP
167
+ delete_field :body
168
+ undef body
169
+
170
+ # @!attribute block_num
171
+ # 16-bit block number
172
+ # @return [Integer]
173
+ define_field :block_num, Types::Int16
174
+ end
175
+
176
+ # TFTP ERROR header
177
+ class ERROR < TFTP
178
+ delete_field :body
179
+ undef body
180
+
181
+ # @!attribute error_code
182
+ # 16-bit error code
183
+ # @return [Integer]
184
+ define_field :error_code, Types::Int16
185
+
186
+ # @!attribute error_msg
187
+ # Error message
188
+ # @return [String]
189
+ define_field :error_msg, Types::CString
190
+ alias error_message error_msg
191
+ end
192
+ end
193
+ UDP.bind_header TFTP, dport: 69
194
+ end
195
+ end
@@ -235,8 +235,8 @@ module PacketGen
235
235
  # Encapulate another packet in +self+
236
236
  # @param [Packet] other
237
237
  # @param [Boolean] parsing set to +true+ to not update last current header field
238
- # from binding with first other's one. Use only when current heade field as
239
- # its value set accordingly.
238
+ # from binding with first other's one. Use only when current header field
239
+ # has its value set accordingly.
240
240
  # @return [self] +self+ with new headers from +other+
241
241
  # @since 1.1.0
242
242
  def encapsulate(other, parsing: false)
@@ -11,7 +11,6 @@ module PacketGen
11
11
  # @author Sylvain Daubert
12
12
  class CString < ::String
13
13
 
14
- # @param [String] str
15
14
  # @param [Hash] options
16
15
  # @option options [Integer] :static_length set a static length for this string
17
16
  def initialize(options={})
@@ -12,7 +12,6 @@ module PacketGen
12
12
  # @author Sylvain Daubert
13
13
  class String < ::String
14
14
 
15
- # @param [String] str
16
15
  # @param [Hash] options
17
16
  # @option options [Types::Int,Proc] :length_from object or proc from which
18
17
  # takes length when reading
@@ -8,5 +8,5 @@
8
8
  # @author Sylvain Daubert
9
9
  module PacketGen
10
10
  # PacketGen version
11
- VERSION = '2.2.0'
11
+ VERSION = '2.3.0'
12
12
  end
data/packetgen.gemspec CHANGED
@@ -25,7 +25,7 @@ Gem::Specification.new do |spec|
25
25
 
26
26
  spec.add_dependency 'pcaprub', '~>0.12.4'
27
27
  spec.add_dependency 'network_interface'
28
- spec.add_dependency 'rasn1', '~>0.3', '>= 0.3.1'
28
+ spec.add_dependency 'rasn1', '~>0.5', '>= 0.6.0'
29
29
 
30
30
  spec.add_development_dependency 'bundler', '~> 1.7'
31
31
  spec.add_development_dependency 'rake', '~> 12.0'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: packetgen
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Sylvain Daubert
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-11-29 00:00:00.000000000 Z
11
+ date: 2017-12-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pcaprub
@@ -44,20 +44,20 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '0.3'
47
+ version: '0.5'
48
48
  - - ">="
49
49
  - !ruby/object:Gem::Version
50
- version: 0.3.1
50
+ version: 0.6.0
51
51
  type: :runtime
52
52
  prerelease: false
53
53
  version_requirements: !ruby/object:Gem::Requirement
54
54
  requirements:
55
55
  - - "~>"
56
56
  - !ruby/object:Gem::Version
57
- version: '0.3'
57
+ version: '0.5'
58
58
  - - ">="
59
59
  - !ruby/object:Gem::Version
60
- version: 0.3.1
60
+ version: 0.6.0
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: bundler
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -205,6 +205,7 @@ files:
205
205
  - lib/packetgen/header/tcp.rb
206
206
  - lib/packetgen/header/tcp/option.rb
207
207
  - lib/packetgen/header/tcp/options.rb
208
+ - lib/packetgen/header/tftp.rb
208
209
  - lib/packetgen/header/udp.rb
209
210
  - lib/packetgen/inspect.rb
210
211
  - lib/packetgen/packet.rb