rex-socket 0.1.26 → 0.1.27
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 +0 -0
- data/lib/rex/socket.rb +3 -1
- data/lib/rex/socket/range_walker.rb +156 -92
- data/lib/rex/socket/switch_board.rb +1 -1
- data/lib/rex/socket/version.rb +1 -1
- metadata +2 -2
- metadata.gz.sig +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1c761ab84c205dd7b2046c7249f279f4f9b4ac2ba16168dd4c7cc62e1ac41fb8
|
4
|
+
data.tar.gz: 4ead3c6958a08e49e7255946a772ee8ba4934de87e3f1e1e96ad94db9399fb69
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5b2ddff4009180354ffc849c021da8087855406e0fa2d7c549981cc7bdfc13adc854cda40da406605c513d719327fa2464948f2e24c06a533b248a149e171061
|
7
|
+
data.tar.gz: 4a862d8480c701c99a28ff67be3db07ecd5803509f18d712f5acfa42bbb432e3022a5797a8847d13e7a989243e19bf4081ad632e7466ee51e5ef29006a5ab39d
|
checksums.yaml.gz.sig
CHANGED
Binary file
|
data.tar.gz.sig
CHANGED
Binary file
|
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
|
|
@@ -745,7 +747,7 @@ module Socket
|
|
745
747
|
peer_name = Socket.from_sockaddr(self.getpeername)
|
746
748
|
rescue ::Errno::EINVAL => e
|
747
749
|
# Ruby's getpeername method may call rb_sys_fail("getpeername(2)")
|
748
|
-
elog("#{e.message} (#{e.class})#{e.backtrace * "\n"}\n",
|
750
|
+
elog("#{e.message} (#{e.class})#{e.backtrace * "\n"}\n", LogSource, LEV_3)
|
749
751
|
end
|
750
752
|
|
751
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
|
-
return false if
|
85
|
-
|
86
|
-
ip_part, mask_part = arg.split("/")
|
87
|
-
return false unless (0..128).include? mask_part.to_i
|
87
|
+
return false 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
|
+
return false 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
|
+
return false 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
|
+
return false 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
|
+
return false 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
|
+
new_ranges = expand_nmap(arg)
|
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.
|
@@ -430,6 +386,98 @@ class RangeWalker
|
|
430
386
|
|
431
387
|
protected
|
432
388
|
|
389
|
+
def parse_hostname(arg)
|
390
|
+
begin
|
391
|
+
ranges = Rex::Socket.getaddresses(arg).map { |addr| Host.new(addr, arg) }
|
392
|
+
rescue Resolv::ResolvError, ::SocketError, Errno::ENOENT
|
393
|
+
return
|
394
|
+
end
|
395
|
+
|
396
|
+
ranges
|
397
|
+
end
|
398
|
+
|
399
|
+
def parse_ipv4_cidr(arg)
|
400
|
+
# Then it's CIDR notation and needs special case
|
401
|
+
return if !valid_cidr_chars?(arg)
|
402
|
+
|
403
|
+
ip_part, mask_part = arg.split("/")
|
404
|
+
return false unless (0..32).include? mask_part.to_i
|
405
|
+
if ip_part =~ /^\d{1,3}(\.\d{1,3}){1,3}$/
|
406
|
+
return unless Rex::Socket.is_ipv4?(ip_part)
|
407
|
+
end
|
408
|
+
|
409
|
+
begin
|
410
|
+
hosts = Rex::Socket.getaddresses(ip_part).select { |addr| Rex::Socket.is_ipv4?(addr) } # drop non-IPv4 addresses
|
411
|
+
rescue Resolv::ResolvError, ::SocketError, Errno::ENOENT
|
412
|
+
return # Can't resolve the ip_part, so bail.
|
413
|
+
end
|
414
|
+
|
415
|
+
hosts.map { |addr| expand_cidr("#{addr}/#{mask_part}") }
|
416
|
+
end
|
417
|
+
|
418
|
+
def parse_ipv4_ranges(arg)
|
419
|
+
# Note, this will /not/ deal with DNS names, or the fancy/obscure 10...1-10...2
|
420
|
+
return unless arg =~ MATCH_IPV4_RANGE
|
421
|
+
|
422
|
+
begin
|
423
|
+
start, stop = Rex::Socket.addr_atoi($1), Rex::Socket.addr_atoi($2)
|
424
|
+
return if start > stop # The end is greater than the beginning.
|
425
|
+
range = Range.new(start, stop)
|
426
|
+
rescue Resolv::ResolvError, ::SocketError, Errno::ENOENT
|
427
|
+
return
|
428
|
+
end
|
429
|
+
|
430
|
+
[range]
|
431
|
+
end
|
432
|
+
|
433
|
+
def parse_ipv6(arg)
|
434
|
+
opts = {}
|
435
|
+
addrs = arg.split('-', 2)
|
436
|
+
|
437
|
+
# Handle a single address
|
438
|
+
if addrs.length == 1
|
439
|
+
addr, scope_id = addrs[0].split('%')
|
440
|
+
opts[:scope_id] = scope_id if scope_id
|
441
|
+
opts[:ipv6] = true
|
442
|
+
|
443
|
+
return unless Rex::Socket.is_ipv6?(addr)
|
444
|
+
addr = Rex::Socket.addr_atoi(addr)
|
445
|
+
range = Range.new(addr, addr, opts)
|
446
|
+
else
|
447
|
+
addr1, scope_id = addrs[0].split('%')
|
448
|
+
opts[:scope_id] = scope_id if scope_id
|
449
|
+
opts[:ipv6] = true
|
450
|
+
|
451
|
+
addr2, scope_id = addrs[1].split('%')
|
452
|
+
( opts[:scope_id] ||= scope_id ) if scope_id
|
453
|
+
|
454
|
+
# Both have to be IPv6 for this to work
|
455
|
+
return unless (Rex::Socket.is_ipv6?(addr1) && Rex::Socket.is_ipv6?(addr2))
|
456
|
+
|
457
|
+
# Handle IPv6 ranges in the form of 2001::1-2001::10
|
458
|
+
addr1 = Rex::Socket.addr_atoi(addr1)
|
459
|
+
addr2 = Rex::Socket.addr_atoi(addr2)
|
460
|
+
|
461
|
+
range = Range.new(addr1, addr2, opts)
|
462
|
+
end
|
463
|
+
|
464
|
+
[range]
|
465
|
+
end
|
466
|
+
|
467
|
+
def parse_ipv6_cidr(arg)
|
468
|
+
return if !valid_cidr_chars?(arg)
|
469
|
+
|
470
|
+
ip_part, mask_part = arg.split("/")
|
471
|
+
return unless (0..128).include? mask_part.to_i
|
472
|
+
|
473
|
+
addr, scope_id = ip_part.split('%')
|
474
|
+
return unless Rex::Socket.is_ipv6?(addr)
|
475
|
+
|
476
|
+
range = expand_cidr(addr + '/' + mask_part)
|
477
|
+
range.options[:scope_id] = scope_id if scope_id
|
478
|
+
[range]
|
479
|
+
end
|
480
|
+
|
433
481
|
def valid_cidr_chars?(arg)
|
434
482
|
return false if arg.include? ',-' # Improper CIDR notation (can't mix with 1,3 or 1-3 style IP ranges)
|
435
483
|
return false if arg.scan("/").size > 1 # ..but there are too many slashes
|
@@ -464,7 +512,7 @@ class Range
|
|
464
512
|
def initialize(start=nil, stop=nil, options=nil)
|
465
513
|
@start = start
|
466
514
|
@stop = stop
|
467
|
-
@options = options
|
515
|
+
@options = options || {}
|
468
516
|
end
|
469
517
|
|
470
518
|
# Compare attributes with +other+
|
@@ -488,5 +536,21 @@ class Range
|
|
488
536
|
end
|
489
537
|
end
|
490
538
|
|
539
|
+
# A single host
|
540
|
+
class Host < Range
|
541
|
+
attr_accessor :hostname
|
542
|
+
|
543
|
+
def initialize(address, hostname=nil, options=nil)
|
544
|
+
address = Rex::Socket.addr_atoi(address) if address.is_a? String
|
545
|
+
|
546
|
+
super(address, address, options)
|
547
|
+
@hostname = hostname
|
548
|
+
end
|
549
|
+
|
550
|
+
def address
|
551
|
+
Rex::Socket.addr_itoa(@start)
|
552
|
+
end
|
553
|
+
|
554
|
+
end
|
491
555
|
end
|
492
556
|
end
|
data/lib/rex/socket/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
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.27
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Metasploit Hackers
|
@@ -93,7 +93,7 @@ cert_chain:
|
|
93
93
|
EknWpNgVhohbot1lfVAMmIhdtOVaRVcQQixWPwprDj/ydB8ryDMDosIMcw+fkoXU
|
94
94
|
9GJsSaSRRYQ9UUkVL27b64okU8D48m8=
|
95
95
|
-----END CERTIFICATE-----
|
96
|
-
date: 2021-03-
|
96
|
+
date: 2021-03-24 00:00:00.000000000 Z
|
97
97
|
dependencies:
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: rake
|
metadata.gz.sig
CHANGED
Binary file
|