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