From 471a80638df4bb6370db35609c82d0fa901598ce Mon Sep 17 00:00:00 2001 From: AJ ONeal Date: Mon, 9 Oct 2017 13:48:54 -0600 Subject: [PATCH] note if data is truncated --- bin/debug.js | 12 ++++++++++-- dns.unpack-labels.js | 5 +++++ parser/type.ns.js | 15 ++++++++++----- parser/type.ptr.js | 12 ++++++++---- 4 files changed, 33 insertions(+), 11 deletions(-) diff --git a/bin/debug.js b/bin/debug.js index 4fee566..0bbde9e 100644 --- a/bin/debug.js +++ b/bin/debug.js @@ -65,6 +65,11 @@ function unpackQuestionLabels(opts) { while (true) { if (total >= len) { + opts.trunc = true; + console.warn(''); + console.warn('[WARNING] The label was truncated by byte length of message or rdata.'); + console.warn('[WARNING] Depending on the Resource Record type, that may be a parse error.'); + console.warn(''); break; } labelLen = dv.getUint8(total, false); // additional count @@ -72,8 +77,11 @@ function unpackQuestionLabels(opts) { if (!labelLen) { break; } - if (192 === labelLen) { - var pointer = dv.getUint8(total, false); + if (labelLen >= 0xc0) { + // (11 000000 & whatever) signifies pointer + // (00 111111 & whatever) bitmask for potentially large pointer + // (00 000001 11111111) largest realistic pointer value (512 byte message size) + var pointer = ((labelLen & 0x3f) << 8) | dv.getUint8(total, false); console.log('Found a pointer to' + ' 0x' + pointer.toString(16) + ' (' + pointer + ')' + ' at byte index' diff --git a/dns.unpack-labels.js b/dns.unpack-labels.js index 9a82d43..46ac18f 100644 --- a/dns.unpack-labels.js +++ b/dns.unpack-labels.js @@ -26,11 +26,16 @@ exports.DNS_UNPACK_LABELS = function (ui8, ptr, q) { len = ui8[total]; if (len === undefined){ // RDATA is terminated by undefined, not len === 0 + q.trunc = true; break; } // Handle message compression pointers. See 4.1.4 of RFC1035 for details. + // 0xc0 // 192 // parseInt('11000000', 2).toString(16) if (len >= 0xc0) { + // Only the two highest bits are used to signify the pointer. + // The remaining bits may be used to specify the address of the pointer + // (it would seem that only 1 extra bit is actually used since the message size is 512 bytes) var cpptr = ((ui8[total] & 0x3f) << 8) | ui8[total + 1]; // We're not coming back, so if this is the first time we're following one of diff --git a/parser/type.ns.js b/parser/type.ns.js index e03d102..20b9a28 100644 --- a/parser/type.ns.js +++ b/parser/type.ns.js @@ -1,6 +1,10 @@ (function (exports) { 'use strict'; +// FORMAT: +// name ttl class rr name +// foo. 15 IN NS www.example.com. + // Comes in variable lengths. It is the name of the primary Master for the Domain. // For example 'ns1.example.com' // It may be a label, pointer or any combination @@ -8,11 +12,12 @@ var unpackLabels = exports.DNS_UNPACK_LABELS || require('../dns.unpack-labels.js exports.DNS_PARSER_TYPE_NS = function (ab , packet, record) { - record.data = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).name; - return record; - + var labelInfo = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }); + if (record.trunc) { + throw new Error("RDATA type NS must be `null`-terminated, not truncated by rdata length."); + } + record.data = labelInfo.name; + return record; }; }('undefined' !== typeof window ? window : exports)); - - diff --git a/parser/type.ptr.js b/parser/type.ptr.js index 1e6e068..83de4a2 100644 --- a/parser/type.ptr.js +++ b/parser/type.ptr.js @@ -6,12 +6,16 @@ // to a host name. // FORMAT: -// ame ttl class rr name -// 15 IN PTR www.example.com. +// name ttl class rr name +// foo. 15 IN PTR www.example.com. var unpackLabels = exports.DNS_UNPACK_LABELS || require('../dns.unpack-labels.js').DNS_UNPACK_LABELS; exports.DNS_PARSER_TYPE_PTR = function (ab, pack, record) { - record.data = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }).name; - return record; + var labelInfo = unpackLabels(new Uint8Array(ab), record.rdstart, { byteLength: 0, cpcount: 0, labels: [], name: '' }); + if (record.trunc) { + throw new Error("RDATA type PTR must be `null`-terminated, not truncated by rdata length."); + } + record.data = labelInfo.name; }; + }('undefined' !== typeof window ? window : exports));