dnsruby 1.60.1 → 1.61.4
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.
- checksums.yaml +5 -5
- data/.travis.yml +6 -7
- data/.yardopts +7 -0
- data/README.md +7 -4
- data/RELEASE_NOTES.md +46 -0
- data/Rakefile +1 -0
- data/demo/digroot.rb +2 -0
- data/dnsruby.gemspec +15 -8
- data/lib/dnsruby/code_mappers.rb +3 -0
- data/lib/dnsruby/config.rb +24 -4
- data/lib/dnsruby/dnssec.rb +4 -0
- data/lib/dnsruby/message/encoder.rb +2 -2
- data/lib/dnsruby/message/header.rb +15 -15
- data/lib/dnsruby/name.rb +18 -2
- data/lib/dnsruby/packet_sender.rb +14 -2
- data/lib/dnsruby/recursor.rb +10 -1
- data/lib/dnsruby/resolver.rb +12 -0
- data/lib/dnsruby/resource/CAA.rb +6 -4
- data/lib/dnsruby/resource/CDNSKEY.rb +17 -0
- data/lib/dnsruby/resource/CDS.rb +35 -0
- data/lib/dnsruby/resource/DNSKEY.rb +33 -6
- data/lib/dnsruby/resource/IN.rb +4 -1
- data/lib/dnsruby/resource/NAPTR.rb +9 -7
- data/lib/dnsruby/resource/URI.rb +57 -0
- data/lib/dnsruby/resource/generic.rb +3 -0
- data/lib/dnsruby/select_thread.rb +1 -2
- data/lib/dnsruby/single_verifier.rb +27 -4
- data/lib/dnsruby/update.rb +65 -48
- data/lib/dnsruby/validator_thread.rb +4 -4
- data/lib/dnsruby/version.rb +1 -1
- data/lib/dnsruby/zone_transfer.rb +5 -1
- data/test/localdns.rb +29 -0
- data/test/tc_caa.rb +0 -1
- data/test/tc_dns.rb +11 -1
- data/test/tc_dnskey.rb +29 -0
- data/test/tc_encoding.rb +31 -0
- data/test/tc_hs.rb +4 -3
- data/test/tc_long_labels.rb +46 -0
- data/test/tc_name.rb +19 -0
- data/test/tc_resolv.rb +5 -4
- data/test/tc_resolver.rb +27 -1
- data/test/tc_rr-opt.rb +9 -3
- data/test/tc_rr.rb +33 -0
- data/test/tc_soak.rb +33 -67
- data/test/tc_tcp_pipelining.rb +27 -19
- data/test/tc_update.rb +12 -0
- data/test/tc_verifier.rb +15 -0
- data/test/test_dnsserver.rb +110 -17
- metadata +50 -44
data/lib/dnsruby/recursor.rb
CHANGED
|
@@ -153,7 +153,7 @@ module Dnsruby
|
|
|
153
153
|
end
|
|
154
154
|
end
|
|
155
155
|
attr_accessor :nameservers, :callback, :recurse, :ipv6_ok
|
|
156
|
-
attr_reader :hints
|
|
156
|
+
attr_reader :hints, :dnssec
|
|
157
157
|
# The resolver to use for the queries
|
|
158
158
|
attr_accessor :resolver
|
|
159
159
|
|
|
@@ -164,6 +164,11 @@ module Dnsruby
|
|
|
164
164
|
@@zones_cache = nil
|
|
165
165
|
@@nameservers = nil
|
|
166
166
|
|
|
167
|
+
def dnssec=(dnssec_on)
|
|
168
|
+
@dnssec = dnssec_on
|
|
169
|
+
@resolver.dnssec = dnssec_on
|
|
170
|
+
end
|
|
171
|
+
|
|
167
172
|
def initialize(res = nil)
|
|
168
173
|
if (res)
|
|
169
174
|
@resolver = res
|
|
@@ -174,6 +179,7 @@ module Dnsruby
|
|
|
174
179
|
@resolver = Resolver.new
|
|
175
180
|
end
|
|
176
181
|
end
|
|
182
|
+
@resolver.dnssec = @dnssec
|
|
177
183
|
@ipv6_ok = false
|
|
178
184
|
end
|
|
179
185
|
# Initialize the hint servers. Recursive queries need a starting name
|
|
@@ -196,6 +202,7 @@ module Dnsruby
|
|
|
196
202
|
@resolver = resolver
|
|
197
203
|
if (resolver.single_resolvers.length == 0)
|
|
198
204
|
resolver = Resolver.new()
|
|
205
|
+
resolver.dnssec = @dnssec
|
|
199
206
|
end
|
|
200
207
|
if (hints && hints.length > 0)
|
|
201
208
|
resolver.nameservers=hints
|
|
@@ -372,6 +379,7 @@ module Dnsruby
|
|
|
372
379
|
end
|
|
373
380
|
|
|
374
381
|
def Recursor.clear_caches(resolver = Resolver.new)
|
|
382
|
+
resolver.dnssec = @dnssec
|
|
375
383
|
Recursor.set_hints(Hash.new, resolver)
|
|
376
384
|
@@zones_cache = Hash.new # key zone_name, values Hash of servers and AddressCaches
|
|
377
385
|
@@zones_cache["."] = @@hints
|
|
@@ -613,6 +621,7 @@ module Dnsruby
|
|
|
613
621
|
}
|
|
614
622
|
end
|
|
615
623
|
resolver = Resolver.new({:nameserver=>nameservers})
|
|
624
|
+
resolver.dnssec = @dnssec
|
|
616
625
|
servers = []
|
|
617
626
|
resolver.single_resolvers.each {|s|
|
|
618
627
|
servers.push(s.server)
|
data/lib/dnsruby/resolver.rb
CHANGED
|
@@ -487,6 +487,7 @@ module Dnsruby
|
|
|
487
487
|
@config.nameserver.each do |ns|
|
|
488
488
|
res = PacketSender.new({
|
|
489
489
|
server: ns,
|
|
490
|
+
port: @port,
|
|
490
491
|
dnssec: @dnssec,
|
|
491
492
|
use_tcp: @use_tcp,
|
|
492
493
|
no_tcp: @no_tcp,
|
|
@@ -890,6 +891,14 @@ module Dnsruby
|
|
|
890
891
|
return
|
|
891
892
|
end
|
|
892
893
|
|
|
894
|
+
begin
|
|
895
|
+
msg.encode
|
|
896
|
+
rescue EncodeError => err
|
|
897
|
+
Dnsruby.log.error { "Can't encode " + msg.to_s + " : #{err}" }
|
|
898
|
+
client_queue.push([client_query_id, err])
|
|
899
|
+
return
|
|
900
|
+
end
|
|
901
|
+
|
|
893
902
|
tick_needed = false
|
|
894
903
|
# add to our data structures
|
|
895
904
|
# @mutex.synchronize{
|
|
@@ -1123,6 +1132,9 @@ module Dnsruby
|
|
|
1123
1132
|
increment_resolver_priority(resolver) unless response.cached
|
|
1124
1133
|
stop_querying(client_query_id)
|
|
1125
1134
|
# @TODO@ Does the client want notified at this point?
|
|
1135
|
+
elsif error.kind_of?(EncodeError)
|
|
1136
|
+
Dnsruby.log.debug{'Encode error - sending to client'}
|
|
1137
|
+
send_result_and_stop_querying(client_queue, client_query_id, select_queue, response, error)
|
|
1126
1138
|
else
|
|
1127
1139
|
# - if it was any other error, then remove that server from the list for that query
|
|
1128
1140
|
# If a Too Many Open Files error, then don't remove, but let retry work.
|
data/lib/dnsruby/resource/CAA.rb
CHANGED
|
@@ -54,15 +54,17 @@ module Dnsruby
|
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
def encode_rdata(msg, canonical=false) #:nodoc: all
|
|
57
|
-
msg.put_pack('
|
|
57
|
+
msg.put_pack('C', flag)
|
|
58
58
|
msg.put_string(@property_tag)
|
|
59
|
-
|
|
59
|
+
# We don't put a length byte on the final string.
|
|
60
|
+
msg.put_bytes(@property_value)
|
|
60
61
|
end
|
|
61
62
|
|
|
62
63
|
def self.decode_rdata(msg) #:nodoc: all
|
|
63
|
-
flag, = msg.get_unpack('
|
|
64
|
+
flag, = msg.get_unpack('C')
|
|
64
65
|
property_tag = msg.get_string
|
|
65
|
-
|
|
66
|
+
# The final string has no length byte - its length is implicit as the remainder of the packet length
|
|
67
|
+
property_value = msg.get_bytes
|
|
66
68
|
return self.new("#{flag} #{property_tag} \"#{property_value}\"")
|
|
67
69
|
end
|
|
68
70
|
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
module Dnsruby
|
|
2
|
+
class RR
|
|
3
|
+
# RFC4034, section 2
|
|
4
|
+
# DNSSEC uses public key cryptography to sign and authenticate DNS
|
|
5
|
+
# resource record sets (RRsets). The public keys are stored in DNSKEY
|
|
6
|
+
# resource records and are used in the DNSSEC authentication process
|
|
7
|
+
# described in [RFC4035]: A zone signs its authoritative RRsets by
|
|
8
|
+
# using a private key and stores the corresponding public key in a
|
|
9
|
+
# DNSKEY RR. A resolver can then use the public key to validate
|
|
10
|
+
# signatures covering the RRsets in the zone, and thus to authenticate
|
|
11
|
+
# them.
|
|
12
|
+
class CDNSKEY < DNSKEY
|
|
13
|
+
ClassValue = nil #:nodoc: all
|
|
14
|
+
TypeValue = Types::CDNSKEY #:nodoc: all
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# --
|
|
2
|
+
# Copyright 2018 Caerketton Tech Ltd
|
|
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
|
+
module Dnsruby
|
|
17
|
+
class RR
|
|
18
|
+
# RFC4034, section 4
|
|
19
|
+
# The DS Resource Record refers to a DNSKEY RR and is used in the DNS
|
|
20
|
+
# DNSKEY authentication process. A DS RR refers to a DNSKEY RR by
|
|
21
|
+
# storing the key tag, algorithm number, and a digest of the DNSKEY RR.
|
|
22
|
+
# Note that while the digest should be sufficient to identify the
|
|
23
|
+
# public key, storing the key tag and key algorithm helps make the
|
|
24
|
+
# identification process more efficient. By authenticating the DS
|
|
25
|
+
# record, a resolver can authenticate the DNSKEY RR to which the DS
|
|
26
|
+
# record points. The key authentication process is described in
|
|
27
|
+
# [RFC4035].
|
|
28
|
+
|
|
29
|
+
class CDS < DS
|
|
30
|
+
|
|
31
|
+
ClassValue = nil #:nodoc: all
|
|
32
|
+
TypeValue = Types::CDS #:nodoc: all
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -313,6 +313,8 @@ module Dnsruby
|
|
|
313
313
|
elsif [Algorithms.DSA,
|
|
314
314
|
Algorithms.DSA_NSEC3_SHA1].include?(@algorithm)
|
|
315
315
|
@public_key = dsa_key
|
|
316
|
+
elsif [Algorithms.ECDSAP256SHA256, Algorithms.ECDSAP384SHA384].include?(@algorithm)
|
|
317
|
+
@public_key = ec_key(Algorithms.ECDSAP256SHA256 == @algorithm ? 'prime256v1' : 'secp384r1')
|
|
316
318
|
end
|
|
317
319
|
end
|
|
318
320
|
# @TODO@ Support other key encodings!
|
|
@@ -340,8 +342,12 @@ module Dnsruby
|
|
|
340
342
|
@key_length = (@key.length - pos) * 8
|
|
341
343
|
|
|
342
344
|
pkey = OpenSSL::PKey::RSA.new
|
|
343
|
-
|
|
344
|
-
|
|
345
|
+
begin
|
|
346
|
+
pkey.set_key(modulus, exponent, nil) # use set_key, present in later versions of openssl gem
|
|
347
|
+
rescue NoMethodError
|
|
348
|
+
pkey.e = exponent # set_key not available in earlier versions, use this approach instead
|
|
349
|
+
pkey.n = modulus
|
|
350
|
+
end
|
|
345
351
|
return pkey
|
|
346
352
|
end
|
|
347
353
|
|
|
@@ -361,10 +367,31 @@ module Dnsruby
|
|
|
361
367
|
@key_length = (pgy_len * 8)
|
|
362
368
|
|
|
363
369
|
pkey = OpenSSL::PKey::DSA.new
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
370
|
+
begin
|
|
371
|
+
pkey.set_pgq(p,g,q)
|
|
372
|
+
pkey.set_key(y, nil) # use set_pgq and set_key, present in later versions of openssl gem
|
|
373
|
+
rescue NoMethodError
|
|
374
|
+
pkey.p = p # set_key not available in earlier versions, use this approach instead
|
|
375
|
+
pkey.q = q
|
|
376
|
+
pkey.g = g
|
|
377
|
+
pkey.pub_key = y
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
pkey
|
|
381
|
+
end
|
|
382
|
+
|
|
383
|
+
# RFC6605, section 4
|
|
384
|
+
# ECDSA public keys consist of a single value, called "Q" in FIPS
|
|
385
|
+
# 186-3. In DNSSEC keys, Q is a simple bit string that represents the
|
|
386
|
+
# uncompressed form of a curve point, "x | y".
|
|
387
|
+
def ec_key(curve = 'prime256v1')
|
|
388
|
+
group = OpenSSL::PKey::EC::Group.new(curve)
|
|
389
|
+
pkey = OpenSSL::PKey::EC.new(group)
|
|
390
|
+
|
|
391
|
+
# DNSSEC pub does not have first octet that determines whether it's uncompressed
|
|
392
|
+
# or compressed form, but it's required by OpenSSL to parse EC point correctly
|
|
393
|
+
point_from_pub = "\x04" + @key.to_s # octet string, \x04 prefix determines uncompressed
|
|
394
|
+
pkey.public_key = OpenSSL::PKey::EC::Point.new(group, point_from_pub)
|
|
368
395
|
|
|
369
396
|
pkey
|
|
370
397
|
end
|
data/lib/dnsruby/resource/IN.rb
CHANGED
|
@@ -19,7 +19,11 @@ module Dnsruby
|
|
|
19
19
|
Types::NS => NS,
|
|
20
20
|
Types::CNAME => CNAME,
|
|
21
21
|
Types::DNAME => DNAME,
|
|
22
|
+
Types::URI => URI,
|
|
23
|
+
Types::DS => DS,
|
|
24
|
+
Types::CDS => CDS,
|
|
22
25
|
Types::DNSKEY => DNSKEY,
|
|
26
|
+
Types::CDNSKEY => CDNSKEY,
|
|
23
27
|
Types::SOA => SOA,
|
|
24
28
|
Types::PTR => PTR,
|
|
25
29
|
Types::HINFO => HINFO,
|
|
@@ -45,7 +49,6 @@ module Dnsruby
|
|
|
45
49
|
Types::ANY => ANY,
|
|
46
50
|
Types::RRSIG => RRSIG,
|
|
47
51
|
Types::NSEC => NSEC,
|
|
48
|
-
Types::DS => DS,
|
|
49
52
|
Types::NSEC3 => NSEC3,
|
|
50
53
|
Types::NSEC3PARAM => NSEC3PARAM,
|
|
51
54
|
Types::DLV => DLV,
|
|
@@ -52,7 +52,7 @@ module Dnsruby
|
|
|
52
52
|
end
|
|
53
53
|
|
|
54
54
|
def from_string(input) #:nodoc: all
|
|
55
|
-
if (input.length > 0)
|
|
55
|
+
if (input.strip.length > 0)
|
|
56
56
|
values = input.split(" ")
|
|
57
57
|
@order = values [0].to_i
|
|
58
58
|
@preference = values [1].to_i
|
|
@@ -76,12 +76,14 @@ module Dnsruby
|
|
|
76
76
|
end
|
|
77
77
|
|
|
78
78
|
def encode_rdata(msg, canonical=false) #:nodoc: all
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
79
|
+
if (@order != nil)
|
|
80
|
+
msg.put_pack('n', @order)
|
|
81
|
+
msg.put_pack('n', @preference)
|
|
82
|
+
msg.put_string(@flags)
|
|
83
|
+
msg.put_string(@service)
|
|
84
|
+
msg.put_string(@regexp)
|
|
85
|
+
msg.put_name(@replacement, true)
|
|
86
|
+
end
|
|
85
87
|
end
|
|
86
88
|
|
|
87
89
|
def self.decode_rdata(msg) #:nodoc: all
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
module Dnsruby
|
|
2
|
+
class RR
|
|
3
|
+
class URI < RR
|
|
4
|
+
ClassValue = nil #:nodoc: all
|
|
5
|
+
TypeValue= Types::URI #:nodoc: all
|
|
6
|
+
|
|
7
|
+
# The NAPTR RR order field
|
|
8
|
+
attr_accessor :priority
|
|
9
|
+
|
|
10
|
+
# The NAPTR RR order field
|
|
11
|
+
attr_accessor :weight
|
|
12
|
+
|
|
13
|
+
# The NAPTR RR order field
|
|
14
|
+
attr_accessor :target
|
|
15
|
+
|
|
16
|
+
def from_hash(hash) #:nodoc: all
|
|
17
|
+
@priority = hash[:priority]
|
|
18
|
+
@weight = hash[:weight]
|
|
19
|
+
@target = hash[:target]
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def from_data(data) #:nodoc: all
|
|
23
|
+
@priority, @weight, @target = data
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def from_string(input) #:nodoc: all
|
|
27
|
+
if (input.strip.length > 0)
|
|
28
|
+
values = input.split(" ")
|
|
29
|
+
@priority = values [0].to_i
|
|
30
|
+
@weight = values [1].to_i
|
|
31
|
+
@target = values [2].gsub!("\"", "")
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def rdata_to_string #:nodoc: all
|
|
36
|
+
"#{@priority} #{@weight} \"#{@target}\""
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def encode_rdata(msg, canonical=false) #:nodoc: all
|
|
40
|
+
if (@priority != nil)
|
|
41
|
+
msg.put_pack('n', @priority)
|
|
42
|
+
msg.put_pack('n', @weight)
|
|
43
|
+
msg.put_bytes(@target)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def self.decode_rdata(msg) #:nodoc: all
|
|
48
|
+
priority, = msg.get_unpack('n')
|
|
49
|
+
weight, = msg.get_unpack('n')
|
|
50
|
+
target = msg.get_bytes
|
|
51
|
+
return self.new([priority, weight, target])
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
@@ -152,9 +152,12 @@ require 'dnsruby/resource/OPT'
|
|
|
152
152
|
require 'dnsruby/resource/TSIG'
|
|
153
153
|
require 'dnsruby/resource/TKEY'
|
|
154
154
|
require 'dnsruby/resource/DNSKEY'
|
|
155
|
+
require 'dnsruby/resource/CDNSKEY'
|
|
155
156
|
require 'dnsruby/resource/RRSIG'
|
|
156
157
|
require 'dnsruby/resource/NSEC'
|
|
157
158
|
require 'dnsruby/resource/DS'
|
|
159
|
+
require 'dnsruby/resource/CDS'
|
|
160
|
+
require 'dnsruby/resource/URI'
|
|
158
161
|
require 'dnsruby/resource/NSEC3'
|
|
159
162
|
require 'dnsruby/resource/NSEC3PARAM'
|
|
160
163
|
require 'dnsruby/resource/DLV'
|
|
@@ -24,7 +24,6 @@ require 'set'
|
|
|
24
24
|
require 'singleton'
|
|
25
25
|
require 'dnsruby/validator_thread.rb'
|
|
26
26
|
module Dnsruby
|
|
27
|
-
Thread::abort_on_exception = true
|
|
28
27
|
class SelectThread #:nodoc: all
|
|
29
28
|
class SelectWakeup < RuntimeError; end
|
|
30
29
|
include Singleton
|
|
@@ -195,7 +194,7 @@ module Dnsruby
|
|
|
195
194
|
rescue SelectWakeup
|
|
196
195
|
# If SelectWakeup, then just restart this loop - the select call will be made with the new data
|
|
197
196
|
next
|
|
198
|
-
rescue IOError => e
|
|
197
|
+
rescue IOError, EncodeError => e
|
|
199
198
|
# print "IO Error =: #{e}\n"
|
|
200
199
|
exceptions = clean_up_closed_sockets
|
|
201
200
|
exceptions.each { |exception| send_exception_to_client(*exception) }
|
|
@@ -65,6 +65,7 @@ module Dnsruby
|
|
|
65
65
|
@@recursor = Recursor.new
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
|
+
@@recursor.dnssec = true
|
|
68
69
|
return @@recursor
|
|
69
70
|
end
|
|
70
71
|
|
|
@@ -72,12 +73,15 @@ module Dnsruby
|
|
|
72
73
|
# if (Dnssec.do_validation_with_recursor?)
|
|
73
74
|
# return Recursor.new
|
|
74
75
|
# else
|
|
76
|
+
resolver = nil
|
|
75
77
|
if (Dnssec.default_resolver)
|
|
76
|
-
|
|
78
|
+
resolver = Dnssec.default_resolver
|
|
77
79
|
else
|
|
78
|
-
|
|
80
|
+
resolver = Resolver.new
|
|
79
81
|
end
|
|
80
82
|
# end
|
|
83
|
+
resolver.dnssec = true
|
|
84
|
+
return resolver
|
|
81
85
|
end
|
|
82
86
|
def add_dlv_key(key)
|
|
83
87
|
# Is this a ZSK or a KSK?
|
|
@@ -796,6 +800,19 @@ module Dnsruby
|
|
|
796
800
|
|
|
797
801
|
asn1 = OpenSSL::ASN1::Sequence.new([r_asn1, s_asn1]).to_der
|
|
798
802
|
verified = keyrec.public_key.verify(OpenSSL::Digest::DSS1.new, asn1, sig_data)
|
|
803
|
+
elsif [Algorithms.ECDSAP256SHA256, Algorithms.ECDSAP384SHA384].include?(sigrec.algorithm)
|
|
804
|
+
byte_size = (keyrec.public_key.group.degree + 7) / 8
|
|
805
|
+
sig_bytes = sigrec.signature[0..(byte_size - 1)]
|
|
806
|
+
sig_char = sigrec.signature[byte_size..-1] || ''
|
|
807
|
+
asn1 = OpenSSL::ASN1::Sequence.new([sig_bytes, sig_char].map { |int| OpenSSL::ASN1::Integer.new(OpenSSL::BN.new(int, 2)) }).to_der
|
|
808
|
+
|
|
809
|
+
digest_obj = if sigrec.algorithm == Algorithms.ECDSAP384SHA384
|
|
810
|
+
OpenSSL::Digest::SHA384.new
|
|
811
|
+
else
|
|
812
|
+
OpenSSL::Digest::SHA256.new
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
verified = keyrec.public_key.dsa_verify_asn1(digest_obj.digest(sig_data), asn1)
|
|
799
816
|
else
|
|
800
817
|
raise RuntimeError.new("Algorithm #{sigrec.algorithm.code} unsupported by Dnsruby")
|
|
801
818
|
end
|
|
@@ -848,6 +865,7 @@ module Dnsruby
|
|
|
848
865
|
end
|
|
849
866
|
end
|
|
850
867
|
end
|
|
868
|
+
res.dnssec = true
|
|
851
869
|
# query = Message.new(name, Types.DNSKEY)
|
|
852
870
|
# query.do_validation = false
|
|
853
871
|
ret = nil
|
|
@@ -1011,6 +1029,7 @@ module Dnsruby
|
|
|
1011
1029
|
end
|
|
1012
1030
|
end
|
|
1013
1031
|
end
|
|
1032
|
+
parent_res.dnssec = true
|
|
1014
1033
|
end
|
|
1015
1034
|
# Use that Resolver to query for DS record and NS for children
|
|
1016
1035
|
ds_rrset = current_anchor
|
|
@@ -1068,6 +1087,7 @@ module Dnsruby
|
|
|
1068
1087
|
child_res = Resolver.new
|
|
1069
1088
|
end
|
|
1070
1089
|
end
|
|
1090
|
+
child_res.dnssec = true
|
|
1071
1091
|
end
|
|
1072
1092
|
end
|
|
1073
1093
|
# Query for DNSKEY record, and verify against DS in parent.
|
|
@@ -1143,11 +1163,14 @@ module Dnsruby
|
|
|
1143
1163
|
if (Dnssec.do_validation_with_recursor?)
|
|
1144
1164
|
return get_recursor
|
|
1145
1165
|
else
|
|
1166
|
+
resolver = nil
|
|
1146
1167
|
if (Dnssec.default_resolver)
|
|
1147
|
-
|
|
1168
|
+
resolver = Dnssec.default_resolver
|
|
1148
1169
|
else
|
|
1149
|
-
|
|
1170
|
+
resolver = Resolver.new
|
|
1150
1171
|
end
|
|
1172
|
+
resolver.dnssec = true
|
|
1173
|
+
return resolver
|
|
1151
1174
|
end
|
|
1152
1175
|
end
|
|
1153
1176
|
|
data/lib/dnsruby/update.rb
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
# --
|
|
2
2
|
# Copyright 2007 Nominet UK
|
|
3
|
-
#
|
|
3
|
+
#
|
|
4
4
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
5
|
# you may not use this file except in compliance with the License.
|
|
6
6
|
# You may obtain a copy of the License at
|
|
7
|
-
#
|
|
7
|
+
#
|
|
8
8
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
9
|
-
#
|
|
9
|
+
#
|
|
10
10
|
# Unless required by applicable law or agreed to in writing, software
|
|
11
11
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
12
12
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
@@ -20,81 +20,81 @@ module Dnsruby
|
|
|
20
20
|
|
|
21
21
|
# The first example below shows a complete program; subsequent examples
|
|
22
22
|
# show only the creation of the update packet.
|
|
23
|
-
#
|
|
23
|
+
#
|
|
24
24
|
# == Add a new host
|
|
25
|
-
#
|
|
25
|
+
#
|
|
26
26
|
# require 'Dnsruby'
|
|
27
|
-
#
|
|
27
|
+
#
|
|
28
28
|
# # Create the update packet.
|
|
29
29
|
# update = Dnsruby::Update.new('example.com')
|
|
30
|
-
#
|
|
30
|
+
#
|
|
31
31
|
# # Prerequisite is that no A records exist for the name.
|
|
32
32
|
# update.absent('foo.example.com.', 'A')
|
|
33
|
-
#
|
|
33
|
+
#
|
|
34
34
|
# # Add two A records for the name.
|
|
35
35
|
# update.add('foo.example.com.', 'A', 86400, '192.168.1.2')
|
|
36
36
|
# update.add('foo.example.com.', 'A', 86400, '172.16.3.4')
|
|
37
|
-
#
|
|
37
|
+
#
|
|
38
38
|
# # Send the update to the zone's primary master.
|
|
39
39
|
# res = Dnsruby::Resolver.new({:nameserver => 'primary-master.example.com'})
|
|
40
|
-
#
|
|
40
|
+
#
|
|
41
41
|
# begin
|
|
42
42
|
# reply = res.send_message(update)
|
|
43
43
|
# print "Update succeeded\n"
|
|
44
44
|
# rescue Exception => e
|
|
45
45
|
# print 'Update failed: #{e}\n'
|
|
46
46
|
# end
|
|
47
|
-
#
|
|
47
|
+
#
|
|
48
48
|
# == Add an MX record for a name that already exists
|
|
49
|
-
#
|
|
49
|
+
#
|
|
50
50
|
# update = Dnsruby::Update.new('example.com')
|
|
51
51
|
# update.present('example.com')
|
|
52
|
-
# update.add('example.com', Dnsruby::Types.MX, 10, 'mailhost.example.com')
|
|
53
|
-
#
|
|
52
|
+
# update.add('example.com', Dnsruby::Types.MX, 86400, 10, 'mailhost.example.com')
|
|
53
|
+
#
|
|
54
54
|
# == Add a TXT record for a name that doesn't exist
|
|
55
|
-
#
|
|
55
|
+
#
|
|
56
56
|
# update = Dnsruby::Update.new('example.com')
|
|
57
57
|
# update.absent('info.example.com')
|
|
58
58
|
# update.add('info.example.com', Types.TXT, 86400, "yabba dabba doo"')
|
|
59
|
-
#
|
|
59
|
+
#
|
|
60
60
|
# == Delete all A records for a name
|
|
61
|
-
#
|
|
61
|
+
#
|
|
62
62
|
# update = Dnsruby::Update.new('example.com')
|
|
63
63
|
# update.present('foo.example.com', 'A')
|
|
64
64
|
# update.delete('foo.example.com', 'A')
|
|
65
|
-
#
|
|
65
|
+
#
|
|
66
66
|
# == Delete all RRs for a name
|
|
67
|
-
#
|
|
67
|
+
#
|
|
68
68
|
# update = Dnsruby::Update.new('example.com')
|
|
69
69
|
# update.present('byebye.example.com')
|
|
70
70
|
# update.delete('byebye.example.com')
|
|
71
|
-
#
|
|
71
|
+
#
|
|
72
72
|
# == Perform a signed update
|
|
73
|
-
#
|
|
73
|
+
#
|
|
74
74
|
# key_name = 'tsig-key'
|
|
75
75
|
# key = 'awwLOtRfpGE+rRKF2+DEiw=='
|
|
76
|
-
#
|
|
76
|
+
#
|
|
77
77
|
# update = Dnsruby::Update.new('example.com')
|
|
78
|
-
# update.add('foo.example.com', 'A', 86400, 10.1.2.3'))
|
|
79
|
-
# update.add('bar.example.com', 'A', 86400, 10.4.5.6'))
|
|
78
|
+
# update.add('foo.example.com', 'A', 86400, '10.1.2.3'))
|
|
79
|
+
# update.add('bar.example.com', 'A', 86400, '10.4.5.6'))
|
|
80
80
|
# res.tsig=(key_name,key)
|
|
81
|
-
#
|
|
81
|
+
#
|
|
82
82
|
class Update < Message
|
|
83
83
|
# Returns a Dnsruby::Update object suitable for performing a DNS
|
|
84
84
|
# dynamic update. Specifically, it creates a message with the header
|
|
85
85
|
# opcode set to UPDATE and the zone record type to SOA (per RFC 2136,
|
|
86
86
|
# Section 2.3).
|
|
87
|
-
#
|
|
87
|
+
#
|
|
88
88
|
# Programs must use the push method to add RRs to the prerequisite,
|
|
89
89
|
# update, and additional sections before performing the update.
|
|
90
|
-
#
|
|
90
|
+
#
|
|
91
91
|
# Arguments are the zone name and the class. If the zone is omitted,
|
|
92
92
|
# the default domain will be taken from the resolver configuration.
|
|
93
93
|
# If the class is omitted, it defaults to IN.
|
|
94
94
|
# packet = Dnsruby::Update.new
|
|
95
95
|
# packet = Dnsruby::Update.new('example.com')
|
|
96
96
|
# packet = Dnsruby::Update.new('example.com', 'HS')
|
|
97
|
-
#
|
|
97
|
+
#
|
|
98
98
|
def initialize(zone=nil, klass=nil)
|
|
99
99
|
|
|
100
100
|
# sort out the zone section (RFC2136, section 2.3)
|
|
@@ -115,25 +115,25 @@ module Dnsruby
|
|
|
115
115
|
end
|
|
116
116
|
|
|
117
117
|
# Ways to create the prerequisite records (exists, notexists, inuse, etc. - RFC2136, section 2.4)
|
|
118
|
-
#
|
|
118
|
+
#
|
|
119
119
|
# (1) RRset exists (value independent). At least one RR with a
|
|
120
120
|
# specified NAME and TYPE (in the zone and class specified by
|
|
121
121
|
# the Zone Section) must exist.
|
|
122
|
-
#
|
|
122
|
+
#
|
|
123
123
|
# update.present(name, type)
|
|
124
|
-
#
|
|
124
|
+
#
|
|
125
125
|
# (2) RRset exists (value dependent). A set of RRs with a
|
|
126
126
|
# specified NAME and TYPE exists and has the same members
|
|
127
127
|
# with the same RDATAs as the RRset specified here in this
|
|
128
128
|
# Section.
|
|
129
|
-
#
|
|
129
|
+
#
|
|
130
130
|
# update.present(name, type, rdata)
|
|
131
|
-
#
|
|
131
|
+
#
|
|
132
132
|
# (4) Name is in use. At least one RR with a specified NAME (in
|
|
133
133
|
# the zone and class specified by the Zone Section) must exist.
|
|
134
134
|
# Note that this prerequisite is NOT satisfied by empty
|
|
135
135
|
# nonterminals.
|
|
136
|
-
#
|
|
136
|
+
#
|
|
137
137
|
# update.present(name)
|
|
138
138
|
def present(*args)
|
|
139
139
|
ttl = 0
|
|
@@ -159,18 +159,18 @@ module Dnsruby
|
|
|
159
159
|
|
|
160
160
|
# Ways to create the prerequisite records (exists, notexists, inuse, etc. - RFC2136, section 2.4)
|
|
161
161
|
# Can be called with one arg :
|
|
162
|
-
#
|
|
162
|
+
#
|
|
163
163
|
# update.absent(name)
|
|
164
164
|
# (5) Name is not in use. No RR of any type is owned by a
|
|
165
165
|
# specified NAME. Note that this prerequisite IS satisfied by
|
|
166
166
|
# empty nonterminals.
|
|
167
|
-
#
|
|
167
|
+
#
|
|
168
168
|
# Or with two :
|
|
169
|
-
#
|
|
169
|
+
#
|
|
170
170
|
# update.absent(name, type)
|
|
171
171
|
# (3) RRset does not exist. No RRs with a specified NAME and TYPE
|
|
172
172
|
# (in the zone and class denoted by the Zone Section) can exist.
|
|
173
|
-
#
|
|
173
|
+
#
|
|
174
174
|
def absent(*args)
|
|
175
175
|
ttl = 0
|
|
176
176
|
rdata = ""
|
|
@@ -191,16 +191,16 @@ module Dnsruby
|
|
|
191
191
|
|
|
192
192
|
# Ways to create the update records (add, delete, RFC2136, section 2.5)
|
|
193
193
|
# " 2.5.1 - Add To An RRset
|
|
194
|
-
#
|
|
194
|
+
#
|
|
195
195
|
# RRs are added to the Update Section whose NAME, TYPE, TTL, RDLENGTH
|
|
196
196
|
# and RDATA are those being added, and CLASS is the same as the zone
|
|
197
197
|
# class. Any duplicate RRs will be silently ignored by the primary
|
|
198
198
|
# master."
|
|
199
|
-
#
|
|
199
|
+
#
|
|
200
200
|
# update.add(rr)
|
|
201
201
|
# update.add([rr1, rr2])
|
|
202
202
|
# update.add(name, type, ttl, rdata)
|
|
203
|
-
#
|
|
203
|
+
#
|
|
204
204
|
def add(*args)
|
|
205
205
|
zoneclass=zone()[0].zclass
|
|
206
206
|
case args[0]
|
|
@@ -244,17 +244,17 @@ module Dnsruby
|
|
|
244
244
|
end
|
|
245
245
|
|
|
246
246
|
# Ways to create the update records (add, delete, RFC2136, section 2.5)
|
|
247
|
-
#
|
|
247
|
+
#
|
|
248
248
|
# 2.5.2 - Delete An RRset
|
|
249
249
|
# update.delete(name, type)
|
|
250
|
-
#
|
|
251
|
-
#
|
|
250
|
+
#
|
|
251
|
+
#
|
|
252
252
|
# 2.5.3 - Delete All RRsets From A Name
|
|
253
253
|
# update.delete(name)
|
|
254
|
-
#
|
|
254
|
+
#
|
|
255
255
|
# 2.5.4 - Delete An RR From An RRset
|
|
256
256
|
# update.delete(name, type, rdata)
|
|
257
|
-
#
|
|
257
|
+
#
|
|
258
258
|
def delete(*args)
|
|
259
259
|
ttl = 0
|
|
260
260
|
klass = Classes.ANY
|
|
@@ -268,11 +268,28 @@ module Dnsruby
|
|
|
268
268
|
resource = RR.create("#{args[0]} #{ttl} #{klass} #{args[1]} #{rdata}")
|
|
269
269
|
add_update(resource)
|
|
270
270
|
when 3 # name, type, rdata
|
|
271
|
-
|
|
271
|
+
name = args[0]
|
|
272
|
+
type = args[1]
|
|
273
|
+
rdata = args[2]
|
|
274
|
+
if (Types.new(type) == Types.TXT)
|
|
275
|
+
instring = "#{name} #{ttl} IN #{type} ";
|
|
276
|
+
if (String === rdata)
|
|
277
|
+
instring += " '#{rdata}'"
|
|
278
|
+
elsif (Array === rdata)
|
|
279
|
+
rdata.length.times {|rcounter|
|
|
280
|
+
instring += " '#{rdata[rcounter]}' "
|
|
281
|
+
}
|
|
282
|
+
else
|
|
283
|
+
instring += rdata
|
|
284
|
+
end
|
|
285
|
+
resource = RR.create(instring)
|
|
286
|
+
else
|
|
287
|
+
resource = RR.create("#{name} #{ttl} IN #{type} #{rdata}")
|
|
288
|
+
end
|
|
272
289
|
resource.klass = Classes.NONE
|
|
273
290
|
add_update(resource)
|
|
274
291
|
end
|
|
275
292
|
return resource
|
|
276
293
|
end
|
|
277
294
|
end
|
|
278
|
-
end
|
|
295
|
+
end
|