rex-socket 0.1.23 → 0.1.28
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- checksums.yaml.gz.sig +1 -1
- data.tar.gz.sig +0 -0
- 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 +165 -103
- data/lib/rex/socket/switch_board.rb +1 -1
- data/lib/rex/socket/version.rb +1 -1
- data/lib/rex/socket/x509_certificate.rb +3 -1
- data/rex-socket.gemspec +4 -5
- metadata +29 -43
- metadata.gz.sig +0 -0
- 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: 324deceef4e08a04cdfee10fa7fcda792dfee027e2a83792492da6294a2a5b18
|
4
|
+
data.tar.gz: bdb5cdb27e4cf46c90fe0c5ace17347c47fcb257497fba247c18a627afe9b536
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b161f04cb05e3e44c6fd0034e4a5fc062d229bc582937a525f44230706a5c3b90c0abbafa71d359453040667034a76a597d93ecb153cf65abec00f4dfc8ef1d
|
7
|
+
data.tar.gz: 8c2238d6a358ef0dbb2cb513ca723d3fd97ea5ce97c64c8e79f7f166764d50a68cb0721e23a3701086d3418e7caac937366f2ab2b0fc887b54e742408cd37312
|
checksums.yaml.gz.sig
CHANGED
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
�!-�w�����>��Y,j{�E��R�o���!z�.G�F�VS
|
data.tar.gz.sig
CHANGED
Binary file
|
@@ -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
|
135
|
+
# @return [Hash<Symbol, String>] The next host in the range
|
136
|
+
def next_host
|
205
137
|
return false if not 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.
|
@@ -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 false 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
@@ -28,7 +28,9 @@ class X509Certificate
|
|
28
28
|
|
29
29
|
certs = []
|
30
30
|
ssl_cert.scan(/-----BEGIN\s*[^\-]+-----+\r?\n[^\-]*-----END\s*[^\-]+-----\r?\n?/nm).each do |pem|
|
31
|
-
if pem =~ /PRIVATE KEY/
|
31
|
+
if pem =~ /EC PRIVATE KEY/
|
32
|
+
key = OpenSSL::PKey::EC.new(pem)
|
33
|
+
elsif pem =~ /PRIVATE KEY/
|
32
34
|
key = OpenSSL::PKey::RSA.new(pem)
|
33
35
|
elsif pem =~ /CERTIFICATE/
|
34
36
|
certs << OpenSSL::X509::Certificate.new(pem)
|
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.28
|
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
Binary file
|