dnsruby 1.58.0 → 1.59.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|