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. Commercial Alternative to JupyterHub.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/msf/core/opt_base.rb
Views: 15981
1
# -*- coding: binary -*-
2
require 'resolv'
3
require 'rex/socket'
4
5
module Msf
6
7
###
8
#
9
# The base class for all options.
10
#
11
###
12
class OptBase
13
14
#
15
# Initializes a named option with the supplied attribute array.
16
# The array is composed of three values.
17
#
18
# attrs[0] = required (boolean type)
19
# attrs[1] = description (string)
20
# attrs[2] = default value
21
# attrs[3] = possible enum values
22
# attrs[4] = Regex to validate the option
23
#
24
# Attrs can also be specified explicitly via named parameters, or attrs can
25
# also be a string as standin for the required description field.
26
#
27
def initialize(in_name, attrs = [],
28
required: false, desc: nil, default: nil, conditions: [], enums: [], regex: nil, aliases: [], max_length: nil,
29
fallbacks: [])
30
self.name = in_name
31
self.advanced = false
32
self.evasion = false
33
self.aliases = aliases
34
self.max_length = max_length
35
self.conditions = conditions
36
self.fallbacks = fallbacks
37
38
if attrs.is_a?(String) || attrs.length == 0
39
self.required = required
40
self.desc = attrs.is_a?(String) ? attrs : desc
41
self.enums = [ *(enums) ].map { |x| x.to_s }
42
if default.nil? && enums.length > 0
43
self.default = enums[0]
44
else
45
self.default = default
46
end
47
regex_temp = regex
48
else
49
if attrs[0].nil?
50
self.required = required
51
else
52
self.required = attrs[0]
53
end
54
self.desc = attrs[1] || desc
55
self.default = attrs[2] || default
56
self.enums = attrs[3] || enums
57
self.enums = [ *(self.enums) ].map { |x| x.to_s }
58
regex_temp = attrs[4] || regex
59
end
60
61
unless max_length.nil?
62
self.desc += " Max parameter length: #{max_length} characters"
63
end
64
65
if regex_temp
66
# convert to string
67
regex_temp = regex_temp.to_s if regex_temp.is_a? Regexp
68
# remove start and end character, they will be added later
69
regex_temp = regex_temp.sub(/^\^/, '').sub(/\$$/, '')
70
# Add start and end marker to match the whole regex
71
regex_temp = "^#{regex_temp}$"
72
begin
73
Regexp.compile(regex_temp)
74
self.regex = regex_temp
75
rescue RegexpError, TypeError => e
76
raise("Invalid Regex #{regex_temp}: #{e}")
77
end
78
end
79
end
80
81
#
82
# Returns true if this is a required option.
83
#
84
def required?
85
required
86
end
87
88
#
89
# Returns true if this is an advanced option.
90
#
91
def advanced?
92
advanced
93
end
94
95
#
96
# Returns true if this is an evasion option.
97
#
98
def evasion?
99
evasion
100
end
101
102
#
103
# Returns true if the supplied type is equivalent to this option's type.
104
#
105
def type?(in_type)
106
type == in_type
107
end
108
109
#
110
# Returns true if this option can be validated on assignment
111
#
112
def validate_on_assignment?
113
true
114
end
115
116
#
117
# If it's required and the value is nil or empty, then it's not valid.
118
#
119
def valid?(value, check_empty: true)
120
if check_empty && required?
121
# required variable not set
122
return false if (value.nil? || value.to_s.empty?)
123
end
124
if regex && !value.nil?
125
return !!value.match(regex)
126
end
127
true
128
end
129
130
#
131
# Returns true if the value supplied is nil and it's required to be
132
# a valid value
133
#
134
def empty_required_value?(value)
135
required? && value.nil?
136
end
137
138
#
139
# Normalizes the supplied value to conform with the type that the option is
140
# conveying.
141
#
142
def normalize(value)
143
value
144
end
145
146
#
147
# Returns a string representing a user-friendly display of the chosen value
148
#
149
def display_value(value)
150
value.to_s
151
end
152
153
#
154
# Returns true if the value supplied is longer then the max allowed length
155
#
156
def invalid_value_length?(value)
157
if !value.nil? && !max_length.nil?
158
value.length > max_length
159
end
160
end
161
162
#
163
# The name of the option.
164
#
165
attr_reader :name
166
#
167
# Whether or not the option is required.
168
#
169
attr_reader :required
170
#
171
# The description of the option.
172
#
173
attr_reader :desc
174
#
175
# The default value of the option.
176
#
177
attr_reader :default
178
#
179
# Storing the name of the option.
180
#
181
attr_writer :name
182
#
183
# Whether or not this is an advanced option.
184
#
185
attr_accessor :advanced
186
#
187
# Whether or not this is an evasion option.
188
#
189
attr_accessor :evasion
190
#
191
# The module or entity that owns this option.
192
#
193
attr_accessor :owner
194
#
195
# The list of potential conditions
196
#
197
attr_accessor :conditions
198
#
199
# The list of potential valid values
200
#
201
attr_accessor :enums
202
#
203
# A optional regex to validate the option value
204
#
205
attr_accessor :regex
206
207
#
208
# Array of aliases for this option for backward compatibility.
209
#
210
# This is useful in the scenario of an existing option being renamed
211
# to a new value. Either the current option name or list of aliases can
212
# be used in modules for retrieving datastore values, or by a user when
213
# setting datastore values manually.
214
#
215
# @return [Array<String>] the array of aliases
216
attr_accessor :aliases
217
218
#
219
# Array of fallbacks for this option.
220
#
221
# This is useful in the scenario of wanting specialised option names such as
222
# {SMBUser}, but to also support gracefully checking a list of more generic fallbacks
223
# option names such as {Username}.
224
#
225
# @return [Array<String>] the array of fallbacks
226
attr_accessor :fallbacks
227
228
#
229
# The max length of the input value
230
#
231
attr_accessor :max_length
232
233
protected
234
235
attr_writer :required, :desc, :default # :nodoc:
236
end
237
end
238
239