wmap 2.4.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (141) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +141 -0
  3. data/LICENSE.txt +15 -0
  4. data/README.rdoc +98 -0
  5. data/TODO +13 -0
  6. data/bin/deprime +21 -0
  7. data/bin/distrust +38 -0
  8. data/bin/googleBot +23 -0
  9. data/bin/prime +21 -0
  10. data/bin/refresh +26 -0
  11. data/bin/run_tests +16 -0
  12. data/bin/spiderBot +26 -0
  13. data/bin/trust +38 -0
  14. data/bin/updateAll +57 -0
  15. data/bin/wadd +25 -0
  16. data/bin/wadds +26 -0
  17. data/bin/wcheck +28 -0
  18. data/bin/wdel +25 -0
  19. data/bin/wdump +21 -0
  20. data/bin/wmap +151 -0
  21. data/bin/wscan +32 -0
  22. data/data/cidrs +2 -0
  23. data/data/deactivated_sites +1 -0
  24. data/data/domains +2 -0
  25. data/data/hosts +1 -0
  26. data/data/prime_hosts +1 -0
  27. data/data/sites +2 -0
  28. data/data/sub_domains +2 -0
  29. data/demos/bruter.rb +27 -0
  30. data/demos/dns_brutes.rb +28 -0
  31. data/demos/filter_cidr.rb +18 -0
  32. data/demos/filter_crawls.rb +5 -0
  33. data/demos/filter_domain.rb +25 -0
  34. data/demos/filter_geoip.rb +26 -0
  35. data/demos/filter_known_services.rb +59 -0
  36. data/demos/filter_netinfo.rb +23 -0
  37. data/demos/filter_prime.rb +25 -0
  38. data/demos/filter_profiler.rb +3 -0
  39. data/demos/filter_redirection.rb +19 -0
  40. data/demos/filter_site.rb +40 -0
  41. data/demos/filter_siteip.rb +31 -0
  42. data/demos/filter_status.rb +17 -0
  43. data/demos/filter_timestamp.rb +23 -0
  44. data/demos/filter_url.rb +19 -0
  45. data/demos/new_fnd.rb +66 -0
  46. data/demos/nmap_parser.pl +138 -0
  47. data/demos/site_format.rb +18 -0
  48. data/demos/whois_domain.rb +78 -0
  49. data/dicts/GeoIP.dat +0 -0
  50. data/dicts/GeoIPASNum.dat +0 -0
  51. data/dicts/GeoLiteCity.dat +0 -0
  52. data/dicts/ccsld.txt +2646 -0
  53. data/dicts/cctld.txt +243 -0
  54. data/dicts/gtld.txt +25 -0
  55. data/dicts/hostnames-dict.big +1402 -0
  56. data/dicts/hostnames-dict.txt +101 -0
  57. data/lib/wmap/cidr_tracker.rb +327 -0
  58. data/lib/wmap/dns_bruter.rb +308 -0
  59. data/lib/wmap/domain_tracker/sub_domain.rb +142 -0
  60. data/lib/wmap/domain_tracker.rb +342 -0
  61. data/lib/wmap/geoip_tracker.rb +72 -0
  62. data/lib/wmap/google_search_scraper.rb +177 -0
  63. data/lib/wmap/host_tracker/primary_host.rb +130 -0
  64. data/lib/wmap/host_tracker.rb +550 -0
  65. data/lib/wmap/network_profiler.rb +144 -0
  66. data/lib/wmap/port_scanner.rb +208 -0
  67. data/lib/wmap/site_tracker/deactivated_site.rb +85 -0
  68. data/lib/wmap/site_tracker.rb +937 -0
  69. data/lib/wmap/url_checker.rb +314 -0
  70. data/lib/wmap/url_crawler.rb +381 -0
  71. data/lib/wmap/utils/domain_root.rb +184 -0
  72. data/lib/wmap/utils/logger.rb +53 -0
  73. data/lib/wmap/utils/url_magic.rb +343 -0
  74. data/lib/wmap/utils/utils.rb +333 -0
  75. data/lib/wmap/whois.rb +76 -0
  76. data/lib/wmap.rb +227 -0
  77. data/logs/wmap.log +17 -0
  78. data/ruby_whois_patches/base_cocca2.rb +149 -0
  79. data/ruby_whois_patches/kero.yachay.pe.rb +120 -0
  80. data/ruby_whois_patches/whois.PublicDomainRegistry.com.rb +124 -0
  81. data/ruby_whois_patches/whois.above.com.rb +61 -0
  82. data/ruby_whois_patches/whois.adamsnames.tc.rb +107 -0
  83. data/ruby_whois_patches/whois.aeda.net.ae.rb +105 -0
  84. data/ruby_whois_patches/whois.ai.rb +112 -0
  85. data/ruby_whois_patches/whois.arnes.si.rb +121 -0
  86. data/ruby_whois_patches/whois.ascio.com.rb +91 -0
  87. data/ruby_whois_patches/whois.cnnic.cn.rb +123 -0
  88. data/ruby_whois_patches/whois.corporatedomains.com.rb +67 -0
  89. data/ruby_whois_patches/whois.crsnic.net.rb +108 -0
  90. data/ruby_whois_patches/whois.denic.de.rb +174 -0
  91. data/ruby_whois_patches/whois.dk-hostmaster.dk.rb +120 -0
  92. data/ruby_whois_patches/whois.dns.be.rb +134 -0
  93. data/ruby_whois_patches/whois.dns.lu.rb +129 -0
  94. data/ruby_whois_patches/whois.dns.pl.rb +150 -0
  95. data/ruby_whois_patches/whois.dns.pt.rb +119 -0
  96. data/ruby_whois_patches/whois.domain.kg.rb +126 -0
  97. data/ruby_whois_patches/whois.domainregistry.my.rb +123 -0
  98. data/ruby_whois_patches/whois.domreg.lt.rb +110 -0
  99. data/ruby_whois_patches/whois.dot.tk.rb +140 -0
  100. data/ruby_whois_patches/whois.hkirc.hk.rb +121 -0
  101. data/ruby_whois_patches/whois.isnic.is.rb +130 -0
  102. data/ruby_whois_patches/whois.je.rb +119 -0
  103. data/ruby_whois_patches/whois.jprs.jp.rb +137 -0
  104. data/ruby_whois_patches/whois.kenic.or.ke.rb +140 -0
  105. data/ruby_whois_patches/whois.markmonitor.com.rb +118 -0
  106. data/ruby_whois_patches/whois.melbourneit.com.rb +58 -0
  107. data/ruby_whois_patches/whois.nic.as.rb +96 -0
  108. data/ruby_whois_patches/whois.nic.at.rb +109 -0
  109. data/ruby_whois_patches/whois.nic.ch.rb +141 -0
  110. data/ruby_whois_patches/whois.nic.cl.rb +117 -0
  111. data/ruby_whois_patches/whois.nic.ec.rb +157 -0
  112. data/ruby_whois_patches/whois.nic.im.rb +120 -0
  113. data/ruby_whois_patches/whois.nic.it.rb +170 -0
  114. data/ruby_whois_patches/whois.nic.lv.rb +116 -0
  115. data/ruby_whois_patches/whois.nic.ly.rb +127 -0
  116. data/ruby_whois_patches/whois.nic.mu.rb +27 -0
  117. data/ruby_whois_patches/whois.nic.mx.rb +123 -0
  118. data/ruby_whois_patches/whois.nic.net.sa.rb +111 -0
  119. data/ruby_whois_patches/whois.nic.or.kr.rb +101 -0
  120. data/ruby_whois_patches/whois.nic.tel.rb +129 -0
  121. data/ruby_whois_patches/whois.nic.tr.rb +133 -0
  122. data/ruby_whois_patches/whois.nic.us.rb +129 -0
  123. data/ruby_whois_patches/whois.nic.ve.rb +135 -0
  124. data/ruby_whois_patches/whois.norid.no.rb +127 -0
  125. data/ruby_whois_patches/whois.pandi.or.id.rb +118 -0
  126. data/ruby_whois_patches/whois.psi-usa.info.rb +63 -0
  127. data/ruby_whois_patches/whois.registro.br.rb +109 -0
  128. data/ruby_whois_patches/whois.registrygate.com.rb +55 -0
  129. data/ruby_whois_patches/whois.rrpproxy.net.rb +61 -0
  130. data/ruby_whois_patches/whois.sgnic.sg.rb +130 -0
  131. data/ruby_whois_patches/whois.srs.net.nz.rb +166 -0
  132. data/ruby_whois_patches/whois.tucows.com.rb +70 -0
  133. data/ruby_whois_patches/whois.twnic.net.tw.rb +133 -0
  134. data/settings/discovery_ports +24 -0
  135. data/settings/google_keywords.txt +9 -0
  136. data/settings/google_locator.txt +23 -0
  137. data/test/domain_tracker_test.rb +31 -0
  138. data/test/utils_test.rb +168 -0
  139. data/version.txt +13 -0
  140. data/wmap.gemspec +49 -0
  141. metadata +202 -0
@@ -0,0 +1,308 @@
1
+ #--
2
+ # Wmap
3
+ #
4
+ # A pure Ruby library for the Internet web application discovery and tracking.
5
+ #
6
+ # Copyright (c) 2012-2015 Yang Li <yang.li@owasp.org>
7
+ #++
8
+ require "dnsruby"
9
+ require "parallel"
10
+
11
+
12
+ # Class to discover valid hosts through either zone transfer or DNS brute-force methods
13
+ class Wmap::DnsBruter
14
+ include Wmap::Utils
15
+
16
+ attr_accessor :hosts_dict, :verbose, :max_parallel, :data_dir
17
+ attr_reader :discovered_hosts_from_dns_bruter, :fail_domain_cnt
18
+
19
+ # Set default instance variables
20
+ def initialize (params = {})
21
+ # Change to your brute-force dictionary file here if necessary
22
+ @data_dir=params.fetch(:data_dir, File.dirname(__FILE__)+'/../../data/')
23
+ @file_hosts = @data_dir + 'hosts'
24
+ @file_hosts_dict = File.dirname(__FILE__)+'/../../dicts/hostnames-dict.txt'
25
+
26
+ @verbose=params.fetch(:verbose, false)
27
+ @discovered_hosts_from_dns_bruter=Hash.new
28
+ @hosts_dict=params.fetch(:hosts_dict, @file_hosts_dict)
29
+ @max_parallel=params.fetch(:max_parallel, 30)
30
+ @fail_domain_cnt=Hash.new
31
+ end
32
+
33
+ # Main worker to perform the brute-forcing on an Internet domain
34
+ def dns_brute_worker(host)
35
+ puts "Start DNS brute forcer on: #{host}"
36
+ results=Hash.new
37
+ domain=get_domain_root(host)
38
+ begin
39
+ host=host.strip.downcase
40
+ raise "Invalid internet host format: #{host}" unless is_fqdn?(host)
41
+ domain=get_domain_root(host)
42
+ # If we can do the zone transfer, then the brute-force process can be skipped.
43
+ if zone_transferable?(domain)
44
+ hosts=zone_transfer(domain)
45
+ else
46
+ hosts=brute_force_dns(host)
47
+ end
48
+ results[domain]=hosts
49
+ puts "Finish discovery on #{host}: #{results}"
50
+ return results
51
+ rescue Exception=>ee
52
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
53
+ return results
54
+ end
55
+ end
56
+ alias_method :query, :dns_brute_worker
57
+ alias_method :brute, :dns_brute_worker
58
+
59
+ # Parallel DNS brute-forcer operating on target domain list - by utilizing fork manager to spawn multiple child processes on multiple domains simultaneously
60
+ def dns_brute_workers(list,num=@max_parallel)
61
+ puts "Start the parallel engine one the domain list: #{list} \nMaximum brute-forcing session: #{num} "
62
+ begin
63
+ targets=list.uniq.keep_if { |x| is_fqdn?(x) }
64
+ results=Hash.new
65
+ Parallel.map(targets, :in_processes => num) { |target|
66
+ dns_brute_worker(target)
67
+ }.each do |process|
68
+ if process.nil?
69
+ next
70
+ elsif process.empty?
71
+ #do nothing in case of thrown an empty array
72
+ else
73
+ #domain=get_domain_root(process.first).downcase
74
+ results.merge!(process)
75
+ end
76
+ end
77
+ puts "Parallel DNS brute-force results: #{results}" if @verbose
78
+ @discovered_hosts_from_dns_bruter.merge!(results)
79
+ return results
80
+ rescue Exception => ee
81
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
82
+ end
83
+ end
84
+ alias_method :queries, :dns_brute_workers
85
+ alias_method :brutes, :dns_brute_workers
86
+
87
+ # Parallel DNS brute-forcer operating on target domain file - by utilizing fork manager to spawn multiple child processes on multiple domains simultaneously
88
+ def dns_brute_file(file_target,num=@max_parallel)
89
+ puts "Start the parallel brute-forcing with multiple child processes on target file #{file_target}: #{num}"
90
+ begin
91
+ hosts=Array.new
92
+ targets=file_2_list(file_target)
93
+ hosts=dns_brute_workers(targets,num)
94
+ return hosts
95
+ rescue Exception => ee
96
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
97
+ return hosts
98
+ end
99
+ end
100
+
101
+ # Perform zone transfer on a domain, return found host entries in an array
102
+ def zone_transfer(domain)
103
+ puts "Perform zone transfer on zone: #{domain}"
104
+ domain=domain.downcase
105
+ nameservers = get_nameservers(domain)
106
+ hosts=Array.new
107
+ puts "Retrieved name servers: #{nameservers}" if @verbose
108
+ nameservers.each do |nssrv|
109
+ begin
110
+ puts "Attempt zone transfer on name server: #{nssrv}"
111
+ if nssrv.nil?
112
+ abort "Method input variable error: no name server found!" if @verbose
113
+ next
114
+ end
115
+ zt = Dnsruby::ZoneTransfer.new
116
+ zt.server=nssrv unless nssrv.empty?
117
+ records = zt.transfer(domain)
118
+ if records==nil
119
+ puts "Zone transfer failed for zone #{domain} on: #{nssrv}"
120
+ next
121
+ else
122
+ puts "Zone transfer successfully for zone #{domain} on the name server: #{nssrv}"
123
+ records = records.delete_if {|x| not x.to_s=~/(\s+|\t+)IN/ }
124
+ records.each { |line| puts line.to_s } if @verbose
125
+ hosts=records.collect {|x| x.to_s.split(/\.(\s+|\t+)/).first}
126
+ hosts=hosts.sort!.uniq!
127
+ puts "Found hosts: #{hosts}" if @verbose
128
+ @discovered_hosts_from_dns_bruter[domain] = hosts
129
+ return hosts
130
+ end
131
+ rescue Exception=>ee
132
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
133
+ end
134
+ end
135
+ return hosts
136
+ end
137
+
138
+ # Test the DNS server if zone transfer is allowed. If allowed, save the found hosts into the class variable.
139
+ def get_vulnerable_ns(domain)
140
+ puts "Identify the vulnerable DNS servers if zone transfer is allowed."
141
+ domain=domain.strip.downcase
142
+ vuln=Array.new
143
+ begin
144
+ nameservers = get_nameservers(domain)
145
+ nameservers.each do |nssrv|
146
+ zt = Dnsruby::ZoneTransfer.new
147
+ zt.server=nssrv unless nssrv.empty?
148
+ records = zt.transfer(domain)
149
+ unless records==nil
150
+ vuln.push(nssrv)
151
+ end
152
+ end
153
+ return vuln
154
+ rescue Exception=>ee
155
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
156
+ end
157
+ end
158
+
159
+ # Return a list of valid hosts by brute-forcing the name servers
160
+ def brute_force_dns (host)
161
+ puts "Start dictionary attacks on the DNS server for: #{host}" if @verbose
162
+ begin
163
+ host=host.strip
164
+ valid_hosts = Array.new
165
+ my_host_tracker = Wmap::HostTracker.new(:data_dir=>@data_dir)
166
+ # build the host dictionary for the brute force method
167
+ dict = Array.new
168
+ if File.exists?(@hosts_dict)
169
+ dict = file_2_list(@hosts_dict)
170
+ elsif File.exists?(@file_hosts)
171
+ dict = my_host_tracker.top_hostname(200)
172
+ my_host_tracker.list_2_file(dict,@hosts_dict)
173
+ else
174
+ abort "Error: Non-existing common hosts dictionary file - #{@host_dict} or hosts file #{@file_hosts}. Please check your file path and name setting again."
175
+ end
176
+ domain=String.new
177
+ unless is_root_domain?(host) or my_host_tracker.sub_domain_known?(host)
178
+ my_hosts=hostname_mutation(host).map {|x| x.split('.')[0]}
179
+ dict+=my_hosts unless my_hosts.empty?
180
+ end
181
+ if is_domain?(host) or my_host_tracker.sub_domain_known?(host)
182
+ domain=host
183
+ elsif
184
+ array_h=host.split('.')
185
+ array_h.shift
186
+ domain=array_h.join('.')
187
+ puts "Domain for #{host}: #{domain}" if @verbose
188
+ end
189
+ dict+=[host.split(".")[0],""]
190
+ puts "Choose Brute-force Dictionary: #{dict}" if @verbose
191
+ cnt=0
192
+ dict.each do |x|
193
+ # 10/09/2013 add logic to skip brute-forcing the domain in case of experiencing more than 2 Dnsruby::ServFail conditions
194
+ if @fail_domain_cnt.key?(domain)
195
+ if @fail_domain_cnt[domain]>2
196
+ puts "Error! Multiple ServFail conditions detected in method #{__method__}. Now skip remaining works on: #{sub_domain}" if @verbose
197
+ return valid_hosts
198
+ end
199
+ end
200
+ cnt=cnt+1
201
+ if x.nil?
202
+ next
203
+ elsif x.empty?
204
+ host=domain
205
+ else
206
+ host=[x,".",domain].join.downcase
207
+ end
208
+ valid_hosts.push(host) if valid_dns_record?(host)
209
+ # Logic to detecting the bluff if the DNS server return hostname we threw to it
210
+ if cnt==10 && valid_hosts.size>=10
211
+ valid_hosts=[host]
212
+ puts "Brute force method fail, as the DNS server response to every host-name threw at it!"
213
+ break
214
+ end
215
+ end
216
+ puts "Found DNS records on domain #{host}: #{valid_hosts}" if @verbose
217
+ @discovered_hosts_from_dns_bruter[host] = valid_hosts
218
+ my_host_tracker = nil
219
+ return valid_hosts.uniq
220
+ rescue Exception => ee
221
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
222
+ end
223
+ end
224
+
225
+ # Parallel DNS brute-forcer operating on the trusted domains - by utilizing fork manager to spawn multiple child processes on multiple sub_domain domains from the local hosts table simultaneously
226
+ def dns_brute_domains(targets,num=@max_parallel)
227
+ puts "Start the parallel brute-forcing with multiple child processes: #{num}"
228
+ begin
229
+ hosts=Array.new
230
+ # Sliced to chunks of 1,000 domains for each process time, to avoid potential overflow of large array ?
231
+ puts "Brute-forcing the following domain: #{targets}" if @verbose
232
+ targets.each_slice(1000).to_a.map do |slice|
233
+ hosts_new=dns_brute_workers(slice,num)
234
+ hosts << hosts_new
235
+ end
236
+ puts "Parallel bruting result: #{hosts.flatten}" if @verbose
237
+ return hosts.flatten
238
+ rescue Exception => ee
239
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
240
+ return hosts.flatten
241
+ end
242
+ end
243
+
244
+ # Parallel DNS brute-force all existing domains
245
+ def brute_all(num=@max_parallel)
246
+ puts "Start the parallel brute-forcing all domains with maximum child processes: #{num}"
247
+ begin
248
+ hosts=Array.new
249
+ my_dis=Wmap::HostTracker.new(:data_dir=>@data_dir)
250
+ known_domains=my_dis.dump_root_domains
251
+ hosts=dns_brute_domains(num, known_domains)
252
+ my_dis.adds(hosts)
253
+ my_dis.save!
254
+ my_dis=nil
255
+ hosts
256
+ rescue Exception => ee
257
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
258
+ end
259
+ end
260
+
261
+ # Return a list of hosts in the mutation form from the original, i.e. "ww1.example.com" => ["ww1,example.com","ww2.example.com",...]
262
+ def hostname_mutation(host)
263
+ puts "Start host mutation emulation on: #{host}" if @verbose
264
+ begin
265
+ hosts=Array.new
266
+ host=host.strip.downcase
267
+ raise "Invalid host format: #{host}" unless is_fqdn?(host)
268
+ unless is_domain_root?(host)
269
+ hostname=host.split('.')[0]
270
+ hosts.push(host)
271
+ case hostname
272
+ when /\d+/
273
+ #first form of mutation, i.e. "ww1" => ["ww1","ww2",...]
274
+ hostname.scan(/\d+/).map do |x|
275
+ y=x.to_i
276
+ 5.times do |i|
277
+ z=y+i+1
278
+ w=(y-i-1).abs
279
+ mut1=host.sub_domain(x,z.to_s)
280
+ mut2=host.sub_domain(x,w.to_s)
281
+ hosts.push(mut1,mut2)
282
+ end
283
+ end
284
+ else
285
+ puts "No mutation found for: #{host}" if @verbose
286
+ end
287
+ end
288
+ puts "Host mutation found: #{hosts.uniq}" if @verbose
289
+ return hosts.uniq
290
+ rescue Exception => ee
291
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
292
+ return hosts # fail-safe
293
+ end
294
+ end
295
+ alias_method :mutation, :hostname_mutation
296
+
297
+ # Print summary report of found hosts from the brute force attacks
298
+ def print_discovered_hosts_from_bruter
299
+ puts "\nSummary Report of the Discovered Hosts:"
300
+ @discovered_hosts_from_dns_bruter.each do |domain,hosts|
301
+ puts "Domain: #{domain}"
302
+ puts "Found hosts:"
303
+ puts @discovered_hosts_from_dns_bruter[domain]['hosts']
304
+ end
305
+ puts "End of the summary"
306
+ end
307
+ alias_method :print, :print_discovered_hosts_from_bruter
308
+ end
@@ -0,0 +1,142 @@
1
+ #--
2
+ # Wmap
3
+ #
4
+ # A pure Ruby library for Internet web application discovery and tracking.
5
+ #
6
+ # Copyright (c) 2012-2015 Yang Li <yang.li@owasp.org>
7
+ #++
8
+ #require "singleton"
9
+
10
+
11
+ module Wmap
12
+ class DomainTracker
13
+
14
+ # Class to differentiate the sub-domain from the top domain for the enterprise. This is needed for better managing
15
+ # of the sub-domains and the associated entities
16
+ class SubDomain < Wmap::DomainTracker
17
+ include Wmap::Utils
18
+ #include Singleton
19
+
20
+ attr_accessor :verbose, :domains_file, :max_parallel, :data_dir
21
+ attr_reader :known_internet_sub_domains
22
+
23
+ # Set default instance variables
24
+ def initialize (params = {})
25
+ @verbose=params.fetch(:verbose, false)
26
+ @data_dir=params.fetch(:data_dir, File.dirname(__FILE__)+'/../../../data/')
27
+ @max_parallel=params.fetch(:max_parallel, 40)
28
+ # Hash table to hold the trusted domains
29
+ @file_sub_domains=@data_dir + 'sub_domains'
30
+ File.write(@file_sub_domains, "") unless File.exist?(@file_sub_domains)
31
+ @known_internet_sub_domains=load_domains_from_file(@file_sub_domains) #unless @known_internet_sub_domains.size>0
32
+ end
33
+
34
+ # 'setter' to add sub-domain entry to the cache one at a time
35
+ def add(sub)
36
+ puts "Add entry to the local sub domain cache table: #{sub}" if @verbose
37
+ begin
38
+ record=Hash.new
39
+ sub=sub.strip.downcase
40
+ if @known_internet_sub_domains.key?(sub)
41
+ puts "Skip on known sub-domain: #{sub}" if @verbose
42
+ return nil
43
+ end
44
+ if zone_transferable?(sub)
45
+ record[sub]=true
46
+ else
47
+ record[sub]=false
48
+ end
49
+ puts "Adding new record into the data store: #{record}" if @verbose
50
+ @known_internet_sub_domains.merge!(record)
51
+ return record
52
+ rescue => ee
53
+ puts "Exception on method #{__method__} for #{sub}: #{ee}" if @verbose
54
+ end
55
+ end
56
+
57
+ # 'setter' to add domain entry to the cache in batch (from a list)
58
+ def bulk_add(list, num=@max_parallel)
59
+ puts "Add entries to the local domains cache table from list: #{list}" if @verbose
60
+ begin
61
+ results=Hash.new
62
+ domains=list
63
+ if domains.size > 0
64
+ Parallel.map(list, :in_processes => num) { |target|
65
+ add(target)
66
+ }.each do |process|
67
+ if process.nil?
68
+ next
69
+ elsif process.empty?
70
+ #do nothing
71
+ else
72
+ results.merge!(process)
73
+ end
74
+ end
75
+ @known_internet_sub_domains.merge!(results)
76
+ puts "Done loading entries."
77
+ return results
78
+ else
79
+ puts "Error: no entry is loaded. Please check your list and try again."
80
+ end
81
+ return results
82
+ rescue => ee
83
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
84
+ end
85
+ end
86
+ alias_method :adds, :bulk_add
87
+
88
+ # Procedures to identify sub-domain from the hosts store
89
+ def update_from_host_store!
90
+ puts "Invoke internal procedures to update the sub-domain list from the host store."
91
+ begin
92
+ # Step 1 - obtain the latest sub-domains
93
+ subs = Wmap::HostTracker.new(:data_dir=>@data_dir).dump_sub_domains - [nil,""]
94
+ # Step 2 - update the sub-domain list
95
+ unless subs.empty?
96
+ #subs.map { |x| self.add(x) unless domain_known?(x) }
97
+ self.bulk_add(subs,@max_parallel)
98
+ end
99
+ puts "Update discovered sub-domains into the store: #{@known_internet_sub_domains}"
100
+ self.save!(file_domains=@file_sub_domains, domains=@known_internet_sub_domains)
101
+ rescue Exception => ee
102
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
103
+ return nil
104
+ end
105
+ end
106
+ alias_method :update!, :update_from_host_store!
107
+
108
+ # Save the current domain hash table into a file
109
+ def save_sub_domains_to_file!(file_domains=@file_sub_domains, domains=@known_internet_sub_domains)
110
+ puts "Saving the current domains cache table from memory to file: #{file_domains} ..." if @verbose
111
+ begin
112
+ timestamp=Time.now
113
+ f=File.open(file_domains, 'w')
114
+ f.write "# Local domains file created by class #{self.class} method #{__method__} at: #{timestamp}\n"
115
+ f.write "# domain name, free zone transfer detected?\n"
116
+ domains.keys.sort.map do |key|
117
+ if domains[key]
118
+ f.write "#{key}, yes\n"
119
+ else
120
+ f.write "#{key}, no\n"
121
+ end
122
+ end
123
+ f.close
124
+ puts "Domain cache table is successfully saved: #{file_domains}"
125
+ rescue => ee
126
+ puts "Exception on method #{__method__}: #{ee}" if @verbose
127
+ end
128
+ end
129
+ alias_method :save!, :save_sub_domains_to_file!
130
+ end
131
+
132
+ # Print summary report on all known / trust domains in the domain cache table
133
+ def print_known_sub_domains
134
+ puts "\nSummary of known Internet Sub-domains:"
135
+ self.known_internet_sub_domains.keys.sort.each do |domain|
136
+ puts domain
137
+ end
138
+ puts "End of the summary"
139
+ end
140
+
141
+ end
142
+ end