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 +4 -4
- data/.travis.yml +2 -2
- data/lib/packetgen/header.rb +1 -0
- data/lib/packetgen/header/eap/md5.rb +2 -0
- data/lib/packetgen/header/http/headers.rb +2 -2
- data/lib/packetgen/header/ike/sa.rb +2 -0
- data/lib/packetgen/header/ike/ts.rb +2 -0
- data/lib/packetgen/header/snmp.rb +22 -13
- data/lib/packetgen/header/tftp.rb +195 -0
- data/lib/packetgen/packet.rb +2 -2
- data/lib/packetgen/types/cstring.rb +0 -1
- data/lib/packetgen/types/string.rb +0 -1
- data/lib/packetgen/version.rb +1 -1
- data/packetgen.gemspec +1 -1
- metadata +7 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ed1c35530cd3ce2e62507e1a78c92fb5f764a49b
|
4
|
+
data.tar.gz: 77d4baf7bc094aa0b04d7e6035e9420233135008
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
-
|
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
|
-
-
|
16
|
+
- bundle exec rake
|
17
17
|
- rvmsudo bundle exec rake spec:sudo
|
data/lib/packetgen/header.rb
CHANGED
@@ -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)
|
@@ -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 <<
|
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
|
data/lib/packetgen/packet.rb
CHANGED
@@ -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
|
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)
|
data/lib/packetgen/version.rb
CHANGED
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.
|
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.
|
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
|
+
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.
|
47
|
+
version: '0.5'
|
48
48
|
- - ">="
|
49
49
|
- !ruby/object:Gem::Version
|
50
|
-
version: 0.
|
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.
|
57
|
+
version: '0.5'
|
58
58
|
- - ">="
|
59
59
|
- !ruby/object:Gem::Version
|
60
|
-
version: 0.
|
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
|