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