From 19286e796dad019c0cbf6bb7d759e4533a4b518a Mon Sep 17 00:00:00 2001 From: dmiller Date: Wed, 21 Oct 2020 20:51:15 +0000 Subject: [PATCH] Fix ICMP Time Exceeded handling. See #110, #2153 We attempted to fix this twice already, so this change reverses r36709 (which simply ignored all Time Exceeded messages for host discovery, leading to long scan times when the TTL is insufficient) and r34557 (which used incorrect logic to match ICMP responses, resulting in ignoring all ICMP error messages in response to ICMP probes, e.g. Time Exceeded for Echo Request). Instead, we'll correctly verify that the ICMP ID of the *encapsulated datagram* matches the one for the probe we are attempting to match. --- scan_engine_raw.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/scan_engine_raw.cc b/scan_engine_raw.cc index 427587baa..9eceb480d 100644 --- a/scan_engine_raw.cc +++ b/scan_engine_raw.cc @@ -627,14 +627,14 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) { if (probe->protocol() != encaps_hdr.proto || sockaddr_storage_cmp(&target_src, &hdr.dst) != 0 || sockaddr_storage_cmp(&target_src, &encaps_hdr.src) != 0 || - sockaddr_storage_cmp(&target_dst, &encaps_hdr.dst) != 0 || - ((probe->protocol() == IPPROTO_ICMP || probe->protocol() == IPPROTO_ICMPV6) && - ntohs(ping->id) != probe->icmpid())) + sockaddr_storage_cmp(&target_dst, &encaps_hdr.dst) != 0) continue; if ((encaps_hdr.proto == IPPROTO_ICMP || encaps_hdr.proto == IPPROTO_ICMPV6) && USI->ptech.rawicmpscan) { /* The response was based on a ping packet we sent */ + if (probe->icmpid() != ntohs(((struct icmp *) encaps_data)->icmp_id)) + continue; } else if (encaps_hdr.proto == IPPROTO_TCP && USI->ptech.rawtcpscan) { struct tcp_hdr *tcp = (struct tcp_hdr *) encaps_data; if (probe->dport() != ntohs(tcp->th_dport) || @@ -688,6 +688,10 @@ int get_ping_pcap_result(UltraScanInfo *USI, struct timeval *stime) { || (hdr.proto == IPPROTO_ICMPV6 && ping->type == 3)) { if (o.debugging) log_write(LOG_STDOUT, "Got Time Exceeded for %s\n", hss->target->targetipstr()); + goodone = 1; + newstate = HOST_DOWN; + /* I don't want anything to do with timing this. */ + adjust_timing = false; } else if (hdr.proto == IPPROTO_ICMP && ping->type == 4) { if (o.debugging) log_write(LOG_STDOUT, "Got ICMP source quench\n");