Land #3269 (Pro) fix report import issue
commit
e556997bf7
|
@ -2172,35 +2172,63 @@ class DBManager
|
|||
end
|
||||
|
||||
|
||||
#
|
||||
# Find or create a task matching this type/data
|
||||
#
|
||||
# TODO This method does not attempt to find. It just creates
|
||||
# a report based on the passed params.
|
||||
def find_or_create_report(opts)
|
||||
report_report(opts)
|
||||
end
|
||||
|
||||
# Creates a Report based on passed parameters. Does not handle
|
||||
# child artifacts.
|
||||
# @param opts [Hash]
|
||||
# @return [Integer] ID of created report
|
||||
def report_report(opts)
|
||||
return if not active
|
||||
::ActiveRecord::Base.connection_pool.with_connection {
|
||||
wspace = opts.delete(:workspace) || workspace
|
||||
path = opts.delete(:path) || (raise RuntimeError, "A report :path is required")
|
||||
|
||||
ret = {}
|
||||
user = opts.delete(:user)
|
||||
options = opts.delete(:options)
|
||||
rtype = opts.delete(:rtype)
|
||||
report = wspace.reports.new
|
||||
report.created_by = user
|
||||
report.options = options
|
||||
report.rtype = rtype
|
||||
report.path = path
|
||||
msf_import_timestamps(opts,report)
|
||||
report.save!
|
||||
report = Report.new(opts)
|
||||
unless report.valid?
|
||||
errors = report.errors.full_messages.join('; ')
|
||||
raise RuntimeError "Report to be imported is not valid: #{errors}"
|
||||
end
|
||||
report.state = :complete # Presume complete since it was exported
|
||||
report.save
|
||||
|
||||
ret[:task] = report
|
||||
report.id
|
||||
}
|
||||
end
|
||||
|
||||
# Creates a ReportArtifact based on passed parameters.
|
||||
# @param opts [Hash] of ReportArtifact attributes
|
||||
def report_artifact(opts)
|
||||
artifacts_dir = Report::ARTIFACT_DIR
|
||||
tmp_path = opts[:file_path]
|
||||
artifact_name = File.basename tmp_path
|
||||
new_path = File.join(artifacts_dir, artifact_name)
|
||||
|
||||
unless File.exists? tmp_path
|
||||
raise DBImportError 'Report artifact file to be imported does not exist.'
|
||||
end
|
||||
|
||||
unless (File.directory?(artifacts_dir) && File.writable?(artifacts_dir))
|
||||
raise DBImportError "Could not move report artifact file to #{artifacts_dir}."
|
||||
end
|
||||
|
||||
if File.exists? new_path
|
||||
unique_basename = "#{(Time.now.to_f*1000).to_i}_#{artifact_name}"
|
||||
new_path = File.join(artifacts_dir, unique_basename)
|
||||
end
|
||||
|
||||
FileUtils.copy(tmp_path, new_path)
|
||||
opts[:file_path] = new_path
|
||||
artifact = ReportArtifact.new(opts)
|
||||
unless artifact.valid?
|
||||
errors = artifact.errors.full_messages.join('; ')
|
||||
raise RuntimeError "Artifact to be imported is not valid: #{errors}"
|
||||
end
|
||||
artifact.save
|
||||
end
|
||||
|
||||
#
|
||||
# This methods returns a list of all reports in the database
|
||||
#
|
||||
|
@ -3793,43 +3821,55 @@ class DBManager
|
|||
|
||||
# Import Reports
|
||||
doc.elements.each("/#{btag}/reports/report") do |report|
|
||||
tmp = args[:ifd][:zip_tmp]
|
||||
report_info = {}
|
||||
report_info[:workspace] = args[:wspace]
|
||||
# Should user be imported (original) or declared (the importing user)?
|
||||
report_info[:user] = nils_for_nulls(report.elements["created-by"].text.to_s.strip)
|
||||
report_info[:options] = nils_for_nulls(report.elements["options"].text.to_s.strip)
|
||||
report_info[:rtype] = nils_for_nulls(report.elements["rtype"].text.to_s.strip)
|
||||
report_info[:created_at] = nils_for_nulls(report.elements["created-at"].text.to_s.strip)
|
||||
report_info[:updated_at] = nils_for_nulls(report.elements["updated-at"].text.to_s.strip)
|
||||
report_info[:orig_path] = nils_for_nulls(report.elements["path"].text.to_s.strip)
|
||||
report_info[:task] = args[:task]
|
||||
report_info[:orig_path].gsub!(/^\./, tmp) if report_info[:orig_path]
|
||||
|
||||
# Only report a report if we actually have it.
|
||||
# TODO: Copypasta. Seperate this out.
|
||||
if ::File.exists? report_info[:orig_path]
|
||||
reports_dir = ::File.join(basedir,"reports")
|
||||
report_file = ::File.split(report_info[:orig_path]).last
|
||||
if ::File.exists? reports_dir
|
||||
unless (::File.directory?(reports_dir) && ::File.writable?(reports_dir))
|
||||
raise DBImportError.new("Could not move files to #{reports_dir}")
|
||||
end
|
||||
else
|
||||
::FileUtils.mkdir_p(reports_dir)
|
||||
end
|
||||
new_report = ::File.join(reports_dir,report_file)
|
||||
report_info[:path] = new_report
|
||||
if ::File.exists?(new_report)
|
||||
::File.unlink new_report
|
||||
else
|
||||
report_report(report_info)
|
||||
end
|
||||
::FileUtils.copy(report_info[:orig_path], new_report)
|
||||
yield(:msf_report, new_report) if block
|
||||
end
|
||||
import_report(report, args, basedir)
|
||||
end
|
||||
end
|
||||
|
||||
# @param report [REXML::Element] to be imported
|
||||
# @param args [Hash]
|
||||
# @param base_dir [String]
|
||||
def import_report(report, args, base_dir)
|
||||
tmp = args[:ifd][:zip_tmp]
|
||||
report_info = {}
|
||||
|
||||
report.elements.each do |e|
|
||||
node_name = e.name
|
||||
node_value = e.text
|
||||
|
||||
# These need to be converted back to arrays:
|
||||
array_attrs = %w|addresses file-formats options sections|
|
||||
if array_attrs.member? node_name
|
||||
node_value = JSON.parse(node_value)
|
||||
end
|
||||
# Don't restore these values:
|
||||
skip_nodes = %w|id workspace-id artifacts|
|
||||
next if skip_nodes.member? node_name
|
||||
|
||||
report_info[node_name.parameterize.underscore.to_sym] = node_value
|
||||
end
|
||||
# Use current workspace
|
||||
report_info[:workspace_id] = args[:wspace].id
|
||||
|
||||
# Create report, need new ID to record artifacts
|
||||
report_id = report_report(report_info)
|
||||
|
||||
# Handle artifacts
|
||||
report.elements['artifacts'].elements.each do |artifact|
|
||||
artifact_opts = {}
|
||||
artifact.elements.each do |attr|
|
||||
skip_nodes = %w|id accessed-at|
|
||||
next if skip_nodes.member? attr.name
|
||||
|
||||
symboled_attr = attr.name.parameterize.underscore.to_sym
|
||||
artifact_opts[symboled_attr] = attr.text
|
||||
end
|
||||
# Use new Report as parent
|
||||
artifact_opts[:report_id] = report_id
|
||||
# Update to full path
|
||||
artifact_opts[:file_path].gsub!(/^\./, tmp)
|
||||
|
||||
report_artifact(artifact_opts)
|
||||
end
|
||||
end
|
||||
|
||||
# Convert the string "NULL" to actual nil
|
||||
|
|
Loading…
Reference in New Issue