diff --git a/documentation/samples/express/discover_rpc.rb b/documentation/samples/express/discover_rpc.rb deleted file mode 100755 index ab720d1623..0000000000 --- a/documentation/samples/express/discover_rpc.rb +++ /dev/null @@ -1,41 +0,0 @@ -#!/usr/bin/env ruby - - -## Note, you may need to change this, depending on the install path of your -## metasploit instance -require '/opt/metasploit-3.5.0/apps/pro/engine/lib/pro/client' - -pro = Pro::Client.new() ## this will connect to the rpc service running on localhost:50505 - -pro.call('db.add_workspace', "default") ## create a workspace -pro.call('db.set_workspace', "default") ## set that workspace - -conf = { - 'workspace' => "default", - 'username' => "rpc", - "ips" => ['10.0.0.0/24'], - 'DS_BLACKLIST_HOSTS' => "10.0.0.1 10.0.0.2", - 'DS_PORTSCAN_SPEED' => "3", - 'DS_PORTS_EXTRA' => "", - 'DS_PORTS_BLACKLIST' => "", - 'DS_PORTS_CUSTOM' => "", - 'DS_PORTSCAN_TIMEOUT' => "5", - 'DS_UDP_PROBES' => "true", - 'DS_IDENTIFY_SERVICES' => "true", - 'DS_SMBUser' => "", - 'DS_SMBPass' => "", - 'DS_SMBDomain' => "", - 'DS_DRY_RUN' => "false", - 'DS_SINGLE_SCAN' => "false", - 'DS_FAST_DETECT' => "false", - 'DS_CustomNmap' => "--reason" -} - -puts "starting discover task" -ret = pro.start_discover(conf) - -task_id = ret['task_id'] -puts "started discover task " + task_id - -pro.task_wait(ret['task_id']) -puts "done!" diff --git a/documentation/samples/express/nexpose_rpc.rb b/documentation/samples/express/nexpose_rpc.rb deleted file mode 100755 index 3c30d8fa5b..0000000000 --- a/documentation/samples/express/nexpose_rpc.rb +++ /dev/null @@ -1,31 +0,0 @@ -#!/usr/bin/env ruby - -require '/opt/metasploit-3.5.0/apps/pro/engine/lib/pro/client' - -pro = Pro::Client.new() ## this will connect to the rpc service running on localhost:50505 - -pro.call('db.add_workspace', "nexpose_custom_scan") ## create a workspace -pro.call('db.set_workspace', "nexpose_custom_scan") ## set that workspace - -conf = { - 'workspace' => "default", - 'username' => "rpc", - 'DS_WHITELIST_HOSTS' => "10.0.0.1", - 'DS_BLACKLIST_HOSTS' => "", - 'DS_NEXPOSE_HOST' => "localhost", - 'DS_NEXPOSE_PORT' => "3780", - 'DS_NEXPOSE_USER' => "nxadmin" , - 'DS_SCAN_TEMPLATE' => "custom-nmap-scan-template", - 'nexpose_pass' => "password", - 'nexpose_credentials' => "", - 'DS_NEXPOSE_PURGE_SITE' => "false" -} - -puts "starting nexpose task" -ret = pro.start_nexpose(conf) - -task_id = ret['task_id'] -puts "started nexpose task " + task_id - -pro.task_wait(ret['task_id']) -puts "done!" diff --git a/documentation/samples/pro/msfrpc_pro_discover.rb b/documentation/samples/pro/msfrpc_pro_discover.rb new file mode 100644 index 0000000000..630acf3db8 --- /dev/null +++ b/documentation/samples/pro/msfrpc_pro_discover.rb @@ -0,0 +1,207 @@ +#!/usr/bin/env ruby +require 'rubygems' +require 'optparse' +require 'msfrpc-client' +require 'rex/ui' + +def usage(ropts) + $stderr.puts ropts + + if @rpc and @rpc.token + wspaces = @rpc.call("pro.workspaces") rescue {} + if wspaces.keys.length > 0 + $stderr.puts "Active Projects:" + wspaces.each_pair do |k,v| + $stderr.puts "\t#{k}" + end + end + end + $stderr.puts "" + exit(1) +end + +opts = {} + +# Parse script-specific options +parser = Msf::RPC::Client.option_parser(opts) +parser.separator('Discover Mandatory Options:') + +parser.on("--project PROJECT") do |x| + opts[:project] = x +end + +parser.on("--targets TARGETS") do |x| + opts[:targets] = [x] +end + +parser.on("--blacklist BLACKLIST (optional)") do |x| + opts[:blacklist] = x +end + +parser.on("--speed SPEED (optional)") do |x| + opts[:speed] = x +end + +parser.on("--extra-ports PORTS (optional)") do |x| + opts[:extra_ports] = x +end + +parser.on("--blacklist-ports PORTS (optional)") do |x| + opts[:blacklist_ports] = x +end + +parser.on("--custom-ports PORTS (optional)") do |x| + opts[:custom_ports] = x +end + +parser.on("--portscan-timeout TIMEOUT (optional)") do |x| + opts[:portscan_timeout] = x +end + +parser.on("--source-port PORT (optional)") do |x| + opts[:source_port] = x +end + +parser.on("--custom-nmap-options OPTIONS (optional)") do |x| + opts[:custom_nmap_options] = x +end + +parser.on("--disable-udp-probes (optional)") do + opts[:disable_udp_probes] = true +end + +parser.on("--disable-finger-users (optional)") do + opts[:disable_finger_users] = true +end + +parser.on("--disable-snmp-scan (optional)") do + opts[:disable_snmp_scan] = true +end + +parser.on("--disable-service-identification (optional)") do + opts[:disable_service_identification] = true +end + +parser.on("--smb-user USER (optional)") do |x| + opts[:smb_user] = x +end + +parser.on("--smb-pass PASS (optional)") do |x| + opts[:smb_pass] = x +end + +parser.on("--smb-domain DOMAIN (optional)") do |x| + opts[:smb_domain] = x +end + +parser.on("--dry-run (optional)") do + opts[:dry_run] = true +end + +parser.on("--single-scan (optional)") do + opts[:single_scan] = true +end + +parser.on("--fast-detect (optional)") do + opts[:fast_detect] = true +end + +parser.on("--help") do + $stderr.puts opts + exit(1) +end + +parser.separator('') +parser.parse!(ARGV) + +@rpc = Msf::RPC::Client.new(opts) + +if not @rpc.token + $stderr.puts "Error: Invalid RPC server options specified" + $stderr.puts parser + exit(1) +end + +# Provide default values for certain options - If there's no alternative set +# use the default provided by Pro -- see the documentation. +project = opts[:project] || usage(parser) +targets = opts[:targets] || usage(parser) +blacklist = opts[:blacklist] +speed = opts[:speed] || "Insane" +extra_ports = opts[:extra_ports] +blacklist_ports = opts[:blacklist_ports] +custom_ports = opts[:custom_ports] +portscan_timeout = opts[:portscan_timeout] || 300 +source_port = opts[:source_port] +custom_nmap_options = opts[:custom_nmap_options] || +disable_udp_probes = opts[:disable_udp_probes] || false +disable_finger_users = opts[:disable_finger_users] || false +disable_snmp_scan = opts[:disable_snmp_scan] || false +disable_service_identification = opts[:disable_service_identification] || false +smb_user = opts[:smb_user] || "" +smb_pass = opts[:smb_pass] || "" +smb_domain = opts[:smb_domain] || "" +single_scan = opts[:single_scan] || false +fast_detect = opts[:fast_detect] || false + +# Get the default user from Pro +user = @rpc.call("pro.default_admin_user")['username'] + +# Create the task object with all options +task = @rpc.call("pro.start_discover", { + 'workspace' => project, + 'username' => user, + 'ips' => targets, + 'DS_BLACKLIST_HOSTS' => blacklist, + 'DS_PORTSCAN_SPEED' => speed, + 'DS_PORTS_EXTRA' => extra_ports, + 'DS_PORTS_BLACKLIST' => blacklist_ports, + 'DS_PORTS_CUSTOM' => custom_ports, + 'DS_PORTSCAN_TIMEOUT' => portscan_timeout, + 'DS_PORTSCAN_SOURCE_PORT' => source_port, + 'DS_CustomNmap' => custom_nmap_options, + 'DS_UDP_PROBES' => disable_udp_probes, + 'DS_FINGER_USERS' => disable_finger_users, + 'DS_SNMP_SCAN' => disable_snmp_scan, + 'DS_IDENTIFY_SERVICES' => disable_service_identification, + 'DS_SMBUser' => smb_user, + 'DS_SMBPass' => smb_pass, + 'DS_SMBDomain' => smb_domain, + 'DS_SINGLE_SCAN' => single_scan, + 'DS_FAST_DETECT' => fast_detect +}) + +puts "DEBUG: Running task with #{task.inspect}" + +if not task['task_id'] + $stderr.puts "[-] Error starting the task: #{task.inspect}" + exit(0) +end + +puts "[*] Creating Task ID #{task['task_id']}..." +while true + select(nil, nil, nil, 0.50) + + stat = @rpc.call("pro.task_status", task['task_id']) + + if stat['status'] == 'invalid' + $stderr.puts "[-] Error checking task status" + exit(0) + end + + info = stat[ task['task_id'] ] + + if not info + $stderr.puts "[-] Error finding the task" + exit(0) + end + + if info['status'] == "error" + $stderr.puts "[-] Error generating report: #{info['error']}" + exit(0) + end + + break if info['progress'] == 100 +end + +$stdout.puts "[+] Task Complete!" diff --git a/documentation/samples/pro/msfrpc_pro_exploit.rb b/documentation/samples/pro/msfrpc_pro_exploit.rb new file mode 100644 index 0000000000..9dab5b486a --- /dev/null +++ b/documentation/samples/pro/msfrpc_pro_exploit.rb @@ -0,0 +1,209 @@ +#!/usr/bin/env ruby +require 'rubygems' +require 'optparse' +require 'msfrpc-client' +require 'rex/ui' + +def usage(ropts) + $stderr.puts ropts + + if @rpc and @rpc.token + wspaces = @rpc.call("pro.workspaces") rescue {} + if wspaces.keys.length > 0 + $stderr.puts "Active Projects:" + wspaces.each_pair do |k,v| + $stderr.puts "\t#{k}" + end + end + end + $stderr.puts "" + exit(1) +end + +opts = {} + +# Parse script-specific options +parser = Msf::RPC::Client.option_parser(opts) +parser.separator('Exploit Specific Options:') + +parser.on("--project PROJECT") do |x| + opts[:project] = x +end + +parser.on("--targets TARGETS") do |x| + opts[:targets] = [x] +end + +parser.on("--speed SPEED") do |x| + opts[:speed] = x +end + +parser.on("--minimum-rank RANK") do |x| + opts[:rank] = x +end + +parser.on("--blacklist BLACKLIST (optional)") do |x| + opts[:blacklist] = x +end + +parser.on("--whitelist-ports PORTS (optional)") do |x| + opts[:whitelist_ports] = x +end + +parser.on("--blacklist-ports PORTS (optional)") do |x| + opts[:blacklist_ports] = x +end + +parser.on("--exploit-timeout TIMEOUT (optional)") do |x| + opts[:exploit_timeout] = x +end + +parser.on("--limit-sessions (optional)") do + opts[:limit_sessions] = true +end + +parser.on("--ignore-fragile-devices (optional)") do + opts[:ignore_fragile_devices] = true +end + +parser.on("--filter-by-os (optional)") do + opts[:filter_by_os] = true +end + +parser.on("--dry-run (optional)") do + opts[:only_match] = true +end + +parser.on("--match-vulns (optional)") do + opts[:match_vulns] = true +end + +parser.on("--match-ports (optional)") do + opts[:match_ports] = true +end + +parser.on("--payload-method AUTO|REVERSE|BIND (optional)") do |x| + opts[:payload_method] = x +end + +parser.on("--payload-type METERPRETER|SHELL (optional)") do |x| + opts[:payload_type] = x +end + +parser.on("--payload-ports PORTS (optional)") do |x| + opts[:payload_ports] = x +end + +parser.on("--evasion-level-tcp LEVEL (optional)") do |x| + opts[:evasion_level_tcp] = x +end + +parser.on("--evasion-level-app LEVEL (optional)") do |x| + opts[:evasion_level_app] = x +end + +parser.on("--module-filter FILTER (optional)") do |x| + opts[:module_filter] = x +end + +parser.on("--help") do + $stderr.puts opts + exit(1) +end + +parser.separator('') +parser.parse!(ARGV) + +@rpc = Msf::RPC::Client.new(opts) + +if not @rpc.token + $stderr.puts "Error: Invalid RPC server options specified" + $stderr.puts parser + exit(1) +end + +# Store the user's settings +project = opts[:project] || usage(parser), +targets = opts[:targets] || usage(parser), +rank = opts[:rank] || usage(parser), +speed = opts[:speed] || usage(parser), +blacklist = opts[:blacklist], +whitelist_ports = opts[:whitelist_ports], +blacklist_ports = opts[:blacklist_ports], +exploit_timeout = opts[:exploit_timeout], +limit_sessions = opts[:limit_sessions], +ignore_fragile_devices = opts[:ignore_fragile_devices], +filter_by_os = opts[:filter_by_os], +only_match = opts[:only_match], #dry run? +match_vulns = opts[:match_vulns] || true, +match_ports = opts[:match_ports] || true, +payload_method = opts[:payload_method], +payload_type = opts[:payload_type], +payload_ports = opts[:payload_ports], +evasion_level_tcp = opts[:evasion_level_tcp], +evasion_level_app = opts[:evasion_level_app], +module_filter = opts[:module_filter] + +# Get the default user +user = @rpc.call("pro.default_admin_user")['username'] + +# Create the task object with all options +task = @rpc.call("pro.start_exploit", { + 'workspace' => project, + 'username' => user, + 'DS_PATH' => path, + 'DS_WHITELIST_HOSTS' => targets, + 'DS_BLACKLIST_HOSTS' => blacklist, + 'DS_WHITELIST_PORTS' => whitelist_ports, + 'DS_BLACKLIST_PORTS' => blacklist_ports, + 'DS_MinimumRank' => rank, + 'DS_EXPLOIT_SPEED' => speed, + 'DS_EXPLOIT_TIMEOUT' => exploit_timeout, + 'DS_LimitSessions' => limit_sessions, + 'DS_IgnoreFragileDevices' => ignore_fragile_devices, + 'DS_FilterByOS' => filter_by_os, + 'DS_OnlyMatch' => only_match, #dry run? + 'DS_MATCH_VULNS' => match_vulns, + 'DS_MATCH_PORTS' => match_ports, + 'DS_PAYLOAD_METHOD' => payload_method, + 'DS_PAYLOAD_TYPE' => payload_type, + 'DS_PAYLOAD_PORTS' => payload_ports, + 'DS_EVASION_LEVEL_TCP' => evasion_level_tcp, + 'DS_EVASION_LEVEL_APP' => evasion_level_app, + 'DS_ModuleFilter' => module_filter +}) + +puts "DEBUG: Running task with #{task.inspect}" + +if not task['task_id'] + $stderr.puts "[-] Error starting the task: #{task.inspect}" + exit(0) +end + +puts "[*] Creating Task ID #{task['task_id']}..." +while true + select(nil, nil, nil, 0.50) + + stat = @rpc.call("pro.task_status", task['task_id']) + + if stat['status'] == 'invalid' + $stderr.puts "[-] Error checking task status" + exit(0) + end + + info = stat[ task['task_id'] ] + + if not info + $stderr.puts "[-] Error finding the task" + exit(0) + end + + if info['status'] == "error" + $stderr.puts "[-] Error generating report: #{info['error']}" + exit(0) + end + + break if info['progress'] == 100 +end + +$stdout.puts "[+] Task Complete!" diff --git a/documentation/samples/pro/msfrpc_pro_import.rb b/documentation/samples/pro/msfrpc_pro_import.rb new file mode 100644 index 0000000000..685807f28a --- /dev/null +++ b/documentation/samples/pro/msfrpc_pro_import.rb @@ -0,0 +1,91 @@ +#!/usr/bin/env ruby +require 'rubygems' +require 'optparse' +require 'msfrpc-client' +require 'rex/ui' + +def usage(ropts) + $stderr.puts ropts + + if @rpc and @rpc.token + wspaces = @rpc.call("pro.workspaces") rescue {} + if wspaces.keys.length > 0 + $stderr.puts "Active Projects:" + wspaces.each_pair do |k,v| + $stderr.puts "\t#{k}" + end + end + end + exit(1) +end + +opts = {} + +# Parse script-specific options +parser = Msf::RPC::Client.option_parser(opts) +parser.separator('Task Options:') + +parser.on("--path PATH") do |path| + opts[:path] = path +end + +parser.on("--project PROJECT") do |project| + opts[:project] = project +end + +parser.on("--help") do + $stderr.puts ropts + exit(1) +end +parser.separator('') + +parser.parse!(ARGV) +@rpc = Msf::RPC::Client.new(opts) + +if not @rpc.token + $stderr.puts "Error: Invalid RPC server options specified" + $stderr.puts parser + exit(1) +end + +project = opts[:project] || usage(parser) +path = opts[:path] || usage(parser) +user = @rpc.call("pro.default_admin_user")['username'] +task = @rpc.call("pro.start_import", { + 'workspace' => project, + 'username' => user, + 'DS_PATH' => path +}) + +if not task['task_id'] + $stderr.puts "[-] Error starting the task: #{task.inspect}" + exit(0) +end + +puts "[*] Creating Task ID #{task['task_id']}..." +while true + select(nil, nil, nil, 0.50) + + stat = @rpc.call("pro.task_status", task['task_id']) + + if stat['status'] == 'invalid' + $stderr.puts "[-] Error checking task status" + exit(0) + end + + info = stat[ task['task_id'] ] + + if not info + $stderr.puts "[-] Error finding the task" + exit(0) + end + + if info['status'] == "error" + $stderr.puts "[-] Error generating report: #{info['error']}" + exit(0) + end + + break if info['progress'] == 100 +end + +$stdout.puts "[+] Task Complete!" diff --git a/documentation/samples/pro/msfrpc_pro_nexpose.rb b/documentation/samples/pro/msfrpc_pro_nexpose.rb new file mode 100644 index 0000000000..451ec4832c --- /dev/null +++ b/documentation/samples/pro/msfrpc_pro_nexpose.rb @@ -0,0 +1,148 @@ +#!/usr/bin/env ruby +require 'rubygems' +require 'optparse' +require 'msfrpc-client' +require 'rex/ui' + +def usage(ropts) + $stderr.puts ropts + + if @rpc and @rpc.token + wspaces = @rpc.call("pro.workspaces") rescue {} + if wspaces.keys.length > 0 + $stderr.puts "Active Projects:" + wspaces.each_pair do |k,v| + $stderr.puts "\t#{k}" + end + end + end + $stderr.puts "" + exit(1) +end + +opts = {} + +# Parse script-specific options +parser = Msf::RPC::Client.option_parser(opts) +parser.separator('NeXpose Specific Options:') + +parser.on("--project PROJECT") do |x| + opts[:project] = x +end + +parser.on("--targets TARGETS") do |x| + opts[:targets] = [x] +end + +parser.on("--nexpose-host HOST") do |x| + opts[:nexpose_host] = x +end + +parser.on("--nexpose-user USER") do |x| + opts[:nexpose_user] = x +end + +parser.on("--nexpose-pass PASSWORD") do |x| + opts[:nexpose_pass] = x +end + +parser.on("--nexpose-pass-file PATH") do |x| + opts[:nexpose_pass_file] = x +end + +parser.on("--scan-template TEMPLATE (optional)") do |x| + opts[:scan_template] = x +end + +parser.on("--nexpose-port PORT (optional)") do |x| + opts[:nexpose_port] = x +end + +parser.on("--blacklist BLACKLIST (optional)") do |x| + opts[:blacklist] = x +end + +parser.on("--help") do + $stderr.puts opts + exit(1) +end + +parser.separator('') +parser.parse!(ARGV) + +@rpc = Msf::RPC::Client.new(opts) + +if not @rpc.token + $stderr.puts "Error: Invalid RPC server options specified" + $stderr.puts parser + exit(1) +end + +# Get the password from the file +if opts[:nexpose_pass_file] + nexpose_pass = File.open(opts[:nexpose_pass_file],"r").read.chomp! +else + nexpose_pass = opts[:nexpose_pass] || usage(parser) +end + +# Store the user's settings +project = opts[:project] || usage(parser), +targets = opts[:targets] || usage(parser), +blacklist = opts[:blacklist], +nexpose_host = opts[:nexpose_host] || usage(parser), +nexpose_port = opts[:nexpose_port] || "3780", +nexpose_user = opts[:nexpose_user] || "nxadmin" +scan_template = opts[:scan_template] || "pentest-audit" + +# Get the default user +user = @rpc.call("pro.default_admin_user")['username'] + +options = { + 'workspace' => project, + 'username' => user, + 'DS_WHITELIST_HOSTS' => targets, + 'DS_NEXPOSE_HOST' => nexpose_host, + 'DS_NEXPOSE_PORT' => nexpose_port, + 'DS_NEXPOSE_USER' => nexpose_user, + 'nexpose_pass' => nexpose_pass, + 'DS_SCAN_TEMPLATE' => scan_template +} + +puts "DEBUG: Running task with #{options}" + +# Create the task object with all options +task = @rpc.call("pro.start_exploit", options) + + +if not task['task_id'] + $stderr.puts "[-] Error starting the task: #{task.inspect}" + exit(0) +end + +puts "[*] Creating Task ID #{task['task_id']}..." +while true + select(nil, nil, nil, 0.50) + + stat = @rpc.call("pro.task_status", task['task_id']) + + if stat['status'] == 'invalid' + $stderr.puts "[-] Error checking task status" + exit(0) + end + + info = stat[ task['task_id'] ] + + if not info + $stderr.puts "[-] Error finding the task" + exit(0) + end + + if info['status'] == "error" + $stderr.puts "[-] Error generating report: #{info['error']}" + exit(0) + end + + break if info['progress'] == 100 +end + +$stdout.puts "[+] Task Complete!" diff --git a/documentation/samples/pro/msfrpc_pro_report.rb b/documentation/samples/pro/msfrpc_pro_report.rb new file mode 100644 index 0000000000..824449519c --- /dev/null +++ b/documentation/samples/pro/msfrpc_pro_report.rb @@ -0,0 +1,126 @@ +#!/usr/bin/env ruby + +require 'rubygems' +require 'optparse' +require 'msfrpc-client' +require 'rex/ui' + +def usage(ropts) + $stderr.puts ropts + + if @rpc and @rpc.token + wspaces = @rpc.call("pro.workspaces") rescue {} + if wspaces.keys.length > 0 + $stderr.puts "Active Projects:" + wspaces.each_pair do |k,v| + $stderr.puts "\t#{k}" + end + end + end + $stderr.puts "" + exit(1) +end + +opts = { + :format => 'PDF' +} + +parser = Msf::RPC::Client.option_parser(opts) + +parser.separator('Report Options:') +parser.on("--format FORMAT") do |v| + opts[:format] = v.upcase +end + +parser.on("--project PROJECT") do |v| + opts[:project] = v +end + +parser.on("--output OUTFILE") do |v| + opts[:output] = v +end + +parser.on("--help") do + $stderr.puts parser + exit(1) +end +parser.separator('') + +parser.parse!(ARGV) +@rpc = Msf::RPC::Client.new(opts) + +if not @rpc.token + $stderr.puts "Error: Invalid RPC server options specified" + $stderr.puts parser + exit(1) +end + +project = opts[:project] || usage(parser) +fname = opts[:output] || usage(parser) +rtype = opts[:format] +user = @rpc.call("pro.default_admin_user")['username'] + +task = @rpc.call("pro.start_report", { + 'DS_WHITELIST_HOSTS' => "", + 'DS_BLACKLIST_HOSTS' => "", + 'workspace' => project, + 'username' => user, + 'DS_MaskPasswords' => false, + 'DS_IncludeTaskLog' => false, + 'DS_JasperDisplaySession' => true, + 'DS_JasperDisplayCharts' => true, + 'DS_LootExcludeScreenshots' => false, + 'DS_LootExcludePasswords' => false, + 'DS_JasperTemplate' => "msfxv3.jrxml", + 'DS_REPORT_TYPE' => rtype.upcase, + 'DS_UseJasper' => true, + 'DS_UseCustomReporting' => true, + 'DS_JasperProductName' => "Metasploit Pro", + 'DS_JasperDbEnv' => "production", + 'DS_JasperLogo' => '', + 'DS_JasperDisplaySections' => "1,2,3,4,5,6,7,8", + 'DS_EnablePCIReport' => true, + 'DS_EnableFISMAReport' => true, + 'DS_JasperDisplayWeb' => true, +}) + + +if not task['task_id'] + $stderr.puts "[-] Error generating the report: #{task.inspect}" + exit(0) +end + +puts "[*] Report is generating with Task ID #{task['task_id']}..." +while true + select(nil, nil, nil, 0.50) + stat = @rpc.call("pro.task_status", task['task_id']) + if stat['status'] == 'invalid' + $stderr.puts "[-] Error checking task status" + exit(0) + end + + info = stat[ task['task_id'] ] + + if not info + $stderr.puts "[-] Error finding the task" + exit(0) + end + + if info['status'] == "error" + $stderr.puts "[-] Error generating report: #{info['error']}" + exit(0) + end + + break if info['progress'] == 100 +end + +report = @rpc.call('pro.report_download_by_task', task['task_id']) +if report and report['data'] + ::File.open(fname, "wb") do |fd| + fd.write(report['data']) + end + $stderr.puts "[-] Report saved to #{::File.expand_path(fname)}" +else + $stderr.puts "[-] Error downloading report: #{report.inspect}" +end +