Skip Menu |

This queue is for tickets about the Net-DNS CPAN distribution.

Report information
The Basics
Id: 102809
Status: resolved
Priority: 0/
Queue: Net-DNS

People
Owner: Nobody in particular
Requestors: tlhackque [...] yahoo.com
Cc:
AdminCc:

Bug Information
Severity: Important
Broken in: (no value)
Fixed in: (no value)



Subject: CAA broken
1) CAA records don't decode properly. An extra byte of garbage appears with the value. In Net::DNS::RR::CAA: sub decode_rdata { ## decode rdata from wire-format octet string my $self = shift; my ( $data, $offset ) = @_; my $taglen = unpack "\@$offset x C", $$data; my $vallen = $self->{rdlength} - $taglen - 1; The -1 should be -2. Value length is rdata_length - length(tag) - 1_for_flags - 1_for_tag_length_byte. 2) Entering values seems to be impossible for at least one required value. Or at least it's so confusing that I haven't figured out how. Consider this record example.net. CAA 128 issue ; This means "Don't issue any cert for this domain" rdstring() doesn't display the quotes shown in the RFC. If entered this way, the ; is treated as a comment character, and the result is a zero-length value. That's reasonable, except that If entered per the RFC (6844 ss 5.2) example.net CAA 128 issue ";" we get the quotes in the value If entered as \;, we get \059 Examples (with the value decode bug fixed): perl -MNet::DNS::RR -de1 printf("%02x ",ord $_) for split( //, Net::DNS::RR->new( q(example.net. CAA 128 issue ;) )->encode ) 07 65 78 61 6d 70 6c 65 03 6e 65 74 00 01 01 00 01 00 00 00 00 00 07 80 05 69 73 73 75 65 fl tl s s s u e printf("%02x ",ord $_) for split( //, Net::DNS::RR->new( q(example.net. CAA 128 issue ";") )->encode ) 07 65 78 61 6d 70 6c 65 03 6e 65 74 00 01 01 00 01 00 00 00 00 00 0a 80 05 69 73 73 75 65 22 3b 22 Fl tl i s s u e " ; " printf("%02x ",ord $_) for split( //, Net::DNS::RR->new( q(example.net. CAA 128 issue \\;) )->encode ) 07 65 78 61 6d 70 6c 65 03 6e 65 74 00 01 01 00 01 00 00 00 00 00 0b 80 05 69 73 73 75 65 5c 30 35 39 fl tl i s s u e \ 0 5 9 In my decode, "fl" is the flags byte (128.), "tl" is the tag length (5), and the rest are printable ascii. plain() is misleading too. This is the same as the second example. nsupdate will not include the quotes in the value (which is correct). But the dump I showed demonstrates that they are encoded onto the wire if fed back into new(); x Net::DNS::RR->new( q(example.net. CAA 128 issue ";") )->plain 0 'example.net. 0 IN CAA 128 issue ";"' Note that you need recent named (I think 9.10) for dig to have CAA support.
From: rwfranks [...] acm.org
On Mon Mar 16 16:34:05 2015, tlhackque wrote: Show quoted text
> 1) CAA records don't decode properly. An extra byte of garbage > appears with the value.
Show quoted text
> 2) Entering values seems to be impossible for at least one required > value. Or at least it's so confusing that I haven't figured out how.
Probably best to start again using Net::DNS::Text elements to provide proper quote and escape handling. Show quoted text
> Note that you need recent named (I think 9.10) for dig to have CAA > support.
Unfortunately CAA support not available when this code was written.
From: tlhackque [...] yahoo.com
On Tue Mar 17 21:19:15 2015, rwfranks@acm.org wrote: Show quoted text
> Unfortunately CAA support not available when this code was written.
Understood. It was a fair effort; just didn't work out. Axiomatically: "If you can't test it, it probably doesn't work..."
Subject: CAA RFC errata
From: tlhackque [...] yahoo.com
A note for the new implementation: there are some errata to the CAA RFC. See: http://www.rfc-editor.org/errata_search.php?rfc=6844 In particular, one clarifies that unlike other text values, CAA "value" has no length byte and is not limited to 255 characters, or segmented like TXT record values... I think this means that using TEXT elements would require some care. A quick look at Net::DNS::Text.pm indicates that some of the code there expects a length byte and new wants to carve the input string into 255 byte chunks. Not insurmountable & you probably already have noticed, but thought I'd mention it.
Subject: CAA in trunk still has issues.
From: tlhackque [...] yahoo.com
I peeked at trunk and noticed a check-in for CAA. Thanks for working on it. I hope it's not improper to comment on what might be a work in progress, but assuming that feedback sooner is better than later: By inspection, the new code does not handle all CAA "value" fields correctly. Specifically, any "value" field longer than 255 bytes will be mishandled. Here's what I saw in the new Net::DNS::RR::CAA::decode: my $tmp = pack 'Ca*', $limit - $offset, substr $$data, $offset, $limit - $offset; $self->{value} = decode Net::DNS::Text( \$tmp ); This attempts to use Net::DNS::Text to parse the value string by packing the string length into a temporary. The intent is that Net::DNS::Text::decode will see a counted text string; that is a byte length + the string. Unfortunately (as I noted in a previous reply), the length of the value can be greater than 255 characters. And unlike TXT and SPF records, longer value strings are not divided into multiple segments, each with its own length byte. This is implicit in the RFC, and made explicit in the erratum that I referenced. The maximum length of "value" is rdlength - (1_flag_byte+1_tag_length_byte+length(tag)). rdlength is a 16-bit unsigned int. (RFC 1035, 3.2.1., bottom of page 10) So packing $limit - $offset into "C" (an 8-bit unsigned int/char) can overflow. In the worst case, rdlength can be 65535, tag length 1. So we have 65532 bytes for the value. This is >> 255. The code will only return the first 252 bytes due to the overflow/truncation by pack. In encode, there is a cousin issue for values longer than 255 bytes. When creating the record from text, Net::DNS::Text::new will break input values into chunks of 255 bytes (or less for the last). When encode calls Net::DNS::Text::encode, the returned string will have a length byte for each segment. (Correct for SPF/TXT.) Although CAA::encode will discard the first length byte, the second and subsequent length bytes will erroneously be included in the wire data. Consider: my $rec = Net::DNS::RR::new->('example.net. 60 CAA 128 issue "' . ('x' x 256) . '"'); The flow for this is CAA::parse_rdata -> CAA::value('x' x 256) -> new Net::DNS::Text: while ( length $_ > 255 ) # Segment into chunks $chunk = substr( $_, 0, 255 ); push @$self, $chunk; ->CAA::encode_rdata -> substr( Net::DNS::Text::encode, 1 ) # Encode string and discard first length byte Net::DNS::Text::encode: join '', map pack( 'C a*', length $_, $_ ), @$self #<< one length byte for each chunk. Thus the wire would have: [bytes 0-254] (1) [byte 255] ^-- this length byte does not belong on the wire Obviously, for 511 byte strings, there would be 2 extra length bytes, and so on. This is what I meant when I wrote -- I think this means that using TEXT elements would require some care. I hope that this review is useful. Thanks again for your efforts.
From: rwfranks [...] acm.org
On Sat Mar 28 08:49:35 2015, tlhackque wrote: Show quoted text
> I peeked at trunk and noticed a check-in for CAA. Thanks for working > on it. > > I hope it's not improper to comment on what might be a work in > progress, > but assuming that feedback sooner is better than later: > > By inspection, the new code does not handle all CAA "value" fields > correctly. > Specifically, any "value" field longer than 255 bytes will be > mishandled. >
The version on trunk is intended to fix the string parsing problem you identified while still having it work for the majority of cases for which the 255 byte restriction is not an issue. Dealing with the general case is not a priority right now and will be fixed when time permits, or a real-world user cites a live and verifiable example with > 255 bytes.
From: tlhackque [...] yahoo.com
On Sun Mar 29 09:59:02 2015, rwfranks@acm.org wrote: Show quoted text
> Dealing with the general case is not a priority right now and will be > fixed when time permits, or a real-world user cites a live and > verifiable example with > 255 bytes.
OK. Although I *am* a "real-word user", I agree that it seems unlikely that 256+ byte values will be required by CAs soon. The CAs I've talked with don't yet have definite plans for CAA, nor sophisticated use models that would drive longer strings. A few users are using CAA to put CAs that they don't use on public notice that they aren't authorized to issue certificates for those users. However, I think it would be a good idea to die() if you decode or are asked to create such a record. Sooner or later one will appear, no doubt first from someone testing their software. (As I am. But I'm aware of the issue.) A "CAA values longer than 255 not yet supported" exception is better than producing incorrect data, especially when you know of the restriction vs. the RFC. It could save someone quite a bit of debugging, and a frustrating "known restriction" response. Thanks for your consideration and for the work you've done so far.
From: rwfranks [...] acm.org
On Sun Mar 29 10:50:29 2015, tlhackque wrote: Show quoted text
> On Sun Mar 29 09:59:02 2015, rwfranks@acm.org wrote:
> > Dealing with the general case is not a priority right now and will be > > fixed when time permits, or a real-world user cites a live and > > verifiable example with > 255 bytes.
> > OK. Although I *am* a "real-word user",
without a CAA with > 255 bytes, your reported problem solved. Show quoted text
> ... I agree that it seems unlikely > that 256+ byte values will be required by CAs soon.
which is why I do not propose to make the required changes to Text.pm right now.