5e495d72f5
When passed arguments as `opts` prefer to avoid side-effects from method execution. This extends similar work from #12740
77 lines
2.1 KiB
Ruby
77 lines
2.1 KiB
Ruby
module Msf::DBManager::Client
|
|
def find_or_create_client(opts)
|
|
report_client(opts)
|
|
end
|
|
|
|
def get_client(opts)
|
|
::ApplicationRecord.connection_pool.with_connection {
|
|
opts = opts.clone() # protect the original caller's opts
|
|
wspace = opts.delete(:workspace) || workspace
|
|
host = get_host(:workspace => wspace, :host => opts[:host]) || return
|
|
client = host.clients.where({:ua_string => opts[:ua_string]}).first()
|
|
return client
|
|
}
|
|
end
|
|
|
|
#
|
|
# Report a client running on a host.
|
|
#
|
|
# opts MUST contain
|
|
# +:ua_string+:: the value of the User-Agent header
|
|
# +:host+:: the host where this client connected from, can be an ip address or a Host object
|
|
#
|
|
# opts can contain
|
|
# +:ua_name+:: one of the Msf::HttpClients constants
|
|
# +:ua_ver+:: detected version of the given client
|
|
# +:campaign+:: an id or Campaign object
|
|
#
|
|
# Returns a Client.
|
|
#
|
|
def report_client(opts)
|
|
return if !active
|
|
::ApplicationRecord.connection_pool.with_connection {
|
|
opts = opts.clone() # protect the original caller's opts
|
|
addr = opts.delete(:host) || return
|
|
wspace = opts.delete(:workspace) || workspace
|
|
report_host(:workspace => wspace, :host => addr)
|
|
|
|
ret = {}
|
|
|
|
host = get_host(:workspace => wspace, :host => addr)
|
|
client = host.clients.where(ua_string: opts[:ua_string]).first_or_initialize
|
|
|
|
opts[:ua_string] = opts[:ua_string].to_s
|
|
|
|
campaign = opts.delete(:campaign)
|
|
if campaign
|
|
case campaign
|
|
when Campaign
|
|
opts[:campaign_id] = campaign.id
|
|
else
|
|
opts[:campaign_id] = campaign
|
|
end
|
|
end
|
|
|
|
opts.each do |k,v|
|
|
if (client.attribute_names.include?(k.to_s))
|
|
client[k] = v
|
|
elsif !v.blank?
|
|
dlog("Unknown attribute for Client: #{k}")
|
|
end
|
|
end
|
|
|
|
begin
|
|
framework.events.on_db_client(client) if client.new_record?
|
|
rescue ::Exception => e
|
|
wlog("Exception in on_db_client event handler: #{e.class}: #{e}")
|
|
wlog("Call Stack\n#{e.backtrace.join("\n")}")
|
|
end
|
|
|
|
if client && client.changed?
|
|
client.save!
|
|
end
|
|
ret[:client] = client
|
|
}
|
|
end
|
|
end
|