Merge branch '4.3-schema'
This commit is contained in:
+13
@@ -0,0 +1,13 @@
|
||||
class InetColumns < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
change_column :hosts, :address, 'INET using address::INET'
|
||||
remove_column :hosts, :address6
|
||||
end
|
||||
|
||||
def self.down
|
||||
change_column :hosts, :address, :text
|
||||
add_column :hosts, :address6, :text
|
||||
end
|
||||
|
||||
end
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
class MoreInetColumns < ActiveRecord::Migration
|
||||
|
||||
def self.up
|
||||
change_column :wmap_requests, :address, 'INET using address::INET'
|
||||
remove_column :wmap_requests, :address6
|
||||
change_column :wmap_targets, :address, 'INET using address::INET'
|
||||
remove_column :wmap_targets, :address6
|
||||
end
|
||||
|
||||
def self.down
|
||||
change_column :wmap_requests, :address, :string, :limit => 16
|
||||
add_column :wmap_requests, :address6, :string, :limit => 255
|
||||
change_column :wmap_targets, :address, :string, :limit => 16
|
||||
add_column :wmap_targets, :address6, :string, :limit => 255
|
||||
end
|
||||
|
||||
end
|
||||
@@ -51,7 +51,7 @@ module Auxiliary::JohnTheRipper
|
||||
end
|
||||
|
||||
when /x86_64-linux/
|
||||
::FileUtils.chmod(755, "#{cpuinfo_base}/cpuinfo.ia64.bin") rescue nil
|
||||
::FileUtils.chmod(0755, "#{cpuinfo_base}/cpuinfo.ia64.bin") rescue nil
|
||||
data = `#{cpuinfo_base}/cpuinfo.ia64.bin` rescue nil
|
||||
case data
|
||||
when /mmx/
|
||||
@@ -61,7 +61,7 @@ module Auxiliary::JohnTheRipper
|
||||
end
|
||||
|
||||
when /i[\d]86-linux/
|
||||
::FileUtils.chmod(755, "#{cpuinfo_base}/cpuinfo.ia32.bin") rescue nil
|
||||
::FileUtils.chmod(0755, "#{cpuinfo_base}/cpuinfo.ia32.bin") rescue nil
|
||||
data = `#{cpuinfo_base}/cpuinfo.ia32.bin` rescue nil
|
||||
case data
|
||||
when /sse2/
|
||||
|
||||
+18
-10
@@ -130,7 +130,7 @@ class DBManager
|
||||
ip_x = ip.to_x
|
||||
ip_i = ip.to_i
|
||||
when "String"
|
||||
if ipv4_validator(ip)
|
||||
if ipv46_validator(ip)
|
||||
ip_x = ip
|
||||
ip_i = Rex::Socket.addr_atoi(ip)
|
||||
else
|
||||
@@ -154,9 +154,17 @@ class DBManager
|
||||
return false
|
||||
end
|
||||
|
||||
def ipv46_validator(addr)
|
||||
ipv4_validator(addr) or ipv6_validator(addr)
|
||||
end
|
||||
|
||||
def ipv4_validator(addr)
|
||||
return false unless addr.kind_of? String
|
||||
addr =~ /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/
|
||||
Rex::Socket.is_ipv4?(addr)
|
||||
end
|
||||
|
||||
def ipv6_validator(addr)
|
||||
Rex::Socket.is_ipv6?(addr)
|
||||
end
|
||||
|
||||
# Takes a space-delimited set of ips and ranges, and subjects
|
||||
@@ -164,7 +172,7 @@ class DBManager
|
||||
def validate_ips(ips)
|
||||
ret = true
|
||||
begin
|
||||
ips.split(' ').each {|ip|
|
||||
ips.split(/\s+/).each {|ip|
|
||||
unless Rex::Socket::RangeWalker.new(ip).ranges
|
||||
ret = false
|
||||
break
|
||||
@@ -267,7 +275,7 @@ class DBManager
|
||||
|
||||
if not addr.kind_of? Host
|
||||
addr = normalize_host(addr)
|
||||
unless ipv4_validator(addr)
|
||||
unless ipv46_validator(addr)
|
||||
raise ::ArgumentError, "Invalid IP address in report_host(): #{addr}"
|
||||
end
|
||||
|
||||
@@ -2215,7 +2223,7 @@ class DBManager
|
||||
# then it's an amap log
|
||||
@import_filedata[:type] = "Amap Log"
|
||||
return :amap_log
|
||||
elsif (firstline =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/)
|
||||
elsif ipv46_validator(firstline)
|
||||
# then its an IP list
|
||||
@import_filedata[:type] = "IP Address List"
|
||||
return :ip_list
|
||||
@@ -2539,7 +2547,7 @@ class DBManager
|
||||
end
|
||||
|
||||
next unless [addr,port,user,pass].compact.size == 4
|
||||
next unless ipv4_validator(addr) # Skip Malformed addrs
|
||||
next unless ipv46_validator(addr) # Skip Malformed addrs
|
||||
next unless port[/^[0-9]+$/] # Skip malformed ports
|
||||
if bl.include? addr
|
||||
next
|
||||
@@ -4302,7 +4310,7 @@ class DBManager
|
||||
data = r[6]
|
||||
|
||||
# If there's no resolution, or if it's malformed, skip it.
|
||||
next unless ipv4_validator(addr)
|
||||
next unless ipv46_validator(addr)
|
||||
|
||||
if bl.include? addr
|
||||
next
|
||||
@@ -4407,7 +4415,7 @@ class DBManager
|
||||
hname = host.elements['HostName'].text
|
||||
end
|
||||
addr ||= host.elements['HostName'].text
|
||||
next unless ipv4_validator(addr) # Skip resolved names and SCAN-ERROR.
|
||||
next unless ipv46_validator(addr) # Skip resolved names and SCAN-ERROR.
|
||||
if bl.include? addr
|
||||
next
|
||||
else
|
||||
@@ -4477,7 +4485,7 @@ class DBManager
|
||||
hobj = nil
|
||||
addr = host['addr'] || host['hname']
|
||||
|
||||
next unless ipv4_validator(addr) # Catches SCAN-ERROR, among others.
|
||||
next unless ipv46_validator(addr) # Catches SCAN-ERROR, among others.
|
||||
|
||||
if bl.include? addr
|
||||
next
|
||||
@@ -4791,7 +4799,7 @@ class DBManager
|
||||
hobj = nil
|
||||
addr = host['addr'] || host['hname']
|
||||
|
||||
next unless ipv4_validator(addr) # Catches SCAN-ERROR, among others.
|
||||
next unless ipv46_validator(addr) # Catches SCAN-ERROR, among others.
|
||||
|
||||
if bl.include? addr
|
||||
next
|
||||
|
||||
@@ -601,7 +601,15 @@ class Module
|
||||
def debugging?
|
||||
(datastore['DEBUG'] || '') =~ /^(1|t|y)/i
|
||||
end
|
||||
|
||||
|
||||
#
|
||||
# Indicates whether the module supports IPv6. This is true by default,
|
||||
# but certain modules require additional work to be compatible or are
|
||||
# hardcoded in terms of application support and should be skipped.
|
||||
#
|
||||
def support_ipv6?
|
||||
true
|
||||
end
|
||||
|
||||
#
|
||||
# This provides a standard set of search filters for every module.
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
module Msf
|
||||
module RPC
|
||||
class Auth < Base
|
||||
|
||||
def login(user,pass)
|
||||
|
||||
# handle authentication here
|
||||
fail = true
|
||||
@users.each do |u|
|
||||
if(u[0] == user and u[1] == pass)
|
||||
fail = false
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if fail
|
||||
# Introduce a random delay in the response to annoy brute forcers
|
||||
delay = [ ( rand(3000) / 1000.0 ), 0.50 ].max
|
||||
::IO.select(nil, nil, nil, delay)
|
||||
|
||||
# Send back a 401 denied error
|
||||
raise ::XMLRPC::FaultException.new(401, "authentication error")
|
||||
end
|
||||
|
||||
token = Rex::Text.rand_text_alphanumeric(32)
|
||||
@tokens[token] = [user, Time.now.to_i, Time.now.to_i]
|
||||
{ "result" => "success", "token" => token }
|
||||
end
|
||||
|
||||
def logout(token)
|
||||
@tokens.delete(token)
|
||||
{ "result" => "success" }
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,38 +0,0 @@
|
||||
module Msf
|
||||
module RPC
|
||||
class Base
|
||||
|
||||
def initialize(framework,tokens,users)
|
||||
@framework = framework
|
||||
@tokens = tokens
|
||||
@users = users
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def authenticate(token)
|
||||
stale = []
|
||||
|
||||
# Force the encoding to ASCII-8BIT
|
||||
token = token.unpack("C*").pack("C*")
|
||||
|
||||
@tokens.each_key do |t|
|
||||
user,ctime,mtime,perm = @tokens[t]
|
||||
if ! perm and mtime + 300 < Time.now.to_i
|
||||
stale << t
|
||||
end
|
||||
end
|
||||
|
||||
stale.each { |t| @tokens.delete(t) }
|
||||
|
||||
if not @tokens[token]
|
||||
raise ::XMLRPC::FaultException.new(401, "authentication error")
|
||||
end
|
||||
|
||||
@tokens[token][2] = Time.now.to_i
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
require "xmlrpc/client"
|
||||
require "rex"
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
|
||||
# Loosely based on the XMLRPC::ClientS class
|
||||
# Reimplemented for Metasploit
|
||||
|
||||
class Client < ::XMLRPC::Client
|
||||
|
||||
attr_accessor :sock, :token
|
||||
|
||||
# Use a TCP socket to do RPC
|
||||
def initialize(info={})
|
||||
|
||||
@buff = ""
|
||||
self.sock = Rex::Socket::Tcp.create(
|
||||
'PeerHost' => info[:host],
|
||||
'PeerPort' => info[:port],
|
||||
'SSL' => info[:ssl]
|
||||
)
|
||||
end
|
||||
|
||||
# This override hooks into the RPCXML library
|
||||
def do_rpc(request,async)
|
||||
|
||||
begin
|
||||
self.sock.put(request + "\x00")
|
||||
|
||||
while(not @buff.index("\x00"))
|
||||
if ::IO.select([self.sock], nil, nil, 30)
|
||||
resp = self.sock.sysread(32768)
|
||||
@buff << resp if resp
|
||||
end
|
||||
end
|
||||
rescue ::Exception => e
|
||||
self.close
|
||||
raise EOFError, "XMLRPC connection closed"
|
||||
end
|
||||
|
||||
mesg,left = @buff.split("\x00", 2)
|
||||
@buff = left.to_s
|
||||
mesg
|
||||
end
|
||||
|
||||
def login(user,pass)
|
||||
res = self.call("auth.login", user, pass)
|
||||
if(not (res and res['result'] == "success"))
|
||||
raise RuntimeError, "authentication failed"
|
||||
end
|
||||
self.token = res['token']
|
||||
true
|
||||
end
|
||||
|
||||
# Prepend the authentication token as the first parameter
|
||||
# of every call except auth.login. Requires the
|
||||
def call(meth, *args)
|
||||
if(meth != "auth.login")
|
||||
if(not self.token)
|
||||
raise RuntimeError, "client not authenticated"
|
||||
end
|
||||
args.unshift(self.token)
|
||||
end
|
||||
super(meth, *args)
|
||||
end
|
||||
|
||||
def close
|
||||
self.sock.close rescue nil
|
||||
self.sock = nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,87 +0,0 @@
|
||||
require 'pp'
|
||||
require 'rex'
|
||||
require 'msf/ui/web/driver'
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
class Console < Base
|
||||
|
||||
def initialize(framework,tokens,users)
|
||||
super(framework, tokens, users)
|
||||
@console_driver = Msf::Ui::Web::Driver.new(:framework => framework)
|
||||
end
|
||||
|
||||
def create(token)
|
||||
authenticate(token)
|
||||
cid = @console_driver.create_console
|
||||
{
|
||||
'id' => cid,
|
||||
'prompt' => Rex::Text.encode_base64(@console_driver.consoles[cid].prompt || ''),
|
||||
'busy' => @console_driver.consoles[cid].busy || false,
|
||||
'encoding' => "base64"
|
||||
}
|
||||
end
|
||||
|
||||
def list(token)
|
||||
authenticate(token)
|
||||
ret = []
|
||||
@console_driver.consoles.each_key do |cid|
|
||||
ret << {
|
||||
'id' => cid,
|
||||
'prompt' => Rex::Text.encode_base64(@console_driver.consoles[cid].prompt || ''),
|
||||
'busy' => @console_driver.consoles[cid].busy || false,
|
||||
'encoding' => "base64"
|
||||
}
|
||||
end
|
||||
{'consoles' => ret}
|
||||
end
|
||||
|
||||
def destroy(token, cid)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
res = @console_driver.destroy_console(cid)
|
||||
{ 'result' => res ? 'success' : 'failure' }
|
||||
end
|
||||
|
||||
def read(token, cid)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
{
|
||||
"data" => Rex::Text.encode_base64(@console_driver.read_console(cid) || ''),
|
||||
"prompt" => Rex::Text.encode_base64(@console_driver.consoles[cid].prompt || ''),
|
||||
"busy" => @console_driver.consoles[cid].busy || false,
|
||||
"encoding" => "base64"
|
||||
}
|
||||
end
|
||||
|
||||
def write(token, cid, data)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
{ "wrote" => @console_driver.write_console(cid, Rex::Text.decode_base64(data || '')) }
|
||||
end
|
||||
|
||||
def tabs(token, cid, line)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
{ "tabs" => @console_driver.consoles[cid].tab_complete(line) }
|
||||
end
|
||||
|
||||
def session_kill(token, cid)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
@console_driver.consoles[cid].session_kill
|
||||
{ 'result' => 'success' }
|
||||
end
|
||||
|
||||
def session_detach(token, cid)
|
||||
authenticate(token)
|
||||
return { 'result' => 'failure' } if not @console_driver.consoles[cid]
|
||||
@console_driver.consoles[cid].session_detach
|
||||
{ 'result' => 'success' }
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,27 +0,0 @@
|
||||
module Msf
|
||||
module RPC
|
||||
class Core < Base
|
||||
|
||||
def initialize(framework, tokens, users, server=nil)
|
||||
@server = server
|
||||
super(framework, tokens, users)
|
||||
end
|
||||
|
||||
def version(token)
|
||||
authenticate(token)
|
||||
{ "version" => ::Msf::Framework::Version, "ruby" => "#{RUBY_VERSION} #{RUBY_PLATFORM} #{RUBY_RELEASE_DATE}" }
|
||||
end
|
||||
|
||||
#
|
||||
# Stop the RPC server. This method will never return a value to the client
|
||||
# because the socket for communicating with it will be closed.
|
||||
#
|
||||
def stop(token)
|
||||
authenticate(token)
|
||||
@server.stop_rpc if @server
|
||||
nil
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,1352 +0,0 @@
|
||||
module Msf
|
||||
module RPC
|
||||
class Db < Base
|
||||
|
||||
private
|
||||
def db
|
||||
@framework.db.active
|
||||
end
|
||||
|
||||
def workspace(wspace = nil)
|
||||
if(wspace and wspace != "")
|
||||
return @framework.db.find_workspace(wspace)
|
||||
end
|
||||
@framework.db.workspace
|
||||
end
|
||||
|
||||
def fix_options(opts)
|
||||
newopts = {}
|
||||
opts.each do |k,v|
|
||||
newopts[k.to_sym] = v
|
||||
end
|
||||
newopts
|
||||
end
|
||||
|
||||
def opts_to_hosts(opts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
hosts = []
|
||||
if opts[:host] or opts[:address]
|
||||
host = opts[:host] || opts[:address]
|
||||
hent = wspace.hosts.find_by_address(host)
|
||||
return hosts if hent == nil
|
||||
hosts << hent if hent.class == Msf::DBManager::Host
|
||||
hosts |= hent if hent.class == Array
|
||||
elsif opts[:addresses]
|
||||
return hosts if opts[:addresses].class != Array
|
||||
conditions = {}
|
||||
conditions[:address] = opts[:addresses]
|
||||
hent = wspace.hosts.all(:conditions => conditions)
|
||||
hosts |= hent if hent.class == Array
|
||||
end
|
||||
return hosts
|
||||
end
|
||||
|
||||
def opts_to_services(hosts,opts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
services = []
|
||||
if opts[:host] or opts[:address] or opts[:addresses]
|
||||
return services if hosts.count < 1
|
||||
hosts.each do |h|
|
||||
if opts[:port] or opts[:proto]
|
||||
conditions = {}
|
||||
conditions[:port] = opts[:port] if opts[:port]
|
||||
conditions[:proto] = opts[:proto] if opts[:proto]
|
||||
sret = h.services.all(:conditions => conditions)
|
||||
next if sret == nil
|
||||
services |= sret if sret.class == Array
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
else
|
||||
services |= h.services
|
||||
end
|
||||
end
|
||||
elsif opts[:port] or opts[:proto]
|
||||
conditions = {}
|
||||
conditions[:port] = opts[:port] if opts[:port]
|
||||
conditions[:proto] = opts[:proto] if opts[:proto]
|
||||
sret = wspace.services.all(:conditions => conditions)
|
||||
services |= sret if sret.class == Array
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
end
|
||||
return services
|
||||
end
|
||||
|
||||
def clean_nils(obj)
|
||||
return '' if obj == nil
|
||||
if obj.is_a? Hash
|
||||
obj.each_key do |key|
|
||||
obj[key] = clean_nils(obj[key])
|
||||
end
|
||||
elsif obj.is_a? Array
|
||||
obj.each_with_index do |ob, i|
|
||||
obj[i] = clean_nils(ob)
|
||||
end
|
||||
end
|
||||
obj
|
||||
end
|
||||
|
||||
public
|
||||
|
||||
def hosts(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
|
||||
opts = fix_options(xopts)
|
||||
|
||||
conditions = {}
|
||||
conditions[:state] = [Msf::HostState::Alive, Msf::HostState::Unknown] if opts[:only_up]
|
||||
conditions[:address] = opts[:addresses] if opts[:addresses]
|
||||
|
||||
wspace = workspace(opts[:workspace])
|
||||
|
||||
ret = {}
|
||||
ret[:hosts] = []
|
||||
wspace.hosts.all(:conditions => conditions, :order => :address).each do |h|
|
||||
host = {}
|
||||
host[:created_at] = h.created_at.to_i
|
||||
host[:address] = h.address.to_s
|
||||
host[:address6] = h.address6.to_s
|
||||
host[:mac] = h.mac.to_s
|
||||
host[:name] = h.name.to_s
|
||||
host[:state] = h.state.to_s
|
||||
host[:os_name] = h.os_name.to_s
|
||||
host[:os_flavor] = h.os_flavor.to_s
|
||||
host[:os_sp] = h.os_sp.to_s
|
||||
host[:os_lang] = h.os_lang.to_s
|
||||
host[:updated_at] = h.updated_at.to_i
|
||||
host[:purpose] = h.purpose.to_s
|
||||
host[:info] = h.info.to_s
|
||||
ret[:hosts] << host
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def services(token, xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
opts[:workspace] = wspace if opts[:workspace]
|
||||
hosts = []
|
||||
|
||||
if opts[:addresses]
|
||||
conditions = {}
|
||||
conditions[:address] = opts[:addresses] if opts[:addresses]
|
||||
hosts = wspace.hosts.all(:conditions => conditions, :order => :address)
|
||||
elsif opts[:host] || opts[:address]
|
||||
host = @framework.db.get_host(opts)
|
||||
hosts << host
|
||||
end
|
||||
|
||||
ret = {}
|
||||
ret[:services] = []
|
||||
|
||||
a = @framework.db.get_host(opts)
|
||||
|
||||
services = []
|
||||
if opts[:host] || opts[:address] || opts[:addresses]
|
||||
hosts.each do |host|
|
||||
sret = nil
|
||||
if(opts[:proto] && opts[:port])
|
||||
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
|
||||
else
|
||||
sret = host.services
|
||||
end
|
||||
next if sret == nil
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
services |= sret if sret.class == Array
|
||||
end
|
||||
else
|
||||
services = wspace.services
|
||||
end
|
||||
|
||||
return ret if (not services)
|
||||
|
||||
services.each do |s|
|
||||
service = {}
|
||||
host = s.host
|
||||
service[:host] = host.address || host.address6 || "unknown"
|
||||
service[:created_at] = s[:created_at].to_i
|
||||
service[:updated_at] = s[:updated_at].to_i
|
||||
service[:port] = s[:port]
|
||||
service[:proto] = s[:proto].to_s
|
||||
service[:state] = s[:state].to_s
|
||||
service[:name] = s[:name].to_s
|
||||
service[:info] = s[:info].to_s
|
||||
ret[:services] << service
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
|
||||
def vulns(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
opts[:workspace] = wspace if opts[:workspace]
|
||||
|
||||
ret = {}
|
||||
ret[:vulns] = []
|
||||
hosts = []
|
||||
services = []
|
||||
vulns = []
|
||||
# Get Matching Hosts
|
||||
if opts[:addresses]
|
||||
conditions = {}
|
||||
conditions[:address] = opts[:addresses] if opts[:addresses]
|
||||
hosts = wspace.hosts.all(:conditions => conditions, :order => :address)
|
||||
elsif opts[:host] || opts[:address]
|
||||
host = @framework.db.get_host(opts)
|
||||
hosts << host
|
||||
end
|
||||
|
||||
#Get Matching Services
|
||||
if opts[:host] || opts[:address] || opts[:addresses]
|
||||
hosts.each do |host|
|
||||
sret = nil
|
||||
if(opts[:proto] && opts[:port])
|
||||
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
|
||||
else
|
||||
sret = host.services
|
||||
end
|
||||
next if sret == nil
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
services |= sret if sret.class == Array
|
||||
end
|
||||
elsif opts[:port] && opts[:proto]
|
||||
sret = wspace.services.find_by_proto_and_port(opts[:proto],opts[:port])
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
services |= sret if sret.class == Array
|
||||
end
|
||||
|
||||
#get list of vulns
|
||||
if services.count > 0
|
||||
services.each do |s|
|
||||
if opts[:name]
|
||||
nret = s.vulns.find_by_name(opts[:name])
|
||||
else
|
||||
nret = s.vulns
|
||||
end
|
||||
next if nret == nil
|
||||
vulns << nret if nret.class == Msf::DBManager::Vuln
|
||||
vulns |= nret if nret.class == Array
|
||||
end
|
||||
elsif hosts.count > 0
|
||||
hosts.each do |h|
|
||||
if opts[:name]
|
||||
nret = h.vulns.find_by_name(opts[:name])
|
||||
else
|
||||
nret = h.vulns
|
||||
end
|
||||
next if nret == nil
|
||||
vulns << nret if nret.class == Msf::DBManager::Vuln
|
||||
vulns |= nret if nret.class == Array
|
||||
end
|
||||
else
|
||||
nret = wspace.vulns
|
||||
vulns << nret if nret.class == Msf::DBManager::Vuln
|
||||
vulns |= nret if nret.class == Array
|
||||
end
|
||||
|
||||
vulns.each do |v|
|
||||
vuln = {}
|
||||
reflist = v.refs.map { |r| r.name }
|
||||
if(v.service)
|
||||
vuln[:port] = v.service.port
|
||||
vuln[:proto] = v.service.proto
|
||||
else
|
||||
vuln[:port] = nil
|
||||
vuln[:proto] = nil
|
||||
end
|
||||
vuln[:time] = v.created_at.to_i
|
||||
vuln[:host] = v.host.address || v.host.address6 || nil
|
||||
vuln[:name] = v.name
|
||||
vuln[:refs] = reflist.join(',')
|
||||
ret[:vulns] << vuln
|
||||
end
|
||||
clean_nils(ret)
|
||||
end
|
||||
|
||||
def workspaces(token)
|
||||
authenticate(token)
|
||||
if(not db)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded")
|
||||
end
|
||||
res = {}
|
||||
res[:workspaces] = []
|
||||
@framework.db.workspaces.each do |j|
|
||||
ws = {}
|
||||
ws[:name] = j.name
|
||||
ws[:created_at] = j.created_at.to_i
|
||||
ws[:updated_at] = j.updated_at.to_i
|
||||
res[:workspaces] << ws
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
def current_workspace(token)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
{ "workspace" => @framework.db.workspace.name }
|
||||
|
||||
end
|
||||
|
||||
def get_workspace(token,wspace)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
wspace = workspace(wspace)
|
||||
ret = {}
|
||||
ret[:workspace] = []
|
||||
if(wspace)
|
||||
w = {}
|
||||
w[:name] = wspace.name
|
||||
w[:created_at] = wspace.created_at.to_i
|
||||
w[:modified_at] = wspace.modified_at.to_i
|
||||
ret[:workspace] << w
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def set_workspace(token,wspace)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
workspace = @framework.db.find_workspace(wspace)
|
||||
if(workspace)
|
||||
@framework.db.workspace = workspace
|
||||
return { 'result' => "success" }
|
||||
end
|
||||
{ 'result' => 'failed' }
|
||||
end
|
||||
|
||||
def del_workspace(token,wspace)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
# Delete workspace
|
||||
workspace = @framework.db.find_workspace(wspace)
|
||||
if workspace.nil?
|
||||
raise ::XMLRPC::FaultException.new(404, "Workspace not found: #{wspace}")
|
||||
elsif workspace.default?
|
||||
workspace.destroy
|
||||
workspace = @framework.db.add_workspace(workspace.name)
|
||||
else
|
||||
# switch to the default workspace if we're about to delete the current one
|
||||
@framework.db.workspace = @framework.db.default_workspace if @framework.db.workspace.name == workspace.name
|
||||
# now destroy the named workspace
|
||||
workspace.destroy
|
||||
end
|
||||
{ 'result' => "success" }
|
||||
end
|
||||
|
||||
def add_workspace(token,wspace)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
wspace = @framework.db.add_workspace(wspace)
|
||||
return { 'result' => 'success' } if(wspace)
|
||||
{ 'result' => 'failed' }
|
||||
end
|
||||
|
||||
def get_host(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
|
||||
ret = {}
|
||||
ret[:host] = []
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
h = @framework.db.get_host(opts)
|
||||
if(h)
|
||||
host = {}
|
||||
host[:created_at] = h.created_at.to_i
|
||||
host[:address] = h.address.to_s
|
||||
host[:address6] = h.address6.to_s
|
||||
host[:mac] = h.mac.to_s
|
||||
host[:name] = h.name.to_s
|
||||
host[:state] = h.state.to_s
|
||||
host[:os_name] = h.os_name.to_s
|
||||
host[:os_flavor] = h.os_flavor.to_s
|
||||
host[:os_sp] = h.os_sp.to_s
|
||||
host[:os_lang] = h.os_lang.to_s
|
||||
host[:updated_at] = h.updated_at.to_i
|
||||
host[:purpose] = h.purpose.to_s
|
||||
host[:info] = h.info.to_s
|
||||
ret[:host] << host
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def report_host(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
|
||||
res = @framework.db.report_host(opts)
|
||||
return { :result => 'success' } if(res)
|
||||
{ :result => 'failed' }
|
||||
|
||||
end
|
||||
|
||||
def report_service(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
res = @framework.db.report_service(opts)
|
||||
return { :result => 'success' } if(res)
|
||||
{ :result => 'failed' }
|
||||
end
|
||||
|
||||
def get_service(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
opts[:workspace] = wspace if opts[:workspace]
|
||||
|
||||
ret = {}
|
||||
ret[:service] = []
|
||||
|
||||
host = @framework.db.get_host(opts)
|
||||
|
||||
services = []
|
||||
sret = nil
|
||||
|
||||
if(host && opts[:proto] && opts[:port])
|
||||
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
|
||||
elsif(opts[:proto] && opts[:port])
|
||||
conditions = {}
|
||||
conditions[:state] = [ServiceState::Open] if opts[:up]
|
||||
conditions[:proto] = opts[:proto] if opts[:proto]
|
||||
conditions[:port] = opts[:port] if opts[:port]
|
||||
conditions[:name] = opts[:names] if opts[:names]
|
||||
sret = wspace.services.all(:conditions => conditions, :order => "hosts.address, port")
|
||||
else
|
||||
sret = host.services
|
||||
end
|
||||
return ret if sret == nil
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
services |= sret if sret.class == Array
|
||||
|
||||
|
||||
services.each do |s|
|
||||
service = {}
|
||||
host = s.host
|
||||
service[:host] = host.address || host.address6 || "unknown"
|
||||
service[:created_at] = s[:created_at].to_i
|
||||
service[:updated_at] = s[:updated_at].to_i
|
||||
service[:port] = s[:port]
|
||||
service[:proto] = s[:proto].to_s
|
||||
service[:state] = s[:state].to_s
|
||||
service[:name] = s[:name].to_s
|
||||
service[:info] = s[:info].to_s
|
||||
ret[:service] << service
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def get_note(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
|
||||
ret = {}
|
||||
ret[:note] = []
|
||||
|
||||
host = @framework.db.get_host(opts)
|
||||
|
||||
return ret if( not host)
|
||||
notes = []
|
||||
if(opts[:proto] && opts[:port])
|
||||
services = []
|
||||
nret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
|
||||
return ret if nret == nil
|
||||
services << nret if nret.class == Msf::DBManager::Service
|
||||
services |= nret if nret.class == Array
|
||||
|
||||
services.each do |s|
|
||||
nret = nil
|
||||
if opts[:ntype]
|
||||
nret = s.notes.find_by_ntype(opts[:ntype])
|
||||
else
|
||||
nret = s.notes
|
||||
end
|
||||
next if nret == nil
|
||||
notes << nret if nret.class == Msf::DBManager::Note
|
||||
notes |= nret if nret.class == Array
|
||||
end
|
||||
else
|
||||
notes = host.notes
|
||||
end
|
||||
notes.each do |n|
|
||||
note = {}
|
||||
host = n.host
|
||||
note[:host] = host.address || host.address6 || "unknown"
|
||||
if n.service
|
||||
note[:port] = n.service.port
|
||||
note[:proto] = n.service.proto
|
||||
end
|
||||
note[:created_at] = n[:created_at].to_i
|
||||
note[:updated_at] = n[:updated_at].to_i
|
||||
note[:ntype] = n[:ntype].to_s
|
||||
note[:data] = n[:data]
|
||||
note[:critical] = n[:critical].to_s
|
||||
note[:seen] = n[:seen].to_s
|
||||
ret[:note] << note
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def get_client(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
ret = {}
|
||||
ret[:client] = []
|
||||
c = @framework.db.get_client(opts)
|
||||
if(c)
|
||||
client = {}
|
||||
host = c.host
|
||||
client[:host] = host.address
|
||||
client[:created_at] = c.created_at.to_i
|
||||
client[:updated_at] = c.updated_at.to_i
|
||||
client[:ua_string] = c.ua_string.to_s
|
||||
client[:ua_name] = c.ua_name.to_s
|
||||
client[:ua_ver] = c.ua_ver.to_s
|
||||
ret[:client] << client
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def report_client(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
res = @framework.db.report_client(opts)
|
||||
return { :result => 'success' } if(res)
|
||||
{ :result => 'failed' }
|
||||
end
|
||||
|
||||
#DOC NOTE: :data and :ntype are REQUIRED
|
||||
def report_note(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
if (opts[:host] or opts[:address]) and opts[:port] and opts[:proto]
|
||||
addr = opts[:host] || opts[:address]
|
||||
wspace = opts[:workspace] || @framework.db.workspace
|
||||
host = wspace.hosts.find_by_address(addr)
|
||||
service = host.services.find_by_proto_and_port(opts[:proto],opts[:port]) if host.services.count > 0
|
||||
opts[:service] = service if service
|
||||
end
|
||||
|
||||
res = @framework.db.report_note(opts)
|
||||
return { :result => 'success' } if(res)
|
||||
{ :result => 'failed' }
|
||||
end
|
||||
|
||||
def notes(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:workspace] = wspace
|
||||
|
||||
ret = {}
|
||||
ret[:notes] = []
|
||||
hosts = []
|
||||
services = []
|
||||
notes = []
|
||||
|
||||
# Get Matching Hosts
|
||||
if opts[:addresses]
|
||||
conditions = {}
|
||||
conditions[:address] = opts[:addresses] if opts[:addresses]
|
||||
hosts = wspace.hosts.all(:conditions => conditions, :order => :address)
|
||||
elsif opts[:host] || opts[:address]
|
||||
host = @framework.db.get_host(opts)
|
||||
hosts << host
|
||||
end
|
||||
|
||||
#Get Matching Services
|
||||
if opts[:host] || opts[:address] || opts[:addresses]
|
||||
hosts.each do |host|
|
||||
sret = nil
|
||||
if(opts[:proto] && opts[:port])
|
||||
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
|
||||
else
|
||||
sret = host.services
|
||||
end
|
||||
next if sret == nil
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
services |= sret if sret.class == Array
|
||||
end
|
||||
elsif opts[:port] && opts[:proto]
|
||||
sret = wspace.services.find_by_proto_and_port(opts[:proto],opts[:port])
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
services |= sret if sret.class == Array
|
||||
end
|
||||
|
||||
#get list of notes
|
||||
if services.count > 0
|
||||
services.each do |s|
|
||||
if opts[:ntype]
|
||||
nret = s.notes.find_by_ntype(opts[:ntype])
|
||||
else
|
||||
nret = s.notes
|
||||
end
|
||||
next if nret == nil
|
||||
notes << nret if nret.class == Msf::DBManager::Note
|
||||
notes |= nret if nret.class == Array
|
||||
end
|
||||
elsif hosts.count > 0
|
||||
hosts.each do |h|
|
||||
if opts[:ntype]
|
||||
nret = h.notes.find_by_ntype(opts[:ntype])
|
||||
else
|
||||
nret = h.notes
|
||||
end
|
||||
next if nret == nil
|
||||
notes << nret if nret.class == Msf::DBManager::Note
|
||||
notes |= nret if nret.class == Array
|
||||
end
|
||||
else
|
||||
nret = wspace.notes
|
||||
notes << nret if nret.class == Msf::DBManager::Note
|
||||
notes |= nret if nret.class == Array
|
||||
end
|
||||
|
||||
notes.each do |n|
|
||||
note = {}
|
||||
note[:time] = n.created_at.to_i
|
||||
note[:host] = ""
|
||||
note[:service] = ""
|
||||
note[:host] = n.host.address || n.host.address6 if(n.host)
|
||||
note[:service] = n.service.name || n.service.port if(n.service)
|
||||
note[:type ] = n.ntype.to_s
|
||||
note[:data] = n.data.inspect
|
||||
ret[:notes] << note
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def report_auth_info(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
res = @framework.db.report_auth_info(opts)
|
||||
return { :result => 'success' } if(res)
|
||||
{ :result => 'failed' }
|
||||
end
|
||||
|
||||
def get_auth_info(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
ret = {}
|
||||
ret[:auth_info] = []
|
||||
ai = @framework.db.get_auth_info(opts)
|
||||
ai.each do |i|
|
||||
info = {}
|
||||
i.each do |k,v|
|
||||
info[k.to_sym] = v
|
||||
end
|
||||
ret[:auth_info] << info
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def get_ref(token,name)
|
||||
authenticate(token)
|
||||
return @framework.db.get_ref(name)
|
||||
end
|
||||
|
||||
def del_vuln(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
hosts = []
|
||||
services = []
|
||||
vulns = []
|
||||
|
||||
if opts[:host] or opts[:address] or opts[:addresses]
|
||||
hosts = opts_to_hosts(opts)
|
||||
end
|
||||
|
||||
if opts[:port] or opts[:proto]
|
||||
if opts[:host] or opts[:address] or opts[:addresses]
|
||||
services = opts_to_services(hosts,opts)
|
||||
else
|
||||
services = opts_to_services([],opts)
|
||||
end
|
||||
end
|
||||
|
||||
if opts[:port] or opts[:proto]
|
||||
services.each do |s|
|
||||
vret = nil
|
||||
if opts[:name]
|
||||
vret = s.vulns.find_by_name(opts[:name])
|
||||
else
|
||||
vret = s.vulns
|
||||
end
|
||||
next if vret == nil
|
||||
vulns << vret if vret.class == Msf::DBManager::Vuln
|
||||
vulns |= vret if vret.class == Array
|
||||
end
|
||||
elsif opts[:address] or opts[:host] or opts[:addresses]
|
||||
hosts.each do |h|
|
||||
vret = nil
|
||||
if opts[:name]
|
||||
vret = h.vulns.find_by_name(opts[:name])
|
||||
else
|
||||
vret = h.vulns
|
||||
end
|
||||
next if vret == nil
|
||||
vulns << vret if vret.class == Msf::DBManager::Vuln
|
||||
vulns |= vret if vret.class == Array
|
||||
end
|
||||
else
|
||||
vret = nil
|
||||
if opts[:name]
|
||||
vret = wspace.vulns.find_by_name(opts[:name])
|
||||
else
|
||||
vret = wspace.vulns
|
||||
end
|
||||
vulns << vret if vret.class == Msf::DBManager::Vuln
|
||||
vulns |= vret if vret.class == Array
|
||||
end
|
||||
|
||||
deleted = []
|
||||
vulns.each do |v|
|
||||
dent = {}
|
||||
dent[:address] = v.host.address.to_s if v.host
|
||||
dent[:port] = v.service.port if v.service
|
||||
dent[:proto] = v.service.proto if v.service
|
||||
dent[:name] = v.name
|
||||
deleted << dent
|
||||
v.destroy
|
||||
end
|
||||
|
||||
return { :result => 'success', :deleted => deleted }
|
||||
end
|
||||
|
||||
def del_note(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
hosts = []
|
||||
services = []
|
||||
notes = []
|
||||
|
||||
if opts[:host] or opts[:address] or opts[:addresses]
|
||||
hosts = opts_to_hosts(opts)
|
||||
end
|
||||
|
||||
if opts[:port] or opts[:proto]
|
||||
if opts[:host] or opts[:address] or opts[:addresses]
|
||||
services = opts_to_services(hosts,opts)
|
||||
else
|
||||
services = opts_to_services([],opts)
|
||||
end
|
||||
end
|
||||
|
||||
if opts[:port] or opts[:proto]
|
||||
services.each do |s|
|
||||
nret = nil
|
||||
if opts[:ntype]
|
||||
nret = s.notes.find_by_ntype(opts[:ntype])
|
||||
else
|
||||
nret = s.notes
|
||||
end
|
||||
next if nret == nil
|
||||
notes << nret if nret.class == Msf::DBManager::Note
|
||||
notes |= nret if nret.class == Array
|
||||
end
|
||||
elsif opts[:address] or opts[:host] or opts[:addresses]
|
||||
hosts.each do |h|
|
||||
nret = nil
|
||||
if opts[:ntype]
|
||||
nret = h.notes.find_by_ntype(opts[:ntype])
|
||||
else
|
||||
nret = h.notes
|
||||
end
|
||||
next if nret == nil
|
||||
notes << nret if nret.class == Msf::DBManager::Note
|
||||
notes |= nret if nret.class == Array
|
||||
end
|
||||
else
|
||||
nret = nil
|
||||
if opts[:ntype]
|
||||
nret = wspace.notes.find_by_ntype(opts[:ntype])
|
||||
else
|
||||
nret = wspace.notes
|
||||
end
|
||||
notes << nret if nret.class == Msf::DBManager::Note
|
||||
notes |= nret if nret.class == Array
|
||||
end
|
||||
deleted = []
|
||||
notes.each do |n|
|
||||
dent = {}
|
||||
dent[:address] = n.host.address.to_s if n.host
|
||||
dent[:port] = n.service.port if n.service
|
||||
dent[:proto] = n.service.proto if n.service
|
||||
dent[:ntype] = n.ntype
|
||||
deleted << dent
|
||||
n.destroy
|
||||
end
|
||||
|
||||
return { :result => 'success', :deleted => deleted }
|
||||
end
|
||||
|
||||
def del_service(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
hosts = []
|
||||
services = []
|
||||
if opts[:host] or opts[:address]
|
||||
host = opts[:host] || opts[:address]
|
||||
hent = wspace.hosts.find_by_address(host)
|
||||
return { :result => 'failed' } if hent == nil or hent.class != Msf::DBManager::Host
|
||||
hosts << hent
|
||||
elsif opts[:addresses]
|
||||
return { :result => 'failed' } if opts[:addresses].class != Array
|
||||
conditions = { :address => opts[:addresses] }
|
||||
hent = wspace.hosts.all(:conditions => conditions)
|
||||
return { :result => 'failed' } if hent == nil
|
||||
hosts |= hent if hent.class == Array
|
||||
hosts << hent if hent.class == Msf::DBManager::Host
|
||||
end
|
||||
if opts[:addresses] or opts[:address] or opts[:host]
|
||||
hosts.each do |h|
|
||||
sret = nil
|
||||
if opts[:port] or opts[:proto]
|
||||
conditions = {}
|
||||
conditions[:port] = opts[:port] if opts[:port]
|
||||
conditions[:proto] = opts[:proto] if opts[:proto]
|
||||
sret = h.services.all(:conditions => conditions)
|
||||
next if sret == nil
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
services |= sret if sret.class == Array
|
||||
else
|
||||
services |= h.services
|
||||
end
|
||||
end
|
||||
elsif opts[:port] or opts[:proto]
|
||||
conditions = {}
|
||||
conditions[:port] = opts[:port] if opts[:port]
|
||||
conditions[:proto] = opts[:proto] if opts[:proto]
|
||||
sret = wspace.services.all(:conditions => conditions)
|
||||
services << sret if sret and sret.class == Msf::DBManager::Service
|
||||
services |= sret if sret and sret.class == Array
|
||||
end
|
||||
|
||||
|
||||
|
||||
deleted = []
|
||||
services.each do |s|
|
||||
dent = {}
|
||||
dent[:address] = s.host.address.to_s
|
||||
dent[:port] = s.port
|
||||
dent[:proto] = s.proto
|
||||
deleted << dent
|
||||
s.destroy
|
||||
end
|
||||
|
||||
return { :result => 'success', :deleted => deleted }
|
||||
end
|
||||
|
||||
def del_host(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
hosts = []
|
||||
if opts[:host] or opts[:address]
|
||||
host = opts[:host] || opts[:address]
|
||||
hent = wspace.hosts.find_by_address(host)
|
||||
return { :result => 'failed' } if hent == nil or hent.class != Msf::DBManager::Host
|
||||
hosts << hent
|
||||
elsif opts[:addresses]
|
||||
return { :result => 'failed' } if opts[:addresses].class != Array
|
||||
conditions = { :address => opts[:addresses] }
|
||||
hent = wspace.hosts.all(:conditions => conditions)
|
||||
return { :result => 'failed' } if hent == nil
|
||||
hosts |= hent if hent.class == Array
|
||||
hosts << hent if hent.class == Msf::DBManager::Host
|
||||
end
|
||||
deleted = []
|
||||
hosts.each do |h|
|
||||
deleted << h.address.to_s
|
||||
h.destroy
|
||||
end
|
||||
|
||||
return { :result => 'success', :deleted => deleted }
|
||||
end
|
||||
|
||||
|
||||
def report_vuln(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
res = @framework.db.report_vuln(opts)
|
||||
return { :result => 'success' } if(res)
|
||||
{ :result => 'failed' }
|
||||
end
|
||||
|
||||
|
||||
def events(token,wspace = nil)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
wspace = workspace(wspace)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown workspace") if(not wspace)
|
||||
ret = {}
|
||||
ret[:events] = []
|
||||
|
||||
@framework.db.events(wspace).each do |e|
|
||||
event = {}
|
||||
event[:host] = e.host.address || e.host.address6 if(e.host)
|
||||
event[:created_at] = e.created_at.to_i
|
||||
event[:updated_at] = e.updated_at.to_i
|
||||
event[:name] = e.name
|
||||
event[:critical] = e.critical if(e.critical)
|
||||
event[:username] = e.username if(e.username)
|
||||
event[:info] = e.info
|
||||
ret[:events] << event
|
||||
end
|
||||
clean_nils(ret)
|
||||
end
|
||||
def report_event(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
res = @framework.db.report_event(opts)
|
||||
return { :result => 'success' } if(res)
|
||||
end
|
||||
|
||||
#NOTE Path is required
|
||||
#NOTE To match a service need host, port, proto
|
||||
def report_loot(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
if opts[:host] && opts[:port] && opts[:proto]
|
||||
opts[:service] = @framework.db.find_or_create_service(opts)
|
||||
end
|
||||
|
||||
res = @framework.db.report_loot(opts)
|
||||
return { :result => 'success' } if(res)
|
||||
end
|
||||
|
||||
def loots(token,wspace=nil)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
wspace = workspace(wspace)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown workspace") if(not wspace)
|
||||
ret = {}
|
||||
ret[:loots] = []
|
||||
@framework.db.loots(wspace).each do |l|
|
||||
loot = {}
|
||||
loot[:host] = l.host.address || l.host.address6 if(l.host)
|
||||
loot[:service] = l.service.name || l.service.port if(l.service)
|
||||
loot[:ltype] = l.ltype
|
||||
loot[:content_type] = l.content_type
|
||||
loot[:data] = l.data if (l.data)
|
||||
loot[:created_at] = l.created_at.to_i
|
||||
loot[:updated_at] = l.updated_at.to_i
|
||||
loot[:name] = l.name if (l.name)
|
||||
loot[:info] = l.info if (l.info)
|
||||
loot[:path] = l.path
|
||||
ret[:loots] << loot
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
# requires host, port, user, pass, ptype, and active
|
||||
def report_cred(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
res = framework.db.find_or_create_cred(opts)
|
||||
return { :result => 'success' } if(res)
|
||||
{ :result => 'failed' }
|
||||
end
|
||||
|
||||
#right now workspace is the only option supported
|
||||
def creds(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
ret = {}
|
||||
ret[:creds] = []
|
||||
@framework.db.creds(wspace).each do |c|
|
||||
cred = {}
|
||||
cred[:host] = c.service.host.address || c.service.host.address6 if(c.service.host)
|
||||
cred[:time] = c.updated_at
|
||||
cred[:port] = c.service.port
|
||||
cred[:proto] = c.service.proto
|
||||
cred[:sname] = c.service.name
|
||||
cred[:type] = c.ptype
|
||||
cred[:user] = c.user
|
||||
cred[:pass] = c.pass
|
||||
cred[:active] = c.active
|
||||
ret[:creds] << cred
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def import_data(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_msfe_xml(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_nexpose_simplexml(args={})
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_nexpose_rawxml(args={})
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_nmap_xml(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_nessus_nbe(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_nessus_xml(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_nessus_xml_v2(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_qualys_xml(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_ip_list(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_amap_log(args={})
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def import_amap_mlog(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
opts[:data] = Rex::Text.decode_base64(opts[:data])
|
||||
@framework.db.import(opts)
|
||||
return { :result => 'success' }
|
||||
end
|
||||
|
||||
def get_vuln(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
|
||||
opts = fix_options(xopts)
|
||||
opts[:workspace] = workspace(opts[:workspace]) if opts[:workspace]
|
||||
|
||||
ret = {}
|
||||
ret[:vuln] = []
|
||||
|
||||
host = @framework.db.get_host(opts)
|
||||
|
||||
return ret if( not host)
|
||||
vulns = []
|
||||
|
||||
if(opts[:proto] && opts[:port])
|
||||
services = []
|
||||
sret = host.services.find_by_proto_and_port(opts[:proto], opts[:port])
|
||||
return ret if sret == nil
|
||||
services << sret if sret.class == Msf::DBManager::Service
|
||||
services |= sret if sret.class == Array
|
||||
|
||||
services.each do |s|
|
||||
vulns |= s.vulns
|
||||
end
|
||||
else
|
||||
vulns = host.vulns
|
||||
end
|
||||
|
||||
return ret if (not vulns)
|
||||
|
||||
vulns.each do |v|
|
||||
vuln= {}
|
||||
host= v.host
|
||||
vuln[:host] = host.address || host.address6 || "unknown"
|
||||
if v.service
|
||||
vuln[:port] = v.service.port
|
||||
vuln[:proto] = v.service.proto
|
||||
end
|
||||
vuln[:created_at] = v[:created_at].to_i
|
||||
vuln[:updated_at] = v[:updated_at].to_i
|
||||
vuln[:name] = v[:name].to_s
|
||||
vuln[:info] = v[:info].to_s
|
||||
vuln[:refs] = []
|
||||
v.refs.each do |r|
|
||||
vuln[:refs] << r.name
|
||||
end
|
||||
ret[:vuln] << vuln
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
def clients(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
hosts = []
|
||||
clients = []
|
||||
ret = {}
|
||||
ret[:clients] = []
|
||||
|
||||
if opts[:host] or opts[:address] or opts[:addresses]
|
||||
hosts = opts_to_hosts(opts)
|
||||
else
|
||||
hosts = wspace.hosts
|
||||
end
|
||||
|
||||
hosts.each do |h|
|
||||
cret = nil
|
||||
if opts[:ua_name] or opts[:ua_ver]
|
||||
conditions = {}
|
||||
conditions[:ua_name] = opts[:ua_name] if opts[:ua_name]
|
||||
conditions[:ua_ver] = opts[:ua_ver] if opts[:ua_ver]
|
||||
cret = h.clients.all(:conditions => conditions)
|
||||
else
|
||||
cret = h.clients
|
||||
end
|
||||
next if cret == nil
|
||||
clients << cret if cret.class == Msf::DBManager::Client
|
||||
clients |= cret if cret.class == Array
|
||||
end
|
||||
clients.each do |c|
|
||||
client = {}
|
||||
client[:host] = c.host.address.to_s if c.host
|
||||
client[:ua_string] = c.ua_string
|
||||
client[:ua_name] = c.ua_name
|
||||
client[:ua_ver] = c.ua_ver
|
||||
client[:created_at] = c.created_at.to_i
|
||||
client[:updated_at] = c.updated_at.to_i
|
||||
ret[:clients] << client
|
||||
end
|
||||
clean_nils(ret)
|
||||
end
|
||||
|
||||
def del_client(token,xopts)
|
||||
authenticate(token)
|
||||
raise ::XMLRPC::FaultException.new(404, "database not loaded") if(not db)
|
||||
|
||||
opts = fix_options(xopts)
|
||||
wspace = workspace(opts[:workspace])
|
||||
hosts = []
|
||||
clients = []
|
||||
|
||||
if opts[:host] or opts[:address] or opts[:addresses]
|
||||
hosts = opts_to_hosts(opts)
|
||||
else
|
||||
hosts = wspace.hosts
|
||||
end
|
||||
|
||||
hosts.each do |h|
|
||||
cret = nil
|
||||
if opts[:ua_name] or opts[:ua_ver]
|
||||
conditions = {}
|
||||
conditions[:ua_name] = opts[:ua_name] if opts[:ua_name]
|
||||
conditions[:ua_ver] = opts[:ua_ver] if opts[:ua_ver]
|
||||
cret = h.clients.all(:conditions => conditions)
|
||||
else
|
||||
cret = h.clients
|
||||
end
|
||||
next if cret == nil
|
||||
clients << cret if cret.class == Msf::DBManager::Client
|
||||
clients |= cret if cret.class == Array
|
||||
end
|
||||
|
||||
deleted = []
|
||||
clients.each do |c|
|
||||
dent = {}
|
||||
dent[:address] = c.host.address.to_s
|
||||
dent[:ua_string] = c.ua_string
|
||||
deleted << dent
|
||||
c.destroy
|
||||
end
|
||||
|
||||
return { :result => 'success', :deleted => deleted }
|
||||
|
||||
end
|
||||
|
||||
def driver(token,xopts)
|
||||
authenticate(token)
|
||||
opts = fix_options(xopts)
|
||||
if opts[:driver]
|
||||
if @framework.db.drivers.include?(opts[:driver])
|
||||
@framework.db.driver = opts[:driver]
|
||||
return { :result => 'success' }
|
||||
else
|
||||
return { :result => 'failed' }
|
||||
|
||||
end
|
||||
else
|
||||
return { :driver => @framework.db.driver.to_s }
|
||||
end
|
||||
return { :result => 'failed' }
|
||||
end
|
||||
|
||||
def connect(token,xopts)
|
||||
authenticate(token)
|
||||
opts = fix_options(xopts)
|
||||
if(not @framework.db.driver and not opts[:driver])
|
||||
return { :result => 'failed' }
|
||||
end
|
||||
|
||||
if opts[:driver]
|
||||
if @framework.db.drivers.include?(opts[:driver])
|
||||
@framework.db.driver = opts[:driver]
|
||||
else
|
||||
return { :result => 'failed' }
|
||||
end
|
||||
end
|
||||
|
||||
driver = @framework.db.driver
|
||||
|
||||
case driver
|
||||
when 'postgresql'
|
||||
opts['adapter'] = 'postgresql'
|
||||
else
|
||||
return { :result => 'failed' }
|
||||
end
|
||||
|
||||
if (not @framework.db.connect(opts))
|
||||
return { :result => 'failed' }
|
||||
end
|
||||
return { :result => 'success' }
|
||||
|
||||
end
|
||||
|
||||
def status(token)
|
||||
authenticate(token)
|
||||
if (not @framework.db.driver)
|
||||
return {:driver => 'None' }
|
||||
end
|
||||
cdb = ""
|
||||
if ActiveRecord::Base.connected? and ActiveRecord::Base.connection.active?
|
||||
if ActiveRecord::Base.connection.respond_to? :current_database
|
||||
cdb = ActiveRecord::Base.connection.current_database
|
||||
else
|
||||
cdb = ActiveRecord::Base.connection.instance_variable_get(:@config)[:database]
|
||||
end
|
||||
return {:driver => @framework.db.driver.to_s , :db => cdb }
|
||||
else
|
||||
return {:driver => @framework.db.driver.to_s}
|
||||
end
|
||||
return {:driver => 'None' }
|
||||
end
|
||||
|
||||
def disconnect(token)
|
||||
authenticate(token)
|
||||
if (@framework.db)
|
||||
@framework.db.disconnect()
|
||||
return { :result => 'success' }
|
||||
else
|
||||
return { :result => 'failed' }
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,49 +0,0 @@
|
||||
module Msf
|
||||
module RPC
|
||||
class Job < Base
|
||||
|
||||
def list(token)
|
||||
authenticate(token)
|
||||
res = {}
|
||||
res['jobs'] = {}
|
||||
@framework.jobs.each do |j|
|
||||
res['jobs'][j[0]] = j[1].name
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
def stop(token,jid)
|
||||
authenticate(token)
|
||||
obj = @framework.jobs[jid.to_s]
|
||||
if(not obj)
|
||||
raise ::XMLRPC::FaultException.new(404, "no such job")
|
||||
else
|
||||
obj.stop
|
||||
{ "result" => "success" }
|
||||
end
|
||||
end
|
||||
def info(token,jid)
|
||||
authenticate(token)
|
||||
obj = @framework.jobs[jid.to_s]
|
||||
if(not obj)
|
||||
raise ::XMLRPC::FaultException.new(404, "no such job")
|
||||
else
|
||||
info = {
|
||||
"jid" => obj.jid,
|
||||
"name" => obj.name,
|
||||
"start_time" => obj.start_time.to_i
|
||||
}
|
||||
if obj.ctx && obj.ctx[0]
|
||||
if obj.ctx[0].respond_to?(:get_resource)
|
||||
info['uripath'] = obj.ctx[0].get_resource
|
||||
end
|
||||
if obj.ctx[0].respond_to?(:datastore)
|
||||
info['datastore'] = obj.ctx[0].datastore
|
||||
end
|
||||
end
|
||||
{ "result" => "success" , "info" => info}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,333 +0,0 @@
|
||||
##
|
||||
# $Id$
|
||||
##
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
class Module < Base
|
||||
|
||||
def exploits(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.exploits.keys }
|
||||
end
|
||||
|
||||
def auxiliary(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.auxiliary.keys }
|
||||
end
|
||||
|
||||
def payloads(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.payloads.keys }
|
||||
end
|
||||
|
||||
def encoders(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.encoders.keys }
|
||||
end
|
||||
|
||||
def nops(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.nops.keys }
|
||||
end
|
||||
|
||||
def post(token)
|
||||
authenticate(token)
|
||||
{ "modules" => @framework.post.keys }
|
||||
end
|
||||
|
||||
|
||||
def info(token, mtype, mname)
|
||||
authenticate(token)
|
||||
|
||||
m = _find_module(mtype,mname)
|
||||
res = {}
|
||||
|
||||
res['name'] = m.name
|
||||
res['description'] = m.description
|
||||
res['license'] = m.license
|
||||
res['filepath'] = m.file_path
|
||||
res['version'] = m.version
|
||||
res['rank'] = m.rank.to_i
|
||||
|
||||
res['references'] = []
|
||||
m.references.each do |r|
|
||||
res['references'] << [r.ctx_id, r.ctx_val]
|
||||
end
|
||||
|
||||
res['authors'] = []
|
||||
m.each_author do |a|
|
||||
res['authors'] << a.to_s
|
||||
end
|
||||
|
||||
if(m.type == "exploit")
|
||||
res['targets'] = {}
|
||||
m.targets.each_index do |i|
|
||||
res['targets'][i] = m.targets[i].name
|
||||
end
|
||||
|
||||
if (m.default_target)
|
||||
res['default_target'] = m.default_target
|
||||
end
|
||||
end
|
||||
|
||||
if(m.type == "auxiliary")
|
||||
res['actions'] = {}
|
||||
m.actions.each_index do |i|
|
||||
res['actions'][i] = m.actions[i].name
|
||||
end
|
||||
|
||||
if (m.default_action)
|
||||
res['default_action'] = m.default_action
|
||||
end
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
|
||||
def compatible_payloads(token, mname)
|
||||
authenticate(token)
|
||||
m = _find_module('exploit',mname)
|
||||
if(not m)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
res = {}
|
||||
res['payloads'] = []
|
||||
m.compatible_payloads.each do |k|
|
||||
res['payloads'] << k[0]
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def compatible_sessions(token, mname)
|
||||
authenticate(token)
|
||||
m = _find_module('post',mname)
|
||||
if(not m)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
res = {}
|
||||
res['sessions'] = m.compatible_sessions
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def target_compatible_payloads(token, mname, target)
|
||||
authenticate(token)
|
||||
m = _find_module('exploit',mname)
|
||||
if(not m)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
res = {}
|
||||
res['payloads'] = []
|
||||
m.datastore['TARGET'] = target.to_i
|
||||
m.compatible_payloads.each do |k|
|
||||
res['payloads'] << k[0]
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def options(token, mtype, mname)
|
||||
authenticate(token)
|
||||
|
||||
m = _find_module(mtype,mname)
|
||||
|
||||
res = {}
|
||||
|
||||
m.options.each_key do |k|
|
||||
o = m.options[k]
|
||||
res[k] = {
|
||||
'type' => o.type,
|
||||
'required' => o.required,
|
||||
'advanced' => o.advanced,
|
||||
'evasion' => o.evasion,
|
||||
'desc' => o.desc
|
||||
}
|
||||
|
||||
if(not o.default.nil?)
|
||||
res[k]['default'] = o.default
|
||||
end
|
||||
|
||||
if(o.enums.length > 1)
|
||||
res[k]['enums'] = o.enums
|
||||
end
|
||||
end
|
||||
|
||||
res
|
||||
end
|
||||
|
||||
def execute(token, mtype, mname, opts)
|
||||
authenticate(token)
|
||||
|
||||
mod = _find_module(mtype,mname)
|
||||
case mtype
|
||||
when 'exploit'
|
||||
_run_exploit(mod, opts)
|
||||
when 'auxiliary'
|
||||
_run_auxiliary(mod, opts)
|
||||
when 'payload'
|
||||
_run_payload(mod, opts)
|
||||
when 'post'
|
||||
_run_post(mod, opts)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def encode(token, data, encoder, options)
|
||||
authenticate(token)
|
||||
buf = Rex::Text.decode_base64(data)
|
||||
|
||||
# Load supported formats
|
||||
supported_formats = Msf::Simple::Buffer.transform_formats + Msf::Util::EXE.to_executable_fmt_formats
|
||||
|
||||
if (fmt = options['format'])
|
||||
if not supported_formats.include?(fmt)
|
||||
raise ::XMLRPC::FaultException.new(500, "failed to generate: invalid format: #{fmt}")
|
||||
end
|
||||
end
|
||||
|
||||
badchars = ''
|
||||
if options['badchars']
|
||||
badchars = Rex::Text.hex_to_raw(options['badchars'])
|
||||
end
|
||||
|
||||
plat = nil
|
||||
if options['plat']
|
||||
plat = Msf::Module::PlatformList.transform(val)
|
||||
end
|
||||
arch = nil
|
||||
if options['arch']
|
||||
arch = options['arch']
|
||||
end
|
||||
|
||||
ecount = 1
|
||||
if options['ecount']
|
||||
ecount = options['ecount'].to_i
|
||||
end
|
||||
|
||||
exeopts = {
|
||||
:inject => options['inject'],
|
||||
:template => options['altexe'],
|
||||
:template_path => options['exedir']
|
||||
}
|
||||
|
||||
# If we were given addshellcode for a win32 payload,
|
||||
# create a double-payload; one running in one thread, one running in the other
|
||||
if options['addshellcode']
|
||||
buf = Msf::Util::EXE.win32_rwx_exec_thread(buf,0,'end')
|
||||
file = ::File.new(options['addshellcode'])
|
||||
file.binmode
|
||||
buf << file.read
|
||||
file.close
|
||||
end
|
||||
|
||||
enc = @framework.encoders.create(encoder)
|
||||
|
||||
begin
|
||||
# Imports options
|
||||
enc.datastore.update(options)
|
||||
|
||||
raw = buf.dup
|
||||
|
||||
1.upto(ecount) do |iteration|
|
||||
# Encode it up
|
||||
raw = enc.encode(raw, badchars, nil, plat)
|
||||
end
|
||||
|
||||
output = Msf::Util::EXE.to_executable_fmt(@framework, arch, plat, raw, fmt, exeopts)
|
||||
|
||||
if not output
|
||||
fmt ||= "ruby"
|
||||
output = Msf::Simple::Buffer.transform(raw, fmt)
|
||||
end
|
||||
|
||||
# How to warn?
|
||||
#if exeopts[:fellback]
|
||||
# $stderr.puts(OutError + "Warning: Falling back to default template: #{exeopts[:fellback]}")
|
||||
#end
|
||||
|
||||
{"encoded" => Rex::Text.encode_base64(output.to_s)}
|
||||
rescue => e
|
||||
raise ::XMLRPC::FaultException.new(500, "#{enc.refname} failed: #{e} #{e.backtrace}")
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _find_module(mtype,mname)
|
||||
mod = @framework.modules.create(mname)
|
||||
|
||||
if(not mod)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
mod
|
||||
end
|
||||
|
||||
def _run_exploit(mod, opts)
|
||||
s = Msf::Simple::Exploit.exploit_simple(mod, {
|
||||
'Payload' => opts['PAYLOAD'],
|
||||
'Target' => opts['TARGET'],
|
||||
'RunAsJob' => true,
|
||||
'Options' => opts
|
||||
})
|
||||
{"result" => "success"}
|
||||
end
|
||||
|
||||
def _run_auxiliary(mod, opts)
|
||||
Msf::Simple::Auxiliary.run_simple(mod, {
|
||||
'Action' => opts['ACTION'],
|
||||
'RunAsJob' => true,
|
||||
'Options' => opts
|
||||
})
|
||||
{"result" => "success"}
|
||||
end
|
||||
|
||||
def _run_payload(mod, opts)
|
||||
badchars = [opts['BadChars'] || ''].pack("H*")
|
||||
fmt = opts['Format'] || 'raw'
|
||||
force = opts['ForceEncode'] || false
|
||||
template = opts['Template'] || nil
|
||||
plat = opts['Platform'] || nil
|
||||
keep = opts['KeepTemplateWorking'] || false
|
||||
force = opts['ForceEncode'] || false
|
||||
sled_size = opts['NopSledSize'].to_i || 0
|
||||
iter = opts['Iterations'].to_i || 0
|
||||
|
||||
begin
|
||||
res = Msf::Simple::Payload.generate_simple(mod, {
|
||||
'BadChars' => badchars,
|
||||
'Encoder' => opts['Encoder'],
|
||||
'Format' => fmt,
|
||||
'NoComment' => true,
|
||||
'NopSledSize' => sled_size,
|
||||
'Options' => opts,
|
||||
'ForceEncode' => force,
|
||||
'Template' => template,
|
||||
'Platform' => plat,
|
||||
'KeepTemplateWorking' => keep,
|
||||
'Iterations' => iter
|
||||
})
|
||||
|
||||
{"result" => "success", "payload" => res.unpack("H*")[0]}
|
||||
rescue ::Exception => e
|
||||
raise ::XMLRPC::FaultException.new(500, "failed to generate: #{e.message}")
|
||||
end
|
||||
end
|
||||
|
||||
def _run_post(mod, opts)
|
||||
Msf::Simple::Post.run_simple(mod, {
|
||||
'RunAsJob' => true,
|
||||
'Options' => opts
|
||||
})
|
||||
{"result" => "success"}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
module Msf
|
||||
module RPC
|
||||
class Plugin < Base
|
||||
|
||||
def load(token,path,xopts = {})
|
||||
|
||||
authenticate(token)
|
||||
opts = {}
|
||||
|
||||
xopts.each do |k,v|
|
||||
if k.class == String
|
||||
opts[k.to_sym] = v
|
||||
end
|
||||
end
|
||||
|
||||
if (path !~ /#{File::SEPARATOR}/)
|
||||
plugin_file_name = path
|
||||
|
||||
# If the plugin isn't in the user direcotry (~/.msf3/plugins/), use the base
|
||||
path = Msf::Config.user_plugin_directory + File::SEPARATOR + plugin_file_name
|
||||
if not File.exists?( path + ".rb" )
|
||||
# If the following "path" doesn't exist it will be caught when we attempt to load
|
||||
path = Msf::Config.plugin_directory + File::SEPARATOR + plugin_file_name
|
||||
end
|
||||
end
|
||||
|
||||
begin
|
||||
if (inst = @framework.plugins.load(path, opts))
|
||||
return { "result" => "success" }
|
||||
end
|
||||
rescue ::Exception => e
|
||||
elog("Error loading plugin #{path}: #{e}\n\n#{e.backtrace.join("\n")}", src = 'core', level = 0, from = caller)
|
||||
return { "result" => "failure" }
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
def unload(token,name)
|
||||
authenticate(token)
|
||||
@framework.plugins.each { |plugin|
|
||||
# Unload the plugin if it matches the name we're searching for
|
||||
if (plugin.name == name)
|
||||
@framework.plugins.unload(plugin)
|
||||
return { "result" => "success" }
|
||||
end
|
||||
}
|
||||
return { "result" => "failure" }
|
||||
|
||||
end
|
||||
|
||||
def loaded(token)
|
||||
authenticate(token)
|
||||
ret = {}
|
||||
ret[:plugins] = []
|
||||
@framework.plugins.each do |plugin|
|
||||
ret[:plugins] << plugin.name
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,210 +0,0 @@
|
||||
require "xmlrpc/server"
|
||||
require 'rex/service_manager'
|
||||
require "rex"
|
||||
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
|
||||
|
||||
module MonkeyPatcher
|
||||
def initialize(*args)
|
||||
|
||||
# Enable Bigint processing (required for big file sizes,etc)
|
||||
if XMLRPC::Config.const_defined?(:ENABLE_BIGINT)
|
||||
XMLRPC::Config.send(:remove_const, :ENABLE_BIGINT)
|
||||
XMLRPC::Config.const_set(:ENABLE_BIGINT, true)
|
||||
end
|
||||
|
||||
# Enable nils in requests
|
||||
if XMLRPC::Config.const_defined?(:ENABLE_NIL_CREATE)
|
||||
XMLRPC::Config.send(:remove_const, :ENABLE_NIL_CREATE)
|
||||
XMLRPC::Config.const_set(:ENABLE_NIL_CREATE, true)
|
||||
end
|
||||
|
||||
# Enable nils in replies
|
||||
if XMLRPC::Config.const_defined?(:ENABLE_NIL_PARSER)
|
||||
XMLRPC::Config.send(:remove_const, :ENABLE_NIL_PARSER)
|
||||
XMLRPC::Config.const_set(:ENABLE_NIL_PARSER, true)
|
||||
end
|
||||
|
||||
super(*args)
|
||||
end
|
||||
end
|
||||
|
||||
class Service < ::XMLRPC::BasicServer
|
||||
|
||||
include MonkeyPatcher
|
||||
|
||||
attr_accessor :service, :state, :on_input, :on_output, :on_error
|
||||
attr_accessor :dispatcher_timeout
|
||||
|
||||
def initialize(srvhost, srvport, ssl=false, cert=nil, ckey=nil)
|
||||
|
||||
self.dispatcher_timeout = 0
|
||||
|
||||
self.service = Rex::Socket::TcpServer.create(
|
||||
'LocalHost' => srvhost,
|
||||
'LocalPort' => srvport,
|
||||
'SSL' => ssl
|
||||
)
|
||||
|
||||
self.service.on_client_connect_proc = Proc.new { |client|
|
||||
on_client_connect(client)
|
||||
}
|
||||
self.service.on_client_data_proc = Proc.new { |client|
|
||||
begin
|
||||
Timeout.timeout(self.dispatcher_timeout) do
|
||||
on_client_data(client)
|
||||
end
|
||||
rescue ::EOFError => e
|
||||
raise e
|
||||
rescue ::Exception => e
|
||||
wlog("XMLRPC Server Error: #{client.inspect} #{e.class} #{e} #{e.backtrace}")
|
||||
raise e
|
||||
end
|
||||
}
|
||||
self.service.on_client_close_proc = Proc.new { |client|
|
||||
on_client_close(client)
|
||||
}
|
||||
|
||||
self.state = {}
|
||||
super()
|
||||
end
|
||||
|
||||
def start
|
||||
self.state = {}
|
||||
self.service.start
|
||||
end
|
||||
|
||||
def stop
|
||||
self.state = {}
|
||||
self.service.stop
|
||||
self.service.close
|
||||
end
|
||||
|
||||
def wait
|
||||
self.service.wait
|
||||
end
|
||||
|
||||
def on_client_close(c)
|
||||
self.state.delete(c)
|
||||
end
|
||||
|
||||
def on_client_connect(c)
|
||||
self.state[c] = ""
|
||||
self.clean_state_table
|
||||
end
|
||||
|
||||
def on_client_data(c)
|
||||
data = c.get_once(-1)
|
||||
if(not data)
|
||||
c.close
|
||||
return
|
||||
end
|
||||
|
||||
if not self.state[c]
|
||||
c.close
|
||||
return
|
||||
end
|
||||
|
||||
self.state[c] << data
|
||||
procxml(c)
|
||||
end
|
||||
|
||||
def clean_state_table
|
||||
self.state.keys.each do |s|
|
||||
self.state.delete(s) if s.closed?
|
||||
end
|
||||
end
|
||||
|
||||
def procxml(c)
|
||||
while(self.state[c].index("\x00"))
|
||||
mesg,left = self.state[c].split("\x00", 2)
|
||||
self.state[c] = left
|
||||
begin
|
||||
self.on_input.call(mesg) if self.on_input
|
||||
|
||||
res = process(mesg)
|
||||
|
||||
self.on_output.call(res) if self.on_output
|
||||
|
||||
c.put(res+"\x00")
|
||||
rescue ::Interrupt
|
||||
raise $!
|
||||
rescue ::Exception => e
|
||||
self.on_error.call(e) if self.on_error
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
class WebService < ::XMLRPC::BasicServer
|
||||
|
||||
include MonkeyPatcher
|
||||
|
||||
attr_accessor :service, :state, :srvhost, :srvport, :uri
|
||||
|
||||
|
||||
def initialize(port, host, uri = "/RPC2")
|
||||
self.srvhost = host
|
||||
self.srvport = port
|
||||
self.uri = uri
|
||||
self.service = nil
|
||||
super()
|
||||
end
|
||||
|
||||
def start
|
||||
self.state = {}
|
||||
self.service = Rex::ServiceManager.start(
|
||||
Rex::Proto::Http::Server,
|
||||
self.srvport,
|
||||
self.srvhost,
|
||||
{}
|
||||
)
|
||||
|
||||
uopts = {
|
||||
'Proc' => Proc.new { |cli, req|
|
||||
on_request_uri(cli, req)
|
||||
},
|
||||
'Path' => self.uri
|
||||
}
|
||||
|
||||
self.service.add_resource(self.uri,uopts)
|
||||
end
|
||||
|
||||
def stop
|
||||
self.state = {}
|
||||
self.service.stop
|
||||
end
|
||||
|
||||
def wait
|
||||
self.service.wait
|
||||
end
|
||||
|
||||
def on_client_close(c)
|
||||
self.state.delete(c)
|
||||
end
|
||||
|
||||
def on_client_connect(c)
|
||||
self.state[c] = ""
|
||||
end
|
||||
def on_request_uri(cli, req)
|
||||
begin
|
||||
res = Rex::Proto::Http::Response.new()
|
||||
res["Content-Type"] = "text/xml"
|
||||
res.body = process(req.body)
|
||||
rescue XMLRPC::FaultException => e
|
||||
res = Rex::Proto::Http::Response.new(e.faultCode,e.faultString)
|
||||
rescue
|
||||
res = Rex::Proto::Http::Response.new(404,"An Error Occured")
|
||||
end
|
||||
cli.send_response(res)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,242 +0,0 @@
|
||||
require 'rex'
|
||||
require 'rex/ui/text/output/buffer'
|
||||
|
||||
module Msf
|
||||
module RPC
|
||||
class Session < Base
|
||||
|
||||
|
||||
def list(token)
|
||||
authenticate(token)
|
||||
res = {}
|
||||
@framework.sessions.each do |sess|
|
||||
i,s = sess
|
||||
res[s.sid] = {
|
||||
'type' => s.type.to_s,
|
||||
'tunnel_local'=> s.tunnel_local.to_s,
|
||||
'tunnel_peer' => s.tunnel_peer.to_s,
|
||||
'via_exploit' => s.via_exploit.to_s,
|
||||
'via_payload' => s.via_payload.to_s,
|
||||
'desc' => s.desc.to_s,
|
||||
'info' => s.info.to_s,
|
||||
'workspace' => s.workspace.to_s,
|
||||
'target_host' => s.target_host.to_s,
|
||||
'username' => s.username.to_s,
|
||||
'uuid' => s.uuid.to_s,
|
||||
'exploit_uuid' => s.exploit_uuid.to_s,
|
||||
'routes' => s.routes.join(",")
|
||||
}
|
||||
if(s.type.to_s == "meterpreter")
|
||||
res[s.sid]['platform'] = s.platform.to_s
|
||||
end
|
||||
end
|
||||
res
|
||||
end
|
||||
|
||||
def stop(token, sid)
|
||||
authenticate(token)
|
||||
s = @framework.sessions[sid.to_i]
|
||||
if(not s)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown session while stopping")
|
||||
end
|
||||
s.kill
|
||||
{ "result" => "success" }
|
||||
end
|
||||
|
||||
# Shell read is now a positon-aware reader of the shell's associated
|
||||
# ring buffer. For more direct control of the pointer into a ring
|
||||
# buffer, a client can instead use ring_read, and note the returned
|
||||
# sequence number on their own (making multiple views into the same
|
||||
# session possible, regardless of position in the stream)
|
||||
def shell_read(token, sid, ptr=nil)
|
||||
_valid_session(token,sid,"shell")
|
||||
# @session_sequence tracks the pointer into the ring buffer
|
||||
# data of sessions (by sid) in order to emulate the old behavior
|
||||
# of shell_read
|
||||
@session_sequence ||= {}
|
||||
@session_sequence[sid] ||= 0
|
||||
ring_buffer = ring_read(token,sid,(ptr || @session_sequence[sid]))
|
||||
if not (ring_buffer["seq"].nil? || ring_buffer["seq"].empty?)
|
||||
@session_sequence[sid] = ring_buffer["seq"].to_i
|
||||
end
|
||||
return ring_buffer
|
||||
end
|
||||
|
||||
# shell_write is pretty much totally identical to ring_put
|
||||
def shell_write(token, sid, data)
|
||||
_valid_session(token,sid,"shell")
|
||||
ring_put(token,sid,data)
|
||||
end
|
||||
|
||||
def shell_upgrade(token, sid, lhost, lport)
|
||||
s = _valid_session(token,sid,"shell")
|
||||
s.exploit_datastore['LHOST'] = lhost
|
||||
s.exploit_datastore['LPORT'] = lport
|
||||
s.execute_script('spawn_meterpreter', nil)
|
||||
{ "result" => "success" }
|
||||
end
|
||||
|
||||
def meterpreter_read(token, sid)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
|
||||
if not s.user_output.respond_to? :dump_buffer
|
||||
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
|
||||
end
|
||||
|
||||
data = s.user_output.dump_buffer
|
||||
{ "data" => Rex::Text.encode_base64(data), "encoding" => "base64" }
|
||||
end
|
||||
|
||||
def ring_read(token, sid, ptr=nil)
|
||||
authenticate(token)
|
||||
s = _valid_session(token,sid,"ring")
|
||||
begin
|
||||
res = s.ring.read_data(ptr)
|
||||
{ "seq" => res[0].to_s, "data" =>(Rex::Text.encode_base64(res[1].to_s)), "encoding" => "base64"}
|
||||
rescue ::Exception => e
|
||||
raise ::XMLRPC::FaultException.new(500, "session disconnected: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
def ring_put(token, sid, data)
|
||||
authenticate(token)
|
||||
s = _valid_session(token,sid,"ring")
|
||||
buff = Rex::Text.decode_base64(data)
|
||||
begin
|
||||
res = s.shell_write(buff)
|
||||
{ "write_count" => res.to_s}
|
||||
rescue ::Exception => e
|
||||
raise ::XMLRPC::FaultException.new(500, "session disconnected: #{e.class} #{e}")
|
||||
end
|
||||
end
|
||||
|
||||
def ring_last(token, sid)
|
||||
authenticate(token)
|
||||
s = _valid_session(token,sid,"ring")
|
||||
{ "seq" => s.ring.last_sequence.to_s }
|
||||
end
|
||||
|
||||
def ring_clear(token, sid)
|
||||
authenticate(token)
|
||||
s = _valid_session(token,sid,"ring")
|
||||
res = s.ring.clear_data
|
||||
if res.compact.empty?
|
||||
{ "result" => "success"}
|
||||
else # Doesn't seem like this can fail. Maybe a race?
|
||||
{ "result" => "failure"}
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Run a single meterpreter console command
|
||||
#
|
||||
def meterpreter_write(token, sid, data)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
|
||||
if not s.user_output.respond_to? :dump_buffer
|
||||
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
|
||||
end
|
||||
|
||||
buff = Rex::Text.decode_base64(data)
|
||||
|
||||
interacting = false
|
||||
s.channels.each_value do |ch|
|
||||
interacting ||= ch.respond_to?('interacting') && ch.interacting
|
||||
end
|
||||
if interacting
|
||||
s.user_input.put(buff+"\n")
|
||||
else
|
||||
@framework.threads.spawn("MeterpreterRunSingle", false, s) { |sess| sess.console.run_single(buff) }
|
||||
end
|
||||
{}
|
||||
end
|
||||
|
||||
def meterpreter_session_detach(token,sid)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
s.channels.each_value do |ch|
|
||||
if(ch.respond_to?('interacting') && ch.interacting)
|
||||
ch.detach()
|
||||
return { "result" => "success" }
|
||||
end
|
||||
end
|
||||
{ "result" => "failure" }
|
||||
end
|
||||
|
||||
def meterpreter_session_kill(token,sid)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
s.channels.each_value do |ch|
|
||||
if(ch.respond_to?('interacting') && ch.interacting)
|
||||
ch._close
|
||||
return { "result" => "success" }
|
||||
end
|
||||
end
|
||||
{ "result" => "failure" }
|
||||
end
|
||||
|
||||
def meterpreter_tabs(token,sid, line)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
{ "tabs" => s.console.tab_complete(line) }
|
||||
end
|
||||
|
||||
# runs a meterpreter command even if interacting with a shell or other channel
|
||||
def meterpreter_run_single(token, sid, data)
|
||||
s = _valid_session(token,sid,"meterpreter")
|
||||
|
||||
if not s.user_output.respond_to? :dump_buffer
|
||||
s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new)
|
||||
end
|
||||
|
||||
@framework.threads.spawn("MeterpreterRunSingle", false, s) { |sess| sess.console.run_single(data) }
|
||||
{}
|
||||
end
|
||||
|
||||
def meterpreter_script(token, sid, data)
|
||||
meterpreter_run_single(token, sid, "run #{data}")
|
||||
end
|
||||
|
||||
def compatible_modules(token, sid)
|
||||
authenticate(token)
|
||||
ret = []
|
||||
|
||||
mtype = "post"
|
||||
names = @framework.post.keys.map{ |x| "post/#{x}" }
|
||||
names.each do |mname|
|
||||
m = _find_module(mtype, mname)
|
||||
next if not m.session_compatible?(sid)
|
||||
ret << m.fullname
|
||||
end
|
||||
ret
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def _find_module(mtype,mname)
|
||||
mod = @framework.modules.create(mname)
|
||||
|
||||
if(not mod)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown module")
|
||||
end
|
||||
|
||||
mod
|
||||
end
|
||||
|
||||
def _valid_session(token,sid,type)
|
||||
authenticate(token)
|
||||
s = @framework.sessions[sid.to_i]
|
||||
if(not s)
|
||||
raise ::XMLRPC::FaultException.new(404, "unknown session while validating")
|
||||
end
|
||||
if type == "ring"
|
||||
if not s.respond_to?(:ring)
|
||||
raise ::XMLRPC::FaultException.new(403, "session #{s.type} does not support ring operations")
|
||||
end
|
||||
elsif(s.type != type)
|
||||
raise ::XMLRPC::FaultException.new(403, "session is not "+type)
|
||||
end
|
||||
s
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -100,7 +100,6 @@ public
|
||||
host = {}
|
||||
host[:created_at] = h.created_at.to_i
|
||||
host[:address] = h.address.to_s
|
||||
host[:address6] = h.address6.to_s
|
||||
host[:mac] = h.mac.to_s
|
||||
host[:name] = h.name.to_s
|
||||
host[:state] = h.state.to_s
|
||||
@@ -135,7 +134,7 @@ public
|
||||
:limit => limit, :offset => offset).each do |s|
|
||||
service = {}
|
||||
host = s.host
|
||||
service[:host] = host.address || host.address6 || "unknown"
|
||||
service[:host] = host.address || "unknown"
|
||||
service[:created_at] = s[:created_at].to_i
|
||||
service[:updated_at] = s[:updated_at].to_i
|
||||
service[:port] = s[:port]
|
||||
@@ -172,7 +171,7 @@ public
|
||||
vuln[:proto] = nil
|
||||
end
|
||||
vuln[:time] = v.created_at.to_i
|
||||
vuln[:host] = v.host.address || v.host.address6 || nil
|
||||
vuln[:host] = v.host.address || nil
|
||||
vuln[:name] = v.name
|
||||
vuln[:refs] = reflist.join(',')
|
||||
ret[:vulns] << vuln
|
||||
@@ -261,7 +260,6 @@ public
|
||||
host = {}
|
||||
host[:created_at] = h.created_at.to_i
|
||||
host[:address] = h.address.to_s
|
||||
host[:address6] = h.address6.to_s
|
||||
host[:mac] = h.mac.to_s
|
||||
host[:name] = h.name.to_s
|
||||
host[:state] = h.state.to_s
|
||||
@@ -324,7 +322,7 @@ public
|
||||
services.each do |s|
|
||||
service = {}
|
||||
host = s.host
|
||||
service[:host] = host.address || host.address6 || "unknown"
|
||||
service[:host] = host.address || "unknown"
|
||||
service[:created_at] = s[:created_at].to_i
|
||||
service[:updated_at] = s[:updated_at].to_i
|
||||
service[:port] = s[:port]
|
||||
@@ -371,7 +369,7 @@ public
|
||||
notes.each do |n|
|
||||
note = {}
|
||||
host = n.host
|
||||
note[:host] = host.address || host.address6 || "unknown"
|
||||
note[:host] = host.address || "unknown"
|
||||
if n.service
|
||||
note[:port] = n.service.port
|
||||
note[:proto] = n.service.proto
|
||||
@@ -449,7 +447,7 @@ public
|
||||
note[:time] = n.created_at.to_i
|
||||
note[:host] = ""
|
||||
note[:service] = ""
|
||||
note[:host] = n.host.address || n.host.address6 if(n.host)
|
||||
note[:host] = n.host.address if(n.host)
|
||||
note[:service] = n.service.name || n.service.port if(n.service)
|
||||
note[:type ] = n.ntype.to_s
|
||||
note[:data] = n.data.inspect
|
||||
@@ -718,7 +716,7 @@ public
|
||||
|
||||
wspace.events.all(:limit => limit, :offset => offset).each do |e|
|
||||
event = {}
|
||||
event[:host] = e.host.address || e.host.address6 if(e.host)
|
||||
event[:host] = e.host.address if(e.host)
|
||||
event[:created_at] = e.created_at.to_i
|
||||
event[:updated_at] = e.updated_at.to_i
|
||||
event[:name] = e.name
|
||||
@@ -757,7 +755,7 @@ public
|
||||
ret[:loots] = []
|
||||
wspace.loots.all(:limit => limit, :offset => offset).each do |l|
|
||||
loot = {}
|
||||
loot[:host] = l.host.address || l.host.address6 if(l.host)
|
||||
loot[:host] = l.host.address if(l.host)
|
||||
loot[:service] = l.service.name || n.service.port if(n.service)
|
||||
loot[:ltype] = l.ltype
|
||||
loot[:ctype] = l.ctype
|
||||
@@ -790,7 +788,7 @@ public
|
||||
DBManager::Cred.find(:all, :include => {:service => :host}, :conditions => ["hosts.workspace_id = ?",
|
||||
framework.db.workspace.id ], :limit => limit, :offset => offset).each do |c|
|
||||
cred = {}
|
||||
cred[:host] = c.service.host.address || c.service.host.address6 if(c.service.host)
|
||||
cred[:host] = c.service.host.address if(c.service.host)
|
||||
cred[:updated_at] = c.updated_at.to_i
|
||||
cred[:port] = c.service.port
|
||||
cred[:proto] = c.service.proto
|
||||
@@ -840,7 +838,7 @@ public
|
||||
vulns.each do |v|
|
||||
vuln= {}
|
||||
host= v.host
|
||||
vuln[:host] = host.address || host.address6 || "unknown"
|
||||
vuln[:host] = host.address || "unknown"
|
||||
if v.service
|
||||
vuln[:port] = v.service.port
|
||||
vuln[:proto] = v.service.proto
|
||||
|
||||
+31
-9
@@ -169,7 +169,7 @@ module Socket
|
||||
#
|
||||
def self.getaddress(addr, accept_ipv6 = true)
|
||||
begin
|
||||
if dotted_ip?(addr)
|
||||
if addr =~ MATCH_IPV4 or (accept_ipv6 and addr =~ MATCH_IPV6)
|
||||
return addr
|
||||
end
|
||||
|
||||
@@ -205,12 +205,12 @@ module Socket
|
||||
#
|
||||
def self.getaddresses(addr, accept_ipv6 = true)
|
||||
begin
|
||||
if dotted_ip?(addr)
|
||||
return addr
|
||||
if addr =~ MATCH_IPV4 or (accept_ipv6 and addr =~ MATCH_IPV6)
|
||||
return [addr]
|
||||
end
|
||||
|
||||
res = ::Socket.gethostbyname(addr)
|
||||
return nil if not res
|
||||
return [] if not res
|
||||
|
||||
# Shift the first three elements out
|
||||
rname = res.shift
|
||||
@@ -223,12 +223,12 @@ module Socket
|
||||
end
|
||||
|
||||
# Make sure we have at least one name
|
||||
return nil if res.length == 0
|
||||
return [] if res.length == 0
|
||||
|
||||
# Return an array of all addresses
|
||||
res.map{ |addr| self.addr_ntoa(addr) }
|
||||
rescue ::ArgumentError # Win32 bug
|
||||
nil
|
||||
[]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -357,10 +357,10 @@ module Socket
|
||||
|
||||
# IPv4
|
||||
if (addr < 0x100000000 and not v6)
|
||||
nboa.unpack('C4').join('.')
|
||||
addr_ntoa(nboa)
|
||||
# IPv6
|
||||
else
|
||||
nboa.unpack('n8').map{ |c| "%.4x" % c }.join(":")
|
||||
addr_ntoa(nboa)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -383,11 +383,32 @@ module Socket
|
||||
|
||||
# IPv6
|
||||
if (addr.length == 16)
|
||||
return addr.unpack('n8').map{ |c| "%.4x" % c }.join(":")
|
||||
return compress_address(addr.unpack('n8').map{ |c| "%x" % c }.join(":"))
|
||||
end
|
||||
|
||||
raise RuntimeError, "Invalid address format"
|
||||
end
|
||||
|
||||
#
|
||||
# Implement zero compression for IPv6 addresses.
|
||||
# Uses the compression method from Marco Ceresa's IPAddress GEM
|
||||
# https://github.com/bluemonk/ipaddress/blob/master/lib/ipaddress/ipv6.rb
|
||||
#
|
||||
def self.compress_address(addr)
|
||||
return addr unless is_ipv6?(addr)
|
||||
addr = addr.dup
|
||||
while true
|
||||
break if addr.sub!(/\A0:0:0:0:0:0:0:0\Z/, '::')
|
||||
break if addr.sub!(/\b0:0:0:0:0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0:0:0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0:0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0:0\b/, ':')
|
||||
break if addr.sub!(/\b0:0\b/, ':')
|
||||
break
|
||||
end
|
||||
addr.sub(/:{3,}/, '::')
|
||||
end
|
||||
|
||||
#
|
||||
# Converts a network byte order address to an integer
|
||||
@@ -655,6 +676,7 @@ module Socket
|
||||
|
||||
return [lsock, rsock]
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
#
|
||||
|
||||
@@ -73,16 +73,19 @@ class RangeWalker
|
||||
else
|
||||
return false
|
||||
end
|
||||
|
||||
elsif arg.include?(":")
|
||||
# Then it's IPv6
|
||||
# Can't really do much with IPv6 right now, just return it and
|
||||
# hope for the best
|
||||
# IPv6 ranges are not yet supported (or useful)
|
||||
return false unless Rex::Socket.is_ipv6?(arg)
|
||||
|
||||
addr = Rex::Socket.addr_atoi(arg)
|
||||
ranges.push [addr, addr, true]
|
||||
|
||||
elsif arg =~ /[^-0-9,.*]/
|
||||
# Then it's a domain name and we should send it on to addr_atoi
|
||||
# unmolested to force a DNS lookup.
|
||||
Rex::Socket.addr_atoi_list(arg).each { |addr| ranges.push [addr, addr] }
|
||||
|
||||
elsif arg =~ /^([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})-([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3})$/
|
||||
# Then it's in the format of 1.2.3.4-5.6.7.8
|
||||
# Note, this will /not/ deal with DNS names, or the fancy/obscure 10...1-10...2
|
||||
|
||||
@@ -48,6 +48,13 @@ class Metasploit3 < Msf::Auxiliary
|
||||
OptBool.new('EXTRALINE', [ true, "Add extra CRLF's in response to LIST",true])
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
# Not compatible today
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
def setup
|
||||
|
||||
@@ -40,7 +40,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
], self.class)
|
||||
end
|
||||
|
||||
|
||||
# Not compatible today
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def resolve(ip)
|
||||
results = ''
|
||||
apikey = datastore['apikey']
|
||||
|
||||
@@ -40,6 +40,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
deregister_options('FILTER','PCAPFILE')
|
||||
end
|
||||
|
||||
# No IPv6 support yet
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run_batch_size
|
||||
datastore['BATCHSIZE'] || 256
|
||||
end
|
||||
|
||||
@@ -41,6 +41,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
deregister_options('RHOST', 'RPORT')
|
||||
end
|
||||
|
||||
# No IPv6 support yet
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run_host(ip)
|
||||
ports = Rex::Socket.portspec_crack(datastore['PORTS'])
|
||||
|
||||
|
||||
@@ -37,6 +37,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
|
||||
deregister_options('FILTER','PCAPFILE')
|
||||
end
|
||||
|
||||
# No IPv6 support yet
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run_batch_size
|
||||
datastore['BATCHSIZE'] || 256
|
||||
|
||||
@@ -40,6 +40,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
deregister_options('FILTER','PCAPFILE')
|
||||
end
|
||||
|
||||
# No IPv6 support yet
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run_batch_size
|
||||
datastore['BATCHSIZE'] || 256
|
||||
end
|
||||
|
||||
@@ -61,6 +61,11 @@ class Metasploit3 < Msf::Auxiliary
|
||||
], self.class)
|
||||
end
|
||||
|
||||
# Not compatible today
|
||||
def support_ipv6?
|
||||
false
|
||||
end
|
||||
|
||||
def run
|
||||
@formsdir = datastore['FORMSDIR']
|
||||
@template = datastore['TEMPLATE']
|
||||
|
||||
@@ -37,7 +37,7 @@ opts = {
|
||||
'User' => 'msf',
|
||||
'SSL' => true,
|
||||
'ServerPort' => 55553,
|
||||
'Type' => 'Xml'
|
||||
'Type' => 'Msg'
|
||||
}
|
||||
|
||||
# Parse command line arguments.
|
||||
@@ -53,8 +53,6 @@ arguments.parse(ARGV) { |opt, idx, val|
|
||||
opts['User'] = val
|
||||
when '-P'
|
||||
opts['Pass'] = val
|
||||
when '-t'
|
||||
opts['Type'] = (val =~ /xml/i) ? 'XML' : 'Msg'
|
||||
when "-h"
|
||||
print("\nUsage: #{File.basename(__FILE__)} <options>\n" + arguments.usage)
|
||||
exit
|
||||
@@ -76,11 +74,7 @@ end
|
||||
|
||||
$0 = "msfrpc"
|
||||
|
||||
if opts['Type'] == 'Msg'
|
||||
require 'msf/core/rpc/v10/client'
|
||||
else
|
||||
require 'msf/core/rpc/client'
|
||||
end
|
||||
require 'msf/core/rpc/v10/client'
|
||||
require 'rex/ui'
|
||||
|
||||
rpc = Msf::RPC::Client.new(
|
||||
|
||||
@@ -28,7 +28,6 @@ arguments = Rex::Parser::Arguments.new(
|
||||
"-p" => [ true, "Bind to this port instead of 55553" ],
|
||||
"-U" => [ true, "Specify the username to access msfrpcd" ],
|
||||
"-P" => [ true, "Specify the password to access msfrpcd" ],
|
||||
"-t" => [ true, "Server type, [Basic|Web|Msg]" ],
|
||||
"-u" => [ true, "URI for Web server" ],
|
||||
"-S" => [ false, "Disable SSL on the RPC socket" ],
|
||||
"-f" => [ false, "Run the daemon in the foreground" ],
|
||||
@@ -40,7 +39,7 @@ opts = {
|
||||
'SSL' => true,
|
||||
'ServerHost' => '0.0.0.0',
|
||||
'ServerPort' => 55553,
|
||||
'ServerType' => 'Basic'
|
||||
'ServerType' => 'Msg'
|
||||
}
|
||||
|
||||
foreground = false
|
||||
@@ -62,8 +61,6 @@ arguments.parse(ARGV) { |opt, idx, val|
|
||||
opts['Pass'] = val
|
||||
when "-f"
|
||||
foreground = true
|
||||
when "-t"
|
||||
opts['ServerType'] = val
|
||||
when "-u"
|
||||
opts['URI'] = val
|
||||
when "-n"
|
||||
@@ -81,8 +78,7 @@ end
|
||||
|
||||
$0 = "msfrpcd"
|
||||
|
||||
rpctype = 'XML'
|
||||
rpctype = 'MSG' if opts['ServerType'].downcase == 'msg'
|
||||
rpctype = 'MSG'
|
||||
|
||||
$stderr.puts "[*] #{rpctype}RPC starting on #{opts['ServerHost']}:#{opts['ServerPort']} (#{opts['SSL'] ? "SSL" : "NO SSL"}):#{opts['ServerType']}..."
|
||||
|
||||
|
||||
@@ -1,188 +0,0 @@
|
||||
#!/usr/bin/env ruby
|
||||
#
|
||||
# $Id$
|
||||
#
|
||||
# This plugin provides an msf daemon interface that spawns a listener on a
|
||||
# defined port (default 55553) and gives each connecting client its own
|
||||
# console interface. These consoles all share the same framework instance.
|
||||
# Be aware that the console instance that spawns on the port is entirely
|
||||
# unauthenticated, so realize that you have been warned.
|
||||
#
|
||||
# $Revision$
|
||||
#
|
||||
|
||||
require "msf/core/rpc"
|
||||
require "fileutils"
|
||||
|
||||
module Msf
|
||||
|
||||
###
|
||||
#
|
||||
# This class implements the msfd plugin interface.
|
||||
#
|
||||
###
|
||||
class Plugin::XMLRPC < Msf::Plugin
|
||||
|
||||
#
|
||||
# The default local hostname that the server listens on.
|
||||
#
|
||||
DefaultHost = "127.0.0.1"
|
||||
|
||||
#
|
||||
# The default local port that the server listens on.
|
||||
#
|
||||
DefaultPort = 55553
|
||||
|
||||
#
|
||||
# ServerPort
|
||||
#
|
||||
# The local port to listen on for connections. The default is 55553
|
||||
#
|
||||
def initialize(framework, opts)
|
||||
super
|
||||
|
||||
host = opts['ServerHost'] || DefaultHost
|
||||
port = opts['ServerPort'] || DefaultPort
|
||||
ssl = (opts['SSL'] and opts['SSL'].to_s =~ /^[ty]/i) ? true : false
|
||||
cert = opts['SSLCert']
|
||||
ckey = opts['SSLKey']
|
||||
|
||||
user = opts['User'] || "msf"
|
||||
pass = opts['Pass'] || ::Rex::Text.rand_text_alphanumeric(8)
|
||||
type = opts['ServerType'] || "Basic"
|
||||
uri = opts['URI'] || "/RPC2"
|
||||
|
||||
print_status("XMLRPC Service: #{host}:#{port} #{ssl ? " (SSL)" : ""}")
|
||||
print_status("XMLRPC Username: #{user}")
|
||||
print_status("XMLRPC Password: #{pass}")
|
||||
print_status("XMLRPC Server Type: #{type}")
|
||||
|
||||
@users = [ [user,pass] ]
|
||||
if(type =~ /Web/i)
|
||||
print_status("XMLRPC Web URI: #{uri}")
|
||||
self.server = ::Msf::RPC::WebService.new(port,host,uri)
|
||||
elsif(type =~ /Basic/i)
|
||||
self.server = ::Msf::RPC::Service.new(host,port,ssl,cert,ckey)
|
||||
else
|
||||
print_status("Invalid server type #{type}, please choose Web or Basic")
|
||||
end
|
||||
|
||||
# If the run in foreground flag is not specified, then go ahead and fire
|
||||
# it off in a worker thread.
|
||||
if (opts['RunInForeground'] != true)
|
||||
# Store a handle to the thread so we can kill it during
|
||||
# cleanup when we get unloaded.
|
||||
self.thread = Thread.new {
|
||||
run
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
#
|
||||
# Returns 'xmlrpc'
|
||||
#
|
||||
def name
|
||||
"xmlrpc"
|
||||
end
|
||||
|
||||
#
|
||||
# Returns the plugin description.
|
||||
#
|
||||
def desc
|
||||
"Provides a XMLRPC interface over a listening TCP port."
|
||||
end
|
||||
|
||||
#
|
||||
# The meat of the plugin, sets up handlers for requests
|
||||
#
|
||||
def run
|
||||
|
||||
# Initialize the list of authenticated sessions
|
||||
@tokens = {}
|
||||
|
||||
args = [framework,@tokens,@users]
|
||||
|
||||
# Add handlers for every class
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("auth"),
|
||||
::Msf::RPC::Auth.new(*args)
|
||||
)
|
||||
|
||||
# Note the extra argument for core as compared to the other
|
||||
# handlers. This allows rpc clients access to the plugin so
|
||||
# they can shutdown the server.
|
||||
core_args = args + [self]
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("core"),
|
||||
::Msf::RPC::Core.new(*core_args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("session"),
|
||||
::Msf::RPC::Session.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("job"),
|
||||
::Msf::RPC::Job.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("module"),
|
||||
::Msf::RPC::Module.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("console"),
|
||||
::Msf::RPC::Console.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("db"),
|
||||
::Msf::RPC::Db.new(*args)
|
||||
)
|
||||
|
||||
self.server.add_handler(::XMLRPC::iPIMethods("plugin"),
|
||||
::Msf::RPC::Plugin.new(*args)
|
||||
)
|
||||
|
||||
# Set the default/catch-all handler
|
||||
self.server.set_default_handler do |name, *args|
|
||||
raise ::XMLRPC::FaultException.new(-99, "Method #{name} missing or wrong number of parameters!")
|
||||
end
|
||||
|
||||
# Start the actual service
|
||||
self.server.start
|
||||
|
||||
# Wait for the service to complete
|
||||
self.server.wait
|
||||
end
|
||||
|
||||
#
|
||||
# Closes the listener service.
|
||||
#
|
||||
def cleanup
|
||||
self.server.stop if self.server
|
||||
self.thread.kill if self.thread
|
||||
self.server = nil
|
||||
super
|
||||
end
|
||||
|
||||
def stop_rpc
|
||||
print_line
|
||||
print_status("XMLRPC Client requested server stop")
|
||||
# Plugins aren't really meant to be able to unload themselves, so this
|
||||
# is a bit of a corner case. Unloading ourselves ends up killing the
|
||||
# thread that's doing the unloading so we need to fire off the unload
|
||||
# in a seperate one.
|
||||
Thread.new {
|
||||
framework.plugins.unload(self)
|
||||
}
|
||||
nil
|
||||
end
|
||||
|
||||
#
|
||||
# The XMLRPC instance.
|
||||
#
|
||||
attr_accessor :server
|
||||
attr_accessor :thread
|
||||
attr_accessor :users
|
||||
attr_accessor :tokens
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user