Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions RELEASE_NOTES.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## Unreleased

* Enforce the 255-octet name limit (RFC 1035 Section 2.3.4, RFC 2181 Section 11) against the wire length rather than the dotted presentation length: names of 256 and 257 wire octets were accepted and encoded into messages, and now raise ResolvError
* Add support for SVCB (type 64) and HTTPS (type 65) resource records - RFC 9460, including zone file parsing with TargetName origin resolution
* Recognises the registered SvcParamKey mnemonics `mandatory`, `alpn`, `no-default-alpn`, `port`, `ipv4hint`, `ipv6hint` (RFC 9460), `ech` (RFC 9848), `dohpath` (RFC 9461), `ohttp` (RFC 9540) and `docpath` (RFC 9953). Any other key reads and writes as `keyNNNNN`
* **Breaking (text output only)** - `Dnsruby::IPv6#to_s` and `#inspect` now emit the RFC 5952 canonical form: lowercase hex, no leading zeros, and `::` for the longest run of all-zero fields (never a single field)
Expand Down
5 changes: 4 additions & 1 deletion lib/dnsruby/name.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,10 @@ def self.split(name)
# This method should only be called internally.
# Use Name::create to create a new Name
def initialize(labels, absolute=true) #:nodoc: all
total_length=labels.length-1
# The 255-octet limit (RFC 1035 section 2.3.4, RFC 2181 section 11) is
# on the wire form, so count each label's length octet, plus the root's
# zero octet.
total_length=labels.length+1
labels.each do |l|
if (!l.kind_of?Label)
raise ArgumentError.new("Name::new called with non-labels. Use Name::create instead?")
Expand Down
33 changes: 27 additions & 6 deletions test/tc_name.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ class TestName < Minitest::Test

include Dnsruby

# Names on either side of the 255-octet wire limit: 249 octets of label text
# in 5 labels, plus a length octet each and the root's zero octet, is 255.
AT_LIMIT_NAME = "#{'a' * 63}.#{'b' * 63}.#{'c' * 63}.#{'d' * 59}.e."
OVER_LIMIT_NAME = "#{'a' * 63}.#{'b' * 63}.#{'c' * 63}.#{'d' * 60}.e."

def test_label_length
Name::Label.set_max_length(Name::Label::MaxLabelLength) # Other tests may have changed this
# Test max label length = 63
Expand All @@ -30,13 +35,29 @@ def test_label_length
end
end

def wire_length(name)
MessageEncoder.new { |msg| msg.put_name(name, true) }.to_s.length
end

# Test max name length=255. The limit is on the wire form, two octets more
# than the dotted presentation form without its trailing dot.
def test_name_length
# Test max name length=255
begin
Name.create("1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123.com")
assert(false, "Name of length > 255 allowed")
rescue ResolvError
end
assert_equal(255, wire_length(Name.create(AT_LIMIT_NAME)))

error = assert_raises(ResolvError) { Name.create(OVER_LIMIT_NAME) }
assert_match(/Name length is 256,/, error.message)
end

# An oversized name must not reach the wire through Message either, and a
# name right at the limit must still survive the round trip.
def test_name_length_in_message
assert_raises(ResolvError) { Message.new(OVER_LIMIT_NAME, "A") }

message = Message.new(AT_LIMIT_NAME, "A")
message.add_answer(RR.create("#{AT_LIMIT_NAME} 3600 IN NS #{AT_LIMIT_NAME}"))
decoded = Message.decode(message.encode)
assert_equal(AT_LIMIT_NAME, decoded.question[0].qname.to_s + ".")
assert_equal(AT_LIMIT_NAME, decoded.answer[0].domainname.to_s + ".")
end

def test_absolute
Expand Down
Loading