dnsruby 1.30 → 1.31

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.
@@ -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
- attr_accessor :salt
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 = Algorithms.new(a)
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
- if (@next_hashed!=nil)
101
- return "#{@hash_alg.code} #{@flags} #{@iterations} #{@salt}"
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
- msg.put_pack("ccnc", @hash_alg.code, @flags, @iterations, @salt_length)
109
- msg.put_bytes(@salt)
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
- # @TODO@ Do we need to validate this? The response has come from the cache -
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
- # print "Found key #{key.key_tag}\n"
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
- # print "VERIFIED OK\n"
756
+ # print "VERIFIED OK\n"
759
757
  return true
760
758
  end
761
759
 
@@ -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
- klass = Classes.NONE
256
- resource = RR.create("#{args[0]} #{ttl} #{klass} #{args[1]} #{args[2]}")
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
@@ -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
@@ -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
@@ -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
@@ -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::Algorithms.RSAMD5, nsec.hash_alg)
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
@@ -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::Algorithms.RSAMD5, nsec.hash_alg)
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
@@ -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
@@ -72,4 +72,5 @@ class TestTKey < Test::Unit::TestCase
72
72
  #@TODO@ Test TKEY against server!
73
73
 
74
74
  end
75
+
75
76
  end
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.30"
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-05-18 00:00:00 +01:00
12
+ date: 2009-06-04 00:00:00 +01:00
13
13
  default_executable:
14
14
  dependencies: []
15
15