Class: Msf::RPC::JSON::Dispatcher
- Inherits:
-
Object
- Object
- Msf::RPC::JSON::Dispatcher
- Defined in:
- lib/msf/core/rpc/json/dispatcher.rb
Constant Summary collapse
- JSON_RPC_VERSION =
'2.0'
- JSON_RPC_REQUIRED_MEMBERS =
%i(jsonrpc method)
- JSON_RPC_MEMBER_TYPES =
{ # A String specifying the version of the JSON-RPC protocol. jsonrpc: [String], # A String containing the name of the method to be invoked. method: [String], # If present, parameters for the rpc call MUST be provided as a Structured # value. Either by-position through an Array or by-name through an Object. # * by-position: params MUST be an Array, containing the values in the # Server expected order. # * by-name: params MUST be an Object, with member names that match the # Server expected parameter names. The absence of expected names MAY # result in an error being generated. The names MUST match exactly, # including case, to the method's expected parameters. params: [Array, Hash], # An identifier established by the Client that MUST contain a String, # Number, or NULL value if included. If it is not included it is assumed # to be a notification. The value SHOULD normally not be Null [1] and # Numbers SHOULD NOT contain fractional parts [2] id: [Integer, String, NilClass] }
Instance Attribute Summary collapse
-
#command ⇒ Object
readonly
Returns the value of attribute command.
-
#framework ⇒ Object
readonly
Returns the value of attribute framework.
Class Method Summary collapse
-
.add_response_id_member(response, request) ⇒ Object
Adds response id based on request id.
-
.create_error_response(error, request = nil) ⇒ Object
Create a JSON-RPC error response.
-
.create_success_response(result, request = nil) ⇒ Object
Create a JSON-RPC success response.
-
.to_json(data) ⇒ String
Serialize data as JSON string.
Instance Method Summary collapse
-
#initialize(framework) ⇒ Dispatcher
constructor
Instantiate a Dispatcher.
-
#parse_json_request(source) ⇒ Hash or Array
Parse the JSON document source into a Hash or Array with symbols for the names (keys).
-
#process(source) ⇒ String
Process the JSON-RPC request.
-
#process_request(request) ⇒ Object
Validate and execute the JSON-RPC request.
-
#set_command(command) ⇒ Object
Set the command.
-
#validate_rpc_request(request) ⇒ Object
Validate the JSON-RPC request.
Constructor Details
#initialize(framework) ⇒ Dispatcher
Instantiate a Dispatcher.
34 35 36 37 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 34 def initialize(framework) @framework = framework @command = nil end |
Instance Attribute Details
#command ⇒ Object (readonly)
Returns the value of attribute command
30 31 32 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 30 def command @command end |
#framework ⇒ Object (readonly)
Returns the value of attribute framework
29 30 31 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 29 def framework @framework end |
Class Method Details
.add_response_id_member(response, request) ⇒ Object
Adds response id based on request id.
212 213 214 215 216 217 218 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 212 def self.add_response_id_member(response, request) if !request.nil? && request.key?(:id) response[:id] = request[:id] else response[:id] = nil end end |
.create_error_response(error, request = nil) ⇒ Object
Create a JSON-RPC error response.
193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 193 def self.create_error_response(error, request = nil) response = { # A String specifying the version of the JSON-RPC protocol. jsonrpc: JSON_RPC_VERSION, # This member is REQUIRED on error. # This member MUST NOT exist if there was no error triggered during invocation. # The value for this member MUST be an Object as defined in section 5.1. error: error.to_h } self.add_response_id_member(response, request) response end |
.create_success_response(result, request = nil) ⇒ Object
Create a JSON-RPC success response.
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 173 def self.create_success_response(result, request = nil) response = { # A String specifying the version of the JSON-RPC protocol. jsonrpc: JSON_RPC_VERSION, # This member is REQUIRED on success. # This member MUST NOT exist if there was an error invoking the method. # The value of this member is determined by the method invoked on the Server. result: result } self.add_response_id_member(response, request) response end |
.to_json(data) ⇒ String
Serialize data as JSON string.
162 163 164 165 166 167 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 162 def self.to_json(data) return nil if data.nil? json = data.to_json return json.to_s end |
Instance Method Details
#parse_json_request(source) ⇒ Hash or Array
Parse the JSON document source into a Hash or Array with symbols for the names (keys). An error occurred on the server while parsing the JSON text.
151 152 153 154 155 156 157 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 151 def parse_json_request(source) begin JSON.parse(source, symbolize_names: true) rescue raise ParseError.new end end |
#process(source) ⇒ String
Process the JSON-RPC request. if successful; otherwise, a JSON-RPC error response.
49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 49 def process(source) begin request = parse_json_request(source) if request.is_a?(Array) # If the batch rpc call itself fails to be recognized as an valid # JSON or as an Array with at least one value, the response from # the Server MUST be a single Response object. raise InvalidRequest.new if request.empty? # process batch request response = request.map { |r| process_request(r) } # A Response object SHOULD exist for each Request object, except that # there SHOULD NOT be any Response objects for notifications. # Remove nil responses from response array response.compact! else response = process_request(request) end rescue ParseError, InvalidRequest => e # If there was an error in detecting the id in the Request object # (e.g. Parse error/Invalid Request), then the id member MUST be # Null. Don't pass request obj when building the error response. response = self.class.create_error_response(e) rescue RpcError => e # other JSON-RPC errors should include the id from the Request object response = self.class.create_error_response(e, request) rescue => e response = self.class.create_error_response(ApplicationServerError.new(e), request) end # When a rpc call is made, the Server MUST reply with a Response, except # for in the case of Notifications. The Response is expressed as a single # JSON Object. self.class.to_json(response) end |
#process_request(request) ⇒ Object
Validate and execute the JSON-RPC request. Msf::RPC::Exception that occurred during execution. if successful; otherwise, a JSON-RPC error response.
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 92 def process_request(request) begin if !validate_rpc_request(request) response = self.class.create_error_response(InvalidRequest.new) return response end # dispatch method execution to command result = @command.execute(request[:method], request[:params]) # A Notification is a Request object without an "id" member. A Request # object that is a Notification signifies the Client's lack of interest # in the corresponding Response object, and as such no Response object # needs to be returned to the client. The Server MUST NOT reply to a # Notification, including those that are within a batch request. if request.key?(:id) response = self.class.create_success_response(result, request) else response = nil end response rescue Msf::OptionValidateError => e raise InvalidParams.new(data: { options: e., message: e. }) rescue ::NoMethodError => e raise MethodNotFound.new(e.name, data: { method: e.name, message: e. }) rescue ArgumentError raise InvalidParams.new rescue Msf::RPC::Exception => e raise ApplicationServerError.new(e., data: { code: e.code }) end end |
#set_command(command) ⇒ Object
Set the command.
41 42 43 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 41 def set_command(command) @command = command end |
#validate_rpc_request(request) ⇒ Object
Validate the JSON-RPC request.
128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 128 def validate_rpc_request(request) # validate request is an object return false unless request.is_a?(Hash) # validate request contains required members JSON_RPC_REQUIRED_MEMBERS.each { |member| return false unless request.key?(member) } return false if request[:jsonrpc] != JSON_RPC_VERSION # validate request members are correct types request.each do |member, value| return false if JSON_RPC_MEMBER_TYPES.key?(member) && !JSON_RPC_MEMBER_TYPES[member].one? { |type| value.is_a?(type) } end true end |