passivedns-client 1.4.1 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: b6916695e05fb5d4056da3c86b42126f646d8db0
4
- data.tar.gz: 47ebd40317c9562e5cfb20a4daffc8c6b334429d
3
+ metadata.gz: d29ccf361ef159d087a669bcb1c079cdcc9cd9d1
4
+ data.tar.gz: b04ddd8e934977225087be6782540cf00b8a3e13
5
5
  SHA512:
6
- metadata.gz: 857c98dcbae9642461142461f62bf6aaec40047a5aebb59fb05dac1cb59d08a0fc33e6c80d99be4f694b86c0c281d7bc7e8e96f00315655c07e1489cda847d94
7
- data.tar.gz: 34af237f756637bdb6313b7476ae84d2c57b9bec641ee042ae6bcf889144389b89ee91da1206741338b961768b321650a8692e05e035f74737eea86fe708bf9b
6
+ metadata.gz: f45ae94c974ebedcb3a2b3d05da9f1ce69698f34f4b275a31137508ef680381116d35525836345a6b8c1a72a4d0359d0261a939b96d3c73f243f8a007f2b0ef6
7
+ data.tar.gz: aa2f36c8c9ded9632d07af3fbb4362212b6e461c0d63e60802404995ca2175f744134950470dac3802e30a4a61fab6bb7d7d57540c54e8fabe7416be505cd852
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # PassiveDNS::Client
2
2
 
3
- This rubygem queries 5 major Passive DNS databases: BFK, CERTEE, DNSParse, DNSDB, and VirusTotal.
3
+ This rubygem queries 7 major Passive DNS databases: BFK, CERTEE, DNSParse, DNSDB, VirusTotal, PassiveDNS.cn, and Mnemonic.
4
4
  Passive DNS is a technique where IP to hostname mappings are made by recording the answers of other people's queries.
5
5
 
6
6
  There is a tool included, pdnstool, that wraps a lot of the functionality that you would need.
@@ -25,63 +25,48 @@ Or install it yourself as:
25
25
 
26
26
  ## Configuration
27
27
 
28
- ### DNSDB (Farsight Security)
29
-
30
- The DNSDB configuration file is located at $HOME/.dnsdb-query.conf by default. The format for its configuration file only requires one line in the following format:
31
-
32
- APIKEY="0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
33
-
34
- To request an API Key, please read https://api.dnsdb.info/.
35
-
36
- ### CERTEE
37
-
38
- CERT-EE does not require any configuration.
39
- BFK.de
40
-
41
- BFK.de does not require any configuration. However, please read and abide by their usage policy at BFK.de. Currently, it just says not to perform automated queries.
42
-
43
- ### VirusTotal
44
-
45
- VirusTotal's (https://www.virustotal.com) passive DNS database requires an apikey in $HOME/.virustotal. It is a 64 character hexstring on a single line.
46
-
47
- 01234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef
48
-
49
-
50
- ### TCPIPUtils
51
-
52
- TCPIPUtils's (http://www.tcpiputils.com/premium-access) passive DNS database requires and apikey in $HOME/.tcpiputils. It is a 64 character hexstring on a single line.
53
-
54
- 01234567890abcdef01234567890abcdef01234567890abcdef01234567890abcdef
55
-
56
-
57
- ### PassiveDNS.cn from 360.cn
58
-
59
- PassiveDNS.cn (http://www.passivedns.cn) requires an API ID and and API KEY, which is obtainable by creating an account and sending an email to request an API key.
60
-
61
- The configuration file can be in /etc/flint.conf (flint is the name of their tool, which is available at <a href='https://github.com/360netlab/flint'>https://github.com/360netlab/flint</a>) or in $HOME/.flint.conf (which is my preference).
62
-
63
- The file must have three lines and looks like:
28
+ From version 2.0.0 on, all configuration keys for passive DNS providers are in one configuration file. By default the location of the file is $HOME/.passivedns-client . The syntax of this file is as follows:
64
29
 
30
+ [dnsdb]
31
+ APIKEY = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
32
+ [cn360]
65
33
  API = http://some.web.address.for.their.api
66
34
  API_ID = a username that is given when you register
67
35
  API_KEY = a long and random password of sorts that is used along with the page request to generate a per page API key
36
+ [tcpiputils]
37
+ APIKEY = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
38
+ [virustotal]
39
+ APIKEY = 0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef
40
+ [mnemonic]
41
+ APIKEY = 01234567890abcdef01234567890abcdef012345
42
+
43
+ ## Getting Access
44
+ * 360.cn : http://www.passivedns.cn
45
+ * BFK.de : No registration required, but please, please ready their usage policy at http://bfk.de
46
+ * CERT-EE : No registration required
47
+ * DNSDB (Farsight Security) : https://api.dnsdb.info/
48
+ * Mnemonic : mss .at. mnemonic.no
49
+ * TCPIPUtils : http://www.tcpiputils.com/premium-access
50
+ * VirusTotal : https://www.virustotal.com
68
51
 
69
52
  ## Usage
70
53
 
71
- require 'passivedns-client'
54
+ require 'passivedns/client'
72
55
 
73
- c = PassiveDNS::Client.new(['bfk','dnsdb']) # providers: bfk, tcpiputils, certee, dnsdb, virustotal
56
+ c = PassiveDNS::Client.new(['bfk','dnsdb']) # providers: bfk, tcpiputils, certee, dnsdb, virustotal, passivedns.cn, mnemonic
74
57
  results = c.query("example.com")
75
58
 
76
59
  Or use the included tool!
77
60
 
78
- Usage: bin/pdnstool [-d [bedvt]] [-g|-v|-m|-c|-x|-y|-j|-t] [-os <sep>] [-f <file>] [-r#|-w#|-v] [-l <count>] <ip|domain|cidr>
79
- -dbedvt uses all of the available passive dns databases
80
- -db only use BFK
81
- -de only use CERT-EE (default)
82
- -dd only use DNSDB (formerly ISC)
83
- -dv only use VirusTotal
84
- -dt only use TCPIPUtils
61
+ Usage: bin/pdnstool [-d [bedvt3m]] [-g|-v|-m|-c|-x|-y|-j|-t] [-os <sep>] [-f <file>] [-r#|-w#|-v] [-l <count>] <ip|domain|cidr>
62
+ -dbedvt3m uses all of the available passive dns databases
63
+ -db use BFK
64
+ -de use CERT-EE (default)
65
+ -dd use DNSDB (formerly ISC)
66
+ -dv use VirusTotal
67
+ -dt use TCPIPUtils
68
+ -d3 use 360.cn (www.passivedns.cn)
69
+ -dm uses Mnemonic (passivedns.mnemonic.no)
85
70
  -dvt uses VirusTotal and TCPIPUtils (for example)
86
71
 
87
72
  -g outputs a link-nodal GDF visualization definition
@@ -100,6 +85,58 @@ Or use the included tool!
100
85
  -v outputs debugging information
101
86
  -l <count> limits the number of records returned per passive dns database queried.
102
87
 
88
+ ## Writing Your Own Database Adaptor
89
+
90
+ module PassiveDNS
91
+ class MyDatabaseAdaptor < PassiveDB
92
+ # override
93
+ def self.name
94
+ "MyPerfectDNS" # short, proper label
95
+ end
96
+ #override
97
+ def self.config_section_name
98
+ "perfect" # very short label to use in the configuration file
99
+ end
100
+ #override
101
+ def self.option_letter
102
+ "p" # single letter to specify the option for the command line tool
103
+ end
104
+
105
+ attr_accessor :debug
106
+ def initialize(options={})
107
+ @debug = options[:debug] || false
108
+ # please include a way to change the base URL, HOST, etc., so that people can test
109
+ # against a test/alternate version of your service
110
+ @base = options["URL"] || "http://myperfectdns.example.com/pdns.cgi?query="
111
+ @apikey = options["APIKEY"] || raise("APIKEY option required for #{self.class}")
112
+ end
113
+
114
+ # override
115
+ def lookup(label, limit=nil)
116
+ $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
117
+ recs = []
118
+ Timeout::timeout(240) {
119
+ t1 = Time.now
120
+ # TODO: your code goes here to fetch the data from your service
121
+ # TODO: don't forget to impose the limit either during the fetch or during the parse phase
122
+ response_time = Time.now - t1
123
+ # TODO: parse your data and add PDNSResult objects to recs array
124
+ recs << PDNSResult.new(self.class.name, response_time, rrname ,
125
+ rdata, rrtype, ttl, first_seen, last_seen, count )
126
+ }
127
+ recs
128
+ rescue Timeout::Error => e # using the implied "begin/try" from the beginning of the function
129
+ $stderr.puts "#{self.class.name} lookup timed out: #{label}"
130
+ end
131
+ end
132
+ end
133
+
134
+ ## Passive DNS - Common Output Format
135
+
136
+ There is an RFC, <a href='http://tools.ietf.org/html/draft-dulaunoy-kaplan-passive-dns-cof-01'>Passive DNS - Common Output Format</a>, and a proof of concept implementation, <a href='https://github.com/adulau/pdns-qof-server'>pdns-qof-server</a>, that describes a recommened JSON format for passive DNS data. passivedns-client is very close to supporting it, but since I've never enteracted with a true implementation of this RFC, I can't attest that I could correctly parse it. I think they way that they can encode multiple results into one record would actually break what I have right now.
137
+
138
+ Right now, I'm in a wait and see mode with how this progresses before I start supporting yet another format or request that other providers start to adhere to a common output format. If you have thoughts on the matter, I would love to discuss.
139
+
103
140
  ## Contributing
104
141
 
105
142
  1. Fork it
@@ -107,3 +144,5 @@ Or use the included tool!
107
144
  3. Commit your changes (`git commit -am 'Add some feature'`)
108
145
  4. Push to the branch (`git push origin my-new-feature`)
109
146
  5. Create new Pull Request
147
+
148
+ <a href='mailto:github@chrislee[dot]dhs[dot]org[stop here]xxx'><img src='http://chrisleephd.us/images/github-email.png?passivedns-client'></a>
data/bin/pdnstool CHANGED
@@ -49,15 +49,20 @@ def printresults(state,format,sep="\t")
49
49
  end
50
50
 
51
51
  def usage
52
- puts "Usage: #{$0} [-d [bedvt]] [-g|-v|-m|-c|-x|-y|-j|-t] [-os <sep>] [-f <file>] [-r#|-w#|-v] [-l <count>] <ip|domain|cidr>"
53
- puts " -dbedvt3 uses all of the available passive dns databases"
54
- puts " -db use BFK"
55
- puts " -de use CERT-EE (default)"
56
- puts " -dd use DNSDB (formerly ISC)"
57
- puts " -dv use VirusTotal"
58
- puts " -dt use TCPIPUtils"
59
- puts " -d3 use 360.cn (www.passivedns.cn)"
60
- puts " -dvt uses VirusTotal and TCPIPUtils (for example)"
52
+ letter_map = {}
53
+ PassiveDNS.constants.each do |const|
54
+ if PassiveDNS.const_get(const).is_a?(Class) and PassiveDNS.const_get(const).superclass == PassiveDNS::PassiveDB
55
+ letter_map[PassiveDNS.const_get(const).option_letter] = [PassiveDNS.const_get(const).name, PassiveDNS.const_get(const).config_section_name]
56
+ end
57
+ end
58
+ databases = letter_map.keys.sort.join("")
59
+
60
+ puts "Usage: #{$0} [-d [#{databases}]] [-g|-v|-m|-c|-x|-y|-j|-t] [-os <sep>] [-f <file>] [-r#|-w#|-v] [-l <count>] <ip|domain|cidr>"
61
+ puts " -d#{databases} uses all of the available passive dns databases"
62
+ letter_map.keys.sort.each do |l|
63
+ puts " -d#{l} use #{letter_map[l][0]}"
64
+ end
65
+ puts " -dvt uses VirusTotal and TCPIPUtils (for example)"
61
66
  puts ""
62
67
  puts " -g outputs a link-nodal GDF visualization definition"
63
68
  puts " -v outputs a link-nodal graphviz visualization definition"
@@ -73,14 +78,14 @@ def usage
73
78
  puts " -r# specifies the levels of recursion to pull. **WARNING** This is quite taxing on the pDNS servers, so use judiciously (never more than 3 or so) or find yourself blocked!"
74
79
  puts " -w# specifies the amount of time to wait, in seconds, between queries (Default: 0)"
75
80
  puts " -v outputs debugging information"
76
- puts " -l <count> limits the number of records returned per passive dns database queried."
81
+ puts " -l <count> limits the number of records returned per passive dns database queried."
77
82
  exit
78
83
  end
79
84
 
80
85
  opts = GetoptLong.new(
81
86
  [ '--help', '-h', GetoptLong::NO_ARGUMENT ],
82
87
  [ '--debug', '-z', GetoptLong::NO_ARGUMENT ],
83
- [ '--database', '-d', GetoptLong::REQUIRED_ARGUMENT ],
88
+ [ '--database', '-d', GetoptLong::REQUIRED_ARGUMENT ],
84
89
 
85
90
  [ '--gdf', '-g', GetoptLong::NO_ARGUMENT ],
86
91
  [ '--graphviz', '-v', GetoptLong::NO_ARGUMENT ],
@@ -95,7 +100,7 @@ opts = GetoptLong.new(
95
100
  [ '--sqlite3', '-f', GetoptLong::REQUIRED_ARGUMENT ],
96
101
  [ '--recurse', '-r', GetoptLong::REQUIRED_ARGUMENT ],
97
102
  [ '--wait', '-w', GetoptLong::REQUIRED_ARGUMENT ],
98
- [ '--limit', '-l', GetoptLong::REQUIRED_ARGUMENT ]
103
+ [ '--limit', '-l', GetoptLong::REQUIRED_ARGUMENT ]
99
104
  )
100
105
 
101
106
  # sets the default search methods
@@ -115,22 +120,12 @@ opts.each do |opt, arg|
115
120
  usage
116
121
  when '--debug'
117
122
  debug = true
118
- when '--database'
119
- arg.split(//).each do |c|
120
- case c
121
- when ','
122
- when 'b'
123
- pdnsdbs << "bfk"
124
- when 'e'
125
- pdnsdbs << "certee"
126
- when 'd'
127
- pdnsdbs << "dnsdb"
128
- when 'v'
129
- pdnsdbs << "virustotal"
130
- when 't'
131
- pdnsdbs << "tcpiputils"
132
- when '3'
133
- pdnsdbs << "cn360"
123
+ when '--database'
124
+ arg.split(//).each do |c|
125
+ if c == ','
126
+ next
127
+ elsif letter_map[c]
128
+ pdnsdbs = letter_map[c][1]
134
129
  else
135
130
  raise "Unknown passive DNS database identifier: #{c}"
136
131
  end
@@ -164,8 +159,8 @@ opts.each do |opt, arg|
164
159
  wait = arg.to_i
165
160
  when '--sqlite3'
166
161
  sqlitedb = arg
167
- when '--limit'
168
- limit = arg.to_i
162
+ when '--limit'
163
+ limit = arg.to_i
169
164
  else
170
165
  usage
171
166
  end
@@ -182,15 +177,15 @@ end
182
177
 
183
178
  if debug
184
179
  $stderr.puts "Using the following databases: #{pdnsdbs.join(", ")}"
185
- $stderr.puts "Recursions: #{recursedepth}, Wait time: #{wait}, Limit: #{limit or 'none'}"
186
- if format == "text" or format == "csv"
187
- $stderr.puts "Output format: #{format} (sep=\"#{sep}\")"
188
- else
189
- $stderr.puts "Output format: #{format}"
190
- end
191
- if ENV['http_proxy']
192
- $stderr.puts "Using proxy settings: http_proxy=#{ENV['http_proxy']}, https_proxy=#{ENV['https_proxy']}"
193
- end
180
+ $stderr.puts "Recursions: #{recursedepth}, Wait time: #{wait}, Limit: #{limit or 'none'}"
181
+ if format == "text" or format == "csv"
182
+ $stderr.puts "Output format: #{format} (sep=\"#{sep}\")"
183
+ else
184
+ $stderr.puts "Output format: #{format}"
185
+ end
186
+ if ENV['http_proxy']
187
+ $stderr.puts "Using proxy settings: http_proxy=#{ENV['http_proxy']}, https_proxy=#{ENV['https_proxy']}"
188
+ end
194
189
  end
195
190
 
196
191
  state = nil
@@ -1,12 +1,27 @@
1
1
  require 'open-uri'
2
+ require_relative 'passivedb'
2
3
 
3
4
  module PassiveDNS
4
- class BFK
5
- attr_accessor :debug
6
- def initialize
7
- @debug = false
5
+ class BFK < PassiveDB
6
+ # override
7
+ def self.name
8
+ "BFK.de"
9
+ end
10
+ #override
11
+ def self.config_section_name
12
+ "bfk"
13
+ end
14
+ #override
15
+ def self.option_letter
16
+ "b"
17
+ end
18
+
19
+ attr_accessor :debug
20
+ def initialize(options={})
21
+ @debug = options[:debug] || false
22
+ @base = options["URL"] || "http://www.bfk.de/bfk_dnslogger.html?query="
8
23
  end
9
- @@base = "http://www.bfk.de/bfk_dnslogger.html?query="
24
+
10
25
  def parse(page,response_time)
11
26
  line = page.unpack('C*').pack('U*').split(/<table/).grep(/ id=\"logger\"/)
12
27
  return [] unless line.length > 0
@@ -29,23 +44,23 @@ module PassiveDNS
29
44
  ######### FIX BLANKS FOR MX
30
45
 
31
46
  end
32
- res << PDNSResult.new('BFK',response_time,r[0],r[2],r[1])
47
+ res << PDNSResult.new(self.class.name,response_time,r[0],r[2],r[1])
33
48
  end
34
49
  end
35
50
  res
36
51
  rescue Exception => e
37
- $stderr.puts "BFKClient Exception: #{e}"
52
+ $stderr.puts "#{self.class.name} Exception: #{e}"
38
53
  raise e
39
54
  end
40
55
 
56
+ # override
41
57
  def lookup(label, limit=nil)
42
- $stderr.puts "DEBUG: BFKClient.lookup(#{label})" if @debug
58
+ $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
43
59
  Timeout::timeout(240) {
44
60
  t1 = Time.now
45
61
  open(
46
- @@base+label,
47
- "User-Agent" => "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}",
48
- :http_basic_authentication => [@user,@pass]
62
+ @base+label,
63
+ "User-Agent" => "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}"
49
64
  ) do |f|
50
65
  t2 = Time.now
51
66
  recs = parse(f.read,t2-t1)
@@ -57,7 +72,7 @@ module PassiveDNS
57
72
  end
58
73
  }
59
74
  rescue Timeout::Error => e
60
- $stderr.puts "BFK lookup timed out: #{label}"
75
+ $stderr.puts "#{self.class.name} lookup timed out: #{label}"
61
76
  end
62
77
  end
63
78
  end
@@ -1,22 +1,40 @@
1
1
  require 'socket'
2
+ require_relative 'passivedb'
2
3
 
3
4
  module PassiveDNS
4
- class CERTEE
5
- @@host = "sim.cert.ee"
6
- attr_accessor :debug
7
- def initialize
5
+ class CERTEE < PassiveDB
6
+ # override
7
+ def self.name
8
+ "CERTEE"
9
+ end
10
+ #override
11
+ def self.config_section_name
12
+ "certee"
13
+ end
14
+ #override
15
+ def self.option_letter
16
+ "e"
17
+ end
18
+
19
+ attr_accessor :debug
20
+ def initialize(options={})
21
+ @debug = options[:debug] || false
22
+ @host = options["HOST"] || "sim.cert.ee"
23
+ @port = options["PORT"].to_i || 43
8
24
  end
25
+
26
+ # override
9
27
  def lookup(label, limit=nil)
10
- $stderr.puts "DEBUG: CERTEE.lookup(#{label})" if @debug
28
+ $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
11
29
  recs = []
12
30
  begin
13
31
  t1 = Time.now
14
- s = TCPSocket.new(@@host,43)
32
+ s = TCPSocket.new(@host,@port)
15
33
  s.puts(label)
16
34
  s.each_line do |l|
17
35
  if l =~ /Traceback \(most recent call last\):/
18
36
  # there is a bug in the CERTEE lookup tool
19
- raise "CERTEE is currently offline"
37
+ raise "#{self.class.name} is currently offline"
20
38
  end
21
39
  (lbl,ans,fs,ls) = l.chomp.split(/\t/)
22
40
  rrtype = 'A'
@@ -28,7 +46,7 @@ module PassiveDNS
28
46
  rrtype = 'CNAME'
29
47
  end
30
48
  t2 = Time.now
31
- recs << PDNSResult.new('CERTEE',t2-t1,lbl,ans,rrtype,0,Time.parse(fs).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),Time.parse(ls).utc.strftime("%Y-%m-%dT%H:%M:%SZ"))
49
+ recs << PDNSResult.new(self.class.name,t2-t1,lbl,ans,rrtype,0,Time.parse(fs).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),Time.parse(ls).utc.strftime("%Y-%m-%dT%H:%M:%SZ"))
32
50
  end
33
51
  rescue SocketError => e
34
52
  $stderr.puts e
@@ -3,34 +3,32 @@ require 'net/https'
3
3
  require 'openssl'
4
4
  require 'json'
5
5
  require 'digest/md5'
6
- require 'configparser'
7
- require 'pp'
8
-
9
- # Please read http://www.tcpiputils.com/terms-of-service under automated requests
6
+ require_relative 'passivedb'
10
7
 
11
8
  module PassiveDNS
12
- class CN360
9
+ class CN360 < PassiveDB
10
+ # override
11
+ def self.name
12
+ "360.cn"
13
+ end
14
+ #override
15
+ def self.config_section_name
16
+ "cn360"
17
+ end
18
+ #override
19
+ def self.option_letter
20
+ "3"
21
+ end
22
+
13
23
  attr_accessor :debug
14
-
15
- def initialize(configfile="#{ENV["HOME"]}/.flint.conf")
16
- @debug = false
17
- if not File.exist?(configfile)
18
- if not File.exist?("/etc/flint.conf")
19
- raise "Cannot find a configuration file at #{configfile} or /etc/flint.conf"
24
+ def initialize(options={})
25
+ @debug = options[:debug] || false
26
+ ["API", "API_ID", "API_KEY"].each do |opt|
27
+ if not options[opt]
28
+ raise "Field #{opt} is required. See README.md"
20
29
  end
21
- configfile = "/etc/flint.conf"
22
- end
23
-
24
- @cp = ConfigParser.new(configfile)
25
- if not @cp["API"]
26
- raise "Field, API, is required in the configuration file. It should specify the URL of the JSON Web API."
27
- end
28
- if not @cp["API_ID"]
29
- raise "Field, API_ID, is required in the configuration file. It should specify the user ID for the API key."
30
- end
31
- if not @cp["API_KEY"]
32
- raise "Field, API_KEY, is required in the configuration file. It should specify the API key."
33
30
  end
31
+ @cp = options
34
32
  end
35
33
 
36
34
  def parse_json(page,query,response_time=0)
@@ -41,11 +39,11 @@ module PassiveDNS
41
39
  time_first = (row["time_first"]) ? Time.at(row["time_first"].to_i) : nil
42
40
  time_last = (row["time_last"]) ? Time.at(row["time_last"].to_i) : nil
43
41
  count = row["count"] || 0
44
- res << PDNSResult.new('cn360', response_time, row["rrname"], row["rdata"], row["rrtype"], time_first, time_last, count)
42
+ res << PDNSResult.new(self.class.name, response_time, row["rrname"], row["rdata"], row["rrtype"], time_first, time_last, count)
45
43
  end
46
44
  res
47
45
  rescue Exception => e
48
- $stderr.puts "360.cn Exception: #{e}"
46
+ $stderr.puts "#{self.class.name} Exception: #{e}"
49
47
  raise e
50
48
  end
51
49
 
@@ -60,7 +58,7 @@ module PassiveDNS
60
58
  url = URI.parse url
61
59
  http = Net::HTTP.new(url.host, url.port)
62
60
  http.use_ssl = (url.scheme == 'https')
63
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
61
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE # I hate doing this
64
62
  http.verify_depth = 5
65
63
  request = Net::HTTP::Get.new(url.path)
66
64
  request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
@@ -3,26 +3,28 @@
3
3
  # to request an API key, please email dnsdb-api at farsightsecurity dot com.
4
4
  require 'net/http'
5
5
  require 'net/https'
6
+ require_relative 'passivedb'
6
7
 
7
8
  module PassiveDNS
8
- class DNSDB
9
- attr_accessor :debug
10
- @@base="https://api.dnsdb.info/lookup"
11
-
12
- def initialize(config="#{ENV['HOME']}/.dnsdb-query.conf")
13
- @debug = false
14
- if File.exist?(config)
15
- @key = File.open(config).readline.chomp
16
- if @key =~ /^[0-9a-f]{64}$/
17
- # pass
18
- elsif @key =~ /^APIKEY=\"([0-9a-f]{64})\"/
19
- @key = $1
20
- else
21
- raise "Format of configuration file (default: #{ENV['HOME']}/.dnsdb-query.conf) is:\nAPIKEY=\"<key>\"\nE.g.,\nAPIKEY=\"d41d8cd98f00b204e9800998ecf8427ed41d8cd98f00b204e9800998ecf8427e\"\n"
22
- end
23
- else
24
- raise "Configuration file for DNSDB is required for intialization\nFormat of configuration file (default: #{ENV['HOME']}/.dnsdb-query.conf) is:\nAPIKEY=\"<key>\"\nE.g.,\nAPIKEY=\"d41d8cd98f00b204e9800998ecf8427ed41d8cd98f00b204e9800998ecf8427e\"\n"
25
- end
9
+ class DNSDB < PassiveDB
10
+ # override
11
+ def self.name
12
+ "DNSDB"
13
+ end
14
+ #override
15
+ def self.config_section_name
16
+ "dnsdb"
17
+ end
18
+ #override
19
+ def self.option_letter
20
+ "d"
21
+ end
22
+
23
+ attr_accessor :debug
24
+ def initialize(options={})
25
+ @debug = options[:debug] || false
26
+ @key = options["APIKEY"] || raise("APIKEY option required for #{self.class}")
27
+ @base = options["URL"] || "https://api.dnsdb.info/lookup"
26
28
  end
27
29
 
28
30
  def parse_json(page,response_time)
@@ -35,28 +37,28 @@ module PassiveDNS
35
37
  record['rdata'] = [record['rdata']] if record['rdata'].class == String
36
38
  record['rdata'].each do |rdata|
37
39
  if record['time_first']
38
- res << PDNSResult.new('DNSDB',response_time,record['rrname'],rdata,record['rrtype'],0,Time.at(record['time_first'].to_i).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),Time.at(record['time_last'].to_i).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),record['count'])
40
+ res << PDNSResult.new(self.class.name,response_time,record['rrname'],rdata,record['rrtype'],0,Time.at(record['time_first'].to_i).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),Time.at(record['time_last'].to_i).utc.strftime("%Y-%m-%dT%H:%M:%SZ"),record['count'])
39
41
  else
40
- res << PDNSResult.new('DNSDB',response_time,record['rrname'],rdata,record['rrtype'])
42
+ res << PDNSResult.new(self.class.name,response_time,record['rrname'],rdata,record['rrtype'])
41
43
  end
42
44
  end
43
45
  end
44
46
  res
45
47
  rescue Exception => e
46
- $stderr.puts "DNSDB Exception: #{e}"
48
+ $stderr.puts "#{self.class.name} Exception: #{e}"
47
49
  $stderr.puts page
48
50
  raise e
49
51
  end
50
52
 
51
53
  def lookup(label, limit=nil)
52
- $stderr.puts "DEBUG: DNSDB.lookup(#{label})" if @debug
54
+ $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
53
55
  Timeout::timeout(240) {
54
56
  url = nil
55
57
  if label =~ /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}(\/\d{1,2})?$/
56
58
  label = label.gsub(/\//,',')
57
- url = "#{@@base}/rdata/ip/#{label}"
59
+ url = "#{@base}/rdata/ip/#{label}"
58
60
  else
59
- url = "#{@@base}/rrset/name/#{label}"
61
+ url = "#{@base}/rrset/name/#{label}"
60
62
  end
61
63
  url = URI.parse url
62
64
  http = Net::HTTP.new(url.host, url.port)
@@ -78,7 +80,7 @@ module PassiveDNS
78
80
  parse_json(response.body,t2-t1)
79
81
  }
80
82
  rescue Timeout::Error => e
81
- $stderr.puts "DNSDB lookup timed out: #{label}"
83
+ $stderr.puts "#{self.class.name} lookup timed out: #{label}"
82
84
  end
83
85
  end
84
86
  end
@@ -0,0 +1,72 @@
1
+ # DESCRIPTION: Module to query Mnemonic's passive DNS repository
2
+ # CONTRIBUTOR: Drew Hunt (pinowudi@yahoo.com)
3
+ require 'net/http'
4
+ require 'net/https'
5
+ require 'openssl'
6
+
7
+ module PassiveDNS
8
+ class Mnemonic < PassiveDB
9
+ # override
10
+ def self.name
11
+ "Mnemonic"
12
+ end
13
+ #override
14
+ def self.config_section_name
15
+ "mnemonic"
16
+ end
17
+ #override
18
+ def self.option_letter
19
+ "m"
20
+ end
21
+
22
+ attr_accessor :debug
23
+ def initialize(options={})
24
+ @debug = options[:debug] || false
25
+ @apikey = options["APIKEY"] || raise("#{self.class.name} requires an APIKEY")
26
+ @url = options["URL"] || "https://passivedns.mnemonic.no/api1/?apikey="
27
+ end
28
+
29
+ def parse_json(page,query,response_time=0)
30
+ res = []
31
+ # need to remove the json_class tag or the parser will crap itself trying to find a class to align it to
32
+ data = JSON.parse(page)
33
+ if data['result']
34
+ data['result'].each do |row|
35
+ if row['query']
36
+ res << PDNSResult.new(self.class.name,response_time,row['query'],row['answer'],row['type'].upcase,row['ttl'],row['first'],row['last'])
37
+ end
38
+ end
39
+ end
40
+ res
41
+ rescue Exception => e
42
+ $stderr.puts "#{self.class.name} Exception: #{e}"
43
+ raise e
44
+ end
45
+
46
+ def lookup(label, limit=nil)
47
+ $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
48
+ Timeout::timeout(240) {
49
+ url = "#{@url}#{@apikey}&query=#{label}&method=exact"
50
+ $stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
51
+ url = URI.parse url
52
+ http = Net::HTTP.new(url.host, url.port)
53
+ http.use_ssl = (url.scheme == 'https')
54
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
55
+ http.verify_depth = 5
56
+ request = Net::HTTP::Get.new(url.path+"?"+url.query)
57
+ request.add_field("User-Agent", "Ruby/#{RUBY_VERSION} passivedns-client rubygem v#{PassiveDNS::Client::VERSION}")
58
+ t1 = Time.now
59
+ response = http.request(request)
60
+ t2 = Time.now
61
+ recs = parse_json(response.body, label, t2-t1)
62
+ if limit
63
+ recs[0,limit]
64
+ else
65
+ recs
66
+ end
67
+ }
68
+ rescue Timeout::Error => e
69
+ $stderr.puts "#{self.class.name} lookup timed out: #{label}"
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,19 @@
1
+ module PassiveDNS
2
+ class PassiveDB
3
+ def self.name
4
+ raise "You should implement your own version of .name"
5
+ end
6
+
7
+ def self.config_section_name
8
+ name
9
+ end
10
+
11
+ def self.option_letter
12
+ raise "You should pick a unique letter to serve as your database option letter for the command line option -d"
13
+ end
14
+
15
+ def lookup(label, limit=nil)
16
+ raise "You must implement the lookup function"
17
+ end
18
+ end
19
+ end
@@ -6,18 +6,25 @@ require 'json'
6
6
  # Please read http://www.tcpiputils.com/terms-of-service under automated requests
7
7
 
8
8
  module PassiveDNS
9
- class TCPIPUtils
9
+ class TCPIPUtils < PassiveDB
10
+ # override
11
+ def self.name
12
+ "TCPIPUtils"
13
+ end
14
+ #override
15
+ def self.config_section_name
16
+ "tcpiputils"
17
+ end
18
+ #override
19
+ def self.option_letter
20
+ "t"
21
+ end
22
+
10
23
  attr_accessor :debug
11
- def initialize(config="#{ENV['HOME']}/.tcpiputils")
12
- @debug = false
13
- if File.exist?(config)
14
- @apikey = File.open(config).read.split(/\n/)[0]
15
- $stderr.puts "DEBUG: TCPIPUtils#initialize(#{@apikey})" if @debug
16
- else
17
- raise "Error: Configuration file for TCPIPUtils is required for intialization
18
- Format of configuration file (default: #{ENV['HOME']}/.tcpiputils) is the 64 hex character apikey on one line.
19
- To obtain an API Key, go to http://www.tcpiputils.com/premium-access and purchase premium API access."
20
- end
24
+ def initialize(options={})
25
+ @debug = options[:debug] || false
26
+ @apikey = options["APIKEY"] || raise("#{self.class.name} requires an APIKEY. See README.md")
27
+ @url = options["URL"] || "https://www.utlsapi.com/api.php?version=1.0&apikey="
21
28
  end
22
29
 
23
30
  def format_recs(reply_data, question, delta)
@@ -26,23 +33,23 @@ To obtain an API Key, go to http://www.tcpiputils.com/premium-access and purchas
26
33
  case key
27
34
  when "ipv4"
28
35
  data.each do |rec|
29
- recs << PDNSResult.new("tcpiputils", delta, question, rec["ip"], "A", nil, nil, rec["updatedate"], nil)
36
+ recs << PDNSResult.new(self.class.name, delta, question, rec["ip"], "A", nil, nil, rec["updatedate"], nil)
30
37
  end
31
38
  when "ipv6"
32
39
  data.each do |rec|
33
- recs << PDNSResult.new("tcpiputils", delta, question, rec["ip"], "AAAA", nil, nil, rec["updatedate"], nil)
40
+ recs << PDNSResult.new(self.class.name, delta, question, rec["ip"], "AAAA", nil, nil, rec["updatedate"], nil)
34
41
  end
35
42
  when "dns"
36
43
  data.each do |rec|
37
- recs << PDNSResult.new("tcpiputils", delta, question, rec["dns"], "NS", nil, nil, rec["updatedate"], nil)
44
+ recs << PDNSResult.new(self.class.name, delta, question, rec["dns"], "NS", nil, nil, rec["updatedate"], nil)
38
45
  end
39
46
  when "mx"
40
47
  data.each do |rec|
41
- recs << PDNSResult.new("tcpiputils", delta, question, rec["dns"], "MX", nil, nil, rec["updatedate"], nil)
48
+ recs << PDNSResult.new(self.class.name, delta, question, rec["dns"], "MX", nil, nil, rec["updatedate"], nil)
42
49
  end
43
50
  when "domains"
44
51
  data.each do |rec|
45
- recs << PDNSResult.new("tcpiputils", delta, rec, question, "A", nil, nil, nil, nil)
52
+ recs << PDNSResult.new(self.class.name, delta, rec, question, "A", nil, nil, nil, nil)
46
53
  end
47
54
  end
48
55
  end
@@ -50,9 +57,9 @@ To obtain an API Key, go to http://www.tcpiputils.com/premium-access and purchas
50
57
  end
51
58
 
52
59
  def lookup(label, limit=nil)
53
- $stderr.puts "DEBUG: TCPIPUtils.lookup(#{label})" if @debug
60
+ $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
54
61
  type = (label.match(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/)) ? "domainneighbors" : "domainipdnshistory"
55
- url = "https://www.utlsapi.com/api.php?version=1.0&apikey=#{@apikey}&type=#{type}&q=#{label}"
62
+ url = "#{@url}#{@apikey}&type=#{type}&q=#{label}"
56
63
  recs = []
57
64
  Timeout::timeout(240) {
58
65
  url = URI.parse url
@@ -70,7 +77,7 @@ To obtain an API Key, go to http://www.tcpiputils.com/premium-access and purchas
70
77
  question = reply["data"]["question"]
71
78
  recs = format_recs(reply["data"], question, delta)
72
79
  elsif reply["status"] and reply["status"] == "error"
73
- raise "TCPIPUtils: error from web API: #{reply["data"]}"
80
+ raise "#{self.class.name}: error from web API: #{reply["data"]}"
74
81
  end
75
82
  if limit
76
83
  recs[0,limit]
@@ -79,7 +86,7 @@ To obtain an API Key, go to http://www.tcpiputils.com/premium-access and purchas
79
86
  end
80
87
  }
81
88
  rescue Timeout::Error => e
82
- $stderr.puts "TCPIPUtils lookup timed out: #{label}"
89
+ $stderr.puts "#{self.class.name} lookup timed out: #{label}"
83
90
  end
84
91
  end
85
92
  end
@@ -1,5 +1,5 @@
1
1
  module PassiveDNS
2
2
  class Client
3
- VERSION = "1.4.1"
3
+ VERSION = "2.0.0"
4
4
  end
5
5
  end
@@ -4,16 +4,26 @@ require 'net/https'
4
4
  require 'openssl'
5
5
 
6
6
  module PassiveDNS
7
- class VirusTotal
8
- attr_accessor :debug
9
- def initialize(config="#{ENV['HOME']}/.virustotal")
10
- if File.exist?(config)
11
- @apikey = File.open(config).read.split(/\n/)[0]
12
- $stderr.puts "DEBUG: VirusTotal#initialize(#{@apikey})" if @debug
13
- else
14
- raise "Configuration file for VirusTotal is required for intialization\nFormat of configuration file (default: #{ENV['HOME']}/.virustotal) is the 64 hex character apikey on one line."
15
- end
16
- end
7
+ class VirusTotal < PassiveDB
8
+ # override
9
+ def self.name
10
+ "VirusTotal"
11
+ end
12
+ #override
13
+ def self.config_section_name
14
+ "virustotal"
15
+ end
16
+ #override
17
+ def self.option_letter
18
+ "v"
19
+ end
20
+
21
+ attr_accessor :debug
22
+ def initialize(options={})
23
+ @debug = options[:debug] || false
24
+ @apikey = options["APIKEY"] || raise("#{self.class.name} requires an APIKEY. See README.md")
25
+ @url = options["URL"] || "https://www.virustotal.com/vtapi/v2/"
26
+ end
17
27
 
18
28
  def parse_json(page,query,response_time=0)
19
29
  res = []
@@ -22,9 +32,9 @@ module PassiveDNS
22
32
  if data['resolutions']
23
33
  data['resolutions'].each do |row|
24
34
  if row['ip_address']
25
- res << PDNSResult.new('VirusTotal',response_time,query,row['ip_address'],'A',nil,nil,row['last_resolved'])
35
+ res << PDNSResult.new(self.class.name,response_time,query,row['ip_address'],'A',nil,nil,row['last_resolved'])
26
36
  elsif row['hostname']
27
- res << PDNSResult.new('VirusTotal',response_time,row['hostname'],query,'A',nil,nil,row['last_resolved'])
37
+ res << PDNSResult.new(self.class.name,response_time,row['hostname'],query,'A',nil,nil,row['last_resolved'])
28
38
  end
29
39
  end
30
40
  end
@@ -35,15 +45,15 @@ module PassiveDNS
35
45
  end
36
46
 
37
47
  def lookup(label, limit=nil)
38
- $stderr.puts "DEBUG: VirusTotal.lookup(#{label})" if @debug
48
+ $stderr.puts "DEBUG: #{self.class.name}.lookup(#{label})" if @debug
39
49
  Timeout::timeout(240) {
40
50
  url = nil
41
51
  if label =~ /^[\d\.]+$/
42
- url = "https://www.virustotal.com/vtapi/v2/ip-address/report?ip=#{label}&apikey=#{@apikey}"
52
+ url = "#{@url}ip-address/report?ip=#{label}&apikey=#{@apikey}"
43
53
  else
44
- url = "https://www.virustotal.com/vtapi/v2/domain/report?domain=#{label}&apikey=#{@apikey}"
54
+ url = "#{@url}domain/report?domain=#{label}&apikey=#{@apikey}"
45
55
  end
46
- $stderr.puts "DEBUG: VirusTotal url = #{url}" if @debug
56
+ $stderr.puts "DEBUG: #{self.class.name} url = #{url}" if @debug
47
57
  url = URI.parse url
48
58
  http = Net::HTTP.new(url.host, url.port)
49
59
  http.use_ssl = (url.scheme == 'https')
@@ -62,7 +72,7 @@ module PassiveDNS
62
72
  end
63
73
  }
64
74
  rescue Timeout::Error => e
65
- $stderr.puts "VirusTotal lookup timed out: #{label}"
75
+ $stderr.puts "#{self.class.name} lookup timed out: #{label}"
66
76
  end
67
77
  end
68
78
  end
@@ -3,6 +3,7 @@ require "passivedns/client/version"
3
3
  # This code is released under the LGPL: http://www.gnu.org/licenses/lgpl-3.0.txt
4
4
  # Please note that use of any passive dns database is subject to the terms of use of that passive dns database. Use of this script in violation of their terms is not encouraged in any way. Also, please do not add any obfuscation to try to work around their terms of service. If you need special services, ask the providers for help/permission.
5
5
  # Remember, these passive DNS operators are my friends. I don't want to have a row with them because some asshat used this library to abuse them.
6
+ require 'passivedns/client/passivedb.rb'
6
7
  require 'passivedns/client/bfk.rb'
7
8
  require 'passivedns/client/certee.rb'
8
9
  require 'passivedns/client/dnsdb.rb'
@@ -10,34 +11,34 @@ require 'passivedns/client/virustotal.rb'
10
11
  require 'passivedns/client/tcpiputils.rb'
11
12
  require 'passivedns/client/cn360.rb'
12
13
  require 'passivedns/client/state.rb'
14
+ require 'passivedns/client/mnemonic.rb'
15
+ require 'configparser'
16
+ require 'pp'
13
17
 
14
18
  module PassiveDNS
15
19
 
16
20
  class PDNSResult < Struct.new(:source, :response_time, :query, :answer, :rrtype, :ttl, :firstseen, :lastseen, :count); end
17
21
 
18
22
  class Client
19
- def initialize(pdns=['bfk','certee','dnsdb','virustotal','tcpiputils','cn360'])
23
+ def initialize(pdns=['bfk','certee','dnsdb','virustotal','tcpiputils','cn360','mnemonic'], configfile="#{ENV['HOME']}/.passivedns-client")
24
+ cp = ConfigParser.new(configfile)
25
+ # this creates a map of all the PassiveDNS provider names and their classes
26
+ class_map = {}
27
+ PassiveDNS.constants.each do |const|
28
+ if PassiveDNS.const_get(const).is_a?(Class) and PassiveDNS.const_get(const).superclass == PassiveDNS::PassiveDB
29
+ class_map[PassiveDNS.const_get(const).config_section_name] = PassiveDNS.const_get(const)
30
+ end
31
+ end
32
+
20
33
  @pdnsdbs = []
21
- pdns.uniq.each do |pd|
22
- case pd
23
- when 'bfk'
24
- @pdnsdbs << PassiveDNS::BFK.new
25
- when 'certee'
26
- @pdnsdbs << PassiveDNS::CERTEE.new
27
- when 'dnsdb'
28
- @pdnsdbs << PassiveDNS::DNSDB.new
29
- when 'isc'
30
- @pdnsdbs << PassiveDNS::DNSDB.new
31
- when 'virustotal'
32
- @pdnsdbs << PassiveDNS::VirusTotal.new
33
- when 'tcpiputils'
34
- @pdnsdbs << PassiveDNS::TCPIPUtils.new
35
- when 'cn360'
36
- @pdnsdbs << PassiveDNS::CN360.new
37
- else
38
- raise "Unknown Passive DNS provider: #{pd}"
39
- end
40
- end
34
+ pdns.uniq.each do |pd|
35
+ if class_map[pd]
36
+ @pdnsdbs << class_map[pd].new(cp[pd] || {})
37
+ else
38
+ raise "Unknown Passive DNS provider: #{pd}"
39
+ end
40
+ end
41
+
41
42
  end #initialize
42
43
 
43
44
  def debug=(d)
@@ -7,8 +7,21 @@ unless Kernel.respond_to?(:require_relative)
7
7
  end
8
8
 
9
9
  require_relative 'helper'
10
+ require 'configparser'
10
11
 
11
12
  class TestPassiveDnsQuery < Test::Unit::TestCase
13
+
14
+ def setup
15
+ configfile="#{ENV['HOME']}/.passivedns-client"
16
+ @cp = ConfigParser.new(configfile)
17
+ @class_map = {}
18
+ PassiveDNS.constants.each do |const|
19
+ if PassiveDNS.const_get(const).is_a?(Class) and PassiveDNS.const_get(const).superclass == PassiveDNS::PassiveDB
20
+ @class_map[PassiveDNS.const_get(const).config_section_name] = PassiveDNS.const_get(const)
21
+ end
22
+ end
23
+ end
24
+
12
25
  def test_instantiate_Nonexisting_Client
13
26
  assert_raise RuntimeError do
14
27
  PassiveDNS::Client.new(['doesnotexist'])
@@ -36,18 +49,19 @@ class TestPassiveDnsQuery < Test::Unit::TestCase
36
49
  end
37
50
 
38
51
  def test_BFK
39
- assert_not_nil(PassiveDNS::BFK.new)
40
52
  assert_nothing_raised do
41
53
  PassiveDNS::Client.new(['bfk'])
42
54
  end
43
- rows = PassiveDNS::BFK.new.lookup("example.org",3)
55
+ d = PassiveDNS::BFK.new(@cp['bfk'] || {})
56
+ assert_not_nil(d)
57
+ rows = d.lookup("example.org",3)
44
58
  assert_not_nil(rows)
45
59
  assert_not_nil(rows.to_s)
46
60
  assert_not_nil(rows.to_xml)
47
61
  assert_not_nil(rows.to_json)
48
62
  assert_not_nil(rows.to_yaml)
49
63
  assert_equal(3, rows.length)
50
- rows = PassiveDNS::BFK.new.lookup("8.8.8.8")
64
+ rows = d.lookup("8.8.8.8")
51
65
  assert_not_nil(rows)
52
66
  assert_not_nil(rows.to_s)
53
67
  assert_not_nil(rows.to_xml)
@@ -57,18 +71,19 @@ class TestPassiveDnsQuery < Test::Unit::TestCase
57
71
 
58
72
  def test_CERTEE
59
73
  assert(false, "CERTEE is still offline")
60
- assert_not_nil(PassiveDNS::CERTEE.new)
61
74
  assert_nothing_raised do
62
75
  PassiveDNS::Client.new(['certee'])
63
76
  end
64
- rows = PassiveDNS::CERTEE.new.lookup("sim.cert.ee",3)
77
+ d = PassiveDNS::CERTEE.new(@cp['certee'] || {})
78
+ assert_not_nil(d)
79
+ rows = d.lookup("sim.cert.ee",3)
65
80
  assert_not_nil(rows)
66
81
  assert_not_nil(rows.to_s)
67
82
  assert_not_nil(rows.to_xml)
68
83
  assert_not_nil(rows.to_json)
69
84
  assert_not_nil(rows.to_yaml)
70
85
  assert_equal(3, rows.length)
71
- rows = PassiveDNS::CERTEE.new.lookup("8.8.8.8")
86
+ rows = d.lookup("8.8.8.8")
72
87
  assert_not_nil(rows)
73
88
  assert_not_nil(rows.to_s)
74
89
  assert_not_nil(rows.to_xml)
@@ -77,18 +92,19 @@ class TestPassiveDnsQuery < Test::Unit::TestCase
77
92
  end
78
93
 
79
94
  def test_DNSDB
80
- assert_not_nil(PassiveDNS::DNSDB.new)
81
95
  assert_nothing_raised do
82
96
  PassiveDNS::Client.new(['dnsdb'])
83
97
  end
84
- rows = PassiveDNS::DNSDB.new.lookup("example.org",3)
98
+ d = PassiveDNS::DNSDB.new(@cp['dnsdb'] || {})
99
+ assert_not_nil(d)
100
+ rows = d.lookup("example.org",3)
85
101
  assert_not_nil(rows)
86
102
  assert_not_nil(rows.to_s)
87
103
  assert_not_nil(rows.to_xml)
88
104
  assert_not_nil(rows.to_json)
89
105
  assert_not_nil(rows.to_yaml)
90
106
  assert_equal(3, rows.length) # this will fail since DNSDB has an off by one error
91
- rows = PassiveDNS::DNSDB.new.lookup("8.8.8.8")
107
+ rows = d.lookup("8.8.8.8")
92
108
  assert_not_nil(rows)
93
109
  assert_not_nil(rows.to_s)
94
110
  assert_not_nil(rows.to_xml)
@@ -97,18 +113,19 @@ class TestPassiveDnsQuery < Test::Unit::TestCase
97
113
  end
98
114
 
99
115
  def test_VirusTotal
100
- assert_not_nil(PassiveDNS::VirusTotal.new)
101
116
  assert_nothing_raised do
102
117
  PassiveDNS::Client.new(['virustotal'])
103
118
  end
104
- rows = PassiveDNS::VirusTotal.new.lookup("google.com",3)
119
+ d = PassiveDNS::VirusTotal.new(@cp['virustotal'] || {})
120
+ assert_not_nil(d)
121
+ rows = d.lookup("google.com",3)
105
122
  assert_not_nil(rows)
106
123
  assert_not_nil(rows.to_s)
107
124
  assert_not_nil(rows.to_xml)
108
125
  assert_not_nil(rows.to_json)
109
126
  assert_not_nil(rows.to_yaml)
110
127
  assert_equal(3, rows.length)
111
- rows = PassiveDNS::VirusTotal.new.lookup("8.8.8.8")
128
+ rows = d.lookup("8.8.8.8")
112
129
  assert_not_nil(rows)
113
130
  assert_not_nil(rows.to_s)
114
131
  assert_not_nil(rows.to_xml)
@@ -117,24 +134,25 @@ class TestPassiveDnsQuery < Test::Unit::TestCase
117
134
  end
118
135
 
119
136
  def test_TCPIPUtils
120
- assert_not_nil(PassiveDNS::TCPIPUtils.new)
121
137
  assert_nothing_raised do
122
138
  PassiveDNS::Client.new(['tcpiputils'])
123
139
  end
124
- rows = PassiveDNS::TCPIPUtils.new.lookup("example.org")
140
+ d = PassiveDNS::TCPIPUtils.new(@cp['tcpiputils'] || {})
141
+ assert_not_nil(d)
142
+ rows = d.lookup("example.org")
125
143
  assert_not_nil(rows)
126
144
  assert_not_nil(rows.to_s)
127
145
  assert_not_nil(rows.to_xml)
128
146
  assert_not_nil(rows.to_json)
129
147
  assert_not_nil(rows.to_yaml)
130
- rows = PassiveDNS::TCPIPUtils.new.lookup("example.org",3)
148
+ rows = d.lookup("example.org",3)
131
149
  assert_not_nil(rows)
132
150
  assert_not_nil(rows.to_s)
133
151
  assert_not_nil(rows.to_xml)
134
152
  assert_not_nil(rows.to_json)
135
153
  assert_not_nil(rows.to_yaml)
136
154
  assert_equal(3, rows.length)
137
- rows = PassiveDNS::TCPIPUtils.new.lookup("8.8.8.8")
155
+ rows = d.lookup("8.8.8.8")
138
156
  assert_not_nil(rows)
139
157
  assert_not_nil(rows.to_s)
140
158
  assert_not_nil(rows.to_xml)
@@ -143,28 +161,56 @@ class TestPassiveDnsQuery < Test::Unit::TestCase
143
161
  end
144
162
 
145
163
  def test_cn360
146
- assert_not_nil(PassiveDNS::CN360.new)
147
164
  assert_nothing_raised do
148
165
  PassiveDNS::Client.new(['cn360'])
149
166
  end
150
- rows = PassiveDNS::CN360.new.lookup("example.org")
167
+ d = PassiveDNS::CN360.new(@cp['cn360'] || {})
168
+ assert_not_nil(d)
169
+ rows = d.lookup("example.org")
151
170
  assert_not_nil(rows)
152
171
  assert_not_nil(rows.to_s)
153
172
  assert_not_nil(rows.to_xml)
154
173
  assert_not_nil(rows.to_json)
155
174
  assert_not_nil(rows.to_yaml)
156
- rows = PassiveDNS::CN360.new.lookup("example.org",3)
175
+ rows = d.lookup("example.org",3)
157
176
  assert_not_nil(rows)
158
177
  assert_not_nil(rows.to_s)
159
178
  assert_not_nil(rows.to_xml)
160
179
  assert_not_nil(rows.to_json)
161
180
  assert_not_nil(rows.to_yaml)
162
181
  assert_equal(3, rows.length)
163
- rows = PassiveDNS::CN360.new.lookup("8.8.8.8")
182
+ rows = d.lookup("8.8.8.8")
164
183
  assert_not_nil(rows)
165
184
  assert_not_nil(rows.to_s)
166
185
  assert_not_nil(rows.to_xml)
167
186
  assert_not_nil(rows.to_json)
168
187
  assert_not_nil(rows.to_yaml)
169
- end
188
+ end
189
+
190
+ def test_nmemonic
191
+ assert_nothing_raised do
192
+ PassiveDNS::Client.new(['mnemonic'])
193
+ end
194
+ d = PassiveDNS::Mnemonic.new(@cp['mnemonic'] || {})
195
+ assert_not_nil(d)
196
+ rows = d.lookup("example.org")
197
+ assert_not_nil(rows)
198
+ assert_not_nil(rows.to_s)
199
+ assert_not_nil(rows.to_xml)
200
+ assert_not_nil(rows.to_json)
201
+ assert_not_nil(rows.to_yaml)
202
+ rows = d.lookup("example.org",3)
203
+ assert_not_nil(rows)
204
+ assert_not_nil(rows.to_s)
205
+ assert_not_nil(rows.to_xml)
206
+ assert_not_nil(rows.to_json)
207
+ assert_not_nil(rows.to_yaml)
208
+ assert_equal(3, rows.length)
209
+ rows = d.lookup("8.8.8.8")
210
+ assert_not_nil(rows)
211
+ assert_not_nil(rows.to_s)
212
+ assert_not_nil(rows.to_xml)
213
+ assert_not_nil(rows.to_json)
214
+ assert_not_nil(rows.to_yaml)
215
+ end
170
216
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: passivedns-client
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.4.1
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - chrislee35
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-09-28 00:00:00.000000000 Z
11
+ date: 2014-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -115,6 +115,8 @@ files:
115
115
  - lib/passivedns/client/certee.rb
116
116
  - lib/passivedns/client/cn360.rb
117
117
  - lib/passivedns/client/dnsdb.rb
118
+ - lib/passivedns/client/mnemonic.rb
119
+ - lib/passivedns/client/passivedb.rb
118
120
  - lib/passivedns/client/state.rb
119
121
  - lib/passivedns/client/tcpiputils.rb
120
122
  - lib/passivedns/client/version.rb