Index: nselib/dns.lua
===================================================================
--- nselib/dns.lua (revision 22634)
+++ nselib/dns.lua (working copy)
@@ -34,6 +34,7 @@
require("ipOps")
require("stdnse")
require("base64")
+require("base32")
get_servers = nmap.get_dns_servers
@@ -239,114 +240,6 @@
-- * dtype: Desired DNS record type (default: "A").
-- * host: DNS server to be queried (default: DNS servers known to Nmap).
-- * port: Port of DNS server to connect to (default: 53).
--- * tries: How often should dnssec_query try to contact another server (for non-recursive queries).
--- * retAll: Return all answers, not just the first.
--- * retPkt: Return the packet instead of using the answer-fetching mechanism.
--- * norecurse If true, do not set the recursion (RD) flag.
--- * retDnssec if true then the value of pkt.DNSSEC is returned as a third return value
--- @return True if a dns response was received and contained an answer of the requested type,
--- or the decoded dns response was requested (retPkt) and is being returned - or False otherwise.
--- @return String answer of the requested type, Table of answers or a String error message of one of the following:
--- "No Such Name", "No Servers", "No Answers", "Unable to handle response"
-function dnssec_query(dname, options)
---This should reall either be joined with or utilise the function below
-
- if not options then options = {} end
-
- local dtype, host, port, tries = options.dtype, options.host, options.port, options.tries
-
- if not tries then tries = 10 end -- don't get into an infinite loop
-
- if not options.sendCount then options.sendCount = 2 end
-
- if type( options.timeout ) ~= "number" then options.timeout = get_default_timeout() end
-
- if type(dtype) == "string" then
- dtype = types[dtype]
- end
- if not dtype then dtype = types.A end
-
- local srv
- local srvI = 1
- if not port then port = 53 end
- if not host then
- srv = get_servers()
- if srv and srv[1] then
- host = srv[1]
- else
- return false, "No Servers"
- end
- elseif type(host) == "table" then
- srv = host
- host = srv[1]
- end
- local pkt = newPacket()
- addQuestion(pkt, dname, dtype)
- if options.norecurse then pkt.flags.RD = false end
-
- addEdns(pkt, true)
-
- local data = encode(pkt)
-
- local status, response = sendPackets(data, host, port, options.timeout, options.sendCount)
-
- -- if working with know nameservers, try the others
- while((not status) and srv and srvI < #srv) do
- srvI = srvI + 1
- host = srv[srvI]
- status, response = sendPackets(data, host, port, options.timeout, options.sendCount)
- end
-
-
- -- if we got any response:
- if status then
- response = response[1].data
- local rPkt = decode(response)
- -- is it a real answer?
- if gotAnswer(rPkt) then
- if (options.retPkt) then
- return rPkt.dnssec,true, rPkt
- else
- return rPkt.dnssec,findNiceAnswer(dtype, rPkt, options.retAll)
- end
- else -- if not, ask the next server in authority
-
- local next_server = getAuthDns(rPkt)
-
- -- if we got a CNAME, ask for the CNAME
- if type(next_server) == 'table' and next_server.cname then
- options.tries = tries - 1
- return rPkt.dnssec,dnssec_query(next_server.cname, options)
- end
-
- -- only ask next server in authority, if
- -- we got an auth dns and
- -- it isn't the one we just asked
- if next_server and next_server ~= host and tries > 1 then
- options.host = next_server
- options.tries = tries - 1
- -- return rPkt.dnssec,dnssec_query(dname, options)
- return rPkt.dnssec, false, "No Answers"
- end
- end
-
- -- nothing worked
- stdnse.print_debug(1, "dns.dnssec_query() failed to resolve the requested dnssec_query%s%s", dname and ": " or ".", dname or "")
- return rPkt.dnssec,false, "No Answers"
- else
- stdnse.print_debug(1, "dns.dnssec_query() got zero responses attempting to resolve dnssec_query%s%s", dname and ": " or ".", dname or "")
- return false, false, "No Answers"
- end
-end
-
-
----
--- Query DNS servers for a DNS record.
--- @param dname Desired domain name entry.
--- @param options A table containing any of the following fields:
--- * dtype: Desired DNS record type (default: "A").
--- * host: DNS server to be queried (default: DNS servers known to Nmap).
--- * port: Port of DNS server to connect to (default: 53).
-- * tries: How often should query try to contact another server (for non-recursive queries).
-- * retAll: Return all answers, not just the first.
-- * retPkt: Return the packet instead of using the answer-fetching mechanism.
@@ -364,6 +257,8 @@
if not options.tries then options.tries = 10 end -- don't get into an infinite loop
if not options.sendCount then options.sendCount = 2 end
+
+ if not options.dnssec then options.dnssec = false end
if type( options.timeout ) ~= "number" then options.timeout = get_default_timeout() end
@@ -391,8 +286,9 @@
addQuestion(pkt, dname, dtype)
if options.norecurse then pkt.flags.RD = false end
+ if options.dnssec then addEdns(pkt,true) end
local data = encode(pkt)
-
+
local status, response = sendPackets(data, host, port, options.timeout, options.sendCount, options.multiple)
@@ -612,7 +508,7 @@
if not retAll then break end
end
if #nsec3 == 0 then
- stdnse.print_debug(1, "dns.answerFetcher found no recornsec3 of the required type: NSEC3")
+ stdnse.print_debug(1, "dns.answerFetcher found no records of the required type: NSEC3")
return false, "No Answers"
end
for _, nsec3rec in ipairs(nsec3) do
@@ -636,7 +532,7 @@
if not retAll then break end
end
if #nsec == 0 then
- stdnse.print_debug(1, "dns.answerFetcher found no recornsec of the required type: NSEC")
+ stdnse.print_debug(1, "dns.answerFetcher found no records of the required type: NSEC")
return false, "No Answers"
end
for _, nsecrec in ipairs(nsec) do
@@ -660,7 +556,7 @@
if not retAll then break end
end
if #dnskey == 0 then
- stdnse.print_debug(1, "dns.answerFetcher found no recordnskey of the required type: DNSKEY")
+ stdnse.print_debug(1, "dns.answerFetcher found no records of the required type: DNSKEY")
return false, "No Answers"
end
for _, dnskeyrec in ipairs(dnskey) do
@@ -684,7 +580,7 @@
if not retAll then break end
end
if #rrsig == 0 then
- stdnse.print_debug(1, "dns.answerFetcher found no recorrrsig of the required type: RRSIG")
+ stdnse.print_debug(1, "dns.answerFetcher found no records of the required type: RRSIG")
return false, "No Answers"
end
for _, rrsigrec in ipairs(rrsig) do
@@ -1364,20 +1260,23 @@
-- @param pos Position in packet after RR.
decoder[types.NSEC3] = function (entry, data, pos)
local np = pos - #entry.data
+ local _
local flags
entry.NSEC3 = {}
+ entry.NSEC3.dname = entry.dname
entry.NSEC3.salt, entry.NSEC3.hash = {}, {}
np, entry.NSEC3.hash.alg,
flags,
- entry.NSEC3.iterations,
- entry.NSEC3.salt.size = bin.unpack(">CBSC", data, np)
+ entry.NSEC3.iterations = bin.unpack(">CBS", data, np)
entry.NSEC3.flags = decodeFlagsNSEC3(flags)
- np, entry.NSEC3.salt.bin = bin.unpack(">H" .. entry.NSEC3.salt.size, data, np)
+ np, entry.NSEC3.salt.bin = bin.unpack(">p", data, np)
+ _, entry.NSEC3.salt.hex = bin.unpack("H" .. #entry.NSEC3.salt.bin, entry.NSEC3.salt.bin)
- np, entry.NSEC3.hash.size = bin.unpack(">C", data, np)
- np, entry.NSEC3.hash.bin = bin.unpack(">H" .. entry.NSEC3.hash.size, data, np)
+ np, entry.NSEC3.hash.bin = bin.unpack(">p" , data, np)
+ _, entry.NSEC3.hash.hex = bin.unpack(">H" .. #entry.NSEC3.hash.bin , entry.NSEC3.hash.bin)
+ entry.NSEC3.hash.base32 = base32.enc(entry.NSEC3.hash.bin, true)
np, entry.NSEC3.WinBlockNo, entry.NSEC3.bmplength = bin.unpack(">CC", data, np)
np, entry.NSEC3.bin = bin.unpack(">B".. entry.NSEC3.bmplength, data, np)
@@ -1389,11 +1288,6 @@
table.insert(entry.NSEC3.types, (entry.NSEC3.WinBlockNo*256+i-1))
end
end
- --stdnse.print_debug("alg: %s, iterations: %s, salt_sz: %s, hash_sz: %s", entry.NSEC3.hash.alg, entry.NSEC3.iterations, entry.NSEC3.salt.size, entry.NSEC3.hash.size)
- --stdnse.print_debug("salt: %s", entry.NSEC3.salt.bin)
- --stdnse.print_debug("hash: %s", entry.NSEC3.hash.bin)
- --stdnse.print_debug("types: %s", stdnse.strjoin(":",entry.NSEC3.types))
-
end