New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Deserialize JSON into MDM Objects #9394

Closed
wants to merge 57 commits into
base: master
from
Commits
Jump to file or symbol
Failed to load files and symbols.
+112 −25
Diff settings

Always

Just for now

Viewing a subset of changes. View all
@@ -1,15 +1,15 @@
module HostDataProxy
def hosts(wspace, non_dead = false, addresses = nil)
def hosts(wspace = workspace, non_dead = false, addresses = nil)
begin
data_service = self.get_data_service()
opts = {}
opts[:wspace] = wspace
opts[:non_dead] = non_dead
opts[:addresses] = addresses
data_service.hosts(opts)
rescue Exception => e
puts"Call to #{data_service.class}#hosts threw exception: #{e.message}"
rescue Exception => e
puts "Call to #{data_service.class}#hosts threw exception: #{e.message}"
end
end
@@ -24,18 +24,27 @@ def report_host(opts)
begin
data_service = self.get_data_service()
data_service.report_host(opts)
rescue Exception => e
puts"Call to #{data_service.class}#report_host threw exception: #{e.message}"
opts.each do |key, value| puts "#{key} : #{value}" end
rescue Exception => e
puts "Call to #{data_service.class}#report_host threw exception: #{e.message}"
opts.each { |k, v| puts "#{k} : #{v}" }
end
end
def report_hosts(hosts)
begin
data_service = self.get_data_service()
data_service.report_hosts(hosts)
rescue Exception => e
puts "Call to #{data_service.class}#report_hosts threw exception: #{e.message}"
rescue Exception => e
puts "Call to #{data_service.class}#report_hosts threw exception: #{e.message}"
end
end
def delete_host(opts)
begin
data_service = self.get_data_service()
data_service.delete_host(opts)
rescue Exception => e
puts "Call to #{data_service.class}#delete_host threw exception: #{e.message}"
end
end
@@ -18,6 +18,7 @@ class RemoteHTTPDataService
EXEC_ASYNC = { :exec_async => true }
GET_REQUEST = 'GET'
POST_REQUEST = 'POST'
DELETE_REQUEST = 'DELETE'
#
# @param endpoint - A RemoteServiceEndpoint. Cannot be nil
@@ -59,15 +60,29 @@ def get_data(path, data_hash = nil)
make_request(GET_REQUEST, path, data_hash)
end
#
# Send DELETE request to delete the specified resource from the HTTP endpoint
#
# @param path - The URI path to send the delete
# @param data_hash - A hash representation of the object to be deleted. Cannot be nil or empty.
#
# @return A wrapped response (ResponseWrapper), see below.
#
def delete_data(path, data_hash)
make_request(DELETE_REQUEST, path, data_hash)
end
def make_request(request_type, path, data_hash = nil)
begin
puts "#{Time.now} - HTTP #{request_type} request to #{path} with #{data_hash ? data_hash : "nil"}"
client = @client_pool.pop()
client = @client_pool.pop()
case request_type
when GET_REQUEST
request = Net::HTTP::Get.new(path)
when POST_REQUEST
request = Net::HTTP::Post.new(path)
when DELETE_REQUEST
request = Net::HTTP::Delete.new(path)
else
raise Exception, 'A request_type must be specified'
end
@@ -11,17 +11,22 @@ def hosts(opts)
end
def report_host(opts)
self.post_data_async(HOST_PATH, opts)
json_to_open_struct_object(self.post_data(HOST_PATH, opts))
end
def find_or_create_host(opts)
json_to_open_struct_object(self.post_data(HOST_PATH, host))
json_to_open_struct_object(self.post_data(HOST_PATH, opts))
end
def report_hosts(hosts)
self.post_data(HOST_PATH, hosts)
end
def delete_host(opts)
json_to_open_struct_object(self.delete_data(HOST_PATH, opts))
end
# TODO: Remove? What is the purpose of this method?
def do_host_search(search)
response = self.post_data(HOST_SEARCH_PATH, search)
return response.body
@@ -15,4 +15,8 @@ def hosts(opts)
def find_or_create_host(opts)
raise 'HostDataService#find_or_create_host is not implemented'
end
def delete_host(opts)
raise 'HostDataService#delete_host is not implemented'
end
end
@@ -1,4 +1,5 @@
module Msf::DBManager::Host
# TODO: doesn't appear to have any callers. How is this used?
# Deletes a host and associated data matching this address/comm
def del_host(wspace, address, comm='')
::ActiveRecord::Base.connection_pool.with_connection {
@@ -8,6 +9,41 @@ def del_host(wspace, address, comm='')
}
end
def delete_host(opts)
wspace = opts[:workspace] || opts[:wspace] || workspace
if wspace.is_a? String
wspace = find_workspace(wspace)
end
::ActiveRecord::Base.connection_pool.with_connection {
hosts = []
if opts[:address] || opts[:host]
opt_addr = opts[:address] || opts[:host]
host = wspace.hosts.find_by_address(opt_addr)
return { error: { message: "Unable to find host by specified address" } } if host.nil? || host.class != ::Mdm::Host
hosts << host
elsif opts[:addresses]
return { error: { message: "Unable to find host by specified addresses" } } if opts[:addresses].class != Array
hosts = wspace.hosts.where(address: opts[:addresses])
return { error: { message: "Unable to find hosts for specified addresses" } } if hosts.nil?
end
deleted = []
hosts.each do |host|
begin
host.destroy
deleted << host.address.to_s
rescue # refs suck
elog("Forcibly deleting #{host.address}")
host.delete
deleted << host.address.to_s
end
end
return { deleted: deleted }
}
end
#
# Iterates over the hosts table calling the supplied block with the host
# instance of each entry.
@@ -7,6 +7,7 @@ def self.api_path
def self.registered(app)
app.get HostServlet.api_path, &get_host
app.post HostServlet.api_path, &report_host
app.delete HostServlet.api_path, &delete_host
end
#######
@@ -28,8 +29,27 @@ def self.get_host
def self.report_host
lambda {
job = lambda { |opts| get_db().report_host(opts) }
begin
job = lambda { |opts|
data = get_db().report_host(opts)
}
exec_report_job(request, &job)
rescue Exception => e
set_error_on_response(e)
end
}
end
def self.delete_host
lambda {
begin
opts = parse_json_request(request, false)
data = get_db().delete_host(opts)
set_json_response(data)
rescue Exception => e
set_error_on_response(e)
end
}
end
end
@@ -585,7 +585,7 @@ def cmd_hosts(*args)
'SortIndex' => order_by
})
# Sentinal value meaning all
# Sentinel value meaning all
host_ranges.push(nil) if host_ranges.empty?
case
@@ -615,6 +615,8 @@ def cmd_hosts(*args)
end
each_host_range_chunk(host_ranges) do |host_search|
break if !host_search.nil? && host_search.empty?
framework.db.hosts(framework.db.workspace, onlyup, host_search).each do |host|
if search_term
next unless (
@@ -646,15 +648,11 @@ def cmd_hosts(*args)
addr = (host.scope ? host.address + '%' + host.scope : host.address)
rhosts << addr
end
if mode == [:delete]
begin
host.destroy
rescue # refs suck
print_error("Forcibly deleting #{host.address}")
host.delete
end
delete_count += 1
end
end
if mode == [:delete]
result = framework.db.delete_host(workspace: framework.db.workspace, addresses: host_search)
delete_count += result[:deleted].size
end
end
@@ -826,7 +824,7 @@ def cmd_services(*args)
'SortIndex' => order_by
})
# Sentinal value meaning all
# Sentinel value meaning all
host_ranges.push(nil) if host_ranges.empty?
ports = nil if ports.empty?
@@ -1293,7 +1291,7 @@ def cmd_loot(*args)
'Columns' => [ 'host', 'service', 'type', 'name', 'content', 'info', 'path' ],
})
# Sentinal value meaning all
# Sentinel value meaning all
host_ranges.push(nil) if host_ranges.empty?
if mode == :add
@@ -1952,7 +1950,7 @@ def each_host_range_chunk(host_ranges, &block)
# Chunk it up and do the query in batches. The naive implementation
# uses so much memory for a /8 that it's basically unusable (1.6
# billion IP addresses take a rather long time to allocate).
# Chunking has roughly the same perfomance for small batches, so
# Chunking has roughly the same performance for small batches, so
# don't worry about it too much.
host_ranges.each do |range|
if range.nil? or range.length.nil?
ProTip! Use n and p to navigate between commits in a pull request.