CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/dns/upstream_rule.rb
Views: 11704
1
# -*- coding: binary -*-
2
3
require 'json'
4
require 'rex/socket'
5
6
module Rex
7
module Proto
8
module DNS
9
##
10
# This represents a configuration rule for how names should be resolved. It matches a single wildcard which acts as a
11
# matching condition and maps it to 0 or more resolvers to use for lookups.
12
##
13
class UpstreamRule
14
15
attr_reader :wildcard, :resolvers, :comm
16
# @param [String] wildcard The wildcard pattern to use for conditionally matching hostnames.
17
# @param [Array] resolvers The resolvers to use when this rule is applied.
18
# @param [Msf::Session::Comm] comm The communication channel to use when creating network connections.
19
def initialize(wildcard: '*', resolvers: [], comm: nil)
20
::ArgumentError.new("Invalid wildcard text: #{wildcard}") unless self.class.valid_wildcard?(wildcard)
21
@wildcard = wildcard
22
socket_options = {}
23
socket_options['Comm'] = comm unless comm.nil?
24
@resolvers = resolvers.map do |resolver|
25
if resolver.is_a?(String) && !Rex::Socket.is_ip_addr?(resolver)
26
resolver = resolver.downcase.to_sym
27
end
28
29
case resolver
30
when UpstreamResolver
31
resolver
32
when UpstreamResolver::Type::BLACK_HOLE
33
UpstreamResolver.create_black_hole
34
when UpstreamResolver::Type::STATIC
35
UpstreamResolver.create_static
36
when UpstreamResolver::Type::SYSTEM
37
UpstreamResolver.create_system
38
else
39
if Rex::Socket.is_ip_addr?(resolver)
40
UpstreamResolver.create_dns_server(resolver, socket_options: socket_options)
41
else
42
raise ::ArgumentError.new("Invalid upstream DNS resolver: #{resolver}")
43
end
44
end
45
end
46
@comm = comm
47
end
48
49
# Check whether or not the defined resolver is valid.
50
#
51
# @param [String] resolver The resolver string to check.
52
# @rtype Boolean
53
def self.valid_resolver?(resolver)
54
return true if Rex::Socket.is_ip_addr?(resolver)
55
56
resolver = resolver.downcase.to_sym
57
[
58
UpstreamResolver::Type::BLACK_HOLE,
59
UpstreamResolver::Type::STATIC,
60
UpstreamResolver::Type::SYSTEM
61
].include?(resolver)
62
end
63
64
# Perform a spell check on resolver to suggest corrections.
65
#
66
# @param [String] resolver The resolver string to check.
67
# @rtype [Nil, Array<String>] The suggestions if resolver is invalid.
68
def self.spell_check_resolver(resolver)
69
return nil if Rex::Socket.is_ip_addr?(resolver)
70
71
suggestions = DidYouMean::SpellChecker.new(dictionary: [
72
UpstreamResolver::Type::BLACK_HOLE,
73
UpstreamResolver::Type::STATIC,
74
UpstreamResolver::Type::SYSTEM
75
]).correct(resolver).map(&:to_s)
76
return nil if suggestions.empty?
77
78
suggestions
79
end
80
81
# Check whether or not the defined wildcard is a valid pattern.
82
#
83
# @param [String] wildcard The wildcard text to check.
84
# @rtype Boolean
85
def self.valid_wildcard?(wildcard)
86
wildcard == '*' || wildcard =~ /^(\*\.)?([a-z\d][a-z\d-]*[a-z\d]\.)+[a-z]+$/
87
end
88
89
# Check whether or not the currently configured wildcard pattern will match all names.
90
#
91
# @rtype Boolean
92
def matches_all?
93
wildcard == '*'
94
end
95
96
# Check whether or not the specified name matches the currently configured wildcard pattern.
97
#
98
# @rtype Boolean
99
def matches_name?(name)
100
if matches_all?
101
true
102
elsif wildcard.start_with?('*.')
103
name.downcase.end_with?(wildcard[1..-1].downcase)
104
else
105
name.casecmp?(wildcard)
106
end
107
end
108
109
def eql?(other)
110
return false unless other.is_a?(self.class)
111
return false unless other.wildcard == wildcard
112
return false unless other.resolvers == resolvers
113
return false unless other.comm == comm
114
true
115
end
116
117
alias == eql?
118
end
119
end
120
end
121
end
122
123