Skip to content

Commit

Permalink
Malformed records or unknown records are now ignored
Browse files Browse the repository at this point in the history
Previously there was a custom record which just hold the raw data.
  • Loading branch information
Supereg committed Dec 5, 2020
1 parent 5c88f80 commit 2c6a4bc
Show file tree
Hide file tree
Showing 8 changed files with 215 additions and 198 deletions.
299 changes: 179 additions & 120 deletions package-lock.json

Large diffs are not rendered by default.

16 changes: 8 additions & 8 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -58,17 +58,17 @@
},
"devDependencies": {
"@types/debug": "^4.1.5",
"@types/jest": "^26.0.15",
"@types/node": "~10.17.47",
"@typescript-eslint/eslint-plugin": "^4.8.2",
"@typescript-eslint/parser": "^4.8.2",
"eslint": "^7.14.0",
"@types/jest": "^26.0.16",
"@types/node": "~10.17.48",
"@typescript-eslint/eslint-plugin": "^4.9.0",
"@typescript-eslint/parser": "^4.9.0",
"eslint": "^7.15.0",
"jest": "^26.6.3",
"rimraf": "^3.0.2",
"semver": "^7.3.2",
"semver": "^7.3.4",
"ts-jest": "^26.4.4",
"ts-node": "^9.0.0",
"typedoc": "0.20.0-beta.17",
"ts-node": "^9.1.0",
"typedoc": "0.20.0-beta.24",
"typescript": "^4.1.2"
}
}
20 changes: 14 additions & 6 deletions src/coder/DNSPacket.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,11 @@ export interface DecodedData<T> {
readBytes: number;
}

export interface OptionalDecodedData<T> {
data?: T;
readBytes: number;
}

export interface DNSQueryDefinition {
questions: Question[];
answers?: ResourceRecord[]; // list of known-answers
Expand Down Expand Up @@ -496,10 +501,10 @@ export class DNSPacket {
const additionalsLength = buffer.readUInt16BE(offset);
offset += 2;

const questions: Question[] = new Array(questionLength);
const answers: ResourceRecord[] = new Array(answerLength);
const authorities: ResourceRecord[] = new Array(authoritiesLength);
const additionals: ResourceRecord[] = new Array(additionalsLength);
const questions: Question[] = [];
const answers: ResourceRecord[] = [];
const authorities: ResourceRecord[] = [];
const additionals: ResourceRecord[] = [];


offset += DNSPacket.decodeList(context, labelCoder, buffer, offset, questionLength, Question.decode.bind(Question), questions);
Expand Down Expand Up @@ -552,13 +557,16 @@ export class DNSPacket {
}

private static decodeList<T>(context: AddressInfo, coder: DNSLabelCoder, buffer: Buffer, offset: number,
length: number, decoder: (context: AddressInfo, coder: DNSLabelCoder, buffer: Buffer, offset: number) => DecodedData<T>, destination: T[]): number {
length: number, decoder: (context: AddressInfo, coder: DNSLabelCoder, buffer: Buffer, offset: number) => OptionalDecodedData<T>, destination: T[]): number {
const oldOffset = offset;

for (let i = 0; i < length; i++) {
const decoded = decoder(context, coder, buffer, offset);
offset += decoded.readBytes;
destination[i] = decoded.data;

if (decoded.data) { // if the rdata is not supported by us or we encountered an parsing error, we ignore the record
destination.push(decoded.data);
}
}

return offset - oldOffset;
Expand Down
13 changes: 1 addition & 12 deletions src/coder/ResourceRecord.spec.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { RClass, RType } from "./DNSPacket";
import { RType } from "./DNSPacket";
import { AAAARecord } from "./records/AAAARecord";
import { ARecord } from "./records/ARecord";
import { CNAMERecord } from "./records/CNAMERecord";
Expand All @@ -7,7 +7,6 @@ import { OPTOption, OPTRecord } from "./records/OPTRecord";
import { PTRRecord } from "./records/PTRRecord";
import { SRVRecord } from "./records/SRVRecord";
import { TXTRecord } from "./records/TXTRecord";
import { UnsupportedOrMalformedRecord } from "./records/UnsupportedOrMalformedRecord";
import { ResourceRecord } from "./ResourceRecord";
import { runRecordEncodingTest } from "./test-utils";

Expand Down Expand Up @@ -60,14 +59,4 @@ describe(ResourceRecord, () => {
runRecordEncodingTest(new TXTRecord("test.local.", [Buffer.from("key=value"), Buffer.from("key2=value2")]));
});

it("should encode unsupported record", () => {
runRecordEncodingTest(new UnsupportedOrMalformedRecord({
type: 99,
class: RClass.IN,
name: "test.local.",
ttl: 250,
flushFlag: false,
}, Buffer.from("foo")));
});

});
17 changes: 11 additions & 6 deletions src/coder/ResourceRecord.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { AddressInfo } from "net";
import { dnsLowerCase } from "../util/dns-equal";
import { dnsTypeToString } from "./dns-string-utils";
import { DNSLabelCoder, NonCompressionLabelCoder } from "./DNSLabelCoder";
import { DecodedData, DNSRecord, RClass, RType } from "./DNSPacket";
import { DecodedData, DNSRecord, OptionalDecodedData, RClass, RType } from "./DNSPacket";

const debug = createDebug("ciao:decoder");

Expand All @@ -25,7 +25,6 @@ export type RRDecoder = (coder: DNSLabelCoder, header: RecordRepresentation, buf
export abstract class ResourceRecord implements DNSRecord { // RFC 1035 4.1.3.

public static readonly typeToRecordDecoder: Map<RType, RRDecoder> = new Map();
public static unsupportedOrMalformedRecordDecoder: RRDecoder;

private static readonly FLUSH_MASK = 0x8000; // 2 bytes, first bit set
private static readonly NOT_FLUSH_MASK = 0x7FFF;
Expand Down Expand Up @@ -165,14 +164,18 @@ export abstract class ResourceRecord implements DNSRecord { // RFC 1035 4.1.3.
return `RR ${this.name} ${this.type} ${this.class} ${this.dataAsString()}`;
}

public static decode(context: AddressInfo, coder: DNSLabelCoder, buffer: Buffer, offset: number): DecodedData<ResourceRecord> {
public static decode(context: AddressInfo, coder: DNSLabelCoder, buffer: Buffer, offset: number): OptionalDecodedData<ResourceRecord> {
const oldOffset = offset;

const decodedHeader = this.decodeRecordHeader(coder, buffer, offset);
offset += decodedHeader.readBytes;

const header = decodedHeader.data;
const rrDecoder = this.typeToRecordDecoder.get(header.type) ?? ResourceRecord.unsupportedOrMalformedRecordDecoder;
const rrDecoder = this.typeToRecordDecoder.get(header.type);

if (!rrDecoder) {
return { readBytes: (offset + header.rDataLength) - oldOffset };
}

coder.initRRLocation(oldOffset, offset, header.rDataLength); // defines record offset and rdata offset for local compression

Expand All @@ -183,8 +186,10 @@ export abstract class ResourceRecord implements DNSRecord { // RFC 1035 4.1.3.
// we slice the buffer (below), so out of bounds error are instantly detected
decodedRecord = rrDecoder(coder, header, rdata, offset);
} catch (error) {
debug(`Received malformed rdata section for ${dnsTypeToString(header.type)} ${header.name} ${header.ttl} from ${context.address}:${context.port}: ${error.stack}`);
decodedRecord = ResourceRecord.unsupportedOrMalformedRecordDecoder(coder, header, rdata, offset);
debug(`Received malformed rdata section for ${dnsTypeToString(header.type)} ${header.name} ${header.ttl} \
from ${context.address}:${context.port} with data '${rdata.slice(offset).toString("hex")}': ${error.stack}`);

return { readBytes: (offset + header.rDataLength) - oldOffset };
}
offset += decodedRecord.readBytes;

Expand Down
43 changes: 0 additions & 43 deletions src/coder/records/UnsupportedOrMalformedRecord.ts

This file was deleted.

2 changes: 0 additions & 2 deletions src/coder/records/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import { OPTRecord } from "./OPTRecord";
import { PTRRecord } from "./PTRRecord";
import { SRVRecord } from "./SRVRecord";
import { TXTRecord } from "./TXTRecord";
import { UnsupportedOrMalformedRecord } from "./UnsupportedOrMalformedRecord";

ResourceRecord.typeToRecordDecoder.set(RType.AAAA, AAAARecord.decodeData);
ResourceRecord.typeToRecordDecoder.set(RType.A, ARecord.decodeData);
Expand All @@ -18,4 +17,3 @@ ResourceRecord.typeToRecordDecoder.set(RType.PTR, PTRRecord.decodeData);
ResourceRecord.typeToRecordDecoder.set(RType.SRV, SRVRecord.decodeData);
ResourceRecord.typeToRecordDecoder.set(RType.OPT, OPTRecord.decodeData);
ResourceRecord.typeToRecordDecoder.set(RType.TXT, TXTRecord.decodeData);
ResourceRecord.unsupportedOrMalformedRecordDecoder = UnsupportedOrMalformedRecord.decodeData;
3 changes: 2 additions & 1 deletion src/coder/test-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ export function runRecordEncodingTest(record: Question | ResourceRecord, legacyU
expect(decodedRecord.readBytes).toBe(buffer.length);

//
const record2 = decodedRecord.data;
const record2 = decodedRecord.data!;
expect(record2).toBeDefined();

coder = new DNSLabelCoder(legacyUnicast);

Expand Down

0 comments on commit 2c6a4bc

Please sign in to comment.