diff --git a/CHANGELOG b/CHANGELOG index fe577daf7..9455e66cb 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,18 +1,6 @@ # Nmap Changelog ($Id$); -*-text-*- 3.97Shmoo -o Reverse DNS resolution is now done in parallel rather than one at a - time. All scans of large networks (particularly list, ping and - just-a-few-ports scans) should benefit substantially from this - change. If you encounter any problems, please let us know. The new - --system_dns option was added so you can use the (slow) system - resolver if you prefer that for some reason. You can specify a - comma separated list of DNS server IP addresses for Nmap to use with - the new --dns_servers option. Otherwise, Nmap looks in - /etc/resolve.conf (UNIX) or the system registry (Windows) to obtain - the nameservers already configured for your system. This excellent - patch was written by Doug Hoyte (doug(a)hcsw.org). - o Added run time interaction as documented at http://www.insecure.org/nmap/man/man-runtime-interaction.html . While Nmap is running, you can now press 'v' to increase verbosity, @@ -25,6 +13,18 @@ o Added run time interaction as documented at equivalents. This feature was created by Paul Tarjan (ptarjan(a)stanford.edu) as part of the Google Summer of Code. +o Reverse DNS resolution is now done in parallel rather than one at a + time. All scans of large networks (particularly list, ping and + just-a-few-ports scans) should benefit substantially from this + change. If you encounter any problems, please let us know. The new + --system_dns option was added so you can use the (slow) system + resolver if you prefer that for some reason. You can specify a + comma separated list of DNS server IP addresses for Nmap to use with + the new --dns_servers option. Otherwise, Nmap looks in + /etc/resolve.conf (UNIX) or the system registry (Windows) to obtain + the nameservers already configured for your system. This excellent + patch was written by Doug Hoyte (doug(a)hcsw.org). + o Added the --badsum option, which causes Nmap to use invalid TCP or UDP checksums for packets sent to target hosts. Since virtually all host IP stacks properly drop these packets, any diff --git a/nmap.cc b/nmap.cc index 12014528e..91419230f 100644 --- a/nmap.cc +++ b/nmap.cc @@ -1620,8 +1620,9 @@ printf("%s %s ( %s )\n" " -r: Scan ports consecutively - don't randomize\n" "SERVICE/VERSION DETECTION:\n" " -sV: Probe open ports to determine service/version info\n" - " --version_light: Limit to most likely probes for faster identification\n" - " --version_all: Try every single probe for version detection\n" + " --version_intensity : Set from 0 (light) to 9 (try all probes)\n" + " --version_light: Limit to most likely probes (intensity 2)\n" + " --version_all: Try every single probe (intensity 9)\n" " --version_trace: Show detailed version scan activity (for debugging)\n" "OS DETECTION:\n" " -O: Enable OS detection\n" diff --git a/nmap_dns.cc b/nmap_dns.cc index 88f039f35..693b30874 100644 --- a/nmap_dns.cc +++ b/nmap_dns.cc @@ -286,28 +286,32 @@ static u16 id_counter; static ScanProgressMeter *SPM; -//------------------- Prototypes --------------------- +//------------------- Prototypes and macros --------------------- void close_dns_servers(); void write_evt_handler(nsock_pool nsp, nsock_event evt, void *req_v); void do_possible_writes(); +int deal_with_timedout_reads(); +#define ACTION_FINISHED 0 +#define ACTION_CNAME_LIST 1 +#define ACTION_TIMEOUT 2 //------------------- Misc code --------------------- void output_summary() { - int tp = stat_ok + stat_nx + stat_sf + stat_dropped; + int tp = stat_ok + stat_nx + stat_dropped; struct timeval now; memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval)); if (o.debugging && (tp%SUMMARY_DELAY == 0)) - log_write(LOG_STDOUT, "mass_rdns: %.2fs %d/%d [#: %lu, OK: %d, NX: %d, SF: %d, DR: %d, TR: %d]\n", + log_write(LOG_STDOUT, "mass_rdns: %.2fs %d/%d [#: %lu, OK: %d, NX: %d, DR: %d, SF: %d, TR: %d]\n", TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0, tp, stat_actual, - servs.size(), stat_ok, stat_nx, stat_sf, stat_dropped, stat_trans); + servs.size(), stat_ok, stat_nx, stat_dropped, stat_sf, stat_trans); } @@ -326,7 +330,7 @@ void check_capacities(dns_server *tpserv) { // After processing a DNS response, we search through the IPs we're // looking for and update their results as necessary. // Returns non-zero if this matches a query we're looking for -int process_result(u32 ia, char *result, int needs_system_dns) { +int process_result(u32 ia, char *result, int action, u16 id) { std::list::iterator servI; std::list::iterator reqI; dns_server *tpserv; @@ -338,19 +342,26 @@ int process_result(u32 ia, char *result, int needs_system_dns) { for(reqI = tpserv->in_process.begin(); reqI != tpserv->in_process.end(); reqI++) { tpreq = *reqI; - if ((u32) (tpreq->targ->v4host().s_addr) == ia) { + if (id == tpreq->id) { + + if (ia != 0 && (u32) (tpreq->targ->v4host().s_addr) != ia) continue; + + if (action == ACTION_CNAME_LIST || action == ACTION_FINISHED) { tpserv->capacity += CAPACITY_UP_STEP; check_capacities(tpserv); if (result) tpreq->targ->setHostName(result); tpserv->in_process.remove(tpreq); tpserv->reqs_on_wire--; + total_reqs--; - if (needs_system_dns) - cname_reqs.push_back(tpreq); - else - delete tpreq; + if (action == ACTION_CNAME_LIST) cname_reqs.push_back(tpreq); + if (action == ACTION_FINISHED) delete tpreq; + } else { + memcpy(&tpreq->timeout, nsock_gettimeofday(), sizeof(struct timeval)); + deal_with_timedout_reads(); + } do_possible_writes(); @@ -457,6 +468,7 @@ void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) { int i, nameloc, rdlen, atype, aclass; int errcode=0; int queries, answers; + u16 packet_id; if (total_reqs >= 1) nsock_read(nsp, nse_iod(evt), read_evt_handler, -1, NULL); @@ -474,6 +486,8 @@ void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) { // Size of header is 12, and we must have additional data as well if (buflen <= 12) return; + packet_id = (buf[1] & 0xFF) + ((buf[0] & 0xFF) << 8); + // Check that this is a response, standard query, and that no truncation was performed // 0xFA == 11111010 (we're not concerned with AA or RD bits) if ((buf[2] & 0xFA) != 0x80) return; @@ -493,11 +507,26 @@ void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) { // If the domain doesn't resolve (NXDOMAIN or SERVFAIL) we should have // 1+ queries and 0 answers: if (errcode) { - if (queries <= 0 || answers > 0) return; - } else { - if (queries <= 0 || answers <= 0) return; + int found; + + // NXDomain means we're finished (doesn't exist for sure) + // but SERVFAIL might just mean a server timeout + found = process_result(0, NULL, errcode == 3 ? ACTION_FINISHED : ACTION_TIMEOUT, packet_id); + + if (errcode == 2 && found) { + if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: SERVFAIL \n", packet_id); + stat_sf++; + } else if (errcode == 3 && found) { + if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: NXDOMAIN \n", packet_id); + output_summary(); + stat_nx++; } + return; + } + + if (queries <= 0 || answers <= 0) return; + curbuf = 12; // Need to safely skip past QUERY section @@ -509,30 +538,7 @@ void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) { // Make sure we have the QTYPE and QCLASS fields if (curbuf + 4 >= buflen) return; curbuf += 4; - - if (errcode) { - struct in_addr ia; - int found; - - ia.s_addr = parse_inaddr_arpa(buf+nameloc, buflen-nameloc); - if (ia.s_addr == 0) return; - - found = process_result(ia.s_addr, NULL, 0); - - if (errcode == 2 && found) { - if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: SERVFAIL <%s>\n", inet_ntoa(ia)); - output_summary(); - stat_sf++; - } else if (errcode == 3 && found) { - if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: NXDOMAIN <%s>\n", inet_ntoa(ia)); - output_summary(); - stat_nx++; } - } - } - - // No answers if NXDOMAIN/SERVFAIL - if (errcode) return; // We're now at the ANSWER section @@ -562,7 +568,7 @@ void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) { if (encoded_name_to_normal(buf+nameloc, outbuf, sizeof(outbuf)) == -1) return; - if (process_result(ia.s_addr, outbuf, 0)) { + if (process_result(ia.s_addr, outbuf, ACTION_FINISHED, packet_id)) { if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: OK MATCHED <%s> to <%s>\n", inet_ntoa(ia), outbuf); output_summary(); stat_ok++; @@ -575,7 +581,7 @@ void read_evt_handler(nsock_pool nsp, nsock_event evt, void *nothing) { if (ia.s_addr == 0) return; if (o.debugging >= TRACE_DEBUG_LEVEL) log_write(LOG_STDOUT, "mass_rdns: CNAME found for <%s>\n", inet_ntoa(ia)); - process_result(ia.s_addr, NULL, 1); + process_result(ia.s_addr, NULL, ACTION_CNAME_LIST, packet_id); } else { if (rdlen < 0 || rdlen + curbuf >= buflen) return; curbuf += rdlen; @@ -662,7 +668,7 @@ int deal_with_timedout_reads() { memcpy(&now, nsock_gettimeofday(), sizeof(struct timeval)); if (keyWasPressed()) - SPM->printStats((double) (stat_ok + stat_nx + stat_sf + stat_dropped) / stat_actual, &now); + SPM->printStats((double) (stat_ok + stat_nx + stat_dropped) / stat_actual, &now); for(servI = servs.begin(); servI != servs.end(); servI++) { tpserv = *servI; @@ -1006,6 +1012,7 @@ void nmap_mass_rdns_core(Target **targets, int num_targets) { int timeout; char *tpname; int i; + bool lasttrace = false; if (o.mass_dns == false) { Target *currenths; @@ -1115,7 +1122,7 @@ void nmap_mass_rdns_core(Target **targets, int num_targets) { if ((dnspool = nsp_new(NULL)) == NULL) fatal("Unable to create nsock pool in nmap_mass_rdns_core()"); - if (o.packetTrace()) + if ((lasttrace = o.packetTrace())) nsp_settrace(dnspool, 5, o.getStartTime()); connect_dns_servers(); @@ -1133,6 +1140,13 @@ void nmap_mass_rdns_core(Target **targets, int num_targets) { if (total_reqs <= 0) break; + /* Because this can change with runtime interaction */ + if (o.packetTrace() != lasttrace) { + lasttrace = !lasttrace; + if (lasttrace) + nsp_settrace(dnspool, 5, o.getStartTime()); + else nsp_settrace(dnspool, 0, o.getStartTime()); + } nsock_loop(dnspool, timeout); } @@ -1198,12 +1212,12 @@ void nmap_mass_rdns(Target **targets, int num_targets) { // #: Number of DNS servers used // OK: Number of fully reverse resolved queries // NX: Number of confirmations of 'No such reverse domain eXists' - // SF: Number of IPs that got 'Server Failure's // DR: Dropped IPs (no valid responses were received) + // SF: Number of IPs that got 'Server Failure's // TR: Total number of transmissions necessary. The number of domains is ideal, higher is worse - log_write(LOG_STDOUT, "DNS resolution of %d IPs took %.2fs. Mode: Async [#: %lu, OK: %d, NX: %d, SF: %d, DR: %d, TR: %d, CN: %d]\n", + log_write(LOG_STDOUT, "DNS resolution of %d IPs took %.2fs. Mode: Async [#: %lu, OK: %d, NX: %d, DR: %d, SF: %d, TR: %d, CN: %d]\n", stat_actual, TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0, - servs.size(), stat_ok, stat_nx, stat_sf, stat_dropped, stat_trans, stat_cname); + servs.size(), stat_ok, stat_nx, stat_dropped, stat_sf, stat_trans, stat_cname); } else { log_write(LOG_STDOUT, "DNS resolution of %d IPs took %.2fs. Mode: System [OK: %d, ??: %d]\n", stat_actual, TIMEVAL_MSEC_SUBTRACT(now, starttv) / 1000.0, diff --git a/timing.cc b/timing.cc index 402f83e99..6ddc57b18 100644 --- a/timing.cc +++ b/timing.cc @@ -264,8 +264,6 @@ ScanProgressMeter::~ScanProgressMeter() { bool ScanProgressMeter::mayBePrinted(const struct timeval *now) { struct timeval tv; - return true; - if (!o.verbose) return false; diff --git a/tty.cc b/tty.cc index be225aaae..81e01239b 100644 --- a/tty.cc +++ b/tty.cc @@ -211,13 +211,14 @@ bool keyWasPressed() o.verbose++; log_write(LOG_STDOUT, "Verbosity Increased to %d.\n", o.verbose); } else if (c == 'V') { - o.verbose--; + if (o.verbose > 0) + o.verbose--; log_write(LOG_STDOUT, "Verbosity Decreased to %d.\n", o.verbose); } else if (c == 'd') { o.debugging++; log_write(LOG_STDOUT, "Debugging Increased to %d.\n", o.debugging); } else if (c == 'D') { - o.debugging--; + if (o.debugging > 0) o.debugging--; log_write(LOG_STDOUT, "Debugging Decreased to %d.\n", o.debugging); } else if (c == 'p') { o.setPacketTrace(true);