packetgen 2.2.0 → 2.3.0

Sign up to get free protection for your applications and to get access to all the features.
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