module BeEF
module Extension
module Dns
class DnsRest < BeEF::Core::Router::Router
before do
@dns ||= BeEF::Extension::Dns::Server.instance
config = BeEF::Core::Configuration.instance
halt 401 unless params[:token] == config.get('beef.api_token')
halt 403 unless BeEF::Core::Rest.permitted_source?(request.ip)
headers 'Content-Type' => 'application/json; charset=UTF-8',
'Pragma' => 'no-cache',
'Cache-Control' => 'no-cache',
'Expires' => '0'
end
get '/ruleset' do
ruleset = @dns.get_ruleset
count = ruleset.length
result = {}
result[:count] = count
result[:ruleset] = ruleset
result.to_json
rescue StandardError => e
print_error "Internal error while retrieving DNS ruleset (#{e.message})"
halt 500
end
get '/rule/:id' do
id = params[:id]
rule = @dns.get_rule(id)
raise InvalidParamError, 'id' if rule.nil?
halt 404 if rule.empty?
rule.to_json
rescue InvalidParamError => e
print_error e.message
halt 400
rescue StandardError => e
print_error "Internal error while retrieving DNS rule with id #{id} (#{e.message})"
halt 500
end
post '/rule' do
body = JSON.parse(request.body.read)
pattern = body['pattern']
resource = body['resource']
response = body['response']
raise InvalidJsonError, 'Empty "pattern" key passed to endpoint /api/dns/rule' if pattern.nil? || pattern.eql?('')
raise InvalidJsonError, 'Invalid "resource" key passed to endpoint /api/dns/rule' if resource !~ /\A[A-Z]+\Z/
raise InvalidJsonError, 'Non-array "response" key passed to endpoint /api/dns/rule' unless response.is_a?(Array)
raise InvalidJsonError, 'Empty "response" array passed to endpoint /api/dns/rule' if response.empty?
case resource
when 'A'
dns_resource = Resolv::DNS::Resource::IN::A
when 'AAAA'
dns_resource = Resolv::DNS::Resource::IN::AAAA
when 'CNAME'
dns_resource = Resolv::DNS::Resource::IN::CNAME
when 'HINFO'
dns_resource = Resolv::DNS::Resource::IN::HINFO
when 'MINFO'
dns_resource = Resolv::DNS::Resource::IN::MINFO
when 'MX'
dns_resource = Resolv::DNS::Resource::IN::MX
when 'NS'
dns_resource = Resolv::DNS::Resource::IN::NS
when 'PTR'
dns_resource = Resolv::DNS::Resource::IN::PTR
when 'SOA'
dns_resource = Resolv::DNS::Resource::IN::SOA
when 'TXT'
dns_resource = Resolv::DNS::Resource::IN::TXT
when 'WKS'
dns_resource = Resolv::DNS::Resource::IN::WKS
else
raise InvalidJsonError, 'Invalid "resource" key passed to endpoint /api/dns/rule'
end
id = @dns.add_rule(
pattern: pattern,
resource: dns_resource,
response: response
)
result = {}
result['success'] = true
result['id'] = id
result.to_json
rescue InvalidJsonError => e
print_error e.message
halt 400
rescue StandardError => e
print_error "Internal error while adding DNS rule (#{e.message})"
halt 500
end
delete '/rule/:id' do
id = params[:id]
removed = @dns.remove_rule!(id)
raise InvalidParamError, 'id' if removed.nil?
result = {}
result['success'] = removed
result.to_json
rescue InvalidParamError => e
print_error e.message
halt 400
rescue StandardError => e
print_error "Internal error while removing DNS rule with id #{id} (#{e.message})"
halt 500
end
class InvalidJsonError < StandardError
DEFAULT_MESSAGE = 'Invalid JSON input passed to /api/dns handler'
def initialize(message = nil)
super(message || DEFAULT_MESSAGE)
end
end
class InvalidParamError < StandardError
DEFAULT_MESSAGE = 'Invalid parameter passed to /api/dns handler'
def initialize(message = nil)
str = 'Invalid "%s" parameter passed to /api/dns handler'
message = format str, message unless message.nil?
super(message)
end
end
end
end
end
end