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) ⇒ Hash
Create a JSON-RPC error response.
-
.create_success_response(result, request = nil) ⇒ Hash
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) ⇒ Hash?
Validate and execute the JSON-RPC request.
-
#set_command(command) ⇒ Object
Set the command.
-
#validate_rpc_request(request) ⇒ Boolean
Validate the JSON-RPC request.
Constructor Details
#initialize(framework) ⇒ Dispatcher
Instantiate a Dispatcher.
33 34 35 36 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 33 def initialize(framework) @framework = framework @command = nil end |
Instance Attribute Details
#command ⇒ Object (readonly)
Returns the value of attribute command.
29 30 31 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 29 def command @command end |
#framework ⇒ Object (readonly)
Returns the value of attribute framework.
28 29 30 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 28 def framework @framework end |
Class Method Details
.add_response_id_member(response, request) ⇒ Object
Adds response id based on request id.
208 209 210 211 212 213 214 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 208 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) ⇒ Hash
Create a JSON-RPC error response.
189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 189 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) ⇒ Hash
Create a JSON-RPC success response.
169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 169 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.
158 159 160 161 162 163 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 158 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.
147 148 149 150 151 152 153 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 147 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.
48 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 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 48 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) ⇒ Hash?
Validate and execute the JSON-RPC request.
88 89 90 91 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 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 88 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.
40 41 42 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 40 def set_command(command) @command = command end |
#validate_rpc_request(request) ⇒ Boolean
Validate the JSON-RPC request.
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 |
# File 'lib/msf/core/rpc/json/dispatcher.rb', line 124 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 |