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