dnsruby 1.30 → 1.31
Sign up to get free protection for your applications and to get access to all the features.
- data/EXAMPLES +9 -5
- data/demo/digdlv.rb +1 -0
- data/demo/digitar.rb +1 -0
- data/html/created.rid +1 -1
- data/html/fr_class_index.html +6 -2
- data/html/fr_method_index.html +275 -273
- data/lib/Dnsruby/Cache.rb +2 -2
- data/lib/Dnsruby/Recursor.rb +42 -42
- data/lib/Dnsruby/dnssec.rb +1 -1
- data/lib/Dnsruby/message.rb +10 -0
- data/lib/Dnsruby/name.rb +19 -0
- data/lib/Dnsruby/resource/DNSKEY.rb +10 -2
- data/lib/Dnsruby/resource/NSEC.rb +4 -1
- data/lib/Dnsruby/resource/NSEC3.rb +113 -32
- data/lib/Dnsruby/resource/NSEC3PARAM.rb +33 -20
- data/lib/Dnsruby/resource/RRSIG.rb +6 -0
- data/lib/Dnsruby/resource/resource.rb +13 -2
- data/lib/Dnsruby/select_thread.rb +1 -2
- data/lib/Dnsruby/single_verifier.rb +2 -4
- data/lib/Dnsruby/update.rb +2 -2
- data/lib/dnsruby.rb +39 -1
- data/test/tc_dnskey.rb +5 -0
- data/test/tc_nsec.rb +5 -0
- data/test/tc_nsec3.rb +37 -12
- data/test/tc_nsec3param.rb +9 -1
- data/test/tc_rrsig.rb +5 -0
- data/test/tc_tkey.rb +1 -0
- metadata +2 -2
@@ -39,10 +39,18 @@ module Dnsruby
|
|
39
39
|
#The Salt Length field defines the length of the Salt field in octets,
|
40
40
|
#ranging in value from 0 to 255.
|
41
41
|
attr_reader :salt_length
|
42
|
+
|
42
43
|
#The Salt field is appended to the original owner name before hashing
|
43
44
|
#in order to defend against pre-calculated dictionary attacks.
|
44
|
-
|
45
|
-
|
45
|
+
def salt
|
46
|
+
return NSEC3.encode_salt(@salt)
|
47
|
+
end
|
48
|
+
|
49
|
+
def salt=(s)
|
50
|
+
@salt = NSEC3.decode_salt(s)
|
51
|
+
@salt_length = @salt.length
|
52
|
+
end
|
53
|
+
|
46
54
|
def hash_alg=(a)
|
47
55
|
if (a.instance_of?String)
|
48
56
|
if (a.length == 1)
|
@@ -50,11 +58,11 @@ module Dnsruby
|
|
50
58
|
end
|
51
59
|
end
|
52
60
|
begin
|
53
|
-
alg =
|
61
|
+
alg = Nsec3HashAlgorithms.new(a)
|
54
62
|
@hash_alg = alg
|
55
63
|
rescue ArgumentError => e
|
56
64
|
raise DecodeError.new(e)
|
57
|
-
end
|
65
|
+
end
|
58
66
|
end
|
59
67
|
|
60
68
|
def types=(t)
|
@@ -69,19 +77,19 @@ module Dnsruby
|
|
69
77
|
end
|
70
78
|
end
|
71
79
|
|
72
|
-
def salt_length=(l)
|
73
|
-
if ((l < 0) || (l > 255))
|
74
|
-
raise DecodeError.new("NSEC3 salt length must be between 0 and 255")
|
75
|
-
end
|
76
|
-
@salt_length = l
|
77
|
-
end
|
78
|
-
|
80
|
+
# def salt_length=(l) # :nodoc: all
|
81
|
+
# if ((l < 0) || (l > 255))
|
82
|
+
# raise DecodeError.new("NSEC3 salt length must be between 0 and 255")
|
83
|
+
# end
|
84
|
+
# @salt_length = l
|
85
|
+
# end
|
86
|
+
#
|
79
87
|
def from_data(data) #:nodoc: all
|
80
88
|
hash_alg, flags, iterations, salt_length, salt = data
|
81
89
|
self.hash_alg=(hash_alg)
|
82
90
|
self.flags=(flags)
|
83
91
|
self.iterations=(iterations)
|
84
|
-
self.salt_length=(salt_length)
|
92
|
+
# self.salt_length=(salt_length)
|
85
93
|
self.salt=(salt)
|
86
94
|
end
|
87
95
|
|
@@ -92,21 +100,26 @@ module Dnsruby
|
|
92
100
|
self.flags=(data[1]).to_i
|
93
101
|
self.iterations=(data[2]).to_i
|
94
102
|
self.salt=(data[3])
|
95
|
-
self.salt_length=(data[3].length)
|
103
|
+
# self.salt_length=(data[3].length)
|
96
104
|
end
|
97
105
|
end
|
98
106
|
|
99
107
|
def rdata_to_string #:nodoc: all
|
100
|
-
|
101
|
-
return "#{@hash_alg.code} #{@flags} #{@iterations} #{
|
102
|
-
else
|
103
|
-
return ""
|
104
|
-
end
|
108
|
+
s = salt()
|
109
|
+
return "#{@hash_alg.code} #{@flags} #{@iterations} #{s}"
|
105
110
|
end
|
106
111
|
|
107
112
|
def encode_rdata(msg, canonical=false) #:nodoc: all
|
108
|
-
|
109
|
-
|
113
|
+
s = salt()
|
114
|
+
sl = s.length()
|
115
|
+
if (s == "-")
|
116
|
+
sl == 0
|
117
|
+
end
|
118
|
+
msg.put_pack("ccnc", @hash_alg.code, @flags, @iterations, sl)
|
119
|
+
|
120
|
+
if (sl > 0)
|
121
|
+
msg.put_bytes(s)
|
122
|
+
end
|
110
123
|
end
|
111
124
|
|
112
125
|
def self.decode_rdata(msg) #:nodoc: all
|
@@ -165,7 +165,13 @@ module Dnsruby
|
|
165
165
|
# the white space out
|
166
166
|
buf=""
|
167
167
|
(index+3..end_index).each {|i|
|
168
|
+
if (comment_index = data[i].index(";"))
|
169
|
+
buf += data[i].slice(0, comment_index)
|
170
|
+
# @TODO@ We lose the comments here - we should really keep them for when we write back to string format?
|
171
|
+
break
|
172
|
+
else
|
168
173
|
buf += data[i]
|
174
|
+
end
|
169
175
|
}
|
170
176
|
buf.gsub!(/\n/, "")
|
171
177
|
buf.gsub!(/ /, "")
|
@@ -23,6 +23,7 @@ module Dnsruby
|
|
23
23
|
# (RRSet)."
|
24
24
|
# This class also stores the RRSIG records which cover the RRSet
|
25
25
|
class RRSet
|
26
|
+
include Comparable
|
26
27
|
# The number of RRSIGs stored in this RRSet
|
27
28
|
attr_reader :num_sigs
|
28
29
|
def initialize(rrs = [])
|
@@ -90,9 +91,19 @@ module Dnsruby
|
|
90
91
|
end
|
91
92
|
|
92
93
|
return privateAdd(r)
|
93
|
-
return true
|
94
|
+
# return true
|
94
95
|
end
|
95
|
-
|
96
|
+
|
97
|
+
def <=>(other)
|
98
|
+
# return 1 if ((!other) || !(other.name) || !(other.type))
|
99
|
+
# return -1 if (!@name)
|
100
|
+
if (@name.canonical == other.name.canonical)
|
101
|
+
return @type.code <=> other.type.code
|
102
|
+
else
|
103
|
+
return @name <=> other.name
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
96
107
|
def sort_canonical
|
97
108
|
#Make a list, for all the RRs, where each RR contributes
|
98
109
|
#the canonical RDATA encoding
|
@@ -492,11 +492,10 @@ module Dnsruby
|
|
492
492
|
# push_to_client(client_id, client_queue, msg, err)
|
493
493
|
client_queue.push([client_id, Resolver::EventType::RECEIVED, msg, err])
|
494
494
|
notify_queue_observers(client_queue, client_id)
|
495
|
-
#
|
495
|
+
# Do we need to validate this? The response has come from the cache -
|
496
496
|
# validate it only if it has not been validated already
|
497
497
|
# So, if we need to validate it, send it to the validation thread
|
498
498
|
# Otherwise, send VALIDATED to the requester.
|
499
|
-
# Should we really just be checking (level != SECURE) ?
|
500
499
|
if (((msg.security_level == Message::SecurityLevel::UNCHECKED) ||
|
501
500
|
(msg.security_level == Message::SecurityLevel::INDETERMINATE)) &&
|
502
501
|
(ValidatorThread.requires_validation?(query, msg, err, res)))
|
@@ -641,7 +641,7 @@ module Dnsruby
|
|
641
641
|
|
642
642
|
sigrecs.each {|sig|
|
643
643
|
if ((key.key_tag == sig.key_tag) && (key.algorithm == sig.algorithm))
|
644
|
-
|
644
|
+
# print "Found key #{key.key_tag}\n"
|
645
645
|
return key, sig
|
646
646
|
end
|
647
647
|
}
|
@@ -654,10 +654,8 @@ module Dnsruby
|
|
654
654
|
#
|
655
655
|
# Returns true if the RRSet verified, false otherwise.
|
656
656
|
def verify_rrset(rrset, keys = nil)
|
657
|
-
# @TODO@ Finer-grained reporting than "false".
|
658
657
|
# print "Verify_rrset #{rrset.name}, #{rrset.type}\n"
|
659
658
|
sigrecs = rrset.sigs
|
660
|
-
# return false if (rrset.num_sigs == 0)
|
661
659
|
if (rrset.rrs.length == 0)
|
662
660
|
raise VerifyError.new("No RRSet to veryify")
|
663
661
|
end
|
@@ -755,7 +753,7 @@ module Dnsruby
|
|
755
753
|
expiration_diff = (sigrec.expiration.to_i - Time.now.to_i).abs
|
756
754
|
rrset.ttl = ([rrset.ttl, sigrec.ttl, sigrec.original_ttl,
|
757
755
|
expiration_diff].sort)[0]
|
758
|
-
|
756
|
+
# print "VERIFIED OK\n"
|
759
757
|
return true
|
760
758
|
end
|
761
759
|
|
data/lib/Dnsruby/update.rb
CHANGED
@@ -252,8 +252,8 @@ module Dnsruby
|
|
252
252
|
resource = RR.create("#{args[0]} #{ttl} #{klass} #{args[1]} #{rdata}")
|
253
253
|
add_update(resource)
|
254
254
|
when 3 # name, type, rdata
|
255
|
-
|
256
|
-
resource =
|
255
|
+
resource = RR.create("#{args[0]} #{ttl} IN #{args[1]} #{args[2]}")
|
256
|
+
resource.klass = Classes.NONE
|
257
257
|
add_update(resource)
|
258
258
|
end
|
259
259
|
return resource
|
data/lib/dnsruby.rb
CHANGED
@@ -75,7 +75,17 @@ require 'Dnsruby/TheLog'
|
|
75
75
|
#* NotImp < ResolvError
|
76
76
|
#
|
77
77
|
#* Refused < ResolvError
|
78
|
+
#
|
79
|
+
#* NotZone < ResolvError
|
80
|
+
#
|
81
|
+
#* YXDomain < ResolvError
|
82
|
+
#
|
83
|
+
#* YXRRSet < ResolvError
|
78
84
|
#
|
85
|
+
#* NXRRSet < ResolvError
|
86
|
+
#
|
87
|
+
#* NotAuth < ResolvError
|
88
|
+
#
|
79
89
|
#* OtherResolvError < ResolvError
|
80
90
|
#
|
81
91
|
#== I/O
|
@@ -377,7 +387,14 @@ module Dnsruby
|
|
377
387
|
# Referred to as Algoriths.RSASHA1_NSEC3_SHA1
|
378
388
|
add_pair("RSASHA1-NSEC3-SHA1", 7)
|
379
389
|
end
|
380
|
-
|
390
|
+
|
391
|
+
# http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml
|
392
|
+
class Nsec3HashAlgorithms < CodeMapper
|
393
|
+
RESERVED = 0
|
394
|
+
update()
|
395
|
+
add_pair("SHA-1", 1)
|
396
|
+
end
|
397
|
+
|
381
398
|
#An error raised while querying for a resource
|
382
399
|
class ResolvError < StandardError
|
383
400
|
end
|
@@ -405,6 +422,27 @@ module Dnsruby
|
|
405
422
|
#The requested operation was refused by the remote resolver
|
406
423
|
class Refused < ResolvError
|
407
424
|
end
|
425
|
+
|
426
|
+
#The update RR is outside the zone (in dynamic update)
|
427
|
+
class NotZone < ResolvError
|
428
|
+
end
|
429
|
+
|
430
|
+
#Some name that ought to exist, does not exist (in dynamic update)
|
431
|
+
class YXDomain < ResolvError
|
432
|
+
end
|
433
|
+
|
434
|
+
#Some RRSet that ought to exist, does not exist (in dynamic update)
|
435
|
+
class YXRRSet < ResolvError
|
436
|
+
end
|
437
|
+
|
438
|
+
#Some RRSet that ought not to exist, does exist (in dynamic update)
|
439
|
+
class NXRRSet < ResolvError
|
440
|
+
end
|
441
|
+
|
442
|
+
#The nameserver is not responsible for the zone (in dynamic update)
|
443
|
+
class NotAuth < ResolvError
|
444
|
+
end
|
445
|
+
|
408
446
|
|
409
447
|
#Another kind of resolver error has occurred
|
410
448
|
class OtherResolvError < ResolvError
|
data/test/tc_dnskey.rb
CHANGED
@@ -34,6 +34,11 @@ class DnskeyTest < Test::Unit::TestCase
|
|
34
34
|
assert(dnskey2.to_s == dnskey.to_s, "#{dnskey.to_s} not equal to \n#{dnskey2.to_s}")
|
35
35
|
end
|
36
36
|
|
37
|
+
def test_from_string_with_comments
|
38
|
+
k = Dnsruby::RR.create("tjeb.nl. 3600 IN DNSKEY 256 3 7 AwEAAcglEOS7bECRK5fqTuGTMJycmDhTzmUu/EQbAhKJOYJxDb5SG/RYqsJgzG7wgtGy0W1aP7I4k6SPtHmwcqjLaZLVUwRNWCGr2adjb9JTFyBR7F99Ngi11lEGM6Uiw/eDRk66lhoSGzohjj/rmhRTV6gN2+0ADPnafv3MBkPgryA3 ;{id = 53177 (zsk), size = 1024b}")
|
39
|
+
assert_equal(53177, k.key_tag)
|
40
|
+
end
|
41
|
+
|
37
42
|
def test_dnskey_from_data
|
38
43
|
dnskey = Dnsruby::RR.create(INPUT)
|
39
44
|
m = Dnsruby::Message.new
|
data/test/tc_nsec.rb
CHANGED
@@ -13,6 +13,11 @@ class NsecTest < Test::Unit::TestCase
|
|
13
13
|
|
14
14
|
nsec2 = Dnsruby::RR.create(nsec.to_s)
|
15
15
|
assert(nsec2.to_s == nsec.to_s)
|
16
|
+
|
17
|
+
s = "tjeb.nl. 3600 IN NSEC dragon.tjeb.nl. A NS SOA MX AAAA RRSIG NSEC DNSKEY"
|
18
|
+
nsec = Dnsruby::RR.create(s)
|
19
|
+
assert(nsec.types.include?(Types.A))
|
20
|
+
assert(nsec.types.include?(Types.DNSKEY))
|
16
21
|
end
|
17
22
|
|
18
23
|
def test_nsec_from_data
|
data/test/tc_nsec3.rb
CHANGED
@@ -12,7 +12,7 @@ class Nsec3Test < Test::Unit::TestCase
|
|
12
12
|
assert(nsec.opt_out?)
|
13
13
|
assert_equal(12, nsec.iterations)
|
14
14
|
assert_equal("aabbccdd", nsec.salt)
|
15
|
-
assert_equal(Dnsruby::
|
15
|
+
assert_equal(Dnsruby::Nsec3HashAlgorithms.SHA_1, nsec.hash_alg)
|
16
16
|
|
17
17
|
nsec2 = Dnsruby::RR.create(nsec.to_s)
|
18
18
|
assert(nsec2.to_s == nsec.to_s)
|
@@ -39,19 +39,44 @@ class Nsec3Test < Test::Unit::TestCase
|
|
39
39
|
nsec3 = m2.additional()[0]
|
40
40
|
assert_equal(nsec.to_s, nsec3.to_s)
|
41
41
|
end
|
42
|
-
|
42
|
+
|
43
|
+
def test_calculate_hash
|
44
|
+
input = [
|
45
|
+
[ "example" , "0p9mhaveqvm6t7vbl5lop2u3t2rp3tom"],
|
46
|
+
[ "a.example" , "35mthgpgcu1qg68fab165klnsnk3dpvl"],
|
47
|
+
[ "ai.example" , "gjeqe526plbf1g8mklp59enfd789njgi"],
|
48
|
+
[ "ns1.example" , "2t7b4g4vsa5smi47k61mv5bv1a22bojr"],
|
49
|
+
[ "ns2.example" , "q04jkcevqvmu85r014c7dkba38o0ji5r"],
|
50
|
+
[ "w.example" , "k8udemvp1j2f7eg6jebps17vp3n8i58h"],
|
51
|
+
[ "*.w.example" , "r53bq7cc2uvmubfu5ocmm6pers9tk9en"],
|
52
|
+
[ "x.w.example" , "b4um86eghhds6nea196smvmlo4ors995"],
|
53
|
+
[ "y.w.example" , "ji6neoaepv8b5o6k4ev33abha8ht9fgc"],
|
54
|
+
[ "x.y.w.example" , "2vptu5timamqttgl4luu9kg21e0aor3s"],
|
55
|
+
[ "xx.example" , "t644ebqk9bibcna874givr6joj62mlhv"],
|
56
|
+
[ "2t7b4g4vsa5smi47k61mv5bv1a22bojr.example" , "kohar7mbb8dc2ce8a9qvl8hon4k53uhi"]
|
57
|
+
]
|
58
|
+
input.each {|name, hash|
|
59
|
+
nsec3 = Dnsruby::RR.create({:type => Dnsruby::Types.NSEC3, :name => name, :salt => "aabbccdd", :iterations => 12, :hash_alg => 1})
|
60
|
+
n = nsec3.calculate_hash
|
61
|
+
assert_equal(n, hash, "Expected #{hash} but got #{n} for #{name}")
|
62
|
+
c = Dnsruby::RR::NSEC3.calculate_hash(name, 12, Dnsruby::RR::NSEC3.decode_salt("aabbccdd"), 1)
|
63
|
+
assert_equal(c, hash, "Expected #{hash} but got #{c} for #{name}")
|
64
|
+
}
|
65
|
+
#
|
66
|
+
end
|
67
|
+
|
43
68
|
def test_nsec_other_stuff
|
44
69
|
nsec = Dnsruby::RR.create(INPUT)
|
45
|
-
begin
|
46
|
-
nsec.salt_length=256
|
47
|
-
fail
|
48
|
-
rescue DecodeError
|
49
|
-
end
|
50
|
-
begin
|
51
|
-
nsec.hash_length=256
|
52
|
-
fail
|
53
|
-
rescue DecodeError
|
54
|
-
end
|
70
|
+
# begin
|
71
|
+
# nsec.salt_length=256
|
72
|
+
# fail
|
73
|
+
# rescue DecodeError
|
74
|
+
# end
|
75
|
+
# begin
|
76
|
+
# nsec.hash_length=256
|
77
|
+
# fail
|
78
|
+
# rescue DecodeError
|
79
|
+
# end
|
55
80
|
# Be liberal in what you accept...
|
56
81
|
# begin
|
57
82
|
# nsec.hash_alg = 8
|
data/test/tc_nsec3param.rb
CHANGED
@@ -8,7 +8,7 @@ class Nsec3ParamTest < Test::Unit::TestCase
|
|
8
8
|
def test_nsec_from_string
|
9
9
|
nsec = Dnsruby::RR.create(INPUT)
|
10
10
|
|
11
|
-
assert_equal(Dnsruby::
|
11
|
+
assert_equal(Dnsruby::Nsec3HashAlgorithms.SHA_1, nsec.hash_alg)
|
12
12
|
assert_equal(0, nsec.flags)
|
13
13
|
assert_equal(12, nsec.iterations)
|
14
14
|
assert_equal("aabbccdd", nsec.salt)
|
@@ -25,6 +25,14 @@ class Nsec3ParamTest < Test::Unit::TestCase
|
|
25
25
|
m2 = Dnsruby::Message.decode(data)
|
26
26
|
nsec3 = m2.additional()[0]
|
27
27
|
assert_equal(nsec.to_s, nsec3.to_s)
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_from_real_string
|
32
|
+
r = Dnsruby::RR.create("tjeb.nl. 3600 IN NSEC3PARAM 1 0 5 beef")
|
33
|
+
assert_equal(Dnsruby::Name.create("tjeb.nl."), r.name)
|
34
|
+
assert_equal("beef", r.salt)
|
35
|
+
assert_equal(Dnsruby::Nsec3HashAlgorithms.SHA_1, r.hash_alg)
|
28
36
|
end
|
29
37
|
|
30
38
|
end
|
data/test/tc_rrsig.rb
CHANGED
@@ -29,4 +29,9 @@ class RrsigTest < Test::Unit::TestCase
|
|
29
29
|
rrsig2 = Dnsruby::RR.create(rrsig.to_s)
|
30
30
|
assert(rrsig2.to_s == rrsig.to_s)
|
31
31
|
end
|
32
|
+
|
33
|
+
def test_string_with_comments
|
34
|
+
r = Dnsruby::RR.create("tjeb.nl. 3600 IN RRSIG NSEC3PARAM 7 2 3600 20090630164649 20090602164649 53177 tjeb.nl. Fw70WQMviRFGyeze3MUpfafaAcWIvHRpnq4ZK3lxexrR1p+rLxK5C4qVKU71XYrPYR7XEBxgUG1oyKNOhFOVyx31EjC462dz7Vxn6UDpD1LIwNnD28+oHfS9AFzGKcn4zUZqT+8IvOO1jiS9c3Y8WAkOloN9AwGIIKWU8zAp1n4= ;{id = 53177}")
|
35
|
+
assert_equal("Fw70WQMviRFGyeze3MUpfafaAcWIvHRpnq4ZK3lxexrR1p+rLxK5C4qVKU71XYrPYR7XEBxgUG1oyKNOhFOVyx31EjC462dz7Vxn6UDpD1LIwNnD28+oHfS9AFzGKcn4zUZqT+8IvOO1jiS9c3Y8WAkOloN9AwGIIKWU8zAp1n4=", ([r.signature].pack("m*")).gsub(/\n/,"").chomp)
|
36
|
+
end
|
32
37
|
end
|
data/test/tc_tkey.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dnsruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: "1.
|
4
|
+
version: "1.31"
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- AlexD
|
@@ -9,7 +9,7 @@ autorequire: dnsruby
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-06-04 00:00:00 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|