dnsruby 1.60.2 → 1.61.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -5
- data/Gemfile +2 -0
- data/README.md +6 -4
- data/RELEASE_NOTES.md +20 -0
- data/demo/digroot.rb +2 -0
- data/dnsruby.gemspec +2 -0
- data/lib/dnsruby/code_mappers.rb +3 -0
- data/lib/dnsruby/config.rb +23 -4
- data/lib/dnsruby/message/encoder.rb +2 -2
- data/lib/dnsruby/message/header.rb +15 -15
- data/lib/dnsruby/name.rb +20 -2
- data/lib/dnsruby/packet_sender.rb +13 -1
- data/lib/dnsruby/recursor.rb +10 -1
- data/lib/dnsruby/resolver.rb +11 -0
- data/lib/dnsruby/resource/CDNSKEY.rb +17 -0
- data/lib/dnsruby/resource/CDS.rb +35 -0
- data/lib/dnsruby/resource/DNSKEY.rb +15 -6
- data/lib/dnsruby/resource/IN.rb +4 -1
- data/lib/dnsruby/resource/URI.rb +57 -0
- data/lib/dnsruby/resource/generic.rb +3 -0
- data/lib/dnsruby/select_thread.rb +1 -1
- data/lib/dnsruby/single_verifier.rb +14 -4
- data/lib/dnsruby/version.rb +1 -1
- data/lib/dnsruby/zone_transfer.rb +5 -1
- data/test/tc_dns.rb +5 -0
- data/test/tc_resolver.rb +26 -0
- data/test/tc_rr.rb +33 -0
- data/test/tc_soak.rb +4 -0
- data/test/tc_tcp_pipelining.rb +7 -0
- metadata +19 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 809b0ba42057c7e1dbec1239f295b2766b345c08
|
4
|
+
data.tar.gz: fdcd08cf292f773ac6e1423acdbee6d810ffd1c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec0a38bb9fb0c517736727579606fa82bf04d03b81a918a19e1f660da746e6333c136f7fd9bb51f804d84d4132a6f9ea73a7dab7e3b2235b3c0aa4562efe4fa4
|
7
|
+
data.tar.gz: 2445c9aa9154a253a9c32c300d11b4166eaa2366be18dc8d6732f6ac3b4df5a5e64afa724ca59155ab8b425023239ac86ab309042b19b6d84d0cdd4a4508bdd1
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,8 @@
|
|
1
1
|
[![Build Status](https://travis-ci.org/alexdalitz/dnsruby.svg?branch=master)](https://travis-ci.org/alexdalitz/dnsruby)
|
2
2
|
[![Coverage Status](https://img.shields.io/coveralls/alexdalitz/dnsruby.svg)](https://coveralls.io/r/alexdalitz/dnsruby?branch=master)
|
3
3
|
|
4
|
+
<img src="http://caerkettontech.com/dnsruby/DNSRuby-colour-mid.png" width="200" height="200" />
|
5
|
+
|
4
6
|
Dnsruby
|
5
7
|
=======
|
6
8
|
|
@@ -16,10 +18,10 @@ queries. It is therefore suitable for high volume DNS applications.
|
|
16
18
|
|
17
19
|
The following is a (non-exhaustive) list of features :
|
18
20
|
|
19
|
-
- Implemented RRs : A, AAAA, AFSDB, ANY, CERT, CNAME, DNAME,
|
20
|
-
HINFO, ISDN, LOC, MB, MG, MINFO, MR, MX, NAPTR, NS, NSAP,
|
21
|
-
OPT, PTR, PX, RP, RT, SOA, SPF, SRV, TKEY, TSIG, TXT,
|
22
|
-
X25, DNSKEY, RRSIG, NSEC, NSEC3, NSEC3PARAM, DS, DLV
|
21
|
+
- Implemented RRs : A, AAAA, AFSDB, ANY, CAA, CERT, CNAME, DNAME,
|
22
|
+
GPOS, HINFO, ISDN, LOC, MB, MG, MINFO, MR, MX, NAPTR, NS, NSAP,
|
23
|
+
NXT, OPT, PTR, PX, RP, RT, SOA, SPF, SRV, TKEY, TSIG, TXT,
|
24
|
+
WKS, X25, DNSKEY, RRSIG, NSEC, NSEC3, NSEC3PARAM, DS, DLV
|
23
25
|
|
24
26
|
- Generic RR types supported (RFC3597)
|
25
27
|
|
data/RELEASE_NOTES.md
CHANGED
@@ -1,5 +1,25 @@
|
|
1
1
|
# Release Notes
|
2
2
|
|
3
|
+
## v1.61.1
|
4
|
+
|
5
|
+
* Add Addressable as a gem runtime dependency
|
6
|
+
|
7
|
+
## v1.61.0
|
8
|
+
|
9
|
+
* Add URI, CDS and CDNSKEY records
|
10
|
+
* Supply port to DNS.new as optiona parameter
|
11
|
+
* Supply timeout to zone transfer connect
|
12
|
+
* Fix multi-line strings
|
13
|
+
* Try absolute name as candidate in DNS even if not dot supplied
|
14
|
+
* Do not try to generate candidates if no domain is given
|
15
|
+
* Handle new OpenSSL interface as well as old
|
16
|
+
* Handle new DSA interface
|
17
|
+
* fix encode error select thread issue
|
18
|
+
* handle encoding errors
|
19
|
+
* add punycode support
|
20
|
+
* Make sure dnssec is enabled in verifier and also in digroot demo
|
21
|
+
* Other minor fixes and changes to test code and infrastructure
|
22
|
+
|
3
23
|
## v1.60.2
|
4
24
|
|
5
25
|
* Fix deletion of TXT records with spaces in dynamic updates (thanks Sean Dilda)
|
data/demo/digroot.rb
CHANGED
data/dnsruby.gemspec
CHANGED
data/lib/dnsruby/code_mappers.rb
CHANGED
@@ -162,6 +162,8 @@ module Dnsruby
|
|
162
162
|
NSEC3PARAM= 51 # RFC still pending at time of writing
|
163
163
|
TLSA = 52 # RFC 6698
|
164
164
|
HIP = 55 # RFC 5205
|
165
|
+
CDS = 59 # RFC 7344
|
166
|
+
CDNSKEY = 60 # RFC 7344
|
165
167
|
SPF = 99 # RFC 4408
|
166
168
|
UINFO = 100 # non-standard
|
167
169
|
UID = 101 # non-standard
|
@@ -174,6 +176,7 @@ module Dnsruby
|
|
174
176
|
MAILB = 253 # RFC 1035 (MB, MG, MR)
|
175
177
|
MAILA = 254 # RFC 1035 (obsolete - see MX)
|
176
178
|
ANY = 255 # RFC 1035
|
179
|
+
URI = 256 # RFC 7553
|
177
180
|
CAA = 257 # RFC 6844
|
178
181
|
DLV = 32769 # RFC 4431 (informational)
|
179
182
|
update()
|
data/lib/dnsruby/config.rb
CHANGED
@@ -101,6 +101,7 @@ module Dnsruby
|
|
101
101
|
dom=""
|
102
102
|
nd = 1
|
103
103
|
@ndots = 1
|
104
|
+
@port = 53
|
104
105
|
@apply_search_list = true
|
105
106
|
@apply_domain = true
|
106
107
|
config_hash = Config.default_config_hash
|
@@ -122,6 +123,7 @@ module Dnsruby
|
|
122
123
|
ns = config_hash[:nameserver] if config_hash.include? :nameserver
|
123
124
|
s = config_hash[:search] if config_hash.include? :search
|
124
125
|
nd = config_hash[:ndots] if config_hash.include? :ndots
|
126
|
+
p = config_hash[:port] if config_hash.include? :port
|
125
127
|
@apply_search_list = config_hash[:apply_search_list] if config_hash.include? :apply_search_list
|
126
128
|
@apply_domain= config_hash[:apply_domain] if config_hash.include? :apply_domain
|
127
129
|
dom = config_hash[:domain] if config_hash.include? :domain
|
@@ -132,6 +134,7 @@ module Dnsruby
|
|
132
134
|
@configured = true
|
133
135
|
send("search=",s)
|
134
136
|
send("ndots=",nd)
|
137
|
+
send("port=",p)
|
135
138
|
send("domain=",dom)
|
136
139
|
}
|
137
140
|
Dnsruby.log.info{to_s}
|
@@ -159,6 +162,15 @@ module Dnsruby
|
|
159
162
|
end
|
160
163
|
end
|
161
164
|
|
165
|
+
# Set port
|
166
|
+
def port=(p)
|
167
|
+
@configured = true
|
168
|
+
@port=p
|
169
|
+
if !@port.kind_of?(Integer)
|
170
|
+
raise ArgumentError.new("invalid port config: #{@port.inspect}")
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
162
174
|
# Set the default search path
|
163
175
|
def search=(s)
|
164
176
|
@configured = true
|
@@ -303,6 +315,7 @@ module Dnsruby
|
|
303
315
|
search = nil
|
304
316
|
domain = nil
|
305
317
|
ndots = 1
|
318
|
+
port = 53
|
306
319
|
open(filename) {|f|
|
307
320
|
f.each {|line|
|
308
321
|
line.sub!(/[#;].*/, '')
|
@@ -312,6 +325,8 @@ module Dnsruby
|
|
312
325
|
}
|
313
326
|
next unless keyword
|
314
327
|
case keyword
|
328
|
+
when 'port'
|
329
|
+
port = args[0].to_i
|
315
330
|
when 'nameserver'
|
316
331
|
nameserver += args
|
317
332
|
when 'domain'
|
@@ -337,7 +352,7 @@ module Dnsruby
|
|
337
352
|
end
|
338
353
|
}
|
339
354
|
}
|
340
|
-
return { :nameserver => nameserver, :domain => domain, :search => search, :ndots => ndots }
|
355
|
+
return { :nameserver => nameserver, :domain => domain, :search => search, :ndots => ndots, :port => port }
|
341
356
|
end
|
342
357
|
|
343
358
|
def inspect #:nodoc: all
|
@@ -357,6 +372,7 @@ module Dnsruby
|
|
357
372
|
ret += " domain : #{domain_string}, search : "
|
358
373
|
search.each {|s| ret += s + ", " }
|
359
374
|
ret += " ndots : #{@ndots}"
|
375
|
+
ret += " port : #{@port}"
|
360
376
|
return ret
|
361
377
|
end
|
362
378
|
|
@@ -423,18 +439,21 @@ module Dnsruby
|
|
423
439
|
end
|
424
440
|
end
|
425
441
|
|
426
|
-
def generate_candidates(
|
442
|
+
def generate_candidates(name_in) #:nodoc: all
|
427
443
|
if !@configured
|
428
444
|
parse_config
|
429
445
|
end
|
430
446
|
candidates = []
|
431
|
-
name = Name.create(
|
447
|
+
name = Name.create(name_in)
|
432
448
|
if name.absolute?
|
433
449
|
candidates = [name]
|
434
450
|
else
|
451
|
+
candidates.push(Name.create(name_in.to_s + "."))
|
435
452
|
if (@apply_domain)
|
436
453
|
if @ndots > name.length - 1
|
437
|
-
|
454
|
+
if (@domain != nil)
|
455
|
+
candidates.push(Name.create(name.to_a+@domain))
|
456
|
+
end
|
438
457
|
end
|
439
458
|
end
|
440
459
|
if (!@apply_search_list)
|
@@ -18,7 +18,7 @@ class MessageEncoder #:nodoc: all
|
|
18
18
|
begin
|
19
19
|
@data << d.pack(template)
|
20
20
|
rescue Encoding::CompatibilityError => e
|
21
|
-
raise Dnsruby::
|
21
|
+
raise Dnsruby::EncodeError.new("IDN support currently requires punycode string")
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
@@ -36,7 +36,7 @@ class MessageEncoder #:nodoc: all
|
|
36
36
|
self.put_pack("C", d.length)
|
37
37
|
@data << d
|
38
38
|
rescue Encoding::CompatibilityError => e
|
39
|
-
raise Dnsruby::
|
39
|
+
raise Dnsruby::EncodeError.new("IDN support currently requires punycode string")
|
40
40
|
end
|
41
41
|
end
|
42
42
|
|
@@ -190,29 +190,29 @@ class Header
|
|
190
190
|
retval = ";; id = #{@id}\n"
|
191
191
|
|
192
192
|
if (@opcode == OpCode::Update)
|
193
|
-
retval += ";; qr = #{@qr} "
|
194
|
-
"opcode = #{@opcode.string} "
|
193
|
+
retval += ";; qr = #{@qr} " \
|
194
|
+
"opcode = #{@opcode.string} "\
|
195
195
|
"rcode = #{@rcode.string}\n"
|
196
196
|
|
197
|
-
retval += ";; zocount = #{@qdcount} "
|
198
|
-
"prcount = #{@ancount} "
|
199
|
-
"upcount = #{@nscount} "
|
197
|
+
retval += ";; zocount = #{@qdcount} "\
|
198
|
+
"prcount = #{@ancount} " \
|
199
|
+
"upcount = #{@nscount} " \
|
200
200
|
"adcount = #{@arcount}\n"
|
201
201
|
else
|
202
|
-
retval += ";; qr = #{@qr} "
|
203
|
-
"opcode = #{@opcode.string} "
|
204
|
-
"aa = #{@aa} "
|
205
|
-
"tc = #{@tc} "
|
202
|
+
retval += ";; qr = #{@qr} " \
|
203
|
+
"opcode = #{@opcode.string} " \
|
204
|
+
"aa = #{@aa} " \
|
205
|
+
"tc = #{@tc} " \
|
206
206
|
"rd = #{@rd}\n"
|
207
207
|
|
208
|
-
retval += ";; ra = #{@ra} "
|
209
|
-
"ad = #{@ad} "
|
210
|
-
"cd = #{@cd} "
|
208
|
+
retval += ";; ra = #{@ra} " \
|
209
|
+
"ad = #{@ad} " \
|
210
|
+
"cd = #{@cd} " \
|
211
211
|
"rcode = #{rcode.string}\n"
|
212
212
|
|
213
|
-
retval += ";; qdcount = #{@qdcount} "
|
214
|
-
"ancount = #{@ancount} "
|
215
|
-
"nscount = #{@nscount} "
|
213
|
+
retval += ";; qdcount = #{@qdcount} " \
|
214
|
+
"ancount = #{@ancount} " \
|
215
|
+
"nscount = #{@nscount} " \
|
216
216
|
"arcount = #{@arcount}\n"
|
217
217
|
end
|
218
218
|
|
data/lib/dnsruby/name.rb
CHANGED
@@ -26,7 +26,8 @@ module Dnsruby
|
|
26
26
|
# * Name#wild?
|
27
27
|
# * Name#subdomain_of?(other)
|
28
28
|
# * Name#labels
|
29
|
-
#
|
29
|
+
#
|
30
|
+
require 'addressable'
|
30
31
|
class Name
|
31
32
|
include Comparable
|
32
33
|
MaxNameLength=255
|
@@ -52,6 +53,7 @@ module Dnsruby
|
|
52
53
|
if (arg=="")
|
53
54
|
return Name.new([],false)
|
54
55
|
end
|
56
|
+
arg = punycode(arg)
|
55
57
|
return Name.new(split_escaped(arg), /\.\z/ =~ arg ? true : false)
|
56
58
|
# return Name.new(Label.split(arg), /\.\z/ =~ arg ? true : false)
|
57
59
|
when Array
|
@@ -61,6 +63,22 @@ module Dnsruby
|
|
61
63
|
end
|
62
64
|
end
|
63
65
|
|
66
|
+
def self.punycode(d)
|
67
|
+
begin
|
68
|
+
c = Addressable::URI.parse("http://" + d.to_s)
|
69
|
+
ret = c.normalized_host.sub("http://", "")
|
70
|
+
if (!d.end_with?".")
|
71
|
+
return ret.chomp(".")
|
72
|
+
end
|
73
|
+
if (!ret.end_with?".")
|
74
|
+
return ret + "."
|
75
|
+
end
|
76
|
+
return ret
|
77
|
+
rescue Exception => e
|
78
|
+
return d
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
64
82
|
def self.split_escaped(arg) #:nodoc: all
|
65
83
|
encodedlabels = name2encodedlabels(arg)
|
66
84
|
return encodedlabels
|
@@ -317,7 +335,7 @@ module Dnsruby
|
|
317
335
|
i=0;
|
318
336
|
|
319
337
|
while (i < length )
|
320
|
-
c=presentation.unpack("x#{i}C1")
|
338
|
+
c=presentation.unpack("x#{i}C1")[0]
|
321
339
|
if (c == 46) # ord('.')
|
322
340
|
endstring = presentation[i+1, presentation.length-(i+1)]
|
323
341
|
return Label.new(wire),endstring
|
@@ -331,7 +331,14 @@ module Dnsruby
|
|
331
331
|
client_query_id = Time.now + rand(10000) # is this safe?!
|
332
332
|
end
|
333
333
|
|
334
|
-
|
334
|
+
begin
|
335
|
+
query_packet = make_query_packet(msg, use_tcp)
|
336
|
+
rescue EncodeError => err
|
337
|
+
Dnsruby.log.error { "#{err}" }
|
338
|
+
st = SelectThread.instance
|
339
|
+
st.push_exception_to_select(client_query_id, client_queue, err, nil)
|
340
|
+
return
|
341
|
+
end
|
335
342
|
|
336
343
|
if (msg.do_caching && (msg.class != Update))
|
337
344
|
# Check the cache!!
|
@@ -622,6 +629,11 @@ module Dnsruby
|
|
622
629
|
# Should send error back up to Resolver here, and then NOT QUERY AGAIN!!!
|
623
630
|
return sig_value
|
624
631
|
end
|
632
|
+
if ((response.header.get_header_rcode == RCode.FORMERR) &&
|
633
|
+
(query.header.arcount == 0))
|
634
|
+
# Raise an error
|
635
|
+
return true
|
636
|
+
end
|
625
637
|
# Should check that question section is same as question that was sent! RFC 5452
|
626
638
|
# If it's not an update...
|
627
639
|
if (query.class == Update)
|
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
@@ -891,6 +891,14 @@ module Dnsruby
|
|
891
891
|
return
|
892
892
|
end
|
893
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
|
+
|
894
902
|
tick_needed = false
|
895
903
|
# add to our data structures
|
896
904
|
# @mutex.synchronize{
|
@@ -1124,6 +1132,9 @@ module Dnsruby
|
|
1124
1132
|
increment_resolver_priority(resolver) unless response.cached
|
1125
1133
|
stop_querying(client_query_id)
|
1126
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)
|
1127
1138
|
else
|
1128
1139
|
# - if it was any other error, then remove that server from the list for that query
|
1129
1140
|
# If a Too Many Open Files error, then don't remove, but let retry work.
|
@@ -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
|
@@ -340,8 +340,12 @@ module Dnsruby
|
|
340
340
|
@key_length = (@key.length - pos) * 8
|
341
341
|
|
342
342
|
pkey = OpenSSL::PKey::RSA.new
|
343
|
-
|
344
|
-
|
343
|
+
begin
|
344
|
+
pkey.set_key(modulus, exponent, nil) # use set_key, present in later versions of openssl gem
|
345
|
+
rescue NoMethodError
|
346
|
+
pkey.e = exponent # set_key not available in earlier versions, use this approach instead
|
347
|
+
pkey.n = modulus
|
348
|
+
end
|
345
349
|
return pkey
|
346
350
|
end
|
347
351
|
|
@@ -361,10 +365,15 @@ module Dnsruby
|
|
361
365
|
@key_length = (pgy_len * 8)
|
362
366
|
|
363
367
|
pkey = OpenSSL::PKey::DSA.new
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
+
begin
|
369
|
+
pkey.set_pgq(p,g,q)
|
370
|
+
pkey.set_key(y, nil) # use set_pgq and set_key, present in later versions of openssl gem
|
371
|
+
rescue NoMethodError
|
372
|
+
pkey.p = p # set_key not available in earlier versions, use this approach instead
|
373
|
+
pkey.q = q
|
374
|
+
pkey.g = g
|
375
|
+
pkey.pub_key = y
|
376
|
+
end
|
368
377
|
|
369
378
|
pkey
|
370
379
|
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,
|
@@ -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'
|
@@ -194,7 +194,7 @@ module Dnsruby
|
|
194
194
|
rescue SelectWakeup
|
195
195
|
# If SelectWakeup, then just restart this loop - the select call will be made with the new data
|
196
196
|
next
|
197
|
-
rescue IOError => e
|
197
|
+
rescue IOError, EncodeError => e
|
198
198
|
# print "IO Error =: #{e}\n"
|
199
199
|
exceptions = clean_up_closed_sockets
|
200
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?
|
@@ -848,6 +852,7 @@ module Dnsruby
|
|
848
852
|
end
|
849
853
|
end
|
850
854
|
end
|
855
|
+
res.dnssec = true
|
851
856
|
# query = Message.new(name, Types.DNSKEY)
|
852
857
|
# query.do_validation = false
|
853
858
|
ret = nil
|
@@ -1011,6 +1016,7 @@ module Dnsruby
|
|
1011
1016
|
end
|
1012
1017
|
end
|
1013
1018
|
end
|
1019
|
+
parent_res.dnssec = true
|
1014
1020
|
end
|
1015
1021
|
# Use that Resolver to query for DS record and NS for children
|
1016
1022
|
ds_rrset = current_anchor
|
@@ -1068,6 +1074,7 @@ module Dnsruby
|
|
1068
1074
|
child_res = Resolver.new
|
1069
1075
|
end
|
1070
1076
|
end
|
1077
|
+
child_res.dnssec = true
|
1071
1078
|
end
|
1072
1079
|
end
|
1073
1080
|
# Query for DNSKEY record, and verify against DS in parent.
|
@@ -1143,11 +1150,14 @@ module Dnsruby
|
|
1143
1150
|
if (Dnssec.do_validation_with_recursor?)
|
1144
1151
|
return get_recursor
|
1145
1152
|
else
|
1153
|
+
resolver = nil
|
1146
1154
|
if (Dnssec.default_resolver)
|
1147
|
-
|
1155
|
+
resolver = Dnssec.default_resolver
|
1148
1156
|
else
|
1149
|
-
|
1157
|
+
resolver = Resolver.new
|
1150
1158
|
end
|
1159
|
+
resolver.dnssec = true
|
1160
|
+
return resolver
|
1151
1161
|
end
|
1152
1162
|
end
|
1153
1163
|
|
data/lib/dnsruby/version.rb
CHANGED
@@ -33,6 +33,8 @@ module Dnsruby
|
|
33
33
|
attr_reader :tsig
|
34
34
|
# Returns the tsigstate of the last transfer (nil if no TSIG signed transfer has occurred)
|
35
35
|
attr_reader :last_tsigstate
|
36
|
+
# Sets the connect timeout in seconds
|
37
|
+
attr_accessor :connect_timeout
|
36
38
|
|
37
39
|
# Sets the TSIG to sign the zone transfer with.
|
38
40
|
# Pass in either a Dnsruby::RR::TSIG, or a key_name and key (or just a key)
|
@@ -54,6 +56,7 @@ module Dnsruby
|
|
54
56
|
@tsig = nil
|
55
57
|
@axfr = nil
|
56
58
|
@src_address = nil
|
59
|
+
@connect_timeout = 5
|
57
60
|
end
|
58
61
|
|
59
62
|
# Perform a zone transfer (RFC1995)
|
@@ -107,7 +110,8 @@ module Dnsruby
|
|
107
110
|
def do_transfer(zone, server) #:nodoc: all
|
108
111
|
@transfer_type = Types.new(@transfer_type)
|
109
112
|
@state = :InitialSoa
|
110
|
-
socket =
|
113
|
+
socket = Socket.tcp(server, @port, @src_address, connect_timeout: @connect_timeout)
|
114
|
+
# socket = TCPSocket.new(server, @port, @src_address)
|
111
115
|
begin
|
112
116
|
# Send an initial query
|
113
117
|
msg = Message.new(zone, @transfer_type, @klass)
|
data/test/tc_dns.rb
CHANGED
@@ -248,5 +248,10 @@ class TestDNS < Minitest::Test
|
|
248
248
|
# assert_equal(a[0].name.to_s, 'a.t.dnsruby.validation-test-servers.nominet.org.uk',"Correct name (with persistent socket and #{method})")
|
249
249
|
end
|
250
250
|
|
251
|
+
def test_port
|
252
|
+
d = DNS.new({:port => 5353})
|
253
|
+
assert_true(d.to_s.include?"5353")
|
254
|
+
end
|
255
|
+
|
251
256
|
end
|
252
257
|
end
|
data/test/tc_resolver.rb
CHANGED
@@ -374,5 +374,31 @@ class TestRawQuery < Minitest::Test
|
|
374
374
|
assert_equal KEY, options[:key]
|
375
375
|
assert_equal ALGO, options[:algorithm]
|
376
376
|
end
|
377
|
+
|
378
|
+
def test_threads
|
379
|
+
resolver = Dnsruby::Resolver.new(nameserver: ["8.8.8.8", "8.8.4.4"])
|
380
|
+
resolver.query("google.com", "MX")
|
381
|
+
resolver.query("google.com", "MX")
|
382
|
+
resolver.query("google.com", "MX")
|
383
|
+
begin
|
384
|
+
resolver.query("googlöe.com", "MX")
|
385
|
+
rescue Dnsruby::ResolvError => e
|
386
|
+
# fine
|
387
|
+
end
|
388
|
+
resolver.query("google.com", "MX")
|
389
|
+
resolver.query("google.com", "MX")
|
390
|
+
begin
|
391
|
+
resolver.query("googlöe.com", "MX")
|
392
|
+
rescue Dnsruby::ResolvError => e
|
393
|
+
# fine
|
394
|
+
end
|
395
|
+
begin
|
396
|
+
resolver.query("googlöe.com", "MX")
|
397
|
+
rescue Dnsruby::ResolvError => e
|
398
|
+
# fine
|
399
|
+
end
|
400
|
+
# Dnsruby::Cache.delete("googlöe.com", "MX")
|
401
|
+
|
402
|
+
end
|
377
403
|
end
|
378
404
|
|
data/test/tc_rr.rb
CHANGED
@@ -285,6 +285,39 @@ class TestRR < Minitest::Test
|
|
285
285
|
update.encode
|
286
286
|
end
|
287
287
|
|
288
|
+
def test_uri
|
289
|
+
rrString = "_ftp._tcp.\t300\tIN\tURI\t10\ 1 \"ftp://ftp1.example.com/public\""
|
290
|
+
rr = RR.create(rrString)
|
291
|
+
assert(rrString.to_s == rr.to_s)
|
292
|
+
m = Dnsruby::Message.new
|
293
|
+
m.add_additional(rr)
|
294
|
+
m2 = Message.decode(m.encode)
|
295
|
+
rr2 = m2.additional()[0]
|
296
|
+
assert(rr == rr2)
|
297
|
+
end
|
298
|
+
|
299
|
+
def test_cds
|
300
|
+
rrString = "dskey.example.com.\t86400\tIN\tCDS\t60485 RSASHA1 1 ( 2BB183AF5F22588179A53B0A98631FAD1A292118 )"
|
301
|
+
rr = RR.create(rrString)
|
302
|
+
assert(rrString.to_s == rr.to_s)
|
303
|
+
m = Dnsruby::Message.new
|
304
|
+
m.add_additional(rr)
|
305
|
+
m2 = Message.decode(m.encode)
|
306
|
+
rr2 = m2.additional()[0]
|
307
|
+
assert(rr.to_s == rr2.to_s)
|
308
|
+
end
|
309
|
+
|
310
|
+
def test_cdnskey
|
311
|
+
rrString = "tjeb.nl.\t3600\tIN\tCDNSKEY\t256 3 RSASHA1-NSEC3-SHA1 ( AwEAAcglEOS7bECRK5fqTuGTMJycmDhTzmUu/EQbAhKJOYJxDb5SG/RYqsJgzG7wgtGy0W1aP7I4k6SPtHmwcqjLaZLVUwRNWCGr2adjb9JTFyBR7F99Ngi11lEGM6Uiw/eDRk66lhoSGzohjj/rmhRTV6gN2+0ADPnafv3MBkPgryA3 ) ; key_tag=53177"
|
312
|
+
rr = RR.create(rrString)
|
313
|
+
assert(rrString.to_s == rr.to_s)
|
314
|
+
m = Dnsruby::Message.new
|
315
|
+
m.add_additional(rr)
|
316
|
+
m2 = Message.decode(m.encode)
|
317
|
+
rr2 = m2.additional()[0]
|
318
|
+
assert(rr.to_s == rr2.to_s)
|
319
|
+
end
|
320
|
+
|
288
321
|
def test_cert
|
289
322
|
rr = RR.create("test.kht.se. 60 IN CERT PGP 0 0 mQGiBDnY2vERBAD3cOxqoAYHYzS+xttvuyN9wZS8CrgwLIlT8Ewo/CCFI11PEO+gJyNPvWPRQsyt1SE60reaIsie2bQTg3DYIg0PmH+ZOlNkpKesPULzdlw4Rx3dD/M3Lkrm977h4Y70ZKC+tbvoYKCCOIkUVevny1PVZ+mB94rb0mMgawSTrct03QCg/w6aHNJFQV7O9ZQ1Fir85M3RS8cEAOo4/1ASVudz3qKZQEhU2Z9O2ydXqpEanHfGirjWYi5RelVsQ9IfBSPFaPAWzQ24nvQ18NU7TgdDQhP4meZXiVXcLBR5Mee2kByf2KAnBUF9aah5s8wZbSrC6u8xEZLuiauvWmCUIWe0Ylc1/L37XeDjrBI2pT+k183X119d6Fr1BACGfZVGsot5rxBUEFPPSrBqYXG/0hRYv9Eq8a4rJAHK2IUWYfivZgL4DtrJnHlha+H5EPQVYkIAN3nGjXoHmosY+J3Sk+GyR+dCBHEwCkoHMKph3igczCEfxAWgqKeYd5mf+QQq2JKrkn2jceiIO7s3CrepeEFAjDSGuxhZjPJVm7QoRGFuaWVsIFAuIE1haG9uZXkgPGRhbm1AcHJpbWUuZ3VzaGkub3JnPohOBBARAgAOBQI52NrxBAsDAQICGQEACgkQ+75aMGJLskn6LgCbBXUD7UmGla5e1zyhuY667hP3F+UAoJIeDZJyRFkQAmb+u8KekRyLD1MLtDJEYW5pZWwgTWFob25leSAoU2Vjb25kYXJ5IEVtYWlsKSA8Z3VzaGlAZ3VzaGkub3JnPohgBBMRAgAgBQJF1J/XAhsjBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQ+75aMGJLskkVhACggsivQ9qLhfdA1rGm6f8LRJBSC4wAoI930h+/hshClj6AkNwGRtHdf5XJuQINBDnY2vQQCAD2Qle3CH8IF3KiutapQvMF6PlTETlPtvFuuUs4INoBp1ajFOmPQFXz0AfGy0OplK33TGSGSfgMg71l6RfUodNQ+PVZX9x2Uk89PY3bzpnhV5JZzf24rnRPxfx2vIPFRzBhznzJZv8V+bv9kV7HAarTW56NoKVyOtQa8L9GAFgr5fSI/VhOSdvNILSd5JEHNmszbDgNRR0PfIizHHxbLY7288kjwEPwpVsYjY67VYy4XTjTNP18F1dDox0YbN4zISy1Kv884bEpQBgRjXyEpwpy1obEAxnIByl6ypUM2Zafq9AKUJsCRtMIPWakXUGfnHy9iUsiGSa6q6Jew1XpMgs7AAICB/9eGjzF2gDh6U7I72x/6bSdlExx2LvIF92OZKc0S55IOS4Lgzs7Hbfm1aOL4oJt7wBg94xkF4cerxz7y8R9J+k3GNl14KOjbYaMAh1rdxdAzikYMH1p1hS78GMtwxky6jE5en87BGGMmnbC84JlxwN+MD7diu8D0Gkgjj/pxOp32D5jEe02wBPVjFTpFLJjpFniLUY6AohRDEdSuZwWPuoKVWhpeWkasNn5qgwGyDREbXpyPsU02BkwE4JiGs+JMMdOn9KMh5dxiuwsMM9gHiQZS3mSNBBKPWI5ZXsdStVFvapjf2FUFDXLUbTROPv1Xhqf0u7YYORFnWeVtvzKIxVaiEYEGBECAAYFAjnY2vQACgkQ+75aMGJLsklBWgCeN7z9xk52y/aoaCuF6hYb0d+3k98AoMRxvHuXI1Nc2FXY/x65PwHiUbaY")
|
290
323
|
rr = RR.create("all.rr.org. IN CERT 6 0 0 FFsAyW1dVK7hIGuvhN56r26UwJx/")
|
data/test/tc_soak.rb
CHANGED
data/test/tc_tcp_pipelining.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dnsruby
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.61.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Alex Dalitz
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-07-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pry
|
@@ -128,6 +128,20 @@ dependencies:
|
|
128
128
|
- - "~>"
|
129
129
|
- !ruby/object:Gem::Version
|
130
130
|
version: '0.7'
|
131
|
+
- !ruby/object:Gem::Dependency
|
132
|
+
name: addressable
|
133
|
+
requirement: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - "~>"
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '2.5'
|
138
|
+
type: :runtime
|
139
|
+
prerelease: false
|
140
|
+
version_requirements: !ruby/object:Gem::Requirement
|
141
|
+
requirements:
|
142
|
+
- - "~>"
|
143
|
+
- !ruby/object:Gem::Version
|
144
|
+
version: '2.5'
|
131
145
|
description: |-
|
132
146
|
Dnsruby is a pure Ruby DNS client library which implements a
|
133
147
|
stub resolver. It aims to comply with all DNS RFCs, including
|
@@ -194,6 +208,8 @@ files:
|
|
194
208
|
- lib/dnsruby/resource/AFSDB.rb
|
195
209
|
- lib/dnsruby/resource/APL.rb
|
196
210
|
- lib/dnsruby/resource/CAA.rb
|
211
|
+
- lib/dnsruby/resource/CDNSKEY.rb
|
212
|
+
- lib/dnsruby/resource/CDS.rb
|
197
213
|
- lib/dnsruby/resource/CERT.rb
|
198
214
|
- lib/dnsruby/resource/DHCID.rb
|
199
215
|
- lib/dnsruby/resource/DLV.rb
|
@@ -230,6 +246,7 @@ files:
|
|
230
246
|
- lib/dnsruby/resource/TLSA.rb
|
231
247
|
- lib/dnsruby/resource/TSIG.rb
|
232
248
|
- lib/dnsruby/resource/TXT.rb
|
249
|
+
- lib/dnsruby/resource/URI.rb
|
233
250
|
- lib/dnsruby/resource/X25.rb
|
234
251
|
- lib/dnsruby/resource/domain_name.rb
|
235
252
|
- lib/dnsruby/resource/generic.rb
|