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 +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
|