dnsruby 1.40 → 1.41
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.
- data/demo/example_recurse.rb +4 -1
- data/lib/Dnsruby/DNS.rb +1 -1
- data/lib/Dnsruby/Recursor.rb +129 -118
- data/lib/Dnsruby/Resolver.rb +83 -60
- data/lib/Dnsruby/SingleResolver.rb +1 -0
- data/lib/Dnsruby/dnssec.rb +4 -4
- data/lib/Dnsruby/resource/DNSKEY.rb +42 -7
- data/lib/Dnsruby/resource/IN.rb +40 -7
- data/lib/Dnsruby/resource/NSEC3.rb +1 -1
- data/lib/Dnsruby/resource/generic.rb +8 -0
- data/lib/Dnsruby/resource/resource.rb +17 -5
- data/lib/Dnsruby/single_verifier.rb +3 -2
- data/lib/Dnsruby/zone_reader.rb +2 -2
- data/test/tc_cache.rb +33 -11
- data/test/tc_ipseckey.rb +1 -0
- data/test/tc_naptr.rb +48 -0
- data/test/tc_resolver.rb +7 -8
- data/test/tc_rr.rb +1 -1
- data/test/tc_rrsig.rb +5 -0
- data/test/tc_update.rb +2 -2
- data/test/tc_verifier.rb +19 -2
- data/test/ts_offline.rb +1 -0
- data/test/ts_online.rb +2 -1
- metadata +7 -6
data/lib/Dnsruby/dnssec.rb
CHANGED
@@ -286,14 +286,14 @@ module Dnsruby
|
|
286
286
|
return @@dlv_verifier.validate(msg, query)
|
287
287
|
end
|
288
288
|
|
289
|
-
def self.verify(msg)
|
289
|
+
def self.verify(msg, keys=nil)
|
290
290
|
begin
|
291
|
-
return true if @@anchor_verifier.verify(msg)
|
291
|
+
return true if @@anchor_verifier.verify(msg, keys=nil)
|
292
292
|
rescue VerifyError
|
293
293
|
begin
|
294
|
-
return true if @@root_verifier.verify(msg)
|
294
|
+
return true if @@root_verifier.verify(msg, keys=nil)
|
295
295
|
rescue VerifyError
|
296
|
-
return true if @@dlv_verifier.verify(msg) # Will carry error to client
|
296
|
+
return true if @@dlv_verifier.verify(msg, keys=nil) # Will carry error to client
|
297
297
|
end
|
298
298
|
end
|
299
299
|
end
|
@@ -49,10 +49,13 @@ module Dnsruby
|
|
49
49
|
attr_reader :key
|
50
50
|
|
51
51
|
def init_defaults
|
52
|
+
@make_new_key_tag = false
|
52
53
|
self.protocol=3
|
53
54
|
self.flags=ZONE_KEY
|
54
55
|
@algorithm=Algorithms.RSASHA1
|
55
56
|
@public_key = nil
|
57
|
+
@key_tag = nil
|
58
|
+
@make_new_key_tag = true
|
56
59
|
end
|
57
60
|
|
58
61
|
def protocol=(p)
|
@@ -60,6 +63,7 @@ module Dnsruby
|
|
60
63
|
raise DecodeError.new("DNSKEY protocol field set to #{p}, contrary to RFC4034 section 2.1.2")
|
61
64
|
else @protocol = p
|
62
65
|
end
|
66
|
+
get_new_key_tag
|
63
67
|
end
|
64
68
|
|
65
69
|
def algorithm=(a)
|
@@ -74,6 +78,7 @@ module Dnsruby
|
|
74
78
|
rescue ArgumentError => e
|
75
79
|
raise DecodeError.new(e)
|
76
80
|
end
|
81
|
+
get_new_key_tag
|
77
82
|
end
|
78
83
|
|
79
84
|
def revoked=(on)
|
@@ -82,6 +87,7 @@ module Dnsruby
|
|
82
87
|
else
|
83
88
|
@flags &= (~REVOKED_KEY)
|
84
89
|
end
|
90
|
+
get_new_key_tag
|
85
91
|
end
|
86
92
|
|
87
93
|
def revoked?
|
@@ -94,6 +100,7 @@ module Dnsruby
|
|
94
100
|
else
|
95
101
|
@flags &= (~ZONE_KEY)
|
96
102
|
end
|
103
|
+
get_new_key_tag
|
97
104
|
end
|
98
105
|
|
99
106
|
def zone_key?
|
@@ -106,6 +113,7 @@ module Dnsruby
|
|
106
113
|
else
|
107
114
|
@flags &= (~SEP_KEY)
|
108
115
|
end
|
116
|
+
get_new_key_tag
|
109
117
|
end
|
110
118
|
|
111
119
|
def sep_key?
|
@@ -123,6 +131,7 @@ module Dnsruby
|
|
123
131
|
end
|
124
132
|
|
125
133
|
@flags = f
|
134
|
+
get_new_key_tag
|
126
135
|
end
|
127
136
|
|
128
137
|
# def bad_flags?
|
@@ -134,13 +143,26 @@ module Dnsruby
|
|
134
143
|
#
|
135
144
|
def from_data(data) #:nodoc: all
|
136
145
|
flags, protocol, algorithm, @key = data
|
146
|
+
@make_new_key_tag = false
|
137
147
|
self.flags=(flags)
|
138
148
|
self.protocol=(protocol)
|
139
149
|
self.algorithm=(algorithm)
|
150
|
+
@make_new_key_tag = true
|
151
|
+
get_new_key_tag
|
140
152
|
end
|
141
153
|
|
142
|
-
|
154
|
+
def from_hash(hash) #:nodoc: all
|
155
|
+
@make_new_key_tag = false
|
156
|
+
hash.keys.each do |param|
|
157
|
+
send(param.to_s+"=", hash[param])
|
158
|
+
end
|
159
|
+
@make_new_key_tag = true
|
160
|
+
get_new_key_tag
|
161
|
+
end
|
162
|
+
|
163
|
+
def from_string(input)
|
143
164
|
if (input.length > 0)
|
165
|
+
@make_new_key_tag = false
|
144
166
|
data = input.split(" ")
|
145
167
|
self.flags=(data[0].to_i)
|
146
168
|
self.protocol=(data[1].to_i)
|
@@ -167,13 +189,15 @@ module Dnsruby
|
|
167
189
|
end
|
168
190
|
}
|
169
191
|
self.key=(buf)
|
192
|
+
@make_new_key_tag = true
|
193
|
+
get_new_key_tag
|
170
194
|
end
|
171
195
|
end
|
172
196
|
|
173
197
|
def rdata_to_string #:nodoc: all
|
174
198
|
if (@flags!=nil)
|
175
199
|
# return "#{@flags} #{@protocol} #{@algorithm.string} ( #{Base64.encode64(@key.to_s)} )"
|
176
|
-
return "#{@flags} #{@protocol} #{@algorithm.string} ( #{[@key.to_s].pack("m*").gsub("\n", "")} )"
|
200
|
+
return "#{@flags} #{@protocol} #{@algorithm.string} ( #{[@key.to_s].pack("m*").gsub("\n", "")} ) ; key_tag=#{key_tag}"
|
177
201
|
else
|
178
202
|
return ""
|
179
203
|
end
|
@@ -204,13 +228,23 @@ module Dnsruby
|
|
204
228
|
return new_key.key_tag
|
205
229
|
end
|
206
230
|
|
231
|
+
def get_new_key_tag
|
232
|
+
if (@make_new_key_tag)
|
233
|
+
rdata = MessageEncoder.new {|msg|
|
234
|
+
encode_rdata(msg)
|
235
|
+
}.to_s
|
236
|
+
tag = generate_key_tag(rdata, @algorithm)
|
237
|
+
@key_tag = tag
|
238
|
+
end
|
239
|
+
end
|
240
|
+
|
207
241
|
# Return the tag for this key
|
208
242
|
def key_tag
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
return
|
243
|
+
if (!@key_tag)
|
244
|
+
@make_new_key_tag = true
|
245
|
+
get_new_key_tag
|
246
|
+
end
|
247
|
+
return @key_tag
|
214
248
|
end
|
215
249
|
|
216
250
|
def generate_key_tag(rdata, algorithm)
|
@@ -259,6 +293,7 @@ module Dnsruby
|
|
259
293
|
key_text.gsub!(/ /, "")
|
260
294
|
# @key=Base64.decode64(key_text)
|
261
295
|
@key=key_text.unpack("m*")[0]
|
296
|
+
get_new_key_tag
|
262
297
|
end
|
263
298
|
|
264
299
|
def public_key
|
data/lib/Dnsruby/resource/IN.rb
CHANGED
@@ -15,18 +15,51 @@
|
|
15
15
|
#++
|
16
16
|
module Dnsruby
|
17
17
|
class RR
|
18
|
-
ClassInsensitiveTypes =
|
19
|
-
NS
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
18
|
+
ClassInsensitiveTypes = {
|
19
|
+
Types::NS => NS,
|
20
|
+
Types::CNAME => CNAME,
|
21
|
+
Types::DNAME => DNAME,
|
22
|
+
Types::DNSKEY => DNSKEY,
|
23
|
+
Types::SOA => SOA,
|
24
|
+
Types::PTR => PTR,
|
25
|
+
Types::HINFO => HINFO,
|
26
|
+
Types::MINFO => MINFO,
|
27
|
+
Types::MX => MX,
|
28
|
+
Types::TXT => TXT,
|
29
|
+
Types::ISDN => ISDN,
|
30
|
+
Types::MB => MB,
|
31
|
+
Types::MG => MG,
|
32
|
+
Types::MR => MR,
|
33
|
+
Types::NAPTR => NAPTR,
|
34
|
+
Types::NSAP => NSAP,
|
35
|
+
Types::OPT => OPT,
|
36
|
+
Types::RP => RP,
|
37
|
+
Types::RT => RT,
|
38
|
+
Types::X25 => X25,
|
39
|
+
Types::KX => KX,
|
40
|
+
Types::SPF => SPF,
|
41
|
+
Types::CERT => CERT,
|
42
|
+
Types::LOC => LOC,
|
43
|
+
Types::TSIG => TSIG,
|
44
|
+
Types::TKEY => TKEY,
|
45
|
+
Types::ANY => ANY,
|
46
|
+
Types::RRSIG => RRSIG,
|
47
|
+
Types::NSEC => NSEC,
|
48
|
+
Types::DS => DS,
|
49
|
+
Types::NSEC3 => NSEC3,
|
50
|
+
Types::NSEC3PARAM => NSEC3PARAM,
|
51
|
+
Types::DLV => DLV,
|
52
|
+
Types::SSHFP => SSHFP,
|
53
|
+
Types::IPSECKEY => IPSECKEY,
|
54
|
+
Types::HIP => HIP,
|
55
|
+
Types::DHCID => DHCID
|
56
|
+
} #:nodoc: all
|
24
57
|
|
25
58
|
# module IN contains ARPA Internet specific RRs
|
26
59
|
module IN
|
27
60
|
ClassValue = Classes::IN
|
28
61
|
|
29
|
-
ClassInsensitiveTypes::each {|s|
|
62
|
+
ClassInsensitiveTypes::values::each {|s|
|
30
63
|
c = Class.new(s)
|
31
64
|
# c < Record
|
32
65
|
c.const_set(:TypeValue, s::TypeValue)
|
@@ -122,6 +122,14 @@ module Dnsruby
|
|
122
122
|
class ANY < RR
|
123
123
|
ClassValue = nil #:nodoc: all
|
124
124
|
TypeValue = Types::ANY #:nodoc: all
|
125
|
+
def encode_rdata(msg, canonical=false) #:nodoc: all
|
126
|
+
return ""
|
127
|
+
end
|
128
|
+
def self.decode_rdata(msg) #:nodoc: all
|
129
|
+
return self.new([])
|
130
|
+
end
|
131
|
+
def from_data(data)
|
132
|
+
end
|
125
133
|
end
|
126
134
|
end
|
127
135
|
end
|
@@ -569,6 +569,20 @@ module Dnsruby
|
|
569
569
|
}
|
570
570
|
return h
|
571
571
|
end
|
572
|
+
|
573
|
+
def self.find_class(type_value, class_value) # :nodoc: all
|
574
|
+
klass = nil
|
575
|
+
if (ret = ClassHash[[type_value, class_value]])
|
576
|
+
return ret
|
577
|
+
elsif (val = ClassInsensitiveTypes[type_value])
|
578
|
+
klass = Class.new(val)
|
579
|
+
klass.const_set(:TypeValue, type_value)
|
580
|
+
klass.const_set(:ClassValue, class_value)
|
581
|
+
return klass
|
582
|
+
else
|
583
|
+
return Generic.create(type_value, class_value)
|
584
|
+
end
|
585
|
+
end
|
572
586
|
|
573
587
|
#Get an RR of the specified type and class
|
574
588
|
def self.get_class(type_value, class_value) #:nodoc: all
|
@@ -577,8 +591,7 @@ module Dnsruby
|
|
577
591
|
end
|
578
592
|
if (type_value.class == Class)
|
579
593
|
type_value = type_value.const_get(:TypeValue)
|
580
|
-
return
|
581
|
-
Generic.create(type_value, Classes.to_code(class_value))
|
594
|
+
return find_class(type_value, Classes.to_code(class_value))
|
582
595
|
else
|
583
596
|
if (type_value.class == Types)
|
584
597
|
type_value = type_value.code
|
@@ -590,8 +603,7 @@ module Dnsruby
|
|
590
603
|
else
|
591
604
|
class_value = Classes.new(class_value).code
|
592
605
|
end
|
593
|
-
return
|
594
|
-
Generic.create(type_value, class_value)
|
606
|
+
return find_class(type_value, class_value)
|
595
607
|
end
|
596
608
|
return ret
|
597
609
|
end
|
@@ -629,7 +641,7 @@ module Dnsruby
|
|
629
641
|
return ret
|
630
642
|
end
|
631
643
|
end
|
632
|
-
end
|
644
|
+
end
|
633
645
|
require 'Dnsruby/resource/domain_name'
|
634
646
|
require 'Dnsruby/resource/generic'
|
635
647
|
require 'Dnsruby/resource/IN'
|
@@ -647,7 +647,8 @@ module Dnsruby
|
|
647
647
|
if ((keys == nil) || (sigrecs == nil))
|
648
648
|
return nil, nil
|
649
649
|
end
|
650
|
-
if (RR::DNSKEY === keys)
|
650
|
+
if ((RR::DNSKEY === keys) || (RR::DS === keys) ||
|
651
|
+
((RR::DLV === keys) && (@verifier_type == VerifierType::DLV)))
|
651
652
|
keys = [keys]
|
652
653
|
end
|
653
654
|
enumerator = keys
|
@@ -677,7 +678,7 @@ module Dnsruby
|
|
677
678
|
# print "Verify_rrset #{rrset.name}, #{rrset.type}\n"
|
678
679
|
sigrecs = rrset.sigs
|
679
680
|
if (rrset.rrs.length == 0)
|
680
|
-
raise VerifyError.new("No RRSet to
|
681
|
+
raise VerifyError.new("No RRSet to verify")
|
681
682
|
end
|
682
683
|
if (rrset.num_sigs == 0)
|
683
684
|
raise VerifyError.new("No signatures in the RRSet : #{rrset.name}, #{rrset.type}")
|
data/lib/Dnsruby/zone_reader.rb
CHANGED
@@ -25,10 +25,10 @@ module Dnsruby
|
|
25
25
|
# Create a new ZoneReader. The zone origin is required. If the desired SOA minimum
|
26
26
|
# and TTL are passed in, then they are used as default values.
|
27
27
|
def initialize(origin, soa_minimum = nil, soa_ttl = nil)
|
28
|
-
@origin = origin
|
28
|
+
@origin = origin.to_s
|
29
29
|
|
30
30
|
if (!Name.create(@origin).absolute?)
|
31
|
-
@origin = @origin + "."
|
31
|
+
@origin = @origin.to_s + "."
|
32
32
|
end
|
33
33
|
@soa_ttl = soa_ttl
|
34
34
|
if (soa_minimum && !@last_explicit_ttl)
|
data/test/tc_cache.rb
CHANGED
@@ -20,35 +20,34 @@ include Dnsruby
|
|
20
20
|
|
21
21
|
class TestCache < Test::Unit::TestCase
|
22
22
|
def test_cache
|
23
|
-
|
23
|
+
cache = Cache.new
|
24
24
|
m1 = Message.new("example.com.", Types.A, Classes.IN)
|
25
25
|
rr1 = RR.create("example.com. 3 IN A 208.77.188.166")
|
26
26
|
m1.add_answer(rr1)
|
27
27
|
m1.header.aa = true
|
28
28
|
assert(!m1.cached)
|
29
|
-
|
30
|
-
ret =
|
29
|
+
cache.add(m1)
|
30
|
+
ret = cache.find("example.com", "A")
|
31
31
|
assert(ret.cached)
|
32
|
-
assert(ret.answer == m1.answer, "#{m1.answer}end\n#{ret.answer}end" )
|
33
|
-
assert(ret.answer.to_s == m1.answer.to_s, "#{m1.answer.to_s}end\n#{ret.answer.to_s}end" )
|
32
|
+
assert(ret.answer.rrset("example.com", "A").to_s == m1.answer.rrset("example.com", "A").to_s, "#{m1.answer.rrset("example.com", "A").to_s}end\n#{ret.answer.rrset("example.com", "A").to_s}end" )
|
34
33
|
assert(ret.header.aa == false)
|
35
34
|
assert(ret.answer.rrsets()[0].ttl == 3)
|
36
35
|
sleep(1)
|
37
|
-
ret =
|
36
|
+
ret = cache.find("example.com", "A")
|
38
37
|
assert(ret.cached)
|
39
38
|
assert((ret.answer.rrsets()[0].ttl == 2) || (ret.answer.rrsets()[0].ttl == 1), "ttl = #{ret.answer.rrsets()[0].ttl}")
|
40
39
|
assert(ret.answer != m1.answer, "ret.answer=#{ret.answer}\nm1.answer=#{m1.answer}" )
|
41
40
|
assert(ret.header.aa == false)
|
42
41
|
sleep(2) # TTL of 3 should have timed out now
|
43
|
-
ret =
|
42
|
+
ret = cache.find("example.com", "A")
|
44
43
|
assert(!ret)
|
45
|
-
|
44
|
+
cache.add(m1)
|
46
45
|
m2 = Message.new("example.com.", Types.A, Classes.IN)
|
47
46
|
rr2 = RR.create("example.com. 200 IN A 208.77.188.166")
|
48
47
|
m2.add_answer(rr2)
|
49
48
|
m2.header.aa = true
|
50
|
-
|
51
|
-
ret =
|
49
|
+
cache.add(m2)
|
50
|
+
ret = cache.find("example.com", "A")
|
52
51
|
assert(ret.cached)
|
53
52
|
assert(ret.answer.rrsets()[0].ttl == 200)
|
54
53
|
end
|
@@ -64,8 +63,31 @@ class TestCache < Test::Unit::TestCase
|
|
64
63
|
|
65
64
|
end
|
66
65
|
|
66
|
+
def test_resolver_do_caching
|
67
|
+
# Get the records back from the test zone
|
68
|
+
Dnsruby::PacketSender.clear_caches
|
69
|
+
res = Resolver.new("ns0.validation-test-servers.nominet.org.uk.")
|
70
|
+
res.do_caching = false
|
71
|
+
assert(!res.do_caching)
|
72
|
+
res.udp_size = 4096
|
73
|
+
ret = res.query("overflow.dnsruby.validation-test-servers.nominet.org.uk", Types.TXT)
|
74
|
+
# print "#{ret}\n"
|
75
|
+
assert(!ret.cached)
|
76
|
+
assert(ret.rcode == RCode.NoError)
|
77
|
+
assert(ret.header.aa)
|
78
|
+
# Store the ttls
|
79
|
+
first_ttls = ret.answer.rrset(
|
80
|
+
"overflow.dnsruby.validation-test-servers.nominet.org.uk", Types.TXT).ttl
|
81
|
+
# Wait a while
|
82
|
+
sleep(1)
|
83
|
+
# Ask for the same records
|
84
|
+
ret = res.query("overflow.dnsruby.validation-test-servers.nominet.org.uk", Types.TXT)
|
85
|
+
# print "#{ret}\n"
|
86
|
+
assert(ret.rcode == RCode.NoError)
|
87
|
+
assert(!ret.cached)
|
88
|
+
end
|
89
|
+
|
67
90
|
def test_online
|
68
|
-
# @TODO@ !!!
|
69
91
|
# Get the records back from the test zone
|
70
92
|
Dnsruby::PacketSender.clear_caches
|
71
93
|
res = SingleResolver.new("ns0.validation-test-servers.nominet.org.uk.")
|
data/test/tc_ipseckey.rb
CHANGED
@@ -62,6 +62,7 @@ class TestIPSECKEY < Test::Unit::TestCase
|
|
62
62
|
assert(ipseckey.gateway_type == ipseckey2.gateway_type)
|
63
63
|
assert(ipseckey.algorithm == ipseckey2.algorithm)
|
64
64
|
assert(ipseckey.gateway == ipseckey2.gateway)
|
65
|
+
assert(ipseckey.klass == ipseckey2.klass)
|
65
66
|
assert(ipseckey == ipseckey2)
|
66
67
|
}
|
67
68
|
}
|
data/test/tc_naptr.rb
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
#--
|
2
|
+
#Copyright 2007 Nominet UK
|
3
|
+
#
|
4
|
+
#Licensed under the Apache License, Version 2.0 (the "License");
|
5
|
+
#you may not use this file except in compliance with the License.
|
6
|
+
#You may obtain a copy of the License at
|
7
|
+
#
|
8
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
9
|
+
#
|
10
|
+
#Unless required by applicable law or agreed to in writing, software
|
11
|
+
#distributed under the License is distributed on an "AS IS" BASIS,
|
12
|
+
#WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
13
|
+
#See the License for the specific language governing permissions and
|
14
|
+
#limitations under the License.
|
15
|
+
#++
|
16
|
+
require 'rubygems'
|
17
|
+
require 'test/unit'
|
18
|
+
require 'dnsruby'
|
19
|
+
include Dnsruby
|
20
|
+
class TestNAPTR < Test::Unit::TestCase
|
21
|
+
def test_naptr
|
22
|
+
txt = "example.com. IN NAPTR 100 50 \"s\" \"z3950+I2L+I2C\" \"\" _z3950._tcp.gatech.edu."
|
23
|
+
naptr = RR.create(txt)
|
24
|
+
assert(naptr.type == Types.NAPTR)
|
25
|
+
assert(naptr.order == 100)
|
26
|
+
assert(naptr.preference == 50)
|
27
|
+
assert(naptr.flags == 's')
|
28
|
+
assert(naptr.service == "z3950+I2L+I2C")
|
29
|
+
assert(naptr.regexp == "")
|
30
|
+
assert(naptr.replacement == Name.create('_z3950._tcp.gatech.edu.'))
|
31
|
+
|
32
|
+
m = Dnsruby::Message.new
|
33
|
+
m.add_additional(naptr)
|
34
|
+
data = m.encode
|
35
|
+
m2 = Dnsruby::Message.decode(data)
|
36
|
+
naptr2 = m2.additional()[0]
|
37
|
+
assert(naptr2.type == Types.NAPTR)
|
38
|
+
assert(naptr2.order == 100)
|
39
|
+
assert(naptr2.preference == 50)
|
40
|
+
assert(naptr2.flags == "s")
|
41
|
+
assert(naptr2.service == "z3950+I2L+I2C")
|
42
|
+
assert(naptr2.regexp == "")
|
43
|
+
assert(naptr2.replacement == Name.create('_z3950._tcp.gatech.edu.'))
|
44
|
+
|
45
|
+
naptr.flags = "u"
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|