passivedns-client 2.0.6 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +6 -0
- data/Rakefile +8 -0
- data/lib/passivedns/client.rb +14 -7
- data/lib/passivedns/client/cli.rb +34 -6
- data/lib/passivedns/client/passivedb.rb +6 -1
- data/lib/passivedns/client/provider/bfk.rb +102 -0
- data/lib/passivedns/client/provider/circl.rb +111 -0
- data/lib/passivedns/client/provider/cn360.rb +108 -0
- data/lib/passivedns/client/provider/dnsdb.rb +110 -0
- data/lib/passivedns/client/provider/mnemonic.rb +98 -0
- data/lib/passivedns/client/provider/passivetotal.rb +103 -0
- data/lib/passivedns/client/provider/riskiq.rb +130 -0
- data/lib/passivedns/client/provider/tcpiputils.rb +118 -0
- data/lib/passivedns/client/provider/virustotal.rb +105 -0
- data/lib/passivedns/client/state.rb +30 -2
- data/lib/passivedns/client/version.rb +4 -2
- data/test/test_cli.rb +6 -5
- data/test/test_passivedns-client.rb +33 -8
- metadata +11 -10
- data/lib/passivedns/client/providers/bfk.rb +0 -77
- data/lib/passivedns/client/providers/circl.rb +0 -79
- data/lib/passivedns/client/providers/cn360.rb +0 -80
- data/lib/passivedns/client/providers/dnsdb.rb +0 -85
- data/lib/passivedns/client/providers/mnemonic.rb +0 -72
- data/lib/passivedns/client/providers/passivetotal.rb +0 -77
- data/lib/passivedns/client/providers/tcpiputils.rb +0 -92
- data/lib/passivedns/client/providers/virustotal.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9bc0b0ff155e1b9570c05b45f22368b0cfa79a83
|
4
|
+
data.tar.gz: 4b2d805d77a29ef052c0003a116c21224166254f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 21dd2aefcc5074d626047c4cf4e798c33b9dc063199667b29a68614463b464e01f91fe72b285ecf2a3a752f8ef1f9a4082c1da797f6ed405950becefa32e5c55
|
7
|
+
data.tar.gz: 39c7c7ae6f931634c58c588a9ce7113bdcd776becc587036e6a51261ba7d67008619b9cdf9da478674ba34cc46d255a965a9dc6dbaec83c9092e59daa95a2b49
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -8,6 +8,7 @@ This rubygem queries the following Passive DNS databases:
|
|
8
8
|
* Mnemonic
|
9
9
|
* PassiveDNS.cn (Qihoo 360 Technology Co.,Ltd)
|
10
10
|
* PassiveTotal
|
11
|
+
* RiskIQ
|
11
12
|
* TCPIPUtils
|
12
13
|
* VirusTotal
|
13
14
|
|
@@ -54,6 +55,9 @@ From version 2.0.0 on, all configuration keys for passive DNS providers are in o
|
|
54
55
|
[circl]
|
55
56
|
USERNAME = circl_user
|
56
57
|
PASSWORD = circl_pass
|
58
|
+
[riskiq]
|
59
|
+
API_TOKEN = 0123456789abcdef
|
60
|
+
API_PRIVATE_KEY = 01234567890abcdefghijklmnopqrstu
|
57
61
|
|
58
62
|
CIRCL also can use and authorization token. In that case, you should drop the USERNAME and PASSWORD options and change the section to something like the following:
|
59
63
|
|
@@ -67,6 +71,7 @@ CIRCL also can use and authorization token. In that case, you should drop the U
|
|
67
71
|
* DNSDB (Farsight Security) : https://api.dnsdb.info/
|
68
72
|
* Mnemonic : mss .at. mnemonic.no
|
69
73
|
* PassiveTotal : https://www.passivetotal.org
|
74
|
+
* RiskIQ : https://github.com/RiskIQ/python_api/blob/master/LICENSE
|
70
75
|
* TCPIPUtils : http://www.tcpiputils.com/premium-access
|
71
76
|
* VirusTotal : https://www.virustotal.com
|
72
77
|
|
@@ -88,6 +93,7 @@ Or use the included tool...
|
|
88
93
|
-dd use DNSDB
|
89
94
|
-dm use Mnemonic
|
90
95
|
-dp use PassiveTotal
|
96
|
+
-dr use RiskIQ
|
91
97
|
-dt use TCPIPUtils
|
92
98
|
-dv use VirusTotal
|
93
99
|
-dvt uses VirusTotal and TCPIPUtils (for example)
|
data/Rakefile
CHANGED
@@ -2,6 +2,7 @@
|
|
2
2
|
require "bundler/gem_tasks"
|
3
3
|
|
4
4
|
require 'rake/testtask'
|
5
|
+
require 'rdoc/task'
|
5
6
|
|
6
7
|
Rake::TestTask.new do |t|
|
7
8
|
t.libs << 'lib'
|
@@ -9,4 +10,11 @@ Rake::TestTask.new do |t|
|
|
9
10
|
t.verbose = true
|
10
11
|
end
|
11
12
|
|
13
|
+
RDoc::Task.new do |rd|
|
14
|
+
rd.main = "README.doc"
|
15
|
+
rd.rdoc_files.include("README.md", "lib/**/*.rb")
|
16
|
+
rd.options << "--all"
|
17
|
+
rd.options << "--verbose"
|
18
|
+
end
|
19
|
+
|
12
20
|
task :default => :test
|
data/lib/passivedns/client.rb
CHANGED
@@ -8,27 +8,32 @@ require 'passivedns/client/passivedb'
|
|
8
8
|
|
9
9
|
# load all the providers
|
10
10
|
$passivedns_providers = Array.new
|
11
|
-
provider_path = File.dirname(__FILE__)+"/client/
|
11
|
+
provider_path = File.dirname(__FILE__)+"/client/provider/*.rb"
|
12
12
|
Dir.glob(provider_path).each do |provider|
|
13
13
|
name = File.basename(provider, '.rb')
|
14
|
-
require "passivedns/client/
|
14
|
+
require "passivedns/client/provider/#{name}.rb"
|
15
15
|
$passivedns_providers << name
|
16
16
|
end
|
17
17
|
|
18
18
|
require 'configparser'
|
19
19
|
|
20
|
-
module PassiveDNS
|
21
|
-
|
20
|
+
module PassiveDNS # :nodoc:
|
21
|
+
# struct to contain the results from a PassiveDNS lookup
|
22
22
|
class PDNSResult < Struct.new(:source, :response_time, :query, :answer, :rrtype, :ttl, :firstseen, :lastseen, :count); end
|
23
23
|
|
24
|
+
# coodinates the lookups accross all configured PassiveDNS providers
|
24
25
|
class Client
|
26
|
+
|
27
|
+
# instantiate and configure all specified PassiveDNS providers
|
28
|
+
# pdns array of passivedns provider names, e.g., ["dnsdb","virustotal"]
|
29
|
+
# configfile filename of the passivedns-client configuration (this should probably be abstracted)
|
25
30
|
def initialize(pdns=$passivedns_providers, configfile="#{ENV['HOME']}/.passivedns-client")
|
26
31
|
cp = ConfigParser.new(configfile)
|
27
32
|
# this creates a map of all the PassiveDNS provider names and their classes
|
28
33
|
class_map = {}
|
29
|
-
PassiveDNS.constants.each do |const|
|
30
|
-
if PassiveDNS.const_get(const).is_a?(Class) and PassiveDNS.const_get(const).superclass == PassiveDNS::PassiveDB
|
31
|
-
class_map[PassiveDNS.const_get(const).config_section_name] = PassiveDNS.const_get(const)
|
34
|
+
PassiveDNS::Provider.constants.each do |const|
|
35
|
+
if PassiveDNS::Provider.const_get(const).is_a?(Class) and PassiveDNS::Provider.const_get(const).superclass == PassiveDNS::PassiveDB
|
36
|
+
class_map[PassiveDNS::Provider.const_get(const).config_section_name] = PassiveDNS::Provider.const_get(const)
|
32
37
|
end
|
33
38
|
end
|
34
39
|
|
@@ -43,12 +48,14 @@ module PassiveDNS
|
|
43
48
|
|
44
49
|
end #initialize
|
45
50
|
|
51
|
+
# set the debug flag
|
46
52
|
def debug=(d)
|
47
53
|
@pdnsdbs.each do |pdnsdb|
|
48
54
|
pdnsdb.debug = d
|
49
55
|
end
|
50
56
|
end
|
51
57
|
|
58
|
+
# perform the query lookup accross all configured PassiveDNS providers
|
52
59
|
def query(item, limit=nil)
|
53
60
|
threads = []
|
54
61
|
@pdnsdbs.each do |pdnsdb|
|
@@ -4,18 +4,39 @@ require 'getoptlong'
|
|
4
4
|
require 'yaml'
|
5
5
|
require 'pp'
|
6
6
|
|
7
|
-
module PassiveDNS
|
7
|
+
module PassiveDNS # :nodoc:
|
8
|
+
# Handles all the command-line parsing, state tracking, and dispatching queries to the PassiveDNS::Client instance
|
9
|
+
# CLInterface is aliased by CLI
|
8
10
|
class CLInterface
|
11
|
+
# generates a mapping between the option letter for each PassiveDNS provider and the class
|
9
12
|
def self.get_letter_map
|
10
13
|
letter_map = {}
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
+
mod = PassiveDNS::Provider
|
15
|
+
mod.constants.each do |const|
|
16
|
+
if mod.const_get(const).is_a?(Class) and mod.const_get(const).superclass == PassiveDNS::PassiveDB
|
17
|
+
letter = mod.const_get(const).option_letter
|
18
|
+
name = mod.const_get(const).name
|
19
|
+
config_section_name = mod.const_get(const).config_section_name
|
20
|
+
letter_map[letter] = [name, config_section_name]
|
14
21
|
end
|
15
22
|
end
|
16
23
|
letter_map
|
17
24
|
end
|
18
25
|
|
26
|
+
# parses the command line and yields an options hash
|
27
|
+
# === Default Options
|
28
|
+
# options = {
|
29
|
+
# :pdnsdbs => [], # passive dns providers to query
|
30
|
+
# :format => "text", # output format
|
31
|
+
# :sep => "\t", # field separator for text format
|
32
|
+
# :recursedepth => 1, # recursion depth
|
33
|
+
# :wait => 0, # wait period between recursions
|
34
|
+
# :res => nil, # unused. I don't remember why this is here.
|
35
|
+
# :debug => false, # debug flag
|
36
|
+
# :sqlitedb => nil, # filename for maintaining state in an sqlite3 db
|
37
|
+
# :limit => nil, # number of results per provider per recursion
|
38
|
+
# :help => false # display the usage text
|
39
|
+
# }
|
19
40
|
def self.parse_command_line(args)
|
20
41
|
origARGV = ARGV.dup
|
21
42
|
ARGV.replace(args)
|
@@ -132,6 +153,8 @@ module PassiveDNS
|
|
132
153
|
[options, args]
|
133
154
|
end
|
134
155
|
|
156
|
+
# returns a string containing the usage information
|
157
|
+
# takes in a hash of letter to passive dns providers
|
135
158
|
def self.usage(letter_map)
|
136
159
|
databases = letter_map.keys.sort.join("")
|
137
160
|
help_text = ""
|
@@ -167,6 +190,7 @@ module PassiveDNS
|
|
167
190
|
help_text
|
168
191
|
end
|
169
192
|
|
193
|
+
# performs a stateful, recursive (if desired) passive DNS lookup against all specified providers
|
170
194
|
def self.pdnslookup(state, pdnsclient, options)
|
171
195
|
recursedepth = options[:recursedepth]
|
172
196
|
wait = options[:wait]
|
@@ -195,6 +219,7 @@ module PassiveDNS
|
|
195
219
|
state
|
196
220
|
end
|
197
221
|
|
222
|
+
# returns a string transforming all the PassiveDNS::PDNSResult stored in the state object into text/xml/json/etc.
|
198
223
|
def self.results_to_s(state,options)
|
199
224
|
format = options[:format]
|
200
225
|
sep = options[:sep]
|
@@ -216,6 +241,7 @@ module PassiveDNS
|
|
216
241
|
end
|
217
242
|
end
|
218
243
|
|
244
|
+
# create a state instance
|
219
245
|
def self.create_state(sqlitedb=nil)
|
220
246
|
state = nil
|
221
247
|
if sqlitedb
|
@@ -225,6 +251,7 @@ module PassiveDNS
|
|
225
251
|
end
|
226
252
|
end
|
227
253
|
|
254
|
+
# main method, takes command-line arguments and performs the desired queries and outputs
|
228
255
|
def self.run(args)
|
229
256
|
options, items = parse_command_line(args)
|
230
257
|
if options[:help]
|
@@ -240,8 +267,8 @@ module PassiveDNS
|
|
240
267
|
pdnsclient = PassiveDNS::Client.new(options[:pdnsdbs])
|
241
268
|
pdnsclient.debug = options[:debug]
|
242
269
|
|
243
|
-
if
|
244
|
-
|
270
|
+
if items.length > 0
|
271
|
+
items.each do |arg|
|
245
272
|
state.add_query(arg,'pending',0)
|
246
273
|
end
|
247
274
|
else
|
@@ -253,6 +280,7 @@ module PassiveDNS
|
|
253
280
|
results_to_s(state,options)
|
254
281
|
end
|
255
282
|
end
|
283
|
+
# Alias for the CLInterface class
|
256
284
|
CLI = PassiveDNS::CLInterface
|
257
285
|
end
|
258
286
|
|
@@ -1,17 +1,22 @@
|
|
1
|
-
module PassiveDNS
|
1
|
+
module PassiveDNS #:nodoc: don't document this
|
2
|
+
# abstract class that all PassiveDNS::Provider should subclass
|
2
3
|
class PassiveDB
|
4
|
+
# raises an exception that this should be implemented by the subclass
|
3
5
|
def self.name
|
4
6
|
raise "You should implement your own version of .name"
|
5
7
|
end
|
6
8
|
|
9
|
+
# raises an exception that this should be implemented by the subclass
|
7
10
|
def self.config_section_name
|
8
11
|
name
|
9
12
|
end
|
10
13
|
|
14
|
+
# raises an exception that this should be implemented by the subclass
|
11
15
|
def self.option_letter
|
12
16
|
raise "You should pick a unique letter to serve as your database option letter for the command line option -d"
|
13
17
|
end
|
14
18
|
|
19
|
+
# raises an exception that this should be implemented by the subclass
|
15
20
|
def lookup(label, limit=nil)
|
16
21
|
raise "You must implement the lookup function"
|
17
22
|
end
|
@@ -0,0 +1,102 @@
|
|
1
|
+
require 'open-uri'
|
2
|
+
|
3
|
+
module PassiveDNS #:nodoc: don't document this
|
4
|
+
# The Provider module contains all the Passive DNS provider client code
|
5
|
+
module Provider
|
6
|
+
|
7
|
+
# Queries BFK.de's passive DNS database
|
8
|
+
class BFK < PassiveDB
|
9
|
+
# Sets the modules self-reported name to "BFK.de"
|
10
|
+
def self.name
|
11
|
+
"BFK.de"
|
12
|
+
end
|
13
|
+
# Sets the configuration section name to "bfk"
|
14
|
+
def self.config_section_name
|
15
|
+
"bfk"
|
16
|
+
end
|
17
|
+
# Sets the command line database argument to "b"
|
18
|
+
def self.option_letter
|
19
|
+
"b"
|
20
|
+
end
|
21
|
+
|
22
|
+
# :debug enables verbose logging to standard output
|
23
|
+
attr_accessor :debug
|
24
|
+
# === Options
|
25
|
+
# * :debug Sets the debug flag for the module
|
26
|
+
# * "URL" Alternate url for testing. Defaults to "http://www.bfk.de/bfk_dnslogger.html?query="
|
27
|
+
#
|
28
|
+
# === Example Instantiation
|
29
|
+
#
|
30
|
+
# options = {
|
31
|
+
# :debug => true,
|
32
|
+
# "URL" => "http://www.bfk.de/bfk_dnslogger.html?query="
|
33
|
+
# }
|
34
|
+
#
|
35
|
+
# PassiveDNS::Provider::BFK.new(options)
|
36
|
+
#
|
37
|
+
|
38
|
+
def initialize(options={})
|
39
|
+
@debug = options[:debug] || false
|
40
|
+
@base = options["URL"] || "http://www.bfk.de/bfk_dnslogger.html?query="
|
41
|
+
end
|
42
|
+
|
43
|
+
# Takes a label (either a domain or an IP address) and returns
|
44
|
+
# an array of PassiveDNS::PDNSResult instances with the answers to the query
|
45
|
+
def lookup(label, limit=nil)
|
46
|
+
$stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
|
47
|
+
Timeout::timeout(240) {
|
48
|
+
t1 = Time.now
|
49
|
+
open(
|
50
|
+
@base+label,
|
51
|
+
"User-Agent" => "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}"
|
52
|
+
) do |f|
|
53
|
+
t2 = Time.now
|
54
|
+
recs = parse(f.read,t2-t1)
|
55
|
+
if limit
|
56
|
+
recs[0,limit]
|
57
|
+
else
|
58
|
+
recs
|
59
|
+
end
|
60
|
+
end
|
61
|
+
}
|
62
|
+
rescue Timeout::Error => e
|
63
|
+
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# parses the webpage returned by BFK to generate an array of PDNSResult
|
69
|
+
def parse(page,response_time)
|
70
|
+
line = page.unpack('C*').pack('U*').split(/<table/).grep(/ id=\"logger\"/)
|
71
|
+
return [] unless line.length > 0
|
72
|
+
line = line[0].gsub(/[\t\n]/,'').gsub(/<\/table.*/,'')
|
73
|
+
rows = line.split(/<tr.*?>/)
|
74
|
+
res = []
|
75
|
+
rows.collect do |row|
|
76
|
+
r = row.split(/<td>/).map{|x| x.gsub(/<.*?>/,'').gsub(/\&.*?;/,'')}[1,1000]
|
77
|
+
if r and r[0] =~ /\w/
|
78
|
+
# BFK includes the MX weight in the answer response. First, find the MX records, then dump the weight to present a consistent record name to the collecting array. Otherwise the other repositories will present the same answer and your results will become cluttered with duplicates.
|
79
|
+
if r[1] == "MX" then
|
80
|
+
# MX lines look like "5 mx.domain.tld", so split on the space and assign r[2] (:answer) to the latter part.
|
81
|
+
#s = r[2].split(/\w/).map{|x| x}[1,1000]
|
82
|
+
# r[2] = s[1]
|
83
|
+
r[2] =~ /[0-9]+?\s(.+)/
|
84
|
+
s=$1
|
85
|
+
puts "DEBUG: == BFK: MX Parsing Strip: Answer: " + r[2] + " : mod: " + s if @debug
|
86
|
+
r[2] = s
|
87
|
+
|
88
|
+
######### FIX BLANKS FOR MX
|
89
|
+
|
90
|
+
end
|
91
|
+
res << PDNSResult.new(self.class.name,response_time,r[0],r[2],r[1])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
res
|
95
|
+
rescue Exception => e
|
96
|
+
$stderr.puts "#{self.class.name} Exception: #{e}"
|
97
|
+
raise e
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
# DESCRIPTION: Module to query PassiveTotal's passive DNS repository
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
require 'net/https'
|
5
|
+
require 'openssl'
|
6
|
+
|
7
|
+
module PassiveDNS #:nodoc: don't document this
|
8
|
+
# The Provider module contains all the Passive DNS provider client code
|
9
|
+
module Provider
|
10
|
+
# Queries CIRCL.LU's passive DNS database
|
11
|
+
# Circl is aliased by CIRCL
|
12
|
+
class Circl < PassiveDB
|
13
|
+
# Sets the modules self-reported name to "CIRCL"
|
14
|
+
def self.name
|
15
|
+
"CIRCL"
|
16
|
+
end
|
17
|
+
# Sets the configuration section name to "circl"
|
18
|
+
def self.config_section_name
|
19
|
+
"circl"
|
20
|
+
end
|
21
|
+
# Sets the command line database argument to "c"
|
22
|
+
def self.option_letter
|
23
|
+
"c"
|
24
|
+
end
|
25
|
+
|
26
|
+
# :debug enables verbose logging to standard output
|
27
|
+
attr_accessor :debug
|
28
|
+
# === Options
|
29
|
+
# * :debug Sets the debug flag for the module
|
30
|
+
# * "USERNAME" User name associated with your CIRCL account
|
31
|
+
# * "PASSWORD" Password associated with your CIRCL account
|
32
|
+
# * "AUTH_TOKEN" Authorization token associated with your CIRCL account
|
33
|
+
# * "URL" Alternate url for testing. Defaults to "https://www.circl.lu/pdns/query"
|
34
|
+
|
35
|
+
# You should either have a username+password or an authorization token to use this service
|
36
|
+
#
|
37
|
+
# === Example Instantiation
|
38
|
+
#
|
39
|
+
# options = {
|
40
|
+
# :debug => true,
|
41
|
+
# "USERNAME" => "circl_user",
|
42
|
+
# "PASSWORD" => "circl_pass",
|
43
|
+
# "URL" => "https://www.circl.lu/pdns/query"
|
44
|
+
# }
|
45
|
+
#
|
46
|
+
# PassiveDNS::Provider::CIRCL.new(options)
|
47
|
+
#
|
48
|
+
def initialize(options={})
|
49
|
+
@debug = options[:debug] || false
|
50
|
+
@username = options["USERNAME"]
|
51
|
+
@password = options["PASSWORD"]
|
52
|
+
@auth_token = options["AUTH_TOKEN"]
|
53
|
+
@url = options["URL"] || "https://www.circl.lu/pdns/query"
|
54
|
+
end
|
55
|
+
|
56
|
+
# Takes a label (either a domain or an IP address) and returns
|
57
|
+
# an array of PassiveDNS::PDNSResult instances with the answers to the query
|
58
|
+
def lookup(label, limit=nil)
|
59
|
+
$stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
|
60
|
+
Timeout::timeout(240) {
|
61
|
+
url = @url+"/"+label
|
62
|
+
$stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
|
63
|
+
url = URI.parse url
|
64
|
+
http = Net::HTTP.new(url.host, url.port)
|
65
|
+
http.use_ssl = (url.scheme == 'https')
|
66
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
67
|
+
http.verify_depth = 5
|
68
|
+
request = Net::HTTP::Get.new(url.request_uri)
|
69
|
+
request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
|
70
|
+
if @username
|
71
|
+
request.basic_auth(@username, @password)
|
72
|
+
end
|
73
|
+
if @auth_token
|
74
|
+
request.add_field("Authorization", @auth_token)
|
75
|
+
end
|
76
|
+
t1 = Time.now
|
77
|
+
response = http.request(request)
|
78
|
+
t2 = Time.now
|
79
|
+
recs = parse_json(response.body, label, t2-t1)
|
80
|
+
if limit
|
81
|
+
recs[0,limit]
|
82
|
+
else
|
83
|
+
recs
|
84
|
+
end
|
85
|
+
}
|
86
|
+
rescue Timeout::Error => e
|
87
|
+
$stderr.puts "#{self.class.name} lookup timed out: #{label}"
|
88
|
+
end
|
89
|
+
|
90
|
+
private
|
91
|
+
|
92
|
+
# parses the response of circl's JSON reply to generate an array of PDNSResult
|
93
|
+
def parse_json(page,query,response_time=0)
|
94
|
+
res = []
|
95
|
+
# need to remove the json_class tag or the parser will crap itself trying to find a class to align it to
|
96
|
+
page.split(/\n/).each do |line|
|
97
|
+
row = JSON.parse(line)
|
98
|
+
res << PDNSResult.new(self.class.name,response_time,
|
99
|
+
row['rrname'], row['rdata'], row['rrtype'], 0,
|
100
|
+
row['time_first'], row['time_last'], row['count'])
|
101
|
+
end
|
102
|
+
res
|
103
|
+
rescue Exception => e
|
104
|
+
$stderr.puts "#{self.class.name} Exception: #{e}"
|
105
|
+
raise e
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
109
|
+
CIRCL = PassiveDNS::Provider::Circl
|
110
|
+
end
|
111
|
+
end
|