rex-socket 0.1.24 → 0.1.29
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
- checksums.yaml.gz.sig +0 -0
- data.tar.gz.sig +1 -3
- data/.github/workflows/verify.yml +57 -0
- data/Gemfile +4 -0
- data/lib/rex/socket.rb +18 -23
- data/lib/rex/socket/range_walker.rb +167 -105
- data/lib/rex/socket/switch_board.rb +1 -1
- data/lib/rex/socket/version.rb +1 -1
- data/rex-socket.gemspec +4 -5
- metadata +29 -43
- metadata.gz.sig +4 -1
- data/.travis.yml +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4d113479436231734487199007f644118a5e448686dc84c62c32d2cf0d8a3610
|
|
4
|
+
data.tar.gz: 10c82f7d6ec3995321f87e0414f5cb27bd2b991764f051be0f2014473a53b255
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 5c6cec9b71223968043ea4b96ac78f750ba27ec1ca087b5deda2ee3717c76340f96e8d730f9e16594732213d2429265891a8dd1dc64b02dc3bd6b1f4adec634e
|
|
7
|
+
data.tar.gz: c21137181b5ef64f7599c5ceb27f233c10d48a198a9ec0c5bffbe64efb6f02024eab4e408a5de7585c1a46dbff864f087dbee3cf32bdcd3129ad518db225d779
|
checksums.yaml.gz.sig
CHANGED
|
Binary file
|
data.tar.gz.sig
CHANGED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
name: Verify
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- '*'
|
|
7
|
+
pull_request:
|
|
8
|
+
branches:
|
|
9
|
+
- '*'
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
test:
|
|
13
|
+
runs-on: ubuntu-16.04
|
|
14
|
+
timeout-minutes: 40
|
|
15
|
+
|
|
16
|
+
strategy:
|
|
17
|
+
fail-fast: true
|
|
18
|
+
matrix:
|
|
19
|
+
ruby:
|
|
20
|
+
- 2.5
|
|
21
|
+
- 2.6
|
|
22
|
+
- 2.7
|
|
23
|
+
- 3.0
|
|
24
|
+
test_cmd:
|
|
25
|
+
- bundle exec rspec
|
|
26
|
+
|
|
27
|
+
env:
|
|
28
|
+
RAILS_ENV: test
|
|
29
|
+
|
|
30
|
+
name: Ruby ${{ matrix.ruby }} - ${{ matrix.test_cmd }}
|
|
31
|
+
steps:
|
|
32
|
+
- name: Checkout code
|
|
33
|
+
uses: actions/checkout@v2
|
|
34
|
+
|
|
35
|
+
- uses: actions/setup-ruby@v1
|
|
36
|
+
with:
|
|
37
|
+
ruby-version: ${{ matrix.ruby }}
|
|
38
|
+
|
|
39
|
+
- name: Setup bundler
|
|
40
|
+
run: |
|
|
41
|
+
gem install bundler
|
|
42
|
+
- uses: actions/cache@v2
|
|
43
|
+
with:
|
|
44
|
+
path: vendor/bundle
|
|
45
|
+
key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
|
|
46
|
+
restore-keys: |
|
|
47
|
+
${{ runner.os }}-gems-
|
|
48
|
+
- name: Bundle install
|
|
49
|
+
run: |
|
|
50
|
+
bundle config path vendor/bundle
|
|
51
|
+
bundle install --jobs 4 --retry 3
|
|
52
|
+
- name: ${{ matrix.test_cmd }}
|
|
53
|
+
run: |
|
|
54
|
+
echo "${CMD}"
|
|
55
|
+
bash -c "${CMD}"
|
|
56
|
+
env:
|
|
57
|
+
CMD: ${{ matrix.test_cmd }}
|
data/Gemfile
CHANGED
data/lib/rex/socket.rb
CHANGED
|
@@ -14,6 +14,8 @@ module Rex
|
|
|
14
14
|
###
|
|
15
15
|
module Socket
|
|
16
16
|
|
|
17
|
+
LogSource = 'rex-socket'
|
|
18
|
+
|
|
17
19
|
module Comm
|
|
18
20
|
end
|
|
19
21
|
|
|
@@ -174,7 +176,7 @@ module Socket
|
|
|
174
176
|
end
|
|
175
177
|
|
|
176
178
|
#
|
|
177
|
-
# Wrapper for +::
|
|
179
|
+
# Wrapper for +::Addrinfo.getaddrinfo+ that takes special care to see if the
|
|
178
180
|
# supplied address is already an ASCII IP address. This is necessary to
|
|
179
181
|
# prevent blocking while waiting on a DNS reverse lookup when we already
|
|
180
182
|
# have what we need.
|
|
@@ -186,26 +188,14 @@ module Socket
|
|
|
186
188
|
return [hostname]
|
|
187
189
|
end
|
|
188
190
|
|
|
189
|
-
res = ::
|
|
190
|
-
return [] if not res
|
|
191
|
+
res = ::Addrinfo.getaddrinfo(hostname, 0, ::Socket::AF_UNSPEC, ::Socket::SOCK_STREAM)
|
|
191
192
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
res.shift # alias hostnames
|
|
196
|
-
res.shift # address_family
|
|
193
|
+
res.map! do |address_info|
|
|
194
|
+
address_info.ip_address
|
|
195
|
+
end
|
|
197
196
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
if res[0] =~ MATCH_IPV4 || res[0] =~ MATCH_IPV6
|
|
201
|
-
unless accept_ipv6
|
|
202
|
-
res.reject!{ |ascii| ascii =~ MATCH_IPV6 }
|
|
203
|
-
end
|
|
204
|
-
else
|
|
205
|
-
unless accept_ipv6
|
|
206
|
-
res.reject!{ |nbo| nbo.length != 4 }
|
|
207
|
-
end
|
|
208
|
-
res.map!{ |nbo| self.addr_ntoa(nbo) }
|
|
197
|
+
unless accept_ipv6
|
|
198
|
+
res.reject! { |ascii| ascii =~ MATCH_IPV6 }
|
|
209
199
|
end
|
|
210
200
|
|
|
211
201
|
res
|
|
@@ -217,7 +207,9 @@ module Socket
|
|
|
217
207
|
# not occur. This is done in order to prevent delays, such as would occur
|
|
218
208
|
# on Windows.
|
|
219
209
|
#
|
|
210
|
+
# @deprecated Please use {#getaddress}, {#resolv_nbo}, or similar instead.
|
|
220
211
|
def self.gethostbyname(host)
|
|
212
|
+
warn "NOTE: #{self}.#{__method__} is deprecated, use getaddress, resolve_nbo, or similar instead. It will be removed in the next Major version"
|
|
221
213
|
if is_ipv4?(host)
|
|
222
214
|
return [ host, [], 2, host.split('.').map{ |c| c.to_i }.pack("C4") ]
|
|
223
215
|
end
|
|
@@ -259,15 +251,18 @@ module Socket
|
|
|
259
251
|
#
|
|
260
252
|
# Resolves a host to raw network-byte order.
|
|
261
253
|
#
|
|
262
|
-
def self.resolv_nbo(host)
|
|
263
|
-
|
|
254
|
+
def self.resolv_nbo(host, accepts_ipv6 = true)
|
|
255
|
+
ip_address = Rex::Socket.getaddress(host, accepts_ipv6)
|
|
256
|
+
IPAddr.new(ip_address).hton
|
|
264
257
|
end
|
|
265
258
|
|
|
266
259
|
#
|
|
267
260
|
# Resolves a host to raw network-byte order.
|
|
268
261
|
#
|
|
269
262
|
def self.resolv_nbo_list(host)
|
|
270
|
-
Rex::Socket.getaddresses(host).map
|
|
263
|
+
Rex::Socket.getaddresses(host).map do |addresses|
|
|
264
|
+
IPAddr.new(addresses).hton
|
|
265
|
+
end
|
|
271
266
|
end
|
|
272
267
|
|
|
273
268
|
#
|
|
@@ -752,7 +747,7 @@ module Socket
|
|
|
752
747
|
peer_name = Socket.from_sockaddr(self.getpeername)
|
|
753
748
|
rescue ::Errno::EINVAL => e
|
|
754
749
|
# Ruby's getpeername method may call rb_sys_fail("getpeername(2)")
|
|
755
|
-
elog("#{e.message} (#{e.class})#{e.backtrace * "\n"}\n",
|
|
750
|
+
elog("#{e.message} (#{e.class})#{e.backtrace * "\n"}\n", LogSource, LEV_3)
|
|
756
751
|
end
|
|
757
752
|
|
|
758
753
|
return peer_name
|
|
@@ -23,6 +23,9 @@ module Socket
|
|
|
23
23
|
###
|
|
24
24
|
class RangeWalker
|
|
25
25
|
|
|
26
|
+
MATCH_IPV4_RANGE = /^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})-([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$/
|
|
27
|
+
private_constant :MATCH_IPV4_RANGE
|
|
28
|
+
|
|
26
29
|
# The total number of IPs within the range
|
|
27
30
|
#
|
|
28
31
|
# @return [Fixnum]
|
|
@@ -74,108 +77,37 @@ class RangeWalker
|
|
|
74
77
|
# @return [self]
|
|
75
78
|
# @return [false] if +parseme+ cannot be parsed
|
|
76
79
|
def parse(parseme)
|
|
77
|
-
return nil
|
|
80
|
+
return nil unless parseme
|
|
81
|
+
|
|
78
82
|
ranges = []
|
|
79
83
|
parseme.split(', ').map{ |a| a.split(' ') }.flatten.each do |arg|
|
|
80
|
-
opts = {}
|
|
81
84
|
|
|
82
85
|
# Handle IPv6 CIDR first
|
|
83
86
|
if arg.include?(':') && arg.include?('/')
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
ip_part, mask_part = arg.split("/")
|
|
87
|
-
return false unless (0..128).include? mask_part.to_i
|
|
87
|
+
next if (new_ranges = parse_ipv6_cidr(arg)).nil?
|
|
88
88
|
|
|
89
|
-
addr, scope_id = ip_part.split('%')
|
|
90
|
-
return false unless Rex::Socket.is_ipv6?(addr)
|
|
91
|
-
|
|
92
|
-
range = expand_cidr(addr + '/' + mask_part)
|
|
93
|
-
range.options[:scope_id] = scope_id if scope_id
|
|
94
|
-
ranges.push(range)
|
|
95
89
|
# Handle plain IPv6 next (support ranges, but not CIDR)
|
|
96
90
|
elsif arg.include?(':')
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
# Handle a single address
|
|
100
|
-
if addrs.length == 1
|
|
101
|
-
addr, scope_id = addrs[0].split('%')
|
|
102
|
-
opts[:scope_id] = scope_id if scope_id
|
|
103
|
-
opts[:ipv6] = true
|
|
104
|
-
|
|
105
|
-
return false unless Rex::Socket.is_ipv6?(addr)
|
|
106
|
-
addr = Rex::Socket.addr_atoi(addr)
|
|
107
|
-
ranges.push(Range.new(addr, addr, opts))
|
|
108
|
-
next
|
|
109
|
-
end
|
|
110
|
-
|
|
111
|
-
addr1, scope_id = addrs[0].split('%')
|
|
112
|
-
opts[:scope_id] = scope_id if scope_id
|
|
113
|
-
opts[:ipv6] = true
|
|
114
|
-
|
|
115
|
-
addr2, scope_id = addrs[1].split('%')
|
|
116
|
-
( opts[:scope_id] ||= scope_id ) if scope_id
|
|
117
|
-
|
|
118
|
-
# Both have to be IPv6 for this to work
|
|
119
|
-
return false unless (Rex::Socket.is_ipv6?(addr1) && Rex::Socket.is_ipv6?(addr2))
|
|
120
|
-
|
|
121
|
-
# Handle IPv6 ranges in the form of 2001::1-2001::10
|
|
122
|
-
addr1 = Rex::Socket.addr_atoi(addr1)
|
|
123
|
-
addr2 = Rex::Socket.addr_atoi(addr2)
|
|
124
|
-
|
|
125
|
-
ranges.push(Range.new(addr1, addr2, opts))
|
|
126
|
-
next
|
|
91
|
+
next if (new_ranges = parse_ipv6(arg)).nil?
|
|
127
92
|
|
|
128
93
|
# Handle IPv4 CIDR
|
|
129
94
|
elsif arg.include?("/")
|
|
130
|
-
|
|
131
|
-
return false if !valid_cidr_chars?(arg)
|
|
132
|
-
ip_part, mask_part = arg.split("/")
|
|
133
|
-
return false unless (0..32).include? mask_part.to_i
|
|
134
|
-
if ip_part =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
|
135
|
-
return false unless ip_part =~ Rex::Socket::MATCH_IPV4
|
|
136
|
-
end
|
|
137
|
-
begin
|
|
138
|
-
Rex::Socket.getaddress(ip_part) # This allows for "www.metasploit.com/24" which is fun.
|
|
139
|
-
rescue Resolv::ResolvError, ::SocketError, Errno::ENOENT
|
|
140
|
-
return false # Can't resolve the ip_part, so bail.
|
|
141
|
-
end
|
|
142
|
-
|
|
143
|
-
expanded = expand_cidr(arg)
|
|
144
|
-
if expanded
|
|
145
|
-
ranges.push(expanded)
|
|
146
|
-
else
|
|
147
|
-
return false
|
|
148
|
-
end
|
|
95
|
+
next if (new_ranges = parse_ipv4_cidr(arg)).nil?
|
|
149
96
|
|
|
150
97
|
# Handle hostnames
|
|
151
98
|
elsif arg =~ /[^-0-9,.*]/
|
|
152
|
-
|
|
153
|
-
# unmolested to force a DNS lookup.
|
|
154
|
-
begin
|
|
155
|
-
ranges += Rex::Socket.addr_atoi_list(arg).map { |a| Range.new(a, a, opts) }
|
|
156
|
-
rescue Resolv::ResolvError, ::SocketError, Errno::ENOENT
|
|
157
|
-
return false
|
|
158
|
-
end
|
|
99
|
+
next if (new_ranges = parse_hostname(arg)).nil?
|
|
159
100
|
|
|
160
101
|
# Handle IPv4 ranges
|
|
161
|
-
elsif arg =~
|
|
162
|
-
|
|
102
|
+
elsif arg =~ MATCH_IPV4_RANGE
|
|
163
103
|
# Then it's in the format of 1.2.3.4-5.6.7.8
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
start, stop = Rex::Socket.addr_atoi($1), Rex::Socket.addr_atoi($2)
|
|
167
|
-
return false if start > stop # The end is greater than the beginning.
|
|
168
|
-
ranges.push(Range.new(start, stop, opts))
|
|
169
|
-
rescue Resolv::ResolvError, ::SocketError, Errno::ENOENT
|
|
170
|
-
return false
|
|
171
|
-
end
|
|
104
|
+
next if (new_ranges = parse_ipv4_ranges(arg)).nil?
|
|
105
|
+
|
|
172
106
|
else
|
|
173
|
-
|
|
174
|
-
expanded = expand_nmap(arg)
|
|
175
|
-
if expanded
|
|
176
|
-
expanded.each { |r| ranges.push(r) }
|
|
177
|
-
end
|
|
107
|
+
next if (new_ranges = expand_nmap(arg)).nil?
|
|
178
108
|
end
|
|
109
|
+
|
|
110
|
+
ranges += new_ranges
|
|
179
111
|
end
|
|
180
112
|
|
|
181
113
|
# Remove any duplicate ranges
|
|
@@ -198,11 +130,12 @@ class RangeWalker
|
|
|
198
130
|
self
|
|
199
131
|
end
|
|
200
132
|
|
|
201
|
-
# Returns the next
|
|
133
|
+
# Returns the next host in the range.
|
|
202
134
|
#
|
|
203
|
-
# @return [String] The next
|
|
204
|
-
def
|
|
205
|
-
return
|
|
135
|
+
# @return [Hash<Symbol, String>] The next host in the range
|
|
136
|
+
def next_host
|
|
137
|
+
return unless valid?
|
|
138
|
+
|
|
206
139
|
if (@curr_addr > @ranges[@curr_range_index].stop)
|
|
207
140
|
# Then we are at the end of this range. Grab the next one.
|
|
208
141
|
|
|
@@ -213,14 +146,26 @@ class RangeWalker
|
|
|
213
146
|
|
|
214
147
|
@curr_addr = @ranges[@curr_range_index].start
|
|
215
148
|
end
|
|
216
|
-
addr = Rex::Socket.addr_itoa(@curr_addr, @ranges[@curr_range_index].ipv6?)
|
|
217
149
|
|
|
218
|
-
|
|
219
|
-
|
|
150
|
+
range = @ranges[@curr_range_index]
|
|
151
|
+
addr = Rex::Socket.addr_itoa(@curr_addr, range.ipv6?)
|
|
152
|
+
|
|
153
|
+
if range.options[:scope_id]
|
|
154
|
+
addr = addr + '%' + range.options[:scope_id]
|
|
220
155
|
end
|
|
221
156
|
|
|
157
|
+
hostname = range.is_a?(Host) ? range.hostname : nil
|
|
158
|
+
|
|
222
159
|
@curr_addr += 1
|
|
223
|
-
return addr
|
|
160
|
+
return { address: addr, hostname: hostname }
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
# Returns the next IP address.
|
|
164
|
+
#
|
|
165
|
+
# @return [String] The next address in the range
|
|
166
|
+
def next_ip
|
|
167
|
+
return nil if (host = next_host).nil?
|
|
168
|
+
host[:address]
|
|
224
169
|
end
|
|
225
170
|
|
|
226
171
|
alias :next :next_ip
|
|
@@ -271,7 +216,7 @@ class RangeWalker
|
|
|
271
216
|
# {#next_ip}
|
|
272
217
|
#
|
|
273
218
|
# @return [self]
|
|
274
|
-
def
|
|
219
|
+
def each_ip(&block)
|
|
275
220
|
while (ip = next_ip)
|
|
276
221
|
block.call(ip)
|
|
277
222
|
end
|
|
@@ -280,6 +225,17 @@ class RangeWalker
|
|
|
280
225
|
self
|
|
281
226
|
end
|
|
282
227
|
|
|
228
|
+
alias each each_ip
|
|
229
|
+
|
|
230
|
+
def each_host(&block)
|
|
231
|
+
while (host_hash = next_host)
|
|
232
|
+
block.call(host_hash)
|
|
233
|
+
end
|
|
234
|
+
reset
|
|
235
|
+
|
|
236
|
+
self
|
|
237
|
+
end
|
|
238
|
+
|
|
283
239
|
#
|
|
284
240
|
# Returns an Array with one element, a {Range} defined by the given CIDR
|
|
285
241
|
# block.
|
|
@@ -291,7 +247,7 @@ class RangeWalker
|
|
|
291
247
|
def expand_cidr(arg)
|
|
292
248
|
start,stop = Rex::Socket.cidr_crack(arg)
|
|
293
249
|
if !start or !stop
|
|
294
|
-
return
|
|
250
|
+
return
|
|
295
251
|
end
|
|
296
252
|
range = Range.new
|
|
297
253
|
range.start = Rex::Socket.addr_atoi(start)
|
|
@@ -319,18 +275,16 @@ class RangeWalker
|
|
|
319
275
|
#
|
|
320
276
|
def expand_nmap(arg)
|
|
321
277
|
# Can't really do anything with IPv6
|
|
322
|
-
return
|
|
278
|
+
return if arg.include?(":")
|
|
323
279
|
|
|
324
280
|
# nmap calls these errors, but it's hard to catch them with our
|
|
325
281
|
# splitting below, so short-cut them here
|
|
326
|
-
return
|
|
282
|
+
return if arg.include?(",-") or arg.include?("-,")
|
|
327
283
|
|
|
328
284
|
bytes = []
|
|
329
285
|
sections = arg.split('.')
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
return false
|
|
333
|
-
end
|
|
286
|
+
return unless sections.length == 4 # Too many or not enough dots
|
|
287
|
+
|
|
334
288
|
sections.each { |section|
|
|
335
289
|
if section.empty?
|
|
336
290
|
# pretty sure this is an unintentional artifact of the C
|
|
@@ -344,7 +298,7 @@ class RangeWalker
|
|
|
344
298
|
# I think this ought to be 1-254, but this is how nmap does it.
|
|
345
299
|
section = "0-255"
|
|
346
300
|
elsif section.include?("*")
|
|
347
|
-
return
|
|
301
|
+
return
|
|
348
302
|
end
|
|
349
303
|
|
|
350
304
|
# Break down the sections into ranges like so
|
|
@@ -361,18 +315,18 @@ class RangeWalker
|
|
|
361
315
|
# if the upper bound is empty, stop at 255
|
|
362
316
|
#
|
|
363
317
|
bounds = r.split('-', -1)
|
|
364
|
-
return
|
|
318
|
+
return if (bounds.length > 2)
|
|
365
319
|
|
|
366
320
|
bounds[0] = 0 if bounds[0].nil? or bounds[0].empty?
|
|
367
321
|
bounds[1] = 255 if bounds[1].nil? or bounds[1].empty?
|
|
368
322
|
bounds.map!{|b| b.to_i}
|
|
369
|
-
return
|
|
323
|
+
return if bounds[0] > bounds[1]
|
|
370
324
|
else
|
|
371
325
|
# Then it's a single value
|
|
372
326
|
bounds[0] = r.to_i
|
|
373
327
|
end
|
|
374
|
-
return
|
|
375
|
-
return
|
|
328
|
+
return if bounds[0] > 255 or (bounds[1] and bounds[1] > 255)
|
|
329
|
+
return if bounds[1] and bounds[0] > bounds[1]
|
|
376
330
|
if bounds[1]
|
|
377
331
|
bounds[0].upto(bounds[1]) do |i|
|
|
378
332
|
sets.push(i)
|
|
@@ -430,6 +384,98 @@ class RangeWalker
|
|
|
430
384
|
|
|
431
385
|
protected
|
|
432
386
|
|
|
387
|
+
def parse_hostname(arg)
|
|
388
|
+
begin
|
|
389
|
+
ranges = Rex::Socket.getaddresses(arg).map { |addr| Host.new(addr, arg) }
|
|
390
|
+
rescue Resolv::ResolvError, ::SocketError, Errno::ENOENT
|
|
391
|
+
return
|
|
392
|
+
end
|
|
393
|
+
|
|
394
|
+
ranges
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
def parse_ipv4_cidr(arg)
|
|
398
|
+
# Then it's CIDR notation and needs special case
|
|
399
|
+
return if !valid_cidr_chars?(arg)
|
|
400
|
+
|
|
401
|
+
ip_part, mask_part = arg.split("/")
|
|
402
|
+
return unless (0..32).include? mask_part.to_i
|
|
403
|
+
if ip_part =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
|
404
|
+
return unless Rex::Socket.is_ipv4?(ip_part)
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
begin
|
|
408
|
+
hosts = Rex::Socket.getaddresses(ip_part).select { |addr| Rex::Socket.is_ipv4?(addr) } # drop non-IPv4 addresses
|
|
409
|
+
rescue Resolv::ResolvError, ::SocketError, Errno::ENOENT
|
|
410
|
+
return # Can't resolve the ip_part, so bail.
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
hosts.map { |addr| expand_cidr("#{addr}/#{mask_part}") }
|
|
414
|
+
end
|
|
415
|
+
|
|
416
|
+
def parse_ipv4_ranges(arg)
|
|
417
|
+
# Note, this will /not/ deal with DNS names, or the fancy/obscure 10...1-10...2
|
|
418
|
+
return unless arg =~ MATCH_IPV4_RANGE
|
|
419
|
+
|
|
420
|
+
begin
|
|
421
|
+
start, stop = Rex::Socket.addr_atoi($1), Rex::Socket.addr_atoi($2)
|
|
422
|
+
return if start > stop # The end is greater than the beginning.
|
|
423
|
+
range = Range.new(start, stop)
|
|
424
|
+
rescue Resolv::ResolvError, ::SocketError, Errno::ENOENT
|
|
425
|
+
return
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
[range]
|
|
429
|
+
end
|
|
430
|
+
|
|
431
|
+
def parse_ipv6(arg)
|
|
432
|
+
opts = {}
|
|
433
|
+
addrs = arg.split('-', 2)
|
|
434
|
+
|
|
435
|
+
# Handle a single address
|
|
436
|
+
if addrs.length == 1
|
|
437
|
+
addr, scope_id = addrs[0].split('%')
|
|
438
|
+
opts[:scope_id] = scope_id if scope_id
|
|
439
|
+
opts[:ipv6] = true
|
|
440
|
+
|
|
441
|
+
return unless Rex::Socket.is_ipv6?(addr)
|
|
442
|
+
addr = Rex::Socket.addr_atoi(addr)
|
|
443
|
+
range = Range.new(addr, addr, opts)
|
|
444
|
+
else
|
|
445
|
+
addr1, scope_id = addrs[0].split('%')
|
|
446
|
+
opts[:scope_id] = scope_id if scope_id
|
|
447
|
+
opts[:ipv6] = true
|
|
448
|
+
|
|
449
|
+
addr2, scope_id = addrs[1].split('%')
|
|
450
|
+
( opts[:scope_id] ||= scope_id ) if scope_id
|
|
451
|
+
|
|
452
|
+
# Both have to be IPv6 for this to work
|
|
453
|
+
return unless (Rex::Socket.is_ipv6?(addr1) && Rex::Socket.is_ipv6?(addr2))
|
|
454
|
+
|
|
455
|
+
# Handle IPv6 ranges in the form of 2001::1-2001::10
|
|
456
|
+
addr1 = Rex::Socket.addr_atoi(addr1)
|
|
457
|
+
addr2 = Rex::Socket.addr_atoi(addr2)
|
|
458
|
+
|
|
459
|
+
range = Range.new(addr1, addr2, opts)
|
|
460
|
+
end
|
|
461
|
+
|
|
462
|
+
[range]
|
|
463
|
+
end
|
|
464
|
+
|
|
465
|
+
def parse_ipv6_cidr(arg)
|
|
466
|
+
return if !valid_cidr_chars?(arg)
|
|
467
|
+
|
|
468
|
+
ip_part, mask_part = arg.split("/")
|
|
469
|
+
return unless (0..128).include? mask_part.to_i
|
|
470
|
+
|
|
471
|
+
addr, scope_id = ip_part.split('%')
|
|
472
|
+
return unless Rex::Socket.is_ipv6?(addr)
|
|
473
|
+
|
|
474
|
+
range = expand_cidr(addr + '/' + mask_part)
|
|
475
|
+
range.options[:scope_id] = scope_id if scope_id
|
|
476
|
+
[range]
|
|
477
|
+
end
|
|
478
|
+
|
|
433
479
|
def valid_cidr_chars?(arg)
|
|
434
480
|
return false if arg.include? ',-' # Improper CIDR notation (can't mix with 1,3 or 1-3 style IP ranges)
|
|
435
481
|
return false if arg.scan("/").size > 1 # ..but there are too many slashes
|
|
@@ -464,7 +510,7 @@ class Range
|
|
|
464
510
|
def initialize(start=nil, stop=nil, options=nil)
|
|
465
511
|
@start = start
|
|
466
512
|
@stop = stop
|
|
467
|
-
@options = options
|
|
513
|
+
@options = options || {}
|
|
468
514
|
end
|
|
469
515
|
|
|
470
516
|
# Compare attributes with +other+
|
|
@@ -488,5 +534,21 @@ class Range
|
|
|
488
534
|
end
|
|
489
535
|
end
|
|
490
536
|
|
|
537
|
+
# A single host
|
|
538
|
+
class Host < Range
|
|
539
|
+
attr_accessor :hostname
|
|
540
|
+
|
|
541
|
+
def initialize(address, hostname=nil, options=nil)
|
|
542
|
+
address = Rex::Socket.addr_atoi(address) if address.is_a? String
|
|
543
|
+
|
|
544
|
+
super(address, address, options)
|
|
545
|
+
@hostname = hostname
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
def address
|
|
549
|
+
Rex::Socket.addr_itoa(@start)
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
end
|
|
491
553
|
end
|
|
492
554
|
end
|
data/lib/rex/socket/version.rb
CHANGED
data/rex-socket.gemspec
CHANGED
|
@@ -6,8 +6,8 @@ require 'rex/socket/version'
|
|
|
6
6
|
Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "rex-socket"
|
|
8
8
|
spec.version = Rex::Socket::VERSION
|
|
9
|
-
spec.authors = [
|
|
10
|
-
spec.email = [
|
|
9
|
+
spec.authors = ['Metasploit Hackers']
|
|
10
|
+
spec.email = ['msfdev@metasploit.com']
|
|
11
11
|
|
|
12
12
|
spec.summary = %q{The Ruby Exploitation (Rex) Socket Abstraction Library.}
|
|
13
13
|
spec.description = %q{The Ruby Exploitation (Rex) Socket Abstraction Library. This library
|
|
@@ -24,9 +24,8 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
|
|
25
25
|
spec.required_ruby_version = '>= 2.2.0'
|
|
26
26
|
|
|
27
|
-
spec.add_development_dependency "
|
|
28
|
-
spec.add_development_dependency "
|
|
29
|
-
spec.add_development_dependency "rspec", "~> 3.0"
|
|
27
|
+
spec.add_development_dependency "rake"
|
|
28
|
+
spec.add_development_dependency "rspec"
|
|
30
29
|
|
|
31
30
|
spec.add_runtime_dependency "rex-core"
|
|
32
31
|
end
|
metadata
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rex-socket
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.29
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
|
-
-
|
|
7
|
+
- Metasploit Hackers
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain:
|
|
@@ -64,20 +64,20 @@ cert_chain:
|
|
|
64
64
|
-----END CERTIFICATE-----
|
|
65
65
|
- |
|
|
66
66
|
-----BEGIN CERTIFICATE-----
|
|
67
|
-
|
|
67
|
+
MIIFIzCCBAugAwIBAgIQCMePMbkSxvnPeJhYXIfaxzANBgkqhkiG9w0BAQsFADBy
|
|
68
68
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
|
69
69
|
d3cuZGlnaWNlcnQuY29tMTEwLwYDVQQDEyhEaWdpQ2VydCBTSEEyIEFzc3VyZWQg
|
|
70
|
-
|
|
70
|
+
SUQgQ29kZSBTaWduaW5nIENBMB4XDTIwMTAwNzAwMDAwMFoXDTIzMTEwNjEyMDAw
|
|
71
71
|
MFowYDELMAkGA1UEBhMCVVMxFjAUBgNVBAgTDU1hc3NhY2h1c2V0dHMxDzANBgNV
|
|
72
72
|
BAcTBkJvc3RvbjETMBEGA1UEChMKUmFwaWQ3IExMQzETMBEGA1UEAxMKUmFwaWQ3
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
73
|
+
IExMQzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALNTz4zvAy7h/vQp
|
|
74
|
+
4dr1txXHlABAagkwYYwTMCtHs5PXsJITx/5SAjx5swuaLfze5kPBNF2YImvFlOXY
|
|
75
|
+
WaB+0PsOnXnaARsDZU683xFlj8izU6IN6VrAHzDLKFBzruJENrOJD/ikbEtbjO/q
|
|
76
|
+
gFbmS9J9v5ohG/pcRSS0t4ZPAwymf8eCp6QsvOKK/Aymp1RhlRaP8N6N5CIpkhz1
|
|
77
|
+
9p968iCE+DjOXVYxcWE+jE/7uB1dbgrXykNBujMSS3GULOvVEY28n6NCmrPlo23g
|
|
78
|
+
yRjYVJ2Vy14nBqnxDZ/yRIfWRVjWoT9TsAEbe9gY29oDpSCSs4wSmLQd5zGCpZ9h
|
|
79
|
+
r0HDFB8CAwEAAaOCAcUwggHBMB8GA1UdIwQYMBaAFFrEuXsqCqOl6nEDwGD5LfZl
|
|
80
|
+
dQ5YMB0GA1UdDgQWBBTLBL7DTwumVEKtdCdpHVYMXOFeDzAOBgNVHQ8BAf8EBAMC
|
|
81
81
|
B4AwEwYDVR0lBAwwCgYIKwYBBQUHAwMwdwYDVR0fBHAwbjA1oDOgMYYvaHR0cDov
|
|
82
82
|
L2NybDMuZGlnaWNlcnQuY29tL3NoYTItYXNzdXJlZC1jcy1nMS5jcmwwNaAzoDGG
|
|
83
83
|
L2h0dHA6Ly9jcmw0LmRpZ2ljZXJ0LmNvbS9zaGEyLWFzc3VyZWQtY3MtZzEuY3Js
|
|
@@ -86,57 +86,43 @@ cert_chain:
|
|
|
86
86
|
JAYIKwYBBQUHMAGGGGh0dHA6Ly9vY3NwLmRpZ2ljZXJ0LmNvbTBOBggrBgEFBQcw
|
|
87
87
|
AoZCaHR0cDovL2NhY2VydHMuZGlnaWNlcnQuY29tL0RpZ2lDZXJ0U0hBMkFzc3Vy
|
|
88
88
|
ZWRJRENvZGVTaWduaW5nQ0EuY3J0MAwGA1UdEwEB/wQCMAAwDQYJKoZIhvcNAQEL
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
89
|
+
BQADggEBAN+GL5/myPWg7oH4mVrG7/OhXF1MoYQF0ddaNiqaweEHMuKJBQCVZRbL
|
|
90
|
+
37HojoKXXv2yyRJBCeTB+ojrxX+5PdLVZa0ss7toWzJ2A1poPXZ1eZvm5xeFD32z
|
|
91
|
+
YQaTmmNWNI3PCDTyJ2PXUc+bDiNNwcZ7yc5o78UNRvp9Jxghya17Q76c9Ov9wvnv
|
|
92
|
+
dxxQKWGOQy0m4fBrkyjAyH9Djjn81RbQrqYgPuhd5nD0HjN3VUQLhQbIJrk9TVs0
|
|
93
|
+
EknWpNgVhohbot1lfVAMmIhdtOVaRVcQQixWPwprDj/ydB8ryDMDosIMcw+fkoXU
|
|
94
|
+
9GJsSaSRRYQ9UUkVL27b64okU8D48m8=
|
|
95
95
|
-----END CERTIFICATE-----
|
|
96
|
-
date:
|
|
96
|
+
date: 2021-03-25 00:00:00.000000000 Z
|
|
97
97
|
dependencies:
|
|
98
|
-
- !ruby/object:Gem::Dependency
|
|
99
|
-
name: bundler
|
|
100
|
-
requirement: !ruby/object:Gem::Requirement
|
|
101
|
-
requirements:
|
|
102
|
-
- - "~>"
|
|
103
|
-
- !ruby/object:Gem::Version
|
|
104
|
-
version: '1.12'
|
|
105
|
-
type: :development
|
|
106
|
-
prerelease: false
|
|
107
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
108
|
-
requirements:
|
|
109
|
-
- - "~>"
|
|
110
|
-
- !ruby/object:Gem::Version
|
|
111
|
-
version: '1.12'
|
|
112
98
|
- !ruby/object:Gem::Dependency
|
|
113
99
|
name: rake
|
|
114
100
|
requirement: !ruby/object:Gem::Requirement
|
|
115
101
|
requirements:
|
|
116
|
-
- - "
|
|
102
|
+
- - ">="
|
|
117
103
|
- !ruby/object:Gem::Version
|
|
118
|
-
version: '
|
|
104
|
+
version: '0'
|
|
119
105
|
type: :development
|
|
120
106
|
prerelease: false
|
|
121
107
|
version_requirements: !ruby/object:Gem::Requirement
|
|
122
108
|
requirements:
|
|
123
|
-
- - "
|
|
109
|
+
- - ">="
|
|
124
110
|
- !ruby/object:Gem::Version
|
|
125
|
-
version: '
|
|
111
|
+
version: '0'
|
|
126
112
|
- !ruby/object:Gem::Dependency
|
|
127
113
|
name: rspec
|
|
128
114
|
requirement: !ruby/object:Gem::Requirement
|
|
129
115
|
requirements:
|
|
130
|
-
- - "
|
|
116
|
+
- - ">="
|
|
131
117
|
- !ruby/object:Gem::Version
|
|
132
|
-
version: '
|
|
118
|
+
version: '0'
|
|
133
119
|
type: :development
|
|
134
120
|
prerelease: false
|
|
135
121
|
version_requirements: !ruby/object:Gem::Requirement
|
|
136
122
|
requirements:
|
|
137
|
-
- - "
|
|
123
|
+
- - ">="
|
|
138
124
|
- !ruby/object:Gem::Version
|
|
139
|
-
version: '
|
|
125
|
+
version: '0'
|
|
140
126
|
- !ruby/object:Gem::Dependency
|
|
141
127
|
name: rex-core
|
|
142
128
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -156,14 +142,14 @@ description: "The Ruby Exploitation (Rex) Socket Abstraction Library. This libra
|
|
|
156
142
|
with the functionality\n for things like L3 pivoting used
|
|
157
143
|
by Metasploit. "
|
|
158
144
|
email:
|
|
159
|
-
-
|
|
145
|
+
- msfdev@metasploit.com
|
|
160
146
|
executables: []
|
|
161
147
|
extensions: []
|
|
162
148
|
extra_rdoc_files: []
|
|
163
149
|
files:
|
|
150
|
+
- ".github/workflows/verify.yml"
|
|
164
151
|
- ".gitignore"
|
|
165
152
|
- ".rspec"
|
|
166
|
-
- ".travis.yml"
|
|
167
153
|
- CODE_OF_CONDUCT.md
|
|
168
154
|
- Gemfile
|
|
169
155
|
- LICENSE
|
metadata.gz.sig
CHANGED