From 2b7cd9ea73dcc2c1674a6b05616bbaa8f155f032 Mon Sep 17 00:00:00 2001 From: Sam Therapy Date: Sun, 19 Jun 2022 15:51:14 +0200 Subject: [PATCH] Untested: add wild domain parsing Signed-off-by: Sam Therapy --- args.ts | 53 +++++++++++++++++++++++++++++++++++++++++++++ awl.ts | 19 +++++----------- deps.ts | 1 + lib/query.ts | 1 + lib/utils.ts | 6 +++++ mod.ts | 3 ++- tests/query_test.ts | 15 +++++++------ 7 files changed, 77 insertions(+), 21 deletions(-) create mode 100644 args.ts diff --git a/args.ts b/args.ts new file mode 100644 index 0000000..2f30085 --- /dev/null +++ b/args.ts @@ -0,0 +1,53 @@ +import { Args } from "./deps.ts"; +import { isRecordType, ServerOptions } from "./lib/utils.ts"; +/** + * A handler for parsing the arguments passed in + * @param {ServerOptions} server - The DNS server to query + * @param {Deno.RecordType} type - The type of DNS request, see Deno.RecordType for more info + * @param {string} name - Server to look up + */ +export type arguments = { + server?: ServerOptions; + type?: Deno.RecordType; + name?: string; +}; + +/** + * @param {Args} args - The arguments, directly passed in + * @returns {arguments} The arguments, parsed + */ +export function parseArgs(args: Args): arguments { + const parsed: arguments = {} as arguments; + args._.forEach((arg) => { + arg = arg.toString(); + + // if it starts with an @, it's a server + if (arg.includes("@")) { + parsed.server = { + server: arg.split("@").pop() as string, + port: args.port, + }; + return; + } + // if there is a dot, it's a name + if (arg.includes(".")) { + parsed.name = arg; + return; + } + + if (isRecordType(arg)) { + parsed.type = arg; + return; + } + + // if all else fails, assume it's a name + parsed.name = arg; + }); + + // Add a . to the end of the name if it's not there + if (parsed.name?.charAt(parsed.name.length - 1) !== ".") { + parsed.name = parsed.name?.concat("."); + } + + return parsed; +} diff --git a/awl.ts b/awl.ts index 9bd0553..9f92ee5 100644 --- a/awl.ts +++ b/awl.ts @@ -3,6 +3,7 @@ import { bold, italic, parse, underline } from "./deps.ts"; import { QueryResponse, ServerOptions } from "./lib/utils.ts"; import { doQuery } from "./lib/query.ts"; import { parseResponse } from "./lib/response.ts"; +import { parseArgs } from "./args.ts"; import { parseNAPTR, parsePTR } from "./lib/reverse.ts"; async function main() { @@ -39,7 +40,7 @@ Written by (YOUR NAME GOES HERE)`, ${bold("")} defaults to A ${bold("<@server>")} defaults to your local resolver - arguments ${bold(underline("NEED TO BE"))} in this order\n + Order ${bold("DOES NOT")} matter\n `, `${underline("Options")}: -p use for query, defaults to 53 @@ -53,12 +54,11 @@ Written by (YOUR NAME GOES HERE)`, if (args.version) Deno.exit(0); - let domain = args._[0]?.toString(); - domain ??= "."; + const parsedArgs = parseArgs(args); - let query: Deno.RecordType = - (args._[1] ?? (args.ptr ? "PTR" : "A")) as Deno.RecordType; + let domain = parsedArgs.name || "."; + let query = parsedArgs.type || "A"; if (domain === ".") query = "NS"; if (query === "PTR") { @@ -69,14 +69,7 @@ Written by (YOUR NAME GOES HERE)`, domain = parseNAPTR(domain); } - if (domain.charAt(domain.length - 1) !== ".") { - domain = domain.concat("."); - } - - const server: ServerOptions = { - server: (args._[2] as string)?.split("@").pop() || "", - port: parseInt(args.port), - }; + const server = parsedArgs.server || { server: "", port: 53 }; const response: QueryResponse = await doQuery(domain, query, server); diff --git a/deps.ts b/deps.ts index c0d035e..0d7ef6c 100644 --- a/deps.ts +++ b/deps.ts @@ -1,4 +1,5 @@ export { parse } from "https://deno.land/std@0.144.0/flags/mod.ts"; +export type { Args } from "https://deno.land/std@0.144.0/flags/mod.ts"; export { bold, italic, diff --git a/lib/query.ts b/lib/query.ts index a758d2d..1cfa196 100644 --- a/lib/query.ts +++ b/lib/query.ts @@ -32,6 +32,7 @@ export async function doQuery( response.response = "NXDOMAIN"; break; default: + console.dir(e) response.response = "SERVFAIL"; } }); diff --git a/lib/utils.ts b/lib/utils.ts index 93442f9..8709d54 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -23,6 +23,12 @@ export type ServerOptions = { port?: number; }; +export function isRecordType(type: string): type is Deno.RecordType { + return type === "A" || type === "AAAA" || type === "CNAME" || type === "MX" || + type === "NS" || type === "PTR" || type === "SOA" || type === "TXT" || + type === "NAPTR" || type === "SRV"; +} + /** * Test if the DNS query is an MX record * @param {QueryResponse["dnsResponse"]} record - DNS response diff --git a/mod.ts b/mod.ts index 2642365..a4e9c12 100644 --- a/mod.ts +++ b/mod.ts @@ -1,7 +1,8 @@ // SPDX-License-Identifier: MIT -// Exports for ldawl, the library for awl +// Exports for lawl, the library for awl export type { QueryResponse, ServerOptions } from "./lib/utils.ts"; +export { isRecordType } from "./lib/utils.ts"; export { doQuery } from "./lib/query.ts"; export { parseResponse } from "./lib/response.ts"; export { parseIPv6, parseNAPTR, parsePTR } from "./lib/reverse.ts"; diff --git a/tests/query_test.ts b/tests/query_test.ts index aa9d95b..35690c3 100644 --- a/tests/query_test.ts +++ b/tests/query_test.ts @@ -20,9 +20,10 @@ Deno.test("PTR localhost", async () => { }); // This test will fail if this random Bri ish phone number goes down +// It's also unreliable, so it's disabled // Deno.test("NAPTR, Remote",async () => { // const res = await doQuery("4.4.2.2.3.3.5.6.8.1.4.4.e164.arpa.", "NAPTR"); -// assertEquals(res.dnsResponse, [ +// assertStrictEquals(res.dnsResponse, [ // { // order: 100, // preference: 10, @@ -48,11 +49,11 @@ Deno.test("Get invalid IP, regular NS", async () => { assertEquals(res.response, "NXDOMAIN"); }); -// This isn't supposed to SERVFAIL but idk +// This isn't supposed to SERVFAIL // It also takes forever -// Deno.test("Get invalid IP, external NS", async () => { -// const res = await doQuery("b", "AAAA", { server: "1.1.1.1" }); -// assertEquals(res.dnsResponse, undefined); -// assertEquals(res.response, "SERVFAIL"); -// }); +Deno.test("Get invalid IP, external NS", async () => { + const res = await doQuery("b", "AAAA", { server: "1.1.1.1" }); + assertEquals(res.dnsResponse, undefined); + assertEquals(res.response, "SERVFAIL"); +});