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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b0bf99960d66db7491db5490f75d4c87a8bfde429dcc76a4e4e1d07306cf61b8
4
- data.tar.gz: 7e665ba1dba7574c1fa7adb9523b9e8781daff17185daef8300cc0d1f5cd8d0b
3
+ metadata.gz: 1c761ab84c205dd7b2046c7249f279f4f9b4ac2ba16168dd4c7cc62e1ac41fb8
4
+ data.tar.gz: 4ead3c6958a08e49e7255946a772ee8ba4934de87e3f1e1e96ad94db9399fb69
5
5
  SHA512:
6
- metadata.gz: a15da2ba7b185bf822db6f467fde6ae641008861f2758c865b9c66b524904dffd02add948e18cb544105747aaf8ce5f90f3083c8eaa18ac84284917ff29fe9cf
7
- data.tar.gz: c6585bddb9cc7b52f29f3d9f193200132801fbb141162550f9d6a9553af51a853a3946c3c42fca55dbaed217a88cd68372066db5d76a8bcbc356a780c6bde61a
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", 'core', LEV_3)
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 if not parseme
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 !valid_cidr_chars?(arg)
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
- addrs = arg.split('-', 2)
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
- # Then it's CIDR notation and needs special case
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
- # Then it's a domain name and we should send it on to addr_atoi
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 =~ /^([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})$/
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
- # Note, this will /not/ deal with DNS names, or the fancy/obscure 10...1-10...2
165
- begin
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
- # Returns an array of ranges
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 IP address.
133
+ # Returns the next host in the range.
202
134
  #
203
- # @return [String] The next address in the range
204
- def next_ip
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
- if @ranges[@curr_range_index].options[:scope_id]
219
- addr = addr + '%' + @ranges[@curr_range_index].options[:scope_id]
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 each(&block)
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
@@ -276,7 +276,7 @@ protected
276
276
  # Initializes the underlying stuff.
277
277
  #
278
278
  def _init
279
- if (@_initialized != true)
279
+ unless @_initialized
280
280
  @_initialized = true
281
281
  self.routes = Array.new
282
282
  self.mutex = Mutex.new
@@ -1,5 +1,5 @@
1
1
  module Rex
2
2
  module Socket
3
- VERSION = "0.1.26"
3
+ VERSION = "0.1.27"
4
4
  end
5
5
  end
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.26
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-10 00:00:00.000000000 Z
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