dns-zone 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/HISTORY.md +19 -0
- data/README.md +49 -11
- data/dns-zone.gemspec +3 -3
- data/lib/dns/zone.rb +97 -13
- data/lib/dns/zone/rr.rb +50 -25
- data/lib/dns/zone/rr/cdnskey.rb +5 -0
- data/lib/dns/zone/rr/cds.rb +5 -0
- data/lib/dns/zone/rr/dlv.rb +5 -0
- data/lib/dns/zone/rr/dnskey.rb +38 -0
- data/lib/dns/zone/rr/ds.rb +38 -0
- data/lib/dns/zone/rr/hinfo.rb +4 -8
- data/lib/dns/zone/rr/naptr.rb +44 -0
- data/lib/dns/zone/rr/nsec.rb +32 -0
- data/lib/dns/zone/rr/nsec3.rb +45 -0
- data/lib/dns/zone/rr/nsec3param.rb +38 -0
- data/lib/dns/zone/rr/rrsig.rb +54 -0
- data/lib/dns/zone/rr/sshfp.rb +35 -0
- data/lib/dns/zone/version.rb +1 -1
- data/test/rr/cdnskey_test.rb +31 -0
- data/test/rr/cds_test.rb +28 -0
- data/test/rr/dlv_test.rb +28 -0
- data/test/rr/dnskey_test.rb +31 -0
- data/test/rr/ds_test.rb +28 -0
- data/test/rr/naptr_test.rb +60 -0
- data/test/rr/nsec3_test.rb +33 -0
- data/test/rr/nsec3param_test.rb +29 -0
- data/test/rr/nsec_test.rb +24 -0
- data/test/rr/rrsig_test.rb +40 -0
- data/test/rr/sshfp_test.rb +24 -0
- data/test/zone_test.rb +32 -0
- metadata +29 -8
- data/Guardfile +0 -14
@@ -0,0 +1,38 @@
|
|
1
|
+
# `DNSKEY` resource record.
|
2
|
+
#
|
3
|
+
# RFC 4034
|
4
|
+
class DNS::Zone::RR::DNSKEY < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
REGEX_DNSKEY_RDATA = %r{
|
7
|
+
(?<flags>\d+)\s*
|
8
|
+
(?<protocol>\d+)\s*
|
9
|
+
(?<algorithm>\d+)\s*
|
10
|
+
(?<key>#{DNS::Zone::RR::REGEX_STRING})\s*
|
11
|
+
}mx
|
12
|
+
|
13
|
+
attr_accessor :flags, :protocol, :algorithm, :key
|
14
|
+
|
15
|
+
def dump
|
16
|
+
parts = general_prefix
|
17
|
+
parts << flags
|
18
|
+
parts << protocol
|
19
|
+
parts << algorithm
|
20
|
+
parts << key
|
21
|
+
parts.join(' ')
|
22
|
+
end
|
23
|
+
|
24
|
+
def load(string, options = {})
|
25
|
+
rdata = load_general_and_get_rdata(string, options)
|
26
|
+
return nil unless rdata
|
27
|
+
|
28
|
+
captures = rdata.match(REGEX_DNSKEY_RDATA)
|
29
|
+
return nil unless captures
|
30
|
+
|
31
|
+
@flags = captures[:flags].to_i
|
32
|
+
@protocol = captures[:protocol].to_i
|
33
|
+
@algorithm = captures[:algorithm].to_i
|
34
|
+
@key = captures[:key].scan(/#{DNS::Zone::RR::REGEX_STRING}/).join
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# `DS` resource record.
|
2
|
+
#
|
3
|
+
# RFC 4034
|
4
|
+
class DNS::Zone::RR::DS < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
REGEX_DS_RDATA = %r{
|
7
|
+
(?<key_tag>\d+)\s*
|
8
|
+
(?<algorithm>\d+)\s*
|
9
|
+
(?<digest_type>\d+)\s*
|
10
|
+
(?<digest>#{DNS::Zone::RR::REGEX_STRING})\s*
|
11
|
+
}mx
|
12
|
+
|
13
|
+
attr_accessor :key_tag, :algorithm, :digest_type, :digest
|
14
|
+
|
15
|
+
def dump
|
16
|
+
parts = general_prefix
|
17
|
+
parts << key_tag
|
18
|
+
parts << algorithm
|
19
|
+
parts << digest_type
|
20
|
+
parts << digest
|
21
|
+
parts.join(' ')
|
22
|
+
end
|
23
|
+
|
24
|
+
def load(string, options = {})
|
25
|
+
rdata = load_general_and_get_rdata(string, options)
|
26
|
+
return nil unless rdata
|
27
|
+
|
28
|
+
captures = rdata.match(REGEX_DS_RDATA)
|
29
|
+
return nil unless captures
|
30
|
+
|
31
|
+
@key_tag = captures[:key_tag].to_i
|
32
|
+
@algorithm = captures[:algorithm].to_i
|
33
|
+
@digest_type = captures[:digest_type].to_i
|
34
|
+
@digest = captures[:digest].scan(/#{DNS::Zone::RR::REGEX_STRING}/).join
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
data/lib/dns/zone/rr/hinfo.rb
CHANGED
@@ -3,13 +3,9 @@
|
|
3
3
|
# RFC 1035
|
4
4
|
class DNS::Zone::RR::HINFO < DNS::Zone::RR::Record
|
5
5
|
|
6
|
-
REGEX_QUOTES_OPTIONAL = %r{
|
7
|
-
"#{DNS::Zone::RR::REGEX_STRING}"|#{DNS::Zone::RR::REGEX_STRING}
|
8
|
-
}mx
|
9
|
-
|
10
6
|
REGEX_HINFO_RDATA = %r{
|
11
|
-
(?<cpu>(?:#{
|
12
|
-
(?<os>(?:#{
|
7
|
+
(?<cpu>(?:#{DNS::Zone::RR::REGEX_CHARACTER_STRING})){1}\s
|
8
|
+
(?<os>(?:#{DNS::Zone::RR::REGEX_CHARACTER_STRING})){1}
|
13
9
|
}mx
|
14
10
|
attr_accessor :cpu
|
15
11
|
attr_accessor :os
|
@@ -27,8 +23,8 @@ class DNS::Zone::RR::HINFO < DNS::Zone::RR::Record
|
|
27
23
|
captures = rdata.match(REGEX_HINFO_RDATA)
|
28
24
|
return nil unless captures
|
29
25
|
|
30
|
-
@cpu = captures[:cpu].scan(/#{
|
31
|
-
@os = captures[:os].scan(
|
26
|
+
@cpu = captures[:cpu].scan(/#{DNS::Zone::RR::REGEX_CHARACTER_STRING}/).join
|
27
|
+
@os = captures[:os].scan(/#{DNS::Zone::RR::REGEX_CHARACTER_STRING}/).join
|
32
28
|
self
|
33
29
|
end
|
34
30
|
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# `NAPTR` resource record.
|
2
|
+
#
|
3
|
+
# RFC 3403
|
4
|
+
class DNS::Zone::RR::NAPTR < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
REGEX_NAPTR_RDATA = %r{
|
7
|
+
(?<order>\d+)\s*
|
8
|
+
(?<pref>\d+)\s*
|
9
|
+
(?<flags>#{DNS::Zone::RR::REGEX_CHARACTER_STRING})\s*
|
10
|
+
(?<service>#{DNS::Zone::RR::REGEX_CHARACTER_STRING})\s*
|
11
|
+
(?<regexp>#{DNS::Zone::RR::REGEX_CHARACTER_STRING})\s*
|
12
|
+
(?<replacement>#{DNS::Zone::RR::REGEX_DOMAINNAME}|\.{1})\s*
|
13
|
+
}mx
|
14
|
+
|
15
|
+
attr_accessor :order, :pref, :flags, :service, :regexp, :replacement
|
16
|
+
|
17
|
+
def dump
|
18
|
+
parts = general_prefix
|
19
|
+
parts << order
|
20
|
+
parts << pref
|
21
|
+
parts << %Q{"#{flags}"}
|
22
|
+
parts << %Q{"#{service}"}
|
23
|
+
parts << %Q{"#{regexp}"}
|
24
|
+
parts << replacement
|
25
|
+
parts.join(' ')
|
26
|
+
end
|
27
|
+
|
28
|
+
def load(string, options = {})
|
29
|
+
rdata = load_general_and_get_rdata(string, options)
|
30
|
+
return nil unless rdata
|
31
|
+
|
32
|
+
captures = rdata.match(REGEX_NAPTR_RDATA)
|
33
|
+
return nil unless captures
|
34
|
+
|
35
|
+
@order = captures[:order].to_i
|
36
|
+
@pref = captures[:pref].to_i
|
37
|
+
@flags = captures[:flags].scan(/#{DNS::Zone::RR::REGEX_CHARACTER_STRING}/).join
|
38
|
+
@service = captures[:service].scan(/#{DNS::Zone::RR::REGEX_CHARACTER_STRING}/).join
|
39
|
+
@regexp = captures[:regexp].scan(/#{DNS::Zone::RR::REGEX_CHARACTER_STRING}/).join
|
40
|
+
@replacement = captures[:replacement]
|
41
|
+
self
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
# `NSEC` resource record.
|
2
|
+
#
|
3
|
+
# RFC 4034
|
4
|
+
class DNS::Zone::RR::NSEC < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
REGEX_NSEC_RDATA = %r{
|
7
|
+
(?<next_domain>#{DNS::Zone::RR::REGEX_DOMAINNAME})\s*
|
8
|
+
(?<rrset_types>#{DNS::Zone::RR::REGEX_STRING})\s*
|
9
|
+
}mx
|
10
|
+
|
11
|
+
attr_accessor :next_domain, :rrset_types
|
12
|
+
|
13
|
+
def dump
|
14
|
+
parts = general_prefix
|
15
|
+
parts << next_domain
|
16
|
+
parts << rrset_types
|
17
|
+
parts.join(' ')
|
18
|
+
end
|
19
|
+
|
20
|
+
def load(string, options = {})
|
21
|
+
rdata = load_general_and_get_rdata(string, options)
|
22
|
+
return nil unless rdata
|
23
|
+
|
24
|
+
captures = rdata.match(REGEX_NSEC_RDATA)
|
25
|
+
return nil unless captures
|
26
|
+
|
27
|
+
@next_domain = captures[:next_domain]
|
28
|
+
@rrset_types = captures[:rrset_types]
|
29
|
+
self
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# `NSEC3` resource record.
|
2
|
+
#
|
3
|
+
# RFC 5155
|
4
|
+
class DNS::Zone::RR::NSEC3 < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
REGEX_NSEC3_RDATA = %r{
|
7
|
+
(?<algorithm>\d+)\s*
|
8
|
+
(?<flags>\d+)\s*
|
9
|
+
(?<iterations>\d+)\s*
|
10
|
+
(?<salt>\S+)\s*
|
11
|
+
(?<next_hashed_owner_name>\S+)\s*
|
12
|
+
(?<rrset_types>#{DNS::Zone::RR::REGEX_STRING})\s*
|
13
|
+
}mx
|
14
|
+
|
15
|
+
attr_accessor :algorithm, :flags, :iterations, :salt,
|
16
|
+
:next_hashed_owner_name, :rrset_types
|
17
|
+
|
18
|
+
def dump
|
19
|
+
parts = general_prefix
|
20
|
+
parts << algorithm
|
21
|
+
parts << flags
|
22
|
+
parts << iterations
|
23
|
+
parts << salt
|
24
|
+
parts << next_hashed_owner_name
|
25
|
+
parts << rrset_types
|
26
|
+
parts.join(' ')
|
27
|
+
end
|
28
|
+
|
29
|
+
def load(string, options = {})
|
30
|
+
rdata = load_general_and_get_rdata(string, options)
|
31
|
+
return nil unless rdata
|
32
|
+
|
33
|
+
captures = rdata.match(REGEX_NSEC3_RDATA)
|
34
|
+
return nil unless captures
|
35
|
+
|
36
|
+
@algorithm = captures[:algorithm].to_i
|
37
|
+
@flags = captures[:flags].to_i
|
38
|
+
@iterations = captures[:iterations].to_i
|
39
|
+
@salt = captures[:salt]
|
40
|
+
@next_hashed_owner_name = captures[:next_hashed_owner_name]
|
41
|
+
@rrset_types = captures[:rrset_types]
|
42
|
+
self
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# `NSEC3PARAM` resource record.
|
2
|
+
#
|
3
|
+
# RFC 5155
|
4
|
+
class DNS::Zone::RR::NSEC3PARAM < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
REGEX_NSEC3PARAM_RDATA = %r{
|
7
|
+
(?<algorithm>\d+)\s*
|
8
|
+
(?<flags>\d+)\s*
|
9
|
+
(?<iterations>\d+)\s*
|
10
|
+
(?<salt>\S+)\s*
|
11
|
+
}mx
|
12
|
+
|
13
|
+
attr_accessor :algorithm, :flags, :iterations, :salt
|
14
|
+
|
15
|
+
def dump
|
16
|
+
parts = general_prefix
|
17
|
+
parts << algorithm
|
18
|
+
parts << flags
|
19
|
+
parts << iterations
|
20
|
+
parts << salt
|
21
|
+
parts.join(' ')
|
22
|
+
end
|
23
|
+
|
24
|
+
def load(string, options = {})
|
25
|
+
rdata = load_general_and_get_rdata(string, options)
|
26
|
+
return nil unless rdata
|
27
|
+
|
28
|
+
captures = rdata.match(REGEX_NSEC3PARAM_RDATA)
|
29
|
+
return nil unless captures
|
30
|
+
|
31
|
+
@algorithm = captures[:algorithm].to_i
|
32
|
+
@flags = captures[:flags].to_i
|
33
|
+
@iterations = captures[:iterations].to_i
|
34
|
+
@salt = captures[:salt]
|
35
|
+
self
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
# `RRSIG` resource record.
|
2
|
+
#
|
3
|
+
# RFC 4034
|
4
|
+
class DNS::Zone::RR::RRSIG < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
REGEX_RRSIG_RDATA = %r{
|
7
|
+
(?<type_covered>\S+)\s*
|
8
|
+
(?<algorithm>\d+)\s*
|
9
|
+
(?<labels>\d+)\s*
|
10
|
+
(?<original_ttl>#{DNS::Zone::RR::REGEX_TTL})\s*
|
11
|
+
(?<signature_expiration>\d+)\s*
|
12
|
+
(?<signature_inception>\d+)\s*
|
13
|
+
(?<key_tag>\d+)\s*
|
14
|
+
(?<signer>#{DNS::Zone::RR::REGEX_DOMAINNAME})\s*
|
15
|
+
(?<signature>#{DNS::Zone::RR::REGEX_CHARACTER_STRING})\s*
|
16
|
+
}mx
|
17
|
+
|
18
|
+
attr_accessor :type_covered, :algorithm, :labels, :original_ttl, :signature_expiration,
|
19
|
+
:signature_inception, :key_tag, :signer, :signature
|
20
|
+
|
21
|
+
def dump
|
22
|
+
parts = general_prefix
|
23
|
+
parts << type_covered
|
24
|
+
parts << algorithm
|
25
|
+
parts << labels
|
26
|
+
parts << original_ttl
|
27
|
+
parts << signature_expiration
|
28
|
+
parts << signature_inception
|
29
|
+
parts << key_tag
|
30
|
+
parts << signer
|
31
|
+
parts << signature
|
32
|
+
parts.join(' ')
|
33
|
+
end
|
34
|
+
|
35
|
+
def load(string, options = {})
|
36
|
+
rdata = load_general_and_get_rdata(string, options)
|
37
|
+
return nil unless rdata
|
38
|
+
|
39
|
+
captures = rdata.match(REGEX_RRSIG_RDATA)
|
40
|
+
return nil unless captures
|
41
|
+
|
42
|
+
@type_covered = captures[:type_covered]
|
43
|
+
@algorithm = captures[:algorithm].to_i
|
44
|
+
@labels = captures[:labels].to_i
|
45
|
+
@original_ttl = captures[:original_ttl].to_i
|
46
|
+
@signature_expiration = captures[:signature_expiration].to_i
|
47
|
+
@signature_inception = captures[:signature_inception].to_i
|
48
|
+
@key_tag = captures[:key_tag].to_i
|
49
|
+
@signer = captures[:signer]
|
50
|
+
@signature = captures[:signature]
|
51
|
+
self
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# `SSHFP` resource record.
|
2
|
+
#
|
3
|
+
# RFC 4255
|
4
|
+
class DNS::Zone::RR::SSHFP < DNS::Zone::RR::Record
|
5
|
+
|
6
|
+
REGEX_SSHFP_RDATA = %r{
|
7
|
+
(?<algorithm_number>\d+)\s*
|
8
|
+
(?<fingerprint_type>\d+)\s*
|
9
|
+
(?<fingerprint>#{DNS::Zone::RR::REGEX_STRING})\s*
|
10
|
+
}mx
|
11
|
+
|
12
|
+
attr_accessor :algorithm_number, :fingerprint_type, :fingerprint
|
13
|
+
|
14
|
+
def dump
|
15
|
+
parts = general_prefix
|
16
|
+
parts << algorithm_number
|
17
|
+
parts << fingerprint_type
|
18
|
+
parts << fingerprint
|
19
|
+
parts.join(' ')
|
20
|
+
end
|
21
|
+
|
22
|
+
def load(string, options = {})
|
23
|
+
rdata = load_general_and_get_rdata(string, options)
|
24
|
+
return nil unless rdata
|
25
|
+
|
26
|
+
captures = rdata.match(REGEX_SSHFP_RDATA)
|
27
|
+
return nil unless captures
|
28
|
+
|
29
|
+
@algorithm_number = captures[:algorithm_number].to_i
|
30
|
+
@fingerprint_type = captures[:fingerprint_type].to_i
|
31
|
+
@fingerprint = captures[:fingerprint]
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
data/lib/dns/zone/version.rb
CHANGED
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'dns/zone/test_case'
|
2
|
+
|
3
|
+
class RR_CDNSKEY_Test < DNS::Zone::TestCase
|
4
|
+
|
5
|
+
# FIXME (lantins): algorithm can be integer _or_ mnemonic!
|
6
|
+
|
7
|
+
TEST_KEY = 'AQPSKmynfzW4kyBv015MUG2DeIQ3Cbl+BBZH4b/0PY1kxkmvHjcZc8nokfzj31GajIQKY+5CptLr3buXA10hWqTkF7H6RfoRqXQeogmMHfpftf6zMv1LyBUgia7za6ZEzOJBOztyvhjL742iU/TpPSEDhm2SNKLijfUppn1UaNvv4w=='
|
8
|
+
|
9
|
+
def test_build_rr__cdnskey
|
10
|
+
rr = DNS::Zone::RR::CDNSKEY.new
|
11
|
+
rr.label = 'example.com.'
|
12
|
+
rr.ttl = 86400
|
13
|
+
rr.flags = 256
|
14
|
+
rr.protocol = 3
|
15
|
+
rr.algorithm = 5
|
16
|
+
rr.key = TEST_KEY
|
17
|
+
|
18
|
+
assert_equal "example.com. 86400 IN CDNSKEY 256 3 5 #{TEST_KEY}", rr.dump
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_load_rr__cdnskey
|
22
|
+
rr = DNS::Zone::RR::CDNSKEY.new.load("example.com. IN CDNSKEY 256 3 5 #{TEST_KEY}")
|
23
|
+
assert_equal 'example.com.', rr.label
|
24
|
+
assert_equal 'CDNSKEY', rr.type
|
25
|
+
assert_equal 256, rr.flags
|
26
|
+
assert_equal 3, rr.protocol
|
27
|
+
assert_equal 5, rr.algorithm
|
28
|
+
assert_equal TEST_KEY, rr.key
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
data/test/rr/cds_test.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'dns/zone/test_case'
|
2
|
+
|
3
|
+
class RR_CDS_Test < DNS::Zone::TestCase
|
4
|
+
|
5
|
+
TEST_DIGEST = '2BB183AF5F22588179A53B0A98631FAD1A292118'
|
6
|
+
|
7
|
+
def test_build_rr__cds
|
8
|
+
rr = DNS::Zone::RR::CDS.new
|
9
|
+
rr.label = 'dskey.example.com.'
|
10
|
+
rr.key_tag = 60485
|
11
|
+
rr.algorithm = 5
|
12
|
+
rr.digest_type = 1
|
13
|
+
rr.digest = TEST_DIGEST
|
14
|
+
|
15
|
+
assert_equal "dskey.example.com. IN CDS 60485 5 1 #{TEST_DIGEST}", rr.dump
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_load_rr__cds
|
19
|
+
rr = DNS::Zone::RR::CDS.new.load("dskey.example.com. IN CDS 60485 5 1 #{TEST_DIGEST}")
|
20
|
+
assert_equal 'dskey.example.com.', rr.label
|
21
|
+
assert_equal 'CDS', rr.type
|
22
|
+
assert_equal 60485, rr.key_tag
|
23
|
+
assert_equal 5, rr.algorithm
|
24
|
+
assert_equal 1, rr.digest_type
|
25
|
+
assert_equal TEST_DIGEST, rr.digest
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
data/test/rr/dlv_test.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'dns/zone/test_case'
|
2
|
+
|
3
|
+
class RR_DLV_Test < DNS::Zone::TestCase
|
4
|
+
|
5
|
+
TEST_DIGEST = '2BB183AF5F22588179A53B0A98631FAD1A292118'
|
6
|
+
|
7
|
+
def test_build_rr__dlv
|
8
|
+
rr = DNS::Zone::RR::DLV.new
|
9
|
+
rr.label = 'dlvtest.example.com.'
|
10
|
+
rr.key_tag = 60485
|
11
|
+
rr.algorithm = 5
|
12
|
+
rr.digest_type = 1
|
13
|
+
rr.digest = TEST_DIGEST
|
14
|
+
|
15
|
+
assert_equal "dlvtest.example.com. IN DLV 60485 5 1 #{TEST_DIGEST}", rr.dump
|
16
|
+
end
|
17
|
+
|
18
|
+
def test_load_rr__dlv
|
19
|
+
rr = DNS::Zone::RR::DLV.new.load("dlvtest.example.com. IN DLV 60485 5 1 #{TEST_DIGEST}")
|
20
|
+
assert_equal 'dlvtest.example.com.', rr.label
|
21
|
+
assert_equal 'DLV', rr.type
|
22
|
+
assert_equal 60485, rr.key_tag
|
23
|
+
assert_equal 5, rr.algorithm
|
24
|
+
assert_equal 1, rr.digest_type
|
25
|
+
assert_equal TEST_DIGEST, rr.digest
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|