rex-socket 0.1.26 → 0.1.27

Sign up to get free protection for your applications and to get access to all the features.
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