dnsruby 1.58.0 → 1.59.0
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.
- checksums.yaml +4 -4
- data/LICENSE +11 -0
- data/RELEASE_NOTES.md +15 -0
- data/Rakefile +2 -1
- data/demo/axfr.rb +84 -85
- data/demo/check_soa.rb +115 -94
- data/demo/check_zone.rb +69 -64
- data/demo/digdlv.rb +22 -24
- data/demo/digroot.rb +23 -19
- data/demo/example_recurse.rb +20 -6
- data/demo/mresolv.rb +26 -14
- data/demo/mx.rb +21 -11
- data/demo/rubydig.rb +34 -25
- data/demo/trace_dns.rb +22 -16
- data/lib/dnsruby/cache.rb +8 -0
- data/lib/dnsruby/config.rb +1 -1
- data/lib/dnsruby/dnssec.rb +6 -2
- data/lib/dnsruby/message/decoder.rb +1 -0
- data/lib/dnsruby/message/question.rb +1 -1
- data/lib/dnsruby/packet_sender.rb +4 -0
- data/lib/dnsruby/recursor.rb +9 -1
- data/lib/dnsruby/resource/OPT.rb +2 -2
- data/lib/dnsruby/resource/RR.rb +4 -4
- data/lib/dnsruby/select_thread.rb +2 -2
- data/lib/dnsruby/single_verifier.rb +24 -4
- data/lib/dnsruby/update.rb +1 -1
- data/lib/dnsruby/validator_thread.rb +2 -1
- data/lib/dnsruby/version.rb +1 -1
- data/test/tc_axfr.rb +1 -1
- data/test/tc_cache.rb +45 -9
- data/test/tc_dns.rb +64 -50
- data/test/tc_message.rb +17 -1
- data/test/tc_res_config.rb +3 -2
- data/test/tc_resolv.rb +1 -1
- data/test/tc_single_resolver.rb +148 -132
- data/test/ts_online.rb +7 -0
- metadata +3 -2
data/demo/mx.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright 2007 Nominet UK
|
3
5
|
#
|
@@ -34,16 +36,24 @@ require 'dnsruby'
|
|
34
36
|
# (Ruby port AlexD, Nominet UK)
|
35
37
|
#
|
36
38
|
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
39
|
+
def fatal_error(message)
|
40
|
+
puts message
|
41
|
+
exit -1
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
unless ARGV.length == 1
|
46
|
+
fatal_error("Usage: #{$0} name")
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
domain = ARGV[0]
|
51
|
+
resolver = Dnsruby::DNS.new
|
52
|
+
|
53
|
+
begin
|
54
|
+
resolver.each_resource(domain, 'MX') do |rr|
|
55
|
+
print rr.preference, "\t", rr.exchange, "\n"
|
46
56
|
end
|
47
|
-
|
48
|
-
|
57
|
+
rescue Exception => e
|
58
|
+
fatal_error("Can't find MX hosts for #{domain}: #{e}")
|
49
59
|
end
|
data/demo/rubydig.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright 2007 Nominet UK
|
3
5
|
#
|
@@ -33,49 +35,56 @@
|
|
33
35
|
# Michael Fuhr <mike@fuhr.org>
|
34
36
|
#
|
35
37
|
|
38
|
+
def fatal_error(message)
|
39
|
+
puts message
|
40
|
+
exit(-1)
|
41
|
+
end
|
42
|
+
|
43
|
+
|
44
|
+
unless (1..3).include?(ARGV.length)
|
45
|
+
fatal_error("Usage: #{$0} [ @nameserver ] name [ type [ class ] ]")
|
46
|
+
end
|
47
|
+
|
48
|
+
|
36
49
|
require 'dnsruby'
|
37
|
-
include Dnsruby
|
38
50
|
|
39
|
-
res = Dnsruby::Resolver.new
|
40
|
-
zt=Dnsruby::ZoneTransfer.new
|
41
51
|
|
42
|
-
|
52
|
+
resolver = Dnsruby::Resolver.new
|
53
|
+
zone_transfer = Dnsruby::ZoneTransfer.new
|
54
|
+
|
55
|
+
|
56
|
+
if ARGV[0] =~ /^@/
|
43
57
|
nameserver = ARGV.shift
|
44
|
-
if
|
45
|
-
|
58
|
+
if nameserver == '@auth'
|
59
|
+
resolver = Dnsruby::Recursor.new
|
46
60
|
else
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
61
|
+
puts "Setting nameserver : #{nameserver}"
|
62
|
+
resolver.nameserver = (nameserver.sub(/^@/, ''))
|
63
|
+
puts "nameservers = #{resolver.config.nameserver}"
|
64
|
+
zone_transfer.server = (nameserver.sub(/^@/, ''))
|
51
65
|
end
|
52
66
|
end
|
53
67
|
|
54
|
-
raise RuntimeError, "Usage: #{$0} [ \@nameserver ] name [ type [ class ] ]\n" unless (ARGV.length >= 1) && (ARGV.length <= 3)
|
55
|
-
|
56
68
|
name, type, klass = ARGV
|
57
|
-
type ||=
|
58
|
-
klass ||=
|
69
|
+
type ||= 'A'
|
70
|
+
klass ||= 'IN'
|
59
71
|
|
60
|
-
if
|
61
|
-
rrs =
|
72
|
+
if type.upcase == 'AXFR'
|
73
|
+
rrs = zone_transfer.transfer(name) # , klass)
|
62
74
|
|
63
|
-
if
|
64
|
-
rrs.each
|
65
|
-
print rr.to_s + "\n"
|
66
|
-
end
|
75
|
+
if rrs
|
76
|
+
rrs.each { |rr| puts rr }
|
67
77
|
else
|
68
|
-
|
78
|
+
fatal_error("Zone transfer failed: #{resolver.errorstring}")
|
69
79
|
end
|
70
80
|
|
71
81
|
else
|
72
82
|
|
73
83
|
# Dnsruby::TheLog.level=Logger::DEBUG
|
74
84
|
begin
|
75
|
-
answer =
|
76
|
-
answer
|
77
|
-
print answer
|
85
|
+
answer = resolver.query(name, type, klass)
|
86
|
+
puts answer
|
78
87
|
rescue Exception => e
|
79
|
-
|
88
|
+
fatal_error("Query failed: #{e}")
|
80
89
|
end
|
81
90
|
end
|
data/demo/trace_dns.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
#! /usr/bin/env ruby
|
2
|
+
|
1
3
|
# --
|
2
4
|
# Copyright 2007 Nominet UK
|
3
5
|
#
|
@@ -15,32 +17,36 @@
|
|
15
17
|
# ++
|
16
18
|
|
17
19
|
require 'dnsruby'
|
18
|
-
include Dnsruby
|
19
20
|
|
20
21
|
# e.g. ruby trace_dns.rb example.com
|
21
22
|
|
23
|
+
unless (1..2).include?(ARGV.length)
|
24
|
+
puts "Usage: #{$0} domain [type]"
|
25
|
+
exit(-1)
|
26
|
+
end
|
27
|
+
|
28
|
+
|
22
29
|
# Load DLV key
|
23
|
-
dlv_key = RR.create("dlv.isc.org. IN DNSKEY 257 3 5 BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2 brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+ 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5 ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt TDN0YUuWrBNh")
|
24
|
-
Dnssec.add_dlv_key(dlv_key)
|
30
|
+
dlv_key = Dnsruby::RR.create("dlv.isc.org. IN DNSKEY 257 3 5 BEAAAAPHMu/5onzrEE7z1egmhg/WPO0+juoZrW3euWEn4MxDCE1+lLy2 brhQv5rN32RKtMzX6Mj70jdzeND4XknW58dnJNPCxn8+jAGl2FZLK8t+ 1uq4W+nnA3qO2+DL+k6BD4mewMLbIYFwe0PG73Te9fZ2kJb56dhgMde5 ymX4BI/oQ+cAK50/xvJv00Frf8kw6ucMTwFlgPe+jnGxPPEmHAte/URk Y62ZfkLoBAADLHQ9IrS2tryAe7mbBZVcOwIeU/Rw/mRx/vwwMCTgNboM QKtUdvNXDrYJDSHZws3xiRXF1Rf+al9UmZfSav/4NWLKjHzpT59k/VSt TDN0YUuWrBNh")
|
31
|
+
Dnsruby::Dnssec.add_dlv_key(dlv_key)
|
25
32
|
|
26
|
-
|
33
|
+
resolver = Dnsruby::Recursor.new
|
27
34
|
# TheLog.level = Logger::DEBUG
|
28
35
|
|
29
36
|
|
30
|
-
|
37
|
+
resolver.recursion_callback = Proc.new do |packet|
|
38
|
+
packet.additional.each { |a| puts a }
|
39
|
+
puts(";; Received #{packet.answersize} bytes from #{packet.answerfrom}. Security Level = #{packet.security_level.string}\n")
|
40
|
+
puts "\n#{'-' * 79}\n"
|
41
|
+
end
|
31
42
|
|
32
|
-
packet.additional.each { |a| print a.to_s + "\n" }
|
33
43
|
|
34
|
-
|
35
|
-
|
44
|
+
domain = ARGV[0]
|
45
|
+
type = ARGV[1] || Types.A
|
36
46
|
|
37
|
-
type = ARGV[1]
|
38
|
-
if (type == nil)
|
39
|
-
type = Types.A
|
40
|
-
end
|
41
47
|
begin
|
42
|
-
|
43
|
-
|
44
|
-
rescue NXDomain
|
45
|
-
|
48
|
+
response = resolver.query(domain, type)
|
49
|
+
puts "\nRESPONSE : #{response}"
|
50
|
+
rescue Dnsruby::NXDomain
|
51
|
+
puts "Domain '#{domain}' doesn't exist"
|
46
52
|
end
|
data/lib/dnsruby/cache.rb
CHANGED
@@ -31,6 +31,7 @@ module Dnsruby
|
|
31
31
|
class Cache # :nodoc: all
|
32
32
|
def initialize()
|
33
33
|
@cache = Hash.new
|
34
|
+
@@max_size = 16*1024 # Get this right...
|
34
35
|
@mutex = Mutex.new
|
35
36
|
end
|
36
37
|
def cache
|
@@ -44,6 +45,9 @@ module Dnsruby
|
|
44
45
|
def length
|
45
46
|
return @cache.length
|
46
47
|
end
|
48
|
+
def Cache.max_size=(length)
|
49
|
+
@@max_size = length
|
50
|
+
end
|
47
51
|
def add(message)
|
48
52
|
q = message.question[0]
|
49
53
|
key = CacheKey.new(q.qname, q.qtype, q.qclass).to_s
|
@@ -55,6 +59,10 @@ module Dnsruby
|
|
55
59
|
TheLog.debug("CACHE ADD : #{q.qname}, #{q.qtype}\n")
|
56
60
|
end
|
57
61
|
@cache[key] = data
|
62
|
+
|
63
|
+
while @cache.size > @@max_size # keep the cache size reasonable
|
64
|
+
@cache.shift
|
65
|
+
end
|
58
66
|
}
|
59
67
|
end
|
60
68
|
# This method "fixes up" the response, so that the header and ttls are OK
|
data/lib/dnsruby/config.rb
CHANGED
@@ -290,7 +290,7 @@ module Dnsruby
|
|
290
290
|
end
|
291
291
|
rescue Exception => e
|
292
292
|
Dnsruby.log.error{"Can't make sense of nameserver : #{server}, exception : #{e}"}
|
293
|
-
|
293
|
+
raise ArgumentError.new("Can't make sense of nameserver : #{server}, exception : #{e}")
|
294
294
|
return nil
|
295
295
|
end
|
296
296
|
end
|
data/lib/dnsruby/dnssec.rb
CHANGED
@@ -66,7 +66,7 @@ module Dnsruby
|
|
66
66
|
@@validation_policy = ValidationPolicy::LOCAL_ANCHORS_THEN_ROOT
|
67
67
|
|
68
68
|
def Dnssec.validation_policy=(p)
|
69
|
-
if ((p >=
|
69
|
+
if ((p >= ValidationPolicy::ALWAYS_ROOT_ONLY) && (p <= ValidationPolicy::ALWAYS_LOCAL_ANCHORS_ONLY))
|
70
70
|
@@validation_policy = p
|
71
71
|
# @TODO@ Should we be clearing the trusted keys now?
|
72
72
|
end
|
@@ -203,6 +203,7 @@ module Dnsruby
|
|
203
203
|
end
|
204
204
|
rescue VerifyError => e
|
205
205
|
msg.security_error = e
|
206
|
+
msg.security_level = Message::SecurityLevel.BOGUS
|
206
207
|
end
|
207
208
|
end
|
208
209
|
|
@@ -240,13 +241,16 @@ module Dnsruby
|
|
240
241
|
Proc.new{|m, q| validate_with_anchors(m, q)}, msg, query)
|
241
242
|
end
|
242
243
|
end
|
243
|
-
if (last_level != Message::SecurityLevel.SECURE)
|
244
|
+
if (last_level != Message::SecurityLevel.SECURE && last_level != Message::SecurityLevel.BOGUS)
|
244
245
|
last_level, last_error, last_error_level = try_validation(last_level, last_error, last_error_level,
|
245
246
|
Proc.new{|m, q| validate_with_dlv(m, q)}, msg, query)
|
246
247
|
end
|
247
248
|
# Set the message security level!
|
248
249
|
msg.security_level = last_level
|
249
250
|
msg.security_error = last_error
|
251
|
+
if (last_error && last_error.index("ification error"))
|
252
|
+
msg.security_level = Message::SecurityLevel.BOGUS
|
253
|
+
end
|
250
254
|
raise VerifyError.new(last_error) if (last_level < 0)
|
251
255
|
return (msg.security_level.code > Message::SecurityLevel::UNCHECKED)
|
252
256
|
end
|
data/lib/dnsruby/recursor.rb
CHANGED
@@ -318,7 +318,11 @@ module Dnsruby
|
|
318
318
|
@@hints = Hash.new
|
319
319
|
@@hints[0] = temp
|
320
320
|
end
|
321
|
-
@@nameservers = @@hints.values
|
321
|
+
# @@nameservers = @@hints.values
|
322
|
+
@@nameservers=[]
|
323
|
+
@@hints.each {|key, value|
|
324
|
+
@@nameservers.push(key)
|
325
|
+
}
|
322
326
|
return @@nameservers
|
323
327
|
end
|
324
328
|
|
@@ -427,6 +431,10 @@ module Dnsruby
|
|
427
431
|
if (Name === n)
|
428
432
|
n = n.to_s # @TODO@ This is a bit crap!
|
429
433
|
end
|
434
|
+
if (n == nil)
|
435
|
+
TheLog.error("Name is nil")
|
436
|
+
raise ResolvError.new("Nameserver invalid!")
|
437
|
+
end
|
430
438
|
name = n.tr("","")
|
431
439
|
if (name[name.length-1] != ".")
|
432
440
|
name = name + "."
|
data/lib/dnsruby/resource/OPT.rb
CHANGED
@@ -142,7 +142,7 @@ module Dnsruby
|
|
142
142
|
end
|
143
143
|
|
144
144
|
def payloadsize=(size)
|
145
|
-
self.klass=size
|
145
|
+
self.klass=Classes.new(size)
|
146
146
|
end
|
147
147
|
|
148
148
|
def options(args)
|
@@ -242,7 +242,7 @@ module Dnsruby
|
|
242
242
|
@options.each do |opt|
|
243
243
|
msg.put_pack('n', opt.code)
|
244
244
|
msg.put_pack('n', opt.data.length)
|
245
|
-
msg.
|
245
|
+
msg.put_pack('a*', opt.data)
|
246
246
|
end
|
247
247
|
end
|
248
248
|
end
|
data/lib/dnsruby/resource/RR.rb
CHANGED
@@ -141,7 +141,7 @@ class RR
|
|
141
141
|
def RR.new_from_hash(inhash)
|
142
142
|
hash = inhash.clone
|
143
143
|
type = hash[:type] || Types::ANY
|
144
|
-
klass = hash[:klass] || Classes::IN
|
144
|
+
klass = Classes.new(hash[:klass] || Classes::IN)
|
145
145
|
ttl = hash[:ttl] || 0
|
146
146
|
record_class = get_class(type, klass)
|
147
147
|
record = record_class.new
|
@@ -151,7 +151,7 @@ class RR
|
|
151
151
|
end
|
152
152
|
record.ttl = ttl
|
153
153
|
record.type = type
|
154
|
-
record.klass = klass
|
154
|
+
record.klass = Classes.new(klass)
|
155
155
|
hash.delete(:name)
|
156
156
|
hash.delete(:type)
|
157
157
|
hash.delete(:ttl)
|
@@ -266,7 +266,7 @@ class RR
|
|
266
266
|
record.name = Name.create(name)
|
267
267
|
record.ttl = ttl
|
268
268
|
record.type = rrtype
|
269
|
-
record.klass = rrclass
|
269
|
+
record.klass = Classes.new(rrclass)
|
270
270
|
record
|
271
271
|
end
|
272
272
|
|
@@ -283,7 +283,7 @@ class RR
|
|
283
283
|
record.name = Name.create(name)
|
284
284
|
record.ttl = ttl
|
285
285
|
record.type = rrtype
|
286
|
-
record.klass = rrclass
|
286
|
+
record.klass = Classes.new(rrclass)
|
287
287
|
return record
|
288
288
|
end
|
289
289
|
end
|
@@ -712,8 +712,8 @@ module Dnsruby
|
|
712
712
|
# validate it only if it has not been validated already
|
713
713
|
# So, if we need to validate it, send it to the validation thread
|
714
714
|
# Otherwise, send VALIDATED to the requester.
|
715
|
-
if (((msg.security_level == Message::SecurityLevel
|
716
|
-
(msg.security_level == Message::SecurityLevel
|
715
|
+
if (((msg.security_level == Message::SecurityLevel.UNCHECKED) ||
|
716
|
+
(msg.security_level == Message::SecurityLevel.INDETERMINATE)) &&
|
717
717
|
(ValidatorThread.requires_validation?(query, msg, err, res)))
|
718
718
|
validator = ValidatorThread.new(client_id, client_queue, msg, err, query ,self, res)
|
719
719
|
validator.run
|
@@ -1044,7 +1044,9 @@ module Dnsruby
|
|
1044
1044
|
rescue VerifyError => e
|
1045
1045
|
# print "FAILED TO VERIFY DS RRSET FOR #{child}\n"
|
1046
1046
|
TheLog.info("FAILED TO VERIFY DS RRSET FOR #{child}")
|
1047
|
-
return false, nil
|
1047
|
+
# return false, nil
|
1048
|
+
# raise ResolvError.new("FAILED TO VERIFY DS RRSET FOR #{child}")
|
1049
|
+
raise VerifyError.new("FAILED TO VERIFY DS RRSET FOR #{child}")
|
1048
1050
|
end
|
1049
1051
|
end
|
1050
1052
|
end
|
@@ -1084,7 +1086,8 @@ module Dnsruby
|
|
1084
1086
|
rescue ResolvError => e
|
1085
1087
|
# print "Error getting DNSKEY for #{child} : #{e}\n"
|
1086
1088
|
TheLog.error("Error getting DNSKEY for #{child} : #{e}")
|
1087
|
-
return false, nil
|
1089
|
+
# return false, nil
|
1090
|
+
raise VerifyError.new("Error getting DNSKEY for #{child} : #{e}")
|
1088
1091
|
end
|
1089
1092
|
verified = true
|
1090
1093
|
key_rrset = key_ret.answer.rrset(child, Types.DNSKEY)
|
@@ -1110,6 +1113,7 @@ module Dnsruby
|
|
1110
1113
|
verify(key_rrset)
|
1111
1114
|
rescue VerifyError =>e
|
1112
1115
|
verified = false
|
1116
|
+
raise VerifyError.new("Couldn't verify DNSKEY and DS records")
|
1113
1117
|
end
|
1114
1118
|
end
|
1115
1119
|
end
|
@@ -1122,13 +1126,15 @@ module Dnsruby
|
|
1122
1126
|
if (!verified)
|
1123
1127
|
TheLog.info("Failed to verify DNSKEY for #{child}")
|
1124
1128
|
return false, nil # new_res
|
1129
|
+
# raise VerifyError.new("Failed to verify DNSKEY for #{child}")
|
1125
1130
|
end
|
1126
1131
|
# Cache.add(key_ret)
|
1127
1132
|
return key_rrset, new_res
|
1128
1133
|
rescue VerifyError => e
|
1129
1134
|
# print "Verification error : #{e}\n"
|
1130
1135
|
TheLog.info("Verification error : #{e}\n")
|
1131
|
-
return false, nil # new_res
|
1136
|
+
# return false, nil # new_res
|
1137
|
+
raise VerifyError.new("Verification error : #{e}\n")
|
1132
1138
|
end
|
1133
1139
|
end
|
1134
1140
|
|
@@ -1271,6 +1277,9 @@ module Dnsruby
|
|
1271
1277
|
msg.security_level = Message::SecurityLevel.INDETERMINATE
|
1272
1278
|
qname = msg.question()[0].qname
|
1273
1279
|
closest_anchor = find_closest_anchor_for(qname)
|
1280
|
+
if (!closest_anchor)
|
1281
|
+
|
1282
|
+
end
|
1274
1283
|
TheLog.debug("Closest anchor for #{qname} is #{closest_anchor} - trying to follow down")
|
1275
1284
|
error = try_to_follow_from_anchor(closest_anchor, msg, qname)
|
1276
1285
|
|
@@ -1304,6 +1313,9 @@ module Dnsruby
|
|
1304
1313
|
if (error)
|
1305
1314
|
raise error
|
1306
1315
|
end
|
1316
|
+
if (msg.security_level == Message::SecurityLevel.BOGUS)
|
1317
|
+
raise VerifyError.new("Bogus record")
|
1318
|
+
end
|
1307
1319
|
if (msg.security_level.code > Message::SecurityLevel::UNCHECKED)
|
1308
1320
|
return true
|
1309
1321
|
else
|
@@ -1315,7 +1327,15 @@ module Dnsruby
|
|
1315
1327
|
error = nil
|
1316
1328
|
if (closest_anchor)
|
1317
1329
|
# Then try to descend to the level we're interested in
|
1318
|
-
actual_anchor =
|
1330
|
+
actual_anchor = false
|
1331
|
+
begin
|
1332
|
+
actual_anchor = follow_chain(closest_anchor, qname)
|
1333
|
+
rescue VerifyError => e
|
1334
|
+
TheLog.debug("Broken chain from anchor : #{closest_anchor.name}")
|
1335
|
+
msg.security_level = Message::SecurityLevel.BOGUS
|
1336
|
+
return e
|
1337
|
+
end
|
1338
|
+
# @TODO@ We need to de ermine whether there was simply no DS record, or whether there was a failure
|
1319
1339
|
if (!actual_anchor)
|
1320
1340
|
TheLog.debug("Unable to follow chain from anchor : #{closest_anchor.name}")
|
1321
1341
|
msg.security_level = Message::SecurityLevel.INSECURE
|